@kodrunhq/opencode-autopilot 1.9.0 → 1.10.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kodrunhq/opencode-autopilot",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Curated agents, skills, and commands for the OpenCode AI coding CLI — autonomous orchestrator, multi-agent code review, model fallback, and in-session asset creation tools.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"keywords": [
|
package/src/agents/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { AgentConfig } from "@opencode-ai/sdk";
|
|
|
3
3
|
export const metaprompterAgent: Readonly<AgentConfig> = Object.freeze({
|
|
4
4
|
description:
|
|
5
5
|
"Crafts high-quality prompts, system instructions, and configurations for OpenCode agents, skills, and commands",
|
|
6
|
-
mode: "
|
|
6
|
+
mode: "subagent",
|
|
7
7
|
prompt: `You are a prompt engineering specialist for OpenCode assets. Your job is to craft high-quality system prompts and YAML frontmatter configurations for agents, skills, and commands.
|
|
8
8
|
|
|
9
9
|
## Instructions
|
package/src/agents/researcher.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AgentConfig } from "@opencode-ai/sdk";
|
|
|
2
2
|
|
|
3
3
|
export const researcherAgent: Readonly<AgentConfig> = Object.freeze({
|
|
4
4
|
description: "Searches the web about a topic and produces a comprehensive report with sources",
|
|
5
|
-
mode: "
|
|
5
|
+
mode: "subagent",
|
|
6
6
|
prompt: `You are a research specialist. Your job is to thoroughly investigate a given topic and produce a clear, well-organized report.
|
|
7
7
|
|
|
8
8
|
## Instructions
|
package/src/tools/stocktake.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { readdir, readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { tool } from "@opencode-ai/plugin";
|
|
4
|
+
import { agents as standardAgents } from "../agents/index";
|
|
5
|
+
import { pipelineAgents } from "../agents/pipeline/index";
|
|
6
|
+
import { AGENT_REGISTRY } from "../registry/model-groups";
|
|
4
7
|
import { lintAgent, lintCommand, lintSkill } from "../skills/linter";
|
|
5
8
|
import { getAssetsDir, getGlobalConfigDir } from "../utils/paths";
|
|
6
9
|
|
|
@@ -11,7 +14,11 @@ interface StocktakeArgs {
|
|
|
11
14
|
interface AssetEntry {
|
|
12
15
|
readonly name: string;
|
|
13
16
|
readonly type: "skill" | "command" | "agent";
|
|
14
|
-
readonly origin: "built-in" | "user-created";
|
|
17
|
+
readonly origin: "built-in" | "config-hook" | "user-created";
|
|
18
|
+
readonly mode?: "all" | "primary" | "subagent";
|
|
19
|
+
readonly model?: string;
|
|
20
|
+
readonly group?: string;
|
|
21
|
+
readonly hidden?: boolean;
|
|
15
22
|
readonly lint?: {
|
|
16
23
|
readonly valid: boolean;
|
|
17
24
|
readonly errors: readonly string[];
|
|
@@ -19,6 +26,24 @@ interface AssetEntry {
|
|
|
19
26
|
};
|
|
20
27
|
}
|
|
21
28
|
|
|
29
|
+
export interface ConfigHookAgent {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly mode?: "all" | "primary" | "subagent";
|
|
32
|
+
readonly hidden?: boolean;
|
|
33
|
+
readonly group?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function configHookAgentToEntry(agent: ConfigHookAgent): AssetEntry {
|
|
37
|
+
return {
|
|
38
|
+
name: agent.name,
|
|
39
|
+
type: "agent",
|
|
40
|
+
origin: "config-hook",
|
|
41
|
+
mode: agent.mode,
|
|
42
|
+
group: agent.group,
|
|
43
|
+
hidden: agent.hidden ?? false,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
22
47
|
/** Read directory entries safely, returning empty array on ENOENT only. */
|
|
23
48
|
async function safeReaddir(dirPath: string): Promise<string[]> {
|
|
24
49
|
try {
|
|
@@ -45,11 +70,15 @@ async function isBuiltIn(assetType: string, name: string): Promise<boolean> {
|
|
|
45
70
|
return cached.has(name);
|
|
46
71
|
}
|
|
47
72
|
|
|
48
|
-
export async function stocktakeCore(
|
|
73
|
+
export async function stocktakeCore(
|
|
74
|
+
args: StocktakeArgs,
|
|
75
|
+
baseDir: string,
|
|
76
|
+
configHookAgents?: readonly ConfigHookAgent[],
|
|
77
|
+
): Promise<string> {
|
|
49
78
|
const shouldLint = args.lint !== false;
|
|
50
79
|
const skills: AssetEntry[] = [];
|
|
51
80
|
const commands: AssetEntry[] = [];
|
|
52
|
-
const
|
|
81
|
+
const agentEntries: AssetEntry[] = [];
|
|
53
82
|
|
|
54
83
|
// Scan skills (each subdirectory is a skill) — filter to directories only
|
|
55
84
|
const skillEntries = await readdir(join(baseDir, "skills"), { withFileTypes: true }).catch(
|
|
@@ -113,22 +142,33 @@ export async function stocktakeCore(args: StocktakeArgs, baseDir: string): Promi
|
|
|
113
142
|
try {
|
|
114
143
|
const content = await readFile(join(baseDir, "agents", file), "utf-8");
|
|
115
144
|
const lint = lintAgent(content);
|
|
116
|
-
|
|
145
|
+
agentEntries.push({ ...entry, lint });
|
|
117
146
|
} catch {
|
|
118
|
-
|
|
147
|
+
agentEntries.push({
|
|
119
148
|
...entry,
|
|
120
149
|
lint: { valid: false, errors: ["Could not read agent file"], warnings: [] },
|
|
121
150
|
});
|
|
122
151
|
}
|
|
123
152
|
} else {
|
|
124
|
-
|
|
153
|
+
agentEntries.push(entry);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Add config-hook agents (skip any already found on filesystem to avoid duplicates)
|
|
158
|
+
const filesystemAgentNames = new Set(agentEntries.map((a) => a.name));
|
|
159
|
+
if (configHookAgents) {
|
|
160
|
+
for (const hookAgent of configHookAgents) {
|
|
161
|
+
if (!filesystemAgentNames.has(hookAgent.name)) {
|
|
162
|
+
agentEntries.push(configHookAgentToEntry(hookAgent));
|
|
163
|
+
}
|
|
125
164
|
}
|
|
126
165
|
}
|
|
127
166
|
|
|
128
167
|
// Compute summary
|
|
129
|
-
const allAssets = [...skills, ...commands, ...
|
|
168
|
+
const allAssets = [...skills, ...commands, ...agentEntries];
|
|
130
169
|
const builtIn = allAssets.filter((a) => a.origin === "built-in").length;
|
|
131
170
|
const userCreated = allAssets.filter((a) => a.origin === "user-created").length;
|
|
171
|
+
const configHook = allAssets.filter((a) => a.origin === "config-hook").length;
|
|
132
172
|
const lintErrors = shouldLint
|
|
133
173
|
? allAssets.reduce((sum, a) => sum + (a.lint?.errors.length ?? 0), 0)
|
|
134
174
|
: 0;
|
|
@@ -140,11 +180,12 @@ export async function stocktakeCore(args: StocktakeArgs, baseDir: string): Promi
|
|
|
140
180
|
{
|
|
141
181
|
skills,
|
|
142
182
|
commands,
|
|
143
|
-
agents,
|
|
183
|
+
agents: agentEntries,
|
|
144
184
|
summary: {
|
|
145
185
|
total: allAssets.length,
|
|
146
186
|
builtIn,
|
|
147
187
|
userCreated,
|
|
188
|
+
configHook,
|
|
148
189
|
lintErrors,
|
|
149
190
|
lintWarnings,
|
|
150
191
|
},
|
|
@@ -165,6 +206,20 @@ export const ocStocktake = tool({
|
|
|
165
206
|
.describe("Run YAML frontmatter linter on all assets"),
|
|
166
207
|
},
|
|
167
208
|
async execute(args) {
|
|
168
|
-
|
|
209
|
+
const configHookAgentList: ConfigHookAgent[] = [
|
|
210
|
+
...Object.entries(standardAgents).map(([name, config]) => ({
|
|
211
|
+
name,
|
|
212
|
+
mode: config.mode as ConfigHookAgent["mode"],
|
|
213
|
+
hidden: (config as Record<string, unknown>).hidden === true,
|
|
214
|
+
group: AGENT_REGISTRY[name]?.group,
|
|
215
|
+
})),
|
|
216
|
+
...Object.entries(pipelineAgents).map(([name, config]) => ({
|
|
217
|
+
name,
|
|
218
|
+
mode: config.mode as ConfigHookAgent["mode"],
|
|
219
|
+
hidden: (config as Record<string, unknown>).hidden === true,
|
|
220
|
+
group: AGENT_REGISTRY[name]?.group,
|
|
221
|
+
})),
|
|
222
|
+
];
|
|
223
|
+
return stocktakeCore(args, getGlobalConfigDir(), configHookAgentList);
|
|
169
224
|
},
|
|
170
225
|
});
|