-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathopencode.jsonc
More file actions
163 lines (163 loc) · 6.6 KB
/
Copy pathopencode.jsonc
File metadata and controls
163 lines (163 loc) · 6.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
{
"$schema": "https://opencode.ai/config.json",
// Appended to every agent's system prompt (including the built-in
// plan/build prompts, which cannot be extended per-agent).
// Relative path: resolved to absolute at install time.
"instructions": ["./yagni.md"],
// The plugin is auto-discovered from plugin/ (no "plugin" array needed).
// Commands live in command/*.md (/usage, /reload_models).
"provider": {
"saia-gwdg": {
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "https://chat-ai.academiccloud.de/v1",
// Backstop only — the PLUGIN owns stall detection. opencode implements
// chunkTimeout as an AbortController merged into the signal it hands to
// the patched fetch, so whatever value is here aborts the request; the
// plugin then sees `signal.aborted`, correctly reads it as a caller
// abort, and does NOT retry. At the old 30000 that fired before the
// plugin's own idle windows (STREAM_IDLE_TIMEOUT_MS 45s,
// SLOW_IDLE_TIMEOUT_MS 90s) every single time, which is why the
// stream-resume machinery never once ran.
// INVARIANT: this MUST stay above SLOW_IDLE_TIMEOUT_MS (90s) or the
// plugin's resume path is silently dead again. It is kept at all only so
// a bug in the plugin's idle timer cannot hang opencode forever.
// Still deliberately no `timeout` / `headerTimeout`: opencode measures
// those around the patched fetch, so they would include the pacer's own
// queue and cooldown waits and fire spuriously. The headers case is
// handled in the plugin (SAIA_TIMEOUT_MS), where only real network time
// is measured.
"chunkTimeout": 150000
}
}
},
"agent": {
"plan": {
// No temperature: opencode's own default (`ke.temperature`) returns
// nothing for SAIA models, so omitting it leaves the provider default
// alone (DeepSeek reasoners want it). Note opencode DOES inject
// top_p 0.95 here regardless — topP is not capability-gated. No steps
// cap either: long autonomous runs must not be cut off mid-task — the
// plugin's budget pacer is the runaway guard.
"color": "warning"
},
// Stub so the plugin's ROLE_MODELS can pin the built-in build agent's
// model (the plugin skips roles absent from config.agent).
// temperature 0.2: an explicit choice, not an override — opencode injects
// no temperature for these models. Matches @coder for deterministic
// implementation. Only reaches the wire because the plugin declares
// `temperature: true` per model; without that opencode drops the field.
// No steps cap, same reason as plan.
"build": {
"temperature": 0.2
},
// opencode's native subagents. They are defined in opencode's own code, not
// in config, so these empty stubs exist ONLY so the plugin's ROLE_MODELS can
// pin them a model. NEVER give them an agent/*.md file: opencode applies
// `prompt = <file body>` unconditionally, so an empty body would overwrite
// their built-in system prompts with "".
// The SAIA subagents (coder, coder2, researcher, debugger) live in agent/*.md
// — auto-discovered, always installed, never touched by the installer's
// filter. Adding one needs no edit here and no edit to any primary.
"general": {},
"explore": {},
"solo": {
"description": "Default workhorse: plans, implements, self-checks in one session, then independent @debugger validation (~5-12 requests/task)",
"mode": "primary",
"model": "saia-gwdg/glm-5.3-flash",
"temperature": 0.2,
"steps": 60,
"prompt": "{file:./prompts/solo.md}",
"permission": {
"edit": "allow",
"bash": "allow",
"write": "allow",
"task": {
// "*" MUST come first: opencode resolves these last-match-wins, so a
// trailing "*" would deny every subagent and remove the task tool.
"*": "deny",
"debugger": "allow"
}
},
"tools": {
"skill": false,
"todowrite": false,
"webfetch": false
}
},
"auto": {
"description": "Orchestrator for big/ambiguous multi-file tasks: plan → implement → validate loop (max 1 fix round)",
"mode": "primary",
"model": "saia-gwdg/qwen3.8-27b",
"temperature": 0.2,
"steps": 40,
"prompt": "{file:./prompts/auto.md}",
"permission": {
"read": "allow",
"glob": "allow",
"grep": "allow",
"list": "allow",
"edit": "deny",
"bash": {
// Read-only commands allowed for auto inspection
"ls *": "allow",
"git status *": "allow",
"git diff *": "allow",
"git log *": "allow",
"git show *": "allow",
"git grep *": "allow",
"rg *": "allow",
"cat *": "allow",
"wc *": "allow",
"find *": "allow",
"pwd": "allow",
"echo *": "allow",
"head *": "allow",
"tail *": "allow",
// Mutating commands denied
"git add *": "deny",
"git commit *": "deny",
"git push *": "deny",
"git reset *": "deny",
"git checkout *": "deny",
"git clean *": "deny",
"rm *": "deny",
"mv *": "deny",
"cp *": "deny",
"mkdir *": "deny",
"touch *": "deny",
"chmod *": "deny",
"chown *": "deny",
"npm *": "deny",
"pip *": "deny",
"cargo *": "deny",
"make *": "deny",
"tee *": "deny",
"sed *": "deny",
"awk *": "deny",
// Catch-all: deny anything not explicitly allowlisted
"*": "deny"
},
"write": "deny",
"task": {
// Allow-by-exception: every subagent shipped in agent/*.md is taskable
// without editing this file — that is the point. "*" MUST stay FIRST:
// opencode resolves these last-match-wins (Permission.findLast), so a
// trailing "*" would override the denies below and re-allow them.
"*": "allow",
// The natives are the failure mode actually observed: under task
// pressure auto substituted @general/@explore for its own roles.
// Denying them here also removes them from the task tool's generated
// agent list, so the model never sees them as an option.
"general": "deny",
"explore": "deny"
}
},
"tools": {
"skill": false,
"todowrite": false,
"webfetch": false
}
}
}
}