Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e33c50754c | ||
|
|
776f31fb47 | ||
|
|
1b47f33a7e |
@@ -8,7 +8,7 @@
|
||||
- **渐进式披露**:初始仅激活一个 `siyuan_discover` loader 工具(含连通性检查),其余 15 个工具按需增量加载,保持系统提示词前缀稳定
|
||||
- **笔记本级 RWD 权限审计**:R 读 / W 写 / D 破坏性(rollback、move 移出、删除类),可自由组合;`NONE` = 禁止一切操作
|
||||
- 拒绝消息包含:目标笔记本(id+name)、需要的权限、缺失的权限、被拒绝的操作名
|
||||
- 新笔记本自动以 `R` 权限同步进配置文件(发现入口 `list_notebooks`,审计豁免)
|
||||
- Pi 启动及调用 `list_notebooks` 时自动同步笔记本;新笔记本以 `R` 权限写入配置文件(审计豁免)
|
||||
- 连接信息:环境变量优先,配置文件兜底
|
||||
|
||||
## 安装
|
||||
@@ -33,7 +33,7 @@ pi -e git:git.ipao.vip:rogee/pi-siyuan
|
||||
|
||||
```bash
|
||||
git clone git@git.ipao.vip:rogee/pi-siyuan.git ~/.pi/agent/extensions/pi-siyuan
|
||||
# src/ 内含 index.ts,pi 会自动加载 extensions/*/index.ts
|
||||
# 包根目录含 index.ts,pi 会自动加载 extensions/*/index.ts
|
||||
```
|
||||
|
||||
发布流程:推送 tag(如 `v0.1.0`)触发 Gitea workflow 自动发布到 npm(`.gitea/workflows/publish-npm.yml`,使用仓库 secret `NPM_PACKAGE_TOKEN`)。
|
||||
@@ -48,7 +48,7 @@ export SIYUAN_API_URL="https://your-siyuan-host" # 默认 http://127.0.0.1:680
|
||||
export SIYUAN_TOKEN="your-api-token" # SiYuan 设置 → 关于 → API token
|
||||
```
|
||||
|
||||
缺失时回落到 `~/.pi/agent/extensions/pi-siyuan/config.json`:
|
||||
修改 `~/.zshenv` 后需新开 shell 并重启 Pi(已有进程不会自动获得新环境变量)。缺失时回落到 `~/.pi/agent/extensions/pi-siyuan/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -64,7 +64,7 @@ export SIYUAN_TOKEN="your-api-token" # SiYuan 设置 → 关于
|
||||
|
||||
- `permissions`:`R`/`W`/`D` 自由组合,或 `["NONE"]`(禁止一切操作)
|
||||
- `name` 仅做 human-readable,一切逻辑按 `id` 匹配
|
||||
- 首次调用 `list_notebooks` 会把未记录的笔记本以 `["R"]` 补写进该文件
|
||||
- Pi 启动时会创建该配置文件并同步笔记本;调用 `list_notebooks` 时也会再次同步。未记录的笔记本以 `["R"]` 补写,已有笔记本名称变化时更新 `name`
|
||||
|
||||
### 权限规则速查
|
||||
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "pi-siyuan",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pi-siyuan",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"typebox": "1.3.7"
|
||||
|
||||
+6
-5
@@ -5,8 +5,8 @@
|
||||
"dependencies": {
|
||||
"typebox": "1.3.7"
|
||||
},
|
||||
"version": "0.1.0",
|
||||
"description": "SiYuan Note extension for pi coding agent \u2014 HTTP API wrapper with notebook-level RWD permission auditing",
|
||||
"version": "0.1.3",
|
||||
"description": "SiYuan Note extension for pi coding agent — HTTP API wrapper with notebook-level RWD permission auditing",
|
||||
"keywords": [
|
||||
"pi-package",
|
||||
"pi-extension",
|
||||
@@ -20,14 +20,15 @@
|
||||
},
|
||||
"pi": {
|
||||
"extensions": [
|
||||
"./src"
|
||||
"./index.ts"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@earendil-works/pi-coding-agent": "0.84.4"
|
||||
},
|
||||
"main": "src/index.ts",
|
||||
"main": "index.ts",
|
||||
"files": [
|
||||
"index.ts",
|
||||
"src",
|
||||
"README.md",
|
||||
"LICENSE",
|
||||
@@ -39,4 +40,4 @@
|
||||
"check": "node --experimental-strip-types --no-warnings src/audit.test.ts"
|
||||
},
|
||||
"prepublishOnly": "node --experimental-strip-types --no-warnings src/audit.test.ts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
*/
|
||||
|
||||
import assert from "node:assert";
|
||||
import { existsSync, rmSync } from "node:fs";
|
||||
import {
|
||||
permsOf,
|
||||
auditNotebook,
|
||||
auditAny,
|
||||
auditAll,
|
||||
denyMessage,
|
||||
loadConfig,
|
||||
syncNotebooks,
|
||||
} from "./audit.ts";
|
||||
|
||||
@@ -87,6 +89,19 @@ assert.ok(
|
||||
assert.ok(msg.includes("get_document_content"), "含操作名");
|
||||
assert.ok(/需要 R/.test(msg) && /缺失 R/.test(msg), "含需要/缺失权限");
|
||||
|
||||
// ---- 配置首次加载自动初始化 ----
|
||||
const initDir = "/tmp/pi-siyuan-audit-test";
|
||||
const initPath = `${initDir}/nested/config.json`;
|
||||
rmSync(initDir, { recursive: true, force: true });
|
||||
const initialized = loadConfig(initPath);
|
||||
assert.equal(existsSync(initPath), true, "配置文件应在首次加载时创建");
|
||||
assert.deepEqual(initialized, {
|
||||
apiUrl: "http://127.0.0.1:6806",
|
||||
token: "",
|
||||
notebooks: [],
|
||||
});
|
||||
rmSync(initDir, { recursive: true, force: true });
|
||||
|
||||
// ---- syncNotebooks(第 10 条)— 用临时路径,不污染真实配置 ----
|
||||
const cfg: any = {
|
||||
apiUrl: "u",
|
||||
|
||||
+9
-5
@@ -5,7 +5,7 @@
|
||||
|
||||
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { dirname, join } from "node:path";
|
||||
import type { SiYuanClient } from "./siyuan-client.ts";
|
||||
|
||||
export type Perm = "R" | "W" | "D";
|
||||
@@ -86,7 +86,13 @@ export function loadConfig(cfgPath: string = CONFIG_PATH): PiSiyuanConfig {
|
||||
// 损坏则重建
|
||||
}
|
||||
}
|
||||
return { apiUrl: "", token: "", notebooks: [] };
|
||||
const cfg = {
|
||||
apiUrl: "http://127.0.0.1:6806",
|
||||
token: "",
|
||||
notebooks: [],
|
||||
};
|
||||
saveConfig(cfg, cfgPath);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
export function resolveConnection(): { apiUrl: string; token: string } {
|
||||
@@ -121,9 +127,7 @@ export function syncNotebooks(
|
||||
}
|
||||
|
||||
export function saveConfig(cfg: PiSiyuanConfig, cfgPath: string = CONFIG_PATH) {
|
||||
mkdirSync(join(homedir(), ".pi/agent/extensions/pi-siyuan"), {
|
||||
recursive: true,
|
||||
});
|
||||
mkdirSync(dirname(cfgPath), { recursive: true });
|
||||
writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n");
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -422,11 +422,16 @@ export default function siyuanExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// 初始只激活 loader(渐进式披露)
|
||||
pi.on("session_start", () => {
|
||||
// 初始只激活 loader(渐进式披露),并同步笔记本权限配置
|
||||
pi.on("session_start", async () => {
|
||||
const initial = pi
|
||||
.getActiveTools()
|
||||
.filter((name) => !SIYUAN_TOOL_NAMES.has(name));
|
||||
pi.setActiveTools([...new Set([...initial, "siyuan_discover"])]);
|
||||
try {
|
||||
syncNotebooks(cfg, await client.lsNotebooks());
|
||||
} catch {
|
||||
// SiYuan 离线不应阻止 Pi 启动;工具调用时会返回连接错误
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user