@spences10/pi-svelte-guardrails 0.0.17 → 0.0.18
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 +50 -18
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,14 +11,30 @@
|
|
|
11
11
|
|
|
12
12
|
<!-- package-readme:header:end -->
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
`pi-svelte-guardrails` blocks
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
Enforce a local policy against agent-written `$effect` by default.
|
|
15
|
+
`pi-svelte-guardrails` blocks matching Svelte `write`/`edit` tool
|
|
16
|
+
calls and recognized bash writes before execution.
|
|
17
|
+
|
|
18
|
+
The [official Svelte guidance](https://svelte.dev/docs/ai/skills) says
|
|
19
|
+
that effects are an escape hatch and should mostly be avoided. Use:
|
|
20
|
+
|
|
21
|
+
- `$derived` / `$derived.by` for computed state.
|
|
22
|
+
- Event handlers or function bindings for user-triggered changes.
|
|
23
|
+
- `onMount` with cleanup for mount-time setup.
|
|
24
|
+
- Attachments for element integrations, `$inspect` for debugging, and
|
|
25
|
+
`createSubscriber` for observing external systems.
|
|
26
|
+
|
|
27
|
+
`onMount` does not rerun when dependencies change, and derived
|
|
28
|
+
expressions must be side-effect-free; neither is a blanket effect
|
|
29
|
+
replacement. The
|
|
30
|
+
[effect reference](https://svelte.dev/docs/svelte/$effect) includes
|
|
31
|
+
legitimate imperative uses, but those require an explicit
|
|
32
|
+
user-controlled policy exception here. External-library imports do not
|
|
33
|
+
grant one automatically.
|
|
34
|
+
|
|
35
|
+
This extension is a text-pattern policy, not a Svelte parser. Keep
|
|
36
|
+
language correctness in the project's compiler, checker, and linter;
|
|
37
|
+
passing those checks does not override this policy.
|
|
22
38
|
|
|
23
39
|
<!-- package-readme:install:start -->
|
|
24
40
|
|
|
@@ -42,9 +58,10 @@ Disable options:
|
|
|
42
58
|
|
|
43
59
|
## Configuration
|
|
44
60
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
Set `packages.svelteGuardrails` in `~/.pi/agent/my-pi-settings.json`
|
|
62
|
+
to configure the guardrail globally, or use
|
|
63
|
+
`.pi/svelte-guardrails.json` for project overrides. This project
|
|
64
|
+
example explicitly enables strict blocking:
|
|
48
65
|
|
|
49
66
|
```json
|
|
50
67
|
{
|
|
@@ -71,13 +88,28 @@ Current default:
|
|
|
71
88
|
}
|
|
72
89
|
```
|
|
73
90
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
the
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
`block` remains the default. Only an explicit user configuration may
|
|
92
|
+
allow exceptions through path globs, `warn`, `off`, or `blockEffect`.
|
|
93
|
+
Agents should not weaken the policy to get a rejected edit through.
|
|
94
|
+
Explicit `warn` mode allows the call with an advisory UI notification;
|
|
95
|
+
notifications require a UI and do not add a model-facing lint result
|
|
96
|
+
in headless sessions. Run language-aware checks in every mode.
|
|
97
|
+
|
|
98
|
+
For writes, only proposed content is checked. For edits, only
|
|
99
|
+
`newText` or each batched `edits[].newText` is checked, so removing an
|
|
100
|
+
existing effect is allowed even in block mode. Recognized bash writes
|
|
101
|
+
are checked as command text; this is not complete shell analysis.
|
|
102
|
+
Comments and strings containing `$effect(` can still match. If this
|
|
103
|
+
blocks necessary content, ask the user for a narrowly scoped exception
|
|
104
|
+
or use their language-aware lint policy instead. This is not a
|
|
105
|
+
complete security boundary against arbitrary file-writing tools.
|
|
106
|
+
|
|
107
|
+
Direct calls and native Codemode calls receive the same enforcement.
|
|
108
|
+
When a write is blocked, the target file was not created or modified.
|
|
109
|
+
Rewrite the proposed change or ask the user to adjust the policy, then
|
|
110
|
+
retry before reporting success. Advisory warnings explicitly say the
|
|
111
|
+
call is allowed. See the
|
|
112
|
+
[validation workflow](https://github.com/spences10/my-pi/tree/main/packages/pi-tool-guidance#language-aware-validation).
|
|
81
113
|
|
|
82
114
|
## Development
|
|
83
115
|
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,6 @@ export interface SvelteEffectAssessment {
|
|
|
8
8
|
mode: Exclude<SvelteGuardrailsConfig['mode'], 'off'>;
|
|
9
9
|
reason: string;
|
|
10
10
|
}
|
|
11
|
-
export declare function assess_svelte_effect(event: ToolCallEvent, config?: SvelteGuardrailsConfig): SvelteEffectAssessment | undefined;
|
|
11
|
+
export declare function assess_svelte_effect(event: ToolCallEvent, config?: SvelteGuardrailsConfig, cwd?: string): SvelteEffectAssessment | undefined;
|
|
12
12
|
export declare function should_block_svelte_effect(event: ToolCallEvent, config?: SvelteGuardrailsConfig): string | undefined;
|
|
13
13
|
export default function svelte_guardrails(pi: ExtensionAPI): void;
|
package/dist/index.js
CHANGED
|
@@ -26,20 +26,38 @@ export function extract_bash_svelte_path(command) {
|
|
|
26
26
|
const heredoc_match = command.match(/\bcat\b[^;&|]*>\s*['"]?([^'"\s>]+\.svelte)['"]?\b/);
|
|
27
27
|
return heredoc_match?.[1];
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
|
|
29
|
+
function effect_reason(path, mode) {
|
|
30
|
+
const alternatives = 'Use $derived/$derived.by for computed state, event handlers or function bindings for user interactions, onMount with cleanup for mount-time setup, and attachments for element integrations. Effects are an escape hatch, not the default solution. External library imports do not grant an exception; ask the user for an explicit policy exception if an effect is unavoidable.';
|
|
31
|
+
if (mode === 'warn') {
|
|
32
|
+
return `Svelte guardrails warning: ${path} contains $effect. This tool call is allowed because warn mode was explicitly configured. ${alternatives}`;
|
|
33
|
+
}
|
|
34
|
+
return `Blocked by Svelte guardrails: ${path} was not created or modified. This project's policy disallows $effect. ${alternatives} Rewrite and retry the proposed change; do not report success until the replacement is written.`;
|
|
35
|
+
}
|
|
36
|
+
function proposed_content(input, tool_name) {
|
|
37
|
+
if (tool_name === 'write')
|
|
38
|
+
return extract_input_strings(input.content);
|
|
39
|
+
const edits = Array.isArray(input.edits) ? input.edits : [];
|
|
40
|
+
return extract_input_strings([
|
|
41
|
+
input.newText,
|
|
42
|
+
...edits.map((edit) => edit && typeof edit === 'object'
|
|
43
|
+
? edit.newText
|
|
44
|
+
: undefined),
|
|
45
|
+
]);
|
|
31
46
|
}
|
|
32
|
-
export function assess_svelte_effect(event, config = load_svelte_guardrails_config()) {
|
|
47
|
+
export function assess_svelte_effect(event, config = load_svelte_guardrails_config(), cwd = process.cwd()) {
|
|
33
48
|
if (!config.blockEffect || config.mode === 'off')
|
|
34
49
|
return undefined;
|
|
35
50
|
const input = event.input;
|
|
36
51
|
if (['write', 'edit'].includes(event.toolName)) {
|
|
37
52
|
const path = find_svelte_path(input);
|
|
38
|
-
if (!path || is_path_allowed(path, config.allow))
|
|
53
|
+
if (!path || is_path_allowed(path, config.allow, cwd))
|
|
39
54
|
return undefined;
|
|
40
|
-
if (!
|
|
55
|
+
if (!proposed_content(input, event.toolName).some(contains_disallowed_effect))
|
|
41
56
|
return undefined;
|
|
42
|
-
return {
|
|
57
|
+
return {
|
|
58
|
+
mode: config.mode,
|
|
59
|
+
reason: effect_reason(path, config.mode),
|
|
60
|
+
};
|
|
43
61
|
}
|
|
44
62
|
if (event.toolName === 'bash') {
|
|
45
63
|
const command = input.command;
|
|
@@ -48,9 +66,12 @@ export function assess_svelte_effect(event, config = load_svelte_guardrails_conf
|
|
|
48
66
|
if (typeof command !== 'string')
|
|
49
67
|
return undefined;
|
|
50
68
|
const path = extract_bash_svelte_path(command);
|
|
51
|
-
if (!path || is_path_allowed(path, config.allow))
|
|
69
|
+
if (!path || is_path_allowed(path, config.allow, cwd))
|
|
52
70
|
return undefined;
|
|
53
|
-
return {
|
|
71
|
+
return {
|
|
72
|
+
mode: config.mode,
|
|
73
|
+
reason: effect_reason(path, config.mode),
|
|
74
|
+
};
|
|
54
75
|
}
|
|
55
76
|
return undefined;
|
|
56
77
|
}
|
|
@@ -60,7 +81,7 @@ export function should_block_svelte_effect(event, config = load_svelte_guardrail
|
|
|
60
81
|
}
|
|
61
82
|
export default function svelte_guardrails(pi) {
|
|
62
83
|
pi.on('tool_call', async (event, ctx) => {
|
|
63
|
-
const assessment = assess_svelte_effect(event);
|
|
84
|
+
const assessment = assess_svelte_effect(event, load_svelte_guardrails_config(ctx.cwd), ctx.cwd);
|
|
64
85
|
if (!assessment)
|
|
65
86
|
return undefined;
|
|
66
87
|
if (assessment.mode === 'warn') {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EACN,eAAe,EACf,6BAA6B,GAE7B,MAAM,aAAa,CAAC;AAErB,MAAM,cAAc,GAAG,qBAAqB,CAAC;AAC7C,MAAM,SAAS,GAAG,yBAAyB,CAAC;AAE5C,MAAM,UAAU,cAAc,CAAC,KAAc;IAC5C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAAc;IACxD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC/B,KAA8B;IAE9B,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,cAAc,CAAC,KAAK,CAAC;YACrD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,wBAAwB,CACvC,OAAe;IAEf,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CACnC,qCAAqC,CACrC,CAAC;IACF,IAAI,cAAc,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IAElD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAC9B,iDAAiD,CACjD,CAAC;IACF,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IAExC,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAClC,mDAAmD,CACnD,CAAC;IACF,OAAO,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spences10/pi-svelte-guardrails",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Svelte
|
|
3
|
+
"version": "0.0.18",
|
|
4
|
+
"description": "Svelte pattern guardrails for Pi with default blocking and explicit policy exceptions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-guardrails",
|
|
7
7
|
"pi",
|