@oomerevren/tryforge 0.1.2 → 0.1.3
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/CHANGELOG.md +107 -13
- package/README.md +172 -232
- package/dist/cli/src/adapters/agents-md.js +24 -0
- package/dist/cli/src/adapters/base.js +99 -0
- package/dist/cli/src/adapters/claude.js +43 -14
- package/dist/cli/src/adapters/codex.js +18 -17
- package/dist/cli/src/adapters/cursor.js +44 -30
- package/dist/cli/src/adapters/dsh.js +28 -30
- package/dist/cli/src/adapters/generic.js +10 -7
- package/dist/cli/src/adapters/opencode.js +23 -23
- package/dist/cli/src/adapters/types.js +12 -9
- package/dist/cli/src/adapters/windsurf.js +48 -28
- package/dist/cli/src/commands/add-external.js +111 -0
- package/dist/cli/src/commands/audit.js +68 -30
- package/dist/cli/src/commands/init.js +2 -2
- package/dist/cli/src/commands/install.js +90 -15
- package/dist/cli/src/commands/pack.js +119 -0
- package/dist/cli/src/commands/sync.js +181 -0
- package/dist/cli/src/commands/test.js +72 -0
- package/dist/cli/src/commands/tui.js +191 -0
- package/dist/cli/src/commands/update.js +4 -4
- package/dist/cli/src/commands/verify.js +62 -0
- package/dist/cli/src/core/fsutil.js +37 -0
- package/dist/cli/src/core/installer.js +9 -9
- package/dist/cli/src/core/lock.js +97 -10
- package/dist/cli/src/core/merge.js +108 -0
- package/dist/cli/src/core/plugin.js +2 -2
- package/dist/cli/src/core/project.js +136 -4
- package/dist/cli/src/core/registry.js +9 -9
- package/dist/cli/src/core/scan.js +159 -0
- package/dist/cli/src/core/semver.js +7 -7
- package/dist/cli/src/core/sign.js +2 -2
- package/dist/cli/src/core/sources.js +171 -0
- package/dist/cli/src/index.js +83 -16
- package/dist/index.cjs +359 -0
- package/dist/scripts/build-registry.js +2 -4
- package/dist/scripts/publish-verified.js +17 -9
- package/dist/scripts/seed-registry-13lite.js +5 -5
- package/dist/scripts/seed-registry.js +4 -4
- package/dist/scripts/verify-npm-mcps.js +6 -4
- package/package.json +15 -6
|
@@ -118,8 +118,6 @@ function build() {
|
|
|
118
118
|
process.exit(1);
|
|
119
119
|
}
|
|
120
120
|
const existing = JSON.parse(readFileSync(INDEX_FILE, "utf-8"));
|
|
121
|
-
const expected = JSON.stringify(index, null, 2);
|
|
122
|
-
const actual = JSON.stringify(existing, null, 2);
|
|
123
121
|
// compare count and package keys (ignore generatedAt)
|
|
124
122
|
const existingCount = existing.count;
|
|
125
123
|
const expectedCount = index.count;
|
|
@@ -130,7 +128,7 @@ function build() {
|
|
|
130
128
|
}
|
|
131
129
|
console.log(`[build --check] OK — index.json in sync (count=${existingCount})`);
|
|
132
130
|
if (placeholderCount > 0)
|
|
133
|
-
console.warn(`[build --check] warn: ${placeholderCount} placeholder sha256 (expected in
|
|
131
|
+
console.warn(`[build --check] warn: ${placeholderCount} placeholder sha256 (expected in Phase 2)`);
|
|
134
132
|
return;
|
|
135
133
|
}
|
|
136
134
|
writeFileSync(INDEX_FILE, JSON.stringify(index, null, 2) + "\n");
|
|
@@ -140,6 +138,6 @@ function build() {
|
|
|
140
138
|
console.log(`[build] wrote ${SEARCH_FILE} (${search.length} entries)`);
|
|
141
139
|
console.log(`[build] wrote ${STATS_FILE} ${JSON.stringify(byType)}`);
|
|
142
140
|
if (placeholderCount > 0)
|
|
143
|
-
console.warn(`[build] warn: ${placeholderCount} placeholder sha256 (
|
|
141
|
+
console.warn(`[build] warn: ${placeholderCount} placeholder sha256 (Phase 2 mock, Phase 3 real)`);
|
|
144
142
|
}
|
|
145
143
|
build();
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
// scripts/publish-verified.ts — forge-authored
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
|
|
2
|
+
// scripts/publish-verified.ts — pack forge-authored content into tarballs, upload
|
|
3
|
+
// them to the registry-v1 release, then pin sha256 + mark verified:true.
|
|
4
|
+
// Idempotent (--clobber upload). Entries carrying fake-SHA values are demoted
|
|
5
|
+
// to the community tier (demote list).
|
|
6
|
+
// Tarballs are built in .cache/forge-publish/ (gitignored temp dir) and removed
|
|
7
|
+
// after upload — prebuilt archives must never live in the git tree.
|
|
8
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync } from "fs";
|
|
6
9
|
import { execSync } from "child_process";
|
|
7
10
|
import { createHash } from "crypto";
|
|
8
11
|
const OWNER_REPO = "oomerevren-beep/forge";
|
|
9
12
|
const RELEASE = "registry-v1";
|
|
10
|
-
//
|
|
13
|
+
// Scratch dir for tarball staging (gitignored via .cache/). Created on demand,
|
|
14
|
+
// cleaned per-asset after upload.
|
|
15
|
+
const STAGE_DIR = ".cache/forge-publish";
|
|
16
|
+
// registry slug -> registry-content dir (same name)
|
|
11
17
|
const VERIFY = [
|
|
12
18
|
"pdf-merge", "pdf-split", "pdf-ocr", "pdf-extract",
|
|
13
19
|
"pdf-compress", "pdf-convert", "pdf-forms", "pdf-tables",
|
|
@@ -15,7 +21,7 @@ const VERIFY = [
|
|
|
15
21
|
"agent-changelog-writer", "agent-researcher",
|
|
16
22
|
"cmd-plan", "cmd-review",
|
|
17
23
|
];
|
|
18
|
-
//
|
|
24
|
+
// Fake hex + 404 URL carriers: demote to community tier (honesty).
|
|
19
25
|
const DEMOTE = ["anthropics-plan", "skill-pdf"];
|
|
20
26
|
function sh(cmd) {
|
|
21
27
|
return execSync(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -27,7 +33,7 @@ async function main() {
|
|
|
27
33
|
console.log(`[publish] release ${RELEASE} exists`);
|
|
28
34
|
}
|
|
29
35
|
catch {
|
|
30
|
-
sh(`gh release create ${RELEASE} --repo ${OWNER_REPO} --title "Forge verified registry content v1" --notes "Seed-verified package tarballs (
|
|
36
|
+
sh(`gh release create ${RELEASE} --repo ${OWNER_REPO} --title "Forge verified registry content v1" --notes "Seed-verified package tarballs (pre-Phase-6). Each asset sha256-pinned in registry/packages/*.json."`);
|
|
31
37
|
console.log(`[publish] release ${RELEASE} created`);
|
|
32
38
|
}
|
|
33
39
|
let ok = 0;
|
|
@@ -40,11 +46,13 @@ async function main() {
|
|
|
40
46
|
}
|
|
41
47
|
const detail = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
42
48
|
const version = detail.latest;
|
|
43
|
-
// forge.toml manifest
|
|
49
|
+
// generate forge.toml manifest (package declaration)
|
|
44
50
|
const manifest = `[package]\nname = "${detail.name}"\nversion = "${version}"\ntype = "${detail.type}"\ndescription = "${detail.description.replace(/"/g, "'")}"\nlicense = "MIT"\nrepository = "https://github.com/${OWNER_REPO}"\n`;
|
|
45
51
|
writeFileSync(`${srcDir}/forge.toml`, manifest);
|
|
46
52
|
const asset = `${slug}-${version}.tar.gz`;
|
|
47
|
-
|
|
53
|
+
// Stage the tarball under the gitignored scratch dir — never in the repo tree.
|
|
54
|
+
mkdirSync(STAGE_DIR, { recursive: true });
|
|
55
|
+
const tmp = `${STAGE_DIR}/${asset}`;
|
|
48
56
|
sh(`tar -czf ${tmp} -C ${srcDir} .`);
|
|
49
57
|
const buf = readFileSync(tmp);
|
|
50
58
|
const sha256 = createHash("sha256").update(buf).digest("hex");
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
// scripts/seed-registry-13lite.ts —
|
|
3
|
-
//
|
|
4
|
-
// Idempotent:
|
|
2
|
+
// scripts/seed-registry-13lite.ts — Phase 13-lite: 100 → 250 packages (+150, hand-curated)
|
|
3
|
+
// Focus: pdf (10+), agent (20+), mcp categories — for a "wow" search.
|
|
4
|
+
// Idempotent: skips existing files, then run 'npm run registry:build'.
|
|
5
5
|
import { existsSync, writeFileSync, mkdirSync } from "fs";
|
|
6
6
|
import { join } from "path";
|
|
7
7
|
const PACKAGES_DIR = "registry/packages";
|
|
8
8
|
const ROWS = [
|
|
9
|
-
// --- PDF (12) — forge search pdf 10+
|
|
9
|
+
// --- PDF (12) — 'forge search pdf' 10+ goal ---
|
|
10
10
|
["pdf/merge", "skill", "PDF merge skill — combine multiple PDFs into one document fast", ["pdf", "merge", "document"]],
|
|
11
11
|
["pdf/split", "skill", "PDF split skill — extract pages and split PDFs by range", ["pdf", "split", "pages"]],
|
|
12
12
|
["pdf/ocr", "skill", "PDF OCR skill — scanned PDFs to searchable text with OCR", ["pdf", "ocr", "scan"]],
|
|
@@ -19,7 +19,7 @@ const ROWS = [
|
|
|
19
19
|
["pdf/convert", "skill", "PDF convert skill — PDF to Word, HTML, Markdown and back", ["pdf", "convert", "export"]],
|
|
20
20
|
["pdf/annotate", "skill", "PDF annotate skill — comments, highlights and review markup", ["pdf", "annotate", "review"]],
|
|
21
21
|
["pdf/tables", "skill", "PDF tables skill — detect and export tables from PDFs to CSV", ["pdf", "tables", "csv"]],
|
|
22
|
-
// --- Agent (25) — forge search agent 20+
|
|
22
|
+
// --- Agent (25) — 'forge search agent' 20+ goal ---
|
|
23
23
|
["agent/pr-reviewer", "agent", "PR reviewer agent — thorough pull request reviews with suggestions", ["agent", "review", "pr"]],
|
|
24
24
|
["agent/changelog-writer", "agent", "Changelog writer agent — generate release notes from commits", ["agent", "changelog", "release"]],
|
|
25
25
|
["agent/migrator", "agent", "Migrator agent — framework and version migration assistant", ["agent", "migrate", "refactor"]],
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
// scripts/seed-registry.ts — Epoch 1d:
|
|
3
|
-
//
|
|
2
|
+
// scripts/seed-registry.ts — Epoch 1d: seed only packages with real tarballs
|
|
3
|
+
// Never adds repos that do not exist — fail-closed
|
|
4
4
|
import { existsSync, writeFileSync, mkdirSync } from "fs";
|
|
5
5
|
import { join } from "path";
|
|
6
6
|
const PACKAGES_DIR = "registry/packages";
|
|
7
|
-
//
|
|
7
|
+
// Only genuinely verified tarballs — Epoch 1d
|
|
8
8
|
const CATALOG = [
|
|
9
|
-
//
|
|
9
|
+
// Real-tarball packages (SHA256 verified)
|
|
10
10
|
{
|
|
11
11
|
name: "pdf/compress", type: "skill", description: "PDF compress skill — shrink PDF size without quality loss",
|
|
12
12
|
keywords: ["pdf", "compress", "optimize"], source: "registry-content",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
// scripts/verify-npm-mcps.ts — MCP
|
|
3
|
-
//
|
|
4
|
-
// Fail-closed:
|
|
2
|
+
// scripts/verify-npm-mcps.ts — verify MCP entries against real upstream npm tarballs.
|
|
3
|
+
// Per package: npm metadata -> dist.tarball download -> sha256 compute -> pin into JSON + verified:true.
|
|
4
|
+
// Fail-closed: any failing step skips that package (placeholder preserved).
|
|
5
5
|
import { readFileSync, writeFileSync } from "fs";
|
|
6
6
|
import { createHash } from "crypto";
|
|
7
7
|
const MAP = [
|
|
@@ -20,7 +20,9 @@ async function main() {
|
|
|
20
20
|
const version = meta["dist-tags"]?.latest;
|
|
21
21
|
if (!version || !meta.versions?.[version]?.dist?.tarball)
|
|
22
22
|
throw new Error("no latest dist");
|
|
23
|
-
const tarball = meta.versions[version].dist
|
|
23
|
+
const tarball = meta.versions[version].dist?.tarball;
|
|
24
|
+
if (!tarball)
|
|
25
|
+
throw new Error("no latest dist");
|
|
24
26
|
const publishedAt = meta.time?.[version] ?? new Date().toISOString();
|
|
25
27
|
const dl = await fetch(tarball);
|
|
26
28
|
if (!dl.ok)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oomerevren/tryforge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "The Homebrew for AI Agents — one CLI for skills, MCPs, plugins, agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ömer Evren",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
],
|
|
28
28
|
"type": "module",
|
|
29
29
|
"bin": {
|
|
30
|
-
"forge": "dist/
|
|
31
|
-
"tryforge": "dist/
|
|
30
|
+
"forge": "./dist/index.cjs",
|
|
31
|
+
"tryforge": "./dist/index.cjs"
|
|
32
32
|
},
|
|
33
33
|
"files": [
|
|
34
34
|
"dist/",
|
|
@@ -45,20 +45,29 @@
|
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"dev": "tsx cli/src/index.ts",
|
|
48
|
-
"build": "tsc",
|
|
49
|
-
"
|
|
48
|
+
"build": "tsc -p tsconfig.build.json",
|
|
49
|
+
"bundle": "esbuild cli/src/index.ts --bundle --platform=node --format=cjs --outfile=dist/index.cjs --banner:js=\"#!/usr/bin/env node\" --minify && node -e \"const fs=require('fs');const p='dist/index.cjs';const L=fs.readFileSync(p,'utf8').split('\\n');if(L[1]&&L[1].startsWith('#!'))L.splice(1,1);fs.writeFileSync(p,L.join('\\n'));fs.chmodSync(p, 0o755)\"",
|
|
50
|
+
"lint": "eslint cli/ scripts/ tests/ eslint.config.js --max-warnings 0",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"prepublishOnly": "npm run build && npm run bundle && npm test && npm run registry:build -- --check",
|
|
50
53
|
"test": "node --import tsx --test tests/**/*.test.ts cli/src/**/*.test.ts",
|
|
51
54
|
"registry:build": "tsx scripts/build-registry.ts",
|
|
52
55
|
"seed": "tsx scripts/seed-registry.ts"
|
|
53
56
|
},
|
|
54
57
|
"dependencies": {
|
|
58
|
+
"@clack/prompts": "^0.11.0",
|
|
55
59
|
"commander": "^12.0.0",
|
|
60
|
+
"picocolors": "^1.1.1",
|
|
56
61
|
"smol-toml": "^1.8.0"
|
|
57
62
|
},
|
|
58
63
|
"devDependencies": {
|
|
64
|
+
"@eslint/js": "^10.0.1",
|
|
59
65
|
"@types/node": "^26.4.1",
|
|
66
|
+
"esbuild": "^0.28.2",
|
|
67
|
+
"eslint": "^10.9.1",
|
|
60
68
|
"playwright": "^1.62.1",
|
|
61
69
|
"tsx": "^4.23.13",
|
|
62
|
-
"typescript": "^
|
|
70
|
+
"typescript": "^6.0.3",
|
|
71
|
+
"typescript-eslint": "^8.69.0"
|
|
63
72
|
}
|
|
64
73
|
}
|