@jetrabbits/agentic 0.3.2 → 0.4.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/CHANGELOG.md +21 -0
- package/Makefile +6 -1
- package/README.md +8 -2
- package/agentic +730 -66
- package/docs/agentic-stabilization/README.md +6 -5
- package/docs/agentic-usage.md +20 -3
- package/docs/mcp/README.md +28 -0
- package/docs/opencode_setup.md +12 -2
- package/docs/review-pipeline/examples/instruction-review.example.md +95 -0
- package/docs/review-pipeline/examples/memory-curation.example.md +56 -0
- package/docs/review-pipeline/examples/summary.example.md +18 -0
- package/extensions/opencode/agents/developer.md +1 -1
- package/extensions/opencode/agents/devops-engineer.md +1 -1
- package/extensions/opencode/agents/instruction_reviewer.md +1 -1
- package/extensions/opencode/agents/memory_curator.md +1 -1
- package/extensions/opencode/agents/team-lead.md +1 -1
- package/extensions/opencode/opencode.json +16 -36
- package/extensions/opencode/profiles/githubcopilot/opencode.json +88 -0
- package/extensions/opencode/profiles/openai/opencode.json +100 -0
- package/package.json +1 -1
- package/extensions/opencode/plugins/agent-model-mapper.ts +0 -117
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://opencode.ai/config.json",
|
|
3
|
+
"plugin": [
|
|
4
|
+
"sound-notification",
|
|
5
|
+
"telegram-notification"
|
|
6
|
+
],
|
|
7
|
+
"agent": {
|
|
8
|
+
"product-owner": {
|
|
9
|
+
"description": "Main coordinator for feature development workflow",
|
|
10
|
+
"mode": "primary",
|
|
11
|
+
"model": "openai/gpt-5.5",
|
|
12
|
+
"fallback": [],
|
|
13
|
+
"permission": {
|
|
14
|
+
"task": {
|
|
15
|
+
"pm": "allow",
|
|
16
|
+
"team-lead": "allow",
|
|
17
|
+
"designer": "allow",
|
|
18
|
+
"developer": "allow",
|
|
19
|
+
"qa": "allow",
|
|
20
|
+
"instruction_reviewer": "allow",
|
|
21
|
+
"memory_curator": "allow"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"pm": {
|
|
26
|
+
"description": "Project Manager - coordinates workflow",
|
|
27
|
+
"mode": "subagent",
|
|
28
|
+
"model": "openai/gpt-5.5",
|
|
29
|
+
"fallback": [],
|
|
30
|
+
"permission": {
|
|
31
|
+
"task": {
|
|
32
|
+
"team-lead": "allow",
|
|
33
|
+
"designer": "allow",
|
|
34
|
+
"developer": "allow",
|
|
35
|
+
"qa": "allow"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"team-lead": {
|
|
40
|
+
"description": "Team Lead - planning and code review",
|
|
41
|
+
"mode": "all",
|
|
42
|
+
"model": "openai/gpt-5.5",
|
|
43
|
+
"fallback": [],
|
|
44
|
+
"permission": {
|
|
45
|
+
"task": {
|
|
46
|
+
"developer": "allow",
|
|
47
|
+
"qa": "allow"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"developer": {
|
|
52
|
+
"description": "Developer - implements code",
|
|
53
|
+
"mode": "all",
|
|
54
|
+
"model": "openai/gpt-5.5",
|
|
55
|
+
"fallback": []
|
|
56
|
+
},
|
|
57
|
+
"devops-engineer": {
|
|
58
|
+
"description": "DevOps Engineer - infrastructure, CI/CD, and platform reliability",
|
|
59
|
+
"mode": "all",
|
|
60
|
+
"model": "openai/gpt-5.5",
|
|
61
|
+
"fallback": []
|
|
62
|
+
},
|
|
63
|
+
"instruction_reviewer": {
|
|
64
|
+
"description": "Instruction Reviewer - post-task review of instruction effectiveness and tool discipline",
|
|
65
|
+
"mode": "all",
|
|
66
|
+
"model": "openai/gpt-5.5",
|
|
67
|
+
"fallback": []
|
|
68
|
+
},
|
|
69
|
+
"memory_curator": {
|
|
70
|
+
"description": "Memory Curator - post-task memory hygiene recommendations without automatic writes",
|
|
71
|
+
"mode": "all",
|
|
72
|
+
"model": "openai/gpt-5.5",
|
|
73
|
+
"fallback": []
|
|
74
|
+
},
|
|
75
|
+
"qa": {
|
|
76
|
+
"description": "QA Engineer - runs tests",
|
|
77
|
+
"mode": "subagent",
|
|
78
|
+
"model": "openai/gpt-5.5",
|
|
79
|
+
"fallback": []
|
|
80
|
+
},
|
|
81
|
+
"designer": {
|
|
82
|
+
"description": "Designer - UI/UX validation",
|
|
83
|
+
"mode": "subagent",
|
|
84
|
+
"model": "openai/gpt-5.5",
|
|
85
|
+
"fallback": []
|
|
86
|
+
},
|
|
87
|
+
"plan": {
|
|
88
|
+
"description": "Planning mode",
|
|
89
|
+
"mode": "primary",
|
|
90
|
+
"model": "openai/gpt-5.5",
|
|
91
|
+
"fallback": []
|
|
92
|
+
},
|
|
93
|
+
"build": {
|
|
94
|
+
"description": "Build mode",
|
|
95
|
+
"mode": "primary",
|
|
96
|
+
"model": "openai/gpt-5.5",
|
|
97
|
+
"fallback": []
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
package/package.json
CHANGED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from "@opencode-ai/plugin"
|
|
2
|
-
import { existsSync, readFileSync } from "node:fs"
|
|
3
|
-
import { readdir, readFile } from "node:fs/promises"
|
|
4
|
-
import { basename, join } from "node:path"
|
|
5
|
-
|
|
6
|
-
type AgenticPluginConfig = {
|
|
7
|
-
agentModelMapper?: {
|
|
8
|
-
enabled?: boolean
|
|
9
|
-
}
|
|
10
|
-
settings?: any
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
type Role = {
|
|
14
|
-
name: string
|
|
15
|
-
description: string
|
|
16
|
-
mode: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function readAgenticConfig(): AgenticPluginConfig {
|
|
20
|
-
const configHome = process.env.XDG_CONFIG_HOME || join(process.env.HOME || "", ".config")
|
|
21
|
-
const configPath = join(configHome, "agentic", "opencode-plugins.json")
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
return JSON.parse(readFileSync(configPath, "utf-8")) as AgenticPluginConfig
|
|
25
|
-
} catch {
|
|
26
|
-
return {}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function readProjectAgenticConfig(directory: string): AgenticPluginConfig {
|
|
31
|
-
try {
|
|
32
|
-
return JSON.parse(readFileSync(join(directory, ".agentic.json"), "utf-8")) as AgenticPluginConfig
|
|
33
|
-
} catch {
|
|
34
|
-
return {}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function parseFrontmatter(text: string): Record<string, string> {
|
|
39
|
-
if (!text.startsWith("---\n")) return {}
|
|
40
|
-
const end = text.indexOf("\n---", 4)
|
|
41
|
-
if (end === -1) return {}
|
|
42
|
-
|
|
43
|
-
const result: Record<string, string> = {}
|
|
44
|
-
for (const line of text.slice(4, end).split("\n")) {
|
|
45
|
-
const index = line.indexOf(":")
|
|
46
|
-
if (index === -1) continue
|
|
47
|
-
result[line.slice(0, index).trim()] = line.slice(index + 1).trim().replace(/^['"]|['"]$/g, "")
|
|
48
|
-
}
|
|
49
|
-
return result
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function readRoles(directory: string): Promise<Role[]> {
|
|
53
|
-
const agentsDir = join(directory, ".opencode", "agents")
|
|
54
|
-
let entries: string[]
|
|
55
|
-
try {
|
|
56
|
-
entries = await readdir(agentsDir)
|
|
57
|
-
} catch {
|
|
58
|
-
return []
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const roles: Role[] = []
|
|
62
|
-
for (const entry of entries.sort()) {
|
|
63
|
-
if (!entry.endsWith(".md")) continue
|
|
64
|
-
const path = join(agentsDir, entry)
|
|
65
|
-
const text = await readFile(path, "utf-8")
|
|
66
|
-
const frontmatter = parseFrontmatter(text)
|
|
67
|
-
roles.push({
|
|
68
|
-
name: basename(entry, ".md"),
|
|
69
|
-
description: frontmatter.description || "OpenCode agent",
|
|
70
|
-
mode: frontmatter.mode || "subagent",
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
return roles
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function readJsonIfExists(path: string): unknown {
|
|
77
|
-
if (!existsSync(path)) return undefined
|
|
78
|
-
try {
|
|
79
|
-
return JSON.parse(readFileSync(path, "utf-8"))
|
|
80
|
-
} catch {
|
|
81
|
-
return undefined
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function hasCompleteAgentModelMapping(directory: string, roles: Role[]): boolean {
|
|
86
|
-
const state = readJsonIfExists(join(directory, ".opencode", "agent-model-mapper.state.json")) as Record<string, any> | undefined
|
|
87
|
-
if (!state?.configured) return false
|
|
88
|
-
|
|
89
|
-
const config = readJsonIfExists(join(directory, ".opencode", "opencode.json")) as Record<string, any> | undefined
|
|
90
|
-
const agents = config?.agent
|
|
91
|
-
if (!agents || typeof agents !== "object") return false
|
|
92
|
-
return roles.every((role) => {
|
|
93
|
-
const agent = agents[role.name]
|
|
94
|
-
return agent && typeof agent === "object" && typeof agent.model === "string" && agent.model.trim().length > 0
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export const AgentModelMapperPlugin: Plugin = async ({ directory }) => {
|
|
99
|
-
const projectConfig = readProjectAgenticConfig(directory)
|
|
100
|
-
const globalConfig = readAgenticConfig()
|
|
101
|
-
const enabled = projectConfig.settings?.opencode_plugins?.agentModelMapper?.enabled ?? globalConfig.agentModelMapper?.enabled
|
|
102
|
-
if (!enabled) return {}
|
|
103
|
-
|
|
104
|
-
const roles = await readRoles(directory)
|
|
105
|
-
if (!roles.length) {
|
|
106
|
-
console.log("agent-model-mapper: skipped because .opencode/agents/*.md was not found")
|
|
107
|
-
return {}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (hasCompleteAgentModelMapping(directory, roles)) {
|
|
111
|
-
console.log("agent-model-mapper: skipped because all Agentic roles already have model mappings")
|
|
112
|
-
return {}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
console.log("agent-model-mapper: install-time model mapping is required; run agentic install or agentic tui")
|
|
116
|
-
return {}
|
|
117
|
-
}
|