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 +15 -12
- package/extensions/packages/fff.ts +23 -7
- package/extensions/packages/readseek.ts +17 -1
- package/extensions/packages/subagents.ts +46 -1
- package/extensions/packages/tool-registration-transform.ts +20 -0
- package/package.json +15 -19
- package/extensions/packages/mcp-adapter.ts +0 -1
- package/extensions/packages/observational-memory.ts +0 -1
- package/skills/librarian/SKILL.md +0 -195
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
|
|
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-
|
|
132
|
-
| [
|
|
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;
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
"
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
36
|
-
"@juicesharp/rpiv-ask-user-question": "^
|
|
37
|
-
"@mrclrchtr/supi-context": "^
|
|
38
|
-
"@narumitw/pi-goal": "^0.
|
|
39
|
-
"@quintinshaw/pi-dynamic-workflows": "^
|
|
40
|
-
"@tintinweb/pi-subagents": "^0.
|
|
41
|
-
"@tintinweb/pi-tasks": "^0.
|
|
42
|
-
"pi-btw": "^0.
|
|
43
|
-
"pi-everforest-tui": "^0.2.
|
|
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-
|
|
46
|
-
"pi-
|
|
47
|
-
"pi-
|
|
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
|