prismalens 0.2.0 → 0.4.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 +29 -13
- package/dist/bin/prismalens.js +39 -50
- package/dist/chunk-2Z7QZSIS.js +20 -0
- package/dist/chunk-5BT3XQOG.js +2990 -0
- package/dist/chunk-6N4PHBII.js +30 -0
- package/dist/chunk-CTKCK7QT.js +387 -0
- package/dist/chunk-CVSS5JPC.js +130 -0
- package/dist/chunk-HPE5CTO4.js +22 -0
- package/dist/chunk-PTBCAI34.js +34 -0
- package/dist/chunk-PVQVFRIV.js +452 -0
- package/dist/chunk-QDK5PAI3.js +155 -0
- package/dist/chunk-SSEIMBQ2.js +204 -0
- package/dist/chunk-TGP6QTFO.js +156 -0
- package/dist/chunk-V6M6ISKI.js +161 -0
- package/dist/chunk-XH6DIKTA.js +83 -0
- package/dist/src/cli/auth.js +112 -101
- package/dist/src/cli/doctor.js +184 -187
- package/dist/src/cli/flags.js +6 -29
- package/dist/src/cli/grouping.js +16 -227
- package/dist/src/cli/init.js +58 -52
- package/dist/src/cli/investigate.js +23 -465
- package/dist/src/cli/listen.js +550 -286
- package/dist/src/cli/report.js +70 -67
- package/dist/src/cli/serve.js +260 -30
- package/dist/src/cli/status.js +87 -86
- package/package.json +16 -7
- package/dist/bin/prismalens.d.ts +0 -3
- package/dist/bin/prismalens.d.ts.map +0 -1
- package/dist/bin/prismalens.js.map +0 -1
- package/dist/src/cli/auth.d.ts +0 -3
- package/dist/src/cli/auth.d.ts.map +0 -1
- package/dist/src/cli/auth.js.map +0 -1
- package/dist/src/cli/doctor.d.ts +0 -18
- package/dist/src/cli/doctor.d.ts.map +0 -1
- package/dist/src/cli/doctor.js.map +0 -1
- package/dist/src/cli/flags.d.ts +0 -2
- package/dist/src/cli/flags.d.ts.map +0 -1
- package/dist/src/cli/flags.js.map +0 -1
- package/dist/src/cli/grouping.d.ts +0 -18
- package/dist/src/cli/grouping.d.ts.map +0 -1
- package/dist/src/cli/grouping.js.map +0 -1
- package/dist/src/cli/init.d.ts +0 -3
- package/dist/src/cli/init.d.ts.map +0 -1
- package/dist/src/cli/init.js.map +0 -1
- package/dist/src/cli/investigate.d.ts +0 -115
- package/dist/src/cli/investigate.d.ts.map +0 -1
- package/dist/src/cli/investigate.js.map +0 -1
- package/dist/src/cli/listen.d.ts +0 -56
- package/dist/src/cli/listen.d.ts.map +0 -1
- package/dist/src/cli/listen.js.map +0 -1
- package/dist/src/cli/report.d.ts +0 -24
- package/dist/src/cli/report.d.ts.map +0 -1
- package/dist/src/cli/report.js.map +0 -1
- package/dist/src/cli/serve.d.ts +0 -3
- package/dist/src/cli/serve.d.ts.map +0 -1
- package/dist/src/cli/serve.js.map +0 -1
- package/dist/src/cli/status.d.ts +0 -19
- package/dist/src/cli/status.d.ts.map +0 -1
- package/dist/src/cli/status.js.map +0 -1
- package/dist/src/config/loader.d.ts +0 -22
- package/dist/src/config/loader.d.ts.map +0 -1
- package/dist/src/config/loader.js +0 -193
- package/dist/src/config/loader.js.map +0 -1
- package/dist/src/config/schema.d.ts +0 -463
- package/dist/src/config/schema.d.ts.map +0 -1
- package/dist/src/config/schema.js +0 -217
- package/dist/src/config/schema.js.map +0 -1
- package/dist/src/core/caps.d.ts +0 -36
- package/dist/src/core/caps.d.ts.map +0 -1
- package/dist/src/core/caps.js +0 -36
- package/dist/src/core/caps.js.map +0 -1
- package/dist/src/core/db.d.ts +0 -3
- package/dist/src/core/db.d.ts.map +0 -1
- package/dist/src/core/db.js +0 -105
- package/dist/src/core/db.js.map +0 -1
- package/dist/src/core/detect-repo.d.ts +0 -4
- package/dist/src/core/detect-repo.d.ts.map +0 -1
- package/dist/src/core/detect-repo.js +0 -28
- package/dist/src/core/detect-repo.js.map +0 -1
- package/dist/src/core/file-session-store.d.ts +0 -10
- package/dist/src/core/file-session-store.d.ts.map +0 -1
- package/dist/src/core/file-session-store.js +0 -34
- package/dist/src/core/file-session-store.js.map +0 -1
- package/dist/src/core/parse-stdin.d.ts +0 -2
- package/dist/src/core/parse-stdin.d.ts.map +0 -1
- package/dist/src/core/parse-stdin.js +0 -21
- package/dist/src/core/parse-stdin.js.map +0 -1
- package/dist/src/core/run-investigation.d.ts +0 -54
- package/dist/src/core/run-investigation.d.ts.map +0 -1
- package/dist/src/core/run-investigation.js +0 -200
- package/dist/src/core/run-investigation.js.map +0 -1
- package/dist/src/core/session.d.ts +0 -63
- package/dist/src/core/session.d.ts.map +0 -1
- package/dist/src/core/session.js +0 -45
- package/dist/src/core/session.js.map +0 -1
- package/dist/src/core/slack-notify.d.ts +0 -9
- package/dist/src/core/slack-notify.d.ts.map +0 -1
- package/dist/src/core/slack-notify.js +0 -57
- package/dist/src/core/slack-notify.js.map +0 -1
- package/dist/src/core/sqlite-session-store.d.ts +0 -39
- package/dist/src/core/sqlite-session-store.d.ts.map +0 -1
- package/dist/src/core/sqlite-session-store.js +0 -239
- package/dist/src/core/sqlite-session-store.js.map +0 -1
- package/dist/src/http/server.d.ts +0 -31
- package/dist/src/http/server.d.ts.map +0 -1
- package/dist/src/http/server.js +0 -164
- package/dist/src/http/server.js.map +0 -1
- package/dist/src/jsonrpc/server.d.ts +0 -15
- package/dist/src/jsonrpc/server.d.ts.map +0 -1
- package/dist/src/jsonrpc/server.js +0 -244
- package/dist/src/jsonrpc/server.js.map +0 -1
- package/dist/src/jsonrpc/types.d.ts +0 -12
- package/dist/src/jsonrpc/types.d.ts.map +0 -1
- package/dist/src/jsonrpc/types.js +0 -4
- package/dist/src/jsonrpc/types.js.map +0 -1
- package/dist/src/version.d.ts +0 -8
- package/dist/src/version.d.ts.map +0 -1
- package/dist/src/version.js +0 -27
- package/dist/src/version.js.map +0 -1
package/dist/src/cli/grouping.js
CHANGED
|
@@ -1,227 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return createHash("sha256").update(sorted).digest("hex");
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
const serviceLabel = pickServiceLabel(alert);
|
|
21
|
-
const alertname = alert.labels?.alertname || "";
|
|
22
|
-
if (serviceLabel) {
|
|
23
|
-
return `${alertname}\0${serviceLabel}`;
|
|
24
|
-
}
|
|
25
|
-
const alertLabels = alert.labels;
|
|
26
|
-
if (alertLabels && Object.keys(alertLabels).length > 0) {
|
|
27
|
-
const sorted = Object.keys(alertLabels)
|
|
28
|
-
.sort()
|
|
29
|
-
.map((k) => `${k}=${alertLabels[k]}`)
|
|
30
|
-
.join(",");
|
|
31
|
-
return createHash("sha256").update(sorted).digest("hex");
|
|
32
|
-
}
|
|
33
|
-
return "default";
|
|
34
|
-
}
|
|
35
|
-
export function deriveDedupeKey(alert) {
|
|
36
|
-
if (typeof alert.fingerprint === "string" && alert.fingerprint) {
|
|
37
|
-
return alert.fingerprint;
|
|
38
|
-
}
|
|
39
|
-
const alertLabels = alert.labels;
|
|
40
|
-
const alertname = alertLabels?.alertname || "";
|
|
41
|
-
const sorted = alertLabels
|
|
42
|
-
? Object.keys(alertLabels)
|
|
43
|
-
.sort()
|
|
44
|
-
.map((k) => `${k}=${alertLabels[k]}`)
|
|
45
|
-
.join(",")
|
|
46
|
-
: "";
|
|
47
|
-
const hash = createHash("sha256").update(sorted).digest("hex");
|
|
48
|
-
const startsAt = alert.startsAt || "";
|
|
49
|
-
return `${alertname}${hash}${startsAt}`;
|
|
50
|
-
}
|
|
51
|
-
export function createGroupingLayer(options) {
|
|
52
|
-
let shuttingDown = false;
|
|
53
|
-
const windows = new Map();
|
|
54
|
-
const running = new Map();
|
|
55
|
-
const activeAlerts = new Map();
|
|
56
|
-
return {
|
|
57
|
-
isShuttingDown() {
|
|
58
|
-
return shuttingDown;
|
|
59
|
-
},
|
|
60
|
-
newGroupCount(firing, payload) {
|
|
61
|
-
const keys = new Set();
|
|
62
|
-
for (const alert of firing) {
|
|
63
|
-
const key = deriveGroupKey(alert, payload);
|
|
64
|
-
if (!windows.has(key) && !running.has(key)) {
|
|
65
|
-
keys.add(key);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return keys.size;
|
|
69
|
-
},
|
|
70
|
-
pendingGroups() {
|
|
71
|
-
return windows.size + running.size;
|
|
72
|
-
},
|
|
73
|
-
admit(firing, payload) {
|
|
74
|
-
if (shuttingDown) {
|
|
75
|
-
options.log("Dropped alert: grouping layer is shutting down");
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
for (const alert of firing) {
|
|
79
|
-
const groupKey = deriveGroupKey(alert, payload);
|
|
80
|
-
const dedupeKey = deriveDedupeKey(alert);
|
|
81
|
-
// 1. Fingerprint-level suppression (Issue #137)
|
|
82
|
-
// If this exact fingerprint is already in-flight anywhere, attach the re-page
|
|
83
|
-
// to its existing investigation and suppress dispatch.
|
|
84
|
-
if (activeAlerts.has(dedupeKey)) {
|
|
85
|
-
const active = activeAlerts.get(dedupeKey);
|
|
86
|
-
if (active && active.phase === "running" && active.runId) {
|
|
87
|
-
const state = running.get(active.groupKey);
|
|
88
|
-
/* v8 ignore next */
|
|
89
|
-
if (state) {
|
|
90
|
-
// Note the re-page on the existing run
|
|
91
|
-
state.writeQueue = state.writeQueue
|
|
92
|
-
.then(() => options.sessions.appendGroupAlert(state.runId, alert))
|
|
93
|
-
/* v8 ignore start */
|
|
94
|
-
.catch((err) => {
|
|
95
|
-
options.log(`Failed to attach re-page to group ${active.groupKey} (run ${state.runId}): ${err}`);
|
|
96
|
-
});
|
|
97
|
-
/* v8 ignore stop */
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
options.log(`Suppression lookup hit but run vanished for dedupeKey ${dedupeKey}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
// If phase === "window", it's buffered; no action needed.
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
// 2. Group-level attachment (AC2)
|
|
107
|
-
// If the group is already running, attach this NEW alert (different dedupeKey) to it.
|
|
108
|
-
if (running.has(groupKey)) {
|
|
109
|
-
const state = running.get(groupKey);
|
|
110
|
-
/* v8 ignore next */
|
|
111
|
-
if (state) {
|
|
112
|
-
// Note: we don't need seenKeys here because activeAlerts handles exact dupes above.
|
|
113
|
-
activeAlerts.set(dedupeKey, {
|
|
114
|
-
phase: "running",
|
|
115
|
-
groupKey,
|
|
116
|
-
runId: state.runId,
|
|
117
|
-
});
|
|
118
|
-
state.dedupeKeys.add(dedupeKey);
|
|
119
|
-
state.writeQueue = state.writeQueue
|
|
120
|
-
.then(() => options.sessions.appendGroupAlert(state.runId, alert))
|
|
121
|
-
/* v8 ignore start */
|
|
122
|
-
.catch((err) => {
|
|
123
|
-
options.log(`Failed to attach late alert to group ${groupKey} (run ${state.runId}): ${err}`);
|
|
124
|
-
});
|
|
125
|
-
/* v8 ignore stop */
|
|
126
|
-
}
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (windows.has(groupKey)) {
|
|
130
|
-
const state = windows.get(groupKey);
|
|
131
|
-
/* v8 ignore next */
|
|
132
|
-
if (state) {
|
|
133
|
-
activeAlerts.set(dedupeKey, { phase: "window", groupKey });
|
|
134
|
-
state.alerts.push(alert);
|
|
135
|
-
}
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
// IDLE -> WINDOW_OPEN
|
|
139
|
-
const state = {
|
|
140
|
-
alerts: [alert],
|
|
141
|
-
timer: setTimeout(() => {
|
|
142
|
-
// timer fires -> RUNNING
|
|
143
|
-
const alertsToRun = state.alerts;
|
|
144
|
-
windows.delete(groupKey);
|
|
145
|
-
const runId = randomUUID();
|
|
146
|
-
const dedupeKeys = new Set();
|
|
147
|
-
// Move all these dedupe keys to the running phase
|
|
148
|
-
for (const a of alertsToRun) {
|
|
149
|
-
const dkey = deriveDedupeKey(a);
|
|
150
|
-
activeAlerts.set(dkey, {
|
|
151
|
-
phase: "running",
|
|
152
|
-
groupKey,
|
|
153
|
-
runId,
|
|
154
|
-
});
|
|
155
|
-
dedupeKeys.add(dkey);
|
|
156
|
-
}
|
|
157
|
-
// synchronously set up the record
|
|
158
|
-
const rec = {
|
|
159
|
-
groupKey,
|
|
160
|
-
formedBy: "window",
|
|
161
|
-
alerts: alertsToRun,
|
|
162
|
-
lateAlerts: [],
|
|
163
|
-
};
|
|
164
|
-
const writePromise = Promise.resolve()
|
|
165
|
-
.then(() => options.sessions.writeGroupRecord(runId, rec))
|
|
166
|
-
.catch((err) => {
|
|
167
|
-
options.log(`Failed to write group record for group ${groupKey} (run ${runId}): ${err} — investigation will proceed without it`);
|
|
168
|
-
});
|
|
169
|
-
running.set(groupKey, {
|
|
170
|
-
runId,
|
|
171
|
-
writeQueue: writePromise,
|
|
172
|
-
dedupeKeys,
|
|
173
|
-
});
|
|
174
|
-
writePromise
|
|
175
|
-
.then(async () => {
|
|
176
|
-
// Shutdown may land between the timer firing and the write
|
|
177
|
-
// resolving; don't start a new investigation while closing.
|
|
178
|
-
if (shuttingDown) {
|
|
179
|
-
running.delete(groupKey);
|
|
180
|
-
for (const key of dedupeKeys) {
|
|
181
|
-
activeAlerts.delete(key);
|
|
182
|
-
}
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
try {
|
|
186
|
-
await options.runInvestigation(runId, alertsToRun);
|
|
187
|
-
}
|
|
188
|
-
catch (err) {
|
|
189
|
-
options.log(`Investigation for group ${groupKey} failed: ${err}`);
|
|
190
|
-
}
|
|
191
|
-
finally {
|
|
192
|
-
running.delete(groupKey);
|
|
193
|
-
// Clean up global fingerprint registry for this run
|
|
194
|
-
for (const key of dedupeKeys) {
|
|
195
|
-
activeAlerts.delete(key);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
})
|
|
199
|
-
.catch((err) => {
|
|
200
|
-
options.log(`Investigation for group ${groupKey} failed: ${err}`);
|
|
201
|
-
running.delete(groupKey);
|
|
202
|
-
for (const key of dedupeKeys) {
|
|
203
|
-
activeAlerts.delete(key);
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
}, options.windowMs),
|
|
207
|
-
};
|
|
208
|
-
activeAlerts.set(dedupeKey, { phase: "window", groupKey });
|
|
209
|
-
windows.set(groupKey, state);
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
shutdown() {
|
|
213
|
-
shuttingDown = true;
|
|
214
|
-
let dropped = 0;
|
|
215
|
-
for (const state of windows.values()) {
|
|
216
|
-
clearTimeout(state.timer);
|
|
217
|
-
dropped++;
|
|
218
|
-
}
|
|
219
|
-
windows.clear();
|
|
220
|
-
activeAlerts.clear();
|
|
221
|
-
if (dropped > 0) {
|
|
222
|
-
options.log(`Shutdown: dropped ${dropped} pending grouping windows`);
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
//# sourceMappingURL=grouping.js.map
|
|
1
|
+
import {
|
|
2
|
+
createGroupingLayer,
|
|
3
|
+
deriveDedupeKey,
|
|
4
|
+
deriveGroupKey
|
|
5
|
+
} from "../../chunk-SSEIMBQ2.js";
|
|
6
|
+
import "../../chunk-QDK5PAI3.js";
|
|
7
|
+
import "../../chunk-CVSS5JPC.js";
|
|
8
|
+
import "../../chunk-5BT3XQOG.js";
|
|
9
|
+
import "../../chunk-6N4PHBII.js";
|
|
10
|
+
import "../../chunk-XH6DIKTA.js";
|
|
11
|
+
import "../../chunk-2Z7QZSIS.js";
|
|
12
|
+
export {
|
|
13
|
+
createGroupingLayer,
|
|
14
|
+
deriveDedupeKey,
|
|
15
|
+
deriveGroupKey
|
|
16
|
+
};
|
package/dist/src/cli/init.js
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import {
|
|
2
|
+
AgentConfigSchema,
|
|
3
|
+
PlConfigSchema
|
|
4
|
+
} from "../../chunk-TGP6QTFO.js";
|
|
5
|
+
import {
|
|
6
|
+
assertKnownFlags
|
|
7
|
+
} from "../../chunk-PTBCAI34.js";
|
|
8
|
+
import "../../chunk-5BT3XQOG.js";
|
|
9
|
+
import {
|
|
10
|
+
INVESTIGATION_DEFAULTS
|
|
11
|
+
} from "../../chunk-6N4PHBII.js";
|
|
12
|
+
import "../../chunk-XH6DIKTA.js";
|
|
13
|
+
import "../../chunk-2Z7QZSIS.js";
|
|
14
|
+
|
|
15
|
+
// src/cli/init.ts
|
|
11
16
|
import { existsSync } from "node:fs";
|
|
12
17
|
import { writeFile } from "node:fs/promises";
|
|
13
18
|
import { resolve } from "node:path";
|
|
14
|
-
import { INVESTIGATION_DEFAULTS } from "@prismalens/config/investigation";
|
|
15
19
|
import { defineCommand } from "citty";
|
|
16
20
|
import consola from "consola";
|
|
17
|
-
|
|
18
|
-
import { assertKnownFlags } from "./flags.js";
|
|
19
|
-
const CONFIG_FILENAME = "prismalens.config.yaml";
|
|
20
|
-
/** Render a commented default config, sourcing live values from schema defaults. */
|
|
21
|
+
var CONFIG_FILENAME = "prismalens.config.yaml";
|
|
21
22
|
function renderDefaultConfig(d) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.options.join(" | ");
|
|
25
|
-
return `# prismalens.config.yaml — investigation engine configuration (ADR-0008/0010).
|
|
23
|
+
const harnessOptions = AgentConfigSchema.shape.default.removeDefault().options.join(" | ");
|
|
24
|
+
return `# prismalens.config.yaml \u2014 investigation engine configuration (ADR-0008/0010).
|
|
26
25
|
# Generated by \`prismalens init\`. Unset values fall back to built-in defaults;
|
|
27
26
|
# \`prismalens doctor\` checks the bits that gate a run.
|
|
28
27
|
|
|
@@ -34,18 +33,18 @@ function renderDefaultConfig(d) {
|
|
|
34
33
|
agent:
|
|
35
34
|
# Which agent harness to rent: ${harnessOptions}
|
|
36
35
|
default: ${d.agent.default}
|
|
37
|
-
# BARE model id, e.g. "gpt-oss:120b"
|
|
36
|
+
# BARE model id, e.g. "gpt-oss:120b" \u2014 the harness applies its own provider prefix.
|
|
38
37
|
# Omit to let the chosen harness pick its own default.
|
|
39
38
|
# model: gpt-oss:120b
|
|
40
39
|
|
|
41
40
|
# Read-only telemetry + app endpoints the harness may query. Point these at your
|
|
42
41
|
# stack; defaults assume a local dev setup.
|
|
43
42
|
telemetry:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
prometheus_url: ${INVESTIGATION_DEFAULTS.telemetry.prometheusUrl}
|
|
44
|
+
alertmanager_url: ${INVESTIGATION_DEFAULTS.telemetry.alertmanagerUrl}
|
|
45
|
+
api_url: ${INVESTIGATION_DEFAULTS.telemetry.apiUrl}
|
|
47
46
|
|
|
48
|
-
# Read-only log-query system the harness may curl (Loki, Elasticsearch,
|
|
47
|
+
# Read-only log-query system the harness may curl (Loki, Elasticsearch, \u2026).
|
|
49
48
|
# logs:
|
|
50
49
|
# kind: loki
|
|
51
50
|
# url: http://localhost:3100
|
|
@@ -61,9 +60,9 @@ telemetry:
|
|
|
61
60
|
|
|
62
61
|
# Where runs, events, and reports are stored.
|
|
63
62
|
workspace:
|
|
64
|
-
|
|
63
|
+
dir: ${d.workspace.dir}
|
|
65
64
|
|
|
66
|
-
# \`pl listen\`
|
|
65
|
+
# \`pl listen\` \u2014 token-authed local webhook intake (Alertmanager). The token is
|
|
67
66
|
# REQUIRED to start listening regardless of bind address; keep it out of the file via env interpolation.
|
|
68
67
|
# listen:
|
|
69
68
|
# host: ${d.listen.host}
|
|
@@ -72,30 +71,37 @@ workspace:
|
|
|
72
71
|
# max_pending: ${d.listen.max_pending}
|
|
73
72
|
`;
|
|
74
73
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
74
|
+
var init_default = defineCommand({
|
|
75
|
+
meta: {
|
|
76
|
+
name: "init",
|
|
77
|
+
description: `Scaffold a ${CONFIG_FILENAME} in the current directory
|
|
78
|
+
|
|
79
|
+
Examples:
|
|
80
|
+
$ pl init
|
|
81
|
+
$ pl init --force`
|
|
82
|
+
},
|
|
83
|
+
async run({ args, cmd }) {
|
|
84
|
+
try {
|
|
85
|
+
assertKnownFlags(args, cmd);
|
|
86
|
+
const configPath = resolve(process.cwd(), CONFIG_FILENAME);
|
|
87
|
+
if (existsSync(configPath)) {
|
|
88
|
+
consola.info(
|
|
89
|
+
`${CONFIG_FILENAME} already exists at ${configPath} \u2014 leaving it untouched.`
|
|
90
|
+
);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const defaults = PlConfigSchema.parse({});
|
|
94
|
+
await writeFile(configPath, renderDefaultConfig(defaults), "utf-8");
|
|
95
|
+
consola.success(`Created ${configPath}`);
|
|
96
|
+
consola.info(
|
|
97
|
+
"Edit it for your stack, then run `prismalens doctor` to verify your environment."
|
|
98
|
+
);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
consola.error(err instanceof Error ? err.message : String(err));
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
100
104
|
});
|
|
101
|
-
|
|
105
|
+
export {
|
|
106
|
+
init_default as default
|
|
107
|
+
};
|