1st-pi 0.1.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,6 +8,8 @@
8
8
 
9
9
  ## 安装
10
10
 
11
+ 需要 Pi `>=1.1.0`;`@tintinweb/pi-subagents` 0.20 起要求该版本,`pi-btw` 0.7 起要求 `>=0.85.1`。
12
+
11
13
  ### GitHub
12
14
 
13
15
  ```bash
@@ -121,25 +123,25 @@ Preset 默认开启以下 TUI 增强,session 中持久化的个人选择优先
121
123
 
122
124
  | 包 | 功能 |
123
125
  |---|---|
124
- | [pi-web-access](https://www.npmjs.com/package/pi-web-access) | Web 搜索、URL/GitHub/YouTube 访问及 librarian skill |
126
+ | [pi-web-access](https://www.npmjs.com/package/pi-web-access) | Web 搜索、URL/GitHub/YouTube 访问、来源检查与可配置 provider routing |
125
127
  | [pi-init](https://www.npmjs.com/package/pi-init) | 生成或更新 `AGENTS.md` 的 init skill |
126
- | [pi-mcp-adapter](https://www.npmjs.com/package/pi-mcp-adapter) | MCP 协议适配 |
127
128
  | [pi-everforest-tui](https://www.npmjs.com/package/pi-everforest-tui) | Everforest light/dark themes 与可选 TUI 增强 |
128
129
  | [pi-session-name](https://www.npmjs.com/package/pi-session-name) | 自动生成会话标题并同步终端标题 |
129
130
  | [@juicesharp/rpiv-ask-user-question](https://www.npmjs.com/package/@juicesharp/rpiv-ask-user-question) | 多问题、选项预览和自由输入的结构化提问 UI |
130
- | [@narumitw/pi-goal](https://www.npmjs.com/package/@narumitw/pi-goal) | Session-scoped `/goal` 持续执行与完成/阻塞门禁 |
131
- | [pi-observational-memory](https://www.npmjs.com/package/pi-observational-memory) | 跨压缩保留 observations/reflections 的长会话记忆 |
132
- | [@ff-labs/pi-fff](https://www.npmjs.com/package/@ff-labs/pi-fff) | 本地 Rust 模糊文件/内容搜索与 `@` 自动补全 |
133
- | [pi-readseek](https://www.npmjs.com/package/pi-readseek) | Parser-backed code map/search、definition/reference、hashline edit 与 workspace rename;其 edit 可进行带警告的 fuzzy anchor relocation,不等同于严格 stale rejection |
131
+ | [@narumitw/pi-goal](https://www.npmjs.com/package/@narumitw/pi-goal) | Session-scoped `/goal` 持续执行与完成/阻塞门禁;可选 experimental ordered-goal queue |
132
+ | [@ff-labs/pi-fff](https://www.npmjs.com/package/@ff-labs/pi-fff) | 本地 Rust 模糊文件/内容搜索与 `@` 自动补全;`find`/`grep` 支持 workspace-relative 约束和 workspace 外的绝对路径 |
133
+ | [pi-readseek](https://www.npmjs.com/package/pi-readseek) | Parser-backed code map/search、PDF index/view、definition/reference、hashline edit 与 workspace rename;其 edit 可进行带警告的 fuzzy anchor relocation,不等同于严格 stale rejection |
134
134
  | [pi-btw](https://www.npmjs.com/package/pi-btw) | 不污染主上下文的并行 `/btw` 旁路对话 |
135
135
  | [@mrclrchtr/supi-context](https://www.npmjs.com/package/@mrclrchtr/supi-context) | `/supi-context` 上下文组成与 token 占用报告 |
136
136
  | [@tintinweb/pi-subagents](https://www.npmjs.com/package/@tintinweb/pi-subagents) | Claude Code 风格 sub-agents |
137
137
  | [@tintinweb/pi-tasks](https://www.npmjs.com/package/@tintinweb/pi-tasks) | Task tracking 与协作 |
138
- | [@quintinshaw/pi-dynamic-workflows](https://www.npmjs.com/package/@quintinshaw/pi-dynamic-workflows) | 动态 workflows;preset 默认关闭 `workflow/workflows` 关键词自动触发,仅通过 `/workflows`、已保存 workflow 的 slash command 或显式 `/workflows-trigger on` 启用 |
138
+ | [@quintinshaw/pi-dynamic-workflows](https://www.npmjs.com/package/@quintinshaw/pi-dynamic-workflows) | 动态 workflows;3.x 的关键词只授权模型选择 workflow、不再强制触发;preset 默认关闭该关键词入口,仍可通过 `/workflows`、已保存 workflow slash command 或显式 `/workflows-trigger on` 启用 |
139
139
 
140
140
  这些包位于普通 npm `dependencies`,安装 preset 时由 npm 获取,不会塞入 `1st-pi` tarball。`extensions/packages/*.ts` 是只负责调用 dependency extension entrypoint 的 thin adapters;因此依赖可以正常 hoist,同时 Pi manifest 只引用本包内稳定路径。FFF 也会由 npm 在 macOS、Linux 和 Windows 上选择正确的原生 binary。
141
141
 
142
- Themes 以及 `pi-init` / `pi-web-access` skills 是发布所需的静态资源,会从锁定依赖同步到本包。更新 dependencies 后运行:
142
+ 当前 dependency extension 版本以 `package.json` 与 lockfile 为准;维护时使用 npm `latest` 稳定标签,并通过 `npm outdated` 确认没有落后版本。
143
+
144
+ Themes 以及 `pi-init` skill 是发布所需的静态资源,会从锁定依赖同步到本包。`pi-web-access` 从 0.14.0 起不再提供 `librarian` skill,preset 同步移除该过期副本,保留 extension 自身的搜索、抓取与 source-check surface。更新 dependencies 后运行:
143
145
 
144
146
  ```bash
145
147
  npm run sync:resources
@@ -151,11 +153,12 @@ npm run check:resources
151
153
  TUI 与 tool ownership:
152
154
 
153
155
  - `pi-everforest-tui`:全局主题、editor chrome、working/status/footer、Command Center 与 Theme Lab
154
- - `@ff-labs/pi-fff`:preset 默认使用 `override` mode,由 FFF 接管 `find`、`grep` 与 `@` autocomplete
155
- - `pi-readseek`:通过 `readseek.replacedTools` 接管 `read`、`edit`、`write`;结构导航和 hashline 工具继续使用 `readSeek_*` 名称,不与 FFF 争夺 `grep`
156
+ - `@ff-labs/pi-fff`:preset 默认使用 `override` mode,由 FFF 接管 `find`、`grep` 与 `@` autocomplete;`--fff-mode`、`PI_FFF_MODE` 或 `~/.pi/agent/pi-fff.json` 的 `mode` 一旦显式设置,均优先于 preset 默认值
157
+ - `pi-readseek`:通过 `readseek.overrideTools` 接管 `read`、`edit`、`write`;`readSeek_grep` 仍可显式用于生成 edit-ready anchors,但 preset 会移除其“优先于 `grep`”提示,默认内容搜索仍由 FFF `grep` 负责
156
158
  - Pi built-ins:继续负责 `bash`、`ls` 及其原生渲染
157
- - `pi-mcp-adapter`:负责 MCP 工具与渲染
159
+ - Pi 内置 MCP:负责 MCP servers、`/mcp` 与 `pi mcp add/list`,读取 `~/.pi/agent/mcp.json` 与 `.pi/mcp.json`。preset 不再捆绑 `pi-mcp-adapter`;原先放在 `.mcp.json` 或 `~/.config/mcp/mcp.json` 的 servers 需要移入上述文件。曾加载 0.3.0 的用户,`settings.json` 的 `extensions` 中可能残留 adapter 写入的 `-builtin:mcp`,需在 `pi config` → Built-in 重新开启 MCP
158
160
  - Tasks、Subagents、Workflows、Goal、BTW、Context 与 Memory:继续使用各 package 自己的领域 UI
161
+ - `workflow` tool 由 `@quintinshaw/pi-dynamic-workflows` 负责。`@tintinweb/pi-subagents` 只保留 `Agent` 等 subagent 能力:全局与项目 `subagents.json` 都未设置 `workflowsEnabled` 时,preset 会在 `~/.pi/agent/subagents.json` 写入 `"workflowsEnabled": false`(保留其他字段,格式损坏的文件不动),关闭其 `SubagentWorkflow`,避免每次启动出现 workflow 冲突 warning(见 [tintinweb/pi-subagents#283](https://github.com/tintinweb/pi-subagents/issues/283))。已有的显式 `true`/`false` 不会被覆盖;设为 `true` 可强制两套 workflow 并存,不推荐
159
162
 
160
163
  Workflow 关键词触发在首次加载 preset 时默认写为关闭;已有明确的 `on`/`off` 用户配置会保留,不会被 preset 覆盖。关闭关键词触发不影响 `/workflows` 及已保存 workflow 的 slash commands。
161
164
 
@@ -166,7 +169,7 @@ Workflow 关键词触发在首次加载 preset 时默认写为关闭;已有明
166
169
  ```json
167
170
  {
168
171
  "readseek": {
169
- "replacedTools": ["read", "edit", "write"]
172
+ "overrideTools": ["read", "edit", "write"]
170
173
  }
171
174
  }
172
175
  ```
@@ -1,12 +1,28 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { loadConfig } from "@ff-labs/pi-fff/src/config.ts";
2
3
  import registerFff from "@ff-labs/pi-fff/src/index.ts";
4
+ import { registerWithToolTransform } from "./tool-registration-transform.ts";
5
+
6
+ const PRESET_MODE = "override";
7
+
8
+ // FFF resolves its mode at session start as flag > env > pi-fff.json > fallback.
9
+ // The preset default fills only the fallback slot, so every explicit choice wins.
10
+ function withPresetModeDefault(pi: ExtensionAPI): void {
11
+ const getFlag = pi.getFlag.bind(pi);
12
+ pi.getFlag = ((name: string) => {
13
+ const value = getFlag(name);
14
+ if (name !== "fff-mode" || value !== undefined) return value;
15
+ if (process.env.PI_FFF_MODE || loadConfig().mode) return value;
16
+ return PRESET_MODE;
17
+ }) as ExtensionAPI["getFlag"];
18
+ }
3
19
 
4
20
  export default function fffAdapter(pi: ExtensionAPI): void {
5
- const configuredMode = process.env.PI_FFF_MODE;
6
- if (!configuredMode) process.env.PI_FFF_MODE = "override";
7
- try {
8
- registerFff(pi);
9
- } finally {
10
- if (!configuredMode) delete process.env.PI_FFF_MODE;
11
- }
21
+ withPresetModeDefault(pi);
22
+ registerWithToolTransform(pi, registerFff, (tool) => ({
23
+ ...tool,
24
+ promptGuidelines: tool.promptGuidelines?.map(
25
+ (guideline) => `${tool.name}: ${guideline}`,
26
+ ),
27
+ }));
12
28
  }
@@ -1 +1,17 @@
1
- export { default } from "pi-readseek";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import registerReadseek from "pi-readseek";
3
+ import { registerWithToolTransform } from "./tool-registration-transform.ts";
4
+
5
+ const READSEEK_GREP_PREFERENCE = "Prefer readSeek_grep over grep when both are available;";
6
+
7
+ export default function readseekAdapter(pi: ExtensionAPI): void {
8
+ registerWithToolTransform(pi, registerReadseek, (tool) => {
9
+ if (tool.name !== "readSeek_grep") return tool;
10
+ return {
11
+ ...tool,
12
+ promptGuidelines: tool.promptGuidelines?.filter(
13
+ (guideline) => !guideline.startsWith(READSEEK_GREP_PREFERENCE),
14
+ ),
15
+ };
16
+ });
17
+ }
@@ -1 +1,46 @@
1
- export { default } from "@tintinweb/pi-subagents/src/index.ts";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
4
+ import { loadSettings } from "@tintinweb/pi-subagents/src/settings.ts";
5
+ import registerSubagents from "@tintinweb/pi-subagents/src/index.ts";
6
+
7
+ type RawSettings = Record<string, unknown>;
8
+
9
+ function readGlobalSettings(path: string): RawSettings | undefined {
10
+ if (!existsSync(path)) return {};
11
+ try {
12
+ const parsed: unknown = JSON.parse(readFileSync(path, "utf-8"));
13
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return undefined;
14
+ return parsed as RawSettings;
15
+ } catch {
16
+ // Leave malformed user files untouched; pi-subagents reports them itself.
17
+ return undefined;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * 1st-pi ships `@quintinshaw/pi-dynamic-workflows` as the sole `workflow`
23
+ * owner. When `workflowsEnabled` is unset, pi-subagents auto-detects that tool,
24
+ * stands down, and warns on every startup (tintinweb/pi-subagents#283). Pin the
25
+ * same outcome globally so the warning disappears, but only when neither the
26
+ * global nor the project settings already contain an explicit choice.
27
+ */
28
+ export function applySubagentsPresetDefaults(cwd: string): void {
29
+ if (typeof loadSettings(cwd).workflowsEnabled === "boolean") return;
30
+
31
+ const path = join(getAgentDir(), "subagents.json");
32
+ const settings = readGlobalSettings(path);
33
+ if (!settings) return;
34
+
35
+ try {
36
+ mkdirSync(dirname(path), { recursive: true });
37
+ writeFileSync(path, `${JSON.stringify({ ...settings, workflowsEnabled: false }, null, 2)}\n`, "utf-8");
38
+ } catch {
39
+ // Non-fatal: pi-subagents still stands down automatically, just with a warning.
40
+ }
41
+ }
42
+
43
+ export default function subagentsAdapter(...args: Parameters<typeof registerSubagents>): ReturnType<typeof registerSubagents> {
44
+ applySubagentsPresetDefaults(process.cwd());
45
+ return registerSubagents(...args);
46
+ }
@@ -0,0 +1,20 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ type RegisteredTool = Parameters<ExtensionAPI["registerTool"]>[0];
4
+
5
+ export function registerWithToolTransform(
6
+ pi: ExtensionAPI,
7
+ register: (api: ExtensionAPI) => void,
8
+ transform: (tool: RegisteredTool) => RegisteredTool,
9
+ ): void {
10
+ const originalRegisterTool = pi.registerTool;
11
+ pi.registerTool = ((tool: RegisteredTool) => {
12
+ originalRegisterTool.call(pi, transform(tool));
13
+ }) as ExtensionAPI["registerTool"];
14
+
15
+ try {
16
+ register(pi);
17
+ } finally {
18
+ pi.registerTool = originalRegisterTool;
19
+ }
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "1st-pi",
3
- "version": "0.1.1",
3
+ "version": "0.3.2",
4
4
  "description": "est7's Pi coding agent preset — skills, extensions, prompts, and themes.",
5
5
  "license": "MIT",
6
6
  "author": "est7",
@@ -32,21 +32,19 @@
32
32
  },
