pi-opium 0.4.0 → 0.4.2
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/CHANGELOG.md +19 -0
- package/README.md +3 -2
- package/agents/researcher.md +8 -3
- package/defaults/opium.json +1 -1
- package/package.json +1 -1
- package/src/doctor.ts +1 -5
- package/src/launch.ts +36 -1
- package/src/mcp.ts +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.2
|
|
4
|
+
|
|
5
|
+
- **researcher reads library docs with the Context7 CLI** (`ctx7 library`,
|
|
6
|
+
then `ctx7 docs`) instead of the `context7` MCP server. Install with
|
|
7
|
+
`npm i -g ctx7` (or use `npx ctx7@latest`); `ctx7 login` raises the
|
|
8
|
+
limits. researcher gets `bash`, but a guard blocks every call that is
|
|
9
|
+
not a single `ctx7 library|docs` command. The default `mcpServers` for
|
|
10
|
+
researcher is now `gh_grep` only.
|
|
11
|
+
|
|
12
|
+
## 0.4.1
|
|
13
|
+
|
|
14
|
+
- **Fix:** `/opium-doctor` no longer warns about the default `codegraph`,
|
|
15
|
+
`context7` and `gh_grep` servers when a `pi-mcp-adapter` config exists
|
|
16
|
+
without its metadata cache.
|
|
17
|
+
- Install guide: back up an existing `opium.json` first, keep a model
|
|
18
|
+
the user set by moving it into the preset, copy model ids exactly, and
|
|
19
|
+
tell the user when a provider still needs a sign-in.
|
|
20
|
+
- README installs from npm (`pi install npm:pi-opium`).
|
|
21
|
+
|
|
3
22
|
## 0.4.0
|
|
4
23
|
|
|
5
24
|
Install by asking your agent, see every agent at work.
|
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ checks the result.
|
|
|
45
45
|
Or by hand:
|
|
46
46
|
|
|
47
47
|
```sh
|
|
48
|
-
pi install
|
|
48
|
+
pi install npm:pi-opium
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
Start Pi (or `/reload` a running session) and keep working as usual. Every agent starts on your
|
|
@@ -93,7 +93,8 @@ it's done.
|
|
|
93
93
|
## Works better with
|
|
94
94
|
|
|
95
95
|
- [pi-web-access](https://github.com/nicobailon/pi-web-access): lets researcher search the web and read pages.
|
|
96
|
-
- `
|
|
96
|
+
- `npm i -g ctx7` (the Context7 CLI; or `npx ctx7@latest`, optional `ctx7 login` for higher limits): up-to-date library docs for researcher.
|
|
97
|
+
- `pi mcp add gh_grep --url https://mcp.grep.app`: GitHub code search for researcher.
|
|
97
98
|
- Any other MCP server added with `pi mcp add`: give it to an agent in `opium.json`, for example `"scout": { "mcpServers": ["my-index"] }`.
|
|
98
99
|
|
|
99
100
|
## Config
|
package/agents/researcher.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: researcher
|
|
3
3
|
description: External knowledge and library research. Use for current library docs, API references, examples, version-specific behavior, bug investigations and web retrieval; answers with sources. Runs in the background (needs web tools).
|
|
4
4
|
advertise: true
|
|
5
|
-
tools: read, grep, find, ls, web_search, fetch_content, get_search_content, source_check
|
|
5
|
+
tools: read, grep, find, ls, bash, web_search, fetch_content, get_search_content, source_check
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
You are Researcher - a research specialist for codebases and documentation.
|
|
@@ -16,14 +16,19 @@ You are Researcher - a research specialist for codebases and documentation.
|
|
|
16
16
|
- Understand library internals and best practices
|
|
17
17
|
|
|
18
18
|
**Tools to use**:
|
|
19
|
+
- Library, framework and SDK docs and API references: ALWAYS try ctx7 first, in two steps via bash:
|
|
20
|
+
1. `ctx7 library <name> "<query>"` resolves a library ID (`/org/project[/version]`); use the official name ("Next.js", not "nextjs app")
|
|
21
|
+
2. `ctx7 docs <libraryId> "<query>"` fetches the docs; pick the best match by reputation, score and version
|
|
22
|
+
- At most 3 ctx7 calls per question; never put secrets or proprietary code in a query
|
|
23
|
+
- Then use web_search/fetch_content to fill gaps or confirm
|
|
19
24
|
- web_search: find official docs, changelogs, issues, examples (use several varied queries)
|
|
20
25
|
- fetch_content: read a page, a PDF or a GitHub repository
|
|
21
26
|
- source_check: gather sources for a specific claim
|
|
22
27
|
- get_search_content: page through stored results
|
|
23
|
-
-
|
|
28
|
+
- GitHub code search MCP tools (grep.app), if available
|
|
24
29
|
|
|
25
30
|
**File operations rules**:
|
|
26
|
-
- READ-ONLY: inspect and report; do not modify files.
|
|
31
|
+
- READ-ONLY: inspect and report; do not modify files. Shell is only for `ctx7 library` / `ctx7 docs`; every other command is blocked.
|
|
27
32
|
- Use find/grep for discovery and read for file contents.
|
|
28
33
|
- Do not spawn subagents; you are not the orchestrator.
|
|
29
34
|
|
package/defaults/opium.json
CHANGED
package/package.json
CHANGED
package/src/doctor.ts
CHANGED
|
@@ -103,11 +103,7 @@ export const RUNNER_EXPORTS: readonly string[] = [
|
|
|
103
103
|
const PING_TIMEOUT_MS = 30_000;
|
|
104
104
|
const PING_CONCURRENCY = 4;
|
|
105
105
|
// shipped defaults of scout, fixer, senior and researcher; absent is fine
|
|
106
|
-
const OPTIONAL_MCP: ReadonlySet<string> = new Set([
|
|
107
|
-
'codegraph',
|
|
108
|
-
'context7',
|
|
109
|
-
'gh_grep',
|
|
110
|
-
]);
|
|
106
|
+
const OPTIONAL_MCP: ReadonlySet<string> = new Set(['codegraph', 'gh_grep']);
|
|
111
107
|
|
|
112
108
|
const ok = (title: string, detail?: string): Check => ({
|
|
113
109
|
status: 'ok',
|
package/src/launch.ts
CHANGED
|
@@ -170,6 +170,39 @@ export const readOnlyLsp: ExtensionFactory = (pi) => {
|
|
|
170
170
|
});
|
|
171
171
|
};
|
|
172
172
|
|
|
173
|
+
// A single `ctx7 library|docs ...` (or via npx) with no shell syntax: no
|
|
174
|
+
// separators, pipes, redirects, substitution, variables or newlines.
|
|
175
|
+
export const CTX7_COMMAND = new RegExp(
|
|
176
|
+
'^\\s*(?:ctx7|npx(?:\\s+(?:-y|--yes))?\\s+ctx7(?:@[\\w.-]+)?)' +
|
|
177
|
+
'\\s+(?:library|docs)(?:\\s[^;&|`$<>\\r\\n]*)?\\s*$',
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
// researcher gets a shell only to read library docs through the Context7
|
|
181
|
+
// CLI; everything else is refused.
|
|
182
|
+
export const ctx7OnlyBash: ExtensionFactory = (pi) => {
|
|
183
|
+
pi.on('tool_call', (event) => {
|
|
184
|
+
const { command } = event.input as { command?: unknown };
|
|
185
|
+
const allowed =
|
|
186
|
+
event.toolName !== 'bash' ||
|
|
187
|
+
(typeof command === 'string' && CTX7_COMMAND.test(command));
|
|
188
|
+
return allowed
|
|
189
|
+
? undefined
|
|
190
|
+
: {
|
|
191
|
+
block: true,
|
|
192
|
+
reason:
|
|
193
|
+
'bash is limited to a single `ctx7 library <name> "<query>"` ' +
|
|
194
|
+
'or `ctx7 docs <libraryId> "<query>"` call (optionally via ' +
|
|
195
|
+
'`npx -y ctx7@latest`), with no pipes, redirects, `;`, `&`, ' +
|
|
196
|
+
'substitution or variables',
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// Agents whose bash tool is restricted, and how.
|
|
202
|
+
const BASH_GUARDS: Readonly<Record<string, ExtensionFactory>> = {
|
|
203
|
+
researcher: ctx7OnlyBash,
|
|
204
|
+
};
|
|
205
|
+
|
|
173
206
|
export const buildLaunch = (
|
|
174
207
|
def: AgentDefinition,
|
|
175
208
|
ctx: LaunchContext,
|
|
@@ -270,11 +303,13 @@ export const buildLaunch = (
|
|
|
270
303
|
!tools.includes('write');
|
|
271
304
|
const lazy =
|
|
272
305
|
tools !== undefined && packages.some((name) => LAZY_PACKAGES.has(name));
|
|
273
|
-
|
|
306
|
+
const bashGuard = tools?.includes('bash') ? BASH_GUARDS[def.name] : undefined;
|
|
307
|
+
if (vision || readOnly || lazy || bashGuard) {
|
|
274
308
|
start.extensionFactories = [
|
|
275
309
|
...sessionGuards,
|
|
276
310
|
...(vision ? [vision.tool(def.name)] : []),
|
|
277
311
|
...(readOnly ? [readOnlyLsp] : []),
|
|
312
|
+
...(bashGuard ? [bashGuard] : []),
|
|
278
313
|
...(lazy && tools ? [activateAllowed(tools)] : []),
|
|
279
314
|
];
|
|
280
315
|
}
|
package/src/mcp.ts
CHANGED
|
@@ -95,11 +95,14 @@ export const resolveMcpTools = (
|
|
|
95
95
|
if (!existsSync(configPath)) return { tools, errors };
|
|
96
96
|
const config = read(configPath, 'MCP config');
|
|
97
97
|
if (typeof config === 'string') return { tools, errors: [config] };
|
|
98
|
-
const cache = read(cachePath, 'MCP metadata cache');
|
|
99
|
-
if (typeof cache === 'string') return { tools, errors: [cache] };
|
|
100
|
-
|
|
101
98
|
const settings = isRecord(config.settings) ? config.settings : {};
|
|
102
99
|
const defs = isRecord(config.mcpServers) ? config.mcpServers : {};
|
|
100
|
+
// the cache only matters for servers the config defines
|
|
101
|
+
if (!servers.some((server) => isRecord(defs[server]))) {
|
|
102
|
+
return { tools, errors };
|
|
103
|
+
}
|
|
104
|
+
const cache = read(cachePath, 'MCP metadata cache');
|
|
105
|
+
if (typeof cache === 'string') return { tools, errors: [cache] };
|
|
103
106
|
const cached = isRecord(cache.servers) ? cache.servers : {};
|
|
104
107
|
for (const server of servers) {
|
|
105
108
|
const def = defs[server];
|