@aethrekh/pi-cs 0.1.10 → 0.2.0-alpha.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/CHANGELOG.md +18 -0
- package/README.md +31 -5
- package/extensions/folder-detector.js +7 -7
- package/extensions/integrity-guard.js +13 -0
- package/extensions/progress-tracker.js +101 -11
- package/extensions/semester-detector.js +14 -0
- package/extensions/workspace.js +108 -0
- package/index.d.ts +2 -0
- package/index.js +11 -9
- package/index.js.map +1 -1
- package/package.json +2 -1
- package/pi-cs.meta.json +2 -2
- package/pi-package.yaml +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.2.0-alpha.0](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10...v0.2.0-alpha.0) (2026-06-05)
|
|
11
|
+
|
|
12
|
+
### ### Added
|
|
13
|
+
|
|
14
|
+
* implement workspace scoping via .pisces marker walk-up ([51444c1](https://github.com/AshishBagdane/pi-cs/commit/51444c19034047fbcd00111ce3ca2c30f7fb37c7))
|
|
15
|
+
|
|
16
|
+
### ### Fixed
|
|
17
|
+
|
|
18
|
+
* clean up ~/.pi-cs/sessions.json on uninstall ([56d020a](https://github.com/AshishBagdane/pi-cs/commit/56d020aa319006b72299912ef43324c7747e0d4d))
|
|
19
|
+
* register workspace.ts as a Pi extension so workspace.js is included in pack ([7f2546c](https://github.com/AshishBagdane/pi-cs/commit/7f2546ce50debcd5bda4a6da6ece9c482a13d861))
|
|
20
|
+
|
|
21
|
+
### ### Changed
|
|
22
|
+
|
|
23
|
+
* add workspace-scoping design document ([098504a](https://github.com/AshishBagdane/pi-cs/commit/098504a8262986def084c34a89d585a08e40531b))
|
|
24
|
+
* align README and STUDENT_GUIDE with v0.1.10 install behaviour ([e8f6ae5](https://github.com/AshishBagdane/pi-cs/commit/e8f6ae5a9ed4ebd54409985e00d18b3356438255))
|
|
25
|
+
* fix false local install scope claims and expand troubleshooting ([0e000f7](https://github.com/AshishBagdane/pi-cs/commit/0e000f7ac947fc641785ab46818649710d857265))
|
|
26
|
+
* update README and STUDENT_GUIDE for workspace-scoped activation ([81e8872](https://github.com/AshishBagdane/pi-cs/commit/81e8872c024edb8c41cbc0d7b1fa85b10ddb16c9))
|
|
27
|
+
|
|
10
28
|
## [0.1.10](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10-alpha.1...v0.1.10) (2026-06-05)
|
|
11
29
|
|
|
12
30
|
## [0.1.10-alpha.1](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10-alpha.0...v0.1.10-alpha.1) (2026-06-05)
|
package/README.md
CHANGED
|
@@ -29,20 +29,23 @@ It covers every dimension of a CS degree:
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
# Install Pisces
|
|
32
|
+
# Install Pisces globally (one-time setup)
|
|
33
|
+
pi install npm:@aethrekh/pi-cs
|
|
34
|
+
|
|
35
|
+
# Mark your university folder as a Pisces workspace
|
|
33
36
|
cd ~/university
|
|
34
|
-
|
|
37
|
+
/pisces --activate
|
|
35
38
|
|
|
36
39
|
# Initialize your semester context
|
|
37
40
|
/semester --init
|
|
38
41
|
|
|
39
|
-
# Start working
|
|
42
|
+
# Start working — from any subdirectory
|
|
40
43
|
/homework
|
|
41
44
|
/explain binary search trees
|
|
42
45
|
/leetcode 42
|
|
43
46
|
```
|
|
44
47
|
|
|
45
|
-
> **
|
|
48
|
+
> **Workspace-scoped by default:** Pisces is silent in non-academic sessions. Once you run `/pisces --activate` in a directory, Pisces activates in every Pi session started inside that directory tree — no reinstalling, no per-folder setup. See the [Installation](#installation) section for details.
|
|
46
49
|
|
|
47
50
|
---
|
|
48
51
|
|
|
@@ -196,10 +199,31 @@ See [`config/schema.json`](config/schema.json) for the full configuration refere
|
|
|
196
199
|
**Requirements:** Pi >= 0.78.0, Node.js >= 18
|
|
197
200
|
|
|
198
201
|
```bash
|
|
202
|
+
# Step 1 — Install globally (one command, once per machine)
|
|
199
203
|
pi install npm:@aethrekh/pi-cs
|
|
204
|
+
|
|
205
|
+
# Step 2 — Activate in your university folder
|
|
206
|
+
cd ~/university
|
|
207
|
+
/pisces --activate
|
|
208
|
+
|
|
209
|
+
# Step 3 — Set up semester context
|
|
210
|
+
/semester --init
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**How scoping works:** Pisces is completely silent outside workspace trees. Once you run `/pisces --activate` in a directory, it creates a `.pisces` marker file there. On every Pi session, Pisces walks up from `process.cwd()` looking for `.pisces` — if found, it activates; if not, it is a silent no-op. This means:
|
|
214
|
+
|
|
215
|
+
- One global install covers every workspace you mark
|
|
216
|
+
- Work and personal sessions are unaffected until you mark them
|
|
217
|
+
- Multiple independent workspaces are supported (just run `/pisces --activate` in each root)
|
|
218
|
+
- Deactivate with `/pisces --deactivate` or `rm .pisces`
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Local install — activates Pisces only in the exact install directory
|
|
222
|
+
cd ~/university
|
|
223
|
+
pi install npm:@aethrekh/pi-cs -l
|
|
200
224
|
```
|
|
201
225
|
|
|
202
|
-
|
|
226
|
+
Pi does not walk up parent directories to find locally installed packages. If you use `-l`, Pisces only loads when Pi is started from `~/university` itself — not from any subdirectory like `~/university/fall2025/CS301/`. Use the global install for most setups.
|
|
203
227
|
|
|
204
228
|
---
|
|
205
229
|
|
|
@@ -220,6 +244,7 @@ pi-cs/
|
|
|
220
244
|
│ │ ├── exam/SKILL.md # /exam skill
|
|
221
245
|
│ │ └── research/SKILL.md # /research skill
|
|
222
246
|
│ ├── extensions/
|
|
247
|
+
│ │ ├── workspace.ts # .pisces walk-up detection (shared)
|
|
223
248
|
│ │ ├── semester-detector.ts # Auto-loads SEMESTER.md
|
|
224
249
|
│ │ ├── folder-detector.ts # Detects CS folder structures
|
|
225
250
|
│ │ ├── integrity-guard.ts # Academic integrity monitoring
|
|
@@ -242,6 +267,7 @@ pi-cs/
|
|
|
242
267
|
- [x] 4 background extensions
|
|
243
268
|
- [x] Semester context system
|
|
244
269
|
- [x] Academic integrity guard
|
|
270
|
+
- [x] Workspace-scoped activation (`.pisces` marker)
|
|
245
271
|
- [ ] arXiv live search integration
|
|
246
272
|
- [ ] Model routing presets
|
|
247
273
|
- [ ] Obsidian vault sync
|
|
@@ -48,6 +48,7 @@ exports.default = default_1;
|
|
|
48
48
|
exports.run = run;
|
|
49
49
|
const fs = __importStar(require("fs"));
|
|
50
50
|
const path = __importStar(require("path"));
|
|
51
|
+
const workspace_1 = require("./workspace");
|
|
51
52
|
// ─── Marker Files ──────────────────────────────────────────────────────────
|
|
52
53
|
const PYTHON_MARKERS = ["requirements.txt", "pyproject.toml", "setup.py", "Pipfile"];
|
|
53
54
|
const TS_MARKERS = ["package.json", "tsconfig.json"];
|
|
@@ -188,15 +189,14 @@ function summarizeFolderContext(result) {
|
|
|
188
189
|
}
|
|
189
190
|
// ─── Pi Extension Factory ──────────────────────────────────────────────────
|
|
190
191
|
function default_1(pi) {
|
|
191
|
-
let contextSummary = "";
|
|
192
|
-
pi.on("session_start", async () => {
|
|
193
|
-
const result = detectFolderContext();
|
|
194
|
-
contextSummary = summarizeFolderContext(result);
|
|
195
|
-
});
|
|
196
192
|
pi.on("before_agent_start", async (event) => {
|
|
197
|
-
|
|
193
|
+
// Re-check workspace on every agent turn — no closure state needed.
|
|
194
|
+
if (!(0, workspace_1.findPiscesMarker)())
|
|
195
|
+
return;
|
|
196
|
+
const summary = summarizeFolderContext(detectFolderContext());
|
|
197
|
+
if (!summary)
|
|
198
198
|
return;
|
|
199
|
-
return { systemPrompt: `${event.systemPrompt}\n\n${
|
|
199
|
+
return { systemPrompt: `${event.systemPrompt}\n\n${summary}` };
|
|
200
200
|
});
|
|
201
201
|
}
|
|
202
202
|
// ─── Pi Extension Entry Point ──────────────────────────────────────────────
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.checkIntegrityRisk = checkIntegrityRisk;
|
|
13
13
|
exports.default = default_1;
|
|
14
14
|
exports.run = run;
|
|
15
|
+
const workspace_1 = require("./workspace");
|
|
15
16
|
// ─── Risk Signals ──────────────────────────────────────────────────────────
|
|
16
17
|
// High-risk: user is likely asking for submission-ready work
|
|
17
18
|
const HIGH_RISK_PATTERNS = [
|
|
@@ -101,10 +102,22 @@ Just let me know!`;
|
|
|
101
102
|
}
|
|
102
103
|
// ─── Pi Extension Factory ──────────────────────────────────────────────────
|
|
103
104
|
function default_1(pi) {
|
|
105
|
+
let isActive = false;
|
|
104
106
|
// Guard against sendUserMessage re-triggering this handler — warning text
|
|
105
107
|
// contains words like "graded" that would otherwise match medium-risk patterns.
|
|
106
108
|
let handlingWarning = false;
|
|
109
|
+
pi.on("session_start", async () => {
|
|
110
|
+
isActive = (0, workspace_1.findPiscesMarker)() !== null;
|
|
111
|
+
});
|
|
112
|
+
// Refresh isActive before each agent turn so mid-session workspace changes
|
|
113
|
+
// are picked up. The input handler may still use a one-turn-stale value for
|
|
114
|
+
// messages that arrive before the first before_agent_start of a new turn.
|
|
115
|
+
pi.on("before_agent_start", async () => {
|
|
116
|
+
isActive = (0, workspace_1.findPiscesMarker)() !== null;
|
|
117
|
+
});
|
|
107
118
|
pi.on("input", async (event) => {
|
|
119
|
+
if (!isActive)
|
|
120
|
+
return { action: "continue" };
|
|
108
121
|
if (handlingWarning)
|
|
109
122
|
return { action: "continue" };
|
|
110
123
|
const skillMatch = event.text.match(/^\/skill:(\w+)\s*/);
|
|
@@ -50,6 +50,7 @@ const fs = __importStar(require("fs"));
|
|
|
50
50
|
const path = __importStar(require("path"));
|
|
51
51
|
const os = __importStar(require("os"));
|
|
52
52
|
const semester_detector_1 = require("./semester-detector");
|
|
53
|
+
const workspace_1 = require("./workspace");
|
|
53
54
|
// ─── Storage ───────────────────────────────────────────────────────────────
|
|
54
55
|
const TRACKER_DIR = path.join(os.homedir(), ".pi-cs");
|
|
55
56
|
const SESSIONS_FILE = path.join(TRACKER_DIR, "sessions.json");
|
|
@@ -161,7 +162,15 @@ function buildWeeklySummary(stats) {
|
|
|
161
162
|
function default_1(pi) {
|
|
162
163
|
const sessionStart = Date.now();
|
|
163
164
|
const skillsUsed = [];
|
|
165
|
+
let isActive = false;
|
|
166
|
+
let workspaceRoot = null;
|
|
167
|
+
pi.on("session_start", async () => {
|
|
168
|
+
workspaceRoot = (0, workspace_1.findPiscesMarker)();
|
|
169
|
+
isActive = workspaceRoot !== null;
|
|
170
|
+
});
|
|
164
171
|
pi.on("input", async (event) => {
|
|
172
|
+
if (!isActive)
|
|
173
|
+
return { action: "continue" };
|
|
165
174
|
const match = event.text.match(/^\/skill:(\w+)/);
|
|
166
175
|
if (match && !skillsUsed.includes(match[1])) {
|
|
167
176
|
skillsUsed.push(match[1]);
|
|
@@ -169,12 +178,19 @@ function default_1(pi) {
|
|
|
169
178
|
return { action: "continue" };
|
|
170
179
|
});
|
|
171
180
|
pi.on("before_agent_start", async (_event, ctx) => {
|
|
181
|
+
// Refresh workspace state on every agent turn so mid-session changes are reflected.
|
|
182
|
+
workspaceRoot = (0, workspace_1.findPiscesMarker)();
|
|
183
|
+
isActive = workspaceRoot !== null;
|
|
184
|
+
if (!isActive)
|
|
185
|
+
return;
|
|
172
186
|
const elapsed = Math.round((Date.now() - sessionStart) / 60000);
|
|
173
187
|
if (elapsed > 0 && elapsed % 180 === 0) {
|
|
174
188
|
ctx.ui.notify(`🐠 You've been at this for ${elapsed} minutes. Take a short break — your brain consolidates learning during rest, not during grinding.`, "info");
|
|
175
189
|
}
|
|
176
190
|
});
|
|
177
191
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
192
|
+
if (!isActive)
|
|
193
|
+
return;
|
|
178
194
|
const durationMinutes = Math.round((Date.now() - sessionStart) / 60000);
|
|
179
195
|
const { nudge, weeklySummary } = run({ sessionDurationMinutes: durationMinutes, skillsUsed });
|
|
180
196
|
if (nudge)
|
|
@@ -183,27 +199,101 @@ function default_1(pi) {
|
|
|
183
199
|
ctx.ui.notify(weeklySummary, "info");
|
|
184
200
|
});
|
|
185
201
|
pi.registerCommand("pisces", {
|
|
186
|
-
description: "
|
|
187
|
-
handler: async (
|
|
202
|
+
description: "Workspace lifecycle and status for Pisces — use --activate, --deactivate, --status, --version",
|
|
203
|
+
handler: async (args, ctx) => {
|
|
204
|
+
const flag = (typeof args === "string" ? args : args[0] ?? "").trim();
|
|
205
|
+
// ── /pisces --activate ───────────────────────────────────────────────
|
|
206
|
+
if (flag === "--activate") {
|
|
207
|
+
const cwd = process.cwd();
|
|
208
|
+
const existing = (0, workspace_1.findPiscesMarker)(cwd);
|
|
209
|
+
if (existing) {
|
|
210
|
+
ctx.ui.notify(`🐠 Workspace already active at: ${existing}\n\nRun /pisces --status for details.`, "info");
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
(0, workspace_1.createPiscesMarker)(cwd);
|
|
215
|
+
workspaceRoot = cwd;
|
|
216
|
+
isActive = true;
|
|
217
|
+
ctx.ui.notify([
|
|
218
|
+
`✅ Workspace activated at: ${cwd}`,
|
|
219
|
+
` ${workspace_1.PISCES_MARKER} created.`,
|
|
220
|
+
``,
|
|
221
|
+
`All Pi sessions in this directory tree will now activate Pisces.`,
|
|
222
|
+
``,
|
|
223
|
+
`Run /semester --init to set up semester context, or start working right away.`,
|
|
224
|
+
].join("\n"), "info");
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
ctx.ui.notify(`❌ Failed to create ${workspace_1.PISCES_MARKER}: ${String(err)}`, "error");
|
|
228
|
+
}
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
// ── /pisces --deactivate ─────────────────────────────────────────────
|
|
232
|
+
if (flag === "--deactivate") {
|
|
233
|
+
if (!workspaceRoot) {
|
|
234
|
+
ctx.ui.notify("🐠 No active Pisces workspace in this session — nothing to deactivate.", "info");
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
(0, workspace_1.removePiscesMarker)(workspaceRoot);
|
|
239
|
+
const removed = workspaceRoot;
|
|
240
|
+
workspaceRoot = null;
|
|
241
|
+
isActive = false;
|
|
242
|
+
ctx.ui.notify(`✅ Workspace deactivated.\n Removed ${workspace_1.PISCES_MARKER} from: ${removed}\n\nTakes full effect on next session start.`, "info");
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
ctx.ui.notify(`❌ Failed to remove ${workspace_1.PISCES_MARKER}: ${String(err)}`, "error");
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// ── /pisces --version ────────────────────────────────────────────────
|
|
250
|
+
if (flag === "--version") {
|
|
251
|
+
// Read version from package.json at runtime to stay in sync with releases
|
|
252
|
+
let version = "unknown";
|
|
253
|
+
try {
|
|
254
|
+
const pkgPath = path.resolve(__dirname, "../../package.json");
|
|
255
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
256
|
+
version = pkg.version;
|
|
257
|
+
}
|
|
258
|
+
catch { /* fall through */ }
|
|
259
|
+
ctx.ui.notify(`🐠 pi-cs (Pisces) v${version}`, "info");
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
// ── /pisces --status (default) ───────────────────────────────────────
|
|
188
263
|
const elapsed = Math.round((Date.now() - sessionStart) / 60000);
|
|
264
|
+
if (!isActive) {
|
|
265
|
+
ctx.ui.notify([
|
|
266
|
+
"Pisces Status",
|
|
267
|
+
"─────────────────────────────────────",
|
|
268
|
+
"Active: ❌ No",
|
|
269
|
+
`Reason: No ${workspace_1.PISCES_MARKER} found within search bounds (15 levels, ~)`,
|
|
270
|
+
"",
|
|
271
|
+
"Run /pisces --activate to mark this directory as a workspace root.",
|
|
272
|
+
].join("\n"), "info");
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
189
275
|
const detection = (0, semester_detector_1.detectSemesterContext)();
|
|
190
276
|
const semCtx = detection.context;
|
|
191
277
|
const lines = [
|
|
192
|
-
"
|
|
278
|
+
"Pisces Status",
|
|
279
|
+
"─────────────────────────────────────",
|
|
280
|
+
"Active: ✅ Yes",
|
|
281
|
+
`Workspace root: ${workspaceRoot}`,
|
|
282
|
+
`Session: ${elapsed} minute${elapsed !== 1 ? "s" : ""}`,
|
|
193
283
|
"",
|
|
194
284
|
semCtx
|
|
195
|
-
?
|
|
196
|
-
: "
|
|
285
|
+
? `Semester: ${semCtx.semester} ${semCtx.year}${semCtx.week ? ` — Week ${semCtx.week}` : ""}`
|
|
286
|
+
: "Semester: ❌ No SEMESTER.md loaded — run /semester --init",
|
|
197
287
|
semCtx?.courses?.length
|
|
198
|
-
?
|
|
288
|
+
? `Courses: ${semCtx.courses.map((c) => c.code).join(", ")}`
|
|
199
289
|
: "",
|
|
200
|
-
semCtx?.active_project ?
|
|
201
|
-
|
|
290
|
+
semCtx?.active_project ? `Project: ${semCtx.active_project}` : "",
|
|
291
|
+
"",
|
|
202
292
|
skillsUsed.length
|
|
203
|
-
?
|
|
204
|
-
: "
|
|
293
|
+
? `Skills used: ${skillsUsed.map((s) => `/skill:${s}`).join(", ")}`
|
|
294
|
+
: "No skills used yet — try /skill:explain, /skill:homework, or /skill:leetcode",
|
|
205
295
|
]
|
|
206
|
-
.filter(
|
|
296
|
+
.filter((l) => l !== undefined)
|
|
207
297
|
.join("\n");
|
|
208
298
|
ctx.ui.notify(lines, "info");
|
|
209
299
|
},
|
|
@@ -49,6 +49,7 @@ exports.run = run;
|
|
|
49
49
|
const fs = __importStar(require("fs"));
|
|
50
50
|
const path = __importStar(require("path"));
|
|
51
51
|
const os = __importStar(require("os"));
|
|
52
|
+
const workspace_1 = require("./workspace");
|
|
52
53
|
// ─── Search Paths ──────────────────────────────────────────────────────────
|
|
53
54
|
function getSearchPaths() {
|
|
54
55
|
return [
|
|
@@ -224,6 +225,8 @@ function default_1(pi) {
|
|
|
224
225
|
const persona = loadPersona();
|
|
225
226
|
let semesterCtx = null;
|
|
226
227
|
pi.on("session_start", async (_event, ctx) => {
|
|
228
|
+
if (!(0, workspace_1.findPiscesMarker)())
|
|
229
|
+
return;
|
|
227
230
|
if (removeLegacyGlobalPersona(persona)) {
|
|
228
231
|
ctx.ui.notify("🐠 Pisces: cleaned up a stale ~/.pi/agent/APPEND_SYSTEM.md from an older install. Persona is now session-scoped.", "info");
|
|
229
232
|
}
|
|
@@ -238,6 +241,17 @@ function default_1(pi) {
|
|
|
238
241
|
}
|
|
239
242
|
});
|
|
240
243
|
pi.on("before_agent_start", async (event) => {
|
|
244
|
+
// Re-check workspace on every agent turn so mid-session activation/deactivation
|
|
245
|
+
// is reflected without needing a session restart.
|
|
246
|
+
if (!(0, workspace_1.findPiscesMarker)())
|
|
247
|
+
return;
|
|
248
|
+
// Lazy-load semester context if it was not available at session_start
|
|
249
|
+
// (e.g. workspace was activated mid-session via /pisces --activate).
|
|
250
|
+
if (!semesterCtx) {
|
|
251
|
+
const result = detectSemesterContext();
|
|
252
|
+
if (result.found && result.context)
|
|
253
|
+
semesterCtx = result.context;
|
|
254
|
+
}
|
|
241
255
|
const parts = [];
|
|
242
256
|
if (persona)
|
|
243
257
|
parts.push(persona);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* workspace.ts
|
|
4
|
+
*
|
|
5
|
+
* Walk-up logic for .pisces workspace marker detection.
|
|
6
|
+
* Shared by all four extensions — each calls findPiscesMarker()
|
|
7
|
+
* independently at session_start and before_agent_start.
|
|
8
|
+
*
|
|
9
|
+
* Registered as a Pi extension so that the pack includes workspace.js
|
|
10
|
+
* alongside the other extension files. The default export is a no-op;
|
|
11
|
+
* the module's value is its named exports (findPiscesMarker et al.).
|
|
12
|
+
*/
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
+
var ownKeys = function(o) {
|
|
31
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
+
var ar = [];
|
|
33
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
+
return ar;
|
|
35
|
+
};
|
|
36
|
+
return ownKeys(o);
|
|
37
|
+
};
|
|
38
|
+
return function (mod) {
|
|
39
|
+
if (mod && mod.__esModule) return mod;
|
|
40
|
+
var result = {};
|
|
41
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
+
__setModuleDefault(result, mod);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
})();
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.PISCES_MARKER = void 0;
|
|
48
|
+
exports.default = default_1;
|
|
49
|
+
exports.findPiscesMarker = findPiscesMarker;
|
|
50
|
+
exports.createPiscesMarker = createPiscesMarker;
|
|
51
|
+
exports.removePiscesMarker = removePiscesMarker;
|
|
52
|
+
const fs = __importStar(require("fs"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
const os = __importStar(require("os"));
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
56
|
+
function default_1(_pi) {
|
|
57
|
+
// Shared utility module — not a standalone extension.
|
|
58
|
+
// Pi loads this file; the named exports are imported by the other extensions.
|
|
59
|
+
}
|
|
60
|
+
exports.PISCES_MARKER = ".pisces";
|
|
61
|
+
const MAX_WALK_LEVELS = 15;
|
|
62
|
+
/**
|
|
63
|
+
* Walks up from cwd looking for a .pisces file. Returns the absolute
|
|
64
|
+
* path of the directory containing .pisces (the workspace root), or null
|
|
65
|
+
* if not found within the search bounds.
|
|
66
|
+
*
|
|
67
|
+
* Bounds (whichever is reached first):
|
|
68
|
+
* - 15 directory levels above cwd
|
|
69
|
+
* - Home directory (~) — .pisces at ~ or above is not a valid workspace root
|
|
70
|
+
* - Filesystem root (/)
|
|
71
|
+
*/
|
|
72
|
+
function findPiscesMarker(cwd = process.cwd()) {
|
|
73
|
+
const home = path.resolve(os.homedir());
|
|
74
|
+
let current = path.resolve(cwd);
|
|
75
|
+
for (let level = 0; level < MAX_WALK_LEVELS; level++) {
|
|
76
|
+
// Stop at home or above — not a valid workspace root
|
|
77
|
+
if (current === home || !current.startsWith(home + path.sep))
|
|
78
|
+
break;
|
|
79
|
+
try {
|
|
80
|
+
if (fs.existsSync(path.join(current, exports.PISCES_MARKER))) {
|
|
81
|
+
return current;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// skip unreadable directories
|
|
86
|
+
}
|
|
87
|
+
const parent = path.dirname(current);
|
|
88
|
+
if (parent === current)
|
|
89
|
+
break; // reached filesystem root
|
|
90
|
+
current = parent;
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Creates a .pisces marker in the given directory (default: cwd),
|
|
96
|
+
* marking it as a Pisces workspace root.
|
|
97
|
+
*/
|
|
98
|
+
function createPiscesMarker(dir = process.cwd()) {
|
|
99
|
+
fs.writeFileSync(path.join(path.resolve(dir), exports.PISCES_MARKER), "");
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Removes the .pisces marker from the given workspace root.
|
|
103
|
+
* Throws if the file does not exist.
|
|
104
|
+
*/
|
|
105
|
+
function removePiscesMarker(workspaceRoot) {
|
|
106
|
+
fs.unlinkSync(path.join(path.resolve(workspaceRoot), exports.PISCES_MARKER));
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=workspace.js.map
|
package/index.d.ts
CHANGED
|
@@ -98,11 +98,13 @@ export declare function onLoad(): {
|
|
|
98
98
|
/**
|
|
99
99
|
* onStartup — called at the start of every Pi session.
|
|
100
100
|
* Runs semester + folder detectors, builds greeting and context injection.
|
|
101
|
+
* Returns empty result silently when no .pisces workspace marker is found.
|
|
101
102
|
*/
|
|
102
103
|
export declare function onStartup(state: SessionState): StartupResult;
|
|
103
104
|
/**
|
|
104
105
|
* onDirectoryChange — called when the user `cd`s to a new directory.
|
|
105
106
|
* Re-runs context detectors so Pi stays accurate.
|
|
107
|
+
* Returns empty result silently when outside a .pisces workspace.
|
|
106
108
|
*/
|
|
107
109
|
export declare function onDirectoryChange(state: SessionState): {
|
|
108
110
|
contextInjection: string;
|
package/index.js
CHANGED
|
@@ -70,6 +70,7 @@ const semester_detector_1 = require("./extensions/semester-detector");
|
|
|
70
70
|
const folder_detector_1 = require("./extensions/folder-detector");
|
|
71
71
|
const integrity_guard_1 = require("./extensions/integrity-guard");
|
|
72
72
|
const progress_tracker_1 = require("./extensions/progress-tracker");
|
|
73
|
+
const workspace_1 = require("./extensions/workspace");
|
|
73
74
|
// ─── Package Metadata ──────────────────────────────────────────────────────
|
|
74
75
|
exports.PACKAGE_NAME = "pi-cs";
|
|
75
76
|
exports.PACKAGE_VERSION = "0.1.0";
|
|
@@ -191,28 +192,27 @@ function onLoad() {
|
|
|
191
192
|
/**
|
|
192
193
|
* onStartup — called at the start of every Pi session.
|
|
193
194
|
* Runs semester + folder detectors, builds greeting and context injection.
|
|
195
|
+
* Returns empty result silently when no .pisces workspace marker is found.
|
|
194
196
|
*/
|
|
195
197
|
function onStartup(state) {
|
|
196
198
|
const config = loadConfig();
|
|
199
|
+
if (!(0, workspace_1.findPiscesMarker)()) {
|
|
200
|
+
return { contextInjection: "", greeting: "", config };
|
|
201
|
+
}
|
|
197
202
|
// Run semester detector
|
|
198
203
|
const semesterResult = (0, semester_detector_1.run)();
|
|
199
204
|
if (semesterResult) {
|
|
200
|
-
// Extract context if found (greeting contains it serialised in comment blocks)
|
|
201
205
|
const detection = (0, semester_detector_1.detectSemesterContext)();
|
|
202
206
|
state.semesterContext = detection.context ?? null;
|
|
203
207
|
}
|
|
204
208
|
// Run folder detector
|
|
205
209
|
const folderResult = (0, folder_detector_1.run)();
|
|
206
210
|
state.folderContext = (0, folder_detector_1.detectFolderContext)();
|
|
207
|
-
// Build the combined context injection block
|
|
208
211
|
const contextParts = [];
|
|
209
|
-
if (semesterResult.inject)
|
|
212
|
+
if (semesterResult.inject)
|
|
210
213
|
contextParts.push(semesterResult.inject);
|
|
211
|
-
|
|
212
|
-
if (folderResult.inject) {
|
|
214
|
+
if (folderResult.inject)
|
|
213
215
|
contextParts.push(folderResult.inject);
|
|
214
|
-
}
|
|
215
|
-
// Inject config-derived hints
|
|
216
216
|
contextParts.push(buildConfigInjection(config));
|
|
217
217
|
return {
|
|
218
218
|
contextInjection: contextParts.filter(Boolean).join("\n\n"),
|
|
@@ -223,20 +223,22 @@ function onStartup(state) {
|
|
|
223
223
|
/**
|
|
224
224
|
* onDirectoryChange — called when the user `cd`s to a new directory.
|
|
225
225
|
* Re-runs context detectors so Pi stays accurate.
|
|
226
|
+
* Returns empty result silently when outside a .pisces workspace.
|
|
226
227
|
*/
|
|
227
228
|
function onDirectoryChange(state) {
|
|
229
|
+
if (!(0, workspace_1.findPiscesMarker)()) {
|
|
230
|
+
return { contextInjection: "", message: null };
|
|
231
|
+
}
|
|
228
232
|
const semesterResult = (0, semester_detector_1.run)();
|
|
229
233
|
const folderResult = (0, folder_detector_1.run)();
|
|
230
234
|
const newFolderContext = (0, folder_detector_1.detectFolderContext)();
|
|
231
235
|
const previousProject = state.folderContext?.project?.name;
|
|
232
236
|
const newProject = newFolderContext?.project?.name;
|
|
233
|
-
// Update session state
|
|
234
237
|
state.folderContext = newFolderContext;
|
|
235
238
|
if ((0, semester_detector_1.detectSemesterContext)().context) {
|
|
236
239
|
state.semesterContext = (0, semester_detector_1.detectSemesterContext)().context ?? null;
|
|
237
240
|
}
|
|
238
241
|
const contextParts = [semesterResult.inject, folderResult.inject].filter(Boolean);
|
|
239
|
-
// Notify if we've moved into a different project
|
|
240
242
|
const message = newProject && newProject !== previousProject
|
|
241
243
|
? `📂 Switched to project: **${newProject}** (${newFolderContext.project?.type ?? "unknown"})`
|
|
242
244
|
: null;
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aethrekh/pi-cs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-alpha.0",
|
|
4
4
|
"description": "Pisces — The CS Student Edition for Pi Coding Agent. Your personal AI teaching assistant from homework to thesis.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"academic",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"pi": {
|
|
34
34
|
"extensions": [
|
|
35
|
+
"./extensions/workspace.js",
|
|
35
36
|
"./extensions/semester-detector.js",
|
|
36
37
|
"./extensions/folder-detector.js",
|
|
37
38
|
"./extensions/integrity-guard.js",
|
package/pi-cs.meta.json
CHANGED
package/pi-package.yaml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name: pi-cs
|
|
2
|
-
version: 0.
|
|
2
|
+
version: 0.2.0-alpha.0
|
|
3
3
|
display_name: "pi-cs (Pisces)"
|
|
4
4
|
description: "The CS Student Edition for Pi — Your personal AI teaching assistant for Computer Science, from homework to thesis."
|
|
5
5
|
icon: public/pisces-logo-512.png
|
|
@@ -39,6 +39,11 @@ skills:
|
|
|
39
39
|
|
|
40
40
|
# Extensions that run automatically in the background
|
|
41
41
|
extensions:
|
|
42
|
+
- name: workspace
|
|
43
|
+
path: extensions/workspace.js
|
|
44
|
+
description: "Shared .pisces walk-up utility — required by all other extensions at runtime"
|
|
45
|
+
triggers:
|
|
46
|
+
- on_startup
|
|
42
47
|
- name: semester-detector
|
|
43
48
|
path: extensions/semester-detector.js
|
|
44
49
|
description: "Auto-detects semester context from SEMESTER.md and folder structures"
|