33
33
  "homepage": "https://github.com/est7/1st-pi#readme",
34
34
  "dependencies": {
35
- "@ff-labs/pi-fff": "^0.9.6",
36
- "@juicesharp/rpiv-ask-user-question": "^1.20.0",
37
- "@mrclrchtr/supi-context": "^2.4.0",
38
- "@narumitw/pi-goal": "^0.15.1",
39
- "@quintinshaw/pi-dynamic-workflows": "^2.13.1",
40
- "@tintinweb/pi-subagents": "^0.14.1",
41
- "@tintinweb/pi-tasks": "^0.7.1",
42
- "pi-btw": "^0.4.1",
43
- "pi-everforest-tui": "^0.2.0",
35
+ "@ff-labs/pi-fff": "^0.11.0",
36
+ "@juicesharp/rpiv-ask-user-question": "^2.12.0",
37
+ "@mrclrchtr/supi-context": "^8.0.1",
38
+ "@narumitw/pi-goal": "^0.54.11",
39
+ "@quintinshaw/pi-dynamic-workflows": "^3.14.0",
40
+ "@tintinweb/pi-subagents": "^0.20.0",
41
+ "@tintinweb/pi-tasks": "^0.9.0",
42
+ "pi-btw": "^0.7.1",
43
+ "pi-everforest-tui": "^0.2.1",
44
44
  "pi-init": "^1.0.0",
45
- "pi-mcp-adapter": "^2.11.0",
46
- "pi-observational-memory": "^3.0.3",
47
- "pi-readseek": "^0.6.6",
48
- "pi-session-name": "^0.1.2",
49
- "pi-web-access": "^0.13.0"
45
+ "pi-readseek": "^0.10.4",
46
+ "pi-session-name": "^0.1.7",
47
+ "pi-web-access": "^0.38.0"
50
48
  },
