@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/README.md +178 -69
- package/{bash-filter.d.ts → dist/bash-filter.d.ts} +16 -6
- package/dist/bash-filter.js +420 -0
- package/{config.d.ts → dist/config.d.ts} +1 -1
- package/{config.js → dist/config.js} +38 -58
- package/dist/index.js +295 -0
- package/{reader-manager.d.ts → dist/reader-manager.d.ts} +26 -1
- package/{reader-manager.js → dist/reader-manager.js} +159 -69
- package/{tool-blocker.js → dist/tool-blocker.js} +13 -20
- package/{ui.js → dist/ui.js} +15 -62
- package/package.json +20 -17
- package/bash-filter.js +0 -242
- package/index.js +0 -278
- package/templates/reader.md +0 -8
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{tool-blocker.d.ts → dist/tool-blocker.d.ts} +0 -0
- /package/{ui.d.ts → dist/ui.d.ts} +0 -0
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
|
package/templates/reader.md
DELETED
|
@@ -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
|