@evandu/super-pi 0.1.111 → 0.1.112
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/dist/.super-pi-check-inputs.json +2 -2
- package/dist/client/.super-pi-client-sources.json +8 -7
- package/dist/client/assets/{CodeMirrorEditor-CaF1aTpR.js → CodeMirrorEditor-moFTk5SE.js} +2 -2
- package/dist/client/assets/{dist-aC6cFQVF.js → dist-BR4s0dNg.js} +1 -1
- package/dist/client/assets/{dist-Bl_iPEld.js → dist-BUuPRG15.js} +1 -1
- package/dist/client/assets/{dist-CPo4IuhO.js → dist-Bds_PUYK.js} +1 -1
- package/dist/client/assets/{dist-BydrWuS9.js → dist-BsO40qxQ.js} +1 -1
- package/dist/client/assets/{dist-jDX3NY00.js → dist-CCYnr6ul.js} +1 -1
- package/dist/client/assets/{dist-f78PQc3f.js → dist-CL65aMXY.js} +1 -1
- package/dist/client/assets/{dist-BjrDHYro.js → dist-D9m04q-s.js} +1 -1
- package/dist/client/assets/{dist-o-3gMx5l.js → dist-DIfmMr8s.js} +1 -1
- package/dist/client/assets/{dist-CJHSsi_2.js → dist-DPDGd2jl.js} +1 -1
- package/dist/client/assets/{dist-C9gmrpfb.js → dist-DPvy57Ph.js} +1 -1
- package/dist/client/assets/{dist-CKziNS6e.js → dist-DQjJMys5.js} +1 -1
- package/dist/client/assets/{dist-CbkXScEJ.js → dist-Dnr5BxAi.js} +1 -1
- package/dist/client/assets/{dist-C2JgfsQ0.js → dist-DrbUrVWB.js} +1 -1
- package/dist/client/assets/{dist-BG1mkRxC.js → dist-DuWhzonJ.js} +1 -1
- package/dist/client/assets/{dist-DnwnynHW.js → dist-TgNJUr7p.js} +1 -1
- package/dist/client/assets/{dist-Bv-QAejS.js → dist-rhPxFuD1.js} +1 -1
- package/dist/client/assets/{index-CME3BwBz.js → index-BixdV7aQ.js} +23 -23
- package/dist/client/assets/index-CGXMw9LP.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/server/application/run-service.d.ts +7 -0
- package/dist/server/application/run-service.js +16 -0
- package/dist/server/file-name-index.d.ts +144 -0
- package/dist/server/file-name-index.js +324 -0
- package/dist/server/http-server.js +112 -3
- package/dist/server/index.js +10 -0
- package/dist/server/server-context.d.ts +9 -0
- package/dist/server/skills.d.ts +23 -0
- package/dist/server/skills.js +171 -0
- package/dist/server/types.d.ts +7 -0
- package/package.json +3 -1
- package/scripts/patch-brace-expansion.mjs +1 -1
- package/dist/client/assets/index-CauO59H-.css +0 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SkillSummary } from "./types.js";
|
|
2
|
+
import type { ActiveMemory } from "./active-memory.js";
|
|
3
|
+
/**
|
|
4
|
+
* Loads and returns all available skills for a given workspace and global environment.
|
|
5
|
+
* Priority is given to Pi SDK's DefaultResourceLoader which scans project and user skills.
|
|
6
|
+
* Falls back to direct filesystem scanning if Pi SDK is unavailable.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getAvailableSkills(workspacePath?: string, options?: {
|
|
9
|
+
memory?: ActiveMemory;
|
|
10
|
+
workspaceId?: string;
|
|
11
|
+
}): Promise<SkillSummary[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Reads the markdown content of a specific skill by name or ID.
|
|
14
|
+
*/
|
|
15
|
+
export declare function readSkill(nameOrId: string, workspacePath?: string, options?: {
|
|
16
|
+
memory?: ActiveMemory;
|
|
17
|
+
workspaceId?: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
content: string;
|
|
23
|
+
} | null>;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
/**
|
|
6
|
+
* Loads and returns all available skills for a given workspace and global environment.
|
|
7
|
+
* Priority is given to Pi SDK's DefaultResourceLoader which scans project and user skills.
|
|
8
|
+
* Falls back to direct filesystem scanning if Pi SDK is unavailable.
|
|
9
|
+
*/
|
|
10
|
+
export async function getAvailableSkills(workspacePath, options) {
|
|
11
|
+
const cwd = workspacePath && existsSync(workspacePath) ? workspacePath : process.cwd();
|
|
12
|
+
const skillsMap = new Map();
|
|
13
|
+
// 1. Try loading via Pi SDK DefaultResourceLoader
|
|
14
|
+
try {
|
|
15
|
+
const sdk = await import("@earendil-works/pi-coding-agent").catch(() => null);
|
|
16
|
+
if (sdk?.DefaultResourceLoader) {
|
|
17
|
+
const agentDir = join(homedir(), ".pi", "agent");
|
|
18
|
+
const loader = new sdk.DefaultResourceLoader({ cwd, agentDir });
|
|
19
|
+
await loader.reload();
|
|
20
|
+
const res = loader.getSkills();
|
|
21
|
+
if (Array.isArray(res?.skills)) {
|
|
22
|
+
for (const s of res.skills) {
|
|
23
|
+
if (!s.name)
|
|
24
|
+
continue;
|
|
25
|
+
const scope = s.sourceInfo?.scope === "project" ? "workspace" : "global";
|
|
26
|
+
skillsMap.set(s.name, {
|
|
27
|
+
id: `skill:${s.name}`,
|
|
28
|
+
name: s.name,
|
|
29
|
+
description: s.description || "",
|
|
30
|
+
scope,
|
|
31
|
+
filePath: s.filePath,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Ignore and proceed to filesystem fallback
|
|
39
|
+
}
|
|
40
|
+
// 2. Fallback: Direct directory scan if SDK loaded nothing or was unavailable
|
|
41
|
+
if (skillsMap.size === 0) {
|
|
42
|
+
const scanDirs = [
|
|
43
|
+
{ dir: join(cwd, ".pi", "skills"), scope: "workspace" },
|
|
44
|
+
{ dir: join(cwd, ".agents", "skills"), scope: "workspace" },
|
|
45
|
+
{ dir: join(homedir(), ".pi", "agent", "skills"), scope: "global" },
|
|
46
|
+
{ dir: join(homedir(), ".agents", "skills"), scope: "global" },
|
|
47
|
+
];
|
|
48
|
+
for (const { dir, scope } of scanDirs) {
|
|
49
|
+
if (!existsSync(dir))
|
|
50
|
+
continue;
|
|
51
|
+
try {
|
|
52
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
let skillFile = "";
|
|
55
|
+
let skillName = entry.name;
|
|
56
|
+
if (entry.isDirectory()) {
|
|
57
|
+
const candidate = join(dir, entry.name, "SKILL.md");
|
|
58
|
+
if (existsSync(candidate)) {
|
|
59
|
+
skillFile = candidate;
|
|
60
|
+
skillName = entry.name;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
64
|
+
skillFile = join(dir, entry.name);
|
|
65
|
+
skillName = entry.name.replace(/\.md$/, "");
|
|
66
|
+
}
|
|
67
|
+
if (skillFile) {
|
|
68
|
+
try {
|
|
69
|
+
const text = await readFile(skillFile, "utf-8");
|
|
70
|
+
const frontmatterMatch = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
|
|
71
|
+
let description = "";
|
|
72
|
+
let parsedName = skillName;
|
|
73
|
+
if (frontmatterMatch) {
|
|
74
|
+
const nameMatch = /^name:\s*(.+)$/m.exec(frontmatterMatch[1]);
|
|
75
|
+
if (nameMatch)
|
|
76
|
+
parsedName = nameMatch[1].trim();
|
|
77
|
+
const descMatch = /^description:\s*(.+)$/m.exec(frontmatterMatch[1]);
|
|
78
|
+
if (descMatch)
|
|
79
|
+
description = descMatch[1].trim();
|
|
80
|
+
}
|
|
81
|
+
if (!skillsMap.has(parsedName)) {
|
|
82
|
+
skillsMap.set(parsedName, {
|
|
83
|
+
id: `skill:${parsedName}`,
|
|
84
|
+
name: parsedName,
|
|
85
|
+
description,
|
|
86
|
+
scope,
|
|
87
|
+
filePath: skillFile,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Ignore unreadable file
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Ignore unreadable directory
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 3. Optional: merge active memory notes skills if available and not colliding
|
|
103
|
+
if (options?.memory && options?.workspaceId) {
|
|
104
|
+
try {
|
|
105
|
+
const memoryEntries = await options.memory.notes.apply(options.workspaceId, "", { target: "skills", action: "list" });
|
|
106
|
+
if (Array.isArray(memoryEntries)) {
|
|
107
|
+
for (const entry of memoryEntries) {
|
|
108
|
+
const firstLine = entry.content.split(/\r?\n/, 1)[0].replace(/^#+\s*/, "").trim();
|
|
109
|
+
const name = firstLine || "unnamed-skill";
|
|
110
|
+
if (!skillsMap.has(name) && !skillsMap.has(entry.id)) {
|
|
111
|
+
skillsMap.set(`mem:${entry.id}`, {
|
|
112
|
+
id: `skill:${entry.id}`,
|
|
113
|
+
name,
|
|
114
|
+
description: "Active memory skill",
|
|
115
|
+
scope: "memory",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Memory may not be ready or active
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return Array.from(skillsMap.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Reads the markdown content of a specific skill by name or ID.
|
|
129
|
+
*/
|
|
130
|
+
export async function readSkill(nameOrId, workspacePath, options) {
|
|
131
|
+
const cleanId = nameOrId.startsWith("skill:") ? nameOrId.slice("skill:".length) : nameOrId;
|
|
132
|
+
const skills = await getAvailableSkills(workspacePath, options);
|
|
133
|
+
const found = skills.find((s) => s.name === cleanId || s.name === nameOrId || s.id === nameOrId || s.id === `skill:${cleanId}`);
|
|
134
|
+
if (!found)
|
|
135
|
+
return null;
|
|
136
|
+
// If it's a file on disk
|
|
137
|
+
if (found.filePath && existsSync(found.filePath)) {
|
|
138
|
+
try {
|
|
139
|
+
const content = await readFile(found.filePath, "utf-8");
|
|
140
|
+
return {
|
|
141
|
+
id: found.id,
|
|
142
|
+
name: found.name,
|
|
143
|
+
description: found.description,
|
|
144
|
+
content,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// If it's stored in active memory
|
|
152
|
+
if (found.scope === "memory" && options?.memory && options?.workspaceId) {
|
|
153
|
+
try {
|
|
154
|
+
const entryId = found.id.startsWith("skill:") ? found.id.slice("skill:".length) : found.id;
|
|
155
|
+
const memoryEntries = await options.memory.notes.apply(options.workspaceId, "", { target: "skills", action: "list" });
|
|
156
|
+
const entry = memoryEntries.find((e) => e.id === entryId || e.id === found.name);
|
|
157
|
+
if (entry) {
|
|
158
|
+
return {
|
|
159
|
+
id: found.id,
|
|
160
|
+
name: found.name,
|
|
161
|
+
description: found.description,
|
|
162
|
+
content: entry.content,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
package/dist/server/types.d.ts
CHANGED
|
@@ -164,6 +164,13 @@ export type MessageAttachment = {
|
|
|
164
164
|
content: string;
|
|
165
165
|
};
|
|
166
166
|
export type MessageAttachments = MessageAttachment[];
|
|
167
|
+
export interface SkillSummary {
|
|
168
|
+
id: string;
|
|
169
|
+
name: string;
|
|
170
|
+
description: string;
|
|
171
|
+
scope?: "workspace" | "global" | "memory";
|
|
172
|
+
filePath?: string;
|
|
173
|
+
}
|
|
167
174
|
/**
|
|
168
175
|
* ONE PARAMETER OF A TOOL CALL, as a call block lists it, and the boundary that keeps Pi's arguments out
|
|
169
176
|
* of `state.json`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evandu/super-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.112",
|
|
4
4
|
"description": "Web control plane and companion for Pi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -89,6 +89,7 @@
|
|
|
89
89
|
"scripts/files-missing-path.test.mjs",
|
|
90
90
|
"scripts/file-changes.test.mjs",
|
|
91
91
|
"scripts/file-index.test.mjs",
|
|
92
|
+
"scripts/file-name-index.test.mjs",
|
|
92
93
|
"scripts/file-content-search.test.mjs",
|
|
93
94
|
"scripts/file-diff-client.test.mjs",
|
|
94
95
|
"scripts/task-tool.test.mjs",
|
|
@@ -116,6 +117,7 @@
|
|
|
116
117
|
"scripts/static-client-assets.test.mjs",
|
|
117
118
|
"scripts/cli.test.mjs",
|
|
118
119
|
"scripts/check-runner.test.mjs",
|
|
120
|
+
"scripts/skills-discovery.test.mjs",
|
|
119
121
|
"scripts/shared-chrome.test.mjs"
|
|
120
122
|
],
|
|
121
123
|
"check:browser": [
|
|
@@ -220,7 +220,7 @@ function findVulnerableCopies() {
|
|
|
220
220
|
try { version = JSON.parse(readFileSync(manifest, "utf8")).version ?? ""; } catch { continue; }
|
|
221
221
|
if (!version) continue;
|
|
222
222
|
if (compareVersions(version, VULNERABLE_BELOW) >= 0) continue;
|
|
223
|
-
found.push({ directory, version
|
|
223
|
+
found.push({ directory, version });
|
|
224
224
|
}
|
|
225
225
|
return found;
|
|
226
226
|
}
|