@herbertgao/pi-extensions 2026.8.14 → 2026.8.15
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 +16 -13
- package/THIRD_PARTY_NOTICES.md +0 -1
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +8 -1
- package/node_modules/@czottmann/pi-automode/README.md +4 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +71 -9
- package/node_modules/@czottmann/pi-automode/package.json +1 -1
- package/node_modules/@herbertgao/pi-bark/LICENSE +21 -0
- package/node_modules/@herbertgao/pi-bark/README.md +44 -0
- package/node_modules/@herbertgao/pi-bark/assets/pi-icon.png +0 -0
- package/node_modules/@herbertgao/pi-bark/package.json +53 -0
- package/node_modules/@herbertgao/pi-bark/src/index.ts +178 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/README.md +125 -88
- package/node_modules/@narumitw/pi-btw/dist/index.ts +140 -45
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +2 -2
- package/node_modules/@narumitw/pi-btw/package.json +5 -8
- package/node_modules/@narumitw/pi-btw/src/btw.ts +31 -26
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +106 -17
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -2
- package/node_modules/@narumitw/pi-btw/src/settings.ts +16 -0
- package/node_modules/@tifan/pi-handoff/README.md +36 -13
- package/node_modules/@tifan/pi-handoff/package.json +2 -2
- package/node_modules/@tifan/pi-handoff/src/index.ts +160 -4
- package/node_modules/@tifan/pi-recap/README.md +1 -1
- package/node_modules/@tifan/pi-recap/package.json +2 -2
- package/node_modules/@tifan/pi-recap/src/index.ts +15 -0
- package/node_modules/@tifan/pi-rename/README.md +42 -21
- package/node_modules/@tifan/pi-rename/package.json +1 -1
- package/node_modules/@tifan/pi-rename/src/index.ts +62 -11
- package/node_modules/@tifan/pi-rename/src/language.ts +18 -0
- package/node_modules/@tifan/pi-rename/src/models.ts +69 -13
- package/node_modules/@tifan/pi-rename/src/naming.ts +36 -7
- package/node_modules/@tifan/pi-rename/src/sanitize.ts +22 -14
- package/node_modules/pi-lens/CHANGELOG.md +320 -0
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +79 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +16 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +13 -6
- package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +12 -0
- package/node_modules/pi-lens/dist/clients/biome-client.js +7 -0
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +20 -0
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +56 -19
- package/node_modules/pi-lens/dist/clients/build-identity.js +95 -0
- package/node_modules/pi-lens/dist/clients/bus-publish.js +3 -0
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +2 -1
- package/node_modules/pi-lens/dist/clients/cache-observability.js +2 -1
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +15 -1
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +14 -11
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +56 -4
- package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +14 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +20 -3
- package/node_modules/pi-lens/dist/clients/deps/minimatch.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +39 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +150 -9
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +231 -9
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +205 -100
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +87 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +21 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +174 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +54 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +37 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +11 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +8 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +76 -25
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +19 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +7 -13
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +51 -17
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +66 -1
- package/node_modules/pi-lens/dist/clients/file-utils.js +157 -7
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +5 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +28 -3
- package/node_modules/pi-lens/dist/clients/git-guard.js +197 -47
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +32 -1
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +5 -1
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +7 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +131 -34
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +3 -1
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +4 -13
- package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +145 -0
- package/node_modules/pi-lens/dist/clients/instance-registry.js +432 -122
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
- package/node_modules/pi-lens/dist/clients/language-profile.js +4 -2
- package/node_modules/pi-lens/dist/clients/latency-logger.js +19 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +3 -1
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +4 -0
- package/node_modules/pi-lens/dist/clients/lsp/client.js +516 -31
- package/node_modules/pi-lens/dist/clients/lsp/config.js +25 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +9 -4
- package/node_modules/pi-lens/dist/clients/lsp/index.js +509 -182
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +5 -0
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +36 -8
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +116 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +142 -13
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +99 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +16 -6
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +32 -23
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +16 -2
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +12 -6
- package/node_modules/pi-lens/dist/clients/mcp/session.js +14 -1
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +23 -1
- package/node_modules/pi-lens/dist/clients/message-end-attribution.js +30 -0
- package/node_modules/pi-lens/dist/clients/metrics-history.js +21 -4
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +232 -18
- package/node_modules/pi-lens/dist/clients/package-manager.js +6 -18
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +14 -1
- package/node_modules/pi-lens/dist/clients/path-utils.js +32 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +0 -8
- package/node_modules/pi-lens/dist/clients/process-singletons.js +210 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +2 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +10 -4
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +33 -11
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +24 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +74 -7
- package/node_modules/pi-lens/dist/clients/recent-touches.js +17 -5
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +639 -62
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +5 -1
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +21 -1
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +68 -0
- package/node_modules/pi-lens/dist/clients/runtime-session.js +30 -12
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +15 -0
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +106 -7
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +242 -27
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +158 -18
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +48 -17
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +238 -42
- package/node_modules/pi-lens/dist/clients/sg-runner.js +27 -15
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +338 -0
- package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +37 -0
- package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +15 -1
- package/node_modules/pi-lens/dist/clients/startup-scan.js +6 -7
- package/node_modules/pi-lens/dist/clients/startup-timing.js +69 -4
- package/node_modules/pi-lens/dist/clients/string-utils.js +20 -0
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +419 -88
- package/node_modules/pi-lens/dist/clients/tool-policy.js +1 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +11 -5
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +17 -1
- package/node_modules/pi-lens/dist/clients/warm-attach.js +8 -10
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +13 -1
- package/node_modules/pi-lens/dist/clients/word-index-store.js +448 -0
- package/node_modules/pi-lens/dist/clients/word-index.js +582 -104
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +17 -0
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +26 -6
- package/node_modules/pi-lens/dist/index.js +11243 -6651
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +8 -7
- package/node_modules/pi-lens/dist/mcp/cli.js +3 -1
- package/node_modules/pi-lens/dist/mcp/server.js +6 -1
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +4 -0
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +14 -5
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
- package/node_modules/pi-lens/docs/agent-guide.md +4 -2
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +41 -10
- package/node_modules/pi-lens/docs/astplayground.md +26 -17
- package/node_modules/pi-lens/package.json +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/c-no-malloc-free-test.yml +20 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-malloc-free-test.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-printf-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-fmt-println-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-panic-in-lib-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-underscore-func-name-test.yml +18 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-errors-is-test.yml +15 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-string-builder-test.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/hyphenated-svg-attribute-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-lateinit-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-nullable-boolean-test.yml +15 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-println-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unnecessary-let-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unsafe-cast-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-var-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-data-class-test.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-is-empty-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-important-test.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-types-test.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-string-concat-in-loop-test.yml +100 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-system-out-println-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/prefer-string-is-empty-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/python-optional-type-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/reducible-list-comprehension-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ruby-symbol-to-proc-candidate-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/rust-no-chars-enumerate-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/c-no-malloc-free.yml +39 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-malloc-free.yml +45 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-printf.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +43 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-panic-in-lib.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-underscore-func-name.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-errors-is.yml +40 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-string-builder.yml +43 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/hyphenated-svg-attribute.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-lateinit.yml +37 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-nullable-boolean.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-println.yml +42 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unnecessary-let.yml +28 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unsafe-cast.yml +28 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-var.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-data-class.yml +66 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-is-empty.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-important.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-types.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-string-concat-in-loop.yml +90 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-system-out-println.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/prefer-string-is-empty.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/python-optional-type.yml +22 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/reducible-list-comprehension.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ruby-symbol-to-proc-candidate.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/rust-no-chars-enumerate.yml +19 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +15 -0
- package/node_modules/pi-mcp-adapter/README.md +2 -2
- package/node_modules/pi-mcp-adapter/commands.ts +1 -1
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +1 -1
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +105 -32
- package/node_modules/pi-mcp-adapter/package.json +1 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +22 -12
- package/node_modules/pi-mcp-adapter/server-manager.ts +6 -0
- package/node_modules/pi-mcp-adapter/types.ts +1 -1
- package/node_modules/pi-web-access/CHANGELOG.md +20 -0
- package/node_modules/pi-web-access/README.md +15 -2
- package/node_modules/pi-web-access/extract.ts +57 -12
- package/node_modules/pi-web-access/github-extract.ts +47 -3
- package/node_modules/pi-web-access/index.ts +1 -1
- package/node_modules/pi-web-access/package.json +1 -1
- package/node_modules/pi-web-access/page-query.ts +61 -8
- package/package.json +16 -16
- package/node_modules/@tifan/pi-titlebar-spinner/README.md +0 -24
- package/node_modules/@tifan/pi-titlebar-spinner/package.json +0 -39
- package/node_modules/@tifan/pi-titlebar-spinner/src/index.ts +0 -49
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync } from "node:fs";
|
|
1
|
+
import { chmodSync, closeSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync } from "node:fs";
|
|
2
2
|
import { execFile, spawn, type ChildProcess } from "node:child_process";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { basename, dirname, extname, join, resolve as resolvePath, sep as pathSep } from "node:path";
|
|
@@ -59,6 +59,7 @@ interface GitHubCloneConfig {
|
|
|
59
59
|
const cloneCache = new Map<string, CachedClone>();
|
|
60
60
|
|
|
61
61
|
let cachedConfig: GitHubCloneConfig | null = null;
|
|
62
|
+
let cloneRuntime: { parentPath: string; rootPath: string } | null = null;
|
|
62
63
|
|
|
63
64
|
function normalizeEnabled(value: unknown, fallback: boolean): boolean {
|
|
64
65
|
return typeof value === "boolean" ? value : fallback;
|
|
@@ -189,10 +190,48 @@ function cacheKey(owner: string, repo: string, ref?: string): string {
|
|
|
189
190
|
return ref ? `${owner}/${repo}@${ref}` : `${owner}/${repo}`;
|
|
190
191
|
}
|
|
191
192
|
|
|
193
|
+
function removeCloneRuntime(parentPath: string, runtimePath: string): void {
|
|
194
|
+
const normalizedParentPath = resolvePath(parentPath);
|
|
195
|
+
const normalizedRuntimePath = resolvePath(runtimePath);
|
|
196
|
+
if (dirname(normalizedRuntimePath) !== normalizedParentPath || !basename(normalizedRuntimePath).startsWith("runtime-")) return;
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const entry = lstatSync(normalizedRuntimePath);
|
|
200
|
+
if (entry.isSymbolicLink()) unlinkSync(normalizedRuntimePath);
|
|
201
|
+
else rmSync(normalizedRuntimePath, { recursive: true, force: true });
|
|
202
|
+
} catch {
|
|
203
|
+
// The runtime directory may already have been removed externally.
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function getCloneRuntimeRoot(config: GitHubCloneConfig): string | null {
|
|
208
|
+
if (cloneRuntime) return cloneRuntime.rootPath;
|
|
209
|
+
|
|
210
|
+
let parentPath: string | null = null;
|
|
211
|
+
let runtimePath: string | null = null;
|
|
212
|
+
try {
|
|
213
|
+
const configuredPath = resolvePath(config.clonePath);
|
|
214
|
+
mkdirSync(configuredPath, { recursive: true });
|
|
215
|
+
parentPath = realpathSync(configuredPath);
|
|
216
|
+
runtimePath = mkdtempSync(join(parentPath, "runtime-"));
|
|
217
|
+
chmodSync(runtimePath, 0o700);
|
|
218
|
+
const rootPath = realpathSync(runtimePath);
|
|
219
|
+
if (dirname(rootPath) !== parentPath) {
|
|
220
|
+
removeCloneRuntime(parentPath, runtimePath);
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
cloneRuntime = { parentPath, rootPath };
|
|
224
|
+
return rootPath;
|
|
225
|
+
} catch {
|
|
226
|
+
if (parentPath && runtimePath) removeCloneRuntime(parentPath, runtimePath);
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
192
231
|
function cloneDestination(config: GitHubCloneConfig, owner: string, repo: string, ref?: string): CloneDestination | null {
|
|
193
232
|
try {
|
|
194
|
-
|
|
195
|
-
|
|
233
|
+
const rootPath = getCloneRuntimeRoot(config);
|
|
234
|
+
if (!rootPath) return null;
|
|
196
235
|
const digest = createHash("sha256").update(JSON.stringify([owner, repo, ref ?? null])).digest("hex");
|
|
197
236
|
const localPath = resolvePath(rootPath, digest);
|
|
198
237
|
if (dirname(localPath) !== rootPath) return null;
|
|
@@ -742,5 +781,10 @@ export function clearCloneCache(): void {
|
|
|
742
781
|
removeCloneDestination(entry.destination);
|
|
743
782
|
}
|
|
744
783
|
cloneCache.clear();
|
|
784
|
+
|
|
785
|
+
if (cloneRuntime) {
|
|
786
|
+
removeCloneRuntime(cloneRuntime.parentPath, cloneRuntime.rootPath);
|
|
787
|
+
}
|
|
788
|
+
cloneRuntime = null;
|
|
745
789
|
cachedConfig = null;
|
|
746
790
|
}
|
|
@@ -2443,7 +2443,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2443
2443
|
description: "Fetch mode: readable (default extraction), raw (exact textual HTTP body), or answer (answer prompt using only fetched content).",
|
|
2444
2444
|
})),
|
|
2445
2445
|
answerModel: Type.Optional(Type.String({
|
|
2446
|
-
description: "Optional provider/model-id override for mode answer. Defaults to the current Pi model.",
|
|
2446
|
+
description: "Optional provider/model-id override for mode answer. Defaults to fetch.answerProvider + fetch.answerModel when configured, otherwise the current Pi model.",
|
|
2447
2447
|
})),
|
|
2448
2448
|
timestamp: Type.Optional(Type.String({
|
|
2449
2449
|
description: "Extract video frame(s) at a timestamp or time range. Single: '1:23:45', '23:45', or '85' (seconds). Range: '23:41-25:00' extracts evenly-spaced frames across that span (default 6). Use frames with ranges to control density; single+frames uses a fixed 5s interval. YouTube requires yt-dlp + ffmpeg; local videos require ffmpeg. Use a range when you know the approximate area but not the exact moment — you'll get a contact sheet to visually identify the right frame.",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-access",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG, Exa, Perplexity, Gemini, and Kimi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { complete, type Api, type Message, type Model } from "@earendil-works/pi-ai/compat";
|
|
2
2
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import {
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { findModelWithProviderRouting, loadEnabledModelPatterns, modelMatchesEnabledPatterns } from "./summary-model-scope.ts";
|
|
5
|
+
import { getWebSearchConfigPath } from "./utils.ts";
|
|
4
6
|
|
|
5
7
|
const OUTPUT_TOKENS = 2_000;
|
|
6
8
|
const INPUT_CONTEXT_FRACTION = 0.6;
|
|
@@ -16,7 +18,48 @@ export interface PageAnswer {
|
|
|
16
18
|
truncated: boolean;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
interface AnswerModelSelector {
|
|
22
|
+
provider: string;
|
|
23
|
+
id: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function loadConfiguredAnswerModel(): AnswerModelSelector | undefined {
|
|
27
|
+
const configPath = getWebSearchConfigPath();
|
|
28
|
+
if (!existsSync(configPath)) return undefined;
|
|
29
|
+
|
|
30
|
+
let raw: unknown;
|
|
31
|
+
try {
|
|
32
|
+
raw = JSON.parse(readFileSync(configPath, "utf8"));
|
|
33
|
+
} catch (err) {
|
|
34
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
35
|
+
throw new Error(`Failed to parse ${configPath}: ${message}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const root = raw && typeof raw === "object" && !Array.isArray(raw)
|
|
39
|
+
? raw as Record<string, unknown>
|
|
40
|
+
: undefined;
|
|
41
|
+
const fetchConfig = root?.fetch;
|
|
42
|
+
if (!fetchConfig || typeof fetchConfig !== "object" || Array.isArray(fetchConfig)) return undefined;
|
|
43
|
+
const values = fetchConfig as Record<string, unknown>;
|
|
44
|
+
const hasProvider = Object.hasOwn(values, "answerProvider");
|
|
45
|
+
const hasModel = Object.hasOwn(values, "answerModel");
|
|
46
|
+
if (!hasProvider && !hasModel) return undefined;
|
|
47
|
+
|
|
48
|
+
const provider = values.answerProvider;
|
|
49
|
+
const model = values.answerModel;
|
|
50
|
+
if (hasProvider && (typeof provider !== "string" || provider.trim().length === 0)) {
|
|
51
|
+
throw new Error(`fetch.answerProvider in ${configPath} must be a non-empty string`);
|
|
52
|
+
}
|
|
53
|
+
if (hasModel && (typeof model !== "string" || model.trim().length === 0)) {
|
|
54
|
+
throw new Error(`fetch.answerModel in ${configPath} must be a non-empty string`);
|
|
55
|
+
}
|
|
56
|
+
if (!hasProvider || !hasModel) {
|
|
57
|
+
throw new Error(`fetch.answerProvider and fetch.answerModel must be configured together in ${configPath}`);
|
|
58
|
+
}
|
|
59
|
+
return { provider: (provider as string).trim(), id: (model as string).trim() };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function parseModelSelector(value: string): AnswerModelSelector {
|
|
20
63
|
const separator = value.indexOf("/");
|
|
21
64
|
if (separator <= 0 || separator === value.length - 1) {
|
|
22
65
|
throw new Error(`Invalid answerModel: ${value}. Use provider/model-id.`);
|
|
@@ -24,14 +67,20 @@ function parseModelSelector(value: string): { provider: string; id: string } {
|
|
|
24
67
|
return { provider: value.slice(0, separator), id: value.slice(separator + 1) };
|
|
25
68
|
}
|
|
26
69
|
|
|
27
|
-
function resolveModel(ctx: ExtensionContext, override?: string): Model<Api> {
|
|
28
|
-
const
|
|
70
|
+
function resolveModel(ctx: ExtensionContext, override?: string, configured?: AnswerModelSelector): Model<Api> {
|
|
71
|
+
const selector = override ? parseModelSelector(override) : configured;
|
|
72
|
+
const model = selector
|
|
29
73
|
? (() => {
|
|
30
|
-
|
|
31
|
-
return ctx.modelRegistry.find(selector.provider, selector.id);
|
|
74
|
+
return findModelWithProviderRouting(ctx.modelRegistry, selector.provider, selector.id);
|
|
32
75
|
})()
|
|
33
76
|
: ctx.model;
|
|
34
|
-
if (!model)
|
|
77
|
+
if (!model) {
|
|
78
|
+
if (override) throw new Error(`Answer model not found: ${override}`);
|
|
79
|
+
if (configured) {
|
|
80
|
+
throw new Error(`Answer model not found: ${configured.provider}/${configured.id} (from fetch.answerProvider/fetch.answerModel in ${getWebSearchConfigPath()})`);
|
|
81
|
+
}
|
|
82
|
+
throw new Error("No current model available for page answering");
|
|
83
|
+
}
|
|
35
84
|
if (!model.input.includes("text")) throw new Error(`Answer model does not support text input: ${model.provider}/${model.id}`);
|
|
36
85
|
if (!modelMatchesEnabledPatterns(model, loadEnabledModelPatterns(ctx))) {
|
|
37
86
|
throw new Error(`Answer model is not enabled: ${model.provider}/${model.id}`);
|
|
@@ -53,7 +102,11 @@ export async function answerFromPage(
|
|
|
53
102
|
ctx: ExtensionContext,
|
|
54
103
|
signal?: AbortSignal,
|
|
55
104
|
): Promise<PageAnswer> {
|
|
56
|
-
|
|
105
|
+
// Resolve an explicit per-call model first. In particular, do not read a
|
|
106
|
+
// malformed or partial config when the caller has supplied an override.
|
|
107
|
+
const model = input.model
|
|
108
|
+
? resolveModel(ctx, input.model)
|
|
109
|
+
: resolveModel(ctx, undefined, loadConfiguredAnswerModel());
|
|
57
110
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
58
111
|
if (!auth.ok || !auth.apiKey) throw new Error(`No API key available for answer model ${model.provider}/${model.id}`);
|
|
59
112
|
const registry = ctx.modelRegistry as typeof ctx.modelRegistry & { complete?: typeof complete };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herbertgao/pi-extensions",
|
|
3
|
-
"version": "2026.8.
|
|
3
|
+
"version": "2026.8.15",
|
|
4
4
|
"description": "Aggregate installer for HerbertGao-maintained Pi extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"extensions",
|
|
@@ -37,17 +37,18 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@ast-grep/cli": "^0.45.0",
|
|
39
39
|
"@ast-grep/napi": "^0.45.0",
|
|
40
|
-
"@czottmann/pi-automode": "1.
|
|
40
|
+
"@czottmann/pi-automode": "1.15.0",
|
|
41
41
|
"@dietrichgebert/ponytail": "4.9.0",
|
|
42
|
-
"@earendil-works/pi-coding-agent": "^0.84.
|
|
43
|
-
"@earendil-works/pi-tui": "^0.84.
|
|
42
|
+
"@earendil-works/pi-coding-agent": "^0.84.4",
|
|
43
|
+
"@earendil-works/pi-tui": "^0.84.4",
|
|
44
44
|
"@effect/platform-node": "4.0.0-beta.103",
|
|
45
45
|
"@effect/platform-node-shared": "4.0.0-beta.103",
|
|
46
|
+
"@herbertgao/pi-bark": "0.1.0",
|
|
46
47
|
"@herbertgao/pi-cc-extensions": "0.8.60",
|
|
47
48
|
"@herbertgao/pi-subagents": "0.17.1",
|
|
48
49
|
"@herbertgao/resume-from": "0.2.0",
|
|
49
|
-
"@juicesharp/rpiv-ask-user-question": "2.
|
|
50
|
-
"@juicesharp/rpiv-config": "^2.
|
|
50
|
+
"@juicesharp/rpiv-ask-user-question": "2.8.0",
|
|
51
|
+
"@juicesharp/rpiv-config": "^2.8.0",
|
|
51
52
|
"@luxusai/pi-hindsight": "0.12.0",
|
|
52
53
|
"@modelcontextprotocol/client": "2.0.0",
|
|
53
54
|
"@modelcontextprotocol/core": "2.0.0",
|
|
@@ -55,20 +56,19 @@
|
|
|
55
56
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
56
57
|
"@mozilla/readability": "^0.6.0",
|
|
57
58
|
"@napi-rs/keyring": "^1.3.0",
|
|
58
|
-
"@narumitw/pi-btw": "0.
|
|
59
|
+
"@narumitw/pi-btw": "0.56.0",
|
|
59
60
|
"@narumitw/pi-tui-kit": "^0.59.0",
|
|
60
61
|
"@noble/ed25519": "^3.1.0",
|
|
61
62
|
"@pi-plugins/fast-mode": "0.1.10",
|
|
62
63
|
"@shikijs/cli": "^4.0.2",
|
|
63
64
|
"@sinclair/typebox": "^0.34.49",
|
|
64
65
|
"@tifan/pi-copy-response": "0.2.6",
|
|
65
|
-
"@tifan/pi-handoff": "2.0
|
|
66
|
+
"@tifan/pi-handoff": "2.2.0",
|
|
66
67
|
"@tifan/pi-inline-skills": "1.0.5",
|
|
67
68
|
"@tifan/pi-mermaid-open": "0.2.0",
|
|
68
69
|
"@tifan/pi-preferred-thinking": "1.0.1",
|
|
69
|
-
"@tifan/pi-recap": "0.4.
|
|
70
|
-
"@tifan/pi-rename": "0.
|
|
71
|
-
"@tifan/pi-titlebar-spinner": "0.1.3",
|
|
70
|
+
"@tifan/pi-recap": "0.4.6",
|
|
71
|
+
"@tifan/pi-rename": "0.6.0",
|
|
72
72
|
"@vectorize-io/hindsight-client": "^0.9.0",
|
|
73
73
|
"ajv": "^8.17.1",
|
|
74
74
|
"ajv-formats": "^3.0.1",
|
|
@@ -88,9 +88,9 @@
|
|
|
88
88
|
"open": "^10.2.0",
|
|
89
89
|
"p-limit": "^6.1.0",
|
|
90
90
|
"pi-footer": "0.5.1",
|
|
91
|
-
"pi-lens": "4.1.
|
|
92
|
-
"pi-mcp-adapter": "2.
|
|
93
|
-
"pi-web-access": "0.
|
|
91
|
+
"pi-lens": "4.1.3",
|
|
92
|
+
"pi-mcp-adapter": "2.31.0",
|
|
93
|
+
"pi-web-access": "0.27.0",
|
|
94
94
|
"pidusage": "^4.0.1",
|
|
95
95
|
"promise.try": "^2.0.1",
|
|
96
96
|
"qrcode-terminal": "^0.12.0",
|
|
@@ -113,6 +113,7 @@
|
|
|
113
113
|
"bundledDependencies": [
|
|
114
114
|
"@czottmann/pi-automode",
|
|
115
115
|
"@dietrichgebert/ponytail",
|
|
116
|
+
"@herbertgao/pi-bark",
|
|
116
117
|
"@herbertgao/pi-cc-extensions",
|
|
117
118
|
"@herbertgao/pi-subagents",
|
|
118
119
|
"@herbertgao/resume-from",
|
|
@@ -127,7 +128,6 @@
|
|
|
127
128
|
"@tifan/pi-preferred-thinking",
|
|
128
129
|
"@tifan/pi-recap",
|
|
129
130
|
"@tifan/pi-rename",
|
|
130
|
-
"@tifan/pi-titlebar-spinner",
|
|
131
131
|
"pi-footer",
|
|
132
132
|
"pi-lens",
|
|
133
133
|
"pi-mcp-adapter",
|
|
@@ -151,8 +151,8 @@
|
|
|
151
151
|
"./node_modules/@tifan/pi-recap/src/index.ts",
|
|
152
152
|
"./node_modules/@tifan/pi-rename/src/index.ts",
|
|
153
153
|
"./node_modules/@herbertgao/pi-subagents/src/index.ts",
|
|
154
|
-
"./node_modules/@tifan/pi-titlebar-spinner/src/index.ts",
|
|
155
154
|
"./node_modules/@juicesharp/rpiv-ask-user-question/index.ts",
|
|
155
|
+
"./node_modules/@herbertgao/pi-bark/src/index.ts",
|
|
156
156
|
"./node_modules/@luxusai/pi-hindsight/extensions/index.ts",
|
|
157
157
|
"./node_modules/@narumitw/pi-btw/dist/index.ts",
|
|
158
158
|
"./node_modules/@pi-plugins/fast-mode/dist/index.mjs",
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# @tifan/pi-titlebar-spinner
|
|
2
|
-
|
|
3
|
-
Show a braille spinner in the pi titlebar while the agent runs.
|
|
4
|
-
|
|
5
|
-
The spinner starts on `agent_start` and stops when the agent settles or the session shuts down. When it stops, the extension restores the default `π - [session - ]cwd` title.
|
|
6
|
-
|
|
7
|
-
[add image: titlebar spinner while agent runs]
|
|
8
|
-
|
|
9
|
-
- The titlebar while the spinner is active.
|
|
10
|
-
- The restored titlebar after the agent finishes.
|
|
11
|
-
|
|
12
|
-
## Install
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
pi install npm:@tifan/pi-titlebar-spinner
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Release notes
|
|
19
|
-
|
|
20
|
-
See [CHANGELOG.md](CHANGELOG.md)
|
|
21
|
-
|
|
22
|
-
## License
|
|
23
|
-
|
|
24
|
-
[MIT](LICENSE)
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@tifan/pi-titlebar-spinner",
|
|
3
|
-
"version": "0.1.3",
|
|
4
|
-
"description": "Show a spinner in the pi titlebar while the agent runs.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"pi",
|
|
7
|
-
"pi-extension",
|
|
8
|
-
"pi-package",
|
|
9
|
-
"spinner",
|
|
10
|
-
"titlebar"
|
|
11
|
-
],
|
|
12
|
-
"homepage": "https://github.com/tifandotme/pi-extensions/tree/master/packages/pi-titlebar-spinner#readme",
|
|
13
|
-
"bugs": "https://github.com/tifandotme/pi-extensions/issues",
|
|
14
|
-
"license": "MIT",
|
|
15
|
-
"author": "Tifan Dwi Avianto <hi@tifan.me>",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/tifandotme/pi-extensions.git",
|
|
19
|
-
"directory": "packages/pi-titlebar-spinner"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"src/**/*.ts",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE"
|
|
25
|
-
],
|
|
26
|
-
"type": "module",
|
|
27
|
-
"publishConfig": {
|
|
28
|
-
"access": "public",
|
|
29
|
-
"provenance": true
|
|
30
|
-
},
|
|
31
|
-
"engines": {
|
|
32
|
-
"node": ">=20"
|
|
33
|
-
},
|
|
34
|
-
"pi": {
|
|
35
|
-
"extensions": [
|
|
36
|
-
"./src/index.ts"
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import path from "node:path"
|
|
2
|
-
import type {
|
|
3
|
-
ExtensionAPI,
|
|
4
|
-
ExtensionContext,
|
|
5
|
-
} from "@earendil-works/pi-coding-agent"
|
|
6
|
-
|
|
7
|
-
const FRAMES = ["⡿", "⣟", "⣯", "⣷", "⣾", "⣽", "⣻", "⢿"]
|
|
8
|
-
const INTERVAL_MS = 70
|
|
9
|
-
|
|
10
|
-
function baseTitle(pi: ExtensionAPI, cwdPath: string): string {
|
|
11
|
-
const cwd = path.basename(cwdPath)
|
|
12
|
-
const session = pi.getSessionName()
|
|
13
|
-
return session ? `π - ${session} - ${cwd}` : `π - ${cwd}`
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default function (pi: ExtensionAPI): void {
|
|
17
|
-
let timer: ReturnType<typeof setInterval> | undefined
|
|
18
|
-
let frameIndex = 0
|
|
19
|
-
|
|
20
|
-
function stop(ctx: ExtensionContext): void {
|
|
21
|
-
if (timer) {
|
|
22
|
-
clearInterval(timer)
|
|
23
|
-
timer = undefined
|
|
24
|
-
}
|
|
25
|
-
frameIndex = 0
|
|
26
|
-
ctx.ui.setTitle(baseTitle(pi, ctx.cwd))
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function start(ctx: ExtensionContext): void {
|
|
30
|
-
stop(ctx)
|
|
31
|
-
timer = setInterval(() => {
|
|
32
|
-
const frame = FRAMES[frameIndex % FRAMES.length]
|
|
33
|
-
ctx.ui.setTitle(`${frame} ${baseTitle(pi, ctx.cwd)}`)
|
|
34
|
-
frameIndex++
|
|
35
|
-
}, INTERVAL_MS)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
pi.on("agent_start", async (_event, ctx) => {
|
|
39
|
-
start(ctx)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
pi.on("agent_settled", async (_event, ctx) => {
|
|
43
|
-
stop(ctx)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
pi.on("session_shutdown", async (_event, ctx) => {
|
|
47
|
-
stop(ctx)
|
|
48
|
-
})
|
|
49
|
-
}
|