@planckspace/cli 0.1.1 → 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.
Files changed (190) hide show
  1. package/README.md +24 -1
  2. package/dist/anomaly/constants.d.ts +13 -0
  3. package/dist/anomaly/constants.d.ts.map +1 -0
  4. package/dist/anomaly/constants.js +13 -0
  5. package/dist/anomaly/constants.js.map +1 -0
  6. package/dist/anomaly/detector.d.ts +12 -0
  7. package/dist/anomaly/detector.d.ts.map +1 -0
  8. package/dist/anomaly/detector.js +98 -0
  9. package/dist/anomaly/detector.js.map +1 -0
  10. package/dist/anomaly/types.d.ts +19 -0
  11. package/dist/anomaly/types.d.ts.map +1 -0
  12. package/dist/anomaly/types.js +2 -0
  13. package/dist/anomaly/types.js.map +1 -0
  14. package/dist/commands/budget.d.ts +26 -0
  15. package/dist/commands/budget.d.ts.map +1 -0
  16. package/dist/commands/budget.js +91 -0
  17. package/dist/commands/budget.js.map +1 -0
  18. package/dist/commands/config.d.ts +4 -0
  19. package/dist/commands/config.d.ts.map +1 -0
  20. package/dist/commands/config.js +45 -0
  21. package/dist/commands/config.js.map +1 -0
  22. package/dist/commands/connect.d.ts +17 -0
  23. package/dist/commands/connect.d.ts.map +1 -0
  24. package/dist/commands/connect.js +191 -0
  25. package/dist/commands/connect.js.map +1 -0
  26. package/dist/commands/daemon.d.ts +8 -0
  27. package/dist/commands/daemon.d.ts.map +1 -0
  28. package/dist/commands/daemon.js +310 -0
  29. package/dist/commands/daemon.js.map +1 -0
  30. package/dist/commands/diagnose.d.ts +2 -0
  31. package/dist/commands/diagnose.d.ts.map +1 -0
  32. package/dist/commands/diagnose.js +81 -0
  33. package/dist/commands/diagnose.js.map +1 -0
  34. package/dist/commands/doctor.d.ts +2 -0
  35. package/dist/commands/doctor.d.ts.map +1 -0
  36. package/dist/commands/doctor.js +67 -0
  37. package/dist/commands/doctor.js.map +1 -0
  38. package/dist/commands/export.d.ts +40 -0
  39. package/dist/commands/export.d.ts.map +1 -0
  40. package/dist/commands/export.js +184 -0
  41. package/dist/commands/export.js.map +1 -0
  42. package/dist/commands/init.d.ts +3 -1
  43. package/dist/commands/init.d.ts.map +1 -1
  44. package/dist/commands/init.js +14 -1
  45. package/dist/commands/init.js.map +1 -1
  46. package/dist/commands/insights.d.ts +2 -0
  47. package/dist/commands/insights.d.ts.map +1 -0
  48. package/dist/commands/insights.js +71 -0
  49. package/dist/commands/insights.js.map +1 -0
  50. package/dist/commands/inspect.d.ts +2 -0
  51. package/dist/commands/inspect.d.ts.map +1 -0
  52. package/dist/commands/inspect.js +81 -0
  53. package/dist/commands/inspect.js.map +1 -0
  54. package/dist/commands/integrations.d.ts +2 -0
  55. package/dist/commands/integrations.d.ts.map +1 -0
  56. package/dist/commands/integrations.js +46 -0
  57. package/dist/commands/integrations.js.map +1 -0
  58. package/dist/commands/login.d.ts +1 -1
  59. package/dist/commands/login.d.ts.map +1 -1
  60. package/dist/commands/login.js +45 -6
  61. package/dist/commands/login.js.map +1 -1
  62. package/dist/commands/metrics.d.ts +6 -0
  63. package/dist/commands/metrics.d.ts.map +1 -0
  64. package/dist/commands/metrics.js +85 -0
  65. package/dist/commands/metrics.js.map +1 -0
  66. package/dist/commands/reconcile.d.ts +2 -0
  67. package/dist/commands/reconcile.d.ts.map +1 -0
  68. package/dist/commands/reconcile.js +63 -0
  69. package/dist/commands/reconcile.js.map +1 -0
  70. package/dist/commands/scan.d.ts.map +1 -1
  71. package/dist/commands/scan.js +53 -10
  72. package/dist/commands/scan.js.map +1 -1
  73. package/dist/commands/status.d.ts +1 -1
  74. package/dist/commands/status.d.ts.map +1 -1
  75. package/dist/commands/status.js +84 -14
  76. package/dist/commands/status.js.map +1 -1
  77. package/dist/commands/subscription.d.ts +15 -0
  78. package/dist/commands/subscription.d.ts.map +1 -0
  79. package/dist/commands/subscription.js +62 -0
  80. package/dist/commands/subscription.js.map +1 -0
  81. package/dist/commands/sync.d.ts +1 -1
  82. package/dist/commands/sync.d.ts.map +1 -1
  83. package/dist/commands/sync.js +77 -10
  84. package/dist/commands/sync.js.map +1 -1
  85. package/dist/commands/value.d.ts +5 -0
  86. package/dist/commands/value.d.ts.map +1 -0
  87. package/dist/commands/value.js +95 -0
  88. package/dist/commands/value.js.map +1 -0
  89. package/dist/config.d.ts +28 -3
  90. package/dist/config.d.ts.map +1 -1
  91. package/dist/config.js +9 -1
  92. package/dist/config.js.map +1 -1
  93. package/dist/correlate.d.ts +7 -0
  94. package/dist/correlate.d.ts.map +1 -1
  95. package/dist/correlate.js +102 -15
  96. package/dist/correlate.js.map +1 -1
  97. package/dist/daemon/daemon.d.ts +2 -0
  98. package/dist/daemon/daemon.d.ts.map +1 -0
  99. package/dist/daemon/daemon.js +188 -0
  100. package/dist/daemon/daemon.js.map +1 -0
  101. package/dist/daemon/daemonState.d.ts +25 -0
  102. package/dist/daemon/daemonState.d.ts.map +1 -0
  103. package/dist/daemon/daemonState.js +82 -0
  104. package/dist/daemon/daemonState.js.map +1 -0
  105. package/dist/daemon/logger.d.ts +7 -0
  106. package/dist/daemon/logger.d.ts.map +1 -0
  107. package/dist/daemon/logger.js +61 -0
  108. package/dist/daemon/logger.js.map +1 -0
  109. package/dist/daemon/syncLoop.d.ts +38 -0
  110. package/dist/daemon/syncLoop.d.ts.map +1 -0
  111. package/dist/daemon/syncLoop.js +119 -0
  112. package/dist/daemon/syncLoop.js.map +1 -0
  113. package/dist/daemon/watcher.d.ts +26 -0
  114. package/dist/daemon/watcher.d.ts.map +1 -0
  115. package/dist/daemon/watcher.js +187 -0
  116. package/dist/daemon/watcher.js.map +1 -0
  117. package/dist/db/store.d.ts +123 -2
  118. package/dist/db/store.d.ts.map +1 -1
  119. package/dist/db/store.js +397 -11
  120. package/dist/db/store.js.map +1 -1
  121. package/dist/detectors/cache-gap.d.ts +3 -0
  122. package/dist/detectors/cache-gap.d.ts.map +1 -0
  123. package/dist/detectors/cache-gap.js +70 -0
  124. package/dist/detectors/cache-gap.js.map +1 -0
  125. package/dist/detectors/context-bloat.d.ts +3 -0
  126. package/dist/detectors/context-bloat.d.ts.map +1 -0
  127. package/dist/detectors/context-bloat.js +68 -0
  128. package/dist/detectors/context-bloat.js.map +1 -0
  129. package/dist/detectors/fileTokens.d.ts +3 -0
  130. package/dist/detectors/fileTokens.d.ts.map +1 -0
  131. package/dist/detectors/fileTokens.js +12 -0
  132. package/dist/detectors/fileTokens.js.map +1 -0
  133. package/dist/detectors/index.d.ts +20 -0
  134. package/dist/detectors/index.d.ts.map +1 -0
  135. package/dist/detectors/index.js +41 -0
  136. package/dist/detectors/index.js.map +1 -0
  137. package/dist/detectors/model-routing.d.ts +3 -0
  138. package/dist/detectors/model-routing.d.ts.map +1 -0
  139. package/dist/detectors/model-routing.js +71 -0
  140. package/dist/detectors/model-routing.js.map +1 -0
  141. package/dist/detectors/repeat-read.d.ts +3 -0
  142. package/dist/detectors/repeat-read.d.ts.map +1 -0
  143. package/dist/detectors/repeat-read.js +69 -0
  144. package/dist/detectors/repeat-read.js.map +1 -0
  145. package/dist/detectors/seat-efficiency.d.ts +4 -0
  146. package/dist/detectors/seat-efficiency.d.ts.map +1 -0
  147. package/dist/detectors/seat-efficiency.js +86 -0
  148. package/dist/detectors/seat-efficiency.js.map +1 -0
  149. package/dist/detectors/types.d.ts +46 -0
  150. package/dist/detectors/types.d.ts.map +1 -0
  151. package/dist/detectors/types.js +2 -0
  152. package/dist/detectors/types.js.map +1 -0
  153. package/dist/health.d.ts +59 -0
  154. package/dist/health.d.ts.map +1 -0
  155. package/dist/health.js +106 -0
  156. package/dist/health.js.map +1 -0
  157. package/dist/index.js +389 -5
  158. package/dist/index.js.map +1 -1
  159. package/dist/metrics.d.ts +29 -0
  160. package/dist/metrics.d.ts.map +1 -0
  161. package/dist/metrics.js +205 -0
  162. package/dist/metrics.js.map +1 -0
  163. package/dist/scrapers/claudeCode.d.ts +1 -0
  164. package/dist/scrapers/claudeCode.d.ts.map +1 -1
  165. package/dist/scrapers/claudeCode.js +43 -13
  166. package/dist/scrapers/claudeCode.js.map +1 -1
  167. package/dist/scrapers/cursor.d.ts +3 -2
  168. package/dist/scrapers/cursor.d.ts.map +1 -1
  169. package/dist/scrapers/cursor.js +56 -16
  170. package/dist/scrapers/cursor.js.map +1 -1
  171. package/dist/scrapers/jetbrains.d.ts +15 -0
  172. package/dist/scrapers/jetbrains.d.ts.map +1 -0
  173. package/dist/scrapers/jetbrains.js +232 -0
  174. package/dist/scrapers/jetbrains.js.map +1 -0
  175. package/dist/scrapers/types.d.ts +4 -1
  176. package/dist/scrapers/types.d.ts.map +1 -1
  177. package/dist/scrapers/windsurf.d.ts +3 -2
  178. package/dist/scrapers/windsurf.d.ts.map +1 -1
  179. package/dist/scrapers/windsurf.js +25 -9
  180. package/dist/scrapers/windsurf.js.map +1 -1
  181. package/dist/sync/payload.d.ts +4 -5
  182. package/dist/sync/payload.d.ts.map +1 -1
  183. package/dist/sync/payload.js +88 -7
  184. package/dist/sync/payload.js.map +1 -1
  185. package/dist/sync/syncEngine.d.ts +19 -3
  186. package/dist/sync/syncEngine.d.ts.map +1 -1
  187. package/dist/sync/syncEngine.js +116 -10
  188. package/dist/sync/syncEngine.js.map +1 -1
  189. package/install.sh +27 -10
  190. package/package.json +43 -42
