@openlines/opl-pi-sht 0.2.8 → 0.2.9

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 CHANGED
@@ -14,15 +14,16 @@
14
14
 
15
15
  A portable collection of various Pi coding agent extensions. Repository directories and config files use `opl-`; established Pi-facing commands and tool names stay compatible.
16
16
 
17
- <div align="center">
18
-
19
17
  >
20
- > ### v0.2.8 (29 Sept 2026) - **SSRF and tool-safety hardening**: `opl-webaccess` and `opl-browser` block private/link-local hosts by default and cloud metadata always (localhost stays available for dev), fetch redirects are re-checked per hop, screenshots refuse to overwrite existing files, and `evaluate` no longer crashes on `undefined`. <br/>See [CHANGELOG.md](CHANGELOG.md) for details.
18
+ > ### v0.2.9 - pi dependencies patch, updated test scripts
19
+ > - `devDependencies` updated to `>=0.87.0`, conforming to latest pi release `v0.99.x`; TUI and tests updates
20
+ > ### v0.2.8 - SSRF and tool-safety hardening
21
+ > - `opl-webaccess` and `opl-browser` block private/link-local hosts by default and cloud metadata always (localhost stays available for dev), fetch redirects are re-checked per hop, screenshots refuse to overwrite existing files, and `evaluate` no longer crashes on `undefined`.
21
22
  >
22
- > `Current project state also marked 'SAFE' for pi v0.99.0 release`<br/>*confirmed this because I was literally typing to push the patches when I noticed the release notif*
23
+ > See [CHANGELOG](CHANGELOG.md) for more details.
24
+ >
25
+ > `Current project state also marked 'SAFE' for pi v0.99.x release`
23
26
  >
24
-
25
- </div>
26
27
 
27
28
  ## Installation
28
29
 
@@ -1,6 +1,6 @@
1
1
  # opl-guardian
2
2
 
3
- A configurable session and tool safety extension. `opl-guardian` filters malformed assistant tool calls, prompts before dangerous Bash commands, blocks operations on protected paths, and confirms destructive session transitions. It replaces the standalone `permission-gate`, `protected-paths`, and `confirm-destructive` extensions while retaining malformed-call diagnostics. It adds no tools, commands, prompts, or model-facing schema overhead.
3
+ A configurable session and tool safety extension. `opl-guardian` filters malformed assistant tool calls, prompts before dangerous Bash commands, blocks operations on protected paths, and confirms destructive session transitions. It replaces the standalone `permission-gate`, `protected-paths`, and `confirm-destructive` extensions while retaining malformed-call diagnostics. It adds no tools, commands, prompts, or model-facing schema overhead. All Guardian notification, selection-prompt, and confirmation message text is rendered in fixed red, regardless of Pi's theme; choice labels retain Pi's normal styling.
4
4
 
5
5
  ## Configuration
6
6
 
@@ -20,6 +20,12 @@ import {
20
20
  import { getProtectedPathBlock, hasPendingUserWork } from "./policies.js";
21
21
 
22
22
  const LOG_PATH = join("err", "guardian.jsonl");
23
+ const RED = "\u001b[31m";
24
+ const RESET_FOREGROUND = "\u001b[39m";
25
+
26
+ function red(text: string): string {
27
+ return `${RED}${text}${RESET_FOREGROUND}`;
28
+ }
23
29
 
24
30
  export async function appendIncident(cwd: string, incident: GuardianIncident): Promise<void> {
25
31
  const directory = join(cwd, "err");
@@ -103,7 +109,7 @@ export function createToolCallHandler(config: GuardianConfig) {
103
109
  const reason = blocked.unresolved
104
110
  ? `[opl-guardian] Cannot safely resolve path "${blocked.path}"; ${blocked.operation} denied by protected-path policy.`
105
111
  : `[opl-guardian] Path "${blocked.path}" is protected (${blocked.operation} denied).`;
106
- if (ctx.hasUI) ctx.ui.notify(reason, "warning");
112
+ if (ctx.hasUI) ctx.ui.notify(red(reason), "warning");
107
113
  return { block: true, reason };
108
114
  }
109
115
  }
@@ -124,7 +130,7 @@ export function createToolCallHandler(config: GuardianConfig) {
124
130
  const options = ["No", "Yes"];
125
131
  if (ctx.mode === "rpc") {
126
132
  try {
127
- const choice = await ctx.ui.select(`Dangerous command: ${preview.slice(0, 256)}\nAllow?`, options);
133
+ const choice = await ctx.ui.select(red(`Dangerous command:\n\n${preview.slice(0, 256)}\n\nAllow?`), options);
128
134
  if (choice === "Yes") return undefined;
129
135
  } catch {
130
136
  // A failed RPC dialog is not approval.
@@ -132,10 +138,10 @@ export function createToolCallHandler(config: GuardianConfig) {
132
138
  return { block: true, reason: "[opl-guardian] Command blocked; confirmation was declined or unavailable." };
133
139
  }
134
140
 
135
- const choice = await ctx.ui.select(`Dangerous command: ${preview.slice(0, 256)}\nAllow?`, options);
141
+ const choice = await ctx.ui.select(red(`Dangerous command:\n\n${preview.slice(0, 256)}\n\nAllow?`), options);
136
142
  if (choice === "Yes") return undefined;
137
143
  const reason = "[opl-guardian] Command blocked by user because it matches a dangerous pattern.";
138
- ctx.ui.notify(reason, "warning");
144
+ ctx.ui.notify(red(reason), "warning");
139
145
  return { block: true, reason };
140
146
  };
141
147
  }
@@ -151,7 +157,7 @@ export function createMessageEndHandler(config: GuardianConfig) {
151
157
  sessionId: ctx.sessionManager.getSessionId(),
152
158
  });
153
159
  if (!guarded) return undefined;
154
- ctx.ui?.notify(guarded.diagnostic, "warning");
160
+ ctx.ui?.notify(red(guarded.diagnostic), "warning");
155
161
  return { message: guarded.message };
156
162
  };
