javi-forge 1.3.0 → 1.5.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/ci-local/ci-local.sh +9 -1
- package/ci-local/hooks/commit-msg +0 -0
- package/ci-local/hooks/pre-commit +1 -1
- package/ci-local/hooks/pre-push +0 -0
- package/ci-local/install.sh +0 -0
- package/ci-local/lib/common.sh +183 -0
- package/dist/__integration__/helpers.d.ts +20 -0
- package/dist/__integration__/helpers.d.ts.map +1 -0
- package/dist/__integration__/helpers.js +31 -0
- package/dist/__integration__/helpers.js.map +1 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/ci.d.ts +4 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +110 -8
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +1 -3
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +14 -6
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/llmstxt.d.ts.map +1 -0
- package/dist/commands/llmstxt.js.map +1 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/constants.d.ts +0 -4
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +0 -4
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -11
- package/dist/index.js.map +1 -0
- package/dist/lib/common.d.ts.map +1 -0
- package/dist/lib/common.js.map +1 -0
- package/dist/lib/docker.d.ts +2 -0
- package/dist/lib/docker.d.ts.map +1 -0
- package/dist/lib/docker.js +2 -1
- package/dist/lib/docker.js.map +1 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/plugin.d.ts.map +1 -0
- package/dist/lib/plugin.js.map +1 -0
- package/dist/lib/template.d.ts.map +1 -0
- package/dist/lib/template.js.map +1 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/AnalyzeUI.d.ts.map +1 -0
- package/dist/ui/AnalyzeUI.js.map +1 -0
- package/dist/ui/App.d.ts.map +1 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/CI.d.ts.map +1 -0
- package/dist/ui/CI.js.map +1 -0
- package/dist/ui/CIContext.d.ts.map +1 -0
- package/dist/ui/CIContext.js.map +1 -0
- package/dist/ui/CISelector.d.ts.map +1 -0
- package/dist/ui/CISelector.js.map +1 -0
- package/dist/ui/Doctor.d.ts.map +1 -0
- package/dist/ui/Doctor.js +1 -1
- package/dist/ui/Doctor.js.map +1 -0
- package/dist/ui/Header.d.ts.map +1 -0
- package/dist/ui/Header.js.map +1 -0
- package/dist/ui/LlmsTxt.d.ts.map +1 -0
- package/dist/ui/LlmsTxt.js.map +1 -0
- package/dist/ui/MemorySelector.d.ts.map +1 -0
- package/dist/ui/MemorySelector.js.map +1 -0
- package/dist/ui/NameInput.d.ts.map +1 -0
- package/dist/ui/NameInput.js.map +1 -0
- package/dist/ui/OptionSelector.d.ts.map +1 -0
- package/dist/ui/OptionSelector.js +1 -1
- package/dist/ui/OptionSelector.js.map +1 -0
- package/dist/ui/Plugin.d.ts.map +1 -0
- package/dist/ui/Plugin.js.map +1 -0
- package/dist/ui/Progress.d.ts.map +1 -0
- package/dist/ui/Progress.js.map +1 -0
- package/dist/ui/StackSelector.d.ts.map +1 -0
- package/dist/ui/StackSelector.js.map +1 -0
- package/dist/ui/Summary.d.ts.map +1 -0
- package/dist/ui/Summary.js.map +1 -0
- package/dist/ui/Welcome.d.ts.map +1 -0
- package/dist/ui/Welcome.js.map +1 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js.map +1 -0
- package/lib/common.sh +2 -2
- package/modules/ghagga/README.md +2 -2
- package/modules/ghagga/setup-ghagga.sh +1 -1
- package/package.json +25 -12
- package/templates/github/ci-go.yml +1 -1
- package/templates/github/ci-java.yml +2 -2
- package/templates/github/ci-node.yml +1 -1
- package/templates/github/ci-python.yml +1 -1
- package/templates/github/ci-rust.yml +1 -1
- package/templates/github/ghagga-review.yml +28 -0
- package/workflows/reusable-build-go.yml +1 -1
- package/workflows/reusable-build-java.yml +1 -1
- package/workflows/reusable-build-node.yml +1 -1
- package/workflows/reusable-build-python.yml +1 -1
- package/workflows/reusable-build-rust.yml +1 -1
- package/workflows/reusable-docker.yml +1 -1
- package/workflows/reusable-ghagga-review.yml +1 -1
- package/workflows/reusable-release.yml +1 -1
- package/.releaserc +0 -45
- package/dist/commands/analyze.test.d.ts +0 -2
- package/dist/commands/doctor.test.d.ts +0 -2
- package/dist/commands/init.test.d.ts +0 -2
- package/dist/commands/llmstxt.test.d.ts +0 -2
- package/dist/commands/plugin.test.d.ts +0 -2
- package/dist/commands/sync.d.ts +0 -8
- package/dist/commands/sync.js +0 -201
- package/dist/e2e/aggressive.e2e.test.d.ts +0 -2
- package/dist/e2e/commands.e2e.test.d.ts +0 -2
- package/dist/lib/common.test.d.ts +0 -2
- package/dist/lib/frontmatter.test.d.ts +0 -2
- package/dist/lib/plugin.test.d.ts +0 -2
- package/dist/lib/template.test.d.ts +0 -2
- package/dist/ui/SyncUI.d.ts +0 -10
- package/dist/ui/SyncUI.js +0 -64
- package/tasks/_TEMPLATE/files-edited.md +0 -3
- package/tasks/_TEMPLATE/plan.md +0 -3
- package/tasks/_TEMPLATE/research.md +0 -3
- package/tasks/_TEMPLATE/verification.md +0 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/ui/theme.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK;;;;;;;CAOR,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,OAAO,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/ui/theme.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,OAAO,EAAG,SAAS,EAAG,SAAS;IAC/B,OAAO,EAAG,OAAO;IACjB,OAAO,EAAG,QAAQ;IAClB,KAAK,EAAK,KAAK;IACf,KAAK,EAAK,MAAM;IAChB,MAAM,EAAI,SAAS;CACX,CAAA"}
|
package/lib/common.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# =============================================================================
|
|
3
|
-
# lib/common.sh - Shared functions for
|
|
3
|
+
# lib/common.sh - Shared functions for javi-forge
|
|
4
4
|
# =============================================================================
|
|
5
5
|
# Source from scripts: source "$(dirname "$0")/../lib/common.sh"
|
|
6
6
|
# Source from ci-local: source "$(dirname "$0")/../lib/common.sh"
|
|
@@ -161,7 +161,7 @@ detect_stack() {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
# =============================================================================
|
|
164
|
-
# detect_framework - Locate the
|
|
164
|
+
# detect_framework - Locate the javi-forge directory
|
|
165
165
|
# =============================================================================
|
|
166
166
|
# Sets: FRAMEWORK_DIR (path to framework root, or empty string)
|
|
167
167
|
# HAS_OPTIONAL (true/false if optional/ dir exists)
|
package/modules/ghagga/README.md
CHANGED
|
@@ -60,7 +60,7 @@ En tu `.github/workflows/ci.yml`:
|
|
|
60
60
|
```yaml
|
|
61
61
|
jobs:
|
|
62
62
|
review:
|
|
63
|
-
uses: JNZader/
|
|
63
|
+
uses: JNZader/javi-forge/.github/workflows/reusable-ghagga-review.yml@main
|
|
64
64
|
with:
|
|
65
65
|
ghagga-url: ${{ vars.GHAGGA_URL }}
|
|
66
66
|
secrets:
|
|
@@ -142,7 +142,7 @@ Ejecuta reglas Semgrep como complemento al analisis LLM, cubriendo patrones de s
|
|
|
142
142
|
|
|
143
143
|
## Integracion con el Framework
|
|
144
144
|
|
|
145
|
-
Cuando usas GHAGGA con
|
|
145
|
+
Cuando usas GHAGGA con javi-forge:
|
|
146
146
|
|
|
147
147
|
- **CI-Local** valida codigo antes del push (pre-commit, pre-push)
|
|
148
148
|
- **GHAGGA** revisa el PR despues del push (review automatico)
|
|
@@ -50,7 +50,7 @@ concurrency:
|
|
|
50
50
|
|
|
51
51
|
jobs:
|
|
52
52
|
review:
|
|
53
|
-
uses: JNZader/
|
|
53
|
+
uses: JNZader/javi-forge/.github/workflows/reusable-ghagga-review.yml@main
|
|
54
54
|
with:
|
|
55
55
|
ghagga-url: ${{ vars.GHAGGA_URL }}
|
|
56
56
|
review-mode: simple
|
package/package.json
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "javi-forge",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Project scaffolding and AI-ready CI bootstrap",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"javi-forge": "./dist/index.js"
|
|
8
8
|
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsx watch src/index.tsx",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
16
|
+
"test:coverage": "vitest run --coverage",
|
|
17
|
+
"test:mutation": "stryker run"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist/",
|
|
21
|
+
"ci-local/",
|
|
22
|
+
"modules/",
|
|
23
|
+
"templates/",
|
|
24
|
+
"workflows/",
|
|
25
|
+
"lib/",
|
|
26
|
+
"!dist/**/*.test.*",
|
|
27
|
+
"!dist/**/__snapshots__",
|
|
28
|
+
"package.json",
|
|
29
|
+
"README.md",
|
|
30
|
+
".gitignore.template"
|
|
31
|
+
],
|
|
9
32
|
"author": "JNZader",
|
|
10
33
|
"license": "MIT",
|
|
11
34
|
"repository": {
|
|
@@ -45,15 +68,5 @@
|
|
|
45
68
|
"tsx": "^4.21.0",
|
|
46
69
|
"typescript": "^5.9.3",
|
|
47
70
|
"vitest": "^4.1.0"
|
|
48
|
-
},
|
|
49
|
-
"scripts": {
|
|
50
|
-
"build": "tsc",
|
|
51
|
-
"dev": "tsx watch src/index.tsx",
|
|
52
|
-
"start": "node dist/index.js",
|
|
53
|
-
"typecheck": "tsc --noEmit",
|
|
54
|
-
"test": "vitest run",
|
|
55
|
-
"test:watch": "vitest",
|
|
56
|
-
"test:coverage": "vitest run --coverage",
|
|
57
|
-
"test:mutation": "stryker run"
|
|
58
71
|
}
|
|
59
|
-
}
|
|
72
|
+
}
|
|
@@ -34,7 +34,7 @@ concurrency:
|
|
|
34
34
|
|
|
35
35
|
jobs:
|
|
36
36
|
build:
|
|
37
|
-
uses: JNZader/
|
|
37
|
+
uses: JNZader/javi-forge/.github/workflows/reusable-build-go.yml@main
|
|
38
38
|
with:
|
|
39
39
|
go-version: '1.23' # Change to: 1.22, 1.23
|
|
40
40
|
run-lint: true
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# ===========================================
|
|
4
4
|
# Copy to: .github/workflows/ci.yml
|
|
5
5
|
#
|
|
6
|
-
# This uses reusable workflows from
|
|
6
|
+
# This uses reusable workflows from javi-forge.
|
|
7
7
|
# Runs on pushes to main, PRs, and manual triggers.
|
|
8
8
|
# ===========================================
|
|
9
9
|
|
|
@@ -37,7 +37,7 @@ concurrency:
|
|
|
37
37
|
|
|
38
38
|
jobs:
|
|
39
39
|
build:
|
|
40
|
-
uses: JNZader/
|
|
40
|
+
uses: JNZader/javi-forge/.github/workflows/reusable-build-java.yml@main
|
|
41
41
|
with:
|
|
42
42
|
java-version: '21' # Change to your version: 17, 21, 25
|
|
43
43
|
run-spotless: true
|
|
@@ -34,7 +34,7 @@ concurrency:
|
|
|
34
34
|
|
|
35
35
|
jobs:
|
|
36
36
|
build:
|
|
37
|
-
uses: JNZader/
|
|
37
|
+
uses: JNZader/javi-forge/.github/workflows/reusable-build-node.yml@main
|
|
38
38
|
with:
|
|
39
39
|
node-version: '20' # Change to: 18, 20, 22
|
|
40
40
|
package-manager: 'npm' # Change to: npm, yarn, pnpm
|
|
@@ -34,7 +34,7 @@ concurrency:
|
|
|
34
34
|
|
|
35
35
|
jobs:
|
|
36
36
|
build:
|
|
37
|
-
uses: JNZader/
|
|
37
|
+
uses: JNZader/javi-forge/.github/workflows/reusable-build-python.yml@main
|
|
38
38
|
with:
|
|
39
39
|
python-version: '3.12' # Change to: 3.10, 3.11, 3.12
|
|
40
40
|
package-manager: 'pip' # Change to: pip, poetry, uv
|
|
@@ -34,7 +34,7 @@ concurrency:
|
|
|
34
34
|
|
|
35
35
|
jobs:
|
|
36
36
|
build:
|
|
37
|
-
uses: JNZader/
|
|
37
|
+
uses: JNZader/javi-forge/.github/workflows/reusable-build-rust.yml@main
|
|
38
38
|
with:
|
|
39
39
|
toolchain: 'stable' # Change to: stable, beta, nightly
|
|
40
40
|
run-clippy: true
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# ===========================================
|
|
2
|
+
# GHAGGA AI Code Review
|
|
3
|
+
# ===========================================
|
|
4
|
+
# Triggers AI code review on pull requests.
|
|
5
|
+
# Requires: GHAGGA GitHub Action (JNZader/ghagga@v1)
|
|
6
|
+
#
|
|
7
|
+
# Modes: simple (default), workflow, consensus
|
|
8
|
+
# ===========================================
|
|
9
|
+
|
|
10
|
+
name: Code Review
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
pull_request:
|
|
14
|
+
types: [opened, synchronize, reopened]
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
pull-requests: write
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
review:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- uses: JNZader/ghagga@v1
|
|
26
|
+
with:
|
|
27
|
+
mode: simple
|
|
28
|
+
provider: github
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Usage:
|
|
7
7
|
# jobs:
|
|
8
8
|
# build:
|
|
9
|
-
# uses: JNZader/
|
|
9
|
+
# uses: JNZader/javi-forge/.github/workflows/reusable-build-go.yml@main
|
|
10
10
|
# with:
|
|
11
11
|
# go-version: '1.23'
|
|
12
12
|
# ===========================================
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Usage in your project:
|
|
7
7
|
# jobs:
|
|
8
8
|
# build:
|
|
9
|
-
# uses: JNZader/
|
|
9
|
+
# uses: JNZader/javi-forge/.github/workflows/reusable-build-java.yml@main
|
|
10
10
|
# with:
|
|
11
11
|
# java-version: '21'
|
|
12
12
|
# ===========================================
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Usage:
|
|
7
7
|
# jobs:
|
|
8
8
|
# build:
|
|
9
|
-
# uses: JNZader/
|
|
9
|
+
# uses: JNZader/javi-forge/.github/workflows/reusable-build-node.yml@main
|
|
10
10
|
# with:
|
|
11
11
|
# node-version: '20'
|
|
12
12
|
# ===========================================
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Usage:
|
|
7
7
|
# jobs:
|
|
8
8
|
# build:
|
|
9
|
-
# uses: JNZader/
|
|
9
|
+
# uses: JNZader/javi-forge/.github/workflows/reusable-build-python.yml@main
|
|
10
10
|
# with:
|
|
11
11
|
# python-version: '3.12'
|
|
12
12
|
# ===========================================
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Usage:
|
|
7
7
|
# jobs:
|
|
8
8
|
# build:
|
|
9
|
-
# uses: JNZader/
|
|
9
|
+
# uses: JNZader/javi-forge/.github/workflows/reusable-build-rust.yml@main
|
|
10
10
|
# ===========================================
|
|
11
11
|
|
|
12
12
|
name: Rust Build (Reusable)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Usage:
|
|
7
7
|
# jobs:
|
|
8
8
|
# docker:
|
|
9
|
-
# uses: JNZader/
|
|
9
|
+
# uses: JNZader/javi-forge/.github/workflows/reusable-docker.yml@main
|
|
10
10
|
# with:
|
|
11
11
|
# dockerfile: './Dockerfile'
|
|
12
12
|
# ===========================================
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Usage:
|
|
7
7
|
# jobs:
|
|
8
8
|
# review:
|
|
9
|
-
# uses: JNZader/
|
|
9
|
+
# uses: JNZader/javi-forge/.github/workflows/reusable-ghagga-review.yml@main
|
|
10
10
|
# with:
|
|
11
11
|
# ghagga-url: ${{ vars.GHAGGA_URL }}
|
|
12
12
|
# secrets:
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Usage:
|
|
7
7
|
# jobs:
|
|
8
8
|
# release:
|
|
9
|
-
# uses: JNZader/
|
|
9
|
+
# uses: JNZader/javi-forge/.github/workflows/reusable-release.yml@main
|
|
10
10
|
# secrets:
|
|
11
11
|
# token: ${{ secrets.GITHUB_TOKEN }}
|
|
12
12
|
# ===========================================
|
package/.releaserc
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"branches": ["main"],
|
|
3
|
-
"tagFormat": "v${version}",
|
|
4
|
-
"plugins": [
|
|
5
|
-
["@semantic-release/commit-analyzer", {
|
|
6
|
-
"preset": "conventionalcommits",
|
|
7
|
-
"releaseRules": [
|
|
8
|
-
{"type": "feat", "release": "minor"},
|
|
9
|
-
{"type": "fix", "release": "patch"},
|
|
10
|
-
{"type": "perf", "release": "patch"},
|
|
11
|
-
{"type": "refactor", "release": "patch"},
|
|
12
|
-
{"type": "docs", "release": false},
|
|
13
|
-
{"type": "style", "release": false},
|
|
14
|
-
{"type": "chore", "release": false},
|
|
15
|
-
{"type": "test", "release": false},
|
|
16
|
-
{"breaking": true, "release": "major"}
|
|
17
|
-
]
|
|
18
|
-
}],
|
|
19
|
-
["@semantic-release/release-notes-generator", {
|
|
20
|
-
"preset": "conventionalcommits",
|
|
21
|
-
"presetConfig": {
|
|
22
|
-
"types": [
|
|
23
|
-
{"type": "feat", "section": "Features"},
|
|
24
|
-
{"type": "fix", "section": "Bug Fixes"},
|
|
25
|
-
{"type": "perf", "section": "Performance"},
|
|
26
|
-
{"type": "refactor", "section": "Refactoring"},
|
|
27
|
-
{"type": "docs", "section": "Documentation", "hidden": true},
|
|
28
|
-
{"type": "chore", "section": "Maintenance", "hidden": true}
|
|
29
|
-
]
|
|
30
|
-
}
|
|
31
|
-
}],
|
|
32
|
-
["@semantic-release/changelog", {
|
|
33
|
-
"changelogFile": "CHANGELOG.md"
|
|
34
|
-
}],
|
|
35
|
-
["@semantic-release/exec", {
|
|
36
|
-
"prepareCmd": "echo ${nextRelease.version} > .framework-version"
|
|
37
|
-
}],
|
|
38
|
-
"@semantic-release/npm",
|
|
39
|
-
["@semantic-release/git", {
|
|
40
|
-
"assets": ["CHANGELOG.md", "package.json", ".framework-version"],
|
|
41
|
-
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
42
|
-
}],
|
|
43
|
-
"@semantic-release/github"
|
|
44
|
-
]
|
|
45
|
-
}
|
package/dist/commands/sync.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { SyncOptions, InitStep } from '../types/index.js';
|
|
2
|
-
type StepCallback = (step: InitStep) => void;
|
|
3
|
-
/**
|
|
4
|
-
* Sync AI config to a project directory, generating CLI-specific config files.
|
|
5
|
-
*/
|
|
6
|
-
export declare function syncAIConfig(options: SyncOptions, onStep: StepCallback): Promise<void>;
|
|
7
|
-
export {};
|
|
8
|
-
//# sourceMappingURL=sync.d.ts.map
|
package/dist/commands/sync.js
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { ensureDirExists } from '../lib/common.js';
|
|
4
|
-
import { parseFrontmatter } from '../lib/frontmatter.js';
|
|
5
|
-
import { AI_CONFIG_DIR, AI_CLI_CONFIG_FILES, MARKER_START, MARKER_END, } from '../constants.js';
|
|
6
|
-
const ALL_TARGETS = ['claude', 'opencode', 'gemini', 'qwen', 'codex', 'copilot'];
|
|
7
|
-
function report(onStep, id, label, status, detail) {
|
|
8
|
-
onStep({ id, label, status, detail });
|
|
9
|
-
}
|
|
10
|
-
/** Read .skillignore and parse exclusion rules */
|
|
11
|
-
async function loadSkillIgnore(configDir) {
|
|
12
|
-
const globalExcludes = new Set();
|
|
13
|
-
const targetExcludes = new Map();
|
|
14
|
-
const ignorePath = path.join(configDir, '.skillignore');
|
|
15
|
-
if (!await fs.pathExists(ignorePath)) {
|
|
16
|
-
return { globalExcludes, targetExcludes };
|
|
17
|
-
}
|
|
18
|
-
const content = await fs.readFile(ignorePath, 'utf-8');
|
|
19
|
-
for (const rawLine of content.split('\n')) {
|
|
20
|
-
const line = rawLine.trim();
|
|
21
|
-
if (!line || line.startsWith('#'))
|
|
22
|
-
continue;
|
|
23
|
-
if (line.includes(':')) {
|
|
24
|
-
const [target, skill] = line.split(':', 2);
|
|
25
|
-
if (target && skill) {
|
|
26
|
-
if (!targetExcludes.has(target))
|
|
27
|
-
targetExcludes.set(target, new Set());
|
|
28
|
-
targetExcludes.get(target).add(skill);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
globalExcludes.add(line);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return { globalExcludes, targetExcludes };
|
|
36
|
-
}
|
|
37
|
-
/** Recursively collect agent/skill markdown files from a directory */
|
|
38
|
-
async function collectMarkdownEntries(baseDir, prefix = '') {
|
|
39
|
-
const entries = [];
|
|
40
|
-
if (!await fs.pathExists(baseDir))
|
|
41
|
-
return entries;
|
|
42
|
-
const items = await fs.readdir(baseDir, { withFileTypes: true });
|
|
43
|
-
for (const item of items) {
|
|
44
|
-
if (item.name.startsWith('_') || item.name.startsWith('.'))
|
|
45
|
-
continue;
|
|
46
|
-
const itemPath = path.join(baseDir, item.name);
|
|
47
|
-
const relPath = prefix ? `${prefix}/${item.name}` : item.name;
|
|
48
|
-
if (item.isDirectory()) {
|
|
49
|
-
// Look for SKILL.md or agent markdown inside
|
|
50
|
-
const skillMd = path.join(itemPath, 'SKILL.md');
|
|
51
|
-
if (await fs.pathExists(skillMd)) {
|
|
52
|
-
const content = await fs.readFile(skillMd, 'utf-8');
|
|
53
|
-
entries.push({ relativePath: relPath, name: item.name, content });
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
// Recurse into subcategory directories
|
|
57
|
-
const subEntries = await collectMarkdownEntries(itemPath, relPath);
|
|
58
|
-
entries.push(...subEntries);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
else if (item.name.endsWith('.md') && item.name !== 'README.md') {
|
|
62
|
-
const content = await fs.readFile(itemPath, 'utf-8');
|
|
63
|
-
const name = item.name.replace('.md', '');
|
|
64
|
-
entries.push({ relativePath: relPath, name, content });
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return entries;
|
|
68
|
-
}
|
|
69
|
-
/** Build a CLAUDE.md / GEMINI.md / etc from agents + skills */
|
|
70
|
-
function buildConfigContent(target, agents, skills) {
|
|
71
|
-
const lines = [];
|
|
72
|
-
lines.push(`# AI Configuration for ${target}`);
|
|
73
|
-
lines.push('');
|
|
74
|
-
lines.push(`Auto-generated by javi-forge sync. Do not edit between markers.`);
|
|
75
|
-
lines.push('');
|
|
76
|
-
if (agents.length > 0) {
|
|
77
|
-
lines.push('## Agents');
|
|
78
|
-
lines.push('');
|
|
79
|
-
for (const agent of agents) {
|
|
80
|
-
const fm = parseFrontmatter(agent.content);
|
|
81
|
-
if (fm?.data) {
|
|
82
|
-
const desc = fm.data['description'] ?? '';
|
|
83
|
-
lines.push(`- **${agent.name}**: ${desc}`);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
lines.push(`- **${agent.name}**`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
lines.push('');
|
|
90
|
-
}
|
|
91
|
-
if (skills.length > 0) {
|
|
92
|
-
lines.push('## Available Skills');
|
|
93
|
-
lines.push('');
|
|
94
|
-
for (const skill of skills) {
|
|
95
|
-
const fm = parseFrontmatter(skill.content);
|
|
96
|
-
if (fm?.data) {
|
|
97
|
-
const desc = fm.data['description'] ?? '';
|
|
98
|
-
lines.push(`- **${skill.name}**: ${desc}`);
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
lines.push(`- **${skill.name}**`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
lines.push('');
|
|
105
|
-
}
|
|
106
|
-
return lines.join('\n');
|
|
107
|
-
}
|
|
108
|
-
/** Merge generated content into an existing file using markers */
|
|
109
|
-
function mergeWithMarkers(existingContent, generatedContent) {
|
|
110
|
-
const startIdx = existingContent.indexOf(MARKER_START);
|
|
111
|
-
const endIdx = existingContent.indexOf(MARKER_END);
|
|
112
|
-
const markerBlock = `${MARKER_START}\n${generatedContent}\n${MARKER_END}`;
|
|
113
|
-
if (startIdx !== -1 && endIdx !== -1) {
|
|
114
|
-
// Replace existing marker block
|
|
115
|
-
return existingContent.slice(0, startIdx) + markerBlock + existingContent.slice(endIdx + MARKER_END.length);
|
|
116
|
-
}
|
|
117
|
-
// Append marker block
|
|
118
|
-
return existingContent.trimEnd() + '\n\n' + markerBlock + '\n';
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Sync AI config to a project directory, generating CLI-specific config files.
|
|
122
|
-
*/
|
|
123
|
-
export async function syncAIConfig(options, onStep) {
|
|
124
|
-
const { target, mode, projectDir, dryRun } = options;
|
|
125
|
-
const targets = target === 'all' ? ALL_TARGETS : [target];
|
|
126
|
-
const configDir = AI_CONFIG_DIR;
|
|
127
|
-
// Load exclusions
|
|
128
|
-
const { globalExcludes, targetExcludes } = await loadSkillIgnore(configDir);
|
|
129
|
-
// Collect agents and skills
|
|
130
|
-
const agentsDir = path.join(configDir, 'agents');
|
|
131
|
-
const skillsDir = path.join(configDir, 'skills');
|
|
132
|
-
const allAgents = await collectMarkdownEntries(agentsDir);
|
|
133
|
-
const allSkills = await collectMarkdownEntries(skillsDir);
|
|
134
|
-
for (const cli of targets) {
|
|
135
|
-
const stepId = `sync-${cli}`;
|
|
136
|
-
report(onStep, stepId, `Sync config for ${cli}`, 'running');
|
|
137
|
-
try {
|
|
138
|
-
// Filter out excluded skills
|
|
139
|
-
const cliExcludes = targetExcludes.get(cli) ?? new Set();
|
|
140
|
-
const filteredSkills = allSkills.filter(s => {
|
|
141
|
-
const nameWithoutExt = s.name;
|
|
142
|
-
const relWithoutExt = s.relativePath.replace(/\.md$/, '').replace(/\/SKILL\.md$/, '');
|
|
143
|
-
return !globalExcludes.has(nameWithoutExt)
|
|
144
|
-
&& !globalExcludes.has(relWithoutExt)
|
|
145
|
-
&& !cliExcludes.has(nameWithoutExt)
|
|
146
|
-
&& !cliExcludes.has(relWithoutExt);
|
|
147
|
-
});
|
|
148
|
-
const filteredAgents = allAgents.filter(a => {
|
|
149
|
-
return !globalExcludes.has(a.name) && !cliExcludes.has(a.name);
|
|
150
|
-
});
|
|
151
|
-
// Build the config content
|
|
152
|
-
const generatedContent = buildConfigContent(cli, filteredAgents, filteredSkills);
|
|
153
|
-
// Determine destination
|
|
154
|
-
const configFileName = AI_CLI_CONFIG_FILES[cli];
|
|
155
|
-
if (!configFileName) {
|
|
156
|
-
report(onStep, stepId, `Sync config for ${cli}`, 'skipped', 'no config file mapping');
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
const destPath = path.join(projectDir, configFileName);
|
|
160
|
-
if (!dryRun) {
|
|
161
|
-
await ensureDirExists(path.dirname(destPath));
|
|
162
|
-
if (mode === 'merge' && await fs.pathExists(destPath)) {
|
|
163
|
-
const existing = await fs.readFile(destPath, 'utf-8');
|
|
164
|
-
const merged = mergeWithMarkers(existing, generatedContent);
|
|
165
|
-
await fs.writeFile(destPath, merged, 'utf-8');
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
await fs.writeFile(destPath, generatedContent, 'utf-8');
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
report(onStep, stepId, `Sync config for ${cli}`, 'done', `${filteredAgents.length} agents, ${filteredSkills.length} skills → ${configFileName}`);
|
|
172
|
-
// Sync Claude commands if target is claude
|
|
173
|
-
if (cli === 'claude') {
|
|
174
|
-
const cmdStepId = `sync-${cli}-commands`;
|
|
175
|
-
report(onStep, cmdStepId, 'Sync Claude commands', 'running');
|
|
176
|
-
try {
|
|
177
|
-
const commandsSrc = path.join(configDir, 'commands');
|
|
178
|
-
if (await fs.pathExists(commandsSrc)) {
|
|
179
|
-
const commandsDest = path.join(projectDir, '.claude', 'commands');
|
|
180
|
-
if (!dryRun) {
|
|
181
|
-
await ensureDirExists(commandsDest);
|
|
182
|
-
await fs.copy(commandsSrc, commandsDest, { overwrite: true });
|
|
183
|
-
}
|
|
184
|
-
const cmdFiles = await fs.readdir(commandsSrc);
|
|
185
|
-
report(onStep, cmdStepId, 'Sync Claude commands', 'done', `${cmdFiles.length} commands`);
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
report(onStep, cmdStepId, 'Sync Claude commands', 'skipped', 'no commands dir');
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
catch (e) {
|
|
192
|
-
report(onStep, cmdStepId, 'Sync Claude commands', 'error', String(e));
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
catch (e) {
|
|
197
|
-
report(onStep, stepId, `Sync config for ${cli}`, 'error', String(e));
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
//# sourceMappingURL=sync.js.map
|
package/dist/ui/SyncUI.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { AI_CLI } from '../types/index.js';
|
|
3
|
-
interface Props {
|
|
4
|
-
target: AI_CLI | 'all';
|
|
5
|
-
mode: 'overwrite' | 'merge';
|
|
6
|
-
dryRun: boolean;
|
|
7
|
-
}
|
|
8
|
-
export default function SyncUI({ target, mode, dryRun }: Props): React.JSX.Element;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=SyncUI.d.ts.map
|