@xynogen/pix-core 0.4.2 → 0.4.4
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 +2 -2
- package/package.json +1 -1
- package/src/once.test.ts +78 -26
package/README.md
CHANGED
|
@@ -18,10 +18,10 @@ Pi activates extensions per installed package via each package's `pi.extensions`
|
|
|
18
18
|
| `pix-footer` | Status bar: mode / git branch / model / cost / live TPS |
|
|
19
19
|
| `pix-models` | `/models` — enhanced model picker with BenchLM rank, context, cost |
|
|
20
20
|
| `pix-update` | `/update` — self-update Pi + refresh extensions |
|
|
21
|
-
| `pix-commands` | `/
|
|
21
|
+
| `pix-commands` | `/clear` slash command |
|
|
22
22
|
| `pix-diagnostics` | Compact LSP diagnostic widget |
|
|
23
23
|
| `pix-prompts` | System-prompt injection (AGENTS.md + repo directive files) |
|
|
24
|
-
| `pix-skills` | Agent skill loader (`read_skills` tool +
|
|
24
|
+
| `pix-skills` | Agent skill loader (`read_skills` tool + 28 bundled skills) |
|
|
25
25
|
| `pix-nudge` | Tool + capability nudge hooks |
|
|
26
26
|
|
|
27
27
|
**Tool suite** (drop-in replacements for Pi's built-in tools)
|
package/package.json
CHANGED
package/src/once.test.ts
CHANGED
|
@@ -1,71 +1,112 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it } from "bun:test";
|
|
2
2
|
import registerTodo from "@xynogen/pix-todo/src/todo.ts";
|
|
3
3
|
|
|
4
|
-
// Mirror of the per-
|
|
4
|
+
// Mirror of the per-instance guard. pix-core does not own once.ts (each member
|
|
5
5
|
// duplicates it to stay cross-dep-free), so we re-declare the contract here and
|
|
6
6
|
// assert the dedupe semantics that the aggregator relies on.
|
|
7
|
-
function once(key: string, fn: () => void): void {
|
|
8
|
-
const g = globalThis as {
|
|
9
|
-
const
|
|
7
|
+
function once(pi: object, key: string, fn: () => void): void {
|
|
8
|
+
const g = globalThis as { __pixOnce?: WeakMap<object, Set<string>> };
|
|
9
|
+
const registry = (g.__pixOnce ??= new WeakMap<object, Set<string>>());
|
|
10
|
+
let loaded = registry.get(pi);
|
|
11
|
+
if (!loaded) {
|
|
12
|
+
loaded = new Set<string>();
|
|
13
|
+
registry.set(pi, loaded);
|
|
14
|
+
}
|
|
10
15
|
if (loaded.has(key)) return;
|
|
11
16
|
loaded.add(key);
|
|
12
17
|
fn();
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
afterEach(() => {
|
|
16
|
-
delete (globalThis as {
|
|
21
|
+
delete (globalThis as { __pixOnce?: WeakMap<object, Set<string>> }).__pixOnce;
|
|
17
22
|
});
|
|
18
23
|
|
|
19
24
|
describe("once", () => {
|
|
20
25
|
it("runs the factory on first invocation", () => {
|
|
26
|
+
const pi = {};
|
|
21
27
|
let calls = 0;
|
|
22
|
-
once("pix-footer", () => {
|
|
28
|
+
once(pi, "pix-footer", () => {
|
|
23
29
|
calls++;
|
|
24
30
|
});
|
|
25
31
|
expect(calls).toBe(1);
|
|
26
32
|
});
|
|
27
33
|
|
|
28
|
-
it("skips repeated invocations of the same key", () => {
|
|
34
|
+
it("skips repeated invocations of the same key on the same pi", () => {
|
|
35
|
+
const pi = {};
|
|
29
36
|
let calls = 0;
|
|
30
37
|
const reg = () => {
|
|
31
38
|
calls++;
|
|
32
39
|
};
|
|
33
|
-
once("pix-footer", reg);
|
|
34
|
-
once("pix-footer", reg);
|
|
35
|
-
once("pix-footer", reg);
|
|
40
|
+
once(pi, "pix-footer", reg);
|
|
41
|
+
once(pi, "pix-footer", reg);
|
|
42
|
+
once(pi, "pix-footer", reg);
|
|
36
43
|
expect(calls).toBe(1);
|
|
37
44
|
});
|
|
38
45
|
|
|
39
|
-
it("isolates distinct keys", () => {
|
|
46
|
+
it("isolates distinct keys on the same pi", () => {
|
|
47
|
+
const pi = {};
|
|
40
48
|
const seen: string[] = [];
|
|
41
|
-
once("pix-footer", () => seen.push("footer"));
|
|
42
|
-
once("pix-welcome", () => seen.push("welcome"));
|
|
49
|
+
once(pi, "pix-footer", () => seen.push("footer"));
|
|
50
|
+
once(pi, "pix-welcome", () => seen.push("welcome"));
|
|
43
51
|
expect(seen).toEqual(["footer", "welcome"]);
|
|
44
52
|
});
|
|
45
53
|
|
|
46
|
-
it("shares the registry across calls via globalThis", () => {
|
|
54
|
+
it("shares the registry across calls via globalThis (same pi)", () => {
|
|
55
|
+
const pi = {};
|
|
47
56
|
let calls = 0;
|
|
48
|
-
once("pix-skills", () => {
|
|
57
|
+
once(pi, "pix-skills", () => {
|
|
49
58
|
calls++;
|
|
50
59
|
});
|
|
51
60
|
// A second loader pass (e.g. standalone install after pix-core) reuses
|
|
52
|
-
// the same globalThis registry and must not re-run.
|
|
53
|
-
once("pix-skills", () => {
|
|
61
|
+
// the same globalThis registry for the same pi and must not re-run.
|
|
62
|
+
once(pi, "pix-skills", () => {
|
|
54
63
|
calls++;
|
|
55
64
|
});
|
|
56
65
|
expect(calls).toBe(1);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("re-runs for a new pi instance with the same key (/new rehydration)", () => {
|
|
69
|
+
const pi1 = {};
|
|
70
|
+
const pi2 = {};
|
|
71
|
+
let calls = 0;
|
|
72
|
+
once(pi1, "pix-footer", () => {
|
|
73
|
+
calls++;
|
|
74
|
+
});
|
|
75
|
+
// pi2 is a fresh instance (as built by Pi on /new, /resume, /fork, /reload).
|
|
76
|
+
// The factory must run again — this is the rehydration guarantee.
|
|
77
|
+
once(pi2, "pix-footer", () => {
|
|
78
|
+
calls++;
|
|
79
|
+
});
|
|
80
|
+
expect(calls).toBe(2);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("same key on two different pi instances dedupes within each instance", () => {
|
|
84
|
+
const pi1 = {};
|
|
85
|
+
const pi2 = {};
|
|
86
|
+
let calls1 = 0;
|
|
87
|
+
let calls2 = 0;
|
|
88
|
+
once(pi1, "pix-welcome", () => {
|
|
89
|
+
calls1++;
|
|
90
|
+
});
|
|
91
|
+
once(pi1, "pix-welcome", () => {
|
|
92
|
+
calls1++;
|
|
93
|
+
}); // second on pi1 → skip
|
|
94
|
+
once(pi2, "pix-welcome", () => {
|
|
95
|
+
calls2++;
|
|
96
|
+
});
|
|
97
|
+
once(pi2, "pix-welcome", () => {
|
|
98
|
+
calls2++;
|
|
99
|
+
}); // second on pi2 → skip
|
|
100
|
+
expect(calls1).toBe(1); // deduped within pi1
|
|
101
|
+
expect(calls2).toBe(1); // deduped within pi2
|
|
62
102
|
});
|
|
63
103
|
});
|
|
64
104
|
|
|
65
105
|
// Behavior pin: prove a REAL guarded member dedupes when its factory runs
|
|
66
|
-
// twice — the exact scenario the aggregator creates when a
|
|
67
|
-
// both via pix-core (this boots it) and standalone (Pi boots
|
|
68
|
-
// member must register its tool only once or Pi reports a
|
|
106
|
+
// twice against the SAME pi — the exact scenario the aggregator creates when a
|
|
107
|
+
// tool is installed both via pix-core (this boots it) and standalone (Pi boots
|
|
108
|
+
// it again). The member must register its tool only once or Pi reports a
|
|
109
|
+
// tool conflict.
|
|
69
110
|
describe("member factory dedupe (pix-todo)", () => {
|
|
70
111
|
function makeHost() {
|
|
71
112
|
const toolNames: string[] = [];
|
|
@@ -79,7 +120,7 @@ describe("member factory dedupe (pix-todo)", () => {
|
|
|
79
120
|
return { pi, toolNames };
|
|
80
121
|
}
|
|
81
122
|
|
|
82
|
-
it("registers the tool once across core + standalone activation", () => {
|
|
123
|
+
it("registers the tool once across core + standalone activation (same pi)", () => {
|
|
83
124
|
const { pi, toolNames } = makeHost();
|
|
84
125
|
// First pass: pix-core's aggregator invokes the member factory.
|
|
85
126
|
registerTodo(pi);
|
|
@@ -88,4 +129,15 @@ describe("member factory dedupe (pix-todo)", () => {
|
|
|
88
129
|
registerTodo(pi);
|
|
89
130
|
expect(toolNames).toEqual(["todo"]);
|
|
90
131
|
});
|
|
132
|
+
|
|
133
|
+
it("registers the tool again for a fresh pi instance (/new rehydration)", () => {
|
|
134
|
+
const { pi: pi1, toolNames: tools1 } = makeHost();
|
|
135
|
+
const { pi: pi2, toolNames: tools2 } = makeHost();
|
|
136
|
+
// First session.
|
|
137
|
+
registerTodo(pi1);
|
|
138
|
+
// /new: a fresh pi is built; factory must run again.
|
|
139
|
+
registerTodo(pi2);
|
|
140
|
+
expect(tools1).toEqual(["todo"]);
|
|
141
|
+
expect(tools2).toEqual(["todo"]);
|
|
142
|
+
});
|
|
91
143
|
});
|