@cleanslop/cli 0.0.0-stage → 0.1.0-beta.1.2

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 (96) hide show
  1. package/README.md +86 -2
  2. package/assets/skill-core.md +62 -0
  3. package/dist/action.d.ts +5 -0
  4. package/dist/action.js +22 -0
  5. package/dist/action.js.map +1 -0
  6. package/dist/args.d.ts +4 -0
  7. package/dist/args.js +243 -0
  8. package/dist/args.js.map +1 -0
  9. package/dist/commands/credits.d.ts +29 -0
  10. package/dist/commands/credits.js +267 -0
  11. package/dist/commands/credits.js.map +1 -0
  12. package/dist/commands/email.d.ts +3 -0
  13. package/dist/commands/email.js +51 -0
  14. package/dist/commands/email.js.map +1 -0
  15. package/dist/commands/link-identity.d.ts +3 -0
  16. package/dist/commands/link-identity.js +37 -0
  17. package/dist/commands/link-identity.js.map +1 -0
  18. package/dist/commands/link-login.d.ts +3 -0
  19. package/dist/commands/link-login.js +63 -0
  20. package/dist/commands/link-login.js.map +1 -0
  21. package/dist/commands/login.d.ts +6 -0
  22. package/dist/commands/login.js +198 -0
  23. package/dist/commands/login.js.map +1 -0
  24. package/dist/commands/logout.d.ts +2 -0
  25. package/dist/commands/logout.js +40 -0
  26. package/dist/commands/logout.js.map +1 -0
  27. package/dist/commands/report.d.ts +8 -0
  28. package/dist/commands/report.js +55 -0
  29. package/dist/commands/report.js.map +1 -0
  30. package/dist/commands/scan-upload.d.ts +3 -0
  31. package/dist/commands/scan-upload.js +85 -0
  32. package/dist/commands/scan-upload.js.map +1 -0
  33. package/dist/commands/scan.d.ts +3 -0
  34. package/dist/commands/scan.js +81 -0
  35. package/dist/commands/scan.js.map +1 -0
  36. package/dist/commands/setup.d.ts +19 -0
  37. package/dist/commands/setup.js +154 -0
  38. package/dist/commands/setup.js.map +1 -0
  39. package/dist/commands/status.d.ts +3 -0
  40. package/dist/commands/status.js +29 -0
  41. package/dist/commands/status.js.map +1 -0
  42. package/dist/commands/whoami.d.ts +3 -0
  43. package/dist/commands/whoami.js +44 -0
  44. package/dist/commands/whoami.js.map +1 -0
  45. package/dist/config.d.ts +26 -0
  46. package/dist/config.js +46 -0
  47. package/dist/config.js.map +1 -0
  48. package/dist/credentials.d.ts +64 -0
  49. package/dist/credentials.js +220 -0
  50. package/dist/credentials.js.map +1 -0
  51. package/dist/deps.d.ts +58 -0
  52. package/dist/deps.js +148 -0
  53. package/dist/deps.js.map +1 -0
  54. package/dist/exit.d.ts +24 -0
  55. package/dist/exit.js +29 -0
  56. package/dist/exit.js.map +1 -0
  57. package/dist/git.d.ts +14 -0
  58. package/dist/git.js +161 -0
  59. package/dist/git.js.map +1 -0
  60. package/dist/http.d.ts +16 -0
  61. package/dist/http.js +210 -0
  62. package/dist/http.js.map +1 -0
  63. package/dist/index.d.ts +2 -0
  64. package/dist/index.js +10 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/link.d.ts +106 -0
  67. package/dist/link.js +650 -0
  68. package/dist/link.js.map +1 -0
  69. package/dist/main.d.ts +6 -0
  70. package/dist/main.js +75 -0
  71. package/dist/main.js.map +1 -0
  72. package/dist/mcp-config.d.ts +13 -0
  73. package/dist/mcp-config.js +65 -0
  74. package/dist/mcp-config.js.map +1 -0
  75. package/dist/output.d.ts +9 -0
  76. package/dist/output.js +65 -0
  77. package/dist/output.js.map +1 -0
  78. package/dist/pack.d.ts +30 -0
  79. package/dist/pack.js +283 -0
  80. package/dist/pack.js.map +1 -0
  81. package/dist/redact.d.ts +2 -0
  82. package/dist/redact.js +17 -0
  83. package/dist/redact.js.map +1 -0
  84. package/dist/skill.d.ts +10 -0
  85. package/dist/skill.js +110 -0
  86. package/dist/skill.js.map +1 -0
  87. package/dist/types.d.ts +144 -0
  88. package/dist/types.js +2 -0
  89. package/dist/types.js.map +1 -0
  90. package/dist/ustar.d.ts +7 -0
  91. package/dist/ustar.js +128 -0
  92. package/dist/ustar.js.map +1 -0
  93. package/dist/wait.d.ts +11 -0
  94. package/dist/wait.js +80 -0
  95. package/dist/wait.js.map +1 -0
  96. package/package.json +30 -4
