@trim21/personal-pi-extensions 0.1.460 → 0.1.465

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.
@@ -1,155 +0,0 @@
1
- /**
2
- * aft_refactor —— workspace-wide refactoring(move / extract / inline)。
3
- *
4
- * 参数经 bridge.toolCall 以 agent 工具名 "refactor" 分派,Rust 侧 subc 翻译层
5
- * 按 op 转成内部命令(move_symbol / extract_function / inline_symbol)。
6
- * 这些命令不支持 preview,写保护退化为路径级审批(workspace 内自动放行,
7
- * 外部路径经 write-guard 确认,无 diff 预览)。
8
- */
9
-
10
- import { readFileSync } from "node:fs";
11
- import { fileURLToPath } from "node:url";
12
-
13
- import { coerceOptionalInt } from "@cortexkit/aft-bridge";
14
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
15
- import { Type } from "typebox";
16
-
17
- import { type ToolPendant } from "../lib/pendant.js";
18
- import { guardWriteAccess } from "../lib/write-guard.js";
19
- import { callAftTool } from "./bridge.js";
20
- import {
21
- type AftToolContext,
22
- bridgeFor,
23
- buildPendantMarkdown,
24
- compactArgs,
25
- resolvePathArg,
26
- } from "./tools.js";
27
-
28
- /** 工具使用指南,以 markdown 形式维护,读起来像文档。 */
29
- const REFACTOR_PROMPT = readFileSync(
30
- fileURLToPath(new URL("refactor.md", import.meta.url)),
31
- "utf8",
32
- ).trim();
33
-
34
- const REFACTOR_OPS = ["move", "extract", "inline"] as const;
35
-
36
- function requireField(value: unknown, name: string, op: string): void {
37
- if (typeof value !== "string" || value.trim().length === 0) {
38
- throw new Error(`'${name}' is required for '${op}' op`);
39
- }
40
- }
41
-
42
- const RefactorParams = Type.Object(
43
- {
44
- op: Type.Union(
45
- REFACTOR_OPS.map((op) => Type.Literal(op)),
46
- { description: "重构操作" },
47
- ),
48
- path: Type.String({
49
- description: "源文件路径(绝对或相对项目根;move 为符号当前所在文件)",
50
- }),
51
- symbol: Type.Optional(Type.String({ description: "符号名(move / inline 必填)" })),
52
- destination: Type.Optional(Type.String({ description: "目标文件(move 必填)" })),
53
- scope: Type.Optional(Type.String({ description: "move 消歧作用域" })),
54
- name: Type.Optional(Type.String({ description: "新函数名(extract 必填)" })),
55
- start_line: Type.Optional(
56
- Type.Union([Type.Number(), Type.String()], {
57
- description: "extract 起始行(1 起,必填)",
58
- }),
59
- ),
60
- end_line: Type.Optional(
61
- Type.Union([Type.Number(), Type.String()], {
62
- description: "extract 结束行(含,必填)",
63
- }),
64
- ),
65
- call_site_line: Type.Optional(
66
- Type.Union([Type.Number(), Type.String()], {
67
- description: "inline 调用点行号(1 起,必填)",
68
- }),
69
- ),
70
- },
71
- { additionalProperties: false },
72
- );
73
-
74
- export function registerRefactorTool(pi: ExtensionAPI, ctx: AftToolContext): void {
75
- pi.registerTool({
76
- name: "aft_refactor",
77
- label: "aft_refactor",
78
- description: [
79
- "workspace-wide 重构:更新跨文件的 import 与引用。",
80
- "move:把顶层符号(非嵌套函数/类方法)移到另一文件,全 workspace 重写 import。",
81
- "extract:把行区间抽成新函数(TS/JS/TSX、Python)。",
82
- "inline:把调用点替换为函数体。",
83
- ].join("\n"),
84
- promptSnippet: "Workspace-wide symbol move / function extraction / inlining",
85
- promptGuidelines: [REFACTOR_PROMPT],
86
- parameters: RefactorParams,
87
- async execute(_id, params, _signal, _onUpdate, extCtx) {
88
- const startLine = coerceOptionalInt(
89
- params.start_line,
90
- "start_line",
91
- 1,
92
- Number.MAX_SAFE_INTEGER,
93
- );
94
- const endLine = coerceOptionalInt(params.end_line, "end_line", 1, Number.MAX_SAFE_INTEGER);
95
- const callSiteLine = coerceOptionalInt(
96
- params.call_site_line,
97
- "call_site_line",
98
- 1,
99
- Number.MAX_SAFE_INTEGER,
100
- );
101
-
102
- if (params.op === "move") {
103
- requireField(params.symbol, "symbol", "move");
104
- requireField(params.destination, "destination", "move");
105
- } else if (params.op === "extract") {
106
- requireField(params.name, "name", "extract");
107
- if (startLine === undefined) throw new Error("'start_line' is required for 'extract' op");
108
- if (endLine === undefined) throw new Error("'end_line' is required for 'extract' op");
109
- } else {
110
- requireField(params.symbol, "symbol", "inline");
111
- if (callSiteLine === undefined) {
112
- throw new Error("'call_site_line' is required for 'inline' op");
113
- }
114
- }
115
-
116
- const filePath = resolvePathArg(extCtx.cwd, params.path);
117
- const destination =
118
- params.destination === undefined || params.destination.trim() === ""
119
- ? undefined
120
- : resolvePathArg(extCtx.cwd, params.destination);
121
-
122
- const targets = destination === undefined ? [filePath] : [filePath, destination];
123
- for (const target of targets) {
124
- await guardWriteAccess(extCtx, { toolName: "aft_refactor", absolutePath: target });
125
- }
126
-
127
- const rawArgs = compactArgs({
128
- op: params.op,
129
- path: filePath,
130
- symbol: params.symbol,
131
- destination,
132
- scope: params.scope,
133
- name: params.name,
134
- startLine,
135
- endLine,
136
- callSiteLine,
137
- });
138
-
139
- const { text } = await callAftTool(bridgeFor(ctx), "refactor", rawArgs, extCtx);
140
- return {
141
- content: [{ type: "text", text }],
142
- details: {
143
- files: targets,
144
- pendant: {
145
- markdown: buildPendantMarkdown({
146
- title: "aft_refactor",
147
- input: params,
148
- output: text,
149
- }),
150
- } satisfies ToolPendant,
151
- },
152
- };
153
- },
154
- });
155
- }