agentsys 5.0.3 → 5.1.0
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/.claude-plugin/marketplace.json +21 -14
- package/.claude-plugin/plugin.json +1 -1
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +18 -0
- package/README.md +7 -6
- package/adapters/codex/skills/agnix/SKILL.md +0 -1
- package/adapters/codex/skills/audit-project/SKILL.md +0 -1
- package/adapters/codex/skills/audit-project-agents/SKILL.md +0 -1
- package/adapters/codex/skills/audit-project-github/SKILL.md +0 -1
- package/adapters/codex/skills/consult/SKILL.md +132 -57
- package/adapters/codex/skills/debate/SKILL.md +214 -0
- package/adapters/codex/skills/delivery-approval/SKILL.md +0 -1
- package/adapters/codex/skills/deslop/SKILL.md +0 -1
- package/adapters/codex/skills/drift-detect/SKILL.md +0 -1
- package/adapters/codex/skills/enhance/SKILL.md +0 -1
- package/adapters/codex/skills/learn/SKILL.md +0 -1
- package/adapters/codex/skills/next-task/SKILL.md +0 -1
- package/adapters/codex/skills/perf/SKILL.md +0 -1
- package/adapters/codex/skills/repo-map/SKILL.md +0 -1
- package/adapters/codex/skills/ship/SKILL.md +0 -1
- package/adapters/codex/skills/ship-ci-review-loop/SKILL.md +0 -1
- package/adapters/codex/skills/ship-deployment/SKILL.md +0 -1
- package/adapters/codex/skills/ship-error-handling/SKILL.md +0 -1
- package/adapters/codex/skills/sync-docs/SKILL.md +0 -1
- package/adapters/opencode/agents/agent-enhancer.md +0 -1
- package/adapters/opencode/agents/agnix-agent.md +0 -1
- package/adapters/opencode/agents/ci-fixer.md +0 -1
- package/adapters/opencode/agents/ci-monitor.md +0 -1
- package/adapters/opencode/agents/claudemd-enhancer.md +0 -1
- package/adapters/opencode/agents/consult-agent.md +122 -30
- package/adapters/opencode/agents/cross-file-enhancer.md +0 -1
- package/adapters/opencode/agents/debate-orchestrator.md +169 -0
- package/adapters/opencode/agents/delivery-validator.md +0 -1
- package/adapters/opencode/agents/deslop-agent.md +0 -1
- package/adapters/opencode/agents/docs-enhancer.md +0 -1
- package/adapters/opencode/agents/exploration-agent.md +0 -1
- package/adapters/opencode/agents/hooks-enhancer.md +0 -1
- package/adapters/opencode/agents/implementation-agent.md +0 -1
- package/adapters/opencode/agents/learn-agent.md +0 -1
- package/adapters/opencode/agents/map-validator.md +0 -1
- package/adapters/opencode/agents/perf-analyzer.md +0 -1
- package/adapters/opencode/agents/perf-code-paths.md +0 -1
- package/adapters/opencode/agents/perf-investigation-logger.md +0 -1
- package/adapters/opencode/agents/perf-orchestrator.md +0 -1
- package/adapters/opencode/agents/perf-theory-gatherer.md +0 -1
- package/adapters/opencode/agents/perf-theory-tester.md +0 -1
- package/adapters/opencode/agents/plan-synthesizer.md +0 -1
- package/adapters/opencode/agents/planning-agent.md +0 -1
- package/adapters/opencode/agents/plugin-enhancer.md +0 -1
- package/adapters/opencode/agents/prompt-enhancer.md +0 -1
- package/adapters/opencode/agents/simple-fixer.md +0 -1
- package/adapters/opencode/agents/skills-enhancer.md +0 -1
- package/adapters/opencode/agents/sync-docs-agent.md +0 -1
- package/adapters/opencode/agents/task-discoverer.md +0 -1
- package/adapters/opencode/agents/test-coverage-checker.md +0 -1
- package/adapters/opencode/agents/worktree-manager.md +0 -1
- package/adapters/opencode/commands/agnix.md +0 -1
- package/adapters/opencode/commands/audit-project-agents.md +0 -1
- package/adapters/opencode/commands/audit-project-github.md +0 -1
- package/adapters/opencode/commands/audit-project.md +0 -1
- package/adapters/opencode/commands/consult.md +133 -57
- package/adapters/opencode/commands/debate.md +224 -0
- package/adapters/opencode/commands/delivery-approval.md +0 -1
- package/adapters/opencode/commands/deslop.md +0 -1
- package/adapters/opencode/commands/drift-detect.md +0 -1
- package/adapters/opencode/commands/enhance.md +0 -1
- package/adapters/opencode/commands/learn.md +0 -1
- package/adapters/opencode/commands/next-task.md +0 -1
- package/adapters/opencode/commands/perf.md +0 -1
- package/adapters/opencode/commands/repo-map.md +0 -1
- package/adapters/opencode/commands/ship-ci-review-loop.md +0 -1
- package/adapters/opencode/commands/ship-deployment.md +0 -1
- package/adapters/opencode/commands/ship-error-handling.md +0 -1
- package/adapters/opencode/commands/ship.md +0 -1
- package/adapters/opencode/commands/sync-docs.md +0 -1
- package/adapters/opencode/skills/agnix/SKILL.md +1 -2
- package/adapters/opencode/skills/consult/SKILL.md +33 -23
- package/adapters/opencode/skills/debate/SKILL.md +245 -0
- package/adapters/opencode/skills/deslop/SKILL.md +1 -2
- package/adapters/opencode/skills/discover-tasks/SKILL.md +1 -2
- package/adapters/opencode/skills/drift-analysis/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-agent-prompts/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-claude-memory/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-cross-file/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-docs/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-hooks/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-orchestrator/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-plugins/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-prompts/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-skills/SKILL.md +1 -2
- package/adapters/opencode/skills/learn/SKILL.md +1 -2
- package/adapters/opencode/skills/orchestrate-review/SKILL.md +0 -1
- package/adapters/opencode/skills/perf-analyzer/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-baseline-manager/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-benchmarker/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-code-paths/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-investigation-logger/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-profiler/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-theory-gatherer/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-theory-tester/SKILL.md +1 -2
- package/adapters/opencode/skills/repo-mapping/SKILL.md +1 -2
- package/adapters/opencode/skills/sync-docs/SKILL.md +1 -2
- package/adapters/opencode/skills/validate-delivery/SKILL.md +1 -2
- package/lib/adapter-transforms.js +24 -4
- package/package.json +1 -1
- package/plugins/agnix/.claude-plugin/plugin.json +1 -1
- package/plugins/agnix/skills/agnix/SKILL.md +1 -1
- package/plugins/audit-project/.claude-plugin/plugin.json +1 -1
- package/plugins/audit-project/lib/adapter-transforms.js +24 -4
- package/plugins/consult/.claude-plugin/plugin.json +1 -1
- package/plugins/consult/agents/consult-agent.md +122 -29
- package/plugins/consult/commands/consult.md +135 -58
- package/plugins/consult/skills/consult/SKILL.md +31 -20
- package/plugins/debate/.claude-plugin/plugin.json +21 -0
- package/plugins/debate/agents/debate-orchestrator.md +175 -0
- package/plugins/debate/commands/debate.md +221 -0
- package/plugins/debate/lib/adapter-transforms.js +298 -0
- package/plugins/debate/lib/collectors/codebase.js +392 -0
- package/plugins/debate/lib/collectors/docs-patterns.js +713 -0
- package/plugins/debate/lib/collectors/documentation.js +219 -0
- package/plugins/debate/lib/collectors/github.js +330 -0
- package/plugins/debate/lib/collectors/index.js +126 -0
- package/plugins/debate/lib/config/index.js +14 -0
- package/plugins/debate/lib/cross-platform/index.js +539 -0
- package/plugins/debate/lib/discovery/index.js +352 -0
- package/plugins/debate/lib/drift-detect/collectors.js +37 -0
- package/plugins/debate/lib/enhance/agent-analyzer.js +421 -0
- package/plugins/debate/lib/enhance/agent-patterns.js +571 -0
- package/plugins/debate/lib/enhance/auto-suppression.js +622 -0
- package/plugins/debate/lib/enhance/benchmark.js +417 -0
- package/plugins/debate/lib/enhance/cross-file-analyzer.js +930 -0
- package/plugins/debate/lib/enhance/cross-file-patterns.js +370 -0
- package/plugins/debate/lib/enhance/docs-analyzer.js +325 -0
- package/plugins/debate/lib/enhance/docs-patterns.js +671 -0
- package/plugins/debate/lib/enhance/fixer.js +721 -0
- package/plugins/debate/lib/enhance/hook-analyzer.js +135 -0
- package/plugins/debate/lib/enhance/hook-patterns.js +40 -0
- package/plugins/debate/lib/enhance/index.js +127 -0
- package/plugins/debate/lib/enhance/plugin-analyzer.js +402 -0
- package/plugins/debate/lib/enhance/plugin-patterns.js +326 -0
- package/plugins/debate/lib/enhance/projectmemory-analyzer.js +551 -0
- package/plugins/debate/lib/enhance/projectmemory-patterns.js +617 -0
- package/plugins/debate/lib/enhance/prompt-analyzer.js +457 -0
- package/plugins/debate/lib/enhance/prompt-patterns.js +1484 -0
- package/plugins/debate/lib/enhance/reporter.js +1348 -0
- package/plugins/debate/lib/enhance/security-patterns.js +284 -0
- package/plugins/debate/lib/enhance/skill-analyzer.js +182 -0
- package/plugins/debate/lib/enhance/skill-patterns.js +147 -0
- package/plugins/debate/lib/enhance/suppression.js +352 -0
- package/plugins/debate/lib/enhance/tool-patterns.js +373 -0
- package/plugins/debate/lib/index.js +270 -0
- package/plugins/debate/lib/patterns/cli-enhancers.js +611 -0
- package/plugins/debate/lib/patterns/pipeline.js +948 -0
- package/plugins/debate/lib/patterns/review-patterns.js +558 -0
- package/plugins/debate/lib/patterns/slop-analyzers.js +2305 -0
- package/plugins/debate/lib/patterns/slop-patterns.js +1187 -0
- package/plugins/debate/lib/perf/analyzer/index.js +22 -0
- package/plugins/debate/lib/perf/argument-parser.js +105 -0
- package/plugins/debate/lib/perf/baseline-comparator.js +50 -0
- package/plugins/debate/lib/perf/baseline-store.js +127 -0
- package/plugins/debate/lib/perf/benchmark-runner.js +404 -0
- package/plugins/debate/lib/perf/breaking-point-finder.js +52 -0
- package/plugins/debate/lib/perf/breaking-point-runner.js +60 -0
- package/plugins/debate/lib/perf/checkpoint.js +123 -0
- package/plugins/debate/lib/perf/code-paths.js +86 -0
- package/plugins/debate/lib/perf/consolidation.js +37 -0
- package/plugins/debate/lib/perf/constraint-runner.js +71 -0
- package/plugins/debate/lib/perf/experiment-runner.js +32 -0
- package/plugins/debate/lib/perf/index.js +41 -0
- package/plugins/debate/lib/perf/investigation-state.js +874 -0
- package/plugins/debate/lib/perf/optimization-runner.js +79 -0
- package/plugins/debate/lib/perf/profilers/go.js +22 -0
- package/plugins/debate/lib/perf/profilers/index.js +46 -0
- package/plugins/debate/lib/perf/profilers/java.js +23 -0
- package/plugins/debate/lib/perf/profilers/node.js +27 -0
- package/plugins/debate/lib/perf/profilers/python.js +23 -0
- package/plugins/debate/lib/perf/profilers/rust.js +23 -0
- package/plugins/debate/lib/perf/profiling-runner.js +75 -0
- package/plugins/debate/lib/perf/schemas.js +140 -0
- package/plugins/debate/lib/platform/detect-platform.js +413 -0
- package/plugins/debate/lib/platform/detection-configs.js +93 -0
- package/plugins/debate/lib/platform/state-dir.js +132 -0
- package/plugins/debate/lib/platform/verify-tools.js +182 -0
- package/plugins/debate/lib/repo-map/cache.js +152 -0
- package/plugins/debate/lib/repo-map/concurrency.js +29 -0
- package/plugins/debate/lib/repo-map/index.js +222 -0
- package/plugins/debate/lib/repo-map/installer.js +212 -0
- package/plugins/debate/lib/repo-map/queries/go.js +27 -0
- package/plugins/debate/lib/repo-map/queries/index.js +100 -0
- package/plugins/debate/lib/repo-map/queries/java.js +38 -0
- package/plugins/debate/lib/repo-map/queries/javascript.js +55 -0
- package/plugins/debate/lib/repo-map/queries/python.js +24 -0
- package/plugins/debate/lib/repo-map/queries/rust.js +73 -0
- package/plugins/debate/lib/repo-map/queries/typescript.js +38 -0
- package/plugins/debate/lib/repo-map/runner.js +1364 -0
- package/plugins/debate/lib/repo-map/updater.js +562 -0
- package/plugins/debate/lib/repo-map/usage-analyzer.js +407 -0
- package/plugins/debate/lib/schemas/plugin-manifest.schema.json +57 -0
- package/plugins/debate/lib/schemas/validator.js +247 -0
- package/plugins/debate/lib/sources/custom-handler.js +199 -0
- package/plugins/debate/lib/sources/policy-questions.js +246 -0
- package/plugins/debate/lib/sources/source-cache.js +165 -0
- package/plugins/debate/lib/state/workflow-state.js +576 -0
- package/plugins/debate/lib/types/agent-frontmatter.d.ts +134 -0
- package/plugins/debate/lib/types/command-frontmatter.d.ts +107 -0
- package/plugins/debate/lib/types/hook-frontmatter.d.ts +115 -0
- package/plugins/debate/lib/types/index.d.ts +84 -0
- package/plugins/debate/lib/types/plugin-manifest.d.ts +102 -0
- package/plugins/debate/lib/types/skill-frontmatter.d.ts +89 -0
- package/plugins/debate/lib/utils/atomic-write.js +94 -0
- package/plugins/debate/lib/utils/cache-manager.js +159 -0
- package/plugins/debate/lib/utils/command-parser.js +0 -0
- package/plugins/debate/lib/utils/context-optimizer.js +300 -0
- package/plugins/debate/lib/utils/deprecation.js +37 -0
- package/plugins/debate/lib/utils/shell-escape.js +88 -0
- package/plugins/debate/lib/utils/state-helpers.js +61 -0
- package/plugins/debate/skills/debate/SKILL.md +264 -0
- package/plugins/deslop/.claude-plugin/plugin.json +1 -1
- package/plugins/deslop/lib/adapter-transforms.js +24 -4
- package/plugins/deslop/skills/deslop/SKILL.md +1 -1
- package/plugins/drift-detect/.claude-plugin/plugin.json +1 -1
- package/plugins/drift-detect/lib/adapter-transforms.js +24 -4
- package/plugins/drift-detect/skills/drift-analysis/SKILL.md +1 -1
- package/plugins/enhance/.claude-plugin/plugin.json +1 -1
- package/plugins/enhance/lib/adapter-transforms.js +24 -4
- package/plugins/enhance/skills/enhance-agent-prompts/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-claude-memory/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-cross-file/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-docs/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-hooks/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-orchestrator/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-plugins/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-prompts/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-skills/SKILL.md +1 -1
- package/plugins/learn/.claude-plugin/plugin.json +1 -1
- package/plugins/learn/agents/learn-agent.md +1 -1
- package/plugins/learn/lib/adapter-transforms.js +24 -4
- package/plugins/learn/skills/learn/SKILL.md +1 -1
- package/plugins/next-task/.claude-plugin/plugin.json +1 -1
- package/plugins/next-task/agents/exploration-agent.md +1 -1
- package/plugins/next-task/lib/adapter-transforms.js +24 -4
- package/plugins/next-task/skills/discover-tasks/SKILL.md +1 -1
- package/plugins/next-task/skills/validate-delivery/SKILL.md +1 -1
- package/plugins/perf/.claude-plugin/plugin.json +1 -1
- package/plugins/perf/lib/adapter-transforms.js +24 -4
- package/plugins/perf/skills/perf-analyzer/SKILL.md +1 -1
- package/plugins/perf/skills/perf-baseline-manager/SKILL.md +1 -1
- package/plugins/perf/skills/perf-benchmarker/SKILL.md +1 -1
- package/plugins/perf/skills/perf-code-paths/SKILL.md +1 -1
- package/plugins/perf/skills/perf-investigation-logger/SKILL.md +1 -1
- package/plugins/perf/skills/perf-profiler/SKILL.md +1 -1
- package/plugins/perf/skills/perf-theory-gatherer/SKILL.md +1 -1
- package/plugins/perf/skills/perf-theory-tester/SKILL.md +1 -1
- package/plugins/repo-map/.claude-plugin/plugin.json +1 -1
- package/plugins/repo-map/lib/adapter-transforms.js +24 -4
- package/plugins/ship/.claude-plugin/plugin.json +1 -1
- package/plugins/ship/lib/adapter-transforms.js +24 -4
- package/plugins/sync-docs/.claude-plugin/plugin.json +1 -1
- package/plugins/sync-docs/lib/adapter-transforms.js +24 -4
- package/plugins/sync-docs/skills/sync-docs/SKILL.md +1 -1
- package/scripts/gen-adapters.js +6 -7
- package/scripts/generate-docs.js +4 -2
- package/scripts/plugins.txt +1 -0
- package/site/content.json +6 -6
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-Platform Best Practices Library
|
|
3
|
+
*
|
|
4
|
+
* Patterns and utilities for building tools that work across:
|
|
5
|
+
* - Claude Code (Anthropic)
|
|
6
|
+
* - OpenCode (multi-model)
|
|
7
|
+
* - Codex CLI (OpenAI)
|
|
8
|
+
*
|
|
9
|
+
* Based on research from official documentation:
|
|
10
|
+
* - Anthropic Claude 4 Best Practices
|
|
11
|
+
* - OpenCode CLI Documentation
|
|
12
|
+
* - Codex CLI Skills and MCP Integration
|
|
13
|
+
* - MCP Specification (2025-11-25)
|
|
14
|
+
*
|
|
15
|
+
* @module cross-platform
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const path = require('path');
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const os = require('os');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Compare semver strings (e.g., "3.9.0" vs "3.10.0")
|
|
24
|
+
* @param {string} a - First version
|
|
25
|
+
* @param {string} b - Second version
|
|
26
|
+
* @returns {number} -1 if a < b, 1 if a > b, 0 if equal
|
|
27
|
+
*/
|
|
28
|
+
function compareSemver(a, b) {
|
|
29
|
+
const partsA = a.split('.').map(n => parseInt(n, 10) || 0);
|
|
30
|
+
const partsB = b.split('.').map(n => parseInt(n, 10) || 0);
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
33
|
+
const numA = partsA[i] || 0;
|
|
34
|
+
const numB = partsB[i] || 0;
|
|
35
|
+
if (numA < numB) return -1;
|
|
36
|
+
if (numA > numB) return 1;
|
|
37
|
+
}
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Platform detection and configuration
|
|
43
|
+
*/
|
|
44
|
+
const PLATFORMS = {
|
|
45
|
+
CLAUDE_CODE: 'claude-code',
|
|
46
|
+
OPENCODE: 'opencode',
|
|
47
|
+
CODEX_CLI: 'codex-cli'
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* State directory by platform
|
|
52
|
+
* Each platform uses its own directory to avoid conflicts
|
|
53
|
+
*/
|
|
54
|
+
const STATE_DIRS = {
|
|
55
|
+
[PLATFORMS.CLAUDE_CODE]: '.claude',
|
|
56
|
+
[PLATFORMS.OPENCODE]: '.opencode',
|
|
57
|
+
[PLATFORMS.CODEX_CLI]: '.codex'
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get the state directory for the current platform
|
|
62
|
+
* Uses AI_STATE_DIR env var if set, otherwise defaults to .claude
|
|
63
|
+
*
|
|
64
|
+
* @returns {string} State directory name
|
|
65
|
+
*/
|
|
66
|
+
function getStateDir() {
|
|
67
|
+
return process.env.AI_STATE_DIR || STATE_DIRS[PLATFORMS.CLAUDE_CODE];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Detect current platform from environment
|
|
72
|
+
*
|
|
73
|
+
* @returns {string} Platform identifier
|
|
74
|
+
*/
|
|
75
|
+
function detectPlatform() {
|
|
76
|
+
const stateDir = process.env.AI_STATE_DIR;
|
|
77
|
+
if (stateDir === '.opencode') return PLATFORMS.OPENCODE;
|
|
78
|
+
if (stateDir === '.codex') return PLATFORMS.CODEX_CLI;
|
|
79
|
+
return PLATFORMS.CLAUDE_CODE;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get plugin root directory (works across all platforms)
|
|
84
|
+
*
|
|
85
|
+
* Search order:
|
|
86
|
+
* 1. PLUGIN_ROOT env var (MCP mode)
|
|
87
|
+
* 2. Search plugin installation directories
|
|
88
|
+
*
|
|
89
|
+
* @param {string} pluginName - Plugin name (e.g., 'enhance')
|
|
90
|
+
* @returns {string} Plugin root path or null if not found
|
|
91
|
+
*/
|
|
92
|
+
function getPluginRoot(pluginName = 'enhance') {
|
|
93
|
+
// Try environment variable first (MCP mode)
|
|
94
|
+
if (process.env.PLUGIN_ROOT) {
|
|
95
|
+
return process.env.PLUGIN_ROOT;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Try to find in plugin cache
|
|
99
|
+
const stateDir = getStateDir();
|
|
100
|
+
const home = os.homedir();
|
|
101
|
+
|
|
102
|
+
// Search pattern: ~/.{stateDir}/plugins/cache/agentsys/{pluginName}/{version}
|
|
103
|
+
const searchPaths = [
|
|
104
|
+
path.join(home, stateDir, 'plugins', 'cache', 'agentsys', pluginName),
|
|
105
|
+
path.join(home, stateDir, 'plugins', 'agentsys', pluginName)
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
for (const searchPath of searchPaths) {
|
|
109
|
+
if (fs.existsSync(searchPath)) {
|
|
110
|
+
// Find latest version directory
|
|
111
|
+
const versions = fs.readdirSync(searchPath).filter(v => {
|
|
112
|
+
return fs.statSync(path.join(searchPath, v)).isDirectory();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (versions.length > 0) {
|
|
116
|
+
// Sort by semver and take latest
|
|
117
|
+
const latest = versions.sort(compareSemver).reverse()[0];
|
|
118
|
+
return path.join(searchPath, latest);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get path to enhance suppressions file
|
|
128
|
+
*
|
|
129
|
+
* @returns {string} Path to suppressions.json in state directory
|
|
130
|
+
*/
|
|
131
|
+
function getSuppressionPath() {
|
|
132
|
+
const stateDir = getStateDir();
|
|
133
|
+
const home = os.homedir();
|
|
134
|
+
return path.join(home, stateDir, 'enhance', 'suppressions.json');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* MCP Tool Schema Best Practices
|
|
139
|
+
*
|
|
140
|
+
* Guidelines for cross-platform tool definitions:
|
|
141
|
+
* 1. Use descriptive, semantic names (workflow_status not ws)
|
|
142
|
+
* 2. Keep descriptions concise (<100 chars) for token efficiency
|
|
143
|
+
* 3. Use flat parameter structures when possible
|
|
144
|
+
* 4. Include enums for constrained values
|
|
145
|
+
* 5. Make parameters optional with sensible defaults
|
|
146
|
+
*/
|
|
147
|
+
const TOOL_SCHEMA_GUIDELINES = {
|
|
148
|
+
// Max description length for token efficiency
|
|
149
|
+
maxDescriptionLength: 100,
|
|
150
|
+
|
|
151
|
+
// Naming conventions
|
|
152
|
+
namingPattern: /^[a-z][a-z0-9_]*$/,
|
|
153
|
+
|
|
154
|
+
// Parameter best practices
|
|
155
|
+
preferFlatStructures: true,
|
|
156
|
+
useEnumsForConstraints: true,
|
|
157
|
+
documentDefaults: true
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Create a tool definition following cross-platform best practices
|
|
162
|
+
*
|
|
163
|
+
* @param {string} name - Tool name (snake_case)
|
|
164
|
+
* @param {string} description - Concise description
|
|
165
|
+
* @param {Object} properties - Input schema properties
|
|
166
|
+
* @param {string[]} required - Required property names
|
|
167
|
+
* @returns {Object} MCP-compatible tool definition
|
|
168
|
+
*/
|
|
169
|
+
function createToolDefinition(name, description, properties = {}, required = []) {
|
|
170
|
+
// Validate name
|
|
171
|
+
if (!TOOL_SCHEMA_GUIDELINES.namingPattern.test(name)) {
|
|
172
|
+
console.warn(`Tool name "${name}" should be snake_case`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Warn if description too long
|
|
176
|
+
if (description.length > TOOL_SCHEMA_GUIDELINES.maxDescriptionLength) {
|
|
177
|
+
console.warn(`Tool "${name}" description exceeds ${TOOL_SCHEMA_GUIDELINES.maxDescriptionLength} chars`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
name,
|
|
182
|
+
description,
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: 'object',
|
|
185
|
+
properties,
|
|
186
|
+
required
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Error Response Patterns
|
|
193
|
+
*
|
|
194
|
+
* MCP uses isError flag for application errors, NOT JSON-RPC error codes.
|
|
195
|
+
* Error messages should be actionable so AI can recover.
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Create a success response
|
|
200
|
+
*
|
|
201
|
+
* @param {*} data - Response data (will be JSON stringified if object)
|
|
202
|
+
* @returns {Object} MCP content response
|
|
203
|
+
*/
|
|
204
|
+
function successResponse(data) {
|
|
205
|
+
const text = typeof data === 'object' ? JSON.stringify(data, null, 2) : String(data);
|
|
206
|
+
return {
|
|
207
|
+
content: [{ type: 'text', text }]
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Create an error response with actionable message
|
|
213
|
+
*
|
|
214
|
+
* @param {string} message - Error message (should suggest recovery)
|
|
215
|
+
* @param {Object} details - Optional additional details
|
|
216
|
+
* @returns {Object} MCP error response
|
|
217
|
+
*/
|
|
218
|
+
function errorResponse(message, details = null) {
|
|
219
|
+
let text = `Error: ${message}`;
|
|
220
|
+
if (details) {
|
|
221
|
+
text += `\nDetails: ${JSON.stringify(details)}`;
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
content: [{ type: 'text', text }],
|
|
225
|
+
isError: true
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Create an error response for missing tool
|
|
231
|
+
*
|
|
232
|
+
* @param {string} name - Tool name that was requested
|
|
233
|
+
* @param {string[]} available - List of available tools
|
|
234
|
+
* @returns {Object} MCP error response
|
|
235
|
+
*/
|
|
236
|
+
function unknownToolResponse(name, available = []) {
|
|
237
|
+
let text = `Error: Unknown tool "${name}"`;
|
|
238
|
+
if (available.length > 0) {
|
|
239
|
+
text += `\nAvailable tools: ${available.join(', ')}`;
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
content: [{ type: 'text', text }],
|
|
243
|
+
isError: true
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Prompt Formatting for Cross-Model Compatibility
|
|
249
|
+
*
|
|
250
|
+
* Different models have different preferences:
|
|
251
|
+
* - Claude: Trained with XML tags, follows instructions literally
|
|
252
|
+
* - GPT-4: Prefers Markdown, more flexible interpretation
|
|
253
|
+
*
|
|
254
|
+
* For maximum compatibility, use both:
|
|
255
|
+
* - Markdown headers for major sections
|
|
256
|
+
* - XML tags for data blocks
|
|
257
|
+
*/
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Format structured data for cross-model prompts
|
|
261
|
+
*
|
|
262
|
+
* @param {string} tag - XML-style tag name
|
|
263
|
+
* @param {string} content - Content to wrap
|
|
264
|
+
* @returns {string} Formatted content block
|
|
265
|
+
*/
|
|
266
|
+
function formatBlock(tag, content) {
|
|
267
|
+
return `<${tag}>\n${content}\n</${tag}>`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Format a list of items for prompts
|
|
272
|
+
*
|
|
273
|
+
* @param {string[]} items - Items to format
|
|
274
|
+
* @param {boolean} numbered - Use numbered list
|
|
275
|
+
* @returns {string} Formatted list
|
|
276
|
+
*/
|
|
277
|
+
function formatList(items, numbered = false) {
|
|
278
|
+
return items.map((item, i) => {
|
|
279
|
+
const prefix = numbered ? `${i + 1}.` : '-';
|
|
280
|
+
return `${prefix} ${item}`;
|
|
281
|
+
}).join('\n');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Create an agent prompt section with cross-model formatting
|
|
286
|
+
*
|
|
287
|
+
* @param {string} title - Section title
|
|
288
|
+
* @param {string} content - Section content
|
|
289
|
+
* @returns {string} Formatted section
|
|
290
|
+
*/
|
|
291
|
+
function formatSection(title, content) {
|
|
292
|
+
return `## ${title}\n\n${content}\n`;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Token Efficiency Strategies
|
|
297
|
+
*
|
|
298
|
+
* Key insights from research:
|
|
299
|
+
* - MCP tools can consume 50K+ tokens before conversation starts
|
|
300
|
+
* - Concise descriptions reduce overhead by 60%+
|
|
301
|
+
* - Consolidate similar tools (one tool with filter vs many tools)
|
|
302
|
+
* - Return minimal structured JSON, not verbose text
|
|
303
|
+
*/
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Truncate text to limit with ellipsis
|
|
307
|
+
*
|
|
308
|
+
* @param {string} text - Text to truncate
|
|
309
|
+
* @param {number} maxLength - Maximum length
|
|
310
|
+
* @returns {string} Truncated text
|
|
311
|
+
*/
|
|
312
|
+
function truncate(text, maxLength) {
|
|
313
|
+
if (text.length <= maxLength) return text;
|
|
314
|
+
return text.substring(0, maxLength - 3) + '...';
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Create a compact summary of findings/results
|
|
319
|
+
*
|
|
320
|
+
* @param {Array} items - Items to summarize
|
|
321
|
+
* @param {Function} keyFn - Function to extract key from item
|
|
322
|
+
* @param {number} maxItems - Maximum items to include
|
|
323
|
+
* @returns {Object} Compact summary
|
|
324
|
+
*/
|
|
325
|
+
function compactSummary(items, keyFn, maxItems = 10) {
|
|
326
|
+
const limited = items.slice(0, maxItems);
|
|
327
|
+
const truncated = items.length > maxItems;
|
|
328
|
+
|
|
329
|
+
// Group by key
|
|
330
|
+
const groups = {};
|
|
331
|
+
for (const item of limited) {
|
|
332
|
+
const key = keyFn(item);
|
|
333
|
+
groups[key] = (groups[key] || 0) + 1;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return {
|
|
337
|
+
total: items.length,
|
|
338
|
+
showing: limited.length,
|
|
339
|
+
truncated,
|
|
340
|
+
byKey: groups
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Agent Prompt Best Practices
|
|
346
|
+
*
|
|
347
|
+
* Cross-model recommendations:
|
|
348
|
+
* 1. State instructions explicitly - don't rely on inference
|
|
349
|
+
* 2. Put critical constraints at START and END (Lost in Middle)
|
|
350
|
+
* 3. Use imperative language: "Do X", "Never Y"
|
|
351
|
+
* 4. Include 2-3 examples for complex tasks
|
|
352
|
+
* 5. Explicit tool allowlisting
|
|
353
|
+
* 6. Flat state management - pass state each turn
|
|
354
|
+
*/
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Agent prompt template structure
|
|
358
|
+
*/
|
|
359
|
+
const AGENT_TEMPLATE = `# Agent: {name}
|
|
360
|
+
|
|
361
|
+
## Role
|
|
362
|
+
{role}
|
|
363
|
+
|
|
364
|
+
## Instructions
|
|
365
|
+
{instructions}
|
|
366
|
+
|
|
367
|
+
## Tools Available
|
|
368
|
+
{tools}
|
|
369
|
+
If a tool is not listed above, respond with: "Tool not available"
|
|
370
|
+
|
|
371
|
+
## Output Format
|
|
372
|
+
{outputFormat}
|
|
373
|
+
|
|
374
|
+
## Critical Constraints
|
|
375
|
+
{constraints}`;
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Create an agent prompt from template
|
|
379
|
+
*
|
|
380
|
+
* @param {Object} config - Agent configuration
|
|
381
|
+
* @param {string} config.name - Agent name
|
|
382
|
+
* @param {string} config.role - One-sentence role description
|
|
383
|
+
* @param {string[]} config.instructions - Imperative instructions
|
|
384
|
+
* @param {Object[]} config.tools - Available tools {name, description}
|
|
385
|
+
* @param {string} config.outputFormat - Expected output format
|
|
386
|
+
* @param {string[]} config.constraints - Critical constraints (repeated for emphasis)
|
|
387
|
+
* @returns {string} Formatted agent prompt
|
|
388
|
+
*/
|
|
389
|
+
function createAgentPrompt(config) {
|
|
390
|
+
const {
|
|
391
|
+
name,
|
|
392
|
+
role,
|
|
393
|
+
instructions = [],
|
|
394
|
+
tools = [],
|
|
395
|
+
outputFormat = 'Respond with structured JSON',
|
|
396
|
+
constraints = []
|
|
397
|
+
} = config;
|
|
398
|
+
|
|
399
|
+
// Format instructions as numbered list
|
|
400
|
+
const instructionsList = instructions.map((inst, i) => `${i + 1}. ${inst}`).join('\n');
|
|
401
|
+
|
|
402
|
+
// Format tools
|
|
403
|
+
const toolsList = tools.map(t => `- ${t.name}: ${t.description}`).join('\n');
|
|
404
|
+
|
|
405
|
+
// Format constraints (repeated for "Lost in Middle" mitigation)
|
|
406
|
+
const constraintsList = constraints.map(c => `- **${c}**`).join('\n');
|
|
407
|
+
|
|
408
|
+
return AGENT_TEMPLATE
|
|
409
|
+
.replace('{name}', name)
|
|
410
|
+
.replace('{role}', role)
|
|
411
|
+
.replace('{instructions}', instructionsList)
|
|
412
|
+
.replace('{tools}', toolsList)
|
|
413
|
+
.replace('{outputFormat}', outputFormat)
|
|
414
|
+
.replace('{constraints}', constraintsList);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Convert a path to forward slashes (safe for require() on all platforms)
|
|
419
|
+
* Windows paths with backslashes break in require() strings
|
|
420
|
+
*
|
|
421
|
+
* @param {string} p - Path to normalize
|
|
422
|
+
* @returns {string} Path with forward slashes
|
|
423
|
+
*/
|
|
424
|
+
function normalizePathForRequire(p) {
|
|
425
|
+
return p.replace(/\\/g, '/');
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Platform-specific configuration helpers
|
|
430
|
+
*/
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Get OpenCode MCP configuration object
|
|
434
|
+
*
|
|
435
|
+
* @param {string} serverPath - Path to MCP server
|
|
436
|
+
* @param {Object} env - Environment variables
|
|
437
|
+
* @returns {Object} OpenCode config structure
|
|
438
|
+
*/
|
|
439
|
+
function getOpenCodeConfig(serverPath, env = {}) {
|
|
440
|
+
return {
|
|
441
|
+
mcp: {
|
|
442
|
+
'agentsys': {
|
|
443
|
+
type: 'local',
|
|
444
|
+
command: ['node', serverPath],
|
|
445
|
+
environment: {
|
|
446
|
+
PLUGIN_ROOT: path.dirname(path.dirname(serverPath)),
|
|
447
|
+
AI_STATE_DIR: '.opencode',
|
|
448
|
+
...env
|
|
449
|
+
},
|
|
450
|
+
timeout: 10000,
|
|
451
|
+
enabled: true
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Get Codex CLI MCP configuration (TOML format)
|
|
459
|
+
*
|
|
460
|
+
* @param {string} serverPath - Path to MCP server
|
|
461
|
+
* @param {Object} env - Environment variables
|
|
462
|
+
* @returns {string} TOML configuration
|
|
463
|
+
*/
|
|
464
|
+
function getCodexConfig(serverPath, env = {}) {
|
|
465
|
+
const envEntries = Object.entries({
|
|
466
|
+
PLUGIN_ROOT: path.dirname(path.dirname(serverPath)),
|
|
467
|
+
AI_STATE_DIR: '.codex',
|
|
468
|
+
...env
|
|
469
|
+
}).map(([k, v]) => `${k} = "${v}"`).join(', ');
|
|
470
|
+
|
|
471
|
+
return `
|
|
472
|
+
[mcp_servers.agentsys]
|
|
473
|
+
command = "node"
|
|
474
|
+
args = ["${serverPath}"]
|
|
475
|
+
env = { ${envEntries} }
|
|
476
|
+
enabled = true
|
|
477
|
+
`.trim();
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Instruction file conventions by platform
|
|
482
|
+
*/
|
|
483
|
+
const INSTRUCTION_FILES = {
|
|
484
|
+
[PLATFORMS.CLAUDE_CODE]: ['CLAUDE.md', '.claude/CLAUDE.md'],
|
|
485
|
+
[PLATFORMS.OPENCODE]: ['AGENTS.md', 'CLAUDE.md'],
|
|
486
|
+
[PLATFORMS.CODEX_CLI]: ['AGENTS.md', 'AGENTS.override.md']
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Get instruction file paths for current platform
|
|
491
|
+
*
|
|
492
|
+
* @param {string} platform - Platform identifier
|
|
493
|
+
* @returns {string[]} Instruction file paths in precedence order
|
|
494
|
+
*/
|
|
495
|
+
function getInstructionFiles(platform = null) {
|
|
496
|
+
const p = platform || detectPlatform();
|
|
497
|
+
return INSTRUCTION_FILES[p] || INSTRUCTION_FILES[PLATFORMS.CLAUDE_CODE];
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
module.exports = {
|
|
501
|
+
// Platform detection
|
|
502
|
+
PLATFORMS,
|
|
503
|
+
STATE_DIRS,
|
|
504
|
+
getStateDir,
|
|
505
|
+
detectPlatform,
|
|
506
|
+
getPluginRoot,
|
|
507
|
+
getSuppressionPath,
|
|
508
|
+
|
|
509
|
+
// Tool schema
|
|
510
|
+
TOOL_SCHEMA_GUIDELINES,
|
|
511
|
+
createToolDefinition,
|
|
512
|
+
|
|
513
|
+
// Response helpers
|
|
514
|
+
successResponse,
|
|
515
|
+
errorResponse,
|
|
516
|
+
unknownToolResponse,
|
|
517
|
+
|
|
518
|
+
// Prompt formatting
|
|
519
|
+
formatBlock,
|
|
520
|
+
formatList,
|
|
521
|
+
formatSection,
|
|
522
|
+
|
|
523
|
+
// Token efficiency
|
|
524
|
+
truncate,
|
|
525
|
+
compactSummary,
|
|
526
|
+
|
|
527
|
+
// Agent prompts
|
|
528
|
+
AGENT_TEMPLATE,
|
|
529
|
+
createAgentPrompt,
|
|
530
|
+
|
|
531
|
+
// Platform configs
|
|
532
|
+
getOpenCodeConfig,
|
|
533
|
+
getCodexConfig,
|
|
534
|
+
getInstructionFiles,
|
|
535
|
+
INSTRUCTION_FILES,
|
|
536
|
+
|
|
537
|
+
// Path normalization
|
|
538
|
+
normalizePathForRequire
|
|
539
|
+
};
|