javi-forge 1.6.0 → 1.6.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/dist/commands/analyze.d.ts +1 -1
- package/dist/commands/analyze.js +15 -15
- package/dist/commands/atlassian-mcp.d.ts +42 -0
- package/dist/commands/atlassian-mcp.js +98 -0
- package/dist/commands/ci.d.ts +3 -3
- package/dist/commands/ci.js +185 -147
- package/dist/commands/crash-recovery.d.ts +34 -0
- package/dist/commands/crash-recovery.js +123 -0
- package/dist/commands/doctor.d.ts +2 -2
- package/dist/commands/doctor.js +113 -61
- package/dist/commands/harness-audit.d.ts +35 -0
- package/dist/commands/harness-audit.js +277 -0
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +384 -141
- package/dist/commands/llmstxt.d.ts +1 -1
- package/dist/commands/llmstxt.js +36 -34
- package/dist/commands/parallel-batch.d.ts +42 -0
- package/dist/commands/parallel-batch.js +90 -0
- package/dist/commands/plugin.d.ts +10 -1
- package/dist/commands/plugin.js +92 -47
- package/dist/commands/secret-scanner.d.ts +30 -0
- package/dist/commands/secret-scanner.js +272 -0
- package/dist/commands/security-analysis.d.ts +74 -0
- package/dist/commands/security-analysis.js +487 -0
- package/dist/commands/security.d.ts +11 -5
- package/dist/commands/security.js +216 -76
- package/dist/commands/skill-scanner.d.ts +63 -0
- package/dist/commands/skill-scanner.js +383 -0
- package/dist/commands/skills.d.ts +62 -5
- package/dist/commands/skills.js +439 -54
- package/dist/commands/supply-chain.d.ts +23 -0
- package/dist/commands/supply-chain.js +126 -0
- package/dist/commands/tdd-pipeline.d.ts +17 -0
- package/dist/commands/tdd-pipeline.js +144 -0
- package/dist/commands/tdd.d.ts +1 -1
- package/dist/commands/tdd.js +21 -18
- package/dist/commands/team-presets.d.ts +53 -0
- package/dist/commands/team-presets.js +201 -0
- package/dist/commands/workflow.d.ts +23 -0
- package/dist/commands/workflow.js +114 -0
- package/dist/constants.d.ts +15 -1
- package/dist/constants.js +161 -122
- package/dist/index.js +308 -98
- package/dist/lib/agent-skills.d.ts +36 -1
- package/dist/lib/agent-skills.js +168 -19
- package/dist/lib/auto-skill-install.d.ts +37 -0
- package/dist/lib/auto-skill-install.js +92 -0
- package/dist/lib/auto-wire.d.ts +20 -0
- package/dist/lib/auto-wire.js +240 -0
- package/dist/lib/claudemd.d.ts +13 -1
- package/dist/lib/claudemd.js +174 -24
- package/dist/lib/codex-export.d.ts +1 -1
- package/dist/lib/codex-export.js +29 -31
- package/dist/lib/common.d.ts +1 -1
- package/dist/lib/common.js +52 -44
- package/dist/lib/context.d.ts +17 -2
- package/dist/lib/context.js +142 -13
- package/dist/lib/docker.d.ts +1 -1
- package/dist/lib/docker.js +141 -112
- package/dist/lib/frontmatter.d.ts +1 -1
- package/dist/lib/frontmatter.js +29 -15
- package/dist/lib/plugin.d.ts +9 -3
- package/dist/lib/plugin.js +128 -69
- package/dist/lib/skill-publish.d.ts +40 -0
- package/dist/lib/skill-publish.js +146 -0
- package/dist/lib/stack-detector.d.ts +38 -0
- package/dist/lib/stack-detector.js +207 -0
- package/dist/lib/template.d.ts +16 -1
- package/dist/lib/template.js +46 -17
- package/dist/lib/workflow/discovery.d.ts +19 -0
- package/dist/lib/workflow/discovery.js +68 -0
- package/dist/lib/workflow/index.d.ts +5 -0
- package/dist/lib/workflow/index.js +5 -0
- package/dist/lib/workflow/parser.d.ts +16 -0
- package/dist/lib/workflow/parser.js +198 -0
- package/dist/lib/workflow/renderer.d.ts +9 -0
- package/dist/lib/workflow/renderer.js +152 -0
- package/dist/lib/workflow/validator.d.ts +10 -0
- package/dist/lib/workflow/validator.js +189 -0
- package/dist/tasks/index.d.ts +4 -0
- package/dist/tasks/index.js +4 -0
- package/dist/tasks/scaffold-tasks.d.ts +3 -0
- package/dist/tasks/scaffold-tasks.js +14 -0
- package/dist/tasks/task-id.d.ts +30 -0
- package/dist/tasks/task-id.js +55 -0
- package/dist/tasks/task-tracker.d.ts +15 -0
- package/dist/tasks/task-tracker.js +81 -0
- package/dist/types/index.d.ts +134 -6
- package/dist/types/index.js +11 -1
- package/dist/ui/AnalyzeUI.d.ts +1 -1
- package/dist/ui/AnalyzeUI.js +38 -39
- package/dist/ui/App.d.ts +5 -3
- package/dist/ui/App.js +86 -46
- package/dist/ui/AutoSkills.d.ts +9 -0
- package/dist/ui/AutoSkills.js +124 -0
- package/dist/ui/CI.d.ts +2 -2
- package/dist/ui/CI.js +24 -26
- package/dist/ui/CIContext.d.ts +1 -1
- package/dist/ui/CIContext.js +3 -2
- package/dist/ui/CISelector.d.ts +2 -2
- package/dist/ui/CISelector.js +23 -15
- package/dist/ui/Doctor.d.ts +1 -1
- package/dist/ui/Doctor.js +35 -29
- package/dist/ui/Header.d.ts +1 -1
- package/dist/ui/Header.js +14 -14
- package/dist/ui/HookProfileSelector.d.ts +9 -0
- package/dist/ui/HookProfileSelector.js +54 -0
- package/dist/ui/LlmsTxt.d.ts +1 -1
- package/dist/ui/LlmsTxt.js +31 -22
- package/dist/ui/MemorySelector.d.ts +2 -2
- package/dist/ui/MemorySelector.js +28 -16
- package/dist/ui/NameInput.d.ts +1 -1
- package/dist/ui/NameInput.js +21 -21
- package/dist/ui/OptionSelector.d.ts +6 -2
- package/dist/ui/OptionSelector.js +83 -32
- package/dist/ui/Plugin.d.ts +4 -3
- package/dist/ui/Plugin.js +78 -35
- package/dist/ui/Progress.d.ts +3 -3
- package/dist/ui/Progress.js +23 -22
- package/dist/ui/Skills.d.ts +2 -2
- package/dist/ui/Skills.js +61 -32
- package/dist/ui/StackSelector.d.ts +2 -2
- package/dist/ui/StackSelector.js +26 -16
- package/dist/ui/Summary.d.ts +3 -3
- package/dist/ui/Summary.js +60 -50
- package/dist/ui/Welcome.d.ts +1 -1
- package/dist/ui/Welcome.js +15 -16
- package/dist/ui/theme.d.ts +1 -1
- package/dist/ui/theme.js +6 -6
- package/package.json +9 -6
- package/templates/common/atlassian/mcp-atlassian-snippet.json +16 -0
- package/templates/common/repoforge/mcp-repoforge-snippet.json +11 -0
- package/templates/common/repoforge/repoforge.yaml +34 -0
- package/templates/github/deploy-docker-zero-downtime.yml +140 -0
- package/templates/github/repoforge-graph.yml +45 -0
- package/templates/gitlab/deploy-docker-zero-downtime.yml +57 -0
- package/templates/local-ai/.env.example +17 -0
- package/templates/local-ai/docker-compose.yml +95 -0
- package/templates/security-hooks/claude-settings-security.json +30 -0
- package/templates/security-hooks/commit-msg-signing +29 -0
- package/templates/security-hooks/pre-commit-permissions +74 -0
- package/templates/security-hooks/pre-commit-secrets +74 -0
- package/templates/security-hooks/pre-push-branch-protection +62 -0
- package/templates/security-hooks/pre-push-deps +83 -0
- package/templates/security-hooks/pre-push-signing +67 -0
- package/templates/woodpecker/deploy-docker-zero-downtime.yml +50 -0
- package/templates/workflows/ci-pipeline.dot +15 -0
- package/templates/workflows/feature-flow.dot +21 -0
- package/templates/workflows/release.dot +16 -0
- package/dist/__integration__/helpers.d.ts +0 -20
- package/dist/__integration__/helpers.d.ts.map +0 -1
- package/dist/__integration__/helpers.js +0 -31
- package/dist/__integration__/helpers.js.map +0 -1
- package/dist/commands/analyze.d.ts.map +0 -1
- package/dist/commands/analyze.js.map +0 -1
- package/dist/commands/ci.d.ts.map +0 -1
- package/dist/commands/ci.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/llmstxt.d.ts.map +0 -1
- package/dist/commands/llmstxt.js.map +0 -1
- package/dist/commands/plugin.d.ts.map +0 -1
- package/dist/commands/plugin.js.map +0 -1
- package/dist/commands/security.d.ts.map +0 -1
- package/dist/commands/security.js.map +0 -1
- package/dist/commands/skills.d.ts.map +0 -1
- package/dist/commands/skills.js.map +0 -1
- package/dist/commands/tdd.d.ts.map +0 -1
- package/dist/commands/tdd.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/agent-skills.d.ts.map +0 -1
- package/dist/lib/agent-skills.js.map +0 -1
- package/dist/lib/claudemd.d.ts.map +0 -1
- package/dist/lib/claudemd.js.map +0 -1
- package/dist/lib/codex-export.d.ts.map +0 -1
- package/dist/lib/codex-export.js.map +0 -1
- package/dist/lib/common.d.ts.map +0 -1
- package/dist/lib/common.js.map +0 -1
- package/dist/lib/context.d.ts.map +0 -1
- package/dist/lib/context.js.map +0 -1
- package/dist/lib/docker.d.ts.map +0 -1
- package/dist/lib/docker.js.map +0 -1
- package/dist/lib/frontmatter.d.ts.map +0 -1
- package/dist/lib/frontmatter.js.map +0 -1
- package/dist/lib/plugin.d.ts.map +0 -1
- package/dist/lib/plugin.js.map +0 -1
- package/dist/lib/template.d.ts.map +0 -1
- package/dist/lib/template.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/ui/AnalyzeUI.d.ts.map +0 -1
- package/dist/ui/AnalyzeUI.js.map +0 -1
- package/dist/ui/App.d.ts.map +0 -1
- package/dist/ui/App.js.map +0 -1
- package/dist/ui/CI.d.ts.map +0 -1
- package/dist/ui/CI.js.map +0 -1
- package/dist/ui/CIContext.d.ts.map +0 -1
- package/dist/ui/CIContext.js.map +0 -1
- package/dist/ui/CISelector.d.ts.map +0 -1
- package/dist/ui/CISelector.js.map +0 -1
- package/dist/ui/Doctor.d.ts.map +0 -1
- package/dist/ui/Doctor.js.map +0 -1
- package/dist/ui/Header.d.ts.map +0 -1
- package/dist/ui/Header.js.map +0 -1
- package/dist/ui/LlmsTxt.d.ts.map +0 -1
- package/dist/ui/LlmsTxt.js.map +0 -1
- package/dist/ui/MemorySelector.d.ts.map +0 -1
- package/dist/ui/MemorySelector.js.map +0 -1
- package/dist/ui/NameInput.d.ts.map +0 -1
- package/dist/ui/NameInput.js.map +0 -1
- package/dist/ui/OptionSelector.d.ts.map +0 -1
- package/dist/ui/OptionSelector.js.map +0 -1
- package/dist/ui/Plugin.d.ts.map +0 -1
- package/dist/ui/Plugin.js.map +0 -1
- package/dist/ui/Progress.d.ts.map +0 -1
- package/dist/ui/Progress.js.map +0 -1
- package/dist/ui/Skills.d.ts.map +0 -1
- package/dist/ui/Skills.js.map +0 -1
- package/dist/ui/StackSelector.d.ts.map +0 -1
- package/dist/ui/StackSelector.js.map +0 -1
- package/dist/ui/Summary.d.ts.map +0 -1
- package/dist/ui/Summary.js.map +0 -1
- package/dist/ui/Welcome.d.ts.map +0 -1
- package/dist/ui/Welcome.js.map +0 -1
- package/dist/ui/theme.d.ts.map +0 -1
- package/dist/ui/theme.js.map +0 -1
package/dist/commands/llmstxt.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { detectStack } from
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import { glob } from "glob";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { detectStack } from "../lib/common.js";
|
|
5
5
|
function report(onStep, id, label, status, detail) {
|
|
6
6
|
onStep({ id, label, status, detail });
|
|
7
7
|
}
|
|
@@ -10,53 +10,55 @@ function report(onStep, id, label, status, detail) {
|
|
|
10
10
|
* Reduces token usage by ~75% compared to full README + docs.
|
|
11
11
|
*/
|
|
12
12
|
export async function generateLlmsTxt(projectDir, dryRun, onStep) {
|
|
13
|
-
report(onStep,
|
|
13
|
+
report(onStep, "scan", "Scan project structure", "running");
|
|
14
14
|
const detection = await detectStack(projectDir);
|
|
15
|
-
const stackLabel = detection?.stackType ??
|
|
15
|
+
const stackLabel = detection?.stackType ?? "unknown";
|
|
16
16
|
// Gather project info
|
|
17
17
|
const name = path.basename(projectDir);
|
|
18
|
-
let description =
|
|
19
|
-
let version =
|
|
18
|
+
let description = "";
|
|
19
|
+
let version = "";
|
|
20
20
|
let entryPoints = [];
|
|
21
21
|
let dependencies = [];
|
|
22
22
|
// Try package.json (Node)
|
|
23
|
-
const pkgPath = path.join(projectDir,
|
|
23
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
24
24
|
if (await fs.pathExists(pkgPath)) {
|
|
25
25
|
try {
|
|
26
26
|
const pkg = await fs.readJson(pkgPath);
|
|
27
|
-
description = pkg.description ??
|
|
28
|
-
version = pkg.version ??
|
|
27
|
+
description = pkg.description ?? "";
|
|
28
|
+
version = pkg.version ?? "";
|
|
29
29
|
entryPoints = pkg.main ? [pkg.main] : [];
|
|
30
30
|
dependencies = Object.keys(pkg.dependencies ?? {}).slice(0, 15);
|
|
31
31
|
}
|
|
32
|
-
catch {
|
|
32
|
+
catch {
|
|
33
|
+
/* ignore */
|
|
34
|
+
}
|
|
33
35
|
}
|
|
34
36
|
// Scan source files
|
|
35
|
-
const sourceFiles = await glob(
|
|
37
|
+
const sourceFiles = await glob("src/**/*.{ts,tsx,js,jsx,py,go,rs}", {
|
|
36
38
|
cwd: projectDir,
|
|
37
|
-
ignore: [
|
|
39
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
|
|
38
40
|
});
|
|
39
41
|
// Scan test files
|
|
40
|
-
const testFiles = await glob(
|
|
42
|
+
const testFiles = await glob("**/*.{test,spec}.{ts,tsx,js,jsx,py}", {
|
|
41
43
|
cwd: projectDir,
|
|
42
|
-
ignore: [
|
|
44
|
+
ignore: ["**/node_modules/**", "**/dist/**"],
|
|
43
45
|
});
|
|
44
|
-
report(onStep,
|
|
46
|
+
report(onStep, "scan", "Scan project structure", "done", `${sourceFiles.length} source, ${testFiles.length} test files`);
|
|
45
47
|
// Build llms.txt content
|
|
46
|
-
report(onStep,
|
|
48
|
+
report(onStep, "generate", "Generate llms.txt", "running");
|
|
47
49
|
const lines = [
|
|
48
50
|
`# ${name}`,
|
|
49
|
-
|
|
50
|
-
`> ${description ||
|
|
51
|
-
|
|
52
|
-
`- stack: ${stackLabel}${detection?.buildTool ? ` (${detection.buildTool})` :
|
|
53
|
-
`- version: ${version ||
|
|
51
|
+
"",
|
|
52
|
+
`> ${description || "No description"}`,
|
|
53
|
+
"",
|
|
54
|
+
`- stack: ${stackLabel}${detection?.buildTool ? ` (${detection.buildTool})` : ""}`,
|
|
55
|
+
`- version: ${version || "unknown"}`,
|
|
54
56
|
`- files: ${sourceFiles.length} source, ${testFiles.length} tests`,
|
|
55
|
-
|
|
57
|
+
"",
|
|
56
58
|
];
|
|
57
59
|
// Structure summary (compact)
|
|
58
60
|
if (sourceFiles.length > 0) {
|
|
59
|
-
lines.push(
|
|
61
|
+
lines.push("## Structure");
|
|
60
62
|
const dirs = new Map();
|
|
61
63
|
for (const f of sourceFiles) {
|
|
62
64
|
const dir = path.dirname(f);
|
|
@@ -65,28 +67,28 @@ export async function generateLlmsTxt(projectDir, dryRun, onStep) {
|
|
|
65
67
|
for (const [dir, count] of [...dirs.entries()].sort().slice(0, 20)) {
|
|
66
68
|
lines.push(`- ${dir}/ (${count})`);
|
|
67
69
|
}
|
|
68
|
-
lines.push(
|
|
70
|
+
lines.push("");
|
|
69
71
|
}
|
|
70
72
|
// Dependencies (compact — name only, no versions)
|
|
71
73
|
if (dependencies.length > 0) {
|
|
72
|
-
lines.push(
|
|
73
|
-
lines.push(dependencies.join(
|
|
74
|
-
lines.push(
|
|
74
|
+
lines.push("## Dependencies");
|
|
75
|
+
lines.push(dependencies.join(", "));
|
|
76
|
+
lines.push("");
|
|
75
77
|
}
|
|
76
78
|
// Entry points
|
|
77
79
|
if (entryPoints.length > 0) {
|
|
78
|
-
lines.push(
|
|
80
|
+
lines.push("## Entry");
|
|
79
81
|
for (const ep of entryPoints) {
|
|
80
82
|
lines.push(`- ${ep}`);
|
|
81
83
|
}
|
|
82
|
-
lines.push(
|
|
84
|
+
lines.push("");
|
|
83
85
|
}
|
|
84
|
-
const content = lines.join(
|
|
86
|
+
const content = lines.join("\n");
|
|
85
87
|
const tokenEstimate = Math.ceil(content.length / 4);
|
|
86
88
|
if (!dryRun) {
|
|
87
|
-
await fs.writeFile(path.join(projectDir,
|
|
89
|
+
await fs.writeFile(path.join(projectDir, "llms.txt"), content, "utf-8");
|
|
88
90
|
}
|
|
89
|
-
report(onStep,
|
|
91
|
+
report(onStep, "generate", "Generate llms.txt", "done", dryRun
|
|
90
92
|
? `dry-run: ~${tokenEstimate} tokens (${content.length} chars)`
|
|
91
93
|
: `written — ~${tokenEstimate} tokens (${content.length} chars)`);
|
|
92
94
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel batch sub-agents — spawn test/lint/build runners per module
|
|
3
|
+
* in parallel during quality scoring. Collects results and aggregates.
|
|
4
|
+
*/
|
|
5
|
+
export type JobStatus = "pending" | "running" | "done" | "error";
|
|
6
|
+
export interface BatchJob {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
command: string;
|
|
10
|
+
module: string;
|
|
11
|
+
status: JobStatus;
|
|
12
|
+
startedAt: number | null;
|
|
13
|
+
completedAt: number | null;
|
|
14
|
+
durationMs: number;
|
|
15
|
+
exitCode: number | null;
|
|
16
|
+
stdout: string;
|
|
17
|
+
stderr: string;
|
|
18
|
+
}
|
|
19
|
+
export interface BatchResult {
|
|
20
|
+
jobs: BatchJob[];
|
|
21
|
+
totalDurationMs: number;
|
|
22
|
+
passedCount: number;
|
|
23
|
+
failedCount: number;
|
|
24
|
+
parallelism: number;
|
|
25
|
+
}
|
|
26
|
+
export interface BatchConfig {
|
|
27
|
+
maxParallel: number;
|
|
28
|
+
timeoutMs: number;
|
|
29
|
+
}
|
|
30
|
+
export declare const DEFAULT_BATCH_CONFIG: BatchConfig;
|
|
31
|
+
export declare function createJob(name: string, command: string, module: string): BatchJob;
|
|
32
|
+
export type JobExecutor = (job: BatchJob) => Promise<BatchJob>;
|
|
33
|
+
/**
|
|
34
|
+
* Default executor — runs command via child_process.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createShellExecutor(timeoutMs?: number): JobExecutor;
|
|
37
|
+
/**
|
|
38
|
+
* Run jobs in parallel with configurable concurrency.
|
|
39
|
+
*/
|
|
40
|
+
export declare function runBatch(jobs: BatchJob[], executor: JobExecutor, config?: BatchConfig): Promise<BatchResult>;
|
|
41
|
+
export declare function formatBatchResult(result: BatchResult): string;
|
|
42
|
+
//# sourceMappingURL=parallel-batch.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel batch sub-agents — spawn test/lint/build runners per module
|
|
3
|
+
* in parallel during quality scoring. Collects results and aggregates.
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_BATCH_CONFIG = {
|
|
6
|
+
maxParallel: 4,
|
|
7
|
+
timeoutMs: 60_000,
|
|
8
|
+
};
|
|
9
|
+
// ── Job creation ──
|
|
10
|
+
let _jobCounter = 0;
|
|
11
|
+
export function createJob(name, command, module) {
|
|
12
|
+
_jobCounter++;
|
|
13
|
+
return {
|
|
14
|
+
id: `job-${Date.now()}-${_jobCounter}`,
|
|
15
|
+
name,
|
|
16
|
+
command,
|
|
17
|
+
module,
|
|
18
|
+
status: "pending",
|
|
19
|
+
startedAt: null,
|
|
20
|
+
completedAt: null,
|
|
21
|
+
durationMs: 0,
|
|
22
|
+
exitCode: null,
|
|
23
|
+
stdout: "",
|
|
24
|
+
stderr: "",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Default executor — runs command via child_process.
|
|
29
|
+
*/
|
|
30
|
+
export function createShellExecutor(timeoutMs = 60_000) {
|
|
31
|
+
return async (job) => {
|
|
32
|
+
const { execFile } = await import("child_process");
|
|
33
|
+
const { promisify } = await import("util");
|
|
34
|
+
const execFileAsync = promisify(execFile);
|
|
35
|
+
job.status = "running";
|
|
36
|
+
job.startedAt = Date.now();
|
|
37
|
+
try {
|
|
38
|
+
const { stdout, stderr } = await execFileAsync("sh", ["-c", job.command], { timeout: timeoutMs, maxBuffer: 5 * 1024 * 1024 });
|
|
39
|
+
job.stdout = stdout;
|
|
40
|
+
job.stderr = stderr;
|
|
41
|
+
job.exitCode = 0;
|
|
42
|
+
job.status = "done";
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
const e = err;
|
|
46
|
+
job.stdout = e.stdout ?? "";
|
|
47
|
+
job.stderr = e.stderr ?? "";
|
|
48
|
+
job.exitCode = e.killed ? -1 : (e.code ?? 1);
|
|
49
|
+
job.status = "error";
|
|
50
|
+
}
|
|
51
|
+
job.completedAt = Date.now();
|
|
52
|
+
job.durationMs = job.completedAt - job.startedAt;
|
|
53
|
+
return job;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Run jobs in parallel with configurable concurrency.
|
|
58
|
+
*/
|
|
59
|
+
export async function runBatch(jobs, executor, config = DEFAULT_BATCH_CONFIG) {
|
|
60
|
+
const start = Date.now();
|
|
61
|
+
const results = [];
|
|
62
|
+
const queue = [...jobs];
|
|
63
|
+
// Process in waves of maxParallel
|
|
64
|
+
while (queue.length > 0) {
|
|
65
|
+
const wave = queue.splice(0, config.maxParallel);
|
|
66
|
+
const waveResults = await Promise.all(wave.map((j) => executor(j)));
|
|
67
|
+
results.push(...waveResults);
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
jobs: results,
|
|
71
|
+
totalDurationMs: Date.now() - start,
|
|
72
|
+
passedCount: results.filter((j) => j.status === "done").length,
|
|
73
|
+
failedCount: results.filter((j) => j.status === "error").length,
|
|
74
|
+
parallelism: config.maxParallel,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// ── Formatting ──
|
|
78
|
+
export function formatBatchResult(result) {
|
|
79
|
+
const status = result.failedCount === 0 ? "✅ ALL PASSED" : "❌ FAILURES";
|
|
80
|
+
const lines = [];
|
|
81
|
+
lines.push(`## Batch Result: ${status}`);
|
|
82
|
+
lines.push(`**Jobs**: ${result.jobs.length} | **Passed**: ${result.passedCount} | **Failed**: ${result.failedCount} | **Time**: ${result.totalDurationMs}ms | **Parallelism**: ${result.parallelism}`);
|
|
83
|
+
lines.push("");
|
|
84
|
+
for (const job of result.jobs) {
|
|
85
|
+
const icon = job.status === "done" ? "✓" : "✗";
|
|
86
|
+
lines.push(` ${icon} ${job.name} (${job.module}) — ${job.durationMs}ms [exit ${job.exitCode}]`);
|
|
87
|
+
}
|
|
88
|
+
return lines.join("\n");
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=parallel-batch.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { InitStep } from
|
|
1
|
+
import type { InitStep } from "../types/index.js";
|
|
2
2
|
type StepCallback = (step: InitStep) => void;
|
|
3
3
|
/**
|
|
4
4
|
* Add (install) a plugin from a GitHub source.
|
|
@@ -36,5 +36,14 @@ export declare function runPluginExportCodex(name: string, onStep: StepCallback)
|
|
|
36
36
|
* Import an Agent Skills spec package and convert to javi-forge plugin format.
|
|
37
37
|
*/
|
|
38
38
|
export declare function runPluginImport(sourceDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Generate a project-level skills.json from all installed plugins.
|
|
41
|
+
* Makes the project discoverable by `npx skills add` and 40+ AI agents.
|
|
42
|
+
*/
|
|
43
|
+
export declare function runPluginExportSkillsJson(projectDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Generate a global skills.json from all globally installed plugins.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runPluginExportGlobalSkillsJson(dryRun: boolean, onStep: StepCallback): Promise<void>;
|
|
39
48
|
export {};
|
|
40
49
|
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/commands/plugin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { exportPluginAsAgentSkills, generateGlobalSkillsJson, generateProjectSkillsJson, importAgentSkillsPackage, } from "../lib/agent-skills.js";
|
|
2
|
+
import { exportPluginAsCodexToml } from "../lib/codex-export.js";
|
|
3
|
+
import { installPlugin, listInstalledPlugins, removePlugin, searchRegistry, syncPlugins, validatePlugin, } from "../lib/plugin.js";
|
|
4
4
|
function report(onStep, id, label, status, detail) {
|
|
5
5
|
onStep({ id, label, status, detail });
|
|
6
6
|
}
|
|
@@ -8,140 +8,185 @@ function report(onStep, id, label, status, detail) {
|
|
|
8
8
|
* Add (install) a plugin from a GitHub source.
|
|
9
9
|
*/
|
|
10
10
|
export async function runPluginAdd(source, dryRun, onStep) {
|
|
11
|
-
const stepId =
|
|
12
|
-
report(onStep, stepId, `Install plugin: ${source}`,
|
|
11
|
+
const stepId = "plugin-add";
|
|
12
|
+
report(onStep, stepId, `Install plugin: ${source}`, "running");
|
|
13
13
|
const result = await installPlugin(source, { dryRun });
|
|
14
14
|
if (result.success) {
|
|
15
|
-
report(onStep, stepId, `Install plugin: ${source}`,
|
|
15
|
+
report(onStep, stepId, `Install plugin: ${source}`, "done", dryRun
|
|
16
|
+
? `dry-run: would install ${result.name}`
|
|
17
|
+
: `installed ${result.name}`);
|
|
16
18
|
}
|
|
17
19
|
else {
|
|
18
|
-
report(onStep, stepId, `Install plugin: ${source}`,
|
|
20
|
+
report(onStep, stepId, `Install plugin: ${source}`, "error", result.error);
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
/**
|
|
22
24
|
* Remove an installed plugin by name.
|
|
23
25
|
*/
|
|
24
26
|
export async function runPluginRemove(name, dryRun, onStep) {
|
|
25
|
-
const stepId =
|
|
26
|
-
report(onStep, stepId, `Remove plugin: ${name}`,
|
|
27
|
+
const stepId = "plugin-remove";
|
|
28
|
+
report(onStep, stepId, `Remove plugin: ${name}`, "running");
|
|
27
29
|
const result = await removePlugin(name, { dryRun });
|
|
28
30
|
if (result.success) {
|
|
29
|
-
report(onStep, stepId, `Remove plugin: ${name}`,
|
|
31
|
+
report(onStep, stepId, `Remove plugin: ${name}`, "done", dryRun ? `dry-run: would remove ${name}` : `removed ${name}`);
|
|
30
32
|
}
|
|
31
33
|
else {
|
|
32
|
-
report(onStep, stepId, `Remove plugin: ${name}`,
|
|
34
|
+
report(onStep, stepId, `Remove plugin: ${name}`, "error", result.error);
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* List all installed plugins.
|
|
37
39
|
*/
|
|
38
40
|
export async function runPluginList(onStep) {
|
|
39
|
-
const stepId =
|
|
40
|
-
report(onStep, stepId,
|
|
41
|
+
const stepId = "plugin-list";
|
|
42
|
+
report(onStep, stepId, "List installed plugins", "running");
|
|
41
43
|
const plugins = await listInstalledPlugins();
|
|
42
44
|
if (plugins.length === 0) {
|
|
43
|
-
report(onStep, stepId,
|
|
45
|
+
report(onStep, stepId, "List installed plugins", "done", "no plugins installed");
|
|
44
46
|
}
|
|
45
47
|
else {
|
|
46
|
-
const summary = plugins.map(p => `${p.name}@${p.version}`).join(
|
|
47
|
-
report(onStep, stepId,
|
|
48
|
+
const summary = plugins.map((p) => `${p.name}@${p.version}`).join(", ");
|
|
49
|
+
report(onStep, stepId, "List installed plugins", "done", `${plugins.length} plugins: ${summary}`);
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
/**
|
|
51
53
|
* Search the remote plugin registry.
|
|
52
54
|
*/
|
|
53
55
|
export async function runPluginSearch(query, onStep) {
|
|
54
|
-
const stepId =
|
|
55
|
-
report(onStep, stepId, `Search plugins${query ? `: ${query}` :
|
|
56
|
+
const stepId = "plugin-search";
|
|
57
|
+
report(onStep, stepId, `Search plugins${query ? `: ${query}` : ""}`, "running");
|
|
56
58
|
const results = await searchRegistry(query);
|
|
57
59
|
if (results.length === 0) {
|
|
58
|
-
report(onStep, stepId, `Search plugins${query ? `: ${query}` :
|
|
60
|
+
report(onStep, stepId, `Search plugins${query ? `: ${query}` : ""}`, "done", query
|
|
61
|
+
? `no plugins matching "${query}"`
|
|
62
|
+
: "registry empty or unreachable");
|
|
59
63
|
}
|
|
60
64
|
else {
|
|
61
|
-
const summary = results
|
|
62
|
-
|
|
65
|
+
const summary = results
|
|
66
|
+
.map((p) => `${p.id} — ${p.description}`)
|
|
67
|
+
.join("\n ");
|
|
68
|
+
report(onStep, stepId, `Search plugins${query ? `: ${query}` : ""}`, "done", `${results.length} results:\n ${summary}`);
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
71
|
/**
|
|
66
72
|
* Validate a local plugin directory.
|
|
67
73
|
*/
|
|
68
74
|
export async function runPluginValidate(pluginDir, onStep) {
|
|
69
|
-
const stepId =
|
|
70
|
-
report(onStep, stepId, `Validate plugin: ${pluginDir}`,
|
|
75
|
+
const stepId = "plugin-validate";
|
|
76
|
+
report(onStep, stepId, `Validate plugin: ${pluginDir}`, "running");
|
|
71
77
|
const result = await validatePlugin(pluginDir);
|
|
72
78
|
if (result.valid) {
|
|
73
|
-
report(onStep, stepId, `Validate plugin: ${pluginDir}`,
|
|
79
|
+
report(onStep, stepId, `Validate plugin: ${pluginDir}`, "done", `valid — ${result.manifest?.name}@${result.manifest?.version}`);
|
|
74
80
|
}
|
|
75
81
|
else {
|
|
76
|
-
const msgs = result.errors
|
|
77
|
-
|
|
82
|
+
const msgs = result.errors
|
|
83
|
+
.map((e) => ` ${e.path}: ${e.message}`)
|
|
84
|
+
.join("\n");
|
|
85
|
+
report(onStep, stepId, `Validate plugin: ${pluginDir}`, "error", `${result.errors.length} errors:\n${msgs}`);
|
|
78
86
|
}
|
|
79
87
|
}
|
|
80
88
|
/**
|
|
81
89
|
* Sync detected plugins into the project manifest.
|
|
82
90
|
*/
|
|
83
91
|
export async function runPluginSync(projectDir, dryRun, onStep) {
|
|
84
|
-
const stepId =
|
|
85
|
-
report(onStep, stepId,
|
|
92
|
+
const stepId = "plugin-sync";
|
|
93
|
+
report(onStep, stepId, "Sync plugins", "running");
|
|
86
94
|
try {
|
|
87
95
|
const result = await syncPlugins(projectDir, { dryRun });
|
|
88
96
|
const parts = [];
|
|
89
97
|
if (result.added.length > 0)
|
|
90
|
-
parts.push(`added: ${result.added.join(
|
|
98
|
+
parts.push(`added: ${result.added.join(", ")}`);
|
|
91
99
|
if (result.removed.length > 0)
|
|
92
|
-
parts.push(`removed: ${result.removed.join(
|
|
100
|
+
parts.push(`removed: ${result.removed.join(", ")}`);
|
|
93
101
|
if (result.unchanged.length > 0)
|
|
94
|
-
parts.push(`unchanged: ${result.unchanged.join(
|
|
102
|
+
parts.push(`unchanged: ${result.unchanged.join(", ")}`);
|
|
103
|
+
if (result.wired.length > 0)
|
|
104
|
+
parts.push(`wired: ${result.wired.length} capabilities`);
|
|
105
|
+
if (result.unwired.length > 0)
|
|
106
|
+
parts.push(`unwired: ${result.unwired.length} capabilities`);
|
|
95
107
|
if (parts.length === 0)
|
|
96
|
-
parts.push(
|
|
97
|
-
const prefix = dryRun ?
|
|
98
|
-
report(onStep, stepId,
|
|
108
|
+
parts.push("no plugins detected");
|
|
109
|
+
const prefix = dryRun ? "dry-run: " : "";
|
|
110
|
+
report(onStep, stepId, "Sync plugins", "done", `${prefix}${parts.join(" | ")}`);
|
|
99
111
|
}
|
|
100
112
|
catch (e) {
|
|
101
113
|
const msg = e instanceof Error ? e.message : String(e);
|
|
102
|
-
report(onStep, stepId,
|
|
114
|
+
report(onStep, stepId, "Sync plugins", "error", msg);
|
|
103
115
|
}
|
|
104
116
|
}
|
|
105
117
|
/**
|
|
106
118
|
* Export an installed plugin to Agent Skills spec format.
|
|
107
119
|
*/
|
|
108
120
|
export async function runPluginExport(name, onStep) {
|
|
109
|
-
const stepId =
|
|
110
|
-
report(onStep, stepId, `Export plugin: ${name}`,
|
|
121
|
+
const stepId = "plugin-export";
|
|
122
|
+
report(onStep, stepId, `Export plugin: ${name}`, "running");
|
|
111
123
|
const result = await exportPluginAsAgentSkills(name);
|
|
112
124
|
if (result.success) {
|
|
113
|
-
report(onStep, stepId, `Export plugin: ${name}`,
|
|
125
|
+
report(onStep, stepId, `Export plugin: ${name}`, "done", `exported to ${result.path}`);
|
|
114
126
|
}
|
|
115
127
|
else {
|
|
116
|
-
report(onStep, stepId, `Export plugin: ${name}`,
|
|
128
|
+
report(onStep, stepId, `Export plugin: ${name}`, "error", result.error);
|
|
117
129
|
}
|
|
118
130
|
}
|
|
119
131
|
/**
|
|
120
132
|
* Export an installed plugin to Codex-compatible TOML subagent files.
|
|
121
133
|
*/
|
|
122
134
|
export async function runPluginExportCodex(name, onStep) {
|
|
123
|
-
const stepId =
|
|
124
|
-
report(onStep, stepId, `Export plugin as Codex TOML: ${name}`,
|
|
135
|
+
const stepId = "plugin-export-codex";
|
|
136
|
+
report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "running");
|
|
125
137
|
const result = await exportPluginAsCodexToml(name);
|
|
126
138
|
if (result.success) {
|
|
127
|
-
report(onStep, stepId, `Export plugin as Codex TOML: ${name}`,
|
|
139
|
+
report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "done", `exported ${result.files.length} TOML file(s)`);
|
|
128
140
|
}
|
|
129
141
|
else {
|
|
130
|
-
report(onStep, stepId, `Export plugin as Codex TOML: ${name}`,
|
|
142
|
+
report(onStep, stepId, `Export plugin as Codex TOML: ${name}`, "error", result.error);
|
|
131
143
|
}
|
|
132
144
|
}
|
|
133
145
|
/**
|
|
134
146
|
* Import an Agent Skills spec package and convert to javi-forge plugin format.
|
|
135
147
|
*/
|
|
136
148
|
export async function runPluginImport(sourceDir, dryRun, onStep) {
|
|
137
|
-
const stepId =
|
|
138
|
-
report(onStep, stepId, `Import agent-skills package: ${sourceDir}`,
|
|
149
|
+
const stepId = "plugin-import";
|
|
150
|
+
report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, "running");
|
|
139
151
|
const result = await importAgentSkillsPackage(sourceDir, { dryRun });
|
|
140
152
|
if (result.success) {
|
|
141
|
-
report(onStep, stepId, `Import agent-skills package: ${sourceDir}`,
|
|
153
|
+
report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, "done", dryRun
|
|
154
|
+
? `dry-run: would import ${result.name}`
|
|
155
|
+
: `imported ${result.name}`);
|
|
142
156
|
}
|
|
143
157
|
else {
|
|
144
|
-
report(onStep, stepId, `Import agent-skills package: ${sourceDir}`,
|
|
158
|
+
report(onStep, stepId, `Import agent-skills package: ${sourceDir}`, "error", result.error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Generate a project-level skills.json from all installed plugins.
|
|
163
|
+
* Makes the project discoverable by `npx skills add` and 40+ AI agents.
|
|
164
|
+
*/
|
|
165
|
+
export async function runPluginExportSkillsJson(projectDir, dryRun, onStep) {
|
|
166
|
+
const stepId = "plugin-export-skills-json";
|
|
167
|
+
report(onStep, stepId, "Generate project skills.json", "running");
|
|
168
|
+
const result = await generateProjectSkillsJson(projectDir, { dryRun });
|
|
169
|
+
if (result.success) {
|
|
170
|
+
const prefix = dryRun ? "dry-run: would generate" : "generated";
|
|
171
|
+
report(onStep, stepId, "Generate project skills.json", "done", `${prefix} ${result.path} (${result.skillCount} skills from ${result.pluginCount} plugins)`);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
report(onStep, stepId, "Generate project skills.json", "error", result.error);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Generate a global skills.json from all globally installed plugins.
|
|
179
|
+
*/
|
|
180
|
+
export async function runPluginExportGlobalSkillsJson(dryRun, onStep) {
|
|
181
|
+
const stepId = "plugin-export-global-skills-json";
|
|
182
|
+
report(onStep, stepId, "Generate global skills.json", "running");
|
|
183
|
+
const result = await generateGlobalSkillsJson({ dryRun });
|
|
184
|
+
if (result.success) {
|
|
185
|
+
const prefix = dryRun ? "dry-run: would generate" : "generated";
|
|
186
|
+
report(onStep, stepId, "Generate global skills.json", "done", `${prefix} ${result.path} (${result.skillCount} skills from ${result.pluginCount} plugins)`);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
report(onStep, stepId, "Generate global skills.json", "error", result.error);
|
|
145
190
|
}
|
|
146
191
|
}
|
|
147
192
|
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret scanner — detects leaked credentials in source files using
|
|
3
|
+
* a curated regex bundle. Designed for pre-commit hooks and CI gates.
|
|
4
|
+
*/
|
|
5
|
+
export interface SecretPattern {
|
|
6
|
+
id: string;
|
|
7
|
+
label: string;
|
|
8
|
+
pattern: RegExp;
|
|
9
|
+
severity: "critical" | "high" | "medium";
|
|
10
|
+
}
|
|
11
|
+
export interface SecretFinding {
|
|
12
|
+
patternId: string;
|
|
13
|
+
label: string;
|
|
14
|
+
severity: SecretPattern["severity"];
|
|
15
|
+
file: string;
|
|
16
|
+
line: number;
|
|
17
|
+
match: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ScanResult {
|
|
20
|
+
findings: SecretFinding[];
|
|
21
|
+
filesScanned: number;
|
|
22
|
+
patternsUsed: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const SECRET_PATTERNS: SecretPattern[];
|
|
25
|
+
export declare function maskSecret(value: string): string;
|
|
26
|
+
export declare function shouldScanFile(filePath: string): boolean;
|
|
27
|
+
export declare function shouldSkipDir(dirName: string): boolean;
|
|
28
|
+
export declare function scanContent(content: string, filePath: string, patterns?: SecretPattern[]): SecretFinding[];
|
|
29
|
+
export declare function scanDirectory(dir: string, patterns?: SecretPattern[]): Promise<ScanResult>;
|
|
30
|
+
//# sourceMappingURL=secret-scanner.d.ts.map
|