@zcy2nn/agent-forge 1.1.1 → 1.1.2
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/cli/index.js +116 -3
- package/dist/cli/skill-sync.d.ts +23 -0
- package/dist/index.js +273 -123
- package/dist/tui.js +14 -0
- package/dist/utils/package-root.d.ts +1 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1208,7 +1208,8 @@ Options:
|
|
|
1208
1208
|
}
|
|
1209
1209
|
|
|
1210
1210
|
// src/cli/install.ts
|
|
1211
|
-
import { existsSync as
|
|
1211
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
1212
|
+
import { join as join6 } from "node:path";
|
|
1212
1213
|
import { createInterface } from "node:readline/promises";
|
|
1213
1214
|
// src/cli/system.ts
|
|
1214
1215
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
@@ -1385,6 +1386,97 @@ function getOpenCodePath() {
|
|
|
1385
1386
|
const path2 = resolveOpenCodePath();
|
|
1386
1387
|
return path2 === "opencode" ? null : path2;
|
|
1387
1388
|
}
|
|
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
|
+
|
|
1388
1480
|
// src/cli/install.ts
|
|
1389
1481
|
var GREEN = "\x1B[32m";
|
|
1390
1482
|
var BLUE = "\x1B[34m";
|
|
@@ -1434,6 +1526,9 @@ async function confirm(message, defaultYes = true) {
|
|
|
1434
1526
|
rl.close();
|
|
1435
1527
|
}
|
|
1436
1528
|
}
|
|
1529
|
+
function installBuiltinSkills() {
|
|
1530
|
+
return syncBuiltinSkills();
|
|
1531
|
+
}
|
|
1437
1532
|
async function askToStarRepo(config) {
|
|
1438
1533
|
if (!config.promptForStar || config.dryRun || !process.stdin.isTTY)
|
|
1439
1534
|
return;
|
|
@@ -1481,7 +1576,7 @@ async function runInstall(config) {
|
|
|
1481
1576
|
const detected = detectCurrentConfig();
|
|
1482
1577
|
const isUpdate = detected.isInstalled;
|
|
1483
1578
|
printHeader(isUpdate);
|
|
1484
|
-
let totalSteps =
|
|
1579
|
+
let totalSteps = 7;
|
|
1485
1580
|
if (config.installSkills)
|
|
1486
1581
|
totalSteps += 1;
|
|
1487
1582
|
let step = 1;
|
|
@@ -1537,7 +1632,7 @@ ${JSON.stringify(liteConfig, null, 2)}
|
|
|
1537
1632
|
`);
|
|
1538
1633
|
} else {
|
|
1539
1634
|
const configPath2 = getExistingLiteConfigPath();
|
|
1540
|
-
const configExists =
|
|
1635
|
+
const configExists = existsSync6(configPath2);
|
|
1541
1636
|
if (configExists && !config.reset) {
|
|
1542
1637
|
printInfo(`Configuration already exists at ${configPath2}. Use --reset to overwrite.`);
|
|
1543
1638
|
} else {
|
|
@@ -1546,6 +1641,24 @@ ${JSON.stringify(liteConfig, null, 2)}
|
|
|
1546
1641
|
return 1;
|
|
1547
1642
|
}
|
|
1548
1643
|
}
|
|
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
|
+
}
|
|
1549
1662
|
if (config.installSkills) {
|
|
1550
1663
|
printStep(step++, totalSteps, "Installing recommended skills...");
|
|
1551
1664
|
if (config.dryRun) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface SkillSyncResult {
|
|
2
|
+
installed: number;
|
|
3
|
+
skipped: number;
|
|
4
|
+
/** Skills that were already correctly symlinked (no change needed) */
|
|
5
|
+
unchanged: number;
|
|
6
|
+
/** Skills installed via file copy (symlink unavailable) */
|
|
7
|
+
copied: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Ensure all built-in skills are symlinked into OpenCode's skills directory.
|
|
11
|
+
*
|
|
12
|
+
* - If a symlink already points to the correct source → skip (unchanged).
|
|
13
|
+
* - If a directory or stale symlink exists → replace with fresh symlink.
|
|
14
|
+
* - If symlink creation fails (e.g. Windows without junction support) →
|
|
15
|
+
* fall back to file copy.
|
|
16
|
+
* - If the source path doesn't exist in the package → skip.
|
|
17
|
+
*
|
|
18
|
+
* @param packageRoot - Absolute path to the agent-forge package root
|
|
19
|
+
* (the directory containing `src/skills/`). Defaults to auto-detected via resolvePackageRoot().
|
|
20
|
+
* @param skillsDirOverride - Override for the target skills directory
|
|
21
|
+
* (useful in tests). Defaults to `<configDir>/skills`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function syncBuiltinSkills(packageRoot?: string, skillsDirOverride?: string): SkillSyncResult;
|
package/dist/index.js
CHANGED
|
@@ -30,8 +30,175 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
30
30
|
return to;
|
|
31
31
|
};
|
|
32
32
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
33
|
+
var __returnValue = (v) => v;
|
|
34
|
+
function __exportSetter(name, newValue) {
|
|
35
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
36
|
+
}
|
|
37
|
+
var __export = (target, all) => {
|
|
38
|
+
for (var name in all)
|
|
39
|
+
__defProp(target, name, {
|
|
40
|
+
get: all[name],
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
set: __exportSetter.bind(all, name)
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
33
47
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
34
48
|
|
|
49
|
+
// src/cli/custom-skills.ts
|
|
50
|
+
var CUSTOM_SKILLS;
|
|
51
|
+
var init_custom_skills = __esm(() => {
|
|
52
|
+
CUSTOM_SKILLS = [
|
|
53
|
+
{
|
|
54
|
+
name: "simplify",
|
|
55
|
+
description: "Code simplification and readability-focused refactoring",
|
|
56
|
+
allowedAgents: ["reviewer"],
|
|
57
|
+
sourcePath: "src/skills/simplify"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "codemap",
|
|
61
|
+
description: "Repository understanding and hierarchical codemap generation",
|
|
62
|
+
allowedAgents: ["orchestrator"],
|
|
63
|
+
sourcePath: "src/skills/codemap"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "brainstorming",
|
|
67
|
+
description: "Turn ideas into designs through collaborative dialogue before implementation",
|
|
68
|
+
allowedAgents: ["orchestrator"],
|
|
69
|
+
sourcePath: "src/skills/brainstorming"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "writing-plans",
|
|
73
|
+
description: "Create comprehensive implementation plans from specs before touching code",
|
|
74
|
+
allowedAgents: ["orchestrator"],
|
|
75
|
+
sourcePath: "src/skills/writing-plans"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "executing-plans",
|
|
79
|
+
description: "Execute written implementation plans with review checkpoints",
|
|
80
|
+
allowedAgents: ["orchestrator"],
|
|
81
|
+
sourcePath: "src/skills/executing-plans"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "subagent-driven-development",
|
|
85
|
+
description: "Execute plans by dispatching fresh subagent per task with two-stage review",
|
|
86
|
+
allowedAgents: ["orchestrator"],
|
|
87
|
+
sourcePath: "src/skills/subagent-driven-development"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "dispatching-parallel-agents",
|
|
91
|
+
description: "Dispatch parallel agents for independent tasks without shared state",
|
|
92
|
+
allowedAgents: ["orchestrator"],
|
|
93
|
+
sourcePath: "src/skills/dispatching-parallel-agents"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "using-git-worktrees",
|
|
97
|
+
description: "Create isolated git worktrees before executing implementation plans",
|
|
98
|
+
allowedAgents: ["orchestrator"],
|
|
99
|
+
sourcePath: "src/skills/using-git-worktrees"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "finishing-a-development-branch",
|
|
103
|
+
description: "Guide completion of development work with structured merge/PR options",
|
|
104
|
+
allowedAgents: ["orchestrator"],
|
|
105
|
+
sourcePath: "src/skills/finishing-a-development-branch"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "requesting-code-review",
|
|
109
|
+
description: "Dispatch code reviewer subagent to catch issues before merging",
|
|
110
|
+
allowedAgents: ["orchestrator"],
|
|
111
|
+
sourcePath: "src/skills/requesting-code-review"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "test-driven-development",
|
|
115
|
+
description: "Write failing tests first, then minimal code to pass, before any implementation",
|
|
116
|
+
allowedAgents: ["implementer"],
|
|
117
|
+
sourcePath: "src/skills/test-driven-development"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "verification-before-completion",
|
|
121
|
+
description: "Run verification commands and confirm output before claiming work is complete",
|
|
122
|
+
allowedAgents: ["implementer"],
|
|
123
|
+
sourcePath: "src/skills/verification-before-completion"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: "systematic-debugging",
|
|
127
|
+
description: "Find root cause before attempting fixes for any bug or test failure",
|
|
128
|
+
allowedAgents: ["reviewer"],
|
|
129
|
+
sourcePath: "src/skills/systematic-debugging"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "receiving-code-review",
|
|
133
|
+
description: "Evaluate code review feedback with technical rigor before implementing suggestions",
|
|
134
|
+
allowedAgents: ["reviewer"],
|
|
135
|
+
sourcePath: "src/skills/receiving-code-review"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "writing-skills",
|
|
139
|
+
description: "Create and edit skills using TDD methodology for process documentation",
|
|
140
|
+
allowedAgents: ["orchestrator"],
|
|
141
|
+
sourcePath: "src/skills/writing-skills"
|
|
142
|
+
}
|
|
143
|
+
];
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// src/cli/paths.ts
|
|
147
|
+
import { homedir } from "node:os";
|
|
148
|
+
import { dirname, join } from "node:path";
|
|
149
|
+
function getDefaultOpenCodeConfigDir() {
|
|
150
|
+
const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join(homedir(), ".config");
|
|
151
|
+
return join(userConfigDir, "opencode");
|
|
152
|
+
}
|
|
153
|
+
function getCustomOpenCodeConfigDir() {
|
|
154
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
155
|
+
return configDir || undefined;
|
|
156
|
+
}
|
|
157
|
+
function getConfigDir() {
|
|
158
|
+
const customConfigDir = getCustomOpenCodeConfigDir();
|
|
159
|
+
if (customConfigDir) {
|
|
160
|
+
return customConfigDir;
|
|
161
|
+
}
|
|
162
|
+
return getDefaultOpenCodeConfigDir();
|
|
163
|
+
}
|
|
164
|
+
function getConfigSearchDirs() {
|
|
165
|
+
const dirs = [getCustomOpenCodeConfigDir(), getDefaultOpenCodeConfigDir()];
|
|
166
|
+
return dirs.filter((dir, index) => {
|
|
167
|
+
return Boolean(dir) && dirs.indexOf(dir) === index;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function getOpenCodeConfigPaths() {
|
|
171
|
+
const configDir = getDefaultOpenCodeConfigDir();
|
|
172
|
+
return [join(configDir, "opencode.json"), join(configDir, "opencode.jsonc")];
|
|
173
|
+
}
|
|
174
|
+
var init_paths = () => {};
|
|
175
|
+
|
|
176
|
+
// src/utils/package-root.ts
|
|
177
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
178
|
+
import { join as join13 } from "node:path";
|
|
179
|
+
function resolvePackageRoot() {
|
|
180
|
+
if (_cachedPackageRoot)
|
|
181
|
+
return _cachedPackageRoot;
|
|
182
|
+
const distDir = import.meta.dirname;
|
|
183
|
+
if (!distDir) {
|
|
184
|
+
throw new Error("import.meta.dirname is not available");
|
|
185
|
+
}
|
|
186
|
+
const npmRoot = join13(distDir, "..", "..");
|
|
187
|
+
if (existsSync10(join13(npmRoot, "src", "skills"))) {
|
|
188
|
+
_cachedPackageRoot = npmRoot;
|
|
189
|
+
return npmRoot;
|
|
190
|
+
}
|
|
191
|
+
const localRoot = join13(distDir, "..");
|
|
192
|
+
if (existsSync10(join13(localRoot, "src", "skills"))) {
|
|
193
|
+
_cachedPackageRoot = localRoot;
|
|
194
|
+
return localRoot;
|
|
195
|
+
}
|
|
196
|
+
_cachedPackageRoot = npmRoot;
|
|
197
|
+
return npmRoot;
|
|
198
|
+
}
|
|
199
|
+
var _cachedPackageRoot;
|
|
200
|
+
var init_package_root = () => {};
|
|
201
|
+
|
|
35
202
|
// node_modules/@mozilla/readability/Readability.js
|
|
36
203
|
var require_Readability = __commonJS((exports, module) => {
|
|
37
204
|
function Readability(doc, options) {
|
|
@@ -18150,14 +18317,14 @@ var require_turndown_cjs = __commonJS((exports, module) => {
|
|
|
18150
18317
|
} else if (node.nodeType === 1) {
|
|
18151
18318
|
replacement = replacementForNode.call(self, node);
|
|
18152
18319
|
}
|
|
18153
|
-
return
|
|
18320
|
+
return join15(output, replacement);
|
|
18154
18321
|
}, "");
|
|
18155
18322
|
}
|
|
18156
18323
|
function postProcess(output) {
|
|
18157
18324
|
var self = this;
|
|
18158
18325
|
this.rules.forEach(function(rule) {
|
|
18159
18326
|
if (typeof rule.append === "function") {
|
|
18160
|
-
output =
|
|
18327
|
+
output = join15(output, rule.append(self.options));
|
|
18161
18328
|
}
|
|
18162
18329
|
});
|
|
18163
18330
|
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -18170,7 +18337,7 @@ var require_turndown_cjs = __commonJS((exports, module) => {
|
|
|
18170
18337
|
content = content.trim();
|
|
18171
18338
|
return whitespace.leading + rule.replacement(content, node, this.options) + whitespace.trailing;
|
|
18172
18339
|
}
|
|
18173
|
-
function
|
|
18340
|
+
function join15(output, replacement) {
|
|
18174
18341
|
var s1 = trimTrailingNewlines(output);
|
|
18175
18342
|
var s2 = trimLeadingNewlines(replacement);
|
|
18176
18343
|
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
@@ -18185,101 +18352,81 @@ var require_turndown_cjs = __commonJS((exports, module) => {
|
|
|
18185
18352
|
module.exports = TurndownService;
|
|
18186
18353
|
});
|
|
18187
18354
|
|
|
18188
|
-
// src/cli/
|
|
18189
|
-
var
|
|
18190
|
-
|
|
18191
|
-
|
|
18192
|
-
|
|
18193
|
-
|
|
18194
|
-
|
|
18195
|
-
|
|
18196
|
-
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
18202
|
-
|
|
18203
|
-
|
|
18204
|
-
|
|
18205
|
-
|
|
18206
|
-
|
|
18207
|
-
|
|
18208
|
-
|
|
18209
|
-
|
|
18210
|
-
|
|
18211
|
-
|
|
18212
|
-
sourcePath
|
|
18213
|
-
|
|
18214
|
-
|
|
18215
|
-
|
|
18216
|
-
|
|
18217
|
-
|
|
18218
|
-
|
|
18219
|
-
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
|
|
18223
|
-
|
|
18224
|
-
|
|
18225
|
-
|
|
18226
|
-
|
|
18227
|
-
|
|
18228
|
-
|
|
18229
|
-
|
|
18230
|
-
|
|
18231
|
-
|
|
18232
|
-
|
|
18233
|
-
|
|
18234
|
-
|
|
18235
|
-
|
|
18236
|
-
|
|
18237
|
-
|
|
18238
|
-
|
|
18239
|
-
|
|
18240
|
-
|
|
18241
|
-
|
|
18242
|
-
|
|
18243
|
-
|
|
18244
|
-
|
|
18245
|
-
name: "requesting-code-review",
|
|
18246
|
-
description: "Dispatch code reviewer subagent to catch issues before merging",
|
|
18247
|
-
allowedAgents: ["orchestrator"],
|
|
18248
|
-
sourcePath: "src/skills/requesting-code-review"
|
|
18249
|
-
},
|
|
18250
|
-
{
|
|
18251
|
-
name: "test-driven-development",
|
|
18252
|
-
description: "Write failing tests first, then minimal code to pass, before any implementation",
|
|
18253
|
-
allowedAgents: ["implementer"],
|
|
18254
|
-
sourcePath: "src/skills/test-driven-development"
|
|
18255
|
-
},
|
|
18256
|
-
{
|
|
18257
|
-
name: "verification-before-completion",
|
|
18258
|
-
description: "Run verification commands and confirm output before claiming work is complete",
|
|
18259
|
-
allowedAgents: ["implementer"],
|
|
18260
|
-
sourcePath: "src/skills/verification-before-completion"
|
|
18261
|
-
},
|
|
18262
|
-
{
|
|
18263
|
-
name: "systematic-debugging",
|
|
18264
|
-
description: "Find root cause before attempting fixes for any bug or test failure",
|
|
18265
|
-
allowedAgents: ["reviewer"],
|
|
18266
|
-
sourcePath: "src/skills/systematic-debugging"
|
|
18267
|
-
},
|
|
18268
|
-
{
|
|
18269
|
-
name: "receiving-code-review",
|
|
18270
|
-
description: "Evaluate code review feedback with technical rigor before implementing suggestions",
|
|
18271
|
-
allowedAgents: ["reviewer"],
|
|
18272
|
-
sourcePath: "src/skills/receiving-code-review"
|
|
18273
|
-
},
|
|
18274
|
-
{
|
|
18275
|
-
name: "writing-skills",
|
|
18276
|
-
description: "Create and edit skills using TDD methodology for process documentation",
|
|
18277
|
-
allowedAgents: ["orchestrator"],
|
|
18278
|
-
sourcePath: "src/skills/writing-skills"
|
|
18355
|
+
// src/cli/skill-sync.ts
|
|
18356
|
+
var exports_skill_sync = {};
|
|
18357
|
+
__export(exports_skill_sync, {
|
|
18358
|
+
syncBuiltinSkills: () => syncBuiltinSkills
|
|
18359
|
+
});
|
|
18360
|
+
import {
|
|
18361
|
+
cpSync,
|
|
18362
|
+
existsSync as existsSync13,
|
|
18363
|
+
lstatSync,
|
|
18364
|
+
mkdirSync as mkdirSync7,
|
|
18365
|
+
readlinkSync,
|
|
18366
|
+
rmSync as rmSync2,
|
|
18367
|
+
symlinkSync
|
|
18368
|
+
} from "node:fs";
|
|
18369
|
+
import { join as join15 } from "node:path";
|
|
18370
|
+
function syncBuiltinSkills(packageRoot, skillsDirOverride) {
|
|
18371
|
+
const resolvedPackageRoot = packageRoot ?? resolvePackageRoot();
|
|
18372
|
+
const skillsDir = skillsDirOverride ?? join15(getConfigDir(), "skills");
|
|
18373
|
+
mkdirSync7(skillsDir, { recursive: true });
|
|
18374
|
+
let installed = 0;
|
|
18375
|
+
let skipped = 0;
|
|
18376
|
+
let unchanged = 0;
|
|
18377
|
+
let copied = 0;
|
|
18378
|
+
for (const skill of CUSTOM_SKILLS) {
|
|
18379
|
+
const sourcePath = join15(resolvedPackageRoot, skill.sourcePath);
|
|
18380
|
+
const linkPath = join15(skillsDir, skill.name);
|
|
18381
|
+
if (!existsSync13(sourcePath)) {
|
|
18382
|
+
skipped++;
|
|
18383
|
+
continue;
|
|
18384
|
+
}
|
|
18385
|
+
try {
|
|
18386
|
+
if (lstatSync(linkPath).isSymbolicLink()) {
|
|
18387
|
+
const currentTarget = getSymlinkTarget(linkPath);
|
|
18388
|
+
if (currentTarget === sourcePath) {
|
|
18389
|
+
unchanged++;
|
|
18390
|
+
continue;
|
|
18391
|
+
}
|
|
18392
|
+
rmSync2(linkPath, { recursive: true, force: true });
|
|
18393
|
+
} else if (existsSync13(linkPath)) {
|
|
18394
|
+
rmSync2(linkPath, { recursive: true, force: true });
|
|
18395
|
+
}
|
|
18396
|
+
} catch {
|
|
18397
|
+
try {
|
|
18398
|
+
rmSync2(linkPath, { recursive: true, force: true });
|
|
18399
|
+
} catch {}
|
|
18400
|
+
}
|
|
18401
|
+
try {
|
|
18402
|
+
symlinkSync(sourcePath, linkPath, "junction");
|
|
18403
|
+
installed++;
|
|
18404
|
+
} catch {
|
|
18405
|
+
try {
|
|
18406
|
+
cpSync(sourcePath, linkPath, { recursive: true, force: true });
|
|
18407
|
+
copied++;
|
|
18408
|
+
} catch {
|
|
18409
|
+
skipped++;
|
|
18410
|
+
}
|
|
18411
|
+
}
|
|
18279
18412
|
}
|
|
18280
|
-
|
|
18413
|
+
return { installed, skipped, unchanged, copied };
|
|
18414
|
+
}
|
|
18415
|
+
function getSymlinkTarget(linkPath) {
|
|
18416
|
+
try {
|
|
18417
|
+
return readlinkSync(linkPath, "utf-8");
|
|
18418
|
+
} catch {
|
|
18419
|
+
return "";
|
|
18420
|
+
}
|
|
18421
|
+
}
|
|
18422
|
+
var init_skill_sync = __esm(() => {
|
|
18423
|
+
init_package_root();
|
|
18424
|
+
init_custom_skills();
|
|
18425
|
+
init_paths();
|
|
18426
|
+
});
|
|
18281
18427
|
|
|
18282
18428
|
// src/cli/skills.ts
|
|
18429
|
+
init_custom_skills();
|
|
18283
18430
|
var RECOMMENDED_SKILLS = [
|
|
18284
18431
|
{
|
|
18285
18432
|
name: "agent-browser",
|
|
@@ -18439,27 +18586,8 @@ var CouncilConfigSchema = z.object({
|
|
|
18439
18586
|
import * as fs from "node:fs";
|
|
18440
18587
|
import * as path from "node:path";
|
|
18441
18588
|
|
|
18442
|
-
// src/cli/
|
|
18443
|
-
|
|
18444
|
-
import { dirname, join } from "node:path";
|
|
18445
|
-
function getDefaultOpenCodeConfigDir() {
|
|
18446
|
-
const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join(homedir(), ".config");
|
|
18447
|
-
return join(userConfigDir, "opencode");
|
|
18448
|
-
}
|
|
18449
|
-
function getCustomOpenCodeConfigDir() {
|
|
18450
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
18451
|
-
return configDir || undefined;
|
|
18452
|
-
}
|
|
18453
|
-
function getConfigSearchDirs() {
|
|
18454
|
-
const dirs = [getCustomOpenCodeConfigDir(), getDefaultOpenCodeConfigDir()];
|
|
18455
|
-
return dirs.filter((dir, index) => {
|
|
18456
|
-
return Boolean(dir) && dirs.indexOf(dir) === index;
|
|
18457
|
-
});
|
|
18458
|
-
}
|
|
18459
|
-
function getOpenCodeConfigPaths() {
|
|
18460
|
-
const configDir = getDefaultOpenCodeConfigDir();
|
|
18461
|
-
return [join(configDir, "opencode.json"), join(configDir, "opencode.jsonc")];
|
|
18462
|
-
}
|
|
18589
|
+
// src/cli/config-io.ts
|
|
18590
|
+
init_paths();
|
|
18463
18591
|
|
|
18464
18592
|
// src/config/agent-mcps.ts
|
|
18465
18593
|
var DEFAULT_AGENT_MCPS = {
|
|
@@ -18493,6 +18621,9 @@ function getAgentMcpList(agentName, config) {
|
|
|
18493
18621
|
return defaultMcps ?? [];
|
|
18494
18622
|
}
|
|
18495
18623
|
|
|
18624
|
+
// src/cli/providers.ts
|
|
18625
|
+
init_custom_skills();
|
|
18626
|
+
|
|
18496
18627
|
// src/cli/config-io.ts
|
|
18497
18628
|
function stripJsonComments(json) {
|
|
18498
18629
|
const commentPattern = /\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g;
|
|
@@ -18500,6 +18631,9 @@ function stripJsonComments(json) {
|
|
|
18500
18631
|
return json.replace(commentPattern, (match, commentGroup) => commentGroup ? "" : match).replace(trailingCommaPattern, (match, comma, closing) => comma ? closing : match);
|
|
18501
18632
|
}
|
|
18502
18633
|
|
|
18634
|
+
// src/config/loader.ts
|
|
18635
|
+
init_paths();
|
|
18636
|
+
|
|
18503
18637
|
// src/config/schema.ts
|
|
18504
18638
|
import { z as z2 } from "zod";
|
|
18505
18639
|
var ProviderModelIdSchema = z2.string().regex(/^[^/\s]+\/[^\s]+$/, "Expected provider/model format (provider/.../model)");
|
|
@@ -21824,6 +21958,10 @@ async function crossWrite(path6, data) {
|
|
|
21824
21958
|
// src/hooks/auto-update-checker/cache.ts
|
|
21825
21959
|
import * as fs5 from "node:fs";
|
|
21826
21960
|
import * as path8 from "node:path";
|
|
21961
|
+
|
|
21962
|
+
// src/cli/config-manager.ts
|
|
21963
|
+
init_paths();
|
|
21964
|
+
|
|
21827
21965
|
// src/hooks/auto-update-checker/checker.ts
|
|
21828
21966
|
import * as fs4 from "node:fs";
|
|
21829
21967
|
import * as path7 from "node:path";
|
|
@@ -22795,6 +22933,7 @@ ${buildRetryGuidance(detected)}`;
|
|
|
22795
22933
|
};
|
|
22796
22934
|
}
|
|
22797
22935
|
// src/hooks/filter-available-skills/index.ts
|
|
22936
|
+
init_custom_skills();
|
|
22798
22937
|
var AVAILABLE_SKILLS_BLOCK_REGEX = /<available_skills>\s*([\s\S]*?)\s*<\/available_skills>/g;
|
|
22799
22938
|
var SKILL_NAME_REGEX = /<name>([^<]+)<\/name>/;
|
|
22800
22939
|
function builtinSkillBlock(name, description) {
|
|
@@ -30104,14 +30243,15 @@ Usage: /preset <name> to switch.`);
|
|
|
30104
30243
|
};
|
|
30105
30244
|
}
|
|
30106
30245
|
// src/tools/skill.ts
|
|
30107
|
-
import { existsSync as
|
|
30108
|
-
import { join as
|
|
30246
|
+
import { existsSync as existsSync11, readFileSync as readFileSync5 } from "node:fs";
|
|
30247
|
+
import { join as join14 } from "node:path";
|
|
30109
30248
|
import { tool as tool4 } from "@opencode-ai/plugin/tool";
|
|
30249
|
+
init_package_root();
|
|
30110
30250
|
var z5 = tool4.schema;
|
|
30111
30251
|
function resolveSkillPath(skillName) {
|
|
30112
|
-
const packageRoot =
|
|
30113
|
-
const bundledPath =
|
|
30114
|
-
if (
|
|
30252
|
+
const packageRoot = resolvePackageRoot();
|
|
30253
|
+
const bundledPath = join14(packageRoot, "src", "skills", skillName, "SKILL.md");
|
|
30254
|
+
if (existsSync11(bundledPath)) {
|
|
30115
30255
|
return bundledPath;
|
|
30116
30256
|
}
|
|
30117
30257
|
return;
|
|
@@ -31767,9 +31907,10 @@ function isInvalidLlmsResult(fetchResult) {
|
|
|
31767
31907
|
}
|
|
31768
31908
|
|
|
31769
31909
|
// src/tools/smartfetch/secondary-model.ts
|
|
31770
|
-
import { existsSync as
|
|
31910
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
31771
31911
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
31772
31912
|
import path17 from "node:path";
|
|
31913
|
+
init_paths();
|
|
31773
31914
|
function parseModelRef(value) {
|
|
31774
31915
|
if (!value)
|
|
31775
31916
|
return;
|
|
@@ -31796,7 +31937,7 @@ function pickAgentModelRef(value) {
|
|
|
31796
31937
|
function findPreferredOpenCodeConfigPath(baseDir) {
|
|
31797
31938
|
for (const file of ["opencode.jsonc", "opencode.json"]) {
|
|
31798
31939
|
const fullPath = path17.join(baseDir, file);
|
|
31799
|
-
if (
|
|
31940
|
+
if (existsSync12(fullPath))
|
|
31800
31941
|
return fullPath;
|
|
31801
31942
|
}
|
|
31802
31943
|
return;
|
|
@@ -32638,6 +32779,15 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
32638
32779
|
mcps = createBuiltinMcps(config.disabled_mcps, config.websearch);
|
|
32639
32780
|
webfetch = createWebfetchTool(ctx);
|
|
32640
32781
|
skillTools = createSkillTool(config);
|
|
32782
|
+
try {
|
|
32783
|
+
const { syncBuiltinSkills: syncBuiltinSkills2 } = await Promise.resolve().then(() => (init_skill_sync(), exports_skill_sync));
|
|
32784
|
+
const syncResult = syncBuiltinSkills2();
|
|
32785
|
+
if (syncResult.installed > 0 || syncResult.skipped > 0) {
|
|
32786
|
+
log("[plugin] skill sync:", syncResult);
|
|
32787
|
+
}
|
|
32788
|
+
} catch (err) {
|
|
32789
|
+
log("[plugin] skill sync failed (non-fatal):", err);
|
|
32790
|
+
}
|
|
32641
32791
|
multiplexerSessionManager = new MultiplexerSessionManager(ctx, multiplexerConfig);
|
|
32642
32792
|
autoUpdateChecker = createAutoUpdateCheckerHook(ctx, {
|
|
32643
32793
|
autoUpdate: config.autoUpdate ?? true
|
package/dist/tui.js
CHANGED
|
@@ -30,6 +30,20 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
30
30
|
return to;
|
|
31
31
|
};
|
|
32
32
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
33
|
+
var __returnValue = (v) => v;
|
|
34
|
+
function __exportSetter(name, newValue) {
|
|
35
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
36
|
+
}
|
|
37
|
+
var __export = (target, all) => {
|
|
38
|
+
for (var name in all)
|
|
39
|
+
__defProp(target, name, {
|
|
40
|
+
get: all[name],
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
set: __exportSetter.bind(all, name)
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
33
47
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
34
48
|
|
|
35
49
|
// src/tui.ts
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolvePackageRoot(): string;
|
package/package.json
CHANGED