@planckspace/cli 0.1.0 → 0.2.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/README.md +24 -1
- package/dist/anomaly/constants.d.ts +13 -0
- package/dist/anomaly/constants.d.ts.map +1 -0
- package/dist/anomaly/constants.js +13 -0
- package/dist/anomaly/constants.js.map +1 -0
- package/dist/anomaly/detector.d.ts +12 -0
- package/dist/anomaly/detector.d.ts.map +1 -0
- package/dist/anomaly/detector.js +98 -0
- package/dist/anomaly/detector.js.map +1 -0
- package/dist/anomaly/types.d.ts +19 -0
- package/dist/anomaly/types.d.ts.map +1 -0
- package/dist/anomaly/types.js +2 -0
- package/dist/anomaly/types.js.map +1 -0
- package/dist/commands/budget.d.ts +26 -0
- package/dist/commands/budget.d.ts.map +1 -0
- package/dist/commands/budget.js +91 -0
- package/dist/commands/budget.js.map +1 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +45 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/connect.d.ts +17 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +191 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/daemon.d.ts +8 -0
- package/dist/commands/daemon.d.ts.map +1 -0
- package/dist/commands/daemon.js +310 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/diagnose.d.ts +2 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/diagnose.js +81 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +67 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/export.d.ts +40 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +184 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/init.d.ts +3 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +14 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/insights.d.ts +2 -0
- package/dist/commands/insights.d.ts.map +1 -0
- package/dist/commands/insights.js +71 -0
- package/dist/commands/insights.js.map +1 -0
- package/dist/commands/inspect.d.ts +2 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +81 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/integrations.d.ts +2 -0
- package/dist/commands/integrations.d.ts.map +1 -0
- package/dist/commands/integrations.js +46 -0
- package/dist/commands/integrations.js.map +1 -0
- package/dist/commands/login.d.ts +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +45 -6
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/metrics.d.ts +6 -0
- package/dist/commands/metrics.d.ts.map +1 -0
- package/dist/commands/metrics.js +85 -0
- package/dist/commands/metrics.js.map +1 -0
- package/dist/commands/reconcile.d.ts +2 -0
- package/dist/commands/reconcile.d.ts.map +1 -0
- package/dist/commands/reconcile.js +63 -0
- package/dist/commands/reconcile.js.map +1 -0
- package/dist/commands/scan.d.ts.map +1 -1
- package/dist/commands/scan.js +53 -10
- package/dist/commands/scan.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +84 -14
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/subscription.d.ts +15 -0
- package/dist/commands/subscription.d.ts.map +1 -0
- package/dist/commands/subscription.js +62 -0
- package/dist/commands/subscription.js.map +1 -0
- package/dist/commands/sync.d.ts +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +77 -10
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/value.d.ts +5 -0
- package/dist/commands/value.d.ts.map +1 -0
- package/dist/commands/value.js +95 -0
- package/dist/commands/value.js.map +1 -0
- package/dist/config.d.ts +28 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -1
- package/dist/config.js.map +1 -1
- package/dist/correlate.d.ts +7 -0
- package/dist/correlate.d.ts.map +1 -1
- package/dist/correlate.js +102 -15
- package/dist/correlate.js.map +1 -1
- package/dist/daemon/daemon.d.ts +2 -0
- package/dist/daemon/daemon.d.ts.map +1 -0
- package/dist/daemon/daemon.js +188 -0
- package/dist/daemon/daemon.js.map +1 -0
- package/dist/daemon/daemonState.d.ts +25 -0
- package/dist/daemon/daemonState.d.ts.map +1 -0
- package/dist/daemon/daemonState.js +82 -0
- package/dist/daemon/daemonState.js.map +1 -0
- package/dist/daemon/logger.d.ts +7 -0
- package/dist/daemon/logger.d.ts.map +1 -0
- package/dist/daemon/logger.js +61 -0
- package/dist/daemon/logger.js.map +1 -0
- package/dist/daemon/syncLoop.d.ts +38 -0
- package/dist/daemon/syncLoop.d.ts.map +1 -0
- package/dist/daemon/syncLoop.js +119 -0
- package/dist/daemon/syncLoop.js.map +1 -0
- package/dist/daemon/watcher.d.ts +26 -0
- package/dist/daemon/watcher.d.ts.map +1 -0
- package/dist/daemon/watcher.js +187 -0
- package/dist/daemon/watcher.js.map +1 -0
- package/dist/db/store.d.ts +123 -2
- package/dist/db/store.d.ts.map +1 -1
- package/dist/db/store.js +397 -11
- package/dist/db/store.js.map +1 -1
- package/dist/detectors/cache-gap.d.ts +3 -0
- package/dist/detectors/cache-gap.d.ts.map +1 -0
- package/dist/detectors/cache-gap.js +70 -0
- package/dist/detectors/cache-gap.js.map +1 -0
- package/dist/detectors/context-bloat.d.ts +3 -0
- package/dist/detectors/context-bloat.d.ts.map +1 -0
- package/dist/detectors/context-bloat.js +68 -0
- package/dist/detectors/context-bloat.js.map +1 -0
- package/dist/detectors/fileTokens.d.ts +3 -0
- package/dist/detectors/fileTokens.d.ts.map +1 -0
- package/dist/detectors/fileTokens.js +12 -0
- package/dist/detectors/fileTokens.js.map +1 -0
- package/dist/detectors/index.d.ts +20 -0
- package/dist/detectors/index.d.ts.map +1 -0
- package/dist/detectors/index.js +41 -0
- package/dist/detectors/index.js.map +1 -0
- package/dist/detectors/model-routing.d.ts +3 -0
- package/dist/detectors/model-routing.d.ts.map +1 -0
- package/dist/detectors/model-routing.js +71 -0
- package/dist/detectors/model-routing.js.map +1 -0
- package/dist/detectors/repeat-read.d.ts +3 -0
- package/dist/detectors/repeat-read.d.ts.map +1 -0
- package/dist/detectors/repeat-read.js +69 -0
- package/dist/detectors/repeat-read.js.map +1 -0
- package/dist/detectors/seat-efficiency.d.ts +4 -0
- package/dist/detectors/seat-efficiency.d.ts.map +1 -0
- package/dist/detectors/seat-efficiency.js +86 -0
- package/dist/detectors/seat-efficiency.js.map +1 -0
- package/dist/detectors/types.d.ts +46 -0
- package/dist/detectors/types.d.ts.map +1 -0
- package/dist/detectors/types.js +2 -0
- package/dist/detectors/types.js.map +1 -0
- package/dist/health.d.ts +59 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +106 -0
- package/dist/health.js.map +1 -0
- package/dist/index.js +389 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics.d.ts +29 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +205 -0
- package/dist/metrics.js.map +1 -0
- package/dist/scrapers/claudeCode.d.ts +1 -0
- package/dist/scrapers/claudeCode.d.ts.map +1 -1
- package/dist/scrapers/claudeCode.js +43 -13
- package/dist/scrapers/claudeCode.js.map +1 -1
- package/dist/scrapers/cursor.d.ts +3 -2
- package/dist/scrapers/cursor.d.ts.map +1 -1
- package/dist/scrapers/cursor.js +56 -16
- package/dist/scrapers/cursor.js.map +1 -1
- package/dist/scrapers/jetbrains.d.ts +15 -0
- package/dist/scrapers/jetbrains.d.ts.map +1 -0
- package/dist/scrapers/jetbrains.js +232 -0
- package/dist/scrapers/jetbrains.js.map +1 -0
- package/dist/scrapers/types.d.ts +4 -1
- package/dist/scrapers/types.d.ts.map +1 -1
- package/dist/scrapers/windsurf.d.ts +3 -2
- package/dist/scrapers/windsurf.d.ts.map +1 -1
- package/dist/scrapers/windsurf.js +25 -9
- package/dist/scrapers/windsurf.js.map +1 -1
- package/dist/sync/payload.d.ts +4 -5
- package/dist/sync/payload.d.ts.map +1 -1
- package/dist/sync/payload.js +88 -7
- package/dist/sync/payload.js.map +1 -1
- package/dist/sync/syncEngine.d.ts +19 -3
- package/dist/sync/syncEngine.d.ts.map +1 -1
- package/dist/sync/syncEngine.js +116 -10
- package/dist/sync/syncEngine.js.map +1 -1
- package/install.sh +27 -10
- package/package.json +43 -42
- package/dist/__tests__/correlate.test.d.ts +0 -2
- package/dist/__tests__/correlate.test.d.ts.map +0 -1
- package/dist/__tests__/correlate.test.js +0 -204
- package/dist/__tests__/correlate.test.js.map +0 -1
- package/dist/scrapers/__tests__/claudeCode.test.d.ts +0 -2
- package/dist/scrapers/__tests__/claudeCode.test.d.ts.map +0 -1
- package/dist/scrapers/__tests__/claudeCode.test.js +0 -115
- package/dist/scrapers/__tests__/claudeCode.test.js.map +0 -1
- package/dist/scrapers/__tests__/cursor.test.d.ts +0 -2
- package/dist/scrapers/__tests__/cursor.test.d.ts.map +0 -1
- package/dist/scrapers/__tests__/cursor.test.js +0 -173
- package/dist/scrapers/__tests__/cursor.test.js.map +0 -1
- package/dist/scrapers/__tests__/windsurf.test.d.ts +0 -2
- package/dist/scrapers/__tests__/windsurf.test.d.ts.map +0 -1
- package/dist/scrapers/__tests__/windsurf.test.js +0 -87
- package/dist/scrapers/__tests__/windsurf.test.js.map +0 -1
- package/dist/scripts/scanTest.d.ts +0 -3
- package/dist/scripts/scanTest.d.ts.map +0 -1
- package/dist/scripts/scanTest.js +0 -146
- package/dist/scripts/scanTest.js.map +0 -1
- package/dist/sync/__tests__/payload.privacy.test.d.ts +0 -2
- package/dist/sync/__tests__/payload.privacy.test.d.ts.map +0 -1
- package/dist/sync/__tests__/payload.privacy.test.js +0 -100
- package/dist/sync/__tests__/payload.privacy.test.js.map +0 -1
package/dist/sync/syncEngine.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getUnsyncedSessions, markSessionsSynced, recordSyncError, } from "../db/store.js";
|
|
1
|
+
import { getUnsyncedSessions, markSessionsSynced, recordSyncError, getUnsyncedInsights, markInsightsSynced, getUnsyncedAnomalies, markAnomaliesSynced, } from "../db/store.js";
|
|
2
2
|
import { buildTelemetryPayload } from "./payload.js";
|
|
3
3
|
const BATCH_SIZE = 100;
|
|
4
4
|
const MAX_RETRIES = 3;
|
|
@@ -17,7 +17,50 @@ function isTransient(outcome) {
|
|
|
17
17
|
return true;
|
|
18
18
|
return outcome.status >= 500 || outcome.status === 429;
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
function buildInsightPayload(r) {
|
|
21
|
+
return {
|
|
22
|
+
id: r.id,
|
|
23
|
+
detectorId: r.detectorId,
|
|
24
|
+
repoName: r.repoName ?? null,
|
|
25
|
+
scope: r.workspaceScope, // backend column is `scope`
|
|
26
|
+
developerEmail: null, // future: per-developer insights
|
|
27
|
+
titleShort: r.titleShort,
|
|
28
|
+
estimatedMonthlySavingsUsd: r.estimatedMonthlySavingsUsd,
|
|
29
|
+
confidence: r.confidence,
|
|
30
|
+
evidence: JSON.parse(r.evidenceJson),
|
|
31
|
+
manualFix: r.manualFix,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function buildAnomalyPayload(r) {
|
|
35
|
+
// Map local field names → backend IngestAnomalySchema field names.
|
|
36
|
+
const kind = r.type === "daily_cost_spike" ? "repo-spike" : "session-outlier";
|
|
37
|
+
const scope = r.repoName ?? r.sessionId ?? "unknown";
|
|
38
|
+
const severity = r.ratio >= 5 ? "critical" : "warn";
|
|
39
|
+
return {
|
|
40
|
+
kind,
|
|
41
|
+
scope,
|
|
42
|
+
severity,
|
|
43
|
+
baselineUsd: r.baselineUsd,
|
|
44
|
+
observedUsd: r.costUsd,
|
|
45
|
+
dedupeKey: r.id,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function buildBudgetPayload(b) {
|
|
49
|
+
// Map CLI Budget → backend IngestBudgetSchema.
|
|
50
|
+
return {
|
|
51
|
+
scope: b.scope,
|
|
52
|
+
scopeName: b.name,
|
|
53
|
+
monthlyUsd: b.monthly,
|
|
54
|
+
alertChannels: [],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* POST one batch to /api/ingest.
|
|
59
|
+
* Insights, subscriptions, anomalies, budgets, and productivity metrics ride in
|
|
60
|
+
* the same envelope — the backend processes them all atomically so there's no
|
|
61
|
+
* separate endpoint needed while B-series endpoints are being deployed.
|
|
62
|
+
*/
|
|
63
|
+
async function postBatch(deps, payloads, insightPayloads = [], anomalyPayloads = [], productivityMetrics = null) {
|
|
21
64
|
try {
|
|
22
65
|
const res = await fetch(`${deps.apiUrl}/api/ingest`, {
|
|
23
66
|
method: "POST",
|
|
@@ -25,7 +68,14 @@ async function postBatch(deps, payloads) {
|
|
|
25
68
|
"Content-Type": "application/json",
|
|
26
69
|
Authorization: `Bearer ${deps.token}`,
|
|
27
70
|
},
|
|
28
|
-
body: JSON.stringify(
|
|
71
|
+
body: JSON.stringify({
|
|
72
|
+
sessions: payloads,
|
|
73
|
+
workspaceSubscriptions: deps.workspaceSubscriptions ?? [],
|
|
74
|
+
insights: insightPayloads,
|
|
75
|
+
anomalies: anomalyPayloads,
|
|
76
|
+
budgets: (deps.budgets ?? []).map(buildBudgetPayload),
|
|
77
|
+
productivityMetric: null,
|
|
78
|
+
}),
|
|
29
79
|
});
|
|
30
80
|
if (res.ok)
|
|
31
81
|
return { ok: true, status: res.status };
|
|
@@ -41,22 +91,62 @@ async function postBatch(deps, payloads) {
|
|
|
41
91
|
}
|
|
42
92
|
}
|
|
43
93
|
/**
|
|
44
|
-
* Push all unsynced sessions to {apiUrl}/api/ingest in
|
|
45
|
-
*
|
|
46
|
-
*
|
|
94
|
+
* Push all unsynced sessions and insights to {apiUrl}/api/ingest in one envelope.
|
|
95
|
+
* Insights ride in the first batch (or the empty-sessions batch) so the backend
|
|
96
|
+
* sees them as soon as they exist, without waiting for a separate endpoint.
|
|
97
|
+
*
|
|
98
|
+
* Transient failures (network / 5xx / 429) retry with exponential backoff.
|
|
99
|
+
* Auth failures (401/403) abort remaining batches and add a warning to the result.
|
|
47
100
|
*/
|
|
48
101
|
export async function syncOnce(deps) {
|
|
102
|
+
const authWarnings = [];
|
|
103
|
+
// Compute workspace-level payloads once — they go in the first batch only.
|
|
104
|
+
// Metrics suppressed — CLI payload shape doesn't match backend schema yet.
|
|
105
|
+
const metricsResult = null;
|
|
106
|
+
const [unsyncedInsightRows, unsyncedAnomalyRows] = await Promise.all([
|
|
107
|
+
Promise.resolve(getUnsyncedInsights()),
|
|
108
|
+
Promise.resolve(getUnsyncedAnomalies()),
|
|
109
|
+
]);
|
|
110
|
+
const insightPayloads = unsyncedInsightRows.map(buildInsightPayload);
|
|
111
|
+
const anomalyPayloads = unsyncedAnomalyRows.map(buildAnomalyPayload);
|
|
49
112
|
const rows = getUnsyncedSessions();
|
|
50
|
-
if (rows.length === 0)
|
|
51
|
-
return { synced: 0, failed: 0 };
|
|
52
113
|
let synced = 0;
|
|
53
114
|
let failed = 0;
|
|
115
|
+
let metricsIncluded = false;
|
|
116
|
+
if (rows.length === 0) {
|
|
117
|
+
// No sessions — push subscriptions + insights + anomalies + budgets + metrics via
|
|
118
|
+
// an empty-sessions envelope so the backend stays current even between scans.
|
|
119
|
+
const outcome = await postBatch(deps, [], insightPayloads, anomalyPayloads, metricsResult);
|
|
120
|
+
if (outcome.ok) {
|
|
121
|
+
if (insightPayloads.length > 0) {
|
|
122
|
+
markInsightsSynced(unsyncedInsightRows.map((r) => r.id));
|
|
123
|
+
}
|
|
124
|
+
if (anomalyPayloads.length > 0) {
|
|
125
|
+
markAnomaliesSynced(unsyncedAnomalyRows.map((r) => r.id));
|
|
126
|
+
}
|
|
127
|
+
metricsIncluded = false;
|
|
128
|
+
const subscriptionCount = deps.workspaceSubscriptions?.length ?? 0;
|
|
129
|
+
return { synced: 0, failed: 0, subscriptionCount, pending: [], authWarnings, metricsIncluded };
|
|
130
|
+
}
|
|
131
|
+
if (outcome.status === 401 || outcome.status === 403)
|
|
132
|
+
authWarnings.push("sessions");
|
|
133
|
+
return { synced: 0, failed: 0, subscriptionCount: 0, pending: [], authWarnings, metricsIncluded: false };
|
|
134
|
+
}
|
|
135
|
+
let anyBatchOk = false;
|
|
136
|
+
let insightsSynced = false;
|
|
137
|
+
let anomaliesSynced = false;
|
|
138
|
+
let firstBatch = true;
|
|
54
139
|
for (const batch of chunk(rows, BATCH_SIZE)) {
|
|
55
140
|
const ids = batch.map((r) => r.id);
|
|
56
141
|
const payloads = batch.map((r) => buildTelemetryPayload(r, deps.workspaceId));
|
|
142
|
+
// Include insights + anomalies in the first batch only. Metrics always null (see above).
|
|
143
|
+
const batchInsights = firstBatch ? insightPayloads : [];
|
|
144
|
+
const batchAnomalies = firstBatch ? anomalyPayloads : [];
|
|
145
|
+
const batchMetrics = null;
|
|
146
|
+
firstBatch = false;
|
|
57
147
|
let outcome = { ok: false };
|
|
58
148
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
59
|
-
outcome = await postBatch(deps, payloads);
|
|
149
|
+
outcome = await postBatch(deps, payloads, batchInsights, batchAnomalies, batchMetrics);
|
|
60
150
|
if (outcome.ok || !isTransient(outcome) || attempt === MAX_RETRIES)
|
|
61
151
|
break;
|
|
62
152
|
// Exponential backoff: 500ms, 1s, 2s.
|
|
@@ -65,12 +155,28 @@ export async function syncOnce(deps) {
|
|
|
65
155
|
if (outcome.ok) {
|
|
66
156
|
markSessionsSynced(ids);
|
|
67
157
|
synced += ids.length;
|
|
158
|
+
anyBatchOk = true;
|
|
159
|
+
if (!insightsSynced && batchInsights.length > 0) {
|
|
160
|
+
markInsightsSynced(unsyncedInsightRows.map((r) => r.id));
|
|
161
|
+
insightsSynced = true;
|
|
162
|
+
}
|
|
163
|
+
if (!anomaliesSynced && batchAnomalies.length > 0) {
|
|
164
|
+
markAnomaliesSynced(unsyncedAnomalyRows.map((r) => r.id));
|
|
165
|
+
anomaliesSynced = true;
|
|
166
|
+
}
|
|
167
|
+
if (batchMetrics !== null)
|
|
168
|
+
metricsIncluded = true;
|
|
68
169
|
}
|
|
69
170
|
else {
|
|
70
171
|
recordSyncError(ids, outcome.error ?? "unknown error");
|
|
71
172
|
failed += ids.length;
|
|
173
|
+
if (outcome.status === 401 || outcome.status === 403) {
|
|
174
|
+
authWarnings.push("sessions");
|
|
175
|
+
break; // All batches will fail — stop early.
|
|
176
|
+
}
|
|
72
177
|
}
|
|
73
178
|
}
|
|
74
|
-
|
|
179
|
+
const subscriptionCount = anyBatchOk ? (deps.workspaceSubscriptions?.length ?? 0) : 0;
|
|
180
|
+
return { synced, failed, subscriptionCount, pending: [], authWarnings, metricsIncluded };
|
|
75
181
|
}
|
|
76
182
|
//# sourceMappingURL=syncEngine.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncEngine.js","sourceRoot":"","sources":["../../src/sync/syncEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,
|
|
1
|
+
{"version":3,"file":"syncEngine.js","sourceRoot":"","sources":["../../src/sync/syncEngine.ts"],"names":[],"mappings":"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"}
|
package/install.sh
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
set -euo pipefail
|
|
8
8
|
|
|
9
9
|
DASHBOARD_URL="https://app.planckspace.dev"
|
|
10
|
-
|
|
10
|
+
VSCODE_EXT_ID="planckspace.planckspace-extension"
|
|
11
|
+
VSCODE_EXT_URL="https://marketplace.visualstudio.com/items?itemName=${VSCODE_EXT_ID}"
|
|
12
|
+
OPENVSX_EXT_URL="https://open-vsx.org/extension/planckspace/planckspace-extension"
|
|
11
13
|
PKG="@planckspace/cli"
|
|
12
14
|
|
|
13
15
|
# ── helpers ──────────────────────────────────────────────────────────────────
|
|
@@ -72,8 +74,8 @@ info "Node $NODE_VER found."
|
|
|
72
74
|
command -v npm >/dev/null 2>&1 || die "npm not found. Re-install Node.js from https://nodejs.org"
|
|
73
75
|
|
|
74
76
|
# ── install CLI ──────────────────────────────────────────────────────────────
|
|
75
|
-
say "Installing $PKG..."
|
|
76
|
-
npm install -g "$PKG" --loglevel error
|
|
77
|
+
say "Installing $PKG@latest..."
|
|
78
|
+
npm install -g "$PKG@latest" --loglevel error
|
|
77
79
|
|
|
78
80
|
# verify the binary is reachable
|
|
79
81
|
command -v planck >/dev/null 2>&1 || {
|
|
@@ -102,13 +104,23 @@ else
|
|
|
102
104
|
fi
|
|
103
105
|
|
|
104
106
|
# ── scan (backfill existing history) ─────────────────────────────────────────
|
|
105
|
-
say "Scanning local AI session history
|
|
107
|
+
say "Scanning local AI session history..."
|
|
106
108
|
planck scan
|
|
107
109
|
|
|
108
110
|
# ── sync (only when connected) ───────────────────────────────────────────────
|
|
109
111
|
if [[ "$CONNECTED" == "true" ]]; then
|
|
110
112
|
say "Syncing data to your workspace..."
|
|
111
|
-
planck sync
|
|
113
|
+
planck scan --sync
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# ── VS Code extension ─────────────────────────────────────────────────────────
|
|
117
|
+
say "Installing VS Code extension..."
|
|
118
|
+
if command -v code >/dev/null 2>&1; then
|
|
119
|
+
code --install-extension "$VSCODE_EXT_ID" --force 2>/dev/null && \
|
|
120
|
+
info "Extension installed via 'code' CLI." || \
|
|
121
|
+
info "Extension install via CLI failed — install manually (see below)."
|
|
122
|
+
else
|
|
123
|
+
info "'code' CLI not found — install the extension manually."
|
|
112
124
|
fi
|
|
113
125
|
|
|
114
126
|
# ── done ─────────────────────────────────────────────────────────────────────
|
|
@@ -116,11 +128,16 @@ say "--------------------------------------"
|
|
|
116
128
|
say "PlanckSpace is ready."
|
|
117
129
|
say "--------------------------------------"
|
|
118
130
|
if [[ "$CONNECTED" == "true" ]]; then
|
|
119
|
-
info "Dashboard:
|
|
131
|
+
info "Dashboard: $DASHBOARD_URL"
|
|
120
132
|
else
|
|
121
|
-
info "Next step:
|
|
122
|
-
info "Dashboard:
|
|
133
|
+
info "Next step: planck login <token>"
|
|
134
|
+
info "Dashboard: $DASHBOARD_URL"
|
|
123
135
|
fi
|
|
124
|
-
info "
|
|
125
|
-
info "
|
|
136
|
+
info ""
|
|
137
|
+
info "VS Code extension:"
|
|
138
|
+
info " Marketplace: $VSCODE_EXT_URL"
|
|
139
|
+
info " Open VSX: $OPENVSX_EXT_URL"
|
|
140
|
+
info " Headless CLI: code --install-extension $VSCODE_EXT_ID"
|
|
141
|
+
info ""
|
|
142
|
+
info "Check setup: planck status"
|
|
126
143
|
say ""
|
package/package.json
CHANGED
|
@@ -1,42 +1,43 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@planckspace/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "PlanckSpace CLI — sync AI token usage from your editor to the team ledger",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"planck": "dist/index.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"build": "tsc",
|
|
11
|
-
"dev": "tsx src/index.ts",
|
|
12
|
-
"clean": "rm -rf dist",
|
|
13
|
-
"scan:test": "tsx src/scripts/scanTest.ts",
|
|
14
|
-
"test": "vitest run",
|
|
15
|
-
"prepublishOnly": "npm run build",
|
|
16
|
-
"release": "npm publish"
|
|
17
|
-
},
|
|
18
|
-
"engines": {
|
|
19
|
-
"node": ">=20"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist",
|
|
23
|
-
"install.sh"
|
|
24
|
-
],
|
|
25
|
-
"publishConfig": {
|
|
26
|
-
"access": "public"
|
|
27
|
-
},
|
|
28
|
-
"dependencies": {
|
|
29
|
-
"@planckspace/core": "
|
|
30
|
-
"better-sqlite3": "^12.10.0",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"@types/
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@planckspace/cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "PlanckSpace CLI — sync AI token usage from your editor to the team ledger",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"planck": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsx src/index.ts",
|
|
12
|
+
"clean": "rm -rf dist",
|
|
13
|
+
"scan:test": "tsx src/scripts/scanTest.ts",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"release": "npm publish"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=20"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"install.sh"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@planckspace/core": "0.2.2",
|
|
30
|
+
"better-sqlite3": "^12.10.0",
|
|
31
|
+
"chokidar": "^5.0.0",
|
|
32
|
+
"commander": "^15.0.0",
|
|
33
|
+
"dotenv": "^17.4.2",
|
|
34
|
+
"simple-git": "^3.36.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
38
|
+
"@types/node": "^25.9.1",
|
|
39
|
+
"tsx": "^4.22.4",
|
|
40
|
+
"typescript": "^6.0.3",
|
|
41
|
+
"vitest": "^4.1.7"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"correlate.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/correlate.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import os from "os";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import { simpleGit } from "simple-git";
|
|
6
|
-
import { initDb, upsertSessions, getSessions, setSessionCorrelation, closeDb, } from "../db/store.js";
|
|
7
|
-
import { correlateSessions } from "../correlate.js";
|
|
8
|
-
// A fixed reference clock. Commit dates are placed relative to it, and the same
|
|
9
|
-
// value is fed to correlateSessions() so the time-window logic is deterministic.
|
|
10
|
-
const NOW = Date.parse("2026-06-01T12:00:00.000Z");
|
|
11
|
-
const DAY = 24 * 60 * 60 * 1000;
|
|
12
|
-
const HOUR = 60 * 60 * 1000;
|
|
13
|
-
const iso = (ms) => new Date(ms).toISOString();
|
|
14
|
-
const SESSION_EMAIL = "dev@example.com";
|
|
15
|
-
// process.env minus undefined values — simple-git's .env() replaces the child's
|
|
16
|
-
// whole environment, so we must carry PATH etc. through. Editor vars are dropped:
|
|
17
|
-
// simple-git refuses to run with EDITOR/*_EDITOR set in a passed env.
|
|
18
|
-
const BASE_ENV = {};
|
|
19
|
-
for (const [k, v] of Object.entries(process.env)) {
|
|
20
|
-
if (v !== undefined && !/EDITOR/i.test(k))
|
|
21
|
-
BASE_ENV[k] = v;
|
|
22
|
-
}
|
|
23
|
-
let tmpRoot;
|
|
24
|
-
const repoDirs = [];
|
|
25
|
-
beforeAll(() => {
|
|
26
|
-
tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "planck-correlate-"));
|
|
27
|
-
initDb(path.join(tmpRoot, "local.db"));
|
|
28
|
-
});
|
|
29
|
-
afterAll(() => {
|
|
30
|
-
closeDb();
|
|
31
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
32
|
-
});
|
|
33
|
-
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
34
|
-
async function makeRepo(label) {
|
|
35
|
-
const dir = fs.mkdtempSync(path.join(tmpRoot, `repo-${label}-`));
|
|
36
|
-
repoDirs.push(dir);
|
|
37
|
-
const git = simpleGit(dir);
|
|
38
|
-
await git.init();
|
|
39
|
-
await git.addConfig("user.email", SESSION_EMAIL);
|
|
40
|
-
await git.addConfig("user.name", "Dev");
|
|
41
|
-
await git.addConfig("commit.gpgsign", "false");
|
|
42
|
-
return { dir, git };
|
|
43
|
-
}
|
|
44
|
-
/** Commit a file with explicit author + committer dates (and optional override author). */
|
|
45
|
-
async function commitAt(git, dir, file, whenMs, authorOverride) {
|
|
46
|
-
fs.writeFileSync(path.join(dir, file), `${file} @ ${whenMs}\n`);
|
|
47
|
-
await git.add(file);
|
|
48
|
-
git.env({ ...BASE_ENV, GIT_AUTHOR_DATE: iso(whenMs), GIT_COMMITTER_DATE: iso(whenMs) });
|
|
49
|
-
const opts = authorOverride ? { "--author": authorOverride } : undefined;
|
|
50
|
-
await git.commit(`add ${file}`, undefined, opts);
|
|
51
|
-
}
|
|
52
|
-
/** Rename the (post-first-commit) current branch to a stable name (default "main"). */
|
|
53
|
-
async function renameTo(git, name = "main") {
|
|
54
|
-
await git.branch(["-m", name]);
|
|
55
|
-
}
|
|
56
|
-
const renameToMain = (git) => renameTo(git);
|
|
57
|
-
let sessionCounter = 0;
|
|
58
|
-
function makeSession(over) {
|
|
59
|
-
sessionCounter += 1;
|
|
60
|
-
return {
|
|
61
|
-
sessionId: `corr-session-${sessionCounter}`,
|
|
62
|
-
tool: "claude_code",
|
|
63
|
-
model: "claude-opus-4-8",
|
|
64
|
-
startedAt: iso(NOW - DAY),
|
|
65
|
-
endedAt: iso(NOW - DAY + HOUR),
|
|
66
|
-
inputTokens: 100,
|
|
67
|
-
outputTokens: 200,
|
|
68
|
-
cacheReadTokens: 0,
|
|
69
|
-
cacheWriteTokens: 0,
|
|
70
|
-
costUsd: 0.01,
|
|
71
|
-
turns: [],
|
|
72
|
-
turnCount: 0,
|
|
73
|
-
filesTouchedCount: 0,
|
|
74
|
-
repoName: "repo",
|
|
75
|
-
gitBranch: "main",
|
|
76
|
-
...over,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
function outcomeOf(id) {
|
|
80
|
-
return getSessions().find((s) => s.id === id)?.outcome;
|
|
81
|
-
}
|
|
82
|
-
function emailOf(id) {
|
|
83
|
-
return getSessions().find((s) => s.id === id)?.gitAuthorEmail;
|
|
84
|
-
}
|
|
85
|
-
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
86
|
-
describe("correlateSessions", () => {
|
|
87
|
-
it("marks a session shipped when its branch commit merged into main", async () => {
|
|
88
|
-
const { dir, git } = await makeRepo("shipped");
|
|
89
|
-
await commitAt(git, dir, "base.txt", NOW - 10 * DAY);
|
|
90
|
-
await renameToMain(git);
|
|
91
|
-
await git.checkoutLocalBranch("feature");
|
|
92
|
-
await commitAt(git, dir, "feature.txt", NOW - 9 * DAY);
|
|
93
|
-
await git.checkout("main");
|
|
94
|
-
await git.merge(["feature"]); // fast-forward — feature becomes reachable from main
|
|
95
|
-
const session = makeSession({
|
|
96
|
-
workingDir: dir,
|
|
97
|
-
gitBranch: "feature",
|
|
98
|
-
startedAt: iso(NOW - 9.5 * DAY),
|
|
99
|
-
});
|
|
100
|
-
upsertSessions([session]);
|
|
101
|
-
await correlateSessions(NOW);
|
|
102
|
-
expect(outcomeOf(session.sessionId)).toBe("shipped");
|
|
103
|
-
expect(emailOf(session.sessionId)).toBe(SESSION_EMAIL);
|
|
104
|
-
});
|
|
105
|
-
it("ships a commit landed directly on a `master` default branch (not just `main`)", async () => {
|
|
106
|
-
// Regression: resolveDefaultBranch must detect `master`, not always pick the
|
|
107
|
-
// first candidate. A commit on master is, by definition, on the default branch.
|
|
108
|
-
const { dir, git } = await makeRepo("master-default");
|
|
109
|
-
await commitAt(git, dir, "base.txt", NOW - 5 * DAY);
|
|
110
|
-
await renameTo(git, "master");
|
|
111
|
-
await commitAt(git, dir, "work.txt", NOW - 4 * DAY); // committed straight to master
|
|
112
|
-
const session = makeSession({
|
|
113
|
-
workingDir: dir,
|
|
114
|
-
gitBranch: "master",
|
|
115
|
-
startedAt: iso(NOW - 4.5 * DAY),
|
|
116
|
-
});
|
|
117
|
-
upsertSessions([session]);
|
|
118
|
-
await correlateSessions(NOW);
|
|
119
|
-
expect(outcomeOf(session.sessionId)).toBe("shipped");
|
|
120
|
-
});
|
|
121
|
-
it("marks a session partial when commits exist, unmerged, and the window has passed", async () => {
|
|
122
|
-
const { dir, git } = await makeRepo("partial");
|
|
123
|
-
await commitAt(git, dir, "base.txt", NOW - 10 * DAY);
|
|
124
|
-
await renameToMain(git);
|
|
125
|
-
await git.checkoutLocalBranch("feature");
|
|
126
|
-
await commitAt(git, dir, "feature.txt", NOW - 8 * DAY); // never merged
|
|
127
|
-
const session = makeSession({
|
|
128
|
-
workingDir: dir,
|
|
129
|
-
gitBranch: "feature",
|
|
130
|
-
startedAt: iso(NOW - 9 * DAY), // 9 days ago → past the 7-day window
|
|
131
|
-
});
|
|
132
|
-
upsertSessions([session]);
|
|
133
|
-
await correlateSessions(NOW);
|
|
134
|
-
expect(outcomeOf(session.sessionId)).toBe("partial");
|
|
135
|
-
expect(emailOf(session.sessionId)).toBe(SESSION_EMAIL);
|
|
136
|
-
});
|
|
137
|
-
it("keeps a session unknown when commits exist, unmerged, but still inside the window", async () => {
|
|
138
|
-
const { dir, git } = await makeRepo("unknown-fresh");
|
|
139
|
-
await commitAt(git, dir, "base.txt", NOW - 2 * DAY);
|
|
140
|
-
await renameToMain(git);
|
|
141
|
-
await git.checkoutLocalBranch("feature");
|
|
142
|
-
await commitAt(git, dir, "feature.txt", NOW - 0.5 * DAY); // unmerged, recent
|
|
143
|
-
const session = makeSession({
|
|
144
|
-
workingDir: dir,
|
|
145
|
-
gitBranch: "feature",
|
|
146
|
-
startedAt: iso(NOW - DAY), // 1 day ago → still inside the 7-day window
|
|
147
|
-
});
|
|
148
|
-
upsertSessions([session]);
|
|
149
|
-
await correlateSessions(NOW);
|
|
150
|
-
expect(outcomeOf(session.sessionId)).toBe("unknown");
|
|
151
|
-
});
|
|
152
|
-
it("marks a session abandoned when it ended >24h ago with no commits by its author", async () => {
|
|
153
|
-
const { dir, git } = await makeRepo("abandoned");
|
|
154
|
-
// Only commit is authored by someone else, so the session's author has none.
|
|
155
|
-
await commitAt(git, dir, "base.txt", NOW - 5 * DAY, "Other Dev <other@example.com>");
|
|
156
|
-
await renameToMain(git);
|
|
157
|
-
const session = makeSession({
|
|
158
|
-
workingDir: dir,
|
|
159
|
-
gitBranch: "main",
|
|
160
|
-
startedAt: iso(NOW - 50 * HOUR),
|
|
161
|
-
endedAt: iso(NOW - 48 * HOUR), // ended 2 days ago
|
|
162
|
-
});
|
|
163
|
-
upsertSessions([session]);
|
|
164
|
-
await correlateSessions(NOW);
|
|
165
|
-
expect(outcomeOf(session.sessionId)).toBe("abandoned");
|
|
166
|
-
// We still record the session's git email even with no attributable commits.
|
|
167
|
-
expect(emailOf(session.sessionId)).toBe(SESSION_EMAIL);
|
|
168
|
-
});
|
|
169
|
-
it("never overrides a scraper-recorded errored outcome", async () => {
|
|
170
|
-
const { dir, git } = await makeRepo("errored");
|
|
171
|
-
await commitAt(git, dir, "base.txt", NOW - 2 * DAY);
|
|
172
|
-
await renameToMain(git);
|
|
173
|
-
const session = makeSession({ workingDir: dir, gitBranch: "main" });
|
|
174
|
-
upsertSessions([session]);
|
|
175
|
-
setSessionCorrelation(session.sessionId, "errored", null); // as the scraper would
|
|
176
|
-
await correlateSessions(NOW);
|
|
177
|
-
expect(outcomeOf(session.sessionId)).toBe("errored");
|
|
178
|
-
});
|
|
179
|
-
it("skips a workingDir that is not a git repo, leaving the outcome untouched", async () => {
|
|
180
|
-
const notARepo = fs.mkdtempSync(path.join(tmpRoot, "not-a-repo-"));
|
|
181
|
-
const session = makeSession({ workingDir: notARepo, gitBranch: "main" });
|
|
182
|
-
upsertSessions([session]); // default outcome is "unknown"
|
|
183
|
-
await correlateSessions(NOW);
|
|
184
|
-
expect(outcomeOf(session.sessionId)).toBe("unknown");
|
|
185
|
-
expect(emailOf(session.sessionId)).toBeNull();
|
|
186
|
-
});
|
|
187
|
-
it("does not crash on a detached HEAD (null branch) — no commits attributable", async () => {
|
|
188
|
-
const { dir, git } = await makeRepo("detached");
|
|
189
|
-
await commitAt(git, dir, "base.txt", NOW - 3 * DAY);
|
|
190
|
-
await renameToMain(git);
|
|
191
|
-
const session = makeSession({
|
|
192
|
-
workingDir: dir,
|
|
193
|
-
gitBranch: null, // detached HEAD captured as no branch
|
|
194
|
-
startedAt: iso(NOW - 50 * HOUR),
|
|
195
|
-
endedAt: iso(NOW - 48 * HOUR),
|
|
196
|
-
});
|
|
197
|
-
upsertSessions([session]);
|
|
198
|
-
await correlateSessions(NOW);
|
|
199
|
-
// No branch ⇒ no commits ⇒ falls through to the time-based abandoned check.
|
|
200
|
-
expect(outcomeOf(session.sessionId)).toBe("abandoned");
|
|
201
|
-
expect(emailOf(session.sessionId)).toBe(SESSION_EMAIL);
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
//# sourceMappingURL=correlate.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"correlate.test.js","sourceRoot":"","sources":["../../src/__tests__/correlate.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claudeCode.test.d.ts","sourceRoot":"","sources":["../../../src/scrapers/__tests__/claudeCode.test.ts"],"names":[],"mappings":""}
|