51
49
  "scripts": {
52
50
  "sync:resources": "node scripts/sync-package-resources.mjs",
@@ -55,8 +53,8 @@
55
53
  "pack:dry-run": "npm pack --dry-run --json"
56
54
  },
57
55
  "peerDependencies": {
58
- "@earendil-works/pi-coding-agent": "*",
59
- "@earendil-works/pi-tui": "*"
56
+ "@earendil-works/pi-coding-agent": ">=1.1.0",
57
+ "@earendil-works/pi-tui": ">=1.1.0"
60
58
  },
61
59
  "pi": {
62
60
  "extensions": [
@@ -66,13 +64,11 @@
66
64
  "./extensions/custom-header.ts",
67
65
  "./extensions/packages/ask-user.ts",
68
66
  "./extensions/packages/goal.ts",
69
- "./extensions/packages/observational-memory.ts",
70
67
  "./extensions/packages/fff.ts",
71
68
  "./extensions/packages/readseek.ts",
72
69
  "./extensions/packages/btw.ts",
73
70
  "./extensions/packages/supi-context.ts",
74
71
  "./extensions/packages/web-access.ts",
75
- "./extensions/packages/mcp-adapter.ts",
76
72
  "./extensions/packages/session-name.ts",
77
73
  "./extensions/packages/tasks.ts",
78
74
  "./extensions/packages/subagents.ts"
@@ -1 +0,0 @@
1
- export { default } from "pi-mcp-adapter/index.ts";
@@ -1 +0,0 @@
1
- export { default } from "pi-observational-memory/src/index.ts";
@@ -1,195 +0,0 @@
1
- ---
2
- name: librarian
3
- description: Research open-source libraries with evidence-backed answers and GitHub permalinks. Use when the user asks about library internals, needs implementation details with source code references, wants to understand why something was changed, or needs authoritative answers backed by actual code. Excels at navigating large open-source repos and providing citations to exact lines of code.
4
- ---
5
-
6
- # Librarian
7
-
8
- Answer questions about open-source libraries by finding evidence with GitHub permalinks. Every claim backed by actual code.
9
-
10
- ## Execution Model
11
-
12
- Pi executes tool calls sequentially, even when you emit multiple calls in one turn. But batching independent calls in a single turn still saves LLM round-trips (~5-10s each). Use these patterns:
13
-
14
- | Pattern | When | Actually parallel? |
15
- |---------|------|-------------------|
16
- | Batch tool calls in one turn | Independent ops (web_search + fetch_content + read) | No, but saves round-trips |
17
- | `fetch_content({ urls: [...] })` | Multiple URLs to fetch | Yes (3 concurrent) |
18
- | Bash with `&` + `wait` | Multiple git/gh commands | Yes (OS-level) |
19
-
20
- ## Step 1: Classify the Request
21
-
22
- Before doing anything, classify the request to pick the right research strategy.
23
-
24
- | Type | Trigger | Primary Approach |
25
- |------|---------|-----------------|
26
- | **Conceptual** | "How do I use X?", "Best practice for Y?" | web_search + fetch_content (README/docs) |
27
- | **Implementation** | "How does X implement Y?", "Show me the source" | fetch_content (clone) + code search |
28
- | **Context/History** | "Why was this changed?", "History of X?" | git log + git blame + issue/PR search |
29
- | **Comprehensive** | Complex or ambiguous requests, "deep dive" | All of the above |
30
-
31
- ## Step 2: Research by Type
32
-
33
- ### Conceptual Questions
34
-
35
- Batch these in one turn:
36
-
37
- 1. **web_search**: `"library-name topic"` via Perplexity for recent articles and discussions
38
- 2. **fetch_content**: the library's GitHub repo URL to clone and check README, docs, or examples
39
-
40
- Synthesize web results + repo docs. Cite official documentation and link to relevant source files.
41
-
42
- ### Implementation Questions
43
-
44
- The core workflow -- clone, find, permalink:
45
-
46
- 1. **fetch_content** the GitHub repo URL -- this clones it locally and returns the file tree
47
- 2. Use **bash** to search the cloned repo: `grep -rn "function_name"`, `find . -name "*.ts"`
48
- 3. Use **read** to examine specific files once you've located them
49
- 4. Get the commit SHA: `cd /tmp/pi-github-repos/owner/repo && git rev-parse HEAD`
50
- 5. Construct permalink: `https://github.com/owner/repo/blob/<sha>/path/to/file#L10-L20`
51
-
52
- Batch the initial calls: fetch_content (clone) + web_search (recent discussions) in one turn. Then dig into the clone with grep/read once it's available.
53
-
54
- ### Context/History Questions
55
-
56
- Use git operations on the cloned repo:
57
-
58
- ```bash
59
- cd /tmp/pi-github-repos/owner/repo
60
-
61
- # Recent changes to a specific file
62
- git log --oneline -n 20 -- path/to/file.ts
63
-
64
- # Who changed what and when
65
- git blame -L 10,30 path/to/file.ts
66
-
67
- # Full diff for a specific commit
68
- git show <sha> -- path/to/file.ts
69
-
70
- # Search commit messages
71
- git log --oneline --grep="keyword" -n 10
72
- ```
73
-
74
- For issues and PRs, use bash:
75
-
76
- ```bash
77
- # Search issues
78
- gh search issues "keyword" --repo owner/repo --state all --limit 10
79
-
80
- # Search merged PRs
81
- gh search prs "keyword" --repo owner/repo --state merged --limit 10
82
-
83
- # View specific issue/PR with comments
84
- gh issue view <number> --repo owner/repo --comments
85
- gh pr view <number> --repo owner/repo --comments
86
-
87
- # Release notes
88
- gh api repos/owner/repo/releases --jq '.[0:5] | .[].tag_name'
89
- ```
90
-
91
- ### Comprehensive Research
92
-
93
- Combine everything. Batch these in one turn:
94
-
95
- 1. **web_search**: recent articles and discussions
96
- 2. **fetch_content**: clone the repo (or multiple repos if comparing)
97
- 3. **bash**: `gh search issues "keyword" --repo owner/repo --limit 10 & gh search prs "keyword" --repo owner/repo --state merged --limit 10 & wait`
98
-
99
- Then dig into the clone with grep, read, git blame, git log as needed.
100
-
101
- ## Step 3: Construct Permalinks
102
-
103
- Permalinks are the whole point. They make your answers citable and verifiable.
104
-
105
- ```
106
- https://github.com/<owner>/<repo>/blob/<commit-sha>/<filepath>#L<start>-L<end>
107
- ```
108
-
109
- Getting the SHA from a cloned repo:
110
-
111
- ```bash
112
- cd /tmp/pi-github-repos/owner/repo && git rev-parse HEAD
113
- ```
114
-
115
- Getting the SHA from a tag:
116
-
117
- ```bash
118
- gh api repos/owner/repo/git/refs/tags/v1.0.0 --jq '.object.sha'
119
- ```
120
-
121
- Always use full commit SHAs, not branch names. Branch links break when code changes. Permalinks don't.
122
-
123
- ## Step 4: Cite Everything
124
-
125
- Every code-related claim needs a permalink. Format:
126
-
127
- ```markdown
128
- The stale time check happens in [`notifyManager.ts`](https://github.com/TanStack/query/blob/abc123/packages/query-core/src/notifyManager.ts#L42-L50):
129
-
130
- \`\`\`typescript
131
- function isStale(query: Query, staleTime: number): boolean {
132
- return query.state.dataUpdatedAt + staleTime < Date.now()
133
- }
134
- \`\`\`
135
- ```
136
-
137
- For conceptual answers, link to official docs and relevant source files. For implementation answers, every function/class reference should have a permalink.
138
-
139
- ## Video Analysis
140
-
141
- For questions about video tutorials, conference talks, or screen recordings:
142
-
143
- ```typescript
144
- // Full extraction (transcript + visual descriptions)
145
- fetch_content({ url: "https://youtube.com/watch?v=abc" })
146
-
147
- // Ask a specific question about a video
148
- fetch_content({ url: "https://youtube.com/watch?v=abc", prompt: "What libraries are imported in this tutorial?" })
149
-
150
- // Single frame at a known moment
151
- fetch_content({ url: "https://youtube.com/watch?v=abc", timestamp: "23:41" })
152
-
153
- // Range scan for visual discovery
154
- fetch_content({ url: "https://youtube.com/watch?v=abc", timestamp: "23:41-25:00" })
155
-
156
- // Custom density across a range
157
- fetch_content({ url: "https://youtube.com/watch?v=abc", timestamp: "23:41-25:00", frames: 3 })
158
-
159
- // Whole-video sampling
160
- fetch_content({ url: "https://youtube.com/watch?v=abc", frames: 6 })
161
-
162
- // Analyze a local recording
163
- fetch_content({ url: "/path/to/demo.mp4", prompt: "What error message appears on screen?" })
164
-
165
- // Batch multiple videos with the same question
166
- fetch_content({
167
- urls: ["https://youtube.com/watch?v=abc", "https://youtube.com/watch?v=def"],
168
- prompt: "What packages are installed?"
169
- })
170
- ```
171
-
172
- Use single timestamps for known moments, ranges for visual scanning, and frames-alone for a quick overview of the whole video.
173
-
174
- The `prompt` parameter only applies to video content (YouTube URLs and local video files). For non-video URLs, it's ignored.
175
-
176
- ## Failure Recovery
177
-
178
- | Failure | Recovery |
179
- |---------|----------|
180
- | grep finds nothing | Broaden the query, try concept names instead of exact function names |
181
- | gh CLI rate limited | Use the already-cloned repo in /tmp/pi-github-repos/ for git operations |
182
- | Repo too large to clone | fetch_content returns an API-only view automatically; use that or add `forceClone: true` |
183
- | File not found in clone | Branch name with slashes may have misresolved; list the repo tree and navigate manually |
184
- | Uncertain about implementation | State your uncertainty explicitly, propose a hypothesis, show what evidence you did find |
185
- | Video extraction fails | Ensure Chrome is signed into gemini.google.com (free) or set GEMINI_API_KEY |
186
- | Page returns 403/bot block | Gemini fallback triggers automatically; no action needed if Gemini is configured |
187
- | web_search fails | Check provider config; try explicit `provider: "gemini"` if Perplexity key is missing |
188
-
189
- ## Guidelines
190
-
191
- - Vary search queries when running multiple searches -- different angles, not the same pattern repeated
192
- - Prefer recent sources; filter out outdated results when they conflict with newer information
193
- - For version-specific questions, clone the tagged version: `fetch_content("https://github.com/owner/repo/tree/v1.0.0")`
194
- - When the repo is already cloned from a previous fetch_content call, reuse it -- check the path before cloning again
195
- - Answer directly. Skip preamble like "I'll help you with..." -- go straight to findings