feat: 组合包配置以包内 config/ 为唯一来源,并新增受保护写入人工审批

配置统一:权限策略、硬防御、Tool Search、提示词封面以及新迁入的
RTK、pi-compaction、pi-worktree、pi-hermes-memory 配置全部由扩展
直接读取已安装组合包内的 config/,pi install / pi update 即完成部署;
删除 rebuild-bundle-config.mjs 与 bundle-manifest.json,my-pi/ 只保留
日志与缓存。update.sh 成功升级后将默认 git 来源的已安装副本
reset 回发布版本。AGENTS.md 新增「组合包配置原则」。

脚本整合:search_config.sh / ssh_config.sh 合并为 configure.sh
search|ssh;install.sh / update.sh 共享函数抽到 scripts/lib.sh,远程
安装器改为先下载到临时文件再执行,下载失败可被检测。

权限:hard-guards 新增 protectedWrites,写入 Pi 凭据/设置、已安装
组合包与扩展目录、pi-ssh 凭据库时一律人工确认(跳过 AutoReview、
yolo 与 Session grant,无 UI 时拒绝);放行 ls、LSP 查询、ctx 只读、
web_search、Chrome 只读与 git 只读命令,skill_manage 改为 ask。

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
云服务部-叶林立
2026-10-20 01:05:31 -07:00
co-authored by Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent a0ee9389c7
commit 2aa1be0b54
105 changed files with 2337 additions and 1413 deletions
+2 -9
View File
@@ -106,16 +106,9 @@ Use ←/→ to switch tabs, ↑/↓ to navigate settings in the active tab, type
## Configuration
Configuration is stored at:
Configuration is read from — and `/rtk` saves to — the installed bundle's `config/rtk-optimizer.json` (the bundle repository's `config/` directory is the single source of truth; `pi update` refreshes the installed copy). Nothing is deployed to or migrated from the agent directory.
```text
Default global path: ~/.pi/agent/my-pi/rtk-optimizer/config.json
Actual global path: $PI_CODING_AGENT_DIR/my-pi/rtk-optimizer/config.json when PI_CODING_AGENT_DIR is set
```
A starter template is included at `config/config.example.json`.
For audit or debugging sessions, keep `showRewriteNotifications` enabled and disable lossy `read` compaction/source filtering before gathering evidence. Existing `config.json` files are user-owned runtime state; do not overwrite local choices unless you intentionally want to change live extension behavior.
For audit or debugging sessions, keep `showRewriteNotifications` enabled and disable lossy `read` compaction/source filtering before gathering evidence. Edit `config/rtk-optimizer.json` in the bundle repository for durable changes; `pi update` overwrites the installed copy on upgrade.
### Configuration Options
+5 -5
View File
@@ -1,6 +1,6 @@
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
import { dirname } from "node:path";
import { CONFIG_PATH } from "./constants.js";
import { resolveConfigPath } from "./constants.js";
import { toRecord } from "./record-utils.js";
import {
DEFAULT_RTK_INTEGRATION_CONFIG,
@@ -151,7 +151,7 @@ export function normalizeRtkIntegrationConfig(raw: unknown): RtkIntegrationConfi
};
}
export function ensureConfigExists(configPath = CONFIG_PATH): EnsureConfigResult {
export function ensureConfigExists(configPath = resolveConfigPath()): EnsureConfigResult {
if (existsSync(configPath)) {
return { created: false };
}
@@ -169,7 +169,7 @@ export function ensureConfigExists(configPath = CONFIG_PATH): EnsureConfigResult
}
}
export function loadRtkIntegrationConfig(configPath = CONFIG_PATH): ConfigLoadResult {
export function loadRtkIntegrationConfig(configPath = resolveConfigPath()): ConfigLoadResult {
if (!existsSync(configPath)) {
return { config: structuredClone(DEFAULT_RTK_INTEGRATION_CONFIG) };
}
@@ -189,7 +189,7 @@ export function loadRtkIntegrationConfig(configPath = CONFIG_PATH): ConfigLoadRe
export function saveRtkIntegrationConfig(
config: RtkIntegrationConfig,
configPath = CONFIG_PATH,
configPath = resolveConfigPath(),
): ConfigSaveResult {
const normalized = normalizeRtkIntegrationConfig(config);
const tmpPath = `${configPath}.tmp`;
@@ -218,6 +218,6 @@ export function saveRtkIntegrationConfig(
}
}
export function getRtkIntegrationConfigPath(configPath = CONFIG_PATH): string {
export function getRtkIntegrationConfigPath(configPath = resolveConfigPath()): string {
return configPath;
}
+17 -4
View File
@@ -1,6 +1,19 @@
import { getAgentDir } from "@earendil-works/pi-coding-agent";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
export const EXTENSION_NAME = "pi-rtk-optimizer";
export const CONFIG_DIR = join(getAgentDir(), "my-pi", "rtk-optimizer");
export const CONFIG_PATH = join(CONFIG_DIR, "config.json");
// Bundle-level `config/` is the single source of truth: the extension reads
// (and /rtk save writes) `config/rtk-optimizer.json` inside the installed
// bundle, resolved relative to this source file. Nothing is deployed to or
// migrated from the agent directory.
export const CONFIG_PATH = fileURLToPath(
new URL("../../config/rtk-optimizer.json", import.meta.url),
);
/**
* Resolve the effective config path. `PI_RTK_CONFIG_PATH` relocates the file
* (tests point it at a temp file; it is never a persisted config value).
*/
export function resolveConfigPath(): string {
return process.env.PI_RTK_CONFIG_PATH ?? CONFIG_PATH;
}
+12 -5
View File
@@ -1,6 +1,7 @@
import assert from "node:assert/strict";
import { mkdirSync, writeFileSync } from "node:fs";
import { dirname } from "node:path";
import { mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { mock, runTest } from "./test-helpers.test.ts";
@@ -37,12 +38,18 @@ const indexModule = await import("./index.ts");
const { createBoundedNoticeTracker, shouldInjectSourceFilterTroubleshootingNote, injectGuidelineIntoPrompt } = indexModule;
const rtkIntegrationExtension = indexModule.default;
const { DEFAULT_RTK_INTEGRATION_CONFIG } = await import("./types.ts");
const { CONFIG_PATH } = await import("./constants.ts");
// Tests must never write the bundle's config/ file: relocate the config to a
// throwaway temp file before any config-store call resolves its path.
const TEST_CONFIG_PATH = join(
mkdtempSync(join(tmpdir(), "my-pi-rtk-test-")),
"rtk-optimizer.json",
);
process.env.PI_RTK_CONFIG_PATH = TEST_CONFIG_PATH;
function writeTestConfig(commandRewritingEnabled: boolean): void {
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
writeFileSync(
CONFIG_PATH,
TEST_CONFIG_PATH,
`${JSON.stringify({ ...DEFAULT_RTK_INTEGRATION_CONFIG, commandRewritingEnabled }, null, 2)}\n`,
"utf-8",
);