@zcy2nn/agent-forge 1.0.1 → 1.0.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 +0 -19
- package/dist/cli/index.js +2 -154
- package/dist/index.js +5 -5
- package/dist/tui.js +7 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,25 +38,6 @@ bunx @zcy2nn/agent-forge@latest install
|
|
|
38
38
|
|
|
39
39
|
安装器会同时在 OpenCode 的 `tui.json` 中注册 TUI 插件,在侧边栏显示 Agent 状态和任务会话。手动安装时,需在 `opencode.json` 和 `tui.json` 的 `plugin` 数组中添加 `@zcy2nn/agent-forge`。
|
|
40
40
|
|
|
41
|
-
### 从 oh-my-opencode-slim 升级
|
|
42
|
-
|
|
43
|
-
如果你已有 `~/.config/opencode/oh-my-opencode-slim.json`,安装器会自动检测并引导迁移:
|
|
44
|
-
|
|
45
|
-
- Agent 名称自动重映射(explorer→researcher, oracle→reviewer, designer→implementer)
|
|
46
|
-
- 文件重命名为 `agent-forge.json`
|
|
47
|
-
- 原文件保留为 `.bak` 备份
|
|
48
|
-
|
|
49
|
-
也可以手动重命名文件并替换 Agent 名称:
|
|
50
|
-
|
|
51
|
-
| 旧名称 | 新名称 | 说明 |
|
|
52
|
-
|--------|--------|------|
|
|
53
|
-
| explorer | researcher | 合并(原 explorer + librarian) |
|
|
54
|
-
| librarian | researcher | 合并(原 explorer + librarian) |
|
|
55
|
-
| oracle | reviewer | 重命名 |
|
|
56
|
-
| designer | implementer | 合并(原 designer + fixer) |
|
|
57
|
-
| fixer | implementer | 合并(原 designer + fixer) |
|
|
58
|
-
| observer | — | 已移除 |
|
|
59
|
-
|
|
60
41
|
### 开始使用
|
|
61
42
|
|
|
62
43
|
安装器默认生成 OpenAI 和 OpenCode Go 两套预设,OpenAI 为默认激活。OpenAI 使用 `openai/gpt-5.5` 作为高判断力 Agent 的模型,`openai/gpt-5.4-mini` 作为快速执行 Agent 的模型。要使用 OpenCode Go,运行 `bunx @zcy2nn/agent-forge@latest install --preset=opencode-go`,或安装后在 `~/.config/opencode/agent-forge.json` 中修改默认预设。
|
package/dist/cli/index.js
CHANGED
|
@@ -1256,7 +1256,7 @@ Options:
|
|
|
1256
1256
|
}
|
|
1257
1257
|
|
|
1258
1258
|
// src/cli/install.ts
|
|
1259
|
-
import { existsSync as
|
|
1259
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
1260
1260
|
import { createInterface } from "node:readline/promises";
|
|
1261
1261
|
// src/cli/system.ts
|
|
1262
1262
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
@@ -1433,124 +1433,6 @@ function getOpenCodePath() {
|
|
|
1433
1433
|
const path2 = resolveOpenCodePath();
|
|
1434
1434
|
return path2 === "opencode" ? null : path2;
|
|
1435
1435
|
}
|
|
1436
|
-
// src/cli/migration.ts
|
|
1437
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1438
|
-
import { join as join5 } from "node:path";
|
|
1439
|
-
var LEGACY_BASE_NAME = "oh-my-opencode-slim";
|
|
1440
|
-
var PRIMARY_AGENT_MAP = {
|
|
1441
|
-
explorer: "researcher",
|
|
1442
|
-
oracle: "reviewer",
|
|
1443
|
-
designer: "implementer"
|
|
1444
|
-
};
|
|
1445
|
-
var SECONDARY_AGENT_MAP = {
|
|
1446
|
-
librarian: "researcher",
|
|
1447
|
-
fixer: "implementer"
|
|
1448
|
-
};
|
|
1449
|
-
var REMOVED_AGENTS = new Set(["observer"]);
|
|
1450
|
-
var ALL_LEGACY_NAMES = new Set([
|
|
1451
|
-
...Object.keys(PRIMARY_AGENT_MAP),
|
|
1452
|
-
...Object.keys(SECONDARY_AGENT_MAP),
|
|
1453
|
-
...REMOVED_AGENTS
|
|
1454
|
-
]);
|
|
1455
|
-
function getLegacyConfigPaths() {
|
|
1456
|
-
const configDir = getConfigDir();
|
|
1457
|
-
return [
|
|
1458
|
-
join5(configDir, `${LEGACY_BASE_NAME}.json`),
|
|
1459
|
-
join5(configDir, `${LEGACY_BASE_NAME}.jsonc`)
|
|
1460
|
-
];
|
|
1461
|
-
}
|
|
1462
|
-
function detectLegacyConfig() {
|
|
1463
|
-
const paths2 = getLegacyConfigPaths();
|
|
1464
|
-
for (const p of paths2) {
|
|
1465
|
-
if (existsSync5(p))
|
|
1466
|
-
return p;
|
|
1467
|
-
}
|
|
1468
|
-
return;
|
|
1469
|
-
}
|
|
1470
|
-
function migrateAgentNames(config) {
|
|
1471
|
-
const result = { ...config };
|
|
1472
|
-
const presets = result.presets;
|
|
1473
|
-
if (presets) {
|
|
1474
|
-
const migratedPresets = {};
|
|
1475
|
-
for (const [presetName, preset] of Object.entries(presets)) {
|
|
1476
|
-
migratedPresets[presetName] = migrateRecord(preset);
|
|
1477
|
-
}
|
|
1478
|
-
result.presets = migratedPresets;
|
|
1479
|
-
}
|
|
1480
|
-
const agents = result.agents;
|
|
1481
|
-
if (agents) {
|
|
1482
|
-
result.agents = migrateRecord(agents);
|
|
1483
|
-
}
|
|
1484
|
-
const disabled = result.disabled_agents;
|
|
1485
|
-
if (Array.isArray(disabled)) {
|
|
1486
|
-
result.disabled_agents = disabled.filter((name) => !REMOVED_AGENTS.has(name));
|
|
1487
|
-
}
|
|
1488
|
-
return result;
|
|
1489
|
-
}
|
|
1490
|
-
function migrateRecord(record) {
|
|
1491
|
-
const result = {};
|
|
1492
|
-
const usedTargets = new Set;
|
|
1493
|
-
for (const [key, value] of Object.entries(record)) {
|
|
1494
|
-
if (REMOVED_AGENTS.has(key)) {
|
|
1495
|
-
continue;
|
|
1496
|
-
}
|
|
1497
|
-
const primaryTarget = PRIMARY_AGENT_MAP[key];
|
|
1498
|
-
if (primaryTarget) {
|
|
1499
|
-
result[primaryTarget] = value;
|
|
1500
|
-
usedTargets.add(primaryTarget);
|
|
1501
|
-
continue;
|
|
1502
|
-
}
|
|
1503
|
-
if (!ALL_LEGACY_NAMES.has(key)) {
|
|
1504
|
-
result[key] = value;
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
for (const [key, value] of Object.entries(record)) {
|
|
1508
|
-
const secondaryTarget = SECONDARY_AGENT_MAP[key];
|
|
1509
|
-
if (secondaryTarget && !usedTargets.has(secondaryTarget)) {
|
|
1510
|
-
result[secondaryTarget] = value;
|
|
1511
|
-
usedTargets.add(secondaryTarget);
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
return result;
|
|
1515
|
-
}
|
|
1516
|
-
function performMigration(legacyPath) {
|
|
1517
|
-
try {
|
|
1518
|
-
const content = readFileSync4(legacyPath, "utf-8");
|
|
1519
|
-
if (content.trim().length === 0) {
|
|
1520
|
-
return {
|
|
1521
|
-
detected: true,
|
|
1522
|
-
migrated: false,
|
|
1523
|
-
legacyPath,
|
|
1524
|
-
error: "Legacy config file is empty"
|
|
1525
|
-
};
|
|
1526
|
-
}
|
|
1527
|
-
const config = JSON.parse(stripJsonComments(content));
|
|
1528
|
-
const migrated = migrateAgentNames(config);
|
|
1529
|
-
const configDir = getConfigDir();
|
|
1530
|
-
const newPath = join5(configDir, "agent-forge.json");
|
|
1531
|
-
const newContent = `${JSON.stringify(migrated, null, 2)}
|
|
1532
|
-
`;
|
|
1533
|
-
const tmpPath = `${newPath}.tmp`;
|
|
1534
|
-
writeFileSync2(tmpPath, newContent);
|
|
1535
|
-
renameSync2(tmpPath, newPath);
|
|
1536
|
-
const bakPath = `${legacyPath}.bak`;
|
|
1537
|
-
renameSync2(legacyPath, bakPath);
|
|
1538
|
-
return {
|
|
1539
|
-
detected: true,
|
|
1540
|
-
migrated: true,
|
|
1541
|
-
newPath,
|
|
1542
|
-
legacyPath
|
|
1543
|
-
};
|
|
1544
|
-
} catch (err) {
|
|
1545
|
-
return {
|
|
1546
|
-
detected: true,
|
|
1547
|
-
migrated: false,
|
|
1548
|
-
legacyPath,
|
|
1549
|
-
error: `Migration failed: ${err}`
|
|
1550
|
-
};
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
1436
|
// src/cli/install.ts
|
|
1555
1437
|
var GREEN = "\x1B[32m";
|
|
1556
1438
|
var BLUE = "\x1B[34m";
|
|
@@ -1652,10 +1534,6 @@ async function runInstall(config) {
|
|
|
1652
1534
|
totalSteps += 1;
|
|
1653
1535
|
if (config.installCustomSkills)
|
|
1654
1536
|
totalSteps += 1;
|
|
1655
|
-
const legacyPath = detectLegacyConfig();
|
|
1656
|
-
const hasLegacy = legacyPath !== undefined;
|
|
1657
|
-
if (hasLegacy)
|
|
1658
|
-
totalSteps += 1;
|
|
1659
1537
|
let step = 1;
|
|
1660
1538
|
printStep(step++, totalSteps, "Checking OpenCode installation...");
|
|
1661
1539
|
if (config.dryRun) {
|
|
@@ -1700,36 +1578,6 @@ async function runInstall(config) {
|
|
|
1700
1578
|
if (!handleStepResult(lspResult, "LSP enabled"))
|
|
1701
1579
|
return 1;
|
|
1702
1580
|
}
|
|
1703
|
-
if (hasLegacy && legacyPath) {
|
|
1704
|
-
printStep(step++, totalSteps, "Migrating legacy configuration...");
|
|
1705
|
-
if (config.dryRun) {
|
|
1706
|
-
printInfo(`Dry run mode - detected legacy config: ${legacyPath}`);
|
|
1707
|
-
printInfo("Would migrate agent names and rename to agent-forge.json");
|
|
1708
|
-
} else if (config.reset) {
|
|
1709
|
-
const migrationResult = performMigration(legacyPath);
|
|
1710
|
-
if (migrationResult.migrated) {
|
|
1711
|
-
printSuccess(`Legacy config migrated ${SYMBOLS.arrow} ${migrationResult.newPath}`);
|
|
1712
|
-
} else if (migrationResult.error) {
|
|
1713
|
-
printInfo(`Legacy config migration skipped: ${migrationResult.error}`);
|
|
1714
|
-
}
|
|
1715
|
-
} else {
|
|
1716
|
-
printInfo(`Legacy config detected: ${DIM}${legacyPath}${RESET}`);
|
|
1717
|
-
printInfo("This is an oh-my-opencode-slim config with old agent names (explorer, librarian, oracle, designer, fixer, observer).");
|
|
1718
|
-
printInfo("New agent names: researcher (explorer+librarian), reviewer (oracle), implementer (designer+fixer).");
|
|
1719
|
-
const shouldMigrate = await confirm("Migrate to agent-forge.json?", true);
|
|
1720
|
-
if (shouldMigrate) {
|
|
1721
|
-
const migrationResult = performMigration(legacyPath);
|
|
1722
|
-
if (migrationResult.migrated) {
|
|
1723
|
-
printSuccess(`Migrated ${SYMBOLS.arrow} ${DIM}${migrationResult.newPath}${RESET}`);
|
|
1724
|
-
printInfo(`Legacy config backed up to ${DIM}${legacyPath}.bak${RESET}`);
|
|
1725
|
-
} else {
|
|
1726
|
-
printError(migrationResult.error ?? "Unknown migration error");
|
|
1727
|
-
}
|
|
1728
|
-
} else {
|
|
1729
|
-
printInfo("Skipped migration. You can manually rename oh-my-opencode-slim.json to agent-forge.json and " + "update agent names: explorer→researcher, " + "oracle→reviewer, designer→implementer.");
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
1581
|
printStep(step++, totalSteps, "Writing agent-forge configuration...");
|
|
1734
1582
|
if (config.dryRun) {
|
|
1735
1583
|
const liteConfig = generateLiteConfig(config);
|
|
@@ -1739,7 +1587,7 @@ ${JSON.stringify(liteConfig, null, 2)}
|
|
|
1739
1587
|
`);
|
|
1740
1588
|
} else {
|
|
1741
1589
|
const configPath2 = getExistingLiteConfigPath();
|
|
1742
|
-
const configExists =
|
|
1590
|
+
const configExists = existsSync5(configPath2);
|
|
1743
1591
|
if (configExists && !config.reset) {
|
|
1744
1592
|
printInfo(`Configuration already exists at ${configPath2}. Use --reset to overwrite.`);
|
|
1745
1593
|
} else {
|
package/dist/index.js
CHANGED
|
@@ -22194,29 +22194,29 @@ async function runBackgroundUpdateCheck(ctx, autoUpdate) {
|
|
|
22194
22194
|
}
|
|
22195
22195
|
log(`[auto-update-checker] Update available (${channel}): ${currentVersion} → ${latestVersion}`);
|
|
22196
22196
|
if (pluginInfo.isPinned) {
|
|
22197
|
-
showToast(ctx, `
|
|
22197
|
+
showToast(ctx, `AGF ${latestVersion}`, `v${latestVersion} available.
|
|
22198
22198
|
Version is pinned. Update your plugin config to apply.`, "info", 8000);
|
|
22199
22199
|
log(`[auto-update-checker] Version is pinned; skipping auto-update.`);
|
|
22200
22200
|
return;
|
|
22201
22201
|
}
|
|
22202
22202
|
if (!autoUpdate) {
|
|
22203
|
-
showToast(ctx, `
|
|
22203
|
+
showToast(ctx, `AGF ${latestVersion}`, `v${latestVersion} available. Auto-update is disabled.`, "info", 8000);
|
|
22204
22204
|
log("[auto-update-checker] Auto-update disabled, notification only");
|
|
22205
22205
|
return;
|
|
22206
22206
|
}
|
|
22207
22207
|
const installDir = preparePackageUpdate(latestVersion, PACKAGE_NAME);
|
|
22208
22208
|
if (!installDir) {
|
|
22209
|
-
showToast(ctx, `
|
|
22209
|
+
showToast(ctx, `AGF ${latestVersion}`, `v${latestVersion} available. Auto-update could not prepare the active install.`, "info", 8000);
|
|
22210
22210
|
log("[auto-update-checker] Failed to prepare install root for auto-update");
|
|
22211
22211
|
return;
|
|
22212
22212
|
}
|
|
22213
22213
|
const installSuccess = await runBunInstallSafe(installDir);
|
|
22214
22214
|
if (installSuccess) {
|
|
22215
|
-
showToast(ctx, "
|
|
22215
|
+
showToast(ctx, "AGF Updated!", `v${currentVersion} → v${latestVersion}
|
|
22216
22216
|
Restart OpenCode to apply.`, "success", 8000);
|
|
22217
22217
|
log(`[auto-update-checker] Update installed: ${currentVersion} → ${latestVersion}`);
|
|
22218
22218
|
} else {
|
|
22219
|
-
showToast(ctx, `
|
|
22219
|
+
showToast(ctx, `AGF ${latestVersion}`, `v${latestVersion} available, but auto-update failed to install it. Check logs or retry manually.`, "error", 8000);
|
|
22220
22220
|
log("[auto-update-checker] bun install failed; update not installed");
|
|
22221
22221
|
}
|
|
22222
22222
|
}
|
package/dist/tui.js
CHANGED
|
@@ -33,6 +33,8 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
|
|
|
33
33
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
34
34
|
|
|
35
35
|
// src/tui.ts
|
|
36
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
37
|
+
import { fileURLToPath } from "node:url";
|
|
36
38
|
import { createElement, insert, setProp } from "@opentui/solid";
|
|
37
39
|
|
|
38
40
|
// src/config/constants.ts
|
|
@@ -143,9 +145,10 @@ function recordTuiAgentModel(input) {
|
|
|
143
145
|
var PLUGIN_NAME = "agent-forge";
|
|
144
146
|
var FALLBACK_SIDEBAR_AGENTS = SUBAGENT_NAMES.filter((agent) => agent !== "councillor" && agent !== "council" && !DEFAULT_DISABLED_AGENTS.includes(agent));
|
|
145
147
|
var BORDER = { type: "single" };
|
|
146
|
-
|
|
148
|
+
function readPackageVersion() {
|
|
147
149
|
try {
|
|
148
|
-
const
|
|
150
|
+
const pkgPath = fileURLToPath(new URL("../package.json", import.meta.url));
|
|
151
|
+
const packageJson = JSON.parse(readFileSync2(pkgPath, "utf8"));
|
|
149
152
|
return typeof packageJson.version === "string" ? packageJson.version : undefined;
|
|
150
153
|
} catch {
|
|
151
154
|
return;
|
|
@@ -204,7 +207,7 @@ function renderSidebar(snapshot, version, theme) {
|
|
|
204
207
|
justifyContent: "space-between",
|
|
205
208
|
alignItems: "center"
|
|
206
209
|
}, [
|
|
207
|
-
box({ paddingLeft: 1, paddingRight: 1, backgroundColor: theme.accent }, [text({ fg: theme.background }, ["
|
|
210
|
+
box({ paddingLeft: 1, paddingRight: 1, backgroundColor: theme.accent }, [text({ fg: theme.background }, ["AGF"])]),
|
|
208
211
|
text({ fg: theme.textMuted }, [`v${version}`])
|
|
209
212
|
]),
|
|
210
213
|
box({ width: "100%", marginTop: 1 }, [
|
|
@@ -219,7 +222,7 @@ function renderSidebar(snapshot, version, theme) {
|
|
|
219
222
|
var plugin = {
|
|
220
223
|
id: `${PLUGIN_NAME}:tui`,
|
|
221
224
|
tui: async (api, _options, meta) => {
|
|
222
|
-
const version = meta.version ??
|
|
225
|
+
const version = meta.version ?? readPackageVersion() ?? "dev";
|
|
223
226
|
let snapshot = readTuiSnapshot();
|
|
224
227
|
const renderTimer = setInterval(async () => {
|
|
225
228
|
try {
|
package/package.json
CHANGED