mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 07:23:06 +00:00
feat: add prompt routing and terminal preset
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
.pi/npm/
|
.pi/npm/
|
||||||
|
.pi-debug/
|
||||||
|
|
||||||
# Compiled Java class files
|
# Compiled Java class files
|
||||||
*.class
|
*.class
|
||||||
|
|||||||
@@ -14,12 +14,13 @@
|
|||||||
- `extensions/permission-system.ts`:在权限扩展注册前,将 `config/pi-permission-system.json` 同步为全局权威配置。
|
- `extensions/permission-system.ts`:在权限扩展注册前,将 `config/pi-permission-system.json` 同步为全局权威配置。
|
||||||
- `extensions/lsp.ts`:部署 Kotlin/JDT LS 全局配置并加载 `pi-lsp`。
|
- `extensions/lsp.ts`:部署 Kotlin/JDT LS 全局配置并加载 `pi-lsp`。
|
||||||
- `extensions/auto-permissions.ts`:部署 contextual Bash guardian 规则并加载 `pi-auto-permissions`。
|
- `extensions/auto-permissions.ts`:部署 contextual Bash guardian 规则并加载 `pi-auto-permissions`。
|
||||||
|
- `extensions/tool-routing.ts`:保留 Pi 默认系统提示词,在每轮开始前按激活工具追加简短路由规则,并提供 `/dump-system-prompt` 将扩展所见的有效提示词写入 `.pi-debug/effective-system-prompt.md`。
|
||||||
- `pi-lsp@0.1.7`:提供声明式 LSP 接入;组合包配置 `kotlin-lsp --stdio` 与 `jdtls`。
|
- `pi-lsp@0.1.7`:提供声明式 LSP 接入;组合包配置 `kotlin-lsp --stdio` 与 `jdtls`。
|
||||||
- `pi-hermes-memory@0.9.6`:提供持久记忆、会话搜索、后台学习和 secret scanning,默认使用 policy-only 模式。
|
- `pi-hermes-memory@0.9.6`:提供持久记忆、会话搜索、后台学习和 secret scanning,默认使用 policy-only 模式。
|
||||||
- `@ogulcancelik/pi-auto-permissions@0.1.3`:根据当前对话复核配置命中的 Bash 命令,不是全工具审批层。
|
- `@ogulcancelik/pi-auto-permissions@0.1.3`:根据当前对话复核配置命中的 Bash 命令,不是全工具审批层。
|
||||||
- `@ogulcancelik/pi-codex-compaction@0.1.3`:为 `openai-codex` 提供原生远程 compaction,默认阈值为 90%。
|
- `@ogulcancelik/pi-codex-compaction@0.1.3`:为 `openai-codex` 提供原生远程 compaction,默认阈值为 90%。
|
||||||
- 根包还固定安装 `pi-context-view`、`@firstpick/pi-extension-codex-fast-mode` 和 `@gotgenes/pi-permission-system`。
|
- 根包还固定安装 `pi-context-view`、`@firstpick/pi-extension-codex-fast-mode` 和 `@gotgenes/pi-permission-system`。
|
||||||
- `install.sh`:先安装根组合包,再交互检查 Kitty/Solarized Dark、Oh My Zsh/Powerlevel10k/Zsh 插件、CodeGraph、Kotlin LSP、Java 21+ 和 JDT LS;缺失项目只在用户明确选择 `Y` 后安装或配置。
|
- `install.sh`:先安装根组合包,再交互检查 Kitty/Solarized Dark、Oh My Zsh/Powerlevel10k/Zsh 插件、CodeGraph、Kotlin LSP、Java 21+ 和 JDT LS;缺失项目只在用户明确选择 `Y` 后安装或配置。Powerlevel10k 默认配置来自仓库内置的 `config/p10k.zsh`(当前 Rainbow/ASCII 单行紧凑主题)。
|
||||||
- `uninstall.sh`:只移除根组合包,不卸载或还原可能被其他项目共享的终端环境、CodeGraph、Kotlin LSP、JDT LS 或 Java。
|
- `uninstall.sh`:只移除根组合包,不卸载或还原可能被其他项目共享的终端环境、CodeGraph、Kotlin LSP、JDT LS 或 Java。
|
||||||
|
|
||||||
## 当前职责与默认行为
|
## 当前职责与默认行为
|
||||||
@@ -30,6 +31,8 @@
|
|||||||
- `readCompaction.enabled`、`sourceCodeFilteringEnabled` 和 `smartTruncate.enabled` 当前均默认 `false`,源码读取保持原样。未经用户明确决定,不因节省上下文而改变这些默认值。
|
- `readCompaction.enabled`、`sourceCodeFilteringEnabled` 和 `smartTruncate.enabled` 当前均默认 `false`,源码读取保持原样。未经用户明确决定,不因节省上下文而改变这些默认值。
|
||||||
- 若以后开启 read 压缩,优先考虑 `readCompaction + smartTruncate`,源码过滤仍独立评估;必须保留精确 `offset/limit` 读取、短文件和行锚点的完整性。
|
- 若以后开启 read 压缩,优先考虑 `readCompaction + smartTruncate`,源码过滤仍独立评估;必须保留精确 `offset/limit` 读取、短文件和行锚点的完整性。
|
||||||
- Context Mode 负责避免批量读取、命令研究和网页原始内容直接撑大上下文;FFF 仍负责精确字面搜索,RTK 仍处理未走 Context Mode 的普通输出。
|
- Context Mode 负责避免批量读取、命令研究和网页原始内容直接撑大上下文;FFF 仍负责精确字面搜索,RTK 仍处理未走 Context Mode 的普通输出。
|
||||||
|
- 工具路由规则不得替换 Pi 默认系统提示词:代码结构与符号关系优先 CodeGraph;字面搜索先用 FFF `find` 收敛文件位置,再在收敛路径内用 `grep`/`multi_grep` 获取行号,最后才按需精确 `read`。遇到大量结果、截断或上限时继续缩小 path/glob/pattern,不得靠提高 limit 或倾倒全部结果解决。
|
||||||
|
- `.pi-debug/` 是 `/dump-system-prompt` 生成的本地诊断目录,不提交到仓库,也不作为组合包运行时配置源。
|
||||||
- CodeGraph 扩展只配置 Pi 到外部 `codegraph` 命令的 MCP 连接。根包安装本身不安装 CodeGraph;便捷脚本仅在组合包安装完成且用户明确选择 `Y` 后调用官方安装器。仓库不执行 `codegraph init`,不创建或管理 `.codegraph/`,也不改动索引、更新或遥测设置。
|
- CodeGraph 扩展只配置 Pi 到外部 `codegraph` 命令的 MCP 连接。根包安装本身不安装 CodeGraph;便捷脚本仅在组合包安装完成且用户明确选择 `Y` 后调用官方安装器。仓库不执行 `codegraph init`,不创建或管理 `.codegraph/`,也不改动索引、更新或遥测设置。
|
||||||
- CodeGraph MCP 使用 `keep-alive` 并只直接暴露 `codegraph_explore`;命令缺失、项目未初始化或连接失败时不得阻止其他扩展加载。
|
- CodeGraph MCP 使用 `keep-alive` 并只直接暴露 `codegraph_explore`;命令缺失、项目未初始化或连接失败时不得阻止其他扩展加载。
|
||||||
- `pi-context-view` 只观察上下文占用,不参与压缩策略。
|
- `pi-context-view` 只观察上下文占用,不参与压缩策略。
|
||||||
@@ -40,7 +43,7 @@
|
|||||||
- 当前只把 Git 非只读操作和包管理类 Bash 命令交给 `pi-auto-permissions` 根据用户上下文复核。低风险操作可自动允许;中风险操作仅在用户明确授权目标与约束时自动允许;高风险操作即使已有概括授权也必须回到用户确认。文件/系统/网络高风险操作继续由现有解析能力更强的 `pi-permission-system` 处理。
|
- 当前只把 Git 非只读操作和包管理类 Bash 命令交给 `pi-auto-permissions` 根据用户上下文复核。低风险操作可自动允许;中风险操作仅在用户明确授权目标与约束时自动允许;高风险操作即使已有概括授权也必须回到用户确认。文件/系统/网络高风险操作继续由现有解析能力更强的 `pi-permission-system` 处理。
|
||||||
- 将 Auto Permissions 规则配置为 `.*` 最多只能复核所有 Bash 命令,不能覆盖其他工具,并会为普通 Bash 调用增加额外模型请求、延迟和成本。若未来目标是让现有所有 `ask` 先经模型裁决,必须另行实现 `pi-permission-system` authorizer 集成,不能仅靠该 npm 包配置实现。
|
- 将 Auto Permissions 规则配置为 `.*` 最多只能复核所有 Bash 命令,不能覆盖其他工具,并会为普通 Bash 调用增加额外模型请求、延迟和成本。若未来目标是让现有所有 `ask` 先经模型裁决,必须另行实现 `pi-permission-system` authorizer 集成,不能仅靠该 npm 包配置实现。
|
||||||
- `pi-lsp` 使用组合包部署的 `kotlin-lsp --stdio` 与 `jdtls` 配置,但根包安装本身不安装这两个系统可执行文件;便捷脚本可在用户逐项明确确认后通过 Homebrew 安装 Kotlin LSP、Java 21 和 JDT LS。
|
- `pi-lsp` 使用组合包部署的 `kotlin-lsp --stdio` 与 `jdtls` 配置,但根包安装本身不安装这两个系统可执行文件;便捷脚本可在用户逐项明确确认后通过 Homebrew 安装 Kotlin LSP、Java 21 和 JDT LS。
|
||||||
- 终端环境配置只属于便捷脚本:Kitty 可选安装后可通过官方 kitten 启用 Solarized Dark;Oh My Zsh 使用不覆盖 `.zshrc`、不切换 shell 的 unattended 安装;Powerlevel10k 默认部署官方 Lean/ASCII 预设以跳过首次向导;`git`、`zsh-autosuggestions`、`zsh-syntax-highlighting` 逐项询问后才安装或启用。修改 `.zshrc` 前必须创建带时间戳的备份。
|
- 终端环境配置只属于便捷脚本:Kitty 可选安装后可通过官方 kitten 启用 Solarized Dark;Oh My Zsh 使用不覆盖 `.zshrc`、不切换 shell 的 unattended 安装;Powerlevel10k 在用户没有现有 `~/.p10k.zsh` 时部署仓库内置的 `config/p10k.zsh`(Rainbow/ASCII 单行紧凑主题)以跳过首次向导,已有配置不得覆盖;`git`、`zsh-autosuggestions`、`zsh-syntax-highlighting` 逐项询问后才安装或启用。修改 `.zshrc` 前必须创建带时间戳的备份。
|
||||||
- Codex 远程压缩只对 `openai-codex` 生效,默认在 turn boundary 达到 90% 时触发;Hermes Memory 默认使用 policy-only 模式。
|
- Codex 远程压缩只对 `openai-codex` 生效,默认在 turn boundary 达到 90% 时触发;Hermes Memory 默认使用 policy-only 模式。
|
||||||
- `install.sh` 默认从 `git:git@bitbucket.org:siakitem/my-pi.git` 安装,并允许用 `PI_PACKAGE_SOURCE` 覆盖来源;组合包安装失败时立即停止,机器级依赖安装失败时继续检查其余依赖并最终返回非零状态。
|
- `install.sh` 默认从 `git:git@bitbucket.org:siakitem/my-pi.git` 安装,并允许用 `PI_PACKAGE_SOURCE` 覆盖来源;组合包安装失败时立即停止,机器级依赖安装失败时继续检查其余依赖并最终返回非零状态。
|
||||||
- CodeGraph 的可选安装使用官方远程安装脚本;macOS Kitty 使用 Homebrew cask,其他系统使用 Kitty 官方安装器;Kotlin LSP、Java 21 和 JDT LS 使用 Homebrew;Oh My Zsh 使用官方安装器,Powerlevel10k 与两个第三方 Zsh 插件从各自官方 Git 仓库克隆。缺少 Homebrew、curl 或 git 时保留已经完成的组合包安装并报告失败。
|
- CodeGraph 的可选安装使用官方远程安装脚本;macOS Kitty 使用 Homebrew cask,其他系统使用 Kitty 官方安装器;Kotlin LSP、Java 21 和 JDT LS 使用 Homebrew;Oh My Zsh 使用官方安装器,Powerlevel10k 与两个第三方 Zsh 插件从各自官方 Git 仓库克隆。缺少 Homebrew、curl 或 git 时保留已经完成的组合包安装并报告失败。
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
- `@ogulcancelik/pi-codex-compaction@0.1.3`:为 `openai-codex` 提供原生远程压缩。
|
- `@ogulcancelik/pi-codex-compaction@0.1.3`:为 `openai-codex` 提供原生远程压缩。
|
||||||
- `@ogulcancelik/pi-auto-permissions@0.1.3`:按当前对话自动复核受控 Bash 操作。
|
- `@ogulcancelik/pi-auto-permissions@0.1.3`:按当前对话自动复核受控 Bash 操作。
|
||||||
- `@gotgenes/pi-permission-system@26.2.1`:负责工具、路径、MCP、硬拒绝和兜底权限基线。
|
- `@gotgenes/pi-permission-system@26.2.1`:负责工具、路径、MCP、硬拒绝和兜底权限基线。
|
||||||
|
- `extensions/tool-routing.ts`:保留 Pi 默认系统提示词,并按当前激活工具追加简短的工具与搜索路由规则;提供 `/dump-system-prompt` 导出当前有效提示词。
|
||||||
|
|
||||||
## 安装与卸载
|
## 安装与卸载
|
||||||
|
|
||||||
@@ -36,8 +37,9 @@ pi install git:git@bitbucket.org:siakitem/my-pi.git
|
|||||||
- 检查 Oh My Zsh。安装采用官方 unattended 模式,不切换默认 shell、不立即启动 Zsh,
|
- 检查 Oh My Zsh。安装采用官方 unattended 模式,不切换默认 shell、不立即启动 Zsh,
|
||||||
也不覆盖现有 `.zshrc`。
|
也不覆盖现有 `.zshrc`。
|
||||||
- 检查 Powerlevel10k;可克隆到 Oh My Zsh 的 custom themes 目录,并在没有现有
|
- 检查 Powerlevel10k;可克隆到 Oh My Zsh 的 custom themes 目录,并在没有现有
|
||||||
`~/.p10k.zsh` 时复制官方 Lean 预设、切换为兼容性更高的 ASCII 图标模式。脚本会把
|
`~/.p10k.zsh` 时复制仓库内置的 `config/p10k.zsh`。该配置来自当前使用的 Powerlevel10k
|
||||||
`ZSH_THEME` 和预设加载语句写入 `.zshrc`,因此首次启动不会进入交互配置向导。
|
Rainbow/ASCII 单行紧凑主题;脚本会把 `ZSH_THEME` 和配置加载语句写入 `.zshrc`,因此
|
||||||
|
首次启动不会进入交互配置向导。已有 `~/.p10k.zsh` 始终保留,不会被覆盖。
|
||||||
- 逐项检查 `git`、`zsh-autosuggestions` 和 `zsh-syntax-highlighting` 是否已经在
|
- 逐项检查 `git`、`zsh-autosuggestions` 和 `zsh-syntax-highlighting` 是否已经在
|
||||||
`.zshrc` 的 `plugins` 数组中启用。后两个插件缺少源码时会先克隆到 Oh My Zsh 的
|
`.zshrc` 的 `plugins` 数组中启用。后两个插件缺少源码时会先克隆到 Oh My Zsh 的
|
||||||
custom plugins 目录;语法高亮按最后一个插件处理。
|
custom plugins 目录;语法高亮按最后一个插件处理。
|
||||||
@@ -81,6 +83,14 @@ CodeGraph 本体不由组合包安装。需要使用 CodeGraph 的机器应自
|
|||||||
|
|
||||||
## 组合行为
|
## 组合行为
|
||||||
|
|
||||||
|
### 工具与搜索路由
|
||||||
|
|
||||||
|
`extensions/tool-routing.ts` 不替换 Pi 默认系统提示词,而是在每轮开始前根据当前激活工具追加简短规则:代码结构和符号关系优先使用 CodeGraph;字面搜索先用 FFF `find` 缩小文件或目录范围,再在已收敛的路径中用 `grep`/`multi_grep` 获取行号,最后才用带 `offset/limit` 的 `read` 读取精确区域。宽泛搜索命中上百或上千结果、发生截断或达到上限时,应继续缩小路径、glob 或 pattern,而不是提高 limit 或输出全部结果。
|
||||||
|
|
||||||
|
日志、测试/构建输出、大文件分析和不可预测的大输出优先交给 Context Mode;需要编辑所依赖的精确原文或短文件才直接使用 `read`。已有工具结果足够时停止检索,避免对同一问题依次重复调用 CodeGraph、FFF 和 `read`。
|
||||||
|
|
||||||
|
使用 `/dump-system-prompt` 可将当前扩展所见的有效提示词写入当前项目的 `.pi-debug/effective-system-prompt.md`。`.pi-debug/` 属于本地诊断输出,默认不提交。
|
||||||
|
|
||||||
### 搜索归 FFF
|
### 搜索归 FFF
|
||||||
|
|
||||||
`extensions/fff-override.ts` 强制设置 FFF 官方的 `PI_FFF_MODE=override`(显式传入
|
`extensions/fff-override.ts` 强制设置 FFF 官方的 `PI_FFF_MODE=override`(显式传入
|
||||||
|
|||||||
+1833
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,83 @@
|
|||||||
|
import type { BuildSystemPromptOptions, ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||||
|
import { mkdir, writeFile } from "node:fs/promises";
|
||||||
|
import { dirname, resolve } from "node:path";
|
||||||
|
|
||||||
|
const ROUTING_MARKER = "<!-- my-pi-tool-routing -->";
|
||||||
|
const DUMP_RELATIVE_PATH = ".pi-debug/effective-system-prompt.md";
|
||||||
|
|
||||||
|
type SelectedTools = BuildSystemPromptOptions["selectedTools"];
|
||||||
|
|
||||||
|
function hasTool(selectedTools: SelectedTools, name: string): boolean {
|
||||||
|
return selectedTools === undefined || selectedTools.includes(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildToolRoutingSection(selectedTools: SelectedTools): string {
|
||||||
|
const rules: string[] = [];
|
||||||
|
|
||||||
|
if (hasTool(selectedTools, "codegraph_explore")) {
|
||||||
|
rules.push(
|
||||||
|
"- Use codegraph_explore first for architecture, symbol relationships, code flows, and symbols you are about to change. Treat source returned by it as already read; do not repeat the same exploration with read or search unless information is missing.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTool(selectedTools, "find") || hasTool(selectedTools, "grep") || hasTool(selectedTools, "multi_grep")) {
|
||||||
|
rules.push(
|
||||||
|
"- For literal search, narrow in stages instead of requesting a repository-wide dump:",
|
||||||
|
" 1. Use find to identify likely files or directories. Constrain path/glob and keep the result limit small.",
|
||||||
|
" 2. Use grep or multi_grep only inside the narrowed path or file to obtain matching line numbers. Start with a specific or literal pattern, a small context window, and a bounded limit.",
|
||||||
|
" 3. Use read with offset/limit only for the exact matching region when full source is still needed.",
|
||||||
|
"- Do not run a broad search expected to return hundreds or thousands of files or matches. If results truncate or hit a limit, narrow the path, glob, or pattern instead of increasing the limit or dumping all results.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTool(selectedTools, "ctx_execute") || hasTool(selectedTools, "ctx_execute_file")) {
|
||||||
|
rules.push(
|
||||||
|
"- Use Context Mode for logs, test/build output, generated data, large-file analysis, and any command whose output may be large or unpredictable. Print only the derived answer needed for the task.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTool(selectedTools, "read")) {
|
||||||
|
rules.push(
|
||||||
|
"- Use read directly when exact text is needed for editing or when a file is small. Do not read a complete large file merely to copy, compare, hash, count, or summarize it.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
rules.push(
|
||||||
|
"- Stop searching once the current evidence is sufficient. Avoid repeating the same lookup through CodeGraph, find, grep, and read without a concrete information gap.",
|
||||||
|
);
|
||||||
|
|
||||||
|
return `${ROUTING_MARKER}\n## Tool Routing\n\n${rules.join("\n")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function appendToolRouting(systemPrompt: string, selectedTools: SelectedTools): string {
|
||||||
|
if (systemPrompt.includes(ROUTING_MARKER)) {
|
||||||
|
return systemPrompt;
|
||||||
|
}
|
||||||
|
return `${systemPrompt}\n\n${buildToolRoutingSection(selectedTools)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSystemPromptDumpPath(cwd: string): string {
|
||||||
|
return resolve(cwd, DUMP_RELATIVE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function toolRoutingExtension(pi: ExtensionAPI): void {
|
||||||
|
let lastEffectivePrompt: string | undefined;
|
||||||
|
|
||||||
|
pi.on("before_agent_start", (event) => {
|
||||||
|
lastEffectivePrompt = appendToolRouting(event.systemPrompt, event.systemPromptOptions.selectedTools);
|
||||||
|
return { systemPrompt: lastEffectivePrompt };
|
||||||
|
});
|
||||||
|
|
||||||
|
pi.registerCommand("dump-system-prompt", {
|
||||||
|
description: "Write the effective Pi system prompt to .pi-debug/effective-system-prompt.md",
|
||||||
|
handler: async (_args, ctx) => {
|
||||||
|
const outputPath = getSystemPromptDumpPath(ctx.cwd);
|
||||||
|
const selectedTools = ctx.getSystemPromptOptions().selectedTools;
|
||||||
|
const effectivePrompt = lastEffectivePrompt ?? appendToolRouting(ctx.getSystemPrompt(), selectedTools);
|
||||||
|
|
||||||
|
await mkdir(dirname(outputPath), { recursive: true });
|
||||||
|
await writeFile(outputPath, effectivePrompt, "utf8");
|
||||||
|
ctx.ui.notify(`System prompt written to ${outputPath} (${effectivePrompt.length} chars)`, "info");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
+9
-4
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(CDPATH=; cd "$(dirname "$0")" && pwd) || exit 1
|
||||||
PACKAGE_SOURCE=${PI_PACKAGE_SOURCE:-git:git@bitbucket.org:siakitem/my-pi.git}
|
PACKAGE_SOURCE=${PI_PACKAGE_SOURCE:-git:git@bitbucket.org:siakitem/my-pi.git}
|
||||||
|
POWERLEVEL10K_PRESET_FILE=$SCRIPT_DIR/config/p10k.zsh
|
||||||
CODEGRAPH_INSTALL_URL=https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh
|
CODEGRAPH_INSTALL_URL=https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh
|
||||||
KITTY_INSTALL_URL=https://sw.kovidgoyal.net/kitty/installer.sh
|
KITTY_INSTALL_URL=https://sw.kovidgoyal.net/kitty/installer.sh
|
||||||
OH_MY_ZSH_INSTALL_URL=https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh
|
OH_MY_ZSH_INSTALL_URL=https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh
|
||||||
@@ -268,9 +270,12 @@ configure_powerlevel10k() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$HOME/.p10k.zsh" ]; then
|
if [ ! -f "$HOME/.p10k.zsh" ]; then
|
||||||
sed 's/POWERLEVEL9K_MODE=nerdfont-complete/POWERLEVEL9K_MODE=ascii/' \
|
if [ ! -f "$POWERLEVEL10K_PRESET_FILE" ]; then
|
||||||
"$powerlevel10k_dir/config/p10k-lean.zsh" > "$HOME/.p10k.zsh" || return 1
|
warn "找不到仓库内置的 Powerlevel10k 配置:$POWERLEVEL10K_PRESET_FILE"
|
||||||
say "已写入 Powerlevel10k Lean/ASCII 预设,首次启动不会进入配置向导。"
|
return 1
|
||||||
|
fi
|
||||||
|
cp "$POWERLEVEL10K_PRESET_FILE" "$HOME/.p10k.zsh" || return 1
|
||||||
|
say "已写入仓库内置的 Powerlevel10k Rainbow/ASCII 配置,首次启动不会进入配置向导。"
|
||||||
fi
|
fi
|
||||||
set_powerlevel10k_theme || return 1
|
set_powerlevel10k_theme || return 1
|
||||||
ensure_oh_my_zsh_loader || return 1
|
ensure_oh_my_zsh_loader || return 1
|
||||||
@@ -407,7 +412,7 @@ if [ "$oh_my_zsh_ok" -eq 1 ]; then
|
|||||||
grep -E "^[[:space:]]*ZSH_THEME[[:space:]]*=[[:space:]]*[\"']?powerlevel10k/powerlevel10k[\"']?" \
|
grep -E "^[[:space:]]*ZSH_THEME[[:space:]]*=[[:space:]]*[\"']?powerlevel10k/powerlevel10k[\"']?" \
|
||||||
"$zshrc_file" >/dev/null 2>&1 && [ -f "$HOME/.p10k.zsh" ] && p10k_config_sourced; then
|
"$zshrc_file" >/dev/null 2>&1 && [ -f "$HOME/.p10k.zsh" ] && p10k_config_sourced; then
|
||||||
say "✓ Powerlevel10k 已安装并配置"
|
say "✓ Powerlevel10k 已安装并配置"
|
||||||
elif ask_yes_no "Powerlevel10k 尚未完整配置。是否安装并应用免向导的 Lean/ASCII 预设?"; then
|
elif ask_yes_no "Powerlevel10k 尚未完整配置。是否安装并应用仓库内置的 Rainbow/ASCII 配置?"; then
|
||||||
configure_powerlevel10k || record_install_failure "Powerlevel10k"
|
configure_powerlevel10k || record_install_failure "Powerlevel10k"
|
||||||
else
|
else
|
||||||
say "- 已跳过 Powerlevel10k。"
|
say "- 已跳过 Powerlevel10k。"
|
||||||
|
|||||||
+2
-1
@@ -29,7 +29,8 @@
|
|||||||
"./node_modules/pi-hermes-memory/src/index.ts",
|
"./node_modules/pi-hermes-memory/src/index.ts",
|
||||||
"./node_modules/@ogulcancelik/pi-codex-compaction/index.ts",
|
"./node_modules/@ogulcancelik/pi-codex-compaction/index.ts",
|
||||||
"./extensions/auto-permissions.ts",
|
"./extensions/auto-permissions.ts",
|
||||||
"./extensions/permission-system.ts"
|
"./extensions/permission-system.ts",
|
||||||
|
"./extensions/tool-routing.ts"
|
||||||
],
|
],
|
||||||
"skills": [
|
"skills": [
|
||||||
"./node_modules/context-mode/skills"
|
"./node_modules/context-mode/skills"
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.
|
||||||
|
|
||||||
|
Available tools:
|
||||||
|
- read: Read file contents
|
||||||
|
- bash: Execute bash commands (ls, grep, find, etc.)
|
||||||
|
- edit: Make precise file edits with exact text replacement, including multiple disjoint edits in one call
|
||||||
|
- write: Create or overwrite files
|
||||||
|
|
||||||
|
In addition to the tools above, you may have access to other custom tools depending on the project.
|
||||||
|
|
||||||
|
Guidelines:
|
||||||
|
- Use bash for file operations like ls, rg, find
|
||||||
|
- Use read to examine files instead of cat or sed.
|
||||||
|
- You can inspect PI_* environment variables for current model and session details.
|
||||||
|
- Use edit for precise changes (edits[].oldText must match exactly)
|
||||||
|
- When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls
|
||||||
|
- Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.
|
||||||
|
- Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.
|
||||||
|
- Use write only for new files or complete rewrites.
|
||||||
|
- Be concise in your responses
|
||||||
|
- Show file paths clearly when working with files
|
||||||
|
|
||||||
|
Pi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):
|
||||||
|
- Main documentation: /Users/sia/.nvm/versions/node/v24.16.0/lib/node_modules/@earendil-works/pi-coding-agent/README.md
|
||||||
|
- Additional docs: /Users/sia/.nvm/versions/node/v24.16.0/lib/node_modules/@earendil-works/pi-coding-agent/docs
|
||||||
|
- Examples: /Users/sia/.nvm/versions/node/v24.16.0/lib/node_modules/@earendil-works/pi-coding-agent/examples (extensions, custom tools, SDK)
|
||||||
|
- When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory
|
||||||
|
- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md)
|
||||||
|
- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing
|
||||||
|
- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)
|
||||||
|
Current working directory: /Users/sia/code/my-pi
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import test from "node:test";
|
||||||
|
|
||||||
|
import toolRoutingExtension, {
|
||||||
|
appendToolRouting,
|
||||||
|
buildToolRoutingSection,
|
||||||
|
getSystemPromptDumpPath,
|
||||||
|
} from "../extensions/tool-routing.ts";
|
||||||
|
|
||||||
|
test("search routing narrows files before requesting matching line numbers", () => {
|
||||||
|
const section = buildToolRoutingSection(["find", "grep", "read"]);
|
||||||
|
|
||||||
|
assert.match(section, /Use find to identify likely files or directories/);
|
||||||
|
assert.match(section, /Use grep or multi_grep only inside the narrowed path or file/);
|
||||||
|
assert.match(section, /obtain matching line numbers/);
|
||||||
|
assert.match(section, /narrow the path, glob, or pattern instead of increasing the limit/);
|
||||||
|
assert.match(section, /Use read with offset\/limit only for the exact matching region/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("routing includes only guidance for active optional tools", () => {
|
||||||
|
const section = buildToolRoutingSection(["read"]);
|
||||||
|
|
||||||
|
assert.doesNotMatch(section, /codegraph_explore first/);
|
||||||
|
assert.doesNotMatch(section, /For literal search/);
|
||||||
|
assert.doesNotMatch(section, /Use Context Mode/);
|
||||||
|
assert.match(section, /Use read directly/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("routing is appended once", () => {
|
||||||
|
const once = appendToolRouting("base prompt", ["find", "grep"]);
|
||||||
|
const twice = appendToolRouting(once, ["find", "grep"]);
|
||||||
|
|
||||||
|
assert.equal(twice, once);
|
||||||
|
assert.equal((once.match(/<!-- my-pi-tool-routing -->/g) ?? []).length, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("dump path stays under the current project", () => {
|
||||||
|
assert.equal(
|
||||||
|
getSystemPromptDumpPath("/workspace/project"),
|
||||||
|
"/workspace/project/.pi-debug/effective-system-prompt.md",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("dump-system-prompt writes the last routed prompt seen by the extension", async () => {
|
||||||
|
let beforeAgentStart: ((event: any) => { systemPrompt: string }) | undefined;
|
||||||
|
let command: { handler: (args: string, ctx: any) => Promise<void> } | undefined;
|
||||||
|
const pi = {
|
||||||
|
on(name: string, handler: typeof beforeAgentStart) {
|
||||||
|
if (name === "before_agent_start") beforeAgentStart = handler;
|
||||||
|
},
|
||||||
|
registerCommand(_name: string, definition: typeof command) {
|
||||||
|
command = definition;
|
||||||
|
},
|
||||||
|
} as unknown as ExtensionAPI;
|
||||||
|
toolRoutingExtension(pi);
|
||||||
|
assert.ok(beforeAgentStart);
|
||||||
|
assert.ok(command);
|
||||||
|
beforeAgentStart({
|
||||||
|
systemPrompt: "prompt already modified by an earlier extension",
|
||||||
|
systemPromptOptions: { selectedTools: ["find", "grep"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
const cwd = await mkdtemp(join(tmpdir(), "my-pi-tool-routing-"));
|
||||||
|
try {
|
||||||
|
let notification = "";
|
||||||
|
await command.handler("", {
|
||||||
|
cwd,
|
||||||
|
getSystemPrompt: () => "base prompt",
|
||||||
|
getSystemPromptOptions: () => ({ selectedTools: ["find", "grep"] }),
|
||||||
|
ui: {
|
||||||
|
notify(message: string) {
|
||||||
|
notification = message;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const outputPath = getSystemPromptDumpPath(cwd);
|
||||||
|
const dumped = await readFile(outputPath, "utf8");
|
||||||
|
assert.match(dumped, /^prompt already modified by an earlier extension/);
|
||||||
|
assert.match(dumped, /<!-- my-pi-tool-routing -->/);
|
||||||
|
assert.match(notification, new RegExp(outputPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
|
||||||
|
} finally {
|
||||||
|
await rm(cwd, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user