157
163
  }
@@ -172,7 +178,7 @@ export function createSessionBeforeSwitchHandler(config: GuardianConfig) {
172
178
  }
173
179
 
174
180
  if (!ctx.hasUI) return config.confirmDestructive.blockWithoutUI ? { cancel: true } : undefined;
175
- return await ctx.ui.confirm(title, message) ? undefined : { cancel: true };
181
+ return await ctx.ui.confirm(red(title), red(message)) ? undefined : { cancel: true };
176
182
  };
177
183
  }
178
184
 
@@ -181,8 +187,8 @@ export function createSessionBeforeForkHandler(config: GuardianConfig) {
181
187
  if (!config.confirmDestructive.forkSession) return undefined;
182
188
  if (!ctx.hasUI) return config.confirmDestructive.blockWithoutUI ? { cancel: true } : undefined;
183
189
  const confirmed = await ctx.ui.confirm(
184
- `Fork from entry ${event.entryId.slice(0, 8)}?`,
185
- "Create a new session branch from this point?",
190
+ red(`Fork from entry ${event.entryId.slice(0, 8)}?`),
191
+ red("Create a new session branch from this point?"),
186
192
  );
187
193
  return confirmed ? undefined : { cancel: true };
188
194
  };
@@ -192,7 +198,7 @@ export default function (pi: ExtensionAPI) {
192
198
  const { config, warnings } = loadGuardianConfig();
193
199
  pi.on("session_start", async (_event, ctx) => {
194
200
  if (warnings.length && ctx.hasUI) {
195
- ctx.ui.notify(`[opl-guardian] Configuration warning(s):\n${warnings.join("\n")}`, "warning");
201
+ ctx.ui.notify(red(`[opl-guardian] Configuration warning(s):\n${warnings.join("\n")}`), "warning");
196
202
  }
197
203
  });
198
204
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openlines/opl-pi-sht",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "opl-pi-sht (shouldHaveThat) Pi coding-agent extension kit: token-efficient context, tool and session safety, fingerprinted /init, model benchmarking, web access, and browser automation.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "type": "module",
42
42
  "scripts": {
43
- "test": "npm run test:opl-browser && npm run test:opl-footer && npm run test:opl-guardian && npm run test:opl-init && npm run test:opl-input && npm run test:opl-modes && npm run test:opl-questionnaire && npm run test:opl-todo && npm run test:opl-webaccess && npm run test:opl-simplebench && npm run test:opl-ctxtrim && npm run test:pi-host",
43
+ "test": "node tests/test-summary.mjs",
44
44
  "test:opl-browser": "bun test tests/opl-browser-helpers.test.mjs && OPL_EXTENSION=opl-browser bun test tests/extension-smoke.test.mjs",
45
45
  "test:opl-footer": "bun test tests/opl-footer-helpers.test.mjs && OPL_EXTENSION=opl-footer bun test tests/extension-smoke.test.mjs",
46
46
  "test:opl-guardian": "bun test tests/opl-guardian.test.mjs && OPL_EXTENSION=opl-guardian bun test tests/extension-smoke.test.mjs",
@@ -55,6 +55,6 @@
55
55
  "test:pi-host": "bun test tests/pi-host-loader.test.mjs"
56
56
  },
57
57
  "devDependencies": {
58
- "@earendil-works/pi-coding-agent": "^0.87.0"
58
+ "@earendil-works/pi-coding-agent": ">=0.87.0"
59
59
  }
60
60
  }