fix: resolve all biome warnings and formatting issues

- Remove unnecessary non-null assertions where values are guaranteed
- Replace array index access with .at() for safer element retrieval
- Use local variables to avoid repeated process.env lookups
- Replace any types with unknown in functional utilities
- Use nullish coalescing for TOTP hash byte access
- Auto-format security patches to match biome config
This commit is contained in:
ezl-keygraph
2026-03-15 00:54:40 +05:30
parent 181f24cfcc
commit 53b4c6b83f
9 changed files with 36 additions and 33 deletions
+2 -2
View File
@@ -219,9 +219,9 @@ async function setupRouter(): Promise<ShannonConfig> {
const router: ShannonConfig['router'] = { default: defaultModel };
if (routerProvider === 'openai') {
router!.openai_key = apiKey;
router.openai_key = apiKey;
} else {
router!.openrouter_key = apiKey;
router.openrouter_key = apiKey;
}
return { router };
+3 -6
View File
@@ -65,11 +65,8 @@ export function start(args: StartArgs): void {
const containerName = `shannon-worker-${suffix}`;
// 8. Generate workspace name if not provided
let workspace = args.workspace;
if (!workspace) {
const hostname = new URL(args.url).hostname.replace(/[^a-zA-Z0-9-]/g, '-');
workspace = `${hostname}_shannon-${Date.now()}`;
}
const workspace =
args.workspace ?? `${new URL(args.url).hostname.replace(/[^a-zA-Z0-9-]/g, '-')}_shannon-${Date.now()}`;
// 9. Resolve credentials
const credentialsDir = getCredentialsDir();
@@ -142,7 +139,7 @@ export function start(args: StartArgs): void {
// Clear waiting line and show info
process.stdout.write('\r\x1b[K');
printInfo(args, useRouter, workspace!, workflowId, repo.hostPath, workspacesDir);
printInfo(args, useRouter, workspace, workflowId, repo.hostPath, workspacesDir);
return;
}
} catch {
+10 -5
View File
@@ -88,7 +88,10 @@ function buildMcpServers(
// NOTE: Explicit allowlist — the Playwright MCP subprocess must not inherit
// secrets (API keys, AWS tokens) from the parent process.
const MCP_ENV_ALLOWLIST = [
'PATH', 'HOME', 'NODE_PATH', 'DISPLAY',
'PATH',
'HOME',
'NODE_PATH',
'DISPLAY',
'PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH',
] as const;
@@ -98,8 +101,9 @@ function buildMcpServers(
};
for (const key of MCP_ENV_ALLOWLIST) {
if (process.env[key]) {
envVars[key] = process.env[key]!;
const val = process.env[key];
if (val) {
envVars[key] = val;
}
}
@@ -252,8 +256,9 @@ export async function runClaudePrompt(
'ANTHROPIC_LARGE_MODEL',
];
for (const name of passthroughVars) {
if (process.env[name]) {
sdkEnv[name] = process.env[name]!;
const val = process.env[name];
if (val) {
sdkEnv[name] = val;
}
}
+4 -4
View File
@@ -89,14 +89,14 @@ function summarizeTodoUpdate(input: ToolCallInput | undefined): string | null {
const inProgress = todos.filter((t) => t.status === 'in_progress');
// Show recently completed tasks
if (completed.length > 0) {
const recent = completed[completed.length - 1]!;
const recent = completed.at(-1);
if (recent) {
return `${recent.content}`;
}
// Show current in-progress task
if (inProgress.length > 0) {
const current = inProgress[0]!;
const current = inProgress.at(0);
if (current) {
return `🔄 ${current.content}`;
}
+1
View File
@@ -336,6 +336,7 @@ export class MetricsTracker {
// Calculate metrics per phase
const phaseMetrics: Record<string, PhaseMetrics> = {};
// biome-ignore lint/style/noNonNullAssertion: called from recalculateAggregations which guards this.data
const totalDuration = this.data!.metrics.total_duration_ms;
for (const [phaseName, agentList] of Object.entries(phases)) {
+7 -8
View File
@@ -37,7 +37,7 @@ async function buildLoginInstructions(authentication: Authentication, logger: Ac
const getSection = (content: string, sectionName: string): string => {
const regex = new RegExp(`<!-- BEGIN:${sectionName} -->([\\s\\S]*?)<!-- END:${sectionName} -->`, 'g');
const match = regex.exec(content);
return match ? match[1]!.trim() : '';
return match?.[1]?.trim() ?? '';
};
// 2. Extract sections based on login type
@@ -101,14 +101,13 @@ async function processIncludes(content: string, baseDir: string): Promise<string
const replacements: IncludeReplacement[] = await Promise.all(
Array.from(content.matchAll(includeRegex)).map(async (match) => {
const includePath = path.resolve(baseDir, match[1]!);
const rawPath = match[1] ?? '';
const includePath = path.resolve(baseDir, rawPath);
if (!includePath.startsWith(resolvedBase + path.sep) && includePath !== resolvedBase) {
throw new PentestError(
`Path traversal detected in @include(): ${match[1]}`,
'prompt',
false,
{ includePath, baseDir: resolvedBase },
);
throw new PentestError(`Path traversal detected in @include(): ${rawPath}`, 'prompt', false, {
includePath,
baseDir: resolvedBase,
});
}
const sharedContent = await fs.readFile(includePath, 'utf8');
return {
+1 -1
View File
@@ -243,7 +243,7 @@ const validateQueueContent = async (
return Object.freeze({
...pathsWithExistence,
queueData: queueValidation.data!,
queueData: queueValidation.data as QueueData,
});
} catch (readError) {
return {
+1 -1
View File
@@ -10,7 +10,7 @@
* Generic functional composition patterns for async operations.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// biome-ignore lint/suspicious/noExplicitAny: pipeline functions need flexible typing for composition
type PipelineFunction = (x: any) => any | Promise<any>;
/**
@@ -48,13 +48,14 @@ function generateHOTP(secret: string, counter: number, digits: number = 6): stri
hmac.update(counterBuffer);
const hash = hmac.digest();
// Dynamic truncation
const offset = hash[hash.length - 1]! & 0x0f;
// Dynamic truncation (SHA-1 always produces 20 bytes)
const lastByte = hash[hash.length - 1] ?? 0;
const offset = lastByte & 0x0f;
const code =
((hash[offset]! & 0x7f) << 24) |
((hash[offset + 1]! & 0xff) << 16) |
((hash[offset + 2]! & 0xff) << 8) |
(hash[offset + 3]! & 0xff);
(((hash[offset] ?? 0) & 0x7f) << 24) |
(((hash[offset + 1] ?? 0) & 0xff) << 16) |
(((hash[offset + 2] ?? 0) & 0xff) << 8) |
((hash[offset + 3] ?? 0) & 0xff);
// Generate digits
const otp = (code % 10 ** digits).toString().padStart(digits, '0');