clikit-plugin 0.3.3 → 0.3.5
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/AGENTS.md +34 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +524 -111
- package/memory/_digest.md +1 -1
- package/memory/project/gotchas.md +102 -0
- package/package.json +3 -4
- package/skill/compaction/SKILL.md +69 -0
- package/skill/context-engineering/SKILL.md +93 -0
- package/skill/context-management/SKILL.md +70 -0
- package/dist/beads-context.test.d.ts +0 -2
- package/dist/beads-context.test.d.ts.map +0 -1
- package/dist/cli.test.d.ts +0 -2
- package/dist/cli.test.d.ts.map +0 -1
- package/dist/clilog.test.d.ts +0 -12
- package/dist/clilog.test.d.ts.map +0 -1
- package/dist/config.test.d.ts +0 -2
- package/dist/config.test.d.ts.map +0 -1
- package/dist/hooks/tilth-reading.test.d.ts +0 -2
- package/dist/hooks/tilth-reading.test.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -3386,7 +3386,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
3386
3386
|
|
|
3387
3387
|
// node_modules/gray-matter/index.js
|
|
3388
3388
|
var require_gray_matter = __commonJS((exports, module) => {
|
|
3389
|
-
var
|
|
3389
|
+
var fs2 = __require("fs");
|
|
3390
3390
|
var sections = require_section_matter();
|
|
3391
3391
|
var defaults = require_defaults();
|
|
3392
3392
|
var stringify = require_stringify();
|
|
@@ -3473,7 +3473,7 @@ var require_gray_matter = __commonJS((exports, module) => {
|
|
|
3473
3473
|
return stringify(file2, data, options2);
|
|
3474
3474
|
};
|
|
3475
3475
|
matter.read = function(filepath, options2) {
|
|
3476
|
-
const str2 =
|
|
3476
|
+
const str2 = fs2.readFileSync(filepath, "utf8");
|
|
3477
3477
|
const file2 = matter(str2, options2);
|
|
3478
3478
|
file2.path = filepath;
|
|
3479
3479
|
return file2;
|
|
@@ -3500,6 +3500,372 @@ var require_gray_matter = __commonJS((exports, module) => {
|
|
|
3500
3500
|
module.exports = matter;
|
|
3501
3501
|
});
|
|
3502
3502
|
|
|
3503
|
+
// src/cli.ts
|
|
3504
|
+
import * as fs from "fs";
|
|
3505
|
+
import * as path from "path";
|
|
3506
|
+
import * as os from "os";
|
|
3507
|
+
import { fileURLToPath } from "url";
|
|
3508
|
+
var PLUGIN_NAME = "clikit-plugin";
|
|
3509
|
+
var DCP_PLUGIN_ENTRY = "@tarquinen/opencode-dcp@beta";
|
|
3510
|
+
var VERSION = "0.0.0";
|
|
3511
|
+
function getPackageRoot() {
|
|
3512
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
3513
|
+
const currentDir = path.dirname(currentFile);
|
|
3514
|
+
if (path.basename(currentDir) === "dist") {
|
|
3515
|
+
return path.dirname(currentDir);
|
|
3516
|
+
}
|
|
3517
|
+
return path.dirname(currentDir);
|
|
3518
|
+
}
|
|
3519
|
+
function getPackageVersion() {
|
|
3520
|
+
const packageJsonPath = path.join(getPackageRoot(), "package.json");
|
|
3521
|
+
try {
|
|
3522
|
+
const raw = fs.readFileSync(packageJsonPath, "utf-8");
|
|
3523
|
+
const parsed = JSON.parse(raw);
|
|
3524
|
+
return parsed.version || VERSION;
|
|
3525
|
+
} catch {
|
|
3526
|
+
return VERSION;
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
function getPluginEntry() {
|
|
3530
|
+
return `${PLUGIN_NAME}@latest`;
|
|
3531
|
+
}
|
|
3532
|
+
function resolveProjectDir(env = process.env, cwd = process.cwd()) {
|
|
3533
|
+
const candidates = [env.INIT_CWD, env.PWD, cwd].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
3534
|
+
for (const candidate of candidates) {
|
|
3535
|
+
const resolved = path.resolve(candidate);
|
|
3536
|
+
try {
|
|
3537
|
+
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
|
|
3538
|
+
return resolved;
|
|
3539
|
+
}
|
|
3540
|
+
} catch {}
|
|
3541
|
+
}
|
|
3542
|
+
return cwd;
|
|
3543
|
+
}
|
|
3544
|
+
function upsertPluginEntry(existingPlugins, pluginEntry) {
|
|
3545
|
+
let pluginName;
|
|
3546
|
+
if (pluginEntry.startsWith("@")) {
|
|
3547
|
+
const versionAt = pluginEntry.indexOf("@", 1);
|
|
3548
|
+
pluginName = versionAt === -1 ? pluginEntry : pluginEntry.slice(0, versionAt);
|
|
3549
|
+
} else {
|
|
3550
|
+
pluginName = pluginEntry.split("@")[0] || pluginEntry;
|
|
3551
|
+
}
|
|
3552
|
+
const filteredPlugins = existingPlugins.filter((p) => p !== pluginName && !p.startsWith(`${pluginName}@`));
|
|
3553
|
+
filteredPlugins.push(pluginEntry);
|
|
3554
|
+
return filteredPlugins;
|
|
3555
|
+
}
|
|
3556
|
+
function copyFileIfMissing(sourcePath, targetPath, stats) {
|
|
3557
|
+
if (!fs.existsSync(sourcePath)) {
|
|
3558
|
+
stats.missingSources.push(sourcePath);
|
|
3559
|
+
return;
|
|
3560
|
+
}
|
|
3561
|
+
if (fs.existsSync(targetPath)) {
|
|
3562
|
+
stats.skipped += 1;
|
|
3563
|
+
return;
|
|
3564
|
+
}
|
|
3565
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
3566
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
3567
|
+
stats.copied += 1;
|
|
3568
|
+
}
|
|
3569
|
+
function copyDirectoryFilesIfMissing(sourceDir, targetDir, stats) {
|
|
3570
|
+
if (!fs.existsSync(sourceDir)) {
|
|
3571
|
+
stats.missingSources.push(sourceDir);
|
|
3572
|
+
return;
|
|
3573
|
+
}
|
|
3574
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
3575
|
+
const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
|
|
3576
|
+
for (const entry of entries) {
|
|
3577
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
3578
|
+
const targetPath = path.join(targetDir, entry.name);
|
|
3579
|
+
if (entry.isDirectory()) {
|
|
3580
|
+
copyDirectoryFilesIfMissing(sourcePath, targetPath, stats);
|
|
3581
|
+
continue;
|
|
3582
|
+
}
|
|
3583
|
+
if (entry.isFile()) {
|
|
3584
|
+
copyFileIfMissing(sourcePath, targetPath, stats);
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
function scaffoldProjectOpencode(projectDir, packageRoot = getPackageRoot()) {
|
|
3589
|
+
const projectOpencodeDir = path.join(projectDir, ".opencode");
|
|
3590
|
+
const stats = {
|
|
3591
|
+
copied: 0,
|
|
3592
|
+
skipped: 0,
|
|
3593
|
+
missingSources: []
|
|
3594
|
+
};
|
|
3595
|
+
fs.mkdirSync(projectOpencodeDir, { recursive: true });
|
|
3596
|
+
copyFileIfMissing(path.join(packageRoot, "AGENTS.md"), path.join(projectOpencodeDir, "AGENTS.md"), stats);
|
|
3597
|
+
copyDirectoryFilesIfMissing(path.join(packageRoot, "command"), path.join(projectOpencodeDir, "command"), stats);
|
|
3598
|
+
copyDirectoryFilesIfMissing(path.join(packageRoot, "skill"), path.join(projectOpencodeDir, "skill"), stats);
|
|
3599
|
+
copyDirectoryFilesIfMissing(path.join(packageRoot, "memory", "_templates"), path.join(projectOpencodeDir, "memory", "_templates"), stats);
|
|
3600
|
+
copyDirectoryFilesIfMissing(path.join(packageRoot, "src", "agents"), path.join(projectOpencodeDir, "src", "agents"), stats);
|
|
3601
|
+
copyFileIfMissing(path.join(packageRoot, "README.md"), path.join(projectOpencodeDir, "README-clikit.md"), stats);
|
|
3602
|
+
const indexPath = path.join(projectOpencodeDir, "index.ts");
|
|
3603
|
+
if (!fs.existsSync(indexPath)) {
|
|
3604
|
+
fs.writeFileSync(indexPath, `import CliKitPlugin from "${PLUGIN_NAME}";
|
|
3605
|
+
|
|
3606
|
+
export default CliKitPlugin;
|
|
3607
|
+
`);
|
|
3608
|
+
stats.copied += 1;
|
|
3609
|
+
} else {
|
|
3610
|
+
stats.skipped += 1;
|
|
3611
|
+
}
|
|
3612
|
+
return stats;
|
|
3613
|
+
}
|
|
3614
|
+
function getShellRcFiles() {
|
|
3615
|
+
const home = getRealHome();
|
|
3616
|
+
const rcFiles = [];
|
|
3617
|
+
const shell = process.env.SHELL || "";
|
|
3618
|
+
if (shell.includes("zsh")) {
|
|
3619
|
+
rcFiles.push(path.join(home, ".zshrc"));
|
|
3620
|
+
} else if (shell.includes("fish")) {
|
|
3621
|
+
rcFiles.push(path.join(home, ".config", "fish", "config.fish"));
|
|
3622
|
+
} else {
|
|
3623
|
+
rcFiles.push(path.join(home, ".bashrc"));
|
|
3624
|
+
const bashProfile = path.join(home, ".bash_profile");
|
|
3625
|
+
if (fs.existsSync(bashProfile)) {
|
|
3626
|
+
rcFiles.push(bashProfile);
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
return rcFiles;
|
|
3630
|
+
}
|
|
3631
|
+
function ensureEnvInShellRc(key, value) {
|
|
3632
|
+
const exportLine = `export ${key}=${value}`;
|
|
3633
|
+
const marker = `# Added by clikit-plugin`;
|
|
3634
|
+
const block = `
|
|
3635
|
+
${marker}
|
|
3636
|
+
${exportLine}
|
|
3637
|
+
`;
|
|
3638
|
+
const rcFiles = getShellRcFiles();
|
|
3639
|
+
for (const rcFile of rcFiles) {
|
|
3640
|
+
try {
|
|
3641
|
+
const existing = fs.existsSync(rcFile) ? fs.readFileSync(rcFile, "utf-8") : "";
|
|
3642
|
+
if (existing.includes(`export ${key}=`) || existing.includes(`${key}=`)) {
|
|
3643
|
+
console.log(`\u2713 ${key} already set in ${rcFile}`);
|
|
3644
|
+
continue;
|
|
3645
|
+
}
|
|
3646
|
+
fs.appendFileSync(rcFile, block, "utf-8");
|
|
3647
|
+
console.log(`\u2713 Added ${exportLine} to ${rcFile}`);
|
|
3648
|
+
} catch (err) {
|
|
3649
|
+
console.warn(`\u26A0 Could not write to ${rcFile}: ${err}`);
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3653
|
+
function removeLegacyGlobalPluginAssets(configDir) {
|
|
3654
|
+
const legacyPluginPath = path.join(configDir, "plugins", "clikit.js");
|
|
3655
|
+
const legacyAgentsDir = path.join(configDir, "plugins", "agents");
|
|
3656
|
+
const legacyCommandDir = path.join(configDir, "command");
|
|
3657
|
+
const legacyStatusPath = path.join(legacyCommandDir, "status.md");
|
|
3658
|
+
const legacyStatusBeadsPath = path.join(legacyCommandDir, "status-beads.md");
|
|
3659
|
+
if (fs.existsSync(legacyPluginPath)) {
|
|
3660
|
+
fs.rmSync(legacyPluginPath, { force: true });
|
|
3661
|
+
console.log(`\u2713 Removed legacy local plugin file: ${legacyPluginPath}`);
|
|
3662
|
+
}
|
|
3663
|
+
if (fs.existsSync(legacyAgentsDir)) {
|
|
3664
|
+
fs.rmSync(legacyAgentsDir, { recursive: true, force: true });
|
|
3665
|
+
console.log(`\u2713 Removed legacy local agents directory: ${legacyAgentsDir}`);
|
|
3666
|
+
}
|
|
3667
|
+
if (fs.existsSync(legacyStatusPath)) {
|
|
3668
|
+
fs.rmSync(legacyStatusPath, { force: true });
|
|
3669
|
+
console.log(`\u2713 Removed legacy command file: ${legacyStatusPath}`);
|
|
3670
|
+
}
|
|
3671
|
+
if (fs.existsSync(legacyStatusBeadsPath)) {
|
|
3672
|
+
fs.rmSync(legacyStatusBeadsPath, { force: true });
|
|
3673
|
+
console.log(`\u2713 Removed legacy command file: ${legacyStatusBeadsPath}`);
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
function getRealHome() {
|
|
3677
|
+
if (process.env.SNAP_REAL_HOME) {
|
|
3678
|
+
return process.env.SNAP_REAL_HOME;
|
|
3679
|
+
}
|
|
3680
|
+
const home = os.homedir();
|
|
3681
|
+
const snapMatch = home.match(/^(\/home\/[^/]+)\/snap\//);
|
|
3682
|
+
if (snapMatch) {
|
|
3683
|
+
return snapMatch[1];
|
|
3684
|
+
}
|
|
3685
|
+
return home;
|
|
3686
|
+
}
|
|
3687
|
+
function getConfigDir() {
|
|
3688
|
+
if (process.env.OPENCODE_CONFIG_DIR) {
|
|
3689
|
+
return process.env.OPENCODE_CONFIG_DIR;
|
|
3690
|
+
}
|
|
3691
|
+
const home = getRealHome();
|
|
3692
|
+
if (process.platform === "win32") {
|
|
3693
|
+
return path.join(process.env.APPDATA || path.join(home, "AppData", "Roaming"), "opencode");
|
|
3694
|
+
}
|
|
3695
|
+
return path.join(process.env.XDG_CONFIG_HOME || path.join(home, ".config"), "opencode");
|
|
3696
|
+
}
|
|
3697
|
+
function getConfigPath() {
|
|
3698
|
+
const configDir = getConfigDir();
|
|
3699
|
+
const jsonPath = path.join(configDir, "opencode.json");
|
|
3700
|
+
const jsoncPath = path.join(configDir, "opencode.jsonc");
|
|
3701
|
+
if (fs.existsSync(jsoncPath))
|
|
3702
|
+
return jsoncPath;
|
|
3703
|
+
if (fs.existsSync(jsonPath))
|
|
3704
|
+
return jsonPath;
|
|
3705
|
+
return jsonPath;
|
|
3706
|
+
}
|
|
3707
|
+
function getCliKitConfigPath(configDir = getConfigDir()) {
|
|
3708
|
+
const candidates = ["clikit.jsonc", "clikit.json", "clikit.config.json"];
|
|
3709
|
+
for (const name of candidates) {
|
|
3710
|
+
const fullPath = path.join(configDir, name);
|
|
3711
|
+
if (fs.existsSync(fullPath)) {
|
|
3712
|
+
return fullPath;
|
|
3713
|
+
}
|
|
3714
|
+
}
|
|
3715
|
+
return path.join(configDir, "clikit.json");
|
|
3716
|
+
}
|
|
3717
|
+
function ensureConfigDir() {
|
|
3718
|
+
const configDir = getConfigDir();
|
|
3719
|
+
if (!fs.existsSync(configDir)) {
|
|
3720
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
function parseConfig(configPath) {
|
|
3724
|
+
try {
|
|
3725
|
+
if (!fs.existsSync(configPath)) {
|
|
3726
|
+
return { config: {}, raw: "", parseError: null };
|
|
3727
|
+
}
|
|
3728
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
3729
|
+
try {
|
|
3730
|
+
const parsed = JSON.parse(content);
|
|
3731
|
+
return { config: parsed, raw: content, parseError: null };
|
|
3732
|
+
} catch {
|
|
3733
|
+
const cleaned = content.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
3734
|
+
const cleanedTrailing = cleaned.replace(/,\s*([}\]])/g, "$1");
|
|
3735
|
+
const parsed = JSON.parse(cleanedTrailing);
|
|
3736
|
+
return { config: parsed, raw: content, parseError: null };
|
|
3737
|
+
}
|
|
3738
|
+
} catch (err) {
|
|
3739
|
+
const raw = fs.existsSync(configPath) ? fs.readFileSync(configPath, "utf-8") : "";
|
|
3740
|
+
return { config: {}, raw, parseError: String(err) };
|
|
3741
|
+
}
|
|
3742
|
+
}
|
|
3743
|
+
function writeConfig(configPath, config) {
|
|
3744
|
+
ensureConfigDir();
|
|
3745
|
+
const tmpPath = `${configPath}.tmp`;
|
|
3746
|
+
const content = JSON.stringify(config, null, 2) + `
|
|
3747
|
+
`;
|
|
3748
|
+
fs.writeFileSync(tmpPath, content);
|
|
3749
|
+
fs.renameSync(tmpPath, configPath);
|
|
3750
|
+
}
|
|
3751
|
+
async function install(options2) {
|
|
3752
|
+
const pluginEntry = getPluginEntry();
|
|
3753
|
+
try {
|
|
3754
|
+
ensureConfigDir();
|
|
3755
|
+
const configPath = getConfigPath();
|
|
3756
|
+
const result = parseConfig(configPath);
|
|
3757
|
+
if (result.parseError && result.raw.trim()) {
|
|
3758
|
+
console.error(`\u2717 Config file has syntax errors and cannot be safely modified.`);
|
|
3759
|
+
console.error(` Error: ${result.parseError}`);
|
|
3760
|
+
console.error(` Please fix the config file manually.`);
|
|
3761
|
+
return 1;
|
|
3762
|
+
}
|
|
3763
|
+
const config = result.config;
|
|
3764
|
+
const existingPlugins = Array.isArray(config.plugin) ? config.plugin.filter((p) => typeof p === "string") : [];
|
|
3765
|
+
const filteredPlugins = upsertPluginEntry(existingPlugins, pluginEntry);
|
|
3766
|
+
const finalPlugins = upsertPluginEntry(filteredPlugins, DCP_PLUGIN_ENTRY);
|
|
3767
|
+
const pluginMergedConfig = { ...config, plugin: finalPlugins };
|
|
3768
|
+
writeConfig(configPath, pluginMergedConfig);
|
|
3769
|
+
if (options2.includeProjectScaffold) {
|
|
3770
|
+
const projectDir = resolveProjectDir();
|
|
3771
|
+
scaffoldProjectOpencode(projectDir);
|
|
3772
|
+
}
|
|
3773
|
+
removeLegacyGlobalPluginAssets(getConfigDir());
|
|
3774
|
+
ensureEnvInShellRc("OPENCODE_ENABLE_EXA", "1");
|
|
3775
|
+
const memoryDir = path.join(getConfigDir(), "memory");
|
|
3776
|
+
const memorySubdirs = ["specs", "plans", "research", "reviews", "handoffs", "beads", "prds"];
|
|
3777
|
+
for (const subdir of memorySubdirs) {
|
|
3778
|
+
const dir = path.join(memoryDir, subdir);
|
|
3779
|
+
if (!fs.existsSync(dir)) {
|
|
3780
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3783
|
+
const clikitConfigPath = getCliKitConfigPath();
|
|
3784
|
+
if (!fs.existsSync(clikitConfigPath)) {
|
|
3785
|
+
const defaultConfig = {
|
|
3786
|
+
$schema: `https://unpkg.com/${PLUGIN_NAME}@latest/schema.json`,
|
|
3787
|
+
disabled_agents: [],
|
|
3788
|
+
disabled_commands: [],
|
|
3789
|
+
disabled_skills: [],
|
|
3790
|
+
agents: {},
|
|
3791
|
+
commands: {},
|
|
3792
|
+
skills: {
|
|
3793
|
+
enable: [],
|
|
3794
|
+
disable: []
|
|
3795
|
+
},
|
|
3796
|
+
hooks: {}
|
|
3797
|
+
};
|
|
3798
|
+
writeConfig(clikitConfigPath, defaultConfig);
|
|
3799
|
+
}
|
|
3800
|
+
console.log(`\u2713 CliKit installed (${pluginEntry})`);
|
|
3801
|
+
console.log(`\u2713 DCP installed (${DCP_PLUGIN_ENTRY})`);
|
|
3802
|
+
console.log(`\u2713 Config: ${configPath}`);
|
|
3803
|
+
console.log("\u2713 Restart OpenCode");
|
|
3804
|
+
return 0;
|
|
3805
|
+
} catch (err) {
|
|
3806
|
+
console.error(`\u2717 Install failed: ${err}`);
|
|
3807
|
+
return 1;
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
function help() {
|
|
3811
|
+
console.log(`
|
|
3812
|
+
CliKit - OpenCode Plugin
|
|
3813
|
+
|
|
3814
|
+
Usage:
|
|
3815
|
+
bun x clikit-plugin <command>
|
|
3816
|
+
|
|
3817
|
+
Commands:
|
|
3818
|
+
install Install CliKit globally for OpenCode
|
|
3819
|
+
help Show this help message
|
|
3820
|
+
version Show version
|
|
3821
|
+
|
|
3822
|
+
Install options:
|
|
3823
|
+
--project Also scaffold project .opencode files (default: disabled)
|
|
3824
|
+
|
|
3825
|
+
Examples:
|
|
3826
|
+
bun x clikit-plugin install
|
|
3827
|
+
bun x clikit-plugin install --project
|
|
3828
|
+
`);
|
|
3829
|
+
}
|
|
3830
|
+
function version() {
|
|
3831
|
+
console.log(`clikit-plugin v${getPackageVersion()}`);
|
|
3832
|
+
}
|
|
3833
|
+
async function main() {
|
|
3834
|
+
const args = process.argv.slice(2);
|
|
3835
|
+
const command = args[0] || "help";
|
|
3836
|
+
const flags = args.slice(1);
|
|
3837
|
+
let exitCode = 0;
|
|
3838
|
+
switch (command) {
|
|
3839
|
+
case "install":
|
|
3840
|
+
case "i":
|
|
3841
|
+
exitCode = await install({
|
|
3842
|
+
includeProjectScaffold: flags.includes("--project")
|
|
3843
|
+
});
|
|
3844
|
+
break;
|
|
3845
|
+
case "help":
|
|
3846
|
+
case "-h":
|
|
3847
|
+
case "--help":
|
|
3848
|
+
help();
|
|
3849
|
+
break;
|
|
3850
|
+
case "version":
|
|
3851
|
+
case "-v":
|
|
3852
|
+
case "--version":
|
|
3853
|
+
version();
|
|
3854
|
+
break;
|
|
3855
|
+
default:
|
|
3856
|
+
console.error(`Unknown command: ${command}`);
|
|
3857
|
+
help();
|
|
3858
|
+
exitCode = 1;
|
|
3859
|
+
}
|
|
3860
|
+
process.exit(exitCode);
|
|
3861
|
+
}
|
|
3862
|
+
if (import.meta.main) {
|
|
3863
|
+
main().catch((err) => {
|
|
3864
|
+
console.error(err);
|
|
3865
|
+
process.exit(1);
|
|
3866
|
+
});
|
|
3867
|
+
}
|
|
3868
|
+
|
|
3503
3869
|
// node_modules/zod/v4/classic/external.js
|
|
3504
3870
|
var exports_external = {};
|
|
3505
3871
|
__export(exports_external, {
|
|
@@ -3733,7 +4099,7 @@ __export(exports_external, {
|
|
|
3733
4099
|
// node_modules/zod/v4/core/index.js
|
|
3734
4100
|
var exports_core2 = {};
|
|
3735
4101
|
__export(exports_core2, {
|
|
3736
|
-
version: () =>
|
|
4102
|
+
version: () => version2,
|
|
3737
4103
|
util: () => exports_util,
|
|
3738
4104
|
treeifyError: () => treeifyError,
|
|
3739
4105
|
toJSONSchema: () => toJSONSchema,
|
|
@@ -4229,10 +4595,10 @@ function mergeDefs(...defs) {
|
|
|
4229
4595
|
function cloneDef(schema) {
|
|
4230
4596
|
return mergeDefs(schema._zod.def);
|
|
4231
4597
|
}
|
|
4232
|
-
function getElementAtPath(obj,
|
|
4233
|
-
if (!
|
|
4598
|
+
function getElementAtPath(obj, path2) {
|
|
4599
|
+
if (!path2)
|
|
4234
4600
|
return obj;
|
|
4235
|
-
return
|
|
4601
|
+
return path2.reduce((acc, key) => acc?.[key], obj);
|
|
4236
4602
|
}
|
|
4237
4603
|
function promiseAllObject(promisesObj) {
|
|
4238
4604
|
const keys = Object.keys(promisesObj);
|
|
@@ -4591,11 +4957,11 @@ function aborted(x, startIndex = 0) {
|
|
|
4591
4957
|
}
|
|
4592
4958
|
return false;
|
|
4593
4959
|
}
|
|
4594
|
-
function prefixIssues(
|
|
4960
|
+
function prefixIssues(path2, issues) {
|
|
4595
4961
|
return issues.map((iss) => {
|
|
4596
4962
|
var _a;
|
|
4597
4963
|
(_a = iss).path ?? (_a.path = []);
|
|
4598
|
-
iss.path.unshift(
|
|
4964
|
+
iss.path.unshift(path2);
|
|
4599
4965
|
return iss;
|
|
4600
4966
|
});
|
|
4601
4967
|
}
|
|
@@ -4763,7 +5129,7 @@ function treeifyError(error, _mapper) {
|
|
|
4763
5129
|
return issue2.message;
|
|
4764
5130
|
};
|
|
4765
5131
|
const result = { errors: [] };
|
|
4766
|
-
const processError = (error2,
|
|
5132
|
+
const processError = (error2, path2 = []) => {
|
|
4767
5133
|
var _a, _b;
|
|
4768
5134
|
for (const issue2 of error2.issues) {
|
|
4769
5135
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -4773,7 +5139,7 @@ function treeifyError(error, _mapper) {
|
|
|
4773
5139
|
} else if (issue2.code === "invalid_element") {
|
|
4774
5140
|
processError({ issues: issue2.issues }, issue2.path);
|
|
4775
5141
|
} else {
|
|
4776
|
-
const fullpath = [...
|
|
5142
|
+
const fullpath = [...path2, ...issue2.path];
|
|
4777
5143
|
if (fullpath.length === 0) {
|
|
4778
5144
|
result.errors.push(mapper(issue2));
|
|
4779
5145
|
continue;
|
|
@@ -4805,8 +5171,8 @@ function treeifyError(error, _mapper) {
|
|
|
4805
5171
|
}
|
|
4806
5172
|
function toDotPath(_path) {
|
|
4807
5173
|
const segs = [];
|
|
4808
|
-
const
|
|
4809
|
-
for (const seg of
|
|
5174
|
+
const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
5175
|
+
for (const seg of path2) {
|
|
4810
5176
|
if (typeof seg === "number")
|
|
4811
5177
|
segs.push(`[${seg}]`);
|
|
4812
5178
|
else if (typeof seg === "symbol")
|
|
@@ -4990,10 +5356,10 @@ var nanoid = /^[a-zA-Z0-9_-]{21}$/;
|
|
|
4990
5356
|
var duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
|
|
4991
5357
|
var extendedDuration = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
|
|
4992
5358
|
var guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
|
4993
|
-
var uuid = (
|
|
4994
|
-
if (!
|
|
5359
|
+
var uuid = (version2) => {
|
|
5360
|
+
if (!version2)
|
|
4995
5361
|
return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
|
|
4996
|
-
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${
|
|
5362
|
+
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version2}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
|
|
4997
5363
|
};
|
|
4998
5364
|
var uuid4 = /* @__PURE__ */ uuid(4);
|
|
4999
5365
|
var uuid6 = /* @__PURE__ */ uuid(6);
|
|
@@ -5652,7 +6018,7 @@ class Doc {
|
|
|
5652
6018
|
}
|
|
5653
6019
|
|
|
5654
6020
|
// node_modules/zod/v4/core/versions.js
|
|
5655
|
-
var
|
|
6021
|
+
var version2 = {
|
|
5656
6022
|
major: 4,
|
|
5657
6023
|
minor: 1,
|
|
5658
6024
|
patch: 8
|
|
@@ -5664,7 +6030,7 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
5664
6030
|
inst ?? (inst = {});
|
|
5665
6031
|
inst._zod.def = def;
|
|
5666
6032
|
inst._zod.bag = inst._zod.bag || {};
|
|
5667
|
-
inst._zod.version =
|
|
6033
|
+
inst._zod.version = version2;
|
|
5668
6034
|
const checks = [...inst._zod.def.checks ?? []];
|
|
5669
6035
|
if (inst._zod.traits.has("$ZodCheck")) {
|
|
5670
6036
|
checks.unshift(inst);
|
|
@@ -15823,15 +16189,18 @@ tool.schema = exports_external;
|
|
|
15823
16189
|
// src/index.ts
|
|
15824
16190
|
import { execFile as execFile3 } from "child_process";
|
|
15825
16191
|
import { promisify as promisify3 } from "util";
|
|
16192
|
+
import * as fs11 from "fs";
|
|
16193
|
+
import * as path11 from "path";
|
|
16194
|
+
import * as os3 from "os";
|
|
15826
16195
|
|
|
15827
16196
|
// src/agents/index.ts
|
|
15828
16197
|
var import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
15829
|
-
import * as
|
|
15830
|
-
import * as
|
|
16198
|
+
import * as fs3 from "fs";
|
|
16199
|
+
import * as path3 from "path";
|
|
15831
16200
|
|
|
15832
16201
|
// src/hooks/error-logger.ts
|
|
15833
|
-
import * as
|
|
15834
|
-
import * as
|
|
16202
|
+
import * as fs2 from "fs";
|
|
16203
|
+
import * as path2 from "path";
|
|
15835
16204
|
var BLOCKED_TOOL_ERROR_PREFIX = "[CliKit] Blocked tool execution:";
|
|
15836
16205
|
var _initErrorBuffer = [];
|
|
15837
16206
|
function bufferInitError(source, level, message, context) {
|
|
@@ -15874,10 +16243,10 @@ function formatHookErrorLog(hookName, error45, context) {
|
|
|
15874
16243
|
}
|
|
15875
16244
|
function writeErrorLog(hookName, error45, projectDir, context) {
|
|
15876
16245
|
try {
|
|
15877
|
-
const logDir =
|
|
15878
|
-
const logPath =
|
|
15879
|
-
if (!
|
|
15880
|
-
|
|
16246
|
+
const logDir = path2.join(projectDir, ".opencode");
|
|
16247
|
+
const logPath = path2.join(logDir, "error-log.txt");
|
|
16248
|
+
if (!fs2.existsSync(logDir)) {
|
|
16249
|
+
fs2.mkdirSync(logDir, { recursive: true });
|
|
15881
16250
|
}
|
|
15882
16251
|
const timestamp = new Date().toISOString();
|
|
15883
16252
|
const message = getErrorMessage(error45);
|
|
@@ -15894,15 +16263,15 @@ ${stack}`] : [],
|
|
|
15894
16263
|
""
|
|
15895
16264
|
].join(`
|
|
15896
16265
|
`);
|
|
15897
|
-
|
|
16266
|
+
fs2.appendFileSync(logPath, entry, "utf-8");
|
|
15898
16267
|
} catch {}
|
|
15899
16268
|
}
|
|
15900
16269
|
function writeBufferedErrorLog(entry, projectDir) {
|
|
15901
16270
|
try {
|
|
15902
|
-
const logDir =
|
|
15903
|
-
const logPath =
|
|
15904
|
-
if (!
|
|
15905
|
-
|
|
16271
|
+
const logDir = path2.join(projectDir, ".opencode");
|
|
16272
|
+
const logPath = path2.join(logDir, "error-log.txt");
|
|
16273
|
+
if (!fs2.existsSync(logDir)) {
|
|
16274
|
+
fs2.mkdirSync(logDir, { recursive: true });
|
|
15906
16275
|
}
|
|
15907
16276
|
const timestamp = new Date().toISOString();
|
|
15908
16277
|
const contextStr = entry.context && Object.keys(entry.context).length > 0 ? `context: ${JSON.stringify(entry.context, null, 2)}` : "";
|
|
@@ -15915,29 +16284,29 @@ function writeBufferedErrorLog(entry, projectDir) {
|
|
|
15915
16284
|
""
|
|
15916
16285
|
].join(`
|
|
15917
16286
|
`);
|
|
15918
|
-
|
|
16287
|
+
fs2.appendFileSync(logPath, line, "utf-8");
|
|
15919
16288
|
} catch {}
|
|
15920
16289
|
}
|
|
15921
16290
|
|
|
15922
16291
|
// src/agents/index.ts
|
|
15923
16292
|
var AGENTS_DIR_CANDIDATES = [
|
|
15924
16293
|
import.meta.dir,
|
|
15925
|
-
|
|
15926
|
-
|
|
15927
|
-
|
|
16294
|
+
path3.join(import.meta.dir, "../src/agents"),
|
|
16295
|
+
path3.join(import.meta.dir, "../../src/agents"),
|
|
16296
|
+
path3.join(import.meta.dir, "../agents")
|
|
15928
16297
|
];
|
|
15929
16298
|
function resolveAgentsDir() {
|
|
15930
16299
|
for (const dir of AGENTS_DIR_CANDIDATES) {
|
|
15931
|
-
if (!
|
|
16300
|
+
if (!fs3.existsSync(dir))
|
|
15932
16301
|
continue;
|
|
15933
16302
|
try {
|
|
15934
|
-
const hasAgentFiles =
|
|
16303
|
+
const hasAgentFiles = fs3.readdirSync(dir).some((f) => f.endsWith(".md") && f !== "AGENTS.md");
|
|
15935
16304
|
if (hasAgentFiles)
|
|
15936
16305
|
return dir;
|
|
15937
16306
|
} catch {}
|
|
15938
16307
|
}
|
|
15939
16308
|
for (const dir of AGENTS_DIR_CANDIDATES) {
|
|
15940
|
-
if (
|
|
16309
|
+
if (fs3.existsSync(dir)) {
|
|
15941
16310
|
return dir;
|
|
15942
16311
|
}
|
|
15943
16312
|
}
|
|
@@ -15946,7 +16315,7 @@ function resolveAgentsDir() {
|
|
|
15946
16315
|
var VALID_MODES = new Set(["subagent", "primary", "all"]);
|
|
15947
16316
|
function validateFrontmatter(frontmatter, filePath) {
|
|
15948
16317
|
const warnings = [];
|
|
15949
|
-
const name =
|
|
16318
|
+
const name = path3.basename(filePath, ".md");
|
|
15950
16319
|
if (!frontmatter.description) {
|
|
15951
16320
|
warnings.push(`[${name}] Missing 'description' \u2014 agent will have empty description`);
|
|
15952
16321
|
}
|
|
@@ -15969,7 +16338,7 @@ function validateFrontmatter(frontmatter, filePath) {
|
|
|
15969
16338
|
}
|
|
15970
16339
|
function parseAgentMarkdown(filePath) {
|
|
15971
16340
|
try {
|
|
15972
|
-
const content =
|
|
16341
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
15973
16342
|
const { data: frontmatter, content: body } = import_gray_matter.default(content);
|
|
15974
16343
|
const warnings = validateFrontmatter(frontmatter, filePath);
|
|
15975
16344
|
for (const warning of warnings) {
|
|
@@ -16005,13 +16374,13 @@ function parseAgentMarkdown(filePath) {
|
|
|
16005
16374
|
function loadAgents() {
|
|
16006
16375
|
const agents = {};
|
|
16007
16376
|
const agentsDir = resolveAgentsDir();
|
|
16008
|
-
if (!
|
|
16377
|
+
if (!fs3.existsSync(agentsDir)) {
|
|
16009
16378
|
return agents;
|
|
16010
16379
|
}
|
|
16011
|
-
const files =
|
|
16380
|
+
const files = fs3.readdirSync(agentsDir).filter((f) => f.endsWith(".md") && f !== "AGENTS.md").sort();
|
|
16012
16381
|
for (const file2 of files) {
|
|
16013
|
-
const agentName =
|
|
16014
|
-
const agentPath =
|
|
16382
|
+
const agentName = path3.basename(file2, ".md");
|
|
16383
|
+
const agentPath = path3.join(agentsDir, file2);
|
|
16015
16384
|
const agent = parseAgentMarkdown(agentPath);
|
|
16016
16385
|
if (agent) {
|
|
16017
16386
|
agents[agentName] = agent;
|
|
@@ -16022,10 +16391,10 @@ function loadAgents() {
|
|
|
16022
16391
|
var _cachedAgents = null;
|
|
16023
16392
|
var _cachedAgentsFingerprint = "";
|
|
16024
16393
|
function getAgentsFingerprint(agentsDir) {
|
|
16025
|
-
const files =
|
|
16394
|
+
const files = fs3.readdirSync(agentsDir).filter((f) => f.endsWith(".md") && f !== "AGENTS.md").sort();
|
|
16026
16395
|
const parts = files.map((file2) => {
|
|
16027
|
-
const fullPath =
|
|
16028
|
-
const stat =
|
|
16396
|
+
const fullPath = path3.join(agentsDir, file2);
|
|
16397
|
+
const stat = fs3.statSync(fullPath);
|
|
16029
16398
|
const size = stat.size;
|
|
16030
16399
|
return `${file2}:${stat.mtimeMs}:${size}`;
|
|
16031
16400
|
});
|
|
@@ -16047,16 +16416,16 @@ function getBuiltinAgents() {
|
|
|
16047
16416
|
|
|
16048
16417
|
// src/commands/index.ts
|
|
16049
16418
|
var import_gray_matter2 = __toESM(require_gray_matter(), 1);
|
|
16050
|
-
import * as
|
|
16051
|
-
import * as
|
|
16419
|
+
import * as fs4 from "fs";
|
|
16420
|
+
import * as path4 from "path";
|
|
16052
16421
|
var COMMANDS_DIR_CANDIDATES = [
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16422
|
+
path4.join(import.meta.dir, "../command"),
|
|
16423
|
+
path4.join(import.meta.dir, "../../command"),
|
|
16424
|
+
path4.join(import.meta.dir, "../../../command")
|
|
16056
16425
|
];
|
|
16057
16426
|
function resolveCommandsDir() {
|
|
16058
16427
|
for (const dir of COMMANDS_DIR_CANDIDATES) {
|
|
16059
|
-
if (
|
|
16428
|
+
if (fs4.existsSync(dir)) {
|
|
16060
16429
|
return dir;
|
|
16061
16430
|
}
|
|
16062
16431
|
}
|
|
@@ -16064,7 +16433,7 @@ function resolveCommandsDir() {
|
|
|
16064
16433
|
}
|
|
16065
16434
|
function parseCommandMarkdown(filePath) {
|
|
16066
16435
|
try {
|
|
16067
|
-
const content =
|
|
16436
|
+
const content = fs4.readFileSync(filePath, "utf-8");
|
|
16068
16437
|
const { data: frontmatter, content: body } = import_gray_matter2.default(content);
|
|
16069
16438
|
const config2 = {
|
|
16070
16439
|
description: frontmatter.description || "",
|
|
@@ -16091,13 +16460,13 @@ function parseCommandMarkdown(filePath) {
|
|
|
16091
16460
|
function loadCommands() {
|
|
16092
16461
|
const commands = {};
|
|
16093
16462
|
const commandsDir = resolveCommandsDir();
|
|
16094
|
-
if (!
|
|
16463
|
+
if (!fs4.existsSync(commandsDir)) {
|
|
16095
16464
|
return commands;
|
|
16096
16465
|
}
|
|
16097
|
-
const files =
|
|
16466
|
+
const files = fs4.readdirSync(commandsDir).filter((f) => f.endsWith(".md")).sort();
|
|
16098
16467
|
for (const file2 of files) {
|
|
16099
|
-
const commandName =
|
|
16100
|
-
const commandPath =
|
|
16468
|
+
const commandName = path4.basename(file2, ".md");
|
|
16469
|
+
const commandPath = path4.join(commandsDir, file2);
|
|
16101
16470
|
const command = parseCommandMarkdown(commandPath);
|
|
16102
16471
|
if (command) {
|
|
16103
16472
|
commands[commandName] = command;
|
|
@@ -16108,10 +16477,10 @@ function loadCommands() {
|
|
|
16108
16477
|
var _cachedCommands = null;
|
|
16109
16478
|
var _cachedCommandsFingerprint = "";
|
|
16110
16479
|
function getCommandsFingerprint(commandsDir) {
|
|
16111
|
-
const files =
|
|
16480
|
+
const files = fs4.readdirSync(commandsDir).filter((f) => f.endsWith(".md")).sort();
|
|
16112
16481
|
const parts = files.map((file2) => {
|
|
16113
|
-
const fullPath =
|
|
16114
|
-
const stat =
|
|
16482
|
+
const fullPath = path4.join(commandsDir, file2);
|
|
16483
|
+
const stat = fs4.statSync(fullPath);
|
|
16115
16484
|
return `${file2}:${stat.mtimeMs}`;
|
|
16116
16485
|
});
|
|
16117
16486
|
return parts.join("|");
|
|
@@ -16132,16 +16501,16 @@ function getBuiltinCommands() {
|
|
|
16132
16501
|
|
|
16133
16502
|
// src/skills/index.ts
|
|
16134
16503
|
var import_gray_matter3 = __toESM(require_gray_matter(), 1);
|
|
16135
|
-
import * as
|
|
16136
|
-
import * as
|
|
16504
|
+
import * as fs5 from "fs";
|
|
16505
|
+
import * as path5 from "path";
|
|
16137
16506
|
var SKILLS_DIR_CANDIDATES = [
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
16507
|
+
path5.join(import.meta.dir, "../skill"),
|
|
16508
|
+
path5.join(import.meta.dir, "../../skill"),
|
|
16509
|
+
path5.join(import.meta.dir, "../../../skill")
|
|
16141
16510
|
];
|
|
16142
16511
|
function resolveSkillsDir() {
|
|
16143
16512
|
for (const dir of SKILLS_DIR_CANDIDATES) {
|
|
16144
|
-
if (
|
|
16513
|
+
if (fs5.existsSync(dir)) {
|
|
16145
16514
|
return dir;
|
|
16146
16515
|
}
|
|
16147
16516
|
}
|
|
@@ -16150,23 +16519,23 @@ function resolveSkillsDir() {
|
|
|
16150
16519
|
function getBuiltinSkills() {
|
|
16151
16520
|
const skills = {};
|
|
16152
16521
|
const skillsDir = resolveSkillsDir();
|
|
16153
|
-
if (!
|
|
16522
|
+
if (!fs5.existsSync(skillsDir)) {
|
|
16154
16523
|
bufferInitError("skills", "warn", `Skills directory not found: ${skillsDir}`);
|
|
16155
16524
|
return skills;
|
|
16156
16525
|
}
|
|
16157
|
-
const skillDirs =
|
|
16526
|
+
const skillDirs = fs5.readdirSync(skillsDir, { withFileTypes: true });
|
|
16158
16527
|
for (const dirent of skillDirs) {
|
|
16159
16528
|
if (!dirent.isDirectory())
|
|
16160
16529
|
continue;
|
|
16161
16530
|
const skillName = dirent.name;
|
|
16162
|
-
const skillPath =
|
|
16163
|
-
const skillMdPath =
|
|
16164
|
-
if (!
|
|
16531
|
+
const skillPath = path5.join(skillsDir, skillName);
|
|
16532
|
+
const skillMdPath = path5.join(skillPath, "SKILL.md");
|
|
16533
|
+
if (!fs5.existsSync(skillMdPath)) {
|
|
16165
16534
|
bufferInitError("skills", "warn", `Missing SKILL.md for skill: ${skillName}`, { skillPath });
|
|
16166
16535
|
continue;
|
|
16167
16536
|
}
|
|
16168
16537
|
try {
|
|
16169
|
-
const fileContent =
|
|
16538
|
+
const fileContent = fs5.readFileSync(skillMdPath, "utf-8");
|
|
16170
16539
|
const { data, content } = import_gray_matter3.default(fileContent);
|
|
16171
16540
|
skills[skillName] = {
|
|
16172
16541
|
name: data.name || skillName,
|
|
@@ -16185,9 +16554,9 @@ function getBuiltinSkills() {
|
|
|
16185
16554
|
}
|
|
16186
16555
|
|
|
16187
16556
|
// src/config.ts
|
|
16188
|
-
import * as
|
|
16189
|
-
import * as
|
|
16190
|
-
import * as
|
|
16557
|
+
import * as fs6 from "fs";
|
|
16558
|
+
import * as path6 from "path";
|
|
16559
|
+
import * as os2 from "os";
|
|
16191
16560
|
var DEFAULT_CONFIG = {
|
|
16192
16561
|
disabled_agents: [],
|
|
16193
16562
|
disabled_commands: [],
|
|
@@ -16277,15 +16646,15 @@ var DEFAULT_CONFIG = {
|
|
|
16277
16646
|
};
|
|
16278
16647
|
function getUserConfigDir() {
|
|
16279
16648
|
if (process.platform === "win32") {
|
|
16280
|
-
return process.env.APPDATA ||
|
|
16649
|
+
return process.env.APPDATA || path6.join(os2.homedir(), "AppData", "Roaming");
|
|
16281
16650
|
}
|
|
16282
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
16651
|
+
return process.env.XDG_CONFIG_HOME || path6.join(os2.homedir(), ".config");
|
|
16283
16652
|
}
|
|
16284
16653
|
function getOpenCodeConfigDir() {
|
|
16285
16654
|
if (process.env.OPENCODE_CONFIG_DIR) {
|
|
16286
16655
|
return process.env.OPENCODE_CONFIG_DIR;
|
|
16287
16656
|
}
|
|
16288
|
-
return
|
|
16657
|
+
return path6.join(getUserConfigDir(), "opencode");
|
|
16289
16658
|
}
|
|
16290
16659
|
function stripJsonComments(content) {
|
|
16291
16660
|
let result = "";
|
|
@@ -16343,10 +16712,10 @@ function stripJsonComments(content) {
|
|
|
16343
16712
|
}
|
|
16344
16713
|
function loadJsonFile(filePath) {
|
|
16345
16714
|
try {
|
|
16346
|
-
if (!
|
|
16715
|
+
if (!fs6.existsSync(filePath)) {
|
|
16347
16716
|
return null;
|
|
16348
16717
|
}
|
|
16349
|
-
const content =
|
|
16718
|
+
const content = fs6.readFileSync(filePath, "utf-8");
|
|
16350
16719
|
try {
|
|
16351
16720
|
return JSON.parse(content);
|
|
16352
16721
|
} catch {
|
|
@@ -16380,12 +16749,12 @@ function loadCliKitConfig(projectDirectory) {
|
|
|
16380
16749
|
const userBaseDir = getOpenCodeConfigDir();
|
|
16381
16750
|
const projectBaseDirs = [
|
|
16382
16751
|
safeDir,
|
|
16383
|
-
|
|
16752
|
+
path6.join(safeDir, ".opencode")
|
|
16384
16753
|
];
|
|
16385
16754
|
const configCandidates = ["clikit.jsonc", "clikit.json", "clikit.config.json"];
|
|
16386
16755
|
let config2 = { ...DEFAULT_CONFIG };
|
|
16387
16756
|
for (const candidate of configCandidates) {
|
|
16388
|
-
const userConfigPath =
|
|
16757
|
+
const userConfigPath = path6.join(userBaseDir, candidate);
|
|
16389
16758
|
const userConfig = loadJsonFile(userConfigPath);
|
|
16390
16759
|
if (userConfig) {
|
|
16391
16760
|
config2 = deepMerge(config2, userConfig);
|
|
@@ -16394,7 +16763,7 @@ function loadCliKitConfig(projectDirectory) {
|
|
|
16394
16763
|
}
|
|
16395
16764
|
for (const baseDir of projectBaseDirs) {
|
|
16396
16765
|
for (const candidate of configCandidates) {
|
|
16397
|
-
const projectConfigPath =
|
|
16766
|
+
const projectConfigPath = path6.join(baseDir, candidate);
|
|
16398
16767
|
const projectConfig = loadJsonFile(projectConfigPath);
|
|
16399
16768
|
if (projectConfig) {
|
|
16400
16769
|
config2 = deepMerge(config2, projectConfig);
|
|
@@ -16904,8 +17273,8 @@ function formatTruncationLog(result) {
|
|
|
16904
17273
|
return `[CliKit:truncator] Truncated output: ${result.originalLines} \u2192 ${result.truncatedLines} lines, saved ${(saved / 1024).toFixed(1)}KB`;
|
|
16905
17274
|
}
|
|
16906
17275
|
// src/hooks/memory-digest.ts
|
|
16907
|
-
import * as
|
|
16908
|
-
import * as
|
|
17276
|
+
import * as fs7 from "fs";
|
|
17277
|
+
import * as path7 from "path";
|
|
16909
17278
|
import { Database } from "bun:sqlite";
|
|
16910
17279
|
function parseJsonArray(value) {
|
|
16911
17280
|
if (typeof value !== "string" || !value.trim())
|
|
@@ -16925,7 +17294,7 @@ function formatDate(iso) {
|
|
|
16925
17294
|
}
|
|
16926
17295
|
}
|
|
16927
17296
|
function writeTopicFile(memoryDir, type, heading, rows) {
|
|
16928
|
-
const topicPath =
|
|
17297
|
+
const topicPath = path7.join(memoryDir, `${type}.md`);
|
|
16929
17298
|
const lines = [];
|
|
16930
17299
|
lines.push(`# ${heading}`);
|
|
16931
17300
|
lines.push("");
|
|
@@ -16966,16 +17335,16 @@ function writeTopicFile(memoryDir, type, heading, rows) {
|
|
|
16966
17335
|
lines.push("---");
|
|
16967
17336
|
lines.push("");
|
|
16968
17337
|
}
|
|
16969
|
-
|
|
17338
|
+
fs7.writeFileSync(topicPath, lines.join(`
|
|
16970
17339
|
`), "utf-8");
|
|
16971
17340
|
}
|
|
16972
17341
|
function generateMemoryDigest(projectDir, config2) {
|
|
16973
17342
|
const result = { written: false, path: "", counts: {} };
|
|
16974
17343
|
if (typeof projectDir !== "string" || !projectDir)
|
|
16975
17344
|
return result;
|
|
16976
|
-
const memoryDir =
|
|
16977
|
-
const dbPath =
|
|
16978
|
-
if (!
|
|
17345
|
+
const memoryDir = path7.join(projectDir, ".opencode", "memory");
|
|
17346
|
+
const dbPath = path7.join(memoryDir, "memory.db");
|
|
17347
|
+
if (!fs7.existsSync(dbPath)) {
|
|
16979
17348
|
return result;
|
|
16980
17349
|
}
|
|
16981
17350
|
const compactMode = config2?.compact_mode !== false;
|
|
@@ -17040,14 +17409,14 @@ function generateMemoryDigest(projectDir, config2) {
|
|
|
17040
17409
|
sections.push("*No observations found in memory database.*");
|
|
17041
17410
|
sections.push("");
|
|
17042
17411
|
}
|
|
17043
|
-
const digestPath =
|
|
17412
|
+
const digestPath = path7.join(memoryDir, "_digest.md");
|
|
17044
17413
|
const content = sections.join(`
|
|
17045
17414
|
`);
|
|
17046
17415
|
try {
|
|
17047
|
-
if (!
|
|
17048
|
-
|
|
17416
|
+
if (!fs7.existsSync(memoryDir)) {
|
|
17417
|
+
fs7.mkdirSync(memoryDir, { recursive: true });
|
|
17049
17418
|
}
|
|
17050
|
-
|
|
17419
|
+
fs7.writeFileSync(digestPath, content, "utf-8");
|
|
17051
17420
|
result.written = true;
|
|
17052
17421
|
result.path = digestPath;
|
|
17053
17422
|
} catch {}
|
|
@@ -17061,8 +17430,8 @@ function formatDigestLog(result) {
|
|
|
17061
17430
|
return `[CliKit:memory-digest] Generated digest: ${parts || "empty"}`;
|
|
17062
17431
|
}
|
|
17063
17432
|
// src/hooks/todo-beads-sync.ts
|
|
17064
|
-
import * as
|
|
17065
|
-
import * as
|
|
17433
|
+
import * as fs8 from "fs";
|
|
17434
|
+
import * as path8 from "path";
|
|
17066
17435
|
import { Database as Database2 } from "bun:sqlite";
|
|
17067
17436
|
import { execFile } from "child_process";
|
|
17068
17437
|
import { promisify } from "util";
|
|
@@ -17217,8 +17586,8 @@ function syncTodosToBeads(projectDirectory, sessionID, todos, config2) {
|
|
|
17217
17586
|
skippedReason: "Todo sync disabled; Beads is authoritative"
|
|
17218
17587
|
};
|
|
17219
17588
|
}
|
|
17220
|
-
const beadsDbPath =
|
|
17221
|
-
if (!
|
|
17589
|
+
const beadsDbPath = path8.join(projectDirectory, ".beads", "beads.db");
|
|
17590
|
+
if (!fs8.existsSync(beadsDbPath)) {
|
|
17222
17591
|
return {
|
|
17223
17592
|
synced: false,
|
|
17224
17593
|
sessionID,
|
|
@@ -17248,7 +17617,7 @@ function syncTodosToBeads(projectDirectory, sessionID, todos, config2) {
|
|
|
17248
17617
|
throw lastError instanceof Error ? lastError : new Error("Todo-Beads sync failed after retries");
|
|
17249
17618
|
}
|
|
17250
17619
|
function flushBeadsJsonl(projectDirectory, result) {
|
|
17251
|
-
const jsonlPath =
|
|
17620
|
+
const jsonlPath = path8.join(projectDirectory, ".beads", "issues.jsonl");
|
|
17252
17621
|
execFileAsync("bd", ["export", "--force", "-o", jsonlPath], {
|
|
17253
17622
|
cwd: projectDirectory,
|
|
17254
17623
|
timeout: 5000
|
|
@@ -17265,8 +17634,8 @@ function formatTodoBeadsSyncLog(result) {
|
|
|
17265
17634
|
return `[CliKit:todo-beads-sync] session=${result.sessionID} todos=${result.totalTodos} created=${result.created} updated=${result.updated} closed=${result.closed}`;
|
|
17266
17635
|
}
|
|
17267
17636
|
// src/hooks/beads-context.ts
|
|
17268
|
-
import * as
|
|
17269
|
-
import * as
|
|
17637
|
+
import * as fs9 from "fs";
|
|
17638
|
+
import * as path9 from "path";
|
|
17270
17639
|
import { Database as Database3 } from "bun:sqlite";
|
|
17271
17640
|
var BEADS_CONTEXT_BUSY_TIMEOUT_MS = 2000;
|
|
17272
17641
|
var PRIORITY_LABELS = {
|
|
@@ -17282,8 +17651,8 @@ var STATUS_ICONS = {
|
|
|
17282
17651
|
closed: "\u2713"
|
|
17283
17652
|
};
|
|
17284
17653
|
function openBeadsDbReadonly(projectDirectory) {
|
|
17285
|
-
const beadsDbPath =
|
|
17286
|
-
if (!
|
|
17654
|
+
const beadsDbPath = path9.join(projectDirectory, ".beads", "beads.db");
|
|
17655
|
+
if (!fs9.existsSync(beadsDbPath)) {
|
|
17287
17656
|
return null;
|
|
17288
17657
|
}
|
|
17289
17658
|
try {
|
|
@@ -17440,8 +17809,8 @@ function shouldAttemptTilthForTool(toolName, toolInput) {
|
|
|
17440
17809
|
const normalized = toolName.toLowerCase();
|
|
17441
17810
|
if (!normalized.includes("read"))
|
|
17442
17811
|
return false;
|
|
17443
|
-
const
|
|
17444
|
-
return typeof
|
|
17812
|
+
const path10 = extractFilePath(toolInput);
|
|
17813
|
+
return typeof path10 === "string" && path10.length > 0;
|
|
17445
17814
|
}
|
|
17446
17815
|
function extractFilePath(toolInput) {
|
|
17447
17816
|
for (const key of ["filePath", "file_path", "path", "file"]) {
|
|
@@ -17527,12 +17896,12 @@ import { execFile as execFile2 } from "child_process";
|
|
|
17527
17896
|
import { promisify as promisify2 } from "util";
|
|
17528
17897
|
|
|
17529
17898
|
// src/tools/memory-db.ts
|
|
17530
|
-
import * as
|
|
17531
|
-
import * as
|
|
17899
|
+
import * as fs10 from "fs";
|
|
17900
|
+
import * as path10 from "path";
|
|
17532
17901
|
import { Database as Database4 } from "bun:sqlite";
|
|
17533
17902
|
function getMemoryPaths(projectDir = process.cwd()) {
|
|
17534
|
-
const memoryDir =
|
|
17535
|
-
const memoryDbPath =
|
|
17903
|
+
const memoryDir = path10.join(projectDir, ".opencode", "memory");
|
|
17904
|
+
const memoryDbPath = path10.join(memoryDir, "memory.db");
|
|
17536
17905
|
return { memoryDir, memoryDbPath };
|
|
17537
17906
|
}
|
|
17538
17907
|
function ensureObservationSchema(db) {
|
|
@@ -17594,8 +17963,8 @@ function ensureObservationSchema(db) {
|
|
|
17594
17963
|
function openMemoryDb(options2 = {}) {
|
|
17595
17964
|
const { projectDir, readonly: readonly2 = false } = options2;
|
|
17596
17965
|
const { memoryDir, memoryDbPath } = getMemoryPaths(projectDir);
|
|
17597
|
-
if (!readonly2 && !
|
|
17598
|
-
|
|
17966
|
+
if (!readonly2 && !fs10.existsSync(memoryDir)) {
|
|
17967
|
+
fs10.mkdirSync(memoryDir, { recursive: true });
|
|
17599
17968
|
}
|
|
17600
17969
|
const db = new Database4(memoryDbPath, readonly2 ? { readonly: true } : undefined);
|
|
17601
17970
|
if (!readonly2) {
|
|
@@ -17953,6 +18322,49 @@ function buildSummary(sections, maxTokens) {
|
|
|
17953
18322
|
|
|
17954
18323
|
// src/index.ts
|
|
17955
18324
|
var execFileAsync3 = promisify3(execFile3);
|
|
18325
|
+
var DCP_PLUGIN_ENTRY2 = "@tarquinen/opencode-dcp@beta";
|
|
18326
|
+
var DCP_PLUGIN_BASE = "@tarquinen/opencode-dcp";
|
|
18327
|
+
function ensureDcpInConfig() {
|
|
18328
|
+
try {
|
|
18329
|
+
const configDir = (() => {
|
|
18330
|
+
if (process.env.OPENCODE_CONFIG_DIR)
|
|
18331
|
+
return process.env.OPENCODE_CONFIG_DIR;
|
|
18332
|
+
const home = (() => {
|
|
18333
|
+
if (process.env.SNAP_REAL_HOME)
|
|
18334
|
+
return process.env.SNAP_REAL_HOME;
|
|
18335
|
+
const h = os3.homedir();
|
|
18336
|
+
const m = h.match(/^(\/home\/[^/]+)\/snap\//);
|
|
18337
|
+
return m ? m[1] : h;
|
|
18338
|
+
})();
|
|
18339
|
+
if (process.platform === "win32") {
|
|
18340
|
+
return path11.join(process.env.APPDATA || path11.join(home, "AppData", "Roaming"), "opencode");
|
|
18341
|
+
}
|
|
18342
|
+
return path11.join(process.env.XDG_CONFIG_HOME || path11.join(home, ".config"), "opencode");
|
|
18343
|
+
})();
|
|
18344
|
+
const jsoncPath = path11.join(configDir, "opencode.jsonc");
|
|
18345
|
+
const jsonPath = path11.join(configDir, "opencode.json");
|
|
18346
|
+
const configPath = fs11.existsSync(jsoncPath) ? jsoncPath : jsonPath;
|
|
18347
|
+
if (!fs11.existsSync(configPath))
|
|
18348
|
+
return;
|
|
18349
|
+
const raw = fs11.readFileSync(configPath, "utf-8");
|
|
18350
|
+
let config2;
|
|
18351
|
+
try {
|
|
18352
|
+
config2 = JSON.parse(raw);
|
|
18353
|
+
} catch {
|
|
18354
|
+
const cleaned = raw.replace(/\/\*[\s\S]*?\*\//g, "").replace(/,\s*([}\]])/g, "$1");
|
|
18355
|
+
config2 = JSON.parse(cleaned);
|
|
18356
|
+
}
|
|
18357
|
+
const plugins = Array.isArray(config2.plugin) ? config2.plugin.filter((p) => typeof p === "string") : [];
|
|
18358
|
+
const hasDcp = plugins.some((p) => p === DCP_PLUGIN_BASE || p.startsWith(`${DCP_PLUGIN_BASE}@`));
|
|
18359
|
+
if (hasDcp)
|
|
18360
|
+
return;
|
|
18361
|
+
const updated = upsertPluginEntry(plugins, DCP_PLUGIN_ENTRY2);
|
|
18362
|
+
const tmpPath = `${configPath}.tmp`;
|
|
18363
|
+
fs11.writeFileSync(tmpPath, JSON.stringify({ ...config2, plugin: updated }, null, 2) + `
|
|
18364
|
+
`);
|
|
18365
|
+
fs11.renameSync(tmpPath, configPath);
|
|
18366
|
+
} catch {}
|
|
18367
|
+
}
|
|
17956
18368
|
var CliKitPlugin = async (ctx) => {
|
|
17957
18369
|
const todosBySession = new Map;
|
|
17958
18370
|
const defaultMcpEntries = {
|
|
@@ -18209,6 +18621,7 @@ ${(content || "").trim()}`.trim();
|
|
|
18209
18621
|
].join(`
|
|
18210
18622
|
`);
|
|
18211
18623
|
}
|
|
18624
|
+
ensureDcpInConfig();
|
|
18212
18625
|
const pluginConfig = loadCliKitConfig(ctx.directory) ?? {};
|
|
18213
18626
|
const debugLogsEnabled = pluginConfig.hooks?.session_logging === true && process.env.CLIKIT_DEBUG === "1";
|
|
18214
18627
|
const toolLogsEnabled = pluginConfig.hooks?.tool_logging === true && process.env.CLIKIT_DEBUG === "1";
|