@trim21/personal-pi-extensions 0.1.664 → 0.1.669
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/package.json +3 -3
- package/src/aft/index.ts +14 -7
- package/src/aft/tools.ts +3 -3
- package/src/codemode/tool.ts +7 -3
- package/src/spawn-agent.ts +19 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trim21/personal-pi-extensions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.669",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
|
|
6
6
|
"keywords": [
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"node": ">=24.14"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
-
"@cortexkit/aft-bridge": "0.58.
|
|
91
|
+
"@cortexkit/aft-bridge": "0.58.2",
|
|
92
92
|
"@mozilla/readability": "^0.6.0",
|
|
93
93
|
"@parcel/watcher": "^2.6.0",
|
|
94
94
|
"@vscode/tree-sitter-wasm": "^0.3.1",
|
|
@@ -105,6 +105,6 @@
|
|
|
105
105
|
"web-tree-sitter": "^0.27.0"
|
|
106
106
|
},
|
|
107
107
|
"optionalDependencies": {
|
|
108
|
-
"@cortexkit/aft-linux-x64": "0.58.
|
|
108
|
+
"@cortexkit/aft-linux-x64": "0.58.2"
|
|
109
109
|
}
|
|
110
110
|
}
|
package/src/aft/index.ts
CHANGED
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* openai_compatible / ollama 且有 base_url)时注册;aft 默认的本地 ONNX
|
|
9
9
|
* fastembed 后端不使用。
|
|
10
10
|
*
|
|
11
|
+
* 项目根是**会话工作目录**(`session_start` 的 `ctx.cwd`),不是 pi 进程的启动
|
|
12
|
+
* 目录:引擎按项目根建索引与调用图存储,用错会把用户家目录当项目根并自动关闭这
|
|
13
|
+
* 些能力。扩展自己只读用户级 aft.jsonc(路径与会话目录无关),项目级 aft.jsonc
|
|
14
|
+
* 由 bridge 按项目根自行读取。
|
|
15
|
+
*
|
|
11
16
|
* bridge 状态(日志 + 常驻 aft 子进程)的生命周期跟 session 走:session_start
|
|
12
17
|
* 时先解析 aft 二进制(含 GitHub release auto-download 兜底)——找不到就
|
|
13
18
|
* notify warning 且不注册任何 aft 工具,避免模型看到只会抛 "not initialized"
|
|
@@ -19,7 +24,7 @@
|
|
|
19
24
|
* pi -e ./aft/index.ts
|
|
20
25
|
*/
|
|
21
26
|
|
|
22
|
-
import {
|
|
27
|
+
import { resolveCortexKitUserConfigPath } from "@cortexkit/aft-bridge";
|
|
23
28
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
24
29
|
|
|
25
30
|
import type { ToolBus } from "../lib/tool-bus.js";
|
|
@@ -27,6 +32,7 @@ import { registerToolsOnSessionStart } from "../lib/tool-registration.js";
|
|
|
27
32
|
import { createAftState, findBinary, resolveSessionId, shutdownAftPool } from "./bridge.js";
|
|
28
33
|
import { loadAftConfig } from "./config.js";
|
|
29
34
|
import {
|
|
35
|
+
type AftToolContext,
|
|
30
36
|
registerCallgraphTool,
|
|
31
37
|
registerOutlineTool,
|
|
32
38
|
registerSearchTool,
|
|
@@ -35,14 +41,15 @@ import {
|
|
|
35
41
|
|
|
36
42
|
/**
|
|
37
43
|
* aft 工具集:入口用它。`registerForSession` 必须在会话启动时调用——二进制
|
|
38
|
-
* 探测、semantic_search 的提示、bridge
|
|
39
|
-
*
|
|
44
|
+
* 探测、semantic_search 的提示、bridge 状态(项目根 = 本会话的 `ctx.cwd`)的
|
|
45
|
+
* 创建都在里面;找不到二进制就不注册任何工具(避免模型看到只会抛
|
|
46
|
+
* "not initialized" 的死工具)。
|
|
40
47
|
*/
|
|
41
48
|
export function createAftTools(pi: ExtensionAPI): {
|
|
42
49
|
registerForSession(bus: ToolBus, ctx: ExtensionContext): Promise<void>;
|
|
43
50
|
} {
|
|
44
|
-
|
|
45
|
-
const cfg = loadAftConfig(
|
|
51
|
+
// 扩展自己的门控只读用户级配置:项目级 aft.jsonc 由 bridge 按会话工作目录读。
|
|
52
|
+
const cfg = loadAftConfig(resolveCortexKitUserConfigPath());
|
|
46
53
|
// bridge 状态跟 session 生命周期走,作用域就是本工厂闭包,不落到模块级。
|
|
47
54
|
let state: Awaited<ReturnType<typeof createAftState>> | null = null;
|
|
48
55
|
|
|
@@ -55,7 +62,7 @@ export function createAftTools(pi: ExtensionAPI): {
|
|
|
55
62
|
return state;
|
|
56
63
|
};
|
|
57
64
|
|
|
58
|
-
const toolCtx = {
|
|
65
|
+
const toolCtx: AftToolContext = { getState };
|
|
59
66
|
|
|
60
67
|
async function registerForSession(bus: ToolBus, ctx: ExtensionContext): Promise<void> {
|
|
61
68
|
if (!cfg.enabled) {
|
|
@@ -91,7 +98,7 @@ export function createAftTools(pi: ExtensionAPI): {
|
|
|
91
98
|
registerSearchTool(bus, toolCtx);
|
|
92
99
|
}
|
|
93
100
|
|
|
94
|
-
state = await createAftState(cwd, resolveSessionId(ctx), binaryPath, cfg.semanticRemote);
|
|
101
|
+
state = await createAftState(ctx.cwd, resolveSessionId(ctx), binaryPath, cfg.semanticRemote);
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
// 释放当前 session 的 bridge 状态。session_shutdown 是 pi 的正常生命周期;
|
package/src/aft/tools.ts
CHANGED
|
@@ -57,13 +57,13 @@ const AFT_GUIDELINES = readFileSync(
|
|
|
57
57
|
).trim();
|
|
58
58
|
|
|
59
59
|
export interface AftToolContext {
|
|
60
|
-
cwd: string;
|
|
61
60
|
/** 当前 session 的 bridge 状态;session 未初始化时抛错。 */
|
|
62
61
|
getState(): AftState;
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
function bridgeFor(ctx: AftToolContext): AftProjectTransport {
|
|
66
|
-
|
|
65
|
+
const { pool } = ctx.getState();
|
|
66
|
+
return pool.pool.getBridge(pool.projectRoot);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
@@ -152,7 +152,7 @@ export function registerOutlineTool(bus: ToolBus, ctx: AftToolContext): void {
|
|
|
152
152
|
filesMode = stats?.isDirectory() ?? false;
|
|
153
153
|
}
|
|
154
154
|
const rawArgs = compactArgs({
|
|
155
|
-
target:
|
|
155
|
+
target: resolved,
|
|
156
156
|
files: filesMode || undefined,
|
|
157
157
|
includeTests: params.includeTests,
|
|
158
158
|
});
|
package/src/codemode/tool.ts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* 的能力是调用 `tools.*`——每个嵌套调用都由主线程经本仓库的工具总线执行,因此工具实现
|
|
4
4
|
* 内部的审批(工作区外写入、Bash 沙箱提权等)照常生效;codemode 不再加自己的确认层。
|
|
5
5
|
*
|
|
6
|
-
* 可调用集合:总线上实际注册的工具减去 codemode
|
|
7
|
-
* pi 自己的 `defaultTools` / `--tools` / 子代理白名单的排除因此同样生效。
|
|
6
|
+
* 可调用集合:总线上实际注册的工具减去 codemode 自身与 spawn-agent,执行时再与 active
|
|
7
|
+
* 列表求交——pi 自己的 `defaultTools` / `--tools` / 子代理白名单的排除因此同样生效。
|
|
8
|
+
* spawn-agent 被排除是因为它启动一个新的隔离会话、成本与运行时长都不适合放进脚本编排。
|
|
8
9
|
*
|
|
9
10
|
* wasm 在注册这个工具时编译一次(`createCodemodeSandbox`),worker 复用编译结果。
|
|
10
11
|
*/
|
|
@@ -26,6 +27,9 @@ import { CODEMODE_SOURCE_GRAMMAR, DEFAULT_OUTPUT_TOKENS, parseCodemodeSource } f
|
|
|
26
27
|
|
|
27
28
|
export const CODEMODE_TOOL_NAME = "codemode";
|
|
28
29
|
|
|
30
|
+
/** 不暴露给脚本的工具:codemode 自身(防递归)与 spawn-agent(见文件头注释)。 */
|
|
31
|
+
const EXCLUDED_TOOL_NAMES: ReadonlySet<string> = new Set([CODEMODE_TOOL_NAME, "spawn-agent"]);
|
|
32
|
+
|
|
29
33
|
/** 估计 token 用的字符数(与 pi 一致)。 */
|
|
30
34
|
const CHARS_PER_TOKEN = 4;
|
|
31
35
|
|
|
@@ -56,7 +60,7 @@ function allowedToolNames(pi: ExtensionAPI): Set<string> | undefined {
|
|
|
56
60
|
function collectTools(bus: ToolBus, allowed: Set<string> | undefined): CallableTool[] {
|
|
57
61
|
return bus
|
|
58
62
|
.list()
|
|
59
|
-
.filter((definition) => definition.name
|
|
63
|
+
.filter((definition) => !EXCLUDED_TOOL_NAMES.has(definition.name))
|
|
60
64
|
.filter((definition) => allowed === undefined || allowed.has(definition.name))
|
|
61
65
|
.map((definition) => ({
|
|
62
66
|
name: definition.name,
|
package/src/spawn-agent.ts
CHANGED
|
@@ -131,7 +131,10 @@ const spawnAgentSchema = Type.Object({
|
|
|
131
131
|
description:
|
|
132
132
|
"Name of the subagent type to invoke. Choose one of the available subagent types listed in your system prompt.",
|
|
133
133
|
}),
|
|
134
|
-
task: Type.String({
|
|
134
|
+
task: Type.String({
|
|
135
|
+
description:
|
|
136
|
+
"Self-contained task for the subagent, which sees none of this conversation: state the repository path, the exact question, and what the answer must contain (file paths with line numbers).",
|
|
137
|
+
}),
|
|
135
138
|
});
|
|
136
139
|
|
|
137
140
|
// ── result types ─────────────────────────────────────────────────────────────
|
|
@@ -499,9 +502,19 @@ export async function runAgent(
|
|
|
499
502
|
export function formatAgentListSection(agents: AgentConfig[]): string {
|
|
500
503
|
const lines = agents.map((a) => `- \`${a.name}\`: ${a.description}`);
|
|
501
504
|
return [
|
|
505
|
+
"### Delegating to subagents",
|
|
506
|
+
"",
|
|
507
|
+
"Delegate a focused, read-only research task when the answer is a summary rather than source you must quote or edit:",
|
|
508
|
+
"",
|
|
509
|
+
"- locating code whose position is unknown, or answering a question that spans several files;",
|
|
510
|
+
"- several independent lookups at once — issue one `spawn-agent` call per lookup in the same message and they run concurrently;",
|
|
511
|
+
"- keeping the searching and reading out of your own context window.",
|
|
512
|
+
"",
|
|
513
|
+
"Do not delegate work you are about to do yourself — a single file you will edit, a change whose evidence must be the exact source text, or anything that writes. A subagent sees none of this conversation, so its task must be self-contained. Treat its answer as a pointer and read the location it names before acting on it.",
|
|
514
|
+
"",
|
|
502
515
|
"### Available subagents",
|
|
503
516
|
"",
|
|
504
|
-
"
|
|
517
|
+
"Pass one of these names as the `agent` parameter:",
|
|
505
518
|
"",
|
|
506
519
|
...lines,
|
|
507
520
|
].join("\n");
|
|
@@ -526,9 +539,11 @@ export function createSpawnAgentTool(): { register(bus: ToolBus): void } {
|
|
|
526
539
|
bus.register<typeof spawnAgentSchema, SubagentDetails>({
|
|
527
540
|
name: "spawn-agent",
|
|
528
541
|
label: "spawn-agent",
|
|
542
|
+
promptSnippet: "Delegate focused research to a subagent with its own context window",
|
|
529
543
|
description: [
|
|
530
|
-
"Delegate a task to a subagent that runs in an isolated session with its own context window, inside this pi process rather than a separate one.",
|
|
531
|
-
"The call blocks until the subagent finishes its turn
|
|
544
|
+
"Delegate a self-contained research task to a subagent that runs in an isolated session with its own context window, inside this pi process rather than a separate one.",
|
|
545
|
+
"The call blocks until the subagent finishes its turn and returns only its final answer: its intermediate tool calls are not visible to you.",
|
|
546
|
+
"Several `spawn-agent` calls issued in the same message run concurrently.",
|
|
532
547
|
"The `agent` parameter must be one of the available subagent types listed in the system prompt.",
|
|
533
548
|
`Subagents run read-only (${DEFAULT_TOOLS.join(", ")}) unless the agent declares an explicit toolset.`,
|
|
534
549
|
].join(" "),
|