pentesting 0.12.13 → 0.16.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 +90 -95
- package/dist/main.js +3103 -0
- package/package.json +13 -13
- package/dist/auto-update-6CLBRLE3.js +0 -24
- package/dist/chunk-3RG5ZIWI.js +0 -10
- package/dist/chunk-5IKQY4A4.js +0 -134
- package/dist/chunk-6IXHQS2A.js +0 -525
- package/dist/chunk-AOJBE232.js +0 -457
- package/dist/index.js +0 -16445
- package/dist/replay-ABCV4F64.js +0 -130
- package/dist/skill-2AON6M2V.js +0 -416
- package/dist/update-34NDFWS3.js +0 -24
- package/dist/web-search-XQYEM24B.js +0 -43
- package/src/agents/specs/crypto.yaml +0 -79
- package/src/agents/specs/default.yaml +0 -60
- package/src/agents/specs/exploit.yaml +0 -70
- package/src/agents/specs/privesc.yaml +0 -83
- package/src/agents/specs/recon.yaml +0 -65
- package/src/agents/specs/web.yaml +0 -73
- /package/dist/{index.d.ts → main.d.ts} +0 -0
package/dist/replay-ABCV4F64.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
__require
|
|
3
|
-
} from "./chunk-3RG5ZIWI.js";
|
|
4
|
-
|
|
5
|
-
// src/core/replay/session-replay.ts
|
|
6
|
-
import { existsSync, readFileSync } from "fs";
|
|
7
|
-
function parseWireFile(filePath) {
|
|
8
|
-
if (!existsSync(filePath)) return [];
|
|
9
|
-
const events = [];
|
|
10
|
-
const content = readFileSync(filePath, "utf-8");
|
|
11
|
-
for (const line of content.split("\n")) {
|
|
12
|
-
if (!line.trim()) continue;
|
|
13
|
-
try {
|
|
14
|
-
const record = JSON.parse(line);
|
|
15
|
-
events.push({
|
|
16
|
-
type: record.message.type,
|
|
17
|
-
timestamp: record.message.timestamp,
|
|
18
|
-
data: record.message.data
|
|
19
|
-
});
|
|
20
|
-
} catch {
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return events;
|
|
24
|
-
}
|
|
25
|
-
function getReplaySummary(events) {
|
|
26
|
-
if (events.length === 0) {
|
|
27
|
-
return { events, duration: 0, toolCalls: 0, findings: 0 };
|
|
28
|
-
}
|
|
29
|
-
const firstTs = events[0].timestamp;
|
|
30
|
-
const lastTs = events[events.length - 1].timestamp;
|
|
31
|
-
const duration = (lastTs - firstTs) / 1e3;
|
|
32
|
-
let toolCalls = 0;
|
|
33
|
-
let findings = 0;
|
|
34
|
-
for (const event of events) {
|
|
35
|
-
if (event.type === "tool_call") toolCalls++;
|
|
36
|
-
if (event.type === "status_update") {
|
|
37
|
-
const data = event.data;
|
|
38
|
-
if (data.event === "finding") findings++;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return { events, duration, toolCalls, findings };
|
|
42
|
-
}
|
|
43
|
-
function formatReplayEvent(event) {
|
|
44
|
-
const time = new Date(event.timestamp).toLocaleTimeString();
|
|
45
|
-
switch (event.type) {
|
|
46
|
-
case "turn_begin":
|
|
47
|
-
return `[${time}] \u{1F504} Turn started`;
|
|
48
|
-
case "step_begin": {
|
|
49
|
-
const data = event.data;
|
|
50
|
-
return `[${time}] \u{1F4CD} Step ${data.stepIndex + 1}`;
|
|
51
|
-
}
|
|
52
|
-
case "content_part": {
|
|
53
|
-
const data = event.data;
|
|
54
|
-
const preview = data.content.slice(0, 50).replace(/\n/g, " ");
|
|
55
|
-
const icon = data.isThinking ? "\u{1F4AD}" : "\u{1F4AC}";
|
|
56
|
-
return `[${time}] ${icon} ${preview}...`;
|
|
57
|
-
}
|
|
58
|
-
case "tool_call": {
|
|
59
|
-
const data = event.data;
|
|
60
|
-
return `[${time}] Tool: ${data.toolName}`;
|
|
61
|
-
}
|
|
62
|
-
case "tool_result": {
|
|
63
|
-
const data = event.data;
|
|
64
|
-
const icon = data.isError ? "\u2717" : "\u2713";
|
|
65
|
-
return `[${time}] ${icon} Tool result`;
|
|
66
|
-
}
|
|
67
|
-
case "status_update": {
|
|
68
|
-
const data = event.data;
|
|
69
|
-
if (data.event === "finding") {
|
|
70
|
-
return `[${time}] \u{1F3AF} Finding: ${data.title}`;
|
|
71
|
-
}
|
|
72
|
-
if (data.event === "phase_change") {
|
|
73
|
-
return `[${time}] \u{1F4CD} Phase: ${data.phase}`;
|
|
74
|
-
}
|
|
75
|
-
return `[${time}] \u{1F4CA} ${data.event}`;
|
|
76
|
-
}
|
|
77
|
-
case "turn_end":
|
|
78
|
-
return `[${time}] \u2713 Turn complete`;
|
|
79
|
-
default:
|
|
80
|
-
return `[${time}] ${event.type}`;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async function replaySession(wirePath, options = {}) {
|
|
84
|
-
const events = parseWireFile(wirePath);
|
|
85
|
-
const summary = getReplaySummary(events);
|
|
86
|
-
if (events.length === 0) return summary;
|
|
87
|
-
const speed = options.speed ?? 0;
|
|
88
|
-
let lastTs = events[0].timestamp;
|
|
89
|
-
for (const event of events) {
|
|
90
|
-
const formatted = formatReplayEvent(event);
|
|
91
|
-
if (options.onEvent) {
|
|
92
|
-
options.onEvent(event, formatted);
|
|
93
|
-
}
|
|
94
|
-
if (speed > 0) {
|
|
95
|
-
const delay = (event.timestamp - lastTs) / speed;
|
|
96
|
-
if (delay > 0 && delay < 5e3) {
|
|
97
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
98
|
-
}
|
|
99
|
-
lastTs = event.timestamp;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return summary;
|
|
103
|
-
}
|
|
104
|
-
function findRecentWireFiles(sessionDir, limit = 10) {
|
|
105
|
-
const { readdirSync, statSync } = __require("fs");
|
|
106
|
-
const { join } = __require("path");
|
|
107
|
-
if (!existsSync(sessionDir)) return [];
|
|
108
|
-
const files = [];
|
|
109
|
-
try {
|
|
110
|
-
const entries = readdirSync(sessionDir, { withFileTypes: true });
|
|
111
|
-
for (const entry of entries) {
|
|
112
|
-
if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
113
|
-
const filePath = join(sessionDir, entry.name);
|
|
114
|
-
const stat = statSync(filePath);
|
|
115
|
-
files.push({ path: filePath, mtime: stat.mtimeMs });
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
} catch {
|
|
119
|
-
return [];
|
|
120
|
-
}
|
|
121
|
-
files.sort((a, b) => b.mtime - a.mtime);
|
|
122
|
-
return files.slice(0, limit).map((f) => f.path);
|
|
123
|
-
}
|
|
124
|
-
export {
|
|
125
|
-
findRecentWireFiles,
|
|
126
|
-
formatReplayEvent,
|
|
127
|
-
getReplaySummary,
|
|
128
|
-
parseWireFile,
|
|
129
|
-
replaySession
|
|
130
|
-
};
|
package/dist/skill-2AON6M2V.js
DELETED
|
@@ -1,416 +0,0 @@
|
|
|
1
|
-
import "./chunk-3RG5ZIWI.js";
|
|
2
|
-
|
|
3
|
-
// src/core/skill/flow.ts
|
|
4
|
-
var FlowError = class extends Error {
|
|
5
|
-
constructor(message) {
|
|
6
|
-
super(message);
|
|
7
|
-
this.name = "FlowError";
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
var FlowParseError = class extends FlowError {
|
|
11
|
-
constructor(message) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.name = "FlowParseError";
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
var FlowValidationError = class extends FlowError {
|
|
17
|
-
constructor(message) {
|
|
18
|
-
super(message);
|
|
19
|
-
this.name = "FlowValidationError";
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
function parseChoice(text) {
|
|
23
|
-
const match = text.match(/<choice>([^<]*)<\/choice>/);
|
|
24
|
-
return match ? match[1].trim() : null;
|
|
25
|
-
}
|
|
26
|
-
function validateFlow(nodes, outgoing) {
|
|
27
|
-
const beginNodes = Array.from(nodes.values()).filter((n) => n.kind === "begin");
|
|
28
|
-
const endNodes = Array.from(nodes.values()).filter((n) => n.kind === "end");
|
|
29
|
-
if (beginNodes.length !== 1) {
|
|
30
|
-
throw new FlowValidationError(`Expected exactly one BEGIN node, found ${beginNodes.length}`);
|
|
31
|
-
}
|
|
32
|
-
if (endNodes.length !== 1) {
|
|
33
|
-
throw new FlowValidationError(`Expected exactly one END node, found ${endNodes.length}`);
|
|
34
|
-
}
|
|
35
|
-
const beginId = beginNodes[0].id;
|
|
36
|
-
const endId = endNodes[0].id;
|
|
37
|
-
const reachable = /* @__PURE__ */ new Set();
|
|
38
|
-
const queue = [beginId];
|
|
39
|
-
while (queue.length > 0) {
|
|
40
|
-
const nodeId = queue.pop();
|
|
41
|
-
if (reachable.has(nodeId)) continue;
|
|
42
|
-
reachable.add(nodeId);
|
|
43
|
-
const edges = outgoing.get(nodeId) || [];
|
|
44
|
-
for (const edge of edges) {
|
|
45
|
-
if (!reachable.has(edge.dst)) {
|
|
46
|
-
queue.push(edge.dst);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
if (!reachable.has(endId)) {
|
|
51
|
-
throw new FlowValidationError("END node is not reachable from BEGIN");
|
|
52
|
-
}
|
|
53
|
-
for (const node of nodes.values()) {
|
|
54
|
-
if (!reachable.has(node.id)) continue;
|
|
55
|
-
const edges = outgoing.get(node.id) || [];
|
|
56
|
-
if (edges.length <= 1) continue;
|
|
57
|
-
const labels = [];
|
|
58
|
-
for (const edge of edges) {
|
|
59
|
-
if (!edge.label?.trim()) {
|
|
60
|
-
throw new FlowValidationError(`Node "${node.id}" has an unlabeled edge`);
|
|
61
|
-
}
|
|
62
|
-
labels.push(edge.label);
|
|
63
|
-
}
|
|
64
|
-
if (new Set(labels).size !== labels.length) {
|
|
65
|
-
throw new FlowValidationError(`Node "${node.id}" has duplicate edge labels`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return { beginId, endId };
|
|
69
|
-
}
|
|
70
|
-
function parseMermaidFlowchart(code) {
|
|
71
|
-
const nodes = /* @__PURE__ */ new Map();
|
|
72
|
-
const outgoing = /* @__PURE__ */ new Map();
|
|
73
|
-
const lines = code.split("\n").map((l) => l.trim()).filter((l) => l);
|
|
74
|
-
for (const line of lines) {
|
|
75
|
-
if (line.match(/^flowchart|^graph/i)) continue;
|
|
76
|
-
const nodeMatch = line.match(/^([A-Za-z0-9_]+)(\[([^\]]+)\]|\{([^\}]+)\}|\(\(([^\)]+)\)\)|\(\[([^\]]+)\]\))?$/);
|
|
77
|
-
if (nodeMatch && !line.includes("-->")) {
|
|
78
|
-
const id = nodeMatch[1];
|
|
79
|
-
const label = nodeMatch[3] || nodeMatch[4] || nodeMatch[5] || nodeMatch[6] || id;
|
|
80
|
-
let kind = "task";
|
|
81
|
-
if (nodeMatch[4]) kind = "decision";
|
|
82
|
-
else if (nodeMatch[5] || label.toLowerCase().includes("start") || label.toLowerCase().includes("begin")) kind = "begin";
|
|
83
|
-
else if (nodeMatch[6] || label.toLowerCase().includes("end")) kind = "end";
|
|
84
|
-
nodes.set(id, { id, label, kind });
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
const edgeMatch = line.match(/^([A-Za-z0-9_]+)\s*-->\s*(?:\|([^\|]+)\|\s*)?([A-Za-z0-9_]+)/);
|
|
88
|
-
if (edgeMatch) {
|
|
89
|
-
const src = edgeMatch[1];
|
|
90
|
-
const label = edgeMatch[2] || null;
|
|
91
|
-
const dst = edgeMatch[3];
|
|
92
|
-
if (!nodes.has(src)) nodes.set(src, { id: src, label: src, kind: "task" });
|
|
93
|
-
if (!nodes.has(dst)) nodes.set(dst, { id: dst, label: dst, kind: "task" });
|
|
94
|
-
const edges = outgoing.get(src) || [];
|
|
95
|
-
edges.push({ src, dst, label });
|
|
96
|
-
outgoing.set(src, edges);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
const { beginId, endId } = validateFlow(nodes, outgoing);
|
|
100
|
-
return { nodes, outgoing, beginId, endId };
|
|
101
|
-
}
|
|
102
|
-
function parseD2Flowchart(code) {
|
|
103
|
-
const nodes = /* @__PURE__ */ new Map();
|
|
104
|
-
const outgoing = /* @__PURE__ */ new Map();
|
|
105
|
-
const lines = code.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
106
|
-
for (const line of lines) {
|
|
107
|
-
const edgeMatch = line.match(/^([A-Za-z0-9_]+)\s*->\s*([A-Za-z0-9_]+)(?:\s*:\s*(.+))?$/);
|
|
108
|
-
if (edgeMatch) {
|
|
109
|
-
const src = edgeMatch[1];
|
|
110
|
-
const dst = edgeMatch[2];
|
|
111
|
-
const label = edgeMatch[3] || null;
|
|
112
|
-
if (!nodes.has(src)) {
|
|
113
|
-
const kind = src.toLowerCase().includes("start") ? "begin" : "task";
|
|
114
|
-
nodes.set(src, { id: src, label: src, kind });
|
|
115
|
-
}
|
|
116
|
-
if (!nodes.has(dst)) {
|
|
117
|
-
const kind = dst.toLowerCase().includes("end") ? "end" : "task";
|
|
118
|
-
nodes.set(dst, { id: dst, label: dst, kind });
|
|
119
|
-
}
|
|
120
|
-
const edges = outgoing.get(src) || [];
|
|
121
|
-
edges.push({ src, dst, label });
|
|
122
|
-
outgoing.set(src, edges);
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
const nodeMatch = line.match(/^([A-Za-z0-9_]+)\s*:\s*"?([^"{}]+)"?\s*(?:\{([^}]+)\})?$/);
|
|
126
|
-
if (nodeMatch) {
|
|
127
|
-
const id = nodeMatch[1];
|
|
128
|
-
const label = nodeMatch[2].trim();
|
|
129
|
-
const attrs = nodeMatch[3] || "";
|
|
130
|
-
let kind = "task";
|
|
131
|
-
if (attrs.includes("diamond")) kind = "decision";
|
|
132
|
-
else if (attrs.includes("oval") && label.toLowerCase().includes("start")) kind = "begin";
|
|
133
|
-
else if (attrs.includes("oval") && label.toLowerCase().includes("end")) kind = "end";
|
|
134
|
-
nodes.set(id, { id, label, kind });
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
const { beginId, endId } = validateFlow(nodes, outgoing);
|
|
138
|
-
return { nodes, outgoing, beginId, endId };
|
|
139
|
-
}
|
|
140
|
-
var FlowExecutor = class {
|
|
141
|
-
flow;
|
|
142
|
-
currentNodeId;
|
|
143
|
-
moveCount = 0;
|
|
144
|
-
maxMoves;
|
|
145
|
-
constructor(flow, maxMoves = 1e3) {
|
|
146
|
-
this.flow = flow;
|
|
147
|
-
this.currentNodeId = flow.beginId;
|
|
148
|
-
this.maxMoves = maxMoves;
|
|
149
|
-
}
|
|
150
|
-
get currentNode() {
|
|
151
|
-
return this.flow.nodes.get(this.currentNodeId);
|
|
152
|
-
}
|
|
153
|
-
get isComplete() {
|
|
154
|
-
return this.currentNodeId === this.flow.endId;
|
|
155
|
-
}
|
|
156
|
-
get availableChoices() {
|
|
157
|
-
const edges = this.flow.outgoing.get(this.currentNodeId) || [];
|
|
158
|
-
return edges.filter((e) => e.label).map((e) => e.label);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Move to next node
|
|
162
|
-
*/
|
|
163
|
-
move(choice) {
|
|
164
|
-
if (this.isComplete) {
|
|
165
|
-
throw new FlowError("Flow is already complete");
|
|
166
|
-
}
|
|
167
|
-
if (this.moveCount >= this.maxMoves) {
|
|
168
|
-
throw new FlowError(`Max moves (${this.maxMoves}) exceeded`);
|
|
169
|
-
}
|
|
170
|
-
const edges = this.flow.outgoing.get(this.currentNodeId) || [];
|
|
171
|
-
if (edges.length === 0) {
|
|
172
|
-
throw new FlowError(`No outgoing edges from node "${this.currentNodeId}"`);
|
|
173
|
-
}
|
|
174
|
-
let nextEdge;
|
|
175
|
-
if (edges.length === 1) {
|
|
176
|
-
nextEdge = edges[0];
|
|
177
|
-
} else if (choice) {
|
|
178
|
-
nextEdge = edges.find((e) => e.label?.toLowerCase() === choice.toLowerCase());
|
|
179
|
-
if (!nextEdge) {
|
|
180
|
-
throw new FlowError(`Invalid choice "${choice}". Available: ${this.availableChoices.join(", ")}`);
|
|
181
|
-
}
|
|
182
|
-
} else {
|
|
183
|
-
throw new FlowError(`Choice required. Available: ${this.availableChoices.join(", ")}`);
|
|
184
|
-
}
|
|
185
|
-
this.currentNodeId = nextEdge.dst;
|
|
186
|
-
this.moveCount++;
|
|
187
|
-
return this.currentNode;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Reset flow
|
|
191
|
-
*/
|
|
192
|
-
reset() {
|
|
193
|
-
this.currentNodeId = this.flow.beginId;
|
|
194
|
-
this.moveCount = 0;
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
// src/core/skill/skill.ts
|
|
199
|
-
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
200
|
-
import { join } from "path";
|
|
201
|
-
import { homedir } from "os";
|
|
202
|
-
function getBuiltinSkillsDir() {
|
|
203
|
-
return join(__dirname, "..", "..", "skills");
|
|
204
|
-
}
|
|
205
|
-
function getUserSkillsDirCandidates() {
|
|
206
|
-
return [
|
|
207
|
-
join(homedir(), ".config", "agents", "skills"),
|
|
208
|
-
join(homedir(), ".agents", "skills"),
|
|
209
|
-
join(homedir(), ".pentest", "skills"),
|
|
210
|
-
join(homedir(), ".claude", "skills")
|
|
211
|
-
];
|
|
212
|
-
}
|
|
213
|
-
function getProjectSkillsDirCandidates(workDir) {
|
|
214
|
-
return [
|
|
215
|
-
join(workDir, ".agents", "skills"),
|
|
216
|
-
join(workDir, ".pentest", "skills"),
|
|
217
|
-
join(workDir, ".claude", "skills")
|
|
218
|
-
];
|
|
219
|
-
}
|
|
220
|
-
function findFirstExistingDir(candidates) {
|
|
221
|
-
for (const candidate of candidates) {
|
|
222
|
-
if (existsSync(candidate)) {
|
|
223
|
-
return candidate;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
function parseFrontmatter(content) {
|
|
229
|
-
const match = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
|
|
230
|
-
if (!match) return {};
|
|
231
|
-
const yaml = match[1];
|
|
232
|
-
const result = {};
|
|
233
|
-
for (const line of yaml.split("\n")) {
|
|
234
|
-
const colonIndex = line.indexOf(":");
|
|
235
|
-
if (colonIndex > 0) {
|
|
236
|
-
const key = line.slice(0, colonIndex).trim();
|
|
237
|
-
const value = line.slice(colonIndex + 1).trim().replace(/^["']|["']$/g, "");
|
|
238
|
-
result[key] = value;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return result;
|
|
242
|
-
}
|
|
243
|
-
function extractCodeBlocks(content) {
|
|
244
|
-
const blocks = [];
|
|
245
|
-
const regex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
246
|
-
let match;
|
|
247
|
-
while ((match = regex.exec(content)) !== null) {
|
|
248
|
-
blocks.push({
|
|
249
|
-
lang: (match[1] || "").toLowerCase(),
|
|
250
|
-
code: match[2].trim()
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
return blocks;
|
|
254
|
-
}
|
|
255
|
-
function parseSkillText(content, dirPath) {
|
|
256
|
-
const frontmatter = parseFrontmatter(content);
|
|
257
|
-
const name = frontmatter.name || dirPath.split("/").pop() || "unnamed";
|
|
258
|
-
const description = frontmatter.description || "No description provided.";
|
|
259
|
-
const skillType = frontmatter.type || "standard";
|
|
260
|
-
let flow;
|
|
261
|
-
if (skillType === "flow") {
|
|
262
|
-
try {
|
|
263
|
-
const codeBlocks = extractCodeBlocks(content);
|
|
264
|
-
for (const block of codeBlocks) {
|
|
265
|
-
if (block.lang === "mermaid") {
|
|
266
|
-
flow = parseMermaidFlowchart(block.code);
|
|
267
|
-
break;
|
|
268
|
-
} else if (block.lang === "d2") {
|
|
269
|
-
flow = parseD2Flowchart(block.code);
|
|
270
|
-
break;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if (!flow) {
|
|
274
|
-
throw new FlowError("Flow skills require a mermaid or d2 code block");
|
|
275
|
-
}
|
|
276
|
-
} catch (e) {
|
|
277
|
-
console.error(`Failed to parse flow skill ${name}:`, e);
|
|
278
|
-
return {
|
|
279
|
-
name,
|
|
280
|
-
description,
|
|
281
|
-
type: "standard",
|
|
282
|
-
dir: dirPath,
|
|
283
|
-
content
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
return {
|
|
288
|
-
name,
|
|
289
|
-
description,
|
|
290
|
-
type: skillType,
|
|
291
|
-
dir: dirPath,
|
|
292
|
-
flow,
|
|
293
|
-
content
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
function discoverSkills(skillsDir) {
|
|
297
|
-
if (!existsSync(skillsDir)) return [];
|
|
298
|
-
const skills = [];
|
|
299
|
-
try {
|
|
300
|
-
const entries = readdirSync(skillsDir, { withFileTypes: true });
|
|
301
|
-
for (const entry of entries) {
|
|
302
|
-
if (!entry.isDirectory()) continue;
|
|
303
|
-
const skillDir = join(skillsDir, entry.name);
|
|
304
|
-
const skillMd = join(skillDir, "SKILL.md");
|
|
305
|
-
if (!existsSync(skillMd)) continue;
|
|
306
|
-
try {
|
|
307
|
-
const content = readFileSync(skillMd, "utf-8");
|
|
308
|
-
const skill = parseSkillText(content, skillDir);
|
|
309
|
-
skills.push(skill);
|
|
310
|
-
} catch {
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
} catch {
|
|
314
|
-
}
|
|
315
|
-
return skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
316
|
-
}
|
|
317
|
-
function discoverSkillsFromRoots(skillsDirs) {
|
|
318
|
-
const skillsByName = /* @__PURE__ */ new Map();
|
|
319
|
-
for (const dir of skillsDirs) {
|
|
320
|
-
for (const skill of discoverSkills(dir)) {
|
|
321
|
-
skillsByName.set(skill.name.toLowerCase(), skill);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
return Array.from(skillsByName.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
325
|
-
}
|
|
326
|
-
function resolveSkillRoots(workDir) {
|
|
327
|
-
const roots = [];
|
|
328
|
-
const builtinDir = getBuiltinSkillsDir();
|
|
329
|
-
if (existsSync(builtinDir)) {
|
|
330
|
-
roots.push(builtinDir);
|
|
331
|
-
}
|
|
332
|
-
const userDir = findFirstExistingDir(getUserSkillsDirCandidates());
|
|
333
|
-
if (userDir) {
|
|
334
|
-
roots.push(userDir);
|
|
335
|
-
}
|
|
336
|
-
const projectDir = findFirstExistingDir(getProjectSkillsDirCandidates(workDir));
|
|
337
|
-
if (projectDir) {
|
|
338
|
-
roots.push(projectDir);
|
|
339
|
-
}
|
|
340
|
-
return roots;
|
|
341
|
-
}
|
|
342
|
-
var SkillManager = class {
|
|
343
|
-
skills = /* @__PURE__ */ new Map();
|
|
344
|
-
workDir;
|
|
345
|
-
constructor(workDir) {
|
|
346
|
-
this.workDir = workDir || process.cwd();
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* Load all skills
|
|
350
|
-
*/
|
|
351
|
-
load() {
|
|
352
|
-
const roots = resolveSkillRoots(this.workDir);
|
|
353
|
-
const skills = discoverSkillsFromRoots(roots);
|
|
354
|
-
this.skills.clear();
|
|
355
|
-
for (const skill of skills) {
|
|
356
|
-
this.skills.set(skill.name.toLowerCase(), skill);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* Find skill by name
|
|
361
|
-
*/
|
|
362
|
-
find(name) {
|
|
363
|
-
return this.skills.get(name.toLowerCase());
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* List all skills
|
|
367
|
-
*/
|
|
368
|
-
list() {
|
|
369
|
-
return Array.from(this.skills.values());
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Get skill content
|
|
373
|
-
*/
|
|
374
|
-
getContent(name) {
|
|
375
|
-
const skill = this.find(name);
|
|
376
|
-
return skill?.content || null;
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Format skills for system prompt
|
|
380
|
-
*/
|
|
381
|
-
formatForPrompt() {
|
|
382
|
-
const skills = this.list();
|
|
383
|
-
if (skills.length === 0) return "No skills found.";
|
|
384
|
-
return skills.map(
|
|
385
|
-
(s) => `- ${s.name}
|
|
386
|
-
- Type: ${s.type}
|
|
387
|
-
- Description: ${s.description}`
|
|
388
|
-
).join("\n");
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
var skillManager = null;
|
|
392
|
-
function getSkillManager(workDir) {
|
|
393
|
-
if (!skillManager) {
|
|
394
|
-
skillManager = new SkillManager(workDir);
|
|
395
|
-
skillManager.load();
|
|
396
|
-
}
|
|
397
|
-
return skillManager;
|
|
398
|
-
}
|
|
399
|
-
export {
|
|
400
|
-
FlowError,
|
|
401
|
-
FlowExecutor,
|
|
402
|
-
FlowParseError,
|
|
403
|
-
FlowValidationError,
|
|
404
|
-
SkillManager,
|
|
405
|
-
discoverSkills,
|
|
406
|
-
discoverSkillsFromRoots,
|
|
407
|
-
extractCodeBlocks,
|
|
408
|
-
getSkillManager,
|
|
409
|
-
parseChoice,
|
|
410
|
-
parseD2Flowchart,
|
|
411
|
-
parseFrontmatter,
|
|
412
|
-
parseMermaidFlowchart,
|
|
413
|
-
parseSkillText,
|
|
414
|
-
resolveSkillRoots,
|
|
415
|
-
validateFlow
|
|
416
|
-
};
|
package/dist/update-34NDFWS3.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
checkForUpdate,
|
|
3
|
-
checkForUpdateAsync,
|
|
4
|
-
compareSemver,
|
|
5
|
-
doUpdate,
|
|
6
|
-
fetchLatestVersion,
|
|
7
|
-
formatUpdateNotification,
|
|
8
|
-
readVersionCache,
|
|
9
|
-
semverTuple,
|
|
10
|
-
writeVersionCache
|
|
11
|
-
} from "./chunk-5IKQY4A4.js";
|
|
12
|
-
import "./chunk-6IXHQS2A.js";
|
|
13
|
-
import "./chunk-3RG5ZIWI.js";
|
|
14
|
-
export {
|
|
15
|
-
checkForUpdate,
|
|
16
|
-
checkForUpdateAsync,
|
|
17
|
-
compareSemver,
|
|
18
|
-
doUpdate,
|
|
19
|
-
fetchLatestVersion,
|
|
20
|
-
formatUpdateNotification,
|
|
21
|
-
readVersionCache,
|
|
22
|
-
semverTuple,
|
|
23
|
-
writeVersionCache
|
|
24
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
closeBrowser,
|
|
3
|
-
ctfResearch,
|
|
4
|
-
deepSearch,
|
|
5
|
-
fetchUrlContent,
|
|
6
|
-
searchADWriteups,
|
|
7
|
-
searchBing,
|
|
8
|
-
searchBrave,
|
|
9
|
-
searchByScenario,
|
|
10
|
-
searchCVE,
|
|
11
|
-
searchDuckDuckGo,
|
|
12
|
-
searchExploits,
|
|
13
|
-
searchGoogle,
|
|
14
|
-
searchLinuxPrivesc,
|
|
15
|
-
searchMachineWriteup,
|
|
16
|
-
searchWindowsPrivesc,
|
|
17
|
-
searchWriteups,
|
|
18
|
-
searchYahoo,
|
|
19
|
-
securityResearch,
|
|
20
|
-
unifiedSearch
|
|
21
|
-
} from "./chunk-AOJBE232.js";
|
|
22
|
-
import "./chunk-3RG5ZIWI.js";
|
|
23
|
-
export {
|
|
24
|
-
closeBrowser,
|
|
25
|
-
ctfResearch,
|
|
26
|
-
deepSearch,
|
|
27
|
-
fetchUrlContent,
|
|
28
|
-
searchADWriteups,
|
|
29
|
-
searchBing,
|
|
30
|
-
searchBrave,
|
|
31
|
-
searchByScenario,
|
|
32
|
-
searchCVE,
|
|
33
|
-
searchDuckDuckGo,
|
|
34
|
-
searchExploits,
|
|
35
|
-
searchGoogle,
|
|
36
|
-
searchLinuxPrivesc,
|
|
37
|
-
searchMachineWriteup,
|
|
38
|
-
searchWindowsPrivesc,
|
|
39
|
-
searchWriteups,
|
|
40
|
-
searchYahoo,
|
|
41
|
-
securityResearch,
|
|
42
|
-
unifiedSearch
|
|
43
|
-
};
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
version: 1
|
|
2
|
-
agent:
|
|
3
|
-
name: crypto
|
|
4
|
-
description: Cryptography & Password Cracking Expert
|
|
5
|
-
extends: ./default.yaml
|
|
6
|
-
|
|
7
|
-
system_prompt: |
|
|
8
|
-
# Cryptography Expert
|
|
9
|
-
|
|
10
|
-
You specialize in cryptographic analysis and password cracking.
|
|
11
|
-
|
|
12
|
-
## Hash Identification
|
|
13
|
-
```bash
|
|
14
|
-
hashid HASH
|
|
15
|
-
hash-identifier
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Hash Types & Hashcat Modes
|
|
19
|
-
|
|
20
|
-
| Hash Type | Example | Hashcat Mode |
|
|
21
|
-
|-----------|---------|--------------|
|
|
22
|
-
| MD5 | 32 hex chars | 0 |
|
|
23
|
-
| SHA1 | 40 hex chars | 100 |
|
|
24
|
-
| SHA256 | 64 hex chars | 1400 |
|
|
25
|
-
| NTLM | 32 hex chars | 1000 |
|
|
26
|
-
| bcrypt | $2a$... | 3200 |
|
|
27
|
-
| Kerberos TGS | $krb5tgs$... | 13100 |
|
|
28
|
-
|
|
29
|
-
## Cracking Strategy
|
|
30
|
-
|
|
31
|
-
### 1. Try Common Passwords First
|
|
32
|
-
```bash
|
|
33
|
-
# rockyou top 1000
|
|
34
|
-
hashcat -m MODE hash.txt /usr/share/wordlists/rockyou.txt --force
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### 2. Apply Rules
|
|
38
|
-
```bash
|
|
39
|
-
hashcat -m MODE hash.txt wordlist.txt -r /usr/share/hashcat/rules/best64.rule
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### 3. Targeted Wordlists
|
|
43
|
-
- Company name variations
|
|
44
|
-
- Username + common patterns
|
|
45
|
-
- Previously leaked passwords
|
|
46
|
-
|
|
47
|
-
## Encoding Detection
|
|
48
|
-
- Base64: ends with = or ==
|
|
49
|
-
- URL encoding: %XX format
|
|
50
|
-
- Hex: only 0-9, a-f
|
|
51
|
-
- ROT13: Caesar cipher
|
|
52
|
-
|
|
53
|
-
## Output Format
|
|
54
|
-
```
|
|
55
|
-
🔐 CRYPTO ANALYSIS
|
|
56
|
-
==================
|
|
57
|
-
Hash: [hash value]
|
|
58
|
-
Type: [detected type]
|
|
59
|
-
|
|
60
|
-
🔓 Cracking Attempt:
|
|
61
|
-
- Method: [dictionary/rules/bruteforce]
|
|
62
|
-
- Wordlist: [wordlist used]
|
|
63
|
-
- Status: [CRACKED/IN PROGRESS/FAILED]
|
|
64
|
-
|
|
65
|
-
✅ Result:
|
|
66
|
-
[plaintext if cracked]
|
|
67
|
-
|
|
68
|
-
💡 Next Steps:
|
|
69
|
-
- [try different wordlist]
|
|
70
|
-
- [apply more rules]
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
tools:
|
|
74
|
-
- bash
|
|
75
|
-
- hashcat
|
|
76
|
-
- john
|
|
77
|
-
- hashid
|
|
78
|
-
- base64
|
|
79
|
-
- openssl
|