@openlines/opl-pi-sht 0.1.14 → 0.1.16

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
@@ -8,21 +8,41 @@ A portable collection of various Pi coding agent extensions. Repository director
8
8
 
9
9
  ### Pi package
10
10
 
11
- Install a versioned GitHub release with Pi:
11
+ Install a versioned release from npm or GitHub. Both ship identical content; pick one source per machine, because Pi treats the npm and Git entries as separate packages and installing both loads every extension twice.
12
12
 
13
13
  ```bash
14
- pi install git:github.com/linellazatin/opl-pi-sht@v0.1.14
14
+ pi install npm:@openlines/opl-pi-sht@0.1.15
15
+ pi install git:github.com/linellazatin/opl-pi-sht@v0.1.15
15
16
  ```
16
17
 
17
- Pi installs the package under `~/.pi/agent/git/github.com/linellazatin/opl-pi-sht` and runs root `npm install`, so `opl-webaccess` and `opl-browser` runtime dependencies are available. Pi packages do not install optional extension config files; copy only the configs you need from that checkout to `~/.pi/agent/configs/`.
18
+ > Omitting the version on the npm source tracks the latest published release; Git refs stay pinned, so move them with `pi install ...@v<new>`.
19
+
20
+ Pi installs the package under `~/.pi/agent/npm/node_modules/@openlines/opl-pi-sht` (npm) or `~/.pi/agent/git/github.com/linellazatin/opl-pi-sht` (Git) and runs root `npm install`, so `opl-webaccess` and `opl-browser` runtime dependencies are available. Pi packages do not install optional extension config files; copy only the configs you need from that checkout's `configs/` to `~/.pi/agent/configs/`.
18
21
 
19
22
  `opl-browser` also needs Chromium once after package installation:
20
23
 
21
24
  ```bash
22
- cd ~/.pi/agent/git/github.com/linellazatin/opl-pi-sht
25
+ cd ~/.pi/agent/npm/node_modules/@openlines/opl-pi-sht # or the git checkout path
23
26
  npx playwright install chromium
24
27
  ```
25
28
 
29
+ #### Selecting extensions
30
+
31
+ `pi install` has no per-extension flag like `./install.sh --only`. After installing the package, narrow it in `~/.pi/agent/settings.json` using the object form (filters are globs relative to the package root and layer on top of the package manifest):
32
+
33
+ ```json
34
+ {
35
+ "packages": [
36
+ {
37
+ "source": "npm:@openlines/opl-pi-sht@0.1.15",
38
+ "extensions": ["extensions/opl-init/index.ts", "extensions/opl-todo/index.ts"]
39
+ }
40
+ ]
41
+ }
42
+ ```
43
+
44
+ `pi config` provides the same control interactively: toggle individual extensions from an installed package without editing globs.
45
+
26
46
  ### Checkout installer
27
47
 
28
48
  ```bash
@@ -152,7 +172,7 @@ The fixed cost of a full install is small and paid once per session, then cached
152
172
 
153
173
  ## Configuration
154
174
 
155
- Copy applicable files from [`configs/`](configs/) to `~/.pi/agent/configs/`. For a Pi Git package installation, the source directory is `~/.pi/agent/git/github.com/linellazatin/opl-pi-sht/configs/`:
175
+ Copy applicable files from [`configs/`](configs/) to `~/.pi/agent/configs/`. For a Pi package installation, the source directory is `~/.pi/agent/npm/node_modules/@openlines/opl-pi-sht/configs/` (npm) or `~/.pi/agent/git/github.com/linellazatin/opl-pi-sht/configs/` (Git):
156
176
 
157
177
  - `opl-footer.json`, `opl-input.json`, `opl-modes.json`, `opl-todo.json`, `opl-webaccess.json`
158
178
  - `opl-browser` has optional configuration (`opl-browser.json`); all fields default, so it works without any config file.
@@ -167,7 +187,7 @@ See each extension README for commands, behavior, configuration fields, runtime
167
187
 
168
188
  ## Runtime requirements
169
189
 
170
- All extensions use Pi's normal extension discovery. Pi installs `opl-webaccess` extraction dependencies and Playwright automatically when installed as a Git package. For the checkout installer, install nested runtime dependencies before using those extensions:
190
+ All extensions use Pi's normal extension discovery. Pi installs `opl-webaccess` extraction dependencies and Playwright automatically when installed as an npm or Git package. For the checkout installer, install nested runtime dependencies before using those extensions:
171
191
 
172
192
  ```bash
173
193
  cd extensions/opl-webaccess
@@ -178,9 +198,9 @@ npm install
178
198
  npx playwright install chromium
179
199
  ```
180
200
 
181
- A Pi Git package still needs the one-time `npx playwright install chromium` command shown above.
201
+ A Pi package (npm or Git) still needs the one-time `npx playwright install chromium` command shown above.
182
202
 
183
- `opl-simplebench` writes a full JSON benchmark artifact in Pi's current working directory by default. `--test-all` additionally writes `research.md` and `page.html` beside `result.json` in a result bundle. Copy `configs/opl-simplebench.json.sample` to `~/.pi/agent/configs/opl-simplebench.json` to configure DDGS/SearXNG research and optional llama-server/llamagputop metadata endpoints. Use `/simplebench --no-artifact` or `simplebench({ no_artifact: true })` when responses must not be written to disk. Provider credentials remain outside tracked configuration; configure them through Pi provider settings, environment variables, or Pi authentication.
203
+ `opl-simplebench` writes a full JSON benchmark artifact in Pi's current working directory by default. `--test-all` additionally writes `research.md` and `page.html` beside `result.json` in a result bundle. `/simplebench --sequence` runs a templated multi-run protocol (for example a model warm-up curve) defined in the `runSequence` block, with per-iteration tags, optional llama-server/llamagputop metrics, and a configurable pause between iterations. Copy `configs/opl-simplebench.json.sample` to `~/.pi/agent/configs/opl-simplebench.json` to configure DDGS/SearXNG research, optional llama-server/llamagputop metadata endpoints, and the run sequence. Use `/simplebench --no-artifact` or `simplebench({ no_artifact: true })` when responses must not be written to disk. Provider credentials remain outside tracked configuration; configure them through Pi provider settings, environment variables, or Pi authentication.
184
204
 
185
205
  ## Tests
186
206
 
@@ -1,8 +1,19 @@
1
1
  {
2
- "_comment": "Copy to ~/.pi/agent/configs/opl-simplebench.json. Endpoints are optional and only used by their corresponding Simplebench flags.",
2
+ "_comment": "Copy to ~/.pi/agent/configs/opl-simplebench.json. Endpoints are optional and only used by their corresponding Simplebench flags. runSequence powers /simplebench --sequence: each entry is a flag string; llamaMetrics appends --llama-server --llamagputop to every entry; pauseMs sleeps between iterations.",
3
3
  "researchSearchProvider": "ddgs",
4
4
  "researchSearchUrl": "http://127.0.0.1:8000",
5
5
  "researchMaxResults": 5,
6
6
  "llamaServerUrl": "http://127.0.0.1:8080/v1",
7
- "llamagputopUrl": "http://127.0.0.1:4321/stats"
7
+ "llamagputopUrl": "http://127.0.0.1:4321/stats",
8
+ "runSequence": {
9
+ "enabled": false,
10
+ "llamaMetrics": true,
11
+ "pauseMs": 5000,
12
+ "sequence": [
13
+ "--coding-lite --tag=coldest",
14
+ "--3ptest --tag=colder",
15
+ "--coding-lite --tag=semiwarm",
16
+ "--test-all --research-live --tag=warm"
17
+ ]
18
+ }
8
19
  }
@@ -19,7 +19,7 @@ Row 1 right: <context bar> <pct%> / <max tokens>
19
19
  Row 2 left: Thinking: <LEVEL> | <active mode>
20
20
  Row 2 right: T: <total> (<cached> cached) ↑ <in> ↓ <out> | $<cost>
21
21
 
22
- Row 3 left: <turns> turns · <steps> steps · <model requests> mreq · <tool calls> mtool
22
+ Row 3 left: <prompts> prompts · <api calls> api calls · <tool calls> tool calls
23
23
  Row 3 right: LLM <time> (<last-turn TAT>) · Tool <time> | TTFT <time> · <tokens>/s | Cache <percent>%
24
24
  ```