@@ -0,0 +1,198 @@
1
+ import { CLIENT_ID, DEVICE_GRANT_TYPE, PACKAGE_VERSION } from "../config.js";
2
+ import { deletePendingLogin, peekStoredCreds, readPendingLogin, resolveOrigin, storeToken, writePendingLogin, } from "../credentials.js";
3
+ import { actionError, CliError, EXIT_ACTION, EXIT_OK, EXIT_UNEXPECTED, usageError, } from "../exit.js";
4
+ import { detectAgentHint, gitToplevel, parseGithubRemote } from "../git.js";
5
+ import { asErrorBody, httpRequest } from "../http.js";
6
+ import { runLinkLogin } from "./link-login.js";
7
+ /** Matches server DEVICE_EXTEND_TTL_MS — first /connect view extends the code. */
8
+ export const DEVICE_POLL_GRACE_MS = 30 * 60 * 1000;
9
+ export function devicePollDeadline(expiresAt) {
10
+ return expiresAt + DEVICE_POLL_GRACE_MS;
11
+ }
12
+ async function repoHint(deps) {
13
+ const top = await gitToplevel(deps, deps.env.cwd());
14
+ if (!top)
15
+ return undefined;
16
+ const remote = await deps.git(["remote", "get-url", "origin"], top);
17
+ if (!remote.ok)
18
+ return undefined;
19
+ return parseGithubRemote(remote.stdout)?.fullName;
20
+ }
21
+ function printApproval(deps, device) {
22
+ deps.io.stderr(`${device.verificationUriComplete}\n`);
23
+ deps.io.stderr(`${device.userCode}\n`);
24
+ deps.io.stderr([
25
+ "CLEANSLOP_ACTION_REQUIRED: approve",
26
+ "",
27
+ `Ask the human to open ${device.verificationUriComplete} and confirm code ${device.userCode}.`,
28
+ "Do not open or approve it yourself.",
29
+ "",
30
+ ].join("\n"));
31
+ }
32
+ async function pollDeviceToken(deps, origin, device) {
33
+ let intervalMs = Math.max(3, device.interval) * 1000;
34
+ const deadline = devicePollDeadline(device.expiresAt);
35
+ while (deps.clock.now() < deadline) {
36
+ await deps.clock.sleep(intervalMs);
37
+ let tokenRes;
38
+ try {
39
+ tokenRes = await httpRequest(deps, origin, "POST", "/oauth/token", {
40
+ body: {
41
+ grant_type: DEVICE_GRANT_TYPE,
42
+ device_code: device.deviceCode,
43
+ client_id: CLIENT_ID,
44
+ },
45
+ });
46
+ }
47
+ catch (err) {
48
+ if (err instanceof CliError && err.exitCode === EXIT_UNEXPECTED) {
49
+ continue;
50
+ }
51
+ throw err;
52
+ }
53
+ if (tokenRes.status >= 500) {
54
+ continue;
55
+ }
56
+ const body = asErrorBody(tokenRes.json);
57
+ const err = body.error;
58
+ if (tokenRes.status >= 200 && tokenRes.status < 300) {
59
+ const issued = tokenRes.json;
60
+ if (!issued || typeof issued.access_token !== "string") {
61
+ throw new CliError("Token response was missing access_token.", EXIT_UNEXPECTED);
62
+ }
63
+ const login = issued.account?.github_login ?? null;
64
+ const prior = peekStoredCreds(deps, origin);
65
+ await storeToken(deps, origin, {
66
+ token: issued.access_token,
67
+ githubLogin: login,
68
+ grantId: issued.grant_id ?? null,
69
+ });
70
+ if (prior?.token) {
71
+ try {
72
+ await httpRequest(deps, origin, "POST", "/oauth/revoke", {
73
+ token: prior.token,
74
+ body: { token: prior.token },
75
+ });
76
+ }
77
+ catch {
78
+ // Best-effort; the new login is already stored.
79
+ }
80
+ }
81
+ deletePendingLogin(deps);
82
+ const label = login ? `@${login}` : "your GitHub account";
83
+ deps.io.stdout(`Connected as ${label}\n`);
84
+ return EXIT_OK;
85
+ }
86
+ if (err === "authorization_pending") {
87
+ continue;
88
+ }
89
+ if (err === "slow_down") {
90
+ intervalMs += 5000;
91
+ continue;
92
+ }
93
+ if (err === "access_denied" || err === "expired_token" || err === "invalid_grant") {
94
+ deletePendingLogin(deps);
95
+ throw actionError(body.error_description ?? body.message ?? err, {
96
+ kind: "approve",
97
+ humanPrompt: body.error_description ??
98
+ "The human denied or the code expired. Run `cleanslop login` again.",
99
+ url: device.verificationUriComplete,
100
+ code: device.userCode,
101
+ });
102
+ }
103
+ throw new CliError(body.error_description ?? body.message ?? "Token poll failed.", EXIT_ACTION);
104
+ }
105
+ deletePendingLogin(deps);
106
+ throw actionError("Device login timed out.", {
107
+ kind: "approve",
108
+ humanPrompt: "The device code expired. Run `cleanslop login` again.",
109
+ url: device.verificationUriComplete,
110
+ code: device.userCode,
111
+ });
112
+ }
113
+ export async function runLogin(deps, args) {
114
+ if (args.link) {
115
+ return runLinkLogin(deps, args);
116
+ }
117
+ if (args.noWait && args.resume) {
118
+ throw usageError("Use either --no-wait or --resume, not both.");
119
+ }
120
+ const origin = resolveOrigin(deps);
121
+ if (args.resume) {
122
+ const pending = readPendingLogin(deps);
123
+ if (!pending || pending.origin !== origin) {
124
+ throw actionError("No pending device login for this origin.", {
125
+ kind: "approve",
126
+ humanPrompt: "Run `cleanslop login --no-wait` and ask the human to approve the code.",
127
+ });
128
+ }
129
+ if (deps.clock.now() >= devicePollDeadline(pending.expiresAt)) {
130
+ deletePendingLogin(deps);
131
+ throw actionError("The pending device code expired.", {
132
+ kind: "approve",
133
+ humanPrompt: "Run `cleanslop login` again.",
134
+ url: pending.verificationUriComplete,
135
+ code: pending.userCode,
136
+ });
137
+ }
138
+ printApproval(deps, {
139
+ verificationUriComplete: pending.verificationUriComplete,
140
+ userCode: pending.userCode,
141
+ });
142
+ return pollDeviceToken(deps, origin, {
143
+ deviceCode: pending.deviceCode,
144
+ userCode: pending.userCode,
145
+ verificationUriComplete: pending.verificationUriComplete,
146
+ interval: pending.interval,
147
+ expiresAt: pending.expiresAt,
148
+ });
149
+ }
150
+ const started = await httpRequest(deps, origin, "POST", "/oauth/device_authorization", {
151
+ body: {
152
+ client_id: CLIENT_ID,
153
+ client: { name: CLIENT_ID, version: PACKAGE_VERSION },
154
+ agent: detectAgentHint(deps.env),
155
+ host: deps.env.hostname().slice(0, 64),
156
+ repo: await repoHint(deps),
157
+ },
158
+ });
159
+ if (started.status >= 400) {
160
+ const body = asErrorBody(started.json);
161
+ throw new CliError(body.message ?? body.error_description ?? "Could not start device login.", started.status === 503 ? EXIT_UNEXPECTED : EXIT_ACTION);
162
+ }
163
+ const device = started.json;
164
+ if (!device ||
165
+ typeof device.device_code !== "string" ||
166
+ typeof device.user_code !== "string" ||
167
+ typeof device.verification_uri_complete !== "string") {
168
+ throw new CliError("Device authorization response was invalid.", EXIT_UNEXPECTED);
169
+ }
170
+ const intervalSec = Math.max(3, Number(device.interval) || 5);
171
+ const expiresSec = Number(device.expires_in);
172
+ const ttlSec = Number.isFinite(expiresSec) ? expiresSec : 600;
173
+ const expiresAt = deps.clock.now() + ttlSec * 1000;
174
+ printApproval(deps, {
175
+ verificationUriComplete: device.verification_uri_complete,
176
+ userCode: device.user_code,
177
+ });
178
+ if (args.noWait) {
179
+ await writePendingLogin(deps, {
180
+ version: 1,
181
+ origin,
182
+ deviceCode: device.device_code,
183
+ userCode: device.user_code,
184
+ verificationUriComplete: device.verification_uri_complete,
185
+ expiresAt,
186
+ interval: intervalSec,
187
+ });
188
+ return EXIT_ACTION;
189
+ }
190
+ return pollDeviceToken(deps, origin, {
191
+ deviceCode: device.device_code,
192
+ userCode: device.user_code,
193
+ verificationUriComplete: device.verification_uri_complete,
194
+ interval: intervalSec,
195
+ expiresAt,
196
+ });
197
+ }
198
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CliDeps } from "../deps.js";
2
+ export declare function runLogout(deps: CliDeps): Promise<number>;
@@ -0,0 +1,40 @@
1
+ import { deleteOriginCreds, deletePendingLogin, resolveOrigin, resolveToken, } from "../credentials.js";
2
+ import { EXIT_OK, EXIT_UNEXPECTED } from "../exit.js";
3
+ import { httpRequest } from "../http.js";
4
+ export async function runLogout(deps) {
5
+ const origin = resolveOrigin(deps);
6
+ const creds = resolveToken(deps, origin);
7
+ let revokeFailed = false;
8
+ if (creds) {
9
+ try {
10
+ const result = await httpRequest(deps, origin, "POST", "/oauth/revoke", {
11
+ token: creds.token,
12
+ body: { token: creds.token },
13
+ });
14
+ if (result.status < 200 || result.status >= 300) {
15
+ deps.io.stderr(`Could not revoke the token (HTTP ${result.status}).\n`);
16
+ revokeFailed = true;
17
+ }
18
+ }
19
+ catch (err) {
20
+ const message = err instanceof Error ? err.message : String(err);
21
+ deps.io.stderr(`Could not revoke the token: ${message}\n`);
22
+ revokeFailed = true;
23
+ }
24
+ }
25
+ if (creds?.source !== "env") {
26
+ await deleteOriginCreds(deps, origin);
27
+ }
28
+ deletePendingLogin(deps);
29
+ if (creds?.source === "env") {
30
+ deps.io.stdout("Disconnected. File credentials were left in place because CLEANSLOP_TOKEN is set.\n");
31
+ return EXIT_OK;
32
+ }
33
+ if (revokeFailed) {
34
+ deps.io.stdout("Removed local credentials, but the server did not confirm revocation. Revoke this agent under Account → Connected agents.\n");
35
+ return EXIT_UNEXPECTED;
36
+ }
37
+ deps.io.stdout("Disconnected.\n");
38
+ return EXIT_OK;
39
+ }
40
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAa;IAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE;gBACtE,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;aAC7B,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBAChD,IAAI,CAAC,EAAE,CAAC,MAAM,CACZ,oCAAoC,MAAM,CAAC,MAAM,MAAM,CACxD,CAAC;gBACF,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,+BAA+B,OAAO,IAAI,CAAC,CAAC;YAC3D,YAAY,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IACD,IAAI,KAAK,EAAE,MAAM,KAAK,KAAK,EAAE,CAAC;QAC5B,MAAM,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IACD,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,KAAK,EAAE,MAAM,KAAK,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC,EAAE,CAAC,MAAM,CACZ,qFAAqF,CACtF,CAAC;QACF,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,CAAC,EAAE,CAAC,MAAM,CACZ,6HAA6H,CAC9H,CAAC;QACF,OAAO,eAAe,CAAC;IACzB,CAAC;IACD,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CliDeps } from "../deps.js";
2
+ import type { ParsedArgs } from "../types.js";
3
+ export declare function resolveScanId(deps: CliDeps, origin: string, id: string | null): string;
4
+ export declare function fetchReport(deps: CliDeps, origin: string, token: string, scanId: string, format: "md" | "json", preview: boolean): Promise<{
5
+ markdown: string | null;
6
+ report: unknown | null;
7
+ }>;
8
+ export declare function runReport(deps: CliDeps, args: ParsedArgs): Promise<number>;
@@ -0,0 +1,55 @@
1
+ import { requireToken, resolveOrigin, peekStoredCreds, } from "../credentials.js";
2
+ import { CliError, EXIT_OK, EXIT_RUNNING, usageError } from "../exit.js";
3
+ import { asErrorBody, httpRequest, requireOk } from "../http.js";
4
+ import { writeJson, writeMarkdownReport } from "../output.js";
5
+ import { writeResume } from "../action.js";
6
+ export function resolveScanId(deps, origin, id) {
7
+ if (id)
8
+ return id;
9
+ const stored = peekStoredCreds(deps, origin);
10
+ if (stored?.lastScanId)
11
+ return stored.lastScanId;
12
+ throw usageError("Pass a scan id or run a scan first.");
13
+ }
14
+ export async function fetchReport(deps, origin, token, scanId, format, preview) {
15
+ const params = new URLSearchParams({ format });
16
+ if (preview)
17
+ params.set("preview", "1");
18
+ const result = await httpRequest(deps, origin, "GET", `/api/agent/v1/scans/${encodeURIComponent(scanId)}/report?${params.toString()}`, {
19
+ token,
20
+ accept: format === "md" ? "text/markdown, application/json" : "application/json",
21
+ });
22
+ if (result.status === 409) {
23
+ const body = asErrorBody(result.json);
24
+ if (body.error === "report_not_ready") {
25
+ throw new CliError(body.message ?? "Report is not ready yet.", EXIT_RUNNING);
26
+ }
27
+ }
28
+ requireOk(result);
29
+ if (format === "md") {
30
+ return { markdown: result.text, report: result.json };
31
+ }
32
+ return { markdown: null, report: result.json };
33
+ }
34
+ export async function runReport(deps, args) {
35
+ const origin = resolveOrigin(deps);
36
+ const creds = requireToken(deps, origin);
37
+ const scanId = resolveScanId(deps, origin, args.id);
38
+ try {
39
+ const fetched = await fetchReport(deps, origin, creds.token, scanId, args.json ? "json" : args.format, args.preview);
40
+ if (args.json) {
41
+ writeJson(deps, fetched.report);
42
+ }
43
+ else {
44
+ writeMarkdownReport(deps, fetched.markdown ?? "");
45
+ }
46
+ return EXIT_OK;
47
+ }
48
+ catch (err) {
49
+ if (err instanceof CliError && err.exitCode === EXIT_RUNNING) {
50
+ writeResume(deps, scanId);
51
+ }
52
+ throw err;
53
+ }
54
+ }
55
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CliDeps } from "../deps.js";
2
+ import type { ParsedArgs } from "../types.js";
3
+ export declare function runUploadScan(deps: CliDeps, args: ParsedArgs): Promise<number>;
@@ -0,0 +1,85 @@
1
+ import { writeAction, writeResume } from "../action.js";
2
+ import { requireToken, resolveOrigin, storeLastScanId, } from "../credentials.js";
3
+ import { CliError, EXIT_OK, EXIT_RUNNING, EXIT_SCAN_FAILED, EXIT_UNEXPECTED } from "../exit.js";
4
+ import { recoverOutOfScansIfOffered } from "./credits.js";
5
+ import { httpRequest, requireOk } from "../http.js";
6
+ import { writeJson, writeMarkdownReport, writeScanProgress } from "../output.js";
7
+ import { formatPackSummary, packManifest, planPack, writePackArchive, } from "../pack.js";
8
+ import { fetchReport } from "./report.js";
9
+ import { isScanFinal, waitForScan } from "../wait.js";
10
+ export async function runUploadScan(deps, args) {
11
+ const origin = resolveOrigin(deps);
12
+ const creds = requireToken(deps, origin);
13
+ const plan = await planPack(deps);
14
+ deps.io.stderr(formatPackSummary(plan, args.dryRun));
15
+ if (args.dryRun)
16
+ return EXIT_OK;
17
+ const archive = await writePackArchive(plan);
18
+ const uploaded = await httpRequest(deps, origin, "POST", "/api/agent/v1/uploads", {
19
+ token: creds.token,
20
+ rawBody: new Uint8Array(archive.bytes),
21
+ contentType: "application/gzip",
22
+ headers: {
23
+ "CleanSlop-Upload-Manifest": JSON.stringify(packManifest(plan, archive.sha256)),
24
+ },
25
+ });
26
+ requireOk(uploaded);
27
+ const rec = uploaded.json;
28
+ if (!rec || typeof rec.uploadId !== "string") {
29
+ throw new CliError("Upload response was missing uploadId.", EXIT_UNEXPECTED);
30
+ }
31
+ const headers = {};
32
+ if (args.force)
33
+ headers["Idempotency-Key"] = deps.randomId();
34
+ const startBody = {
35
+ uploadId: rec.uploadId,
36
+ force: args.force || undefined,
37
+ surface: "cli",
38
+ };
39
+ const postStart = () => httpRequest(deps, origin, "POST", "/api/agent/v1/scans", {
40
+ token: creds.token,
41
+ headers,
42
+ body: startBody,
43
+ });
44
+ const started = await recoverOutOfScansIfOffered(deps, args, await postStart(), postStart);
45
+ requireOk(started);
46
+ const payload = started.json;
47
+ if (!payload?.scan?.id) {
48
+ throw new CliError("Scan create response was invalid.", EXIT_UNEXPECTED);
49
+ }
50
+ const scan0 = payload.scan;
51
+ await storeLastScanId(deps, origin, scan0.id);
52
+ writeScanProgress(deps, scan0);
53
+ let scan = scan0;
54
+ if (!isScanFinal(scan) && args.wait) {
55
+ scan = await waitForScan(deps, origin, creds.token, scan0.id, args.waitMs);
56
+ writeScanProgress(deps, scan);
57
+ }
58
+ if (scan.status === "failed") {
59
+ throw new CliError(scan.error?.message ?? "Scan failed.", EXIT_SCAN_FAILED);
60
+ }
61
+ const wantReport = isScanFinal(scan) || args.preview;
62
+ if (!wantReport) {
63
+ writeResume(deps, scan.id);
64
+ throw new CliError("Scan is still running.", EXIT_RUNNING);
65
+ }
66
+ try {
67
+ const fetched = await fetchReport(deps, origin, creds.token, scan.id, args.json ? "json" : "md", args.preview && !scan.final);
68
+ if (args.json) {
69
+ writeJson(deps, { scan, report: fetched.report });
70
+ }
71
+ else if (fetched.markdown) {
72
+ writeMarkdownReport(deps, fetched.markdown);
73
+ }
74
+ }
75
+ catch (err) {
76
+ if (err instanceof CliError && err.exitCode === EXIT_RUNNING) {
77
+ writeResume(deps, scan.id);
78
+ if (err.action)
79
+ writeAction(deps, err.action);
80
+ }
81
+ throw err;
82
+ }
83
+ return EXIT_OK;
84
+ }
85
+ //# sourceMappingURL=scan-upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-upload.js","sourceRoot":"","sources":["../../src/commands/scan-upload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CliDeps } from "../deps.js";
2
+ import type { ParsedArgs } from "../types.js";
3
+ export declare function runScan(deps: CliDeps, args: ParsedArgs): Promise<number>;
@@ -0,0 +1,81 @@
1
+ import { writeAction, writeResume } from "../action.js";
2
+ import { requireToken, resolveOrigin, storeLastScanId, } from "../credentials.js";
3
+ import { CliError, EXIT_OK, EXIT_RUNNING, EXIT_SCAN_FAILED, EXIT_UNEXPECTED, } from "../exit.js";
4
+ import { assertGithubReady, inspectGit } from "../git.js";
5
+ import { recoverOutOfScansIfOffered } from "./credits.js";
6
+ import { httpRequest, requireOk } from "../http.js";
7
+ import { writeJson, writeMarkdownReport, writeScanProgress } from "../output.js";
8
+ import { fetchReport } from "./report.js";
9
+ import { runUploadScan } from "./scan-upload.js";
10
+ import { isScanFinal, waitForScan } from "../wait.js";
11
+ export async function runScan(deps, args) {
12
+ const origin = resolveOrigin(deps);
13
+ const creds = requireToken(deps, origin);
14
+ const meRes = await httpRequest(deps, origin, "GET", "/api/agent/v1/me", {
15
+ token: creds.token,
16
+ });
17
+ requireOk(meRes);
18
+ const me = (meRes.json ?? {});
19
+ if (me.uploads === true) {
20
+ return runUploadScan(deps, args);
21
+ }
22
+ const git = await inspectGit(deps);
23
+ assertGithubReady(git);
24
+ const headers = {};
25
+ if (args.force) {
26
+ headers["Idempotency-Key"] = deps.randomId();
27
+ }
28
+ const startBody = {
29
+ remote: git.remote,
30
+ commitSha: git.commitSha,
31
+ branch: git.branch,
32
+ force: args.force || undefined,
33
+ surface: "cli",
34
+ };
35
+ const postStart = () => httpRequest(deps, origin, "POST", "/api/agent/v1/scans", {
36
+ token: creds.token,
37
+ headers,
38
+ body: startBody,
39
+ });
40
+ const started = await recoverOutOfScansIfOffered(deps, args, await postStart(), postStart);
41
+ requireOk(started);
42
+ const payload = started.json;
43
+ if (!payload?.scan?.id) {
44
+ throw new CliError("Scan create response was invalid.", EXIT_UNEXPECTED);
45
+ }
46
+ const scan0 = payload.scan;
47
+ await storeLastScanId(deps, origin, scan0.id);
48
+ writeScanProgress(deps, scan0);
49
+ let scan = scan0;
50
+ if (!isScanFinal(scan) && args.wait) {
51
+ scan = await waitForScan(deps, origin, creds.token, scan0.id, args.waitMs);
52
+ writeScanProgress(deps, scan);
53
+ }
54
+ if (scan.status === "failed") {
55
+ throw new CliError(scan.error?.message ?? "Scan failed.", EXIT_SCAN_FAILED);
56
+ }
57
+ const wantReport = isScanFinal(scan) || args.preview;
58
+ if (!wantReport) {
59
+ writeResume(deps, scan.id, scan);
60
+ throw new CliError("Scan is still running.", EXIT_RUNNING);
61
+ }
62
+ try {
63
+ const fetched = await fetchReport(deps, origin, creds.token, scan.id, args.json ? "json" : "md", args.preview && !scan.final);
64
+ if (args.json) {
65
+ writeJson(deps, { scan, report: fetched.report });
66
+ }
67
+ else if (fetched.markdown) {
68
+ writeMarkdownReport(deps, fetched.markdown);
69
+ }
70
+ }
71
+ catch (err) {
72
+ if (err instanceof CliError && err.exitCode === EXIT_RUNNING) {
73
+ writeResume(deps, scan.id, scan);
74
+ if (err.action)
75
+ writeAction(deps, err.action);
76
+ }
77
+ throw err;
78
+ }
79
+ return EXIT_OK;
80
+ }
81
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAa,EACb,IAAgB;IAEhB,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE;QACvE,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC,CAAC;IACH,SAAS,CAAC,KAAK,CAAC,CAAC;IACjB,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAe,CAAC;IAC5C,IAAI,EAAE,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACnC,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAEvB,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS;QAC9B,OAAO,EAAE,KAAK;KACf,CAAC;IACF,MAAM,SAAS,GAAG,GAAG,EAAE,CACrB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE;QACvD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO;QACP,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC;IACL,MAAM,OAAO,GAAG,MAAM,0BAA0B,CAC9C,IAAI,EACJ,IAAI,EACJ,MAAM,SAAS,EAAE,EACjB,SAAS,CACV,CAAC;IACF,SAAS,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAgC,CAAC;IACzD,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,QAAQ,CAAC,mCAAmC,EAAE,eAAe,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3B,MAAM,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9C,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAE/B,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3E,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,IAAI,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC;IACrD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACjC,MAAM,IAAI,QAAQ,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAC/B,IAAI,EACJ,MAAM,EACN,KAAK,CAAC,KAAK,EACX,IAAI,CAAC,EAAE,EACP,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EACzB,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAC5B,CAAC;QACF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,SAAS,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC5B,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC7D,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACjC,IAAI,GAAG,CAAC,MAAM;gBAAE,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAChD,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { CliDeps } from "../deps.js";
2
+ export type SetupTarget = {
3
+ id: "claude" | "cursor" | "codex" | "agents";
4
+ label: string;
5
+ path: string;
6
+ kind: "owned" | "marker";
7
+ render: (core: string) => string;
8
+ };
9
+ export declare function setupTargets(deps: CliDeps, project: boolean): SetupTarget[];
10
+ export declare function runSetup(deps: CliDeps, args: {
11
+ dryRun: boolean;
12
+ uninstall: boolean;
13
+ project: boolean;
14
+ yes: boolean;
15
+ }): Promise<number>;
16
+ export declare const SETUP_MARKERS: {
17
+ begin: string;
18
+ end: string;
19
+ };