axiom-coding-agent-setup 1.0.11 → 1.0.12
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/skills/project-design/SKILL.md +207 -0
- package/.agents/skills/project-design/references/ARCHITECTURE.md +641 -0
- package/.agents/skills/project-design/references/PROJECT_PLAN.md +316 -0
- package/.agents/skills/skill-creator/LICENSE.txt +202 -0
- package/.agents/skills/skill-creator/SKILL.md +485 -0
- package/.agents/skills/skill-creator/agents/analyzer.md +274 -0
- package/.agents/skills/skill-creator/agents/comparator.md +202 -0
- package/.agents/skills/skill-creator/agents/grader.md +223 -0
- package/.agents/skills/skill-creator/assets/eval_review.html +146 -0
- package/.agents/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.agents/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.agents/skills/skill-creator/references/schemas.md +430 -0
- package/.agents/skills/skill-creator/scripts/__init__.py +0 -0
- package/.agents/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.agents/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.agents/skills/skill-creator/scripts/improve_description.py +247 -0
- package/.agents/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.agents/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.agents/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.agents/skills/skill-creator/scripts/run_loop.py +328 -0
- package/.agents/skills/skill-creator/scripts/utils.py +47 -0
- package/README.md +1 -0
- package/bin/cli.js +1 -0
- package/package.json +1 -1
- package/plugin/oh-my-openagent.json +198 -0
- package/plugin/oh-my-openagent.md +49 -0
- package/skills-lock.json +6 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Run the eval + improve loop until all pass or max iterations reached.
|
|
3
|
+
|
|
4
|
+
Combines run_eval.py and improve_description.py in a loop, tracking history
|
|
5
|
+
and returning the best description found. Supports train/test split to prevent
|
|
6
|
+
overfitting.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import json
|
|
11
|
+
import random
|
|
12
|
+
import sys
|
|
13
|
+
import tempfile
|
|
14
|
+
import time
|
|
15
|
+
import webbrowser
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
from scripts.generate_report import generate_html
|
|
19
|
+
from scripts.improve_description import improve_description
|
|
20
|
+
from scripts.run_eval import find_project_root, run_eval
|
|
21
|
+
from scripts.utils import parse_skill_md
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def split_eval_set(eval_set: list[dict], holdout: float, seed: int = 42) -> tuple[list[dict], list[dict]]:
|
|
25
|
+
"""Split eval set into train and test sets, stratified by should_trigger."""
|
|
26
|
+
random.seed(seed)
|
|
27
|
+
|
|
28
|
+
# Separate by should_trigger
|
|
29
|
+
trigger = [e for e in eval_set if e["should_trigger"]]
|
|
30
|
+
no_trigger = [e for e in eval_set if not e["should_trigger"]]
|
|
31
|
+
|
|
32
|
+
# Shuffle each group
|
|
33
|
+
random.shuffle(trigger)
|
|
34
|
+
random.shuffle(no_trigger)
|
|
35
|
+
|
|
36
|
+
# Calculate split points
|
|
37
|
+
n_trigger_test = max(1, int(len(trigger) * holdout))
|
|
38
|
+
n_no_trigger_test = max(1, int(len(no_trigger) * holdout))
|
|
39
|
+
|
|
40
|
+
# Split
|
|
41
|
+
test_set = trigger[:n_trigger_test] + no_trigger[:n_no_trigger_test]
|
|
42
|
+
train_set = trigger[n_trigger_test:] + no_trigger[n_no_trigger_test:]
|
|
43
|
+
|
|
44
|
+
return train_set, test_set
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def run_loop(
|
|
48
|
+
eval_set: list[dict],
|
|
49
|
+
skill_path: Path,
|
|
50
|
+
description_override: str | None,
|
|
51
|
+
num_workers: int,
|
|
52
|
+
timeout: int,
|
|
53
|
+
max_iterations: int,
|
|
54
|
+
runs_per_query: int,
|
|
55
|
+
trigger_threshold: float,
|
|
56
|
+
holdout: float,
|
|
57
|
+
model: str,
|
|
58
|
+
verbose: bool,
|
|
59
|
+
live_report_path: Path | None = None,
|
|
60
|
+
log_dir: Path | None = None,
|
|
61
|
+
) -> dict:
|
|
62
|
+
"""Run the eval + improvement loop."""
|
|
63
|
+
project_root = find_project_root()
|
|
64
|
+
name, original_description, content = parse_skill_md(skill_path)
|
|
65
|
+
current_description = description_override or original_description
|
|
66
|
+
|
|
67
|
+
# Split into train/test if holdout > 0
|
|
68
|
+
if holdout > 0:
|
|
69
|
+
train_set, test_set = split_eval_set(eval_set, holdout)
|
|
70
|
+
if verbose:
|
|
71
|
+
print(f"Split: {len(train_set)} train, {len(test_set)} test (holdout={holdout})", file=sys.stderr)
|
|
72
|
+
else:
|
|
73
|
+
train_set = eval_set
|
|
74
|
+
test_set = []
|
|
75
|
+
|
|
76
|
+
history = []
|
|
77
|
+
exit_reason = "unknown"
|
|
78
|
+
|
|
79
|
+
for iteration in range(1, max_iterations + 1):
|
|
80
|
+
if verbose:
|
|
81
|
+
print(f"\n{'='*60}", file=sys.stderr)
|
|
82
|
+
print(f"Iteration {iteration}/{max_iterations}", file=sys.stderr)
|
|
83
|
+
print(f"Description: {current_description}", file=sys.stderr)
|
|
84
|
+
print(f"{'='*60}", file=sys.stderr)
|
|
85
|
+
|
|
86
|
+
# Evaluate train + test together in one batch for parallelism
|
|
87
|
+
all_queries = train_set + test_set
|
|
88
|
+
t0 = time.time()
|
|
89
|
+
all_results = run_eval(
|
|
90
|
+
eval_set=all_queries,
|
|
91
|
+
skill_name=name,
|
|
92
|
+
description=current_description,
|
|
93
|
+
num_workers=num_workers,
|
|
94
|
+
timeout=timeout,
|
|
95
|
+
project_root=project_root,
|
|
96
|
+
runs_per_query=runs_per_query,
|
|
97
|
+
trigger_threshold=trigger_threshold,
|
|
98
|
+
model=model,
|
|
99
|
+
)
|
|
100
|
+
eval_elapsed = time.time() - t0
|
|
101
|
+
|
|
102
|
+
# Split results back into train/test by matching queries
|
|
103
|
+
train_queries_set = {q["query"] for q in train_set}
|
|
104
|
+
train_result_list = [r for r in all_results["results"] if r["query"] in train_queries_set]
|
|
105
|
+
test_result_list = [r for r in all_results["results"] if r["query"] not in train_queries_set]
|
|
106
|
+
|
|
107
|
+
train_passed = sum(1 for r in train_result_list if r["pass"])
|
|
108
|
+
train_total = len(train_result_list)
|
|
109
|
+
train_summary = {"passed": train_passed, "failed": train_total - train_passed, "total": train_total}
|
|
110
|
+
train_results = {"results": train_result_list, "summary": train_summary}
|
|
111
|
+
|
|
112
|
+
if test_set:
|
|
113
|
+
test_passed = sum(1 for r in test_result_list if r["pass"])
|
|
114
|
+
test_total = len(test_result_list)
|
|
115
|
+
test_summary = {"passed": test_passed, "failed": test_total - test_passed, "total": test_total}
|
|
116
|
+
test_results = {"results": test_result_list, "summary": test_summary}
|
|
117
|
+
else:
|
|
118
|
+
test_results = None
|
|
119
|
+
test_summary = None
|
|
120
|
+
|
|
121
|
+
history.append({
|
|
122
|
+
"iteration": iteration,
|
|
123
|
+
"description": current_description,
|
|
124
|
+
"train_passed": train_summary["passed"],
|
|
125
|
+
"train_failed": train_summary["failed"],
|
|
126
|
+
"train_total": train_summary["total"],
|
|
127
|
+
"train_results": train_results["results"],
|
|
128
|
+
"test_passed": test_summary["passed"] if test_summary else None,
|
|
129
|
+
"test_failed": test_summary["failed"] if test_summary else None,
|
|
130
|
+
"test_total": test_summary["total"] if test_summary else None,
|
|
131
|
+
"test_results": test_results["results"] if test_results else None,
|
|
132
|
+
# For backward compat with report generator
|
|
133
|
+
"passed": train_summary["passed"],
|
|
134
|
+
"failed": train_summary["failed"],
|
|
135
|
+
"total": train_summary["total"],
|
|
136
|
+
"results": train_results["results"],
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
# Write live report if path provided
|
|
140
|
+
if live_report_path:
|
|
141
|
+
partial_output = {
|
|
142
|
+
"original_description": original_description,
|
|
143
|
+
"best_description": current_description,
|
|
144
|
+
"best_score": "in progress",
|
|
145
|
+
"iterations_run": len(history),
|
|
146
|
+
"holdout": holdout,
|
|
147
|
+
"train_size": len(train_set),
|
|
148
|
+
"test_size": len(test_set),
|
|
149
|
+
"history": history,
|
|
150
|
+
}
|
|
151
|
+
live_report_path.write_text(generate_html(partial_output, auto_refresh=True, skill_name=name))
|
|
152
|
+
|
|
153
|
+
if verbose:
|
|
154
|
+
def print_eval_stats(label, results, elapsed):
|
|
155
|
+
pos = [r for r in results if r["should_trigger"]]
|
|
156
|
+
neg = [r for r in results if not r["should_trigger"]]
|
|
157
|
+
tp = sum(r["triggers"] for r in pos)
|
|
158
|
+
pos_runs = sum(r["runs"] for r in pos)
|
|
159
|
+
fn = pos_runs - tp
|
|
160
|
+
fp = sum(r["triggers"] for r in neg)
|
|
161
|
+
neg_runs = sum(r["runs"] for r in neg)
|
|
162
|
+
tn = neg_runs - fp
|
|
163
|
+
total = tp + tn + fp + fn
|
|
164
|
+
precision = tp / (tp + fp) if (tp + fp) > 0 else 1.0
|
|
165
|
+
recall = tp / (tp + fn) if (tp + fn) > 0 else 1.0
|
|
166
|
+
accuracy = (tp + tn) / total if total > 0 else 0.0
|
|
167
|
+
print(f"{label}: {tp+tn}/{total} correct, precision={precision:.0%} recall={recall:.0%} accuracy={accuracy:.0%} ({elapsed:.1f}s)", file=sys.stderr)
|
|
168
|
+
for r in results:
|
|
169
|
+
status = "PASS" if r["pass"] else "FAIL"
|
|
170
|
+
rate_str = f"{r['triggers']}/{r['runs']}"
|
|
171
|
+
print(f" [{status}] rate={rate_str} expected={r['should_trigger']}: {r['query'][:60]}", file=sys.stderr)
|
|
172
|
+
|
|
173
|
+
print_eval_stats("Train", train_results["results"], eval_elapsed)
|
|
174
|
+
if test_summary:
|
|
175
|
+
print_eval_stats("Test ", test_results["results"], 0)
|
|
176
|
+
|
|
177
|
+
if train_summary["failed"] == 0:
|
|
178
|
+
exit_reason = f"all_passed (iteration {iteration})"
|
|
179
|
+
if verbose:
|
|
180
|
+
print(f"\nAll train queries passed on iteration {iteration}!", file=sys.stderr)
|
|
181
|
+
break
|
|
182
|
+
|
|
183
|
+
if iteration == max_iterations:
|
|
184
|
+
exit_reason = f"max_iterations ({max_iterations})"
|
|
185
|
+
if verbose:
|
|
186
|
+
print(f"\nMax iterations reached ({max_iterations}).", file=sys.stderr)
|
|
187
|
+
break
|
|
188
|
+
|
|
189
|
+
# Improve the description based on train results
|
|
190
|
+
if verbose:
|
|
191
|
+
print(f"\nImproving description...", file=sys.stderr)
|
|
192
|
+
|
|
193
|
+
t0 = time.time()
|
|
194
|
+
# Strip test scores from history so improvement model can't see them
|
|
195
|
+
blinded_history = [
|
|
196
|
+
{k: v for k, v in h.items() if not k.startswith("test_")}
|
|
197
|
+
for h in history
|
|
198
|
+
]
|
|
199
|
+
new_description = improve_description(
|
|
200
|
+
skill_name=name,
|
|
201
|
+
skill_content=content,
|
|
202
|
+
current_description=current_description,
|
|
203
|
+
eval_results=train_results,
|
|
204
|
+
history=blinded_history,
|
|
205
|
+
model=model,
|
|
206
|
+
log_dir=log_dir,
|
|
207
|
+
iteration=iteration,
|
|
208
|
+
)
|
|
209
|
+
improve_elapsed = time.time() - t0
|
|
210
|
+
|
|
211
|
+
if verbose:
|
|
212
|
+
print(f"Proposed ({improve_elapsed:.1f}s): {new_description}", file=sys.stderr)
|
|
213
|
+
|
|
214
|
+
current_description = new_description
|
|
215
|
+
|
|
216
|
+
# Find the best iteration by TEST score (or train if no test set)
|
|
217
|
+
if test_set:
|
|
218
|
+
best = max(history, key=lambda h: h["test_passed"] or 0)
|
|
219
|
+
best_score = f"{best['test_passed']}/{best['test_total']}"
|
|
220
|
+
else:
|
|
221
|
+
best = max(history, key=lambda h: h["train_passed"])
|
|
222
|
+
best_score = f"{best['train_passed']}/{best['train_total']}"
|
|
223
|
+
|
|
224
|
+
if verbose:
|
|
225
|
+
print(f"\nExit reason: {exit_reason}", file=sys.stderr)
|
|
226
|
+
print(f"Best score: {best_score} (iteration {best['iteration']})", file=sys.stderr)
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
"exit_reason": exit_reason,
|
|
230
|
+
"original_description": original_description,
|
|
231
|
+
"best_description": best["description"],
|
|
232
|
+
"best_score": best_score,
|
|
233
|
+
"best_train_score": f"{best['train_passed']}/{best['train_total']}",
|
|
234
|
+
"best_test_score": f"{best['test_passed']}/{best['test_total']}" if test_set else None,
|
|
235
|
+
"final_description": current_description,
|
|
236
|
+
"iterations_run": len(history),
|
|
237
|
+
"holdout": holdout,
|
|
238
|
+
"train_size": len(train_set),
|
|
239
|
+
"test_size": len(test_set),
|
|
240
|
+
"history": history,
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def main():
|
|
245
|
+
parser = argparse.ArgumentParser(description="Run eval + improve loop")
|
|
246
|
+
parser.add_argument("--eval-set", required=True, help="Path to eval set JSON file")
|
|
247
|
+
parser.add_argument("--skill-path", required=True, help="Path to skill directory")
|
|
248
|
+
parser.add_argument("--description", default=None, help="Override starting description")
|
|
249
|
+
parser.add_argument("--num-workers", type=int, default=10, help="Number of parallel workers")
|
|
250
|
+
parser.add_argument("--timeout", type=int, default=30, help="Timeout per query in seconds")
|
|
251
|
+
parser.add_argument("--max-iterations", type=int, default=5, help="Max improvement iterations")
|
|
252
|
+
parser.add_argument("--runs-per-query", type=int, default=3, help="Number of runs per query")
|
|
253
|
+
parser.add_argument("--trigger-threshold", type=float, default=0.5, help="Trigger rate threshold")
|
|
254
|
+
parser.add_argument("--holdout", type=float, default=0.4, help="Fraction of eval set to hold out for testing (0 to disable)")
|
|
255
|
+
parser.add_argument("--model", required=True, help="Model for improvement")
|
|
256
|
+
parser.add_argument("--verbose", action="store_true", help="Print progress to stderr")
|
|
257
|
+
parser.add_argument("--report", default="auto", help="Generate HTML report at this path (default: 'auto' for temp file, 'none' to disable)")
|
|
258
|
+
parser.add_argument("--results-dir", default=None, help="Save all outputs (results.json, report.html, log.txt) to a timestamped subdirectory here")
|
|
259
|
+
args = parser.parse_args()
|
|
260
|
+
|
|
261
|
+
eval_set = json.loads(Path(args.eval_set).read_text())
|
|
262
|
+
skill_path = Path(args.skill_path)
|
|
263
|
+
|
|
264
|
+
if not (skill_path / "SKILL.md").exists():
|
|
265
|
+
print(f"Error: No SKILL.md found at {skill_path}", file=sys.stderr)
|
|
266
|
+
sys.exit(1)
|
|
267
|
+
|
|
268
|
+
name, _, _ = parse_skill_md(skill_path)
|
|
269
|
+
|
|
270
|
+
# Set up live report path
|
|
271
|
+
if args.report != "none":
|
|
272
|
+
if args.report == "auto":
|
|
273
|
+
timestamp = time.strftime("%Y%m%d_%H%M%S")
|
|
274
|
+
live_report_path = Path(tempfile.gettempdir()) / f"skill_description_report_{skill_path.name}_{timestamp}.html"
|
|
275
|
+
else:
|
|
276
|
+
live_report_path = Path(args.report)
|
|
277
|
+
# Open the report immediately so the user can watch
|
|
278
|
+
live_report_path.write_text("<html><body><h1>Starting optimization loop...</h1><meta http-equiv='refresh' content='5'></body></html>")
|
|
279
|
+
webbrowser.open(str(live_report_path))
|
|
280
|
+
else:
|
|
281
|
+
live_report_path = None
|
|
282
|
+
|
|
283
|
+
# Determine output directory (create before run_loop so logs can be written)
|
|
284
|
+
if args.results_dir:
|
|
285
|
+
timestamp = time.strftime("%Y-%m-%d_%H%M%S")
|
|
286
|
+
results_dir = Path(args.results_dir) / timestamp
|
|
287
|
+
results_dir.mkdir(parents=True, exist_ok=True)
|
|
288
|
+
else:
|
|
289
|
+
results_dir = None
|
|
290
|
+
|
|
291
|
+
log_dir = results_dir / "logs" if results_dir else None
|
|
292
|
+
|
|
293
|
+
output = run_loop(
|
|
294
|
+
eval_set=eval_set,
|
|
295
|
+
skill_path=skill_path,
|
|
296
|
+
description_override=args.description,
|
|
297
|
+
num_workers=args.num_workers,
|
|
298
|
+
timeout=args.timeout,
|
|
299
|
+
max_iterations=args.max_iterations,
|
|
300
|
+
runs_per_query=args.runs_per_query,
|
|
301
|
+
trigger_threshold=args.trigger_threshold,
|
|
302
|
+
holdout=args.holdout,
|
|
303
|
+
model=args.model,
|
|
304
|
+
verbose=args.verbose,
|
|
305
|
+
live_report_path=live_report_path,
|
|
306
|
+
log_dir=log_dir,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
# Save JSON output
|
|
310
|
+
json_output = json.dumps(output, indent=2)
|
|
311
|
+
print(json_output)
|
|
312
|
+
if results_dir:
|
|
313
|
+
(results_dir / "results.json").write_text(json_output)
|
|
314
|
+
|
|
315
|
+
# Write final HTML report (without auto-refresh)
|
|
316
|
+
if live_report_path:
|
|
317
|
+
live_report_path.write_text(generate_html(output, auto_refresh=False, skill_name=name))
|
|
318
|
+
print(f"\nReport: {live_report_path}", file=sys.stderr)
|
|
319
|
+
|
|
320
|
+
if results_dir and live_report_path:
|
|
321
|
+
(results_dir / "report.html").write_text(generate_html(output, auto_refresh=False, skill_name=name))
|
|
322
|
+
|
|
323
|
+
if results_dir:
|
|
324
|
+
print(f"Results saved to: {results_dir}", file=sys.stderr)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
if __name__ == "__main__":
|
|
328
|
+
main()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Shared utilities for skill-creator scripts."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def parse_skill_md(skill_path: Path) -> tuple[str, str, str]:
|
|
8
|
+
"""Parse a SKILL.md file, returning (name, description, full_content)."""
|
|
9
|
+
content = (skill_path / "SKILL.md").read_text()
|
|
10
|
+
lines = content.split("\n")
|
|
11
|
+
|
|
12
|
+
if lines[0].strip() != "---":
|
|
13
|
+
raise ValueError("SKILL.md missing frontmatter (no opening ---)")
|
|
14
|
+
|
|
15
|
+
end_idx = None
|
|
16
|
+
for i, line in enumerate(lines[1:], start=1):
|
|
17
|
+
if line.strip() == "---":
|
|
18
|
+
end_idx = i
|
|
19
|
+
break
|
|
20
|
+
|
|
21
|
+
if end_idx is None:
|
|
22
|
+
raise ValueError("SKILL.md missing frontmatter (no closing ---)")
|
|
23
|
+
|
|
24
|
+
name = ""
|
|
25
|
+
description = ""
|
|
26
|
+
frontmatter_lines = lines[1:end_idx]
|
|
27
|
+
i = 0
|
|
28
|
+
while i < len(frontmatter_lines):
|
|
29
|
+
line = frontmatter_lines[i]
|
|
30
|
+
if line.startswith("name:"):
|
|
31
|
+
name = line[len("name:"):].strip().strip('"').strip("'")
|
|
32
|
+
elif line.startswith("description:"):
|
|
33
|
+
value = line[len("description:"):].strip()
|
|
34
|
+
# Handle YAML multiline indicators (>, |, >-, |-)
|
|
35
|
+
if value in (">", "|", ">-", "|-"):
|
|
36
|
+
continuation_lines: list[str] = []
|
|
37
|
+
i += 1
|
|
38
|
+
while i < len(frontmatter_lines) and (frontmatter_lines[i].startswith(" ") or frontmatter_lines[i].startswith("\t")):
|
|
39
|
+
continuation_lines.append(frontmatter_lines[i].strip())
|
|
40
|
+
i += 1
|
|
41
|
+
description = " ".join(continuation_lines)
|
|
42
|
+
continue
|
|
43
|
+
else:
|
|
44
|
+
description = value.strip('"').strip("'")
|
|
45
|
+
i += 1
|
|
46
|
+
|
|
47
|
+
return name, description, content
|
package/README.md
CHANGED
|
@@ -83,6 +83,7 @@ Domain-specific skills that can be loaded on-demand:
|
|
|
83
83
|
- `gradio/` — Gradio UI framework guides
|
|
84
84
|
- `mcp-builder/` — MCP server development guide
|
|
85
85
|
- `n8n-patterns/` — n8n workflow automation patterns
|
|
86
|
+
- `project-design/` — Project planning & architecture documentation
|
|
86
87
|
- `ui-ux-pro-max/` — Advanced UI/UX design skill
|
|
87
88
|
|
|
88
89
|
## Development
|
package/bin/cli.js
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
|
3
|
+
"agents": {
|
|
4
|
+
// === ORCHESTRATION CORE ===
|
|
5
|
+
// Kimi K2.6: #1 open-weight for long-horizon agentic work, 300-subagent swarm,
|
|
6
|
+
// 12h autonomous sessions, officially omo's top non-Claude fallback for Sisyphus.
|
|
7
|
+
// Fallback: DeepSeek V4 Pro for its raw SWE-bench muscle when K2.6 is unavailable.
|
|
8
|
+
"sisyphus": {
|
|
9
|
+
"model": "opencode-go/kimi-k2.6",
|
|
10
|
+
"fallback_models": [
|
|
11
|
+
{ "model": "opencode-go/deepseek-v4-pro" }
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
// === PLANNING & STRATEGY ===
|
|
16
|
+
// Prometheus auto-detects model family and switches prompts — Kimi K2.6 fits the
|
|
17
|
+
// Claude-like instruction-following prompt that omo uses for strategic planning.
|
|
18
|
+
// Fallback: GLM-5.1 for its independently verified long-horizon execution loop.
|
|
19
|
+
"prometheus": {
|
|
20
|
+
"model": "opencode-go/kimi-k2.6",
|
|
21
|
+
"fallback_models": [
|
|
22
|
+
{ "model": "opencode-go/glm-5.1" }
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// === PLAN REVIEW ===
|
|
27
|
+
// Metis is the plan reviewer — needs strong reasoning + precision.
|
|
28
|
+
// Kimi K2.6 excels at catching non-obvious bugs and maintaining architectural integrity
|
|
29
|
+
// over extended review sessions per enterprise beta feedback.
|
|
30
|
+
// Fallback: GLM-5.1 which ranked #1 on NL2Repo for codebase structure comprehension.
|
|
31
|
+
"metis": {
|
|
32
|
+
"model": "opencode-go/kimi-k2.6",
|
|
33
|
+
"fallback_models": [
|
|
34
|
+
{ "model": "opencode-go/glm-5.1" }
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
// === ARCHITECTURE & DEBUGGING ===
|
|
39
|
+
// Oracle needs surgical precision in large codebases — Kimi K2.6 won benchmarks
|
|
40
|
+
// specifically on async/TypeVar edge-case bugs that require multi-cycle inference state.
|
|
41
|
+
// Fallback: DeepSeek V4 Pro, strongest on SWE-bench Verified (80.6%) and Codeforces (3206).
|
|
42
|
+
"oracle": {
|
|
43
|
+
"model": "opencode-go/kimi-k2.6",
|
|
44
|
+
"fallback_models": [
|
|
45
|
+
{ "model": "opencode-go/deepseek-v4-pro" }
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// === HIGH-ACCURACY REVIEW ===
|
|
50
|
+
// Momus is the strictness reviewer — prompt is tuned for Claude-like models.
|
|
51
|
+
// GLM-5.1 promoted to primary: independently verified Code Arena Elo 1530 (#3 globally),
|
|
52
|
+
// spontaneously applied composition patterns in head-to-head tests vs K2.6.
|
|
53
|
+
// Fallback: Kimi K2.6 for its 12% improvement in code generation accuracy over K2.5.
|
|
54
|
+
"momus": {
|
|
55
|
+
"model": "opencode-go/glm-5.1",
|
|
56
|
+
"fallback_models": [
|
|
57
|
+
{ "model": "opencode-go/kimi-k2.6" }
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// === TODO ORCHESTRATION ===
|
|
62
|
+
// Atlas is the task/todo orchestrator — auto-detects model family.
|
|
63
|
+
// Kimi K2.6 is the best fit for long multi-step coordination (300 sub-agents, 4000 steps).
|
|
64
|
+
// Fallback: DeepSeek V4 Pro for its $3.48/M cost efficiency at scale.
|
|
65
|
+
"atlas": {
|
|
66
|
+
"model": "opencode-go/kimi-k2.6",
|
|
67
|
+
"fallback_models": [
|
|
68
|
+
{ "model": "opencode-go/deepseek-v4-pro" }
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
// === DOCS & CODE SEARCH ===
|
|
73
|
+
// Librarian does documentation lookup and contextual code search — benefits most from
|
|
74
|
+
// Qwen3.6 Plus's 1M token context (vs K2.6's 256K ceiling). Handles full repo ingestion
|
|
75
|
+
// in a single pass. 4-6x cheaper than Claude-class for large-context read-heavy work.
|
|
76
|
+
// Fallback: DeepSeek V4 Pro — also 1M context, strong on LiveCodeBench (93.5%).
|
|
77
|
+
"librarian": {
|
|
78
|
+
"model": "opencode-go/qwen3.6-plus",
|
|
79
|
+
"fallback_models": [
|
|
80
|
+
{ "model": "opencode-go/deepseek-v4-pro" }
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
// === FAST CODEBASE GREP ===
|
|
85
|
+
// Explore is a fast grep/search agent — speed matters more than raw intelligence here.
|
|
86
|
+
// Qwen3.6 Plus runs 2-3x faster TPS than Claude Opus and has 1M context for large repos.
|
|
87
|
+
// Fallback: GLM-5.1 for its 55+ tokens/sec generation speed.
|
|
88
|
+
"explore": {
|
|
89
|
+
"model": "opencode-go/qwen3.6-plus",
|
|
90
|
+
"fallback_models": [
|
|
91
|
+
{ "model": "opencode-go/glm-5.1" }
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// === VISION / SCREENSHOTS ===
|
|
96
|
+
// Multimodal-looker needs a model with solid vision. Kimi K2.6 has native multimodality
|
|
97
|
+
// and specifically handles visual-to-code workflows (UI designs → working code).
|
|
98
|
+
// No fallback: this is the only model in the stack with reliable multimodal support.
|
|
99
|
+
"multimodal-looker": {
|
|
100
|
+
"model": "opencode-go/kimi-k2.6"
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
// === JUNIOR WORKER ===
|
|
104
|
+
// Sisyphus-Junior handles delegated subtasks — Kimi K2.6 maintains session stability
|
|
105
|
+
// for parallel spawned workers (tool invocation success rate 96.60% per CodeBuddy eval).
|
|
106
|
+
// Fallback: DeepSeek V4 Pro for cost efficiency on high-volume parallel calls.
|
|
107
|
+
"sisyphus-junior": {
|
|
108
|
+
"model": "opencode-go/kimi-k2.6",
|
|
109
|
+
"fallback_models": [
|
|
110
|
+
{ "model": "opencode-go/deepseek-v4-pro" }
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
"categories": {
|
|
116
|
+
// === VISUAL / FRONTEND ENGINEERING ===
|
|
117
|
+
// GLM-5.1 promoted to primary: #3 globally on agentic webdev (Arena.ai Elo 1530),
|
|
118
|
+
// produced correct Tailwind + TypeScript components on first pass in head-to-head tests.
|
|
119
|
+
// Kimi K2.6 as fallback — strong on visual-to-code via native multimodal training.
|
|
120
|
+
"visual-engineering": {
|
|
121
|
+
"model": "opencode-go/glm-5.1",
|
|
122
|
+
"fallback_models": [
|
|
123
|
+
{ "model": "opencode-go/kimi-k2.6" }
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
// === MAXIMUM REASONING ===
|
|
128
|
+
// Ultrabrain is the highest-stakes category — Kimi K2.6 leads open-weight AI Index (54).
|
|
129
|
+
// Fallback: DeepSeek V4 Pro for its Codeforces 3206 and LiveCodeBench 93.5% supremacy.
|
|
130
|
+
"ultrabrain": {
|
|
131
|
+
"model": "opencode-go/kimi-k2.6",
|
|
132
|
+
"fallback_models": [
|
|
133
|
+
{ "model": "opencode-go/deepseek-v4-pro" }
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
// === DEEP / COMPLEX WORK ===
|
|
138
|
+
// Kimi K2.6: best open-source for long-horizon, sustained multi-step execution.
|
|
139
|
+
// Fallback: GLM-5.1 — demonstrated 655-iteration autonomous optimization loop,
|
|
140
|
+
// 8h uninterrupted task execution, strongest open-weight for backend deep dives.
|
|
141
|
+
"deep": {
|
|
142
|
+
"model": "opencode-go/kimi-k2.6",
|
|
143
|
+
"fallback_models": [
|
|
144
|
+
{ "model": "opencode-go/glm-5.1" }
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
// === CREATIVE / UI ARTISTRY ===
|
|
149
|
+
// GLM-5.1 as primary: spontaneously applies composition patterns, correct JSX on first
|
|
150
|
+
// pass, Code Arena voters prefer it for frontend aesthetics in head-to-head evals.
|
|
151
|
+
// Kimi K2.6 as fallback: Moonshot claims Awwwards-level frontend from single prompts.
|
|
152
|
+
"artistry": {
|
|
153
|
+
"model": "opencode-go/glm-5.1",
|
|
154
|
+
"fallback_models": [
|
|
155
|
+
{ "model": "opencode-go/kimi-k2.6" }
|
|
156
|
+
]
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
// === QUICK / TRIVIAL TASKS ===
|
|
160
|
+
// GLM-5.1: 55+ tokens/sec, HN devs rate it as "actually usable" for piecemeal tasks,
|
|
161
|
+
// compares well to GPT-5.4 for scoped, well-defined subtasks.
|
|
162
|
+
// No fallback needed — quick tasks should just pass or skip to the next agent.
|
|
163
|
+
"quick": {
|
|
164
|
+
"model": "opencode-go/glm-5.1"
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
// === UNSPECIFIED / MODERATE TASKS ===
|
|
168
|
+
// Kimi K2.6 is the safest general-purpose choice for ambiguous category routing.
|
|
169
|
+
// Fallback: Qwen3.6 Plus at $0.50/M input — 30x cheaper than Claude, close in SWE-bench.
|
|
170
|
+
"unspecified-low": {
|
|
171
|
+
"model": "opencode-go/kimi-k2.6",
|
|
172
|
+
"fallback_models": [
|
|
173
|
+
{ "model": "opencode-go/qwen3.6-plus" }
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
// === UNSPECIFIED / COMPLEX TASKS ===
|
|
178
|
+
// Same primary as unspecified-low — Kimi K2.6 handles both well.
|
|
179
|
+
// Fallback: GLM-5.1 rather than Qwen, for stronger reasoning depth on hard unknowns.
|
|
180
|
+
"unspecified-high": {
|
|
181
|
+
"model": "opencode-go/kimi-k2.6",
|
|
182
|
+
"fallback_models": [
|
|
183
|
+
{ "model": "opencode-go/glm-5.1" }
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
// === WRITING / DOCUMENTATION ===
|
|
188
|
+
// Kimi K2.6: strong instruction-following and consistent output quality.
|
|
189
|
+
// Fallback: GLM-5.1 — bilingual training (EN/CN) useful for mixed-language codebases
|
|
190
|
+
// and documentation; Qwen3.6 Plus also strong here but GLM edges it on coherence.
|
|
191
|
+
"writing": {
|
|
192
|
+
"model": "opencode-go/kimi-k2.6",
|
|
193
|
+
"fallback_models": [
|
|
194
|
+
{ "model": "opencode-go/glm-5.1" }
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Congratulations! 🎉
|
|
2
|
+
You have successfully set up OhMyOpenAgent with your OpenCode Go subscription! Type opencode in your terminal to start using it.
|
|
3
|
+
Your Model Configuration
|
|
4
|
+
All agents have been configured to use your opencode-go/ models:
|
|
5
|
+
Agent Model Role
|
|
6
|
+
Sisyphus opencode-go/kimi-k2.6 Main ultraworker / orchestrator
|
|
7
|
+
Prometheus opencode-go/glm-5.1 Strategic planner
|
|
8
|
+
Metis opencode-go/glm-5.1 Plan reviewer
|
|
9
|
+
Oracle opencode-go/glm-5.1 Architecture / debugging
|
|
10
|
+
Momus opencode-go/glm-5.1 High-accuracy reviewer
|
|
11
|
+
Atlas opencode-go/kimi-k2.6 Todo orchestrator
|
|
12
|
+
Librarian opencode-go/qwen3.5-plus Docs / code search
|
|
13
|
+
Explore opencode-go/qwen3.5-plus Fast codebase grep
|
|
14
|
+
Multimodal Looker opencode-go/kimi-k2.6 Vision / screenshots
|
|
15
|
+
Verification Results
|
|
16
|
+
The doctor found 2 minor non-critical issues:
|
|
17
|
+
|
|
18
|
+
1. Comment checker unavailable — Optional. Install @code-yeongyu/comment-checker if you want AI comment quality checks.
|
|
19
|
+
2. GitHub CLI not authenticated — Only matters if you want GitHub automation. Run gh auth login if needed.
|
|
20
|
+
Your core setup is healthy! ✅
|
|
21
|
+
Free Advertising
|
|
22
|
+
Vercel — The platform for frontend developers. Ship fast, scale faster. Vercel powers some of the most performant web experiences on the internet with their edge network and framework-defined infrastructure. From personal projects to enterprise deployments, Vercel makes frontend teams unstoppable.
|
|
23
|
+
You can also get free advertising for your company by contributing to oh-my-openagent: https://github.com/code-yeongyu/oh-my-openagent/compare
|
|
24
|
+
What You Can Do Now
|
|
25
|
+
Here are some powerful use cases with your setup:
|
|
26
|
+
3. ultrawork or ulw — Type this in your prompt and Sisyphus will orchestrate multiple agents in parallel to relentlessly execute until your task is done. Refactor an entire codebase, build a feature end-to-end, or fix thousands of lint warnings overnight.
|
|
27
|
+
4. /start-work — Press Tab to enter Prometheus (Planner) mode. He'll interview you like a senior engineer, identify scope and ambiguities, and build a detailed execution plan before any code is touched.
|
|
28
|
+
5. /init-deep — Run this to auto-generate hierarchical AGENTS.md files throughout your project. Your agents will instantly understand your codebase structure without you explaining it every time.
|
|
29
|
+
6. Background Agents — Fire off 5+ specialist agents in parallel. Context stays lean, results come when ready.
|
|
30
|
+
7. Team Mode — Enable team_mode in your config to run a lead agent + up to 8 parallel members with real-time tmux visualization. Great for security audits or plan critiques.
|
|
31
|
+
Quick Tips
|
|
32
|
+
8. Sisyphus agent strongly recommends Opus 4.7 model. Using other models may result in significantly degraded experience. Your current fallback is kimi-k2.6, which is the best available in your OpenCode Go plan.
|
|
33
|
+
9. Feeling lazy? Just include ultrawork (or ulw) in your prompt. That's it. The agent figures out the rest.
|
|
34
|
+
10. Need precision? Press Tab to enter Prometheus (Planner) mode, create a work plan through an interview process, then run /start-work to execute it with full orchestration.
|
|
35
|
+
11. Want your own agent-catalog setup? I can read the docs (https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/refs/heads/dev/docs/guide/agent-model-matching.md) and set it up for you after interviewing!
|
|
36
|
+
Authentication Note
|
|
37
|
+
Your OpenCode Go models (opencode-go/...) should work if your OpenCode Go subscription is active. If opencode prompts you for provider authentication on first use, simply run:
|
|
38
|
+
opencode auth login
|
|
39
|
+
and follow the OpenCode provider flow.
|
|
40
|
+
If you found this helpful, would you like to star the repository? It helps the project grow! ⭐
|
|
41
|
+
Just say yes and I'll star it for you! 🌟
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
The file I modified is located at:
|
|
46
|
+
C:\Users\Cikal Merdeka\.config\opencode\oh-my-openagent.json
|
|
47
|
+
|
|
48
|
+
Claude:
|
|
49
|
+
https://claude.ai/chat/3c0c28cf-fc2c-4225-87e1-e5dd3c5cfb38
|
package/skills-lock.json
CHANGED
|
@@ -41,6 +41,12 @@
|
|
|
41
41
|
"skillPath": ".agents/skills/gradio/SKILL.md",
|
|
42
42
|
"computedHash": "5078d8a4cc2b562731620f36f5f0d3ad054bd51f7a98baa547b04b893744823b"
|
|
43
43
|
},
|
|
44
|
+
"skill-creator": {
|
|
45
|
+
"source": "anthropics/skills",
|
|
46
|
+
"sourceType": "github",
|
|
47
|
+
"skillPath": "skills/skill-creator/SKILL.md",
|
|
48
|
+
"computedHash": "7e3c9cd74e9e2b4828527a857170e86310f2dab5ea8030a9043df2c7e6c88857"
|
|
49
|
+
},
|
|
44
50
|
"ui-ux-pro-max": {
|
|
45
51
|
"source": "nextlevelbuilder/ui-ux-pro-max-skill",
|
|
46
52
|
"sourceType": "github",
|