solidity-argus 0.1.8 → 0.3.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/AGENTS.md +3 -3
- package/README.md +229 -13
- package/package.json +37 -8
- package/skills/INVENTORY.md +88 -57
- package/skills/README.md +72 -6
- package/skills/case-studies/beanstalk-governance/SKILL.md +52 -0
- package/skills/case-studies/bzx-flash-loan/SKILL.md +53 -0
- package/skills/case-studies/cream-finance/SKILL.md +52 -0
- package/skills/case-studies/curve-reentrancy/SKILL.md +52 -0
- package/skills/case-studies/dao-hack/SKILL.md +51 -0
- package/skills/case-studies/euler-finance/SKILL.md +52 -0
- package/skills/case-studies/harvest-finance/SKILL.md +52 -0
- package/skills/case-studies/level-finance/SKILL.md +51 -0
- package/skills/case-studies/mango-markets/SKILL.md +53 -0
- package/skills/case-studies/nomad-bridge/SKILL.md +51 -0
- package/skills/case-studies/parity-multisig/SKILL.md +55 -0
- package/skills/case-studies/poly-network/SKILL.md +51 -0
- package/skills/case-studies/rari-fuse/SKILL.md +51 -0
- package/skills/case-studies/ronin-bridge/SKILL.md +52 -0
- package/skills/case-studies/wormhole-bridge/SKILL.md +51 -0
- package/skills/checklists/cyfrin-defi-core/SKILL.md +3 -0
- package/skills/manifests/cyfrin.json +16 -0
- package/skills/manifests/defifofum.json +25 -0
- package/skills/manifests/kadenzipfel.json +48 -0
- package/skills/manifests/scvd.json +9 -0
- package/skills/manifests/smartbugs.json +9 -0
- package/skills/manifests/solodit.json +9 -0
- package/skills/manifests/sunweb3sec.json +9 -0
- package/skills/manifests/trailofbits.json +9 -0
- package/skills/methodology/audit-workflow/SKILL.md +3 -0
- package/skills/protocol-patterns/amm-dex/SKILL.md +3 -0
- package/skills/references/exploit-reference/SKILL.md +3 -0
- package/skills/vulnerability-patterns/access-control/SKILL.md +27 -0
- package/skills/vulnerability-patterns/arbitrary-storage-location/SKILL.md +13 -1
- package/skills/vulnerability-patterns/assert-violation/SKILL.md +8 -1
- package/skills/vulnerability-patterns/asserting-contract-from-code-size/SKILL.md +12 -1
- package/skills/vulnerability-patterns/authorization-txorigin/SKILL.md +8 -1
- package/skills/vulnerability-patterns/cross-chain-bridge-vulnerabilities/SKILL.md +217 -0
- package/skills/vulnerability-patterns/default-visibility/SKILL.md +13 -1
- package/skills/vulnerability-patterns/delegatecall-untrusted-callee/SKILL.md +8 -1
- package/skills/vulnerability-patterns/dos-gas-limit/SKILL.md +8 -1
- package/skills/vulnerability-patterns/dos-revert/SKILL.md +14 -1
- package/skills/vulnerability-patterns/erc4626-exchange-rate-manipulation/SKILL.md +64 -0
- package/skills/vulnerability-patterns/fee-on-transfer-tokens/SKILL.md +93 -0
- package/skills/vulnerability-patterns/flash-loan-attacks/SKILL.md +13 -0
- package/skills/vulnerability-patterns/floating-pragma/SKILL.md +8 -1
- package/skills/vulnerability-patterns/front-running-attacks/SKILL.md +209 -0
- package/skills/vulnerability-patterns/gas-optimization-patterns/SKILL.md +203 -0
- package/skills/vulnerability-patterns/governance-attacks/SKILL.md +208 -0
- package/skills/vulnerability-patterns/hash-collision/SKILL.md +8 -1
- package/skills/vulnerability-patterns/inadherence-to-standards/SKILL.md +12 -1
- package/skills/vulnerability-patterns/incorrect-constructor/SKILL.md +8 -1
- package/skills/vulnerability-patterns/incorrect-inheritance-order/SKILL.md +8 -1
- package/skills/vulnerability-patterns/insufficient-gas-griefing/SKILL.md +12 -1
- package/skills/vulnerability-patterns/lack-of-precision/SKILL.md +7 -1
- package/skills/vulnerability-patterns/logic-errors/SKILL.md +10 -0
- package/skills/vulnerability-patterns/missing-parameter-bounds/SKILL.md +44 -0
- package/skills/vulnerability-patterns/missing-protection-signature-replay/SKILL.md +17 -1
- package/skills/vulnerability-patterns/msgvalue-loop/SKILL.md +12 -1
- package/skills/vulnerability-patterns/off-by-one/SKILL.md +7 -1
- package/skills/vulnerability-patterns/oracle-manipulation/SKILL.md +22 -0
- package/skills/vulnerability-patterns/outdated-compiler-version/SKILL.md +8 -1
- package/skills/vulnerability-patterns/overflow-underflow/SKILL.md +11 -1
- package/skills/vulnerability-patterns/proxy-vulnerabilities/SKILL.md +209 -0
- package/skills/vulnerability-patterns/reentrancy/SKILL.md +22 -0
- package/skills/vulnerability-patterns/shadowing-state-variables/SKILL.md +8 -1
- package/skills/vulnerability-patterns/share-accounting-desynchronization/SKILL.md +44 -0
- package/skills/vulnerability-patterns/signature-malleability/SKILL.md +11 -1
- package/skills/vulnerability-patterns/stateful-parameter-update-drift/SKILL.md +44 -0
- package/skills/vulnerability-patterns/unbounded-return-data/SKILL.md +12 -1
- package/skills/vulnerability-patterns/unchecked-return-values/SKILL.md +13 -1
- package/skills/vulnerability-patterns/unencrypted-private-data-on-chain/SKILL.md +8 -1
- package/skills/vulnerability-patterns/unexpected-ecrecover-null-address/SKILL.md +8 -1
- package/skills/vulnerability-patterns/uninitialized-storage-pointer/SKILL.md +8 -1
- package/skills/vulnerability-patterns/unsafe-erc20-transfers/SKILL.md +132 -0
- package/skills/vulnerability-patterns/unsafe-low-level-call/SKILL.md +12 -1
- package/skills/vulnerability-patterns/unsecure-signatures/SKILL.md +12 -1
- package/skills/vulnerability-patterns/unsupported-opcodes/SKILL.md +11 -1
- package/skills/vulnerability-patterns/unused-variables/SKILL.md +8 -1
- package/skills/vulnerability-patterns/use-of-deprecated-functions/SKILL.md +8 -1
- package/skills/vulnerability-patterns/weak-sources-randomness/SKILL.md +8 -1
- package/skills/vulnerability-patterns/weird-tokens/SKILL.md +10 -0
- package/skills/vulnerability-patterns/zero-address-misconfiguration/SKILL.md +48 -0
- package/src/agents/argus-prompt.ts +27 -10
- package/src/agents/pythia-prompt.ts +7 -8
- package/src/agents/scribe-prompt.ts +10 -5
- package/src/agents/sentinel-prompt.ts +36 -7
- package/src/cli/cli-output.ts +16 -0
- package/src/cli/cli-program.ts +29 -22
- package/src/cli/commands/check-skills.ts +135 -0
- package/src/cli/commands/doctor.ts +303 -23
- package/src/cli/commands/init.ts +8 -6
- package/src/cli/commands/install.ts +10 -8
- package/src/cli/commands/lint-skills.ts +118 -0
- package/src/cli/index.ts +5 -5
- package/src/cli/tui-prompts.ts +4 -2
- package/src/cli/types.ts +3 -3
- package/src/config/index.ts +1 -1
- package/src/config/loader.ts +4 -6
- package/src/config/schema.ts +6 -5
- package/src/config/types.ts +2 -2
- package/src/constants/defaults.ts +2 -0
- package/src/create-hooks.ts +225 -29
- package/src/create-managers.ts +10 -8
- package/src/create-tools.ts +14 -8
- package/src/features/background-agent/background-manager.ts +93 -87
- package/src/features/background-agent/index.ts +1 -1
- package/src/features/context-monitor/context-monitor.ts +3 -3
- package/src/features/context-monitor/index.ts +2 -2
- package/src/features/error-recovery/session-recovery.ts +2 -4
- package/src/features/error-recovery/tool-error-recovery.ts +79 -19
- package/src/features/index.ts +5 -5
- package/src/features/persistent-state/audit-state-manager.ts +158 -52
- package/src/features/persistent-state/global-run-index.ts +38 -0
- package/src/features/persistent-state/index.ts +1 -1
- package/src/features/persistent-state/run-journal.ts +86 -0
- package/src/hooks/agent-tracker.ts +53 -0
- package/src/hooks/compaction-hook.ts +46 -37
- package/src/hooks/config-handler.ts +31 -11
- package/src/hooks/context-budget.ts +42 -0
- package/src/hooks/event-hook.ts +48 -23
- package/src/hooks/hook-system.ts +4 -4
- package/src/hooks/index.ts +5 -5
- package/src/hooks/knowledge-sync-hook.ts +19 -21
- package/src/hooks/recon-context-builder.ts +66 -0
- package/src/hooks/safe-create-hook.ts +9 -11
- package/src/hooks/system-prompt-hook.ts +128 -0
- package/src/hooks/tool-tracking-hook.ts +162 -29
- package/src/hooks/types.ts +2 -1
- package/src/index.ts +23 -13
- package/src/knowledge/retry.ts +53 -0
- package/src/knowledge/scvd-client.ts +103 -83
- package/src/knowledge/scvd-errors.ts +89 -0
- package/src/knowledge/scvd-index.ts +110 -62
- package/src/knowledge/scvd-sync.ts +223 -47
- package/src/knowledge/source-manifest.ts +102 -0
- package/src/managers/index.ts +1 -1
- package/src/managers/types.ts +19 -14
- package/src/plugin-interface.ts +19 -8
- package/src/shared/binary-utils.ts +44 -34
- package/src/shared/deep-merge.ts +55 -36
- package/src/shared/file-utils.ts +21 -19
- package/src/shared/index.ts +11 -5
- package/src/shared/jsonc-parser.ts +123 -28
- package/src/shared/logger.ts +91 -17
- package/src/shared/project-utils.ts +30 -0
- package/src/skills/analysis/cluster.ts +414 -0
- package/src/skills/analysis/gates.ts +227 -0
- package/src/skills/analysis/index.ts +33 -0
- package/src/skills/analysis/normalize.ts +217 -0
- package/src/skills/analysis/similarity.ts +224 -0
- package/src/skills/argus-skill-resolver.ts +237 -0
- package/src/skills/skill-schema.ts +99 -0
- package/src/solodit-lifecycle.ts +202 -0
- package/src/state/audit-state.ts +10 -8
- package/src/state/finding-store.ts +68 -55
- package/src/state/types.ts +96 -44
- package/src/tools/argus-skill-load-tool.ts +78 -0
- package/src/tools/contract-analyzer-tool.ts +60 -77
- package/src/tools/forge-coverage-tool.ts +226 -0
- package/src/tools/forge-fuzz-tool.ts +127 -127
- package/src/tools/forge-test-tool.ts +153 -157
- package/src/tools/gas-analysis-tool.ts +264 -0
- package/src/tools/pattern-checker-tool.ts +206 -167
- package/src/tools/pattern-loader.ts +77 -0
- package/src/tools/pattern-schema.ts +51 -0
- package/src/tools/proxy-detection-tool.ts +224 -0
- package/src/tools/report-generator-tool.ts +333 -142
- package/src/tools/slither-tool.ts +300 -210
- package/src/tools/solodit-search-tool.ts +255 -80
- package/src/tools/sync-knowledge-tool.ts +7 -11
- package/src/utils/audit-artifact-detector.ts +118 -0
- package/src/utils/dependency-scanner.ts +93 -0
- package/src/utils/project-detector.ts +175 -86
- package/src/utils/solidity-parser.ts +112 -67
- package/src/utils/solodit-health.ts +29 -0
- package/src/hooks/event-hook-v2.ts +0 -99
- package/src/state/plugin-state.ts +0 -14
|
@@ -1,122 +1,125 @@
|
|
|
1
|
-
import type { BackgroundManager } from "../../managers/types"
|
|
2
|
-
import { createLogger } from "../../shared/logger"
|
|
1
|
+
import type { BackgroundManager } from "../../managers/types"
|
|
2
|
+
import { createLogger } from "../../shared/logger"
|
|
3
3
|
|
|
4
|
-
type TaskStatus = "queued" | "running" | "completed" | "failed" | "cancelled"
|
|
5
|
-
type CompletionCallback = (taskId: string, result: unknown) => void
|
|
4
|
+
type TaskStatus = "queued" | "running" | "completed" | "failed" | "cancelled"
|
|
5
|
+
type CompletionCallback = (taskId: string, result: unknown) => void
|
|
6
6
|
|
|
7
7
|
export interface BackgroundTaskOptions {
|
|
8
|
-
priority?: number
|
|
9
|
-
max_concurrent?: number
|
|
8
|
+
priority?: number
|
|
9
|
+
max_concurrent?: number
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface BackgroundManagerWithTaskCallbacks extends BackgroundManager {
|
|
13
|
-
dispatch(agentName: string, prompt: string, options?: BackgroundTaskOptions): string
|
|
14
|
-
onComplete(callback: CompletionCallback): void
|
|
15
|
-
onComplete(taskId: string, callback: CompletionCallback): void
|
|
13
|
+
dispatch(agentName: string, prompt: string, options?: BackgroundTaskOptions): string
|
|
14
|
+
onComplete(callback: CompletionCallback): void
|
|
15
|
+
onComplete(taskId: string, callback: CompletionCallback): void
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
interface TaskInfo {
|
|
19
|
-
status: TaskStatus
|
|
20
|
-
agentName: string
|
|
21
|
-
prompt: string
|
|
22
|
-
options?: BackgroundTaskOptions
|
|
23
|
-
result?: unknown
|
|
24
|
-
error?: unknown
|
|
25
|
-
callbacks: Set<CompletionCallback
|
|
19
|
+
status: TaskStatus
|
|
20
|
+
agentName: string
|
|
21
|
+
prompt: string
|
|
22
|
+
options?: BackgroundTaskOptions
|
|
23
|
+
result?: unknown
|
|
24
|
+
error?: unknown
|
|
25
|
+
callbacks: Set<CompletionCallback>
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
type Dispatcher = (
|
|
28
|
+
export type Dispatcher = (
|
|
29
29
|
agentName: string,
|
|
30
30
|
prompt: string,
|
|
31
31
|
options?: BackgroundTaskOptions,
|
|
32
|
-
) => Promise<string
|
|
32
|
+
) => Promise<string>
|
|
33
33
|
|
|
34
34
|
export function createBackgroundManager(
|
|
35
|
-
|
|
35
|
+
initialDispatcher: Dispatcher,
|
|
36
|
+
options?: { maxConcurrent?: number },
|
|
36
37
|
): BackgroundManagerWithTaskCallbacks {
|
|
37
|
-
const logger = createLogger()
|
|
38
|
-
const tasks = new Map<string, TaskInfo>()
|
|
39
|
-
const queue: string[] = []
|
|
40
|
-
const globalCallbacks = new Set<CompletionCallback>()
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
let
|
|
44
|
-
|
|
38
|
+
const logger = createLogger()
|
|
39
|
+
const tasks = new Map<string, TaskInfo>()
|
|
40
|
+
const queue: string[] = []
|
|
41
|
+
const globalCallbacks = new Set<CompletionCallback>()
|
|
42
|
+
|
|
43
|
+
const dispatcher = initialDispatcher
|
|
44
|
+
let runningCount = 0
|
|
45
|
+
const maxConcurrent = options?.maxConcurrent ?? 3
|
|
46
|
+
let taskCount = 0
|
|
47
|
+
|
|
48
|
+
function safeInvokeCallback(callback: CompletionCallback, taskId: string, result: unknown): void {
|
|
49
|
+
try {
|
|
50
|
+
callback(taskId, result)
|
|
51
|
+
} catch (error: unknown) {
|
|
52
|
+
logger.error(`Background callback failed: ${taskId}`, error)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
45
55
|
|
|
46
56
|
function invokeCallbacks(taskId: string, result: unknown): void {
|
|
47
|
-
const task = tasks.get(taskId)
|
|
57
|
+
const task = tasks.get(taskId)
|
|
48
58
|
if (!task) {
|
|
49
|
-
return
|
|
59
|
+
return
|
|
50
60
|
}
|
|
51
61
|
|
|
52
62
|
for (const callback of globalCallbacks) {
|
|
53
|
-
callback
|
|
63
|
+
safeInvokeCallback(callback, taskId, result)
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
for (const callback of task.callbacks) {
|
|
57
|
-
callback
|
|
67
|
+
safeInvokeCallback(callback, taskId, result)
|
|
58
68
|
}
|
|
59
69
|
|
|
60
|
-
task.callbacks.clear()
|
|
70
|
+
task.callbacks.clear()
|
|
61
71
|
}
|
|
62
72
|
|
|
63
73
|
function processQueue(): void {
|
|
64
74
|
while (runningCount < maxConcurrent && queue.length > 0) {
|
|
65
|
-
const nextTaskId = queue.shift()
|
|
75
|
+
const nextTaskId = queue.shift()
|
|
66
76
|
|
|
67
77
|
if (!nextTaskId) {
|
|
68
|
-
return
|
|
78
|
+
return
|
|
69
79
|
}
|
|
70
80
|
|
|
71
|
-
const task = tasks.get(nextTaskId)
|
|
81
|
+
const task = tasks.get(nextTaskId)
|
|
72
82
|
if (!task || task.status === "cancelled") {
|
|
73
|
-
continue
|
|
83
|
+
continue
|
|
74
84
|
}
|
|
75
85
|
|
|
76
|
-
task.status = "running"
|
|
77
|
-
runningCount += 1
|
|
86
|
+
task.status = "running"
|
|
87
|
+
runningCount += 1
|
|
78
88
|
|
|
79
89
|
dispatcher(task.agentName, task.prompt, task.options)
|
|
80
90
|
.then((result) => {
|
|
81
|
-
const currentTask = tasks.get(nextTaskId)
|
|
91
|
+
const currentTask = tasks.get(nextTaskId)
|
|
82
92
|
|
|
83
93
|
if (!currentTask || currentTask.status === "cancelled") {
|
|
84
|
-
return
|
|
94
|
+
return
|
|
85
95
|
}
|
|
86
96
|
|
|
87
|
-
currentTask.status = "completed"
|
|
88
|
-
currentTask.result = result
|
|
89
|
-
invokeCallbacks(nextTaskId, result)
|
|
97
|
+
currentTask.status = "completed"
|
|
98
|
+
currentTask.result = result
|
|
99
|
+
invokeCallbacks(nextTaskId, result)
|
|
90
100
|
})
|
|
91
101
|
.catch((error: unknown) => {
|
|
92
|
-
const currentTask = tasks.get(nextTaskId)
|
|
102
|
+
const currentTask = tasks.get(nextTaskId)
|
|
93
103
|
|
|
94
104
|
if (!currentTask || currentTask.status === "cancelled") {
|
|
95
|
-
return
|
|
105
|
+
return
|
|
96
106
|
}
|
|
97
107
|
|
|
98
|
-
currentTask.status = "failed"
|
|
99
|
-
currentTask.error = error
|
|
100
|
-
logger.error(`Background task failed: ${nextTaskId}`, error)
|
|
108
|
+
currentTask.status = "failed"
|
|
109
|
+
currentTask.error = error
|
|
110
|
+
logger.error(`Background task failed: ${nextTaskId}`, error)
|
|
111
|
+
invokeCallbacks(nextTaskId, error)
|
|
101
112
|
})
|
|
102
113
|
.finally(() => {
|
|
103
|
-
runningCount = Math.max(0, runningCount - 1)
|
|
104
|
-
processQueue()
|
|
105
|
-
})
|
|
114
|
+
runningCount = Math.max(0, runningCount - 1)
|
|
115
|
+
processQueue()
|
|
116
|
+
})
|
|
106
117
|
}
|
|
107
118
|
}
|
|
108
119
|
|
|
109
|
-
function dispatch(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
options?: BackgroundTaskOptions,
|
|
113
|
-
): string {
|
|
114
|
-
if (typeof options?.max_concurrent === "number" && options.max_concurrent > 0) {
|
|
115
|
-
maxConcurrent = options.max_concurrent;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
taskCount += 1;
|
|
119
|
-
const taskId = `task-${taskCount}`;
|
|
120
|
+
function dispatch(agentName: string, prompt: string, options?: BackgroundTaskOptions): string {
|
|
121
|
+
taskCount += 1
|
|
122
|
+
const taskId = `task-${taskCount}`
|
|
120
123
|
|
|
121
124
|
tasks.set(taskId, {
|
|
122
125
|
status: "queued",
|
|
@@ -124,70 +127,73 @@ export function createBackgroundManager(
|
|
|
124
127
|
prompt,
|
|
125
128
|
options,
|
|
126
129
|
callbacks: new Set<CompletionCallback>(),
|
|
127
|
-
})
|
|
130
|
+
})
|
|
128
131
|
|
|
129
|
-
queue.push(taskId)
|
|
130
|
-
processQueue()
|
|
132
|
+
queue.push(taskId)
|
|
133
|
+
processQueue()
|
|
131
134
|
|
|
132
|
-
return taskId
|
|
135
|
+
return taskId
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
function cancel(taskId: string): void {
|
|
136
|
-
const task = tasks.get(taskId)
|
|
139
|
+
const task = tasks.get(taskId)
|
|
137
140
|
if (!task) {
|
|
138
|
-
return
|
|
141
|
+
return
|
|
139
142
|
}
|
|
140
143
|
|
|
141
|
-
task.status = "cancelled"
|
|
144
|
+
task.status = "cancelled"
|
|
142
145
|
|
|
143
|
-
const queuedTaskIndex = queue.indexOf(taskId)
|
|
146
|
+
const queuedTaskIndex = queue.indexOf(taskId)
|
|
144
147
|
if (queuedTaskIndex >= 0) {
|
|
145
|
-
queue.splice(queuedTaskIndex, 1)
|
|
148
|
+
queue.splice(queuedTaskIndex, 1)
|
|
146
149
|
}
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
function getResult(taskId: string): Promise<unknown> {
|
|
150
|
-
const task = tasks.get(taskId)
|
|
153
|
+
const task = tasks.get(taskId)
|
|
151
154
|
if (!task || task.status !== "completed") {
|
|
152
|
-
return Promise.resolve(undefined)
|
|
155
|
+
return Promise.resolve(undefined)
|
|
153
156
|
}
|
|
154
157
|
|
|
155
|
-
return Promise.resolve(task.result)
|
|
158
|
+
return Promise.resolve(task.result)
|
|
156
159
|
}
|
|
157
160
|
|
|
158
|
-
function onComplete(
|
|
161
|
+
function onComplete(
|
|
162
|
+
taskIdOrCallback: string | CompletionCallback,
|
|
163
|
+
callback?: CompletionCallback,
|
|
164
|
+
): void {
|
|
159
165
|
if (typeof taskIdOrCallback === "function") {
|
|
160
|
-
globalCallbacks.add(taskIdOrCallback)
|
|
161
|
-
return
|
|
166
|
+
globalCallbacks.add(taskIdOrCallback)
|
|
167
|
+
return
|
|
162
168
|
}
|
|
163
169
|
|
|
164
170
|
if (!callback) {
|
|
165
|
-
return
|
|
171
|
+
return
|
|
166
172
|
}
|
|
167
173
|
|
|
168
|
-
const task = tasks.get(taskIdOrCallback)
|
|
174
|
+
const task = tasks.get(taskIdOrCallback)
|
|
169
175
|
if (!task) {
|
|
170
|
-
return
|
|
176
|
+
return
|
|
171
177
|
}
|
|
172
178
|
|
|
173
179
|
if (task.status === "completed") {
|
|
174
|
-
callback
|
|
175
|
-
return
|
|
180
|
+
safeInvokeCallback(callback, taskIdOrCallback, task.result)
|
|
181
|
+
return
|
|
176
182
|
}
|
|
177
183
|
|
|
178
|
-
task.callbacks.add(callback)
|
|
184
|
+
task.callbacks.add(callback)
|
|
179
185
|
}
|
|
180
186
|
|
|
181
187
|
function getActiveCount(): number {
|
|
182
|
-
let activeCount = 0
|
|
188
|
+
let activeCount = 0
|
|
183
189
|
|
|
184
190
|
for (const task of tasks.values()) {
|
|
185
191
|
if (task.status === "queued" || task.status === "running") {
|
|
186
|
-
activeCount += 1
|
|
192
|
+
activeCount += 1
|
|
187
193
|
}
|
|
188
194
|
}
|
|
189
195
|
|
|
190
|
-
return activeCount
|
|
196
|
+
return activeCount
|
|
191
197
|
}
|
|
192
198
|
|
|
193
199
|
return {
|
|
@@ -196,5 +202,5 @@ export function createBackgroundManager(
|
|
|
196
202
|
getResult,
|
|
197
203
|
onComplete,
|
|
198
204
|
getActiveCount,
|
|
199
|
-
}
|
|
205
|
+
}
|
|
200
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./background-manager"
|
|
1
|
+
export * from "./background-manager"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { AuditState } from "../../state/types"
|
|
2
1
|
import { createLogger } from "../../shared/logger"
|
|
2
|
+
import type { AuditState } from "../../state/types"
|
|
3
3
|
|
|
4
4
|
const DEFAULT_MAX_TOKENS = 200_000
|
|
5
|
-
const REMINDER_THRESHOLD = 0.
|
|
5
|
+
const REMINDER_THRESHOLD = 0.7
|
|
6
6
|
const COMPACTION_THRESHOLD = 0.85
|
|
7
7
|
|
|
8
8
|
export interface ContextMonitorConfig {
|
|
@@ -19,7 +19,7 @@ export function createContextMonitor(config: ContextMonitorConfig = {}) {
|
|
|
19
19
|
|
|
20
20
|
function getContextStatus(
|
|
21
21
|
systemText: string,
|
|
22
|
-
|
|
22
|
+
_auditState: AuditState | null,
|
|
23
23
|
): { usage: number; reminder: string | null; shouldCompact: boolean } {
|
|
24
24
|
const tokens = estimateTokens(systemText)
|
|
25
25
|
const usage = tokens / maxTokens
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createContextMonitor } from "./context-monitor"
|
|
2
1
|
export type { ContextMonitorConfig } from "./context-monitor"
|
|
3
|
-
export {
|
|
2
|
+
export { createContextMonitor } from "./context-monitor"
|
|
4
3
|
export type { TruncatorConfig } from "./tool-output-truncator"
|
|
4
|
+
export { createToolOutputTruncator } from "./tool-output-truncator"
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import type { AuditState } from "../../state/types"
|
|
2
1
|
import type { AuditStateManager } from "../../managers/types"
|
|
3
2
|
import { createLogger } from "../../shared/logger"
|
|
3
|
+
import type { AuditState } from "../../state/types"
|
|
4
4
|
|
|
5
|
-
export function createSessionRecoveryHandler(
|
|
6
|
-
auditStateManager: AuditStateManager,
|
|
7
|
-
) {
|
|
5
|
+
export function createSessionRecoveryHandler(auditStateManager: AuditStateManager) {
|
|
8
6
|
const logger = createLogger()
|
|
9
7
|
|
|
10
8
|
return async (event: {
|
|
@@ -1,15 +1,61 @@
|
|
|
1
1
|
import { createLogger } from "../../shared/logger"
|
|
2
|
+
import type { AuditState } from "../../state/types"
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
solodit: "Check network connectivity or Solodit API status",
|
|
7
|
-
scvd: "Check SCVD API at https://api.scvd.dev — may be temporarily unavailable",
|
|
4
|
+
type ToolFallbackEntry = {
|
|
5
|
+
install: string
|
|
6
|
+
fallback: string
|
|
8
7
|
}
|
|
9
8
|
|
|
10
|
-
const
|
|
9
|
+
const TOOL_FALLBACKS: Record<string, ToolFallbackEntry> = {
|
|
10
|
+
slither: {
|
|
11
|
+
install: "pip install slither-analyzer",
|
|
12
|
+
fallback:
|
|
13
|
+
'Slither is unavailable. PROCEED with the audit using `argus_analyze_contract` for structural profiling and `argus_check_patterns` for vulnerability scanning. Note in the final report: "Automated static analysis (Slither) was unavailable; manual review intensity increased."',
|
|
14
|
+
},
|
|
15
|
+
forge: {
|
|
16
|
+
install: "curl -L https://foundry.paradigm.xyz | bash && foundryup",
|
|
17
|
+
fallback:
|
|
18
|
+
'Foundry/Forge is unavailable. SKIP automated testing and fuzzing. Verify findings through manual code tracing and static analysis. Note in the final report: "Dynamic testing (Forge) was unavailable; findings verified via manual analysis."',
|
|
19
|
+
},
|
|
20
|
+
solodit: {
|
|
21
|
+
install: "",
|
|
22
|
+
fallback:
|
|
23
|
+
'Solodit API is unreachable. PROCEED using `argus_check_patterns` with local vulnerability rules. Note in the final report: "External vulnerability databases were inaccessible; research limited to local patterns."',
|
|
24
|
+
},
|
|
25
|
+
scvd: {
|
|
26
|
+
install: "",
|
|
27
|
+
fallback:
|
|
28
|
+
"SCVD API is unavailable. PROCEED with local patterns and Solodit search if available.",
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const VIA_IR_HINT =
|
|
33
|
+
"Project uses via_ir — Slither uses forge-flatten fallback automatically. Ensure forge and solc-select are installed."
|
|
34
|
+
|
|
35
|
+
function isToolUnavailable(lowerResult: string): boolean {
|
|
36
|
+
return (
|
|
37
|
+
lowerResult.includes("enoent") ||
|
|
38
|
+
lowerResult.includes("not found") ||
|
|
39
|
+
lowerResult.includes("not installed")
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isToolError(lowerResult: string): boolean {
|
|
44
|
+
return (
|
|
45
|
+
isToolUnavailable(lowerResult) ||
|
|
46
|
+
lowerResult.includes("command failed") ||
|
|
47
|
+
lowerResult.includes("error:")
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function resolveToolBase(tool: string): string {
|
|
52
|
+
return tool.replace("argus_", "").split("_")[0] ?? ""
|
|
53
|
+
}
|
|
11
54
|
|
|
12
|
-
export function createToolErrorRecoveryHandler(
|
|
55
|
+
export function createToolErrorRecoveryHandler(
|
|
56
|
+
getAuditState?: () => AuditState | null,
|
|
57
|
+
updateAuditState?: (patch: Partial<AuditState>) => Promise<void>,
|
|
58
|
+
) {
|
|
13
59
|
const logger = createLogger()
|
|
14
60
|
|
|
15
61
|
return (toolResult: { tool: string; result: string }): string | null => {
|
|
@@ -27,22 +73,36 @@ export function createToolErrorRecoveryHandler() {
|
|
|
27
73
|
return `\n[Argus Recovery Hint] ${VIA_IR_HINT}`
|
|
28
74
|
}
|
|
29
75
|
|
|
30
|
-
|
|
31
|
-
lowerResult.includes("enoent") ||
|
|
32
|
-
lowerResult.includes("not found") ||
|
|
33
|
-
lowerResult.includes("command failed") ||
|
|
34
|
-
lowerResult.includes("error:")
|
|
76
|
+
if (!isToolError(lowerResult)) return null
|
|
35
77
|
|
|
36
|
-
|
|
78
|
+
const toolBase = resolveToolBase(tool)
|
|
79
|
+
const entry = TOOL_FALLBACKS[toolBase]
|
|
80
|
+
if (!entry) return null
|
|
37
81
|
|
|
38
|
-
const
|
|
39
|
-
|
|
82
|
+
const unavailable = isToolUnavailable(lowerResult)
|
|
83
|
+
|
|
84
|
+
if (unavailable && getAuditState && updateAuditState) {
|
|
85
|
+
const state = getAuditState()
|
|
86
|
+
if (state) {
|
|
87
|
+
const existing = state.unavailableTools ?? []
|
|
88
|
+
if (!existing.includes(toolBase)) {
|
|
89
|
+
void updateAuditState({
|
|
90
|
+
unavailableTools: [...existing, toolBase],
|
|
91
|
+
}).catch((error: unknown) => {
|
|
92
|
+
logger.warn(`Failed to persist unavailable tool state for ${toolBase}`, error)
|
|
93
|
+
})
|
|
94
|
+
logger.info(`Recorded ${toolBase} as unavailable — fallback activated`)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
40
98
|
|
|
41
|
-
if (
|
|
42
|
-
logger.info(`Tool
|
|
43
|
-
return `\n[Argus
|
|
99
|
+
if (unavailable) {
|
|
100
|
+
logger.info(`Tool unavailable fallback for ${tool}`)
|
|
101
|
+
return `\n[Argus Fallback] ${entry.fallback}`
|
|
44
102
|
}
|
|
45
103
|
|
|
46
|
-
|
|
104
|
+
const installHint = entry.install ? ` (install: ${entry.install})` : ""
|
|
105
|
+
logger.info(`Tool error recovery hint for ${tool}`)
|
|
106
|
+
return `\n[Argus Recovery Hint] ${toolBase} error${installHint}. ${entry.fallback}`
|
|
47
107
|
}
|
|
48
108
|
}
|
package/src/features/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
1
|
+
export * from "./audit-enforcer"
|
|
2
|
+
export * from "./background-agent"
|
|
3
|
+
export * from "./context-monitor"
|
|
4
|
+
export * from "./error-recovery"
|
|
5
|
+
export * from "./persistent-state"
|