@preapexis/pi-kit 1.0.0 → 1.0.7

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,154 +1,154 @@
1
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
-
3
- type EventContext = Parameters<Parameters<ExtensionAPI["on"]>[1]>[1];
4
-
5
- type AssistantMessageLike = {
6
- role: "assistant";
7
- usage?: {
8
- input?: number;
9
- output?: number;
10
- cacheRead?: number;
11
- cacheWrite?: number;
12
- cost?: {
13
- total?: number;
14
- };
15
- };
16
- };
17
- type UsageTotals = {
18
- input: number;
19
- output: number;
20
- cacheRead: number;
21
- cacheWrite: number;
22
- totalTokens: number;
23
- cost: number;
24
- };
25
-
26
- export default function (pi: ExtensionAPI): void {
27
- const STATUS_KEY = "usage-tracker";
28
- let baseline: UsageTotals = emptyTotals();
29
-
30
- function emptyTotals(): UsageTotals {
31
- return {
32
- input: 0,
33
- output: 0,
34
- cacheRead: 0,
35
- cacheWrite: 0,
36
- totalTokens: 0,
37
- cost: 0
38
- };
39
- }
40
-
41
- function formatNumber(value: number): string {
42
- if (value >= 1_000_000) return `${(value / 1_000_000).toFixed(1)}m`;
43
- if (value >= 1_000) return `${(value / 1_000).toFixed(1)}k`;
44
- return String(value);
45
- }
46
-
47
- function formatCost(value: number): string {
48
- if (value < 0.001) return "$0.000";
49
- return `$${value.toFixed(3)}`;
50
- }
51
-
52
- function subtractTotals(
53
- current: UsageTotals,
54
- base: UsageTotals
55
- ): UsageTotals {
56
- return {
57
- input: Math.max(0, current.input - base.input),
58
- output: Math.max(0, current.output - base.output),
59
- cacheRead: Math.max(0, current.cacheRead - base.cacheRead),
60
- cacheWrite: Math.max(0, current.cacheWrite - base.cacheWrite),
61
- totalTokens: Math.max(0, current.totalTokens - base.totalTokens),
62
- cost: Math.max(0, current.cost - base.cost)
63
- };
64
- }
65
-
66
- function getUsageTotals(ctx: EventContext): UsageTotals {
67
- const totals = emptyTotals();
68
-
69
- for (const entry of ctx.sessionManager.getBranch()) {
70
- if (entry.type !== "message") continue;
71
- if (entry.message.role !== "assistant") continue;
72
-
73
- const message = entry.message as AssistantMessageLike;
74
- const usage = message.usage;
75
-
76
- if (!usage) continue;
77
-
78
- totals.input += usage.input ?? 0;
79
- totals.output += usage.output ?? 0;
80
- totals.cacheRead += usage.cacheRead ?? 0;
81
- totals.cacheWrite += usage.cacheWrite ?? 0;
82
- totals.cost += usage.cost?.total ?? 0;
83
- }
84
-
85
- totals.totalTokens =
86
- totals.input + totals.output + totals.cacheRead + totals.cacheWrite;
87
-
88
- return totals;
89
- }
90
-
91
- function updateStatus(ctx: EventContext): void {
92
- if (!ctx.hasUI) return;
93
-
94
- const totals = subtractTotals(getUsageTotals(ctx), baseline);
95
-
96
- ctx.ui.setStatus(
97
- STATUS_KEY,
98
- `usage: ${formatNumber(totals.totalTokens)} ${formatCost(totals.cost)}`
99
- );
100
- }
101
-
102
- function buildUsageReport(ctx: EventContext): string {
103
- const totals = subtractTotals(getUsageTotals(ctx), baseline);
104
-
105
- return [
106
- "Token and price usage",
107
- "",
108
- `Input tokens: ${totals.input.toLocaleString()}`,
109
- `Output tokens: ${totals.output.toLocaleString()}`,
110
- `Cache read tokens: ${totals.cacheRead.toLocaleString()}`,
111
- `Cache write tokens: ${totals.cacheWrite.toLocaleString()}`,
112
- `Total tokens: ${totals.totalTokens.toLocaleString()}`,
113
- `Estimated cost: ${formatCost(totals.cost)}`,
114
- "",
115
- `Model: ${ctx.model?.id ?? "unknown"}`
116
- ].join("\n");
117
- }
118
-
119
- pi.on("session_start", async (_event, ctx) => {
120
- baseline = emptyTotals();
121
- updateStatus(ctx);
122
- });
123
-
124
- pi.on("message_end", async (event, ctx) => {
125
- if (event.message.role === "assistant") {
126
- updateStatus(ctx);
127
- }
128
- });
129
-
130
- pi.on("model_select", async (_event, ctx) => {
131
- updateStatus(ctx);
132
- });
133
-
134
- pi.registerCommand("usage", {
135
- description: "Show token and price usage for this session",
136
- handler: async (_args, ctx) => {
137
- if (!ctx.hasUI) return;
138
- ctx.ui.notify(buildUsageReport(ctx), "info");
139
- updateStatus(ctx);
140
- }
141
- });
142
-
143
- pi.registerCommand("usage-reset", {
144
- description: "Reset token and price tracker baseline",
145
- handler: async (_args, ctx) => {
146
- baseline = getUsageTotals(ctx);
147
-
148
- if (ctx.hasUI) {
149
- ctx.ui.notify("Usage tracker reset for this session.", "info");
150
- updateStatus(ctx);
151
- }
152
- }
153
- });
154
- }
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ type EventContext = Parameters<Parameters<ExtensionAPI["on"]>[1]>[1];
4
+
5
+ type AssistantMessageLike = {
6
+ role: "assistant";
7
+ usage?: {
8
+ input?: number;
9
+ output?: number;
10
+ cacheRead?: number;
11
+ cacheWrite?: number;
12
+ cost?: {
13
+ total?: number;
14
+ };
15
+ };
16
+ };
17
+ type UsageTotals = {
18
+ input: number;
19
+ output: number;
20
+ cacheRead: number;
21
+ cacheWrite: number;
22
+ totalTokens: number;
23
+ cost: number;
24
+ };
25
+
26
+ export default function (pi: ExtensionAPI): void {
27
+ const STATUS_KEY = "usage-tracker";
28
+ let baseline: UsageTotals = emptyTotals();
29
+
30
+ function emptyTotals(): UsageTotals {
31
+ return {
32
+ input: 0,
33
+ output: 0,
34
+ cacheRead: 0,
35
+ cacheWrite: 0,
36
+ totalTokens: 0,
37
+ cost: 0
38
+ };
39
+ }
40
+
41
+ function formatNumber(value: number): string {
42
+ if (value >= 1_000_000) return `${(value / 1_000_000).toFixed(1)}m`;
43
+ if (value >= 1_000) return `${(value / 1_000).toFixed(1)}k`;
44
+ return String(value);
45
+ }
46
+
47
+ function formatCost(value: number): string {
48
+ if (value < 0.001) return "$0.000";
49
+ return `$${value.toFixed(3)}`;
50
+ }
51
+
52
+ function subtractTotals(
53
+ current: UsageTotals,
54
+ base: UsageTotals
55
+ ): UsageTotals {
56
+ return {
57
+ input: Math.max(0, current.input - base.input),
58
+ output: Math.max(0, current.output - base.output),
59
+ cacheRead: Math.max(0, current.cacheRead - base.cacheRead),
60
+ cacheWrite: Math.max(0, current.cacheWrite - base.cacheWrite),
61
+ totalTokens: Math.max(0, current.totalTokens - base.totalTokens),
62
+ cost: Math.max(0, current.cost - base.cost)
63
+ };
64
+ }
65
+
66
+ function getUsageTotals(ctx: EventContext): UsageTotals {
67
+ const totals = emptyTotals();
68
+
69
+ for (const entry of ctx.sessionManager.getBranch()) {
70
+ if (entry.type !== "message") continue;
71
+ if (entry.message.role !== "assistant") continue;
72
+
73
+ const message = entry.message as AssistantMessageLike;
74
+ const usage = message.usage;
75
+
76
+ if (!usage) continue;
77
+
78
+ totals.input += usage.input ?? 0;
79
+ totals.output += usage.output ?? 0;
80
+ totals.cacheRead += usage.cacheRead ?? 0;
81
+ totals.cacheWrite += usage.cacheWrite ?? 0;
82
+ totals.cost += usage.cost?.total ?? 0;
83
+ }
84
+
85
+ totals.totalTokens =
86
+ totals.input + totals.output + totals.cacheRead + totals.cacheWrite;
87
+
88
+ return totals;
89
+ }
90
+
91
+ function updateStatus(ctx: EventContext): void {
92
+ if (!ctx.hasUI) return;
93
+
94
+ const totals = subtractTotals(getUsageTotals(ctx), baseline);
95
+
96
+ ctx.ui.setStatus(
97
+ STATUS_KEY,
98
+ `usage: ${formatNumber(totals.totalTokens)} ${formatCost(totals.cost)}`
99
+ );
100
+ }
101
+
102
+ function buildUsageReport(ctx: EventContext): string {
103
+ const totals = subtractTotals(getUsageTotals(ctx), baseline);
104
+
105
+ return [
106
+ "Token and price usage",
107
+ "",
108
+ `Input tokens: ${totals.input.toLocaleString()}`,
109
+ `Output tokens: ${totals.output.toLocaleString()}`,
110
+ `Cache read tokens: ${totals.cacheRead.toLocaleString()}`,
111
+ `Cache write tokens: ${totals.cacheWrite.toLocaleString()}`,
112
+ `Total tokens: ${totals.totalTokens.toLocaleString()}`,
113
+ `Estimated cost: ${formatCost(totals.cost)}`,
114
+ "",
115
+ `Model: ${ctx.model?.id ?? "unknown"}`
116
+ ].join("\n");
117
+ }
118
+
119
+ pi.on("session_start", async (_event, ctx) => {
120
+ baseline = emptyTotals();
121
+ updateStatus(ctx);
122
+ });
123
+
124
+ pi.on("message_end", async (event, ctx) => {
125
+ if (event.message.role === "assistant") {
126
+ updateStatus(ctx);
127
+ }
128
+ });
129
+
130
+ pi.on("model_select", async (_event, ctx) => {
131
+ updateStatus(ctx);
132
+ });
133
+
134
+ pi.registerCommand("usage", {
135
+ description: "Show token and price usage for this session",
136
+ handler: async (_args, ctx) => {
137
+ if (!ctx.hasUI) return;
138
+ ctx.ui.notify(buildUsageReport(ctx), "info");
139
+ updateStatus(ctx);
140
+ }
141
+ });
142
+
143
+ pi.registerCommand("usage-reset", {
144
+ description: "Reset token and price tracker baseline",
145
+ handler: async (_args, ctx) => {
146
+ baseline = getUsageTotals(ctx);
147
+
148
+ if (ctx.hasUI) {
149
+ ctx.ui.notify("Usage tracker reset for this session.", "info");
150
+ updateStatus(ctx);
151
+ }
152
+ }
153
+ });
154
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preapexis/pi-kit",
3
- "version": "1.0.0",
3
+ "version": "1.0.7",
4
4
  "description": "Personal Pi coding-agent kit with safety extensions, status UI, prompt workflows, skills, and themes.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -32,10 +32,14 @@
32
32
  "type": "module",
33
33
  "scripts": {
34
34
  "test": "vitest run",
35
- "test:watch": "vitest"
35
+ "test:watch": "vitest",
36
+ "release": "npm version patch && git push --follow-tags"
36
37
  },
37
38
  "devDependencies": {
38
39
  "typescript": "^5.5.0",
39
40
  "vitest": "^2.0.0"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
40
44
  }
41
45
  }
