sentinelayer-cli 0.4.5 → 0.6.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.
- package/README.md +996 -998
- package/bin/create-sentinelayer.js +5 -5
- package/bin/sentinelayer-cli.js +4 -4
- package/bin/sl.js +5 -5
- package/package.json +63 -63
- package/src/agents/jules/config/definition.js +160 -209
- package/src/agents/jules/config/system-prompt.js +182 -175
- package/src/agents/jules/error-intake.js +51 -51
- package/src/agents/jules/fix-cycle.js +17 -377
- package/src/agents/jules/loop.js +450 -367
- package/src/agents/jules/pulse.js +10 -327
- package/src/agents/jules/stream.js +186 -186
- package/src/agents/jules/swarm/file-scanner.js +74 -74
- package/src/agents/jules/swarm/index.js +11 -11
- package/src/agents/jules/swarm/orchestrator.js +362 -362
- package/src/agents/jules/swarm/pattern-hunter.js +123 -123
- package/src/agents/jules/swarm/sub-agent.js +309 -308
- package/src/agents/jules/tools/aidenid-email.js +189 -0
- package/src/agents/jules/tools/auth-audit.js +1691 -557
- package/src/agents/jules/tools/dispatch.js +335 -327
- package/src/agents/jules/tools/file-edit.js +2 -180
- package/src/agents/jules/tools/file-read.js +2 -100
- package/src/agents/jules/tools/frontend-analyze.js +570 -570
- package/src/agents/jules/tools/glob.js +2 -168
- package/src/agents/jules/tools/grep.js +2 -228
- package/src/agents/jules/tools/index.js +29 -29
- package/src/agents/jules/tools/path-guards.js +2 -161
- package/src/agents/jules/tools/runtime-audit.js +507 -503
- package/src/agents/jules/tools/shell.js +2 -383
- package/src/agents/jules/tools/url-policy.js +100 -100
- package/src/agents/persona-visuals.js +61 -0
- package/src/agents/shared-tools/dispatch-core.js +315 -0
- package/src/agents/shared-tools/file-edit.js +180 -0
- package/src/agents/shared-tools/file-read.js +100 -0
- package/src/agents/shared-tools/glob.js +168 -0
- package/src/agents/shared-tools/grep.js +228 -0
- package/src/agents/shared-tools/index.js +46 -0
- package/src/agents/shared-tools/path-guards.js +161 -0
- package/src/agents/shared-tools/shell.js +383 -0
- package/src/ai/aidenid.js +1009 -972
- package/src/ai/client.js +553 -508
- package/src/ai/domain-target-store.js +268 -268
- package/src/ai/identity-store.js +270 -270
- package/src/ai/proxy.js +137 -0
- package/src/ai/site-store.js +145 -145
- package/src/audit/agents/architecture.js +180 -180
- package/src/audit/agents/compliance.js +179 -179
- package/src/audit/agents/documentation.js +165 -165
- package/src/audit/agents/performance.js +145 -145
- package/src/audit/agents/security.js +215 -215
- package/src/audit/agents/testing.js +172 -172
- package/src/audit/orchestrator.js +557 -557
- package/src/audit/package.js +204 -204
- package/src/audit/registry.js +284 -284
- package/src/audit/replay.js +103 -103
- package/src/auth/gate.js +371 -126
- package/src/auth/http.js +611 -270
- package/src/auth/service.js +1106 -891
- package/src/auth/session-store.js +813 -359
- package/src/cli.js +252 -252
- package/src/commands/ai/identity-lifecycle.js +1338 -1338
- package/src/commands/ai/provision-governance.js +1272 -1272
- package/src/commands/ai/shared.js +147 -147
- package/src/commands/ai.js +11 -11
- package/src/commands/apply.js +12 -12
- package/src/commands/audit.js +1166 -1166
- package/src/commands/auth.js +419 -375
- package/src/commands/chat.js +191 -191
- package/src/commands/config.js +184 -184
- package/src/commands/cost.js +311 -311
- package/src/commands/daemon/core.js +850 -850
- package/src/commands/daemon/extended.js +1048 -1048
- package/src/commands/daemon/shared.js +213 -213
- package/src/commands/daemon.js +11 -11
- package/src/commands/guide.js +174 -174
- package/src/commands/ingest.js +58 -58
- package/src/commands/init.js +55 -55
- package/src/commands/legacy-args.js +10 -10
- package/src/commands/mcp.js +461 -461
- package/src/commands/omargate.js +29 -21
- package/src/commands/persona.js +20 -20
- package/src/commands/plugin.js +260 -260
- package/src/commands/policy.js +132 -132
- package/src/commands/prompt.js +238 -238
- package/src/commands/review.js +704 -704
- package/src/commands/scan.js +872 -866
- package/src/commands/spec.js +716 -716
- package/src/commands/swarm.js +651 -651
- package/src/commands/telemetry.js +202 -202
- package/src/commands/watch.js +511 -510
- package/src/config/agent-dictionary.js +182 -182
- package/src/config/io.js +56 -56
- package/src/config/paths.js +18 -18
- package/src/config/schema.js +55 -55
- package/src/config/service.js +184 -184
- package/src/cost/budget.js +235 -235
- package/src/cost/history.js +188 -188
- package/src/cost/tracker.js +171 -171
- package/src/daemon/artifact-lineage.js +534 -534
- package/src/daemon/assignment-ledger.js +770 -770
- package/src/daemon/ast-parser-layer.js +258 -258
- package/src/daemon/budget-governor.js +633 -633
- package/src/daemon/callgraph-overlay.js +646 -646
- package/src/daemon/error-worker.js +626 -626
- package/src/daemon/fix-cycle.js +377 -0
- package/src/daemon/hybrid-mapper.js +929 -929
- package/src/daemon/jira-lifecycle.js +632 -632
- package/src/daemon/operator-control.js +657 -657
- package/src/daemon/pulse.js +327 -0
- package/src/daemon/reliability-lane.js +471 -471
- package/src/daemon/watchdog.js +971 -971
- package/src/guide/generator.js +316 -316
- package/src/ingest/engine.js +918 -918
- package/src/interactive/index.js +97 -95
- package/src/legacy-cli.js +2994 -2592
- package/src/mcp/registry.js +695 -695
- package/src/memory/blackboard.js +301 -301
- package/src/memory/retrieval.js +581 -581
- package/src/plugin/manifest.js +553 -553
- package/src/policy/packs.js +144 -144
- package/src/prompt/generator.js +118 -118
- package/src/review/ai-review.js +679 -669
- package/src/review/local-review.js +1305 -1295
- package/src/review/omargate-interactive.js +68 -0
- package/src/review/omargate-orchestrator.js +300 -0
- package/src/review/persona-prompts.js +296 -0
- package/src/review/replay.js +235 -235
- package/src/review/report.js +664 -664
- package/src/review/scan-modes.js +42 -0
- package/src/review/spec-binding.js +487 -487
- package/src/scaffold/generator.js +67 -67
- package/src/scaffold/templates.js +150 -150
- package/src/scan/generator.js +418 -418
- package/src/scan/gh-secrets.js +107 -107
- package/src/spec/generator.js +519 -519
- package/src/spec/regenerate.js +237 -237
- package/src/spec/templates.js +91 -91
- package/src/swarm/dashboard.js +247 -247
- package/src/swarm/factory.js +363 -363
- package/src/swarm/pentest.js +934 -934
- package/src/swarm/registry.js +419 -419
- package/src/swarm/report.js +158 -158
- package/src/swarm/runtime.js +576 -576
- package/src/swarm/scenario-dsl.js +272 -272
- package/src/telemetry/ledger.js +302 -302
- package/src/telemetry/session-tracker.js +234 -118
- package/src/telemetry/sync.js +203 -199
- package/src/ui/command-hints.js +13 -0
- package/src/ui/markdown.js +220 -220
package/src/cli.js
CHANGED
|
@@ -1,252 +1,252 @@
|
|
|
1
|
-
import process from "node:process";
|
|
2
|
-
import { Command } from "commander";
|
|
3
|
-
|
|
4
|
-
import { CLI_VERSION, runLegacyCliWithErrorHandling } from "./legacy-cli.js";
|
|
5
|
-
|
|
6
|
-
const COMMAND_REGISTRARS = {
|
|
7
|
-
init: {
|
|
8
|
-
loader: () => import("./commands/init.js"),
|
|
9
|
-
exportName: "registerInitCommand",
|
|
10
|
-
needsLegacy: true,
|
|
11
|
-
},
|
|
12
|
-
omargate: {
|
|
13
|
-
loader: () => import("./commands/omargate.js"),
|
|
14
|
-
exportName: "registerOmarGateCommand",
|
|
15
|
-
needsLegacy: true,
|
|
16
|
-
},
|
|
17
|
-
audit: {
|
|
18
|
-
loader: () => import("./commands/audit.js"),
|
|
19
|
-
exportName: "registerAuditCommand",
|
|
20
|
-
needsLegacy: true,
|
|
21
|
-
},
|
|
22
|
-
persona: {
|
|
23
|
-
loader: () => import("./commands/persona.js"),
|
|
24
|
-
exportName: "registerPersonaCommand",
|
|
25
|
-
needsLegacy: true,
|
|
26
|
-
},
|
|
27
|
-
apply: {
|
|
28
|
-
loader: () => import("./commands/apply.js"),
|
|
29
|
-
exportName: "registerApplyCommand",
|
|
30
|
-
needsLegacy: true,
|
|
31
|
-
},
|
|
32
|
-
config: {
|
|
33
|
-
loader: () => import("./commands/config.js"),
|
|
34
|
-
exportName: "registerConfigCommand",
|
|
35
|
-
needsLegacy: false,
|
|
36
|
-
},
|
|
37
|
-
ingest: {
|
|
38
|
-
loader: () => import("./commands/ingest.js"),
|
|
39
|
-
exportName: "registerIngestCommand",
|
|
40
|
-
needsLegacy: false,
|
|
41
|
-
},
|
|
42
|
-
spec: {
|
|
43
|
-
loader: () => import("./commands/spec.js"),
|
|
44
|
-
exportName: "registerSpecCommand",
|
|
45
|
-
needsLegacy: false,
|
|
46
|
-
},
|
|
47
|
-
prompt: {
|
|
48
|
-
loader: () => import("./commands/prompt.js"),
|
|
49
|
-
exportName: "registerPromptCommand",
|
|
50
|
-
needsLegacy: false,
|
|
51
|
-
},
|
|
52
|
-
scan: {
|
|
53
|
-
loader: () => import("./commands/scan.js"),
|
|
54
|
-
exportName: "registerScanCommand",
|
|
55
|
-
needsLegacy: false,
|
|
56
|
-
},
|
|
57
|
-
guide: {
|
|
58
|
-
loader: () => import("./commands/guide.js"),
|
|
59
|
-
exportName: "registerGuideCommand",
|
|
60
|
-
needsLegacy: false,
|
|
61
|
-
},
|
|
62
|
-
cost: {
|
|
63
|
-
loader: () => import("./commands/cost.js"),
|
|
64
|
-
exportName: "registerCostCommand",
|
|
65
|
-
needsLegacy: false,
|
|
66
|
-
},
|
|
67
|
-
telemetry: {
|
|
68
|
-
loader: () => import("./commands/telemetry.js"),
|
|
69
|
-
exportName: "registerTelemetryCommand",
|
|
70
|
-
needsLegacy: false,
|
|
71
|
-
},
|
|
72
|
-
auth: {
|
|
73
|
-
loader: () => import("./commands/auth.js"),
|
|
74
|
-
exportName: "registerAuthCommand",
|
|
75
|
-
needsLegacy: false,
|
|
76
|
-
},
|
|
77
|
-
watch: {
|
|
78
|
-
loader: () => import("./commands/watch.js"),
|
|
79
|
-
exportName: "registerWatchCommand",
|
|
80
|
-
needsLegacy: false,
|
|
81
|
-
},
|
|
82
|
-
mcp: {
|
|
83
|
-
loader: () => import("./commands/mcp.js"),
|
|
84
|
-
exportName: "registerMcpCommand",
|
|
85
|
-
needsLegacy: false,
|
|
86
|
-
},
|
|
87
|
-
plugin: {
|
|
88
|
-
loader: () => import("./commands/plugin.js"),
|
|
89
|
-
exportName: "registerPluginCommand",
|
|
90
|
-
needsLegacy: false,
|
|
91
|
-
},
|
|
92
|
-
ai: {
|
|
93
|
-
loader: () => import("./commands/ai.js"),
|
|
94
|
-
exportName: "registerAiCommand",
|
|
95
|
-
needsLegacy: false,
|
|
96
|
-
},
|
|
97
|
-
review: {
|
|
98
|
-
loader: () => import("./commands/review.js"),
|
|
99
|
-
exportName: "registerReviewCommand",
|
|
100
|
-
needsLegacy: false,
|
|
101
|
-
},
|
|
102
|
-
chat: {
|
|
103
|
-
loader: () => import("./commands/chat.js"),
|
|
104
|
-
exportName: "registerChatCommand",
|
|
105
|
-
needsLegacy: false,
|
|
106
|
-
},
|
|
107
|
-
policy: {
|
|
108
|
-
loader: () => import("./commands/policy.js"),
|
|
109
|
-
exportName: "registerPolicyCommand",
|
|
110
|
-
needsLegacy: false,
|
|
111
|
-
},
|
|
112
|
-
swarm: {
|
|
113
|
-
loader: () => import("./commands/swarm.js"),
|
|
114
|
-
exportName: "registerSwarmCommand",
|
|
115
|
-
needsLegacy: false,
|
|
116
|
-
},
|
|
117
|
-
daemon: {
|
|
118
|
-
loader: () => import("./commands/daemon.js"),
|
|
119
|
-
exportName: "registerDaemonCommand",
|
|
120
|
-
needsLegacy: false,
|
|
121
|
-
},
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const COMMAND_SET = new Set(Object.keys(COMMAND_REGISTRARS));
|
|
125
|
-
|
|
126
|
-
// Map slash-prefixed commands to their Commander equivalents.
|
|
127
|
-
// /omargate → omargate, /audit → audit local, etc.
|
|
128
|
-
// Only remap /omargate to Commander. The others (/audit, /persona, /apply)
|
|
129
|
-
// stay on the legacy path for backward compatibility (different output format).
|
|
130
|
-
const SLASH_TO_COMMANDER = {
|
|
131
|
-
"/omargate": "omargate",
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
function normalizeSlashArgs(rawArgs) {
|
|
135
|
-
if (!Array.isArray(rawArgs) || rawArgs.length === 0) return rawArgs;
|
|
136
|
-
const first = String(rawArgs[0] || "").trim();
|
|
137
|
-
|
|
138
|
-
// Direct slash match: /omargate → omargate
|
|
139
|
-
const mapped = SLASH_TO_COMMANDER[first];
|
|
140
|
-
if (mapped) {
|
|
141
|
-
return [mapped, ...rawArgs.slice(1)];
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Windows Git Bash path mangling fix: /omargate gets converted to
|
|
145
|
-
// "C:/Program Files/Git/omargate" by MSYS. Detect and recover.
|
|
146
|
-
for (const [slash, cmd] of Object.entries(SLASH_TO_COMMANDER)) {
|
|
147
|
-
const suffix = slash.slice(1); // "omargate" from "/omargate"
|
|
148
|
-
if (first.endsWith("/" + suffix) || first.endsWith("\\" + suffix)) {
|
|
149
|
-
return [cmd, ...rawArgs.slice(1)];
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return rawArgs;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function shouldBypassCommander(rawArgs) {
|
|
157
|
-
if (!Array.isArray(rawArgs) || rawArgs.length === 0) {
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const first = String(rawArgs[0] || "").trim();
|
|
162
|
-
if (!first) {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Slash commands are now handled by normalizeSlashArgs before this check
|
|
167
|
-
if (first.startsWith("/") && !SLASH_TO_COMMANDER[first]) {
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (first === "--help" || first === "-h" || first === "help" || first === "--version" || first === "-v") {
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (first.startsWith("-")) {
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const resolved = SLASH_TO_COMMANDER[first] || first;
|
|
180
|
-
return !COMMAND_SET.has(resolved);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async function registerCommands(program, { invokeLegacy, onlyCommand } = {}) {
|
|
184
|
-
const commandNames =
|
|
185
|
-
onlyCommand && COMMAND_REGISTRARS[onlyCommand]
|
|
186
|
-
? [onlyCommand]
|
|
187
|
-
: Object.keys(COMMAND_REGISTRARS);
|
|
188
|
-
|
|
189
|
-
for (const commandName of commandNames) {
|
|
190
|
-
const descriptor = COMMAND_REGISTRARS[commandName];
|
|
191
|
-
const loaded = await descriptor.loader();
|
|
192
|
-
const registerFn = loaded[descriptor.exportName];
|
|
193
|
-
if (typeof registerFn !== "function") {
|
|
194
|
-
throw new Error(
|
|
195
|
-
`Command registrar '${descriptor.exportName}' was not exported by '${commandName}' loader.`
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
if (descriptor.needsLegacy) {
|
|
199
|
-
registerFn(program, invokeLegacy);
|
|
200
|
-
} else {
|
|
201
|
-
registerFn(program);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export async function buildCliProgram({
|
|
207
|
-
invokeLegacy = runLegacyCliWithErrorHandling,
|
|
208
|
-
onlyCommand = null,
|
|
209
|
-
} = {}) {
|
|
210
|
-
const program = new Command();
|
|
211
|
-
|
|
212
|
-
program
|
|
213
|
-
.name("sentinelayer-cli")
|
|
214
|
-
.description("Sentinelayer CLI")
|
|
215
|
-
.version(CLI_VERSION)
|
|
216
|
-
.option("--verbose", "Verbose execution logs")
|
|
217
|
-
.option("--quiet", "Suppress progress indicators and terminal notifications")
|
|
218
|
-
.option("--json", "Emit machine-readable output when supported")
|
|
219
|
-
.showHelpAfterError();
|
|
220
|
-
|
|
221
|
-
await registerCommands(program, {
|
|
222
|
-
invokeLegacy,
|
|
223
|
-
onlyCommand: onlyCommand && COMMAND_SET.has(onlyCommand) ? onlyCommand : null,
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
return program;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export async function runCli(rawArgs = process.argv.slice(2)) {
|
|
230
|
-
// Normalize slash commands (/omargate → omargate, /audit → audit, etc.)
|
|
231
|
-
const normalizedArgs = normalizeSlashArgs(rawArgs);
|
|
232
|
-
|
|
233
|
-
// Auth gate — require login for all commands except auth/help/version/config
|
|
234
|
-
const { checkAuthGate, printAuthRequired } = await import("./auth/gate.js");
|
|
235
|
-
const authResult = await checkAuthGate(normalizedArgs);
|
|
236
|
-
if (!authResult.authenticated) {
|
|
237
|
-
printAuthRequired();
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (shouldBypassCommander(normalizedArgs)) {
|
|
242
|
-
await runLegacyCliWithErrorHandling(normalizedArgs);
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const program = await buildCliProgram({
|
|
247
|
-
invokeLegacy: runLegacyCliWithErrorHandling,
|
|
248
|
-
onlyCommand: normalizedArgs[0],
|
|
249
|
-
});
|
|
250
|
-
await program.parseAsync(["node", "sentinelayer-cli", ...normalizedArgs]);
|
|
251
|
-
}
|
|
252
|
-
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
|
|
4
|
+
import { CLI_VERSION, runLegacyCliWithErrorHandling } from "./legacy-cli.js";
|
|
5
|
+
|
|
6
|
+
const COMMAND_REGISTRARS = {
|
|
7
|
+
init: {
|
|
8
|
+
loader: () => import("./commands/init.js"),
|
|
9
|
+
exportName: "registerInitCommand",
|
|
10
|
+
needsLegacy: true,
|
|
11
|
+
},
|
|
12
|
+
omargate: {
|
|
13
|
+
loader: () => import("./commands/omargate.js"),
|
|
14
|
+
exportName: "registerOmarGateCommand",
|
|
15
|
+
needsLegacy: true,
|
|
16
|
+
},
|
|
17
|
+
audit: {
|
|
18
|
+
loader: () => import("./commands/audit.js"),
|
|
19
|
+
exportName: "registerAuditCommand",
|
|
20
|
+
needsLegacy: true,
|
|
21
|
+
},
|
|
22
|
+
persona: {
|
|
23
|
+
loader: () => import("./commands/persona.js"),
|
|
24
|
+
exportName: "registerPersonaCommand",
|
|
25
|
+
needsLegacy: true,
|
|
26
|
+
},
|
|
27
|
+
apply: {
|
|
28
|
+
loader: () => import("./commands/apply.js"),
|
|
29
|
+
exportName: "registerApplyCommand",
|
|
30
|
+
needsLegacy: true,
|
|
31
|
+
},
|
|
32
|
+
config: {
|
|
33
|
+
loader: () => import("./commands/config.js"),
|
|
34
|
+
exportName: "registerConfigCommand",
|
|
35
|
+
needsLegacy: false,
|
|
36
|
+
},
|
|
37
|
+
ingest: {
|
|
38
|
+
loader: () => import("./commands/ingest.js"),
|
|
39
|
+
exportName: "registerIngestCommand",
|
|
40
|
+
needsLegacy: false,
|
|
41
|
+
},
|
|
42
|
+
spec: {
|
|
43
|
+
loader: () => import("./commands/spec.js"),
|
|
44
|
+
exportName: "registerSpecCommand",
|
|
45
|
+
needsLegacy: false,
|
|
46
|
+
},
|
|
47
|
+
prompt: {
|
|
48
|
+
loader: () => import("./commands/prompt.js"),
|
|
49
|
+
exportName: "registerPromptCommand",
|
|
50
|
+
needsLegacy: false,
|
|
51
|
+
},
|
|
52
|
+
scan: {
|
|
53
|
+
loader: () => import("./commands/scan.js"),
|
|
54
|
+
exportName: "registerScanCommand",
|
|
55
|
+
needsLegacy: false,
|
|
56
|
+
},
|
|
57
|
+
guide: {
|
|
58
|
+
loader: () => import("./commands/guide.js"),
|
|
59
|
+
exportName: "registerGuideCommand",
|
|
60
|
+
needsLegacy: false,
|
|
61
|
+
},
|
|
62
|
+
cost: {
|
|
63
|
+
loader: () => import("./commands/cost.js"),
|
|
64
|
+
exportName: "registerCostCommand",
|
|
65
|
+
needsLegacy: false,
|
|
66
|
+
},
|
|
67
|
+
telemetry: {
|
|
68
|
+
loader: () => import("./commands/telemetry.js"),
|
|
69
|
+
exportName: "registerTelemetryCommand",
|
|
70
|
+
needsLegacy: false,
|
|
71
|
+
},
|
|
72
|
+
auth: {
|
|
73
|
+
loader: () => import("./commands/auth.js"),
|
|
74
|
+
exportName: "registerAuthCommand",
|
|
75
|
+
needsLegacy: false,
|
|
76
|
+
},
|
|
77
|
+
watch: {
|
|
78
|
+
loader: () => import("./commands/watch.js"),
|
|
79
|
+
exportName: "registerWatchCommand",
|
|
80
|
+
needsLegacy: false,
|
|
81
|
+
},
|
|
82
|
+
mcp: {
|
|
83
|
+
loader: () => import("./commands/mcp.js"),
|
|
84
|
+
exportName: "registerMcpCommand",
|
|
85
|
+
needsLegacy: false,
|
|
86
|
+
},
|
|
87
|
+
plugin: {
|
|
88
|
+
loader: () => import("./commands/plugin.js"),
|
|
89
|
+
exportName: "registerPluginCommand",
|
|
90
|
+
needsLegacy: false,
|
|
91
|
+
},
|
|
92
|
+
ai: {
|
|
93
|
+
loader: () => import("./commands/ai.js"),
|
|
94
|
+
exportName: "registerAiCommand",
|
|
95
|
+
needsLegacy: false,
|
|
96
|
+
},
|
|
97
|
+
review: {
|
|
98
|
+
loader: () => import("./commands/review.js"),
|
|
99
|
+
exportName: "registerReviewCommand",
|
|
100
|
+
needsLegacy: false,
|
|
101
|
+
},
|
|
102
|
+
chat: {
|
|
103
|
+
loader: () => import("./commands/chat.js"),
|
|
104
|
+
exportName: "registerChatCommand",
|
|
105
|
+
needsLegacy: false,
|
|
106
|
+
},
|
|
107
|
+
policy: {
|
|
108
|
+
loader: () => import("./commands/policy.js"),
|
|
109
|
+
exportName: "registerPolicyCommand",
|
|
110
|
+
needsLegacy: false,
|
|
111
|
+
},
|
|
112
|
+
swarm: {
|
|
113
|
+
loader: () => import("./commands/swarm.js"),
|
|
114
|
+
exportName: "registerSwarmCommand",
|
|
115
|
+
needsLegacy: false,
|
|
116
|
+
},
|
|
117
|
+
daemon: {
|
|
118
|
+
loader: () => import("./commands/daemon.js"),
|
|
119
|
+
exportName: "registerDaemonCommand",
|
|
120
|
+
needsLegacy: false,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const COMMAND_SET = new Set(Object.keys(COMMAND_REGISTRARS));
|
|
125
|
+
|
|
126
|
+
// Map slash-prefixed commands to their Commander equivalents.
|
|
127
|
+
// /omargate → omargate, /audit → audit local, etc.
|
|
128
|
+
// Only remap /omargate to Commander. The others (/audit, /persona, /apply)
|
|
129
|
+
// stay on the legacy path for backward compatibility (different output format).
|
|
130
|
+
const SLASH_TO_COMMANDER = {
|
|
131
|
+
"/omargate": "omargate",
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
function normalizeSlashArgs(rawArgs) {
|
|
135
|
+
if (!Array.isArray(rawArgs) || rawArgs.length === 0) return rawArgs;
|
|
136
|
+
const first = String(rawArgs[0] || "").trim();
|
|
137
|
+
|
|
138
|
+
// Direct slash match: /omargate → omargate
|
|
139
|
+
const mapped = SLASH_TO_COMMANDER[first];
|
|
140
|
+
if (mapped) {
|
|
141
|
+
return [mapped, ...rawArgs.slice(1)];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Windows Git Bash path mangling fix: /omargate gets converted to
|
|
145
|
+
// "C:/Program Files/Git/omargate" by MSYS. Detect and recover.
|
|
146
|
+
for (const [slash, cmd] of Object.entries(SLASH_TO_COMMANDER)) {
|
|
147
|
+
const suffix = slash.slice(1); // "omargate" from "/omargate"
|
|
148
|
+
if (first.endsWith("/" + suffix) || first.endsWith("\\" + suffix)) {
|
|
149
|
+
return [cmd, ...rawArgs.slice(1)];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return rawArgs;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function shouldBypassCommander(rawArgs) {
|
|
157
|
+
if (!Array.isArray(rawArgs) || rawArgs.length === 0) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const first = String(rawArgs[0] || "").trim();
|
|
162
|
+
if (!first) {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Slash commands are now handled by normalizeSlashArgs before this check
|
|
167
|
+
if (first.startsWith("/") && !SLASH_TO_COMMANDER[first]) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (first === "--help" || first === "-h" || first === "help" || first === "--version" || first === "-v") {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (first.startsWith("-")) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const resolved = SLASH_TO_COMMANDER[first] || first;
|
|
180
|
+
return !COMMAND_SET.has(resolved);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function registerCommands(program, { invokeLegacy, onlyCommand } = {}) {
|
|
184
|
+
const commandNames =
|
|
185
|
+
onlyCommand && COMMAND_REGISTRARS[onlyCommand]
|
|
186
|
+
? [onlyCommand]
|
|
187
|
+
: Object.keys(COMMAND_REGISTRARS);
|
|
188
|
+
|
|
189
|
+
for (const commandName of commandNames) {
|
|
190
|
+
const descriptor = COMMAND_REGISTRARS[commandName];
|
|
191
|
+
const loaded = await descriptor.loader();
|
|
192
|
+
const registerFn = loaded[descriptor.exportName];
|
|
193
|
+
if (typeof registerFn !== "function") {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Command registrar '${descriptor.exportName}' was not exported by '${commandName}' loader.`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
if (descriptor.needsLegacy) {
|
|
199
|
+
registerFn(program, invokeLegacy);
|
|
200
|
+
} else {
|
|
201
|
+
registerFn(program);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export async function buildCliProgram({
|
|
207
|
+
invokeLegacy = runLegacyCliWithErrorHandling,
|
|
208
|
+
onlyCommand = null,
|
|
209
|
+
} = {}) {
|
|
210
|
+
const program = new Command();
|
|
211
|
+
|
|
212
|
+
program
|
|
213
|
+
.name("sentinelayer-cli")
|
|
214
|
+
.description("Sentinelayer CLI")
|
|
215
|
+
.version(CLI_VERSION)
|
|
216
|
+
.option("--verbose", "Verbose execution logs")
|
|
217
|
+
.option("--quiet", "Suppress progress indicators and terminal notifications")
|
|
218
|
+
.option("--json", "Emit machine-readable output when supported")
|
|
219
|
+
.showHelpAfterError();
|
|
220
|
+
|
|
221
|
+
await registerCommands(program, {
|
|
222
|
+
invokeLegacy,
|
|
223
|
+
onlyCommand: onlyCommand && COMMAND_SET.has(onlyCommand) ? onlyCommand : null,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
return program;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export async function runCli(rawArgs = process.argv.slice(2)) {
|
|
230
|
+
// Normalize slash commands (/omargate → omargate, /audit → audit, etc.)
|
|
231
|
+
const normalizedArgs = normalizeSlashArgs(rawArgs);
|
|
232
|
+
|
|
233
|
+
// Auth gate — require login for all commands except auth/help/version/config
|
|
234
|
+
const { checkAuthGate, printAuthRequired } = await import("./auth/gate.js");
|
|
235
|
+
const authResult = await checkAuthGate(normalizedArgs);
|
|
236
|
+
if (!authResult.authenticated) {
|
|
237
|
+
printAuthRequired();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (shouldBypassCommander(normalizedArgs)) {
|
|
242
|
+
await runLegacyCliWithErrorHandling(normalizedArgs);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const program = await buildCliProgram({
|
|
247
|
+
invokeLegacy: runLegacyCliWithErrorHandling,
|
|
248
|
+
onlyCommand: normalizedArgs[0],
|
|
249
|
+
});
|
|
250
|
+
await program.parseAsync(["node", "sentinelayer-cli", ...normalizedArgs]);
|
|
251
|
+
}
|
|
252
|
+
|