25
25
 
@@ -31,7 +31,7 @@ The third row is populated after the first completed turn. Its session and perfo
31
31
  - **Context bar**: configurable gradient bar with percentage and context-window size
32
32
  - **Git integration**: branch plus staged, unstaged, and untracked counts, with invalidation after relevant file and Git commands
33
33
  - **Token and cost tracking**: total, cache, input/output, and accumulated cost segments
34
- - **Session statistics**: turns, tool steps, model requests, and model tool calls
34
+ - **Session statistics**: prompt, API-call, and model tool-call counts
35
35
  - **Performance statistics**: cumulative LLM/tool duration, most recent user-prompt-to-completion turnaround time, average time to first token, output rate, and cache-hit percentage
36
36
  - **Thinking and mode indicators**: thinking-level colors plus caveman, plan, chat, or unified mode segments when available
37
37
  - **Nerd Font support**: automatic detection with plain-icon fallbacks
@@ -152,7 +152,7 @@ The `git` segment shows:
152
152
 
153
153
  ## Session and Performance Statistics
154
154
 
155
- The `session_stats` segment shows turns, tool steps, and (when available) model requests and model tool calls for the current branch; turns and steps are reconstructed from session history so they survive quit/resume.
155
+ The `session_stats` segment shows prompt, API-call, and model tool-call counts for the current branch, reconstructed from session history so they survive quit/resume. `prompts` counts user messages and `api calls` counts completed assistant responses, so one prompt typically drives many API calls (each tool round trip is one call); `tool calls` counts the tool-call blocks the model emitted.
156
156
 
157
157
  The `perf_stats` segment shows cumulative session LLM and tool time, average time to first token, output tokens/sec, and cache-hit percentage. The `LLM` figure is followed by the most recent user-prompt-to-completion turnaround time in parentheses, e.g. `LLM 18m 22s (2m 13s)`. This turnaround reflects only fully-settled turns (the `agent_settled` signal, after any retries or compaction), so it stays blank until the first turn completes. All `perf_stats` timing values are ephemeral — they reset each session and are not reconstructed from branch history.
158
158
 
