sentinelayer-cli 0.4.4 → 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
|
@@ -1,118 +1,234 @@
|
|
|
1
|
-
import pc from "picocolors";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Session Tracker — tracks tokens, tool calls, cost, and time per CLI run.
|
|
7
|
+
*
|
|
8
|
+
* Inspired by src/bootstrap/state.ts and src/cost-tracker.ts patterns:
|
|
9
|
+
* - Single global session state initialized once
|
|
10
|
+
* - Accumulator functions for each metric
|
|
11
|
+
* - Summary getter for final report
|
|
12
|
+
* - Print summary on completion
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const SESSIONS = new Map();
|
|
16
|
+
let ACTIVE_SESSION_ID = null;
|
|
17
|
+
const MAX_SESSIONS = 50;
|
|
18
|
+
const SESSION_TTL_MS = 60 * 60 * 1000;
|
|
19
|
+
const VERBOSE_TELEMETRY_ENV = "SENTINELAYER_VERBOSE_TELEMETRY";
|
|
20
|
+
const DEBUG_ERRORS_ENV = "SENTINELAYER_DEBUG_ERRORS";
|
|
21
|
+
const UNMASK_TRACE_ID_ENV = "SENTINELAYER_UNMASK_TRACE_ID";
|
|
22
|
+
const EMIT_TRACE_ID_ENV = "SENTINELAYER_EMIT_TRACE_ID";
|
|
23
|
+
|
|
24
|
+
function isTruthyEnvFlag(value) {
|
|
25
|
+
const normalized = String(value || "").trim().toLowerCase();
|
|
26
|
+
return normalized === "true" || normalized === "1" || normalized === "yes";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function normalizeNonNegativeNumber(value) {
|
|
30
|
+
const normalized = Number(value);
|
|
31
|
+
if (!Number.isFinite(normalized) || normalized < 0) {
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
return normalized;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function resolveSession(sessionId) {
|
|
38
|
+
const resolvedId = String(sessionId || ACTIVE_SESSION_ID || "").trim();
|
|
39
|
+
if (!resolvedId) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return SESSIONS.get(resolvedId) || null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function pruneSessions(now = Date.now()) {
|
|
46
|
+
for (const [sessionId, session] of SESSIONS.entries()) {
|
|
47
|
+
if (!session || !session.startedAt) continue;
|
|
48
|
+
if (now - session.startedAt > SESSION_TTL_MS) {
|
|
49
|
+
SESSIONS.delete(sessionId);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
while (SESSIONS.size > MAX_SESSIONS) {
|
|
53
|
+
const oldestKey = SESSIONS.keys().next().value;
|
|
54
|
+
if (!oldestKey) break;
|
|
55
|
+
SESSIONS.delete(oldestKey);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function shouldExposeTraceId() {
|
|
60
|
+
const verbose = isTruthyEnvFlag(process.env[VERBOSE_TELEMETRY_ENV]);
|
|
61
|
+
const debug = isTruthyEnvFlag(process.env[DEBUG_ERRORS_ENV]);
|
|
62
|
+
if (!verbose && !debug) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (!isTruthyEnvFlag(process.env[UNMASK_TRACE_ID_ENV])) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const nodeEnv = String(process.env.NODE_ENV || "").trim().toLowerCase();
|
|
69
|
+
if (nodeEnv !== "development" && nodeEnv !== "test") {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return Boolean(process.stderr && process.stderr.isTTY);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function shouldEmitTraceId() {
|
|
76
|
+
if (!isTruthyEnvFlag(process.env[EMIT_TRACE_ID_ENV])) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
return Boolean(process.stderr && process.stderr.isTTY);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function maskTraceId(traceId) {
|
|
83
|
+
const normalized = String(traceId || "").trim();
|
|
84
|
+
if (normalized.length <= 8) {
|
|
85
|
+
return "trace_id=****";
|
|
86
|
+
}
|
|
87
|
+
const prefix = normalized.slice(0, 4);
|
|
88
|
+
const suffix = normalized.slice(-4);
|
|
89
|
+
return `trace_id=${prefix}…${suffix}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Initialize a new tracking session.
|
|
94
|
+
* Call this at the start of any auditable command.
|
|
95
|
+
*/
|
|
96
|
+
export function startSession(command) {
|
|
97
|
+
pruneSessions();
|
|
98
|
+
let sessionId;
|
|
99
|
+
try {
|
|
100
|
+
sessionId = crypto.randomUUID();
|
|
101
|
+
} catch {
|
|
102
|
+
const ts = Date.now().toString(36);
|
|
103
|
+
const rand = crypto.randomBytes(16).toString("hex");
|
|
104
|
+
sessionId = `sess-${ts}-${rand}`;
|
|
105
|
+
}
|
|
106
|
+
const session = {
|
|
107
|
+
id: sessionId,
|
|
108
|
+
traceId: sessionId,
|
|
109
|
+
command: command || "unknown",
|
|
110
|
+
startedAt: Date.now(),
|
|
111
|
+
inputTokens: 0,
|
|
112
|
+
outputTokens: 0,
|
|
113
|
+
costUsd: 0,
|
|
114
|
+
toolCalls: 0,
|
|
115
|
+
llmCalls: 0,
|
|
116
|
+
findings: { P0: 0, P1: 0, P2: 0, P3: 0 },
|
|
117
|
+
};
|
|
118
|
+
SESSIONS.set(sessionId, session);
|
|
119
|
+
ACTIVE_SESSION_ID = sessionId;
|
|
120
|
+
return session;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function endSession({ sessionId } = {}) {
|
|
124
|
+
const resolvedId = String(sessionId || ACTIVE_SESSION_ID || "").trim();
|
|
125
|
+
if (!resolvedId) return false;
|
|
126
|
+
const existed = SESSIONS.delete(resolvedId);
|
|
127
|
+
if (ACTIVE_SESSION_ID === resolvedId) {
|
|
128
|
+
ACTIVE_SESSION_ID = null;
|
|
129
|
+
}
|
|
130
|
+
return existed;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Record token usage from an LLM call.
|
|
135
|
+
*/
|
|
136
|
+
export function recordLlmUsage({ inputTokens = 0, outputTokens = 0, costUsd = 0, sessionId } = {}) {
|
|
137
|
+
const session = resolveSession(sessionId);
|
|
138
|
+
if (!session) return;
|
|
139
|
+
const safeInput = normalizeNonNegativeNumber(inputTokens);
|
|
140
|
+
const safeOutput = normalizeNonNegativeNumber(outputTokens);
|
|
141
|
+
const safeCost = normalizeNonNegativeNumber(costUsd);
|
|
142
|
+
session.inputTokens += safeInput;
|
|
143
|
+
session.outputTokens += safeOutput;
|
|
144
|
+
session.costUsd += safeCost;
|
|
145
|
+
session.llmCalls += 1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Record a tool call.
|
|
150
|
+
*/
|
|
151
|
+
export function recordToolCall({ sessionId } = {}) {
|
|
152
|
+
const session = resolveSession(sessionId);
|
|
153
|
+
if (!session) return;
|
|
154
|
+
session.toolCalls += 1;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Record findings.
|
|
159
|
+
*/
|
|
160
|
+
export function recordFindings(summary, { sessionId } = {}) {
|
|
161
|
+
const session = resolveSession(sessionId);
|
|
162
|
+
if (!session) return;
|
|
163
|
+
const p0 = normalizeNonNegativeNumber(summary?.P0);
|
|
164
|
+
const p1 = normalizeNonNegativeNumber(summary?.P1);
|
|
165
|
+
const p2 = normalizeNonNegativeNumber(summary?.P2);
|
|
166
|
+
const p3 = normalizeNonNegativeNumber(summary?.P3);
|
|
167
|
+
if (p0) session.findings.P0 += p0;
|
|
168
|
+
if (p1) session.findings.P1 += p1;
|
|
169
|
+
if (p2) session.findings.P2 += p2;
|
|
170
|
+
if (p3) session.findings.P3 += p3;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get the current session summary.
|
|
175
|
+
*/
|
|
176
|
+
export function getSessionSummary({ sessionId } = {}) {
|
|
177
|
+
const session = resolveSession(sessionId);
|
|
178
|
+
if (!session) return null;
|
|
179
|
+
const durationMs = Date.now() - session.startedAt;
|
|
180
|
+
return {
|
|
181
|
+
traceId: session.traceId || session.id,
|
|
182
|
+
command: session.command,
|
|
183
|
+
durationMs,
|
|
184
|
+
inputTokens: session.inputTokens,
|
|
185
|
+
outputTokens: session.outputTokens,
|
|
186
|
+
totalTokens: session.inputTokens + session.outputTokens,
|
|
187
|
+
costUsd: session.costUsd,
|
|
188
|
+
toolCalls: session.toolCalls,
|
|
189
|
+
llmCalls: session.llmCalls,
|
|
190
|
+
findings: { ...session.findings },
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Print the session summary to stderr.
|
|
196
|
+
* Called at the end of any auditable command.
|
|
197
|
+
*/
|
|
198
|
+
export function printSessionSummary({ sessionId } = {}) {
|
|
199
|
+
const summary = getSessionSummary({ sessionId });
|
|
200
|
+
if (!summary) return;
|
|
201
|
+
|
|
202
|
+
const duration = summary.durationMs < 60000
|
|
203
|
+
? (summary.durationMs / 1000).toFixed(1) + "s"
|
|
204
|
+
: (summary.durationMs / 60000).toFixed(1) + "m";
|
|
205
|
+
|
|
206
|
+
const tokens = summary.totalTokens > 1000
|
|
207
|
+
? (summary.totalTokens / 1000).toFixed(1) + "K"
|
|
208
|
+
: String(summary.totalTokens);
|
|
209
|
+
|
|
210
|
+
const parts = [];
|
|
211
|
+
parts.push(pc.gray("Run complete:"));
|
|
212
|
+
parts.push(pc.white(tokens + " tokens"));
|
|
213
|
+
parts.push(pc.white(summary.toolCalls + " tools"));
|
|
214
|
+
if (summary.costUsd > 0) parts.push(pc.white("$" + summary.costUsd.toFixed(2)));
|
|
215
|
+
parts.push(pc.white(duration));
|
|
216
|
+
if (summary.traceId && shouldEmitTraceId()) {
|
|
217
|
+
const traceLabel = shouldExposeTraceId() ? `trace_id=${summary.traceId}` : maskTraceId(summary.traceId);
|
|
218
|
+
parts.push(pc.gray(traceLabel));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const findingParts = [];
|
|
222
|
+
if (summary.findings.P0 > 0) findingParts.push(pc.red("P0=" + summary.findings.P0));
|
|
223
|
+
if (summary.findings.P1 > 0) findingParts.push(pc.yellow("P1=" + summary.findings.P1));
|
|
224
|
+
if (summary.findings.P2 > 0) findingParts.push(pc.cyan("P2=" + summary.findings.P2));
|
|
225
|
+
if (summary.findings.P3 > 0) findingParts.push(pc.gray("P3=" + summary.findings.P3));
|
|
226
|
+
|
|
227
|
+
process.stderr.write("\n" + parts.join(" · "));
|
|
228
|
+
if (findingParts.length > 0) {
|
|
229
|
+
process.stderr.write(" | " + findingParts.join(" "));
|
|
230
|
+
}
|
|
231
|
+
process.stderr.write("\n");
|
|
232
|
+
endSession({ sessionId });
|
|
233
|
+
return summary;
|
|
234
|
+
}
|