@zcy2nn/agent-forge 1.1.0 → 1.1.1

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * A custom skill bundled in this repository.
3
- * Unlike npx-installed skills, these are copied from src/skills/ to the OpenCode skills directory
3
+ * Built-in skills are read directly from the package at runtime (no file copy needed).
4
4
  */
5
5
  export interface CustomSkill {
6
6
  /** Skill name (folder name) */
@@ -16,14 +16,3 @@ export interface CustomSkill {
16
16
  * Registry of custom skills bundled in this repository.
17
17
  */
18
18
  export declare const CUSTOM_SKILLS: CustomSkill[];
19
- /**
20
- * Get the target directory for custom skills installation.
21
- */
22
- export declare function getCustomSkillsDir(): string;
23
- /**
24
- * Install a custom skill by copying from src/skills/ to the OpenCode skills directory
25
- * @param skill - The custom skill to install
26
- * @param projectRoot - Root directory of agent-forge project
27
- * @returns True if installation succeeded, false otherwise
28
- */
29
- export declare function installCustomSkill(skill: CustomSkill): boolean;
package/dist/cli/index.js CHANGED
@@ -13,14 +13,14 @@ import * as path from "node:path";
13
13
 
14
14
  // src/cli/config-io.ts
15
15
  import {
16
- copyFileSync as copyFileSync2,
17
- existsSync as existsSync3,
16
+ copyFileSync,
17
+ existsSync as existsSync2,
18
18
  readFileSync,
19
19
  renameSync,
20
- statSync as statSync2,
20
+ statSync,
21
21
  writeFileSync
22
22
  } from "node:fs";
23
- import { dirname as dirname3, join as join3 } from "node:path";
23
+ import { dirname as dirname2, join as join2 } from "node:path";
24
24
 
25
25
  // src/cli/paths.ts
26
26
  import { existsSync, mkdirSync } from "node:fs";
@@ -390,15 +390,6 @@ var DEFAULT_AGENT_MCPS = {
390
390
  };
391
391
 
392
392
  // src/cli/custom-skills.ts
393
- import {
394
- copyFileSync,
395
- existsSync as existsSync2,
396
- mkdirSync as mkdirSync2,
397
- readdirSync,
398
- statSync
399
- } from "node:fs";
400
- import { dirname as dirname2, join as join2 } from "node:path";
401
- import { fileURLToPath } from "node:url";
402
393
  var CUSTOM_SKILLS = [
403
394
  {
404
395
  name: "simplify",
@@ -491,45 +482,6 @@ var CUSTOM_SKILLS = [
491
482
  sourcePath: "src/skills/writing-skills"
492
483
  }
493
484
  ];
494
- function getCustomSkillsDir() {
495
- return join2(getConfigDir(), "skills");
496
- }
497
- function copyDirRecursive(src, dest) {
498
- if (!existsSync2(dest)) {
499
- mkdirSync2(dest, { recursive: true });
500
- }
501
- const entries = readdirSync(src);
502
- for (const entry of entries) {
503
- const srcPath = join2(src, entry);
504
- const destPath = join2(dest, entry);
505
- const stat = statSync(srcPath);
506
- if (stat.isDirectory()) {
507
- copyDirRecursive(srcPath, destPath);
508
- } else {
509
- const destDir = dirname2(destPath);
510
- if (!existsSync2(destDir)) {
511
- mkdirSync2(destDir, { recursive: true });
512
- }
513
- copyFileSync(srcPath, destPath);
514
- }
515
- }
516
- }
517
- function installCustomSkill(skill) {
518
- try {
519
- const packageRoot = fileURLToPath(new URL("../..", import.meta.url));
520
- const sourcePath = join2(packageRoot, skill.sourcePath);
521
- const targetPath = join2(getCustomSkillsDir(), skill.name);
522
- if (!existsSync2(sourcePath)) {
523
- console.error(`Custom skill source not found: ${sourcePath}`);
524
- return false;
525
- }
526
- copyDirRecursive(sourcePath, targetPath);
527
- return true;
528
- } catch (error) {
529
- console.error(`Failed to install custom skill: ${skill.name}`, error);
530
- return false;
531
- }
532
- }
533
485
 
534
486
  // src/cli/skills.ts
535
487
  import { spawnSync } from "node:child_process";
@@ -642,7 +594,7 @@ function generateLiteConfig(installConfig) {
642
594
  ...RECOMMENDED_SKILLS.filter((s) => s.allowedAgents.includes("*") || s.allowedAgents.includes(agentName)).map((s) => s.skillName),
643
595
  ...CUSTOM_SKILLS.filter((s) => s.allowedAgents.includes("*") || s.allowedAgents.includes(agentName)).map((s) => s.name)
644
596
  ];
645
- if (agentName === "implementer" && !skills.includes("agent-browser")) {
597
+ if (installConfig.installSkills && agentName === "implementer" && !skills.includes("agent-browser")) {
646
598
  skills.push("agent-browser");
647
599
  }
648
600
  return {
@@ -696,10 +648,10 @@ function normalizePathForMatch(path) {
696
648
  return path.replaceAll("\\", "/");
697
649
  }
698
650
  function findPackageRoot(startPath) {
699
- let currentPath = dirname3(startPath);
651
+ let currentPath = dirname2(startPath);
700
652
  while (true) {
701
- const packageJsonPath = join3(currentPath, "package.json");
702
- if (existsSync3(packageJsonPath)) {
653
+ const packageJsonPath = join2(currentPath, "package.json");
654
+ if (existsSync2(packageJsonPath)) {
703
655
  try {
704
656
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
705
657
  if (packageJson.name === PACKAGE_NAME) {
@@ -707,7 +659,7 @@ function findPackageRoot(startPath) {
707
659
  }
708
660
  } catch {}
709
661
  }
710
- const parentPath = dirname3(currentPath);
662
+ const parentPath = dirname2(currentPath);
711
663
  if (parentPath === currentPath) {
712
664
  return null;
713
665
  }
@@ -722,8 +674,8 @@ function isLocalPackageRootEntry(entry) {
722
674
  if (!entry || entry.startsWith("file://")) {
723
675
  return false;
724
676
  }
725
- const packageJsonPath = join3(entry, "package.json");
726
- if (!existsSync3(packageJsonPath)) {
677
+ const packageJsonPath = join2(entry, "package.json");
678
+ if (!existsSync2(packageJsonPath)) {
727
679
  return false;
728
680
  }
729
681
  try {
@@ -762,9 +714,9 @@ function stripJsonComments(json) {
762
714
  }
763
715
  function parseConfigFile(path) {
764
716
  try {
765
- if (!existsSync3(path))
717
+ if (!existsSync2(path))
766
718
  return { config: null };
767
- const stat = statSync2(path);
719
+ const stat = statSync(path);
768
720
  if (stat.size === 0)
769
721
  return { config: null };
770
722
  const content = readFileSync(path, "utf-8");
@@ -793,8 +745,8 @@ function writeConfig(configPath, config) {
793
745
  const bakPath = `${configPath}.bak`;
794
746
  const content = `${JSON.stringify(config, null, 2)}
795
747
  `;
796
- if (existsSync3(configPath)) {
797
- copyFileSync2(configPath, bakPath);
748
+ if (existsSync2(configPath)) {
749
+ copyFileSync(configPath, bakPath);
798
750
  }
799
751
  writeFileSync(tmpPath, content);
800
752
  renameSync(tmpPath, configPath);
@@ -880,8 +832,8 @@ function writeLiteConfig(installConfig, targetPath) {
880
832
  const bakPath = `${configPath}.bak`;
881
833
  const content = `${JSON.stringify(config, null, 2)}
882
834
  `;
883
- if (existsSync3(configPath)) {
884
- copyFileSync2(configPath, bakPath);
835
+ if (existsSync2(configPath)) {
836
+ copyFileSync(configPath, bakPath);
885
837
  }
886
838
  writeFileSync(tmpPath, content);
887
839
  renameSync(tmpPath, configPath);
@@ -1256,11 +1208,11 @@ Options:
1256
1208
  }
1257
1209
 
1258
1210
  // src/cli/install.ts
1259
- import { existsSync as existsSync5 } from "node:fs";
1211
+ import { existsSync as existsSync4 } from "node:fs";
1260
1212
  import { createInterface } from "node:readline/promises";
1261
1213
  // src/cli/system.ts
1262
1214
  import { spawnSync as spawnSync2 } from "node:child_process";
1263
- import { statSync as statSync4 } from "node:fs";
1215
+ import { statSync as statSync3 } from "node:fs";
1264
1216
 
1265
1217
  // src/utils/compat.ts
1266
1218
  import { spawn as nodeSpawn } from "node:child_process";
@@ -1381,7 +1333,7 @@ function resolveOpenCodePath() {
1381
1333
  if (opencodePath === "opencode")
1382
1334
  continue;
1383
1335
  try {
1384
- const stat = statSync4(opencodePath);
1336
+ const stat = statSync3(opencodePath);
1385
1337
  if (stat.isFile()) {
1386
1338
  cachedOpenCodePath = opencodePath;
1387
1339
  return opencodePath;
@@ -1532,8 +1484,6 @@ async function runInstall(config) {
1532
1484
  let totalSteps = 6;
1533
1485
  if (config.installSkills)
1534
1486
  totalSteps += 1;
1535
- if (config.installCustomSkills)
1536
- totalSteps += 1;
1537
1487
  let step = 1;
1538
1488
  printStep(step++, totalSteps, "Checking OpenCode installation...");
1539
1489
  if (config.dryRun) {
@@ -1587,7 +1537,7 @@ ${JSON.stringify(liteConfig, null, 2)}
1587
1537
  `);
1588
1538
  } else {
1589
1539
  const configPath2 = getExistingLiteConfigPath();
1590
- const configExists = existsSync5(configPath2);
1540
+ const configExists = existsSync4(configPath2);
1591
1541
  if (configExists && !config.reset) {
1592
1542
  printInfo(`Configuration already exists at ${configPath2}. Use --reset to overwrite.`);
1593
1543
  } else {
@@ -1616,28 +1566,8 @@ ${JSON.stringify(liteConfig, null, 2)}
1616
1566
  }
1617
1567
  printSuccess(`${skillsInstalled}/${RECOMMENDED_SKILLS.length} skills processed`);
1618
1568
  }
1619
- }
1620
- if (config.installCustomSkills) {
1621
- printStep(step++, totalSteps, "Installing custom skills...");
1622
- if (config.dryRun) {
1623
- printInfo("Dry run mode - would install custom skills:");
1624
- for (const skill of CUSTOM_SKILLS) {
1625
- printInfo(` - ${skill.name}`);
1626
- }
1627
- } else {
1628
- let customSkillsInstalled = 0;
1629
- for (const skill of CUSTOM_SKILLS) {
1630
- printInfo(`Installing ${skill.name}...`);
1631
- if (installCustomSkill(skill)) {
1632
- printSuccess(`Installed: ${skill.name}`);
1633
- customSkillsInstalled++;
1634
- } else {
1635
- printInfo(`Skipped: ${skill.name} (already installed)`);
1636
- }
1637
- }
1638
- const totalCustom = CUSTOM_SKILLS.length;
1639
- printSuccess(`${customSkillsInstalled}/${totalCustom} custom skills processed`);
1640
- }
1569
+ } else {
1570
+ printInfo("Recommended skills (e.g. agent-browser) not installed. Use --skills=yes to install them.");
1641
1571
  }
1642
1572
  const statusMsg = isUpdate ? "Configuration updated!" : "Installation complete!";
1643
1573
  console.log(`${SYMBOLS.star} ${BOLD}${GREEN}${statusMsg}${RESET}`);
@@ -1674,7 +1604,6 @@ async function install(args) {
1674
1604
  const config = {
1675
1605
  hasTmux: false,
1676
1606
  installSkills: args.skills === "yes",
1677
- installCustomSkills: args.skills === "yes",
1678
1607
  preset: args.preset,
1679
1608
  promptForStar: args.tui,
1680
1609
  dryRun: args.dryRun,
@@ -1696,7 +1625,7 @@ function getGeneratedPresetNames2() {
1696
1625
  function parseArgs(args) {
1697
1626
  const result = {
1698
1627
  tui: true,
1699
- skills: "yes"
1628
+ skills: "no"
1700
1629
  };
1701
1630
  for (const arg of args) {
1702
1631
  if (arg === "--no-tui") {
@@ -1730,7 +1659,7 @@ Usage:
1730
1659
  bunx @zcy2nn/agent-forge doctor [OPTIONS]
1731
1660
 
1732
1661
  Options:
1733
- --skills=yes|no Install recommended and bundled skills (default: yes)
1662
+ --skills=yes|no Install recommended skills like agent-browser (default: no)
1734
1663
  --preset=<name> Active generated config preset (default: openai)
1735
1664
  --no-tui Non-interactive mode
1736
1665
  --dry-run Simulate install without writing files
@@ -15,7 +15,6 @@ export interface OpenCodeConfig {
15
15
  export interface InstallConfig {
16
16
  hasTmux: boolean;
17
17
  installSkills: boolean;
18
- installCustomSkills: boolean;
19
18
  preset?: string;
20
19
  promptForStar?: boolean;
21
20
  dryRun?: boolean;
@@ -1,7 +1,8 @@
1
1
  /**
2
- * Filter available_skills block based on the current agent's permission.skill rules.
3
- * OpenCode core injects `<available_skills>` globally, so this hook rewrites that
4
- * block before the prompt is sent.
2
+ * Filter and inject available_skills block based on the current agent's permission.skill rules.
3
+ * OpenCode core injects `<available_skills>` from installed skills, so this hook rewrites that
4
+ * block before the prompt is sent. Built-in skills from the package are also injected so they
5
+ * are always visible even without being copied to the OpenCode skills directory.
5
6
  */
6
7
  import type { PluginInput } from '@opencode-ai/plugin';
7
8
  import { type PluginConfig } from '../../config';
@@ -19,6 +20,14 @@ interface MessageWithParts {
19
20
  parts: MessagePart[];
20
21
  }
21
22
  type SkillRule = 'allow' | 'ask' | 'deny';
23
+ interface SkillEntry {
24
+ name: string;
25
+ block: string;
26
+ }
27
+ /**
28
+ * Merge installed skill entries with built-in entries (dedup by name, installed takes precedence).
29
+ */
30
+ declare function mergeWithBuiltinSkills(installedEntries: SkillEntry[]): SkillEntry[];
22
31
  declare function filterAvailableSkillsText(text: string, permissionRules: Record<string, SkillRule>): string;
23
32
  /**
24
33
  * Creates the experimental.chat.messages.transform hook for filtering available skills.
@@ -29,4 +38,4 @@ export declare function createFilterAvailableSkillsHook(_ctx: PluginInput, confi
29
38
  messages: MessageWithParts[];
30
39
  }) => Promise<void>;
31
40
  };
32
- export { filterAvailableSkillsText };
41
+ export { filterAvailableSkillsText, mergeWithBuiltinSkills };
package/dist/index.js CHANGED
@@ -18150,14 +18150,14 @@ var require_turndown_cjs = __commonJS((exports, module) => {
18150
18150
  } else if (node.nodeType === 1) {
18151
18151
  replacement = replacementForNode.call(self, node);
18152
18152
  }
18153
- return join15(output, replacement);
18153
+ return join14(output, replacement);
18154
18154
  }, "");
18155
18155
  }
18156
18156
  function postProcess(output) {
18157
18157
  var self = this;
18158
18158
  this.rules.forEach(function(rule) {
18159
18159
  if (typeof rule.append === "function") {
18160
- output = join15(output, rule.append(self.options));
18160
+ output = join14(output, rule.append(self.options));
18161
18161
  }
18162
18162
  });
18163
18163
  return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
@@ -18170,7 +18170,7 @@ var require_turndown_cjs = __commonJS((exports, module) => {
18170
18170
  content = content.trim();
18171
18171
  return whitespace.leading + rule.replacement(content, node, this.options) + whitespace.trailing;
18172
18172
  }
18173
- function join15(output, replacement) {
18173
+ function join14(output, replacement) {
18174
18174
  var s1 = trimTrailingNewlines(output);
18175
18175
  var s2 = trimLeadingNewlines(replacement);
18176
18176
  var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
@@ -18185,38 +18185,6 @@ var require_turndown_cjs = __commonJS((exports, module) => {
18185
18185
  module.exports = TurndownService;
18186
18186
  });
18187
18187
 
18188
- // src/cli/custom-skills.ts
18189
- import { dirname as dirname2, join as join2 } from "node:path";
18190
-
18191
- // src/cli/paths.ts
18192
- import { homedir } from "node:os";
18193
- import { dirname, join } from "node:path";
18194
- function getDefaultOpenCodeConfigDir() {
18195
- const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join(homedir(), ".config");
18196
- return join(userConfigDir, "opencode");
18197
- }
18198
- function getCustomOpenCodeConfigDir() {
18199
- const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
18200
- return configDir || undefined;
18201
- }
18202
- function getConfigDir() {
18203
- const customConfigDir = getCustomOpenCodeConfigDir();
18204
- if (customConfigDir) {
18205
- return customConfigDir;
18206
- }
18207
- return getDefaultOpenCodeConfigDir();
18208
- }
18209
- function getConfigSearchDirs() {
18210
- const dirs = [getCustomOpenCodeConfigDir(), getDefaultOpenCodeConfigDir()];
18211
- return dirs.filter((dir, index) => {
18212
- return Boolean(dir) && dirs.indexOf(dir) === index;
18213
- });
18214
- }
18215
- function getOpenCodeConfigPaths() {
18216
- const configDir = getDefaultOpenCodeConfigDir();
18217
- return [join(configDir, "opencode.json"), join(configDir, "opencode.jsonc")];
18218
- }
18219
-
18220
18188
  // src/cli/custom-skills.ts
18221
18189
  var CUSTOM_SKILLS = [
18222
18190
  {
@@ -18310,9 +18278,6 @@ var CUSTOM_SKILLS = [
18310
18278
  sourcePath: "src/skills/writing-skills"
18311
18279
  }
18312
18280
  ];
18313
- function getCustomSkillsDir() {
18314
- return join2(getConfigDir(), "skills");
18315
- }
18316
18281
 
18317
18282
  // src/cli/skills.ts
18318
18283
  var RECOMMENDED_SKILLS = [
@@ -18474,6 +18439,28 @@ var CouncilConfigSchema = z.object({
18474
18439
  import * as fs from "node:fs";
18475
18440
  import * as path from "node:path";
18476
18441
 
18442
+ // src/cli/paths.ts
18443
+ import { homedir } from "node:os";
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
+ }
18463
+
18477
18464
  // src/config/agent-mcps.ts
18478
18465
  var DEFAULT_AGENT_MCPS = {
18479
18466
  orchestrator: ["*", "!context7"],
@@ -22810,6 +22797,19 @@ ${buildRetryGuidance(detected)}`;
22810
22797
  // src/hooks/filter-available-skills/index.ts
22811
22798
  var AVAILABLE_SKILLS_BLOCK_REGEX = /<available_skills>\s*([\s\S]*?)\s*<\/available_skills>/g;
22812
22799
  var SKILL_NAME_REGEX = /<name>([^<]+)<\/name>/;
22800
+ function builtinSkillBlock(name, description) {
22801
+ return `<skill>
22802
+ <name>${name}</name>
22803
+ <description>${description}</description>
22804
+ <location>builtin</location>
22805
+ </skill>`;
22806
+ }
22807
+ function getBuiltinSkillEntries() {
22808
+ return CUSTOM_SKILLS.map((skill) => ({
22809
+ name: skill.name,
22810
+ block: builtinSkillBlock(skill.name, skill.description)
22811
+ }));
22812
+ }
22813
22813
  function getCurrentAgent(messages) {
22814
22814
  for (let index = messages.length - 1;index >= 0; index -= 1) {
22815
22815
  const message = messages[index];
@@ -22842,9 +22842,21 @@ function isSkillAllowed(skillName, permissionRules) {
22842
22842
  }
22843
22843
  return permissionRules["*"] === "allow";
22844
22844
  }
22845
+ function mergeWithBuiltinSkills(installedEntries) {
22846
+ const builtinEntries = getBuiltinSkillEntries();
22847
+ const installedNames = new Set(installedEntries.map((e) => e.name));
22848
+ for (const entry of builtinEntries) {
22849
+ if (!installedNames.has(entry.name)) {
22850
+ installedEntries.push(entry);
22851
+ }
22852
+ }
22853
+ return installedEntries;
22854
+ }
22845
22855
  function filterAvailableSkillsText(text, permissionRules) {
22846
22856
  return text.replace(AVAILABLE_SKILLS_BLOCK_REGEX, (_fullMatch, blockContent) => {
22847
- const allowedEntries = extractSkillEntries(blockContent).filter((entry) => isSkillAllowed(entry.name, permissionRules));
22857
+ let allEntries = extractSkillEntries(blockContent);
22858
+ allEntries = mergeWithBuiltinSkills(allEntries);
22859
+ const allowedEntries = allEntries.filter((entry) => isSkillAllowed(entry.name, permissionRules));
22848
22860
  if (allowedEntries.length === 0) {
22849
22861
  return `<available_skills>
22850
22862
  No skills available.
@@ -22856,6 +22868,22 @@ ${allowedEntries.map((entry) => entry.block).join(`
22856
22868
  </available_skills>`;
22857
22869
  });
22858
22870
  }
22871
+ function injectBuiltinSkillsIfMissing(text, permissionRules) {
22872
+ if (text.includes("<available_skills>")) {
22873
+ return text;
22874
+ }
22875
+ const builtinEntries = getBuiltinSkillEntries();
22876
+ const allowedEntries = builtinEntries.filter((entry) => isSkillAllowed(entry.name, permissionRules));
22877
+ if (allowedEntries.length === 0) {
22878
+ return text;
22879
+ }
22880
+ const block = `<available_skills>
22881
+ ${allowedEntries.map((entry) => entry.block).join(`
22882
+ `)}
22883
+ </available_skills>`;
22884
+ return `${text}
22885
+ ${block}`;
22886
+ }
22859
22887
  function createFilterAvailableSkillsHook(_ctx, config) {
22860
22888
  const permissionRulesByAgent = new Map;
22861
22889
  const getPermissionRules = (agentName) => {
@@ -22878,10 +22906,14 @@ function createFilterAvailableSkillsHook(_ctx, config) {
22878
22906
  const permissionRules = getPermissionRules(agentName);
22879
22907
  for (const message of messages) {
22880
22908
  for (const part of message.parts) {
22881
- if (part.type !== "text" || !part.text || !part.text.includes("<available_skills>")) {
22909
+ if (part.type !== "text" || !part.text) {
22882
22910
  continue;
22883
22911
  }
22884
- part.text = filterAvailableSkillsText(part.text, permissionRules);
22912
+ if (part.text.includes("<available_skills>")) {
22913
+ part.text = filterAvailableSkillsText(part.text, permissionRules);
22914
+ } else {
22915
+ part.text = injectBuiltinSkillsIfMissing(part.text, permissionRules);
22916
+ }
22885
22917
  }
22886
22918
  }
22887
22919
  }
@@ -23123,7 +23155,7 @@ import {
23123
23155
  unlinkSync as unlinkSync2,
23124
23156
  writeFileSync as writeFileSync3
23125
23157
  } from "node:fs";
23126
- import { basename as basename2, extname, join as join8 } from "node:path";
23158
+ import { basename as basename2, extname, join as join7 } from "node:path";
23127
23159
  var lastCleanupByDir = new Map;
23128
23160
  var CLEANUP_INTERVAL = 10 * 60 * 1000;
23129
23161
  function isImagePart(p) {
@@ -23171,7 +23203,7 @@ function cleanupAllSessions(saveDir) {
23171
23203
  const dirsToScan = [];
23172
23204
  try {
23173
23205
  for (const entry of readdirSync2(saveDir, { withFileTypes: true })) {
23174
- const fp = join8(saveDir, entry.name);
23206
+ const fp = join7(saveDir, entry.name);
23175
23207
  if (entry.isDirectory()) {
23176
23208
  dirsToScan.push(fp);
23177
23209
  } else {
@@ -23188,7 +23220,7 @@ function cleanupAllSessions(saveDir) {
23188
23220
  let allRemoved = true;
23189
23221
  for (const f of readdirSync2(dir)) {
23190
23222
  isEmpty = false;
23191
- const fp = join8(dir, f);
23223
+ const fp = join7(dir, f);
23192
23224
  try {
23193
23225
  if (now - statSync3(fp).mtimeMs > maxAge) {
23194
23226
  unlinkSync2(fp);
@@ -23210,7 +23242,7 @@ function cleanupAllSessions(saveDir) {
23210
23242
  function writeUniqueFile(dir, name, data, log2) {
23211
23243
  const ext = extname(name);
23212
23244
  const base = basename2(name, ext) || name;
23213
- let candidate = join8(dir, name);
23245
+ let candidate = join7(dir, name);
23214
23246
  if (existsSync5(candidate)) {
23215
23247
  return candidate;
23216
23248
  }
@@ -23223,7 +23255,7 @@ function writeUniqueFile(dir, name, data, log2) {
23223
23255
  } catch (e) {
23224
23256
  if (e instanceof Error && e.code === "EEXIST") {
23225
23257
  counter += 1;
23226
- candidate = join8(dir, `${base}-${counter}${ext}`);
23258
+ candidate = join7(dir, `${base}-${counter}${ext}`);
23227
23259
  continue;
23228
23260
  }
23229
23261
  log2(`[image-hook] failed to save image: ${e}`);
@@ -23247,13 +23279,13 @@ function processImageAttachments(args) {
23247
23279
  messagesWithImages.push({ msg, imageParts });
23248
23280
  }
23249
23281
  }
23250
- const saveDir = join8(workDir, ".opencode", "images");
23282
+ const saveDir = join7(workDir, ".opencode", "images");
23251
23283
  if (messagesWithImages.length === 0) {
23252
23284
  if (existsSync5(saveDir))
23253
23285
  cleanupAllSessions(saveDir);
23254
23286
  return;
23255
23287
  }
23256
- const gitignorePath = join8(workDir, ".opencode", ".gitignore");
23288
+ const gitignorePath = join7(workDir, ".opencode", ".gitignore");
23257
23289
  try {
23258
23290
  mkdirSync3(saveDir, { recursive: true });
23259
23291
  if (!existsSync5(gitignorePath))
@@ -23265,7 +23297,7 @@ function processImageAttachments(args) {
23265
23297
  cleanupAllSessions(saveDir);
23266
23298
  for (const { msg, imageParts } of messagesWithImages) {
23267
23299
  const sessionSubdir = msg.info.sessionID ? sanitizeFilename(msg.info.sessionID) : undefined;
23268
- const targetDir = sessionSubdir ? join8(saveDir, sessionSubdir) : saveDir;
23300
+ const targetDir = sessionSubdir ? join7(saveDir, sessionSubdir) : saveDir;
23269
23301
  try {
23270
23302
  mkdirSync3(targetDir, { recursive: true });
23271
23303
  } catch (e) {
@@ -29236,13 +29268,13 @@ import { existsSync as existsSync9 } from "node:fs";
29236
29268
  // src/tools/ast-grep/constants.ts
29237
29269
  import { existsSync as existsSync8, statSync as statSync4 } from "node:fs";
29238
29270
  import { createRequire as createRequire3 } from "node:module";
29239
- import { dirname as dirname7, join as join12 } from "node:path";
29271
+ import { dirname as dirname6, join as join11 } from "node:path";
29240
29272
 
29241
29273
  // src/tools/ast-grep/downloader.ts
29242
29274
  import { chmodSync, existsSync as existsSync7, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4 } from "node:fs";
29243
29275
  import { createRequire as createRequire2 } from "node:module";
29244
29276
  import { homedir as homedir5 } from "node:os";
29245
- import { join as join11 } from "node:path";
29277
+ import { join as join10 } from "node:path";
29246
29278
  var REPO = "ast-grep/ast-grep";
29247
29279
  var DEFAULT_VERSION = "0.40.0";
29248
29280
  function getAstGrepVersion() {
@@ -29266,18 +29298,18 @@ var PLATFORM_MAP = {
29266
29298
  function getCacheDir2() {
29267
29299
  if (process.platform === "win32") {
29268
29300
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
29269
- const base2 = localAppData || join11(homedir5(), "AppData", "Local");
29270
- return join11(base2, "agent-forge", "bin");
29301
+ const base2 = localAppData || join10(homedir5(), "AppData", "Local");
29302
+ return join10(base2, "agent-forge", "bin");
29271
29303
  }
29272
29304
  const xdgCache = process.env.XDG_CACHE_HOME;
29273
- const base = xdgCache || join11(homedir5(), ".cache");
29274
- return join11(base, "agent-forge", "bin");
29305
+ const base = xdgCache || join10(homedir5(), ".cache");
29306
+ return join10(base, "agent-forge", "bin");
29275
29307
  }
29276
29308
  function getBinaryName() {
29277
29309
  return process.platform === "win32" ? "sg.exe" : "sg";
29278
29310
  }
29279
29311
  function getCachedBinaryPath() {
29280
- const binaryPath = join11(getCacheDir2(), getBinaryName());
29312
+ const binaryPath = join10(getCacheDir2(), getBinaryName());
29281
29313
  return existsSync7(binaryPath) ? binaryPath : null;
29282
29314
  }
29283
29315
  async function downloadAstGrep(version = DEFAULT_VERSION) {
@@ -29289,7 +29321,7 @@ async function downloadAstGrep(version = DEFAULT_VERSION) {
29289
29321
  }
29290
29322
  const cacheDir = getCacheDir2();
29291
29323
  const binaryName = getBinaryName();
29292
- const binaryPath = join11(cacheDir, binaryName);
29324
+ const binaryPath = join10(cacheDir, binaryName);
29293
29325
  if (existsSync7(binaryPath)) {
29294
29326
  return binaryPath;
29295
29327
  }
@@ -29305,7 +29337,7 @@ async function downloadAstGrep(version = DEFAULT_VERSION) {
29305
29337
  if (!response.ok) {
29306
29338
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
29307
29339
  }
29308
- const archivePath = join11(cacheDir, assetName);
29340
+ const archivePath = join10(cacheDir, assetName);
29309
29341
  const arrayBuffer = await response.arrayBuffer();
29310
29342
  await crossWrite(archivePath, arrayBuffer);
29311
29343
  await extractZip(archivePath, cacheDir);
@@ -29393,8 +29425,8 @@ function findSgCliPathSync() {
29393
29425
  try {
29394
29426
  const require2 = createRequire3(import.meta.url);
29395
29427
  const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
29396
- const cliDir = dirname7(cliPkgPath);
29397
- const sgPath = join12(cliDir, binaryName);
29428
+ const cliDir = dirname6(cliPkgPath);
29429
+ const sgPath = join11(cliDir, binaryName);
29398
29430
  if (existsSync8(sgPath) && isValidBinary(sgPath)) {
29399
29431
  return sgPath;
29400
29432
  }
@@ -29404,9 +29436,9 @@ function findSgCliPathSync() {
29404
29436
  try {
29405
29437
  const require2 = createRequire3(import.meta.url);
29406
29438
  const pkgPath = require2.resolve(`${platformPkg}/package.json`);
29407
- const pkgDir = dirname7(pkgPath);
29439
+ const pkgDir = dirname6(pkgPath);
29408
29440
  const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
29409
- const binaryPath = join12(pkgDir, astGrepName);
29441
+ const binaryPath = join11(pkgDir, astGrepName);
29410
29442
  if (existsSync8(binaryPath) && isValidBinary(binaryPath)) {
29411
29443
  return binaryPath;
29412
29444
  }
@@ -30073,16 +30105,12 @@ Usage: /preset <name> to switch.`);
30073
30105
  }
30074
30106
  // src/tools/skill.ts
30075
30107
  import { existsSync as existsSync10, readFileSync as readFileSync5 } from "node:fs";
30076
- import { join as join14 } from "node:path";
30108
+ import { join as join13 } from "node:path";
30077
30109
  import { tool as tool4 } from "@opencode-ai/plugin/tool";
30078
30110
  var z5 = tool4.schema;
30079
30111
  function resolveSkillPath(skillName) {
30080
- const installedPath = join14(getCustomSkillsDir(), skillName, "SKILL.md");
30081
- if (existsSync10(installedPath)) {
30082
- return installedPath;
30083
- }
30084
- const packageRoot = join14(import.meta.dirname, "..", "..");
30085
- const bundledPath = join14(packageRoot, "src", "skills", skillName, "SKILL.md");
30112
+ const packageRoot = join13(import.meta.dirname, "..", "..");
30113
+ const bundledPath = join13(packageRoot, "src", "skills", skillName, "SKILL.md");
30086
30114
  if (existsSync10(bundledPath)) {
30087
30115
  return bundledPath;
30088
30116
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zcy2nn/agent-forge",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Lightweight agent orchestration plugin for OpenCode - a slimmed-down fork of oh-my-opencode",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",