Compare commits
245 Commits
feat/renam
...
refactor/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
829c58ccb0 | ||
|
|
23df6bd255 | ||
|
|
7895361f42 | ||
|
|
90919bf359 | ||
|
|
32f2c688e7 | ||
|
|
e6d0484e57 | ||
|
|
abd62472cf | ||
|
|
b1e099130a | ||
|
|
09fb364bfb | ||
|
|
d1ff8b1e3f | ||
|
|
6e42b553cc | ||
|
|
02ab83f4d4 | ||
|
|
ce1bffbc4d | ||
|
|
4d4680be3c | ||
|
|
ce877ec0d8 | ||
|
|
ec20a82b4e | ||
|
|
5043cc21ac | ||
|
|
8df3a2876a | ||
|
|
087e33d086 | ||
|
|
46c6e1dcf6 | ||
|
|
5befb60229 | ||
|
|
55df2179b8 | ||
|
|
76420b36ab | ||
|
|
a15f6076bc | ||
|
|
7c0289d7bc | ||
|
|
5e9231e251 | ||
|
|
f04cc0fa9c | ||
|
|
613ef8eee8 | ||
|
|
99b398063c | ||
|
|
2af9324400 | ||
|
|
7a52639a1b | ||
|
|
5df54bced4 | ||
|
|
cd04e6a19e | ||
|
|
e974b151c1 | ||
|
|
6f213a0ac9 | ||
|
|
71004e88d3 | ||
|
|
5898d36321 | ||
|
|
90aa3e4489 | ||
|
|
2268ba45f9 | ||
|
|
aca9342722 | ||
|
|
a3519c3a14 | ||
|
|
e610d88558 | ||
|
|
ed09bf5462 | ||
|
|
1d48518b41 | ||
|
|
d6d4cece9d | ||
|
|
9d930656da | ||
|
|
f86b8b3336 | ||
|
|
1f5d7702ff | ||
|
|
1e70f64001 | ||
|
|
d4f962b55d | ||
|
|
fb085538eb | ||
|
|
e5c5438a44 | ||
|
|
a77a16c494 | ||
|
|
7761e48dca | ||
|
|
d7a1945b27 | ||
|
|
44fb114370 | ||
|
|
bf804b0626 | ||
|
|
c4aa380855 | ||
|
|
993bd51eac | ||
|
|
732743960f | ||
|
|
bff573488c | ||
|
|
77424f86c8 | ||
|
|
919f7e4092 | ||
|
|
78a3e985be | ||
|
|
42fb2548d6 | ||
|
|
bff74f4237 | ||
|
|
038b8a79ec | ||
|
|
0aa8bfe839 | ||
|
|
422eaa9ae0 | ||
|
|
63ebedc9a2 | ||
|
|
f0b5835459 | ||
|
|
2a495c2e8d | ||
|
|
0edb87b1c1 | ||
|
|
cca057dc0f | ||
|
|
e000a3bb0d | ||
|
|
c19fc4ba22 | ||
|
|
e0de06851d | ||
|
|
26ac413dd9 | ||
|
|
81c912cf04 | ||
|
|
9c348db450 | ||
|
|
2993b3255d | ||
|
|
0b77e2def0 | ||
|
|
bfa8fa2378 | ||
|
|
6ee680af99 | ||
|
|
d327334ded | ||
|
|
07d120a78d | ||
|
|
8b7b1c843a | ||
|
|
a1786f469d | ||
|
|
da77d8addf | ||
|
|
971912e065 | ||
|
|
af301ab29a | ||
|
|
984464470c | ||
|
|
535ecee318 | ||
|
|
32035d153e | ||
|
|
a0649616bf | ||
|
|
cb12b286c8 | ||
|
|
8e239e134c | ||
|
|
733676f1a9 | ||
|
|
d2e566ba9d | ||
|
|
6da4d2dae0 | ||
|
|
3b41191980 | ||
|
|
0b614b751c | ||
|
|
c56a01c15d | ||
|
|
d2d48fc9ff | ||
|
|
41a43c62fc | ||
|
|
cea8769a7f | ||
|
|
7fa2417c42 | ||
|
|
4bba924dad | ||
|
|
e691303919 | ||
|
|
d4aee20743 | ||
|
|
bad70f5e24 | ||
|
|
b9fa2a3ebc | ||
|
|
0e7bd595f8 | ||
|
|
0732cb85f9 | ||
|
|
500784a9b9 | ||
|
|
5e856b4fde | ||
|
|
03dc903e8e | ||
|
|
69d0b23ab6 | ||
|
|
ee8735cd2c | ||
|
|
d8fe61131c | ||
|
|
935995d270 | ||
|
|
23d8b88c4a | ||
|
|
b4285ce565 | ||
|
|
f9d354b63e | ||
|
|
370eb945ee | ||
|
|
6387065e6f | ||
|
|
bebdb97c21 | ||
|
|
b5e2ead4e1 | ||
|
|
91922dae36 | ||
|
|
cb3d8af995 | ||
|
|
0fb3e2063a | ||
|
|
b37b877c45 | ||
|
|
f854246d7f | ||
|
|
f1eaa7bf9b | ||
|
|
ed9b4a6329 | ||
|
|
a00a22ac4c | ||
|
|
8879581fc1 | ||
|
|
230ce835e5 | ||
|
|
10e56badb3 | ||
|
|
cddf78434c | ||
|
|
0078b736b9 | ||
|
|
6d7f69625b | ||
|
|
fda17dd161 | ||
|
|
c41d6fd912 | ||
|
|
6e9128e060 | ||
|
|
92509d8cfb | ||
|
|
331f7ec52b | ||
|
|
4ba2da7ebb | ||
|
|
f95d3b1ef5 | ||
|
|
d5d7c7dd26 | ||
|
|
6a56c0e241 | ||
|
|
94c234c88c | ||
|
|
2ab976c511 | ||
|
|
dc66088483 | ||
|
|
67b5f46a7c | ||
|
|
0e483d27ac | ||
|
|
f5eaa648e9 | ||
|
|
4c4760a4ee | ||
|
|
7f20dd6ff5 | ||
|
|
de371be236 | ||
|
|
f3c2138ef4 | ||
|
|
0810e37240 | ||
|
|
a64e364fa6 | ||
|
|
f16d55ad95 | ||
|
|
d886ac701f | ||
|
|
3c49bf3a8c | ||
|
|
29a7bc2d31 | ||
|
|
11f1d71c93 | ||
|
|
62d2704009 | ||
|
|
db32bad004 | ||
|
|
5777bf9894 | ||
|
|
30dc50d880 | ||
|
|
b17e633464 | ||
|
|
07ea8debdc | ||
|
|
eec268ee42 | ||
|
|
363661c0d6 | ||
|
|
0d52519293 | ||
|
|
031503bb8c | ||
|
|
5986583641 | ||
|
|
261bbdf4dc | ||
|
|
8aec4c5cb3 | ||
|
|
16cbc847ac | ||
|
|
436ce71dc8 | ||
|
|
3773e370ec | ||
|
|
23a30e86f2 | ||
|
|
0e610a72bc | ||
|
|
d2a49428b9 | ||
|
|
04637ff0f1 | ||
|
|
c3b23bf603 | ||
|
|
50094de73e | ||
|
|
3aa2748c04 | ||
|
|
ccaf759b6b | ||
|
|
521a1f76a9 | ||
|
|
490f0f2090 | ||
|
|
caf595e727 | ||
|
|
1f64a45113 | ||
|
|
9b2dc2189c | ||
|
|
071fab1618 | ||
|
|
f6c24e42af | ||
|
|
22fd976eb9 | ||
|
|
826284f3d9 | ||
|
|
3c7e6a3940 | ||
|
|
33ef4db502 | ||
|
|
458ec06b0e | ||
|
|
6b66f69433 | ||
|
|
ce8957e1e1 | ||
|
|
0d96e0d3bc | ||
|
|
a3db64b931 | ||
|
|
8859da5fef | ||
|
|
23c0ff60f2 | ||
|
|
4723319eef | ||
|
|
b8f3186d65 | ||
|
|
01e18f8773 | ||
|
|
1669c83782 | ||
|
|
09cfd0b408 | ||
|
|
d48ea025f0 | ||
|
|
c5c7ba4eed | ||
|
|
90aa3a306c | ||
|
|
c2f7d059d2 | ||
|
|
7a96a167e6 | ||
|
|
2da19fe608 | ||
|
|
952bd5338d | ||
|
|
719a58270b | ||
|
|
71b1f7e807 | ||
|
|
8adf6a2c47 | ||
|
|
5c6194372e | ||
|
|
399796cbe4 | ||
|
|
77c3ed1a1f | ||
|
|
82e25c845b | ||
|
|
c644930753 | ||
|
|
b79df5e018 | ||
|
|
6455b851b8 | ||
|
|
9346bc8379 | ||
|
|
7e3c36ee03 | ||
|
|
11d942f3a2 | ||
|
|
2b6b08345a | ||
|
|
abdd39da00 | ||
|
|
711aac0f0a | ||
|
|
f2b26e5346 | ||
|
|
a7a7799b44 | ||
|
|
1e0823a0fc | ||
|
|
edfa411684 | ||
|
|
6d8bc95fa6 | ||
|
|
229c6b0cdb | ||
|
|
3eb97110c6 |
26
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
26
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,24 +1,26 @@
|
||||
name: Bug Report
|
||||
description: Report a bug or unexpected behavior in oh-my-openagent
|
||||
description: Report a bug or unexpected behavior in oh-my-opencode
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "needs-triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-openagent/blob/dev/CONTRIBUTING.md#language-policy) for details.
|
||||
**Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy) for details.
|
||||
|
||||
- type: checkboxes
|
||||
id: prerequisites
|
||||
attributes:
|
||||
label: Prerequisites
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-openagent/blob/dev/CONTRIBUTING.md#language-policy))
|
||||
- label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy))
|
||||
required: true
|
||||
- label: I have searched existing issues to avoid duplicates
|
||||
required: true
|
||||
- label: I am using the latest version of oh-my-openagent
|
||||
- label: I am using the latest version of oh-my-opencode
|
||||
required: true
|
||||
- label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-openagent#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
|
||||
- label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-opencode#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
@@ -36,7 +38,8 @@ body:
|
||||
label: Steps to Reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Configure oh-my-openagent with...
|
||||
1. Configure oh-my-opencode with...
|
||||
2. Run command '...'
|
||||
3. See error...
|
||||
validations:
|
||||
required: true
|
||||
@@ -64,12 +67,15 @@ body:
|
||||
attributes:
|
||||
label: Doctor Output
|
||||
description: |
|
||||
**Required:** Run `bunx oh-my-openagent doctor` and paste the full output below.
|
||||
**Required:** Run `bunx oh-my-opencode doctor` and paste the full output below.
|
||||
This helps us diagnose your environment and configuration.
|
||||
placeholder: |
|
||||
Paste the output of: bunx oh-my-openagent doctor
|
||||
Paste the output of: bunx oh-my-opencode doctor
|
||||
|
||||
Example:
|
||||
✓ OpenCode version: 1.0.150
|
||||
✓ oh-my-openagent version: 1.2.3
|
||||
✓ oh-my-opencode version: 1.2.3
|
||||
✓ Plugin loaded successfully
|
||||
...
|
||||
render: shell
|
||||
validations:
|
||||
@@ -87,7 +93,7 @@ body:
|
||||
id: config
|
||||
attributes:
|
||||
label: Configuration
|
||||
description: If relevant, share your oh-my-openagent configuration (remove sensitive data)
|
||||
description: If relevant, share your oh-my-opencode configuration (remove sensitive data)
|
||||
placeholder: |
|
||||
{
|
||||
"agents": { ... },
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/config.yml
vendored
3
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -4,4 +4,5 @@ contact_links:
|
||||
url: https://discord.gg/PUwSMR9XNk
|
||||
about: Join our Discord server for real-time discussions and community support
|
||||
- name: Documentation
|
||||
url: https://github.com/code-yeongyu/oh-my-openagent#readme
|
||||
url: https://github.com/code-yeongyu/oh-my-opencode#readme
|
||||
about: Read the comprehensive documentation and guides
|
||||
|
||||
18
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
18
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,24 +1,26 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature or enhancement for oh-my-openagent
|
||||
description: Suggest a new feature or enhancement for oh-my-opencode
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement", "needs-triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-openagent/blob/dev/CONTRIBUTING.md#language-policy) for details.
|
||||
**Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy) for details.
|
||||
|
||||
- type: checkboxes
|
||||
id: prerequisites
|
||||
attributes:
|
||||
label: Prerequisites
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-openagent/blob/dev/CONTRIBUTING.md#language-policy))
|
||||
- label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy))
|
||||
required: true
|
||||
- label: I have searched existing issues and discussions to avoid duplicates
|
||||
required: true
|
||||
- label: This feature request is specific to oh-my-openagent (not OpenCode core)
|
||||
- label: This feature request is specific to oh-my-opencode (not OpenCode core)
|
||||
required: true
|
||||
- label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-openagent#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
|
||||
- label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-opencode#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
@@ -57,9 +59,11 @@ body:
|
||||
attributes:
|
||||
label: Doctor Output (Optional)
|
||||
description: |
|
||||
If relevant to your feature request, run `bunx oh-my-openagent doctor` and paste the output.
|
||||
If relevant to your feature request, run `bunx oh-my-opencode doctor` and paste the output.
|
||||
This helps us understand your environment.
|
||||
placeholder: |
|
||||
Paste the output of: bunx oh-my-openagent doctor
|
||||
Paste the output of: bunx oh-my-opencode doctor
|
||||
(Optional for feature requests)
|
||||
render: shell
|
||||
|
||||
- type: textarea
|
||||
|
||||
13
.github/ISSUE_TEMPLATE/general.yml
vendored
13
.github/ISSUE_TEMPLATE/general.yml
vendored
@@ -1,23 +1,24 @@
|
||||
name: Question or Discussion
|
||||
description: Ask a question or start a discussion about oh-my-openagent
|
||||
description: Ask a question or start a discussion about oh-my-opencode
|
||||
title: "[Question]: "
|
||||
labels: ["question", "needs-triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-openagent/blob/dev/CONTRIBUTING.md#language-policy) for details.
|
||||
**Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy) for details.
|
||||
|
||||
- type: checkboxes
|
||||
id: prerequisites
|
||||
attributes:
|
||||
label: Prerequisites
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-openagent/blob/dev/CONTRIBUTING.md#language-policy))
|
||||
- label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy))
|
||||
required: true
|
||||
- label: I have searched existing issues and discussions
|
||||
required: true
|
||||
- label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-openagent#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
|
||||
- label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-opencode#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
|
||||
required: true
|
||||
- label: This is a question (not a bug report or feature request)
|
||||
required: true
|
||||
@@ -52,9 +53,9 @@ body:
|
||||
attributes:
|
||||
label: Doctor Output (Optional)
|
||||
description: |
|
||||
If your question is about configuration or setup, run `bunx oh-my-openagent doctor` and paste the output.
|
||||
If your question is about configuration or setup, run `bunx oh-my-opencode doctor` and paste the output.
|
||||
placeholder: |
|
||||
Paste the output of: bunx oh-my-openagent doctor
|
||||
Paste the output of: bunx oh-my-opencode doctor
|
||||
(Optional for questions)
|
||||
render: shell
|
||||
|
||||
|
||||
BIN
.github/assets/building-in-public.png
vendored
Normal file
BIN
.github/assets/building-in-public.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 278 KiB |
5
.github/workflows/cla.yml
vendored
5
.github/workflows/cla.yml
vendored
@@ -23,11 +23,12 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
path-to-signatures: 'signatures/cla.json'
|
||||
path-to-document: 'https://github.com/code-yeongyu/oh-my-openagent/blob/master/CLA.md'
|
||||
path-to-document: 'https://github.com/code-yeongyu/oh-my-opencode/blob/master/CLA.md'
|
||||
branch: 'dev'
|
||||
allowlist: code-yeongyu,bot*,dependabot*,github-actions*,*[bot],sisyphus-dev-ai,web-flow
|
||||
custom-notsigned-prcomment: |
|
||||
Thank you for your contribution! Before we can merge this PR, we need you to sign our [Contributor License Agreement (CLA)](https://github.com/code-yeongyu/oh-my-openagent/blob/master/CLA.md).
|
||||
Thank you for your contribution! Before we can merge this PR, we need you to sign our [Contributor License Agreement (CLA)](https://github.com/code-yeongyu/oh-my-opencode/blob/master/CLA.md).
|
||||
|
||||
**To sign the CLA**, please comment on this PR with:
|
||||
```
|
||||
I have read the CLA Document and I hereby sign the CLA
|
||||
|
||||
95
.github/workflows/publish-platform.yml
vendored
95
.github/workflows/publish-platform.yml
vendored
@@ -216,10 +216,6 @@ jobs:
|
||||
retention-days: 1
|
||||
if-no-files-found: error
|
||||
|
||||
# =============================================================================
|
||||
# Job 2: Publish all platforms (oh-my-openagent + oh-my-opencode)
|
||||
# - Uses NODE_AUTH_TOKEN for auth + OIDC for provenance attestation
|
||||
# =============================================================================
|
||||
publish:
|
||||
needs: build
|
||||
if: always() && !cancelled()
|
||||
@@ -230,35 +226,38 @@ jobs:
|
||||
matrix:
|
||||
platform: [darwin-arm64, darwin-x64, darwin-x64-baseline, linux-x64, linux-x64-baseline, linux-arm64, linux-x64-musl, linux-x64-musl-baseline, linux-arm64-musl, windows-x64, windows-x64-baseline]
|
||||
steps:
|
||||
- name: Check if oh-my-openagent already published
|
||||
- name: Check if already published
|
||||
id: check
|
||||
run: |
|
||||
PKG_NAME="oh-my-openagent-${{ matrix.platform }}"
|
||||
VERSION="${{ inputs.version }}"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/${PKG_NAME}/${VERSION}")
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ ${PKG_NAME}@${VERSION} already published, skipping"
|
||||
|
||||
OC_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-opencode-${{ matrix.platform }}/${VERSION}")
|
||||
OA_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-openagent-${{ matrix.platform }}/${VERSION}")
|
||||
|
||||
if [ "$OC_STATUS" = "200" ]; then
|
||||
echo "skip_opencode=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ oh-my-opencode-${{ matrix.platform }}@${VERSION} already published"
|
||||
else
|
||||
echo "→ ${PKG_NAME}@${VERSION} will be published"
|
||||
echo "skip_opencode=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check if oh-my-opencode already published
|
||||
id: check-opencode
|
||||
run: |
|
||||
PKG_NAME="oh-my-opencode-${{ matrix.platform }}"
|
||||
VERSION="${{ inputs.version }}"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/${PKG_NAME}/${VERSION}")
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ ${PKG_NAME}@${VERSION} already published, skipping"
|
||||
|
||||
if [ "$OA_STATUS" = "200" ]; then
|
||||
echo "skip_openagent=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ oh-my-openagent-${{ matrix.platform }}@${VERSION} already published"
|
||||
else
|
||||
echo "→ ${PKG_NAME}@${VERSION} will be published"
|
||||
echo "skip_openagent=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Need artifact if either package needs publishing
|
||||
if [ "$OC_STATUS" = "200" ] && [ "$OA_STATUS" = "200" ]; then
|
||||
echo "skip_all=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "skip_all=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Download artifact
|
||||
id: download
|
||||
if: steps.check.outputs.skip != 'true' || steps.check-opencode.outputs.skip != 'true'
|
||||
if: steps.check.outputs.skip_all != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -266,7 +265,7 @@ jobs:
|
||||
path: .
|
||||
|
||||
- name: Extract artifact
|
||||
if: (steps.check.outputs.skip != 'true' || steps.check-opencode.outputs.skip != 'true') && steps.download.outcome == 'success'
|
||||
if: steps.check.outputs.skip_all != 'true' && steps.download.outcome == 'success'
|
||||
run: |
|
||||
PLATFORM="${{ matrix.platform }}"
|
||||
mkdir -p packages/${PLATFORM}
|
||||
@@ -282,43 +281,43 @@ jobs:
|
||||
ls -la packages/${PLATFORM}/bin/
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
if: (steps.check.outputs.skip != 'true' || steps.check-opencode.outputs.skip != 'true') && steps.download.outcome == 'success'
|
||||
if: steps.check.outputs.skip_all != 'true' && steps.download.outcome == 'success'
|
||||
with:
|
||||
node-version: "24"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
- name: Publish oh-my-opencode-${{ matrix.platform }}
|
||||
if: steps.check.outputs.skip_opencode != 'true' && steps.download.outcome == 'success'
|
||||
run: |
|
||||
cd packages/${{ matrix.platform }}
|
||||
|
||||
TAG_ARG=""
|
||||
if [ -n "${{ inputs.dist_tag }}" ]; then
|
||||
TAG_ARG="--tag ${{ inputs.dist_tag }}"
|
||||
fi
|
||||
|
||||
npm publish --access public --provenance $TAG_ARG
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
timeout-minutes: 15
|
||||
|
||||
- name: Publish oh-my-openagent-${{ matrix.platform }}
|
||||
if: steps.check.outputs.skip != 'true' && steps.download.outcome == 'success'
|
||||
if: steps.check.outputs.skip_openagent != 'true' && steps.download.outcome == 'success'
|
||||
run: |
|
||||
cd packages/${{ matrix.platform }}
|
||||
|
||||
TAG_ARG=""
|
||||
if [ -n "${{ inputs.dist_tag }}" ]; then
|
||||
TAG_ARG="--tag ${{ inputs.dist_tag }}"
|
||||
fi
|
||||
|
||||
npm publish --access public --provenance $TAG_ARG
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
timeout-minutes: 15
|
||||
|
||||
- name: Publish oh-my-opencode-${{ matrix.platform }} (alias)
|
||||
if: steps.check-opencode.outputs.skip != 'true' && steps.download.outcome == 'success'
|
||||
run: |
|
||||
cd packages/${{ matrix.platform }}
|
||||
|
||||
# Rename package for oh-my-opencode
|
||||
jq --arg name "oh-my-opencode-${{ matrix.platform }}" \
|
||||
--arg desc "Platform-specific binary for oh-my-opencode (${{ matrix.platform }})" \
|
||||
'.name = $name | .description = $desc | .bin = {"oh-my-opencode": (.bin | to_entries | .[0].value)}' \
|
||||
# Rename package for oh-my-openagent
|
||||
jq --arg name "oh-my-openagent-${{ matrix.platform }}" \
|
||||
--arg desc "Platform-specific binary for oh-my-openagent (${{ matrix.platform }})" \
|
||||
'.name = $name | .description = $desc | .bin = {"oh-my-openagent": (.bin | to_entries | .[0].value)}' \
|
||||
package.json > tmp.json && mv tmp.json package.json
|
||||
|
||||
|
||||
TAG_ARG=""
|
||||
if [ -n "${{ inputs.dist_tag }}" ]; then
|
||||
TAG_ARG="--tag ${{ inputs.dist_tag }}"
|
||||
fi
|
||||
|
||||
|
||||
npm publish --access public --provenance $TAG_ARG
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
|
||||
81
.github/workflows/publish.yml
vendored
81
.github/workflows/publish.yml
vendored
@@ -57,6 +57,7 @@ jobs:
|
||||
bun test src/cli/doctor/format-default.test.ts
|
||||
bun test src/tools/call-omo-agent/sync-executor.test.ts
|
||||
bun test src/tools/call-omo-agent/session-creator.test.ts
|
||||
bun test src/tools/session-manager
|
||||
bun test src/features/opencode-skill-loader/loader.test.ts
|
||||
bun test src/hooks/anthropic-context-window-limit-recovery/recovery-hook.test.ts
|
||||
bun test src/hooks/anthropic-context-window-limit-recovery/executor.test.ts
|
||||
@@ -66,9 +67,8 @@ jobs:
|
||||
# Enumerate subdirectories/files explicitly to EXCLUDE mock-heavy files
|
||||
# that were already run in isolation above.
|
||||
# Excluded from src/cli: doctor/formatter.test.ts, doctor/format-default.test.ts
|
||||
# Excluded from src/tools: call-omo-agent/sync-executor.test.ts, call-omo-agent/session-creator.test.ts
|
||||
# Excluded from src/tools: call-omo-agent/sync-executor.test.ts, call-omo-agent/session-creator.test.ts, session-manager (all)
|
||||
# Excluded from src/hooks/anthropic-context-window-limit-recovery: recovery-hook.test.ts, executor.test.ts
|
||||
# Excluded from src/tools: call-omo-agent/sync-executor.test.ts, call-omo-agent/session-creator.test.ts
|
||||
bun test bin script src/config src/mcp src/index.test.ts \
|
||||
src/agents src/shared \
|
||||
src/cli/run src/cli/config-manager src/cli/mcp-oauth \
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
src/cli/doctor/runner.test.ts src/cli/doctor/checks \
|
||||
src/tools/ast-grep src/tools/background-task src/tools/delegate-task \
|
||||
src/tools/glob src/tools/grep src/tools/interactive-bash \
|
||||
src/tools/look-at src/tools/lsp src/tools/session-manager \
|
||||
src/tools/look-at src/tools/lsp \
|
||||
src/tools/skill src/tools/skill-mcp src/tools/slashcommand src/tools/task \
|
||||
src/tools/call-omo-agent/background-agent-executor.test.ts \
|
||||
src/tools/call-omo-agent/background-executor.test.ts \
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
run: |
|
||||
VERSION="${{ inputs.version }}"
|
||||
if [ -z "$VERSION" ]; then
|
||||
PREV=$(curl -s https://registry.npmjs.org/oh-my-openagent/latest | jq -r '.version // "0.0.0"')
|
||||
PREV=$(curl -s https://registry.npmjs.org/oh-my-opencode/latest | jq -r '.version // "0.0.0"')
|
||||
BASE="${PREV%%-*}"
|
||||
IFS='.' read -r MAJOR MINOR PATCH <<< "$BASE"
|
||||
case "${{ inputs.bump }}" in
|
||||
@@ -175,10 +175,10 @@ jobs:
|
||||
id: check
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-openagent/${VERSION}")
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-opencode/${VERSION}")
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ oh-my-openagent@${VERSION} already published"
|
||||
echo "✓ oh-my-opencode@${VERSION} already published"
|
||||
else
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
@@ -204,27 +204,9 @@ jobs:
|
||||
bunx tsc --emitDeclarationOnly
|
||||
bun run build:schema
|
||||
|
||||
- name: Publish oh-my-openagent (primary)
|
||||
- name: Publish oh-my-opencode
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
run: |
|
||||
# Update package name to oh-my-openagent
|
||||
jq '.name = "oh-my-openagent"' package.json > tmp.json && mv tmp.json package.json
|
||||
|
||||
# Update optionalDependencies to use oh-my-openagent naming
|
||||
jq '.optionalDependencies = {
|
||||
"oh-my-openagent-darwin-arm64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-darwin-x64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-darwin-x64-baseline": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-linux-arm64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-linux-arm64-musl": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-linux-x64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-linux-x64-baseline": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-linux-x64-musl": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-linux-x64-musl-baseline": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-windows-x64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-openagent-windows-x64-baseline": "${{ steps.version.outputs.version }}"
|
||||
}' package.json > tmp.json && mv tmp.json package.json
|
||||
|
||||
TAG_ARG=""
|
||||
if [ -n "${{ steps.version.outputs.dist_tag }}" ]; then
|
||||
TAG_ARG="--tag ${{ steps.version.outputs.dist_tag }}"
|
||||
@@ -233,37 +215,46 @@ jobs:
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
- name: Publish oh-my-opencode (alias)
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
|
||||
- name: Check if oh-my-openagent already published
|
||||
id: check-openagent
|
||||
run: |
|
||||
# Update package name/bin to oh-my-opencode alias
|
||||
jq '.name = "oh-my-opencode" | .bin = {"oh-my-opencode": "bin/oh-my-openagent.js"}' package.json > tmp.json && mv tmp.json package.json
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-openagent/${VERSION}")
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ oh-my-openagent@${VERSION} already published"
|
||||
else
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Publish oh-my-openagent
|
||||
if: steps.check-openagent.outputs.skip != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
|
||||
# Update optionalDependencies to use oh-my-opencode naming
|
||||
jq '.optionalDependencies = {
|
||||
"oh-my-opencode-darwin-arm64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-darwin-x64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-darwin-x64-baseline": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-linux-arm64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-linux-arm64-musl": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-linux-x64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-linux-x64-baseline": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-linux-x64-musl": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-linux-x64-musl-baseline": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-windows-x64": "${{ steps.version.outputs.version }}",
|
||||
"oh-my-opencode-windows-x64-baseline": "${{ steps.version.outputs.version }}"
|
||||
}' package.json > tmp.json && mv tmp.json package.json
|
||||
# Update package name, version, and optionalDependencies for oh-my-openagent
|
||||
jq --arg v "$VERSION" '
|
||||
.name = "oh-my-openagent" |
|
||||
.version = $v |
|
||||
.optionalDependencies = (
|
||||
.optionalDependencies | to_entries |
|
||||
map(.key = (.key | sub("^oh-my-opencode-"; "oh-my-openagent-")) | .value = $v) |
|
||||
from_entries
|
||||
)
|
||||
' package.json > tmp.json && mv tmp.json package.json
|
||||
|
||||
TAG_ARG=""
|
||||
if [ -n "${{ steps.version.outputs.dist_tag }}" ]; then
|
||||
TAG_ARG="--tag ${{ steps.version.outputs.dist_tag }}"
|
||||
fi
|
||||
npm publish --access public --provenance $TAG_ARG || echo "oh-my-opencode alias publish may have failed (package may already exist)"
|
||||
npm publish --access public --provenance $TAG_ARG || echo "::warning::oh-my-openagent publish failed"
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
|
||||
- name: Restore package.json
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
if: steps.check-openagent.outputs.skip != 'true'
|
||||
run: |
|
||||
git checkout -- package.json
|
||||
|
||||
|
||||
46
.github/workflows/refresh-model-capabilities.yml
vendored
Normal file
46
.github/workflows/refresh-model-capabilities.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Refresh Model Capabilities
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "17 4 * * 1"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
refresh:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'code-yeongyu/oh-my-openagent'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
env:
|
||||
BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"
|
||||
|
||||
- name: Refresh bundled model capabilities snapshot
|
||||
run: bun run build:model-capabilities
|
||||
|
||||
- name: Validate capability guardrails
|
||||
run: bun run test:model-capabilities
|
||||
|
||||
- name: Create refresh pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
commit-message: "chore: refresh model capabilities snapshot"
|
||||
title: "chore: refresh model capabilities snapshot"
|
||||
body: |
|
||||
Automated refresh of `src/generated/model-capabilities.generated.json` from `https://models.dev/api.json`.
|
||||
|
||||
This keeps the bundled capability snapshot aligned with upstream model metadata without relying on manual refreshes.
|
||||
branch: automation/refresh-model-capabilities
|
||||
delete-branch: true
|
||||
labels: |
|
||||
maintenance
|
||||
14
.github/workflows/sisyphus-agent.yml
vendored
14
.github/workflows/sisyphus-agent.yml
vendored
@@ -69,14 +69,14 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bun-
|
||||
|
||||
# Build local oh-my-openagent
|
||||
- name: Build oh-my-openagent
|
||||
# Build local oh-my-opencode
|
||||
- name: Build oh-my-opencode
|
||||
run: |
|
||||
bun install
|
||||
bun run build
|
||||
|
||||
# Install OpenCode + configure local plugin + auth in single step
|
||||
- name: Setup OpenCode with oh-my-openagent
|
||||
- name: Setup OpenCode with oh-my-opencode
|
||||
env:
|
||||
OPENCODE_AUTH_JSON: ${{ secrets.OPENCODE_AUTH_JSON }}
|
||||
ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL }}
|
||||
@@ -102,14 +102,14 @@ jobs:
|
||||
fi
|
||||
opencode --version
|
||||
|
||||
# Run local oh-my-openagent install (uses built dist)
|
||||
# Run local oh-my-opencode install (uses built dist)
|
||||
bun run dist/cli/index.js install --no-tui --claude=max20 --openai=no --gemini=no --copilot=no
|
||||
|
||||
# Override plugin to use local file reference
|
||||
OPENCODE_JSON=~/.config/opencode/opencode.json
|
||||
REPO_PATH=$(pwd)
|
||||
jq --arg path "file://$REPO_PATH/src/index.ts" '
|
||||
.plugin = [.plugin[] | select(. != "oh-my-opencode" and . != "oh-my-openagent")] + [$path]
|
||||
.plugin = [.plugin[] | select(. != "oh-my-opencode")] + [$path]
|
||||
' "$OPENCODE_JSON" > /tmp/oc.json && mv /tmp/oc.json "$OPENCODE_JSON"
|
||||
|
||||
OPENCODE_JSON=~/.config/opencode/opencode.json
|
||||
@@ -190,7 +190,7 @@ jobs:
|
||||
}
|
||||
' "$OPENCODE_JSON" > /tmp/oc.json && mv /tmp/oc.json "$OPENCODE_JSON"
|
||||
|
||||
OMO_JSON=~/.config/opencode/oh-my-openagent.json
|
||||
OMO_JSON=~/.config/opencode/oh-my-opencode.json
|
||||
PROMPT_APPEND=$(cat << 'PROMPT_EOF'
|
||||
<ultrawork-mode>
|
||||
[CODE RED] Maximum precision required. Ultrathink before acting.
|
||||
@@ -397,7 +397,7 @@ jobs:
|
||||
--add-label "sisyphus: working" || true
|
||||
fi
|
||||
|
||||
- name: Run oh-my-openagent
|
||||
- name: Run oh-my-opencode
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||
USER_COMMENT: ${{ steps.context.outputs.comment }}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -36,3 +36,4 @@ test-injection/
|
||||
notepad.md
|
||||
oauth-success.html
|
||||
*.bun-build
|
||||
.omx/
|
||||
|
||||
@@ -79,47 +79,65 @@ Pass `REPO`, `REPORT_DIR`, and `COMMIT_SHA` to every subagent.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Fetch All Open Items
|
||||
---
|
||||
|
||||
<fetch>
|
||||
Paginate if 500 results returned.
|
||||
## Phase 1: Fetch All Open Items (CORRECTED)
|
||||
|
||||
**IMPORTANT:** `body` and `comments` fields may contain control characters that break jq parsing. Fetch basic metadata first, then fetch full details per-item in subagents.
|
||||
|
||||
```bash
|
||||
ISSUES=$(gh issue list --repo $REPO --state open --limit 500 \
|
||||
--json number,title,state,createdAt,updatedAt,labels,author,body,comments)
|
||||
ISSUE_LEN=$(echo "$ISSUES" | jq length)
|
||||
if [ "$ISSUE_LEN" -eq 500 ]; then
|
||||
LAST_DATE=$(echo "$ISSUES" | jq -r '.[-1].createdAt')
|
||||
# Step 1: Fetch basic metadata (without body/comments to avoid JSON parsing issues)
|
||||
ISSUES_LIST=$(gh issue list --repo $REPO --state open --limit 500 \
|
||||
--json number,title,labels,author,createdAt)
|
||||
ISSUE_COUNT=$(echo "$ISSUES_LIST" | jq length)
|
||||
|
||||
# Paginate if needed
|
||||
if [ "$ISSUE_COUNT" -eq 500 ]; then
|
||||
LAST_DATE=$(echo "$ISSUES_LIST" | jq -r '.[-1].createdAt')
|
||||
while true; do
|
||||
PAGE=$(gh issue list --repo $REPO --state open --limit 500 \
|
||||
--search "created:<$LAST_DATE" \
|
||||
--json number,title,state,createdAt,updatedAt,labels,author,body,comments)
|
||||
PAGE_LEN=$(echo "$PAGE" | jq length)
|
||||
[ "$PAGE_LEN" -eq 0 ] && break
|
||||
ISSUES=$(echo "[$ISSUES, $PAGE]" | jq -s 'add | unique_by(.number)')
|
||||
[ "$PAGE_LEN" -lt 500 ] && break
|
||||
--json number,title,labels,author,createdAt)
|
||||
PAGE_COUNT=$(echo "$PAGE" | jq length)
|
||||
[ "$PAGE_COUNT" -eq 0 ] && break
|
||||
ISSUES_LIST=$(echo "$ISSUES_LIST" "$PAGE" | jq -s '.[0] + .[1] | unique_by(.number)')
|
||||
ISSUE_COUNT=$(echo "$ISSUES_LIST" | jq length)
|
||||
[ "$PAGE_COUNT" -lt 500 ] && break
|
||||
LAST_DATE=$(echo "$PAGE" | jq -r '.[-1].createdAt')
|
||||
done
|
||||
fi
|
||||
|
||||
PRS=$(gh pr list --repo $REPO --state open --limit 500 \
|
||||
--json number,title,state,createdAt,updatedAt,labels,author,body,headRefName,baseRefName,isDraft,mergeable,reviewDecision,statusCheckRollup)
|
||||
PR_LEN=$(echo "$PRS" | jq length)
|
||||
if [ "$PR_LEN" -eq 500 ]; then
|
||||
LAST_DATE=$(echo "$PRS" | jq -r '.[-1].createdAt')
|
||||
# Same for PRs
|
||||
PRS_LIST=$(gh pr list --repo $REPO --state open --limit 500 \
|
||||
--json number,title,labels,author,headRefName,baseRefName,isDraft,createdAt)
|
||||
PR_COUNT=$(echo "$PRS_LIST" | jq length)
|
||||
|
||||
if [ "$PR_COUNT" -eq 500 ]; then
|
||||
LAST_DATE=$(echo "$PRS_LIST" | jq -r '.[-1].createdAt')
|
||||
while true; do
|
||||
PAGE=$(gh pr list --repo $REPO --state open --limit 500 \
|
||||
--search "created:<$LAST_DATE" \
|
||||
--json number,title,state,createdAt,updatedAt,labels,author,body,headRefName,baseRefName,isDraft,mergeable,reviewDecision,statusCheckRollup)
|
||||
PAGE_LEN=$(echo "$PAGE" | jq length)
|
||||
[ "$PAGE_LEN" -eq 0 ] && break
|
||||
PRS=$(echo "[$PRS, $PAGE]" | jq -s 'add | unique_by(.number)')
|
||||
[ "$PAGE_LEN" -lt 500 ] && break
|
||||
--json number,title,labels,author,headRefName,baseRefName,isDraft,createdAt)
|
||||
PAGE_COUNT=$(echo "$PAGE" | jq length)
|
||||
[ "$PAGE_COUNT" -eq 0 ] && break
|
||||
PRS_LIST=$(echo "$PRS_LIST" "$PAGE" | jq -s '.[0] + .[1] | unique_by(.number)')
|
||||
PR_COUNT=$(echo "$PRS_LIST" | jq length)
|
||||
[ "$PAGE_COUNT" -lt 500 ] && break
|
||||
LAST_DATE=$(echo "$PAGE" | jq -r '.[-1].createdAt')
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Total issues: $ISSUE_COUNT, Total PRs: $PR_COUNT"
|
||||
```
|
||||
</fetch>
|
||||
|
||||
**LARGE REPOSITORY HANDLING:**
|
||||
If total items exceeds 50, you MUST process ALL items. Use the pagination code above to fetch every single open issue and PR.
|
||||
**DO NOT** sample or limit to 50 items - process the entire backlog.
|
||||
|
||||
Example: If there are 500 open issues, spawn 500 subagents. If there are 1000 open PRs, spawn 1000 subagents.
|
||||
|
||||
**Note:** Background task system will queue excess tasks automatically.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
10
AGENTS.md
10
AGENTS.md
@@ -4,7 +4,7 @@
|
||||
|
||||
## OVERVIEW
|
||||
|
||||
OpenCode plugin (npm: `oh-my-opencode`) that extends Claude Code (OpenCode fork) with multi-agent orchestration, 46 lifecycle hooks, 26 tools, skill/command/MCP systems, and Claude Code compatibility. 1268 TypeScript files, 160k LOC.
|
||||
OpenCode plugin (npm: `oh-my-opencode`) that extends Claude Code (OpenCode fork) with multi-agent orchestration, 48 lifecycle hooks, 26 tools, skill/command/MCP systems, and Claude Code compatibility. 1268 TypeScript files, 160k LOC.
|
||||
|
||||
## STRUCTURE
|
||||
|
||||
@@ -14,14 +14,14 @@ oh-my-opencode/
|
||||
│ ├── index.ts # Plugin entry: loadConfig → createManagers → createTools → createHooks → createPluginInterface
|
||||
│ ├── plugin-config.ts # JSONC multi-level config: user → project → defaults (Zod v4)
|
||||
│ ├── agents/ # 11 agents (Sisyphus, Hephaestus, Oracle, Librarian, Explore, Atlas, Prometheus, Metis, Momus, Multimodal-Looker, Sisyphus-Junior)
|
||||
│ ├── hooks/ # 46 hooks across 45 directories + 11 standalone files
|
||||
│ ├── hooks/ # 48 lifecycle hooks across dedicated modules and standalone files
|
||||
│ ├── tools/ # 26 tools across 15 directories
|
||||
│ ├── features/ # 19 feature modules (background-agent, skill-loader, tmux, MCP-OAuth, etc.)
|
||||
│ ├── shared/ # 95+ utility files in 13 categories
|
||||
│ ├── config/ # Zod v4 schema system (24 files)
|
||||
│ ├── cli/ # CLI: install, run, doctor, mcp-oauth (Commander.js)
|
||||
│ ├── mcp/ # 3 built-in remote MCPs (websearch, context7, grep_app)
|
||||
│ ├── plugin/ # 8 OpenCode hook handlers + 46 hook composition
|
||||
│ ├── plugin/ # 8 OpenCode hook handlers + 48 hook composition
|
||||
│ └── plugin-handlers/ # 6-phase config loading pipeline
|
||||
├── packages/ # Monorepo: cli-runner, 12 platform binaries
|
||||
└── local-ignore/ # Dev-only test fixtures
|
||||
@@ -34,7 +34,7 @@ OhMyOpenCodePlugin(ctx)
|
||||
├─→ loadPluginConfig() # JSONC parse → project/user merge → Zod validate → migrate
|
||||
├─→ createManagers() # TmuxSessionManager, BackgroundManager, SkillMcpManager, ConfigHandler
|
||||
├─→ createTools() # SkillContext + AvailableCategories + ToolRegistry (26 tools)
|
||||
├─→ createHooks() # 3-tier: Core(37) + Continuation(7) + Skill(2) = 46 hooks
|
||||
├─→ createHooks() # 3-tier: Core(39) + Continuation(7) + Skill(2) = 48 hooks
|
||||
└─→ createPluginInterface() # 8 OpenCode hook handlers → PluginInterface
|
||||
```
|
||||
|
||||
@@ -97,7 +97,7 @@ Fields: agents (14 overridable, 21 fields each), categories (8 built-in + custom
|
||||
- **Test pattern**: Bun test (`bun:test`), co-located `*.test.ts`, given/when/then style (nested describe with `#given`/`#when`/`#then` prefixes)
|
||||
- **CI test split**: mock-heavy tests run in isolation (separate `bun test` processes), rest in batch
|
||||
- **Factory pattern**: `createXXX()` for all tools, hooks, agents
|
||||
- **Hook tiers**: Session (23) → Tool-Guard (10) → Transform (4) → Continuation (7) → Skill (2)
|
||||
- **Hook tiers**: Session (23) → Tool-Guard (12) → Transform (4) → Continuation (7) → Skill (2)
|
||||
- **Agent modes**: `primary` (respects UI model) vs `subagent` (own fallback chain) vs `all`
|
||||
- **Model resolution**: 4-step: override → category-default → provider-fallback → system-default
|
||||
- **Config format**: JSONC with comments, Zod v4 validation, snake_case keys
|
||||
|
||||
2
CLA.md
2
CLA.md
@@ -1,6 +1,6 @@
|
||||
# Contributor License Agreement
|
||||
|
||||
Thank you for your interest in contributing to oh-my-openagent ("Project"), owned by YeonGyu Kim ("Owner").
|
||||
Thank you for your interest in contributing to oh-my-opencode ("Project"), owned by YeonGyu Kim ("Owner").
|
||||
|
||||
By signing this Contributor License Agreement ("Agreement"), you agree to the following terms:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contributing to Oh My OpenCode
|
||||
|
||||
First off, thanks for taking the time to contribute! This document provides guidelines and instructions for contributing to oh-my-openagent.
|
||||
First off, thanks for taking the time to contribute! This document provides guidelines and instructions for contributing to oh-my-opencode.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@@ -87,19 +87,19 @@ After making changes, you can test your local build in OpenCode:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": ["file:///absolute/path/to/oh-my-openagent/dist/index.js"]
|
||||
"plugin": ["file:///absolute/path/to/oh-my-opencode/dist/index.js"]
|
||||
}
|
||||
```
|
||||
|
||||
For example, if your project is at `/Users/yourname/projects/oh-my-openagent`:
|
||||
For example, if your project is at `/Users/yourname/projects/oh-my-opencode`:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": ["file:///Users/yourname/projects/oh-my-openagent/dist/index.js"]
|
||||
"plugin": ["file:///Users/yourname/projects/oh-my-opencode/dist/index.js"]
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**: Remove `"oh-my-openagent"` from the plugin array if it exists, to avoid conflicts with the npm version.
|
||||
> **Note**: Remove `"oh-my-opencode"` from the plugin array if it exists, to avoid conflicts with the npm version.
|
||||
|
||||
3. **Restart OpenCode** to load the changes.
|
||||
|
||||
@@ -108,9 +108,9 @@ After making changes, you can test your local build in OpenCode:
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
oh-my-openagent/
|
||||
oh-my-opencode/
|
||||
├── src/
|
||||
│ ├── index.ts # Plugin entry (OhMyOpenAgentPlugin)
|
||||
│ ├── index.ts # Plugin entry (OhMyOpenCodePlugin)
|
||||
│ ├── plugin-config.ts # JSONC multi-level config (Zod v4)
|
||||
│ ├── agents/ # 11 agents (Sisyphus, Hephaestus, Oracle, Librarian, Explore, Atlas, Prometheus, Metis, Momus, Multimodal-Looker, Sisyphus-Junior)
|
||||
│ ├── hooks/ # Lifecycle hooks for orchestration, recovery, UX, and context management
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Portions of this software are licensed as follows:
|
||||
|
||||
- All third party components incorporated into the oh-my-openagent Software are licensed under the original license
|
||||
- All third party components incorporated into the oh-my-opencode Software are licensed under the original license
|
||||
provided by the owner of the applicable component.
|
||||
- Content outside of the above mentioned files or restrictions is available under the "Sustainable Use
|
||||
License" as defined below.
|
||||
|
||||
37
README.ja.md
37
README.ja.md
@@ -4,6 +4,17 @@
|
||||
> コアメンテナーのQが負傷したため、今週は Issue/PR への返信とリリースが遅れる可能性があります。
|
||||
> ご理解とご支援に感謝します。
|
||||
|
||||
> [!TIP]
|
||||
> **Building in Public**
|
||||
>
|
||||
> メンテナーが Jobdori を使い、oh-my-opencode をリアルタイムで開発・メンテナンスしています。Jobdori は OpenClaw をベースに大幅カスタマイズされた AI アシスタントです。
|
||||
> すべての機能開発、修正、Issue トリアージを Discord でライブでご覧いただけます。
|
||||
>
|
||||
> [](https://discord.gg/PUwSMR9XNk)
|
||||
>
|
||||
> [**→ #building-in-public で確認する**](https://discord.gg/PUwSMR9XNk)
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> [](https://sisyphuslabs.ai)
|
||||
@@ -12,18 +23,18 @@
|
||||
> [!TIP]
|
||||
> 私たちと一緒に!
|
||||
>
|
||||
> | [<img alt="Discord link" src="https://img.shields.io/discord/1452487457085063218?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square" width="156px" />](https://discord.gg/PUwSMR9XNk) | [Discordコミュニティ](https://discord.gg/PUwSMR9XNk)に参加して、コントリビューターや他の `oh-my-openagent` ユーザーと交流しましょう。 |
|
||||
> | [<img alt="Discord link" src="https://img.shields.io/discord/1452487457085063218?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square" width="156px" />](https://discord.gg/PUwSMR9XNk) | [Discordコミュニティ](https://discord.gg/PUwSMR9XNk)に参加して、コントリビューターや他の `oh-my-opencode` ユーザーと交流しましょう。 |
|
||||
> | :-----| :----- |
|
||||
> | [<img alt="X link" src="https://img.shields.io/badge/Follow-%40justsisyphus-00CED1?style=flat-square&logo=x&labelColor=black" width="156px" />](https://x.com/justsisyphus) | `oh-my-openagent` のニュースやアップデートは私のXアカウントで投稿されていましたが、 <br /> 誤って凍結されてしまったため、現在は [@justsisyphus](https://x.com/justsisyphus) が代わりにアップデートを投稿しています。 |
|
||||
> | [<img alt="X link" src="https://img.shields.io/badge/Follow-%40justsisyphus-00CED1?style=flat-square&logo=x&labelColor=black" width="156px" />](https://x.com/justsisyphus) | `oh-my-opencode` のニュースやアップデートは私のXアカウントで投稿されていましたが、 <br /> 誤って凍結されてしまったため、現在は [@justsisyphus](https://x.com/justsisyphus) が代わりにアップデートを投稿しています。 |
|
||||
> | [<img alt="GitHub Follow" src="https://img.shields.io/github/followers/code-yeongyu?style=flat-square&logo=github&labelColor=black&color=24292f" width="156px" />](https://github.com/code-yeongyu) | さらに多くのプロジェクトを見たい場合は、GitHubで [@code-yeongyu](https://github.com/code-yeongyu) をフォローしてください。 |
|
||||
|
||||
<!-- <CENTERED SECTION FOR GITHUB DISPLAY> -->
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-opencode)
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-opencode)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -34,7 +45,7 @@
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/releases)
|
||||
https://www.npmjs.com/package/oh-my-openagent
|
||||
[](https://www.npmjs.com/package/oh-my-opencode)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/graphs/contributors)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/network/members)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/stargazers)
|
||||
@@ -58,7 +69,7 @@ https://www.npmjs.com/package/oh-my-openagent
|
||||
|
||||
> 「Ohmyopencodeとralph loopを使って、45k行のtauriアプリを一晩でSaaSウェブアプリに変換しました。インタビューモードから始めて、私のプロンプトに対して質問や推奨事項を尋ねました。勝手に作業していくのを見るのは楽しかったし、今朝起きたらウェブサイトがほぼ動いているのを見て驚愕しました!」 - [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
> 「oh-my-openagentを使ってください。もう二度と元には戻れません。」 <br/>- [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
> 「oh-my-opencodeを使ってください。もう二度と元には戻れません。」 <br/>- [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
|
||||
> 「何がどうすごいのかまだ上手く言語化できないんですが、開発体験が完全に異次元に到達してしまいました。」 - [苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
|
||||
@@ -90,7 +101,7 @@ OmOをインストールして、`ultrawork`とタイプしてください。狂
|
||||
以下のプロンプトをコピーして、あなたのLLMエージェント(Claude Code、AmpCode、Cursorなど)に貼り付けてください:
|
||||
|
||||
```
|
||||
Install and configure oh-my-openagent by following the instructions here:
|
||||
Install and configure oh-my-opencode by following the instructions here:
|
||||
https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/refs/heads/dev/docs/guide/installation.md
|
||||
```
|
||||
|
||||
@@ -260,19 +271,19 @@ project/
|
||||
|
||||
> **背景のストーリーを知りたいですか?** なぜSisyphusは岩を転がすのか、なぜHephaestusは「正当なる職人」なのか、そして[オーケストレーションガイド](docs/guide/orchestration.md)をお読みください。
|
||||
>
|
||||
> oh-my-openagentは初めてですか?どのモデルを使うべきかについては、**[インストールガイド](docs/guide/installation.md#step-5-understand-your-model-setup)** で推奨モデルを確認してください。
|
||||
> oh-my-opencodeは初めてですか?どのモデルを使うべきかについては、**[インストールガイド](docs/guide/installation.md#step-5-understand-your-model-setup)** で推奨モデルを確認してください。
|
||||
|
||||
## アンインストール (Uninstallation)
|
||||
|
||||
oh-my-openagentを削除するには:
|
||||
oh-my-opencodeを削除するには:
|
||||
|
||||
1. **OpenCodeの設定からプラグインを削除する**
|
||||
|
||||
`~/.config/opencode/opencode.json`(または `opencode.jsonc`)を編集し、`plugin` 配列から `"oh-my-openagent"` を削除します:
|
||||
`~/.config/opencode/opencode.json`(または `opencode.jsonc`)を編集し、`plugin` 配列から `"oh-my-opencode"` を削除します:
|
||||
|
||||
```bash
|
||||
# jq を使用する場合
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-openagent")]' \
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-opencode")]' \
|
||||
~/.config/opencode/opencode.json > /tmp/oc.json && \
|
||||
mv /tmp/oc.json ~/.config/opencode/opencode.json
|
||||
```
|
||||
@@ -281,10 +292,10 @@ oh-my-openagentを削除するには:
|
||||
|
||||
```bash
|
||||
# ユーザー設定を削除
|
||||
rm -f ~/.config/opencode/oh-my-openagent.json ~/.config/opencode/oh-my-openagent.jsonc
|
||||
rm -f ~/.config/opencode/oh-my-opencode.json ~/.config/opencode/oh-my-opencode.jsonc
|
||||
|
||||
# プロジェクト設定を削除(存在する場合)
|
||||
rm -f .opencode/oh-my-openagent.json .opencode/oh-my-openagent.jsonc
|
||||
rm -f .opencode/oh-my-opencode.json .opencode/oh-my-opencode.jsonc
|
||||
```
|
||||
|
||||
3. **削除の確認**
|
||||
|
||||
37
README.ko.md
37
README.ko.md
@@ -4,21 +4,32 @@
|
||||
> 핵심 메인테이너 Q가 부상을 입어, 이번 주에는 이슈/PR 응답 및 릴리스가 지연될 수 있습니다.
|
||||
> 양해와 응원에 감사드립니다.
|
||||
|
||||
> [!TIP]
|
||||
> **Building in Public**
|
||||
>
|
||||
> 메인테이너가 Jobdori를 통해 oh-my-opencode를 실시간으로 개발하고 있습니다. Jobdori는 OpenClaw를 기반으로 대폭 커스터마이징된 AI 어시스턴트입니다.
|
||||
> 모든 기능 개발, 버그 수정, 이슈 트리아지를 Discord에서 실시간으로 확인하세요.
|
||||
>
|
||||
> [](https://discord.gg/PUwSMR9XNk)
|
||||
>
|
||||
> [**→ #building-in-public에서 확인하기**](https://discord.gg/PUwSMR9XNk)
|
||||
|
||||
|
||||
> [!TIP]
|
||||
> 저희와 함께 하세요!
|
||||
>
|
||||
> | [<img alt="Discord link" src="https://img.shields.io/discord/1452487457085063218?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square" width="156px" />](https://discord.gg/PUwSMR9XNk) | [Discord 커뮤니티](https://discord.gg/PUwSMR9XNk)에 가입하여 기여자 및 다른 `oh-my-openagent` 사용자들과 소통하세요. |
|
||||
> | [<img alt="Discord link" src="https://img.shields.io/discord/1452487457085063218?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square" width="156px" />](https://discord.gg/PUwSMR9XNk) | [Discord 커뮤니티](https://discord.gg/PUwSMR9XNk)에 가입하여 기여자 및 다른 `oh-my-opencode` 사용자들과 소통하세요. |
|
||||
> | :-----| :----- |
|
||||
> | [<img alt="X link" src="https://img.shields.io/badge/Follow-%40justsisyphus-00CED1?style=flat-square&logo=x&labelColor=black" width="156px" />](https://x.com/justsisyphus) | `oh-my-openagent`에 대한 소식과 업데이트는 제 X 계정에 올라왔었지만, <br /> 실수로 정지된 이후에는 [@justsisyphus](https://x.com/justsisyphus)가 대신 업데이트를 게시하고 있습니다. |
|
||||
> | [<img alt="X link" src="https://img.shields.io/badge/Follow-%40justsisyphus-00CED1?style=flat-square&logo=x&labelColor=black" width="156px" />](https://x.com/justsisyphus) | `oh-my-opencode`에 대한 소식과 업데이트는 제 X 계정에 올라왔었지만, <br /> 실수로 정지된 이후에는 [@justsisyphus](https://x.com/justsisyphus)가 대신 업데이트를 게시하고 있습니다. |
|
||||
> | [<img alt="GitHub Follow" src="https://img.shields.io/github/followers/code-yeongyu?style=flat-square&logo=github&labelColor=black&color=24292f" width="156px" />](https://github.com/code-yeongyu) | 더 많은 프로젝트를 보려면 GitHub에서 [@code-yeongyu](https://github.com/code-yeongyu)를 팔로우하세요. |
|
||||
|
||||
<!-- <CENTERED SECTION FOR GITHUB DISPLAY> -->
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-opencode)
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-opencode)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -29,7 +40,7 @@
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/releases)
|
||||
[](https://www.npmjs.com/package/oh-my-openagent)
|
||||
[](https://www.npmjs.com/package/oh-my-opencode)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/graphs/contributors)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/network/members)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/stargazers)
|
||||
@@ -53,7 +64,7 @@
|
||||
|
||||
> "Ohmyopencode와 ralph loop를 써서 45k 라인짜리 tauri 앱을 하룻밤 만에 SaaS 웹앱으로 변환했어요. 인터뷰 모드로 시작해서, 제가 쓴 프롬프트에 대해 질문하고 추천을 부탁했죠. 일하는 걸 지켜보는 것도 재밌었고, 아침에 일어났더니 웹사이트가 대부분 돌아가고 있는 걸 보고 경악했습니다!" - [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
> "oh-my-openagent 쓰세요, 다시는 예전으로 못 돌아갑니다." <br/>- [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
> "oh-my-opencode 쓰세요, 다시는 예전으로 못 돌아갑니다." <br/>- [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
|
||||
> "뭐가 이렇게 대단한 건지 아직 정확하게 말로 표현하긴 어려운데, 개발 경험 자체가 완전히 다른 차원에 도달해버렸어요." - [苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
|
||||
@@ -84,7 +95,7 @@ OmO 설치하고. `ultrawork` 치세요. 끝.
|
||||
다음 프롬프트를 복사해서 여러분의 LLM 에이전트(Claude Code, AmpCode, Cursor 등)에 붙여넣으세요:
|
||||
|
||||
```
|
||||
Install and configure oh-my-openagent by following the instructions here:
|
||||
Install and configure oh-my-opencode by following the instructions here:
|
||||
https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/refs/heads/dev/docs/guide/installation.md
|
||||
```
|
||||
|
||||
@@ -254,19 +265,19 @@ project/
|
||||
|
||||
> **비하인드 스토리가 궁금하신가요?** 왜 Sisyphus가 돌을 굴리는지, 왜 Hephaestus가 "진정한 장인"인지, 그리고 [오케스트레이션 가이드](docs/guide/orchestration.md)를 읽어보세요.
|
||||
>
|
||||
> oh-my-openagent가 처음이신가요? 어떤 모델을 써야 할지 **[설치 가이드](docs/guide/installation.md#step-5-understand-your-model-setup)** 에서 추천 조합을 확인하세요.
|
||||
> oh-my-opencode가 처음이신가요? 어떤 모델을 써야 할지 **[설치 가이드](docs/guide/installation.md#step-5-understand-your-model-setup)** 에서 추천 조합을 확인하세요.
|
||||
|
||||
## 제거 (Uninstallation)
|
||||
|
||||
oh-my-openagent를 지우려면:
|
||||
oh-my-opencode를 지우려면:
|
||||
|
||||
1. **OpenCode 설정에서 플러그인 제거**
|
||||
|
||||
`~/.config/opencode/opencode.json` (또는 `opencode.jsonc`)를 열고 `plugin` 배열에서 `"oh-my-openagent"`를 지우세요.
|
||||
`~/.config/opencode/opencode.json` (또는 `opencode.jsonc`)를 열고 `plugin` 배열에서 `"oh-my-opencode"`를 지우세요.
|
||||
|
||||
```bash
|
||||
# jq 사용 시
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-openagent")]' \
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-opencode")]' \
|
||||
~/.config/opencode/opencode.json > /tmp/oc.json && \
|
||||
mv /tmp/oc.json ~/.config/opencode/opencode.json
|
||||
```
|
||||
@@ -275,10 +286,10 @@ oh-my-openagent를 지우려면:
|
||||
|
||||
```bash
|
||||
# 사용자 설정 제거
|
||||
rm -f ~/.config/opencode/oh-my-openagent.json ~/.config/opencode/oh-my-openagent.jsonc
|
||||
rm -f ~/.config/opencode/oh-my-opencode.json ~/.config/opencode/oh-my-opencode.jsonc
|
||||
|
||||
# 프로젝트 설정 제거 (있는 경우)
|
||||
rm -f .opencode/oh-my-openagent.json .opencode/oh-my-openagent.jsonc
|
||||
rm -f .opencode/oh-my-opencode.json .opencode/oh-my-opencode.jsonc
|
||||
```
|
||||
|
||||
3. **제거 확인**
|
||||
|
||||
36
README.md
36
README.md
@@ -1,3 +1,13 @@
|
||||
> [!TIP]
|
||||
> **Building in Public**
|
||||
>
|
||||
> The maintainer builds and maintains oh-my-opencode in real-time with Jobdori, an AI assistant built on a heavily customized fork of OpenClaw.
|
||||
> Every feature, every fix, every issue triage — live in our Discord.
|
||||
>
|
||||
> [](https://discord.gg/PUwSMR9XNk)
|
||||
>
|
||||
> [**→ Watch it happen in #building-in-public**](https://discord.gg/PUwSMR9XNk)
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> [](https://sisyphuslabs.ai)
|
||||
@@ -6,9 +16,9 @@
|
||||
> [!TIP]
|
||||
> Be with us!
|
||||
>
|
||||
> | [<img alt="Discord link" src="https://img.shields.io/discord/1452487457085063218?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square" width="156px" />](https://discord.gg/PUwSMR9XNk) | Join our [Discord community](https://discord.gg/PUwSMR9XNk) to connect with contributors and fellow `oh-my-openagent` users. |
|
||||
> | [<img alt="Discord link" src="https://img.shields.io/discord/1452487457085063218?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square" width="156px" />](https://discord.gg/PUwSMR9XNk) | Join our [Discord community](https://discord.gg/PUwSMR9XNk) to connect with contributors and fellow `oh-my-opencode` users. |
|
||||
> | :-----| :----- |
|
||||
> | [<img alt="X link" src="https://img.shields.io/badge/Follow-%40justsisyphus-00CED1?style=flat-square&logo=x&labelColor=black" width="156px" />](https://x.com/justsisyphus) | News and updates for `oh-my-openagent` used to be posted on my X account. <br /> Since it was suspended mistakenly, [@justsisyphus](https://x.com/justsisyphus) now posts updates on my behalf. |
|
||||
> | [<img alt="X link" src="https://img.shields.io/badge/Follow-%40justsisyphus-00CED1?style=flat-square&logo=x&labelColor=black" width="156px" />](https://x.com/justsisyphus) | News and updates for `oh-my-opencode` used to be posted on my X account. <br /> Since it was suspended mistakenly, [@justsisyphus](https://x.com/justsisyphus) now posts updates on my behalf. |
|
||||
> | [<img alt="GitHub Follow" src="https://img.shields.io/github/followers/code-yeongyu?style=flat-square&logo=github&labelColor=black&color=24292f" width="156px" />](https://github.com/code-yeongyu) | Follow [@code-yeongyu](https://github.com/code-yeongyu) on GitHub for more projects. |
|
||||
|
||||
<!-- <CENTERED SECTION FOR GITHUB DISPLAY> -->
|
||||
@@ -55,7 +65,7 @@
|
||||
|
||||
> "I converted a 45k line tauri app into a SaaS web app overnight using Ohmyopencode and ralph loop. Started with interview me prompt, asked it for ratings and recommendations on the questions. It was amazing to watch it work and to wake up this morning to a mostly working website!" - [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
> "use oh-my-openagent, you will never go back" <br/>- [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
> "use oh-my-opencode, you will never go back" <br/>- [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
|
||||
> "I haven't really been able to articulate exactly what makes it so great yet, but the development experience has reached a completely different dimension." - [
|
||||
苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
@@ -87,7 +97,7 @@ Install OmO. Type `ultrawork`. Done.
|
||||
Copy and paste this prompt to your LLM agent (Claude Code, AmpCode, Cursor, etc.):
|
||||
|
||||
```
|
||||
Install and configure oh-my-openagent by following the instructions here:
|
||||
Install and configure oh-my-opencode by following the instructions here:
|
||||
https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/refs/heads/dev/docs/guide/installation.md
|
||||
```
|
||||
|
||||
@@ -255,19 +265,19 @@ Add your own: `.opencode/skills/*/SKILL.md` or `~/.config/opencode/skills/*/SKIL
|
||||
|
||||
---
|
||||
|
||||
> **New to oh-my-openagent?** Read the **[Overview](docs/guide/overview.md)** to understand what you have, or check the **[Orchestration Guide](docs/guide/orchestration.md)** for how agents collaborate.
|
||||
> **New to oh-my-opencode?** Read the **[Overview](docs/guide/overview.md)** to understand what you have, or check the **[Orchestration Guide](docs/guide/orchestration.md)** for how agents collaborate.
|
||||
|
||||
## Uninstallation
|
||||
|
||||
To remove oh-my-openagent:
|
||||
To remove oh-my-opencode:
|
||||
|
||||
1. **Remove the plugin from your OpenCode config**
|
||||
|
||||
Edit `~/.config/opencode/opencode.json` (or `opencode.jsonc`) and remove `"oh-my-openagent"` from the `plugin` array:
|
||||
Edit `~/.config/opencode/opencode.json` (or `opencode.jsonc`) and remove `"oh-my-opencode"` from the `plugin` array:
|
||||
|
||||
```bash
|
||||
# Using jq
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-openagent")]' \
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-opencode")]' \
|
||||
~/.config/opencode/opencode.json > /tmp/oc.json && \
|
||||
mv /tmp/oc.json ~/.config/opencode/opencode.json
|
||||
```
|
||||
@@ -276,10 +286,10 @@ To remove oh-my-openagent:
|
||||
|
||||
```bash
|
||||
# Remove user config
|
||||
rm -f ~/.config/opencode/oh-my-openagent.json ~/.config/opencode/oh-my-openagent.jsonc
|
||||
rm -f ~/.config/opencode/oh-my-opencode.json ~/.config/opencode/oh-my-opencode.jsonc
|
||||
|
||||
# Remove project config (if exists)
|
||||
rm -f .opencode/oh-my-openagent.json .opencode/oh-my-openagent.jsonc
|
||||
rm -f .opencode/oh-my-opencode.json .opencode/oh-my-opencode.jsonc
|
||||
```
|
||||
|
||||
3. **Verify removal**
|
||||
@@ -304,7 +314,7 @@ See full [Features Documentation](docs/reference/features.md).
|
||||
- **Claude Code Compatibility**: Full hook system, commands, skills, agents, MCPs
|
||||
- **Built-in MCPs**: websearch (Exa), context7 (docs), grep_app (GitHub search)
|
||||
- **Session Tools**: List, read, search, and analyze session history
|
||||
- **Productivity Features**: Ralph Loop, Todo Enforcer, GPT permission-tail continuation, Comment Checker, Think Mode, and more
|
||||
- **Productivity Features**: Ralph Loop, Todo Enforcer, Comment Checker, Think Mode, and more
|
||||
- **Model Setup**: Agent-model matching is built into the [Installation Guide](docs/guide/installation.md#step-5-understand-your-model-setup)
|
||||
|
||||
## Configuration
|
||||
@@ -314,14 +324,14 @@ Opinionated defaults, adjustable if you insist.
|
||||
See [Configuration Documentation](docs/reference/configuration.md).
|
||||
|
||||
**Quick Overview:**
|
||||
- **Config Locations**: `.opencode/oh-my-openagent.jsonc` or `.opencode/oh-my-openagent.json` (project), `~/.config/opencode/oh-my-openagent.jsonc` or `~/.config/opencode/oh-my-openagent.json` (user)
|
||||
- **Config Locations**: `.opencode/oh-my-opencode.jsonc` or `.opencode/oh-my-opencode.json` (project), `~/.config/opencode/oh-my-opencode.jsonc` or `~/.config/opencode/oh-my-opencode.json` (user)
|
||||
- **JSONC Support**: Comments and trailing commas supported
|
||||
- **Agents**: Override models, temperatures, prompts, and permissions for any agent
|
||||
- **Built-in Skills**: `playwright` (browser automation), `git-master` (atomic commits)
|
||||
- **Sisyphus Agent**: Main orchestrator with Prometheus (Planner) and Metis (Plan Consultant)
|
||||
- **Background Tasks**: Configure concurrency limits per provider/model
|
||||
- **Categories**: Domain-specific task delegation (`visual`, `business-logic`, custom)
|
||||
- **Hooks**: 25+ built-in hooks, including `gpt-permission-continuation`, all configurable via `disabled_hooks`
|
||||
- **Hooks**: 25+ built-in hooks, all configurable via `disabled_hooks`
|
||||
- **MCPs**: Built-in websearch (Exa), context7 (docs), grep_app (GitHub search)
|
||||
- **LSP**: Full LSP support with refactoring tools
|
||||
- **Experimental**: Aggressive truncation, auto-resume, and more
|
||||
|
||||
39
README.ru.md
39
README.ru.md
@@ -4,6 +4,17 @@
|
||||
> Ключевой мейнтейнер Q получил травму, поэтому на этой неделе ответы по issue/PR и релизы могут задерживаться.
|
||||
> Спасибо за терпение и поддержку.
|
||||
|
||||
> [!TIP]
|
||||
> **Building in Public**
|
||||
>
|
||||
> Мейнтейнер разрабатывает и поддерживает oh-my-opencode в режиме реального времени с помощью Jobdori — ИИ-ассистента на базе глубоко кастомизированной версии OpenClaw.
|
||||
> Каждая фича, каждый фикс, каждый триаж issue — в прямом эфире в нашем Discord.
|
||||
>
|
||||
> [](https://discord.gg/PUwSMR9XNk)
|
||||
>
|
||||
> [**→ Смотрите в #building-in-public**](https://discord.gg/PUwSMR9XNk)
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> [](https://sisyphuslabs.ai)
|
||||
@@ -12,16 +23,16 @@
|
||||
|
||||
> [!TIP] Будьте с нами!
|
||||
>
|
||||
> | [](https://discord.gg/PUwSMR9XNk) | Вступайте в наш [Discord](https://discord.gg/PUwSMR9XNk), чтобы общаться с контрибьюторами и пользователями `oh-my-openagent`. |
|
||||
> | [](https://discord.gg/PUwSMR9XNk) | Вступайте в наш [Discord](https://discord.gg/PUwSMR9XNk), чтобы общаться с контрибьюторами и пользователями `oh-my-opencode`. |
|
||||
> | ----------------------------------- | ------------------------------------------------------------ |
|
||||
> | [](https://x.com/justsisyphus) | Новости и обновления `oh-my-openagent` раньше публиковались на моём аккаунте X. <br /> После ошибочной блокировки, [@justsisyphus](https://x.com/justsisyphus) публикует обновления вместо меня. |
|
||||
> | [](https://x.com/justsisyphus) | Новости и обновления `oh-my-opencode` раньше публиковались на моём аккаунте X. <br /> После ошибочной блокировки, [@justsisyphus](https://x.com/justsisyphus) публикует обновления вместо меня. |
|
||||
> | [](https://github.com/code-yeongyu) | Подпишитесь на [@code-yeongyu](https://github.com/code-yeongyu) на GitHub, чтобы следить за другими проектами. |
|
||||
|
||||
<!-- <CENTERED SECTION FOR GITHUB DISPLAY> --> <div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-opencode)
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-opencode)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -31,7 +42,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
https://www.npmjs.com/package/oh-my-openagent
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/releases) [](https://www.npmjs.com/package/oh-my-opencode) [](https://github.com/code-yeongyu/oh-my-openagent/graphs/contributors) [](https://github.com/code-yeongyu/oh-my-openagent/network/members) [](https://github.com/code-yeongyu/oh-my-openagent/stargazers) [](https://github.com/code-yeongyu/oh-my-openagent/issues) [](https://github.com/code-yeongyu/oh-my-openagent/blob/master/LICENSE.md) [](https://deepwiki.com/code-yeongyu/oh-my-openagent)
|
||||
|
||||
English | 한국어 | 日本語 | 简体中文 | Русский
|
||||
|
||||
@@ -47,7 +58,7 @@ English | 한국어 | 日本語 | 简体中文 | Русский
|
||||
|
||||
> «За ночь конвертировал приложение на tauri в 45k строк в веб-SaaS с помощью Ohmyopencode и ralph loop. Начал с промпта «проинтервьюируй меня», попросил оценки и рекомендации по вопросам. Было удивительно наблюдать за работой и утром проснуться с почти рабочим сайтом!» — [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
> «Используйте oh-my-openagent — вы не захотите возвращаться назад.» <br/>— [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
> «Используйте oh-my-opencode — вы не захотите возвращаться назад.» <br/>— [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
|
||||
> «Пока не могу точно объяснить, почему это так круто, но опыт разработки вышел на совершенно другой уровень.» — [苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
|
||||
@@ -76,7 +87,7 @@ English | 한국어 | 日本語 | 简体中文 | Русский
|
||||
Скопируйте и вставьте этот промпт в ваш LLM-агент (Claude Code, AmpCode, Cursor и т.д.):
|
||||
|
||||
```
|
||||
Install and configure oh-my-openagent by following the instructions here:
|
||||
Install and configure oh-my-opencode by following the instructions here:
|
||||
https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/refs/heads/dev/docs/guide/installation.md
|
||||
```
|
||||
|
||||
@@ -242,19 +253,19 @@ project/
|
||||
|
||||
------
|
||||
|
||||
> **Впервые в oh-my-openagent?** Прочитайте **Обзор**, чтобы понять, что у вас есть, или ознакомьтесь с **руководством по оркестрации**, чтобы узнать, как агенты взаимодействуют.
|
||||
> **Впервые в oh-my-opencode?** Прочитайте **Обзор**, чтобы понять, что у вас есть, или ознакомьтесь с **руководством по оркестрации**, чтобы узнать, как агенты взаимодействуют.
|
||||
|
||||
## Удаление
|
||||
|
||||
Чтобы удалить oh-my-openagent:
|
||||
Чтобы удалить oh-my-opencode:
|
||||
|
||||
1. **Удалите плагин из конфига OpenCode**
|
||||
|
||||
Отредактируйте `~/.config/opencode/opencode.json` (или `opencode.jsonc`) и уберите `"oh-my-openagent"` из массива `plugin`:
|
||||
Отредактируйте `~/.config/opencode/opencode.json` (или `opencode.jsonc`) и уберите `"oh-my-opencode"` из массива `plugin`:
|
||||
|
||||
```bash
|
||||
# С помощью jq
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-openagent")]' \
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-opencode")]' \
|
||||
~/.config/opencode/opencode.json > /tmp/oc.json && \
|
||||
mv /tmp/oc.json ~/.config/opencode/opencode.json
|
||||
```
|
||||
@@ -263,10 +274,10 @@ project/
|
||||
|
||||
```bash
|
||||
# Удалить пользовательский конфиг
|
||||
rm -f ~/.config/opencode/oh-my-openagent.json ~/.config/opencode/oh-my-openagent.jsonc
|
||||
rm -f ~/.config/opencode/oh-my-opencode.json ~/.config/opencode/oh-my-opencode.jsonc
|
||||
|
||||
# Удалить конфиг проекта (если существует)
|
||||
rm -f .opencode/oh-my-openagent.json .opencode/oh-my-openagent.jsonc
|
||||
rm -f .opencode/oh-my-opencode.json .opencode/oh-my-opencode.jsonc
|
||||
```
|
||||
|
||||
3. **Проверьте удаление**
|
||||
@@ -303,7 +314,7 @@ project/
|
||||
|
||||
**Краткий обзор:**
|
||||
|
||||
- **Расположение конфигов**: `.opencode/oh-my-openagent.jsonc` или `.opencode/oh-my-openagent.json` (проект), `~/.config/opencode/oh-my-openagent.jsonc` или `~/.config/opencode/oh-my-openagent.json` (пользователь)
|
||||
- **Расположение конфигов**: `.opencode/oh-my-opencode.jsonc` или `.opencode/oh-my-opencode.json` (проект), `~/.config/opencode/oh-my-opencode.jsonc` или `~/.config/opencode/oh-my-opencode.json` (пользователь)
|
||||
- **Поддержка JSONC**: Комментарии и конечные запятые поддерживаются
|
||||
- **Агенты**: Переопределение моделей, температур, промптов и разрешений для любого агента
|
||||
- **Встроенные навыки**: `playwright` (автоматизация браузера), `git-master` (атомарные коммиты)
|
||||
|
||||
@@ -4,6 +4,17 @@
|
||||
> 核心维护者 Q 因受伤,本周 issue/PR 回复和发布可能会延迟。
|
||||
> 感谢你的耐心与支持。
|
||||
|
||||
> [!TIP]
|
||||
> **Building in Public**
|
||||
>
|
||||
> 维护者正在使用 Jobdori 实时开发和维护 oh-my-opencode。Jobdori 是基于 OpenClaw 深度定制的 AI 助手。
|
||||
> 每个功能开发、每次修复、每次 Issue 分类,都在 Discord 上实时进行。
|
||||
>
|
||||
> [](https://discord.gg/PUwSMR9XNk)
|
||||
>
|
||||
> [**→ 在 #building-in-public 频道中查看**](https://discord.gg/PUwSMR9XNk)
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> [](https://sisyphuslabs.ai)
|
||||
@@ -12,18 +23,18 @@
|
||||
> [!TIP]
|
||||
> 加入我们!
|
||||
>
|
||||
> | [<img alt="Discord link" src="https://img.shields.io/discord/1452487457085063218?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square" width="156px" />](https://discord.gg/PUwSMR9XNk) | 加入我们的 [Discord 社区](https://discord.gg/PUwSMR9XNk),与贡献者及其他 `oh-my-openagent` 用户交流。 |
|
||||
> | [<img alt="Discord link" src="https://img.shields.io/discord/1452487457085063218?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square" width="156px" />](https://discord.gg/PUwSMR9XNk) | 加入我们的 [Discord 社区](https://discord.gg/PUwSMR9XNk),与贡献者及其他 `oh-my-opencode` 用户交流。 |
|
||||
> | :-----| :----- |
|
||||
> | [<img alt="X link" src="https://img.shields.io/badge/Follow-%40justsisyphus-00CED1?style=flat-square&logo=x&labelColor=black" width="156px" />](https://x.com/justsisyphus) | 关于 `oh-my-openagent` 的新闻和更新过去发布在我的 X 账号上。<br /> 因为账号被意外停用,现在由 [@justsisyphus](https://x.com/justsisyphus) 代为发布更新。 |
|
||||
> | [<img alt="X link" src="https://img.shields.io/badge/Follow-%40justsisyphus-00CED1?style=flat-square&logo=x&labelColor=black" width="156px" />](https://x.com/justsisyphus) | 关于 `oh-my-opencode` 的新闻和更新过去发布在我的 X 账号上。<br /> 因为账号被意外停用,现在由 [@justsisyphus](https://x.com/justsisyphus) 代为发布更新。 |
|
||||
> | [<img alt="GitHub Follow" src="https://img.shields.io/github/followers/code-yeongyu?style=flat-square&logo=github&labelColor=black&color=24292f" width="156px" />](https://github.com/code-yeongyu) | 在 GitHub 上关注 [@code-yeongyu](https://github.com/code-yeongyu) 获取更多项目信息。 |
|
||||
|
||||
<!-- <CENTERED SECTION FOR GITHUB DISPLAY> -->
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-opencode)
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-opencode)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -34,7 +45,7 @@
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/releases)
|
||||
[](https://www.npmjs.com/package/oh-my-openagent)
|
||||
[](https://www.npmjs.com/package/oh-my-opencode)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/graphs/contributors)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/network/members)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/stargazers)
|
||||
@@ -58,7 +69,7 @@
|
||||
|
||||
> “我用 Ohmyopencode 和 ralph loop 花了一晚上的时间,把一个 45k 行代码的 tauri 应用转换成了 SaaS Web 应用。从面试模式开始,让它对我提供的提示词进行提问和提出建议。看着它工作很有趣,今早醒来看到网站基本已经跑起来了,太震撼了!” - [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
> “用 oh-my-openagent 吧,你绝对回不去了。” <br/>- [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
> “用 oh-my-opencode 吧,你绝对回不去了。” <br/>- [d0t3ch](https://x.com/d0t3ch/status/2001685618200580503)
|
||||
|
||||
> “我很难准确描述它到底哪里牛逼,但开发体验已经达到完全不同的维度了。” - [苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
|
||||
@@ -91,7 +102,7 @@
|
||||
复制并粘贴以下提示词到你的 LLM Agent (Claude Code, AmpCode, Cursor 等):
|
||||
|
||||
```
|
||||
Install and configure oh-my-openagent by following the instructions here:
|
||||
Install and configure oh-my-opencode by following the instructions here:
|
||||
https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/refs/heads/dev/docs/guide/installation.md
|
||||
```
|
||||
|
||||
@@ -259,19 +270,19 @@ Agent 会自动顺藤摸瓜加载对应的 Context,免去了你所有的手动
|
||||
|
||||
---
|
||||
|
||||
> **第一次用 oh-my-openagent?** 阅读 **[概述](docs/guide/overview.md)** 了解你拥有哪些功能,或查看 **[编排指南](docs/guide/orchestration.md)** 了解 Agent 如何协作。
|
||||
> **第一次用 oh-my-opencode?** 阅读 **[概述](docs/guide/overview.md)** 了解你拥有哪些功能,或查看 **[编排指南](docs/guide/orchestration.md)** 了解 Agent 如何协作。
|
||||
|
||||
## 如何卸载 (Uninstallation)
|
||||
|
||||
要移除 oh-my-openagent:
|
||||
要移除 oh-my-opencode:
|
||||
|
||||
1. **从你的 OpenCode 配置文件中去掉插件**
|
||||
|
||||
编辑 `~/.config/opencode/opencode.json` (或 `opencode.jsonc`) ,并把 `"oh-my-openagent"` 从 `plugin` 数组中删掉:
|
||||
编辑 `~/.config/opencode/opencode.json` (或 `opencode.jsonc`) ,并把 `"oh-my-opencode"` 从 `plugin` 数组中删掉:
|
||||
|
||||
```bash
|
||||
# 如果你有 jq 的话
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-openagent")]' \
|
||||
jq '.plugin = [.plugin[] | select(. != "oh-my-opencode")]' \
|
||||
~/.config/opencode/opencode.json > /tmp/oc.json && \
|
||||
mv /tmp/oc.json ~/.config/opencode/opencode.json
|
||||
```
|
||||
@@ -280,10 +291,10 @@ Agent 会自动顺藤摸瓜加载对应的 Context,免去了你所有的手动
|
||||
|
||||
```bash
|
||||
# 移除全局用户配置
|
||||
rm -f ~/.config/opencode/oh-my-openagent.json ~/.config/opencode/oh-my-openagent.jsonc
|
||||
rm -f ~/.config/opencode/oh-my-opencode.json ~/.config/opencode/oh-my-opencode.jsonc
|
||||
|
||||
# 移除当前项目的配置
|
||||
rm -f .opencode/oh-my-openagent.json .opencode/oh-my-openagent.jsonc
|
||||
rm -f .opencode/oh-my-opencode.json .opencode/oh-my-opencode.jsonc
|
||||
```
|
||||
|
||||
3. **确认卸载成功**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
// bin/oh-my-openagent.js
|
||||
// bin/oh-my-opencode.js
|
||||
// Wrapper script that detects platform and spawns the correct binary
|
||||
|
||||
import { spawnSync } from "node:child_process";
|
||||
@@ -32,7 +32,7 @@ function supportsAvx2() {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (process.env.OH_MY_OPENAGENT_FORCE_BASELINE === "1" || process.env.OH_MY_OPENCODE_FORCE_BASELINE === "1") {
|
||||
if (process.env.OH_MY_OPENCODE_FORCE_BASELINE === "1") {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ function main() {
|
||||
preferBaseline: avx2Supported === false,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`\noh-my-openagent: ${error.message}\n`);
|
||||
console.error(`\noh-my-opencode: ${error.message}\n`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ function main() {
|
||||
.filter((entry) => entry !== null);
|
||||
|
||||
if (resolvedBinaries.length === 0) {
|
||||
console.error(`\noh-my-openagent: Platform binary not installed.`);
|
||||
console.error(`\noh-my-opencode: Platform binary not installed.`);
|
||||
console.error(`\nYour platform: ${platform}-${arch}${libcFamily === "musl" ? "-musl" : ""}`);
|
||||
console.error(`Expected packages (in order): ${packageCandidates.join(", ")}`);
|
||||
console.error(`\nTo fix, run:`);
|
||||
@@ -120,7 +120,7 @@ function main() {
|
||||
continue;
|
||||
}
|
||||
|
||||
console.error(`\noh-my-openagent: Failed to execute binary.`);
|
||||
console.error(`\noh-my-opencode: Failed to execute binary.`);
|
||||
console.error(`Error: ${result.error.message}\n`);
|
||||
process.exit(2);
|
||||
}
|
||||
@@ -8,7 +8,7 @@ Think of AI models as developers on a team. Each has a different brain, differen
|
||||
|
||||
This isn't a bug. It's the foundation of the entire system.
|
||||
|
||||
Oh My OpenCode assigns each agent a model that matches its _working style_ — like building a team where each person is in the role that fits their personality.
|
||||
Oh My OpenAgent assigns each agent a model that matches its _working style_ — like building a team where each person is in the role that fits their personality.
|
||||
|
||||
### Sisyphus: The Sociable Lead
|
||||
|
||||
@@ -92,10 +92,10 @@ These agents do grep, search, and retrieval. They intentionally use the fastest,
|
||||
|
||||
| Agent | Role | Fallback Chain | Notes |
|
||||
| --------------------- | ------------------ | ---------------------------------------------- | ----------------------------------------------------- |
|
||||
| **Explore** | Fast codebase grep | Grok Code Fast → opencode-go/minimax-m2.5 → MiniMax Free → Haiku → GPT-5-Nano | Speed is everything. Fire 10 in parallel. |
|
||||
| **Librarian** | Docs/code search | opencode-go/minimax-m2.5 → MiniMax Free → Haiku → GPT-5-Nano | Doc retrieval doesn't need deep reasoning. |
|
||||
| **Multimodal Looker** | Vision/screenshots | GPT-5.4 → opencode-go/kimi-k2.5 → GLM-4.6v → GPT-5-Nano | Uses the first available multimodal-capable fallback. |
|
||||
| **Sisyphus-Junior** | Category executor | Claude Sonnet → opencode-go/kimi-k2.5 → GPT-5.4 → Big Pickle | Handles delegated category tasks. Sonnet-tier default. |
|
||||
| **Explore** | Fast codebase grep | Grok Code Fast → opencode-go/minimax-m2.7-highspeed → MiniMax M2.7 → Haiku → GPT-5-Nano | Speed is everything. Fire 10 in parallel. |
|
||||
| **Librarian** | Docs/code search | opencode-go/minimax-m2.7 → MiniMax M2.7-highspeed → Haiku → GPT-5-Nano | Doc retrieval doesn't need deep reasoning. |
|
||||
| **Multimodal Looker** | Vision/screenshots | GPT-5.4 → opencode-go/kimi-k2.5 → GLM-4.6v → GPT-5-Nano | Uses the first available multimodal-capable fallback. |
|
||||
| **Sisyphus-Junior** | Category executor | Claude Sonnet → opencode-go/kimi-k2.5 → GPT-5.4 → MiniMax M2.7 → Big Pickle | Handles delegated category tasks. Sonnet-tier default. |
|
||||
|
||||
---
|
||||
|
||||
@@ -121,6 +121,7 @@ Principle-driven, explicit reasoning, deep technical capability. Best for agents
|
||||
| ----------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| **GPT-5.3 Codex** | Deep coding powerhouse. Autonomous exploration. Required for Hephaestus. |
|
||||
| **GPT-5.4** | High intelligence, strategic reasoning. Default for Oracle, Momus, and a key fallback for Prometheus / Atlas. Uses xhigh variant for Momus. |
|
||||
| **GPT-5.4 Mini** | Fast + strong reasoning. Good for lightweight autonomous tasks. Default for quick category. |
|
||||
| **GPT-5-Nano** | Ultra-cheap, fast. Good for simple utility tasks. |
|
||||
|
||||
### Other Models
|
||||
@@ -130,7 +131,8 @@ Principle-driven, explicit reasoning, deep technical capability. Best for agents
|
||||
| **Gemini 3.1 Pro** | Excels at visual/frontend tasks. Different reasoning style. Default for `visual-engineering` and `artistry`. |
|
||||
| **Gemini 3 Flash** | Fast. Good for doc search and light tasks. |
|
||||
| **Grok Code Fast 1** | Blazing fast code grep. Default for Explore agent. |
|
||||
| **MiniMax M2.5** | Fast and smart. Good for utility tasks and search/retrieval. |
|
||||
| **MiniMax M2.7** | Fast and smart. Good for utility tasks and search/retrieval. Upgraded from M2.5 with better reasoning. |
|
||||
| **MiniMax M2.7 Highspeed** | Ultra-fast variant. Optimized for latency-sensitive tasks like codebase grep. |
|
||||
|
||||
### OpenCode Go
|
||||
|
||||
@@ -142,11 +144,11 @@ A premium subscription tier ($10/month) that provides reliable access to Chinese
|
||||
| ------------------------ | --------------------------------------------------------------------- |
|
||||
| **opencode-go/kimi-k2.5** | Vision-capable, Claude-like reasoning. Used by Sisyphus, Atlas, Sisyphus-Junior, Multimodal Looker. |
|
||||
| **opencode-go/glm-5** | Text-only orchestration model. Used by Oracle, Prometheus, Metis, Momus. |
|
||||
| **opencode-go/minimax-m2.5** | Ultra-cheap, fast responses. Used by Librarian, Explore for utility work. |
|
||||
| **opencode-go/minimax-m2.7** | Ultra-cheap, fast responses. Used by Librarian, Explore, Atlas, Sisyphus-Junior for utility work. |
|
||||
|
||||
**When It Gets Used:**
|
||||
|
||||
OpenCode Go models appear in fallback chains as intermediate options. They bridge the gap between premium Claude access and free-tier alternatives. The system tries OpenCode Go models before falling back to free tiers (MiniMax Free, Big Pickle) or GPT alternatives.
|
||||
OpenCode Go models appear in fallback chains as intermediate options. They bridge the gap between premium Claude access and free-tier alternatives. The system tries OpenCode Go models before falling back to free tiers (MiniMax M2.7-highspeed, Big Pickle) or GPT alternatives.
|
||||
|
||||
**Go-Only Scenarios:**
|
||||
|
||||
@@ -154,7 +156,7 @@ Some model identifiers like `k2p5` (paid Kimi K2.5) and `glm-5` may only be avai
|
||||
|
||||
### About Free-Tier Fallbacks
|
||||
|
||||
You may see model names like `kimi-k2.5-free`, `minimax-m2.5-free`, or `big-pickle` (GLM 4.6) in the source code or logs. These are free-tier versions of the same model families, served through the OpenCode Zen provider. They exist as lower-priority entries in fallback chains.
|
||||
You may see model names like `kimi-k2.5-free`, `minimax-m2.7-highspeed`, or `big-pickle` (GLM 4.6) in the source code or logs. These are free-tier or speed-optimized versions of the same model families. They exist as lower-priority entries in fallback chains.
|
||||
|
||||
You don't need to configure them. The system includes them so it degrades gracefully when you don't have every paid subscription. If you have the paid version, the paid version is always preferred.
|
||||
|
||||
@@ -170,7 +172,7 @@ When agents delegate work, they don't pick a model name — they pick a **catego
|
||||
| `ultrabrain` | Maximum reasoning needed | GPT-5.4 → Gemini 3.1 Pro → Claude Opus → opencode-go/glm-5 |
|
||||
| `deep` | Deep coding, complex logic | GPT-5.3 Codex → Claude Opus → Gemini 3.1 Pro |
|
||||
| `artistry` | Creative, novel approaches | Gemini 3.1 Pro → Claude Opus → GPT-5.4 |
|
||||
| `quick` | Simple, fast tasks | Claude Haiku → Gemini Flash → opencode-go/minimax-m2.5 → GPT-5-Nano |
|
||||
| `quick` | Simple, fast tasks | GPT-5.4 Mini → Claude Haiku → Gemini Flash → opencode-go/minimax-m2.7 → GPT-5-Nano |
|
||||
| `unspecified-high` | General complex work | Claude Opus → GPT-5.4 → GLM 5 → K2P5 → opencode-go/glm-5 → Kimi K2.5 |
|
||||
| `unspecified-low` | General standard work | Claude Sonnet → GPT-5.3 Codex → opencode-go/kimi-k2.5 → Gemini Flash |
|
||||
| `writing` | Text, docs, prose | Gemini Flash → opencode-go/kimi-k2.5 → Claude Sonnet |
|
||||
|
||||
@@ -69,7 +69,7 @@ Ask the user these questions to determine CLI options:
|
||||
- If **no** → `--zai-coding-plan=no` (default)
|
||||
|
||||
7. **Do you have an OpenCode Go subscription?**
|
||||
- OpenCode Go is a $10/month subscription providing access to GLM-5, Kimi K2.5, and MiniMax M2.5 models
|
||||
- OpenCode Go is a $10/month subscription providing access to GLM-5, Kimi K2.5, and MiniMax M2.7 models
|
||||
- If **yes** → `--opencode-go=yes`
|
||||
- If **no** → `--opencode-go=no` (default)
|
||||
|
||||
@@ -176,7 +176,7 @@ The `opencode-antigravity-auth` plugin uses different model names than the built
|
||||
|
||||
**Available models (Gemini CLI quota)**:
|
||||
|
||||
- `google/gemini-2.5-flash`, `google/gemini-2.5-pro`, `google/gemini-3-flash-preview`, `google/gemini-3-pro-preview`
|
||||
- `google/gemini-2.5-flash`, `google/gemini-2.5-pro`, `google/gemini-3-flash-preview`, `google/gemini-3.1-pro-preview`
|
||||
|
||||
> **Note**: Legacy tier-suffixed names like `google/antigravity-gemini-3-pro-high` still work but variants are recommended. Use `--variant=high` with the base model name instead.
|
||||
|
||||
@@ -205,7 +205,7 @@ When GitHub Copilot is the best available provider, oh-my-openagent uses these m
|
||||
|
||||
| Agent | Model |
|
||||
| ------------- | --------------------------------- |
|
||||
| **Sisyphus** | `github-copilot/claude-opus-4-6` |
|
||||
| **Sisyphus** | `github-copilot/claude-opus-4.6` |
|
||||
| **Oracle** | `github-copilot/gpt-5.4` |
|
||||
| **Explore** | `github-copilot/grok-code-fast-1` |
|
||||
| **Librarian** | `github-copilot/gemini-3-flash` |
|
||||
@@ -227,7 +227,7 @@ If Z.ai is your main provider, the most important fallbacks are:
|
||||
|
||||
#### OpenCode Zen
|
||||
|
||||
OpenCode Zen provides access to `opencode/` prefixed models including `opencode/claude-opus-4-6`, `opencode/gpt-5.4`, `opencode/gpt-5.3-codex`, `opencode/gpt-5-nano`, `opencode/glm-5`, `opencode/big-pickle`, and `opencode/minimax-m2.5-free`.
|
||||
OpenCode Zen provides access to `opencode/` prefixed models including `opencode/claude-opus-4-6`, `opencode/gpt-5.4`, `opencode/gpt-5.3-codex`, `opencode/gpt-5-nano`, `opencode/glm-5`, `opencode/big-pickle`, and `opencode/minimax-m2.7-highspeed`.
|
||||
|
||||
When OpenCode Zen is the best available provider (no native or Copilot), these models are used:
|
||||
|
||||
@@ -236,7 +236,7 @@ When OpenCode Zen is the best available provider (no native or Copilot), these m
|
||||
| **Sisyphus** | `opencode/claude-opus-4-6` |
|
||||
| **Oracle** | `opencode/gpt-5.4` |
|
||||
| **Explore** | `opencode/gpt-5-nano` |
|
||||
| **Librarian** | `opencode/minimax-m2.5-free` / `opencode/big-pickle` |
|
||||
| **Librarian** | `opencode/minimax-m2.7-highspeed` / `opencode/big-pickle` |
|
||||
|
||||
##### Setup
|
||||
|
||||
@@ -287,16 +287,17 @@ Not all models behave the same way. Understanding which models are "similar" hel
|
||||
| ----------------- | -------------------------------- | ------------------------------------------------- |
|
||||
| **GPT-5.3-codex** | openai, github-copilot, opencode | Deep coding powerhouse. Required for Hephaestus. |
|
||||
| **GPT-5.4** | openai, github-copilot, opencode | High intelligence. Default for Oracle. |
|
||||
| **GPT-5.4 Mini** | openai, github-copilot, opencode | Fast + strong reasoning. Default for quick category. |
|
||||
| **GPT-5-Nano** | opencode | Ultra-cheap, fast. Good for simple utility tasks. |
|
||||
|
||||
**Different-Behavior Models**:
|
||||
|
||||
| Model | Provider(s) | Notes |
|
||||
| --------------------- | -------------------------------- | ----------------------------------------------------------- |
|
||||
| **Gemini 3 Pro** | google, github-copilot, opencode | Excels at visual/frontend tasks. Different reasoning style. |
|
||||
| **Gemini 3.1 Pro** | google, github-copilot, opencode | Excels at visual/frontend tasks. Different reasoning style. |
|
||||
| **Gemini 3 Flash** | google, github-copilot, opencode | Fast, good for doc search and light tasks. |
|
||||
| **MiniMax M2.5** | venice | Fast and smart. Good for utility tasks. |
|
||||
| **MiniMax M2.5 Free** | opencode | Free-tier MiniMax. Fast for search/retrieval. |
|
||||
| **MiniMax M2.7** | venice, opencode-go | Fast and smart. Good for utility tasks. Upgraded from M2.5. |
|
||||
| **MiniMax M2.7 Highspeed** | opencode | Ultra-fast MiniMax variant. Optimized for latency. |
|
||||
|
||||
**Speed-Focused Models**:
|
||||
|
||||
@@ -304,7 +305,7 @@ Not all models behave the same way. Understanding which models are "similar" hel
|
||||
| ----------------------- | ---------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Grok Code Fast 1** | github-copilot, venice | Very fast | Optimized for code grep/search. Default for Explore. |
|
||||
| **Claude Haiku 4.5** | anthropic, opencode | Fast | Good balance of speed and intelligence. |
|
||||
| **MiniMax M2.5 (Free)** | opencode, venice | Fast | Smart for its speed class. |
|
||||
| **MiniMax M2.7 Highspeed** | opencode | Very fast | Ultra-fast MiniMax variant. Smart for its speed class. |
|
||||
| **GPT-5.3-codex-spark** | openai | Extremely fast | Blazing fast but compacts so aggressively that oh-my-openagent's context management doesn't work well with it. Not recommended for omo agents. |
|
||||
|
||||
#### What Each Agent Does and Which Model It Got
|
||||
@@ -316,7 +317,7 @@ Based on your subscriptions, here's how the agents were configured:
|
||||
| Agent | Role | Default Chain | What It Does |
|
||||
| ------------ | ---------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| **Sisyphus** | Main ultraworker | Opus (max) → Kimi K2.5 → GLM 5 → Big Pickle | Primary coding agent. Orchestrates everything. **Never use GPT — no GPT prompt exists.** |
|
||||
| **Metis** | Plan review | Opus (max) → Kimi K2.5 → GPT-5.4 → Gemini 3 Pro | Reviews Prometheus plans for gaps. |
|
||||
| **Metis** | Plan review | Opus (max) → Kimi K2.5 → GPT-5.4 → Gemini 3.1 Pro | Reviews Prometheus plans for gaps. |
|
||||
|
||||
**Dual-Prompt Agents** (auto-switch between Claude and GPT prompts):
|
||||
|
||||
@@ -326,7 +327,7 @@ Priority: **Claude > GPT > Claude-like models**
|
||||
|
||||
| Agent | Role | Default Chain | GPT Prompt? |
|
||||
| -------------- | ----------------- | ---------------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| **Prometheus** | Strategic planner | Opus (max) → **GPT-5.4 (high)** → Kimi K2.5 → Gemini 3 Pro | Yes — XML-tagged, principle-driven (~300 lines vs ~1,100 Claude) |
|
||||
| **Prometheus** | Strategic planner | Opus (max) → **GPT-5.4 (high)** → Kimi K2.5 → Gemini 3.1 Pro | Yes — XML-tagged, principle-driven (~300 lines vs ~1,100 Claude) |
|
||||
| **Atlas** | Todo orchestrator | **Kimi K2.5** → Sonnet → GPT-5.4 | Yes — GPT-optimized todo management |
|
||||
|
||||
**GPT-Native Agents** (built for GPT, don't override to Claude):
|
||||
@@ -334,8 +335,8 @@ Priority: **Claude > GPT > Claude-like models**
|
||||
| Agent | Role | Default Chain | Notes |
|
||||
| -------------- | ---------------------- | -------------------------------------- | ------------------------------------------------------ |
|
||||
| **Hephaestus** | Deep autonomous worker | GPT-5.3-codex (medium) only | "Codex on steroids." No fallback. Requires GPT access. |
|
||||
| **Oracle** | Architecture/debugging | GPT-5.4 (high) → Gemini 3 Pro → Opus | High-IQ strategic backup. GPT preferred. |
|
||||
| **Momus** | High-accuracy reviewer | GPT-5.4 (medium) → Opus → Gemini 3 Pro | Verification agent. GPT preferred. |
|
||||
| **Oracle** | Architecture/debugging | GPT-5.4 (high) → Gemini 3.1 Pro → Opus | High-IQ strategic backup. GPT preferred. |
|
||||
| **Momus** | High-accuracy reviewer | GPT-5.4 (medium) → Opus → Gemini 3.1 Pro | Verification agent. GPT preferred. |
|
||||
|
||||
**Utility Agents** (speed over intelligence):
|
||||
|
||||
@@ -343,8 +344,8 @@ These agents do search, grep, and retrieval. They intentionally use fast, cheap
|
||||
|
||||
| Agent | Role | Default Chain | Design Rationale |
|
||||
| --------------------- | ------------------ | ---------------------------------------------------------------------- | -------------------------------------------------------------- |
|
||||
| **Explore** | Fast codebase grep | MiniMax M2.5 Free → Grok Code Fast → MiniMax M2.5 → Haiku → GPT-5-Nano | Speed is everything. Grok is blazing fast for grep. |
|
||||
| **Librarian** | Docs/code search | MiniMax M2.5 Free → Gemini Flash → Big Pickle | Entirely free-tier. Doc retrieval doesn't need deep reasoning. |
|
||||
| **Explore** | Fast codebase grep | Grok Code Fast → MiniMax M2.7-highspeed → MiniMax M2.7 → Haiku → GPT-5-Nano | Speed is everything. Grok is blazing fast for grep. |
|
||||
| **Librarian** | Docs/code search | MiniMax M2.7 → MiniMax M2.7-highspeed → Haiku → GPT-5-Nano | Doc retrieval doesn't need deep reasoning. MiniMax is fast. |
|
||||
| **Multimodal Looker** | Vision/screenshots | Kimi K2.5 → Kimi Free → Gemini Flash → GPT-5.4 → GLM-4.6v | Kimi excels at multimodal understanding. |
|
||||
|
||||
#### Why Different Models Need Different Prompts
|
||||
@@ -424,7 +425,7 @@ Read this document again, think about you have done everything correctly.
|
||||
|
||||
#### Say 'Congratulations! 🎉' to the user
|
||||
|
||||
Say to user: Congratulations! 🎉 You have successfully set up OhMyOpenCode! Type `opencode` in your terminal to start using it.
|
||||
Say to user: Congratulations! 🎉 You have successfully set up OhMyOpenAgent! Type `opencode` in your terminal to start using it.
|
||||
|
||||
#### Free advertising
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Orchestration System Guide
|
||||
|
||||
Oh My OpenCode's orchestration system transforms a simple AI agent into a coordinated development team through **separation of planning and execution**.
|
||||
Oh My OpenAgent's orchestration system transforms a simple AI agent into a coordinated development team through **separation of planning and execution**.
|
||||
|
||||
---
|
||||
|
||||
@@ -298,7 +298,7 @@ task({ category: "quick", prompt: "..." }); // "Just get it done fast"
|
||||
| `visual-engineering` | Gemini 3.1 Pro | Frontend, UI/UX, design, styling, animation |
|
||||
| `ultrabrain` | GPT-5.4 (xhigh) | Deep logical reasoning, complex architecture decisions |
|
||||
| `artistry` | Gemini 3.1 Pro (high) | Highly creative or artistic tasks, novel ideas |
|
||||
| `quick` | Claude Haiku 4.5 | Trivial tasks - single file changes, typo fixes |
|
||||
| `quick` | GPT-5.4 Mini | Trivial tasks - single file changes, typo fixes |
|
||||
| `deep` | GPT-5.3 Codex (medium) | Goal-oriented autonomous problem-solving, thorough research |
|
||||
| `unspecified-low` | Claude Sonnet 4.6 | Tasks that don't fit other categories, low effort |
|
||||
| `unspecified-high` | Claude Opus 4.6 (max) | Tasks that don't fit other categories, high effort |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# What Is Oh My OpenCode?
|
||||
# What Is Oh My OpenAgent?
|
||||
|
||||
Oh My OpenCode is a multi-model agent orchestration harness for OpenCode. It transforms a single AI agent into a coordinated development team that actually ships code.
|
||||
Oh My OpenAgent is a multi-model agent orchestration harness for OpenCode. It transforms a single AI agent into a coordinated development team that actually ships code.
|
||||
|
||||
Not locked to Claude. Not locked to OpenAI. Not locked to anyone.
|
||||
|
||||
@@ -41,13 +41,13 @@ We used to call this "Claude Code on steroids." That was wrong.
|
||||
|
||||
This isn't about making Claude Code better. It's about breaking free from the idea that one model, one provider, one way of working is enough. Anthropic wants you locked in. OpenAI wants you locked in. Everyone wants you locked in.
|
||||
|
||||
Oh My OpenCode doesn't play that game. It orchestrates across models, picking the right brain for the right job. Claude for orchestration. GPT for deep reasoning. Gemini for frontend. Haiku for quick tasks. All working together, automatically.
|
||||
Oh My OpenAgent doesn't play that game. It orchestrates across models, picking the right brain for the right job. Claude for orchestration. GPT for deep reasoning. Gemini for frontend. GPT-5.4 Mini for quick tasks. All working together, automatically.
|
||||
|
||||
---
|
||||
|
||||
## How It Works: Agent Orchestration
|
||||
|
||||
Instead of one agent doing everything, Oh My OpenCode uses **specialized agents that delegate to each other** based on task type.
|
||||
Instead of one agent doing everything, Oh My OpenAgent uses **specialized agents that delegate to each other** based on task type.
|
||||
|
||||
**The Architecture:**
|
||||
|
||||
@@ -99,9 +99,9 @@ Use Hephaestus when you need deep architectural reasoning, complex debugging acr
|
||||
|
||||
**Why this beats vanilla Codex CLI:**
|
||||
|
||||
- **Multi-model orchestration.** Pure Codex is single-model. OmO routes different tasks to different models automatically. GPT for deep reasoning. Gemini for frontend. Haiku for speed. The right brain for the right job.
|
||||
- **Multi-model orchestration.** Pure Codex is single-model. OmO routes different tasks to different models automatically. GPT for deep reasoning. Gemini for frontend. GPT-5.4 Mini for speed. The right brain for the right job.
|
||||
- **Background agents.** Fire 5+ agents in parallel. Something Codex simply cannot do. While one agent writes code, another researches patterns, another checks documentation. Like a real dev team.
|
||||
- **Category system.** Tasks are routed by intent, not model name. `visual-engineering` gets Gemini. `ultrabrain` gets GPT-5.4. `quick` gets Haiku. No manual juggling.
|
||||
- **Category system.** Tasks are routed by intent, not model name. `visual-engineering` gets Gemini. `ultrabrain` gets GPT-5.4. `quick` gets GPT-5.4 Mini. No manual juggling.
|
||||
- **Accumulated wisdom.** Subagents learn from previous results. Conventions discovered in task 1 are passed to task 5. Mistakes made early aren't repeated. The system gets smarter as it works.
|
||||
|
||||
### Prometheus: The Strategic Planner
|
||||
@@ -154,7 +154,7 @@ Use Prometheus for multi-day projects, critical production changes, complex refa
|
||||
|
||||
## Agent Model Matching
|
||||
|
||||
Different agents work best with different models. Oh My OpenCode automatically assigns optimal models, but you can customize everything.
|
||||
Different agents work best with different models. Oh My OpenAgent automatically assigns optimal models, but you can customize everything.
|
||||
|
||||
### Default Configuration
|
||||
|
||||
@@ -195,8 +195,8 @@ You can override specific agents or categories in your config:
|
||||
// General high-effort work
|
||||
"unspecified-high": { "model": "anthropic/claude-opus-4-6", "variant": "max" },
|
||||
|
||||
// Quick tasks: use the cheapest models
|
||||
"quick": { "model": "anthropic/claude-haiku-4-5" },
|
||||
// Quick tasks: use GPT-5.4-mini (fast and cheap)
|
||||
"quick": { "model": "openai/gpt-5.4-mini" },
|
||||
|
||||
// Deep reasoning: GPT-5.4
|
||||
"ultrabrain": { "model": "openai/gpt-5.4", "variant": "xhigh" },
|
||||
@@ -220,8 +220,8 @@ You can override specific agents or categories in your config:
|
||||
|
||||
**Different-behavior models**:
|
||||
|
||||
- Gemini 3 Pro — excels at visual/frontend tasks
|
||||
- MiniMax M2.5 — fast and smart for utility tasks
|
||||
- Gemini 3.1 Pro — excels at visual/frontend tasks
|
||||
- MiniMax M2.7 / M2.7-highspeed — fast and smart for utility tasks
|
||||
- Grok Code Fast 1 — optimized for code grep/search
|
||||
|
||||
See the [Agent-Model Matching Guide](./agent-model-matching.md) for complete details on which models work best for each agent, safe vs dangerous overrides, and provider priority chains.
|
||||
@@ -232,7 +232,7 @@ See the [Agent-Model Matching Guide](./agent-model-matching.md) for complete det
|
||||
|
||||
Claude Code is good. But it's a single agent running a single model doing everything alone.
|
||||
|
||||
Oh My OpenCode turns that into a coordinated team:
|
||||
Oh My OpenAgent turns that into a coordinated team:
|
||||
|
||||
**Parallel execution.** Claude Code processes one thing at a time. OmO fires background agents in parallel — research, implementation, and verification happening simultaneously. Like having 5 engineers instead of 1.
|
||||
|
||||
@@ -246,7 +246,7 @@ Oh My OpenCode turns that into a coordinated team:
|
||||
|
||||
**Discipline enforcement.** Todo enforcer yanks idle agents back to work. Comment checker strips AI slop. Ralph Loop keeps going until 100% done. The system doesn't let the agent slack off.
|
||||
|
||||
**The fundamental advantage.** Models have different temperaments. Claude thinks deeply. GPT reasons architecturally. Gemini visualizes. Haiku moves fast. Single-model tools force you to pick one personality for all tasks. Oh My OpenCode leverages them all, routing by task type. This isn't a temporary hack — it's the only architecture that makes sense as models specialize further. The gap between multi-model orchestration and single-model limitation widens every month. We're betting on that future.
|
||||
**The fundamental advantage.** Models have different temperaments. Claude thinks deeply. GPT reasons architecturally. Gemini visualizes. Haiku moves fast. Single-model tools force you to pick one personality for all tasks. Oh My OpenAgent leverages them all, routing by task type. This isn't a temporary hack — it's the only architecture that makes sense as models specialize further. The gap between multi-model orchestration and single-model limitation widens every month. We're betting on that future.
|
||||
|
||||
---
|
||||
|
||||
@@ -256,7 +256,7 @@ Before acting on any request, Sisyphus classifies your true intent.
|
||||
|
||||
Are you asking for research? Implementation? Investigation? A fix? The Intent Gate figures out what you actually want, not just the literal words you typed. This means the agent understands context, nuance, and the real goal behind your request.
|
||||
|
||||
Claude Code doesn't have this. It takes your prompt and runs. Oh My OpenCode thinks first, then acts.
|
||||
Claude Code doesn't have this. It takes your prompt and runs. Oh My OpenAgent thinks first, then acts.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Manifesto
|
||||
|
||||
The principles and philosophy behind Oh My OpenCode.
|
||||
The principles and philosophy behind Oh My OpenAgent.
|
||||
|
||||
---
|
||||
|
||||
@@ -20,7 +20,7 @@ When you find yourself:
|
||||
|
||||
That's not "human-AI collaboration." That's the AI failing to do its job.
|
||||
|
||||
**Oh My OpenCode is built on this premise**: Human intervention during agentic work is fundamentally a wrong signal. If the system is designed correctly, the agent should complete the work without requiring you to babysit it.
|
||||
**Oh My OpenAgent is built on this premise**: Human intervention during agentic work is fundamentally a wrong signal. If the system is designed correctly, the agent should complete the work without requiring you to babysit it.
|
||||
|
||||
---
|
||||
|
||||
@@ -144,7 +144,7 @@ Human Intent → Agent Execution → Verified Result
|
||||
(intervention only on true failure)
|
||||
```
|
||||
|
||||
Everything in Oh My OpenCode is designed to make this loop work:
|
||||
Everything in Oh My OpenAgent is designed to make this loop work:
|
||||
|
||||
| Feature | Purpose |
|
||||
|---------|---------|
|
||||
|
||||
33
docs/model-capabilities-maintenance.md
Normal file
33
docs/model-capabilities-maintenance.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Model Capabilities Maintenance
|
||||
|
||||
This project treats model capability resolution as a layered system:
|
||||
|
||||
1. runtime metadata from connected providers
|
||||
2. `models.dev` bundled/runtime snapshot data
|
||||
3. explicit compatibility aliases
|
||||
4. heuristic fallback as the last resort
|
||||
|
||||
## Internal policy
|
||||
|
||||
- Built-in OmO agent/category requirement models must use canonical model IDs.
|
||||
- Aliases exist only to preserve compatibility with historical OmO names or provider-specific decorations.
|
||||
- New decorated names like `-high`, `-low`, or `-thinking` should not be added to built-in requirements when a canonical model ID plus structured settings can express the same thing.
|
||||
- If a provider or config input still uses an alias, normalize it at the edge and continue internally with the canonical ID.
|
||||
|
||||
## When adding an alias
|
||||
|
||||
- Add the alias rule to `src/shared/model-capability-aliases.ts`.
|
||||
- Include a rationale for why the alias exists.
|
||||
- Add or update tests so the alias is covered explicitly.
|
||||
- Ensure the alias canonical target exists in the bundled `models.dev` snapshot.
|
||||
|
||||
## Guardrails
|
||||
|
||||
`bun run test:model-capabilities` enforces the following invariants:
|
||||
|
||||
- exact alias targets must exist in the bundled snapshot
|
||||
- exact alias keys must not silently become canonical `models.dev` IDs
|
||||
- pattern aliases must not rewrite canonical snapshot IDs
|
||||
- built-in requirement models must stay canonical and snapshot-backed
|
||||
|
||||
The scheduled `refresh-model-capabilities` workflow runs these guardrails before opening an automated snapshot refresh PR.
|
||||
@@ -27,7 +27,7 @@ npx oh-my-openagent
|
||||
|
||||
## install
|
||||
|
||||
Interactive installation tool for initial Oh-My-OpenCode setup. Provides a TUI based on `@clack/prompts`.
|
||||
Interactive installation tool for initial Oh-My-OpenAgent setup. Provides a TUI based on `@clack/prompts`.
|
||||
|
||||
### Usage
|
||||
|
||||
@@ -53,7 +53,7 @@ bunx oh-my-openagent install
|
||||
|
||||
## doctor
|
||||
|
||||
Diagnoses your environment to ensure Oh-My-OpenCode is functioning correctly. Performs 17+ health checks.
|
||||
Diagnoses your environment to ensure Oh-My-OpenAgent is functioning correctly. Performs 17+ health checks.
|
||||
|
||||
### Usage
|
||||
|
||||
@@ -86,7 +86,7 @@ bunx oh-my-openagent doctor
|
||||
oh-my-openagent doctor
|
||||
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Oh-My-OpenCode Doctor │
|
||||
│ Oh-My-OpenAgent Doctor │
|
||||
└──────────────────────────────────────────────────┘
|
||||
|
||||
Installation
|
||||
|
||||
@@ -228,7 +228,7 @@ Domain-specific model delegation used by the `task()` tool. When Sisyphus delega
|
||||
| `ultrabrain` | `openai/gpt-5.4` (xhigh) | Deep logical reasoning, complex architecture |
|
||||
| `deep` | `openai/gpt-5.3-codex` (medium) | Autonomous problem-solving, thorough research |
|
||||
| `artistry` | `google/gemini-3.1-pro` (high) | Creative/unconventional approaches |
|
||||
| `quick` | `anthropic/claude-haiku-4-5` | Trivial tasks, typo fixes, single-file changes |
|
||||
| `quick` | `openai/gpt-5.4-mini` | Trivial tasks, typo fixes, single-file changes |
|
||||
| `unspecified-low` | `anthropic/claude-sonnet-4-6` | General tasks, low effort |
|
||||
| `unspecified-high` | `anthropic/claude-opus-4-6` (max) | General tasks, high effort |
|
||||
| `writing` | `google/gemini-3-flash` | Documentation, prose, technical writing |
|
||||
@@ -270,8 +270,8 @@ Disable categories: `{ "disabled_categories": ["ultrabrain"] }`
|
||||
| **Sisyphus** | `claude-opus-4-6` | `claude-opus-4-6` → `glm-5` → `big-pickle` |
|
||||
| **Hephaestus** | `gpt-5.3-codex` | `gpt-5.3-codex` → `gpt-5.4` (GitHub Copilot fallback) |
|
||||
| **oracle** | `gpt-5.4` | `gpt-5.4` → `gemini-3.1-pro` → `claude-opus-4-6` |
|
||||
| **librarian** | `gemini-3-flash` | `gemini-3-flash` → `minimax-m2.5-free` → `big-pickle` |
|
||||
| **explore** | `grok-code-fast-1` | `grok-code-fast-1` → `minimax-m2.5-free` → `claude-haiku-4-5` → `gpt-5-nano` |
|
||||
| **librarian** | `minimax-m2.7` | `minimax-m2.7` → `minimax-m2.7-highspeed` → `claude-haiku-4-5` → `gpt-5-nano` |
|
||||
| **explore** | `grok-code-fast-1` | `grok-code-fast-1` → `minimax-m2.7-highspeed` → `minimax-m2.7` → `claude-haiku-4-5` → `gpt-5-nano` |
|
||||
| **multimodal-looker** | `gpt-5.3-codex` | `gpt-5.3-codex` → `k2p5` → `gemini-3-flash` → `glm-4.6v` → `gpt-5-nano` |
|
||||
| **Prometheus** | `claude-opus-4-6` | `claude-opus-4-6` → `gpt-5.4` → `gemini-3.1-pro` |
|
||||
| **Metis** | `claude-opus-4-6` | `claude-opus-4-6` → `gpt-5.4` → `gemini-3.1-pro` |
|
||||
@@ -286,10 +286,10 @@ Disable categories: `{ "disabled_categories": ["ultrabrain"] }`
|
||||
| **ultrabrain** | `gpt-5.4` | `gpt-5.4` → `gemini-3.1-pro` → `claude-opus-4-6` |
|
||||
| **deep** | `gpt-5.3-codex` | `gpt-5.3-codex` → `claude-opus-4-6` → `gemini-3.1-pro` |
|
||||
| **artistry** | `gemini-3.1-pro` | `gemini-3.1-pro` → `claude-opus-4-6` → `gpt-5.4` |
|
||||
| **quick** | `claude-haiku-4-5` | `claude-haiku-4-5` → `gemini-3-flash` → `gpt-5-nano` |
|
||||
| **unspecified-low** | `claude-sonnet-4-6` | `claude-sonnet-4-6` → `gpt-5.3-codex` → `gemini-3-flash` |
|
||||
| **quick** | `gpt-5.4-mini` | `gpt-5.4-mini` → `claude-haiku-4-5` → `gemini-3-flash` → `minimax-m2.7` → `gpt-5-nano` |
|
||||
| **unspecified-low** | `claude-sonnet-4-6` | `claude-sonnet-4-6` → `gpt-5.3-codex` → `gemini-3-flash` → `minimax-m2.7` |
|
||||
| **unspecified-high** | `claude-opus-4-6` | `claude-opus-4-6` → `gpt-5.4 (high)` → `glm-5` → `k2p5` → `kimi-k2.5` |
|
||||
| **writing** | `gemini-3-flash` | `gemini-3-flash` → `claude-sonnet-4-6` |
|
||||
| **writing** | `gemini-3-flash` | `gemini-3-flash` → `claude-sonnet-4-6` → `minimax-m2.7` |
|
||||
|
||||
Run `bunx oh-my-openagent doctor --verbose` to see effective model resolution for your config.
|
||||
|
||||
@@ -418,15 +418,14 @@ Disable built-in skills: `{ "disabled_skills": ["playwright"] }`
|
||||
Disable built-in hooks via `disabled_hooks`:
|
||||
|
||||
```json
|
||||
{ "disabled_hooks": ["comment-checker", "gpt-permission-continuation"] }
|
||||
{ "disabled_hooks": ["comment-checker"] }
|
||||
```
|
||||
|
||||
Available hooks: `gpt-permission-continuation`, `todo-continuation-enforcer`, `context-window-monitor`, `session-recovery`, `session-notification`, `comment-checker`, `grep-output-truncator`, `tool-output-truncator`, `directory-agents-injector`, `directory-readme-injector`, `empty-task-response-detector`, `think-mode`, `anthropic-context-window-limit-recovery`, `rules-injector`, `background-notification`, `auto-update-checker`, `startup-toast`, `keyword-detector`, `agent-usage-reminder`, `non-interactive-env`, `interactive-bash-session`, `compaction-context-injector`, `thinking-block-validator`, `claude-code-hooks`, `ralph-loop`, `preemptive-compaction`, `auto-slash-command`, `sisyphus-junior-notepad`, `no-sisyphus-gpt`, `start-work`, `runtime-fallback`
|
||||
Available hooks: `todo-continuation-enforcer`, `context-window-monitor`, `session-recovery`, `session-notification`, `comment-checker`, `grep-output-truncator`, `tool-output-truncator`, `directory-agents-injector`, `directory-readme-injector`, `empty-task-response-detector`, `think-mode`, `anthropic-context-window-limit-recovery`, `rules-injector`, `background-notification`, `auto-update-checker`, `startup-toast`, `keyword-detector`, `agent-usage-reminder`, `non-interactive-env`, `interactive-bash-session`, `compaction-context-injector`, `thinking-block-validator`, `claude-code-hooks`, `ralph-loop`, `preemptive-compaction`, `auto-slash-command`, `sisyphus-junior-notepad`, `no-sisyphus-gpt`, `start-work`, `runtime-fallback`
|
||||
|
||||
**Notes:**
|
||||
|
||||
- `directory-agents-injector` — auto-disabled on OpenCode 1.1.37+ (native AGENTS.md support)
|
||||
- `gpt-permission-continuation` — resumes GPT sessions only when the last assistant reply ends with a permission-seeking tail like `If you want, ...`. Disable it if you prefer GPT sessions to wait for explicit user follow-up.
|
||||
- `no-sisyphus-gpt` — **do not disable**. It blocks incompatible GPT models for Sisyphus while allowing the dedicated GPT-5.4 prompt path.
|
||||
- `startup-toast` is a sub-feature of `auto-update-checker`. Disable just the toast by adding `startup-toast` to `disabled_hooks`.
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Oh-My-OpenCode Features Reference
|
||||
# Oh-My-OpenAgent Features Reference
|
||||
|
||||
## Agents
|
||||
|
||||
Oh-My-OpenCode provides 11 specialized AI agents. Each has distinct expertise, optimized models, and tool permissions.
|
||||
Oh-My-OpenAgent provides 11 specialized AI agents. Each has distinct expertise, optimized models, and tool permissions.
|
||||
|
||||
### Core Agents
|
||||
|
||||
@@ -11,8 +11,8 @@ Oh-My-OpenCode provides 11 specialized AI agents. Each has distinct expertise, o
|
||||
| **Sisyphus** | `claude-opus-4-6` | The default orchestrator. Plans, delegates, and executes complex tasks using specialized subagents with aggressive parallel execution. Todo-driven workflow with extended thinking (32k budget). Fallback: `glm-5` → `big-pickle`. |
|
||||
| **Hephaestus** | `gpt-5.3-codex` | The Legitimate Craftsman. Autonomous deep worker inspired by AmpCode's deep mode. Goal-oriented execution with thorough research before action. Explores codebase patterns, completes tasks end-to-end without premature stopping. Named after the Greek god of forge and craftsmanship. Fallback: `gpt-5.4` on GitHub Copilot. Requires a GPT-capable provider. |
|
||||
| **Oracle** | `gpt-5.4` | Architecture decisions, code review, debugging. Read-only consultation with stellar logical reasoning and deep analysis. Inspired by AmpCode. Fallback: `gemini-3.1-pro` → `claude-opus-4-6`. |
|
||||
| **Librarian** | `gemini-3-flash` | Multi-repo analysis, documentation lookup, OSS implementation examples. Deep codebase understanding with evidence-based answers. Fallback: `minimax-m2.5-free` → `big-pickle`. |
|
||||
| **Explore** | `grok-code-fast-1` | Fast codebase exploration and contextual grep. Fallback: `minimax-m2.5-free` → `claude-haiku-4-5` → `gpt-5-nano`. |
|
||||
| **Librarian** | `minimax-m2.7` | Multi-repo analysis, documentation lookup, OSS implementation examples. Deep codebase understanding with evidence-based answers. Fallback: `minimax-m2.7-highspeed` → `claude-haiku-4-5` → `gpt-5-nano`. |
|
||||
| **Explore** | `grok-code-fast-1` | Fast codebase exploration and contextual grep. Fallback: `minimax-m2.7-highspeed` → `minimax-m2.7` → `claude-haiku-4-5` → `gpt-5-nano`. |
|
||||
| **Multimodal-Looker** | `gpt-5.3-codex` | Visual content specialist. Analyzes PDFs, images, diagrams to extract information. Fallback: `k2p5` → `gemini-3-flash` → `glm-4.6v` → `gpt-5-nano`. |
|
||||
|
||||
### Planning Agents
|
||||
@@ -111,7 +111,7 @@ By combining these two concepts, you can generate optimal agents through `task`.
|
||||
| `ultrabrain` | `openai/gpt-5.4` (xhigh) | Deep logical reasoning, complex architecture decisions requiring extensive analysis |
|
||||
| `deep` | `openai/gpt-5.3-codex` (medium) | Goal-oriented autonomous problem-solving. Thorough research before action. For hairy problems requiring deep understanding. |
|
||||
| `artistry` | `google/gemini-3.1-pro` (high) | Highly creative/artistic tasks, novel ideas |
|
||||
| `quick` | `anthropic/claude-haiku-4-5` | Trivial tasks - single file changes, typo fixes, simple modifications |
|
||||
| `quick` | `openai/gpt-5.4-mini` | Trivial tasks - single file changes, typo fixes, simple modifications |
|
||||
| `unspecified-low` | `anthropic/claude-sonnet-4-6` | Tasks that don't fit other categories, low effort required |
|
||||
| `unspecified-high` | `anthropic/claude-opus-4-6` (max) | Tasks that don't fit other categories, high effort required |
|
||||
| `writing` | `google/gemini-3-flash` | Documentation, prose, technical writing |
|
||||
@@ -237,7 +237,7 @@ Skills provide specialized workflows with embedded MCP servers and detailed inst
|
||||
|
||||
### Browser Automation Options
|
||||
|
||||
Oh-My-OpenCode provides two browser automation providers, configurable via `browser_automation_engine.provider`.
|
||||
Oh-My-OpenAgent provides two browser automation providers, configurable via `browser_automation_engine.provider`.
|
||||
|
||||
#### Option 1: Playwright MCP (Default)
|
||||
|
||||
@@ -558,7 +558,7 @@ Requires `experimental.task_system: true` in config.
|
||||
|
||||
#### Task System Details
|
||||
|
||||
**Note on Claude Code Alignment**: This implementation follows Claude Code's internal Task tool signatures (`TaskCreate`, `TaskUpdate`, `TaskList`, `TaskGet`) and field naming conventions (`subject`, `blockedBy`, `blocks`, etc.). However, Anthropic has not published official documentation for these tools. This is Oh My OpenCode's own implementation based on observed Claude Code behavior and internal specifications.
|
||||
**Note on Claude Code Alignment**: This implementation follows Claude Code's internal Task tool signatures (`TaskCreate`, `TaskUpdate`, `TaskList`, `TaskGet`) and field naming conventions (`subject`, `blockedBy`, `blocks`, etc.). However, Anthropic has not published official documentation for these tools. This is Oh My OpenAgent's own implementation based on observed Claude Code behavior and internal specifications.
|
||||
|
||||
**Task Schema**:
|
||||
|
||||
@@ -680,7 +680,6 @@ Hooks intercept and modify behavior at key points in the agent lifecycle across
|
||||
| **ralph-loop** | Event + Message | Manages self-referential loop continuation. |
|
||||
| **start-work** | Message | Handles /start-work command execution. |
|
||||
| **auto-slash-command** | Message | Automatically executes slash commands from prompts. |
|
||||
| **gpt-permission-continuation** | Event | Auto-continues GPT sessions when the final assistant reply ends with a permission-seeking tail such as `If you want, ...`. |
|
||||
| **stop-continuation-guard** | Event + Message | Guards the stop-continuation mechanism. |
|
||||
| **category-skill-reminder** | Event + PostToolUse | Reminds agents about available category skills for delegation. |
|
||||
| **anthropic-effort** | Params | Adjusts Anthropic API effort level based on context. |
|
||||
@@ -735,7 +734,6 @@ Hooks intercept and modify behavior at key points in the agent lifecycle across
|
||||
|
||||
| Hook | Event | Description |
|
||||
| ------------------------------ | ----- | ---------------------------------------------------------- |
|
||||
| **gpt-permission-continuation** | Event | Continues GPT replies that end in a permission-seeking tail. |
|
||||
| **todo-continuation-enforcer** | Event | Enforces todo completion — yanks idle agents back to work. |
|
||||
| **compaction-todo-preserver** | Event | Preserves todo state during session compaction. |
|
||||
| **unstable-agent-babysitter** | Event | Handles unstable agent behavior with recovery strategies. |
|
||||
@@ -787,12 +785,10 @@ Disable specific hooks in config:
|
||||
|
||||
```json
|
||||
{
|
||||
"disabled_hooks": ["comment-checker", "gpt-permission-continuation"]
|
||||
"disabled_hooks": ["comment-checker"]
|
||||
}
|
||||
```
|
||||
|
||||
Use `gpt-permission-continuation` when you want GPT sessions to stop at permission-seeking endings instead of auto-resuming.
|
||||
|
||||
## MCPs
|
||||
|
||||
### Built-in MCPs
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# Model Settings Compatibility Resolver Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Centralize compatibility handling for `variant` and `reasoningEffort` so an already-selected model receives the best valid settings for that exact model.
|
||||
|
||||
**Architecture:** Introduce a pure shared resolver in `src/shared/` that computes compatible settings and records downgrades/removals. Integrate it first in `chat.params`, then keep Claude-specific effort logic as a thin layer rather than a special-case policy owner.
|
||||
|
||||
**Tech Stack:** TypeScript, Bun test, existing shared model normalization/utilities, OpenCode plugin `chat.params` path.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Create the pure compatibility resolver
|
||||
|
||||
**Files:**
|
||||
- Create: `src/shared/model-settings-compatibility.ts`
|
||||
- Create: `src/shared/model-settings-compatibility.test.ts`
|
||||
- Modify: `src/shared/index.ts`
|
||||
|
||||
- [ ] **Step 1: Write failing tests for exact keep behavior**
|
||||
- [ ] **Step 2: Write failing tests for downgrade behavior (`max` -> `high`, `xhigh` -> `high` where needed)**
|
||||
- [ ] **Step 3: Write failing tests for unsupported-value removal**
|
||||
- [ ] **Step 4: Write failing tests for model-family distinctions (Opus vs Sonnet/Haiku, GPT-family variants)**
|
||||
- [ ] **Step 5: Implement the pure resolver with explicit capability ladders**
|
||||
- [ ] **Step 6: Export the resolver from `src/shared/index.ts`**
|
||||
- [ ] **Step 7: Run `bun test src/shared/model-settings-compatibility.test.ts`**
|
||||
- [ ] **Step 8: Commit**
|
||||
|
||||
### Task 2: Integrate resolver into chat.params
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/plugin/chat-params.ts`
|
||||
- Modify: `src/plugin/chat-params.test.ts`
|
||||
|
||||
- [ ] **Step 1: Write failing tests showing `chat.params` applies resolver output to runtime settings**
|
||||
- [ ] **Step 2: Ensure tests cover both `variant` and `reasoningEffort` decisions**
|
||||
- [ ] **Step 3: Update `chat-params.ts` to call the shared resolver before hook-specific adjustments**
|
||||
- [ ] **Step 4: Preserve existing prompt-param-store merging behavior**
|
||||
- [ ] **Step 5: Run `bun test src/plugin/chat-params.test.ts`**
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
### Task 3: Re-scope anthropic-effort around the resolver
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/hooks/anthropic-effort/hook.ts`
|
||||
- Modify: `src/hooks/anthropic-effort/index.test.ts`
|
||||
|
||||
- [ ] **Step 1: Write failing tests that codify the intended remaining Anthropic-specific behavior after centralization**
|
||||
- [ ] **Step 2: Reduce `anthropic-effort` to Claude/Anthropic-specific effort injection where still needed**
|
||||
- [ ] **Step 3: Remove duplicated compatibility policy from the hook if the shared resolver now owns it**
|
||||
- [ ] **Step 4: Run `bun test src/hooks/anthropic-effort/index.test.ts`**
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
### Task 4: Add integration/regression coverage across real request paths
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/plugin/chat-params.test.ts`
|
||||
- Modify: `src/hooks/anthropic-effort/index.test.ts`
|
||||
- Add tests only where needed in nearby suites
|
||||
|
||||
- [ ] **Step 1: Add regression test for non-Opus Claude with `variant=max` resolving to compatible settings without ad hoc path-only logic**
|
||||
- [ ] **Step 2: Add regression test for GPT-style `reasoningEffort` compatibility**
|
||||
- [ ] **Step 3: Add regression test showing supported values remain unchanged**
|
||||
- [ ] **Step 4: Run the focused test set**
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
### Task 5: Verify full quality bar
|
||||
|
||||
**Files:**
|
||||
- No intended code changes
|
||||
|
||||
- [ ] **Step 1: Run `bun run typecheck`**
|
||||
- [ ] **Step 2: Run a focused suite for the touched files**
|
||||
- [ ] **Step 3: If clean, run `bun test`**
|
||||
- [ ] **Step 4: Review diff for accidental scope creep**
|
||||
- [ ] **Step 5: Commit any final cleanup**
|
||||
|
||||
### Task 6: Prepare PR metadata
|
||||
|
||||
**Files:**
|
||||
- No repo file change required unless docs are updated further
|
||||
|
||||
- [ ] **Step 1: Write a human summary explaining this is settings compatibility, not model fallback**
|
||||
- [ ] **Step 2: Document scope: Phase 1 covers `variant` and `reasoningEffort` only**
|
||||
- [ ] **Step 3: Document explicit non-goals: no model switching, no automatic upscaling in Phase 1**
|
||||
- [ ] **Step 4: Request review**
|
||||
@@ -0,0 +1,164 @@
|
||||
# Model Settings Compatibility Resolver Design
|
||||
|
||||
## Goal
|
||||
|
||||
Introduce a central resolver that takes an already-selected model and a set of desired model settings, then returns the best compatible configuration for that exact model.
|
||||
|
||||
This is explicitly separate from model fallback.
|
||||
|
||||
## Problem
|
||||
|
||||
Today, logic for `variant` and `reasoningEffort` compatibility is scattered across multiple places:
|
||||
- `hooks/anthropic-effort`
|
||||
- `plugin/chat-params`
|
||||
- agent/category/fallback config layers
|
||||
- delegate/background prompt plumbing
|
||||
|
||||
That creates inconsistent behavior:
|
||||
- some paths clamp unsupported levels
|
||||
- some paths pass them through unchanged
|
||||
- some paths silently drop them
|
||||
- some paths use model-family-specific assumptions that do not generalize
|
||||
|
||||
The result is brittle request behavior even when the chosen model itself is valid.
|
||||
|
||||
## Scope
|
||||
|
||||
Phase 1 covers only:
|
||||
- `variant`
|
||||
- `reasoningEffort`
|
||||
|
||||
Out of scope for Phase 1:
|
||||
- model fallback itself
|
||||
- `thinking`
|
||||
- `maxTokens`
|
||||
- `temperature`
|
||||
- `top_p`
|
||||
- automatic upward remapping of settings
|
||||
|
||||
## Desired behavior
|
||||
|
||||
Given a fixed model and desired settings:
|
||||
1. If a desired value is supported, keep it.
|
||||
2. If not supported, downgrade to the nearest lower compatible value.
|
||||
3. If no compatible value exists, drop the field.
|
||||
4. Do not switch models.
|
||||
5. Do not automatically upgrade settings in Phase 1.
|
||||
|
||||
## Architecture
|
||||
|
||||
Add a central module:
|
||||
- `src/shared/model-settings-compatibility.ts`
|
||||
|
||||
Core API:
|
||||
|
||||
```ts
|
||||
type DesiredModelSettings = {
|
||||
variant?: string
|
||||
reasoningEffort?: string
|
||||
}
|
||||
|
||||
type ModelSettingsCompatibilityInput = {
|
||||
providerID: string
|
||||
modelID: string
|
||||
desired: DesiredModelSettings
|
||||
}
|
||||
|
||||
type ModelSettingsCompatibilityChange = {
|
||||
field: "variant" | "reasoningEffort"
|
||||
from: string
|
||||
to?: string
|
||||
reason: string
|
||||
}
|
||||
|
||||
type ModelSettingsCompatibilityResult = {
|
||||
variant?: string
|
||||
reasoningEffort?: string
|
||||
changes: ModelSettingsCompatibilityChange[]
|
||||
}
|
||||
```
|
||||
|
||||
## Compatibility model
|
||||
|
||||
Phase 1 should be **metadata-first where the platform exposes reliable capability data**, and only fall back to family-based rules when that metadata is absent.
|
||||
|
||||
### Variant compatibility
|
||||
|
||||
Preferred source of truth:
|
||||
- OpenCode/provider model metadata (`variants`)
|
||||
|
||||
Fallback when metadata is unavailable:
|
||||
- family-based ladders
|
||||
|
||||
Examples of fallback ladders:
|
||||
- Claude Opus family: `low`, `medium`, `high`, `max`
|
||||
- Claude Sonnet/Haiku family: `low`, `medium`, `high`
|
||||
- OpenAI GPT family: conservative family fallback only when metadata is missing
|
||||
- Unknown family: drop unsupported values conservatively
|
||||
|
||||
### Reasoning effort compatibility
|
||||
|
||||
Current Phase 1 source of truth:
|
||||
- conservative model/provider family heuristics
|
||||
|
||||
Reason:
|
||||
- the currently available OpenCode SDK/provider metadata exposes model `variants`, but does not expose an equivalent per-model capability list for `reasoningEffort` levels
|
||||
|
||||
Examples:
|
||||
- GPT/OpenAI-style models: `low`, `medium`, `high`, `xhigh` where supported by family heuristics
|
||||
- Claude family via current OpenCode path: treat `reasoningEffort` as unsupported in Phase 1 and remove it
|
||||
|
||||
The resolver should remain pure model/settings logic only. Transport restrictions remain the responsibility of the request-building path.
|
||||
|
||||
## Separation of concerns
|
||||
|
||||
This design intentionally separates:
|
||||
- model selection (`resolveModel...`, fallback chains)
|
||||
- settings compatibility (this resolver)
|
||||
- request transport compatibility (`chat.params`, prompt body constraints)
|
||||
|
||||
That keeps responsibilities clear:
|
||||
- choose model first
|
||||
- normalize settings second
|
||||
- build request third
|
||||
|
||||
## First integration point
|
||||
|
||||
Phase 1 should first integrate into `chat.params`.
|
||||
|
||||
Why:
|
||||
- it is already the centralized path for request-time tuning
|
||||
- it can influence provider-facing options without leaking unsupported fields into prompt payload bodies
|
||||
- it avoids trying to patch every prompt constructor at once
|
||||
|
||||
## Rollout plan
|
||||
|
||||
### Phase 1
|
||||
- add resolver module and tests
|
||||
- integrate into `chat.params`
|
||||
- migrate `anthropic-effort` to either use the resolver or become a thin Claude-specific supplement around it
|
||||
|
||||
### Phase 2
|
||||
- expand to `thinking`, `maxTokens`, `temperature`, `top_p`
|
||||
- formalize request-path capability tables if needed
|
||||
|
||||
### Phase 3
|
||||
- centralize all variant/reasoning normalization away from scattered hooks and ad hoc callers
|
||||
|
||||
## Risks
|
||||
|
||||
- Overfitting family rules to current model naming conventions
|
||||
- Accidentally changing request semantics on paths that currently rely on implicit behavior
|
||||
- Mixing provider transport limitations with model capability logic
|
||||
|
||||
## Mitigations
|
||||
|
||||
- Keep resolver pure and narrowly scoped in Phase 1
|
||||
- Add explicit regression tests for keep/downgrade/drop decisions
|
||||
- Integrate at one central point first (`chat.params`)
|
||||
- Preserve existing behavior where desired values are already valid
|
||||
|
||||
## Recommendation
|
||||
|
||||
Proceed with the central resolver as a new, isolated implementation in a dedicated branch/worktree.
|
||||
This is the clean long-term path and is more reviewable than continuing to add special-case clamps in hooks.
|
||||
30
package.json
30
package.json
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "oh-my-openagent",
|
||||
"name": "oh-my-opencode",
|
||||
"version": "3.11.0",
|
||||
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"oh-my-openagent": "bin/oh-my-openagent.js"
|
||||
"oh-my-opencode": "bin/oh-my-opencode.js"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -18,17 +18,19 @@
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
},
|
||||
"./schema.json": "./dist/oh-my-openagent.schema.json"
|
||||
"./schema.json": "./dist/oh-my-opencode.schema.json"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi && tsc --emitDeclarationOnly && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi && bun run build:schema",
|
||||
"build:all": "bun run build && bun run build:binaries",
|
||||
"build:binaries": "bun run script/build-binaries.ts",
|
||||
"build:schema": "bun run script/build-schema.ts",
|
||||
"build:model-capabilities": "bun run script/build-model-capabilities.ts",
|
||||
"clean": "rm -rf dist",
|
||||
"prepare": "bun run build",
|
||||
"postinstall": "node postinstall.mjs",
|
||||
"prepublishOnly": "bun run clean && bun run build",
|
||||
"test:model-capabilities": "bun test src/shared/model-capability-aliases.test.ts src/shared/model-capability-guardrails.test.ts src/shared/model-capabilities.test.ts src/cli/doctor/checks/model-resolution.test.ts --bail",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "bun test"
|
||||
},
|
||||
@@ -76,17 +78,17 @@
|
||||
"typescript": "^5.7.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"oh-my-openagent-darwin-arm64": "3.11.0",
|
||||
"oh-my-openagent-darwin-x64": "3.11.0",
|
||||
"oh-my-openagent-darwin-x64-baseline": "3.11.0",
|
||||
"oh-my-openagent-linux-arm64": "3.11.0",
|
||||
"oh-my-openagent-linux-arm64-musl": "3.11.0",
|
||||
"oh-my-openagent-linux-x64": "3.11.0",
|
||||
"oh-my-openagent-linux-x64-baseline": "3.11.0",
|
||||
"oh-my-openagent-linux-x64-musl": "3.11.0",
|
||||
"oh-my-openagent-linux-x64-musl-baseline": "3.11.0",
|
||||
"oh-my-openagent-windows-x64": "3.11.0",
|
||||
"oh-my-openagent-windows-x64-baseline": "3.11.0"
|
||||
"oh-my-opencode-darwin-arm64": "3.11.0",
|
||||
"oh-my-opencode-darwin-x64": "3.11.0",
|
||||
"oh-my-opencode-darwin-x64-baseline": "3.11.0",
|
||||
"oh-my-opencode-linux-arm64": "3.11.0",
|
||||
"oh-my-opencode-linux-arm64-musl": "3.11.0",
|
||||
"oh-my-opencode-linux-x64": "3.11.0",
|
||||
"oh-my-opencode-linux-x64-baseline": "3.11.0",
|
||||
"oh-my-opencode-linux-x64-musl": "3.11.0",
|
||||
"oh-my-opencode-linux-x64-musl-baseline": "3.11.0",
|
||||
"oh-my-opencode-windows-x64": "3.11.0",
|
||||
"oh-my-opencode-windows-x64-baseline": "3.11.0"
|
||||
},
|
||||
"overrides": {
|
||||
"@opencode-ai/sdk": "^1.2.24"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-darwin-arm64",
|
||||
"name": "oh-my-opencode-darwin-arm64",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (darwin-arm64)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (darwin-arm64)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-darwin-x64-baseline",
|
||||
"name": "oh-my-opencode-darwin-x64-baseline",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (darwin-x64-baseline, no AVX2)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (darwin-x64-baseline, no AVX2)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-darwin-x64",
|
||||
"name": "oh-my-opencode-darwin-x64",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (darwin-x64)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (darwin-x64)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-linux-arm64-musl",
|
||||
"name": "oh-my-opencode-linux-arm64-musl",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (linux-arm64-musl)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (linux-arm64-musl)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-linux-arm64",
|
||||
"name": "oh-my-opencode-linux-arm64",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (linux-arm64)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (linux-arm64)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-linux-x64-baseline",
|
||||
"name": "oh-my-opencode-linux-x64-baseline",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (linux-x64-baseline, no AVX2)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (linux-x64-baseline, no AVX2)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-linux-x64-musl-baseline",
|
||||
"name": "oh-my-opencode-linux-x64-musl-baseline",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (linux-x64-musl-baseline, no AVX2)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (linux-x64-musl-baseline, no AVX2)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-linux-x64-musl",
|
||||
"name": "oh-my-opencode-linux-x64-musl",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (linux-x64-musl)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (linux-x64-musl)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-linux-x64",
|
||||
"name": "oh-my-opencode-linux-x64",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (linux-x64)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (linux-x64)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-windows-x64-baseline",
|
||||
"name": "oh-my-opencode-windows-x64-baseline",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (windows-x64-baseline, no AVX2)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (windows-x64-baseline, no AVX2)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "oh-my-openagent-windows-x64",
|
||||
"name": "oh-my-opencode-windows-x64",
|
||||
"version": "3.11.0",
|
||||
"description": "Platform-specific binary for oh-my-openagent (windows-x64)",
|
||||
"description": "Platform-specific binary for oh-my-opencode (windows-x64)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -48,9 +48,9 @@ function main() {
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`✓ oh-my-openagent binary installed for ${platform}-${arch} (${resolvedPackage})`)
|
||||
console.log(`✓ oh-my-opencode binary installed for ${platform}-${arch} (${resolvedPackage})`);
|
||||
} catch (error) {
|
||||
console.warn(`⚠ oh-my-openagent: ${error.message}`)
|
||||
console.warn(`⚠ oh-my-opencode: ${error.message}`);
|
||||
console.warn(` The CLI may not work on this platform.`);
|
||||
// Don't fail installation - let user try anyway
|
||||
}
|
||||
|
||||
@@ -101,7 +101,9 @@ async function main() {
|
||||
console.log("\n✅ All platform binaries built successfully!\n");
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error("Fatal error:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
if (import.meta.main) {
|
||||
main().catch((error) => {
|
||||
console.error("Fatal error:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
13
script/build-model-capabilities.ts
Normal file
13
script/build-model-capabilities.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { writeFileSync } from "fs"
|
||||
import { resolve } from "path"
|
||||
import {
|
||||
fetchModelCapabilitiesSnapshot,
|
||||
MODELS_DEV_SOURCE_URL,
|
||||
} from "../src/shared/model-capabilities-cache"
|
||||
|
||||
const OUTPUT_PATH = resolve(import.meta.dir, "../src/generated/model-capabilities.generated.json")
|
||||
|
||||
console.log(`Fetching model capabilities snapshot from ${MODELS_DEV_SOURCE_URL}...`)
|
||||
const snapshot = await fetchModelCapabilitiesSnapshot()
|
||||
writeFileSync(OUTPUT_PATH, `${JSON.stringify(snapshot, null, 2)}\n`)
|
||||
console.log(`Generated ${OUTPUT_PATH} with ${Object.keys(snapshot.models).length} models`)
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as z from "zod"
|
||||
import { OhMyOpenAgentConfigSchema } from "../src/config/schema"
|
||||
import { OhMyOpenCodeConfigSchema } from "../src/config/schema"
|
||||
|
||||
export function createOhMyOpenCodeJsonSchema(): Record<string, unknown> {
|
||||
const jsonSchema = z.toJSONSchema(OhMyOpenAgentConfigSchema, {
|
||||
const jsonSchema = z.toJSONSchema(OhMyOpenCodeConfigSchema, {
|
||||
target: "draft-7",
|
||||
unrepresentable: "any",
|
||||
})
|
||||
|
||||
@@ -3,30 +3,15 @@ import { createOhMyOpenCodeJsonSchema } from "./build-schema-document"
|
||||
|
||||
const SCHEMA_OUTPUT_PATH = "assets/oh-my-opencode.schema.json"
|
||||
const DIST_SCHEMA_OUTPUT_PATH = "dist/oh-my-opencode.schema.json"
|
||||
const OPENAGENT_SCHEMA_OUTPUT_PATH = "assets/oh-my-openagent.schema.json"
|
||||
const OPENAGENT_DIST_SCHEMA_OUTPUT_PATH = "dist/oh-my-openagent.schema.json"
|
||||
|
||||
async function main() {
|
||||
console.log("Generating JSON Schema...")
|
||||
|
||||
const finalSchema = createOhMyOpenCodeJsonSchema()
|
||||
|
||||
// oh-my-opencode schema (backward compatibility)
|
||||
await Bun.write(SCHEMA_OUTPUT_PATH, JSON.stringify(finalSchema, null, 2))
|
||||
await Bun.write(DIST_SCHEMA_OUTPUT_PATH, JSON.stringify(finalSchema, null, 2))
|
||||
|
||||
// oh-my-openagent schema (new name)
|
||||
const openAgentSchema = {
|
||||
...finalSchema,
|
||||
$id: "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
title: "Oh My OpenAgent Configuration",
|
||||
description: "Configuration schema for oh-my-openagent plugin",
|
||||
}
|
||||
await Bun.write(OPENAGENT_SCHEMA_OUTPUT_PATH, JSON.stringify(openAgentSchema, null, 2))
|
||||
await Bun.write(OPENAGENT_DIST_SCHEMA_OUTPUT_PATH, JSON.stringify(openAgentSchema, null, 2))
|
||||
|
||||
console.log(`✓ JSON Schema generated: ${SCHEMA_OUTPUT_PATH}`)
|
||||
console.log(`✓ JSON Schema generated: ${OPENAGENT_SCHEMA_OUTPUT_PATH}`)
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
@@ -2239,6 +2239,94 @@
|
||||
"created_at": "2026-03-17T20:42:42Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2656
|
||||
},
|
||||
{
|
||||
"name": "walioo",
|
||||
"id": 25835823,
|
||||
"comment_id": 4087098221,
|
||||
"created_at": "2026-03-19T02:13:02Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2688
|
||||
},
|
||||
{
|
||||
"name": "trafgals",
|
||||
"id": 6454757,
|
||||
"comment_id": 4087725932,
|
||||
"created_at": "2026-03-19T04:22:32Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2690
|
||||
},
|
||||
{
|
||||
"name": "tonymfer",
|
||||
"id": 66512584,
|
||||
"comment_id": 4091847232,
|
||||
"created_at": "2026-03-19T17:13:49Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2701
|
||||
},
|
||||
{
|
||||
"name": "nguyentamdat",
|
||||
"id": 16253213,
|
||||
"comment_id": 4096267323,
|
||||
"created_at": "2026-03-20T07:34:22Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2718
|
||||
},
|
||||
{
|
||||
"name": "whackur",
|
||||
"id": 26926041,
|
||||
"comment_id": 4102330445,
|
||||
"created_at": "2026-03-21T05:27:17Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2733
|
||||
},
|
||||
{
|
||||
"name": "ndaemy",
|
||||
"id": 18691542,
|
||||
"comment_id": 4103008804,
|
||||
"created_at": "2026-03-21T10:18:22Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2734
|
||||
},
|
||||
{
|
||||
"name": "0xYiliu",
|
||||
"id": 3838688,
|
||||
"comment_id": 4104738337,
|
||||
"created_at": "2026-03-21T22:59:33Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2738
|
||||
},
|
||||
{
|
||||
"name": "hunghoang3011",
|
||||
"id": 65234777,
|
||||
"comment_id": 4107900881,
|
||||
"created_at": "2026-03-23T04:28:20Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2758
|
||||
},
|
||||
{
|
||||
"name": "anas-asghar4831",
|
||||
"id": 110368394,
|
||||
"comment_id": 4128950310,
|
||||
"created_at": "2026-03-25T18:48:19Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2837
|
||||
},
|
||||
{
|
||||
"name": "clansty",
|
||||
"id": 18461360,
|
||||
"comment_id": 4129934858,
|
||||
"created_at": "2026-03-25T21:33:35Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2839
|
||||
},
|
||||
{
|
||||
"name": "ventsislav-georgiev",
|
||||
"id": 5616486,
|
||||
"comment_id": 4130417794,
|
||||
"created_at": "2026-03-25T23:11:32Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2840
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -14,7 +14,7 @@ Entry point `index.ts` orchestrates 5-step initialization: loadConfig → create
|
||||
| `plugin-config.ts` | JSONC parse, multi-level merge, Zod v4 validation |
|
||||
| `create-managers.ts` | TmuxSessionManager, BackgroundManager, SkillMcpManager, ConfigHandler |
|
||||
| `create-tools.ts` | SkillContext + AvailableCategories + ToolRegistry (26 tools) |
|
||||
| `create-hooks.ts` | 3-tier: Core(37) + Continuation(7) + Skill(2) = 46 hooks |
|
||||
| `create-hooks.ts` | 3-tier: Core(39) + Continuation(7) + Skill(2) = 48 hooks |
|
||||
| `plugin-interface.ts` | 8 OpenCode hook handlers: config, tool, chat.message, chat.params, chat.headers, event, tool.execute.before, tool.execute.after |
|
||||
|
||||
## CONFIG LOADING
|
||||
@@ -32,10 +32,10 @@ loadPluginConfig(directory, ctx)
|
||||
|
||||
```
|
||||
createHooks()
|
||||
├─→ createCoreHooks() # 37 hooks
|
||||
├─→ createCoreHooks() # 39 hooks
|
||||
│ ├─ createSessionHooks() # 23: contextWindowMonitor, thinkMode, ralphLoop, modelFallback, runtimeFallback, noSisyphusGpt, noHephaestusNonGpt, anthropicEffort, intentGate...
|
||||
│ ├─ createToolGuardHooks() # 10: commentChecker, rulesInjector, writeExistingFileGuard, jsonErrorRecovery, hashlineReadEnhancer...
|
||||
│ ├─ createToolGuardHooks() # 12: commentChecker, rulesInjector, writeExistingFileGuard, jsonErrorRecovery, hashlineReadEnhancer...
|
||||
│ └─ createTransformHooks() # 4: claudeCodeHooks, keywordDetector, contextInjector, thinkingBlockValidator
|
||||
├─→ createContinuationHooks() # 7: todoContinuationEnforcer, atlas, stopContinuationGuard, ralphLoopActivator...
|
||||
├─→ createContinuationHooks() # 7: todoContinuationEnforcer, atlas, stopContinuationGuard, compactionContextInjector...
|
||||
└─→ createSkillHooks() # 2: categorySkillReminder, autoSlashCommand
|
||||
```
|
||||
|
||||
@@ -13,8 +13,8 @@ Agent factories following `createXXXAgent(model) → AgentConfig` pattern. Each
|
||||
| **Sisyphus** | claude-opus-4-6 max | 0.1 | all | k2p5 → kimi-k2.5 → gpt-5.4 medium → glm-5 → big-pickle | Main orchestrator, plans + delegates |
|
||||
| **Hephaestus** | gpt-5.3-codex medium | 0.1 | all | gpt-5.4 medium (copilot) | Autonomous deep worker |
|
||||
| **Oracle** | gpt-5.4 high | 0.1 | subagent | gemini-3.1-pro high → claude-opus-4-6 max | Read-only consultation |
|
||||
| **Librarian** | gemini-3-flash | 0.1 | subagent | minimax-m2.5-free → big-pickle | External docs/code search |
|
||||
| **Explore** | grok-code-fast-1 | 0.1 | subagent | minimax-m2.5-free → claude-haiku-4-5 → gpt-5-nano | Contextual grep |
|
||||
| **Librarian** | minimax-m2.7 | 0.1 | subagent | minimax-m2.7-highspeed → claude-haiku-4-5 → gpt-5-nano | External docs/code search |
|
||||
| **Explore** | grok-code-fast-1 | 0.1 | subagent | minimax-m2.7-highspeed → minimax-m2.7 → claude-haiku-4-5 → gpt-5-nano | Contextual grep |
|
||||
| **Multimodal-Looker** | gpt-5.3-codex medium | 0.1 | subagent | k2p5 → gemini-3-flash → glm-4.6v → gpt-5-nano | PDF/image analysis |
|
||||
| **Metis** | claude-opus-4-6 max | **0.3** | subagent | gpt-5.4 high → gemini-3.1-pro high | Pre-planning consultant |
|
||||
| **Momus** | gpt-5.4 xhigh | 0.1 | subagent | claude-opus-4-6 max → gemini-3.1-pro high | Plan reviewer |
|
||||
|
||||
@@ -101,7 +101,7 @@ function buildDynamicOrchestratorPrompt(ctx?: OrchestratorContext): string {
|
||||
export function createAtlasAgent(ctx: OrchestratorContext): AgentConfig {
|
||||
const baseConfig = {
|
||||
description:
|
||||
"Orchestrates work via task() to complete ALL tasks in a todo list until fully done. (Atlas - OhMyOpenAgent)",
|
||||
"Orchestrates work via task() to complete ALL tasks in a todo list until fully done. (Atlas - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
...(ctx.model ? { model: ctx.model } : {}),
|
||||
temperature: 0.1,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { buildAntiDuplicationSection } from "../dynamic-agent-prompt-builder"
|
||||
|
||||
export const ATLAS_SYSTEM_PROMPT = `
|
||||
<identity>
|
||||
You are Atlas - the Master Orchestrator from OhMyOpenAgent.
|
||||
You are Atlas - the Master Orchestrator from OhMyOpenCode.
|
||||
|
||||
In Greek mythology, Atlas holds up the celestial heavens. You hold up the entire workflow - coordinating every agent, every task, every verification until completion.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { buildAntiDuplicationSection } from "../dynamic-agent-prompt-builder"
|
||||
|
||||
export const ATLAS_GEMINI_SYSTEM_PROMPT = `
|
||||
<identity>
|
||||
You are Atlas - Master Orchestrator from OhMyOpenAgent.
|
||||
You are Atlas - Master Orchestrator from OhMyOpenCode.
|
||||
Role: Conductor, not musician. General, not soldier.
|
||||
You DELEGATE, COORDINATE, and VERIFY. You NEVER write code yourself.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { buildAntiDuplicationSection } from "../dynamic-agent-prompt-builder"
|
||||
|
||||
export const ATLAS_GPT_SYSTEM_PROMPT = `
|
||||
<identity>
|
||||
You are Atlas - Master Orchestrator from OhMyOpenAgent.
|
||||
You are Atlas - Master Orchestrator from OhMyOpenCode.
|
||||
Role: Conductor, not musician. General, not soldier.
|
||||
You DELEGATE, COORDINATE, and VERIFY. You NEVER write code yourself.
|
||||
</identity>
|
||||
|
||||
@@ -44,6 +44,10 @@ export function mergeAgentConfig(
|
||||
const { prompt_append, ...rest } = migratedOverride
|
||||
const merged = deepMerge(base, rest as Partial<AgentConfig>)
|
||||
|
||||
if (merged.prompt && typeof merged.prompt === 'string' && merged.prompt.startsWith('file://')) {
|
||||
merged.prompt = resolvePromptAppend(merged.prompt, directory)
|
||||
}
|
||||
|
||||
if (prompt_append && merged.prompt) {
|
||||
merged.prompt = merged.prompt + "\n" + resolvePromptAppend(prompt_append, directory)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export function maybeCreateAtlasConfig(input: {
|
||||
const atlasRequirement = AGENT_MODEL_REQUIREMENTS["atlas"]
|
||||
|
||||
const atlasResolution = applyModelResolution({
|
||||
uiSelectedModel: orchestratorOverride?.model ? undefined : uiSelectedModel,
|
||||
uiSelectedModel: orchestratorOverride?.model !== undefined ? undefined : uiSelectedModel,
|
||||
userModel: orchestratorOverride?.model,
|
||||
requirement: atlasRequirement,
|
||||
availableModels,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { buildAgent, isFactory } from "../agent-builder"
|
||||
import { applyOverrides } from "./agent-overrides"
|
||||
import { applyEnvironmentContext } from "./environment-context"
|
||||
import { applyModelResolution, getFirstFallbackModel } from "./model-resolution"
|
||||
import { log } from "../../shared/logger"
|
||||
|
||||
export function collectPendingBuiltinAgents(input: {
|
||||
agentSources: Record<BuiltinAgentName, import("../agent-builder").AgentSource>
|
||||
@@ -69,13 +70,19 @@ export function collectPendingBuiltinAgents(input: {
|
||||
const isPrimaryAgent = isFactory(source) && source.mode === "primary"
|
||||
|
||||
let resolution = applyModelResolution({
|
||||
uiSelectedModel: (isPrimaryAgent && !override?.model) ? uiSelectedModel : undefined,
|
||||
uiSelectedModel: (isPrimaryAgent && override?.model === undefined) ? uiSelectedModel : undefined,
|
||||
userModel: override?.model,
|
||||
requirement,
|
||||
availableModels,
|
||||
systemDefaultModel,
|
||||
})
|
||||
if (!resolution && isFirstRunNoCache && !override?.model) {
|
||||
if (!resolution) {
|
||||
if (override?.model) {
|
||||
log("[agent-registration] User-configured model could not be resolved, falling back", {
|
||||
agent: agentName,
|
||||
configuredModel: override.model,
|
||||
})
|
||||
}
|
||||
resolution = getFirstFallbackModel(requirement)
|
||||
}
|
||||
if (!resolution) continue
|
||||
|
||||
@@ -52,7 +52,7 @@ export function maybeCreateSisyphusConfig(input: {
|
||||
if (disabledAgents.includes("sisyphus") || !meetsSisyphusAnyModelRequirement) return undefined
|
||||
|
||||
let sisyphusResolution = applyModelResolution({
|
||||
uiSelectedModel: sisyphusOverride?.model ? undefined : uiSelectedModel,
|
||||
uiSelectedModel: sisyphusOverride?.model !== undefined ? undefined : uiSelectedModel,
|
||||
userModel: sisyphusOverride?.model,
|
||||
requirement: sisyphusRequirement,
|
||||
availableModels,
|
||||
|
||||
@@ -181,7 +181,7 @@ describe("buildParallelDelegationSection", () => {
|
||||
|
||||
it("#given non-Claude model with deep category #when building #then returns aggressive delegation section", () => {
|
||||
//#given
|
||||
const model = "google/gemini-3-pro"
|
||||
const model = "google/gemini-3.1-pro"
|
||||
const categories = [deepCategory, otherCategory]
|
||||
|
||||
//#when
|
||||
@@ -237,7 +237,7 @@ describe("buildParallelDelegationSection", () => {
|
||||
describe("buildNonClaudePlannerSection", () => {
|
||||
it("#given non-Claude model #when building #then returns plan agent section", () => {
|
||||
//#given
|
||||
const model = "google/gemini-3-pro"
|
||||
const model = "google/gemini-3.1-pro"
|
||||
|
||||
//#when
|
||||
const result = buildNonClaudePlannerSection(model)
|
||||
@@ -272,4 +272,3 @@ describe("buildNonClaudePlannerSection", () => {
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ export function createExploreAgent(model: string): AgentConfig {
|
||||
|
||||
return {
|
||||
description:
|
||||
'Contextual grep for codebases. Answers "Where is X?", "Which file has Y?", "Find the code that does Z". Fire multiple in parallel for broad searches. Specify thoroughness: "quick" for basic, "medium" for moderate, "very thorough" for comprehensive analysis. (Explore - OhMyOpenAgent)',
|
||||
'Contextual grep for codebases. Answers "Where is X?", "Which file has Y?", "Find the code that does Z". Fire multiple in parallel for broad searches. Specify thoroughness: "quick" for basic, "medium" for moderate, "very thorough" for comprehensive analysis. (Explore - OhMyOpenCode)',
|
||||
mode: MODE,
|
||||
model,
|
||||
temperature: 0.1,
|
||||
|
||||
@@ -111,7 +111,7 @@ export function createHephaestusAgent(
|
||||
|
||||
return {
|
||||
description:
|
||||
"Autonomous Deep Worker - goal-oriented execution with GPT Codex. Explores thoroughly before acting, uses explore/librarian agents for comprehensive context, completes tasks end-to-end. Inspired by AmpCode deep mode. (Hephaestus - OhMyOpenAgent)",
|
||||
"Autonomous Deep Worker - goal-oriented execution with GPT Codex. Explores thoroughly before acting, uses explore/librarian agents for comprehensive context, completes tasks end-to-end. Inspired by AmpCode deep mode. (Hephaestus - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
maxTokens: 32000,
|
||||
|
||||
@@ -162,6 +162,10 @@ Asking the user is the LAST resort after exhausting creative alternatives.
|
||||
- User asks a question implying work → Answer briefly, DO the implied work in the same turn
|
||||
- You wrote a plan in your response → EXECUTE the plan before ending turn — plans are starting lines, not finish lines
|
||||
|
||||
### Task Scope Clarification
|
||||
|
||||
You handle multi-step sub-tasks of a SINGLE GOAL. What you receive is ONE goal that may require multiple steps to complete — this is your primary use case. Only reject when given MULTIPLE INDEPENDENT goals in one request.
|
||||
|
||||
## Hard Constraints
|
||||
|
||||
${hardBlocks}
|
||||
@@ -527,7 +531,7 @@ export function createHephaestusAgent(
|
||||
|
||||
return {
|
||||
description:
|
||||
"Autonomous Deep Worker - goal-oriented execution with GPT 5.4 Codex. Explores thoroughly before acting, uses explore/librarian agents for comprehensive context, completes tasks end-to-end. Inspired by AmpCode deep mode. (Hephaestus - OhMyOpenAgent)",
|
||||
"Autonomous Deep Worker - goal-oriented execution with GPT 5.4 Codex. Explores thoroughly before acting, uses explore/librarian agents for comprehensive context, completes tasks end-to-end. Inspired by AmpCode deep mode. (Hephaestus - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
maxTokens: 32000,
|
||||
|
||||
@@ -121,6 +121,10 @@ When blocked: try a different approach → decompose the problem → challenge a
|
||||
- User asks a question implying work → Answer briefly, DO the implied work in the same turn
|
||||
- You wrote a plan in your response → EXECUTE the plan before ending turn — plans are starting lines, not finish lines
|
||||
|
||||
### Task Scope Clarification
|
||||
|
||||
You handle multi-step sub-tasks of a SINGLE GOAL. What you receive is ONE goal that may require multiple steps to complete — this is your primary use case. Only reject when given MULTIPLE INDEPENDENT goals in one request.
|
||||
|
||||
## Hard Constraints
|
||||
|
||||
${hardBlocks}
|
||||
|
||||
@@ -112,6 +112,10 @@ Asking the user is the LAST resort after exhausting creative alternatives.
|
||||
- Note assumptions in final message, not as questions mid-work
|
||||
- Need context? Fire explore/librarian in background IMMEDIATELY — continue only with non-overlapping work while they search
|
||||
|
||||
### Task Scope Clarification
|
||||
|
||||
You handle multi-step sub-tasks of a SINGLE GOAL. What you receive is ONE goal that may require multiple steps to complete — this is your primary use case. Only reject when given MULTIPLE INDEPENDENT goals in one request.
|
||||
|
||||
## Hard Constraints
|
||||
|
||||
${hardBlocks}
|
||||
|
||||
@@ -32,7 +32,7 @@ export function createLibrarianAgent(model: string): AgentConfig {
|
||||
|
||||
return {
|
||||
description:
|
||||
"Specialized codebase understanding agent for multi-repository analysis, searching remote codebases, retrieving official documentation, and finding implementation examples using GitHub CLI, Context7, and Web Search. MUST BE USED when users ask to look up code in remote repositories, explain library internals, or find usage examples in open source. (Librarian - OhMyOpenAgent)",
|
||||
"Specialized codebase understanding agent for multi-repository analysis, searching remote codebases, retrieving official documentation, and finding implementation examples using GitHub CLI, Context7, and Web Search. MUST BE USED when users ask to look up code in remote repositories, explain library internals, or find usage examples in open source. (Librarian - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
temperature: 0.1,
|
||||
|
||||
@@ -302,7 +302,7 @@ const metisRestrictions = createAgentToolRestrictions([
|
||||
export function createMetisAgent(model: string): AgentConfig {
|
||||
return {
|
||||
description:
|
||||
"Pre-planning consultant that analyzes requests to identify hidden intentions, ambiguities, and AI failure points. (Metis - OhMyOpenAgent)",
|
||||
"Pre-planning consultant that analyzes requests to identify hidden intentions, ambiguities, and AI failure points. (Metis - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
temperature: 0.3,
|
||||
|
||||
@@ -291,7 +291,7 @@ export function createMomusAgent(model: string): AgentConfig {
|
||||
|
||||
const base = {
|
||||
description:
|
||||
"Expert reviewer for evaluating work plans against rigorous clarity, verifiability, and completeness standards. (Momus - OhMyOpenAgent)",
|
||||
"Expert reviewer for evaluating work plans against rigorous clarity, verifiability, and completeness standards. (Momus - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
temperature: 0.1,
|
||||
|
||||
@@ -16,7 +16,7 @@ export function createMultimodalLookerAgent(model: string): AgentConfig {
|
||||
|
||||
return {
|
||||
description:
|
||||
"Analyze media files (PDFs, images, diagrams) that require interpretation beyond raw text. Extracts specific information or summaries from documents, describes visual content. Use when you need analyzed/extracted data rather than literal file contents. (Multimodal-Looker - OhMyOpenAgent)",
|
||||
"Analyze media files (PDFs, images, diagrams) that require interpretation beyond raw text. Extracts specific information or summaries from documents, describes visual content. Use when you need analyzed/extracted data rather than literal file contents. (Multimodal-Looker - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
temperature: 0.1,
|
||||
|
||||
@@ -252,7 +252,7 @@ export function createOracleAgent(model: string): AgentConfig {
|
||||
|
||||
const base = {
|
||||
description:
|
||||
"Read-only consultation agent. High-IQ reasoning specialist for debugging hard problems and high-difficulty architecture design. (Oracle - OhMyOpenAgent)",
|
||||
"Read-only consultation agent. High-IQ reasoning specialist for debugging hard problems and high-difficulty architecture design. (Oracle - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
temperature: 0.1,
|
||||
|
||||
@@ -13,7 +13,7 @@ import { buildAntiDuplicationSection } from "../dynamic-agent-prompt-builder"
|
||||
|
||||
export const PROMETHEUS_GEMINI_SYSTEM_PROMPT = `
|
||||
<identity>
|
||||
You are Prometheus - Strategic Planning Consultant from OhMyOpenAgent.
|
||||
You are Prometheus - Strategic Planning Consultant from OhMyOpenCode.
|
||||
Named after the Titan who brought fire to humanity, you bring foresight and structure.
|
||||
|
||||
**YOU ARE A PLANNER. NOT AN IMPLEMENTER. NOT A CODE WRITER. NOT AN EXECUTOR.**
|
||||
|
||||
@@ -12,7 +12,7 @@ import { buildAntiDuplicationSection } from "../dynamic-agent-prompt-builder";
|
||||
|
||||
export const PROMETHEUS_GPT_SYSTEM_PROMPT = `
|
||||
<identity>
|
||||
You are Prometheus - Strategic Planning Consultant from OhMyOpenAgent.
|
||||
You are Prometheus - Strategic Planning Consultant from OhMyOpenCode.
|
||||
Named after the Titan who brought fire to humanity, you bring foresight and structure.
|
||||
|
||||
**YOU ARE A PLANNER. NOT AN IMPLEMENTER. NOT A CODE WRITER.**
|
||||
|
||||
42
src/agents/prometheus/system-prompt.test.ts
Normal file
42
src/agents/prometheus/system-prompt.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, it, expect } from "bun:test"
|
||||
import { getPrometheusPrompt } from "./system-prompt"
|
||||
|
||||
describe("getPrometheusPrompt", () => {
|
||||
describe("#given question tool is not disabled", () => {
|
||||
describe("#when generating prompt", () => {
|
||||
it("#then should include Question tool references", () => {
|
||||
const prompt = getPrometheusPrompt(undefined, [])
|
||||
|
||||
expect(prompt).toContain("Question({")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given question tool is disabled via disabled_tools", () => {
|
||||
describe("#when generating prompt", () => {
|
||||
it("#then should strip Question tool code examples", () => {
|
||||
const prompt = getPrometheusPrompt(undefined, ["question"])
|
||||
|
||||
expect(prompt).not.toContain("Question({")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#when disabled_tools includes question among other tools", () => {
|
||||
it("#then should strip Question tool code examples", () => {
|
||||
const prompt = getPrometheusPrompt(undefined, ["todowrite", "question", "interactive_bash"])
|
||||
|
||||
expect(prompt).not.toContain("Question({")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given no disabled_tools provided", () => {
|
||||
describe("#when generating prompt with undefined", () => {
|
||||
it("#then should include Question tool references", () => {
|
||||
const prompt = getPrometheusPrompt(undefined, undefined)
|
||||
|
||||
expect(prompt).toContain("Question({")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -52,16 +52,34 @@ export function getPrometheusPromptSource(model?: string): PrometheusPromptSourc
|
||||
* Gemini models → Gemini-optimized prompt (aggressive tool-call enforcement, thinking checkpoints)
|
||||
* Default (Claude, etc.) → Claude-optimized prompt (modular sections)
|
||||
*/
|
||||
export function getPrometheusPrompt(model?: string): string {
|
||||
export function getPrometheusPrompt(model?: string, disabledTools?: readonly string[]): string {
|
||||
const source = getPrometheusPromptSource(model)
|
||||
const isQuestionDisabled = disabledTools?.includes("question") ?? false
|
||||
|
||||
let prompt: string
|
||||
switch (source) {
|
||||
case "gpt":
|
||||
return getGptPrometheusPrompt()
|
||||
prompt = getGptPrometheusPrompt()
|
||||
break
|
||||
case "gemini":
|
||||
return getGeminiPrometheusPrompt()
|
||||
prompt = getGeminiPrometheusPrompt()
|
||||
break
|
||||
case "default":
|
||||
default:
|
||||
return PROMETHEUS_SYSTEM_PROMPT
|
||||
prompt = PROMETHEUS_SYSTEM_PROMPT
|
||||
}
|
||||
|
||||
if (isQuestionDisabled) {
|
||||
prompt = stripQuestionToolReferences(prompt)
|
||||
}
|
||||
|
||||
return prompt
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes Question tool usage examples from prompt text when question tool is disabled.
|
||||
*/
|
||||
function stripQuestionToolReferences(prompt: string): string {
|
||||
// Remove Question({...}) code blocks (multi-line)
|
||||
return prompt.replace(/```typescript\n\s*Question\(\{[\s\S]*?\}\)\s*\n```/g, "")
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ export function createSisyphusJuniorAgentWithOverrides(
|
||||
|
||||
const base: AgentConfig = {
|
||||
description: override?.description ??
|
||||
"Focused task executor. Same discipline, no delegation. (Sisyphus-Junior - OhMyOpenAgent)",
|
||||
"Focused task executor. Same discipline, no delegation. (Sisyphus-Junior - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
temperature,
|
||||
|
||||
@@ -20,7 +20,7 @@ export function buildDefaultSisyphusJuniorPrompt(
|
||||
: "All todos marked completed"
|
||||
|
||||
const prompt = `<Role>
|
||||
Sisyphus-Junior - Focused executor from OhMyOpenAgent.
|
||||
Sisyphus-Junior - Focused executor from OhMyOpenCode.
|
||||
Execute tasks directly.
|
||||
</Role>
|
||||
|
||||
@@ -35,6 +35,11 @@ Task NOT complete without:
|
||||
- ${verificationText}
|
||||
</Verification>
|
||||
|
||||
<Termination>
|
||||
STOP after first successful verification. Do NOT re-verify.
|
||||
Maximum status checks: 2. Then stop regardless.
|
||||
</Termination>
|
||||
|
||||
<Style>
|
||||
- Start immediately. No acknowledgments.
|
||||
- Match user's communication style.
|
||||
|
||||
@@ -19,7 +19,8 @@ export function buildGeminiSisyphusJuniorPrompt(
|
||||
const verificationText = useTaskSystem
|
||||
? "All tasks marked completed"
|
||||
: "All todos marked completed"
|
||||
const prompt = `You are Sisyphus-Junior — a focused task executor from OhMyOpenAgent.
|
||||
|
||||
const prompt = `You are Sisyphus-Junior — a focused task executor from OhMyOpenCode.
|
||||
|
||||
## Identity
|
||||
|
||||
@@ -190,4 +191,4 @@ No tasks on multi-step work = INCOMPLETE WORK. The user tracks your progress thr
|
||||
- **Batching** — NEVER batch completions. Mark EACH todo individually.
|
||||
|
||||
No todos on multi-step work = INCOMPLETE WORK. The user tracks your progress through todos.`
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,8 @@ export function buildGpt53CodexSisyphusJuniorPrompt(
|
||||
const verificationText = useTaskSystem
|
||||
? "All tasks marked completed"
|
||||
: "All todos marked completed"
|
||||
const prompt = `You are Sisyphus-Junior — a focused task executor from OhMyOpenAgent.
|
||||
|
||||
const prompt = `You are Sisyphus-Junior — a focused task executor from OhMyOpenCode.
|
||||
|
||||
## Identity
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ export function buildGpt54SisyphusJuniorPrompt(
|
||||
const verificationText = useTaskSystem
|
||||
? "All tasks marked completed"
|
||||
: "All todos marked completed";
|
||||
const prompt = `You are Sisyphus-Junior — a focused task executor from OhMyOpenAgent.
|
||||
|
||||
const prompt = `You are Sisyphus-Junior — a focused task executor from OhMyOpenCode.
|
||||
|
||||
## Identity
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ export function buildGptSisyphusJuniorPrompt(
|
||||
const verificationText = useTaskSystem
|
||||
? "All tasks marked completed"
|
||||
: "All todos marked completed"
|
||||
const prompt = `You are Sisyphus-Junior — a focused task executor from OhMyOpenAgent.
|
||||
|
||||
const prompt = `You are Sisyphus-Junior — a focused task executor from OhMyOpenCode.
|
||||
|
||||
## Identity
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ function buildDynamicSisyphusPrompt(
|
||||
: "YOUR TODO CREATION WOULD BE TRACKED BY HOOK([SYSTEM REMINDER - TODO CONTINUATION])";
|
||||
|
||||
return `<Role>
|
||||
You are "Sisyphus" - Powerful AI Agent with orchestration capabilities from OhMyOpenAgent.
|
||||
You are "Sisyphus" - Powerful AI Agent with orchestration capabilities from OhMyOpenCode.
|
||||
|
||||
**Why Sisyphus?**: Humans roll their boulder every day. So do you. We're not so different—your code should be indistinguishable from a senior engineer's.
|
||||
|
||||
@@ -467,7 +467,7 @@ export function createSisyphusAgent(
|
||||
);
|
||||
return {
|
||||
description:
|
||||
"Powerful AI orchestrator. Plans obsessively with todos, assesses search complexity before exploration, delegates strategically via category+skills combinations. Uses explore for internal code (parallel-friendly), librarian for external docs. (Sisyphus - OhMyOpenAgent)",
|
||||
"Powerful AI orchestrator. Plans obsessively with todos, assesses search complexity before exploration, delegates strategically via category+skills combinations. Uses explore for internal code (parallel-friendly), librarian for external docs. (Sisyphus - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
maxTokens: 64000,
|
||||
@@ -518,7 +518,7 @@ export function createSisyphusAgent(
|
||||
} as AgentConfig["permission"];
|
||||
const base = {
|
||||
description:
|
||||
"Powerful AI orchestrator. Plans obsessively with todos, assesses search complexity before exploration, delegates strategically via category+skills combinations. Uses explore for internal code (parallel-friendly), librarian for external docs. (Sisyphus - OhMyOpenAgent)",
|
||||
"Powerful AI orchestrator. Plans obsessively with todos, assesses search complexity before exploration, delegates strategically via category+skills combinations. Uses explore for internal code (parallel-friendly), librarian for external docs. (Sisyphus - OhMyOpenCode)",
|
||||
mode: MODE,
|
||||
model,
|
||||
maxTokens: 64000,
|
||||
|
||||
@@ -167,7 +167,7 @@ export function buildDefaultSisyphusPrompt(
|
||||
: "YOUR TODO CREATION WOULD BE TRACKED BY HOOK([SYSTEM REMINDER - TODO CONTINUATION])";
|
||||
|
||||
return `<Role>
|
||||
You are "Sisyphus" - Powerful AI Agent with orchestration capabilities from OhMyOpenAgent.
|
||||
You are "Sisyphus" - Powerful AI Agent with orchestration capabilities from OhMyOpenCode.
|
||||
|
||||
**Why Sisyphus?**: Humans roll their boulder every day. So do you. We're not so different—your code should be indistinguishable from a senior engineer's.
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ export function buildGpt54SisyphusPrompt(
|
||||
: "YOUR TODO CREATION WOULD BE TRACKED BY HOOK([SYSTEM REMINDER - TODO CONTINUATION])";
|
||||
|
||||
const identityBlock = `<identity>
|
||||
You are Sisyphus — an AI orchestrator from OhMyOpenAgent.
|
||||
You are Sisyphus — an AI orchestrator from OhMyOpenCode.
|
||||
|
||||
You are a senior SF Bay Area engineer. You delegate, verify, and ship. Your code is indistinguishable from a senior engineer's work.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, test, expect } from "bun:test";
|
||||
import { isGptModel, isGeminiModel, isGpt5_4Model } from "./types";
|
||||
import { isGptModel, isGeminiModel, isGpt5_4Model, isMiniMaxModel } from "./types";
|
||||
|
||||
describe("isGpt5_4Model", () => {
|
||||
test("detects gpt-5.4 models", () => {
|
||||
@@ -79,6 +79,28 @@ describe("isGptModel", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("isMiniMaxModel", () => {
|
||||
test("detects minimax models with provider prefix", () => {
|
||||
expect(isMiniMaxModel("opencode-go/minimax-m2.7")).toBe(true);
|
||||
expect(isMiniMaxModel("opencode/minimax-m2.7-highspeed")).toBe(true);
|
||||
expect(isMiniMaxModel("opencode-go/minimax-m2.5")).toBe(true);
|
||||
expect(isMiniMaxModel("opencode/minimax-m2.5-free")).toBe(true);
|
||||
});
|
||||
|
||||
test("detects minimax models without provider prefix", () => {
|
||||
expect(isMiniMaxModel("minimax-m2.7")).toBe(true);
|
||||
expect(isMiniMaxModel("minimax-m2.7-highspeed")).toBe(true);
|
||||
expect(isMiniMaxModel("minimax-m2.5")).toBe(true);
|
||||
});
|
||||
|
||||
test("does not match non-minimax models", () => {
|
||||
expect(isMiniMaxModel("openai/gpt-5.4")).toBe(false);
|
||||
expect(isMiniMaxModel("anthropic/claude-opus-4-6")).toBe(false);
|
||||
expect(isMiniMaxModel("google/gemini-3.1-pro")).toBe(false);
|
||||
expect(isMiniMaxModel("opencode-go/kimi-k2.5")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isGeminiModel", () => {
|
||||
test("#given google provider models #then returns true", () => {
|
||||
expect(isGeminiModel("google/gemini-3.1-pro")).toBe(true);
|
||||
|
||||
@@ -91,6 +91,11 @@ export function isGpt5_3CodexModel(model: string): boolean {
|
||||
|
||||
const GEMINI_PROVIDERS = ["google/", "google-vertex/"];
|
||||
|
||||
export function isMiniMaxModel(model: string): boolean {
|
||||
const modelName = extractModelName(model).toLowerCase();
|
||||
return modelName.includes("minimax");
|
||||
}
|
||||
|
||||
export function isGeminiModel(model: string): boolean {
|
||||
if (GEMINI_PROVIDERS.some((prefix) => model.startsWith(prefix))) return true;
|
||||
|
||||
@@ -123,7 +128,7 @@ export type AgentName = BuiltinAgentName;
|
||||
export type AgentOverrideConfig = Partial<AgentConfig> & {
|
||||
prompt_append?: string;
|
||||
variant?: string;
|
||||
fallback_models?: string | string[];
|
||||
fallback_models?: string | (string | import("../config/schema/fallback-models").FallbackModelObject)[];
|
||||
};
|
||||
|
||||
export type AgentOverrides = Partial<
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`generateModelConfig no providers available returns ULTIMATE_FALLBACK for all agents and categories when no providers 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
@@ -66,7 +66,7 @@ exports[`generateModelConfig no providers available returns ULTIMATE_FALLBACK fo
|
||||
|
||||
exports[`generateModelConfig single native provider uses Claude models when only Claude is available 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -128,7 +128,7 @@ exports[`generateModelConfig single native provider uses Claude models when only
|
||||
|
||||
exports[`generateModelConfig single native provider uses Claude models with isMax20 flag 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -191,7 +191,7 @@ exports[`generateModelConfig single native provider uses Claude models with isMa
|
||||
|
||||
exports[`generateModelConfig single native provider uses OpenAI models when only OpenAI is available 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -248,8 +248,7 @@ exports[`generateModelConfig single native provider uses OpenAI models when only
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"variant": "low",
|
||||
"model": "openai/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -277,7 +276,7 @@ exports[`generateModelConfig single native provider uses OpenAI models when only
|
||||
|
||||
exports[`generateModelConfig single native provider uses OpenAI models with isMax20 flag 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -334,8 +333,7 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"variant": "low",
|
||||
"model": "openai/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -363,7 +361,7 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
|
||||
|
||||
exports[`generateModelConfig single native provider uses Gemini models when only Gemini is available 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
@@ -423,7 +421,7 @@ exports[`generateModelConfig single native provider uses Gemini models when only
|
||||
|
||||
exports[`generateModelConfig single native provider uses Gemini models with isMax20 flag 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
@@ -483,7 +481,7 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa
|
||||
|
||||
exports[`generateModelConfig all native providers uses preferred models from fallback chains when all natives available 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -533,7 +531,7 @@ exports[`generateModelConfig all native providers uses preferred models from fal
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
"model": "openai/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -558,7 +556,7 @@ exports[`generateModelConfig all native providers uses preferred models from fal
|
||||
|
||||
exports[`generateModelConfig all native providers uses preferred models with isMax20 flag when all natives available 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -608,7 +606,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
"model": "openai/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -634,7 +632,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM
|
||||
|
||||
exports[`generateModelConfig fallback providers uses OpenCode Zen models when only OpenCode Zen is available 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/claude-sonnet-4-6",
|
||||
@@ -684,7 +682,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "opencode/claude-haiku-4-5",
|
||||
"model": "opencode/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5.4",
|
||||
@@ -709,7 +707,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on
|
||||
|
||||
exports[`generateModelConfig fallback providers uses OpenCode Zen models with isMax20 flag 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/claude-sonnet-4-6",
|
||||
@@ -759,7 +757,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "opencode/claude-haiku-4-5",
|
||||
"model": "opencode/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5.4",
|
||||
@@ -785,7 +783,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is
|
||||
|
||||
exports[`generateModelConfig fallback providers uses GitHub Copilot models when only Copilot is available 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
@@ -830,7 +828,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
|
||||
"variant": "high",
|
||||
},
|
||||
"quick": {
|
||||
"model": "github-copilot/claude-haiku-4.5",
|
||||
"model": "github-copilot/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "github-copilot/gemini-3.1-pro-preview",
|
||||
@@ -855,7 +853,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
|
||||
|
||||
exports[`generateModelConfig fallback providers uses GitHub Copilot models with isMax20 flag 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
@@ -900,7 +898,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
|
||||
"variant": "high",
|
||||
},
|
||||
"quick": {
|
||||
"model": "github-copilot/claude-haiku-4.5",
|
||||
"model": "github-copilot/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "github-copilot/gemini-3.1-pro-preview",
|
||||
@@ -926,7 +924,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
|
||||
|
||||
exports[`generateModelConfig fallback providers uses ZAI model for librarian when only ZAI is available 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
@@ -984,7 +982,7 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian whe
|
||||
|
||||
exports[`generateModelConfig fallback providers uses ZAI model for librarian with isMax20 flag 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
@@ -1042,7 +1040,7 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian wit
|
||||
|
||||
exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen combination 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -1092,7 +1090,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
"model": "opencode/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5.4",
|
||||
@@ -1117,7 +1115,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen
|
||||
|
||||
exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot combination 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
@@ -1167,7 +1165,7 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "github-copilot/claude-haiku-4.5",
|
||||
"model": "openai/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -1192,7 +1190,7 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb
|
||||
|
||||
exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combination (librarian uses ZAI) 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -1256,7 +1254,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat
|
||||
|
||||
exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combination (explore uses Gemini) 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -1322,7 +1320,7 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi
|
||||
|
||||
exports[`generateModelConfig mixed provider scenarios uses all fallback providers together 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
@@ -1375,7 +1373,7 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "github-copilot/claude-haiku-4.5",
|
||||
"model": "github-copilot/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5.4",
|
||||
@@ -1400,7 +1398,7 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
|
||||
|
||||
exports[`generateModelConfig mixed provider scenarios uses all providers together 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -1453,7 +1451,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
"model": "openai/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -1478,7 +1476,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
|
||||
|
||||
exports[`generateModelConfig mixed provider scenarios uses all providers with isMax20 flag 1`] = `
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
@@ -1531,7 +1529,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
|
||||
"variant": "medium",
|
||||
},
|
||||
"quick": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
"model": "openai/gpt-5.4-mini",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.4",
|
||||
|
||||
@@ -43,7 +43,7 @@ describe("runCliInstaller", () => {
|
||||
}),
|
||||
spyOn(configManager, "writeOmoConfig").mockReturnValue({
|
||||
success: true,
|
||||
configPath: "/tmp/oh-my-openagent.jsonc"
|
||||
configPath: "/tmp/oh-my-opencode.jsonc",
|
||||
}),
|
||||
]
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export async function runCliInstaller(args: InstallArgs, version: string): Promi
|
||||
}
|
||||
console.log()
|
||||
printInfo(
|
||||
"Usage: bunx oh-my-openagent install --no-tui --claude=<no|yes|max20> --gemini=<no|yes> --copilot=<no|yes>"
|
||||
"Usage: bunx oh-my-opencode install --no-tui --claude=<no|yes|max20> --gemini=<no|yes> --copilot=<no|yes>",
|
||||
)
|
||||
console.log()
|
||||
return 1
|
||||
@@ -65,7 +65,7 @@ export async function runCliInstaller(args: InstallArgs, version: string): Promi
|
||||
|
||||
const config = argsToConfig(args)
|
||||
|
||||
printStep(step++, totalSteps, "Adding oh-my-openagent plugin...")
|
||||
printStep(step++, totalSteps, "Adding oh-my-opencode plugin...")
|
||||
const pluginResult = await addPluginToOpenCodeConfig(version)
|
||||
if (!pluginResult.success) {
|
||||
printError(`Failed: ${pluginResult.error}`)
|
||||
@@ -75,7 +75,7 @@ export async function runCliInstaller(args: InstallArgs, version: string): Promi
|
||||
`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${color.dim(pluginResult.configPath)}`,
|
||||
)
|
||||
|
||||
printStep(step++, totalSteps, "Writing oh-my-openagent configuration...")
|
||||
printStep(step++, totalSteps, "Writing oh-my-opencode configuration...")
|
||||
const omoResult = writeOmoConfig(config)
|
||||
if (!omoResult.success) {
|
||||
printError(`Failed: ${omoResult.error}`)
|
||||
|
||||
@@ -3,6 +3,7 @@ import { install } from "./install"
|
||||
import { run } from "./run"
|
||||
import { getLocalVersion } from "./get-local-version"
|
||||
import { doctor } from "./doctor"
|
||||
import { refreshModelCapabilities } from "./refresh-model-capabilities"
|
||||
import { createMcpOAuthCommand } from "./mcp-oauth"
|
||||
import type { InstallArgs } from "./types"
|
||||
import type { RunOptions } from "./run"
|
||||
@@ -15,14 +16,14 @@ const VERSION = packageJson.version
|
||||
const program = new Command()
|
||||
|
||||
program
|
||||
.name("oh-my-openagent")
|
||||
.name("oh-my-opencode")
|
||||
.description("The ultimate OpenCode plugin - multi-model orchestration, LSP tools, and more")
|
||||
.version(VERSION, "-v, --version", "Show version number")
|
||||
.enablePositionalOptions()
|
||||
|
||||
program
|
||||
.command("install")
|
||||
.description("Install and configure oh-my-openagent with interactive setup")
|
||||
.description("Install and configure oh-my-opencode with interactive setup")
|
||||
.option("--no-tui", "Run in non-interactive mode (requires all options)")
|
||||
.option("--claude <value>", "Claude subscription: no, yes, max20")
|
||||
.option("--openai <value>", "OpenAI/ChatGPT subscription: no, yes (default: no)")
|
||||
@@ -35,14 +36,14 @@ program
|
||||
.option("--skip-auth", "Skip authentication setup hints")
|
||||
.addHelpText("after", `
|
||||
Examples:
|
||||
$ bunx oh-my-openagent install
|
||||
$ bunx oh-my-openagent install --no-tui --claude=max20 --openai=yes --gemini=yes --copilot=no
|
||||
$ bunx oh-my-openagent install --no-tui --claude=no --gemini=no --copilot=yes --opencode-zen=yes
|
||||
$ bunx oh-my-opencode install
|
||||
$ bunx oh-my-opencode install --no-tui --claude=max20 --openai=yes --gemini=yes --copilot=no
|
||||
$ bunx oh-my-opencode install --no-tui --claude=no --gemini=no --copilot=yes --opencode-zen=yes
|
||||
|
||||
Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi):
|
||||
Claude Native anthropic/ models (Opus, Sonnet, Haiku)
|
||||
OpenAI Native openai/ models (GPT-5.4 for Oracle)
|
||||
Gemini Native google/ models (Gemini 3 Pro, Flash)
|
||||
Gemini Native google/ models (Gemini 3.1 Pro, Flash)
|
||||
Copilot github-copilot/ models (fallback)
|
||||
OpenCode Zen opencode/ models (opencode/claude-opus-4-6, etc.)
|
||||
Z.ai zai-coding-plan/glm-5 (visual-engineering fallback)
|
||||
@@ -82,20 +83,20 @@ program
|
||||
.option("--session-id <id>", "Resume existing session instead of creating new one")
|
||||
.addHelpText("after", `
|
||||
Examples:
|
||||
$ bunx oh-my-openagent run "Fix the bug in index.ts"
|
||||
$ bunx oh-my-openagent run --agent Sisyphus "Implement feature X"
|
||||
$ bunx oh-my-openagent run --port 4321 "Fix the bug"
|
||||
$ bunx oh-my-openagent run --attach http://127.0.0.1:4321 "Fix the bug"
|
||||
$ bunx oh-my-openagent run --json "Fix the bug" | jq .sessionId
|
||||
$ bunx oh-my-openagent run --on-complete "notify-send Done" "Fix the bug"
|
||||
$ bunx oh-my-openagent run --session-id ses_abc123 "Continue the work"
|
||||
$ bunx oh-my-openagent run --model anthropic/claude-sonnet-4 "Fix the bug"
|
||||
$ bunx oh-my-openagent run --agent Sisyphus --model openai/gpt-5.4 "Implement feature X"
|
||||
$ bunx oh-my-opencode run "Fix the bug in index.ts"
|
||||
$ bunx oh-my-opencode run --agent Sisyphus "Implement feature X"
|
||||
$ bunx oh-my-opencode run --port 4321 "Fix the bug"
|
||||
$ bunx oh-my-opencode run --attach http://127.0.0.1:4321 "Fix the bug"
|
||||
$ bunx oh-my-opencode run --json "Fix the bug" | jq .sessionId
|
||||
$ bunx oh-my-opencode run --on-complete "notify-send Done" "Fix the bug"
|
||||
$ bunx oh-my-opencode run --session-id ses_abc123 "Continue the work"
|
||||
$ bunx oh-my-opencode run --model anthropic/claude-sonnet-4 "Fix the bug"
|
||||
$ bunx oh-my-opencode run --agent Sisyphus --model openai/gpt-5.4 "Implement feature X"
|
||||
|
||||
Agent resolution order:
|
||||
1) --agent flag
|
||||
2) OPENCODE_DEFAULT_AGENT
|
||||
3) oh-my-openagent.json "default_run_agent"
|
||||
3) oh-my-opencode.json "default_run_agent"
|
||||
4) Sisyphus (fallback)
|
||||
|
||||
Available core agents:
|
||||
@@ -134,9 +135,9 @@ program
|
||||
.option("--json", "Output in JSON format for scripting")
|
||||
.addHelpText("after", `
|
||||
Examples:
|
||||
$ bunx oh-my-openagent get-local-version
|
||||
$ bunx oh-my-openagent get-local-version --json
|
||||
$ bunx oh-my-openagent get-local-version --directory /path/to/project
|
||||
$ bunx oh-my-opencode get-local-version
|
||||
$ bunx oh-my-opencode get-local-version --json
|
||||
$ bunx oh-my-opencode get-local-version --directory /path/to/project
|
||||
|
||||
This command shows:
|
||||
- Current installed version
|
||||
@@ -155,16 +156,16 @@ This command shows:
|
||||
|
||||
program
|
||||
.command("doctor")
|
||||
.description("Check oh-my-openagent installation health and diagnose issues")
|
||||
.description("Check oh-my-opencode installation health and diagnose issues")
|
||||
.option("--status", "Show compact system dashboard")
|
||||
.option("--verbose", "Show detailed diagnostic information")
|
||||
.option("--json", "Output results in JSON format")
|
||||
.addHelpText("after", `
|
||||
Examples:
|
||||
$ bunx oh-my-openagent doctor # Show problems only
|
||||
$ bunx oh-my-openagent doctor --status # Compact dashboard
|
||||
$ bunx oh-my-openagent doctor --verbose # Deep diagnostics
|
||||
$ bunx oh-my-openagent doctor --json # JSON output
|
||||
$ bunx oh-my-opencode doctor # Show problems only
|
||||
$ bunx oh-my-opencode doctor --status # Compact dashboard
|
||||
$ bunx oh-my-opencode doctor --verbose # Deep diagnostics
|
||||
$ bunx oh-my-opencode doctor --json # JSON output
|
||||
`)
|
||||
.action(async (options) => {
|
||||
const mode = options.status ? "status" : options.verbose ? "verbose" : "default"
|
||||
@@ -176,11 +177,26 @@ Examples:
|
||||
process.exit(exitCode)
|
||||
})
|
||||
|
||||
program
|
||||
.command("refresh-model-capabilities")
|
||||
.description("Refresh the cached models.dev-based model capabilities snapshot")
|
||||
.option("-d, --directory <path>", "Working directory to read oh-my-opencode config from")
|
||||
.option("--source-url <url>", "Override the models.dev source URL")
|
||||
.option("--json", "Output refresh summary as JSON")
|
||||
.action(async (options) => {
|
||||
const exitCode = await refreshModelCapabilities({
|
||||
directory: options.directory,
|
||||
sourceUrl: options.sourceUrl,
|
||||
json: options.json ?? false,
|
||||
})
|
||||
process.exit(exitCode)
|
||||
})
|
||||
|
||||
program
|
||||
.command("version")
|
||||
.description("Show version information")
|
||||
.action(() => {
|
||||
console.log(`oh-my-openagent v${VERSION}`)
|
||||
console.log(`oh-my-opencode v${VERSION}`)
|
||||
})
|
||||
|
||||
program.addCommand(createMcpOAuthCommand())
|
||||
|
||||
@@ -23,7 +23,7 @@ describe("getPluginNameWithVersion", () => {
|
||||
const result = await getPluginNameWithVersion("2.14.0")
|
||||
|
||||
// #then should use @latest tag
|
||||
expect(result).toBe("oh-my-openagent@latest")
|
||||
expect(result).toBe("oh-my-opencode@latest")
|
||||
})
|
||||
|
||||
test("returns @beta when current version matches beta tag", async () => {
|
||||
@@ -39,7 +39,7 @@ describe("getPluginNameWithVersion", () => {
|
||||
const result = await getPluginNameWithVersion("3.0.0-beta.3")
|
||||
|
||||
// #then should use @beta tag
|
||||
expect(result).toBe("oh-my-openagent@beta")
|
||||
expect(result).toBe("oh-my-opencode@beta")
|
||||
})
|
||||
|
||||
test("returns @next when current version matches next tag", async () => {
|
||||
@@ -55,7 +55,7 @@ describe("getPluginNameWithVersion", () => {
|
||||
const result = await getPluginNameWithVersion("3.1.0-next.1")
|
||||
|
||||
// #then should use @next tag
|
||||
expect(result).toBe("oh-my-openagent@next")
|
||||
expect(result).toBe("oh-my-opencode@next")
|
||||
})
|
||||
|
||||
test("returns prerelease channel tag when no dist-tag matches prerelease version", async () => {
|
||||
@@ -71,7 +71,7 @@ describe("getPluginNameWithVersion", () => {
|
||||
const result = await getPluginNameWithVersion("3.0.0-beta.2")
|
||||
|
||||
// #then should preserve prerelease channel
|
||||
expect(result).toBe("oh-my-openagent@beta")
|
||||
expect(result).toBe("oh-my-opencode@beta")
|
||||
})
|
||||
|
||||
test("returns prerelease channel tag when fetch fails", async () => {
|
||||
@@ -82,7 +82,7 @@ describe("getPluginNameWithVersion", () => {
|
||||
const result = await getPluginNameWithVersion("3.0.0-beta.3")
|
||||
|
||||
// #then should preserve prerelease channel
|
||||
expect(result).toBe("oh-my-openagent@beta")
|
||||
expect(result).toBe("oh-my-opencode@beta")
|
||||
})
|
||||
|
||||
test("returns bare package name when npm returns non-ok response for stable version", async () => {
|
||||
@@ -98,7 +98,7 @@ describe("getPluginNameWithVersion", () => {
|
||||
const result = await getPluginNameWithVersion("2.14.0")
|
||||
|
||||
// #then should fall back to bare package entry
|
||||
expect(result).toBe("oh-my-openagent")
|
||||
expect(result).toBe("oh-my-opencode")
|
||||
})
|
||||
|
||||
test("prioritizes latest over other tags when version matches multiple", async () => {
|
||||
@@ -114,7 +114,7 @@ describe("getPluginNameWithVersion", () => {
|
||||
const result = await getPluginNameWithVersion("3.0.0")
|
||||
|
||||
// #then should prioritize @latest
|
||||
expect(result).toBe("oh-my-openagent@latest")
|
||||
expect(result).toBe("oh-my-opencode@latest")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -207,7 +207,7 @@ describe("generateOmoConfig - model fallback system", () => {
|
||||
const result = generateOmoConfig(config)
|
||||
|
||||
// #then Sisyphus is omitted (requires all fallback providers)
|
||||
expect(result.$schema).toBe("https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-openagent.schema.json")
|
||||
expect(result.$schema).toBe("https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json")
|
||||
expect((result.agents as Record<string, { model: string }>).sisyphus).toBeUndefined()
|
||||
})
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from "bun:test"
|
||||
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"
|
||||
import { tmpdir } from "node:os"
|
||||
import { join } from "node:path"
|
||||
|
||||
import { initConfigContext, resetConfigContext } from "./config-context"
|
||||
import { addPluginToOpenCodeConfig } from "./add-plugin-to-opencode-config"
|
||||
|
||||
describe("addPluginToOpenCodeConfig", () => {
|
||||
let testConfigDir = ""
|
||||
let testConfigPath = ""
|
||||
|
||||
beforeEach(() => {
|
||||
testConfigDir = join(tmpdir(), `omo-add-plugin-${Date.now()}-${Math.random().toString(36).slice(2)}`)
|
||||
testConfigPath = join(testConfigDir, "opencode.json")
|
||||
|
||||
mkdirSync(testConfigDir, { recursive: true })
|
||||
process.env.OPENCODE_CONFIG_DIR = testConfigDir
|
||||
resetConfigContext()
|
||||
initConfigContext("opencode", null)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(testConfigDir, { recursive: true, force: true })
|
||||
resetConfigContext()
|
||||
delete process.env.OPENCODE_CONFIG_DIR
|
||||
})
|
||||
|
||||
describe("#given opencode.json with oh-my-opencode plugin", () => {
|
||||
it("replaces oh-my-opencode with new plugin entry", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-opencode"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
// getPluginNameWithVersion returns just the name (without version) for non-dist-tag versions
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
expect(savedConfig.plugin).not.toContain("oh-my-opencode")
|
||||
})
|
||||
|
||||
it("replaces oh-my-opencode@old-version with new plugin entry", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-opencode@1.0.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
expect(savedConfig.plugin).not.toContain("oh-my-opencode@1.0.0")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given opencode.json with oh-my-openagent plugin", () => {
|
||||
it("keeps existing oh-my-openagent when no version change needed", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
// Should keep the existing entry since getPluginNameWithVersion returns same name
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
})
|
||||
|
||||
it("replaces oh-my-openagent@old-version with new plugin entry", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent@1.0.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given opencode.json with other plugins", () => {
|
||||
it("adds new plugin alongside existing plugins", async () => {
|
||||
// given
|
||||
const config = { plugin: ["some-other-plugin"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
expect(savedConfig.plugin).toContain("some-other-plugin")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import { readFileSync, writeFileSync } from "node:fs"
|
||||
import { LEGACY_PLUGIN_NAME, PLUGIN_NAME } from "../../shared"
|
||||
import type { ConfigMergeResult } from "../types"
|
||||
import { PLUGIN_NAME, LEGACY_PLUGIN_NAME } from "../../shared"
|
||||
import { getConfigDir } from "./config-context"
|
||||
import { ensureConfigDirectoryExists } from "./ensure-config-directory-exists"
|
||||
import { formatErrorWithSuggestion } from "./format-error-with-suggestion"
|
||||
@@ -8,21 +8,19 @@ import { detectConfigFormat } from "./opencode-config-format"
|
||||
import { parseOpenCodeConfigFileWithError, type OpenCodeConfig } from "./parse-opencode-config-file"
|
||||
import { getPluginNameWithVersion } from "./plugin-name-with-version"
|
||||
|
||||
const PACKAGE_NAME = PLUGIN_NAME
|
||||
|
||||
export async function addPluginToOpenCodeConfig(currentVersion: string): Promise<ConfigMergeResult> {
|
||||
try {
|
||||
ensureConfigDirectoryExists()
|
||||
} catch (error) {
|
||||
} catch (err) {
|
||||
return {
|
||||
success: false,
|
||||
configPath: getConfigDir(),
|
||||
error: formatErrorWithSuggestion(error, "create config directory"),
|
||||
error: formatErrorWithSuggestion(err, "create config directory"),
|
||||
}
|
||||
}
|
||||
|
||||
const { format, path } = detectConfigFormat()
|
||||
const pluginEntry = await getPluginNameWithVersion(currentVersion, PACKAGE_NAME)
|
||||
const pluginEntry = await getPluginNameWithVersion(currentVersion, PLUGIN_NAME)
|
||||
|
||||
try {
|
||||
if (format === "none") {
|
||||
@@ -42,6 +40,8 @@ export async function addPluginToOpenCodeConfig(currentVersion: string): Promise
|
||||
|
||||
const config = parseResult.config
|
||||
const plugins = config.plugin ?? []
|
||||
|
||||
// Check for existing plugin (either current or legacy name)
|
||||
const currentNameIndex = plugins.findIndex(
|
||||
(plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`)
|
||||
)
|
||||
@@ -49,12 +49,14 @@ export async function addPluginToOpenCodeConfig(currentVersion: string): Promise
|
||||
(plugin) => plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`)
|
||||
)
|
||||
|
||||
// If either name exists, update to new name
|
||||
if (currentNameIndex !== -1) {
|
||||
if (plugins[currentNameIndex] === pluginEntry) {
|
||||
return { success: true, configPath: path }
|
||||
}
|
||||
plugins[currentNameIndex] = pluginEntry
|
||||
} else if (legacyNameIndex !== -1) {
|
||||
// Upgrade legacy name to new name
|
||||
plugins[legacyNameIndex] = pluginEntry
|
||||
} else {
|
||||
plugins.push(pluginEntry)
|
||||
@@ -68,7 +70,7 @@ export async function addPluginToOpenCodeConfig(currentVersion: string): Promise
|
||||
const match = content.match(pluginArrayRegex)
|
||||
|
||||
if (match) {
|
||||
const formattedPlugins = plugins.map((plugin) => `"${plugin}"`).join(",\n ")
|
||||
const formattedPlugins = plugins.map((p) => `"${p}"`).join(",\n ")
|
||||
const newContent = content.replace(pluginArrayRegex, `"plugin": [\n ${formattedPlugins}\n ]`)
|
||||
writeFileSync(path, newContent)
|
||||
} else {
|
||||
@@ -80,11 +82,11 @@ export async function addPluginToOpenCodeConfig(currentVersion: string): Promise
|
||||
}
|
||||
|
||||
return { success: true, configPath: path }
|
||||
} catch (error) {
|
||||
} catch (err) {
|
||||
return {
|
||||
success: false,
|
||||
configPath: path,
|
||||
error: formatErrorWithSuggestion(error, "update opencode config"),
|
||||
error: formatErrorWithSuggestion(err, "update opencode config"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from "bun:test"
|
||||
import { mkdirSync, rmSync, writeFileSync } from "node:fs"
|
||||
import { tmpdir } from "node:os"
|
||||
import { join } from "node:path"
|
||||
|
||||
import { initConfigContext, resetConfigContext } from "./config-context"
|
||||
import { detectCurrentConfig } from "./detect-current-config"
|
||||
|
||||
describe("detectCurrentConfig", () => {
|
||||
let testConfigDir = ""
|
||||
let testConfigPath = ""
|
||||
|
||||
beforeEach(() => {
|
||||
testConfigDir = join(tmpdir(), `omo-detect-config-${Date.now()}-${Math.random().toString(36).slice(2)}`)
|
||||
testConfigPath = join(testConfigDir, "opencode.json")
|
||||
|
||||
mkdirSync(testConfigDir, { recursive: true })
|
||||
process.env.OPENCODE_CONFIG_DIR = testConfigDir
|
||||
resetConfigContext()
|
||||
initConfigContext("opencode", null)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(testConfigDir, { recursive: true, force: true })
|
||||
resetConfigContext()
|
||||
delete process.env.OPENCODE_CONFIG_DIR
|
||||
})
|
||||
|
||||
describe("#given opencode.json with oh-my-opencode plugin", () => {
|
||||
it("returns isInstalled: true when plugin array contains oh-my-opencode", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-opencode"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
|
||||
it("returns isInstalled: true when plugin array contains oh-my-opencode with version", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-opencode@3.11.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given opencode.json with oh-my-openagent plugin", () => {
|
||||
it("returns isInstalled: true when plugin array contains oh-my-openagent", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
|
||||
it("returns isInstalled: true when plugin array contains oh-my-openagent with version", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent@3.11.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given opencode.json with no plugin", () => {
|
||||
it("returns isInstalled: false when plugin array is empty", () => {
|
||||
// given
|
||||
const config = { plugin: [] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(false)
|
||||
})
|
||||
|
||||
it("returns isInstalled: false when plugin array does not contain our plugin", () => {
|
||||
// given
|
||||
const config = { plugin: ["some-other-plugin"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -36,12 +36,12 @@ function detectProvidersFromOmoConfig(): {
|
||||
}
|
||||
}
|
||||
|
||||
const configString = JSON.stringify(omoConfig)
|
||||
const hasOpenAI = configString.includes('"openai/')
|
||||
const hasOpencodeZen = configString.includes('"opencode/')
|
||||
const hasZaiCodingPlan = configString.includes('"zai-coding-plan/')
|
||||
const hasKimiForCoding = configString.includes('"kimi-for-coding/')
|
||||
const hasOpencodeGo = configString.includes('"opencode-go/')
|
||||
const configStr = JSON.stringify(omoConfig)
|
||||
const hasOpenAI = configStr.includes('"openai/')
|
||||
const hasOpencodeZen = configStr.includes('"opencode/')
|
||||
const hasZaiCodingPlan = configStr.includes('"zai-coding-plan/')
|
||||
const hasKimiForCoding = configStr.includes('"kimi-for-coding/')
|
||||
const hasOpencodeGo = configStr.includes('"opencode-go/')
|
||||
|
||||
return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo }
|
||||
} catch {
|
||||
@@ -56,12 +56,8 @@ function detectProvidersFromOmoConfig(): {
|
||||
}
|
||||
|
||||
function isOurPlugin(plugin: string): boolean {
|
||||
return (
|
||||
plugin === PLUGIN_NAME ||
|
||||
plugin.startsWith(`${PLUGIN_NAME}@`) ||
|
||||
plugin === LEGACY_PLUGIN_NAME ||
|
||||
plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`)
|
||||
)
|
||||
return plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`) ||
|
||||
plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`)
|
||||
}
|
||||
|
||||
export function detectCurrentConfig(): DetectedConfig {
|
||||
|
||||
@@ -15,7 +15,7 @@ describe("detectCurrentConfig - single package detection", () => {
|
||||
beforeEach(() => {
|
||||
testConfigDir = join(tmpdir(), `omo-detect-config-${Date.now()}-${Math.random().toString(36).slice(2)}`)
|
||||
testConfigPath = join(testConfigDir, "opencode.json")
|
||||
testOmoConfigPath = join(testConfigDir, "oh-my-openagent.json")
|
||||
testOmoConfigPath = join(testConfigDir, "oh-my-opencode.json")
|
||||
|
||||
mkdirSync(testConfigDir, { recursive: true })
|
||||
process.env.OPENCODE_CONFIG_DIR = testConfigDir
|
||||
@@ -28,31 +28,7 @@ describe("detectCurrentConfig - single package detection", () => {
|
||||
delete process.env.OPENCODE_CONFIG_DIR
|
||||
})
|
||||
|
||||
it("detects oh-my-openagent in plugin array", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
|
||||
it("detects oh-my-openagent with version pin", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent@3.11.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
|
||||
it("detects oh-my-opencode as installed (legacy name)", () => {
|
||||
it("detects oh-my-opencode in plugin array", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-opencode"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
@@ -64,7 +40,7 @@ describe("detectCurrentConfig - single package detection", () => {
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
|
||||
it("detects oh-my-opencode with version pin as installed (legacy name)", () => {
|
||||
it("detects oh-my-opencode with version pin", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-opencode@3.11.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
@@ -76,6 +52,30 @@ describe("detectCurrentConfig - single package detection", () => {
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
|
||||
it("detects oh-my-openagent as installed (legacy name)", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
|
||||
it("detects oh-my-openagent with version pin as installed (legacy name)", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent@3.11.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when plugin not present", () => {
|
||||
// given
|
||||
const config = { plugin: ["some-other-plugin"] }
|
||||
@@ -89,7 +89,7 @@ describe("detectCurrentConfig - single package detection", () => {
|
||||
})
|
||||
|
||||
it("returns false when plugin not present (even with similar name)", () => {
|
||||
// given
|
||||
// given - not exactly oh-my-openagent
|
||||
const config = { plugin: ["oh-my-openagent-extra"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
@@ -102,7 +102,7 @@ describe("detectCurrentConfig - single package detection", () => {
|
||||
|
||||
it("detects OpenCode Go from the existing omo config", () => {
|
||||
// given
|
||||
writeFileSync(testConfigPath, JSON.stringify({ plugin: ["oh-my-openagent"] }, null, 2) + "\n", "utf-8")
|
||||
writeFileSync(testConfigPath, JSON.stringify({ plugin: ["oh-my-opencode"] }, null, 2) + "\n", "utf-8")
|
||||
writeFileSync(
|
||||
testOmoConfigPath,
|
||||
JSON.stringify({ agents: { atlas: { model: "opencode-go/kimi-k2.5" } } }, null, 2) + "\n",
|
||||
@@ -137,36 +137,7 @@ describe("addPluginToOpenCodeConfig - single package writes", () => {
|
||||
delete process.env.OPENCODE_CONFIG_DIR
|
||||
})
|
||||
|
||||
it("keeps oh-my-openagent when it already exists", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
})
|
||||
|
||||
it("replaces version-pinned oh-my-openagent@X.Y.Z", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent@3.10.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
expect(savedConfig.plugin).not.toContain("oh-my-openagent@3.10.0")
|
||||
})
|
||||
|
||||
it("recognizes oh-my-opencode as already installed (legacy name)", async () => {
|
||||
it("keeps oh-my-opencode when it already exists", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-opencode"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
@@ -177,12 +148,10 @@ describe("addPluginToOpenCodeConfig - single package writes", () => {
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
// Should upgrade to new name
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
expect(savedConfig.plugin).not.toContain("oh-my-opencode")
|
||||
expect(savedConfig.plugin).toContain("oh-my-opencode")
|
||||
})
|
||||
|
||||
it("replaces version-pinned oh-my-opencode@X.Y.Z with new name", async () => {
|
||||
it("replaces version-pinned oh-my-opencode@X.Y.Z", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-opencode@3.10.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
@@ -190,12 +159,43 @@ describe("addPluginToOpenCodeConfig - single package writes", () => {
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
expect(savedConfig.plugin).toContain("oh-my-opencode")
|
||||
expect(savedConfig.plugin).not.toContain("oh-my-opencode@3.10.0")
|
||||
})
|
||||
|
||||
it("recognizes oh-my-openagent as already installed (legacy name)", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
// Should upgrade to new name
|
||||
expect(savedConfig.plugin).toContain("oh-my-opencode")
|
||||
expect(savedConfig.plugin).not.toContain("oh-my-openagent")
|
||||
})
|
||||
|
||||
it("replaces version-pinned oh-my-openagent@X.Y.Z with new name", async () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent@3.10.0"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = await addPluginToOpenCodeConfig("3.11.0")
|
||||
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
// Legacy should be replaced with new name
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
expect(savedConfig.plugin).not.toContain("oh-my-opencode")
|
||||
expect(savedConfig.plugin).toContain("oh-my-opencode")
|
||||
expect(savedConfig.plugin).not.toContain("oh-my-openagent")
|
||||
})
|
||||
|
||||
it("adds new plugin when none exists", async () => {
|
||||
@@ -209,7 +209,7 @@ describe("addPluginToOpenCodeConfig - single package writes", () => {
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
expect(savedConfig.plugin).toContain("oh-my-opencode")
|
||||
})
|
||||
|
||||
it("adds plugin when plugin array is empty", async () => {
|
||||
@@ -223,6 +223,6 @@ describe("addPluginToOpenCodeConfig - single package writes", () => {
|
||||
// then
|
||||
expect(result.success).toBe(true)
|
||||
const savedConfig = JSON.parse(readFileSync(testConfigPath, "utf-8"))
|
||||
expect(savedConfig.plugin).toContain("oh-my-openagent")
|
||||
expect(savedConfig.plugin).toContain("oh-my-opencode")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { PLUGIN_NAME } from "../../shared/plugin-identity"
|
||||
import { fetchNpmDistTags } from "./npm-dist-tags"
|
||||
|
||||
const DEFAULT_PACKAGE_NAME = PLUGIN_NAME
|
||||
const DEFAULT_PACKAGE_NAME = "oh-my-opencode"
|
||||
const PRIORITIZED_TAGS = ["latest", "beta", "next"] as const
|
||||
|
||||
function getFallbackEntry(version: string, packageName: string): string {
|
||||
@@ -19,6 +18,7 @@ export async function getPluginNameWithVersion(
|
||||
): Promise<string> {
|
||||
const distTags = await fetchNpmDistTags(packageName)
|
||||
|
||||
|
||||
if (distTags) {
|
||||
const allTags = new Set([...PRIORITIZED_TAGS, ...Object.keys(distTags)])
|
||||
for (const tag of allTags) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user