@herbertgao/pi-extensions 2026.8.7 → 2026.8.9
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 +8 -6
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +24 -0
- package/node_modules/@czottmann/pi-automode/README.md +78 -112
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +18 -14
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +44 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +5 -0
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +198 -104
- package/node_modules/@czottmann/pi-automode/docs/configuration.md +155 -0
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +55 -14
- package/node_modules/@czottmann/pi-automode/docs/diagnostics.md +90 -0
- package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +61 -26
- package/node_modules/@czottmann/pi-automode/examples/automode.local.json +5 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +172 -18
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +127 -30
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +3 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +273 -31
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/log.ts +60 -5
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +92 -8
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +203 -13
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/state.ts +1 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +11 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/utils.ts +9 -1
- package/node_modules/@czottmann/pi-automode/package.json +9 -2
- package/node_modules/@czottmann/pi-automode/skills/automode-diagnostics/SKILL.md +63 -0
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +3 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +3 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +8 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +63 -15
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +56 -29
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +78 -16
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +13 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +30 -17
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +29 -0
- package/node_modules/@herbertgao/pi-handoff/README.md +15 -18
- package/node_modules/@herbertgao/pi-handoff/package.json +11 -4
- package/node_modules/@herbertgao/pi-handoff/src/complete-text.ts +33 -0
- package/node_modules/@herbertgao/pi-handoff/src/index.ts +127 -232
- package/node_modules/@herbertgao/pi-handoff/src/session-query.ts +15 -30
- package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +14 -0
- package/node_modules/@herbertgao/pi-mermaid-open/README.md +21 -4
- package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +11 -0
- package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/viewer.mjs +305 -0
- package/node_modules/@herbertgao/pi-mermaid-open/package.json +15 -4
- package/node_modules/@herbertgao/pi-mermaid-open/src/index.ts +351 -101
- package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +12 -0
- package/node_modules/@herbertgao/pi-preferred-thinking/README.md +30 -14
- package/node_modules/@herbertgao/pi-preferred-thinking/package.json +7 -4
- package/node_modules/@herbertgao/pi-preferred-thinking/src/index.ts +140 -85
- package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +12 -0
- package/node_modules/@herbertgao/pi-recap/README.md +5 -3
- package/node_modules/@herbertgao/pi-recap/package.json +9 -3
- package/node_modules/@herbertgao/pi-recap/src/index.ts +3 -7
- package/node_modules/@herbertgao/pi-recap/src/model-picker.ts +6 -19
- package/node_modules/@herbertgao/pi-recap/src/models.ts +9 -21
- package/node_modules/@herbertgao/pi-recap/src/tui.ts +1 -1
- package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +49 -0
- package/node_modules/@herbertgao/pi-rename/README.md +13 -11
- package/node_modules/@herbertgao/pi-rename/package.json +13 -3
- package/node_modules/@herbertgao/pi-rename/src/index.ts +135 -59
- package/node_modules/@herbertgao/pi-rename/src/models.ts +5 -13
- package/node_modules/@herbertgao/pi-rename/src/naming.ts +2 -6
- package/node_modules/@herbertgao/pi-stash/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +16 -3
- package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
- package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +15 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +16 -0
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +5 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +4 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +154 -96
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +3 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +10 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +7 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/tool-schema.md +11 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +3 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +137 -96
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +44 -32
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/selectors/projections.ts +22 -15
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state-reducer.ts +11 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/tool/response-envelope.ts +11 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/tool/types.ts +11 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/multi-select-view.ts +31 -17
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/preview/preview-block-renderer.ts +15 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/wrapping-select.ts +15 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +56 -34
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +50 -4
- package/node_modules/@narumitw/pi-btw/package.json +2 -2
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +44 -1856
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/package.json +4 -6
- package/node_modules/pi-lens/CHANGELOG.md +90 -0
- package/node_modules/pi-lens/README.md +106 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +97 -6
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +16 -6
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +14 -0
- package/node_modules/pi-lens/dist/clients/cache-observability.js +353 -76
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +22 -1
- package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +8 -2
- package/node_modules/pi-lens/dist/clients/deps/typebox.js +8 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +9 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +9 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +8 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +8 -10
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +10 -10
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +20 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +44 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +10 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +19 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +35 -13
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +8 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +110 -23
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +117 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +16 -14
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +8 -9
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +22 -0
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +5 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +7 -2
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +27 -2
- package/node_modules/pi-lens/dist/clients/lsp/client.js +144 -5
- package/node_modules/pi-lens/dist/clients/lsp/index.js +151 -6
- package/node_modules/pi-lens/dist/clients/module-report.js +14 -1
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +114 -23
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +18 -9
- package/node_modules/pi-lens/dist/clients/project-report.js +62 -27
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +7 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +88 -19
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +194 -31
- package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +21 -0
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +6 -3
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +44 -0
- package/node_modules/pi-lens/dist/clients/runtime-session.js +41 -0
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +47 -2
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +184 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +6 -2
- package/node_modules/pi-lens/dist/clients/startup-scan.js +5 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +1 -0
- package/node_modules/pi-lens/dist/index.js +1224 -393
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +10 -3
- package/node_modules/pi-lens/package.json +18 -5
- package/node_modules/pi-lens/scripts/install-selftest.mjs +99 -11
- package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +75 -0
- package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +285 -0
- package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +233 -0
- package/node_modules/pi-web-access/CHANGELOG.md +27 -0
- package/node_modules/pi-web-access/README.md +8 -7
- package/node_modules/pi-web-access/chrome-cookies.ts +96 -20
- package/node_modules/pi-web-access/data-uri-sanitize.ts +406 -0
- package/node_modules/pi-web-access/extract.ts +12 -2
- package/node_modules/pi-web-access/firecrawl.ts +18 -2
- package/node_modules/pi-web-access/gemini-search.ts +28 -10
- package/node_modules/pi-web-access/github-extract.ts +65 -36
- package/node_modules/pi-web-access/index.ts +43 -14
- package/node_modules/pi-web-access/openai-search.ts +17 -6
- package/node_modules/pi-web-access/package.json +1 -1
- package/node_modules/pi-web-access/pdf-extract.ts +18 -5
- package/node_modules/pi-web-access/ssrf-protection.ts +12 -2
- package/package.json +19 -18
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync } from "node:fs";
|
|
2
2
|
import { execFile, spawn, type ChildProcess } from "node:child_process";
|
|
3
|
-
import {
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { basename, dirname, extname, join, resolve as resolvePath, sep as pathSep } from "node:path";
|
|
4
5
|
import { activityMonitor } from "./activity.ts";
|
|
5
6
|
import type { ExtractedContent } from "./extract.ts";
|
|
6
7
|
import { checkGhAvailable, checkRepoSize, fetchViaApi, showGhHint } from "./github-api.ts";
|
|
@@ -39,10 +40,15 @@ export interface GitHubUrlInfo {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
interface CachedClone {
|
|
42
|
-
|
|
43
|
+
destination: CloneDestination;
|
|
43
44
|
clonePromise: Promise<string | null>;
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
interface CloneDestination {
|
|
48
|
+
rootPath: string;
|
|
49
|
+
localPath: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
46
52
|
interface GitHubCloneConfig {
|
|
47
53
|
enabled: boolean;
|
|
48
54
|
maxRepoSizeMB: number;
|
|
@@ -137,20 +143,21 @@ export function parseGitHubUrl(url: string): GitHubUrlInfo | null {
|
|
|
137
143
|
const host = parsed.hostname.toLowerCase();
|
|
138
144
|
if (host !== "github.com" && host !== "www.github.com") return null;
|
|
139
145
|
|
|
140
|
-
const segments =
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
});
|
|
146
|
+
const segments: string[] = [];
|
|
147
|
+
for (const segment of parsed.pathname.split("/").filter(Boolean)) {
|
|
148
|
+
try {
|
|
149
|
+
segments.push(decodeURIComponent(segment));
|
|
150
|
+
} catch {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
150
154
|
if (segments.length < 2) return null;
|
|
151
155
|
|
|
152
156
|
const owner = segments[0];
|
|
153
157
|
const repo = segments[1].replace(/\.git$/, "");
|
|
158
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/.test(owner)) return null;
|
|
159
|
+
if (owner.includes("--")) return null;
|
|
160
|
+
if (!/^[A-Za-z0-9._-]{1,100}$/.test(repo) || repo === "." || repo === "..") return null;
|
|
154
161
|
|
|
155
162
|
if (NON_CODE_SEGMENTS.has(segments[2]?.toLowerCase())) return null;
|
|
156
163
|
|
|
@@ -163,6 +170,7 @@ export function parseGitHubUrl(url: string): GitHubUrlInfo | null {
|
|
|
163
170
|
if (segments.length < 4) return null;
|
|
164
171
|
|
|
165
172
|
const ref = segments[3];
|
|
173
|
+
if (ref.length === 0 || ref.length > 1024 || /[\0-\x1f\x7f]/.test(ref)) return null;
|
|
166
174
|
const refIsFullSha = /^[0-9a-f]{40}$/.test(ref);
|
|
167
175
|
const pathParts = segments.slice(4);
|
|
168
176
|
const path = pathParts.length > 0 ? pathParts.join("/") : "";
|
|
@@ -181,9 +189,32 @@ function cacheKey(owner: string, repo: string, ref?: string): string {
|
|
|
181
189
|
return ref ? `${owner}/${repo}@${ref}` : `${owner}/${repo}`;
|
|
182
190
|
}
|
|
183
191
|
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
192
|
+
function cloneDestination(config: GitHubCloneConfig, owner: string, repo: string, ref?: string): CloneDestination | null {
|
|
193
|
+
try {
|
|
194
|
+
mkdirSync(resolvePath(config.clonePath), { recursive: true });
|
|
195
|
+
const rootPath = realpathSync(resolvePath(config.clonePath));
|
|
196
|
+
const digest = createHash("sha256").update(JSON.stringify([owner, repo, ref ?? null])).digest("hex");
|
|
197
|
+
const localPath = resolvePath(rootPath, digest);
|
|
198
|
+
if (dirname(localPath) !== rootPath) return null;
|
|
199
|
+
return { rootPath, localPath };
|
|
200
|
+
} catch {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function removeCloneDestination(destination: CloneDestination): boolean {
|
|
206
|
+
const rootPath = resolvePath(destination.rootPath);
|
|
207
|
+
const localPath = resolvePath(destination.localPath);
|
|
208
|
+
if (dirname(localPath) !== rootPath || !/^[0-9a-f]{64}$/.test(basename(localPath))) return false;
|
|
209
|
+
try {
|
|
210
|
+
const entry = lstatSync(localPath);
|
|
211
|
+
if (entry.isSymbolicLink()) unlinkSync(localPath);
|
|
212
|
+
else rmSync(localPath, { recursive: true, force: true });
|
|
213
|
+
return true;
|
|
214
|
+
} catch (err) {
|
|
215
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") return true;
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
187
218
|
}
|
|
188
219
|
|
|
189
220
|
const PROCESS_KILL_GRACE_MS = 3000;
|
|
@@ -225,8 +256,9 @@ function terminateProcessTree(child: ChildProcess): void {
|
|
|
225
256
|
forceKill.unref();
|
|
226
257
|
}
|
|
227
258
|
|
|
228
|
-
function execClone(args: string[],
|
|
259
|
+
function execClone(args: string[], destination: CloneDestination, timeoutMs: number, signal?: AbortSignal): Promise<string | null> {
|
|
229
260
|
return new Promise((resolve) => {
|
|
261
|
+
const { localPath } = destination;
|
|
230
262
|
let settled = false;
|
|
231
263
|
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
232
264
|
let onAbort: (() => void) | undefined;
|
|
@@ -238,10 +270,7 @@ function execClone(args: string[], localPath: string, timeoutMs: number, signal?
|
|
|
238
270
|
if (signal && onAbort) signal.removeEventListener("abort", onAbort);
|
|
239
271
|
|
|
240
272
|
if (!success) {
|
|
241
|
-
|
|
242
|
-
rmSync(localPath, { recursive: true, force: true });
|
|
243
|
-
} catch {
|
|
244
|
-
}
|
|
273
|
+
removeCloneDestination(destination);
|
|
245
274
|
resolve(null);
|
|
246
275
|
return;
|
|
247
276
|
}
|
|
@@ -282,14 +311,11 @@ async function cloneRepo(
|
|
|
282
311
|
repo: string,
|
|
283
312
|
ref: string | undefined,
|
|
284
313
|
config: GitHubCloneConfig,
|
|
314
|
+
destination: CloneDestination,
|
|
285
315
|
signal?: AbortSignal,
|
|
286
316
|
): Promise<string | null> {
|
|
287
|
-
const localPath =
|
|
288
|
-
|
|
289
|
-
try {
|
|
290
|
-
rmSync(localPath, { recursive: true, force: true });
|
|
291
|
-
} catch {
|
|
292
|
-
}
|
|
317
|
+
const { localPath } = destination;
|
|
318
|
+
if (!removeCloneDestination(destination)) return null;
|
|
293
319
|
|
|
294
320
|
const timeoutMs = config.cloneTimeoutSeconds * 1000;
|
|
295
321
|
const hasGh = await checkGhAvailable();
|
|
@@ -297,7 +323,7 @@ async function cloneRepo(
|
|
|
297
323
|
if (hasGh) {
|
|
298
324
|
const args = ["gh", "repo", "clone", `${owner}/${repo}`, localPath, "--", "--depth", "1", "--single-branch"];
|
|
299
325
|
if (ref) args.push("--branch", ref);
|
|
300
|
-
return execClone(args,
|
|
326
|
+
return execClone(args, destination, timeoutMs, signal);
|
|
301
327
|
}
|
|
302
328
|
|
|
303
329
|
showGhHint();
|
|
@@ -306,7 +332,7 @@ async function cloneRepo(
|
|
|
306
332
|
const args = ["git", "clone", "--depth", "1", "--single-branch"];
|
|
307
333
|
if (ref) args.push("--branch", ref);
|
|
308
334
|
args.push(gitUrl, localPath);
|
|
309
|
-
return execClone(args,
|
|
335
|
+
return execClone(args, destination, timeoutMs, signal);
|
|
310
336
|
}
|
|
311
337
|
|
|
312
338
|
function isBinaryFile(filePath: string): boolean {
|
|
@@ -671,9 +697,15 @@ export async function extractGitHub(
|
|
|
671
697
|
return cachedResult;
|
|
672
698
|
}
|
|
673
699
|
|
|
674
|
-
const
|
|
675
|
-
|
|
676
|
-
|
|
700
|
+
const destination = cloneDestination(config, owner, repo, info.ref);
|
|
701
|
+
if (!destination) {
|
|
702
|
+
const apiFallback = await fetchViaApi(url, owner, repo, info);
|
|
703
|
+
if (apiFallback) activityMonitor.logComplete(activityId, 200);
|
|
704
|
+
else activityMonitor.logError(activityId, "invalid clone destination");
|
|
705
|
+
return apiFallback;
|
|
706
|
+
}
|
|
707
|
+
const clonePromise = cloneRepo(owner, repo, info.ref, config, destination, signal);
|
|
708
|
+
cloneCache.set(key, { destination, clonePromise });
|
|
677
709
|
|
|
678
710
|
const result = await clonePromise;
|
|
679
711
|
if (signal?.aborted) {
|
|
@@ -707,10 +739,7 @@ export async function extractGitHub(
|
|
|
707
739
|
|
|
708
740
|
export function clearCloneCache(): void {
|
|
709
741
|
for (const entry of cloneCache.values()) {
|
|
710
|
-
|
|
711
|
-
rmSync(entry.localPath, { recursive: true, force: true });
|
|
712
|
-
} catch {
|
|
713
|
-
}
|
|
742
|
+
removeCloneDestination(entry.destination);
|
|
714
743
|
}
|
|
715
744
|
cloneCache.clear();
|
|
716
745
|
cachedConfig = null;
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
type SummaryMeta,
|
|
35
35
|
} from "./summary-review.ts";
|
|
36
36
|
import { randomUUID } from "node:crypto";
|
|
37
|
-
import { execFileSync } from "node:child_process";
|
|
37
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
38
38
|
import { createRequire } from "node:module";
|
|
39
39
|
import { platform } from "node:os";
|
|
40
40
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
@@ -152,7 +152,7 @@ interface WebSearchConfig {
|
|
|
152
152
|
};
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
interface ProviderAvailability {
|
|
155
|
+
export interface ProviderAvailability {
|
|
156
156
|
all: boolean;
|
|
157
157
|
openai: boolean;
|
|
158
158
|
brave: boolean;
|
|
@@ -184,7 +184,7 @@ interface ProviderAvailability {
|
|
|
184
184
|
|
|
185
185
|
type WebSearchWorkflow = "none" | "summary-review" | "auto-summary";
|
|
186
186
|
type CuratorWorkflow = "summary-review";
|
|
187
|
-
type CuratorProvider = Exclude<SearchProvider, "auto">;
|
|
187
|
+
export type CuratorProvider = Exclude<SearchProvider, "auto">;
|
|
188
188
|
type SummaryWorkflow = "summary-review" | "auto-summary";
|
|
189
189
|
|
|
190
190
|
interface CuratorBootstrap {
|
|
@@ -420,13 +420,16 @@ async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderA
|
|
|
420
420
|
};
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
function
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
423
|
+
function shouldUseOpenAICodexDefault(ctx?: Pick<ExtensionContext, "model">): boolean {
|
|
424
|
+
return ctx?.model?.provider === "openai-codex";
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function shouldPreferOpenAI(options: Pick<PendingCurate, "numResults" | "recencyFilter"> | undefined, preferOpenAICodexDefault: boolean): boolean {
|
|
428
|
+
if (options?.recencyFilter) return false;
|
|
429
|
+
if (typeof options?.numResults === "number" && Number.isFinite(options.numResults) && Math.floor(options.numResults) !== 5) {
|
|
427
430
|
return false;
|
|
428
431
|
}
|
|
429
|
-
return
|
|
432
|
+
return preferOpenAICodexDefault;
|
|
430
433
|
}
|
|
431
434
|
|
|
432
435
|
async function loadCuratorBootstrap(
|
|
@@ -439,15 +442,25 @@ async function loadCuratorBootstrap(
|
|
|
439
442
|
if (Array.isArray(provider)) availableProviders.all = true;
|
|
440
443
|
return {
|
|
441
444
|
availableProviders,
|
|
442
|
-
defaultProvider:
|
|
445
|
+
defaultProvider: resolveCuratorDefaultProvider(provider, availableProviders, ctx, options),
|
|
443
446
|
timeoutSeconds: getCuratorTimeoutSeconds(),
|
|
444
447
|
};
|
|
445
448
|
}
|
|
446
449
|
|
|
450
|
+
export function resolveCuratorDefaultProvider(
|
|
451
|
+
provider: SearchProviderSelection,
|
|
452
|
+
available: ProviderAvailability,
|
|
453
|
+
ctx?: Pick<ExtensionContext, "model">,
|
|
454
|
+
options?: Pick<PendingCurate, "numResults" | "recencyFilter">,
|
|
455
|
+
): CuratorProvider {
|
|
456
|
+
return resolveProvider(provider, available, options, shouldUseOpenAICodexDefault(ctx));
|
|
457
|
+
}
|
|
458
|
+
|
|
447
459
|
function firstAvailableProvider(available: ProviderAvailability, preferOpenAI: boolean, fallback: ResolvedSearchProvider): ResolvedSearchProvider {
|
|
448
460
|
if (available.searxng) return "searxng";
|
|
449
461
|
if (preferOpenAI && available.openai) return "openai";
|
|
450
462
|
if (available.exa) return "exa";
|
|
463
|
+
if (available.openai) return "openai";
|
|
451
464
|
if (available.brave) return "brave";
|
|
452
465
|
if (available.parallel) return "parallel";
|
|
453
466
|
if (available.tinyfish) return "tinyfish";
|
|
@@ -470,9 +483,10 @@ function resolveProvider(
|
|
|
470
483
|
provider: SearchProviderSelection,
|
|
471
484
|
available: ProviderAvailability,
|
|
472
485
|
options?: Pick<PendingCurate, "numResults" | "recencyFilter">,
|
|
486
|
+
preferOpenAICodexDefault = false,
|
|
473
487
|
): CuratorProvider {
|
|
474
488
|
if (Array.isArray(provider)) return "all";
|
|
475
|
-
const preferOpenAI = shouldPreferOpenAI(options);
|
|
489
|
+
const preferOpenAI = shouldPreferOpenAI(options, preferOpenAICodexDefault);
|
|
476
490
|
|
|
477
491
|
if (provider === "auto") {
|
|
478
492
|
const routing = getConfiguredSearchRouting();
|
|
@@ -744,11 +758,26 @@ function closeCurator(callId?: string): void {
|
|
|
744
758
|
|
|
745
759
|
async function openInBrowser(pi: ExtensionAPI, url: string): Promise<void> {
|
|
746
760
|
const plat = platform();
|
|
761
|
+
if (plat !== "darwin" && plat !== "win32") {
|
|
762
|
+
await new Promise<void>((resolve, reject) => {
|
|
763
|
+
const child = spawn("xdg-open", [url], { detached: true, stdio: "ignore" });
|
|
764
|
+
const timer = setTimeout(resolve, 100);
|
|
765
|
+
child.once("error", (err) => {
|
|
766
|
+
clearTimeout(timer);
|
|
767
|
+
reject(err);
|
|
768
|
+
});
|
|
769
|
+
child.once("exit", (code) => {
|
|
770
|
+
clearTimeout(timer);
|
|
771
|
+
if (code === 0) resolve();
|
|
772
|
+
else reject(new Error(`Failed to open browser (exit code ${code ?? "unknown"})`));
|
|
773
|
+
});
|
|
774
|
+
child.unref();
|
|
775
|
+
});
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
747
778
|
const result = plat === "darwin"
|
|
748
779
|
? await pi.exec("open", [url])
|
|
749
|
-
:
|
|
750
|
-
? await pi.exec("cmd", ["/c", "start", "", url])
|
|
751
|
-
: await pi.exec("xdg-open", [url]);
|
|
780
|
+
: await pi.exec("cmd", ["/c", "start", "", url]);
|
|
752
781
|
if (result.code !== 0) {
|
|
753
782
|
throw new Error(result.stderr || `Failed to open browser (exit code ${result.code})`);
|
|
754
783
|
}
|
|
@@ -1645,7 +1674,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1645
1674
|
name: toolNames.webSearch,
|
|
1646
1675
|
label: "Web Search",
|
|
1647
1676
|
description:
|
|
1648
|
-
`Search the web using OpenAI, Brave, Parallel, Parallel MCP, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, Valyu, xAI, Bright Data, SerpBase, or Serper. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper. Returns an AI-synthesized answer with source citations. OpenAI search uses a Codex subscription or OpenAI API key; xAI search uses a SuperGrok/X Premium subscription or xAI API key. Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are available only when explicitly selected. For comprehensive research, prefer queries (plural) with 2-4 varied angles over a single query — each query gets its own synthesized answer, so varying phrasing and scope gives much broader coverage. When includeContent is true, full page content is fetched in the background. Searches auto-open the interactive browser curator and stream results live; set workflow to "none" to skip curation or "auto-summary" for a model-generated summary without the browser curator. The configured provider is used when provider is omitted or set to auto; omit provider unless explicitly overriding it. Without a configured provider,
|
|
1677
|
+
`Search the web using OpenAI, Brave, Parallel, Parallel MCP, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, Valyu, xAI, Bright Data, SerpBase, or Serper. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper. Returns an AI-synthesized answer with source citations. OpenAI search uses a Codex subscription or OpenAI API key; xAI search uses a SuperGrok/X Premium subscription or xAI API key. Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are available only when explicitly selected. For comprehensive research, prefer queries (plural) with 2-4 varied angles over a single query — each query gets its own synthesized answer, so varying phrasing and scope gives much broader coverage. When includeContent is true, full page content is fetched in the background. Searches auto-open the interactive browser curator and stream results live; set workflow to "none" to skip curation or "auto-summary" for a model-generated summary without the browser curator. The configured provider is used when provider is omitted or set to auto; omit provider unless explicitly overriding it. Without a configured provider, SearXNG is preferred first for local/private search. When the active Pi model is openai-codex, Codex-backed OpenAI search is preferred next. Otherwise Exa is preferred before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, or Gemini Web.`,
|
|
1649
1678
|
promptSnippet:
|
|
1650
1679
|
"Use for web research questions. Prefer {queries:[...]} with 2-4 varied angles over a single query for broader coverage. Omit provider unless explicitly overriding the configured default.",
|
|
1651
1680
|
parameters: Type.Object({
|
|
@@ -19,7 +19,7 @@ const MODEL_PREFERENCE = [
|
|
|
19
19
|
(id: string) => id.includes("terra"),
|
|
20
20
|
(id: string) => /^gpt-\d+(\.\d+)?$/.test(id),
|
|
21
21
|
];
|
|
22
|
-
const
|
|
22
|
+
const DEFAULT_SEARCH_PROVIDERS: readonly string[] = ["openai-codex", "openai"];
|
|
23
23
|
|
|
24
24
|
function pickSearchModel<T extends { id: string }>(models: readonly T[]): T | undefined {
|
|
25
25
|
const candidates = models
|
|
@@ -36,12 +36,13 @@ interface WebSearchConfig {
|
|
|
36
36
|
openaiApiKey?: unknown;
|
|
37
37
|
openaiResponsesUrl?: unknown;
|
|
38
38
|
openaiSearchModel?: unknown;
|
|
39
|
+
openaiSearchProviders?: unknown;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
type ProviderHeaders = Record<string, string | null>;
|
|
42
43
|
|
|
43
44
|
interface OpenAIAuth {
|
|
44
|
-
provider:
|
|
45
|
+
provider: string;
|
|
45
46
|
apiKey: string;
|
|
46
47
|
model: string;
|
|
47
48
|
headers: ProviderHeaders;
|
|
@@ -149,6 +150,14 @@ function resolveConfiguredResponsesUrl(value: unknown): string {
|
|
|
149
150
|
return url.toString();
|
|
150
151
|
}
|
|
151
152
|
|
|
153
|
+
function resolveConfiguredSearchProviders(value: unknown): readonly string[] {
|
|
154
|
+
if (value === undefined) return DEFAULT_SEARCH_PROVIDERS;
|
|
155
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.trim().length === 0)) {
|
|
156
|
+
throw new Error(`openaiSearchProviders in ${CONFIG_PATH} must be an array of non-empty Pi provider ids`);
|
|
157
|
+
}
|
|
158
|
+
return value.map((entry) => entry.trim());
|
|
159
|
+
}
|
|
160
|
+
|
|
152
161
|
function resolveConfiguredSearchModel(value: unknown): string | undefined {
|
|
153
162
|
if (value == null) return undefined;
|
|
154
163
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
@@ -165,14 +174,14 @@ function toRequestHeaders(headers: ProviderHeaders): Record<string, string> {
|
|
|
165
174
|
return requestHeaders;
|
|
166
175
|
}
|
|
167
176
|
|
|
168
|
-
async function resolvePiAuth(ctx: ExtensionContext, responsesUrl: string, modelOverride?: string): Promise<OpenAIAuth | undefined> {
|
|
177
|
+
async function resolvePiAuth(ctx: ExtensionContext, responsesUrl: string, providers: readonly string[], modelOverride?: string): Promise<OpenAIAuth | undefined> {
|
|
169
178
|
let models: ReturnType<typeof ctx.modelRegistry.getAll>;
|
|
170
179
|
try {
|
|
171
180
|
models = ctx.modelRegistry.getAll();
|
|
172
181
|
} catch {
|
|
173
182
|
return undefined;
|
|
174
183
|
}
|
|
175
|
-
for (const provider of
|
|
184
|
+
for (const provider of providers) {
|
|
176
185
|
const preferred = pickSearchModel(models.filter((model) => model.provider === provider));
|
|
177
186
|
if (!preferred) continue;
|
|
178
187
|
try {
|
|
@@ -196,8 +205,9 @@ export async function resolveOpenAIAuth(ctx?: ExtensionContext, signal?: AbortSi
|
|
|
196
205
|
const config = loadConfig();
|
|
197
206
|
const responsesUrl = resolveConfiguredResponsesUrl(config.openaiResponsesUrl);
|
|
198
207
|
const modelOverride = resolveConfiguredSearchModel(config.openaiSearchModel);
|
|
208
|
+
const providers = resolveConfiguredSearchProviders(config.openaiSearchProviders);
|
|
199
209
|
if (ctx) {
|
|
200
|
-
const auth = await resolvePiAuth(ctx, responsesUrl, modelOverride);
|
|
210
|
+
const auth = await resolvePiAuth(ctx, responsesUrl, providers, modelOverride);
|
|
201
211
|
if (auth) return auth;
|
|
202
212
|
}
|
|
203
213
|
|
|
@@ -221,7 +231,8 @@ export async function resolveOpenAIAuth(ctx?: ExtensionContext, signal?: AbortSi
|
|
|
221
231
|
export async function isOpenAISearchAvailable(ctx?: ExtensionContext): Promise<boolean> {
|
|
222
232
|
const config = loadConfig();
|
|
223
233
|
const responsesUrl = resolveConfiguredResponsesUrl(config.openaiResponsesUrl);
|
|
224
|
-
|
|
234
|
+
const providers = resolveConfiguredSearchProviders(config.openaiSearchProviders);
|
|
235
|
+
if (ctx && await resolvePiAuth(ctx, responsesUrl, providers)) return true;
|
|
225
236
|
return hasCredentialSource({
|
|
226
237
|
provider: "OpenAI",
|
|
227
238
|
configuredValue: config.openaiApiKey,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-access",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.2",
|
|
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, and Gemini.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -51,6 +51,7 @@ export const PDF_PROVIDER_VALUES = new Set<PDFProvider>([
|
|
|
51
51
|
export interface PDFConfig {
|
|
52
52
|
enabled: boolean;
|
|
53
53
|
maxSizeMB: number;
|
|
54
|
+
maxPages: number;
|
|
54
55
|
provider: PDFProvider;
|
|
55
56
|
datalabMode: DatalabMode;
|
|
56
57
|
datalabTimeoutMs: number;
|
|
@@ -69,6 +70,7 @@ export function loadPDFConfig(): PDFConfig {
|
|
|
69
70
|
return {
|
|
70
71
|
enabled: true,
|
|
71
72
|
maxSizeMB: DEFAULT_PDF_MAX_SIZE_MB,
|
|
73
|
+
maxPages: DEFAULT_MAX_PAGES,
|
|
72
74
|
provider: "auto",
|
|
73
75
|
datalabMode: normalizeDatalabMode(process.env.DATALAB_MODE),
|
|
74
76
|
datalabTimeoutMs: DEFAULT_DATALAB_TIMEOUT_MS,
|
|
@@ -98,6 +100,13 @@ export function loadPDFConfig(): PDFConfig {
|
|
|
98
100
|
configured > 0
|
|
99
101
|
? Math.min(configured, MAX_PDF_MAX_SIZE_MB)
|
|
100
102
|
: DEFAULT_PDF_MAX_SIZE_MB;
|
|
103
|
+
const configuredMaxPages = pdf.maxPages;
|
|
104
|
+
const maxPages =
|
|
105
|
+
typeof configuredMaxPages === "number" &&
|
|
106
|
+
Number.isFinite(configuredMaxPages) &&
|
|
107
|
+
configuredMaxPages > 0
|
|
108
|
+
? Math.max(1, Math.floor(configuredMaxPages))
|
|
109
|
+
: DEFAULT_MAX_PAGES;
|
|
101
110
|
|
|
102
111
|
const provider =
|
|
103
112
|
typeof pdf.provider === "string" &&
|
|
@@ -120,6 +129,7 @@ export function loadPDFConfig(): PDFConfig {
|
|
|
120
129
|
return {
|
|
121
130
|
enabled,
|
|
122
131
|
maxSizeMB: normalized,
|
|
132
|
+
maxPages,
|
|
123
133
|
provider,
|
|
124
134
|
datalabMode,
|
|
125
135
|
datalabTimeoutMs,
|
|
@@ -155,18 +165,21 @@ export async function extractPDFToMarkdown(
|
|
|
155
165
|
options: PDFExtractOptions = {},
|
|
156
166
|
): Promise<PDFExtractResult> {
|
|
157
167
|
const {
|
|
158
|
-
maxPages
|
|
168
|
+
maxPages,
|
|
159
169
|
outputDir = DEFAULT_OUTPUT_DIR,
|
|
160
170
|
filename,
|
|
161
171
|
signal,
|
|
162
172
|
geminiTimeoutMs,
|
|
163
173
|
} = options;
|
|
164
174
|
|
|
165
|
-
const safeMaxPages = Number.isFinite(maxPages)
|
|
166
|
-
? Math.max(1, Math.floor(maxPages))
|
|
167
|
-
: DEFAULT_MAX_PAGES;
|
|
168
|
-
const urlTitle = extractTitleFromURL(url);
|
|
169
175
|
const pdfConfig = loadPDFConfig();
|
|
176
|
+
const safeMaxPages =
|
|
177
|
+
maxPages === undefined
|
|
178
|
+
? pdfConfig.maxPages
|
|
179
|
+
: Number.isFinite(maxPages)
|
|
180
|
+
? Math.max(1, Math.floor(maxPages))
|
|
181
|
+
: DEFAULT_MAX_PAGES;
|
|
182
|
+
const urlTitle = extractTitleFromURL(url);
|
|
170
183
|
const provider = pdfConfig.provider;
|
|
171
184
|
|
|
172
185
|
if (provider === "auto" || provider === "datalab") {
|
|
@@ -5,6 +5,7 @@ import { getWebSearchConfigPath } from "./utils.ts";
|
|
|
5
5
|
|
|
6
6
|
const DEFAULT_MAX_REDIRECTS = 5;
|
|
7
7
|
const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
|
|
8
|
+
const LOOPBACK_ALLOW_RANGES = ["127.0.0.0/8", "::1", "::ffff:127.0.0.0/104"];
|
|
8
9
|
|
|
9
10
|
export type LookupAddress = { address: string; family: number };
|
|
10
11
|
export type Lookup = (hostname: string) => Promise<LookupAddress[]>;
|
|
@@ -152,6 +153,8 @@ interface ValidationOptions {
|
|
|
152
153
|
* the local SSRF preflight. This does not configure proxy transport.
|
|
153
154
|
*/
|
|
154
155
|
trustEnvProxy?: boolean;
|
|
156
|
+
/** Allow loopback URLs for explicit provider base endpoints, not fetched targets. */
|
|
157
|
+
allowLoopback?: boolean;
|
|
155
158
|
}
|
|
156
159
|
|
|
157
160
|
/** Parsed entry from `allowRanges`: a network address (4 or 16 bytes) + prefix length. */
|
|
@@ -185,7 +188,11 @@ export async function validateRemoteUrl(rawUrl: string | URL, options: Validatio
|
|
|
185
188
|
|
|
186
189
|
const hostname = normalizeHostname(url.hostname);
|
|
187
190
|
if (!hostname) throw new Error("URL must include a hostname");
|
|
188
|
-
if (hostname === "localhost"
|
|
191
|
+
if (hostname === "localhost") {
|
|
192
|
+
if (options.allowLoopback === true) return url;
|
|
193
|
+
throw new Error(`Blocked internal hostname: ${hostname}`);
|
|
194
|
+
}
|
|
195
|
+
if (hostname.endsWith(".localhost")) {
|
|
189
196
|
throw new Error(`Blocked internal hostname: ${hostname}`);
|
|
190
197
|
}
|
|
191
198
|
|
|
@@ -193,7 +200,10 @@ export async function validateRemoteUrl(rawUrl: string | URL, options: Validatio
|
|
|
193
200
|
assertDomainPolicy(hostname, options.domainPolicy);
|
|
194
201
|
|
|
195
202
|
if (net.isIP(hostname)) {
|
|
196
|
-
|
|
203
|
+
const addressAllowRanges = options.allowLoopback === true
|
|
204
|
+
? [...allowRanges, ...parseAllowRanges(LOOPBACK_ALLOW_RANGES)]
|
|
205
|
+
: allowRanges;
|
|
206
|
+
assertPublicAddress(hostname, hostname, addressAllowRanges);
|
|
197
207
|
return url;
|
|
198
208
|
}
|
|
199
209
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herbertgao/pi-extensions",
|
|
3
|
-
"version": "2026.8.
|
|
3
|
+
"version": "2026.8.9",
|
|
4
4
|
"description": "Aggregate installer for HerbertGao-maintained Pi extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"extensions",
|
|
@@ -36,35 +36,35 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@ast-grep/cli": "^0.45.0",
|
|
38
38
|
"@ast-grep/napi": "^0.45.0",
|
|
39
|
-
"@czottmann/pi-automode": "1.
|
|
39
|
+
"@czottmann/pi-automode": "1.12.0",
|
|
40
40
|
"@dietrichgebert/ponytail": "4.9.0",
|
|
41
41
|
"@earendil-works/pi-coding-agent": "^0.84.2",
|
|
42
42
|
"@earendil-works/pi-tui": "^0.84.2",
|
|
43
43
|
"@effect/platform-node": "4.0.0-beta.103",
|
|
44
44
|
"@effect/platform-node-shared": "4.0.0-beta.103",
|
|
45
|
-
"@herbertgao/pi-cc-extensions": "0.8.
|
|
45
|
+
"@herbertgao/pi-cc-extensions": "0.8.58",
|
|
46
46
|
"@herbertgao/pi-copy-response": "0.2.6",
|
|
47
|
-
"@herbertgao/pi-handoff": "
|
|
47
|
+
"@herbertgao/pi-handoff": "2.0.0",
|
|
48
48
|
"@herbertgao/pi-inline-skills": "1.0.5",
|
|
49
|
-
"@herbertgao/pi-mermaid-open": "0.
|
|
50
|
-
"@herbertgao/pi-preferred-thinking": "0.
|
|
51
|
-
"@herbertgao/pi-recap": "0.4.
|
|
52
|
-
"@herbertgao/pi-rename": "0.
|
|
53
|
-
"@herbertgao/pi-stash": "0.1.
|
|
54
|
-
"@herbertgao/pi-subagents": "0.16.
|
|
49
|
+
"@herbertgao/pi-mermaid-open": "0.2.0",
|
|
50
|
+
"@herbertgao/pi-preferred-thinking": "0.4.0",
|
|
51
|
+
"@herbertgao/pi-recap": "0.4.5",
|
|
52
|
+
"@herbertgao/pi-rename": "0.5.0",
|
|
53
|
+
"@herbertgao/pi-stash": "0.1.2",
|
|
54
|
+
"@herbertgao/pi-subagents": "0.16.1",
|
|
55
55
|
"@herbertgao/pi-titlebar-spinner": "0.1.3",
|
|
56
|
-
"@juicesharp/rpiv-ask-user-question": "2.
|
|
57
|
-
"@juicesharp/rpiv-config": "^2.
|
|
56
|
+
"@juicesharp/rpiv-ask-user-question": "2.7.0",
|
|
57
|
+
"@juicesharp/rpiv-config": "^2.7.0",
|
|
58
58
|
"@modelcontextprotocol/client": "2.0.0",
|
|
59
59
|
"@modelcontextprotocol/core": "2.0.0",
|
|
60
60
|
"@modelcontextprotocol/ext-apps": "^1.2.2",
|
|
61
61
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
62
62
|
"@mozilla/readability": "^0.6.0",
|
|
63
63
|
"@napi-rs/keyring": "^1.3.0",
|
|
64
|
-
"@narumitw/pi-btw": "0.55.
|
|
65
|
-
"@narumitw/pi-tui-kit": "^0.
|
|
64
|
+
"@narumitw/pi-btw": "0.55.1",
|
|
65
|
+
"@narumitw/pi-tui-kit": "^0.57.0",
|
|
66
66
|
"@noble/ed25519": "^3.1.0",
|
|
67
|
-
"@pi-plugins/fast-mode": "0.1.
|
|
67
|
+
"@pi-plugins/fast-mode": "0.1.10",
|
|
68
68
|
"@shikijs/cli": "^4.0.2",
|
|
69
69
|
"@sinclair/typebox": "^0.34.49",
|
|
70
70
|
"ajv": "^8.17.1",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"croner": "^10.0.1",
|
|
74
74
|
"cross-spawn": "^7.0.6",
|
|
75
75
|
"effect": "4.0.0-beta.103",
|
|
76
|
-
"grok-mermaid": "
|
|
76
|
+
"grok-mermaid": "0.2.2",
|
|
77
77
|
"jiti": "^2.7.0",
|
|
78
78
|
"js-yaml": "^5.2.2",
|
|
79
79
|
"linkedom": "^0.16.0",
|
|
@@ -82,9 +82,9 @@
|
|
|
82
82
|
"open": "^10.2.0",
|
|
83
83
|
"p-limit": "^6.1.0",
|
|
84
84
|
"pi-footer": "0.5.1",
|
|
85
|
-
"pi-lens": "4.1.
|
|
85
|
+
"pi-lens": "4.1.1",
|
|
86
86
|
"pi-mcp-adapter": "2.27.0",
|
|
87
|
-
"pi-web-access": "0.24.
|
|
87
|
+
"pi-web-access": "0.24.2",
|
|
88
88
|
"pidusage": "^4.0.1",
|
|
89
89
|
"promise.try": "^2.0.1",
|
|
90
90
|
"qrcode-terminal": "^0.12.0",
|
|
@@ -159,6 +159,7 @@
|
|
|
159
159
|
"./node_modules/@herbertgao/pi-cc-extensions/themes/cc-light.json"
|
|
160
160
|
],
|
|
161
161
|
"skills": [
|
|
162
|
+
"./node_modules/@czottmann/pi-automode/skills",
|
|
162
163
|
"./node_modules/@dietrichgebert/ponytail/skills",
|
|
163
164
|
"./node_modules/pi-mcp-adapter/skills",
|
|
164
165
|
"./node_modules/pi-lens/skills"
|