@@ -0,0 +1,184 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { initDb, getSessionsForExport } from "../db/store.js";
4
+ import { readConfig } from "../config.js";
5
+ // ── internal helpers ──────────────────────────────────────────────────────────
6
+ function parseMonth(month) {
7
+ const match = /^(\d{4})-(\d{2})$/.exec(month);
8
+ if (!match)
9
+ throw new Error(`--month must be in YYYY-MM format, got: ${month}`);
10
+ const year = parseInt(match[1], 10);
11
+ const mon = parseInt(match[2], 10);
12
+ if (mon < 1 || mon > 12)
13
+ throw new Error(`Invalid month number: ${mon}`);
14
+ const nextMon = mon === 12 ? 1 : mon + 1;
15
+ const nextYear = mon === 12 ? year + 1 : year;
16
+ const monthStart = `${year}-${String(mon).padStart(2, "0")}-01T00:00:00.000Z`;
17
+ const monthEnd = `${nextYear}-${String(nextMon).padStart(2, "0")}-01T00:00:00.000Z`;
18
+ return { monthStart, monthEnd };
19
+ }
20
+ function globMatch(pattern, str) {
21
+ const re = new RegExp("^" +
22
+ pattern
23
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
24
+ .replace(/\*/g, ".*")
25
+ .replace(/\?/g, ".") +
26
+ "$");
27
+ return re.test(str);
28
+ }
29
+ function resolveTeam(repoName, mappings) {
30
+ if (!repoName)
31
+ return "(unassigned)";
32
+ for (const m of mappings) {
33
+ for (const pat of m.repos) {
34
+ if (globMatch(pat, repoName))
35
+ return m.team;
36
+ }
37
+ }
38
+ return "(unassigned)";
39
+ }
40
+ function csvField(val) {
41
+ if (val === null || val === undefined)
42
+ return "";
43
+ const s = String(val);
44
+ if (s.includes(",") || s.includes('"') || s.includes("\n") || s.includes("\r")) {
45
+ return `"${s.replace(/"/g, '""')}"`;
46
+ }
47
+ return s;
48
+ }
49
+ // ── core logic (exported for tests) ──────────────────────────────────────────
50
+ /**
51
+ * Aggregate session rows into chargeback rows.
52
+ *
53
+ * In collaborative mode the developerEmail property is omitted from every row,
54
+ * and rows are grouped by (team, repo, tool, model, costType) only.
55
+ * In individual mode developerEmail is included as an additional group-by dimension.
56
+ */
57
+ export function buildChargebackRows(sessions, opts) {
58
+ const { month, costCenter, teamMappings, privacyMode } = opts;
59
+ const isCollaborative = privacyMode === "collaborative";
60
+ const agg = new Map();
61
+ for (const row of sessions) {
62
+ const team = resolveTeam(row.repoName, teamMappings);
63
+ const repo = row.repoName ?? "(unknown)";
64
+ const developerEmail = isCollaborative
65
+ ? undefined
66
+ : (row.gitAuthorEmail ?? "(unattributed)");
67
+ const key = isCollaborative
68
+ ? `${month}|${costCenter}|${team}|${repo}|${row.tool}|${row.model}|${row.costType}`
69
+ : `${month}|${costCenter}|${team}|${repo}|${developerEmail}|${row.tool}|${row.model}|${row.costType}`;
70
+ const existing = agg.get(key);
71
+ if (existing) {
72
+ existing.costUsd += row.costUsd;
73
+ existing.consumptionValueUsd += row.costUsd;
74
+ if (row.mergedPrNumber !== null)
75
+ existing.shippedPrNumbers.add(row.mergedPrNumber);
76
+ existing.sessionCount++;
77
+ }
78
+ else {
79
+ const base = {
80
+ month,
81
+ costCenter,
82
+ team,
83
+ repo,
84
+ tool: row.tool,
85
+ model: row.model,
86
+ costType: row.costType,
87
+ ...(developerEmail !== undefined ? { developerEmail } : {}),
88
+ };
89
+ agg.set(key, {
90
+ base,
91
+ costUsd: row.costUsd,
92
+ consumptionValueUsd: row.costUsd,
93
+ shippedPrNumbers: row.mergedPrNumber !== null ? new Set([row.mergedPrNumber]) : new Set(),
94
+ sessionCount: 1,
95
+ });
96
+ }
97
+ }
98
+ return [...agg.values()].map((a) => ({
99
+ ...a.base,
100
+ costUsd: a.costUsd,
101
+ consumptionValueUsd: a.consumptionValueUsd,
102
+ shippedPrCount: a.shippedPrNumbers.size,
103
+ sessions: a.sessionCount,
104
+ }));
105
+ }
106
+ function rowsToCsv(rows, isCollaborative) {
107
+ const header = isCollaborative
108
+ ? ["month", "costCenter", "team", "repo", "tool", "model", "costType",
109
+ "costUsd", "consumptionValueUsd", "shippedPrCount", "sessions"]
110
+ : ["month", "costCenter", "team", "repo", "developerEmail", "tool", "model", "costType",
111
+ "costUsd", "consumptionValueUsd", "shippedPrCount", "sessions"];
112
+ const lines = [header.join(",")];
113
+ for (const r of rows) {
114
+ const cols = isCollaborative
115
+ ? [
116
+ csvField(r.month), csvField(r.costCenter), csvField(r.team), csvField(r.repo),
117
+ csvField(r.tool), csvField(r.model), csvField(r.costType),
118
+ csvField(r.costUsd.toFixed(6)), csvField(r.consumptionValueUsd.toFixed(6)),
119
+ csvField(r.shippedPrCount), csvField(r.sessions),
120
+ ]
121
+ : [
122
+ csvField(r.month), csvField(r.costCenter), csvField(r.team), csvField(r.repo),
123
+ csvField(r.developerEmail), csvField(r.tool), csvField(r.model), csvField(r.costType),
124
+ csvField(r.costUsd.toFixed(6)), csvField(r.consumptionValueUsd.toFixed(6)),
125
+ csvField(r.shippedPrCount), csvField(r.sessions),
126
+ ];
127
+ lines.push(cols.join(","));
128
+ }
129
+ return lines.join("\r\n") + "\r\n";
130
+ }
131
+ // ── CLI handlers ──────────────────────────────────────────────────────────────
132
+ export function runExportChargeback(opts) {
133
+ const { monthStart, monthEnd } = parseMonth(opts.month);
134
+ initDb();
135
+ const config = readConfig();
136
+ const costCenter = config.workspaceName ?? config.workspaceId ?? "(unknown)";
137
+ const { teamMappings, privacyMode } = config;
138
+ const sessions = getSessionsForExport(monthStart, monthEnd);
139
+ const rows = buildChargebackRows(sessions, {
140
+ month: opts.month,
141
+ costCenter,
142
+ teamMappings,
143
+ privacyMode,
144
+ });
145
+ const csv = rowsToCsv(rows, privacyMode === "collaborative");
146
+ const outPath = path.resolve(opts.out);
147
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
148
+ fs.writeFileSync(outPath, csv, { encoding: "utf-8" });
149
+ console.log(`Exported ${rows.length} row(s) to ${outPath}`);
150
+ }
151
+ export function runExportSessions(opts) {
152
+ const { monthStart, monthEnd } = parseMonth(opts.month);
153
+ initDb();
154
+ const sessions = getSessionsForExport(monthStart, monthEnd);
155
+ const lines = sessions.map((row) => JSON.stringify({
156
+ id: row.id,
157
+ tool: row.tool,
158
+ model: row.model,
159
+ startedAt: row.startedAt,
160
+ endedAt: row.endedAt,
161
+ inputTokens: row.inputTokens,
162
+ outputTokens: row.outputTokens,
163
+ cacheReadTokens: row.cacheReadTokens,
164
+ cacheWriteTokens: row.cacheWriteTokens,
165
+ costUsd: row.costUsd,
166
+ costType: row.costType,
167
+ subscriptionPlan: row.subscriptionPlan,
168
+ repoName: row.repoName,
169
+ gitBranch: row.gitBranch,
170
+ gitAuthorEmail: row.gitAuthorEmail,
171
+ workingDir: row.workingDir,
172
+ turnCount: row.turnCount,
173
+ filesTouchedCount: row.filesTouchedCount,
174
+ outcome: row.outcome,
175
+ mergedPrNumber: row.mergedPrNumber,
176
+ mergedAt: row.mergedAt,
177
+ timeToMergeMs: row.timeToMergeMs,
178
+ }));
179
+ const outPath = path.resolve(opts.out);
180
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
181
+ fs.writeFileSync(outPath, lines.length > 0 ? lines.join("\n") + "\n" : "", { encoding: "utf-8" });
182
+ console.log(`Exported ${sessions.length} session(s) to ${outPath}`);
183
+ }
184
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,4 @@
1
- export declare function runInit(): void;
1
+ export declare function runInit(opts?: {
2
+ noDaemon?: boolean;
3
+ }): void;
2
4
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAGA,wBAAgB,OAAO,IAAI,IAAI,CAS9B"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,wBAAgB,OAAO,CAAC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,IAAI,CAsB/D"}
@@ -1,12 +1,25 @@
1
1
  import fs from "fs";
