@aliou/pi-dev-kit 0.4.9 → 0.6.0
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/README.md +60 -0
- package/package.json +63 -2
- package/src/commands/index.ts +6 -0
- package/src/commands/update.ts +144 -0
- package/src/index.ts +8 -0
- package/src/prompts/setup-demo.md +35 -0
- package/src/skills/demo-setup/SKILL.md +217 -0
- package/src/skills/pi-extension/SKILL.md +154 -0
- package/src/skills/pi-extension/references/additional-apis.md +304 -0
- package/src/skills/pi-extension/references/commands.md +100 -0
- package/src/skills/pi-extension/references/components.md +166 -0
- package/src/skills/pi-extension/references/documentation.md +54 -0
- package/src/skills/pi-extension/references/hooks.md +244 -0
- package/src/skills/pi-extension/references/messages.md +169 -0
- package/src/skills/pi-extension/references/modes.md +156 -0
- package/src/skills/pi-extension/references/providers.md +134 -0
- package/src/skills/pi-extension/references/publish.md +139 -0
- package/src/skills/pi-extension/references/state.md +56 -0
- package/src/skills/pi-extension/references/structure.md +522 -0
- package/src/skills/pi-extension/references/testing.md +183 -0
- package/src/skills/pi-extension/references/tools.md +948 -0
- package/src/tools/changelog-tool.ts +484 -0
- package/src/tools/docs-tool.ts +181 -0
- package/src/tools/index.ts +12 -0
- package/src/tools/package-manager-tool.ts +194 -0
- package/src/tools/utils.ts +38 -0
- package/src/tools/version-tool.ts +70 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { ToolCallHeader } from "@aliou/pi-utils-ui";
|
|
4
|
+
import type {
|
|
5
|
+
AgentToolResult,
|
|
6
|
+
ExtensionAPI,
|
|
7
|
+
ExtensionContext,
|
|
8
|
+
Theme,
|
|
9
|
+
ToolRenderResultOptions,
|
|
10
|
+
} from "@mariozechner/pi-coding-agent";
|
|
11
|
+
import { Text } from "@mariozechner/pi-tui";
|
|
12
|
+
import { Type } from "@sinclair/typebox";
|
|
13
|
+
|
|
14
|
+
const Params = Type.Object({});
|
|
15
|
+
type PackageManagerParams = Record<string, never>;
|
|
16
|
+
|
|
17
|
+
interface PackageManagerDetails {
|
|
18
|
+
packageManager?: string;
|
|
19
|
+
version?: string;
|
|
20
|
+
lockfile?: string;
|
|
21
|
+
installCommand?: string;
|
|
22
|
+
runCommand?: string;
|
|
23
|
+
cwd?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const LOCKFILES: Record<string, string> = {
|
|
27
|
+
"pnpm-lock.yaml": "pnpm",
|
|
28
|
+
"yarn.lock": "yarn",
|
|
29
|
+
"package-lock.json": "npm",
|
|
30
|
+
"bun.lockb": "bun",
|
|
31
|
+
"bun.lock": "bun",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const COMMANDS: Record<string, { install: string; run: string }> = {
|
|
35
|
+
pnpm: { install: "pnpm install", run: "pnpm" },
|
|
36
|
+
yarn: { install: "yarn install", run: "yarn" },
|
|
37
|
+
npm: { install: "npm install", run: "npm run" },
|
|
38
|
+
bun: { install: "bun install", run: "bun run" },
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export function setupPackageManagerTool(pi: ExtensionAPI) {
|
|
42
|
+
pi.registerTool<typeof Params, PackageManagerDetails>({
|
|
43
|
+
name: "detect_package_manager",
|
|
44
|
+
label: "Package Manager",
|
|
45
|
+
description:
|
|
46
|
+
"Detect the package manager used in the current project by checking lockfiles and package.json",
|
|
47
|
+
promptSnippet: "Detect the package manager for this project",
|
|
48
|
+
promptGuidelines: [
|
|
49
|
+
"Use when you need to know which package manager (npm, yarn, pnpm, bun) the project uses",
|
|
50
|
+
"Helpful before running install commands or scripts",
|
|
51
|
+
],
|
|
52
|
+
|
|
53
|
+
parameters: Params,
|
|
54
|
+
|
|
55
|
+
async execute(
|
|
56
|
+
_toolCallId: string,
|
|
57
|
+
_params: PackageManagerParams,
|
|
58
|
+
_signal: AbortSignal | undefined,
|
|
59
|
+
_onUpdate: unknown,
|
|
60
|
+
ctx: ExtensionContext,
|
|
61
|
+
): Promise<AgentToolResult<PackageManagerDetails>> {
|
|
62
|
+
const cwd = ctx.cwd;
|
|
63
|
+
|
|
64
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
65
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
66
|
+
throw new Error(`No package.json found in ${cwd}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Walk up from cwd to repo root, collecting packageManager and lockfile.
|
|
70
|
+
// Stop at .git boundary to avoid escaping the repository.
|
|
71
|
+
let declaredPm: string | undefined;
|
|
72
|
+
let declaredVersion: string | undefined;
|
|
73
|
+
let lockfile: string | undefined;
|
|
74
|
+
let lockfilePm: string | undefined;
|
|
75
|
+
|
|
76
|
+
let searchDir = cwd;
|
|
77
|
+
while (true) {
|
|
78
|
+
// Check packageManager field in package.json
|
|
79
|
+
if (!declaredPm) {
|
|
80
|
+
const pkgPath = path.join(searchDir, "package.json");
|
|
81
|
+
try {
|
|
82
|
+
if (fs.existsSync(pkgPath)) {
|
|
83
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
84
|
+
if (typeof pkg.packageManager === "string") {
|
|
85
|
+
const match = pkg.packageManager.match(/^([^@]+)@?(.*)?$/);
|
|
86
|
+
if (match) {
|
|
87
|
+
declaredPm = match[1];
|
|
88
|
+
declaredVersion = match[2] || undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} catch {
|
|
93
|
+
// Ignore parse errors
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Check lockfiles
|
|
98
|
+
if (!lockfilePm) {
|
|
99
|
+
for (const [filename, pm] of Object.entries(LOCKFILES)) {
|
|
100
|
+
if (fs.existsSync(path.join(searchDir, filename))) {
|
|
101
|
+
lockfilePm = pm;
|
|
102
|
+
lockfile = filename;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Stop if we found both, hit .git, or hit filesystem root
|
|
109
|
+
if (
|
|
110
|
+
(declaredPm && lockfilePm) ||
|
|
111
|
+
fs.existsSync(path.join(searchDir, ".git"))
|
|
112
|
+
) {
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
const parent = path.dirname(searchDir);
|
|
116
|
+
if (parent === searchDir) break;
|
|
117
|
+
searchDir = parent;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const pm = declaredPm || lockfilePm || "npm";
|
|
121
|
+
const fallback = { install: `${pm} install`, run: pm };
|
|
122
|
+
const commands = COMMANDS[pm] ?? fallback;
|
|
123
|
+
|
|
124
|
+
const parts: string[] = [];
|
|
125
|
+
parts.push(`Package manager: ${pm}`);
|
|
126
|
+
if (declaredVersion) {
|
|
127
|
+
parts.push(`Declared version: ${declaredVersion}`);
|
|
128
|
+
}
|
|
129
|
+
if (lockfile) {
|
|
130
|
+
parts.push(`Lockfile: ${lockfile}`);
|
|
131
|
+
}
|
|
132
|
+
if (!lockfile && !declaredPm) {
|
|
133
|
+
parts.push(
|
|
134
|
+
"No lockfile or packageManager field found, defaulting to npm",
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
parts.push(`Install: ${commands.install}`);
|
|
138
|
+
parts.push(`Run: ${commands.run}`);
|
|
139
|
+
|
|
140
|
+
const message = parts.join("\n");
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
content: [{ type: "text", text: message }],
|
|
144
|
+
details: {
|
|
145
|
+
packageManager: pm,
|
|
146
|
+
version: declaredVersion,
|
|
147
|
+
lockfile,
|
|
148
|
+
installCommand: commands.install,
|
|
149
|
+
runCommand: commands.run,
|
|
150
|
+
cwd,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
renderCall(_args: PackageManagerParams, theme: Theme) {
|
|
156
|
+
return new ToolCallHeader({ toolName: "Detect Package Manager" }, theme);
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
renderResult(
|
|
160
|
+
result: AgentToolResult<PackageManagerDetails>,
|
|
161
|
+
_options: ToolRenderResultOptions,
|
|
162
|
+
theme: Theme,
|
|
163
|
+
): Text {
|
|
164
|
+
const { details } = result;
|
|
165
|
+
|
|
166
|
+
// Check for missing expected fields (framework passes {} on error)
|
|
167
|
+
if (!details?.packageManager) {
|
|
168
|
+
// Extract error message from result.content
|
|
169
|
+
const text = result.content[0];
|
|
170
|
+
const errorMessage =
|
|
171
|
+
text?.type === "text" && text.text
|
|
172
|
+
? text.text
|
|
173
|
+
: "Failed to detect package manager";
|
|
174
|
+
return new Text(theme.fg("error", errorMessage), 0, 0);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const lines: string[] = [];
|
|
178
|
+
lines.push(
|
|
179
|
+
theme.fg(
|
|
180
|
+
"success",
|
|
181
|
+
`Package manager: ${theme.bold(details.packageManager)}`,
|
|
182
|
+
),
|
|
183
|
+
);
|
|
184
|
+
if (details.version) {
|
|
185
|
+
lines.push(theme.fg("dim", `Version: ${details.version}`));
|
|
186
|
+
}
|
|
187
|
+
if (details.lockfile) {
|
|
188
|
+
lines.push(theme.fg("dim", `Lockfile: ${details.lockfile}`));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return new Text(lines.join("\n"), 0, 0);
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Find the currently running Pi installation directory by resolving the
|
|
6
|
+
* pi-coding-agent package location.
|
|
7
|
+
*/
|
|
8
|
+
export function findPiInstallation(): string | null {
|
|
9
|
+
try {
|
|
10
|
+
const piModulePath = require.resolve(
|
|
11
|
+
"@mariozechner/pi-coding-agent/package.json",
|
|
12
|
+
);
|
|
13
|
+
return path.dirname(piModulePath);
|
|
14
|
+
} catch (_error) {
|
|
15
|
+
const scriptPath = process.argv[1];
|
|
16
|
+
if (scriptPath) {
|
|
17
|
+
let currentDir = path.dirname(scriptPath);
|
|
18
|
+
|
|
19
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
20
|
+
const packageJsonPath = path.join(currentDir, "package.json");
|
|
21
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
22
|
+
try {
|
|
23
|
+
const packageContent = fs.readFileSync(packageJsonPath, "utf-8");
|
|
24
|
+
const packageJson = JSON.parse(packageContent);
|
|
25
|
+
if (packageJson.name === "@mariozechner/pi-coding-agent") {
|
|
26
|
+
return currentDir;
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
// Continue searching
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
currentDir = path.dirname(currentDir);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ToolCallHeader } from "@aliou/pi-utils-ui";
|
|
2
|
+
import type {
|
|
3
|
+
AgentToolResult,
|
|
4
|
+
ExtensionAPI,
|
|
5
|
+
ExtensionContext,
|
|
6
|
+
Theme,
|
|
7
|
+
ToolRenderResultOptions,
|
|
8
|
+
} from "@mariozechner/pi-coding-agent";
|
|
9
|
+
import { VERSION } from "@mariozechner/pi-coding-agent";
|
|
10
|
+
import { Text } from "@mariozechner/pi-tui";
|
|
11
|
+
import { Type } from "@sinclair/typebox";
|
|
12
|
+
|
|
13
|
+
const VersionParams = Type.Object({});
|
|
14
|
+
type VersionParamsType = Record<string, never>;
|
|
15
|
+
|
|
16
|
+
interface VersionDetails {
|
|
17
|
+
version?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function setupVersionTool(pi: ExtensionAPI) {
|
|
21
|
+
pi.registerTool<typeof VersionParams, VersionDetails>({
|
|
22
|
+
name: "pi_version",
|
|
23
|
+
label: "Pi Version",
|
|
24
|
+
description: "Get the version of the currently running Pi instance",
|
|
25
|
+
promptSnippet: "Check the current Pi version.",
|
|
26
|
+
promptGuidelines: [
|
|
27
|
+
"Use when the user asks about the Pi version or when a task depends on knowing the installed version.",
|
|
28
|
+
],
|
|
29
|
+
|
|
30
|
+
parameters: VersionParams,
|
|
31
|
+
|
|
32
|
+
async execute(
|
|
33
|
+
_toolCallId: string,
|
|
34
|
+
_params: VersionParamsType,
|
|
35
|
+
_signal: AbortSignal | undefined,
|
|
36
|
+
_onUpdate: unknown,
|
|
37
|
+
_ctx: ExtensionContext,
|
|
38
|
+
): Promise<AgentToolResult<VersionDetails>> {
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: "text", text: `Pi version ${VERSION}` }],
|
|
41
|
+
details: { version: VERSION },
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
renderCall(_args: VersionParamsType, theme: Theme) {
|
|
46
|
+
return new ToolCallHeader({ toolName: "Pi Version" }, theme);
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
renderResult(
|
|
50
|
+
result: AgentToolResult<VersionDetails>,
|
|
51
|
+
_options: ToolRenderResultOptions,
|
|
52
|
+
theme: Theme,
|
|
53
|
+
): Text {
|
|
54
|
+
const { details } = result;
|
|
55
|
+
|
|
56
|
+
if (!details?.version) {
|
|
57
|
+
const textBlock = result.content.find((c) => c.type === "text");
|
|
58
|
+
const msg =
|
|
59
|
+
(textBlock?.type === "text" && textBlock.text) || "Unknown version";
|
|
60
|
+
return new Text(theme.fg("error", msg), 0, 0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return new Text(
|
|
64
|
+
theme.fg("accent", `Pi version: ${details.version}`),
|
|
65
|
+
0,
|
|
66
|
+
0,
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|