@@ -103,11 +103,7 @@ export default function footer(pi: ExtensionAPI) {
103
103
  let cachedUsageStats: UsageStats | null = null;
104
104
  let tuiRef: TUI | null = null;
105
105
 
106
- // Session stats accumulators
107
- let turns = 0;
108
- let steps = 0;
109
- let modelRequests = 0;
110
- let modelToolCalls = 0;
106
+ // Session stats accumulators (timing only; counts are reconstructed from the branch)
111
107
  let llmMs = 0;
112
108
  let toolMs = 0;
113
109
  let ttftSamples: number[] = [];
@@ -124,10 +120,6 @@ export default function footer(pi: ExtensionAPI) {
124
120
  currentCtx = ctx;
125
121
  lastBranchLength = 0;
126
122
  cachedUsageStats = null;
127
- turns = 0;
128
- steps = 0;
129
- modelRequests = 0;
130
- modelToolCalls = 0;
131
123
  llmMs = 0;
132
124
  toolMs = 0;
133
125
  ttftSamples = [];
@@ -165,13 +157,11 @@ export default function footer(pi: ExtensionAPI) {
165
157
  });
166
158
 
167
159
  pi.on("turn_end", async (_event: unknown, _ctx: ExtensionContext) => {
168
- turns++;
169
160
  const elapsed = Date.now() - turnStartMs;
170
161
  llmMs += Math.max(0, elapsed - toolMsThisTurn);
171
162
  });
172
163
 
173
164
  pi.on("tool_execution_start", async (event: { toolCallId: string }, _ctx: ExtensionContext) => {
174
- steps++;
175
165
  toolStartTimes.set(event.toolCallId, Date.now());
176
166
  });
177
167
 
@@ -278,18 +268,15 @@ export default function footer(pi: ExtensionAPI) {
278
268
  // This allows litellm proxy to correctly separate local vs cloud models
279
269
  const isLocalModel = ctx.model?.id?.startsWith?.("local.") ?? false;
280
270
 
281
- // Reconstruct turns/steps from branch so they survive quit/resume.
271
+ // Reconstruct prompt/API-call/tool-call counts from the branch so they survive quit/resume.
282
272
  // Timing stats (llmMs, toolMs, ttftSamples) are ephemeral — not stored in messages.
283
- const branchTurns = completedMessages.length;
284
- const branchSteps = branch.filter(
285
- (e) => e.type === "message" && (e as AssistantMessageEvent).message?.role === "toolResult",
273
+ const branchPrompts = branch.filter(
274
+ (e) => e.type === "message" && (e as AssistantMessageEvent).message?.role === "user",
286
275
  ).length;
287
-
288
- // Count model requests (each assistant message = 1 request)
289
- const branchModelRequests = completedMessages.length;
276
+ const branchApiCalls = completedMessages.length;
290
277
 
291
278
  // Count tool calls from assistant message content
292
- const branchModelToolCalls = completedMessages.reduce((sum, msg) => {
279
+ const branchToolCalls = completedMessages.reduce((sum, msg) => {
293
280
  const content = (msg as any).content || [];
294
281
  return sum + content.filter((block: any) => block?.type === "toolCall").length;
295
282
  }, 0);
@@ -310,7 +297,7 @@ export default function footer(pi: ExtensionAPI) {
310
297
  theme,
311
298
  colors,
312
299
  icons: getIcons(effectiveConfig.icons),
313
- sessionStats: { turns: branchTurns, steps: branchSteps, modelRequests: branchModelRequests, modelToolCalls: branchModelToolCalls, llmMs, toolMs, ttftSamples, lastTurnaroundMs },
300
+ sessionStats: { prompts: branchPrompts, apiCalls: branchApiCalls, toolCalls: branchToolCalls, llmMs, toolMs, ttftSamples, lastTurnaroundMs },
314
301
  };
315
302
  }
316
303
 
@@ -19,22 +19,15 @@ export function formatMs(ms: number): string {
19
19
  export const sessionStatsSegment = {
20
20
  id: "session_stats" as const,
21
21
  render(ctx: SegmentContext): RenderedSegment {
22
- const { turns, steps, modelRequests, modelToolCalls } = ctx.sessionStats;
23
- if (turns === 0) return { content: "", visible: false };
22
+ const { prompts, apiCalls, toolCalls } = ctx.sessionStats;
23
+ if (prompts === 0) return { content: "", visible: false };
24
24
 
25
- const parts: string[] = [
26
- val(ctx, `${turns}`) + dim(ctx, " turns"),
27
- val(ctx, `${steps}`) + dim(ctx, " steps"),
25
+ const parts = [
26
+ val(ctx, `${prompts}`) + dim(ctx, " prompts"),
27
+ val(ctx, `${apiCalls}`) + dim(ctx, " api calls"),
28
+ val(ctx, `${toolCalls}`) + dim(ctx, " tool calls"),
28
29
  ];
29
30
 
30
- // Add model stats if available
31
- if (modelRequests > 0) {
32
- parts.push(val(ctx, `${modelRequests}`) + dim(ctx, " mreq"));
33
- }
34
- if (modelToolCalls > 0) {
35
- parts.push(val(ctx, `${modelToolCalls}`) + dim(ctx, " mtool"));
36
- }
37
-
38
31
  return { content: parts.join(dim(ctx, " · ")), visible: true };
39
32
  },
40
33
  };
@@ -42,8 +35,8 @@ export const sessionStatsSegment = {
42
35
  export const perfStatsSegment = {
43
36
  id: "perf_stats" as const,
44
37
  render(ctx: SegmentContext): RenderedSegment {
45
- const { turns, llmMs, toolMs, ttftSamples, lastTurnaroundMs } = ctx.sessionStats;
46
- if (turns === 0) return { content: "", visible: false };
38
+ const { prompts, llmMs, toolMs, ttftSamples, lastTurnaroundMs } = ctx.sessionStats;
39
+ if (prompts === 0) return { content: "", visible: false };
47
40
 
48
41
  const { input, output, cacheRead } = ctx.usageStats;
49
42
 
@@ -97,12 +97,11 @@ export interface UsageStats {
97
97
  cost: number;
98
98
  }
99
99
 
100
- // Session performance stats accumulated via events
100
+ // Session performance stats accumulated via events; counts reconstructed from the branch
101
101
  export interface SessionStats {
102
- turns: number;
103
- steps: number;
104
- modelRequests: number;
105
- modelToolCalls: number;
102
+ prompts: number;
103
+ apiCalls: number;
104
+ toolCalls: number;
106
105
  llmMs: number;
107
106
  toolMs: number;
108
107
  ttftSamples: number[];
@@ -8,12 +8,14 @@ Auditable Pi model benchmark for closed-answer contracts, JSON instruction follo
8
8
  /simplebench
9
9
  /simplebench <model>
10
10
  /simplebench <model> [--no-artifact] [--thinking-max]
11
+ /simplebench <model> --3ptest
11
12
  /simplebench <model> --coding-lite
12
13
  /simplebench <model> --test-all
13
14
  /simplebench <model> --research-live
14
15
  /simplebench <model> --llama-server
15
16
  /simplebench <model> --llamagputop
16
17
  /simplebench <model> --tag=<word>
18
+ /simplebench <model> --sequence
17
19
  /simplebench --all [--no-artifact]
18
20
  /simplebench --all --test-all
19
21
  /simplebench --help
@@ -39,6 +41,8 @@ simplebench({ model: "global.openai.gpt-5.6-terra", test_all: true })
39
41
  - Twenty fixed closed-answer contracts, one strict JSON instruction test, and one chained tool-call test.
40
42
  - Six opt-in execution-backed coding tasks in disposable directories (`--coding-lite`).
41
43
  - `--test-all` runs baseline, coding-lite, and deterministic grounded research; `--research-live` adds the configured live research-artifact integration smoke test. `--all` still selects every Ollama model.
44
+ - `--3ptest` is the explicit form of the default baseline suite (reasoning, instruction following, tool calls). It changes nothing about the run; artifacts already name the baseline suite `3ptest`.
45
+ - `--sequence` runs the templated multi-iteration benchmark stored in `opl-simplebench.json` (`runSequence`): sequential iterations, per-entry flags and `--tag`, optional `llamaMetrics` and `pauseMs` cooldown. See "Run a templated sequence" below.
42
46
  - `--llama-server` (`llama_server: true`) captures configured direct llama-server `/props` and `/metrics` without changing inference routing, so it works with a LiteLLM proxy.
43
47
  - `--llamagputop` (`llamagputop: true`) captures configured llama.cpp `/stats` metadata independently of the inference provider; its served model ID is authoritative.
44
48
  - `--tag=<word>` (`tag: "<word>"`) labels a run: stored as `benchmark.tag` and prefixed onto the artifact file or bundle name, for example `simplebench-coldrun-coding-lite-<model>-...`. The tag must be a single word (letters, digits, dot, dash, underscore).
@@ -80,6 +84,37 @@ Use this in sensitive environments. The terminal summary still reports category
80
84
 
81
85
  `--all` is intentionally limited to Ollama discovery. It writes one artifact per model unless `--no-artifact` is set.
82
86
 
87
+ ### Run a templated sequence
88
+
89
+ ```text
90
+ /simplebench --sequence
91
+ ```
92
+
93
+ Repeating a warm-up protocol (first-run-after-boot coding check, then baseline, then the full suite) means re-typing the same flags every session. `--sequence` reads the `runSequence` block from `~/.pi/agent/configs/opl-simplebench.json` and runs each entry as its own iteration against the current model (or the model passed with `--sequence`):
94
+
95
+ ```json
96
+ {
97
+ "runSequence": {
98
+ "enabled": true,
99
+ "llamaMetrics": true,
100
+ "pauseMs": 5000,
101
+ "sequence": [
102
+ "--coding-lite --tag=coldest",
103
+ "--3ptest --tag=colder",
104
+ "--coding-lite --tag=semiwarm",
105
+ "--test-all --research-live --tag=warm"
106
+ ]
107
+ }
108
+ }
109
+ ```
110
+
111
+ - `enabled` gates the flag: `/simplebench --sequence` errors when it is missing or `false`. A bare `/simplebench` is unaffected.
112
+ - Each `sequence` entry is the same flag string you would type after `/simplebench`, including its own `--tag`.
113
+ - `llamaMetrics: true` appends `--llama-server --llamagputop` to every entry, so local server stats are captured per iteration without repeating the flags.
114
+ - `pauseMs` sleeps between iterations (never after the last one), including after a failed iteration, so thermal/KV-cache cooldown stays consistent across the warm-up curve.
115
+ - Iterations run sequentially and each writes its normal artifact/bundle; a failed iteration is reported and the sequence continues. A final summary line counts completed iterations.
116
+ - Entries containing `--all` or `--sequence` are rejected before anything runs, as are invalid configurations (empty sequence, negative `pauseMs`) and invalid per-entry tags. The outer `--tag` is ignored; each entry carries its own.
117
+
83
118
  ### Grounded research in `--test-all`
84
119
 
85
120
  `--test-all` runs a deterministic agent workflow after coding-lite. `web_search` returns three benchmark-local source cards. The model must write every required finding as a Markdown bullet with its inline source ID (`[S1]`, `[S2]`) and list each cited source under `## Sources` as a Markdown link, for example `- [S1](https://research.fixture/S1)`. The verifier checks each exact claim-to-source relationship, source-list URL, tool trace, and the responsive minimalist `page.html` contract. It invokes no LLM judge, external search service, embedding model, or entailment model.
@@ -94,7 +129,7 @@ When coding-lite is enabled, each coding task is recorded as a `kind: "coding"`
94
129
 
95
130
  ### Configured metadata (`--llama-server`, `--llamagputop`)
96
131
 
97
- Copy `configs/opl-simplebench.json.sample` to `~/.pi/agent/configs/opl-simplebench.json`. It uses camelCase fields: `llamaServerUrl`, `llamagputopUrl`, `researchSearchProvider`, `researchSearchUrl`, and `researchMaxResults`. `--llama-server` captures `GET /props` and `/metrics` from configured `llamaServerUrl`; inference remains on the configured provider route, including LiteLLM. `--llamagputop` captures configured `llamagputopUrl` stats.
132
+ Copy `configs/opl-simplebench.json.sample` to `~/.pi/agent/configs/opl-simplebench.json`. It uses camelCase fields: `llamaServerUrl`, `llamagputopUrl`, `researchSearchProvider`, `researchSearchUrl`, `researchMaxResults`, and `runSequence` (see "Run a templated sequence"). `--llama-server` captures `GET /props` and `/metrics` from configured `llamaServerUrl`; inference remains on the configured provider route, including LiteLLM. `--llamagputop` captures configured `llamagputopUrl` stats.
98
133
 
99
134
  `serverStats` is omitted entirely for runs without the flag. Its shape:
100
135
 
@@ -1,7 +1,7 @@
1
1
  import type { ExtensionAPI, AgentToolResult } from "@earendil-works/pi-coding-agent";
2
2
  import { debugLog } from "./util/debug";
3
3
  import { detectProvider } from "./util/providers";
4
- import { TOOL_SUPPORT_CACHE_PATH } from "./util/config";
4
+ import { readTestConfig, TOOL_SUPPORT_CACHE_PATH, type ModelTestUserConfig } from "./util/config";
5
5
  import type { SimplebenchOptions } from "./types";
6
6
  import { createBenchmark } from "./benchmark";
7
7
 
@@ -13,7 +13,25 @@ export function parseCommandArgs(args: string): SimplebenchOptions {
13
13
  tag = tagToken.slice("--tag=".length);
14
14
  if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(tag)) throw new Error(`--tag must be a single word (letters, digits, dot, dash, underscore): got "${tag}"`);
15
15
  }
16
- return { model: tokens.find(token => !token.startsWith("--")), allModels: tokens.includes("--all"), writeArtifact: !tokens.includes("--no-artifact"), thinkingMax: tokens.includes("--thinking-max"), codingLite: tokens.includes("--coding-lite"), testAll: tokens.includes("--test-all"), researchLive: tokens.includes("--research-live"), llamaServer: tokens.includes("--llama-server"), llamagputop: tokens.includes("--llamagputop"), ...(tag ? { tag } : {}) };
16
+ return { model: tokens.find(token => !token.startsWith("--")), allModels: tokens.includes("--all"), writeArtifact: !tokens.includes("--no-artifact"), thinkingMax: tokens.includes("--thinking-max"), codingLite: tokens.includes("--coding-lite"), testAll: tokens.includes("--test-all"), researchLive: tokens.includes("--research-live"), llamaServer: tokens.includes("--llama-server"), llamagputop: tokens.includes("--llamagputop"), ...(tag ? { tag } : {}), ...(tokens.includes("--3ptest") ? { threePTest: true } : {}), ...(tokens.includes("--sequence") ? { sequence: true } : {}) };
17
+ }
18
+
19
+ export interface ResolvedRunSequence { runs: Array<{ entry: string; options: SimplebenchOptions }>; pauseMs: number }
20
+
21
+ /** Expand the configured runSequence into per-iteration benchmark options. Throws on disabled/invalid configuration. */
22
+ export function resolveRunSequence(userConfig: ModelTestUserConfig): ResolvedRunSequence {
23
+ const rs = userConfig.runSequence;
24
+ if (!rs?.enabled) throw new Error("runSequence is not enabled in opl-simplebench.json");
25
+ if (!Array.isArray(rs.sequence) || rs.sequence.length === 0) throw new Error("runSequence.sequence must be a non-empty array of flag strings");
26
+ const pauseMs = rs.pauseMs ?? 0;
27
+ if (typeof pauseMs !== "number" || !Number.isFinite(pauseMs) || pauseMs < 0) throw new Error(`runSequence.pauseMs must be a non-negative number: got ${JSON.stringify(rs.pauseMs)}`);
28
+ const runs = rs.sequence.map((entry: string) => {
29
+ const tokens = String(entry).trim().split(/\s+/);
30
+ if (tokens.includes("--all")) throw new Error(`runSequence entry cannot contain --all: "${entry}"`);
31
+ if (tokens.includes("--sequence")) throw new Error(`runSequence entry cannot contain --sequence: "${entry}"`);
32
+ return { entry: String(entry), options: parseCommandArgs(`${entry}${rs.llamaMetrics ? " --llama-server --llamagputop" : ""}`) };
33
+ });
34
+ return { runs, pauseMs };
17
35
  }
18
36
 
19
37
  export default function (pi: ExtensionAPI) {
@@ -22,7 +40,7 @@ export default function (pi: ExtensionAPI) {
22
40
 
23
41
  pi.registerCommand("simplebench", {
24
42
  description: "Benchmark a model with auditable closed-answer, instruction, and tool-use tests.",
25
- detailedHelp: "\n\n🔍 Simplebench Extension\n\nThis extension tests AI models across multiple dimensions:\n• Closed-answer contract: 20 deterministic final-line answers (logic, math, spatial, commonsense)\n• Tool Usage: Ability to use available tools effectively\n• Instruction Following: How well the model follows complex JSON instructions\n• Coding Lite: Six isolated, execution-backed coding tasks\n\n📋 Usage Examples:\n /simplebench # Test current model\n /simplebench <model> # Test a specific model\n /simplebench --all # Test all Ollama models\n /simplebench <model> --coding-lite # Run only coding tasks\n /simplebench <model> --test-all # Run baseline, coding, and grounded research\n /simplebench <model> --research-live # Add live search integration smoke test\n /simplebench --all --test-all # Run complete suite for every Ollama model\n /simplebench <model> --thinking-max # Request max reasoning\n /simplebench <model> --llama-server # Capture configured /props and /metrics\n /simplebench <model> --llamagputop # Capture configured llama.cpp stats\n /simplebench <model> --tag=coldrun # Label the run: benchmark.tag plus artifact filename prefix\n /simplebench --help # Show this help\n /simplebench --clear-cache # Clear tool support cache\n\nCoding tasks run in disposable directories and never access the user repository.\n",
43
+ detailedHelp: "\n\n🔍 Simplebench Extension\n\nThis extension tests AI models across multiple dimensions:\n• Closed-answer contract: 20 deterministic final-line answers (logic, math, spatial, commonsense)\n• Tool Usage: Ability to use available tools effectively\n• Instruction Following: How well the model follows complex JSON instructions\n• Coding Lite: Six isolated, execution-backed coding tasks\n\n📋 Usage Examples:\n /simplebench # Test current model\n /simplebench <model> # Test a specific model\n /simplebench --all # Test all Ollama models\n /simplebench <model> --3ptest # Run the default 3ptest baseline explicitly\n /simplebench <model> --coding-lite # Run only coding tasks\n /simplebench <model> --test-all # Run baseline, coding, and grounded research\n /simplebench <model> --research-live # Add live search integration smoke test\n /simplebench --all --test-all # Run complete suite for every Ollama model\n /simplebench <model> --sequence # Run the configured runSequence template\n /simplebench <model> --thinking-max # Request max reasoning\n /simplebench <model> --llama-server # Capture configured /props and /metrics\n /simplebench <model> --llamagputop # Capture configured llama.cpp stats\n /simplebench <model> --tag=coldrun # Label the run: benchmark.tag plus artifact filename prefix\n /simplebench --help # Show this help\n /simplebench --clear-cache # Clear tool support cache\n\nCoding tasks run in disposable directories and never access the user repository.\n",
26
44
  getArgumentCompletions: async (prefix) => {
27
45
  try {
28
46
  const models = await getOllamaModels();
@@ -54,6 +72,8 @@ pi.registerCommand("simplebench", {
54
72
  " /simplebench [model] --test-all - Run baseline, coding, and deterministic grounded research\n" +
55
73
  " /simplebench [model] --research-live - Add live-search integration smoke test\n" +
56
74
  " /simplebench [model] --tag=<word> - Label the run (single word; added to benchmark.tag and the artifact name)\n" +
75
+ " /simplebench [model] --3ptest - Run the default baseline suite explicitly\n" +
76
+ " /simplebench [model] --sequence - Run the templated multi-iteration sequence from opl-simplebench.json (runSequence; per-entry --tag, llamaMetrics and pauseMs supported; the outer --tag is ignored)\n" +
57
77
  " /simplebench --all --test-all - Run complete suite for all Ollama models\n" +
58
78
  " /simplebench --clear-cache - Clear tool support cache\n",
59
79
  "info"
@@ -76,6 +96,46 @@ pi.registerCommand("simplebench", {
76
96
  return;
77
97
  }
78
98
 
99
+ if (parsedArgs.sequence) {
100
+ let resolved: ResolvedRunSequence;
101
+ try {
102
+ resolved = resolveRunSequence(readTestConfig());
103
+ } catch (e: any) {
104
+ ctx.ui.notify(e?.message || String(e), "error");
105
+ return;
106
+ }
107
+ const sequenceModel = parsedArgs.model || ctx.model?.id;
108
+ if (!sequenceModel) {
109
+ ctx.ui.notify("No model specified and no model currently selected", "error");
110
+ return;
111
+ }
112
+ ctx.ui.notify(`Running ${resolved.runs.length}-iteration sequence (${resolved.runs.map(r => r.entry).join(" | ")})...`, "info");
113
+ let completed = 0;
114
+ for (let i = 0; i < resolved.runs.length; i++) {
115
+ if (i > 0 && resolved.pauseMs > 0) {
116
+ ctx.ui.notify(`Cooling down ${resolved.pauseMs / 1000}s before iteration ${i + 1}/${resolved.runs.length}...`, "info");
117
+ await new Promise(resolve => setTimeout(resolve, resolved.pauseMs));
118
+ }
119
+ const { entry, options } = resolved.runs[i];
120
+ const model = options.model || sequenceModel;
121
+ ctx.ui.notify(`Iteration ${i + 1}/${resolved.runs.length} (${entry}) on ${model}...`, "info");
122
+ try {
123
+ const report = await testModel(model, ctx, { ...options, model });
124
+ completed += 1;
125
+ pi.sendMessage({
126
+ customType: "simplebench-report",
127
+ content: report,
128
+ display: { type: "content", content: report },
129
+ details: { model, timestamp: new Date().toISOString() },
130
+ });
131
+ } catch (e: any) {
132
+ ctx.ui.notify(`Iteration ${i + 1} (${entry}) failed: ${e.message}`, "error");
133
+ }
134
+ }
135
+ ctx.ui.notify(`Sequence done: ${completed}/${resolved.runs.length} iterations completed`, "info");
136
+ return;
137
+ }
138
+
79
139
  if (parsedArgs.allModels) {
80
140
  const providerInfo = detectProvider(ctx);
81
141
  if (providerInfo.kind !== "ollama") {
@@ -1,6 +1,6 @@
1
1
  import type { ServerStats } from "./llama-server";
2
2
 
3
- export interface SimplebenchOptions { model?: string; allModels: boolean; writeArtifact: boolean; thinkingMax?: boolean; codingLite?: boolean; testAll?: boolean; researchLive?: boolean; llamaServer?: boolean; llamagputop?: boolean; tag?: string; }
3
+ export interface SimplebenchOptions { model?: string; allModels: boolean; writeArtifact: boolean; thinkingMax?: boolean; codingLite?: boolean; testAll?: boolean; researchLive?: boolean; llamaServer?: boolean; llamagputop?: boolean; tag?: string; threePTest?: boolean; sequence?: boolean; }
4
4
  export interface RequestMetrics { requestCount: number; retryCount: number; wallTimeMs: number; timeToAnswerMs: number; timeToFirstTokenMs: number | null; startedAt: string | null; finishedAt: string | null; inputTokens: number | null; outputTokens: number | null; totalTokens: number | null; outputTokensPerSecond: number | null; toolCalls: Array<{ name: string; arguments?: unknown }>; }
5
5
  export interface TestRecord { id: string; kind: "reasoning" | "instructions" | "tools" | "coding" | "research-grounded" | "research-live"; category?: string; prompt: string; response: string | null; expectedAnswer?: string | string[]; extractedAnswer?: string; score: string; passed: boolean; error: string | null; metrics: RequestMetrics; coding?: { publicPassed: boolean; hiddenPassed: boolean; verifiedAfterEdit: boolean; unrelatedFiles: string[]; toolCalls: number; turns: number; efficiency?: "STRONG" | "MODERATE" | "WEAK" | "FAIL"; }; research?: { toolCalls: string[]; files: string[]; }; }
6
6
  export interface RunArtifact { schemaVersion: 1; benchmark: { name: "opl-simplebench"; suite?: "baseline" | "coding-lite" | "test-all"; tag?: string; model: string; provider: string; providerKind: string; thinking: { requested: "default" | "max"; effective: "provider-default" | "openai-reasoning-effort" | "pi-bedrock-reasoning"; level: "max" | null; modelMetadataSource: "active-context" | "scoped-model" | null; }; startedAt: string; finishedAt: string; wallTimeMs: number; artifactEnabled: boolean; }; tests: TestRecord[]; summary: Record<string, unknown> & { serverStats?: ServerStats }; }
@@ -79,6 +79,15 @@ export interface ModelTestUserConfig {
79
79
  researchMaxResults?: number;
80
80
  llamaServerUrl?: string;
81
81
  llamagputopUrl?: string;
82
+ runSequence?: RunSequenceConfig;
83
+ }
84
+
85
+ /** Templated multi-run benchmark sequence used by `/simplebench --sequence`. */
86
+ export interface RunSequenceConfig {
87
+ enabled?: boolean;
88
+ llamaMetrics?: boolean;
89
+ pauseMs?: number;
90
+ sequence?: string[];
82
91
  }
83
92
 
84
93
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openlines/opl-pi-sht",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Pi coding-agent extension kit: token-efficient context, safe modes, fingerprinted /init, model benchmarking, web access, and browser automation.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,48 +0,0 @@
1
- {
2
- "_comment": " \ue22c Available segment IDs: pi, model, path, git, thinking, caveman, plan_mode, chat_mode, mode_switcher, separator, token_in, token_out, token_total, cache_read, cache_write, cost, context_pct, context_total, session_stats, perf_stats, text:<literal>",
3
- "row1LeftSegments": ["pi", "separator", "model", "separator", "path", "git"],
4
- "row1RightSegments": ["context_pct"],
5
- "row2LeftSegments": [
6
- "thinking",
7
- "separator",
8
- "mode_switcher"
9
- ],
10
- "row2RightSegments": ["token_total", "separator", "cost"],
11
- "row3LeftSegments": ["session_stats"],
12
- "row3RightSegments": ["perf_stats"],
13
- "icons": {
14
- "pi": "\udb80\udfff",
15
- "folder": "\uf115",
16
- "branch": "\uf126",
17
- "git": "\uf1d3",
18
- "separator": "|"
19
- },
20
- "colors": {
21
- "model": "#c07898",
22
- "thinkingHigh": "#afb9fe",
23
- "thinkingXhigh": "#9575cd",
24
- "thinkingMax": "#ce93d8",
25
- "separator": "#87827a"
26
- },
27
- "segmentOptions": {
28
- "path": {
29
- "mode": "full"
30
- },
31
- "git": {
32
- "showBranch": true,
33
- "showStaged": true,
34
- "showUnstaged": true,
35
- "showUntracked": true
36
- },
37
- "contextBar": {
38
- "barWidth": 18,
39
- "filledChar": "▋",
40
- "unfilledChar": "▋",
41
- "unfilledColor": "#4e4c49",
42
- "gradientStart": "#f29373",
43
- "gradientMid": "#d67858",
44
- "gradientEnd": "#ae4f2f",
45
- "gradientMidPoint": 0.55
46
- }
47
- }
48
- }
@@ -1,22 +0,0 @@
1
- {
2
- "boxedView": false,
3
- "companion": {
4
- "enabled": true,
5
- "color": "accent",
6
- "type": "dog",
7
- "types": [
8
- {
9
- "typeName": "cat",
10
- "top": " /\\,/\\ "
11
- },
12
- {
13
- "typeName": "dog",
14
- "top": " /),(\\ "
15
- },
16
- {
17
- "typeName": "bunny",
18
- "top": " (\\,/) "
19
- }
20
- ]
21
- }
22
- }
@@ -1,291 +0,0 @@
1
- {
2
- "_comment": "Every field below is optional; values shown are the extension's built-in defaults for reference.",
3
- "ui": {
4
- "hideNotify": false,
5
- "hideWidget": true
6
- },
7
- "shortcuts": {
8
- "_comment": "Shortcut that cycles through all enabled, visible modes in registry order. Default: ctrl+alt+m.",
9
- "cycleMode": "shift+tab"
10
- },
11
- "cleanup": {
12
- "_comment": "Set to true to delete the plan file automatically after plan_complete is called.",
13
- "cleanupOnComplete": false
14
- },
15
- "defaultNotifyTemplate": "✓ {Name} mode ON",
16
- "_comment_defaultNotifyTemplate": "Default notify text for any custom mode that doesn't set its own labels.notify. {Name} is replaced with the mode name, capitalized.",
17
- "_comment_lazyTools": "Tool names withheld from the active set at rest and enabled on demand via the load_tools tool. Only affects modes that would otherwise include them (off/execute and custom modes that list them). Core built-ins, plan_complete, and load_tools are protected and ignored. Omit or leave empty to keep all tools always active.",
18
- "lazyTools": [
19
- "subagent",
20
- "subagent_wait",
21
- "subagent_supervisor",
22
- "browser",
23
- "simplebench"
24
- ],
25
- "bashPatterns": {
26
- "_comment_safe": "Replace-only: providing safePatterns replaces ALL defaults for both built-in chat/plan modes (shared base). Omit to keep built-in safe patterns. Shown here with the built-in list.",
27
- "_comment_destructive": "Replace-only: providing destructivePatterns replaces ALL defaults for both built-in chat/plan modes (shared base). Omit to keep built-in destructive patterns. Shown here with the built-in list.",
28
- "safePatterns": [
29
- "^\\s*cat\\b",
30
- "^\\s*head\\b",
31
- "^\\s*tail\\b",
32
- "^\\s*less\\b",
33
- "^\\s*more\\b",
34
- "^\\s*grep\\b",
35
- "^\\s*find\\b",
36
- "^\\s*ls\\b",
37
- "^\\s*pwd\\b",
38
- "^\\s*cd\\b",
39
- "^\\s*echo\\b",
40
- "^\\s*printf\\b",
41
- "^\\s*wc\\b",
42
- "^\\s*sort\\b",
43
- "^\\s*diff\\b",
44
- "^\\s*file\\b",
45
- "^\\s*stat\\b",
46
- "^\\s*du\\b",
47
- "^\\s*df\\b",
48
- "^\\s*tree\\b",
49
- "^\\s*which\\b",
50
- "^\\s*whereis\\b",
51
- "^\\s*type\\b",
52
- "^\\s*env\\b",
53
- "^\\s*printenv\\b",
54
- "^\\s*uname\\b",
55
- "^\\s*whoami\\b",
56
- "^\\s*date\\b",
57
- "^\\s*uptime\\b",
58
- "^\\s*ps\\b",
59
- "^\\s*free\\b",
60
- "^\\s*rg\\b",
61
- "^\\s*fd\\b",
62
- "^\\s*bat\\b",
63
- "^\\s*jq\\b",
64
- "^\\s*git\\s+(status|log|diff|show|branch|remote)",
65
- "^\\s*node\\s+--version",
66
- "^\\s*python\\s+--version",
67
- "^\\s*(npx\\s+)?tsc\\b.*--noEmit",
68
- "^\\s*npm\\s+(list|ls|view|info|outdated|audit)",
69
- "^\\s*yarn\\s+(list|info|why|audit)"
70
- ],
71
- "destructivePatterns": [
72
- "\\brm\\b",
73
- "\\brmdir\\b",
74
- "\\bmv\\b",
75
- "\\bcp\\b",
76
- "\\bmkdir\\b",
77
- "\\btouch\\b",
78
- "\\bchmod\\b",
79
- "\\bchown\\b",
80
- "\\btee\\b",
81
- "\\bdd\\b",
82
- "\\bshred\\b",
83
- "(^|[^<])>(?!>|&)",
84
- ">>",
85
- "\\bnpm\\s+(install|uninstall|update|ci)",
86
- "\\byarn\\s+(add|remove|install)",
87
- "\\bpip\\s+(install|uninstall)",
88
- "\\bgit\\s+(add|commit|push|merge|rebase|reset|checkout|branch\\s+-)",
89
- "\\bsudo\\b",
90
- "\\bsu\\b",
91
- "\\bkill\\b",
92
- "\\bpkill\\b",
93
- "\\b(sh|bash|zsh)\\b",
94
- "\\b(vim?|nano|emacs|code|subl)\\b"
95
- ]
96
- },
97
- "_comment_tools": "Set modes.chat.tools or modes.plan.tools to replace their default tools. The legacy top-level chatAllowedTools and planAllowedTools keys remain supported but are deprecated.",
98
- "_comment_widgetColor": "available colors - accent, border, borderAccent, borderMuted, success, error, warning, muted, dim, text, thinkingText, searchMatchText, userMessageText, customMessageText, customMessageLabel, toolTitle, toolOutput, mdHeading, mdLink, mdLinkUrl, mdCode, mdCodeBlock, mdCodeBlockBorder, mdQuote, mdQuoteBorder, mdHr, mdListBullet, toolDiffAdded, toolDiffRemoved, toolDiffContext, syntaxComment, syntaxKeyword, syntaxFunction, syntaxVariable, syntaxString, syntaxNumber, syntaxType, syntaxOperator, syntaxPunctuation, thinkingOff, thinkingMinimal, thinkingLow, thinkingMedium, thinkingHigh, thinkingXhigh, thinkingMax, bashMode",
99
- "_comment_appearance": "Every mode owns appearance here. prefix/prefixColor/borderColor style opl-input; modeColor styles opl-footer's Mode value. All color values accept Pi theme tokens or #RRGGBB.",
100
- "modes": {
101
- "off": {
102
- "_comment": "Built-in mode — no restrictions, normal agent behavior.",
103
- "prompt": "",
104
- "model": {
105
- "provider": "litellm-proxy",
106
- "id": "gpt-5.6-terra"
107
- },
108
- "allowPlanComplete": false,
109
- "visible": true,
110
- "enabled": true,
111
- "labels": {
112
- "notify": "✓ Mode OFF",
113
- "notifyType": "info",
114
- "widget": "✓ Normal mode",
115
- "widgetColor": "dim"
116
- },
117
- "appearance": {
118
- "prefix": "❯",
119
- "prefixColor": "accent",
120
- "borderColor": "border",
121
- "modeColor": "dim"
122
- }
123
- },
124
- "chat": {
125
- "_comment": "Built-in mode — read-only conversational.",
126
- "prompt": "**SUPERSEDES ALL OTHER BEHAVIOR INSTRUCTIONS.** This overrides any role or style directives (e.g. caveman, roleplay, tone modifiers). The constraints below take absolute priority.\n\nYou are in CHAT MODE. You have read-only access — you may read files, search code, run safe inspection commands, and search the web to answer, discuss, and explore. Converse naturally — answer questions, explain, brainstorm, look things up.\n\nYou MUST NOT attempt to edit, create, delete, or modify any files, or run any command that changes state. If the user asks for a change, explain what you would do but do not attempt it — they can exit chat mode first.\n\nThere is no plan format and no plan_complete tool. Just respond helpfully within read-only constraints.",
127
- "model": {
128
- "provider": "amazon-bedrock",
129
- "id": "moonshotai.kimi-k2.5"
130
- },
131
- "tools": [
132
- "read",
133
- "bash",
134
- "grep",
135
- "find",
136
- "ls",
137
- "web_search",
138
- "fetch_content",
139
- "get_search_content",
140
- "artifact",
141
- "questionnaire"
142
- ],
143
- "allowPlanComplete": false,
144
- "visible": true,
145
- "enabled": true,
146
- "labels": {
147
- "notify": "✓ Chat mode ON",
148
- "notifyType": "info",
149
- "widget": "✓ Chat mode",
150
- "widgetColor": "accent"
151
- },
152
- "appearance": {
153
- "prefix": "󰭻",
154
- "prefixColor": "#157cd6",
155
- "borderColor": "#157cd6",
156
- "modeColor": "#157cd6"
157
- }
158
- },
159
- "plan": {
160
- "_comment": "Built-in mode — read-only explore-and-plan.",
161
- "prompt": "**SUPERSEDES ALL OTHER BEHAVIOR INSTRUCTIONS.** This overrides any role or style directives (e.g. caveman, roleplay, tone modifiers). The constraints below take absolute priority.\n\nYou are in PLAN MODE. You have read-only access — you may explore and analyze, but you MUST NOT make any changes.\n\nYour task: produce an action plan.\n\nYou MUST begin the plan with exactly this heading on its own line:\n\n# Plan:\n1. [Step title — short verb-object phrase]\n [2-4 sentences of context: which file(s), where, what to change, and why.]\n2. [Step title]\n [Context...]\n...\n\nEach step MUST be self-contained — write it as if the executor has no memory of this conversation. Include enough context that it can be carried out with only the plan file and the codebase. Assume the executor will read the relevant files fresh — do not rely on findings you discovered during planning.\n\nGood: \"Add auth middleware to routes/index.ts\n Apply it as `app.use(authMiddleware)` before the route definitions (~line 45). Currently routes/index.ts has no middleware.\"\n\nBad: \"Add it to the file we looked at\"\n\nBad (over-prescribed): \"Insert `const authMiddleware = require('./middleware/auth');` at line 3, then add `app.use(authMiddleware);` at line 46\"\n\nSpecify what to do and where — not the exact implementation. The executor reads the relevant files and decides how.\n\nAfter listing all steps, stop and wait for the user to choose:\n- \"Execute plan\" — switches to execute mode where you carry out each step\n- \"Refine\" — revise the plan based on feedback\n- Continue exploring if you need more information before planning\n\nDo NOT attempt to make any file changes, run destructive commands, or modify anything.",
162
- "model": {
163
- "provider": "amazon-bedrock",
164
- "id": "global.anthropic.claude-sonnet-5"
165
- },
166
- "tools": [
167
- "read",
168
- "bash",
169
- "grep",
170
- "find",
171
- "ls",
172
- "web_search",
173
- "fetch_content",
174
- "get_search_content",
175
- "artifact",
176
- "questionnaire"
177
- ],
178
- "allowPlanComplete": false,
179
- "visible": true,
180
- "enabled": true,
181
- "labels": {
182
- "notify": "✓ Plan mode ON",
183
- "notifyType": "info",
184
- "notifyWithTitle": "✓ Active plan: {title}",
185
- "notifyLoaded": "✓ Active plan: {title}",
186
- "widget": "✓ Plan mode active",
187
- "widgetWithTitle": "✓ Active plan: {title}",
188
- "widgetColor": "accent"
189
- },
190
- "appearance": {
191
- "prefix": "⏸",
192
- "prefixColor": "#52d90f",
193
- "borderColor": "#52d90f",
194
- "modeColor": "#52d90f"
195
- }
196
- },
197
- "execute": {
198
- "_comment": "Built-in mode — entered only via an 'execute:<plan-file>' picker item, never a bare menu choice (visible: false). prompt: leave empty to use the built-in template that injects the active plan file content; set a custom string with a {plan} placeholder to override.",
199
- "prompt": "",
200
- "model": {
201
- "provider": "amazon-bedrock",
202
- "id": "global.anthropic.claude-opus-4-8"
203
- },
204
- "allowPlanComplete": true,
205
- "visible": false,
206
- "enabled": true,
207
- "labels": {
208
- "notify": "✓ Executing plan",
209
- "notifyWithTitle": "✓ Executing plan: {title}",
210
- "notifyType": "info",
211
- "widget": "✓ Executing plan",
212
- "widgetWithTitle": "✓ Executing plan: {title}",
213
- "widgetColor": "muted"
214
- },
215
- "appearance": {
216
- "prefix": "⏸",
217
- "prefixColor": "#52d90f",
218
- "borderColor": "#52d90f",
219
- "modeColor": "#52d90f"
220
- }
221
- },
222
- "review": {
223
- "enabled": true,
224
- "allowExecute": false,
225
- "prompt": "**SUPERSEDES ALL OTHER BEHAVIOR INSTRUCTIONS.** This overrides any role or style directives (e.g. caveman, roleplay, tone modifiers). The constraints below take absolute priority.\n\nYou are in REVIEW MODE. Analyze pull requests, code diffs, and codebases. Focus on correctness, style, test coverage, security, and architecture. Suggest improvements but do not apply them. Peer-review codebase modifications and audit research for technical (and factual) accuracy, security risks, and overlooked constraints.\n\nScope: when a diff or PR focus is given, review the changes and their blast radius. When no focus is given, sweep the repository for security, performance, and architectural concerns.\n\n## 1. Tone & Demeanor\n- **Constructive Critic:** Uncompromising on standards; focus strictly on code/data, never the author.\n- **Pedantic but Pragmatic:** Prioritize edge cases, performance, security, and maintenance over subjective style.\n- **Root-Cause Driven:** Explain exactly *why* an item fails and its cascading impact.\n\n## 2. Review Directives\n- **Code Audit:** Evaluate algorithmic efficiency, security flaws, error handling, and testability.\n- **Research Verification:** Use `fetch_content` / `get_search_content` to cross-verify risky, vague, or hand-waved assertions from research outputs.\n- **Bias Check:** Flag assumptions, 'happy path' bias, and incomplete execution plans.\n\n## 3. Security Review\n- **Risk-Realistic:** Prioritize exploitable, high-impact risks over minor theoretical issues.\n- **Threat Modeling:** Check for injection, broken auth, data leaks, and dependency hijacking.\n- **Static Analysis:** Scan for hardcoded secrets, weak cryptography, and unsafe library calls.\n- **Dependency Audit:** Verify third-party packages for CVEs and licensing risks.\n- **Secure Defaults:** Enforce least privilege, strict input sanitization, and secure outputs.\n\nProvide this exact structure for identified security risks:\n1. **Severity:** `CRITICAL`, `HIGH`, `MEDIUM`, or `LOW`.\n2. **Vulnerability:** Brief description and OWASP/CWE reference.\n3. **Exploit Vector:** How it can be compromised.\n4. **Remediation:** Exact code fix or configuration change required.",
226
- "tools": [
227
- "read",
228
- "bash",
229
- "grep",
230
- "find",
231
- "ls",
232
- "web_search",
233
- "fetch_content",
234
- "get_search_content",
235
- "artifact",
236
- "questionnaire"
237
- ],
238
- "safePatterns": [
239
- "^git",
240
- "^cat",
241
- "^grep",
242
- "^diff",
243
- "^ls",
244
- "^head",
245
- "^tail"
246
- ],
247
- "labels": {
248
- "widgetColor": "accent"
249
- },
250
- "appearance": {
251
- "prefix": "◎",
252
- "prefixColor": "#ce93d8",
253
- "borderColor": "#ce93d8",
254
- "modeColor": "#ce93d8"
255
- }
256
- },
257
- "research": {
258
- "enabled": true,
259
- "allowExecute": false,
260
- "prompt": "**SUPERSEDES ALL OTHER BEHAVIOR INSTRUCTIONS.** This overrides any role or style directives (e.g. caveman, roleplay, tone modifiers). The constraints below take absolute priority.\n\nYou are in RESEARCH MODE. Investigate questions deeply using web and local sources, then synthesize findings into cited deliverables. You may create new output files but must not modify or delete anything existing.\n\n## 1. Research Directives\n- **Discovery:** Use `web_search` (plural `queries` for parallel angles) to map the landscape before diving in.\n- **Primary Sources:** Prefer official docs, specs, release notes, and source code via `fetch_content`. Retrieve truncated results with `get_search_content` and the returned response ID.\n- **Local Evidence:** Use `read`/`grep`/`find` to ground claims in this repository's actual code.\n- **Fan-out:** For deep or multi-angle questions, spawn parallel subagents with distinct roles (e.g. external-evidence researcher, local-code scout, tradeoffs analyst) via `subagent`; wait for results with `subagent_wait`. Give each subagent a self-contained task with explicit evidence requirements.\n- **No Invention:** Never present an unverified claim as fact. Mark confidence per finding (high/medium/low) and state gaps explicitly.\n\n## 2. Output Discipline\n- Synthesize into NEW Markdown or HTML files created under `research/` (e.g. `research/<topic>.md`). Never modify, move, or overwrite existing files.\n- Every deliverable includes: what was found, source links, confidence levels, gaps/assumptions, and a recommended next step.\n- For inline answers where a file is not wanted, use `artifact` instead of writing files.\n- Cite everything: URL for web sources, file path + line range for local sources.",
261
- "model": {
262
- "provider": "amazon-bedrock",
263
- "id": "zai.glm-5"
264
- },
265
- "tools": [
266
- "read",
267
- "grep",
268
- "find",
269
- "ls",
270
- "web_search",
271
- "fetch_content",
272
- "get_search_content",
273
- "artifact",
274
- "questionnaire",
275
- "subagent",
276
- "subagent_wait",
277
- "write"
278
- ],
279
- "labels": {
280
- "widget": "✓ Research mode active",
281
- "widgetColor": "accent"
282
- },
283
- "appearance": {
284
- "prefix": "⌕",
285
- "prefixColor": "#f2eb5a",
286
- "borderColor": "#f2eb5a",
287
- "modeColor": "#f2eb5a"
288
- }
289
- }
290
- }
291
- }
@@ -1,8 +0,0 @@
1
- {
2
- "_comment": "Copy to ~/.pi/agent/configs/opl-simplebench.json. Endpoints are optional and only used by their corresponding Simplebench flags.",
3
- "researchSearchProvider": "ddgs",
4
- "researchSearchUrl": "http://192.168.1.100:8000",
5
- "researchMaxResults": 5,
6
- "llamaServerUrl": "http://192.168.1.106:7679/v1",
7
- "llamagputopUrl": "http://192.168.1.106:4321/stats"
8
- }
@@ -1,12 +0,0 @@
1
- {
2
- "allDoneHideMs": 10000,
3
- "shortcuts": {
4
- "toggleWidget": "ctrl+alt+t",
5
- "resetDone": "ctrl+alt+r"
6
- },
7
- "widget": {
8
- "widthPercent": 33,
9
- "maxHeightPercent": 50,
10
- "minWidth": 32
11
- }
12
- }
@@ -1,31 +0,0 @@
1
- {
2
- "provider": "ddgs",
3
- "providers": {
4
- "gemini": {
5
- "apiKeyEnv": "GEMINI_API_KEY",
6
- "baseUrl": "https://generativelanguage.googleapis.com/v1beta",
7
- "model": "gemini-3.5-flash-lite",
8
- "_available_models": ["gemini-3.6-flash", "gemini-3.5-flash-lite", "gemini-2.5-flash", "gemini-2.5-pro"]
9
- },
10
- "tavily": {
11
- "apiKeyEnv": "TAVILY_API_KEY",
12
- "maxResults": 5
13
- },
14
- "ddgs": {
15
- "apiUrl": "http://192.168.1.100:8000",
16
- "maxResults": 12
17
- },
18
- "searxng": {
19
- "instanceUrl": "http://192.168.1.100:8888",
20
- "maxResults": 12,
21
- "categories": "general",
22
- "safeSearch": 0
23
- },
24
- "exa": {
25
- "apiKeyEnv": "EXA_API_KEY",
26
- "maxResults": 5,
27
- "searchType": "auto",
28
- "includeSummary": true
29
- }
30
- }
31
- }