2
2
  import { PLANCKSPACE_DIR, DB_PATH, initDb } from "../db/store.js";
3
- export function runInit() {
3
+ import { installDaemon } from "./daemon.js";
4
+ export function runInit(opts = {}) {
4
5
  fs.mkdirSync(PLANCKSPACE_DIR, { recursive: true, mode: 0o700 });
5
6
  initDb(DB_PATH);
6
7
  console.log("PlanckSpace initialized.");
7
8
  console.log(` Directory : ${PLANCKSPACE_DIR}`);
8
9
  console.log(` Database : ${DB_PATH} (WAL mode)`);
9
10
  console.log("");
11
+ if (!opts.noDaemon) {
12
+ console.log("Installing background sync daemon...");
13
+ try {
14
+ installDaemon();
15
+ }
16
+ catch (err) {
17
+ // Non-fatal: daemon install failure should not block init.
18
+ console.warn(` Warning: daemon install failed — ${String(err)}`);
19
+ console.warn(" Run `planck daemon install` manually to retry.");
20
+ }
21
+ console.log("");
22
+ }
10
23
  console.log("Next step: run `planck login` to connect your workspace.");
11
24
  }
12
25
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAElE,MAAM,UAAU,OAAO;IACrB,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,OAAO,CAAC,CAAC;IAEhB,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,iBAAiB,eAAe,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,iBAAiB,OAAO,aAAa,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;AAC1E,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,UAAU,OAAO,CAAC,OAA+B,EAAE;IACvD,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,OAAO,CAAC,CAAC;IAEhB,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,iBAAiB,eAAe,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,iBAAiB,OAAO,aAAa,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,IAAI,CAAC;YACH,aAAa,EAAE,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,2DAA2D;YAC3D,OAAO,CAAC,IAAI,CAAC,sCAAsC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runInsights(): Promise<void>;
2
+ //# sourceMappingURL=insights.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insights.d.ts","sourceRoot":"","sources":["../../src/commands/insights.ts"],"names":[],"mappings":"AAkCA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoDjD"}
@@ -0,0 +1,71 @@
1
+ import { initDb, getSessions, upsertInsights } from "../db/store.js";
2
+ import { readConfig } from "../config.js";
3
+ import { parseSession, runDetectors } from "../detectors/index.js";
4
+ import { syncOnce } from "../sync/syncEngine.js";
5
+ import { getSyncDeps } from "./sync.js";
6
+ function formatSavings(usd) {
7
+ return usd > 0 ? `$${usd.toFixed(2)}/mo` : "—";
8
+ }
9
+ function printInsightTable(insights) {
10
+ const COL = { detector: 24, scope: 12, savings: 13, confidence: 10 };
11
+ const header = " " +
12
+ "Detector".padEnd(COL.detector) +
13
+ "Scope".padEnd(COL.scope) +
14
+ "Savings/mo".padEnd(COL.savings) +
15
+ "Confidence";
16
+ const divider = " " + "─".repeat(COL.detector + COL.scope + COL.savings + COL.confidence);
17
+ console.log(header);
18
+ console.log(divider);
19
+ for (const insight of insights) {
20
+ const detector = insight.detectorId.padEnd(COL.detector);
21
+ const scope = insight.workspaceScope.padEnd(COL.scope);
22
+ const savings = formatSavings(insight.estimatedMonthlySavingsUsd).padEnd(COL.savings);
23
+ const confidence = insight.confidence;
24
+ console.log(` ${detector}${scope}${savings}${confidence}`);
25
+ console.log(` → ${insight.titleShort}`);
26
+ }
27
+ }
28
+ export async function runInsights() {
29
+ initDb();
30
+ const config = readConfig();
31
+ const rows = getSessions();
32
+ if (rows.length === 0) {
33
+ console.log("No sessions in local DB. Run `planck scan` first.");
34
+ return;
35
+ }
36
+ const sessions = rows.map(parseSession);
37
+ const { insights, skipped } = runDetectors(sessions, config.subscriptions);
38
+ console.log(`PlanckSpace Insights (${new Date().toISOString().slice(0, 10)})`);
39
+ console.log("═══════════════════════════════════════════════════════════════");
40
+ if (skipped.length > 0) {
41
+ console.log("\n Skipped (insufficient data):");
42
+ for (const { detectorId, reason } of skipped) {
43
+ console.log(` ${detectorId.padEnd(22)} ${reason}`);
44
+ }
45
+ }
46
+ if (insights.length === 0) {
47
+ console.log("\n No actionable insights — you're running lean.");
48
+ }
49
+ else {
50
+ console.log("");
51
+ printInsightTable(insights);
52
+ const totalSavings = insights.reduce((s, i) => s + i.estimatedMonthlySavingsUsd, 0);
53
+ console.log("");
54
+ console.log(` ${insights.length} insight(s) | Est. total savings: $${totalSavings.toFixed(2)}/mo`);
55
+ upsertInsights(insights);
56
+ console.log(" Insights saved to local DB.");
57
+ // Attempt sync if the workspace is connected. Failures are advisory.
58
+ const deps = await getSyncDeps();
59
+ if (deps) {
60
+ const result = await syncOnce(deps);
61
+ if (result.authWarnings.length > 0) {
62
+ console.log(" Insights sync: auth failure — re-run `planck login`.");
63
+ }
64
+ else {
65
+ console.log(" Insights synced.");
66
+ }
67
+ }
68
+ }
69
+ console.log("");
70
+ }
71
+ //# sourceMappingURL=insights.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insights.js","sourceRoot":"","sources":["../../src/commands/insights.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runInspect(sessionId: string): void;
2
+ //# sourceMappingURL=inspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"AAIA,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAuElD"}
@@ -0,0 +1,81 @@
1
+ import { initDb, getSessionById } from "../db/store.js";
2
+ import { buildTelemetryPayload } from "../sync/payload.js";
3
+ export function runInspect(sessionId) {
4
+ initDb();
5
+ const row = getSessionById(sessionId);
6
+ if (!row) {
7
+ console.error(`Session not found: ${sessionId}`);
8
+ process.exitCode = 1;
9
+ return;
10
+ }
11
+ // Build the same payload that would be sent on the wire so the view is accurate.
12
+ const payload = buildTelemetryPayload(row, "(local-inspect)");
13
+ const sep = "─".repeat(72);
14
+ console.log(sep);
15
+ console.log(`Session ${payload.sessionId}`);
16
+ console.log(sep);
17
+ // ── Session-level header ───────────────────────────────────────────────────
18
+ console.log(` Tool ${payload.tool}`);
19
+ console.log(` Model ${payload.model} (dominant / first-turn)`);
20
+ console.log(` Started ${payload.startedAt}`);
21
+ console.log(` Ended ${payload.endedAt}`);
22
+ console.log(` Repo ${payload.repoName}`);
23
+ console.log(` Branch ${payload.gitBranch ?? "(none)"}`);
24
+ console.log(` Author ${payload.gitAuthorEmail ?? "(unresolved)"}`);
25
+ console.log(` Outcome ${payload.outcome}`);
26
+ if (payload.mergedPrNumber !== null) {
27
+ console.log(` Merged PR #${payload.mergedPrNumber} at ${payload.mergedAt}`);
28
+ }
29
+ // ── Cost summary ──────────────────────────────────────────────────────────
30
+ console.log();
31
+ console.log(" Cost");
32
+ console.log(` costType ${payload.costType}`);
33
+ console.log(` subscriptionPlan ${payload.subscriptionPlan ?? "(none)"}`);
34
+ console.log(` costUsd $${payload.costUsd.toFixed(6)}`);
35
+ console.log(` consumptionValueUsd $${payload.consumptionValueUsd.toFixed(6)}`);
36
+ console.log(` unmatchedTurns ${payload.unmatchedTurns}` +
37
+ (payload.unmatchedTurns > 0 ? " ⚠ cost for these turns is 0" : ""));
38
+ // ── Token summary ─────────────────────────────────────────────────────────
39
+ console.log();
40
+ console.log(" Tokens (session aggregate)");
41
+ console.log(` input ${payload.inputTokens.toLocaleString()}`);
42
+ console.log(` output ${payload.outputTokens.toLocaleString()}`);
43
+ console.log(` cacheRead ${payload.cacheReadTokens.toLocaleString()}`);
44
+ console.log(` cacheWrite ${payload.cacheWriteTokens.toLocaleString()}`);
45
+ // ── Per-turn breakdown ────────────────────────────────────────────────────
46
+ console.log();
47
+ console.log(` Turns (${payload.turns.length})`);
48
+ for (const turn of payload.turns) {
49
+ printTurn(turn);
50
+ }
51
+ // ── Re-read patterns ──────────────────────────────────────────────────────
52
+ if (payload.reReadPatterns.length > 0) {
53
+ console.log();
54
+ console.log(" Re-read files (touched in >1 turn)");
55
+ for (const { path: p, count } of payload.reReadPatterns) {
56
+ const bar = "█".repeat(Math.min(count, 20));
57
+ console.log(` ${String(count).padStart(3)}× ${bar} ${p}`);
58
+ }
59
+ }
60
+ else {
61
+ console.log();
62
+ console.log(" Re-read files (none — each file touched in only one turn)");
63
+ }
64
+ console.log();
65
+ console.log(sep);
66
+ }
67
+ function printTurn(t) {
68
+ const tools = t.toolCalls.map((tc) => `${tc.name}×${tc.count}`).join(", ") || "(none)";
69
+ const files = t.filesTouched.length > 0
70
+ ? t.filesTouched.map((f) => `\n ${f}`).join("")
71
+ : " (none)";
72
+ console.log();
73
+ console.log(` ┌─ Turn ${t.sequence} ${t.timestamp}`);
74
+ console.log(` │ model ${t.model}`);
75
+ console.log(` │ tokens in=${t.inputTokens.toLocaleString()} out=${t.outputTokens.toLocaleString()} ` +
76
+ `cacheRead=${t.cacheReadTokens.toLocaleString()} cacheCreate=${t.cacheCreationInputTokens.toLocaleString()}`);
77
+ console.log(` │ cost $${t.costUsd.toFixed(6)}`);
78
+ console.log(` │ tools ${tools}`);
79
+ console.log(` └─ files ${files}`);
80
+ }
81
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runIntegrationsList(): Promise<void>;
2
+ //# sourceMappingURL=integrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../src/commands/integrations.ts"],"names":[],"mappings":"AAaA,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgDzD"}
@@ -0,0 +1,46 @@
1
+ import { readConfig, resolveApiUrl } from "../config.js";
2
+ import { redactSecrets } from "./connect.js";
3
+ export async function runIntegrationsList() {
4
+ const config = readConfig();
5
+ if (!config.token) {
6
+ console.error("Not connected. Run `planck login <token>` first.");
7
+ process.exitCode = 1;
8
+ return;
9
+ }
10
+ const apiUrl = resolveApiUrl();
11
+ let res;
12
+ try {
13
+ res = await fetch(`${apiUrl}/api/integrations`, {
14
+ headers: { Authorization: `Bearer ${config.token}` },
15
+ });
16
+ }
17
+ catch (err) {
18
+ console.error(`Could not reach backend: ${redactSecrets(String(err))}`);
19
+ process.exitCode = 1;
20
+ return;
21
+ }
22
+ if (!res.ok) {
23
+ console.error(`Backend returned ${res.status}.`);
24
+ process.exitCode = 1;
25
+ return;
26
+ }
27
+ const integrations = (await res.json());
28
+ if (!integrations.length) {
29
+ console.log("No integrations connected.");
30
+ console.log("Add one with `planck connect anthropic`, `planck connect openai`, or `planck connect bedrock`.");
31
+ return;
32
+ }
33
+ console.log(`Connected integrations (${integrations.length}):\n`);
34
+ for (const entry of integrations) {
35
+ console.log(` ${entry.kind} [${entry.status}]`);
36
+ console.log(` Last validated: ${entry.lastValidatedAt ?? "never"}`);
37
+ console.log(` Last sync: ${entry.lastSyncedAt ?? "never"}`);
38
+ if (entry.lastError) {
39
+ // Redact defensively — a provider validation error stored server-side may
40
+ // echo a key fragment; it must never surface here.
41
+ console.log(` Last error: ${redactSecrets(entry.lastError)}`);
42
+ }
43
+ console.log();
44
+ }
45
+ }
46
+ //# sourceMappingURL=integrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../src/commands/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAY7C,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,mBAAmB,EAAE;YAC9C,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,KAAK,EAAE,EAAE;SACrD,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QACxE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,oBAAoB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAC;IAE9D,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CACT,gGAAgG,CACjG,CAAC;QACF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2BAA2B,YAAY,CAAC,MAAM,MAAM,CAAC,CAAC;IAClE,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,eAAe,IAAI,OAAO,EAAE,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,YAAY,IAAI,OAAO,EAAE,CAAC,CAAC;QACpE,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,0EAA0E;YAC1E,mDAAmD;YACnD,OAAO,CAAC,GAAG,CAAC,uBAAuB,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare function runLogin(tokenArg?: string): Promise<void>;
1
+ export declare function runLogin(tokenArg?: string, apiUrlArg?: string): Promise<void>;
2
2
  //# sourceMappingURL=login.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAOA,wBAAsB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiD/D"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAgBA,wBAAsB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFnF"}
@@ -1,5 +1,8 @@
1
1
  import { readConfig, writeConfig, resolveApiUrl } from "../config.js";
2
- export async function runLogin(tokenArg) {
2
+ import { initDb, resetSyncState } from "../db/store.js";
3
+ import { commitHealthState } from "../health.js";
4
+ import { runScan } from "./scan.js";
5
+ export async function runLogin(tokenArg, apiUrlArg) {
3
6
  const token = tokenArg ?? process.env.PLANCKSPACE_TOKEN ?? null;
4
7
  if (!token) {
5
8
  console.error("No token provided.\n" +
@@ -9,7 +12,9 @@ export async function runLogin(tokenArg) {
9
12
  process.exit(1);
10
13
  }
11
14
  const config = readConfig();
12
- const apiUrl = resolveApiUrl();
15
+ // Precedence: --api-url flag (cross-platform, works in cmd/PowerShell/sh)
16
+ // → PLANCKSPACE_API_URL env → config file → default.
17
+ const apiUrl = apiUrlArg?.trim() || resolveApiUrl();
13
18
  let workspaceId = null;
14
19
  let workspaceName = null;
15
20
  try {
@@ -32,14 +37,48 @@ export async function runLogin(tokenArg) {
32
37
  catch {
33
38
  console.error("Could not reach API; token stored, workspace will resolve on first sync.");
34
39
  }
35
- // Persist the apiUrl we actually used (may come from PLANCKSPACE_API_URL),
36
- // so later commands stay pointed at the same backend without the env var.
40
+ const previousWorkspaceId = config.workspaceId;
37
41
  writeConfig({ ...config, apiUrl, token, workspaceId, workspaceName });
38
- if (workspaceName) {
39
- console.log(`Connected to ${workspaceName}.`);
42
+ // Initialize DB before any DB operations (resetSyncState, commitHealthState).
43
+ initDb();
44
+ if (previousWorkspaceId && workspaceId && previousWorkspaceId !== workspaceId) {
45
+ resetSyncState();
46
+ console.log("Workspace changed — queuing all local sessions for re-sync.");
47
+ }
48
+ // After a successful login, record health state so future runs can detect drift.
49
+ if (workspaceId) {
50
+ try {
51
+ const healthRes = await fetch(`${apiUrl}/api/me/health`, {
52
+ headers: { Authorization: `Bearer ${token}` },
53
+ signal: AbortSignal.timeout(10_000),
54
+ });
55
+ if (healthRes.ok) {
56
+ const hd = (await healthRes.json());
57
+ if (hd.backendDbInstanceId) {
58
+ commitHealthState(hd.backendDbInstanceId, workspaceId);
59
+ const shortId = hd.backendDbInstanceId.slice(0, 8);
60
+ const displayName = workspaceName ?? workspaceId;
61
+ console.log(`Connected to ${displayName} (db instance ${shortId})`);
62
+ }
63
+ else if (workspaceName) {
64
+ console.log(`Connected to ${workspaceName}.`);
65
+ }
66
+ else {
67
+ console.log("Token saved. Run `planck sync` to complete workspace setup.");
68
+ }
69
+ }
70
+ else {
71
+ // Health endpoint not yet deployed — fall back gracefully.
72
+ console.log(workspaceName ? `Connected to ${workspaceName}.` : "Token saved.");
73
+ }
74
+ }
75
+ catch {
76
+ console.log(workspaceName ? `Connected to ${workspaceName}.` : "Token saved.");
77
+ }
40
78
  }
41
79
  else {
42
80
  console.log("Token saved. Run `planck sync` to complete workspace setup.");
43
81
  }
82
+ await runScan({ sync: true });
44
83
  }
45
84
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAOtE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAiB;IAC9C,MAAM,KAAK,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC;IAEhE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CACX,sBAAsB;YACpB,0BAA0B;YAC1B,sCAAsC;YACtC,8CAA8C,CACjD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,IAAI,WAAW,GAAkB,IAAI,CAAC;IACtC,IAAI,aAAa,GAAkB,IAAI,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,SAAS,EAAE;YAC1C,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;SAC9C,CAAC,CAAC;QAEH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAe,CAAC;YAC9C,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC;YACvC,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC;QAC7C,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CACX,gBAAgB,GAAG,CAAC,MAAM,uDAAuD,CAClF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC5F,CAAC;IAED,2EAA2E;IAC3E,0EAA0E;IAC1E,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC;IAEtE,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,gBAAgB,aAAa,GAAG,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type MetricsCommandOptions = {
2
+ byRepo?: boolean;
3
+ byDeveloper?: boolean;
4
+ };
5
+ export declare function runMetrics(options?: MetricsCommandOptions): Promise<void>;
6
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/commands/metrics.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AA4EF,wBAAsB,UAAU,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BnF"}