package/prompts/init.md CHANGED
@@ -1,98 +1,98 @@
1
- # Initialize Repository Understanding
2
-
3
- Initialize your understanding of this repository.
4
-
5
- Do not edit files.
6
-
7
- Your job is to inspect the project and produce a clear onboarding report for future work.
8
-
9
- If the repository is large, inspect the most important files first and clearly mention what was not inspected.
10
-
11
- ## Steps
12
-
13
- 1. Read the most important project files first:
14
- - README.md
15
- - AGENTS.md
16
- - package.json / pyproject.toml / go.mod / Cargo.toml / pom.xml / build.gradle
17
- - CONTRIBUTING.md
18
- - docs/
19
- - .github/workflows/
20
- - docker-compose.yml / Dockerfile
21
- - existing test configuration
22
-
23
- 2. Identify the project structure:
24
- - main application entry points
25
- - important directories
26
- - test locations
27
- - config files
28
- - generated/build output directories
29
- - files that should be treated carefully
30
-
31
- 3. Detect the development workflow:
32
- - install command
33
- - dev command
34
- - build command
35
- - test command
36
- - lint command
37
- - typecheck command
38
- - formatting command
39
-
40
- 4. Identify safety risks:
41
- - secrets or env files
42
- - deployment files
43
- - database migrations
44
- - production config
45
- - generated files
46
- - lockfiles
47
- - destructive scripts
48
- - commands that should require confirmation
49
-
50
- 5. Infer coding conventions:
51
- - language/framework
52
- - naming style
53
- - error handling style
54
- - testing style
55
- - API conventions
56
- - dependency management
57
-
58
- ## Output
59
-
60
- Return a repository onboarding report with these sections:
61
-
62
- # Repository Summary
63
-
64
- Briefly explain what this project appears to do.
65
-
66
- # Tech Stack
67
-
68
- List the detected languages, frameworks, libraries, and tools.
69
-
70
- # Project Map
71
-
72
- Explain the important folders and files.
73
-
74
- # Common Commands
75
-
76
- List install, dev, build, test, lint, typecheck, and format commands if found.
77
-
78
- # Safety Notes
79
-
80
- List files, directories, and commands that should be treated carefully.
81
-
82
- # Coding Conventions
83
-
84
- Summarize the project’s apparent patterns.
85
-
86
- # Recommended Agent Rules
87
-
88
- Suggest repo-specific rules that should be added to AGENTS.md or team instructions.
89
-
90
- # Open Questions
91
-
92
- List anything unclear or missing.
93
-
94
- # Inspection Notes
95
-
96
- Mention important files or areas that were not inspected.
97
-
98
- Do not modify the repository unless I explicitly ask.
1
+ # Initialize Repository Understanding
2
+
3
+ Initialize your understanding of this repository.
4
+
5
+ Do not edit files.
6
+
7
+ Your job is to inspect the project and produce a clear onboarding report for future work.
8
+
9
+ If the repository is large, inspect the most important files first and clearly mention what was not inspected.
10
+
11
+ ## Steps
12
+
13
+ 1. Read the most important project files first:
14
+ - README.md
15
+ - AGENTS.md
16
+ - package.json / pyproject.toml / go.mod / Cargo.toml / pom.xml / build.gradle
17
+ - CONTRIBUTING.md
18
+ - docs/
19
+ - .github/workflows/
20
+ - docker-compose.yml / Dockerfile
21
+ - existing test configuration
22
+
23
+ 2. Identify the project structure:
24
+ - main application entry points
25
+ - important directories
26
+ - test locations
27
+ - config files
28
+ - generated/build output directories
29
+ - files that should be treated carefully
30
+
31
+ 3. Detect the development workflow:
32
+ - install command
33
+ - dev command
34
+ - build command
35
+ - test command
36
+ - lint command
37
+ - typecheck command
38
+ - formatting command
39
+
40
+ 4. Identify safety risks:
41
+ - secrets or env files
42
+ - deployment files
43
+ - database migrations
44
+ - production config
45
+ - generated files
46
+ - lockfiles
47
+ - destructive scripts
48
+ - commands that should require confirmation
49
+
50
+ 5. Infer coding conventions:
51
+ - language/framework
52
+ - naming style
53
+ - error handling style
54
+ - testing style
55
+ - API conventions
56
+ - dependency management
57
+
58
+ ## Output
59
+
60
+ Return a repository onboarding report with these sections:
61
+
62
+ # Repository Summary
63
+
64
+ Briefly explain what this project appears to do.
65
+
66
+ # Tech Stack
67
+
68
+ List the detected languages, frameworks, libraries, and tools.
69
+
70
+ # Project Map
71
+
72
+ Explain the important folders and files.
73
+
74
+ # Common Commands
75
+
76
+ List install, dev, build, test, lint, typecheck, and format commands if found.
77
+
78
+ # Safety Notes
79
+
80
+ List files, directories, and commands that should be treated carefully.
81
+
82
+ # Coding Conventions
83
+
84
+ Summarize the project’s apparent patterns.
85
+
86
+ # Recommended Agent Rules
87
+
88
+ Suggest repo-specific rules that should be added to AGENTS.md or team instructions.
89
+
90
+ # Open Questions
91
+
92
+ List anything unclear or missing.
93
+
94
+ # Inspection Notes
95
+
96
+ Mention important files or areas that were not inspected.
97
+
98
+ Do not modify the repository unless I explicitly ask.
package/settings.json CHANGED
@@ -1,4 +1,4 @@
1
- {
2
- "theme": "neon-guardian",
3
- "defaultProjectTrust": "ask"
4
- }
1
+ {
2
+ "theme": "neon-guardian",
3
+ "defaultProjectTrust": "ask"
4
+ }