aiblueprint-cli 1.4.13 ā 1.4.15
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/claude-code-config/scripts/CLAUDE.md +50 -0
- package/claude-code-config/scripts/biome.json +37 -0
- package/claude-code-config/scripts/bun.lockb +0 -0
- package/claude-code-config/scripts/package.json +39 -0
- package/claude-code-config/scripts/statusline/__tests__/context.test.ts +229 -0
- package/claude-code-config/scripts/statusline/__tests__/formatters.test.ts +108 -0
- package/claude-code-config/scripts/statusline/__tests__/statusline.test.ts +309 -0
- package/claude-code-config/scripts/statusline/data/.gitignore +8 -0
- package/claude-code-config/scripts/statusline/data/.gitkeep +0 -0
- package/claude-code-config/scripts/statusline/defaults.json +4 -0
- package/claude-code-config/scripts/statusline/docs/ARCHITECTURE.md +166 -0
- package/claude-code-config/scripts/statusline/fixtures/mock-transcript.jsonl +4 -0
- package/claude-code-config/scripts/statusline/fixtures/test-input.json +35 -0
- package/claude-code-config/scripts/statusline/src/index.ts +74 -0
- package/claude-code-config/scripts/statusline/src/lib/config-types.ts +4 -0
- package/claude-code-config/scripts/statusline/src/lib/menu-factories.ts +224 -0
- package/claude-code-config/scripts/statusline/src/lib/presets.ts +177 -0
- package/claude-code-config/scripts/statusline/src/lib/render-pure.ts +341 -21
- package/claude-code-config/scripts/statusline/src/lib/utils.ts +15 -0
- package/claude-code-config/scripts/statusline/src/tests/spend-v2.test.ts +306 -0
- package/claude-code-config/scripts/statusline/statusline.config.json +25 -39
- package/claude-code-config/scripts/statusline/test-with-fixtures.ts +37 -0
- package/claude-code-config/scripts/statusline/test.ts +20 -0
- package/claude-code-config/scripts/tsconfig.json +27 -0
- package/dist/cli.js +16 -11
- package/package.json +1 -1
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
3
|
+
import { existsSync, rmSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
const TEST_DB_PATH = join(import.meta.dir, "..", "..", "data", "test.db");
|
|
7
|
+
|
|
8
|
+
describe("SQLite Delta Tracking", () => {
|
|
9
|
+
let db: Database;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
if (existsSync(TEST_DB_PATH)) {
|
|
13
|
+
rmSync(TEST_DB_PATH);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
db = new Database(TEST_DB_PATH);
|
|
17
|
+
|
|
18
|
+
db.run(`
|
|
19
|
+
CREATE TABLE sessions (
|
|
20
|
+
session_id TEXT PRIMARY KEY,
|
|
21
|
+
total_cost REAL NOT NULL DEFAULT 0,
|
|
22
|
+
cwd TEXT NOT NULL,
|
|
23
|
+
date TEXT NOT NULL,
|
|
24
|
+
duration_ms INTEGER NOT NULL DEFAULT 0,
|
|
25
|
+
lines_added INTEGER NOT NULL DEFAULT 0,
|
|
26
|
+
lines_removed INTEGER NOT NULL DEFAULT 0,
|
|
27
|
+
last_resets_at TEXT
|
|
28
|
+
)
|
|
29
|
+
`);
|
|
30
|
+
|
|
31
|
+
db.run(`
|
|
32
|
+
CREATE TABLE session_period_tracking (
|
|
33
|
+
session_id TEXT NOT NULL,
|
|
34
|
+
period_id TEXT NOT NULL,
|
|
35
|
+
counted_cost REAL NOT NULL DEFAULT 0,
|
|
36
|
+
last_session_cost REAL NOT NULL DEFAULT 0,
|
|
37
|
+
PRIMARY KEY (session_id, period_id)
|
|
38
|
+
)
|
|
39
|
+
`);
|
|
40
|
+
|
|
41
|
+
db.run(`
|
|
42
|
+
CREATE TABLE periods (
|
|
43
|
+
period_id TEXT PRIMARY KEY,
|
|
44
|
+
total_cost REAL NOT NULL DEFAULT 0,
|
|
45
|
+
utilization INTEGER NOT NULL DEFAULT 0,
|
|
46
|
+
date TEXT NOT NULL
|
|
47
|
+
)
|
|
48
|
+
`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
afterEach(() => {
|
|
52
|
+
db.close();
|
|
53
|
+
if (existsSync(TEST_DB_PATH)) {
|
|
54
|
+
rmSync(TEST_DB_PATH);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("New session: full cost added to period", () => {
|
|
59
|
+
const sessionId = "session-1";
|
|
60
|
+
const periodId = "2025-12-09T10:00:00.000Z";
|
|
61
|
+
const sessionCost = 10.0;
|
|
62
|
+
|
|
63
|
+
db.run(
|
|
64
|
+
"INSERT INTO sessions (session_id, total_cost, cwd, date, last_resets_at) VALUES (?, ?, ?, ?, ?)",
|
|
65
|
+
[sessionId, sessionCost, "/test", "2025-12-09", periodId],
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
db.run(
|
|
69
|
+
"INSERT INTO session_period_tracking (session_id, period_id, counted_cost, last_session_cost) VALUES (?, ?, ?, ?)",
|
|
70
|
+
[sessionId, periodId, sessionCost, sessionCost],
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
db.run(
|
|
74
|
+
"INSERT INTO periods (period_id, total_cost, utilization, date) VALUES (?, ?, ?, ?)",
|
|
75
|
+
[periodId, sessionCost, 0, "2025-12-09"],
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const period = db
|
|
79
|
+
.query<{ total_cost: number }, [string]>(
|
|
80
|
+
"SELECT total_cost FROM periods WHERE period_id = ?",
|
|
81
|
+
)
|
|
82
|
+
.get(periodId);
|
|
83
|
+
|
|
84
|
+
expect(period?.total_cost).toBe(10.0);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("Continued session: only delta added to period", () => {
|
|
88
|
+
const sessionId = "session-1";
|
|
89
|
+
const periodId = "2025-12-09T10:00:00.000Z";
|
|
90
|
+
|
|
91
|
+
db.run(
|
|
92
|
+
"INSERT INTO sessions (session_id, total_cost, cwd, date, last_resets_at) VALUES (?, ?, ?, ?, ?)",
|
|
93
|
+
[sessionId, 10.0, "/test", "2025-12-09", periodId],
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
db.run(
|
|
97
|
+
"INSERT INTO session_period_tracking (session_id, period_id, counted_cost, last_session_cost) VALUES (?, ?, ?, ?)",
|
|
98
|
+
[sessionId, periodId, 10.0, 10.0],
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
db.run(
|
|
102
|
+
"INSERT INTO periods (period_id, total_cost, utilization, date) VALUES (?, ?, ?, ?)",
|
|
103
|
+
[periodId, 10.0, 0, "2025-12-09"],
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const newSessionCost = 24.0;
|
|
107
|
+
const delta = newSessionCost - 10.0;
|
|
108
|
+
|
|
109
|
+
db.run("UPDATE sessions SET total_cost = ? WHERE session_id = ?", [
|
|
110
|
+
newSessionCost,
|
|
111
|
+
sessionId,
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
const tracking = db
|
|
115
|
+
.query<
|
|
116
|
+
{ counted_cost: number; last_session_cost: number },
|
|
117
|
+
[string, string]
|
|
118
|
+
>(
|
|
119
|
+
"SELECT counted_cost, last_session_cost FROM session_period_tracking WHERE session_id = ? AND period_id = ?",
|
|
120
|
+
)
|
|
121
|
+
.get(sessionId, periodId);
|
|
122
|
+
|
|
123
|
+
const newCountedCost = (tracking?.counted_cost ?? 0) + delta;
|
|
124
|
+
|
|
125
|
+
db.run(
|
|
126
|
+
"UPDATE session_period_tracking SET counted_cost = ?, last_session_cost = ? WHERE session_id = ? AND period_id = ?",
|
|
127
|
+
[newCountedCost, newSessionCost, sessionId, periodId],
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
db.run(
|
|
131
|
+
"UPDATE periods SET total_cost = total_cost + ? WHERE period_id = ?",
|
|
132
|
+
[delta, periodId],
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const period = db
|
|
136
|
+
.query<{ total_cost: number }, [string]>(
|
|
137
|
+
"SELECT total_cost FROM periods WHERE period_id = ?",
|
|
138
|
+
)
|
|
139
|
+
.get(periodId);
|
|
140
|
+
const updatedTracking = db
|
|
141
|
+
.query<{ counted_cost: number }, [string, string]>(
|
|
142
|
+
"SELECT counted_cost FROM session_period_tracking WHERE session_id = ? AND period_id = ?",
|
|
143
|
+
)
|
|
144
|
+
.get(sessionId, periodId);
|
|
145
|
+
|
|
146
|
+
expect(period?.total_cost).toBe(24.0);
|
|
147
|
+
expect(updatedTracking?.counted_cost).toBe(24.0);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("Session spanning periods: only new delta in new period", () => {
|
|
151
|
+
const sessionId = "session-1";
|
|
152
|
+
const periodA = "2025-12-09T05:00:00.000Z";
|
|
153
|
+
const periodB = "2025-12-09T10:00:00.000Z";
|
|
154
|
+
|
|
155
|
+
db.run(
|
|
156
|
+
"INSERT INTO sessions (session_id, total_cost, cwd, date, last_resets_at) VALUES (?, ?, ?, ?, ?)",
|
|
157
|
+
[sessionId, 10.0, "/test", "2025-12-09", periodA],
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
db.run(
|
|
161
|
+
"INSERT INTO session_period_tracking (session_id, period_id, counted_cost, last_session_cost) VALUES (?, ?, ?, ?)",
|
|
162
|
+
[sessionId, periodA, 10.0, 10.0],
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
db.run(
|
|
166
|
+
"INSERT INTO periods (period_id, total_cost, utilization, date) VALUES (?, ?, ?, ?)",
|
|
167
|
+
[periodA, 10.0, 0, "2025-12-09"],
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const newSessionCost = 24.0;
|
|
171
|
+
const session = db
|
|
172
|
+
.query<{ total_cost: number }, [string]>(
|
|
173
|
+
"SELECT total_cost FROM sessions WHERE session_id = ?",
|
|
174
|
+
)
|
|
175
|
+
.get(sessionId);
|
|
176
|
+
const delta = newSessionCost - (session?.total_cost ?? 0);
|
|
177
|
+
|
|
178
|
+
db.run(
|
|
179
|
+
"UPDATE sessions SET total_cost = ?, last_resets_at = ? WHERE session_id = ?",
|
|
180
|
+
[newSessionCost, periodB, sessionId],
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
db.run(
|
|
184
|
+
"INSERT INTO session_period_tracking (session_id, period_id, counted_cost, last_session_cost) VALUES (?, ?, ?, ?)",
|
|
185
|
+
[sessionId, periodB, delta, newSessionCost],
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
db.run(
|
|
189
|
+
"INSERT OR IGNORE INTO periods (period_id, total_cost, utilization, date) VALUES (?, ?, ?, ?)",
|
|
190
|
+
[periodB, 0, 0, "2025-12-09"],
|
|
191
|
+
);
|
|
192
|
+
db.run(
|
|
193
|
+
"UPDATE periods SET total_cost = total_cost + ? WHERE period_id = ?",
|
|
194
|
+
[delta, periodB],
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
const periodACost = db
|
|
198
|
+
.query<{ total_cost: number }, [string]>(
|
|
199
|
+
"SELECT total_cost FROM periods WHERE period_id = ?",
|
|
200
|
+
)
|
|
201
|
+
.get(periodA);
|
|
202
|
+
const periodBCost = db
|
|
203
|
+
.query<{ total_cost: number }, [string]>(
|
|
204
|
+
"SELECT total_cost FROM periods WHERE period_id = ?",
|
|
205
|
+
)
|
|
206
|
+
.get(periodB);
|
|
207
|
+
const trackingA = db
|
|
208
|
+
.query<{ counted_cost: number }, [string, string]>(
|
|
209
|
+
"SELECT counted_cost FROM session_period_tracking WHERE session_id = ? AND period_id = ?",
|
|
210
|
+
)
|
|
211
|
+
.get(sessionId, periodA);
|
|
212
|
+
const trackingB = db
|
|
213
|
+
.query<{ counted_cost: number }, [string, string]>(
|
|
214
|
+
"SELECT counted_cost FROM session_period_tracking WHERE session_id = ? AND period_id = ?",
|
|
215
|
+
)
|
|
216
|
+
.get(sessionId, periodB);
|
|
217
|
+
|
|
218
|
+
expect(periodACost?.total_cost).toBe(10.0);
|
|
219
|
+
expect(periodBCost?.total_cost).toBe(14.0);
|
|
220
|
+
expect(trackingA?.counted_cost).toBe(10.0);
|
|
221
|
+
expect(trackingB?.counted_cost).toBe(14.0);
|
|
222
|
+
|
|
223
|
+
expect(
|
|
224
|
+
(periodACost?.total_cost ?? 0) + (periodBCost?.total_cost ?? 0),
|
|
225
|
+
).toBe(24.0);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("Multiple sessions in same period: costs sum correctly", () => {
|
|
229
|
+
const periodId = "2025-12-09T10:00:00.000Z";
|
|
230
|
+
|
|
231
|
+
db.run(
|
|
232
|
+
"INSERT INTO periods (period_id, total_cost, utilization, date) VALUES (?, ?, ?, ?)",
|
|
233
|
+
[periodId, 0, 0, "2025-12-09"],
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
const sessions = [
|
|
237
|
+
{ id: "session-1", cost: 10.0 },
|
|
238
|
+
{ id: "session-2", cost: 15.0 },
|
|
239
|
+
{ id: "session-3", cost: 8.0 },
|
|
240
|
+
];
|
|
241
|
+
|
|
242
|
+
for (const session of sessions) {
|
|
243
|
+
db.run(
|
|
244
|
+
"INSERT INTO sessions (session_id, total_cost, cwd, date, last_resets_at) VALUES (?, ?, ?, ?, ?)",
|
|
245
|
+
[session.id, session.cost, "/test", "2025-12-09", periodId],
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
db.run(
|
|
249
|
+
"INSERT INTO session_period_tracking (session_id, period_id, counted_cost, last_session_cost) VALUES (?, ?, ?, ?)",
|
|
250
|
+
[session.id, periodId, session.cost, session.cost],
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
db.run(
|
|
254
|
+
"UPDATE periods SET total_cost = total_cost + ? WHERE period_id = ?",
|
|
255
|
+
[session.cost, periodId],
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const period = db
|
|
260
|
+
.query<{ total_cost: number }, [string]>(
|
|
261
|
+
"SELECT total_cost FROM periods WHERE period_id = ?",
|
|
262
|
+
)
|
|
263
|
+
.get(periodId);
|
|
264
|
+
|
|
265
|
+
expect(period?.total_cost).toBe(33.0);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("No double counting: continuing old session after restart", () => {
|
|
269
|
+
const sessionId = "session-1";
|
|
270
|
+
const periodId = "2025-12-09T10:00:00.000Z";
|
|
271
|
+
|
|
272
|
+
db.run(
|
|
273
|
+
"INSERT INTO sessions (session_id, total_cost, cwd, date, last_resets_at) VALUES (?, ?, ?, ?, ?)",
|
|
274
|
+
[sessionId, 10.0, "/test", "2025-12-09", periodId],
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
db.run(
|
|
278
|
+
"INSERT INTO session_period_tracking (session_id, period_id, counted_cost, last_session_cost) VALUES (?, ?, ?, ?)",
|
|
279
|
+
[sessionId, periodId, 10.0, 10.0],
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
db.run(
|
|
283
|
+
"INSERT INTO periods (period_id, total_cost, utilization, date) VALUES (?, ?, ?, ?)",
|
|
284
|
+
[periodId, 10.0, 0, "2025-12-09"],
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
const tracking = db
|
|
288
|
+
.query<{ last_session_cost: number }, [string, string]>(
|
|
289
|
+
"SELECT last_session_cost FROM session_period_tracking WHERE session_id = ? AND period_id = ?",
|
|
290
|
+
)
|
|
291
|
+
.get(sessionId, periodId);
|
|
292
|
+
|
|
293
|
+
const currentSessionCost = 10.0;
|
|
294
|
+
const delta = currentSessionCost - (tracking?.last_session_cost ?? 0);
|
|
295
|
+
|
|
296
|
+
expect(delta).toBe(0);
|
|
297
|
+
|
|
298
|
+
const period = db
|
|
299
|
+
.query<{ total_cost: number }, [string]>(
|
|
300
|
+
"SELECT total_cost FROM periods WHERE period_id = ?",
|
|
301
|
+
)
|
|
302
|
+
.get(periodId);
|
|
303
|
+
|
|
304
|
+
expect(period?.total_cost).toBe(10.0);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
+
"features": {
|
|
3
|
+
"usageLimits": false,
|
|
4
|
+
"spendTracking": false
|
|
5
|
+
},
|
|
2
6
|
"oneLine": true,
|
|
3
|
-
"showSonnetModel":
|
|
7
|
+
"showSonnetModel": false,
|
|
4
8
|
"pathDisplayMode": "truncated",
|
|
5
9
|
"git": {
|
|
6
10
|
"enabled": true,
|
|
@@ -10,21 +14,12 @@
|
|
|
10
14
|
"showStaged": true,
|
|
11
15
|
"showUnstaged": true
|
|
12
16
|
},
|
|
13
|
-
"separator": "
|
|
17
|
+
"separator": "ā¢",
|
|
14
18
|
"session": {
|
|
15
19
|
"infoSeparator": null,
|
|
16
|
-
"cost": {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
},
|
|
20
|
-
"duration": {
|
|
21
|
-
"enabled": true
|
|
22
|
-
},
|
|
23
|
-
"tokens": {
|
|
24
|
-
"enabled": true,
|
|
25
|
-
"showMax": false,
|
|
26
|
-
"showDecimals": false
|
|
27
|
-
},
|
|
20
|
+
"cost": { "enabled": true, "format": "decimal1" },
|
|
21
|
+
"duration": { "enabled": true },
|
|
22
|
+
"tokens": { "enabled": true, "showMax": false, "showDecimals": false },
|
|
28
23
|
"percentage": {
|
|
29
24
|
"enabled": true,
|
|
30
25
|
"showValue": true,
|
|
@@ -41,53 +36,44 @@
|
|
|
41
36
|
"usePayloadContextWindow": true,
|
|
42
37
|
"maxContextTokens": 200000,
|
|
43
38
|
"autocompactBufferTokens": 45000,
|
|
44
|
-
"useUsableContextOnly":
|
|
39
|
+
"useUsableContextOnly": true,
|
|
45
40
|
"overheadTokens": 0
|
|
46
41
|
},
|
|
47
42
|
"limits": {
|
|
48
|
-
"enabled":
|
|
49
|
-
"showTimeLeft":
|
|
50
|
-
"showPacingDelta":
|
|
51
|
-
"cost": {
|
|
52
|
-
"enabled": false,
|
|
53
|
-
"format": "decimal1"
|
|
54
|
-
},
|
|
43
|
+
"enabled": false,
|
|
44
|
+
"showTimeLeft": false,
|
|
45
|
+
"showPacingDelta": false,
|
|
46
|
+
"cost": { "enabled": false, "format": "decimal1" },
|
|
55
47
|
"percentage": {
|
|
56
|
-
"enabled":
|
|
57
|
-
"showValue":
|
|
48
|
+
"enabled": false,
|
|
49
|
+
"showValue": false,
|
|
58
50
|
"progressBar": {
|
|
59
51
|
"enabled": false,
|
|
60
52
|
"length": 10,
|
|
61
|
-
"style": "
|
|
53
|
+
"style": "braille",
|
|
62
54
|
"color": "progressive",
|
|
63
55
|
"background": "none"
|
|
64
56
|
}
|
|
65
57
|
}
|
|
66
58
|
},
|
|
67
59
|
"weeklyUsage": {
|
|
68
|
-
"enabled":
|
|
60
|
+
"enabled": false,
|
|
69
61
|
"showTimeLeft": false,
|
|
70
|
-
"showPacingDelta":
|
|
71
|
-
"cost": {
|
|
72
|
-
"enabled": false,
|
|
73
|
-
"format": "decimal1"
|
|
74
|
-
},
|
|
62
|
+
"showPacingDelta": false,
|
|
63
|
+
"cost": { "enabled": false, "format": "decimal1" },
|
|
75
64
|
"percentage": {
|
|
76
|
-
"enabled":
|
|
77
|
-
"showValue":
|
|
65
|
+
"enabled": false,
|
|
66
|
+
"showValue": false,
|
|
78
67
|
"progressBar": {
|
|
79
68
|
"enabled": false,
|
|
80
69
|
"length": 10,
|
|
81
|
-
"style": "
|
|
70
|
+
"style": "braille",
|
|
82
71
|
"color": "progressive",
|
|
83
72
|
"background": "none"
|
|
84
73
|
}
|
|
85
74
|
}
|
|
86
75
|
},
|
|
87
76
|
"dailySpend": {
|
|
88
|
-
"cost": {
|
|
89
|
-
"enabled": true,
|
|
90
|
-
"format": "decimal1"
|
|
91
|
-
}
|
|
77
|
+
"cost": { "enabled": false, "format": "decimal1" }
|
|
92
78
|
}
|
|
93
|
-
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { $ } from "bun";
|
|
6
|
+
|
|
7
|
+
const fixtureArg = process.argv[2] || "test-input.json";
|
|
8
|
+
const fixturePath = join(
|
|
9
|
+
import.meta.dir,
|
|
10
|
+
"fixtures",
|
|
11
|
+
fixtureArg.endsWith(".json") ? fixtureArg : `${fixtureArg}.json`,
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const fixture = await readFile(fixturePath, "utf-8");
|
|
16
|
+
|
|
17
|
+
console.log("š Testing statusline with fixture:", fixtureArg);
|
|
18
|
+
console.log("ā".repeat(60));
|
|
19
|
+
|
|
20
|
+
const result =
|
|
21
|
+
await $`echo ${fixture} | bun ${join(import.meta.dir, "src/index.ts")}`.quiet();
|
|
22
|
+
|
|
23
|
+
console.log(result.stdout.toString());
|
|
24
|
+
console.log("ā".repeat(60));
|
|
25
|
+
console.log("ā
Test complete!");
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if ((error as any).code === "ENOENT") {
|
|
28
|
+
console.error(`ā Fixture not found: ${fixturePath}`);
|
|
29
|
+
console.log("\nAvailable fixtures:");
|
|
30
|
+
const files =
|
|
31
|
+
await $`ls ${join(import.meta.dir, "fixtures")}/*.json`.quiet();
|
|
32
|
+
console.log(files.stdout.toString());
|
|
33
|
+
} else {
|
|
34
|
+
console.error("ā Error:", error);
|
|
35
|
+
}
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { $ } from "bun";
|
|
5
|
+
|
|
6
|
+
const fixtureFile = process.argv[2] || "fixtures/test-input.json";
|
|
7
|
+
const fixtureFullPath = join(import.meta.dir, fixtureFile);
|
|
8
|
+
|
|
9
|
+
console.log(`\nš Testing with fixture: ${fixtureFile}\n`);
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const content = await Bun.file(fixtureFullPath).text();
|
|
13
|
+
const result = await $`echo ${content} | bun run src/index.ts`.text();
|
|
14
|
+
|
|
15
|
+
console.log(result);
|
|
16
|
+
console.log("\nā
Test completed successfully!\n");
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error("ā Test failed:", error);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Enable latest features
|
|
4
|
+
"lib": ["ESNext", "DOM"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
|
|
22
|
+
// Some stricter flags (disabled by default)
|
|
23
|
+
"noUnusedLocals": false,
|
|
24
|
+
"noUnusedParameters": false,
|
|
25
|
+
"noPropertyAccessFromIndexSignature": false
|
|
26
|
+
}
|
|
27
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -35434,7 +35434,7 @@ function getTokenInfo() {
|
|
|
35434
35434
|
// src/commands/pro.ts
|
|
35435
35435
|
var import_fs_extra16 = __toESM(require_lib4(), 1);
|
|
35436
35436
|
var API_URL = "https://codeline.app/api/products";
|
|
35437
|
-
var
|
|
35437
|
+
var PRODUCT_IDS = ["prd_XJVgxVPbGG", "prd_NKabAkdOkw"];
|
|
35438
35438
|
async function countInstalledItems(claudeDir) {
|
|
35439
35439
|
const counts = {
|
|
35440
35440
|
commands: 0,
|
|
@@ -35490,18 +35490,23 @@ async function proActivateCommand(userToken) {
|
|
|
35490
35490
|
userToken = result;
|
|
35491
35491
|
}
|
|
35492
35492
|
const spinner = Y2();
|
|
35493
|
-
spinner.start("Validating token...");
|
|
35494
|
-
|
|
35495
|
-
|
|
35496
|
-
|
|
35497
|
-
|
|
35498
|
-
|
|
35499
|
-
|
|
35493
|
+
spinner.start("Validating token against premium products...");
|
|
35494
|
+
let validationSuccess = false;
|
|
35495
|
+
let data = null;
|
|
35496
|
+
for (const productId of PRODUCT_IDS) {
|
|
35497
|
+
const response = await fetch(`${API_URL}/${productId}/have-access?token=${userToken}`);
|
|
35498
|
+
if (response.ok) {
|
|
35499
|
+
const responseData = await response.json();
|
|
35500
|
+
if (responseData.hasAccess) {
|
|
35501
|
+
data = responseData;
|
|
35502
|
+
validationSuccess = true;
|
|
35503
|
+
break;
|
|
35504
|
+
}
|
|
35505
|
+
}
|
|
35500
35506
|
}
|
|
35501
|
-
|
|
35502
|
-
if (!data.hasAccess) {
|
|
35507
|
+
if (!validationSuccess || !data) {
|
|
35503
35508
|
spinner.stop("Token validation failed");
|
|
35504
|
-
M2.error(
|
|
35509
|
+
M2.error("Invalid token or no access to premium products");
|
|
35505
35510
|
M2.info("\uD83D\uDC8E Get AIBlueprint CLI Premium at: https://mlv.sh/claude-cli");
|
|
35506
35511
|
Se(source_default.red("ā Activation failed"));
|
|
35507
35512
|
process.exit(1);
|