@stfade/pi-read-delegator 1.0.11 → 1.0.13

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/index.js DELETED
@@ -1,278 +0,0 @@
1
- "use strict";
2
- /**
3
- * index.ts — pi-read-delegator entry point
4
- *
5
- * Blocks read tools from the orchestrator and tells it to delegate every
6
- * file-read / search task to the 'reader' subagent.
7
- *
8
- * Architecture:
9
- * - Factory body: registration only (pi.on, pi.registerCommand, ensureReaderTemplate)
10
- * - session_start: dependency check → tool blocking → status bar
11
- * - before_agent_start: inject orchestrator system prompt
12
- * - tool_call: intercept bash read commands → redirect to reader
13
- */
14
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- var desc = Object.getOwnPropertyDescriptor(m, k);
17
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
- desc = { enumerable: true, get: function() { return m[k]; } };
19
- }
20
- Object.defineProperty(o, k2, desc);
21
- }) : (function(o, m, k, k2) {
22
- if (k2 === undefined) k2 = k;
23
- o[k2] = m[k];
24
- }));
25
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
- Object.defineProperty(o, "default", { enumerable: true, value: v });
27
- }) : function(o, v) {
28
- o["default"] = v;
29
- });
30
- var __importStar = (this && this.__importStar) || (function () {
31
- var ownKeys = function(o) {
32
- ownKeys = Object.getOwnPropertyNames || function (o) {
33
- var ar = [];
34
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
- return ar;
36
- };
37
- return ownKeys(o);
38
- };
39
- return function (mod) {
40
- if (mod && mod.__esModule) return mod;
41
- var result = {};
42
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
- __setModuleDefault(result, mod);
44
- return result;
45
- };
46
- })();
47
- Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.default = default_1;
49
- const fs = __importStar(require("node:fs"));
50
- const os = __importStar(require("node:os"));
51
- const path = __importStar(require("node:path"));
52
- const config_1 = require("./config");
53
- const reader_manager_1 = require("./reader-manager");
54
- const ui_1 = require("./ui");
55
- // ---------------------------------------------------------------------------
56
- // Bash read commands — these are intercepted and redirected to reader
57
- // ---------------------------------------------------------------------------
58
- const READ_BASH_COMMANDS = new Set([
59
- "cat",
60
- "grep",
61
- "find",
62
- "ls",
63
- "head",
64
- "tail",
65
- "less",
66
- "wc",
67
- "nl",
68
- "more",
69
- "bat",
70
- "rg",
71
- "fd",
72
- "awk",
73
- "du",
74
- "df",
75
- "stat",
76
- "file",
77
- "which",
78
- "where",
79
- "type",
80
- "dir",
81
- ]);
82
- // ---------------------------------------------------------------------------
83
- // Reader template path
84
- // ---------------------------------------------------------------------------
85
- function readerPath() {
86
- return path.join(os.homedir(), ".pi", "agent", "agents", "reader.md");
87
- }
88
- async function ensureReaderTemplate() {
89
- const rp = readerPath();
90
- if (fs.existsSync(rp))
91
- return;
92
- const content = [
93
- "---",
94
- "name: reader",
95
- "description: Token-efficient code reader that returns minimal results.",
96
- "tools: read, grep, find, ls",
97
- "model: lmstudio/nvidia/nemotron-3-nano-4b",
98
- "---",
99
- "",
100
- "You are a token-efficient analyst. Execute read/search/list tasks and return",
101
- "ONLY the essential result. Maximum 10 lines. Use bullet summaries.",
102
- "Never dump entire files. Focus only on what was asked.",
103
- ].join("\n");
104
- try {
105
- const dir = path.dirname(rp);
106
- fs.mkdirSync(dir, { recursive: true });
107
- await fs.promises.writeFile(rp, content, "utf8");
108
- }
109
- catch {
110
- // read-only home directory — template creation is best-effort
111
- }
112
- }
113
- // ---------------------------------------------------------------------------
114
- // Tool helpers
115
- // ---------------------------------------------------------------------------
116
- /** Determine which tools stay active after blocking read tools.
117
- * Always keeps "subagent" — the bridge to the reader. */
118
- function computeActiveTools(pi, blocked) {
119
- const all = pi.getAllTools();
120
- const blockedSet = new Set(blocked);
121
- const forceKeep = new Set(["subagent"]);
122
- return all
123
- .map((t) => t.name)
124
- .filter((name) => forceKeep.has(name) || !blockedSet.has(name));
125
- }
126
- // ---------------------------------------------------------------------------
127
- // Dependency check helpers — extracted to keep session_start handler lean
128
- // ---------------------------------------------------------------------------
129
- function createProgressCallback(ctx) {
130
- return (status) => {
131
- if (status === "installing") {
132
- ctx.ui.setStatus("read-delegator", "⏳ Installing pi-subagents…");
133
- ctx.ui.notify((0, ui_1.msg)("deps_installing") +
134
- " This may take up to 60 seconds. Please wait…", "info");
135
- }
136
- else if (status === "done") {
137
- ctx.ui.setStatus("read-delegator", (0, ui_1.msg)("status_active"));
138
- ctx.ui.notify("✅ pi-subagents installed successfully.", "info");
139
- }
140
- else if (status === "failed") {
141
- ctx.ui.setStatus("read-delegator", (0, ui_1.msg)("status_error"));
142
- }
143
- };
144
- }
145
- async function performDependencyCheck(ctx, config) {
146
- const promptFn = async (message) => {
147
- const ok = await ctx.ui.confirm("pi-subagents required", message);
148
- return ok ? "y" : "n";
149
- };
150
- const ready = await (0, reader_manager_1.checkDependencies)(promptFn, createProgressCallback(ctx));
151
- if (!ready) {
152
- config.enabled = false;
153
- (0, config_1.saveConfig)(config, { silent: true });
154
- ctx.ui.setStatus("read-delegator", (0, ui_1.msg)("status_error"));
155
- ctx.ui.notify((0, ui_1.msg)("deps_disabled"), "warning");
156
- return false;
157
- }
158
- if (!config.enabled) {
159
- config.enabled = true;
160
- (0, config_1.saveConfig)(config, { silent: true });
161
- }
162
- return true;
163
- }
164
- // ---------------------------------------------------------------------------
165
- // Extension factory — registration only; actions go inside events
166
- // ---------------------------------------------------------------------------
167
- async function default_1(pi) {
168
- const config = (0, config_1.loadConfig)();
169
- // Detect language
170
- (0, ui_1.getLanguage)(config.language);
171
- // Quick sync dependency check — interactive prompt is deferred to
172
- // session_start where we have access to ctx.ui.confirm().
173
- let depsReady = (0, reader_manager_1.isSubagentsInstalled)();
174
- let depsChecked = depsReady; // if already ready, no need to check again
175
- // -----------------------------------------------------------------------
176
- // 1. session_start: dependency check → tool blocking → status bar
177
- // -----------------------------------------------------------------------
178
- pi.on("session_start", async (_event, ctx) => {
179
- // --- Dependency check ---
180
- if (!depsChecked) {
181
- depsReady = await performDependencyCheck(ctx, config);
182
- depsChecked = true;
183
- if (!depsReady)
184
- return;
185
- }
186
- // --- Tool blocking ---
187
- if (config.enabled) {
188
- pi.setActiveTools(computeActiveTools(pi, config.blocked_tools));
189
- }
190
- ctx.ui.setStatus("read-delegator", config.enabled ? (0, ui_1.msg)("status_active") : (0, ui_1.msg)("status_off"));
191
- });
192
- // -----------------------------------------------------------------------
193
- // 2. before_agent_start: inject orchestrator system prompt
194
- // -----------------------------------------------------------------------
195
- pi.on("before_agent_start", (event, _ctx) => {
196
- if (!config.enabled)
197
- return;
198
- return {
199
- systemPrompt: event.systemPrompt + "\n\n" + config.orchestrator_prompt,
200
- };
201
- });
202
- // -----------------------------------------------------------------------
203
- // 3. tool_call: intercept bash read commands
204
- // -----------------------------------------------------------------------
205
- pi.on("tool_call", (event, _ctx) => {
206
- if (!config.enabled)
207
- return;
208
- if (event.toolName === "bash" || event.toolName === "shell") {
209
- const command = String(event.input?.command ?? "");
210
- if (!command)
211
- return;
212
- const firstWord = command.trim().split(/\s+/)[0]?.toLowerCase() ?? "";
213
- if (READ_BASH_COMMANDS.has(firstWord)) {
214
- return {
215
- block: true,
216
- reason: [
217
- 'Use subagent(agent: "' +
218
- config.reader_subagent_name +
219
- '", task: "Execute and summarize: ' +
220
- command +
221
- '")',
222
- "instead of running file-reading commands directly.",
223
- ].join(" "),
224
- };
225
- }
226
- }
227
- });
228
- // -----------------------------------------------------------------------
229
- // 4. /read-delegator command
230
- // -----------------------------------------------------------------------
231
- pi.registerCommand("read-delegator", {
232
- description: "Manage read delegation (on|off|status)",
233
- handler: (args, ctx) => {
234
- const sub = args?.trim().toLowerCase() ?? "status";
235
- switch (sub) {
236
- case "on":
237
- case "enable": {
238
- if (!depsReady) {
239
- ctx.ui.notify("pi-subagents not installed. Install it first to enable read delegation.", "warning");
240
- return;
241
- }
242
- config.enabled = true;
243
- (0, config_1.saveConfig)(config, { silent: true });
244
- pi.setActiveTools(computeActiveTools(pi, config.blocked_tools));
245
- ctx.ui.notify((0, ui_1.msg)("enabled"), "info");
246
- ctx.ui.setStatus("read-delegator", (0, ui_1.msg)("status_active"));
247
- return;
248
- }
249
- case "off":
250
- case "disable": {
251
- config.enabled = false;
252
- (0, config_1.saveConfig)(config, { silent: true });
253
- pi.setActiveTools(pi.getAllTools().map((t) => t.name));
254
- ctx.ui.notify((0, ui_1.msg)("disabled"), "info");
255
- ctx.ui.setStatus("read-delegator", (0, ui_1.msg)("status_off"));
256
- return;
257
- }
258
- case "status":
259
- default: {
260
- const lines = [
261
- "Read delegation: " +
262
- (config.enabled ? "🟢 enabled" : "🔴 disabled"),
263
- "Reader subagent: " + config.reader_subagent_name,
264
- "Dependencies: " + (depsReady ? "✅ ready" : "❌ missing"),
265
- "Blocked tools: " + config.blocked_tools.join(", "),
266
- ];
267
- ctx.ui.notify(lines.join("\n"), "info");
268
- return;
269
- }
270
- }
271
- },
272
- });
273
- // -----------------------------------------------------------------------
274
- // 5. Background: ensure reader.md template
275
- // -----------------------------------------------------------------------
276
- await ensureReaderTemplate();
277
- }
278
- //# sourceMappingURL=index.js.map
@@ -1,8 +0,0 @@
1
- ---
2
- name: reader
3
- description: Read-only file agent that returns minimal results
4
- tools: read, grep, find, ls
5
- model: lmstudio/nemotron-mini
6
- ---
7
-
8
- You are a token-efficient assistant. Execute read/search tasks and return ONLY the essential result. Max 5 lines or a single number. Never dump files. If running a shell command, return only the output, nothing else.
File without changes
File without changes
File without changes