@zcy2nn/agent-forge 1.1.2 → 1.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/README.md +247 -247
- package/dist/agents/designer.d.ts +2 -0
- package/dist/agents/explorer.d.ts +2 -0
- package/dist/agents/fixer.d.ts +2 -0
- package/dist/agents/librarian.d.ts +2 -0
- package/dist/agents/observer.d.ts +2 -0
- package/dist/agents/oracle.d.ts +2 -0
- package/dist/cli/index.js +6 -129
- package/dist/cli/migration.d.ts +46 -0
- package/dist/hooks/filter-available-skills/index.d.ts +4 -13
- package/dist/index.js +124 -316
- package/dist/skills/systematic-debugging/condition-based-waiting-example.d.ts +51 -0
- package/dist/tui.js +0 -14
- package/package.json +104 -104
- package/src/skills/brainstorming/SKILL.md +186 -186
- package/src/skills/brainstorming/scripts/frame-template.html +214 -214
- package/src/skills/brainstorming/scripts/server.cjs +354 -354
- package/src/skills/systematic-debugging/SKILL.md +318 -318
- package/src/skills/test-driven-development/SKILL.md +392 -392
- package/src/skills/verification-before-completion/SKILL.md +153 -153
- package/src/skills/writing-skills/graphviz-conventions.dot +171 -171
- package/dist/cli/skill-sync.d.ts +0 -23
- package/dist/utils/package-root.d.ts +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
// @bun
|
|
3
2
|
import { createRequire } from "node:module";
|
|
4
3
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
5
4
|
|
|
@@ -1208,8 +1207,7 @@ Options:
|
|
|
1208
1207
|
}
|
|
1209
1208
|
|
|
1210
1209
|
// src/cli/install.ts
|
|
1211
|
-
import { existsSync as
|
|
1212
|
-
import { join as join6 } from "node:path";
|
|
1210
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
1213
1211
|
import { createInterface } from "node:readline/promises";
|
|
1214
1212
|
// src/cli/system.ts
|
|
1215
1213
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
@@ -1386,97 +1384,6 @@ function getOpenCodePath() {
|
|
|
1386
1384
|
const path2 = resolveOpenCodePath();
|
|
1387
1385
|
return path2 === "opencode" ? null : path2;
|
|
1388
1386
|
}
|
|
1389
|
-
// src/cli/skill-sync.ts
|
|
1390
|
-
import {
|
|
1391
|
-
cpSync,
|
|
1392
|
-
existsSync as existsSync5,
|
|
1393
|
-
lstatSync,
|
|
1394
|
-
mkdirSync as mkdirSync2,
|
|
1395
|
-
readlinkSync,
|
|
1396
|
-
rmSync,
|
|
1397
|
-
symlinkSync
|
|
1398
|
-
} from "node:fs";
|
|
1399
|
-
import { join as join5 } from "node:path";
|
|
1400
|
-
|
|
1401
|
-
// src/utils/package-root.ts
|
|
1402
|
-
import { existsSync as existsSync4 } from "node:fs";
|
|
1403
|
-
import { join as join4 } from "node:path";
|
|
1404
|
-
var _cachedPackageRoot;
|
|
1405
|
-
function resolvePackageRoot() {
|
|
1406
|
-
if (_cachedPackageRoot)
|
|
1407
|
-
return _cachedPackageRoot;
|
|
1408
|
-
const distDir = import.meta.dirname;
|
|
1409
|
-
if (!distDir) {
|
|
1410
|
-
throw new Error("import.meta.dirname is not available");
|
|
1411
|
-
}
|
|
1412
|
-
const npmRoot = join4(distDir, "..", "..");
|
|
1413
|
-
if (existsSync4(join4(npmRoot, "src", "skills"))) {
|
|
1414
|
-
_cachedPackageRoot = npmRoot;
|
|
1415
|
-
return npmRoot;
|
|
1416
|
-
}
|
|
1417
|
-
const localRoot = join4(distDir, "..");
|
|
1418
|
-
if (existsSync4(join4(localRoot, "src", "skills"))) {
|
|
1419
|
-
_cachedPackageRoot = localRoot;
|
|
1420
|
-
return localRoot;
|
|
1421
|
-
}
|
|
1422
|
-
_cachedPackageRoot = npmRoot;
|
|
1423
|
-
return npmRoot;
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
// src/cli/skill-sync.ts
|
|
1427
|
-
function syncBuiltinSkills(packageRoot, skillsDirOverride) {
|
|
1428
|
-
const resolvedPackageRoot = packageRoot ?? resolvePackageRoot();
|
|
1429
|
-
const skillsDir = skillsDirOverride ?? join5(getConfigDir(), "skills");
|
|
1430
|
-
mkdirSync2(skillsDir, { recursive: true });
|
|
1431
|
-
let installed = 0;
|
|
1432
|
-
let skipped = 0;
|
|
1433
|
-
let unchanged = 0;
|
|
1434
|
-
let copied = 0;
|
|
1435
|
-
for (const skill of CUSTOM_SKILLS) {
|
|
1436
|
-
const sourcePath = join5(resolvedPackageRoot, skill.sourcePath);
|
|
1437
|
-
const linkPath = join5(skillsDir, skill.name);
|
|
1438
|
-
if (!existsSync5(sourcePath)) {
|
|
1439
|
-
skipped++;
|
|
1440
|
-
continue;
|
|
1441
|
-
}
|
|
1442
|
-
try {
|
|
1443
|
-
if (lstatSync(linkPath).isSymbolicLink()) {
|
|
1444
|
-
const currentTarget = getSymlinkTarget(linkPath);
|
|
1445
|
-
if (currentTarget === sourcePath) {
|
|
1446
|
-
unchanged++;
|
|
1447
|
-
continue;
|
|
1448
|
-
}
|
|
1449
|
-
rmSync(linkPath, { recursive: true, force: true });
|
|
1450
|
-
} else if (existsSync5(linkPath)) {
|
|
1451
|
-
rmSync(linkPath, { recursive: true, force: true });
|
|
1452
|
-
}
|
|
1453
|
-
} catch {
|
|
1454
|
-
try {
|
|
1455
|
-
rmSync(linkPath, { recursive: true, force: true });
|
|
1456
|
-
} catch {}
|
|
1457
|
-
}
|
|
1458
|
-
try {
|
|
1459
|
-
symlinkSync(sourcePath, linkPath, "junction");
|
|
1460
|
-
installed++;
|
|
1461
|
-
} catch {
|
|
1462
|
-
try {
|
|
1463
|
-
cpSync(sourcePath, linkPath, { recursive: true, force: true });
|
|
1464
|
-
copied++;
|
|
1465
|
-
} catch {
|
|
1466
|
-
skipped++;
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
return { installed, skipped, unchanged, copied };
|
|
1471
|
-
}
|
|
1472
|
-
function getSymlinkTarget(linkPath) {
|
|
1473
|
-
try {
|
|
1474
|
-
return readlinkSync(linkPath, "utf-8");
|
|
1475
|
-
} catch {
|
|
1476
|
-
return "";
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
1387
|
// src/cli/install.ts
|
|
1481
1388
|
var GREEN = "\x1B[32m";
|
|
1482
1389
|
var BLUE = "\x1B[34m";
|
|
@@ -1526,9 +1433,6 @@ async function confirm(message, defaultYes = true) {
|
|
|
1526
1433
|
rl.close();
|
|
1527
1434
|
}
|
|
1528
1435
|
}
|
|
1529
|
-
function installBuiltinSkills() {
|
|
1530
|
-
return syncBuiltinSkills();
|
|
1531
|
-
}
|
|
1532
1436
|
async function askToStarRepo(config) {
|
|
1533
1437
|
if (!config.promptForStar || config.dryRun || !process.stdin.isTTY)
|
|
1534
1438
|
return;
|
|
@@ -1576,7 +1480,7 @@ async function runInstall(config) {
|
|
|
1576
1480
|
const detected = detectCurrentConfig();
|
|
1577
1481
|
const isUpdate = detected.isInstalled;
|
|
1578
1482
|
printHeader(isUpdate);
|
|
1579
|
-
let totalSteps =
|
|
1483
|
+
let totalSteps = 6;
|
|
1580
1484
|
if (config.installSkills)
|
|
1581
1485
|
totalSteps += 1;
|
|
1582
1486
|
let step = 1;
|
|
@@ -1632,7 +1536,7 @@ ${JSON.stringify(liteConfig, null, 2)}
|
|
|
1632
1536
|
`);
|
|
1633
1537
|
} else {
|
|
1634
1538
|
const configPath2 = getExistingLiteConfigPath();
|
|
1635
|
-
const configExists =
|
|
1539
|
+
const configExists = existsSync4(configPath2);
|
|
1636
1540
|
if (configExists && !config.reset) {
|
|
1637
1541
|
printInfo(`Configuration already exists at ${configPath2}. Use --reset to overwrite.`);
|
|
1638
1542
|
} else {
|
|
@@ -1641,24 +1545,6 @@ ${JSON.stringify(liteConfig, null, 2)}
|
|
|
1641
1545
|
return 1;
|
|
1642
1546
|
}
|
|
1643
1547
|
}
|
|
1644
|
-
printStep(step++, totalSteps, "Installing built-in skills...");
|
|
1645
|
-
if (config.dryRun) {
|
|
1646
|
-
printInfo("Dry run mode - would install built-in skills:");
|
|
1647
|
-
for (const skill of CUSTOM_SKILLS) {
|
|
1648
|
-
printInfo(` - ${skill.name}`);
|
|
1649
|
-
}
|
|
1650
|
-
} else {
|
|
1651
|
-
const result = installBuiltinSkills();
|
|
1652
|
-
if (result.installed > 0) {
|
|
1653
|
-
printSuccess(`${result.installed} built-in skill(s) symlinked to ${join6(getConfigDir(), "skills")}`);
|
|
1654
|
-
}
|
|
1655
|
-
if (result.copied > 0) {
|
|
1656
|
-
printInfo(`${result.copied} skill(s) copied (symlink unavailable — auto-update will NOT sync these)`);
|
|
1657
|
-
}
|
|
1658
|
-
if (result.skipped > 0) {
|
|
1659
|
-
printInfo(`${result.skipped} skill(s) skipped`);
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
1548
|
if (config.installSkills) {
|
|
1663
1549
|
printStep(step++, totalSteps, "Installing recommended skills...");
|
|
1664
1550
|
if (config.dryRun) {
|
|
@@ -1725,15 +1611,6 @@ async function install(args) {
|
|
|
1725
1611
|
return runInstall(config);
|
|
1726
1612
|
}
|
|
1727
1613
|
|
|
1728
|
-
// src/cli/providers.ts
|
|
1729
|
-
var GENERATED_PRESETS2 = ["openai", "opencode-go"];
|
|
1730
|
-
function isGeneratedPresetName2(value) {
|
|
1731
|
-
return GENERATED_PRESETS2.includes(value);
|
|
1732
|
-
}
|
|
1733
|
-
function getGeneratedPresetNames2() {
|
|
1734
|
-
return [...GENERATED_PRESETS2];
|
|
1735
|
-
}
|
|
1736
|
-
|
|
1737
1614
|
// src/cli/index.ts
|
|
1738
1615
|
function parseArgs(args) {
|
|
1739
1616
|
const result = {
|
|
@@ -1747,8 +1624,8 @@ function parseArgs(args) {
|
|
|
1747
1624
|
result.skills = arg.split("=")[1];
|
|
1748
1625
|
} else if (arg.startsWith("--preset=")) {
|
|
1749
1626
|
const preset = arg.split("=")[1];
|
|
1750
|
-
if (!
|
|
1751
|
-
console.error(`Unsupported preset: ${preset}. Available presets: ${
|
|
1627
|
+
if (!isGeneratedPresetName(preset)) {
|
|
1628
|
+
console.error(`Unsupported preset: ${preset}. Available presets: ${getGeneratedPresetNames().join(", ")}`);
|
|
1752
1629
|
process.exit(1);
|
|
1753
1630
|
}
|
|
1754
1631
|
result.preset = preset;
|
|
@@ -1782,7 +1659,7 @@ Options:
|
|
|
1782
1659
|
Doctor options:
|
|
1783
1660
|
--json Print diagnostics as JSON
|
|
1784
1661
|
|
|
1785
|
-
Available presets: ${
|
|
1662
|
+
Available presets: ${getGeneratedPresetNames().join(", ")}
|
|
1786
1663
|
|
|
1787
1664
|
The installer generates OpenAI and OpenCode Go presets by default.
|
|
1788
1665
|
OpenAI is active unless --preset selects another generated preset.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Result of a migration attempt. */
|
|
2
|
+
export interface MigrationResult {
|
|
3
|
+
/** Whether a legacy config was detected. */
|
|
4
|
+
detected: boolean;
|
|
5
|
+
/** Whether the migration was performed. */
|
|
6
|
+
migrated: boolean;
|
|
7
|
+
/** Path to the new config file, if migrated. */
|
|
8
|
+
newPath?: string;
|
|
9
|
+
/** Path to the legacy config file that was found. */
|
|
10
|
+
legacyPath?: string;
|
|
11
|
+
/** Error message if migration failed. */
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get all possible legacy config file paths (json and jsonc).
|
|
16
|
+
*/
|
|
17
|
+
export declare function getLegacyConfigPaths(): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Detect whether a legacy `oh-my-opencode-slim.json` config exists.
|
|
20
|
+
* Returns the path if found, or undefined.
|
|
21
|
+
*/
|
|
22
|
+
export declare function detectLegacyConfig(): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Check if a config object contains any legacy agent names
|
|
25
|
+
* in its presets or agents sections.
|
|
26
|
+
*/
|
|
27
|
+
export declare function hasLegacyAgentNames(config: Record<string, unknown>): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Migrate agent names in a config object.
|
|
30
|
+
*
|
|
31
|
+
* - Renames primary mapping keys (explorer→researcher, oracle→reviewer,
|
|
32
|
+
* designer→implementer).
|
|
33
|
+
* - For secondary mappings (librarian→researcher, fixer→implementer),
|
|
34
|
+
* only applies if the primary mapping target doesn't already exist.
|
|
35
|
+
* - Removes observer entries entirely.
|
|
36
|
+
* - Preserves all non-agent config keys unchanged.
|
|
37
|
+
*/
|
|
38
|
+
export declare function migrateAgentNames(config: Record<string, unknown>): Record<string, unknown>;
|
|
39
|
+
/**
|
|
40
|
+
* Perform the full migration:
|
|
41
|
+
* 1. Read legacy config
|
|
42
|
+
* 2. Migrate agent names
|
|
43
|
+
* 3. Write to `agent-forge.json`
|
|
44
|
+
* 4. Rename legacy file to `.bak`
|
|
45
|
+
*/
|
|
46
|
+
export declare function performMigration(legacyPath: string): MigrationResult;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Filter
|
|
3
|
-
* OpenCode core injects `<available_skills>` from installed skills, so this hook rewrites
|
|
4
|
-
* block before the prompt is sent.
|
|
5
|
-
* are always visible even without being copied to the OpenCode skills directory.
|
|
2
|
+
* Filter available_skills blocks based on the current agent's permission.skill rules.
|
|
3
|
+
* OpenCode core injects `<available_skills>` from installed skills, so this hook only rewrites
|
|
4
|
+
* that block before the prompt is sent.
|
|
6
5
|
*/
|
|
7
6
|
import type { PluginInput } from '@opencode-ai/plugin';
|
|
8
7
|
import { type PluginConfig } from '../../config';
|
|
@@ -20,14 +19,6 @@ interface MessageWithParts {
|
|
|
20
19
|
parts: MessagePart[];
|
|
21
20
|
}
|
|
22
21
|
type SkillRule = 'allow' | 'ask' | 'deny';
|
|
23
|
-
interface SkillEntry {
|
|
24
|
-
name: string;
|
|
25
|
-
block: string;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Merge installed skill entries with built-in entries (dedup by name, installed takes precedence).
|
|
29
|
-
*/
|
|
30
|
-
declare function mergeWithBuiltinSkills(installedEntries: SkillEntry[]): SkillEntry[];
|
|
31
22
|
declare function filterAvailableSkillsText(text: string, permissionRules: Record<string, SkillRule>): string;
|
|
32
23
|
/**
|
|
33
24
|
* Creates the experimental.chat.messages.transform hook for filtering available skills.
|
|
@@ -38,4 +29,4 @@ export declare function createFilterAvailableSkillsHook(_ctx: PluginInput, confi
|
|
|
38
29
|
messages: MessageWithParts[];
|
|
39
30
|
}) => Promise<void>;
|
|
40
31
|
};
|
|
41
|
-
export { filterAvailableSkillsText
|
|
32
|
+
export { filterAvailableSkillsText };
|