oh-my-opencode 0.1.14 → 0.1.16
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/README.ko.md +12 -77
- package/README.md +12 -90
- package/dist/index.js +85 -7
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -96,76 +96,9 @@ OpenCode 가 낭만이 사라진것같은 오늘날의 시대에, 당신에게
|
|
|
96
96
|
|
|
97
97
|
### Agent 설정
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
`agents` 옵션으로 에이전트의 모델, 프롬프트, 권한 등을 세밀하게 조정할 수 있습니다. 스키마를 통해 자동완성을 지원합니다.
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
| 옵션 | 설명 |
|
|
104
|
-
|------|------|
|
|
105
|
-
| `model` | 사용할 모델 ID (예: `anthropic/claude-sonnet-4`) |
|
|
106
|
-
| `temperature` | 창의성 조절 (0.0 ~ 2.0) |
|
|
107
|
-
| `top_p` | 단어 선택 다양성 (0.0 ~ 1.0) |
|
|
108
|
-
| `prompt` | 시스템 프롬프트 오버라이드 |
|
|
109
|
-
| `tools` | 특정 도구 활성화/비활성화 (`{"tool_name": false}`) |
|
|
110
|
-
| `disable` | 에이전트 비활성화 (`true`/`false`) |
|
|
111
|
-
| `description` | 에이전트 설명 수정 |
|
|
112
|
-
| `mode` | 에이전트 모드 (`subagent`, `primary`, `all`) |
|
|
113
|
-
| `color` | 터미널 출력 색상 (HEX 코드) |
|
|
114
|
-
| `permission` | 권한 설정 (아래 표 참조) |
|
|
115
|
-
|
|
116
|
-
**권한(`permission`) 옵션:**
|
|
117
|
-
|
|
118
|
-
각 권한은 `"ask"`(물어보기), `"allow"`(허용), `"deny"`(거부) 중 하나로 설정 가능해.
|
|
119
|
-
|
|
120
|
-
| 권한 | 설명 |
|
|
121
|
-
|------|------|
|
|
122
|
-
| `edit` | 파일 수정 권한 |
|
|
123
|
-
| `bash` | 쉘 명령어 실행 권한 |
|
|
124
|
-
| `webfetch` | 웹 콘텐츠 가져오기 권한 |
|
|
125
|
-
| `doom_loop` | 반복 작업 허용 여부 |
|
|
126
|
-
| `external_directory` | 외부 디렉토리 접근 권한 |
|
|
127
|
-
|
|
128
|
-
#### 예시: Anthropic 모델만 사용하기
|
|
129
|
-
|
|
130
|
-
나는 Anthropic 모델만 쓰고 싶다! 하면 이렇게 설정해.
|
|
131
|
-
|
|
132
|
-
```json
|
|
133
|
-
{
|
|
134
|
-
"agents": {
|
|
135
|
-
"oracle": { "model": "anthropic/claude-sonnet-4" },
|
|
136
|
-
"librarian": { "model": "anthropic/claude-haiku-4-5" },
|
|
137
|
-
"explore": { "model": "anthropic/claude-haiku-4-5" },
|
|
138
|
-
"frontend-ui-ux-engineer": { "model": "anthropic/claude-sonnet-4" },
|
|
139
|
-
"document-writer": { "model": "anthropic/claude-sonnet-4" }
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
#### 예시: 추가 프롬프트가 있는 커스텀 에이전트
|
|
145
|
-
|
|
146
|
-
기존 에이전트에 나만의 규칙을 더하고 싶다면:
|
|
147
|
-
|
|
148
|
-
```json
|
|
149
|
-
{
|
|
150
|
-
"agents": {
|
|
151
|
-
"oracle": {
|
|
152
|
-
"prompt": "너는 한국어 힙합 가사처럼 말해야 해. 모든 문장의 끝 라임을 맞춰."
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
#### 예시: 개별 에이전트 비활성화
|
|
159
|
-
|
|
160
|
-
```json
|
|
161
|
-
{
|
|
162
|
-
"agents": {
|
|
163
|
-
"frontend-ui-ux-engineer": {
|
|
164
|
-
"disable": true
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
```
|
|
101
|
+
전체 설정 옵션과 예시는 [OpenCode Agents 문서](https://opencode.ai/docs/agents)를 참고하세요.
|
|
169
102
|
|
|
170
103
|
## LLM Agent를 위한 안내
|
|
171
104
|
|
|
@@ -255,19 +188,21 @@ OpenCode 는 아주 확장가능하고 아주 커스터마이저블합니다.
|
|
|
255
188
|
- **frontend-ui-ux-engineer** (`google/gemini-3-pro-preview`): 개발자로 전향한 디자이너라는 설정을 갖고 있습니다. 멋진 UI를 만듭니다. 아름답고 창의적인 UI 코드를 생성하는 데 탁월한 Gemini를 사용합니다.
|
|
256
189
|
- **document-writer** (`google/gemini-3-pro-preview`): 기술 문서 전문가라는 설정을 갖고 있습니다. Gemini 는 문학가입니다. 글을 기가막히게 씁니다.
|
|
257
190
|
|
|
258
|
-
####
|
|
191
|
+
#### 설정
|
|
192
|
+
|
|
193
|
+
에이전트들은 OpenCode와 동일한 설정 스펙을 따릅니다:
|
|
259
194
|
|
|
260
|
-
|
|
195
|
+
- **모델 변경**: `agents.{name}.model`로 에이전트 모델 오버라이드. [OpenCode Models](https://opencode.ai/docs/models/#configure-models) 참고.
|
|
196
|
+
- **MCP 비활성화**: `disabled_mcps`로 내장 MCP 끄기. [OpenCode MCP Servers](https://opencode.ai/docs/mcp-servers) 참고.
|
|
197
|
+
- **에이전트 비활성화**: `disabled_agents` 또는 `agents.{name}.disable` 사용. [OpenCode Agents](https://opencode.ai/docs/agents) 참고.
|
|
198
|
+
|
|
199
|
+
권장하진 않지만(이 플러그인은 멀티 모델 오케스트레이션용), Anthropic만 사용하는 경우 예시:
|
|
261
200
|
|
|
262
201
|
```json
|
|
263
202
|
{
|
|
264
203
|
"agents": {
|
|
265
|
-
"explore": {
|
|
266
|
-
|
|
267
|
-
},
|
|
268
|
-
"frontend-ui-ux-engineer": {
|
|
269
|
-
"model": "anthropic/claude-opus-4"
|
|
270
|
-
}
|
|
204
|
+
"explore": { "model": "anthropic/claude-haiku-4-5" },
|
|
205
|
+
"frontend-ui-ux-engineer": { "model": "anthropic/claude-opus-4" }
|
|
271
206
|
}
|
|
272
207
|
}
|
|
273
208
|
```
|
package/README.md
CHANGED
|
@@ -146,89 +146,9 @@ Available agents: `oracle`, `librarian`, `explore`, `frontend-ui-ux-engineer`, `
|
|
|
146
146
|
|
|
147
147
|
### Agent Configuration
|
|
148
148
|
|
|
149
|
-
You can override
|
|
149
|
+
You can override any built-in agent's model, prompt, permissions, and more using the `agents` option. Configuration uses autocomplete via schema.
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
| Option | Type | Description |
|
|
154
|
-
|--------|------|-------------|
|
|
155
|
-
| `model` | string | Override the default model (e.g., "anthropic/claude-sonnet-4") |
|
|
156
|
-
| `temperature` | number (0-2) | Controls randomness (0 = deterministic, 2 = creative) |
|
|
157
|
-
| `top_p` | number (0-1) | Nucleus sampling parameter |
|
|
158
|
-
| `prompt` | string | Additional system prompt to append |
|
|
159
|
-
| `tools` | object | Enable/disable specific tools (e.g., `{"websearch_exa": false}`) |
|
|
160
|
-
| `disable` | boolean | Completely disable the agent |
|
|
161
|
-
| `description` | string | Override agent description |
|
|
162
|
-
| `mode` | "subagent" | "primary" | "all" | When agent is available |
|
|
163
|
-
| `color` | string | Hex color code for terminal output (e.g., "#FF0000") |
|
|
164
|
-
| `permission` | object | Permission settings for sensitive operations |
|
|
165
|
-
|
|
166
|
-
#### Permission Options
|
|
167
|
-
|
|
168
|
-
| Option | Values | Description |
|
|
169
|
-
|--------|--------|-------------|
|
|
170
|
-
| `edit` | "ask" | "allow" | "deny" | File modification permissions |
|
|
171
|
-
| `bash` | "ask" | "allow" | "deny" | object | Shell command execution permissions |
|
|
172
|
-
| `webfetch` | "ask" | "allow" | "deny" | Web access permissions |
|
|
173
|
-
| `doom_loop` | "ask" | "allow" | "deny" | Infinite loop prevention |
|
|
174
|
-
| `external_directory` | "ask" | "allow" | "deny" | Access outside project root |
|
|
175
|
-
|
|
176
|
-
#### Examples
|
|
177
|
-
|
|
178
|
-
**Using Only Anthropic Models**
|
|
179
|
-
|
|
180
|
-
This configuration forces all agents to use Anthropic models, suitable for users with only Anthropic API access.
|
|
181
|
-
|
|
182
|
-
```json
|
|
183
|
-
{
|
|
184
|
-
"agents": {
|
|
185
|
-
"oracle": {
|
|
186
|
-
"model": "anthropic/claude-sonnet-4"
|
|
187
|
-
},
|
|
188
|
-
"librarian": {
|
|
189
|
-
"model": "anthropic/claude-haiku-4-5"
|
|
190
|
-
},
|
|
191
|
-
"explore": {
|
|
192
|
-
"model": "anthropic/claude-haiku-4-5"
|
|
193
|
-
},
|
|
194
|
-
"frontend-ui-ux-engineer": {
|
|
195
|
-
"model": "anthropic/claude-sonnet-4"
|
|
196
|
-
},
|
|
197
|
-
"document-writer": {
|
|
198
|
-
"model": "anthropic/claude-sonnet-4"
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Custom Agent with Additional Prompt**
|
|
205
|
-
|
|
206
|
-
Inject custom instructions into an agent's system prompt.
|
|
207
|
-
|
|
208
|
-
```json
|
|
209
|
-
{
|
|
210
|
-
"agents": {
|
|
211
|
-
"frontend-ui-ux-engineer": {
|
|
212
|
-
"prompt": "ALWAYS use Tailwind CSS. NEVER use inline styles. Prefer dark mode defaults.",
|
|
213
|
-
"temperature": 0.8
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
**Disable Agents Individually**
|
|
220
|
-
|
|
221
|
-
You can also disable agents using the `disable` property within the agent config.
|
|
222
|
-
|
|
223
|
-
```json
|
|
224
|
-
{
|
|
225
|
-
"agents": {
|
|
226
|
-
"explore": {
|
|
227
|
-
"disable": true
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
```
|
|
151
|
+
For full configuration options and examples, see the [OpenCode Agents documentation](https://opencode.ai/docs/agents).
|
|
232
152
|
|
|
233
153
|
## Why OpenCode & Why Oh My OpenCode
|
|
234
154
|
|
|
@@ -265,19 +185,21 @@ I believe in the right tool for the job. For your wallet's sake, use CLIProxyAPI
|
|
|
265
185
|
- **frontend-ui-ux-engineer** (`google/gemini-3-pro-preview`): A designer turned developer. Creates stunning UIs. Uses Gemini because its creativity and UI code generation are superior.
|
|
266
186
|
- **document-writer** (`google/gemini-3-pro-preview`): A technical writing expert. Gemini is a wordsmith; it writes prose that flows naturally.
|
|
267
187
|
|
|
268
|
-
####
|
|
188
|
+
#### Configuration
|
|
189
|
+
|
|
190
|
+
Agents follow the same configuration spec as OpenCode:
|
|
191
|
+
|
|
192
|
+
- **Change models**: Override any agent's model via `agents.{name}.model`. See [OpenCode Models](https://opencode.ai/docs/models/#configure-models).
|
|
193
|
+
- **Disable MCPs**: Use `disabled_mcps` to turn off built-in MCPs. See [OpenCode MCP Servers](https://opencode.ai/docs/mcp-servers).
|
|
194
|
+
- **Disable agents**: Use `disabled_agents` or `agents.{name}.disable`. See [OpenCode Agents](https://opencode.ai/docs/agents).
|
|
269
195
|
|
|
270
|
-
|
|
196
|
+
While not generally recommended (this plugin is designed for multi-model orchestration), here's an example for Anthropic-only users:
|
|
271
197
|
|
|
272
198
|
```json
|
|
273
199
|
{
|
|
274
200
|
"agents": {
|
|
275
|
-
"explore": {
|
|
276
|
-
|
|
277
|
-
},
|
|
278
|
-
"frontend-ui-ux-engineer": {
|
|
279
|
-
"model": "anthropic/claude-opus-4"
|
|
280
|
-
}
|
|
201
|
+
"explore": { "model": "anthropic/claude-haiku-4-5" },
|
|
202
|
+
"frontend-ui-ux-engineer": { "model": "anthropic/claude-opus-4" }
|
|
281
203
|
}
|
|
282
204
|
}
|
|
283
205
|
```
|
package/dist/index.js
CHANGED
|
@@ -893,14 +893,71 @@ async function recoverThinkingDisabledViolation(client, sessionID, failedAssista
|
|
|
893
893
|
} catch {}
|
|
894
894
|
return false;
|
|
895
895
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
const
|
|
899
|
-
if (!
|
|
896
|
+
var THINKING_TYPES = new Set(["thinking", "redacted_thinking", "reasoning"]);
|
|
897
|
+
function hasNonEmptyOutput(msg) {
|
|
898
|
+
const parts = msg.parts;
|
|
899
|
+
if (!parts || parts.length === 0)
|
|
900
|
+
return false;
|
|
901
|
+
return parts.some((p) => {
|
|
902
|
+
if (THINKING_TYPES.has(p.type))
|
|
903
|
+
return false;
|
|
904
|
+
if (p.type === "step-start" || p.type === "step-finish")
|
|
905
|
+
return false;
|
|
906
|
+
if (p.type === "text" && p.text && p.text.trim())
|
|
907
|
+
return true;
|
|
908
|
+
if (p.type === "tool_use" && p.id)
|
|
909
|
+
return true;
|
|
910
|
+
if (p.type === "tool_result")
|
|
911
|
+
return true;
|
|
900
912
|
return false;
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
function findEmptyContentMessage(msgs) {
|
|
916
|
+
for (let i = 0;i < msgs.length; i++) {
|
|
917
|
+
const msg = msgs[i];
|
|
918
|
+
const isLastMessage = i === msgs.length - 1;
|
|
919
|
+
const isAssistant = msg.info?.role === "assistant";
|
|
920
|
+
if (isLastMessage && isAssistant)
|
|
921
|
+
continue;
|
|
922
|
+
if (!hasNonEmptyOutput(msg)) {
|
|
923
|
+
return msg;
|
|
924
|
+
}
|
|
901
925
|
}
|
|
902
|
-
|
|
926
|
+
return null;
|
|
927
|
+
}
|
|
928
|
+
async function recoverEmptyContentMessage(client, sessionID, failedAssistantMsg, directory) {
|
|
903
929
|
try {
|
|
930
|
+
const messagesResp = await client.session.messages({
|
|
931
|
+
path: { id: sessionID },
|
|
932
|
+
query: { directory }
|
|
933
|
+
});
|
|
934
|
+
const msgs = messagesResp.data;
|
|
935
|
+
if (!msgs || msgs.length === 0)
|
|
936
|
+
return false;
|
|
937
|
+
const emptyMsg = findEmptyContentMessage(msgs) || failedAssistantMsg;
|
|
938
|
+
const messageID = emptyMsg.info?.id;
|
|
939
|
+
if (!messageID)
|
|
940
|
+
return false;
|
|
941
|
+
const existingParts = emptyMsg.parts || [];
|
|
942
|
+
const hasOnlyThinkingOrMeta = existingParts.length > 0 && existingParts.every((p) => THINKING_TYPES.has(p.type) || p.type === "step-start" || p.type === "step-finish");
|
|
943
|
+
if (hasOnlyThinkingOrMeta) {
|
|
944
|
+
const strippedParts = [{ type: "text", text: "(interrupted)" }];
|
|
945
|
+
try {
|
|
946
|
+
await client.message?.update?.({
|
|
947
|
+
path: { id: messageID },
|
|
948
|
+
body: { parts: strippedParts }
|
|
949
|
+
});
|
|
950
|
+
return true;
|
|
951
|
+
} catch {}
|
|
952
|
+
try {
|
|
953
|
+
await client.session.patch?.({
|
|
954
|
+
path: { id: sessionID },
|
|
955
|
+
body: { messageID, parts: strippedParts }
|
|
956
|
+
});
|
|
957
|
+
return true;
|
|
958
|
+
} catch {}
|
|
959
|
+
}
|
|
960
|
+
const revertTargetID = emptyMsg.info?.parentID || messageID;
|
|
904
961
|
await client.session.revert({
|
|
905
962
|
path: { id: sessionID },
|
|
906
963
|
body: { messageID: revertTargetID },
|
|
@@ -15494,10 +15551,30 @@ function showOutputToUser(context, output) {
|
|
|
15494
15551
|
const ctx = context;
|
|
15495
15552
|
ctx.metadata?.({ metadata: { output } });
|
|
15496
15553
|
}
|
|
15554
|
+
var JS_TS_LANGUAGES = ["javascript", "typescript", "tsx"];
|
|
15555
|
+
function validatePatternForCli(pattern, lang) {
|
|
15556
|
+
if (!JS_TS_LANGUAGES.includes(lang)) {
|
|
15557
|
+
return;
|
|
15558
|
+
}
|
|
15559
|
+
const src = pattern.trim();
|
|
15560
|
+
const incompleteFunctionDecl = /^(export\s+)?(default\s+)?(async\s+)?function\s+\$[A-Z_][A-Z0-9_]*\s*$/i.test(src);
|
|
15561
|
+
if (incompleteFunctionDecl) {
|
|
15562
|
+
throw new Error(`Incomplete AST pattern for ${lang}: "${pattern}"
|
|
15563
|
+
|
|
15564
|
+
` + `ast-grep requires complete AST nodes. Function declarations must include parameters and body.
|
|
15565
|
+
|
|
15566
|
+
` + `Examples of correct patterns:
|
|
15567
|
+
` + ` - "export async function $NAME($$$) { $$$ }" (matches export async functions)
|
|
15568
|
+
` + ` - "function $NAME($$$) { $$$ }" (matches all function declarations)
|
|
15569
|
+
` + ` - "async function $NAME($$$) { $$$ }" (matches async functions)
|
|
15570
|
+
|
|
15571
|
+
` + `Your pattern "${pattern}" is missing the parameter list and body.`);
|
|
15572
|
+
}
|
|
15573
|
+
}
|
|
15497
15574
|
var ast_grep_search = tool({
|
|
15498
|
-
description: "Search code patterns across filesystem using AST-aware matching. Supports 25 languages. " + "Use meta-variables: $VAR (single node), $$$ (multiple nodes). " + "Examples: 'console.log($MSG)', 'def $FUNC($$$):', 'async function $NAME($$$)'",
|
|
15575
|
+
description: "Search code patterns across filesystem using AST-aware matching. Supports 25 languages. " + "Use meta-variables: $VAR (single node), $$$ (multiple nodes). " + "IMPORTANT: Patterns must be complete AST nodes (valid code). " + "For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not 'export async function $NAME'. " + "Examples: 'console.log($MSG)', 'def $FUNC($$$):', 'async function $NAME($$$)'",
|
|
15499
15576
|
args: {
|
|
15500
|
-
pattern: tool.schema.string().describe("AST pattern with meta-variables ($VAR, $$$)"),
|
|
15577
|
+
pattern: tool.schema.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
|
|
15501
15578
|
lang: tool.schema.enum(CLI_LANGUAGES).describe("Target language"),
|
|
15502
15579
|
paths: tool.schema.array(tool.schema.string()).optional().describe("Paths to search (default: ['.'])"),
|
|
15503
15580
|
globs: tool.schema.array(tool.schema.string()).optional().describe("Include/exclude globs (prefix ! to exclude)"),
|
|
@@ -15505,6 +15582,7 @@ var ast_grep_search = tool({
|
|
|
15505
15582
|
},
|
|
15506
15583
|
execute: async (args, context) => {
|
|
15507
15584
|
try {
|
|
15585
|
+
validatePatternForCli(args.pattern, args.lang);
|
|
15508
15586
|
const matches = await runSg({
|
|
15509
15587
|
pattern: args.pattern,
|
|
15510
15588
|
lang: args.lang,
|