pentesting 0.12.13 → 0.14.1
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 +6 -95
- package/dist/{chunk-6IXHQS2A.js → chunk-5KIJPRTS.js} +315 -8
- package/dist/{chunk-AOJBE232.js → chunk-M2IFHZDV.js} +148 -3
- package/dist/index.js +3452 -1082
- package/dist/{skill-2AON6M2V.js → skill-NGH4KQUH.js} +210 -15
- package/dist/{web-search-XQYEM24B.js → web-search-IOD4SUIR.js} +9 -3
- package/package.json +6 -6
- package/dist/auto-update-6CLBRLE3.js +0 -24
- package/dist/chunk-5IKQY4A4.js +0 -134
- package/dist/replay-ABCV4F64.js +0 -130
- package/dist/update-34NDFWS3.js +0 -24
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PATHS
|
|
3
|
+
} from "./chunk-5KIJPRTS.js";
|
|
1
4
|
import "./chunk-3RG5ZIWI.js";
|
|
2
5
|
|
|
6
|
+
// src/core/skill/skill.ts
|
|
7
|
+
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
|
|
3
11
|
// src/core/skill/flow.ts
|
|
4
12
|
var FlowError = class extends Error {
|
|
5
13
|
constructor(message) {
|
|
@@ -7,12 +15,6 @@ var FlowError = class extends Error {
|
|
|
7
15
|
this.name = "FlowError";
|
|
8
16
|
}
|
|
9
17
|
};
|
|
10
|
-
var FlowParseError = class extends FlowError {
|
|
11
|
-
constructor(message) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.name = "FlowParseError";
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
18
|
var FlowValidationError = class extends FlowError {
|
|
17
19
|
constructor(message) {
|
|
18
20
|
super(message);
|
|
@@ -196,9 +198,6 @@ var FlowExecutor = class {
|
|
|
196
198
|
};
|
|
197
199
|
|
|
198
200
|
// src/core/skill/skill.ts
|
|
199
|
-
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
200
|
-
import { join } from "path";
|
|
201
|
-
import { homedir } from "os";
|
|
202
201
|
function getBuiltinSkillsDir() {
|
|
203
202
|
return join(__dirname, "..", "..", "skills");
|
|
204
203
|
}
|
|
@@ -206,14 +205,14 @@ function getUserSkillsDirCandidates() {
|
|
|
206
205
|
return [
|
|
207
206
|
join(homedir(), ".config", "agents", "skills"),
|
|
208
207
|
join(homedir(), ".agents", "skills"),
|
|
209
|
-
|
|
208
|
+
PATHS.SKILLS,
|
|
210
209
|
join(homedir(), ".claude", "skills")
|
|
211
210
|
];
|
|
212
211
|
}
|
|
213
212
|
function getProjectSkillsDirCandidates(workDir) {
|
|
214
213
|
return [
|
|
215
214
|
join(workDir, ".agents", "skills"),
|
|
216
|
-
|
|
215
|
+
PATHS.SKILLS,
|
|
217
216
|
join(workDir, ".claude", "skills")
|
|
218
217
|
];
|
|
219
218
|
}
|
|
@@ -396,11 +395,208 @@ function getSkillManager(workDir) {
|
|
|
396
395
|
}
|
|
397
396
|
return skillManager;
|
|
398
397
|
}
|
|
398
|
+
|
|
399
|
+
// src/core/skill/skill-loader.ts
|
|
400
|
+
import { promises as fs } from "fs";
|
|
401
|
+
import path from "path";
|
|
402
|
+
import { EventEmitter } from "events";
|
|
403
|
+
var DEFAULT_CONFIG = {
|
|
404
|
+
skillDirs: [PATHS.SKILLS, PATHS.AGENT_SPECS],
|
|
405
|
+
filePatterns: ["*.md", "*.yaml", "*.yml"],
|
|
406
|
+
watchForChanges: false
|
|
407
|
+
};
|
|
408
|
+
function parseFrontmatter2(content) {
|
|
409
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
|
|
410
|
+
if (!match) {
|
|
411
|
+
return { metadata: {}, body: content };
|
|
412
|
+
}
|
|
413
|
+
const yamlBlock = match[1];
|
|
414
|
+
const body = match[2];
|
|
415
|
+
const metadata = {};
|
|
416
|
+
for (const line of yamlBlock.split("\n")) {
|
|
417
|
+
const kvMatch = line.match(/^(\w[\w-]*)\s*:\s*(.*)$/);
|
|
418
|
+
if (kvMatch) {
|
|
419
|
+
const key = kvMatch[1].trim();
|
|
420
|
+
let value = kvMatch[2].trim();
|
|
421
|
+
if (typeof value === "string" && value.startsWith("[") && value.endsWith("]")) {
|
|
422
|
+
value = value.slice(1, -1).split(",").map((s) => s.trim().replace(/^['"]|['"]$/g, ""));
|
|
423
|
+
} else if (value === "true") value = true;
|
|
424
|
+
else if (value === "false") value = false;
|
|
425
|
+
else if (!isNaN(Number(value)) && value !== "") value = Number(value);
|
|
426
|
+
metadata[key] = value;
|
|
427
|
+
}
|
|
428
|
+
const listMatch = line.match(/^\s+-\s+(.+)$/);
|
|
429
|
+
if (listMatch) {
|
|
430
|
+
const keys = Object.keys(metadata);
|
|
431
|
+
const lastKey = keys[keys.length - 1];
|
|
432
|
+
if (lastKey) {
|
|
433
|
+
const existing = metadata[lastKey];
|
|
434
|
+
if (Array.isArray(existing)) {
|
|
435
|
+
existing.push(listMatch[1].trim());
|
|
436
|
+
} else {
|
|
437
|
+
metadata[lastKey] = [existing, listMatch[1].trim()].filter(Boolean);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return { metadata, body };
|
|
443
|
+
}
|
|
444
|
+
var SkillLoader = class extends EventEmitter {
|
|
445
|
+
config;
|
|
446
|
+
skills = /* @__PURE__ */ new Map();
|
|
447
|
+
loaded = false;
|
|
448
|
+
constructor(config = {}) {
|
|
449
|
+
super();
|
|
450
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Load all skills from configured directories
|
|
454
|
+
*/
|
|
455
|
+
async loadAll() {
|
|
456
|
+
this.skills.clear();
|
|
457
|
+
let count = 0;
|
|
458
|
+
for (const dir of this.config.skillDirs) {
|
|
459
|
+
try {
|
|
460
|
+
const resolvedDir = path.resolve(dir);
|
|
461
|
+
const exists = await fs.access(resolvedDir).then(() => true).catch(() => false);
|
|
462
|
+
if (!exists) continue;
|
|
463
|
+
count += await this.loadFromDirectory(resolvedDir);
|
|
464
|
+
} catch {
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
this.loaded = true;
|
|
468
|
+
return count;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Load skills from a single directory (recursive)
|
|
472
|
+
*/
|
|
473
|
+
async loadFromDirectory(dir) {
|
|
474
|
+
let count = 0;
|
|
475
|
+
try {
|
|
476
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
477
|
+
for (const entry of entries) {
|
|
478
|
+
const fullPath = path.join(dir, entry.name);
|
|
479
|
+
if (entry.isDirectory()) {
|
|
480
|
+
const skillFile = path.join(fullPath, "SKILL.md");
|
|
481
|
+
const hasSkillFile = await fs.access(skillFile).then(() => true).catch(() => false);
|
|
482
|
+
if (hasSkillFile) {
|
|
483
|
+
const skill = await this.loadSkillFile(skillFile);
|
|
484
|
+
if (skill) {
|
|
485
|
+
this.skills.set(skill.name, skill);
|
|
486
|
+
count++;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
count += await this.loadFromDirectory(fullPath);
|
|
490
|
+
} else if (this.isSkillFile(entry.name)) {
|
|
491
|
+
const skill = await this.loadSkillFile(fullPath);
|
|
492
|
+
if (skill) {
|
|
493
|
+
this.skills.set(skill.name, skill);
|
|
494
|
+
count++;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
return count;
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Load a single skill file
|
|
504
|
+
*/
|
|
505
|
+
async loadSkillFile(filePath) {
|
|
506
|
+
try {
|
|
507
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
508
|
+
const { metadata, body } = parseFrontmatter2(content);
|
|
509
|
+
const name = String(metadata.name ?? path.basename(path.dirname(filePath)));
|
|
510
|
+
if (!name) return null;
|
|
511
|
+
const triggers = Array.isArray(metadata.triggers) ? metadata.triggers.map(String) : typeof metadata.triggers === "string" ? [metadata.triggers] : [];
|
|
512
|
+
const tools = Array.isArray(metadata.tools) ? metadata.tools.map(String) : typeof metadata.tools === "string" ? [metadata.tools] : [];
|
|
513
|
+
return {
|
|
514
|
+
name,
|
|
515
|
+
description: String(metadata.description ?? ""),
|
|
516
|
+
triggers,
|
|
517
|
+
tools,
|
|
518
|
+
phase: metadata.phase,
|
|
519
|
+
priority: metadata.priority,
|
|
520
|
+
instructions: body.trim(),
|
|
521
|
+
filePath,
|
|
522
|
+
metadata
|
|
523
|
+
};
|
|
524
|
+
} catch {
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Check if filename matches skill patterns
|
|
530
|
+
*/
|
|
531
|
+
isSkillFile(filename) {
|
|
532
|
+
return filename.endsWith(".md") || filename.endsWith(".yaml") || filename.endsWith(".yml");
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Match user input against skill triggers
|
|
536
|
+
*/
|
|
537
|
+
match(userInput) {
|
|
538
|
+
const input = userInput.toLowerCase();
|
|
539
|
+
const matches = [];
|
|
540
|
+
for (const [, skill] of this.skills) {
|
|
541
|
+
const matchedTriggers = [];
|
|
542
|
+
let score = 0;
|
|
543
|
+
for (const trigger of skill.triggers) {
|
|
544
|
+
if (input.includes(trigger.toLowerCase())) {
|
|
545
|
+
matchedTriggers.push(trigger);
|
|
546
|
+
score += trigger.length / input.length;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (matchedTriggers.length > 0) {
|
|
550
|
+
matches.push({ skill, score: Math.min(1, score), matchedTriggers });
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return matches.sort((a, b) => b.score - a.score);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Get a skill by name
|
|
557
|
+
*/
|
|
558
|
+
get(name) {
|
|
559
|
+
return this.skills.get(name);
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Get all loaded skills
|
|
563
|
+
*/
|
|
564
|
+
getAll() {
|
|
565
|
+
return Array.from(this.skills.values());
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Get skills by phase
|
|
569
|
+
*/
|
|
570
|
+
getByPhase(phase) {
|
|
571
|
+
return this.getAll().filter((s) => s.phase === phase);
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Check if skills are loaded
|
|
575
|
+
*/
|
|
576
|
+
isLoaded() {
|
|
577
|
+
return this.loaded;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Get skill count
|
|
581
|
+
*/
|
|
582
|
+
get count() {
|
|
583
|
+
return this.skills.size;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Format skills list for display
|
|
587
|
+
*/
|
|
588
|
+
formatList() {
|
|
589
|
+
const skills = this.getAll();
|
|
590
|
+
if (skills.length === 0) return "No skills loaded";
|
|
591
|
+
return skills.map(
|
|
592
|
+
(s) => `\u{1F4E6} ${s.name}: ${s.description} (triggers: ${s.triggers.join(", ")})`
|
|
593
|
+
).join("\n");
|
|
594
|
+
}
|
|
595
|
+
};
|
|
399
596
|
export {
|
|
400
597
|
FlowError,
|
|
401
598
|
FlowExecutor,
|
|
402
|
-
|
|
403
|
-
FlowValidationError,
|
|
599
|
+
SkillLoader,
|
|
404
600
|
SkillManager,
|
|
405
601
|
discoverSkills,
|
|
406
602
|
discoverSkillsFromRoots,
|
|
@@ -411,6 +607,5 @@ export {
|
|
|
411
607
|
parseFrontmatter,
|
|
412
608
|
parseMermaidFlowchart,
|
|
413
609
|
parseSkillText,
|
|
414
|
-
resolveSkillRoots
|
|
415
|
-
validateFlow
|
|
610
|
+
resolveSkillRoots
|
|
416
611
|
};
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ctfResearch,
|
|
4
4
|
deepSearch,
|
|
5
5
|
fetchUrlContent,
|
|
6
|
+
recursiveSearch,
|
|
6
7
|
searchADWriteups,
|
|
7
8
|
searchBing,
|
|
8
9
|
searchBrave,
|
|
@@ -17,14 +18,17 @@ import {
|
|
|
17
18
|
searchWriteups,
|
|
18
19
|
searchYahoo,
|
|
19
20
|
securityResearch,
|
|
20
|
-
unifiedSearch
|
|
21
|
-
|
|
21
|
+
unifiedSearch,
|
|
22
|
+
waybackSearch,
|
|
23
|
+
zeroDayResearch
|
|
24
|
+
} from "./chunk-M2IFHZDV.js";
|
|
22
25
|
import "./chunk-3RG5ZIWI.js";
|
|
23
26
|
export {
|
|
24
27
|
closeBrowser,
|
|
25
28
|
ctfResearch,
|
|
26
29
|
deepSearch,
|
|
27
30
|
fetchUrlContent,
|
|
31
|
+
recursiveSearch,
|
|
28
32
|
searchADWriteups,
|
|
29
33
|
searchBing,
|
|
30
34
|
searchBrave,
|
|
@@ -39,5 +43,7 @@ export {
|
|
|
39
43
|
searchWriteups,
|
|
40
44
|
searchYahoo,
|
|
41
45
|
securityResearch,
|
|
42
|
-
unifiedSearch
|
|
46
|
+
unifiedSearch,
|
|
47
|
+
waybackSearch,
|
|
48
|
+
zeroDayResearch
|
|
43
49
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pentesting",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Autonomous Penetration Testing AI Agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"release:minor": "npm version minor && npm run build && npm publish",
|
|
27
27
|
"release:major": "npm version major && npm run build && npm publish",
|
|
28
28
|
"release": "npm run release:patch",
|
|
29
|
-
"publish:token": "npm config set //registry.npmjs.org/:_authToken
|
|
29
|
+
"publish:token": "npm config set //registry.npmjs.org/:_authToken=${NPM_TOKEN} && npm run build && npm publish",
|
|
30
30
|
"release:token:patch": "npm version patch && npm run publish:token",
|
|
31
31
|
"release:token:minor": "npm version minor && npm run publish:token",
|
|
32
32
|
"release:token:major": "npm version major && npm run publish:token",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
},
|
|
38
38
|
"repository": {
|
|
39
39
|
"type": "git",
|
|
40
|
-
"url": "git+https://github.com/agnusdei1207
|
|
40
|
+
"url": "git+https://github.com/agnusdei1207"
|
|
41
41
|
},
|
|
42
|
-
"homepage": "https://
|
|
42
|
+
"homepage": "https://agnusdei.kr",
|
|
43
43
|
"bugs": {
|
|
44
|
-
"url": "https://github.com/agnusdei1207
|
|
44
|
+
"url": "https://github.com/agnusdei1207"
|
|
45
45
|
},
|
|
46
46
|
"keywords": [
|
|
47
47
|
"penetration-testing",
|
|
@@ -91,4 +91,4 @@
|
|
|
91
91
|
"typescript": "^5.7.3",
|
|
92
92
|
"vitest": "^4.0.18"
|
|
93
93
|
}
|
|
94
|
-
}
|
|
94
|
+
}
|
|
@@ -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
|
-
};
|
package/dist/chunk-5IKQY4A4.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
APP_NAME,
|
|
3
|
-
APP_VERSION
|
|
4
|
-
} from "./chunk-6IXHQS2A.js";
|
|
5
|
-
|
|
6
|
-
// src/core/update/auto-update.ts
|
|
7
|
-
import { execSync } from "child_process";
|
|
8
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
9
|
-
import { join } from "path";
|
|
10
|
-
import { homedir } from "os";
|
|
11
|
-
var UPDATE_CHECK_INTERVAL = 24 * 60 * 60 * 1e3;
|
|
12
|
-
var VERSION_CACHE_FILE = join(homedir(), ".pentest", "latest_version.json");
|
|
13
|
-
function semverTuple(version) {
|
|
14
|
-
const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
15
|
-
if (!match) return [0, 0, 0];
|
|
16
|
-
return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])];
|
|
17
|
-
}
|
|
18
|
-
function compareSemver(a, b) {
|
|
19
|
-
const [a1, a2, a3] = semverTuple(a);
|
|
20
|
-
const [b1, b2, b3] = semverTuple(b);
|
|
21
|
-
if (a1 !== b1) return a1 < b1 ? -1 : 1;
|
|
22
|
-
if (a2 !== b2) return a2 < b2 ? -1 : 1;
|
|
23
|
-
if (a3 !== b3) return a3 < b3 ? -1 : 1;
|
|
24
|
-
return 0;
|
|
25
|
-
}
|
|
26
|
-
function readVersionCache() {
|
|
27
|
-
try {
|
|
28
|
-
if (!existsSync(VERSION_CACHE_FILE)) return null;
|
|
29
|
-
const data = JSON.parse(readFileSync(VERSION_CACHE_FILE, "utf-8"));
|
|
30
|
-
return data;
|
|
31
|
-
} catch {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
function writeVersionCache(info) {
|
|
36
|
-
try {
|
|
37
|
-
const dir = join(homedir(), ".pentest");
|
|
38
|
-
if (!existsSync(dir)) {
|
|
39
|
-
mkdirSync(dir, { recursive: true });
|
|
40
|
-
}
|
|
41
|
-
writeFileSync(VERSION_CACHE_FILE, JSON.stringify(info, null, 2));
|
|
42
|
-
} catch {
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function fetchLatestVersion(packageName = APP_NAME) {
|
|
46
|
-
try {
|
|
47
|
-
const output = execSync(`npm view ${packageName} version`, {
|
|
48
|
-
encoding: "utf-8",
|
|
49
|
-
timeout: 1e4,
|
|
50
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
51
|
-
});
|
|
52
|
-
return output.trim();
|
|
53
|
-
} catch {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function checkForUpdate(forceCheck = false) {
|
|
58
|
-
const currentVersion = APP_VERSION;
|
|
59
|
-
const cached = readVersionCache();
|
|
60
|
-
const now = Date.now();
|
|
61
|
-
if (!forceCheck && cached && now - cached.checkedAt < UPDATE_CHECK_INTERVAL) {
|
|
62
|
-
const hasUpdate2 = compareSemver(cached.version, currentVersion) > 0;
|
|
63
|
-
return {
|
|
64
|
-
hasUpdate: hasUpdate2,
|
|
65
|
-
currentVersion,
|
|
66
|
-
latestVersion: cached.version
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
const latestVersion = fetchLatestVersion();
|
|
70
|
-
if (!latestVersion) {
|
|
71
|
-
return {
|
|
72
|
-
hasUpdate: false,
|
|
73
|
-
currentVersion,
|
|
74
|
-
latestVersion: null,
|
|
75
|
-
error: "Failed to fetch latest version"
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
writeVersionCache({
|
|
79
|
-
version: latestVersion,
|
|
80
|
-
checkedAt: now
|
|
81
|
-
});
|
|
82
|
-
const hasUpdate = compareSemver(latestVersion, currentVersion) > 0;
|
|
83
|
-
return {
|
|
84
|
-
hasUpdate,
|
|
85
|
-
currentVersion,
|
|
86
|
-
latestVersion
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
async function checkForUpdateAsync() {
|
|
90
|
-
return new Promise((resolve) => {
|
|
91
|
-
setImmediate(() => {
|
|
92
|
-
resolve(checkForUpdate());
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
function formatUpdateNotification(result) {
|
|
97
|
-
if (!result.hasUpdate || !result.latestVersion) return null;
|
|
98
|
-
return `
|
|
99
|
-
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
|
|
100
|
-
\u2502 \u{1F195} A new version of ${APP_NAME} is available! \u2502
|
|
101
|
-
\u2502 \u2502
|
|
102
|
-
\u2502 Current: ${result.currentVersion.padEnd(10)} Latest: ${result.latestVersion.padEnd(10)} \u2502
|
|
103
|
-
\u2502 \u2502
|
|
104
|
-
\u2502 Run: npm update -g ${APP_NAME} \u2502
|
|
105
|
-
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
|
|
106
|
-
`.trim();
|
|
107
|
-
}
|
|
108
|
-
function doUpdate() {
|
|
109
|
-
try {
|
|
110
|
-
execSync(`npm update -g ${APP_NAME}`, {
|
|
111
|
-
encoding: "utf-8",
|
|
112
|
-
timeout: 12e4,
|
|
113
|
-
stdio: "inherit"
|
|
114
|
-
});
|
|
115
|
-
return { success: true, message: `Updated ${APP_NAME} successfully!` };
|
|
116
|
-
} catch (e) {
|
|
117
|
-
return {
|
|
118
|
-
success: false,
|
|
119
|
-
message: `Failed to update: ${e instanceof Error ? e.message : String(e)}`
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export {
|
|
125
|
-
semverTuple,
|
|
126
|
-
compareSemver,
|
|
127
|
-
readVersionCache,
|
|
128
|
-
writeVersionCache,
|
|
129
|
-
fetchLatestVersion,
|
|
130
|
-
checkForUpdate,
|
|
131
|
-
checkForUpdateAsync,
|
|
132
|
-
formatUpdateNotification,
|
|
133
|
-
doUpdate
|
|
134
|
-
};
|
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/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
|
-
};
|