@yadsh/dsh-prompt-firewall 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-prompt-firewall contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,165 @@
1
+ # dsh-prompt-firewall
2
+
3
+ [![CI](https://github.com/xarleyn/dsh-plugins/actions/workflows/ci.yml/badge.svg)](https://github.com/xarleyn/dsh-plugins/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/%40yadsh%2Fdsh-prompt-firewall.svg)](https://www.npmjs.com/package/@yadsh/dsh-prompt-firewall)
5
+ [![npm downloads](https://img.shields.io/npm/dm/%40yadsh%2Fdsh-prompt-firewall.svg)](https://www.npmjs.com/package/@yadsh/dsh-prompt-firewall)
6
+ [![Node.js](https://img.shields.io/node/v/%40yadsh%2Fdsh-prompt-firewall.svg)](package.json)
7
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
+
9
+ Prompt hygiene, observability, and policy middleware for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness).
10
+
11
+ `dsh-prompt-firewall` inspects the final structured system-prompt assembly, audits every section, and can remove explicitly denied sections without changing user messages, tool calls, contexts, variables, or allowed section objects. It is a policy and observability layer, not a security sandbox.
12
+
13
+ [Specification](SPEC_%20dsh-prompt-firewall.md)
14
+
15
+ ## Installation
16
+
17
+ Install the published npm package by name:
18
+
19
+ ```bash
20
+ dsh plugin --profile web add @yadsh/dsh-prompt-firewall
21
+ ```
22
+
23
+ To remove the plugin:
24
+
25
+ ```bash
26
+ dsh plugin --profile web remove @yadsh/dsh-prompt-firewall
27
+ ```
28
+
29
+ Restart the DeepSeek Harness host if bundle hot reload does not pick up the newly installed plugin or browser client.
30
+
31
+ ## What works now
32
+
33
+ - `off`, `audit`, `blocklist`, and `allowlist` modes;
34
+ - exact, prefix, and glob rules with deterministic priority;
35
+ - explicit and verified protection for core namespaces;
36
+ - `clean`, `strict`, and `audit-only` presets;
37
+ - approximate token counts using `ceil(chars / 4)`;
38
+ - bounded in-memory audit history and known-section tracking;
39
+ - label-free aggregate metrics with stable Prometheus/OTel-compatible names;
40
+ - live settings with persistent per-section actions and revision fencing;
41
+ - a Prompt Inspector with decisions, sizes, reasons, and safe previews;
42
+ - fail-open behavior on internal firewall errors;
43
+ - integration through the official `system-prompt/assemble` Cordis middleware.
44
+
45
+ The default configuration is deliberately neutral: blocklist mode with no blocked rules. Select `preset: clean` to remove the known noisy plugin sections listed in the specification.
46
+
47
+ ## Settings UI
48
+
49
+ The browser half adds a **Prompt Firewall** card under **Settings → Plugins**. It provides:
50
+
51
+ - live mode, preset, core-protection, audit, preview, history, and metrics settings;
52
+ - an exact, prefix, and glob rule editor;
53
+ - last-request totals and estimated token savings;
54
+ - a periodically refreshed section inspector;
55
+ - one-click Allow, Block, Protect, and Clear actions.
56
+
57
+ Token values are estimates. Section text is hidden unless `audit.includePreview` is enabled; even then, only the configured prefix is retained in memory and displayed.
58
+
59
+ ## Configuration
60
+
61
+ The bundle inserts the `dsh-prompt-firewall` Cordis row. Override its configuration in the profile patch when needed:
62
+
63
+ ```yaml
64
+ - id: dsh-prompt-firewall
65
+ config:
66
+ mode: blocklist
67
+ preset: clean
68
+ blockedSections:
69
+ - plugin:another-noisy-plugin
70
+ blockedPrefixes:
71
+ - announcement:
72
+ ```
73
+
74
+ Audit without changing the prompt:
75
+
76
+ ```yaml
77
+ - id: dsh-prompt-firewall
78
+ config:
79
+ mode: audit
80
+ audit:
81
+ enabled: true
82
+ logAllowed: true
83
+ includePreview: false
84
+ ```
85
+
86
+ Strict allowlist:
87
+
88
+ ```yaml
89
+ - id: dsh-prompt-firewall
90
+ config:
91
+ mode: allowlist
92
+ allowedSections:
93
+ - plugin:my-important-plugin
94
+ protectCoreSections: true
95
+ ```
96
+
97
+ Rule priority is protected, exact allow, exact block, prefix allow, prefix block, glob allow, glob block, then the mode's default policy.
98
+
99
+ ## Service API
100
+
101
+ When mounted, the plugin exposes `ctx.promptFirewall`:
102
+
103
+ ```ts
104
+ const lastAudit = ctx.promptFirewall.inspectLast();
105
+ const auditHistory = ctx.promptFirewall.inspectHistory();
106
+ const knownSections = ctx.promptFirewall.getKnownSections();
107
+ const metrics = ctx.promptFirewall.getMetrics();
108
+ const decision = ctx.promptFirewall.evaluateSection({
109
+ name: "plugin:example",
110
+ text: "Example instructions.",
111
+ });
112
+
113
+ await ctx.promptFirewall.setSectionPolicy("plugin:example", "block");
114
+ ```
115
+
116
+ The collector exposes aggregate counters without section-name labels:
117
+
118
+ ```text
119
+ dsh_prompt_firewall_requests_total
120
+ dsh_prompt_firewall_sections_total
121
+ dsh_prompt_firewall_sections_blocked_total
122
+ dsh_prompt_firewall_chars_removed_total
123
+ dsh_prompt_firewall_estimated_tokens_removed_total
124
+ ```
125
+
126
+ When the DSH settings provider is mounted, configuration is registered under `prompt-firewall` and changes apply live. `setSectionPolicy()` accepts `allow`, `block`, `protect`, or `clear`; callers can supply a settings revision to reject stale writes. Without a settings provider, inspection and filtering still work, while mutation fails explicitly.
127
+
128
+ ## Design boundaries
129
+
130
+ - Audit previews are never retained or logged unless `audit.includePreview` is explicitly enabled.
131
+ - The plugin prepends a wrapper and filters after `next()` resolves, so it normally sees downstream assembly changes; composition authors should still avoid relying on adversarial load order.
132
+ - DSH restores effective complete sections after the waterfall. The firewall therefore does not override or decompose a complete replacement.
133
+ - The plugin does not modify user messages, tool calls, contexts, or variables.
134
+
135
+ ## Requirements
136
+
137
+ - Node.js 20 or newer
138
+ - pnpm 10.4.1 for development
139
+ - DeepSeek Harness `>=0.1.1-rc.2 <0.2.0`
140
+ - Cordis `^4.0.1`
141
+
142
+ ## Development
143
+
144
+ From the monorepo root:
145
+
146
+ ```bash
147
+ pnpm install --frozen-lockfile
148
+ pnpm --filter @yadsh/dsh-prompt-firewall lint
149
+ pnpm --filter @yadsh/dsh-prompt-firewall typecheck
150
+ pnpm --filter @yadsh/dsh-prompt-firewall test
151
+ pnpm --filter @yadsh/dsh-prompt-firewall build
152
+ pnpm --filter @yadsh/dsh-prompt-firewall verify
153
+ ```
154
+
155
+ ## Releases
156
+
157
+ This package uses independent Nx Version Plans from the monorepo. Add a plan with `pnpm release:plan`; maintainers publish verified tarballs through the shared [release workflow](../../docs/RELEASING.md).
158
+
159
+ ## Contributing
160
+
161
+ Issues and focused pull requests are welcome. Read the monorepo [contribution guide](../../CONTRIBUTING.md) and run the package checks before submitting a change.
162
+
163
+ ## License
164
+
165
+ [MIT](LICENSE). This is an independent community project and is not affiliated with or endorsed by DeepSeek.
@@ -0,0 +1,4 @@
1
+ # The DSH plugin manager discovers this bundle through package.json.
2
+ - insert:
3
+ - id: dsh-prompt-firewall
4
+ name: "@yadsh/dsh-prompt-firewall"
package/lib/audit.js ADDED
@@ -0,0 +1,121 @@
1
+ const ANNOUNCEMENT_MARKERS = Object.freeze([
2
+ 'installed plugin',
3
+ '本机已安装',
4
+ '用户提到',
5
+ 'when user mentions',
6
+ ]);
7
+ export function estimateTokens(chars) {
8
+ return Math.ceil(chars / 4);
9
+ }
10
+ export function looksLikeAnnouncement(text) {
11
+ const normalized = text.toLocaleLowerCase('en-US');
12
+ return ANNOUNCEMENT_MARKERS.some(marker => normalized.includes(marker));
13
+ }
14
+ function auditDecision(decision) {
15
+ if (decision.action === 'block')
16
+ return 'blocked';
17
+ if (decision.action === 'protect')
18
+ return 'protected';
19
+ return 'allowed';
20
+ }
21
+ export function createSectionAudit(section, decision, config) {
22
+ const chars = section.text.length;
23
+ return {
24
+ name: section.name,
25
+ decision: auditDecision(decision),
26
+ reason: decision.reason,
27
+ chars,
28
+ estimatedTokens: estimateTokens(chars),
29
+ ...(config.includePreview ? { preview: section.text.slice(0, config.previewChars) } : {}),
30
+ ...(looksLikeAnnouncement(section.text) ? { suspicious: true } : {}),
31
+ };
32
+ }
33
+ export function createAuditResult(sections, decisions, config, bypassReason) {
34
+ if (sections.length !== decisions.length) {
35
+ throw new TypeError('section and decision counts must match');
36
+ }
37
+ const audited = sections.map((section, index) => {
38
+ const decision = decisions[index];
39
+ if (decision === undefined)
40
+ throw new TypeError(`missing decision for section ${index}`);
41
+ return createSectionAudit(section, decision, config);
42
+ });
43
+ const charsBefore = audited.reduce((sum, section) => sum + section.chars, 0);
44
+ const charsRemoved = audited.reduce((sum, section) => sum + (section.decision === 'blocked' ? section.chars : 0), 0);
45
+ const blockedSections = audited.filter(section => section.decision === 'blocked').length;
46
+ const charsAfter = charsBefore - charsRemoved;
47
+ return {
48
+ timestamp: Date.now(),
49
+ totalSections: audited.length,
50
+ allowedSections: audited.length - blockedSections,
51
+ blockedSections,
52
+ charsBefore,
53
+ charsAfter,
54
+ charsRemoved,
55
+ estimatedTokensBefore: estimateTokens(charsBefore),
56
+ estimatedTokensAfter: estimateTokens(charsAfter),
57
+ estimatedTokensRemoved: estimateTokens(charsRemoved),
58
+ sections: audited,
59
+ ...(bypassReason === undefined ? {} : { bypassed: true, bypassReason }),
60
+ };
61
+ }
62
+ function cloneAudit(result) {
63
+ return {
64
+ ...result,
65
+ sections: result.sections.map(section => ({ ...section })),
66
+ };
67
+ }
68
+ export class AuditStore {
69
+ historySize;
70
+ highlightNewSections;
71
+ history = [];
72
+ known = new Map();
73
+ constructor(historySize, highlightNewSections) {
74
+ this.historySize = historySize;
75
+ this.highlightNewSections = highlightNewSections;
76
+ }
77
+ configure(historySize, highlightNewSections = this.highlightNewSections) {
78
+ this.historySize = historySize;
79
+ this.highlightNewSections = highlightNewSections;
80
+ if (this.history.length > historySize) {
81
+ this.history.splice(0, this.history.length - historySize);
82
+ }
83
+ }
84
+ record(result) {
85
+ for (const section of result.sections) {
86
+ const known = this.known.get(section.name);
87
+ if (known === undefined) {
88
+ if (this.highlightNewSections && section.name.startsWith('plugin:'))
89
+ section.isNew = true;
90
+ this.known.set(section.name, {
91
+ name: section.name,
92
+ firstSeenAt: result.timestamp,
93
+ lastSeenAt: result.timestamp,
94
+ observations: 1,
95
+ });
96
+ }
97
+ else {
98
+ known.lastSeenAt = result.timestamp;
99
+ known.observations += 1;
100
+ }
101
+ }
102
+ if (this.historySize === 0)
103
+ return;
104
+ this.history.push(cloneAudit(result));
105
+ if (this.history.length > this.historySize)
106
+ this.history.shift();
107
+ }
108
+ last() {
109
+ const last = this.history.at(-1);
110
+ return last === undefined ? null : cloneAudit(last);
111
+ }
112
+ entries() {
113
+ return this.history.map(cloneAudit);
114
+ }
115
+ knownSections() {
116
+ return [...this.known.values()]
117
+ .map(section => ({ ...section }))
118
+ .sort((left, right) => left.name.localeCompare(right.name));
119
+ }
120
+ }
121
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AASA,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,kBAAkB;IAClB,OAAO;IACP,MAAM;IACN,oBAAoB;CACrB,CAAC,CAAA;AAEF,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAClD,OAAO,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;AACzE,CAAC;AAED,SAAS,aAAa,CAAC,QAA0B;IAC/C,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,SAAS,CAAA;IACjD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,WAAW,CAAA;IACrD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,OAAwB,EACxB,QAA0B,EAC1B,MAA6B;IAE7B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAA;IACjC,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC;QACjC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,KAAK;QACL,eAAe,EAAE,cAAc,CAAC,KAAK,CAAC;QACtC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzF,GAAG,CAAC,qBAAqB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAA;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAAoC,EACpC,SAAsC,EACtC,MAA6B,EAC7B,YAAqB;IAErB,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QAC9C,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;QACjC,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,SAAS,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAA;QACxF,OAAO,kBAAkB,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;IACF,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC5E,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CACjC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAC5E,CAAC,CACF,CAAA;IACD,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM,CAAA;IACxF,MAAM,UAAU,GAAG,WAAW,GAAG,YAAY,CAAA;IAE7C,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,aAAa,EAAE,OAAO,CAAC,MAAM;QAC7B,eAAe,EAAE,OAAO,CAAC,MAAM,GAAG,eAAe;QACjD,eAAe;QACf,WAAW;QACX,UAAU;QACV,YAAY;QACZ,qBAAqB,EAAE,cAAc,CAAC,WAAW,CAAC;QAClD,oBAAoB,EAAE,cAAc,CAAC,UAAU,CAAC;QAChD,sBAAsB,EAAE,cAAc,CAAC,YAAY,CAAC;QACpD,QAAQ,EAAE,OAAO;QACjB,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;KACxE,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,MAAyB;IAC3C,OAAO;QACL,GAAG,MAAM;QACT,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;KAC3D,CAAA;AACH,CAAC;AAED,MAAM,OAAO,UAAU;IAKX,WAAW;IACX,oBAAoB;IALb,OAAO,GAAwB,EAAE,CAAA;IACjC,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAA;IAExD,YACU,WAAmB,EACnB,oBAA6B;2BAD7B,WAAW;oCACX,oBAAoB;IAC3B,CAAC;IAEJ,SAAS,CAAC,WAAmB,EAAE,oBAAoB,GAAG,IAAI,CAAC,oBAAoB;QAC7E,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;QAC9B,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,CAAA;QAChD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,MAAyB;QAC9B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YAC1C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,IAAI,CAAC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;oBAAE,OAAO,CAAC,KAAK,GAAG,IAAI,CAAA;gBACzF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE;oBAC3B,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,WAAW,EAAE,MAAM,CAAC,SAAS;oBAC7B,UAAU,EAAE,MAAM,CAAC,SAAS;oBAC5B,YAAY,EAAE,CAAC;iBAChB,CAAC,CAAA;YACJ,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,CAAA;gBACnC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAA;YACzB,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,KAAK,CAAC;YAAE,OAAM;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;QACrC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;IAClE,CAAC;IAED,IAAI;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAChC,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IACrD,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACrC,CAAC;IAED,aAAa;QACX,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;aAC5B,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;aAChC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;IAC/D,CAAC;CACF"}
@@ -0,0 +1,155 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState, useSyncExternalStore, } from 'react';
3
+ import promptFirewallRemote from '@yadsh/dsh-prompt-firewall/remote';
4
+ import { styles } from './styles.js';
5
+ const SETTINGS_NAMESPACE = 'prompt-firewall';
6
+ const REFRESH_INTERVAL_MS = 3_000;
7
+ const EMPTY_LIST = Object.freeze([]);
8
+ function list(config, field) {
9
+ return config?.[field] ?? EMPTY_LIST;
10
+ }
11
+ function displayError(error) {
12
+ if (error instanceof Error)
13
+ return error.message;
14
+ if (typeof error === 'string')
15
+ return error;
16
+ return 'Could not load Prompt Inspector data.';
17
+ }
18
+ function Shield() {
19
+ return (_jsx("span", { className: "pf-shield", "aria-hidden": "true", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", children: [_jsx("path", { d: "M12 3 19 6v5c0 4.8-2.8 8.2-7 10-4.2-1.8-7-5.2-7-10V6l7-3Z" }), _jsx("path", { d: "m9 12 2 2 4-4" })] }) }));
20
+ }
21
+ function Toggle(props) {
22
+ return (_jsxs("label", { className: "pf-toggle-row", children: [_jsxs("span", { className: "pf-toggle-copy", children: [_jsx("strong", { children: props.label }), _jsx("span", { children: props.hint })] }), _jsx("input", { className: "pf-toggle", type: "checkbox", checked: props.checked, disabled: props.disabled, onChange: event => { props.onChange(event.currentTarget.checked); } })] }));
23
+ }
24
+ function PromptFirewallCard({ scope, inspect, setSectionPolicy }) {
25
+ const settings = useSyncExternalStore(scope.subscribe, scope.getSnapshot, scope.getSnapshot);
26
+ const config = settings.value;
27
+ const writable = settings.status === 'ready' && settings.writable;
28
+ const [inspector, setInspector] = useState(null);
29
+ const [error, setError] = useState(null);
30
+ const [refreshing, setRefreshing] = useState(false);
31
+ const [rule, setRule] = useState('');
32
+ const [ruleKind, setRuleKind] = useState('exact');
33
+ const [ruleAction, setRuleAction] = useState('block');
34
+ const activeRequest = useRef(0);
35
+ const refresh = useCallback(async () => {
36
+ const request = ++activeRequest.current;
37
+ setRefreshing(true);
38
+ try {
39
+ const result = await inspect();
40
+ if (request !== activeRequest.current)
41
+ return;
42
+ if (result.ok) {
43
+ setInspector(result.value);
44
+ setError(null);
45
+ }
46
+ else {
47
+ setError(displayError(result.error));
48
+ }
49
+ }
50
+ catch (cause) {
51
+ if (request === activeRequest.current)
52
+ setError(displayError(cause));
53
+ }
54
+ finally {
55
+ if (request === activeRequest.current)
56
+ setRefreshing(false);
57
+ }
58
+ }, [inspect]);
59
+ useEffect(() => {
60
+ void refresh();
61
+ const interval = window.setInterval(() => { void refresh(); }, REFRESH_INTERVAL_MS);
62
+ return () => {
63
+ window.clearInterval(interval);
64
+ activeRequest.current += 1;
65
+ };
66
+ }, [refresh]);
67
+ const setPath = useCallback((path, value) => {
68
+ const [field, nested] = path;
69
+ if (field === undefined)
70
+ return;
71
+ if (nested === undefined) {
72
+ void scope.set(field, value);
73
+ return;
74
+ }
75
+ const current = scope.getSnapshot().value;
76
+ const parent = field === 'audit' ? current?.audit : current?.metrics;
77
+ void scope.set(field, { ...parent, [nested]: value });
78
+ }, [scope]);
79
+ const setPolicy = useCallback(async (name, policy) => {
80
+ const current = scope.getSnapshot();
81
+ const result = await setSectionPolicy(name, policy, current.revision);
82
+ if (!result.ok)
83
+ setError(displayError(result.error));
84
+ await refresh();
85
+ }, [refresh, scope, setSectionPolicy]);
86
+ const addRule = (event) => {
87
+ event.preventDefault();
88
+ const value = rule.trim();
89
+ if (value.length === 0)
90
+ return;
91
+ const field = ruleAction === 'protect'
92
+ ? 'protectedSections'
93
+ : ruleKind === 'exact'
94
+ ? `${ruleAction === 'allow' ? 'allowed' : 'blocked'}Sections`
95
+ : ruleKind === 'prefix'
96
+ ? `${ruleAction === 'allow' ? 'allowed' : 'blocked'}Prefixes`
97
+ : `${ruleAction === 'allow' ? 'allowed' : 'blocked'}Patterns`;
98
+ const values = [...new Set([...list(config, field), value])];
99
+ setPath([field], values);
100
+ setRule('');
101
+ };
102
+ const explicitRules = [
103
+ ...list(config, 'allowedSections').map(value => ({ field: 'allowedSections', value, kind: 'exact', action: 'allow' })),
104
+ ...list(config, 'blockedSections').map(value => ({ field: 'blockedSections', value, kind: 'exact', action: 'block' })),
105
+ ...list(config, 'protectedSections').map(value => ({ field: 'protectedSections', value, kind: 'exact', action: 'protect' })),
106
+ ...list(config, 'allowedPrefixes').map(value => ({ field: 'allowedPrefixes', value, kind: 'prefix', action: 'allow' })),
107
+ ...list(config, 'blockedPrefixes').map(value => ({ field: 'blockedPrefixes', value, kind: 'prefix', action: 'block' })),
108
+ ...list(config, 'allowedPatterns').map(value => ({ field: 'allowedPatterns', value, kind: 'glob', action: 'allow' })),
109
+ ...list(config, 'blockedPatterns').map(value => ({ field: 'blockedPatterns', value, kind: 'glob', action: 'block' })),
110
+ ];
111
+ const enabled = config?.enabled ?? true;
112
+ const last = inspector?.last ?? null;
113
+ const effectiveMode = inspector?.config.mode ?? config?.mode ?? 'blocklist';
114
+ const configuredMode = config?.mode
115
+ ?? (config?.preset === 'strict' ? 'allowlist' : config?.preset === 'audit-only' ? 'audit' : 'blocklist');
116
+ return (_jsxs("article", { className: "pf-card", children: [_jsxs("header", { className: "pf-head", children: [_jsxs("div", { className: "pf-title", children: [_jsx(Shield, {}), _jsxs("div", { children: [_jsx("h2", { children: "Prompt Firewall" }), _jsx("p", { children: "Prompt hygiene, section policy, and request-level observability." })] })] }), _jsxs("span", { className: `pf-badge${enabled ? '' : ' off'}`, children: [_jsx("i", { className: "pf-dot" }), enabled ? 'Enabled' : 'Disabled'] })] }), _jsxs("div", { className: "pf-body", children: [settings.status === 'unavailable' && _jsx("div", { className: "pf-error", children: "Settings are unavailable for this connection." }), error !== null && _jsx("div", { className: "pf-error", children: error }), _jsxs("section", { className: "pf-section", children: [_jsxs("div", { className: "pf-section-title", children: [_jsx("h3", { children: "Policy" }), _jsx("span", { className: "pf-muted", children: "Changes apply live" })] }), _jsxs("div", { className: "pf-grid", children: [_jsx(Toggle, { checked: enabled, disabled: !writable, label: "Firewall enabled", hint: "Keep auditing available when policy is off.", onChange: value => { setPath(['enabled'], value); } }), _jsx(Toggle, { checked: config?.protectCoreSections ?? true, disabled: !writable, label: "Protect core sections", hint: "Prevents ordinary rules from removing Harness internals.", onChange: value => { setPath(['protectCoreSections'], value); } }), _jsxs("label", { className: "pf-field", children: [_jsx("span", { children: "Mode" }), _jsxs("select", { className: "pf-control", value: configuredMode, disabled: !writable, onChange: event => { setPath(['mode'], event.currentTarget.value); }, children: [_jsx("option", { value: "off", children: "Off" }), _jsx("option", { value: "audit", children: "Audit only" }), _jsx("option", { value: "blocklist", children: "Blocklist" }), _jsx("option", { value: "allowlist", children: "Allowlist" })] })] }), _jsxs("label", { className: "pf-field", children: [_jsx("span", { children: "Preset" }), _jsxs("select", { className: "pf-control", value: config?.preset ?? '', disabled: !writable, onChange: event => {
117
+ const value = event.currentTarget.value;
118
+ if (value === '')
119
+ void scope.unset('preset');
120
+ else
121
+ setPath(['preset'], value);
122
+ }, children: [_jsx("option", { value: "", children: "None" }), _jsx("option", { value: "clean", children: "Clean" }), _jsx("option", { value: "strict", children: "Strict" }), _jsx("option", { value: "audit-only", children: "Audit only" })] })] }), _jsxs("label", { className: "pf-field", children: [_jsx("span", { children: "Unknown plugin sections" }), _jsxs("select", { className: "pf-control", value: config?.unknownPluginPolicy ?? 'allow', disabled: !writable, onChange: event => { setPath(['unknownPluginPolicy'], event.currentTarget.value); }, children: [_jsx("option", { value: "allow", children: "Allow" }), _jsx("option", { value: "block", children: "Block" })] })] })] })] }), _jsxs("section", { className: "pf-section", children: [_jsxs("div", { className: "pf-section-title", children: [_jsx("h3", { children: "Last request" }), _jsx("button", { className: "pf-btn", disabled: refreshing, onClick: () => { void refresh(); }, children: refreshing ? 'Refreshing…' : 'Refresh' })] }), _jsxs("div", { className: "pf-stats", children: [_jsxs("div", { className: "pf-stat", children: [_jsx("b", { children: last?.totalSections ?? '—' }), _jsx("span", { children: "sections" })] }), _jsxs("div", { className: "pf-stat", children: [_jsx("b", { children: last?.blockedSections ?? '—' }), _jsx("span", { children: "blocked" })] }), _jsxs("div", { className: "pf-stat", children: [_jsx("b", { children: last === null ? '—' : `~${last.estimatedTokensRemoved}` }), _jsx("span", { children: "tokens removed (estimate)" })] }), _jsxs("div", { className: "pf-stat", children: [_jsx("b", { children: effectiveMode }), _jsx("span", { children: "effective mode" })] })] })] }), _jsxs("section", { className: "pf-section", children: [_jsxs("div", { className: "pf-section-title", children: [_jsx("h3", { children: "Rules" }), _jsx("span", { className: "pf-muted", children: "Explicit rules; preset rules are applied in addition" })] }), _jsxs("form", { className: "pf-editor", onSubmit: addRule, children: [_jsx("input", { className: "pf-control", value: rule, disabled: !writable, placeholder: "plugin:example or announcement:*", onChange: event => { setRule(event.currentTarget.value); } }), _jsxs("select", { className: "pf-control", value: ruleKind, disabled: !writable || ruleAction === 'protect', onChange: event => { setRuleKind(event.currentTarget.value); }, children: [_jsx("option", { value: "exact", children: "Exact" }), _jsx("option", { value: "prefix", children: "Prefix" }), _jsx("option", { value: "glob", children: "Glob" })] }), _jsxs("select", { className: "pf-control", value: ruleAction, disabled: !writable, onChange: event => {
123
+ const action = event.currentTarget.value;
124
+ setRuleAction(action);
125
+ if (action === 'protect')
126
+ setRuleKind('exact');
127
+ }, children: [_jsx("option", { value: "block", children: "Block" }), _jsx("option", { value: "allow", children: "Allow" }), _jsx("option", { value: "protect", children: "Protect" })] }), _jsx("button", { className: "pf-btn primary", type: "submit", disabled: !writable || rule.trim().length === 0, children: "Add rule" })] }), _jsxs("div", { className: "pf-rules", children: [explicitRules.length === 0 && _jsx("div", { className: "pf-empty", children: "No explicit rules yet." }), explicitRules.map(item => _jsxs("div", { className: "pf-rule", children: [_jsx("code", { title: item.value, children: item.value }), _jsx("span", { className: "pf-pill pf-kind", children: item.kind }), _jsx("span", { className: `pf-pill ${item.action}`, children: item.action }), _jsx("button", { className: "pf-btn link danger", disabled: !writable, onClick: () => { setPath([item.field], list(config, item.field).filter(value => value !== item.value)); }, children: "Remove" })] }, `${item.field}:${item.value}`))] })] }), _jsxs("details", { className: "pf-advanced", children: [_jsx("summary", { children: "Audit & metrics" }), _jsxs("div", { className: "pf-advanced-content pf-grid", children: [_jsx(Toggle, { checked: config?.audit?.enabled ?? true, disabled: !writable, label: "Audit history", hint: "Keep recent assemblies in Host memory.", onChange: value => { setPath(['audit', 'enabled'], value); } }), _jsx(Toggle, { checked: config?.audit?.includePreview ?? false, disabled: !writable, label: "Section preview", hint: "Expose only the configured prefix in Inspector.", onChange: value => { setPath(['audit', 'includePreview'], value); } }), _jsx(Toggle, { checked: config?.audit?.logBlocked ?? true, disabled: !writable, label: "Log blocked sections", hint: "Names and sizes only unless preview is enabled.", onChange: value => { setPath(['audit', 'logBlocked'], value); } }), _jsx(Toggle, { checked: config?.audit?.logAllowed ?? false, disabled: !writable, label: "Log allowed sections", hint: "Useful for initial policy discovery.", onChange: value => { setPath(['audit', 'logAllowed'], value); } }), _jsx(Toggle, { checked: config?.audit?.highlightNewSections ?? true, disabled: !writable, label: "Highlight new plugin sections", hint: "Informational only; never blocks automatically.", onChange: value => { setPath(['audit', 'highlightNewSections'], value); } }), _jsx(Toggle, { checked: config?.metrics?.enabled ?? true, disabled: !writable, label: "Aggregate metrics", hint: "No arbitrary section-name labels.", onChange: value => { setPath(['metrics', 'enabled'], value); } }), _jsxs("label", { className: "pf-field", children: [_jsx("span", { children: "Preview characters" }), _jsx("input", { className: "pf-control", type: "number", min: "0", step: "1", value: config?.audit?.previewChars ?? 160, disabled: !writable, onChange: event => { setPath(['audit', 'previewChars'], Number(event.currentTarget.value)); } })] }), _jsxs("label", { className: "pf-field", children: [_jsx("span", { children: "History size" }), _jsx("input", { className: "pf-control", type: "number", min: "0", step: "1", value: config?.audit?.historySize ?? 100, disabled: !writable, onChange: event => { setPath(['audit', 'historySize'], Number(event.currentTarget.value)); } })] })] })] }), _jsxs("section", { className: "pf-section", children: [_jsxs("div", { className: "pf-section-title", children: [_jsx("h3", { children: "Prompt Inspector" }), _jsx("span", { className: "pf-muted", children: "Updates every 3 seconds" })] }), _jsx("div", { className: "pf-table-wrap", children: last === null ? _jsx("div", { className: "pf-empty", children: "No audited prompt assembly yet." }) : _jsxs("table", { className: "pf-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Section" }), _jsx("th", { children: "Size" }), _jsx("th", { children: "Decision" }), _jsx("th", { children: "Reason" }), _jsx("th", { children: "Policy" })] }) }), _jsx("tbody", { children: last.sections.map((section, index) => _jsxs("tr", { children: [_jsxs("td", { children: [_jsxs("div", { className: "pf-section-name", children: [_jsx("span", { children: section.name }), section.isNew && _jsx("span", { className: "pf-new", children: "NEW" }), section.suspicious && _jsx("span", { className: "pf-warn", children: "POSSIBLE ANNOUNCEMENT" })] }), section.preview !== undefined && _jsx("div", { className: "pf-preview", children: section.preview })] }), _jsxs("td", { children: ["~", section.estimatedTokens, " t", _jsx("br", {}), _jsxs("span", { className: "pf-muted", children: [section.chars, " chars"] })] }), _jsx("td", { children: _jsx("span", { className: `pf-pill ${section.decision === 'blocked' ? 'block' : section.decision === 'protected' ? 'protect' : 'allow'}`, children: section.decision }) }), _jsx("td", { children: section.reason }), _jsx("td", { children: _jsxs("div", { className: "pf-actions", children: [_jsx("button", { className: "pf-btn link", disabled: !writable, onClick: () => { void setPolicy(section.name, 'allow'); }, children: "Allow" }), _jsx("button", { className: "pf-btn link danger", disabled: !writable, onClick: () => { void setPolicy(section.name, 'block'); }, children: "Block" }), _jsx("button", { className: "pf-btn link", disabled: !writable, onClick: () => { void setPolicy(section.name, 'protect'); }, children: "Protect" }), _jsx("button", { className: "pf-btn link", disabled: !writable, onClick: () => { void setPolicy(section.name, 'clear'); }, children: "Clear" })] }) })] }, `${section.name}:${index}`)) })] }) }), _jsx("p", { className: "pf-footer-note", children: "Token counts are estimates. Prompt Firewall is a hygiene and observability layer, not a security boundary." })] })] })] }));
128
+ }
129
+ export const inject = ['slots', 'settingsScope', 'remote'];
130
+ /** Mount the generated Remote contribution and register the native Settings card. */
131
+ export async function apply(ctx) {
132
+ const remote = ctx.remote;
133
+ const disposeRemote = await remote.$mount(promptFirewallRemote);
134
+ const scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
135
+ const face = {
136
+ scope,
137
+ inspect: () => remote.promptFirewall.inspect(),
138
+ setSectionPolicy: (section, policy, revision) => (remote.promptFirewall.setSectionPolicy(section, policy, revision)),
139
+ };
140
+ const style = document.createElement('style');
141
+ style.dataset.plugin = 'dsh-prompt-firewall';
142
+ style.textContent = styles;
143
+ document.head.appendChild(style);
144
+ const disposeSlot = ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({
145
+ name: 'settings.plugin.item',
146
+ key: SETTINGS_NAMESPACE,
147
+ inject: () => face,
148
+ }, PromptFirewallCard));
149
+ return async () => {
150
+ disposeSlot();
151
+ style.remove();
152
+ await disposeRemote();
153
+ };
154
+ }
155
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export const styles = `
2
+ .pf-card{border:1px solid var(--border,#2a2f3a);border-radius:14px;background:var(--card,#151821);color:var(--foreground,#eef1f6);overflow:hidden;box-shadow:0 10px 32px rgba(0,0,0,.12)}
3
+ .pf-card *{box-sizing:border-box}.pf-head{display:flex;justify-content:space-between;gap:20px;padding:20px 22px;border-bottom:1px solid var(--border,#2a2f3a);background:linear-gradient(135deg,rgba(75,114,255,.10),transparent 55%)}
4
+ .pf-title{display:flex;gap:13px;align-items:flex-start}.pf-shield{width:38px;height:38px;display:grid;place-items:center;border-radius:11px;background:rgba(75,114,255,.15);color:#7c9cff;flex:0 0 auto}.pf-shield svg{width:22px;height:22px}.pf-title h2{font-size:17px;line-height:1.25;margin:1px 0 5px}.pf-title p,.pf-muted{color:var(--muted-foreground,#9da5b4);font-size:12px;margin:0;line-height:1.5}.pf-badge{display:inline-flex;align-items:center;gap:6px;height:25px;padding:0 10px;border-radius:999px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;background:rgba(45,190,125,.13);color:#51d69b}.pf-badge.off{background:rgba(148,154,166,.13);color:#aeb4c1}.pf-dot{width:7px;height:7px;border-radius:50%;background:currentColor}.pf-body{padding:20px 22px;display:grid;gap:18px}.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-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:11px}.pf-field{display:grid;gap:6px}.pf-field>span{font-size:11px;color:var(--muted-foreground,#9da5b4);font-weight:600}.pf-control{width:100%;height:36px;border:1px solid var(--border,#343946);border-radius:8px;background:var(--background,#10131a);color:inherit;padding:0 10px;font:inherit;font-size:12px;outline:none}.pf-control:focus{border-color:#6687ff;box-shadow:0 0 0 3px rgba(75,114,255,.12)}.pf-toggle-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border:1px solid var(--border,#2a2f3a);border-radius:9px}.pf-toggle-copy{display:grid;gap:2px}.pf-toggle-copy strong{font-size:12px}.pf-toggle-copy span{font-size:10px;color:var(--muted-foreground,#9da5b4)}.pf-toggle{appearance:none;width:34px;height:19px;border-radius:999px;background:#4a505c;position:relative;cursor:pointer;transition:.18s;flex:none}.pf-toggle:after{content:'';position:absolute;top:3px;left:3px;width:13px;height:13px;border-radius:50%;background:white;transition:.18s}.pf-toggle:checked{background:#5578f5}.pf-toggle:checked:after{transform:translateX(15px)}.pf-toggle:disabled,.pf-control:disabled,.pf-btn:disabled{cursor:not-allowed;opacity:.45}.pf-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.pf-stat{padding:12px;border-radius:9px;background:var(--muted,#1c202a);border:1px solid var(--border,#292e39)}.pf-stat b{display:block;font-size:17px;margin-bottom:3px}.pf-stat span{font-size:10px;color:var(--muted-foreground,#9da5b4)}.pf-editor{display:grid;grid-template-columns:1.2fr .8fr .8fr auto;gap:8px}.pf-btn{height:34px;border:1px solid var(--border,#343946);border-radius:8px;background:var(--muted,#20242e);color:inherit;padding:0 12px;font:inherit;font-size:11px;font-weight:650;cursor:pointer;white-space:nowrap}.pf-btn:hover:not(:disabled){border-color:#677080;background:#272c38}.pf-btn.primary{border-color:#5578f5;background:#5578f5;color:white}.pf-btn.danger{color:#ff8791}.pf-btn.link{height:27px;padding:0 8px;background:transparent}.pf-rules{display:grid;gap:6px}.pf-rule{display:grid;grid-template-columns:minmax(0,1fr) 70px 70px auto;gap:9px;align-items:center;padding:7px 9px;border:1px solid var(--border,#292e39);border-radius:8px;font-size:11px}.pf-rule code{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#cbd5ff}.pf-pill{font-size:9px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-foreground,#9da5b4)}.pf-pill.block{color:#ff8791}.pf-pill.allow{color:#62dba2}.pf-pill.protect{color:#7ca1ff}.pf-advanced{border:1px solid var(--border,#292e39);border-radius:10px;padding:0 12px}.pf-advanced summary{cursor:pointer;padding:11px 0;font-size:12px;font-weight:650}.pf-advanced-content{padding:2px 0 13px;display:grid;gap:10px}.pf-table-wrap{overflow:auto;border:1px solid var(--border,#292e39);border-radius:10px}.pf-table{width:100%;border-collapse:collapse;font-size:11px;min-width:720px}.pf-table th{text-align:left;color:var(--muted-foreground,#9da5b4);font-weight:600;background:var(--muted,#1c202a);padding:8px 10px}.pf-table td{padding:9px 10px;border-top:1px solid var(--border,#292e39);vertical-align:top}.pf-section-name{display:flex;align-items:center;gap:6px;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.pf-new,.pf-warn{font-family:inherit;font-size:8px;font-weight:800;border-radius:4px;padding:2px 4px;background:rgba(85,120,245,.16);color:#88a5ff}.pf-warn{background:rgba(255,177,75,.14);color:#ffbe68}.pf-actions{display:flex;gap:4px}.pf-preview{margin-top:5px;max-width:360px;white-space:pre-wrap;color:var(--muted-foreground,#9da5b4);font-size:10px;line-height:1.4}.pf-empty{padding:22px;text-align:center;color:var(--muted-foreground,#9da5b4);font-size:12px}.pf-error{padding:9px 11px;border-radius:8px;background:rgba(235,76,88,.12);color:#ff9098;font-size:11px}.pf-footer-note{font-size:10px;color:var(--muted-foreground,#9da5b4)}
5
+ @media(max-width:720px){.pf-head,.pf-body{padding-left:15px;padding-right:15px}.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}}
6
+ `;
7
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/client/styles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAW;;;;;CAK7B,CAAA"}