@akasecurity/ai-tc-claude-code 0.9.6 → 0.9.7
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/.claude-plugin/plugin.json +1 -1
- package/commands/setup.md +0 -23
- package/package.json +6 -5
- package/scripts/apply-suppressions.js +1428 -970
- package/scripts/backfill.js +1533 -1016
- package/scripts/dashboard.js +131 -10
- package/scripts/filescan.js +1458 -1009
- package/scripts/firstrun.js +1307 -901
- package/scripts/intro.js +1000 -894
- package/scripts/message-display.js +1404 -979
- package/scripts/onboard.js +1330 -891
- package/scripts/post-tool-use.js +1521 -1004
- package/scripts/pre-tool-use.js +1526 -1009
- package/scripts/query.js +1313 -902
- package/scripts/reconcile.js +1479 -1002
- package/scripts/remediate.js +1526 -1009
- package/scripts/scan-worker.js +996 -916
- package/scripts/session-start.js +1435 -1004
- package/scripts/start-light.js +1007 -902
- package/scripts/statusline.js +1307 -901
- package/scripts/stop.js +1069 -898
- package/scripts/user-prompt-submit.js +1525 -1008
package/scripts/dashboard.js
CHANGED
|
@@ -1,5 +1,112 @@
|
|
|
1
1
|
// src/dashboard.ts
|
|
2
|
-
import { spawn, spawnSync } from "child_process";
|
|
2
|
+
import { spawn, spawnSync as spawnSync2 } from "child_process";
|
|
3
|
+
|
|
4
|
+
// ../../packages/plugin-sdk/src/bare-command.ts
|
|
5
|
+
import { spawnSync } from "child_process";
|
|
6
|
+
import { homedir } from "os";
|
|
7
|
+
import { win32 } from "path";
|
|
8
|
+
var CMD_LINE_MAX = 8191;
|
|
9
|
+
var CMD_WRAPPER_ALLOWANCE = 64;
|
|
10
|
+
var DIRECT_EXTENSIONS = /* @__PURE__ */ new Set([".exe", ".com"]);
|
|
11
|
+
var CMD_HAZARDS = [
|
|
12
|
+
['"', "a double quote, which would close the quoted argument"],
|
|
13
|
+
["%", "a percent sign, which cmd.exe expands inside quotes and re-parses"],
|
|
14
|
+
["!", "an exclamation mark, which cmd.exe expands when delayed expansion is on"],
|
|
15
|
+
["\r", "a carriage return, which a Windows command line cannot carry"],
|
|
16
|
+
["\n", "a line break, which a Windows command line cannot carry"],
|
|
17
|
+
["\0", "a NUL byte"]
|
|
18
|
+
];
|
|
19
|
+
var BACKSLASH = 92;
|
|
20
|
+
var BARE_COMMAND_ERROR_CODE = "ERR_AKA_WINDOWS_ARGV";
|
|
21
|
+
var BareCommandUnsupportedError = class extends Error {
|
|
22
|
+
code = BARE_COMMAND_ERROR_CODE;
|
|
23
|
+
reason;
|
|
24
|
+
constructor(reason) {
|
|
25
|
+
super(`cannot spawn this command on Windows: ${reason}`);
|
|
26
|
+
this.name = "BareCommandUnsupportedError";
|
|
27
|
+
this.reason = reason;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
function isBareCommandUnsupported(err) {
|
|
31
|
+
return typeof err === "object" && err !== null && err.code === BARE_COMMAND_ERROR_CODE && typeof err.reason === "string";
|
|
32
|
+
}
|
|
33
|
+
function cmdLineHazard(command, args2) {
|
|
34
|
+
for (const [index, arg] of [command, ...args2].entries()) {
|
|
35
|
+
for (const [char, why] of CMD_HAZARDS) {
|
|
36
|
+
if (arg.includes(char)) {
|
|
37
|
+
const where = index === 0 ? "the command name" : `argument ${String(index)}`;
|
|
38
|
+
return `${where} contains ${why}`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const length = quoteCommandLine(command, args2).length + CMD_WRAPPER_ALLOWANCE;
|
|
43
|
+
if (length > CMD_LINE_MAX) {
|
|
44
|
+
return `the command line is ${String(length)} characters once cmd.exe's own prefix is counted, over its ${String(CMD_LINE_MAX)}`;
|
|
45
|
+
}
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
function quoteForCmd(value) {
|
|
49
|
+
let runStart = value.length;
|
|
50
|
+
while (runStart > 0 && value.charCodeAt(runStart - 1) === BACKSLASH) runStart -= 1;
|
|
51
|
+
const trailingBackslashes = value.slice(runStart);
|
|
52
|
+
const body = value.slice(0, runStart);
|
|
53
|
+
return `"${body}${trailingBackslashes}${trailingBackslashes}"`;
|
|
54
|
+
}
|
|
55
|
+
function quoteCommandLine(command, args2) {
|
|
56
|
+
return [command, ...args2].map(quoteForCmd).join(" ");
|
|
57
|
+
}
|
|
58
|
+
var RESOLVE_TIMEOUT_MS = 5e3;
|
|
59
|
+
function systemWhere(env) {
|
|
60
|
+
for (const [key, value] of Object.entries(env ?? process.env)) {
|
|
61
|
+
if (key.toLowerCase() !== "systemroot") continue;
|
|
62
|
+
if (typeof value !== "string" || value.trim() === "") return void 0;
|
|
63
|
+
return win32.join(value, "System32", "where.exe");
|
|
64
|
+
}
|
|
65
|
+
return void 0;
|
|
66
|
+
}
|
|
67
|
+
function resolveWindowsCommand(command, env, home) {
|
|
68
|
+
try {
|
|
69
|
+
const probe = spawnSync(systemWhere(env) ?? "where", [command], {
|
|
70
|
+
encoding: "utf8",
|
|
71
|
+
cwd: home,
|
|
72
|
+
windowsHide: true,
|
|
73
|
+
timeout: RESOLVE_TIMEOUT_MS,
|
|
74
|
+
...env === void 0 ? {} : { env }
|
|
75
|
+
});
|
|
76
|
+
if (probe.status !== 0 || typeof probe.stdout !== "string") return void 0;
|
|
77
|
+
const first = probe.stdout.split(/\r?\n/).find((line) => line.trim() !== "");
|
|
78
|
+
return first?.trim();
|
|
79
|
+
} catch {
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function isDirectlyExecutable(file) {
|
|
84
|
+
return DIRECT_EXTENSIONS.has(win32.extname(file).toLowerCase());
|
|
85
|
+
}
|
|
86
|
+
function planBareCommand(command, args2, deps = {}) {
|
|
87
|
+
const platform = deps.platform ?? process.platform;
|
|
88
|
+
if (platform !== "win32") {
|
|
89
|
+
return { file: command, args: args2, options: {}, viaShell: false, resolved: void 0 };
|
|
90
|
+
}
|
|
91
|
+
const home = deps.home ?? homedir();
|
|
92
|
+
const resolve = deps.resolve ?? resolveWindowsCommand;
|
|
93
|
+
const resolved = resolve(command, deps.env, home);
|
|
94
|
+
if (resolved !== void 0 && isDirectlyExecutable(resolved)) {
|
|
95
|
+
return { file: resolved, args: args2, options: { cwd: home }, viaShell: false, resolved };
|
|
96
|
+
}
|
|
97
|
+
const hazard = cmdLineHazard(command, args2);
|
|
98
|
+
if (hazard !== void 0) {
|
|
99
|
+
const why = resolved === void 0 ? `${command} did not resolve to an executable, so it could only be run through cmd.exe` : `${command} resolves only to a batch shim, which must be run through cmd.exe`;
|
|
100
|
+
throw new BareCommandUnsupportedError(`${why}, and ${hazard}`);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
file: quoteCommandLine(command, args2),
|
|
104
|
+
args: [],
|
|
105
|
+
options: { shell: true, cwd: home },
|
|
106
|
+
viaShell: true,
|
|
107
|
+
resolved
|
|
108
|
+
};
|
|
109
|
+
}
|
|
3
110
|
|
|
4
111
|
// src/dashboard-launch.ts
|
|
5
112
|
var DEFAULT_PORT = "4319";
|
|
@@ -20,27 +127,41 @@ function startMessage(url) {
|
|
|
20
127
|
It serves your local store at ~/.aka/data; leave it running (stop it with Ctrl-C in that process).`;
|
|
21
128
|
}
|
|
22
129
|
var INSTALL_HINT = "The AKA dashboard is launched by the `aka` CLI, which the plugin does not bundle.\nInstall it and run /aka:dashboard again:\n npm i -g @akasecurity/cli # then it is on your PATH as `aka`\nFrom a repo checkout instead: pnpm --filter @akasecurity/cli dev dashboard";
|
|
130
|
+
function unsupportedArgvMessage(reason) {
|
|
131
|
+
return `The AKA dashboard could not be launched: ${reason}.
|
|
132
|
+
Re-run without that flag, or start the dashboard directly:
|
|
133
|
+
aka dashboard`;
|
|
134
|
+
}
|
|
135
|
+
var PROBE_FLAG = "--help";
|
|
136
|
+
function akaMissing(plan, probe) {
|
|
137
|
+
if (plan.viaShell) return plan.resolved === void 0;
|
|
138
|
+
const { error } = probe(plan.file, [PROBE_FLAG], { stdio: "ignore", ...plan.options });
|
|
139
|
+
return error?.code === "ENOENT";
|
|
140
|
+
}
|
|
23
141
|
|
|
24
142
|
// src/dashboard.ts
|
|
25
143
|
var args = process.argv.slice(2);
|
|
26
|
-
function akaMissing() {
|
|
27
|
-
const probe = spawnSync("aka", ["--help"], { stdio: "ignore" });
|
|
28
|
-
return probe.error !== void 0 && probe.error.code === "ENOENT";
|
|
29
|
-
}
|
|
30
144
|
try {
|
|
31
|
-
|
|
145
|
+
const plan = planBareCommand("aka", ["dashboard", ...args]);
|
|
146
|
+
if (akaMissing(plan, (file, probeArgs, options) => spawnSync2(file, [...probeArgs], options))) {
|
|
32
147
|
process.stdout.write(`${INSTALL_HINT}
|
|
33
148
|
`);
|
|
34
149
|
process.exit(0);
|
|
35
150
|
}
|
|
36
|
-
const child = spawn(
|
|
151
|
+
const child = spawn(plan.file, [...plan.args], {
|
|
152
|
+
detached: true,
|
|
153
|
+
stdio: "ignore",
|
|
154
|
+
...plan.options
|
|
155
|
+
});
|
|
37
156
|
child.on("error", () => {
|
|
38
157
|
});
|
|
39
158
|
child.unref();
|
|
40
159
|
process.stdout.write(`${startMessage(dashboardUrl(parsePort(args)))}
|
|
41
160
|
`);
|
|
42
|
-
} catch {
|
|
43
|
-
process.stdout.write(
|
|
44
|
-
|
|
161
|
+
} catch (err) {
|
|
162
|
+
process.stdout.write(
|
|
163
|
+
`${isBareCommandUnsupported(err) ? unsupportedArgvMessage(err.reason) : INSTALL_HINT}
|
|
164
|
+
`
|
|
165
|
+
);
|
|
45
166
|
process.exit(0);
|
|
46
167
|
}
|