sentinelayer-cli 0.4.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -18
- package/package.json +7 -6
- package/src/agents/jules/config/definition.js +13 -62
- package/src/agents/jules/config/system-prompt.js +8 -1
- package/src/agents/jules/fix-cycle.js +12 -372
- package/src/agents/jules/loop.js +116 -26
- package/src/agents/jules/pulse.js +10 -327
- package/src/agents/jules/stream.js +13 -12
- package/src/agents/jules/swarm/orchestrator.js +3 -3
- package/src/agents/jules/swarm/sub-agent.js +6 -3
- package/src/agents/jules/tools/aidenid-email.js +189 -0
- package/src/agents/jules/tools/auth-audit.js +1187 -45
- package/src/agents/jules/tools/dispatch.js +25 -12
- 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/glob.js +2 -168
- package/src/agents/jules/tools/grep.js +2 -228
- package/src/agents/jules/tools/path-guards.js +2 -161
- package/src/agents/jules/tools/runtime-audit.js +6 -2
- package/src/agents/jules/tools/shell.js +2 -383
- package/src/agents/persona-visuals.js +64 -0
- package/src/agents/shared-tools/dispatch-core.js +320 -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 +56 -7
- package/src/ai/client.js +45 -0
- package/src/ai/proxy.js +137 -0
- package/src/auth/gate.js +290 -16
- package/src/auth/http.js +450 -39
- package/src/auth/service.js +262 -47
- package/src/auth/session-store.js +475 -21
- package/src/cli.js +5 -0
- package/src/commands/audit.js +13 -8
- package/src/commands/auth.js +53 -9
- package/src/commands/omargate.js +10 -2
- package/src/commands/scan.js +10 -4
- package/src/commands/session.js +590 -0
- package/src/commands/spec.js +62 -0
- package/src/commands/watch.js +3 -2
- package/src/daemon/assignment-ledger.js +196 -0
- package/src/daemon/error-worker.js +599 -16
- package/src/daemon/fix-cycle.js +384 -0
- package/src/daemon/ingest-refresh.js +10 -9
- package/src/daemon/jira-lifecycle.js +135 -0
- package/src/daemon/pulse.js +327 -0
- package/src/daemon/scope-engine.js +1068 -0
- package/src/events/schema.js +190 -0
- package/src/interactive/index.js +18 -16
- package/src/legacy-cli.js +606 -37
- package/src/prompt/generator.js +19 -1
- package/src/review/ai-review.js +11 -1
- package/src/review/local-review.js +75 -19
- package/src/review/omargate-interactive.js +68 -0
- package/src/review/omargate-orchestrator.js +404 -0
- package/src/review/persona-prompts.js +296 -0
- package/src/review/scan-modes.js +48 -0
- package/src/scan/generator.js +1 -1
- package/src/session/agent-registry.js +352 -0
- package/src/session/daemon.js +801 -0
- package/src/session/paths.js +33 -0
- package/src/session/runtime-bridge.js +739 -0
- package/src/session/store.js +388 -0
- package/src/session/stream.js +325 -0
- package/src/spec/generator.js +100 -0
- package/src/telemetry/session-tracker.js +148 -32
- package/src/telemetry/sync.js +6 -2
- package/src/ui/command-hints.js +13 -0
package/src/commands/auth.js
CHANGED
|
@@ -14,6 +14,10 @@ import {
|
|
|
14
14
|
} from "../auth/service.js";
|
|
15
15
|
import { resolveCredentialsFilePath } from "../auth/session-store.js";
|
|
16
16
|
import { CLI_VERSION } from "../legacy-cli.js";
|
|
17
|
+
import { authLoginHint } from "../ui/command-hints.js";
|
|
18
|
+
|
|
19
|
+
const AUTH_DEBUG_ENV = "SENTINELAYER_DEBUG_ERRORS";
|
|
20
|
+
const AUTH_UNMASK_REQUEST_IDS_ENV = "SENTINELAYER_UNMASK_REQUEST_IDS";
|
|
17
21
|
|
|
18
22
|
function shouldEmitJson(options, command) {
|
|
19
23
|
const local = Boolean(options && options.json);
|
|
@@ -53,12 +57,39 @@ function formatApiError(error) {
|
|
|
53
57
|
if (!(error instanceof SentinelayerApiError)) {
|
|
54
58
|
return error instanceof Error ? error.message : String(error || "Unknown error");
|
|
55
59
|
}
|
|
56
|
-
const
|
|
60
|
+
const requestIdValue = error.requestId
|
|
61
|
+
? (shouldExposeSensitiveAuthInfo() ? error.requestId : maskIdentifier(error.requestId))
|
|
62
|
+
: "";
|
|
63
|
+
const requestId = requestIdValue ? ` request_id=${requestIdValue}` : "";
|
|
57
64
|
return `${error.message} [${error.code}] status=${error.status}${requestId}`;
|
|
58
65
|
}
|
|
59
66
|
|
|
67
|
+
function shouldExposeSensitiveAuthInfo() {
|
|
68
|
+
const normalized = String(process.env[AUTH_DEBUG_ENV] || "").trim().toLowerCase();
|
|
69
|
+
const unmask = String(process.env[AUTH_UNMASK_REQUEST_IDS_ENV] || "").trim().toLowerCase();
|
|
70
|
+
const isTty = Boolean(process.stdout && process.stdout.isTTY);
|
|
71
|
+
const nodeEnv = String(process.env.NODE_ENV || "").trim().toLowerCase();
|
|
72
|
+
const isDev = nodeEnv === "development";
|
|
73
|
+
const debugEnabled = normalized === "true" || normalized === "1" || normalized === "yes";
|
|
74
|
+
const unmaskEnabled = unmask === "true" || unmask === "1" || unmask === "yes";
|
|
75
|
+
return debugEnabled && unmaskEnabled && isTty && isDev;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function shouldRevealTokenIdentifiers() {
|
|
79
|
+
return shouldExposeSensitiveAuthInfo();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function maskIdentifier(value) {
|
|
83
|
+
const raw = String(value || "").trim();
|
|
84
|
+
if (!raw) return "";
|
|
85
|
+
if (raw.length <= 6) {
|
|
86
|
+
return `${raw.slice(0, 2)}…`;
|
|
87
|
+
}
|
|
88
|
+
return `${raw.slice(0, 4)}…${raw.slice(-2)}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
60
91
|
function printAuthHint() {
|
|
61
|
-
console.log(pc.gray(
|
|
92
|
+
console.log(pc.gray(`Run \`${authLoginHint()}\` to create a persistent CLI session.`));
|
|
62
93
|
}
|
|
63
94
|
|
|
64
95
|
export function registerAuthCommand(program) {
|
|
@@ -192,10 +223,16 @@ export function registerAuthCommand(program) {
|
|
|
192
223
|
const displayUser = status.remoteUser || status.user || {};
|
|
193
224
|
console.log(pc.green(`Authenticated as ${renderUserSummary(displayUser)}`));
|
|
194
225
|
|
|
195
|
-
if (status.aidenid && status.aidenid.orgId) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
226
|
+
if (status.aidenid && (status.aidenid.orgId || status.aidenid.projectId)) {
|
|
227
|
+
if (shouldExposeSensitiveAuthInfo()) {
|
|
228
|
+
const orgDisplay = status.aidenid.orgId ? maskIdentifier(status.aidenid.orgId) : "unknown";
|
|
229
|
+
const projectDisplay = status.aidenid.projectId ? maskIdentifier(status.aidenid.projectId) : "unknown";
|
|
230
|
+
console.log(pc.green(`AIdenID: provisioned (org: ${orgDisplay}, project: ${projectDisplay})`));
|
|
231
|
+
if (status.aidenid.apiKeyPrefix) {
|
|
232
|
+
console.log(pc.gray(` API key prefix: ${maskIdentifier(status.aidenid.apiKeyPrefix)}`));
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
console.log(pc.green("AIdenID: provisioned"));
|
|
199
236
|
}
|
|
200
237
|
} else {
|
|
201
238
|
console.log(pc.gray("AIdenID: not provisioned (will provision on next login)"));
|
|
@@ -205,10 +242,15 @@ export function registerAuthCommand(program) {
|
|
|
205
242
|
|
|
206
243
|
if (status.remoteError) {
|
|
207
244
|
console.log(pc.red(`Remote validation failed: ${status.remoteError.message}`));
|
|
245
|
+
const requestIdValue = status.remoteError.requestId
|
|
246
|
+
? (shouldExposeSensitiveAuthInfo()
|
|
247
|
+
? status.remoteError.requestId
|
|
248
|
+
: maskIdentifier(status.remoteError.requestId))
|
|
249
|
+
: "";
|
|
208
250
|
console.log(
|
|
209
251
|
pc.gray(
|
|
210
252
|
`Error code: ${status.remoteError.code} status=${status.remoteError.status}${
|
|
211
|
-
|
|
253
|
+
requestIdValue ? ` request_id=${requestIdValue}` : ""
|
|
212
254
|
}`
|
|
213
255
|
)
|
|
214
256
|
);
|
|
@@ -260,7 +302,8 @@ export function registerAuthCommand(program) {
|
|
|
260
302
|
`${renderUserSummary(session.user)} | source=${session.source} | storage=${session.storage || "unknown"}`
|
|
261
303
|
);
|
|
262
304
|
if (session.tokenId) {
|
|
263
|
-
|
|
305
|
+
const tokenDisplay = shouldRevealTokenIdentifiers() ? session.tokenId : maskIdentifier(session.tokenId);
|
|
306
|
+
console.log(pc.gray(` token_id: ${tokenDisplay}`));
|
|
264
307
|
}
|
|
265
308
|
if (session.tokenExpiresAt) {
|
|
266
309
|
console.log(pc.gray(` expires_at: ${session.tokenExpiresAt}`));
|
|
@@ -303,7 +346,8 @@ export function registerAuthCommand(program) {
|
|
|
303
346
|
return;
|
|
304
347
|
}
|
|
305
348
|
|
|
306
|
-
|
|
349
|
+
const tokenDisplay = shouldRevealTokenIdentifiers() ? result.tokenId : maskIdentifier(result.tokenId);
|
|
350
|
+
console.log(pc.green(`Revoked token: ${tokenDisplay}`));
|
|
307
351
|
console.log(pc.gray(`API: ${result.apiUrl}`));
|
|
308
352
|
if (result.matchedStoredSession) {
|
|
309
353
|
console.log(
|
package/src/commands/omargate.js
CHANGED
|
@@ -3,13 +3,21 @@ import { buildLegacyArgs } from "./legacy-args.js";
|
|
|
3
3
|
export function registerOmarGateCommand(program, invokeLegacy) {
|
|
4
4
|
const omargate = program
|
|
5
5
|
.command("omargate")
|
|
6
|
-
.description("Run local Omar Gate
|
|
6
|
+
.description("Run local Omar Gate security analysis (deterministic + AI persona swarm)");
|
|
7
7
|
|
|
8
8
|
omargate
|
|
9
9
|
.command("deep")
|
|
10
|
-
.description("Run
|
|
10
|
+
.description("Run full Omar Gate deep scan with 22-rule deterministic + multi-persona AI analysis")
|
|
11
11
|
.option("--path <path>", "Target repository path")
|
|
12
12
|
.option("--output-dir <path>", "Artifact root for report output")
|
|
13
|
+
.option("--no-ai", "Skip AI review layer (deterministic only)")
|
|
14
|
+
.option("--ai-dry-run", "Run AI layer in dry-run mode (no LLM call)")
|
|
15
|
+
.option("--scan-mode <mode>", "Scan depth: baseline (1 persona), deep (6), full-depth (13)")
|
|
16
|
+
.option("--max-parallel <n>", "Max concurrent persona calls (default: 4)")
|
|
17
|
+
.option("--model <id>", "LLM model override (default: gpt-5.3-codex)")
|
|
18
|
+
.option("--provider <name>", "LLM provider: sentinelayer, openai, anthropic, google")
|
|
19
|
+
.option("--max-cost <usd>", "Maximum AI layer cost in USD (default: 5.0)")
|
|
20
|
+
.option("--stream", "Emit NDJSON events to stdout as personas run")
|
|
13
21
|
.option("--json", "Emit machine-readable output")
|
|
14
22
|
.action(async (options, command) => {
|
|
15
23
|
const legacyArgs = buildLegacyArgs(["/omargate", "deep"], {
|
package/src/commands/scan.js
CHANGED
|
@@ -30,7 +30,8 @@ import {
|
|
|
30
30
|
} from "../scan/generator.js";
|
|
31
31
|
import { detectRepoSlug, setupSecrets } from "../scan/gh-secrets.js";
|
|
32
32
|
import { appendRunEvent, deriveStopClassFromBudget } from "../telemetry/ledger.js";
|
|
33
|
-
import {
|
|
33
|
+
import { resolveActiveAuthSession } from "../auth/service.js";
|
|
34
|
+
import { authLoginHint } from "../ui/command-hints.js";
|
|
34
35
|
|
|
35
36
|
const LEGACY_SCAN_WORKFLOW_PATH = ".github/workflows/security-review.yml";
|
|
36
37
|
|
|
@@ -832,16 +833,21 @@ export function registerScanCommand(program) {
|
|
|
832
833
|
|
|
833
834
|
let tokenValue = "";
|
|
834
835
|
try {
|
|
835
|
-
const session = await
|
|
836
|
+
const session = await resolveActiveAuthSession({
|
|
837
|
+
cwd: targetPath,
|
|
838
|
+
env: process.env,
|
|
839
|
+
autoRotate: false,
|
|
840
|
+
});
|
|
836
841
|
if (session && session.token) {
|
|
837
842
|
tokenValue = session.token;
|
|
838
843
|
}
|
|
839
844
|
} catch {
|
|
840
|
-
/* no
|
|
845
|
+
/* no active auth session */
|
|
841
846
|
}
|
|
842
847
|
|
|
843
848
|
if (!tokenValue) {
|
|
844
|
-
const msg =
|
|
849
|
+
const msg =
|
|
850
|
+
`No SentinelLayer token found. Run '${authLoginHint()}', set SENTINELAYER_TOKEN, or use --dry-run for instructions.`;
|
|
845
851
|
if (emitJson) {
|
|
846
852
|
console.log(JSON.stringify({ command: "scan setup-secrets", ok: false, reason: msg }, null, 2));
|
|
847
853
|
} else {
|