@herbertgao/pi-extensions 2026.8.5 → 2026.8.6
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 +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +10 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +5 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/README.md +24 -17
- package/node_modules/@narumitw/pi-btw/package.json +5 -5
- package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +33 -13
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/pi-lens/CHANGELOG.md +95 -0
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
- package/node_modules/pi-lens/dist/clients/biome-client.js +121 -13
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
- package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +135 -30
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +19 -7
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +6 -4
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +114 -10
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +101 -16
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +37 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +230 -50
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/extension-log.js +296 -3
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
- package/node_modules/pi-lens/dist/clients/git-guard.js +18 -21
- package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +116 -7
- package/node_modules/pi-lens/dist/clients/host-ports.js +1 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +5 -1
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +4 -9
- package/node_modules/pi-lens/dist/clients/knip-client.js +51 -14
- package/node_modules/pi-lens/dist/clients/latency-logger.js +50 -1
- package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +58 -13
- package/node_modules/pi-lens/dist/clients/lsp/client.js +169 -8
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +29 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +264 -66
- package/node_modules/pi-lens/dist/clients/lsp/server.js +247 -60
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +30 -17
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +29 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +153 -7
- package/node_modules/pi-lens/dist/clients/runtime-context.js +104 -11
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +170 -22
- package/node_modules/pi-lens/dist/clients/runtime-session.js +28 -5
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +124 -10
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +388 -35
- package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +88 -5
- package/node_modules/pi-lens/dist/clients/sg-runner.js +141 -23
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
- package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +431 -24
- package/node_modules/pi-lens/dist/clients/tool-policy.js +2 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
- package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
- package/node_modules/pi-lens/dist/index.js +4827 -1633
- package/node_modules/pi-lens/dist/mcp/server.js +8 -2
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +3 -2
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +62 -7
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +38 -13
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +11 -3
- package/node_modules/pi-lens/docs/features.md +14 -1
- package/node_modules/pi-lens/docs/globalconfig.md +11 -0
- package/node_modules/pi-lens/docs/servercapabilities.md +1 -1
- package/node_modules/pi-lens/docs/settings.md +6 -0
- package/node_modules/pi-lens/docs/usage.md +23 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +1 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +79 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +13 -0
- package/node_modules/pi-mcp-adapter/README.md +4 -1
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/cli.js +25 -4
- package/node_modules/pi-mcp-adapter/config.ts +4 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +18 -15
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +18 -8
- package/node_modules/pi-mcp-adapter/package.json +2 -1
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
- package/node_modules/pi-mcp-adapter/server-manager.ts +5 -0
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
- package/node_modules/pi-mcp-adapter/types.ts +93 -10
- package/node_modules/pi-web-access/CHANGELOG.md +14 -0
- package/node_modules/pi-web-access/README.md +18 -12
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +106 -34
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +18 -4
- package/node_modules/pi-web-access/index.ts +120 -48
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/summary-review.ts +11 -5
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -11,13 +11,13 @@ pi install npm:@herbertgao/pi-extensions
|
|
|
11
11
|
The package bundles 11 active `@herbertgao/*` child packages, including `@herbertgao/pi-cc-extensions`, plus the following upstream packages under their original names:
|
|
12
12
|
|
|
13
13
|
- `@dietrichgebert/ponytail@4.9.0`
|
|
14
|
-
- `@juicesharp/rpiv-ask-user-question@2.
|
|
15
|
-
- `@narumitw/pi-btw@0.
|
|
14
|
+
- `@juicesharp/rpiv-ask-user-question@2.6.0`
|
|
15
|
+
- `@narumitw/pi-btw@0.52.0`
|
|
16
16
|
- `@pi-plugins/fast-mode@0.1.9`
|
|
17
|
-
- `pi-mcp-adapter@2.
|
|
17
|
+
- `pi-mcp-adapter@2.26.0`
|
|
18
18
|
- `pi-footer@0.5.1`
|
|
19
|
-
- `pi-lens@4.0.
|
|
20
|
-
- `pi-web-access@0.
|
|
19
|
+
- `pi-lens@4.0.1`
|
|
20
|
+
- `pi-web-access@0.23.0`
|
|
21
21
|
- `remote-pi@0.7.0`
|
|
22
22
|
- `@czottmann/pi-automode@1.11.0`
|
|
23
23
|
|
|
@@ -40,7 +40,7 @@ Run `/reload` after installation.
|
|
|
40
40
|
| Claude Code Output | Tool summaries, expand/collapse, rich edit/write diffs, and `on` / `compact` / `off` modes | `/ccstyle` |
|
|
41
41
|
| Fullscreen mode | Tool card/group click-to-toggle, previews, hover highlight, and a back-to-bottom button | `TUIMODE=fullscreen` or `--tui-mode fullscreen` |
|
|
42
42
|
| Settings panel | `Style / Diff / Thinking / Feature` tabs with startup, wheel, and optional feature toggles | `/ccstyle` |
|
|
43
|
-
| Context inspection | Usage breakdown and previews for the system prompt, tools, skills, and messages
|
|
43
|
+
| Context inspection | Usage breakdown and previews for the system prompt, tools, tool results, skills, and messages | `/context` |
|
|
44
44
|
| Session/Subagent references | Search and inject effective context from previous Sessions or existing SubAgents | `@` |
|
|
45
45
|
| Theme | Bundled CC Dark and CC Light themes | `/theme` |
|
|
46
46
|
|
|
@@ -40,7 +40,7 @@ pi install npm:@herbertgao/pi-cc-extensions
|
|
|
40
40
|
| Claude Code UI | 工具摘要、折叠展开、rich edit/write diff,以及 `on` / `compact` / `off` 三种模式 | `/ccstyle` |
|
|
41
41
|
| Fullscreen mode | 工具卡/group 点击展开与收起、预览、hover 高亮、回到底部按钮 | `TUIMODE=fullscreen` 或 `--tui-mode fullscreen` |
|
|
42
42
|
| 配置面板 | `Style / Diff / Thinking / Feature` 四页签,含启动头、滚轮步进及可选功能开关 | `/ccstyle` |
|
|
43
|
-
| 上下文检查 | 查看上下文占用,并预览 System prompt、Tools、Skills 和消息内容
|
|
43
|
+
| 上下文检查 | 查看上下文占用,并预览 System prompt、Tools、Tool results、Skills 和消息内容 | `/context` |
|
|
44
44
|
| Session/Subagent 引用 | 搜索并注入历史 Session 或现有 SubAgent 的有效上下文 | `@` |
|
|
45
45
|
| 主题 | 随包提供内置 CC Dark、CC Light 主题 | `/theme` |
|
|
46
46
|
|
|
@@ -12,7 +12,7 @@ export type ContextPart = {
|
|
|
12
12
|
color: "accent" | "success" | "warning" | "muted" | "dim";
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
type PreviewKey = "systemPrompt" | "tools" | "contextFiles" | "skills";
|
|
15
|
+
type PreviewKey = "systemPrompt" | "tools" | "toolResults" | "contextFiles" | "skills";
|
|
16
16
|
|
|
17
17
|
type ContextPreview = {
|
|
18
18
|
key: PreviewKey;
|
|
@@ -303,6 +303,48 @@ export function scaleParts(parts: ContextPart[], target: number): ContextPart[]
|
|
|
303
303
|
return scaled;
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
+
export function resolveUsedTokens(
|
|
307
|
+
usage: { tokens: number | null; percent: number | null } | undefined,
|
|
308
|
+
estimated: number,
|
|
309
|
+
contextWindow: number,
|
|
310
|
+
): number {
|
|
311
|
+
const reported = usage?.tokens;
|
|
312
|
+
const fromPercent =
|
|
313
|
+
usage?.percent !== null && usage?.percent !== undefined && contextWindow > 0
|
|
314
|
+
? Math.round((usage.percent / 100) * contextWindow)
|
|
315
|
+
: undefined;
|
|
316
|
+
let resolved = reported ?? fromPercent ?? estimated;
|
|
317
|
+
if (reported !== null && reported !== undefined && fromPercent !== undefined) {
|
|
318
|
+
const tolerance = Math.max(32, Math.round(contextWindow * 0.001));
|
|
319
|
+
if (Math.abs(reported - fromPercent) > tolerance) resolved = fromPercent;
|
|
320
|
+
}
|
|
321
|
+
if (estimated > 0 && resolved < estimated * 0.25) return estimated;
|
|
322
|
+
return resolved;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function capParts(parts: ContextPart[], target: number, fixedPrefix = 0): ContextPart[] {
|
|
326
|
+
const fixed = parts.slice(0, fixedPrefix);
|
|
327
|
+
const variable = parts.slice(fixedPrefix);
|
|
328
|
+
const fixedTokens = fixed.reduce((sum, part) => sum + part.tokens, 0);
|
|
329
|
+
const variableTarget = Math.max(0, target - fixedTokens);
|
|
330
|
+
const estimated = variable.reduce((sum, part) => sum + part.tokens, 0);
|
|
331
|
+
if (estimated <= variableTarget || estimated === 0) return parts;
|
|
332
|
+
if (variableTarget === 0) return [...fixed, ...variable.map((part) => ({ ...part, tokens: 0 }))];
|
|
333
|
+
let previous = 0;
|
|
334
|
+
let cumulative = 0;
|
|
335
|
+
const capped = variable.map((part, index) => {
|
|
336
|
+
cumulative += part.tokens;
|
|
337
|
+
const next =
|
|
338
|
+
index === variable.length - 1
|
|
339
|
+
? variableTarget
|
|
340
|
+
: Math.round((cumulative / estimated) * variableTarget);
|
|
341
|
+
const tokens = next - previous;
|
|
342
|
+
previous = next;
|
|
343
|
+
return { ...part, tokens };
|
|
344
|
+
});
|
|
345
|
+
return [...fixed, ...capped];
|
|
346
|
+
}
|
|
347
|
+
|
|
306
348
|
export function formatTokens(tokens: number): string {
|
|
307
349
|
if (tokens < 1_000) return String(tokens);
|
|
308
350
|
if (tokens < 100_000) return `${(tokens / 1_000).toFixed(1)}k`;
|
|
@@ -326,13 +368,14 @@ type ContextBreakdown = {
|
|
|
326
368
|
parts: ContextPart[];
|
|
327
369
|
options: SystemPromptOptions;
|
|
328
370
|
systemPrompt: string;
|
|
371
|
+
toolResults: string;
|
|
329
372
|
};
|
|
330
373
|
|
|
331
374
|
/**
|
|
332
375
|
* Single pass over prompt options + session entries. Returns options/systemPrompt
|
|
333
376
|
* so the /context UI does not re-fetch or re-stringify the same sources.
|
|
334
377
|
*/
|
|
335
|
-
function collectContextBreakdown(ctx: ExtensionCommandContext): ContextBreakdown {
|
|
378
|
+
export function collectContextBreakdown(ctx: ExtensionCommandContext): ContextBreakdown {
|
|
336
379
|
const options = (ctx.getSystemPromptOptions?.() ?? {}) as SystemPromptOptions;
|
|
337
380
|
const systemPrompt = typeof ctx.getSystemPrompt === "function" ? ctx.getSystemPrompt() : "";
|
|
338
381
|
|
|
@@ -361,12 +404,16 @@ function collectContextBreakdown(ctx: ExtensionCommandContext): ContextBreakdown
|
|
|
361
404
|
let assistant = 0;
|
|
362
405
|
let toolResults = 0;
|
|
363
406
|
let summaries = 0;
|
|
407
|
+
const toolResultPreview: string[] = [];
|
|
364
408
|
for (const entry of ctx.sessionManager.buildContextEntries()) {
|
|
365
409
|
if (entry.type === "message") {
|
|
366
410
|
const tokens = estimateTokens(entry.message);
|
|
367
411
|
if (entry.message.role === "user") user += tokens;
|
|
368
412
|
else if (entry.message.role === "assistant") assistant += tokens;
|
|
369
413
|
else toolResults += tokens;
|
|
414
|
+
if (entry.message.role === "toolResult") {
|
|
415
|
+
toolResultPreview.push(`## Tool result\n\n${JSON.stringify(entry.message, null, 2)}`);
|
|
416
|
+
}
|
|
370
417
|
} else if (entry.type === "compaction" || entry.type === "branch_summary") {
|
|
371
418
|
summaries += tokenEstimate(entry);
|
|
372
419
|
}
|
|
@@ -388,6 +435,7 @@ function collectContextBreakdown(ctx: ExtensionCommandContext): ContextBreakdown
|
|
|
388
435
|
parts: parts.filter((part) => part.tokens > 0),
|
|
389
436
|
options,
|
|
390
437
|
systemPrompt,
|
|
438
|
+
toolResults: toolResultPreview.join("\n\n") || "No tool results in the current context.",
|
|
391
439
|
};
|
|
392
440
|
}
|
|
393
441
|
|
|
@@ -398,10 +446,25 @@ export default function contextUsageExtension(pi: ExtensionAPI) {
|
|
|
398
446
|
const usage = ctx.getContextUsage();
|
|
399
447
|
const contextWindow = usage?.contextWindow ?? ctx.model?.contextWindow ?? 0;
|
|
400
448
|
const breakdown = collectContextBreakdown(ctx);
|
|
401
|
-
const
|
|
402
|
-
const
|
|
449
|
+
const estimated = breakdown.parts.reduce((sum, part) => sum + part.tokens, 0);
|
|
450
|
+
const fixedParts = breakdown.parts.filter(
|
|
451
|
+
(part) => part.label === "System prompt" || part.label === "Tools",
|
|
452
|
+
);
|
|
453
|
+
const variableParts = breakdown.parts.filter(
|
|
454
|
+
(part) => part.label !== "System prompt" && part.label !== "Tools",
|
|
455
|
+
);
|
|
456
|
+
const orderedParts = [...fixedParts, ...variableParts];
|
|
457
|
+
const fixedTokens = fixedParts.reduce((sum, part) => sum + part.tokens, 0);
|
|
458
|
+
const used = Math.max(resolveUsedTokens(usage, estimated, contextWindow), fixedTokens);
|
|
459
|
+
const parts = capParts(orderedParts, used, fixedParts.length);
|
|
460
|
+
const attributed = parts.reduce((sum, part) => sum + part.tokens, 0);
|
|
461
|
+
const other = Math.max(0, used - attributed);
|
|
403
462
|
const free = Math.max(0, contextWindow - used);
|
|
404
|
-
const allParts = [
|
|
463
|
+
const allParts = [
|
|
464
|
+
...parts,
|
|
465
|
+
{ label: "Other", tokens: other, color: "muted" as const },
|
|
466
|
+
{ label: "Free space", tokens: free, color: "dim" as const },
|
|
467
|
+
];
|
|
405
468
|
|
|
406
469
|
if (ctx.mode !== "tui") {
|
|
407
470
|
const lines = allParts.map((part) => `${part.label}: ${formatTokens(part.tokens)} tokens`);
|
|
@@ -456,6 +519,12 @@ export default function contextUsageExtension(pi: ExtensionAPI) {
|
|
|
456
519
|
title: "Tools",
|
|
457
520
|
content: toolContent.join("\n\n") || "No active tools.",
|
|
458
521
|
},
|
|
522
|
+
{
|
|
523
|
+
key: "toolResults",
|
|
524
|
+
label: "Tool results",
|
|
525
|
+
title: "Tool Results",
|
|
526
|
+
content: breakdown.toolResults,
|
|
527
|
+
},
|
|
459
528
|
{
|
|
460
529
|
key: "contextFiles",
|
|
461
530
|
label: "Context files",
|
|
@@ -80,14 +80,20 @@ function renderAdmonition(lines: string[], i: number): { output: string[]; next:
|
|
|
80
80
|
// 裸 URL 转可点击超链接
|
|
81
81
|
// ============================================================================
|
|
82
82
|
|
|
83
|
-
const URL_RE = /(?<!<)(?<!\]\()https?:\/\/[^\s<>'"
|
|
84
|
-
const TRIM_URL_RE = /[.,;:!?】」』"'
|
|
83
|
+
const URL_RE = /(?<!<)(?<!\]\()https?:\/\/[^\s<>'"|,。;:!?、」』】()【】《》『』「」]+/g;
|
|
84
|
+
const TRIM_URL_RE = /[.,;:!?】」』"'》)}]+$/;
|
|
85
85
|
|
|
86
86
|
/** 去掉 URL 尾部标点;括号按平衡保留(如 Wikipedia 链接含括号)。 */
|
|
87
87
|
function trimUrl(url: string): string {
|
|
88
88
|
let t = url.replace(TRIM_URL_RE, "");
|
|
89
|
-
while (
|
|
90
|
-
t
|
|
89
|
+
while (true) {
|
|
90
|
+
if (t.endsWith(")") && (t.match(/\(/g)?.length ?? 0) < (t.match(/\)/g)?.length ?? 0)) {
|
|
91
|
+
t = t.slice(0, -1);
|
|
92
|
+
} else if (t.endsWith("]") && (t.match(/\[/g)?.length ?? 0) < (t.match(/\]/g)?.length ?? 0)) {
|
|
93
|
+
t = t.slice(0, -1);
|
|
94
|
+
} else {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
91
97
|
}
|
|
92
98
|
return t;
|
|
93
99
|
}
|
|
@@ -246,6 +252,41 @@ function deCircled(markdown: string): string {
|
|
|
246
252
|
return output.join("\n");
|
|
247
253
|
}
|
|
248
254
|
|
|
255
|
+
// ============================================================================
|
|
256
|
+
// 跨行链接规整
|
|
257
|
+
// ============================================================================
|
|
258
|
+
|
|
259
|
+
const MULTILINE_LINK_RE = /\[([^\]\n]*(?:\n[^\]\n]*)+)\](?=\()/g;
|
|
260
|
+
|
|
261
|
+
/** 防止 Markdown 跨行链接把行尾填充空格纳入 OSC 8 点击区。 */
|
|
262
|
+
function normalizeMultilineLinks(markdown: string): string {
|
|
263
|
+
const out: string[] = [];
|
|
264
|
+
let prose: string[] = [];
|
|
265
|
+
let fence: MarkdownFence | undefined;
|
|
266
|
+
const flush = () => {
|
|
267
|
+
if (prose.length === 0) return;
|
|
268
|
+
out.push(
|
|
269
|
+
prose.join("\n").replace(MULTILINE_LINK_RE, (_match, label: string) => {
|
|
270
|
+
const normalized = label.replace(/[ \t]*\n[ \t]*/g, " ").trim();
|
|
271
|
+
return `[${normalized}]`;
|
|
272
|
+
}),
|
|
273
|
+
);
|
|
274
|
+
prose = [];
|
|
275
|
+
};
|
|
276
|
+
for (const line of markdown.split("\n")) {
|
|
277
|
+
const scanned = scanMarkdownFence(line, fence);
|
|
278
|
+
fence = scanned.fence;
|
|
279
|
+
if (scanned.protected) {
|
|
280
|
+
flush();
|
|
281
|
+
out.push(line);
|
|
282
|
+
} else {
|
|
283
|
+
prose.push(line);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
flush();
|
|
287
|
+
return out.join("\n");
|
|
288
|
+
}
|
|
289
|
+
|
|
249
290
|
// ============================================================================
|
|
250
291
|
// 注册
|
|
251
292
|
// ============================================================================
|
|
@@ -255,8 +296,9 @@ export default function (pi: ExtensionAPI): void {
|
|
|
255
296
|
// 所以三个转换合并为一次注册,内部按序链式执行。
|
|
256
297
|
pi.registerMarkdownTransformer((markdown, context) => {
|
|
257
298
|
const { messageType, isStreaming = false } = context ?? {};
|
|
258
|
-
|
|
259
|
-
|
|
299
|
+
if (messageType === "assistant-thinking") return markdown;
|
|
300
|
+
markdown = normalizeMultilineLinks(markdown);
|
|
301
|
+
if (isStreaming) return markdown;
|
|
260
302
|
// 0. 圈数字转半角括号(Nerd Font 补丁字形缺陷规避)
|
|
261
303
|
markdown = deCircled(markdown);
|
|
262
304
|
// 1. Mermaid 方言渲染
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herbertgao/pi-cc-extensions",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.55",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "A Pi productivity suite with Claude Code-style UI, context inspection, and agent/session references",
|
|
6
6
|
"type": "module",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
},
|
|
70
70
|
"x-upstream": {
|
|
71
71
|
"package": "pi-cc-extensions",
|
|
72
|
-
"version": "0.8.
|
|
72
|
+
"version": "0.8.60",
|
|
73
73
|
"repository": "https://github.com/minuque/pi-cc-extensions",
|
|
74
|
-
"commit": "
|
|
74
|
+
"commit": "268e017acde0b2adb65cefef3c740e37b1aef202"
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.15.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#72](https://github.com/HerbertGao/pi-extensions/pull/72) [`5a133d4`](https://github.com/HerbertGao/pi-extensions/commit/5a133d4753532beef884b093638bceacf0545629) Thanks [@HerbertGao](https://github.com/HerbertGao)! - Bypass Git signing for internal worktree preservation commits so interactive signers cannot time out and discard agent changes.
|
|
8
|
+
|
|
9
|
+
- [#73](https://github.com/HerbertGao/pi-extensions/pull/73) [`553f466`](https://github.com/HerbertGao/pi-extensions/commit/553f4662b968cacaf969c1f4e588d29403c54bfc) Thanks [@HerbertGao](https://github.com/HerbertGao)! - Use the primary text color across selected FleetView rows while preserving configured agent badges, and record the reviewed post-0.16.1 upstream range.
|
|
10
|
+
|
|
11
|
+
- [#66](https://github.com/HerbertGao/pi-extensions/pull/66) [`af56b15`](https://github.com/HerbertGao/pi-extensions/commit/af56b159ce7081daf191d12da6afe3155e2b52b0) Thanks [@HerbertGao](https://github.com/HerbertGao)! - Sync the applicable pi-subagents 0.16.1 compatibility fix and advance the reviewed upstream baseline to bb47763 while preserving the local fork behavior.
|
|
12
|
+
|
|
3
13
|
## 0.15.4
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herbertgao/pi-subagents",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.5",
|
|
4
4
|
"description": "Claude Code-style autonomous subagents for Pi, with HerbertGao-maintained UI extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
},
|
|
69
69
|
"x-upstream": {
|
|
70
70
|
"package": "@tintinweb/pi-subagents",
|
|
71
|
-
"version": "0.16.
|
|
71
|
+
"version": "0.16.1",
|
|
72
72
|
"repository": "https://github.com/tintinweb/pi-subagents",
|
|
73
|
-
"commit": "
|
|
73
|
+
"commit": "bb47763"
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -958,18 +958,21 @@ export async function runAgent(
|
|
|
958
958
|
type SessionOptions = NonNullable<Parameters<typeof createAgentSession>[0]>
|
|
959
959
|
const parentModelRuntime = (
|
|
960
960
|
ctx.modelRegistry as unknown as {
|
|
961
|
-
runtime?:
|
|
961
|
+
runtime?: unknown
|
|
962
962
|
}
|
|
963
963
|
).runtime
|
|
964
964
|
const sessionOpts: SessionOptions & {
|
|
965
965
|
modelRegistry: ExtensionContext["modelRegistry"]
|
|
966
|
+
modelRuntime?: unknown
|
|
966
967
|
} = {
|
|
967
968
|
cwd: effectiveCwd,
|
|
968
969
|
agentDir,
|
|
969
970
|
sessionManager,
|
|
970
971
|
settingsManager,
|
|
971
972
|
modelRegistry: ctx.modelRegistry,
|
|
972
|
-
...(parentModelRuntime != null && {
|
|
973
|
+
...(parentModelRuntime != null && {
|
|
974
|
+
modelRuntime: parentModelRuntime as never,
|
|
975
|
+
}),
|
|
973
976
|
model,
|
|
974
977
|
tools: sessionTools,
|
|
975
978
|
customTools: nestedTools,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
truncateToWidth,
|
|
20
20
|
visibleWidth,
|
|
21
21
|
} from "@earendil-works/pi-tui"
|
|
22
|
-
import { renderAgentName } from "../agent-color.js"
|
|
22
|
+
import { hasAgentBadge, renderAgentName } from "../agent-color.js"
|
|
23
23
|
import type { AgentManager } from "../agent-manager.js"
|
|
24
24
|
import type { AgentRecord } from "../types.js"
|
|
25
25
|
import { getLifetimeTotal } from "../usage.js"
|
|
@@ -476,15 +476,24 @@ export class FleetList {
|
|
|
476
476
|
width: number,
|
|
477
477
|
theme: Theme,
|
|
478
478
|
): string {
|
|
479
|
-
const
|
|
479
|
+
const selected = rosterIndex === sel
|
|
480
|
+
const name = renderAgentName(
|
|
481
|
+
record.type,
|
|
482
|
+
theme,
|
|
483
|
+
selected
|
|
484
|
+
? { fallbackColor: "text", bold: hasAgentBadge(record.type) }
|
|
485
|
+
: { fallbackColor: "muted" },
|
|
486
|
+
)
|
|
487
|
+
const description = selected
|
|
488
|
+
? theme.fg("text", record.description)
|
|
489
|
+
: record.description
|
|
490
|
+
const left = ` ${this.bullet(rosterIndex, sel, theme)} ${name} ${description}`
|
|
480
491
|
const tokens = getLifetimeTotal(
|
|
481
492
|
this.agentActivity.get(record.id)?.lifetimeUsage ?? record.lifetimeUsage,
|
|
482
493
|
)
|
|
483
494
|
const elapsedMs = (record.completedAt ?? Date.now()) - record.startedAt // freezes once finished
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
`${formatFleetElapsed(elapsedMs)} · ${formatFleetTokens(tokens)}`,
|
|
487
|
-
)
|
|
495
|
+
const stats = `${formatFleetElapsed(elapsedMs)} · ${formatFleetTokens(tokens)}`
|
|
496
|
+
const right = selected ? theme.fg("text", stats) : theme.fg("dim", stats)
|
|
488
497
|
return rightAlign(left, right, width)
|
|
489
498
|
}
|
|
490
499
|
}
|
|
@@ -134,11 +134,15 @@ export function cleanupWorktree(
|
|
|
134
134
|
// Truncate description for commit message (no shell sanitization needed — execFileSync uses argv)
|
|
135
135
|
const safeDesc = agentDescription.slice(0, 200)
|
|
136
136
|
const commitMsg = `pi-agent: ${safeDesc}`
|
|
137
|
-
execFileSync(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
execFileSync(
|
|
138
|
+
"git",
|
|
139
|
+
["commit", "--no-verify", "--no-gpg-sign", "-m", commitMsg],
|
|
140
|
+
{
|
|
141
|
+
cwd: worktree.path,
|
|
142
|
+
stdio: "pipe",
|
|
143
|
+
timeout: 10000,
|
|
144
|
+
},
|
|
145
|
+
)
|
|
142
146
|
} else {
|
|
143
147
|
const currentSha = execFileSync("git", ["rev-parse", "HEAD"], {
|
|
144
148
|
cwd: worktree.path,
|
|
@@ -27,6 +27,8 @@ Nothing to set up — the tool is live as soon as Pi restarts. Hand the model a
|
|
|
27
27
|
|
|
28
28
|
Rather than picking a strategy on your behalf, the model calls `ask_user_question` and a dialog takes over the bottom of your terminal. Move with `↑`/`↓`, choose with `Enter`, press `n` to attach a note, or land on the `Type something.` row to answer in your own words. While typing, `Shift+Enter` adds a line, `Ctrl+G` opens Pi's configured external editor, and `Ctrl+U` clears the draft; browsing another option and returning keeps what you wrote. `Esc` abandons the questionnaire entirely.
|
|
29
29
|
|
|
30
|
+
When the questionnaire begins waiting in an interactive TTY, it emits one standard terminal BEL (`\x07`). Your terminal configuration determines whether that appears as an audible alert, a visual alert, or nothing; redirected and non-TTY output is untouched.
|
|
31
|
+
|
|
30
32
|

|
|
31
33
|
|
|
32
34
|
When the model asks several things at once, `Tab` moves between them and a Submit tab reviews everything before it goes back:
|
|
@@ -61,6 +61,24 @@ const ERROR_SESSION_LOAD_FAILED =
|
|
|
61
61
|
const ERROR_STALE_MODULE_CACHE =
|
|
62
62
|
"Error: the questionnaire UI cannot load — the host's module cache went stale after an earlier failed load (typically dependencies replaced on disk mid-session). This is unrecoverable within the current Pi process. The user never saw the questions — do NOT treat this as a decline. Ask the questions as plain chat text instead, and tell the user to restart Pi to restore this tool.";
|
|
63
63
|
|
|
64
|
+
/** Standard terminal bell — same byte rpiv-warp exports as OSC_TERMINATOR. */
|
|
65
|
+
export const BEL = "\x07";
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Emit one portable terminal attention signal without touching redirected output.
|
|
69
|
+
* Writes to stdout rather than rpiv-warp's `/dev/tty` transport: the `isTTY` gate
|
|
70
|
+
* both proves an interactive terminal owns the coming wait and keeps the byte out
|
|
71
|
+
* of piped RPC transports (VS Code pendant, Zed) — a `/dev/tty` write would ring
|
|
72
|
+
* even when the questionnaire renders in a remote host's own UI.
|
|
73
|
+
*/
|
|
74
|
+
function emitTerminalAttention(): void {
|
|
75
|
+
try {
|
|
76
|
+
if (process.stdout.isTTY) process.stdout.write(BEL);
|
|
77
|
+
} catch {
|
|
78
|
+
// Terminal attention is best effort; the questionnaire must still proceed.
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
64
82
|
/** Delay before the background session-graph pre-warm; mirrors rpiv-workflow's /wf prewarm. */
|
|
65
83
|
export const PREWARM_DELAY_MS = 2000;
|
|
66
84
|
|
|
@@ -173,6 +191,7 @@ Preview content is rendered as markdown in a monospace box. Multi-line text with
|
|
|
173
191
|
if ((ctx as { mode?: string }).mode === "rpc" && hasDialogUI(ctx.ui)) {
|
|
174
192
|
emitAskUserBlockedEvent(pi, true);
|
|
175
193
|
try {
|
|
194
|
+
emitTerminalAttention();
|
|
176
195
|
return buildQuestionnaireResponse(await runRpcQuestionnaire(ctx.ui, typed), typed);
|
|
177
196
|
} finally {
|
|
178
197
|
emitAskUserBlockedEvent(pi, false);
|
|
@@ -232,6 +251,7 @@ Preview content is rendered as markdown in a monospace box. Multi-line text with
|
|
|
232
251
|
|
|
233
252
|
emitAskUserBlockedEvent(pi, true);
|
|
234
253
|
try {
|
|
254
|
+
emitTerminalAttention();
|
|
235
255
|
const result = await ctx.ui.custom<QuestionnaireResult>(
|
|
236
256
|
(tui, theme, keybindings, done) => {
|
|
237
257
|
const session = new QuestionnaireSession({
|
|
@@ -11,6 +11,12 @@ render at all.
|
|
|
11
11
|
| RPC / ACP host (VS Code pendant, Zed, Paseo) | `ask_user_question` in its tool list | A sequence of the host's own native select and input dialogs |
|
|
12
12
|
| Non-interactive run (no UI) | Nothing — the tool is removed | Nothing |
|
|
13
13
|
|
|
14
|
+
### Terminal attention
|
|
15
|
+
|
|
16
|
+
After UI availability and questionnaire validation succeed, the package emits exactly one standard terminal BEL (`\x07`) immediately before the interactive wait begins. The signal is sent to `stdout` only when `process.stdout.isTTY` is true, so redirected output and non-TTY RPC streams stay untouched. A TTY-backed RPC dialog walker receives the same signal as the TUI path.
|
|
17
|
+
|
|
18
|
+
The BEL is best effort: if the synchronous terminal write fails, the questionnaire continues and its existing prompt/blocked lifecycle and result envelope are unchanged. The terminal configuration decides whether the BEL is audible, visual, or ignored. No BEL is emitted for missing UI, invalid questionnaires, or a failed TUI session load.
|
|
19
|
+
|
|
14
20
|
### Non-interactive runs
|
|
15
21
|
|
|
16
22
|
A `before_agent_start` hook reconciles the active tool set against `ctx.hasUI` before every
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juicesharp/rpiv-ask-user-question",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Pi extension. A structured questionnaire the model can put to you when it would otherwise guess, with typed options instead of free-form replies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
}
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"@juicesharp/rpiv-config": "^2.
|
|
96
|
+
"@juicesharp/rpiv-config": "^2.6.0",
|
|
97
97
|
"typebox": "^1.1.24"
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -18,7 +18,7 @@ Use it when you want to ask a temporary question, inspect context, or get a shor
|
|
|
18
18
|
- Optionally brings the latest answer, a question-to-end suffix, an exact line range, or the entire side thread into the main editor.
|
|
19
19
|
- Uses the current session branch as context.
|
|
20
20
|
- Uses Pi's current model or an independent model selected in `pi-btw.json`.
|
|
21
|
-
- Uses a pi-btw thinking level that can
|
|
21
|
+
- Uses a pi-btw thinking level that can either start from the main thread or use a fixed remembered value.
|
|
22
22
|
- Does not append the side question or answer to the main conversation.
|
|
23
23
|
- Works as an independently installable npm Pi extension package.
|
|
24
24
|
|
|
@@ -61,7 +61,7 @@ Examples:
|
|
|
61
61
|
Running `/btw` alone opens a menu with **Start side thread** selected first.
|
|
62
62
|
When the current Pi session has non-empty side threads in memory, **Resume side thread** opens a bounded searchable choice list.
|
|
63
63
|
Search matches the displayed first question and question count while returning the thread's raw in-memory ID.
|
|
64
|
-
**Settings** changes the starting thinking level and whether shortcut changes are remembered.
|
|
64
|
+
**Settings** changes the starting thinking level and whether shortcut changes for fixed levels are remembered.
|
|
65
65
|
Each Resume row keeps the first question as its fixed title, shows its question count, and the list is ordered by the newest recorded answer or visible error.
|
|
66
66
|
Opening and closing a thread without a new result does not reorder it.
|
|
67
67
|
`/btw <question>` bypasses this menu and always starts a fresh side thread.
|
|
@@ -79,9 +79,11 @@ Previous side questions and answers remain available to the model and visible fo
|
|
|
79
79
|
invocation. The side-thread header shows its current thinking level. Press Pi's configured
|
|
80
80
|
`app.thinking.cycle` shortcut (`Shift+Tab` by default) in the composer to cycle the levels
|
|
81
81
|
supported by the side-thread model; every later question uses the displayed level until it is
|
|
82
|
-
changed again.
|
|
83
|
-
invocation. Turn **Remember thinking level changes** off in
|
|
84
|
-
current side thread.
|
|
82
|
+
changed again. When a fixed thinking level is selected, each shortcut change is also written to
|
|
83
|
+
`pi-btw.json` for the next invocation by default. Turn **Remember thinking level changes** off in
|
|
84
|
+
Settings to keep fixed-level changes local to the current side thread. When **Same as main thread** is
|
|
85
|
+
selected, shortcut changes are always local to the current side thread. Neither path changes the main
|
|
86
|
+
session's thinking level.
|
|
85
87
|
While a response is running, the transcript and composer remain visible above an `Answering…`
|
|
86
88
|
status.
|
|
87
89
|
Type another question and press `Enter` to queue it as `Steering`; queued questions are shown in
|
|
@@ -148,18 +150,23 @@ cannot be found or authenticated, pi-btw warns and falls back to the current ses
|
|
|
148
150
|
If neither model is available, `/btw` reports an error and stops. This selection affects only
|
|
149
151
|
`/btw`; it does not change the main session model.
|
|
150
152
|
|
|
151
|
-
Pi calls its reasoning setting the **thinking level**.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
`
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
A
|
|
153
|
+
Pi calls its reasoning setting the **thinking level**. In Settings, choose **Same as main thread**
|
|
154
|
+
to start each new side thread from the main thread's current thinking level. This is stored by
|
|
155
|
+
omitting `thinkingLevel` from `pi-btw.json`.
|
|
156
|
+
|
|
157
|
+
Set `thinkingLevel` only when you want a fixed pi-btw starting level. Accepted fixed values are
|
|
158
|
+
`off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. The initial value and shortcut cycle
|
|
159
|
+
are clamped to the selected side model's capabilities using Pi's model rules. Resumed side threads
|
|
160
|
+
keep their own local thinking level instead of re-syncing with the main thread. Pi-btw does not read,
|
|
161
|
+
write, or change the main session's `defaultThinkingLevel`.
|
|
162
|
+
|
|
163
|
+
`rememberThinkingLevelChanges` controls only persistence for fixed thinking levels and defaults to
|
|
164
|
+
`true` when omitted. A side-thread shortcut always changes that side thread immediately. When a fixed
|
|
165
|
+
thinking level is selected and remembering is on, the concrete level is written for the next
|
|
166
|
+
invocation; when off, `pi-btw.json` stays unchanged. When **Same as main thread** is selected,
|
|
167
|
+
shortcut changes stay local even when remembering is on. If a shortcut write fails, the local change
|
|
168
|
+
remains active and pi-btw warns that it was not remembered. A failed Settings-screen save instead
|
|
169
|
+
restores the previous displayed value.
|
|
163
170
|
|
|
164
171
|
A missing settings file is a side-effect-free read: pi-btw creates it only after a Settings change
|
|
165
172
|
or a remembered shortcut change. Saves are ordered within the Pi process and published atomically
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narumitw/pi-btw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.52.0",
|
|
4
4
|
"description": "Pi extension that adds a /btw side-question command.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"typecheck": "tsc --noEmit"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@biomejs/biome": "2.5.
|
|
35
|
-
"@earendil-works/pi-ai": "0.84.
|
|
36
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
37
|
-
"@earendil-works/pi-tui": "0.84.
|
|
34
|
+
"@biomejs/biome": "2.5.8",
|
|
35
|
+
"@earendil-works/pi-ai": "0.84.2",
|
|
36
|
+
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
37
|
+
"@earendil-works/pi-tui": "0.84.2",
|
|
38
38
|
"typescript": "7.0.2"
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
@@ -194,7 +194,7 @@ export async function loadBtwThinkingLevel(
|
|
|
194
194
|
|
|
195
195
|
options.warn?.(
|
|
196
196
|
sanitizeSingleLine(
|
|
197
|
-
`pi-btw settings ignored: ${settings.reason}; expected optional model "provider/model-id", thinkingLevel "${BTW_THINKING_LEVELS.join('" | "')}", and boolean rememberThinkingLevelChanges. Using current Pi thinking level.`,
|
|
197
|
+
`pi-btw settings ignored: ${settings.reason}; expected optional model "provider/model-id", omitted thinkingLevel for Same as main thread or thinkingLevel "${BTW_THINKING_LEVELS.join('" | "')}", and boolean rememberThinkingLevelChanges. Using current Pi thinking level.`,
|
|
198
198
|
),
|
|
199
199
|
);
|
|
200
200
|
return currentThinkingLevel;
|
|
@@ -265,6 +265,7 @@ export default function btw(pi: ExtensionAPI, dependencies: BtwExtensionDependen
|
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
const settings = await loadSettings(ctx);
|
|
268
|
+
const sameAsMainThinkingLevel = settings.thinkingLevel === undefined;
|
|
268
269
|
const resolution = await resolveModel(settings, ctx);
|
|
269
270
|
if (resolution.kind === "cancelled") {
|
|
270
271
|
notifySafely(ctx, "Cancelled", "info");
|
|
@@ -302,7 +303,8 @@ export default function btw(pi: ExtensionAPI, dependencies: BtwExtensionDependen
|
|
|
302
303
|
initialQuestion: question || undefined,
|
|
303
304
|
selected: resolution.selected,
|
|
304
305
|
thinkingLevel: state.thinkingLevel,
|
|
305
|
-
rememberThinkingLevelChanges:
|
|
306
|
+
rememberThinkingLevelChanges:
|
|
307
|
+
!sameAsMainThinkingLevel && effectiveRememberThinkingLevelChanges(settings),
|
|
306
308
|
state,
|
|
307
309
|
ctx: fullscreenCtx,
|
|
308
310
|
});
|