auditor-lambda 0.6.4 → 0.6.5
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/dist/cli/dispatch.d.ts +2 -1
- package/dist/cli/dispatch.js +12 -2
- package/dist/cli.js +17 -5
- package/dist/providers/index.js +10 -3
- package/package.json +1 -1
- package/scripts/postinstall.mjs +43 -0
package/dist/cli/dispatch.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionConfig, DispatchModelHint } from "@audit-tools/shared";
|
|
1
|
+
import type { ProviderRateLimits, SessionConfig, DispatchModelHint } from "@audit-tools/shared";
|
|
2
2
|
import type { ArtifactBundle } from "../io/artifacts.js";
|
|
3
3
|
import type { AuditTask } from "../types.js";
|
|
4
4
|
export declare const LARGE_FILE_PACKET_TARGET_LINES = 2500;
|
|
@@ -76,5 +76,6 @@ export declare function prepareDispatchArtifacts(params: {
|
|
|
76
76
|
root?: string;
|
|
77
77
|
sessionConfig?: SessionConfig;
|
|
78
78
|
hostModel?: string | null;
|
|
79
|
+
queryLimits?: (model: string | null) => Promise<ProviderRateLimits | null>;
|
|
79
80
|
hostActiveSubagentLimit?: number | null;
|
|
80
81
|
}): Promise<PrepareDispatchResult>;
|
package/dist/cli/dispatch.js
CHANGED
|
@@ -2,12 +2,13 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
4
4
|
import { isFileMissingError, readJsonFile, writeJsonFile } from "@audit-tools/shared";
|
|
5
|
+
import { buildQuotaSource } from "@audit-tools/shared/quota/compositeQuotaSource";
|
|
5
6
|
import { loadArtifactBundle } from "../io/artifacts.js";
|
|
6
7
|
import { orderTasksForPacketReview, buildReviewPackets, sizeIndexFromManifest, } from "../orchestrator/reviewPackets.js";
|
|
7
8
|
import { buildFileAnchorSummary } from "../orchestrator/fileAnchors.js";
|
|
8
9
|
import { resolveFreshSessionProviderName } from "../providers/index.js";
|
|
9
10
|
import { loadSessionConfig } from "../supervisor/sessionConfig.js";
|
|
10
|
-
import { scheduleWave, buildProviderModelKey, readQuotaState, resolveHostActiveSubagentLimit, lookupDiscoveredLimits, } from "../quota/index.js";
|
|
11
|
+
import { scheduleWave, buildProviderModelKey, readQuotaState, resolveHostActiveSubagentLimit, lookupDiscoveredLimits, mergeDiscoveredLimits, } from "../quota/index.js";
|
|
11
12
|
import { taskResultPath, packetPromptPath, artifactNameForId, toBase64Url, fromBase64Url, getFlag, } from "./args.js";
|
|
12
13
|
export const LARGE_FILE_PACKET_TARGET_LINES = 2500;
|
|
13
14
|
export const SMALL_MODEL_HINT_MAX_LINES = 500;
|
|
@@ -462,7 +463,15 @@ export async function prepareDispatchArtifacts(params) {
|
|
|
462
463
|
explicitLimit: params.hostActiveSubagentLimit,
|
|
463
464
|
sessionConfig,
|
|
464
465
|
});
|
|
466
|
+
const providerLimits = await params.queryLimits?.(hostModel)
|
|
467
|
+
.then((r) => r ? { ...r, source: "provider_query" } : null)
|
|
468
|
+
.catch(() => null)
|
|
469
|
+
?? null;
|
|
465
470
|
const dispatchCachedLimits = await lookupDiscoveredLimits(quotaProviderKey).catch(() => null);
|
|
471
|
+
const discoveredLimits = mergeDiscoveredLimits(providerLimits, dispatchCachedLimits);
|
|
472
|
+
const halfLifeHours = sessionConfig.quota?.empirical_half_life_hours ?? 24;
|
|
473
|
+
const quotaSource = buildQuotaSource({ halfLifeHours });
|
|
474
|
+
const quotaSourceSnapshot = await quotaSource.queryCurrentUsage(quotaProviderKey).catch(() => null);
|
|
466
475
|
const waveSchedule = scheduleWave({
|
|
467
476
|
providerName: quotaProviderName,
|
|
468
477
|
sessionConfig,
|
|
@@ -471,7 +480,8 @@ export async function prepareDispatchArtifacts(params) {
|
|
|
471
480
|
estimatedSlotTokens: perPacketTokens,
|
|
472
481
|
quotaStateEntry,
|
|
473
482
|
hostConcurrencyLimit,
|
|
474
|
-
discoveredLimits
|
|
483
|
+
discoveredLimits,
|
|
484
|
+
quotaSourceSnapshot,
|
|
475
485
|
});
|
|
476
486
|
const dispatchQuota = {
|
|
477
487
|
contract_version: "audit-code-dispatch-quota/v1alpha2",
|
package/dist/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import { buildRuntimeValidationTasks, } from "./orchestrator/runtimeValidation.j
|
|
|
12
12
|
import { initializeCoverageFromPlan } from "./orchestrator/planning.js";
|
|
13
13
|
import { loadArtifactBundle, writeCoreArtifacts, promoteFinalAuditReport, AUDIT_REPORT_FILENAME, } from "./io/artifacts.js";
|
|
14
14
|
import { isFileMissingError, readJsonFile, writeJsonFile, prefixValidationIssues, RunLogger } from "@audit-tools/shared";
|
|
15
|
+
import { buildQuotaSource } from "@audit-tools/shared/quota/compositeQuotaSource";
|
|
15
16
|
import { validateArtifactBundle } from "./validation/artifacts.js";
|
|
16
17
|
import { validateAuditResults, formatAuditResultIssues, } from "./validation/auditResults.js";
|
|
17
18
|
import { validateConfiguredProviderEnvironment, validateSessionConfig, } from "./validation/sessionConfig.js";
|
|
@@ -35,7 +36,7 @@ import { renderWorkerPrompt } from "./prompts/renderWorkerPrompt.js";
|
|
|
35
36
|
import { estimateTaskGroupTokens, sizeIndexFromManifest, } from "./orchestrator/reviewPackets.js";
|
|
36
37
|
import { LOCAL_SUBPROCESS_PROVIDER_NAME } from "./providers/constants.js";
|
|
37
38
|
import { runAuditCodeMcpServer } from "./mcp/server.js";
|
|
38
|
-
import { scheduleWave, buildProviderModelKey, readQuotaState, recordWaveOutcome, resolveLimits, resolveHostActiveSubagentLimit, probeProvider, computeMaxSafeConcurrency, getQuotaStatePath, detectRateLimitError, computeCooldownUntil, runSlidingWindow,
|
|
39
|
+
import { scheduleWave, buildProviderModelKey, readQuotaState, recordWaveOutcome, resolveLimits, resolveHostActiveSubagentLimit, probeProvider, computeMaxSafeConcurrency, getQuotaStatePath, detectRateLimitError, computeCooldownUntil, runSlidingWindow, lookupDiscoveredLimits, updateDiscoveredLimits, mergeDiscoveredLimits, getHeaderExtractorForProvider, setQuotaStateDir, } from "./quota/index.js";
|
|
39
40
|
// Re-exports from extracted modules
|
|
40
41
|
export { resolveHostDispatchCapability, DIRECT_CLI_DEFAULTS, getFlag, hasFlag, getOptionalBooleanFlag, getArtifactsDir, getRootDir, getBatchResultsDir, getMaxRuns, getAgentBatchSize, getParallelWorkers, getTimeoutMs, chunkArray, getUiMode, looksLikeCliFlag, countLines, warnIfNotGitRepo, } from "./cli/args.js";
|
|
41
42
|
import { DIRECT_CLI_DEFAULTS, getFlag, hasFlag, getOptionalBooleanFlag, fromBase64Url, renderCommand, summarizeLaunchExit, taskResultPath, readStdinText, getArtifactsDir, getRootDir, warnIfNotGitRepo, getBatchResultsDir, getMaxRuns, getAgentBatchSize, getParallelWorkers, getTimeoutMs, getExplicitProvider, getHostModel, getHostMaxActiveSubagents, getQuotaProbeMode, resolveRunProviderName, chunkArray, getUiMode, looksLikeCliFlag, resolveHostDispatchCapability, countLines, listBatchResultFiles, } from "./cli/args.js";
|
|
@@ -915,11 +916,16 @@ async function renderSemanticReviewStep(params) {
|
|
|
915
916
|
},
|
|
916
917
|
});
|
|
917
918
|
}
|
|
919
|
+
const sessionConfig = await loadSessionConfig(artifactsDir).catch(() => ({}));
|
|
920
|
+
const provider = createFreshSessionProvider(undefined, sessionConfig);
|
|
918
921
|
const dispatch = await prepareDispatchArtifacts({
|
|
919
922
|
packageRoot,
|
|
920
923
|
runId: activeReviewRun.run_id,
|
|
921
924
|
artifactsDir,
|
|
922
925
|
root,
|
|
926
|
+
sessionConfig,
|
|
927
|
+
hostModel: sessionConfig.block_quota?.host_model ?? null,
|
|
928
|
+
queryLimits: provider.queryLimits?.bind(provider),
|
|
923
929
|
hostActiveSubagentLimit: params.hostMaxActiveSubagents,
|
|
924
930
|
});
|
|
925
931
|
const mergeCommand = mergeAndIngestCommand(artifactsDir, activeReviewRun.run_id);
|
|
@@ -1473,7 +1479,7 @@ async function cmdRunToCompletion(argv) {
|
|
|
1473
1479
|
const cachedLimits = await lookupDiscoveredLimits(providerModelKey).catch(() => null);
|
|
1474
1480
|
const discoveredLimits = mergeDiscoveredLimits(providerLimits, cachedLimits);
|
|
1475
1481
|
const halfLifeHours = sessionConfig.quota?.empirical_half_life_hours ?? 24;
|
|
1476
|
-
const quotaSource =
|
|
1482
|
+
const quotaSource = buildQuotaSource({ halfLifeHours });
|
|
1477
1483
|
const quotaSourceSnapshot = await quotaSource.queryCurrentUsage(providerModelKey).catch(() => null);
|
|
1478
1484
|
const hostConcurrencyLimit = resolveHostActiveSubagentLimit({
|
|
1479
1485
|
sessionConfig,
|
|
@@ -2155,12 +2161,18 @@ async function cmdPrepareDispatch(argv) {
|
|
|
2155
2161
|
const runId = getFlag(argv, "--run-id");
|
|
2156
2162
|
if (!runId)
|
|
2157
2163
|
throw new Error("prepare-dispatch requires --run-id <run_id>");
|
|
2164
|
+
const artifactsDir = getArtifactsDir(argv);
|
|
2165
|
+
const sessionConfig = await loadSessionConfig(artifactsDir).catch(() => ({}));
|
|
2166
|
+
const provider = createFreshSessionProvider(getExplicitProvider(argv), sessionConfig);
|
|
2167
|
+
const hostModel = getHostModel(argv) ?? sessionConfig.block_quota?.host_model ?? null;
|
|
2158
2168
|
const result = await prepareDispatchArtifacts({
|
|
2159
2169
|
packageRoot,
|
|
2160
2170
|
runId,
|
|
2161
|
-
artifactsDir
|
|
2171
|
+
artifactsDir,
|
|
2162
2172
|
root: getFlag(argv, "--root") ? getRootDir(argv) : undefined,
|
|
2163
|
-
|
|
2173
|
+
sessionConfig,
|
|
2174
|
+
hostModel,
|
|
2175
|
+
queryLimits: provider.queryLimits?.bind(provider),
|
|
2164
2176
|
hostActiveSubagentLimit: getHostMaxActiveSubagents(argv),
|
|
2165
2177
|
});
|
|
2166
2178
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -2958,7 +2970,7 @@ async function cmdQuota(argv) {
|
|
|
2958
2970
|
explicitLimit: getHostMaxActiveSubagents(argv),
|
|
2959
2971
|
sessionConfig,
|
|
2960
2972
|
});
|
|
2961
|
-
const quotaSource =
|
|
2973
|
+
const quotaSource = buildQuotaSource({ halfLifeHours });
|
|
2962
2974
|
const quotaSourceSnapshot = await quotaSource.queryCurrentUsage(providerModelKey).catch(() => null);
|
|
2963
2975
|
const queryDiscoveredLimits = await lookupDiscoveredLimits(providerModelKey).catch(() => null);
|
|
2964
2976
|
const waveSchedule = scheduleWave({
|
package/dist/providers/index.js
CHANGED
|
@@ -22,8 +22,11 @@ function commandExists(command) {
|
|
|
22
22
|
return result.status === 0;
|
|
23
23
|
}
|
|
24
24
|
export function resolveFreshSessionProviderName(name, sessionConfig = {}, options = {}) {
|
|
25
|
-
const requestedProvider = name ?? sessionConfig.provider
|
|
26
|
-
|
|
25
|
+
const requestedProvider = name ?? sessionConfig.provider;
|
|
26
|
+
const shouldAutoDetect = requestedProvider === undefined ||
|
|
27
|
+
requestedProvider === "auto" ||
|
|
28
|
+
(name === undefined && requestedProvider === "local-subprocess");
|
|
29
|
+
if (!shouldAutoDetect) {
|
|
27
30
|
return requestedProvider;
|
|
28
31
|
}
|
|
29
32
|
const env = options.env ?? process.env;
|
|
@@ -65,8 +68,12 @@ export function resolveFreshSessionProviderName(name, sessionConfig = {}, option
|
|
|
65
68
|
export function createFreshSessionProvider(name, sessionConfig = {}) {
|
|
66
69
|
const providerName = resolveFreshSessionProviderName(name, sessionConfig);
|
|
67
70
|
const opentoken = sessionConfig.opentoken ?? {};
|
|
71
|
+
const requestedProvider = name ?? sessionConfig.provider;
|
|
72
|
+
const autoDetectionRequested = requestedProvider === undefined ||
|
|
73
|
+
requestedProvider === "auto" ||
|
|
74
|
+
(name === undefined && requestedProvider === "local-subprocess");
|
|
68
75
|
if (providerName === "local-subprocess" &&
|
|
69
|
-
|
|
76
|
+
autoDetectionRequested) {
|
|
70
77
|
process.stderr.write("audit-code: auto provider resolved to local-subprocess — no capable agent provider detected. " +
|
|
71
78
|
"Agent tasks will require manual dispatch. Configure claude-code, opencode, or subprocess-template " +
|
|
72
79
|
"in session-config.json to automate them.\n");
|
package/package.json
CHANGED
package/scripts/postinstall.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { mkdirSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
|
|
7
7
|
const pkgRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
8
|
+
const packageVersion = JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf8')).version ?? '0.0.0';
|
|
8
9
|
const promptSourceFile = join(pkgRoot, 'skills', 'audit-code', 'audit-code.prompt.md');
|
|
9
10
|
const skillSourceFile = join(pkgRoot, 'skills', 'audit-code', 'SKILL.md');
|
|
10
11
|
const codexOpenAiAgentSourceFile = join(pkgRoot, 'skills', 'audit-code', 'agents', 'openai.yaml');
|
|
@@ -330,6 +331,10 @@ function mergeOpenCodeGlobalConfig(existing) {
|
|
|
330
331
|
};
|
|
331
332
|
}
|
|
332
333
|
|
|
334
|
+
function claudePluginExternalDir() {
|
|
335
|
+
return join(homedir(), '.claude', 'plugins', 'marketplaces', 'claude-plugins-official', 'external_plugins', 'audit-code');
|
|
336
|
+
}
|
|
337
|
+
|
|
333
338
|
function claudeDesktopConfigPath() {
|
|
334
339
|
if (process.platform === 'win32') {
|
|
335
340
|
return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
|
|
@@ -459,6 +464,44 @@ try {
|
|
|
459
464
|
console.warn(`audit-code: could not install Antigravity plugin (${err.message})`);
|
|
460
465
|
}
|
|
461
466
|
|
|
467
|
+
// Install Claude Desktop plugin so /audit-code appears in the slash-command menu
|
|
468
|
+
// Claude Desktop reads external plugins from ~/.claude/plugins/marketplaces/claude-plugins-official/external_plugins/
|
|
469
|
+
const claudePluginDir = claudePluginExternalDir();
|
|
470
|
+
const claudePluginManifestPath = join(claudePluginDir, '.claude-plugin', 'plugin.json');
|
|
471
|
+
const claudePluginCommandPath = join(claudePluginDir, 'commands', 'audit-code.md');
|
|
472
|
+
const claudePluginSkillPath = join(claudePluginDir, 'skills', 'audit-code', 'SKILL.md');
|
|
473
|
+
try {
|
|
474
|
+
const manifest = {
|
|
475
|
+
name: 'audit-code',
|
|
476
|
+
description: 'Autonomous local-loop code auditing workflow',
|
|
477
|
+
version: packageVersion,
|
|
478
|
+
author: {
|
|
479
|
+
name: 'auditor-lambda',
|
|
480
|
+
url: 'https://github.com/OhOkThisIsFine/auditor-lambda',
|
|
481
|
+
},
|
|
482
|
+
homepage: 'https://github.com/OhOkThisIsFine/auditor-lambda',
|
|
483
|
+
repository: 'https://github.com/OhOkThisIsFine/auditor-lambda',
|
|
484
|
+
license: 'MIT',
|
|
485
|
+
keywords: ['audit', 'code-audit', 'static-analysis', 'orchestration'],
|
|
486
|
+
};
|
|
487
|
+
const manifestAction = writeGeneratedFile(
|
|
488
|
+
claudePluginManifestPath,
|
|
489
|
+
Buffer.from(JSON.stringify(manifest, null, 2) + '\n'),
|
|
490
|
+
);
|
|
491
|
+
console.log(`audit-code: ${manifestAction} Claude Desktop plugin manifest at ${claudePluginManifestPath}`);
|
|
492
|
+
|
|
493
|
+
const commandAction = writeGeneratedFile(claudePluginCommandPath, promptSource);
|
|
494
|
+
console.log(`audit-code: ${commandAction} Claude Desktop plugin command at ${claudePluginCommandPath}`);
|
|
495
|
+
|
|
496
|
+
const skillAction = writeGeneratedFile(claudePluginSkillPath, skillSource);
|
|
497
|
+
console.log(`audit-code: ${skillAction} Claude Desktop plugin skill at ${claudePluginSkillPath}`);
|
|
498
|
+
|
|
499
|
+
console.log(`audit-code: restart Claude Desktop for /audit-code to appear in the slash-command menu`);
|
|
500
|
+
} catch (err) {
|
|
501
|
+
console.warn(`audit-code: could not install Claude Desktop plugin (${err.message})`);
|
|
502
|
+
console.warn(` Plugin directory: ${claudePluginDir}`);
|
|
503
|
+
}
|
|
504
|
+
|
|
462
505
|
// Register auditor MCP server with Claude Desktop so /audit-code appears in its slash-command menu
|
|
463
506
|
const claudeDesktopConfig = claudeDesktopConfigPath();
|
|
464
507
|
try {
|