decorated-pi 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -151
- package/extensions/extend-model.ts +1 -6
- package/extensions/lsp/client.ts +12 -1
- package/extensions/lsp/env.ts +6 -0
- package/extensions/lsp/format.ts +6 -0
- package/extensions/lsp/index.ts +6 -0
- package/extensions/lsp/prompt.ts +6 -0
- package/extensions/lsp/server-manager.ts +6 -0
- package/extensions/lsp/servers.ts +9 -1
- package/extensions/lsp/tools.ts +8 -0
- package/extensions/lsp/trust.ts +6 -0
- package/extensions/safety.ts +609 -104
- package/extensions/smart-at.ts +10 -3
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -1,70 +1,46 @@
|
|
|
1
1
|
# decorated-pi
|
|
2
2
|
|
|
3
|
-
`decorated-pi` is a Pi extension
|
|
4
|
-
|
|
5
|
-
## Status
|
|
6
|
-
|
|
7
|
-
Current scope is **functionally complete for local use**.
|
|
8
|
-
|
|
9
|
-
Recent audit highlights:
|
|
10
|
-
- Fixed stale LSP diagnostics caused by returning cached diagnostics after `didChange`
|
|
11
|
-
- Fixed `subdir-agents` path capture on `tool_call`
|
|
12
|
-
- Fixed a `smart-at` multi-token search bug
|
|
13
|
-
- Updated safety checks so shell overwrite attempts on existing files are treated as dangerous
|
|
3
|
+
`decorated-pi` is a Pi extension that adds safety gates, LSP tools, image/compaction model helpers, smarter `@` file search, dynamic subdirectory `AGENTS.md` loading, and a few workflow quality-of-life improvements.
|
|
14
4
|
|
|
15
5
|
## Features
|
|
16
6
|
|
|
17
|
-
### 1.
|
|
18
|
-
Adds global system-prompt guidance via `before_agent_start.systemPrompt`:
|
|
19
|
-
- Restate understanding before acting
|
|
20
|
-
- Break medium/large tasks into discrete steps
|
|
21
|
-
|
|
22
|
-
### 2. Safety Layer
|
|
23
|
-
Implemented in `extensions/safety.ts`.
|
|
7
|
+
### 1. Safety Layer
|
|
24
8
|
|
|
25
9
|
- **Dangerous bash guard**
|
|
26
|
-
-
|
|
10
|
+
- asks for confirmation on destructive commands such as:
|
|
27
11
|
- `rm`
|
|
28
12
|
- `sudo`
|
|
29
|
-
- `svn commit`
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
32
|
-
- `
|
|
33
|
-
|
|
34
|
-
- `git push`
|
|
35
|
-
- `git revert`
|
|
36
|
-
- **Shell overwrite detection**
|
|
37
|
-
- Detects `bash` commands that would overwrite an **existing regular file**, including:
|
|
38
|
-
- `>` / `>>`
|
|
39
|
-
- `1>` / `1>>`
|
|
40
|
-
- `2>` / `2>>`
|
|
41
|
-
- `&>` / `&>>`
|
|
42
|
-
- `tee`
|
|
43
|
-
- Aggregates **all** dangerous reasons found in one command
|
|
13
|
+
- `svn commit/revert`
|
|
14
|
+
- `git reset/restore/clean/push/revert`
|
|
15
|
+
- `npm publish`
|
|
16
|
+
- `>` / `1>` / `2>` / `&>` / `tee` overwrite existing files
|
|
17
|
+
- Hints the agent to use `edit` instead of `write` on non-empty files
|
|
44
18
|
- **Protected paths**
|
|
45
|
-
- Blocks `write`
|
|
46
|
-
- **Write guard**
|
|
47
|
-
- Blocks the `write` tool when it would overwrite a non-empty file
|
|
48
|
-
- Instructs the model to use `edit` instead
|
|
19
|
+
- Blocks read/write access (via `write`/`edit`/`read` tools or `cat`/`head`/`tail`/`grep`/`rg` etc. bash commands) to sensitive locations such as `.env`, `.git/`, `.ssh/`, `*.pem`, `*.key`, etc.
|
|
49
20
|
- **Secret redaction**
|
|
50
|
-
-
|
|
21
|
+
- Dual-layer detection: 40+ known-format patterns (AWS, GitHub, OpenAI, etc.) + Adjusted Shannon Entropy analysis for unknown formats. Based on [opencode-secrets-protect](https://github.com/jscheel/opencode-secrets-protect) (MIT)
|
|
22
|
+
|
|
23
|
+
### 2. Smart `@` File Search
|
|
51
24
|
|
|
52
|
-
|
|
53
|
-
Implemented in `extensions/smart-at.ts`.
|
|
25
|
+
Replaces Pi's default file search with a faster project-aware search strategy:
|
|
54
26
|
|
|
55
|
-
Replaces Pi's default file autocomplete behavior with a faster project-aware search strategy:
|
|
56
27
|
- Uses `git ls-files` in git repos
|
|
57
28
|
- Falls back to `fd` outside git repos
|
|
58
29
|
- Caches results for 10 seconds
|
|
59
30
|
- Scores primarily on **filename match quality**, not full-path fuzziness
|
|
60
31
|
- Penalizes hidden/cache/build directories
|
|
61
32
|
- Hides hidden paths from empty-query results
|
|
62
|
-
- Keeps Pi's original `applyCompletion` / `shouldTriggerFileCompletion` binding behavior intact
|
|
63
33
|
|
|
64
|
-
###
|
|
65
|
-
|
|
34
|
+
### 3. LSP Tool Suite
|
|
35
|
+
|
|
36
|
+
Based on [@spences10/pi-lsp](https://github.com/spences10/my-pi/tree/main/packages/pi-lsp) by Scott Spence (MIT License), with additions:
|
|
37
|
+
|
|
38
|
+
- C/C++ (clangd) and Lua support
|
|
39
|
+
- `lsp_find_symbol`, `lsp_rename`, multi-file support merged into `lsp_diagnostics`
|
|
40
|
+
- Force-sync on `didChange` (no stale diagnostics)
|
|
66
41
|
|
|
67
42
|
Registered tools:
|
|
43
|
+
|
|
68
44
|
- `lsp_diagnostics`
|
|
69
45
|
- `lsp_find_symbol`
|
|
70
46
|
- `lsp_hover`
|
|
@@ -74,8 +50,8 @@ Registered tools:
|
|
|
74
50
|
- `lsp_rename`
|
|
75
51
|
|
|
76
52
|
Supported languages:
|
|
77
|
-
|
|
78
|
-
- cpp
|
|
53
|
+
|
|
54
|
+
- c/cpp
|
|
79
55
|
- go
|
|
80
56
|
- java
|
|
81
57
|
- lua
|
|
@@ -85,134 +61,49 @@ Supported languages:
|
|
|
85
61
|
- svelte
|
|
86
62
|
- typescript
|
|
87
63
|
|
|
88
|
-
|
|
89
|
-
- prompt snippets for `Available tools`
|
|
90
|
-
- tool-specific prompt guidelines
|
|
91
|
-
- parameter descriptions for the JSON schema
|
|
92
|
-
- trust checks for project-local LSP binaries
|
|
93
|
-
- an LSP-specific system-prompt section injected only when LSP tools are active
|
|
64
|
+
### 4. Auxiliary Models (Image + Compact)
|
|
94
65
|
|
|
95
|
-
|
|
96
|
-
Implemented in `extensions/extend-model.ts`.
|
|
66
|
+
Uses cheaper models for auxiliary tasks, configured via `/extend-model`:
|
|
97
67
|
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
- Calls a configured vision-capable model
|
|
101
|
-
- Replaces the read result with image analysis text
|
|
68
|
+
- **Image read fallback** — when the model reads an image file, detects type via magic bytes, calls a configured vision-capable model, and replaces the read result with image analysis text (jpeg, png, gif, webp)
|
|
69
|
+
- **Compact model** — uses a configured model for context compaction (instead of the main model), auto-resumes after compaction.
|
|
102
70
|
|
|
103
|
-
|
|
104
|
-
- jpeg
|
|
105
|
-
- png
|
|
106
|
-
- gif
|
|
107
|
-
- webp
|
|
108
|
-
|
|
109
|
-
### 6. Custom Compact Model + Auto Resume
|
|
110
|
-
Also implemented in `extensions/extend-model.ts`.
|
|
111
|
-
|
|
112
|
-
- Supports a configured **compact model** through `session_before_compact`
|
|
113
|
-
- Preserves auto-resume behavior through `session_compact`
|
|
114
|
-
- Appends read/modified file summaries to compaction output
|
|
115
|
-
|
|
116
|
-
### 7. `/extend-model`
|
|
117
|
-
Implemented in `extensions/slash.ts`.
|
|
118
|
-
|
|
119
|
-
Interactive command for configuring:
|
|
120
|
-
- image model
|
|
121
|
-
- compact model
|
|
122
|
-
|
|
123
|
-
### 8. `/retry`
|
|
124
|
-
Implemented in `extensions/slash.ts`.
|
|
125
|
-
|
|
126
|
-
Allows continuing after interruption by:
|
|
127
|
-
- aborting the current run if needed
|
|
128
|
-
- sending a hidden continuation trigger
|
|
129
|
-
- injecting a one-turn retry note into the system prompt
|
|
130
|
-
|
|
131
|
-
### 9. Dynamic Subdirectory `AGENTS.md` / `CLAUDE.md`
|
|
132
|
-
Implemented in `extensions/subdir-agents.ts`.
|
|
71
|
+
### 5. Dynamic Subdirectory `AGENTS.md` / `CLAUDE.md`
|
|
133
72
|
|
|
134
73
|
When the agent reads or edits a file:
|
|
74
|
+
|
|
135
75
|
- discovers `AGENTS.md` / `CLAUDE.md` in the file's directory and ancestor directories
|
|
136
76
|
- injects newly discovered guidance into tool results
|
|
137
77
|
- persists discovered files into the session so they are restored on resume
|
|
138
78
|
|
|
139
|
-
###
|
|
140
|
-
Implemented in `extensions/session-title.ts`.
|
|
141
|
-
|
|
142
|
-
- Derives the session name from the first user message
|
|
143
|
-
- Avoids overriding a manually assigned session name
|
|
79
|
+
### 6. Extend Providers
|
|
144
80
|
|
|
145
|
-
|
|
81
|
+
Extend providers are registered via `/login` → "Use a subscription":
|
|
146
82
|
|
|
147
|
-
|
|
83
|
+
| Provider | Base URL |
|
|
84
|
+
| ---------- | ----------- |
|
|
85
|
+
| Ollama Cloud | `ollama.com/v1` |
|
|
86
|
+
| Baidu Qianfan | `qianfan.baidubce.com/v2/coding` |
|
|
87
|
+
| ARK Coding | `ark.cn-beijing.volces.com/api/coding/v3` |
|
|
148
88
|
|
|
149
|
-
|
|
150
|
-
pi install /path/to/decorated-pi
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Then reload Pi:
|
|
89
|
+
## Install
|
|
154
90
|
|
|
155
91
|
```bash
|
|
156
|
-
/
|
|
92
|
+
pi install /path/to/decorated-pi #local
|
|
93
|
+
pi install npm:decorated-pi #npm
|
|
94
|
+
pi install git:github.com/lcwecker/decorated-pi #github
|
|
157
95
|
```
|
|
158
96
|
|
|
159
|
-
|
|
160
|
-
Not published yet.
|
|
97
|
+
Then reload Pi
|
|
161
98
|
|
|
162
99
|
## Configuration
|
|
163
100
|
|
|
164
101
|
Runtime settings are stored in:
|
|
165
102
|
|
|
166
103
|
```text
|
|
167
|
-
~/.pi/agent/
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
Current keys:
|
|
171
|
-
- `imageModelKey`
|
|
172
|
-
- `compactModelKey`
|
|
173
|
-
|
|
174
|
-
Design rule:
|
|
175
|
-
- **only** `extensions/settings.ts` writes this file
|
|
176
|
-
- all other modules read through exported getters/setters
|
|
177
|
-
|
|
178
|
-
## Architecture
|
|
179
|
-
|
|
180
|
-
Entry point:
|
|
181
|
-
- `extensions/index.ts`
|
|
182
|
-
|
|
183
|
-
Main modules:
|
|
184
|
-
- `extensions/guidance.ts` — global system prompt guidance
|
|
185
|
-
- `extensions/safety.ts` — command guard, protected paths, write guard, secret redaction
|
|
186
|
-
- `extensions/smart-at.ts` — smart `@` autocomplete
|
|
187
|
-
- `extensions/extend-model.ts` — image fallback, compact model, auto-resume
|
|
188
|
-
- `extensions/slash.ts` — `/extend-model`, `/retry`
|
|
189
|
-
- `extensions/subdir-agents.ts` — dynamic `AGENTS.md` / `CLAUDE.md`
|
|
190
|
-
- `extensions/session-title.ts` — session naming
|
|
191
|
-
- `extensions/lsp/*` — LSP client, server manager, prompt wiring, tools
|
|
192
|
-
- `extensions/settings.ts` — config I/O
|
|
193
|
-
|
|
194
|
-
## Current Limitations
|
|
195
|
-
|
|
196
|
-
- `write` protection applies to the **LLM's `write` tool**; agent attempts to overwrite files via `bash` are handled separately by the dangerous-command gate
|
|
197
|
-
- shell overwrite detection only escalates when the target resolves to an **existing regular file**
|
|
198
|
-
- compact behavior still relies on Pi's normal compaction flow; this extension customizes the model and post-compact continuation, not the global compaction threshold UI
|
|
199
|
-
- npm distribution is not set up yet
|
|
200
|
-
- there is no dedicated automated test suite yet; current validation is based on Pi runtime checks, LSP diagnostics, and manual smoke tests
|
|
201
|
-
|
|
202
|
-
## Development Notes
|
|
203
|
-
|
|
204
|
-
Helpful checks during development:
|
|
205
|
-
|
|
206
|
-
```bash
|
|
207
|
-
pi install /path/to/decorated-pi
|
|
208
|
-
/reload
|
|
104
|
+
~/.pi/agent/decorated-pi.json
|
|
209
105
|
```
|
|
210
106
|
|
|
211
|
-
For focused validation, use:
|
|
212
|
-
- `lsp_diagnostics` on edited source files
|
|
213
|
-
- real `pi "..."` smoke tests for safety behavior
|
|
214
|
-
- manual autocomplete checks for `smart-at`
|
|
215
|
-
|
|
216
107
|
## License
|
|
217
108
|
|
|
218
109
|
MIT
|
|
@@ -387,12 +387,7 @@ export function setupExtendModel(pi: ExtensionAPI) {
|
|
|
387
387
|
auth.apiKey ?? "", auth.headers, signal, customInstructions, previousSummary);
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
|
|
391
|
-
const modifiedFiles = [...new Set([...fileOps.edited, ...fileOps.written])].sort();
|
|
392
|
-
if (readFiles.length > 0) summary += `\n\n<read-files>\n${readFiles.join("\n")}\n</read-files>`;
|
|
393
|
-
if (modifiedFiles.length > 0) summary += `\n\n<modified-files>\n${modifiedFiles.join("\n")}\n</modified-files>`;
|
|
394
|
-
|
|
395
|
-
return { compaction: { summary, firstKeptEntryId, tokensBefore, details: { readFiles, modifiedFiles } } };
|
|
390
|
+
return { compaction: { summary, firstKeptEntryId, tokensBefore } };
|
|
396
391
|
} catch (err) {
|
|
397
392
|
if (signal.aborted) return;
|
|
398
393
|
ctx.ui.notify(`Compact failed: ${err instanceof Error ? err.message : err}`, "error");
|
package/extensions/lsp/client.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP Client — JSON-RPC over stdio transport
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*
|
|
7
|
+
* Modifications: added rename() method, simplified type exports
|
|
8
|
+
*/
|
|
1
9
|
import { spawn, ChildProcess } from "node:child_process";
|
|
2
10
|
import { EventEmitter } from "node:events";
|
|
3
11
|
import { pathToFileURL } from "node:url";
|
|
@@ -204,7 +212,10 @@ export class LspClient extends EventEmitter {
|
|
|
204
212
|
async ensure_document_open(uri: string, text: string): Promise<void> {
|
|
205
213
|
const existing = this.#open_docs.get(uri);
|
|
206
214
|
if (existing) {
|
|
207
|
-
|
|
215
|
+
// Always force-sync: the file may have been modified externally
|
|
216
|
+
// (e.g. by pi's edit/write tools), and even if text matches the
|
|
217
|
+
// cached version, diagnostics may be stale due to changes in
|
|
218
|
+
// other files. Never skip the sync based on text comparison.
|
|
208
219
|
const next_version = existing.version + 1;
|
|
209
220
|
this.#open_docs.set(uri, { version: next_version, text });
|
|
210
221
|
this.#diagnostics_by_uri.delete(uri);
|
package/extensions/lsp/env.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP Child Process Environment — restricted env for LSP server processes
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*/
|
|
1
7
|
import { create_child_process_env as create_shared_child_process_env } from "@spences10/pi-child-env";
|
|
2
8
|
|
|
3
9
|
export function create_child_process_env(
|
package/extensions/lsp/format.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP Output Formatting — diagnostics, hover, locations, symbols
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*/
|
|
1
7
|
import { fileURLToPath } from "node:url";
|
|
2
8
|
import type { LspDiagnostic, LspHover, LspLocation, LspDocumentSymbol } from "./client.js";
|
|
3
9
|
import { LspClientStartError } from "./client.js";
|
package/extensions/lsp/index.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP Extension Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*/
|
|
1
7
|
import { LspServerManager } from "./server-manager.js";
|
|
2
8
|
import { register_lsp_tools } from "./tools.js";
|
|
3
9
|
import { setup_lsp_prompt } from "./prompt.js";
|
package/extensions/lsp/prompt.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP System Prompt — injects LSP guidance into agent system prompt
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*/
|
|
1
7
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
8
|
import { list_supported_languages } from "./servers.js";
|
|
3
9
|
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP Server Manager — lifecycle, per-language instances, project-local trust
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*/
|
|
1
7
|
import { resolve_project_trust } from "@spences10/pi-project-trust";
|
|
2
8
|
import { readFile } from "node:fs/promises";
|
|
3
9
|
import { isAbsolute, resolve } from "node:path";
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP Server Config — language detection, server commands, workspace roots
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*
|
|
7
|
+
* Modifications: added C/C++ (clangd) and Lua support
|
|
8
|
+
*/
|
|
1
9
|
import { existsSync } from "node:fs";
|
|
2
10
|
import { dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
3
11
|
|
|
@@ -31,7 +39,7 @@ const EXTENSION_LANGUAGES: Record<string, string> = {
|
|
|
31
39
|
".svelte": "svelte",
|
|
32
40
|
};
|
|
33
41
|
|
|
34
|
-
type LanguageConfig = {
|
|
42
|
+
export type LanguageConfig = {
|
|
35
43
|
language: string;
|
|
36
44
|
command: string;
|
|
37
45
|
args: string[];
|
package/extensions/lsp/tools.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP Tool Definitions — diagnostics, hover, definition, references, symbols, rename
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*
|
|
7
|
+
* Modifications: added lsp_find_symbol, lsp_rename, multi-file lsp_diagnostics
|
|
8
|
+
*/
|
|
1
9
|
import { defineTool, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
10
|
import { Type } from "typebox";
|
|
3
11
|
import { list_supported_languages } from "./servers.js";
|
package/extensions/lsp/trust.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP Binary Trust Store — project-local binary trust management
|
|
3
|
+
*
|
|
4
|
+
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
+
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
+
*/
|
|
1
7
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
2
8
|
import {
|
|
3
9
|
is_project_subject_trusted,
|