@chainpatrol/cli 0.3.2 → 0.3.3
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/CHANGELOG.md +25 -0
- package/dist/{breakdown-BECXDJIS.js → breakdown-FFNYSXRQ.js} +2 -2
- package/dist/chunk-EBJMOX3Q.js +83 -0
- package/dist/{chunk-S7PQNG4E.js → chunk-R7BPW32M.js} +40 -0
- package/dist/{chunk-B3CCMSG2.js → chunk-WBKCXGLV.js} +1 -1
- package/dist/cli.js +24 -21
- package/dist/{configs-update-AHI7T6S4.js → configs-update-VOWH674W.js} +2 -2
- package/dist/{create-RS37JAMM.js → create-ASGUBKZ7.js} +2 -2
- package/dist/{drift-2JRZK2MC.js → drift-PASGDEEX.js} +2 -2
- package/dist/{found-YYYFF4FD.js → found-TIW7T4VX.js} +2 -2
- package/dist/{healthcheck-6RHZBEVE.js → healthcheck-SIE5EXN3.js} +2 -2
- package/dist/{list-MHEIY7LQ.js → list-CEWBMKJ3.js} +2 -2
- package/dist/{list-M2UQCXIO.js → list-KTIZ3UHA.js} +3 -3
- package/dist/{list-56BS25X4.js → list-TMFLCS5U.js} +4 -4
- package/dist/{list-json-GANUT7SB.js → list-json-SUZL2GBJ.js} +2 -2
- package/dist/{login-ML2EKF44.js → login-C66GRR3Y.js} +4 -2
- package/dist/login-json-XGMXT5VJ.js +50 -0
- package/dist/login-plain-CWKOUZKE.js +60 -0
- package/dist/{run-7NTCD7JI.js → run-3TTLZ6HA.js} +3 -3
- package/dist/{run-JZNZSCDJ.js → run-MGOASUON.js} +2 -2
- package/dist/{setup-skill-XZRLJE3A.js → setup-skill-KKWETU4A.js} +1 -1
- package/dist/{snapshot-KGMO44YB.js → snapshot-MQ6DWDFG.js} +2 -2
- package/dist/{summary-PA2CCZVO.js → summary-QORQFCMW.js} +2 -2
- package/dist/{validate-NIBVL7X5.js → validate-II6GH6H6.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-ZVM45CTB.js +0 -19
- package/dist/login-json-Y3AIQIIB.js +0 -75
- package/dist/{chunk-DSOM6TZX.js → chunk-44FSS3CZ.js} +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @chainpatrol/cli
|
|
2
2
|
|
|
3
|
+
## 0.3.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 415dbcd: `chainpatrol login`:
|
|
8
|
+
|
|
9
|
+
- Auto-detect non-TTY stdout (Claude Code on the web, CI runners, piped
|
|
10
|
+
invocations) and fall back to a plain-text login flow that prints the
|
|
11
|
+
device code and verification URL immediately. Previously the
|
|
12
|
+
interactive Ink-based UI rendered nothing in those environments,
|
|
13
|
+
making the command appear to hang with no output until the device
|
|
14
|
+
code expired.
|
|
15
|
+
- `chainpatrol --json login` now emits the device-code line on **stdout**
|
|
16
|
+
instead of stderr, matching the `{"status":"success",...}` line. This
|
|
17
|
+
makes the URL visible without callers needing to remember `2>&1`.
|
|
18
|
+
Consumers should treat the output as JSON-lines and read the last
|
|
19
|
+
line for the terminal result.
|
|
20
|
+
|
|
21
|
+
Claude Code skill bundled with the CLI:
|
|
22
|
+
|
|
23
|
+
- New "Running `login` from an agent (headless / non-TTY)" section
|
|
24
|
+
documenting the background+tail pattern so agents surface the
|
|
25
|
+
verification URL to the user immediately instead of blocking on the
|
|
26
|
+
polling step.
|
|
27
|
+
|
|
3
28
|
## 0.3.2
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
} from "./chunk-VFT3TD3E.js";
|
|
5
5
|
import {
|
|
6
6
|
createApiClient
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-TFCNKBRC.js";
|
|
7
|
+
} from "./chunk-44FSS3CZ.js";
|
|
9
8
|
import "./chunk-EEG7T6WT.js";
|
|
9
|
+
import "./chunk-TFCNKBRC.js";
|
|
10
10
|
import "./chunk-U73SABXK.js";
|
|
11
11
|
|
|
12
12
|
// src/commands/metrics/breakdown.ts
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetchUserEmail,
|
|
3
|
+
getCredentials,
|
|
4
|
+
isLoggedIn,
|
|
5
|
+
pollForToken,
|
|
6
|
+
requestDeviceCode,
|
|
7
|
+
storeCredentials
|
|
8
|
+
} from "./chunk-EEG7T6WT.js";
|
|
9
|
+
import {
|
|
10
|
+
DateTime
|
|
11
|
+
} from "./chunk-TFCNKBRC.js";
|
|
12
|
+
|
|
13
|
+
// src/lib/login-flow.ts
|
|
14
|
+
async function runLoginFlow(emit) {
|
|
15
|
+
if (isLoggedIn()) {
|
|
16
|
+
const creds = getCredentials();
|
|
17
|
+
emit({ type: "already_logged_in", email: creds.email ?? null });
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
const deviceCode = await requestDeviceCode();
|
|
21
|
+
emit({ type: "device_code", code: deviceCode });
|
|
22
|
+
let interval = deviceCode.interval * 1e3;
|
|
23
|
+
while (true) {
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
25
|
+
const result = await pollForToken(deviceCode.device_code);
|
|
26
|
+
switch (result.status) {
|
|
27
|
+
case "success": {
|
|
28
|
+
const expiresAt = DateTime.now().toUTC().plus({ seconds: result.expiresIn }).toISO();
|
|
29
|
+
if (!expiresAt) {
|
|
30
|
+
emit({ type: "error", message: "Failed to compute credential expiry." });
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const email = await fetchUserEmail(result.accessToken);
|
|
34
|
+
storeCredentials({
|
|
35
|
+
accessToken: result.accessToken,
|
|
36
|
+
expiresAt,
|
|
37
|
+
...email ? { email } : {}
|
|
38
|
+
});
|
|
39
|
+
emit({ type: "success", email: email ?? null });
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
case "pending":
|
|
43
|
+
continue;
|
|
44
|
+
case "slow_down":
|
|
45
|
+
interval += result.addSeconds * 1e3;
|
|
46
|
+
continue;
|
|
47
|
+
case "expired":
|
|
48
|
+
emit({ type: "expired" });
|
|
49
|
+
return false;
|
|
50
|
+
case "denied":
|
|
51
|
+
emit({ type: "denied" });
|
|
52
|
+
return false;
|
|
53
|
+
case "error":
|
|
54
|
+
emit({ type: "error", message: result.message });
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function formatUserCode(code) {
|
|
60
|
+
return code.length === 8 ? `${code.slice(0, 4)}-${code.slice(4)}` : code;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/lib/headless.ts
|
|
64
|
+
function isHeadlessEnv(env = process.env, platform = process.platform) {
|
|
65
|
+
if (env.CHAINPATROL_HEADLESS === "1") return true;
|
|
66
|
+
if (env.CHAINPATROL_HEADLESS === "0") return false;
|
|
67
|
+
if (env.CLAUDE_CODE_REMOTE === "true") return true;
|
|
68
|
+
if (env.CODESPACES === "true") return true;
|
|
69
|
+
if (env.GITPOD_WORKSPACE_ID) return true;
|
|
70
|
+
if (env.REPL_ID) return true;
|
|
71
|
+
if (env.CI === "true") return true;
|
|
72
|
+
if (env.SSH_CONNECTION || env.SSH_TTY) return true;
|
|
73
|
+
if (platform === "linux" && !env.DISPLAY && !env.WAYLAND_DISPLAY && !env.MIR_SOCKET) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
runLoginFlow,
|
|
81
|
+
formatUserCode,
|
|
82
|
+
isHeadlessEnv
|
|
83
|
+
};
|
|
@@ -150,6 +150,46 @@ JSON mode (for automation):
|
|
|
150
150
|
chainpatrol --json login
|
|
151
151
|
\`\`\`
|
|
152
152
|
|
|
153
|
+
#### Running \`login\` from an agent (headless / non-TTY)
|
|
154
|
+
|
|
155
|
+
The login flow blocks for up to 30 minutes while polling for the user to
|
|
156
|
+
authorize in their browser. If you (the agent) run it as a foreground
|
|
157
|
+
command and wait for it to exit before reading output, you will appear
|
|
158
|
+
stuck \u2014 the verification URL will never be shown because the process is
|
|
159
|
+
still polling.
|
|
160
|
+
|
|
161
|
+
**Always run \`login\` in the background and stream its output**, then
|
|
162
|
+
surface the verification URL to the user as soon as it appears:
|
|
163
|
+
|
|
164
|
+
\`\`\`bash
|
|
165
|
+
# 1. Kick off login in the background (do NOT wait for it to exit)
|
|
166
|
+
chainpatrol --json login > /tmp/cp-login.out 2>&1 &
|
|
167
|
+
|
|
168
|
+
# 2. Wait briefly for the first line, which contains the URL
|
|
169
|
+
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
|
170
|
+
test -s /tmp/cp-login.out && break
|
|
171
|
+
sleep 1
|
|
172
|
+
done
|
|
173
|
+
cat /tmp/cp-login.out
|
|
174
|
+
\`\`\`
|
|
175
|
+
|
|
176
|
+
The first line emitted is JSON describing the device code, e.g.:
|
|
177
|
+
|
|
178
|
+
\`\`\`json
|
|
179
|
+
{"action":"open_url","user_code":"ABCD-1234","verification_uri":"https://app.chainpatrol.io/auth/verify-device","verification_uri_complete":"https://app.chainpatrol.io/auth/verify-device?user_code=ABCD-1234","expires_in":1800,"headless":true}
|
|
180
|
+
\`\`\`
|
|
181
|
+
|
|
182
|
+
Show the user the \`verification_uri_complete\` link (or
|
|
183
|
+
\`verification_uri\` + \`user_code\` as a fallback) and explain that the
|
|
184
|
+
CLI will pick up the token automatically once they authorize. Then keep
|
|
185
|
+
the background process running and tail it for the final
|
|
186
|
+
\`{"status":"success",...}\` or \`{"error":...}\` line.
|
|
187
|
+
|
|
188
|
+
CLI v0.3.3+ also auto-detects non-TTY stdout and prints the URL as plain
|
|
189
|
+
text immediately when you run \`chainpatrol login\` without \`--json\`,
|
|
190
|
+
so the same background+tail pattern works without \`--json\`. Prefer
|
|
191
|
+
\`--json\` so the output is structured and machine-parseable.
|
|
192
|
+
|
|
153
193
|
### \`logout\` \u2014 Clear stored credentials
|
|
154
194
|
|
|
155
195
|
\`\`\`bash
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
getCliVersion,
|
|
14
14
|
isSkillInstalled,
|
|
15
15
|
readInstalledSkillVersion
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-R7BPW32M.js";
|
|
17
17
|
import "./chunk-IUZB3DQW.js";
|
|
18
18
|
import {
|
|
19
19
|
DateTime
|
|
@@ -686,12 +686,12 @@ function parseAttachmentUrls() {
|
|
|
686
686
|
}
|
|
687
687
|
async function handleConfigsList(org) {
|
|
688
688
|
if (jsonMode) {
|
|
689
|
-
const { listConfigsJson } = await import("./list-json-
|
|
689
|
+
const { listConfigsJson } = await import("./list-json-SUZL2GBJ.js");
|
|
690
690
|
await listConfigsJson({ org });
|
|
691
691
|
return;
|
|
692
692
|
}
|
|
693
693
|
const { render } = await import("ink");
|
|
694
|
-
const { default: ConfigsList } = await import("./list-
|
|
694
|
+
const { default: ConfigsList } = await import("./list-TMFLCS5U.js");
|
|
695
695
|
const { default: React } = await import("react");
|
|
696
696
|
render(React.createElement(ConfigsList, { org }));
|
|
697
697
|
}
|
|
@@ -746,11 +746,14 @@ async function main() {
|
|
|
746
746
|
);
|
|
747
747
|
}
|
|
748
748
|
if (jsonMode) {
|
|
749
|
-
const { loginJson } = await import("./login-json-
|
|
749
|
+
const { loginJson } = await import("./login-json-XGMXT5VJ.js");
|
|
750
750
|
await loginJson();
|
|
751
|
+
} else if (!process.stdout.isTTY) {
|
|
752
|
+
const { loginPlain } = await import("./login-plain-CWKOUZKE.js");
|
|
753
|
+
await loginPlain();
|
|
751
754
|
} else {
|
|
752
755
|
const { render } = await import("ink");
|
|
753
|
-
const { default: Login } = await import("./login-
|
|
756
|
+
const { default: Login } = await import("./login-C66GRR3Y.js");
|
|
754
757
|
const { default: React } = await import("react");
|
|
755
758
|
render(React.createElement(Login));
|
|
756
759
|
}
|
|
@@ -786,7 +789,7 @@ async function main() {
|
|
|
786
789
|
case "detections": {
|
|
787
790
|
const org = await resolveOrg();
|
|
788
791
|
if (subcommand === "healthcheck") {
|
|
789
|
-
const { runDetectionsHealthcheck } = await import("./healthcheck-
|
|
792
|
+
const { runDetectionsHealthcheck } = await import("./healthcheck-SIE5EXN3.js");
|
|
790
793
|
await runDetectionsHealthcheck({
|
|
791
794
|
org,
|
|
792
795
|
source: cli.flags.source,
|
|
@@ -801,7 +804,7 @@ async function main() {
|
|
|
801
804
|
break;
|
|
802
805
|
}
|
|
803
806
|
if (subcommand === "validate") {
|
|
804
|
-
const { runDetectionsValidate } = await import("./validate-
|
|
807
|
+
const { runDetectionsValidate } = await import("./validate-II6GH6H6.js");
|
|
805
808
|
await runDetectionsValidate({
|
|
806
809
|
org,
|
|
807
810
|
source: cli.flags.source,
|
|
@@ -816,7 +819,7 @@ async function main() {
|
|
|
816
819
|
break;
|
|
817
820
|
}
|
|
818
821
|
if (subcommand === "drift") {
|
|
819
|
-
const { runDetectionsDrift } = await import("./drift-
|
|
822
|
+
const { runDetectionsDrift } = await import("./drift-PASGDEEX.js");
|
|
820
823
|
await runDetectionsDrift({
|
|
821
824
|
org,
|
|
822
825
|
source: cli.flags.source,
|
|
@@ -830,7 +833,7 @@ async function main() {
|
|
|
830
833
|
break;
|
|
831
834
|
}
|
|
832
835
|
if (subcommand === "run") {
|
|
833
|
-
const { runDetectionsRun } = await import("./run-
|
|
836
|
+
const { runDetectionsRun } = await import("./run-MGOASUON.js");
|
|
834
837
|
await runDetectionsRun({
|
|
835
838
|
org,
|
|
836
839
|
configId: cli.flags.configId,
|
|
@@ -849,7 +852,7 @@ async function main() {
|
|
|
849
852
|
break;
|
|
850
853
|
}
|
|
851
854
|
if (action === "run") {
|
|
852
|
-
const { runDetectionsRun } = await import("./run-
|
|
855
|
+
const { runDetectionsRun } = await import("./run-MGOASUON.js");
|
|
853
856
|
await runDetectionsRun({
|
|
854
857
|
org,
|
|
855
858
|
configId: cli.flags.configId,
|
|
@@ -867,7 +870,7 @@ async function main() {
|
|
|
867
870
|
throw new Error("detections configs update requires --config-id");
|
|
868
871
|
}
|
|
869
872
|
const configPatch = getConfigPatchFromSetFlags();
|
|
870
|
-
const { runDetectionsConfigsUpdate } = await import("./configs-update-
|
|
873
|
+
const { runDetectionsConfigsUpdate } = await import("./configs-update-VOWH674W.js");
|
|
871
874
|
await runDetectionsConfigsUpdate({
|
|
872
875
|
org,
|
|
873
876
|
configId: cli.flags.configId,
|
|
@@ -894,7 +897,7 @@ async function main() {
|
|
|
894
897
|
case "metrics": {
|
|
895
898
|
const org = await resolveOrg();
|
|
896
899
|
if (subcommand === "summary") {
|
|
897
|
-
const { runMetricsSummary } = await import("./summary-
|
|
900
|
+
const { runMetricsSummary } = await import("./summary-QORQFCMW.js");
|
|
898
901
|
await runMetricsSummary({
|
|
899
902
|
org,
|
|
900
903
|
from: cli.flags.from,
|
|
@@ -906,7 +909,7 @@ async function main() {
|
|
|
906
909
|
break;
|
|
907
910
|
}
|
|
908
911
|
if (subcommand === "found") {
|
|
909
|
-
const { runMetricsFound } = await import("./found-
|
|
912
|
+
const { runMetricsFound } = await import("./found-TIW7T4VX.js");
|
|
910
913
|
await runMetricsFound({
|
|
911
914
|
org,
|
|
912
915
|
from: cli.flags.from,
|
|
@@ -923,7 +926,7 @@ async function main() {
|
|
|
923
926
|
if (!by || !["day", "type", "brand"].includes(by)) {
|
|
924
927
|
throw new Error("metrics breakdown requires --by <day|type|brand>");
|
|
925
928
|
}
|
|
926
|
-
const { runMetricsBreakdown } = await import("./breakdown-
|
|
929
|
+
const { runMetricsBreakdown } = await import("./breakdown-FFNYSXRQ.js");
|
|
927
930
|
await runMetricsBreakdown({
|
|
928
931
|
org,
|
|
929
932
|
by,
|
|
@@ -943,7 +946,7 @@ async function main() {
|
|
|
943
946
|
case "reports": {
|
|
944
947
|
if (subcommand === "list") {
|
|
945
948
|
const org = await resolveOrg();
|
|
946
|
-
const { runReportsList } = await import("./list-
|
|
949
|
+
const { runReportsList } = await import("./list-CEWBMKJ3.js");
|
|
947
950
|
await runReportsList({
|
|
948
951
|
org,
|
|
949
952
|
limit: cli.flags.limit,
|
|
@@ -959,7 +962,7 @@ async function main() {
|
|
|
959
962
|
}
|
|
960
963
|
if (subcommand === "create") {
|
|
961
964
|
const org = await tryResolveOrg();
|
|
962
|
-
const { runReportsCreate } = await import("./create-
|
|
965
|
+
const { runReportsCreate } = await import("./create-ASGUBKZ7.js");
|
|
963
966
|
await runReportsCreate({
|
|
964
967
|
org,
|
|
965
968
|
title: cli.flags.title,
|
|
@@ -983,7 +986,7 @@ async function main() {
|
|
|
983
986
|
}
|
|
984
987
|
case "queues": {
|
|
985
988
|
if (subcommand === "snapshot") {
|
|
986
|
-
const { runQueuesSnapshot } = await import("./snapshot-
|
|
989
|
+
const { runQueuesSnapshot } = await import("./snapshot-MQ6DWDFG.js");
|
|
987
990
|
await runQueuesSnapshot({
|
|
988
991
|
org: cli.flags.org,
|
|
989
992
|
all: cli.flags.all,
|
|
@@ -1001,7 +1004,7 @@ async function main() {
|
|
|
1001
1004
|
}
|
|
1002
1005
|
case "presets": {
|
|
1003
1006
|
if (subcommand === "list") {
|
|
1004
|
-
const { runPresetsList } = await import("./list-
|
|
1007
|
+
const { runPresetsList } = await import("./list-KTIZ3UHA.js");
|
|
1005
1008
|
await runPresetsList({ outputFormat: cliContext.outputFormat });
|
|
1006
1009
|
break;
|
|
1007
1010
|
}
|
|
@@ -1012,7 +1015,7 @@ async function main() {
|
|
|
1012
1015
|
);
|
|
1013
1016
|
}
|
|
1014
1017
|
const org = await resolveOrg();
|
|
1015
|
-
const { runPresetsRun } = await import("./run-
|
|
1018
|
+
const { runPresetsRun } = await import("./run-3TTLZ6HA.js");
|
|
1016
1019
|
await runPresetsRun({
|
|
1017
1020
|
presetId: action,
|
|
1018
1021
|
org,
|
|
@@ -1029,12 +1032,12 @@ async function main() {
|
|
|
1029
1032
|
case "setup":
|
|
1030
1033
|
case "install":
|
|
1031
1034
|
case "i": {
|
|
1032
|
-
const { setupSkill } = await import("./setup-skill-
|
|
1035
|
+
const { setupSkill } = await import("./setup-skill-KKWETU4A.js");
|
|
1033
1036
|
setupSkill({ json: jsonMode });
|
|
1034
1037
|
break;
|
|
1035
1038
|
}
|
|
1036
1039
|
case "uninstall": {
|
|
1037
|
-
const { uninstallSkill } = await import("./setup-skill-
|
|
1040
|
+
const { uninstallSkill } = await import("./setup-skill-KKWETU4A.js");
|
|
1038
1041
|
uninstallSkill({ json: jsonMode });
|
|
1039
1042
|
break;
|
|
1040
1043
|
}
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
} from "./chunk-VFT3TD3E.js";
|
|
8
8
|
import {
|
|
9
9
|
createApiClient
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-TFCNKBRC.js";
|
|
10
|
+
} from "./chunk-44FSS3CZ.js";
|
|
12
11
|
import "./chunk-EEG7T6WT.js";
|
|
12
|
+
import "./chunk-TFCNKBRC.js";
|
|
13
13
|
import "./chunk-U73SABXK.js";
|
|
14
14
|
|
|
15
15
|
// src/commands/detections/configs-update.ts
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
9
|
import {
|
|
10
10
|
createApiClient
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-TFCNKBRC.js";
|
|
11
|
+
} from "./chunk-44FSS3CZ.js";
|
|
13
12
|
import "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/reports/create.ts
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
9
|
import {
|
|
10
10
|
createApiClient
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-TFCNKBRC.js";
|
|
11
|
+
} from "./chunk-44FSS3CZ.js";
|
|
13
12
|
import "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/detections/drift.ts
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
} from "./chunk-VFT3TD3E.js";
|
|
5
5
|
import {
|
|
6
6
|
createApiClient
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-44FSS3CZ.js";
|
|
8
|
+
import "./chunk-EEG7T6WT.js";
|
|
8
9
|
import {
|
|
9
10
|
DateTime
|
|
10
11
|
} from "./chunk-TFCNKBRC.js";
|
|
11
|
-
import "./chunk-EEG7T6WT.js";
|
|
12
12
|
import "./chunk-U73SABXK.js";
|
|
13
13
|
|
|
14
14
|
// src/lib/date-range.ts
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
9
|
import {
|
|
10
10
|
createApiClient
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-TFCNKBRC.js";
|
|
11
|
+
} from "./chunk-44FSS3CZ.js";
|
|
13
12
|
import "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/detections/healthcheck.ts
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
9
|
import {
|
|
10
10
|
createApiClient
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-TFCNKBRC.js";
|
|
11
|
+
} from "./chunk-44FSS3CZ.js";
|
|
13
12
|
import "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/reports/list.ts
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PRESETS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WBKCXGLV.js";
|
|
4
4
|
import "./chunk-E2LAMILJ.js";
|
|
5
5
|
import {
|
|
6
6
|
printOutput,
|
|
7
7
|
toCsvRows
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-TFCNKBRC.js";
|
|
9
|
+
import "./chunk-44FSS3CZ.js";
|
|
11
10
|
import "./chunk-EEG7T6WT.js";
|
|
11
|
+
import "./chunk-TFCNKBRC.js";
|
|
12
12
|
import "./chunk-U73SABXK.js";
|
|
13
13
|
|
|
14
14
|
// src/commands/presets/list.ts
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createApiClient
|
|
3
|
-
} from "./chunk-DSOM6TZX.js";
|
|
4
|
-
import "./chunk-TFCNKBRC.js";
|
|
5
1
|
import {
|
|
6
2
|
ErrorDisplay,
|
|
7
3
|
Spinner
|
|
8
4
|
} from "./chunk-JCMWDZYY.js";
|
|
5
|
+
import {
|
|
6
|
+
createApiClient
|
|
7
|
+
} from "./chunk-44FSS3CZ.js";
|
|
9
8
|
import {
|
|
10
9
|
AuthCorruptedError,
|
|
11
10
|
AuthExpiredError,
|
|
12
11
|
AuthNotLoggedInError
|
|
13
12
|
} from "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/configs/list.tsx
|
|
@@ -3,8 +3,9 @@ import {
|
|
|
3
3
|
Spinner
|
|
4
4
|
} from "./chunk-JCMWDZYY.js";
|
|
5
5
|
import {
|
|
6
|
+
formatUserCode,
|
|
6
7
|
isHeadlessEnv
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-EBJMOX3Q.js";
|
|
8
9
|
import {
|
|
9
10
|
fetchUserEmail,
|
|
10
11
|
getCredentials,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
requestDeviceCode,
|
|
14
15
|
storeCredentials
|
|
15
16
|
} from "./chunk-EEG7T6WT.js";
|
|
17
|
+
import "./chunk-TFCNKBRC.js";
|
|
16
18
|
import "./chunk-U73SABXK.js";
|
|
17
19
|
|
|
18
20
|
// src/commands/login.tsx
|
|
@@ -140,7 +142,7 @@ function Login() {
|
|
|
140
142
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
141
143
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
142
144
|
/* @__PURE__ */ jsx(Text, { children: "Your code: " }),
|
|
143
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children:
|
|
145
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: formatUserCode(state.deviceCode.user_code) })
|
|
144
146
|
] }),
|
|
145
147
|
completeUri ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
146
148
|
/* @__PURE__ */ jsx(Text, { children: "Open this URL on any device to approve in one step:" }),
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isHeadlessEnv,
|
|
3
|
+
runLoginFlow
|
|
4
|
+
} from "./chunk-EBJMOX3Q.js";
|
|
5
|
+
import "./chunk-EEG7T6WT.js";
|
|
6
|
+
import "./chunk-TFCNKBRC.js";
|
|
7
|
+
import "./chunk-U73SABXK.js";
|
|
8
|
+
|
|
9
|
+
// src/commands/login-json.ts
|
|
10
|
+
async function loginJson() {
|
|
11
|
+
const ok = await runLoginFlow((event) => {
|
|
12
|
+
switch (event.type) {
|
|
13
|
+
case "already_logged_in":
|
|
14
|
+
console.log(JSON.stringify({ status: "already_logged_in", email: event.email }));
|
|
15
|
+
return;
|
|
16
|
+
case "device_code":
|
|
17
|
+
console.log(
|
|
18
|
+
JSON.stringify({
|
|
19
|
+
action: "open_url",
|
|
20
|
+
user_code: event.code.user_code,
|
|
21
|
+
verification_uri: event.code.verification_uri,
|
|
22
|
+
verification_uri_complete: event.code.verification_uri_complete ?? null,
|
|
23
|
+
expires_in: event.code.expires_in,
|
|
24
|
+
headless: isHeadlessEnv()
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
return;
|
|
28
|
+
case "success":
|
|
29
|
+
console.log(JSON.stringify({ status: "success", email: event.email }));
|
|
30
|
+
return;
|
|
31
|
+
case "expired":
|
|
32
|
+
console.error(
|
|
33
|
+
JSON.stringify({ error: "Code expired. Run `chainpatrol login` again." })
|
|
34
|
+
);
|
|
35
|
+
return;
|
|
36
|
+
case "denied":
|
|
37
|
+
console.error(JSON.stringify({ error: "Authorization denied." }));
|
|
38
|
+
return;
|
|
39
|
+
case "error":
|
|
40
|
+
console.error(JSON.stringify({ error: event.message }));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
if (!ok) {
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
loginJson
|
|
50
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatUserCode,
|
|
3
|
+
isHeadlessEnv,
|
|
4
|
+
runLoginFlow
|
|
5
|
+
} from "./chunk-EBJMOX3Q.js";
|
|
6
|
+
import "./chunk-EEG7T6WT.js";
|
|
7
|
+
import "./chunk-TFCNKBRC.js";
|
|
8
|
+
import "./chunk-U73SABXK.js";
|
|
9
|
+
|
|
10
|
+
// src/commands/login-plain.ts
|
|
11
|
+
async function loginPlain() {
|
|
12
|
+
const ok = await runLoginFlow((event) => {
|
|
13
|
+
switch (event.type) {
|
|
14
|
+
case "already_logged_in":
|
|
15
|
+
console.log(
|
|
16
|
+
event.email ? `Already logged in as ${event.email}` : "Already logged in"
|
|
17
|
+
);
|
|
18
|
+
return;
|
|
19
|
+
case "device_code": {
|
|
20
|
+
const completeUri = event.code.verification_uri_complete;
|
|
21
|
+
const userCode = formatUserCode(event.code.user_code);
|
|
22
|
+
if (completeUri) {
|
|
23
|
+
console.log("Open this URL on any device to approve in one step:");
|
|
24
|
+
console.log(` ${completeUri}`);
|
|
25
|
+
console.log(
|
|
26
|
+
`Or visit ${event.code.verification_uri} and enter the code: ${userCode}`
|
|
27
|
+
);
|
|
28
|
+
} else {
|
|
29
|
+
console.log(`Open this URL in your browser: ${event.code.verification_uri}`);
|
|
30
|
+
console.log(`Enter the code: ${userCode}`);
|
|
31
|
+
}
|
|
32
|
+
if (isHeadlessEnv()) {
|
|
33
|
+
console.log("(headless environment detected \u2014 browser will not auto-open)");
|
|
34
|
+
}
|
|
35
|
+
console.log("Waiting for approval...");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
case "success":
|
|
39
|
+
console.log(
|
|
40
|
+
event.email ? `Logged in successfully as ${event.email}` : "Logged in successfully"
|
|
41
|
+
);
|
|
42
|
+
return;
|
|
43
|
+
case "expired":
|
|
44
|
+
console.error("Code expired. Run `chainpatrol login` again.");
|
|
45
|
+
return;
|
|
46
|
+
case "denied":
|
|
47
|
+
console.error("Authorization denied.");
|
|
48
|
+
return;
|
|
49
|
+
case "error":
|
|
50
|
+
console.error(event.message);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
if (!ok) {
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
loginPlain
|
|
60
|
+
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getPresetDefinition,
|
|
3
3
|
runPreset
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WBKCXGLV.js";
|
|
5
5
|
import {
|
|
6
6
|
CliExitError,
|
|
7
7
|
ExitCode
|
|
8
8
|
} from "./chunk-E2LAMILJ.js";
|
|
9
9
|
import "./chunk-VFT3TD3E.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-TFCNKBRC.js";
|
|
10
|
+
import "./chunk-44FSS3CZ.js";
|
|
12
11
|
import "./chunk-EEG7T6WT.js";
|
|
12
|
+
import "./chunk-TFCNKBRC.js";
|
|
13
13
|
import "./chunk-U73SABXK.js";
|
|
14
14
|
|
|
15
15
|
// src/commands/presets/run.ts
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
9
|
import {
|
|
10
10
|
createApiClient
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-TFCNKBRC.js";
|
|
11
|
+
} from "./chunk-44FSS3CZ.js";
|
|
13
12
|
import "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/detections/run.ts
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
9
|
import {
|
|
10
10
|
createApiClient
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-TFCNKBRC.js";
|
|
11
|
+
} from "./chunk-44FSS3CZ.js";
|
|
13
12
|
import "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/queues/snapshot.ts
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
} from "./chunk-VFT3TD3E.js";
|
|
5
5
|
import {
|
|
6
6
|
createApiClient
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-TFCNKBRC.js";
|
|
7
|
+
} from "./chunk-44FSS3CZ.js";
|
|
9
8
|
import "./chunk-EEG7T6WT.js";
|
|
9
|
+
import "./chunk-TFCNKBRC.js";
|
|
10
10
|
import "./chunk-U73SABXK.js";
|
|
11
11
|
|
|
12
12
|
// src/commands/metrics/summary.ts
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
9
|
import {
|
|
10
10
|
createApiClient
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-TFCNKBRC.js";
|
|
11
|
+
} from "./chunk-44FSS3CZ.js";
|
|
13
12
|
import "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/detections/validate.ts
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@chainpatrol/cli",
|
|
3
3
|
"description": "The official ChainPatrol CLI — terminal interface for threat detection",
|
|
4
4
|
"author": "Umar Ahmed <umar@chainpatrol.io>",
|
|
5
|
-
"version": "0.3.
|
|
5
|
+
"version": "0.3.3",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"homepage": "https://chainpatrol.com/docs/cli",
|
|
8
8
|
"keywords": [
|
package/dist/chunk-ZVM45CTB.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// src/lib/headless.ts
|
|
2
|
-
function isHeadlessEnv(env = process.env, platform = process.platform) {
|
|
3
|
-
if (env.CHAINPATROL_HEADLESS === "1") return true;
|
|
4
|
-
if (env.CHAINPATROL_HEADLESS === "0") return false;
|
|
5
|
-
if (env.CLAUDE_CODE_REMOTE === "true") return true;
|
|
6
|
-
if (env.CODESPACES === "true") return true;
|
|
7
|
-
if (env.GITPOD_WORKSPACE_ID) return true;
|
|
8
|
-
if (env.REPL_ID) return true;
|
|
9
|
-
if (env.CI === "true") return true;
|
|
10
|
-
if (env.SSH_CONNECTION || env.SSH_TTY) return true;
|
|
11
|
-
if (platform === "linux" && !env.DISPLAY && !env.WAYLAND_DISPLAY && !env.MIR_SOCKET) {
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export {
|
|
18
|
-
isHeadlessEnv
|
|
19
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isHeadlessEnv
|
|
3
|
-
} from "./chunk-ZVM45CTB.js";
|
|
4
|
-
import {
|
|
5
|
-
fetchUserEmail,
|
|
6
|
-
getCredentials,
|
|
7
|
-
isLoggedIn,
|
|
8
|
-
pollForToken,
|
|
9
|
-
requestDeviceCode,
|
|
10
|
-
storeCredentials
|
|
11
|
-
} from "./chunk-EEG7T6WT.js";
|
|
12
|
-
import "./chunk-U73SABXK.js";
|
|
13
|
-
|
|
14
|
-
// src/commands/login-json.ts
|
|
15
|
-
async function loginJson() {
|
|
16
|
-
if (isLoggedIn()) {
|
|
17
|
-
const creds = getCredentials();
|
|
18
|
-
console.log(
|
|
19
|
-
JSON.stringify({ status: "already_logged_in", email: creds.email ?? null })
|
|
20
|
-
);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
const deviceCode = await requestDeviceCode();
|
|
24
|
-
console.error(
|
|
25
|
-
JSON.stringify({
|
|
26
|
-
action: "open_url",
|
|
27
|
-
user_code: deviceCode.user_code,
|
|
28
|
-
verification_uri: deviceCode.verification_uri,
|
|
29
|
-
verification_uri_complete: deviceCode.verification_uri_complete ?? null,
|
|
30
|
-
expires_in: deviceCode.expires_in,
|
|
31
|
-
headless: isHeadlessEnv()
|
|
32
|
-
})
|
|
33
|
-
);
|
|
34
|
-
let interval = deviceCode.interval * 1e3;
|
|
35
|
-
while (true) {
|
|
36
|
-
await new Promise((r) => setTimeout(r, interval));
|
|
37
|
-
const result = await pollForToken(deviceCode.device_code);
|
|
38
|
-
switch (result.status) {
|
|
39
|
-
case "success": {
|
|
40
|
-
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
41
|
-
const email = await fetchUserEmail(result.accessToken);
|
|
42
|
-
const creds = {
|
|
43
|
-
accessToken: result.accessToken,
|
|
44
|
-
expiresAt,
|
|
45
|
-
...email ? { email } : {}
|
|
46
|
-
};
|
|
47
|
-
storeCredentials(creds);
|
|
48
|
-
console.log(JSON.stringify({ status: "success", email: email ?? null }));
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
case "pending":
|
|
52
|
-
continue;
|
|
53
|
-
case "slow_down":
|
|
54
|
-
interval += result.addSeconds * 1e3;
|
|
55
|
-
continue;
|
|
56
|
-
case "expired":
|
|
57
|
-
console.error(
|
|
58
|
-
JSON.stringify({ error: "Code expired. Run `chainpatrol login` again." })
|
|
59
|
-
);
|
|
60
|
-
process.exit(1);
|
|
61
|
-
break;
|
|
62
|
-
case "denied":
|
|
63
|
-
console.error(JSON.stringify({ error: "Authorization denied." }));
|
|
64
|
-
process.exit(1);
|
|
65
|
-
break;
|
|
66
|
-
case "error":
|
|
67
|
-
console.error(JSON.stringify({ error: result.message }));
|
|
68
|
-
process.exit(1);
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
export {
|
|
74
|
-
loginJson
|
|
75
|
-
};
|