Compare commits
2 Commits
feat/renam
...
fix/docs-o
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c25dbb94b2 | ||
|
|
bed98988b3 |
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
85
.github/workflows/publish-platform.yml
vendored
85
.github/workflows/publish-platform.yml
vendored
@@ -59,39 +59,20 @@ jobs:
|
||||
- name: Check if already published
|
||||
id: check
|
||||
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}")
|
||||
# Convert platform name for output (replace - with _)
|
||||
PLATFORM_KEY="${{ matrix.platform }}"
|
||||
PLATFORM_KEY="${PLATFORM_KEY//-/_}"
|
||||
|
||||
# Check oh-my-opencode
|
||||
OC_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-opencode-${{ matrix.platform }}/${VERSION}")
|
||||
# Check oh-my-openagent
|
||||
OA_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-openagent-${{ matrix.platform }}/${VERSION}")
|
||||
|
||||
echo "oh-my-opencode-${{ matrix.platform }}@${VERSION}: ${OC_STATUS}"
|
||||
echo "oh-my-openagent-${{ matrix.platform }}@${VERSION}: ${OA_STATUS}"
|
||||
|
||||
if [ "$OC_STATUS" = "200" ]; then
|
||||
echo "skip_opencode=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ oh-my-opencode-${{ matrix.platform }}@${VERSION} already published"
|
||||
else
|
||||
echo "skip_opencode=false" >> $GITHUB_OUTPUT
|
||||
echo "→ oh-my-opencode-${{ matrix.platform }}@${VERSION} needs publishing"
|
||||
fi
|
||||
|
||||
if [ "$OA_STATUS" = "200" ]; then
|
||||
echo "skip_openagent=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ oh-my-openagent-${{ matrix.platform }}@${VERSION} already published"
|
||||
else
|
||||
echo "skip_openagent=false" >> $GITHUB_OUTPUT
|
||||
echo "→ oh-my-openagent-${{ matrix.platform }}@${VERSION} needs publishing"
|
||||
fi
|
||||
|
||||
# Skip build only if BOTH are already published
|
||||
if [ "$OC_STATUS" = "200" ] && [ "$OA_STATUS" = "200" ]; then
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
echo "skip_${PLATFORM_KEY}=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ ${PKG_NAME}@${VERSION} already published"
|
||||
else
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
echo "skip_${PLATFORM_KEY}=false" >> $GITHUB_OUTPUT
|
||||
echo "→ ${PKG_NAME}@${VERSION} needs publishing"
|
||||
fi
|
||||
|
||||
- name: Update version in package.json
|
||||
@@ -216,10 +197,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,21 +207,8 @@ 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
|
||||
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"
|
||||
else
|
||||
echo "→ ${PKG_NAME}@${VERSION} will be published"
|
||||
fi
|
||||
|
||||
- name: Check if oh-my-opencode already published
|
||||
id: check-opencode
|
||||
id: check
|
||||
run: |
|
||||
PKG_NAME="oh-my-opencode-${{ matrix.platform }}"
|
||||
VERSION="${{ inputs.version }}"
|
||||
@@ -253,12 +217,13 @@ jobs:
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ ${PKG_NAME}@${VERSION} already published, skipping"
|
||||
else
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
echo "→ ${PKG_NAME}@${VERSION} will be published"
|
||||
fi
|
||||
|
||||
- name: Download artifact
|
||||
id: download
|
||||
if: steps.check.outputs.skip != 'true' || steps.check-opencode.outputs.skip != 'true'
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -266,7 +231,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 != 'true' && steps.download.outcome == 'success'
|
||||
run: |
|
||||
PLATFORM="${{ matrix.platform }}"
|
||||
mkdir -p packages/${PLATFORM}
|
||||
@@ -282,12 +247,12 @@ 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 != 'true' && steps.download.outcome == 'success'
|
||||
with:
|
||||
node-version: "24"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
- name: Publish oh-my-openagent-${{ matrix.platform }}
|
||||
- name: Publish ${{ matrix.platform }}
|
||||
if: steps.check.outputs.skip != 'true' && steps.download.outcome == 'success'
|
||||
run: |
|
||||
cd packages/${{ matrix.platform }}
|
||||
@@ -302,25 +267,3 @@ jobs:
|
||||
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)}' \
|
||||
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 }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
timeout-minutes: 15
|
||||
|
||||
59
.github/workflows/publish.yml
vendored
59
.github/workflows/publish.yml
vendored
@@ -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,39 +215,6 @@ 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'
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
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)"
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
- name: Restore package.json
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
run: |
|
||||
git checkout -- package.json
|
||||
|
||||
trigger-platform:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
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 }}
|
||||
|
||||
@@ -26,7 +26,7 @@ For each commit, you MUST:
|
||||
|
||||
<version-context>
|
||||
<published-version>
|
||||
!`npm view oh-my-opencode version 2>/dev/null || echo "not published"`
|
||||
!`npm view oh-my-openagent version 2>/dev/null || echo "not published"`
|
||||
</published-version>
|
||||
<local-version>
|
||||
!`node -p "require('./package.json').version" 2>/dev/null || echo "unknown"`
|
||||
@@ -38,13 +38,13 @@ For each commit, you MUST:
|
||||
|
||||
<git-context>
|
||||
<commits-since-release>
|
||||
!`npm view oh-my-opencode version 2>/dev/null | xargs -I{} git log "v{}"..HEAD --oneline 2>/dev/null || echo "no commits since release"`
|
||||
!`npm view oh-my-openagent version 2>/dev/null | xargs -I{} git log "v{}"..HEAD --oneline 2>/dev/null || echo "no commits since release"`
|
||||
</commits-since-release>
|
||||
<diff-stat>
|
||||
!`npm view oh-my-opencode version 2>/dev/null | xargs -I{} git diff "v{}"..HEAD --stat 2>/dev/null || echo "no diff available"`
|
||||
!`npm view oh-my-openagent version 2>/dev/null | xargs -I{} git diff "v{}"..HEAD --stat 2>/dev/null || echo "no diff available"`
|
||||
</diff-stat>
|
||||
<files-changed-summary>
|
||||
!`npm view oh-my-opencode version 2>/dev/null | xargs -I{} git diff "v{}"..HEAD --stat 2>/dev/null | tail -1 || echo ""`
|
||||
!`npm view oh-my-openagent version 2>/dev/null | xargs -I{} git diff "v{}"..HEAD --stat 2>/dev/null | tail -1 || echo ""`
|
||||
</files-changed-summary>
|
||||
</git-context>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Easter egg command - about oh-my-opencode
|
||||
description: Easter egg command - about oh-my-openagent
|
||||
---
|
||||
|
||||
<command-instruction>
|
||||
@@ -13,9 +13,9 @@ Print the following message to the user EXACTLY as written (in a friendly, celeb
|
||||
|
||||
**You found the easter egg!** 🥚✨
|
||||
|
||||
## What is Oh My OpenCode?
|
||||
## What is Oh My OpenAgent?
|
||||
|
||||
**Oh My OpenCode** is a powerful OpenCode plugin that transforms your AI agent into a full development team:
|
||||
**Oh My OpenAgent** is a powerful OpenCode plugin that transforms your AI agent into a full development team:
|
||||
|
||||
- 🤖 **Multi-Agent Orchestration**: Oracle (GPT-5.2), Librarian (Claude), Explore (Grok), Frontend Engineer (Gemini), and more
|
||||
- 🔧 **LSP Tools**: Full IDE capabilities for your agents - hover, goto definition, find references, rename, code actions
|
||||
@@ -28,7 +28,7 @@ Print the following message to the user EXACTLY as written (in a friendly, celeb
|
||||
|
||||
Created with ❤️ by **[code-yeongyu](https://github.com/code-yeongyu)**
|
||||
|
||||
🔗 **GitHub**: https://github.com/code-yeongyu/oh-my-opencode
|
||||
🔗 **GitHub**: https://github.com/code-yeongyu/oh-my-openagent
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
description: Publish oh-my-opencode to npm via GitHub Actions workflow
|
||||
description: Publish oh-my-openagent to npm via GitHub Actions workflow
|
||||
argument-hint: <patch|minor|major>
|
||||
---
|
||||
|
||||
<command-instruction>
|
||||
You are the release manager for oh-my-opencode. Execute the FULL publish workflow from start to finish.
|
||||
You are the release manager for oh-my-openagent. Execute the FULL publish workflow from start to finish.
|
||||
|
||||
## CRITICAL: ARGUMENT REQUIREMENT
|
||||
|
||||
@@ -277,7 +277,7 @@ gh release view "v${NEW_VERSION}" --json url --jq '.url'
|
||||
|
||||
Poll npm registry until the new version appears:
|
||||
```bash
|
||||
npm view oh-my-opencode version
|
||||
npm view oh-my-openagent version
|
||||
```
|
||||
|
||||
Compare with expected version. If not matching after 2 minutes, warn user about npm propagation delay.
|
||||
@@ -314,7 +314,7 @@ After publish-platform workflow completes, verify all 7 platform packages are pu
|
||||
```bash
|
||||
PLATFORMS="darwin-arm64 darwin-x64 linux-x64 linux-arm64 linux-x64-musl linux-arm64-musl windows-x64"
|
||||
for PLATFORM in $PLATFORMS; do
|
||||
npm view "oh-my-opencode-${PLATFORM}" version
|
||||
npm view "oh-my-openagent-${PLATFORM}" version
|
||||
done
|
||||
```
|
||||
|
||||
@@ -323,13 +323,13 @@ All 7 packages should show the same version as the main package (`${NEW_VERSION}
|
||||
**Expected packages:**
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| `oh-my-opencode-darwin-arm64` | macOS Apple Silicon |
|
||||
| `oh-my-opencode-darwin-x64` | macOS Intel |
|
||||
| `oh-my-opencode-linux-x64` | Linux x64 (glibc) |
|
||||
| `oh-my-opencode-linux-arm64` | Linux ARM64 (glibc) |
|
||||
| `oh-my-opencode-linux-x64-musl` | Linux x64 (musl/Alpine) |
|
||||
| `oh-my-opencode-linux-arm64-musl` | Linux ARM64 (musl/Alpine) |
|
||||
| `oh-my-opencode-windows-x64` | Windows x64 |
|
||||
| `oh-my-openagent-darwin-arm64` | macOS Apple Silicon |
|
||||
| `oh-my-openagent-darwin-x64` | macOS Intel |
|
||||
| `oh-my-openagent-linux-x64` | Linux x64 (glibc) |
|
||||
| `oh-my-openagent-linux-arm64` | Linux ARM64 (glibc) |
|
||||
| `oh-my-openagent-linux-x64-musl` | Linux x64 (musl/Alpine) |
|
||||
| `oh-my-openagent-linux-arm64-musl` | Linux ARM64 (musl/Alpine) |
|
||||
| `oh-my-openagent-windows-x64` | Windows x64 |
|
||||
|
||||
If any platform package version doesn't match, warn the user and suggest checking the publish-platform workflow logs.
|
||||
|
||||
@@ -339,8 +339,8 @@ If any platform package version doesn't match, warn the user and suggest checkin
|
||||
|
||||
Report success to user with:
|
||||
- New version number
|
||||
- GitHub release URL: https://github.com/code-yeongyu/oh-my-opencode/releases/tag/v{version}
|
||||
- npm package URL: https://www.npmjs.com/package/oh-my-opencode
|
||||
- GitHub release URL: https://github.com/code-yeongyu/oh-my-openagent/releases/tag/v{version}
|
||||
- npm package URL: https://www.npmjs.com/package/oh-my-openagent
|
||||
- Platform packages status: List all 7 platform packages with their versions
|
||||
|
||||
---
|
||||
@@ -362,7 +362,7 @@ Respond to user in English.
|
||||
|
||||
<current-context>
|
||||
<published-version>
|
||||
!`npm view oh-my-opencode version 2>/dev/null || echo "not published"`
|
||||
!`npm view oh-my-openagent version 2>/dev/null || echo "not published"`
|
||||
</published-version>
|
||||
<local-version>
|
||||
!`node -p "require('./package.json').version" 2>/dev/null || echo "unknown"`
|
||||
@@ -371,6 +371,6 @@ Respond to user in English.
|
||||
!`git status --porcelain`
|
||||
</git-status>
|
||||
<recent-commits>
|
||||
!`npm view oh-my-opencode version 2>/dev/null | xargs -I{} git log "v{}"..HEAD --oneline 2>/dev/null | head -15 || echo "no commits"`
|
||||
!`npm view oh-my-openagent version 2>/dev/null | xargs -I{} git log "v{}"..HEAD --oneline 2>/dev/null | head -15 || echo "no commits"`
|
||||
</recent-commits>
|
||||
</current-context>
|
||||
|
||||
@@ -136,36 +136,7 @@ fi
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Spawn Subagents (Individual Tool Calls)
|
||||
|
||||
**CRITICAL: Create tasks ONE BY ONE using individual `task_create` tool calls. NEVER batch or script.**
|
||||
|
||||
For each item, execute these steps sequentially:
|
||||
|
||||
### Step 3.1: Create Task Record
|
||||
```typescript
|
||||
task_create(
|
||||
subject="Triage: #{number} {title}",
|
||||
description="GitHub {issue|PR} triage analysis - {type}",
|
||||
metadata={"type": "{ISSUE_QUESTION|ISSUE_BUG|ISSUE_FEATURE|ISSUE_OTHER|PR_BUGFIX|PR_OTHER}", "number": {number}}
|
||||
)
|
||||
```
|
||||
|
||||
### Step 3.2: Spawn Analysis Subagent (Background)
|
||||
```typescript
|
||||
task(
|
||||
category="quick",
|
||||
run_in_background=true,
|
||||
load_skills=[],
|
||||
prompt=SUBAGENT_PROMPT
|
||||
)
|
||||
```
|
||||
|
||||
**ABSOLUTE RULES for Subagents:**
|
||||
- **ONLY ANALYZE** - Never take action on GitHub (no comments, merges, closes)
|
||||
- **READ-ONLY** - Use tools only for reading code/GitHub data
|
||||
- **WRITE REPORT ONLY** - Output goes to `{REPORT_DIR}/{issue|pr}-{number}.md` via Write tool
|
||||
- **EVIDENCE REQUIRED** - Every claim must have GitHub permalink as proof
|
||||
## Phase 3: Spawn Subagents
|
||||
|
||||
```
|
||||
For each item:
|
||||
@@ -199,7 +170,6 @@ ABSOLUTE RULES (violating ANY = critical failure):
|
||||
- Your ONLY writable output: {REPORT_DIR}/{issue|pr}-{number}.md via the Write tool
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
### ISSUE_QUESTION
|
||||
|
||||
@@ -37,7 +37,7 @@ Then capture raw data needed by agent prompts:
|
||||
|
||||
```bash
|
||||
# Extract versions (already in /get-unpublished-changes output)
|
||||
PUBLISHED=$(npm view oh-my-opencode version 2>/dev/null || echo "not published")
|
||||
PUBLISHED=$(npm view oh-my-openagent version 2>/dev/null || echo "not published")
|
||||
LOCAL=$(node -p "require('./package.json').version" 2>/dev/null || echo "unknown")
|
||||
|
||||
# Raw data for agents (diffs, file lists)
|
||||
@@ -85,7 +85,7 @@ task(
|
||||
<review_type>PER-CHANGE DEEP ANALYSIS</review_type>
|
||||
<change_group>{GROUP_NAME}</change_group>
|
||||
|
||||
<project>oh-my-opencode (npm package)</project>
|
||||
<project>oh-my-openagent (npm package)</project>
|
||||
<published_version>{PUBLISHED}</published_version>
|
||||
<target_version>{LOCAL}</target_version>
|
||||
|
||||
@@ -160,7 +160,7 @@ task(
|
||||
prompt="""
|
||||
Run /review-work on the unpublished changes between v{PUBLISHED} and HEAD.
|
||||
|
||||
GOAL: Review all changes heading into npm publish of oh-my-opencode. These changes span {COMMIT_COUNT} commits across {FILE_COUNT} files.
|
||||
GOAL: Review all changes heading into npm publish of oh-my-openagent. These changes span {COMMIT_COUNT} commits across {FILE_COUNT} files.
|
||||
|
||||
CONSTRAINTS:
|
||||
- This is a plugin published to npm — public API stability matters
|
||||
@@ -169,7 +169,7 @@ CONSTRAINTS:
|
||||
- Factory pattern (createXXX) for tools, hooks, agents
|
||||
- kebab-case files, barrel exports, no catch-all files
|
||||
|
||||
BACKGROUND: Pre-publish review of oh-my-opencode, an OpenCode plugin with 1268 TypeScript files, 160k LOC. Changes since v{PUBLISHED} are about to be published.
|
||||
BACKGROUND: Pre-publish review of oh-my-openagent, an OpenCode plugin with 1268 TypeScript files, 160k LOC. Changes since v{PUBLISHED} are about to be published.
|
||||
|
||||
The diff base is: git diff v{PUBLISHED}..HEAD
|
||||
|
||||
@@ -190,7 +190,7 @@ task(
|
||||
prompt="""
|
||||
<review_type>RELEASE SYNTHESIS — OVERALL ASSESSMENT</review_type>
|
||||
|
||||
<project>oh-my-opencode (npm package)</project>
|
||||
<project>oh-my-openagent (npm package)</project>
|
||||
<published_version>{PUBLISHED}</published_version>
|
||||
<local_version>{LOCAL}</local_version>
|
||||
|
||||
@@ -325,7 +325,7 @@ Do NOT deliver the final report until ALL agents have completed.
|
||||
Compile the final report:
|
||||
|
||||
```markdown
|
||||
# Pre-Publish Review — oh-my-opencode
|
||||
# Pre-Publish Review — oh-my-openagent
|
||||
|
||||
## Release: v{PUBLISHED} -> v{LOCAL}
|
||||
**Commits:** {COMMIT_COUNT} | **Files Changed:** {FILE_COUNT} | **Agents:** {AGENT_COUNT}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
Add a `max_background_agents` config option to oh-my-opencode that limits total simultaneous background agents across all models/providers. Currently, concurrency is only limited per-model/provider key (default 5 per key). This new option adds a **global ceiling** on total running background agents.
|
||||
Add a `max_background_agents` config option to oh-my-openagent that limits total simultaneous background agents across all models/providers. Currently, concurrency is only limited per-model/provider key (default 5 per key). This new option adds a **global ceiling** on total running background agents.
|
||||
|
||||
## Step-by-Step Plan
|
||||
|
||||
@@ -80,7 +80,7 @@ Check `src/config/schema/background-task.ts` and `src/features/background-agent/
|
||||
|
||||
| File | Reason |
|
||||
|------|--------|
|
||||
| `src/config/schema/oh-my-opencode-config.ts` | No change needed - `BackgroundTaskConfigSchema` is already composed into root schema via `background_task` field |
|
||||
| `src/config/schema/oh-my-openagent-config.ts` | No change needed - `BackgroundTaskConfigSchema` is already composed into root schema via `background_task` field |
|
||||
| `src/create-managers.ts` | No change needed - `pluginConfig.background_task` already passed to `BackgroundManager` constructor |
|
||||
| `src/features/background-agent/manager.ts` | No change needed - already passes config to `ConcurrencyManager` |
|
||||
| `src/plugin-config.ts` | No change needed - `background_task` is a simple object field, uses default override merge |
|
||||
|
||||
@@ -63,7 +63,7 @@ All existing tests must continue to pass unchanged.
|
||||
Verify the config flows correctly through the system:
|
||||
|
||||
1. **Schema → Type**: `BackgroundTaskConfig` type auto-includes `maxBackgroundAgents` via `z.infer`
|
||||
2. **Config file → Schema**: `loadConfigFromPath()` in `plugin-config.ts` uses `OhMyOpenCodeConfigSchema.safeParse()` which includes `BackgroundTaskConfigSchema`
|
||||
2. **Config file → Schema**: `loadConfigFromPath()` in `plugin-config.ts` uses `OhMyOpenAgentConfigSchema.safeParse()` which includes `BackgroundTaskConfigSchema`
|
||||
3. **Config → Manager**: `create-managers.ts` passes `pluginConfig.background_task` to `BackgroundManager` constructor
|
||||
4. **Manager → ConcurrencyManager**: `BackgroundManager` constructor passes config to `new ConcurrencyManager(config)`
|
||||
5. **ConcurrencyManager → Enforcement**: `acquire()` reads `config.maxBackgroundAgents` via `getGlobalLimit()`
|
||||
|
||||
@@ -36,7 +36,7 @@ import { createWebsearchConfig } from "./websearch"
|
||||
import { context7 } from "./context7"
|
||||
import { grep_app } from "./grep-app"
|
||||
import { arxiv } from "./arxiv"
|
||||
import type { OhMyOpenCodeConfig } from "../config/schema"
|
||||
import type { OhMyOpenAgentConfig } from "../config/schema"
|
||||
|
||||
export { McpNameSchema, type McpName } from "./types"
|
||||
|
||||
@@ -48,7 +48,7 @@ type RemoteMcpConfig = {
|
||||
oauth?: false
|
||||
}
|
||||
|
||||
export function createBuiltinMcps(disabledMcps: string[] = [], config?: OhMyOpenCodeConfig) {
|
||||
export function createBuiltinMcps(disabledMcps: string[] = [], config?: OhMyOpenAgentConfig) {
|
||||
const mcps: Record<string, RemoteMcpConfig> = {}
|
||||
|
||||
if (!disabledMcps.includes("websearch")) {
|
||||
|
||||
@@ -41,7 +41,7 @@ Pattern followed: `grep-app.ts` (static export, no auth, no config factory neede
|
||||
import { context7 } from "./context7"
|
||||
import { grep_app } from "./grep-app"
|
||||
+import { arxiv } from "./arxiv"
|
||||
import type { OhMyOpenCodeConfig } from "../config/schema"
|
||||
import type { OhMyOpenAgentConfig } from "../config/schema"
|
||||
|
||||
-export { McpNameSchema, type McpName } from "./types"
|
||||
+export { McpNameSchema, type McpName } from "./types"
|
||||
@@ -54,7 +54,7 @@ Pattern followed: `grep-app.ts` (static export, no auth, no config factory neede
|
||||
oauth?: false
|
||||
}
|
||||
|
||||
export function createBuiltinMcps(disabledMcps: string[] = [], config?: OhMyOpenCodeConfig) {
|
||||
export function createBuiltinMcps(disabledMcps: string[] = [], config?: OhMyOpenAgentConfig) {
|
||||
const mcps: Record<string, RemoteMcpConfig> = {}
|
||||
|
||||
if (!disabledMcps.includes("websearch")) {
|
||||
|
||||
@@ -51,7 +51,7 @@ Since the regex lives in the Go binary and this repo wraps it, the fix is two-pr
|
||||
- Relax `(?i)^[\s#/*-]*note:\s*\w` to only match AI-style memo patterns like `Note: this was changed...`, `Note: implementation details...`
|
||||
- Add `--exclude-pattern` CLI flag for user-configurable exclusions
|
||||
|
||||
**B. This repo (oh-my-opencode)** - the PR scope:
|
||||
**B. This repo (oh-my-openagent)** - the PR scope:
|
||||
1. Add `exclude_patterns` config field to `CommentCheckerConfigSchema`
|
||||
2. Pass `--exclude-pattern` flags to the CLI binary
|
||||
3. Add integration tests with mock binaries for false positive scenarios
|
||||
|
||||
@@ -20,7 +20,7 @@ Additionally, the binary flags ALL non-filtered comments (not just agent memos),
|
||||
## Architecture Understanding
|
||||
|
||||
```
|
||||
TypeScript (oh-my-opencode) Go Binary (go-claude-code-comment-checker)
|
||||
TypeScript (oh-my-openagent) Go Binary (go-claude-code-comment-checker)
|
||||
───────────────────────────── ──────────────────────────────────────────
|
||||
hook.ts main.go
|
||||
├─ tool.execute.before ├─ Read JSON from stdin
|
||||
@@ -33,7 +33,7 @@ hook.ts main.go
|
||||
└─ append to output
|
||||
```
|
||||
|
||||
Key files in oh-my-opencode:
|
||||
Key files in oh-my-openagent:
|
||||
- `src/hooks/comment-checker/hook.ts` - Hook factory, registers before/after handlers
|
||||
- `src/hooks/comment-checker/cli-runner.ts` - Orchestrates CLI invocation, semaphore
|
||||
- `src/hooks/comment-checker/cli.ts` - Binary resolution, process spawning, timeout handling
|
||||
|
||||
16
AGENTS.md
16
AGENTS.md
@@ -1,15 +1,15 @@
|
||||
# oh-my-opencode — O P E N C O D E Plugin
|
||||
# oh-my-openagent — O P E N C O D E Plugin
|
||||
|
||||
**Generated:** 2026-03-06 | **Commit:** 7fe44024 | **Branch:** dev
|
||||
|
||||
## 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-openagent`) 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.
|
||||
|
||||
## STRUCTURE
|
||||
|
||||
```
|
||||
oh-my-opencode/
|
||||
oh-my-openagent/
|
||||
├── src/
|
||||
│ ├── index.ts # Plugin entry: loadConfig → createManagers → createTools → createHooks → createPluginInterface
|
||||
│ ├── plugin-config.ts # JSONC multi-level config: user → project → defaults (Zod v4)
|
||||
@@ -30,7 +30,7 @@ oh-my-opencode/
|
||||
## INITIALIZATION FLOW
|
||||
|
||||
```
|
||||
OhMyOpenCodePlugin(ctx)
|
||||
OhMyOpenAgentPlugin(ctx)
|
||||
├─→ loadPluginConfig() # JSONC parse → project/user merge → Zod validate → migrate
|
||||
├─→ createManagers() # TmuxSessionManager, BackgroundManager, SkillMcpManager, ConfigHandler
|
||||
├─→ createTools() # SkillContext + AvailableCategories + ToolRegistry (26 tools)
|
||||
@@ -65,7 +65,7 @@ OhMyOpenCodePlugin(ctx)
|
||||
| Add new command | `src/features/builtin-commands/` | Template in templates/ |
|
||||
| Add new CLI command | `src/cli/cli-program.ts` | Commander.js subcommand |
|
||||
| Add new doctor check | `src/cli/doctor/checks/` | Register in checks/index.ts |
|
||||
| Modify config schema | `src/config/schema/` + update root schema | Zod v4, add to OhMyOpenCodeConfigSchema |
|
||||
| Modify config schema | `src/config/schema/` + update root schema | Zod v4, add to OhMyOpenAgentConfigSchema |
|
||||
| Add new category | `src/tools/delegate-task/constants.ts` | DEFAULT_CATEGORIES + CATEGORY_MODEL_REQUIREMENTS |
|
||||
|
||||
## MULTI-LEVEL CONFIG
|
||||
@@ -128,9 +128,9 @@ bun test # Bun test suite
|
||||
bun run build # Build plugin (ESM + declarations + schema)
|
||||
bun run build:all # Build + platform binaries
|
||||
bun run typecheck # tsc --noEmit
|
||||
bunx oh-my-opencode install # Interactive setup
|
||||
bunx oh-my-opencode doctor # Health diagnostics
|
||||
bunx oh-my-opencode run # Non-interactive session
|
||||
bunx oh-my-openagent install # Interactive setup
|
||||
bunx oh-my-openagent doctor # Health diagnostics
|
||||
bunx oh-my-openagent run # Non-interactive session
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Contributing to Oh My OpenCode
|
||||
# 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-openagent.
|
||||
|
||||
@@ -272,4 +272,4 @@ export function createMyHook(input: PluginInput) {
|
||||
|
||||
---
|
||||
|
||||
Thank you for contributing to Oh My OpenCode! Your efforts help make AI-assisted coding better for everyone.
|
||||
Thank you for contributing to Oh My OpenAgent! Your efforts help make AI-assisted coding better for everyone.
|
||||
|
||||
@@ -72,7 +72,7 @@ Use ultrawork (ulw) to spawn UltraBrain agents in parallel. Each UB agent gets a
|
||||
## ADDITIONAL BLOCKERS FROM GPT-5.4 REVIEW
|
||||
|
||||
### G1: Package Identity Split-Brain
|
||||
**Problem:** Installer writes oh-my-openagent but doctor, auto-update, version lookup, publish workflow still reference oh-my-opencode. Half-migrated state.
|
||||
**Problem:** Installer writes oh-my-openagent but doctor, auto-update, version lookup, publish workflow still reference oh-my-openagent. Half-migrated state.
|
||||
**Fix:** Audit ALL references to package name. Either complete the migration consistently or revert to single name for this release.
|
||||
**Files:** Installer, doctor, auto-update, version lookup, publish workflow -- grep for both package names
|
||||
|
||||
|
||||
16
README.ja.md
16
README.ja.md
@@ -21,7 +21,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
|
||||
@@ -34,7 +34,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-openagent)
|
||||
[](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)
|
||||
@@ -54,7 +54,7 @@ https://www.npmjs.com/package/oh-my-openagent
|
||||
|
||||
> 「Claude Codeが人間なら3ヶ月かかることを7日でやるとしたら、Sisyphusはそれを1時間でやってのけます。タスクが終わるまでひたすら働き続けます。まさに規律あるエージェントです。」 <br/>- B, Quant Researcher
|
||||
|
||||
> 「Oh My Opencodeを使って、たった1日で8000個の eslint 警告を叩き潰しました。」 <br/>- [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
> 「Oh My OpenAgentを使って、たった1日で8000個の eslint 警告を叩き潰しました。」 <br/>- [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
|
||||
> 「Ohmyopencodeとralph loopを使って、45k行のtauriアプリを一晩でSaaSウェブアプリに変換しました。インタビューモードから始めて、私のプロンプトに対して質問や推奨事項を尋ねました。勝手に作業していくのを見るのは楽しかったし、今朝起きたらウェブサイトがほぼ動いているのを見て驚愕しました!」 - [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
@@ -62,17 +62,17 @@ https://www.npmjs.com/package/oh-my-openagent
|
||||
|
||||
> 「何がどうすごいのかまだ上手く言語化できないんですが、開発体験が完全に異次元に到達してしまいました。」 - [苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
|
||||
> 「週末にマインクラフト/ソウルライクな化け物を作ろうと、open code、oh my opencode、supermemoryで実験中です。昼食後の散歩に行っている間に、しゃがむアニメーションを追加するように指示しておきました。[動画]」 - [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
> 「週末にマインクラフト/ソウルライクな化け物を作ろうと、open code、oh my openagent、supermemoryで実験中です。昼食後の散歩に行っている間に、しゃがむアニメーションを追加するように指示しておきました。[動画]」 - [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
|
||||
> 「これをコアに取り込んで彼を採用すべきだ。マジで。これ、本当に、本当に、本当に良い。」 <br/>- Henning Kilset
|
||||
|
||||
> 「彼を説得できるなら @yeon_gyu_kim を雇ってください。彼がopencodeに革命を起こしました。」 <br/>- [mysticaltech](https://x.com/mysticaltech/status/2001858758608376079)
|
||||
|
||||
> 「Oh My OpenCodeはマジでヤバい」 - [YouTube - Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
> 「Oh My OpenAgentはマジでヤバい」 - [YouTube - Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
|
||||
---
|
||||
|
||||
# Oh My OpenCode
|
||||
# Oh My OpenAgent
|
||||
|
||||
最初はこれを「Claude Codeにステロイドを打ったもの」と呼んでいました。それは過小評価でした。
|
||||
|
||||
@@ -281,10 +281,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. **削除の確認**
|
||||
|
||||
16
README.ko.md
16
README.ko.md
@@ -16,7 +16,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
|
||||
@@ -29,7 +29,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-openagent)
|
||||
[](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)
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
> "Claude Code가 인간이 3개월 걸릴 일을 7일 만에 한다면, Sisyphus는 1시간 만에 해냅니다. 작업이 끝날 때까지 그냥 계속 알아서 작동합니다. 이건 정말 규율이 잡힌 에이전트예요." <br/>- B, Quant Researcher
|
||||
|
||||
> "Oh My Opencode로 하루 만에 eslint 경고 8000개를 해결했습니다." <br/>- [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
> "Oh My OpenAgent로 하루 만에 eslint 경고 8000개를 해결했습니다." <br/>- [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
|
||||
> "Ohmyopencode와 ralph loop를 써서 45k 라인짜리 tauri 앱을 하룻밤 만에 SaaS 웹앱으로 변환했어요. 인터뷰 모드로 시작해서, 제가 쓴 프롬프트에 대해 질문하고 추천을 부탁했죠. 일하는 걸 지켜보는 것도 재밌었고, 아침에 일어났더니 웹사이트가 대부분 돌아가고 있는 걸 보고 경악했습니다!" - [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
@@ -57,17 +57,17 @@
|
||||
|
||||
> "뭐가 이렇게 대단한 건지 아직 정확하게 말로 표현하긴 어려운데, 개발 경험 자체가 완전히 다른 차원에 도달해버렸어요." - [苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
|
||||
> "주말에 마인크래프트/소울라이크 같은 괴물 같은 걸 만들어보려고 open code, oh my opencode, supermemory로 실험 중입니다. 점심 먹고 산책 다녀오는 동안 앉기 애니메이션을 추가하라고 시켜뒀어요. [영상]" - [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
> "주말에 마인크래프트/소울라이크 같은 괴물 같은 걸 만들어보려고 open code, oh my openagent, supermemory로 실험 중입니다. 점심 먹고 산책 다녀오는 동안 앉기 애니메이션을 추가하라고 시켜뒀어요. [영상]" - [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
|
||||
> "이걸 코어에 당겨오고 저 사람 스카우트해야 돼요. 진심으로. 이거 진짜, 진짜, 진짜 좋습니다." <br/>- Henning Kilset
|
||||
|
||||
> "설득할 수만 있다면 @yeon_gyu_kim 채용하세요, 이 사람이 opencode를 혁명적으로 바꿨습니다." <br/>- [mysticaltech](https://x.com/mysticaltech/status/2001858758608376079)
|
||||
|
||||
> "Oh My OpenCode는 진짜 미쳤다" - [YouTube - Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
> "Oh My OpenAgent는 진짜 미쳤다" - [YouTube - Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
|
||||
---
|
||||
|
||||
# Oh My OpenCode
|
||||
# Oh My OpenAgent
|
||||
|
||||
Claude Code, Codex, 온갖 OSS 모델들 사이에서 헤매고 있나요. 워크플로우 설정하랴, 에이전트 디버깅하랴 피곤할 겁니다.
|
||||
|
||||
@@ -275,10 +275,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. **제거 확인**
|
||||
|
||||
27
README.md
27
README.md
@@ -15,9 +15,9 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](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)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
|
||||
|
||||
</div>
|
||||
@@ -31,7 +31,7 @@
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent/releases)
|
||||
[](https://www.npmjs.com/package/oh-my-opencode)
|
||||
[](https://www.npmjs.com/package/oh-my-openagent)
|
||||
[](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)
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
> "If Claude Code does in 7 days what a human does in 3 months, Sisyphus does it in 1 hour. It just works until the task is done. It is a discipline agent." <br/>- B, Quant Researcher
|
||||
|
||||
> "Knocked out 8000 eslint warnings with Oh My Opencode, just in a day" <br/>- [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
> "Knocked out 8000 eslint warnings with Oh My OpenAgent, just in a day" <br/>- [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
|
||||
> "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)
|
||||
|
||||
@@ -60,18 +60,18 @@
|
||||
> "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)
|
||||
|
||||
> "Experimenting with open code, oh my opencode and supermemory this weekend to build some minecraft/souls-like abomination."
|
||||
> "Experimenting with open code, oh my openagent and supermemory this weekend to build some minecraft/souls-like abomination."
|
||||
> "Asking it to add crouch animations while I go take my post-lunch walk. [Video]" - [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
|
||||
> "You guys should pull this into core and recruit him. Seriously. It's really, really, really good." <br/>- Henning Kilset
|
||||
|
||||
> "Hire @yeon_gyu_kim if you can convince him, this dude has revolutionized opencode." <br/>- [mysticaltech](https://x.com/mysticaltech/status/2001858758608376079)
|
||||
|
||||
> "Oh My OpenCode Is Actually Insane" - [YouTube - Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
> "Oh My OpenAgent Is Actually Insane" - [YouTube - Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
|
||||
---
|
||||
|
||||
# Oh My OpenCode
|
||||
# Oh My OpenAgent
|
||||
|
||||
You're juggling Claude Code, Codex, random OSS models. Configuring workflows. Debugging agents.
|
||||
|
||||
@@ -158,6 +158,10 @@ Even only with following subscriptions, ultrawork will work well (this project i
|
||||
|
||||
**Prometheus** (`claude-opus-4-6` / **`kimi-k2.5`** / **`glm-5`** ) is your strategic planner. Interview mode: it questions, identifies scope, and builds a detailed plan before a single line of code is touched.
|
||||
|
||||
**Atlas** (`claude-sonnet-4-6`) is the executor. He takes the plan from Prometheus and drives it to completion, managing the todo list and coordinating subagents.
|
||||
|
||||
**Sisyphus-Junior** is the dedicated executor for category-based tasks.
|
||||
|
||||
Every agent is tuned to its model's specific strengths. No manual model-juggling. [Learn more →](docs/guide/overview.md)
|
||||
|
||||
> Anthropic [blocked OpenCode because of us.](https://x.com/thdxr/status/2010149530486911014) That's why Hephaestus is called "The Legitimate Craftsman." The irony is intentional.
|
||||
@@ -276,10 +280,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**
|
||||
@@ -296,7 +300,8 @@ Features you'll think should've always existed. Once you use them, you can't go
|
||||
See full [Features Documentation](docs/reference/features.md).
|
||||
|
||||
**Quick Overview:**
|
||||
- **Agents**: Sisyphus (the main agent), Prometheus (planner), Oracle (architecture/debugging), Librarian (docs/code search), Explore (fast codebase grep), Multimodal Looker
|
||||
- **Primary Agents**: Sisyphus (the main agent), Hephaestus (deep worker), Prometheus (planner), Atlas (executor), Sisyphus-Junior (category executor)
|
||||
- **Specialist Subagents**: Oracle (architecture/debugging), Librarian (docs/code search), Explore (fast codebase grep), Multimodal Looker (vision)
|
||||
- **Background Agents**: Run multiple agents in parallel like a real dev team
|
||||
- **LSP & AST Tools**: Refactoring, rename, diagnostics, AST-aware code search
|
||||
- **Hash-anchored Edit Tool**: `LINE#ID` references validate content before applying every change. Surgical edits, zero stale-line errors
|
||||
@@ -314,7 +319,7 @@ 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)
|
||||
|
||||
18
README.ru.md
18
README.ru.md
@@ -19,7 +19,7 @@
|
||||
|
||||
<!-- <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-openagent)
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
|
||||
@@ -31,7 +31,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-openagent) [](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 | 한국어 | 日本語 | 简体中文 | Русский
|
||||
|
||||
@@ -43,7 +43,7 @@ English | 한국어 | 日本語 | 简体中文 | Русский
|
||||
|
||||
> «Если Claude Code делает за 7 дней то, на что у человека уходит 3 месяца, Sisyphus справляется за 1 час. Он просто работает, пока задача не выполнена. Это дисциплинированный агент.» <br/>— B, исследователь в области квантовых финансов
|
||||
|
||||
> «За один день устранил 8000 предупреждений eslint с помощью Oh My Opencode.» <br/>— [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
> «За один день устранил 8000 предупреждений eslint с помощью Oh My OpenAgent.» <br/>— [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
|
||||
> «За ночь конвертировал приложение на tauri в 45k строк в веб-SaaS с помощью Ohmyopencode и ralph loop. Начал с промпта «проинтервьюируй меня», попросил оценки и рекомендации по вопросам. Было удивительно наблюдать за работой и утром проснуться с почти рабочим сайтом!» — [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
@@ -51,17 +51,17 @@ English | 한국어 | 日本語 | 简体中文 | Русский
|
||||
|
||||
> «Пока не могу точно объяснить, почему это так круто, но опыт разработки вышел на совершенно другой уровень.» — [苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
|
||||
> «Экспериментирую с open code, oh my opencode и supermemory этим выходным, чтобы собрать нечто среднее между Minecraft и souls-like.» «Попросил добавить анимации приседания, пока хожу на обеденную прогулку. [Видео]» — [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
> «Экспериментирую с open code, oh my openagent и supermemory этим выходным, чтобы собрать нечто среднее между Minecraft и souls-like.» «Попросил добавить анимации приседания, пока хожу на обеденную прогулку. [Видео]» — [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
|
||||
> «Ребята, вам нужно включить это в ядро и нанять его. Серьёзно. Это очень, очень, очень хорошо.» <br/>— Henning Kilset
|
||||
|
||||
> «Наймите @yeon_gyu_kim, если сможете его уговорить, этот парень революционизировал opencode.» <br/>— [mysticaltech](https://x.com/mysticaltech/status/2001858758608376079)
|
||||
|
||||
> «Oh My OpenCode — это что-то с чем-то» — [YouTube — Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
> «Oh My OpenAgent — это что-то с чем-то» — [YouTube — Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
|
||||
------
|
||||
|
||||
# Oh My OpenCode
|
||||
# Oh My OpenAgent
|
||||
|
||||
Вы жонглируете Claude Code, Codex, случайными OSS-моделями. Настраиваете рабочие процессы. Дебажите агентов.
|
||||
|
||||
@@ -263,10 +263,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 +303,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` (атомарные коммиты)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
|
||||
[](https://github.com/code-yeongyu/oh-my-openagent#oh-my-openagent)
|
||||
|
||||
@@ -34,7 +34,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-openagent)
|
||||
[](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)
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
> “如果人类需要 3 个月完成的事情 Claude Code 需要 7 天,那么 Sisyphus 只需要 1 小时。它会一直工作直到任务完成。它是一个极度自律的智能体。” <br/>- B, 量化研究员
|
||||
|
||||
> “用 Oh My Opencode 一天之内解决了 8000 个 eslint 警告。” <br/>- [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
> “用 Oh My OpenAgent 一天之内解决了 8000 个 eslint 警告。” <br/>- [Jacob Ferrari](https://x.com/jacobferrari_/status/2003258761952289061)
|
||||
|
||||
> “我用 Ohmyopencode 和 ralph loop 花了一晚上的时间,把一个 45k 行代码的 tauri 应用转换成了 SaaS Web 应用。从面试模式开始,让它对我提供的提示词进行提问和提出建议。看着它工作很有趣,今早醒来看到网站基本已经跑起来了,太震撼了!” - [James Hargis](https://x.com/hargabyte/status/2007299688261882202)
|
||||
|
||||
@@ -62,17 +62,17 @@
|
||||
|
||||
> “我很难准确描述它到底哪里牛逼,但开发体验已经达到完全不同的维度了。” - [苔硯:こけすずり](https://x.com/kokesuzuri/status/2008532913961529372?s=20)
|
||||
|
||||
> “这周末我用 open code、oh my opencode 和 supermemory 瞎折腾一个像我的世界/魂系一样的怪物游戏。吃完午饭去散步前,我让它把下蹲动画加进去。[视频]” - [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
> “这周末我用 open code、oh my openagent 和 supermemory 瞎折腾一个像我的世界/魂系一样的怪物游戏。吃完午饭去散步前,我让它把下蹲动画加进去。[视频]” - [MagiMetal](https://x.com/MagiMetal/status/2005374704178373023)
|
||||
|
||||
> “你们真该把这个合并到核心代码里,然后把他招安了。说真的,这东西实在太牛了。” <br/>- Henning Kilset
|
||||
|
||||
> “如果你们能说服 @yeon_gyu_kim,赶紧招募他。这个人彻底改变了 opencode。” <br/>- [mysticaltech](https://x.com/mysticaltech/status/2001858758608376079)
|
||||
|
||||
> “Oh My OpenCode 简直疯了。” - [YouTube - Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
> “Oh My OpenAgent 简直疯了。” - [YouTube - Darren Builds AI](https://www.youtube.com/watch?v=G_Snfh2M41M)
|
||||
|
||||
---
|
||||
|
||||
# Oh My OpenCode
|
||||
# Oh My OpenAgent
|
||||
|
||||
我们最初把这叫做“给 Claude Code 打类固醇”。那是低估了它。
|
||||
|
||||
@@ -280,10 +280,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
@@ -3699,35 +3699,6 @@
|
||||
"syncPollTimeoutMs": {
|
||||
"type": "number",
|
||||
"minimum": 60000
|
||||
},
|
||||
"maxToolCalls": {
|
||||
"type": "integer",
|
||||
"minimum": 10,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"circuitBreaker": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"maxToolCalls": {
|
||||
"type": "integer",
|
||||
"minimum": 10,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"windowSize": {
|
||||
"type": "integer",
|
||||
"minimum": 5,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"repetitionThresholdPercent": {
|
||||
"type": "number",
|
||||
"exclusiveMinimum": 0,
|
||||
"maximum": 100
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"": {
|
||||
"name": "hashline-edit-benchmark",
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai-compatible": "^2.0.35",
|
||||
"@friendliai/ai-provider": "^1.0.9",
|
||||
"ai": "^6.0.94",
|
||||
"zod": "^4.1.0",
|
||||
},
|
||||
@@ -14,11 +14,13 @@
|
||||
"packages": {
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.55", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.15", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7xMeTJnCjwRwXKVCiv4Ly4qzWvDuW3+W1WIV0X1EFu6W83d4mEhV9bFArto10MeTw40ewuDjrbrZd21mXKohkw=="],
|
||||
|
||||
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-g3wA57IAQFb+3j4YuFndgkUdXyRETZVvbfAWM+UX7bZSxA3xjes0v3XKgIdKdekPtDGsh4ZX2byHD0gJIMPfiA=="],
|
||||
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.30", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.15" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iTjumHf1/u4NhjXYFn/aONM2GId3/o7J1Lp5ql8FCbgIMyRwrmanR5xy1S3aaVkfTscuDvLTzWiy1mAbGzK3nQ=="],
|
||||
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="],
|
||||
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.19", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg=="],
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.15", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8XiKWbemmCbvNN0CLR9u3PQiet4gtEVIrX4zzLxnCj06AwsEDJwJVBbKrEI4t6qE8XRSIvU2irka0dcpziKW6w=="],
|
||||
|
||||
"@friendliai/ai-provider": ["@friendliai/ai-provider@1.1.4", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.30", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.15" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.12" } }, "sha512-9TU4B1QFqPhbkONjI5afCF7Ox4jOqtGg1xw8mA9QHZdtlEbZxU+mBNvMPlI5pU5kPoN6s7wkXmFmxpID+own1A=="],
|
||||
|
||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||
|
||||
@@ -33,9 +35,5 @@
|
||||
"json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
|
||||
|
||||
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
|
||||
|
||||
"@ai-sdk/gateway/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.15", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8XiKWbemmCbvNN0CLR9u3PQiet4gtEVIrX4zzLxnCj06AwsEDJwJVBbKrEI4t6qE8XRSIvU2irka0dcpziKW6w=="],
|
||||
|
||||
"ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.15", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8XiKWbemmCbvNN0CLR9u3PQiet4gtEVIrX4zzLxnCj06AwsEDJwJVBbKrEI4t6qE8XRSIvU2irka0dcpziKW6w=="],
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,16 @@ import { readFile, writeFile, mkdir } from "node:fs/promises"
|
||||
import { join, dirname } from "node:path"
|
||||
import { stepCountIs, streamText, type CoreMessage } from "ai"
|
||||
import { tool } from "ai"
|
||||
import { createOpenAICompatible } from "@ai-sdk/openai-compatible"
|
||||
import { createFriendli } from "@friendliai/ai-provider"
|
||||
import { z } from "zod"
|
||||
import { formatHashLines } from "../../src/tools/hashline-edit/hash-computation"
|
||||
import { normalizeHashlineEdits } from "../../src/tools/hashline-edit/normalize-edits"
|
||||
import { applyHashlineEditsWithReport } from "../../src/tools/hashline-edit/edit-operations"
|
||||
import { canonicalizeFileText, restoreFileText } from "../../src/tools/hashline-edit/file-text-canonicalization"
|
||||
import { HASHLINE_EDIT_DESCRIPTION } from "../../src/tools/hashline-edit/tool-description"
|
||||
import { formatHashLines } from "../src/tools/hashline-edit/hash-computation"
|
||||
import { normalizeHashlineEdits } from "../src/tools/hashline-edit/normalize-edits"
|
||||
import { applyHashlineEditsWithReport } from "../src/tools/hashline-edit/edit-operations"
|
||||
import { canonicalizeFileText, restoreFileText } from "../src/tools/hashline-edit/file-text-canonicalization"
|
||||
|
||||
const DEFAULT_MODEL = "minimax-m2.5-free"
|
||||
const DEFAULT_MODEL = "MiniMaxAI/MiniMax-M2.5"
|
||||
const MAX_STEPS = 50
|
||||
const sessionId = `hashline-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
||||
const sessionId = `bench-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
||||
|
||||
const emit = (event: Record<string, unknown>) =>
|
||||
console.log(JSON.stringify({ sessionId, timestamp: new Date().toISOString(), ...event }))
|
||||
@@ -34,7 +33,7 @@ function parseArgs(): { prompt: string; modelId: string } {
|
||||
// --no-translate, --think consumed silently
|
||||
}
|
||||
if (!prompt) {
|
||||
console.error("Usage: bun run tests/hashline/headless.ts -p <prompt> [-m <model>]")
|
||||
console.error("Usage: bun run benchmarks/headless.ts -p <prompt> [-m <model>]")
|
||||
process.exit(1)
|
||||
}
|
||||
return { prompt, modelId }
|
||||
@@ -58,7 +57,7 @@ const readFileTool = tool({
|
||||
})
|
||||
|
||||
const editFileTool = tool({
|
||||
description: HASHLINE_EDIT_DESCRIPTION,
|
||||
description: "Edit a file using hashline anchors (LINE#ID format)",
|
||||
inputSchema: z.object({
|
||||
path: z.string(),
|
||||
edits: z.array(
|
||||
@@ -117,12 +116,8 @@ const editFileTool = tool({
|
||||
async function run() {
|
||||
const { prompt, modelId } = parseArgs()
|
||||
|
||||
const provider = createOpenAICompatible({
|
||||
name: "hashline-test",
|
||||
baseURL: process.env.HASHLINE_TEST_BASE_URL ?? "https://quotio.mengmota.com/v1",
|
||||
apiKey: process.env.HASHLINE_TEST_API_KEY ?? "quotio-local-60A613FE-DB74-40FF-923E-A14151951E5D",
|
||||
})
|
||||
const model = provider.chatModel(modelId)
|
||||
const friendli = createFriendli({ apiKey: process.env.FRIENDLI_TOKEN! })
|
||||
const model = friendli(modelId)
|
||||
const tools = { read_file: readFileTool, edit_file: editFileTool }
|
||||
|
||||
emit({ type: "user", content: prompt })
|
||||
@@ -130,8 +125,7 @@ async function run() {
|
||||
const messages: CoreMessage[] = [{ role: "user", content: prompt }]
|
||||
const system =
|
||||
"You are a code editing assistant. Use read_file to read files and edit_file to edit them. " +
|
||||
"Always read a file before editing it to get fresh LINE#ID anchors.\n\n" +
|
||||
"edit_file tool description:\n" + HASHLINE_EDIT_DESCRIPTION
|
||||
"Always read a file before editing it to get fresh LINE#ID anchors."
|
||||
|
||||
for (let step = 0; step < MAX_STEPS; step++) {
|
||||
const stream = streamText({
|
||||
@@ -167,7 +161,6 @@ async function run() {
|
||||
...(isError ? { error: output } : {}),
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,4 +191,3 @@ run()
|
||||
const elapsed = ((Date.now() - startTime) / 1000).toFixed(2)
|
||||
console.error(`[headless] Completed in ${elapsed}s`)
|
||||
})
|
||||
|
||||
18
benchmarks/package.json
Normal file
18
benchmarks/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "hashline-edit-benchmark",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Hashline edit tool benchmark using Vercel AI SDK with FriendliAI provider",
|
||||
"scripts": {
|
||||
"bench:basic": "bun run test-edit-ops.ts",
|
||||
"bench:edge": "bun run test-edge-cases.ts",
|
||||
"bench:multi": "bun run test-multi-model.ts",
|
||||
"bench:all": "bun run bench:basic && bun run bench:edge"
|
||||
},
|
||||
"dependencies": {
|
||||
"@friendliai/ai-provider": "^1.0.9",
|
||||
"ai": "^6.0.94",
|
||||
"zod": "^4.1.0"
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,10 @@ import { resolve } from "node:path";
|
||||
|
||||
// ── Models ────────────────────────────────────────────────────
|
||||
const MODELS = [
|
||||
{ id: "minimax-m2.5-free", short: "M2.5-Free" },
|
||||
{ id: "MiniMaxAI/MiniMax-M2.5", short: "M2.5" },
|
||||
// { id: "MiniMaxAI/MiniMax-M2.1", short: "M2.1" }, // masked: slow + timeout-prone
|
||||
// { id: "zai-org/GLM-5", short: "GLM-5" }, // masked: API 503
|
||||
{ id: "zai-org/GLM-4.7", short: "GLM-4.7" },
|
||||
];
|
||||
|
||||
// ── CLI args ──────────────────────────────────────────────────
|
||||
@@ -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
|
||||
|
||||
@@ -64,8 +64,8 @@ These agents have Claude-optimized prompts — long, detailed, mechanics-driven.
|
||||
|
||||
| Agent | Role | Fallback Chain | Notes |
|
||||
| ------------ | ----------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| **Sisyphus** | Main orchestrator | Claude Opus → opencode-go/kimi-k2.5 → K2P5 → Kimi K2.5 → GPT-5.4 → GLM-5 → Big Pickle | Claude-family first. GPT-5.4 has dedicated prompt support. Kimi available through multiple providers. |
|
||||
| **Metis** | Plan gap analyzer | Claude Opus → GPT-5.4 → opencode-go/glm-5 → K2P5 | Claude preferred. GPT-5.4 as secondary before GLM-5 fallback. |
|
||||
| **Sisyphus** | Main orchestrator | Claude Opus → opencode-go/kimi-k2.5 → K2P5 → GPT-5.4 → GLM-5 → Big Pickle | Claude-family first. GPT-5.4 has dedicated prompt support. Kimi/GLM as intermediate fallbacks. |
|
||||
| **Metis** | Plan gap analyzer | Claude Opus → opencode-go/glm-5 → K2P5 | Claude preferred. Uses opencode-go for reliable GLM-5 access. |
|
||||
|
||||
### Dual-Prompt Agents → Claude preferred, GPT supported
|
||||
|
||||
@@ -74,7 +74,7 @@ These agents ship separate prompts for Claude and GPT families. They auto-detect
|
||||
| Agent | Role | Fallback Chain | Notes |
|
||||
| -------------- | ----------------- | -------------------------------------- | -------------------------------------------------------------------- |
|
||||
| **Prometheus** | Strategic planner | Claude Opus → GPT-5.4 → opencode-go/glm-5 → Gemini 3.1 Pro | Interview-mode planning. GPT prompt is compact and principle-driven. |
|
||||
| **Atlas** | Todo orchestrator | Claude Sonnet → opencode-go/kimi-k2.5 → GPT-5.4 | Claude first, opencode-go as intermediate, GPT-5.4 as last resort. |
|
||||
| **Atlas** | Todo orchestrator | Claude Sonnet → opencode-go/kimi-k2.5 | Claude first, opencode-go as the current fallback path. |
|
||||
|
||||
### Deep Specialists → GPT
|
||||
|
||||
@@ -82,9 +82,9 @@ These agents are built for GPT's principle-driven style. Their prompts assume au
|
||||
|
||||
| Agent | Role | Fallback Chain | Notes |
|
||||
| -------------- | ----------------------- | -------------------------------------- | ------------------------------------------------ |
|
||||
| **Hephaestus** | Autonomous deep worker | GPT-5.3 Codex → GPT-5.4 (Copilot) | Requires GPT access. GPT-5.4 via Copilot as fallback. The craftsman. |
|
||||
| **Oracle** | Architecture consultant | GPT-5.4 → Gemini 3.1 Pro → Claude Opus → opencode-go/glm-5 | Read-only high-IQ consultation. |
|
||||
| **Momus** | Ruthless reviewer | GPT-5.4 → Claude Opus → Gemini 3.1 Pro → opencode-go/glm-5 | Verification and plan review. GPT-5.4 uses xhigh variant. |
|
||||
| **Hephaestus** | Autonomous deep worker | GPT-5.3 Codex only | No fallback. Requires GPT access. The craftsman. |
|
||||
| **Oracle** | Architecture consultant | GPT-5.4 → Gemini 3.1 Pro → Claude Opus | Read-only high-IQ consultation. |
|
||||
| **Momus** | Ruthless reviewer | GPT-5.4 → Claude Opus → Gemini 3.1 Pro | Verification and plan review. |
|
||||
|
||||
### Utility Runners → Speed over Intelligence
|
||||
|
||||
@@ -95,7 +95,6 @@ These agents do grep, search, and retrieval. They intentionally use the fastest,
|
||||
| **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. |
|
||||
|
||||
---
|
||||
|
||||
@@ -120,7 +119,8 @@ Principle-driven, explicit reasoning, deep technical capability. Best for agents
|
||||
| Model | Strengths |
|
||||
| ----------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| **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** | High intelligence, strategic reasoning. Default for Oracle. |
|
||||
| **GPT-5.4** | Strong principle-driven reasoning. Default for Momus and a key fallback for Prometheus / Atlas. |
|
||||
| **GPT-5-Nano** | Ultra-cheap, fast. Good for simple utility tasks. |
|
||||
|
||||
### Other Models
|
||||
@@ -166,14 +166,14 @@ When agents delegate work, they don't pick a model name — they pick a **catego
|
||||
|
||||
| Category | When Used | Fallback Chain |
|
||||
| -------------------- | -------------------------- | -------------------------------------------- |
|
||||
| `visual-engineering` | Frontend, UI, CSS, design | Gemini 3.1 Pro → GLM 5 → Claude Opus → opencode-go/glm-5 → K2P5 |
|
||||
| `ultrabrain` | Maximum reasoning needed | GPT-5.4 → Gemini 3.1 Pro → Claude Opus → opencode-go/glm-5 |
|
||||
| `visual-engineering` | Frontend, UI, CSS, design | Gemini 3.1 Pro → GLM 5 → Claude Opus |
|
||||
| `ultrabrain` | Maximum reasoning needed | GPT-5.4 → Gemini 3.1 Pro → Claude Opus |
|
||||
| `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 |
|
||||
| `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 |
|
||||
| `quick` | Simple, fast tasks | Claude Haiku → Gemini Flash → GPT-5-Nano |
|
||||
| `unspecified-high` | General complex work | Claude Opus → GPT-5.4 (high) → GLM 5 → K2P5 |
|
||||
| `unspecified-low` | General standard work | Claude Sonnet → GPT-5.3 Codex → Gemini Flash |
|
||||
| `writing` | Text, docs, prose | Gemini Flash → Claude Sonnet |
|
||||
|
||||
See the [Orchestration System Guide](./orchestration.md) for how agents dispatch tasks to categories.
|
||||
|
||||
@@ -185,7 +185,7 @@ See the [Orchestration System Guide](./orchestration.md) for how agents dispatch
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$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": {
|
||||
// Main orchestrator: Claude Opus or Kimi K2.5 work best
|
||||
|
||||
@@ -156,7 +156,7 @@ Read the [opencode-antigravity-auth documentation](https://github.com/NoeFabris/
|
||||
|
||||
##### oh-my-openagent Agent Model Override
|
||||
|
||||
The `opencode-antigravity-auth` plugin uses different model names than the built-in Google auth. Override the agent models in `oh-my-openagent.json` (or `.opencode/oh-my-openagent.json`):
|
||||
The `opencode-antigravity-auth` plugin uses different model names than the built-in Google auth. Override the agent models in `oh-my-opencode.json` (or `.opencode/oh-my-opencode.json`):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -344,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. |
|
||||
| **Multimodal Looker** | Vision/screenshots | Kimi K2.5 → Kimi Free → Gemini Flash → GPT-5.4 → GLM-4.6v | Kimi excels at multimodal understanding. |
|
||||
| **Librarian** | Docs/code search | MiniMax M2.5 → MiniMax Free → Haiku → Nano | Fast, cheap models for search. |
|
||||
| **Multimodal Looker** | Vision/screenshots | GPT-5.4 → Kimi K2.5 → GLM-4.6v → GPT-5-Nano | Strong vision capabilities. |
|
||||
|
||||
#### Why Different Models Need Different Prompts
|
||||
|
||||
@@ -364,7 +364,7 @@ This is why Prometheus and Atlas ship separate prompts per model family — they
|
||||
|
||||
#### Custom Model Configuration
|
||||
|
||||
If the user wants to override which model an agent uses, you can customize in `oh-my-openagent.json`:
|
||||
If the user wants to override which model an agent uses, you can customize in `oh-my-opencode.json`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
@@ -424,7 +424,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**.
|
||||
|
||||
---
|
||||
|
||||
@@ -475,7 +475,7 @@ Use the `ulw` keyword in Sisyphus when:
|
||||
|
||||
## Configuration
|
||||
|
||||
You can control related features in `oh-my-openagent.json`:
|
||||
You can control related features in `oh-my-opencode.json`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
||||
@@ -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. Haiku 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:**
|
||||
|
||||
@@ -60,10 +60,11 @@ User Request
|
||||
↓
|
||||
├─→ [Prometheus] — Strategic planning (interview mode)
|
||||
├─→ [Atlas] — Todo orchestration and execution
|
||||
├─→ [Oracle] — Architecture consultation
|
||||
├─→ [Librarian] — Documentation/code search
|
||||
├─→ [Explore] — Fast codebase grep
|
||||
└─→ [Category-based agents] — Specialized by task type
|
||||
├─→ [Specialist Subagents]
|
||||
│ ├─→ [Oracle] — Architecture consultation
|
||||
│ ├─→ [Librarian] — Documentation/code search
|
||||
│ └─→ [Explore] — Fast codebase grep
|
||||
└─→ [Sisyphus-Junior] — Category-based executor
|
||||
```
|
||||
|
||||
When Sisyphus delegates to a subagent, it doesn't pick a model name. It picks a **category** — `visual-engineering`, `ultrabrain`, `quick`, `deep`. The category automatically maps to the right model. You touch nothing.
|
||||
@@ -116,17 +117,20 @@ Atlas executes Prometheus plans. Distributes tasks to specialized subagents. Acc
|
||||
|
||||
Run `/start-work` to activate Atlas on your latest plan.
|
||||
|
||||
### Oracle: The Consultant
|
||||
### Sisyphus-Junior: The Specialist
|
||||
|
||||
Read-only high-IQ consultant for architecture decisions and complex debugging. Consult Oracle when facing unfamiliar patterns, security concerns, or multi-system tradeoffs.
|
||||
When Sisyphus delegates a task via a specific **Category** (like `visual-engineering` or `deep`), **Sisyphus-Junior** is the agent that performs it. It is optimized for focused execution within a specific domain and cannot re-delegate, preventing infinite loops.
|
||||
|
||||
### Supporting Cast
|
||||
### Specialist Subagents
|
||||
|
||||
These agents are primarily designed to be called by other agents or for specific queries, rather than managing a full workflow.
|
||||
|
||||
- **Oracle** — Read-only high-IQ consultant for architecture decisions and complex debugging.
|
||||
- **Librarian** — Documentation and OSS code search. Stays current on library APIs and best practices.
|
||||
- **Explore** — Fast codebase grep. Uses speed-focused models for pattern discovery.
|
||||
- **Multimodal Looker** — Vision and screenshot analysis.
|
||||
- **Metis** — Gap analyzer. Catches what Prometheus missed before plans are finalized.
|
||||
- **Momus** — Ruthless reviewer. Validates plans against clarity, verification, and context criteria.
|
||||
- **Explore** — Fast codebase grep. Uses speed-focused models for pattern discovery.
|
||||
- **Librarian** — Documentation and OSS code search. Stays current on library APIs and best practices.
|
||||
- **Multimodal Looker** — Vision and screenshot analysis.
|
||||
|
||||
---
|
||||
|
||||
@@ -154,7 +158,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
|
||||
|
||||
@@ -168,7 +172,7 @@ You can override specific agents or categories in your config:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$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": {
|
||||
// Main orchestrator: Claude Opus or Kimi K2.5 work best
|
||||
@@ -232,7 +236,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 +250,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 +260,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 |
|
||||
|---------|---------|
|
||||
|
||||
@@ -39,7 +39,7 @@ bunx oh-my-openagent install
|
||||
|
||||
1. **Provider Selection**: Choose your AI provider (Claude, ChatGPT, or Gemini)
|
||||
2. **API Key Input**: Enter the API key for your selected provider
|
||||
3. **Configuration File Creation**: Generates `opencode.json` or `oh-my-openagent.json` files
|
||||
3. **Configuration File Creation**: Generates `opencode.json` or `oh-my-opencode.json` files
|
||||
4. **Plugin Registration**: Automatically registers the oh-my-openagent plugin in OpenCode settings
|
||||
|
||||
### Options
|
||||
@@ -94,7 +94,7 @@ Installation
|
||||
✓ Plugin registered in opencode.json
|
||||
|
||||
Configuration
|
||||
✓ oh-my-openagent.json is valid
|
||||
✓ oh-my-opencode.json is valid
|
||||
⚠ categories.visual-engineering: using default model
|
||||
|
||||
Authentication
|
||||
@@ -178,8 +178,8 @@ Tokens are stored in `~/.config/opencode/mcp-oauth.json` with `0600` permissions
|
||||
|
||||
The CLI searches for configuration files in the following locations (in priority order):
|
||||
|
||||
1. **Project Level**: `.opencode/oh-my-openagent.json`
|
||||
2. **User Level**: `~/.config/opencode/oh-my-openagent.json`
|
||||
1. **Project Level**: `.opencode/oh-my-opencode.json`
|
||||
2. **User Level**: `~/.config/opencode/oh-my-opencode.json`
|
||||
|
||||
### JSONC Support
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Configuration Reference
|
||||
|
||||
Complete reference for `oh-my-openagent.jsonc` configuration. This document covers every available option with examples.
|
||||
Complete reference for `oh-my-opencode.jsonc` configuration. This document covers every available option with examples.
|
||||
|
||||
---
|
||||
|
||||
@@ -44,13 +44,13 @@ Complete reference for `oh-my-openagent.jsonc` configuration. This document cove
|
||||
|
||||
Priority order (project overrides user):
|
||||
|
||||
1. `.opencode/oh-my-openagent.jsonc` / `.opencode/oh-my-openagent.json`
|
||||
1. `.opencode/oh-my-opencode.jsonc` / `.opencode/oh-my-opencode.json`
|
||||
2. User config (`.jsonc` preferred over `.json`):
|
||||
|
||||
| Platform | Path |
|
||||
| ----------- | ----------------------------------------- |
|
||||
| macOS/Linux | `~/.config/opencode/oh-my-openagent.jsonc` |
|
||||
| Windows | `%APPDATA%\opencode\oh-my-openagent.jsonc` |
|
||||
| macOS/Linux | `~/.config/opencode/oh-my-opencode.jsonc` |
|
||||
| Windows | `%APPDATA%\opencode\oh-my-opencode.jsonc` |
|
||||
|
||||
JSONC supports `// line comments`, `/* block comments */`, and trailing commas.
|
||||
|
||||
@@ -58,7 +58,7 @@ Enable schema autocomplete:
|
||||
|
||||
```json
|
||||
{
|
||||
"$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"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -70,7 +70,7 @@ Here's a practical starting configuration:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$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": {
|
||||
// Main orchestrator: Claude Opus or Kimi K2.5 work best
|
||||
|
||||
@@ -4,31 +4,26 @@
|
||||
|
||||
Oh-My-OpenCode provides 11 specialized AI agents. Each has distinct expertise, optimized models, and tool permissions.
|
||||
|
||||
### Core Agents
|
||||
### Primary Agents
|
||||
|
||||
| Agent | Model | Purpose |
|
||||
| --------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **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`. |
|
||||
| **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`. |
|
||||
| **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: `kimi-k2.5` → `glm-5`. |
|
||||
| **Hephaestus** | `gpt-5.3-codex` | The Legitimate Craftsman. Autonomous deep worker. Goal-oriented execution with thorough research before action. Explores codebase patterns, completes tasks end-to-end. Fallback: `gpt-5.4` on GitHub Copilot. Requires a GPT-capable provider. |
|
||||
| **Prometheus** | `claude-opus-4-6` | Strategic planner with interview mode. Creates detailed work plans through iterative questioning. Fallback: `gpt-5.4` → `gemini-3.1-pro`. |
|
||||
| **Atlas** | `claude-sonnet-4-6`| Executor. Takes the plan from Prometheus and drives it to completion, managing the todo list and coordinating subagents. Fallback: `gpt-5.4` (medium). |
|
||||
| **Sisyphus-Junior** | _(category-dependent)_ | Category-spawned executor. Model is selected automatically based on the task category. Used when the main agent delegates work via the `task` tool. |
|
||||
|
||||
### Planning Agents
|
||||
### Specialist Subagents
|
||||
|
||||
| Agent | Model | Purpose |
|
||||
| -------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Prometheus** | `claude-opus-4-6` | Strategic planner with interview mode. Creates detailed work plans through iterative questioning. Fallback: `gpt-5.4` → `gemini-3.1-pro`. |
|
||||
| **Metis** | `claude-opus-4-6` | Plan consultant — pre-planning analysis. Identifies hidden intentions, ambiguities, and AI failure points. Fallback: `gpt-5.4` → `gemini-3.1-pro`. |
|
||||
| **Momus** | `gpt-5.4` | Plan reviewer — validates plans against clarity, verifiability, and completeness standards. Fallback: `claude-opus-4-6` → `gemini-3.1-pro`. |
|
||||
|
||||
### Orchestration Agents
|
||||
|
||||
| Agent | Model | Purpose |
|
||||
| ------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Atlas** | `claude-sonnet-4-6` | Todo-list orchestrator. Executes planned tasks systematically, managing todo items and coordinating work. Fallback: `gpt-5.4` (medium). |
|
||||
| **Sisyphus-Junior** | _(category-dependent)_ | Category-spawned executor. Model is selected automatically based on the task category (visual-engineering, quick, deep, etc.). Used when the main agent delegates work via the `task` tool. |
|
||||
| Agent | Model | Purpose |
|
||||
| --------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Oracle** | `gpt-5.4` | Architecture decisions, code review, debugging. Read-only consultation. Fallback: `gemini-3.1-pro` → `claude-opus-4-6`. |
|
||||
| **Librarian** | `minimax-m2.5` | Multi-repo analysis, documentation lookup, OSS implementation examples. Fallback: `minimax-m2.5-free` → `claude-haiku-4-5` → `gpt-5-nano`. |
|
||||
| **Explore** | `grok-code-fast-1` | Fast codebase exploration and contextual grep. Fallback: `minimax-m2.5` → `minimax-m2.5-free` → `claude-haiku-4-5`. |
|
||||
| **Multimodal-Looker** | `gpt-5.4` | Visual content specialist. Analyzes PDFs, images, diagrams. Fallback: `kimi-k2.5` → `glm-4.6v` → `gpt-5-nano`. |
|
||||
| **Metis** | `claude-opus-4-6` | Plan consultant — pre-planning analysis. Identifies hidden intentions, ambiguities, and AI failure points. Fallback: `gpt-5.4` → `gemini-3.1-pro`. |
|
||||
| **Momus** | `gpt-5.4` | Plan reviewer — validates plans against clarity, verifiability, and completeness standards. Fallback: `claude-opus-4-6` → `gemini-3.1-pro`. |
|
||||
|
||||
### Invoking Agents
|
||||
|
||||
@@ -90,7 +85,7 @@ When running inside tmux:
|
||||
- Each pane shows agent output live
|
||||
- Auto-cleanup when agents complete
|
||||
|
||||
Customize agent models, prompts, and permissions in `oh-my-openagent.json`.
|
||||
Customize agent models, prompts, and permissions in `oh-my-opencode.json`.
|
||||
|
||||
## Category System
|
||||
|
||||
@@ -129,7 +124,7 @@ task({
|
||||
|
||||
### Custom Categories
|
||||
|
||||
You can define custom categories in `oh-my-openagent.json`.
|
||||
You can define custom categories in `oh-my-opencode.json`.
|
||||
|
||||
#### Category Configuration Schema
|
||||
|
||||
@@ -558,7 +553,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**:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"oh-my-openagent": "bin/oh-my-openagent.js"
|
||||
"oh-my-openagent": "bin/oh-my-opencode.js"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -18,7 +18,7 @@
|
||||
"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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -2207,38 +2207,6 @@
|
||||
"created_at": "2026-03-16T04:55:10Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2604
|
||||
},
|
||||
{
|
||||
"name": "gxlife",
|
||||
"id": 110413359,
|
||||
"comment_id": 4068427047,
|
||||
"created_at": "2026-03-16T15:17:01Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2625
|
||||
},
|
||||
{
|
||||
"name": "HaD0Yun",
|
||||
"id": 102889891,
|
||||
"comment_id": 4073195308,
|
||||
"created_at": "2026-03-17T08:27:45Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2640
|
||||
},
|
||||
{
|
||||
"name": "tad-hq",
|
||||
"id": 213478119,
|
||||
"comment_id": 4077697128,
|
||||
"created_at": "2026-03-17T20:07:09Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2655
|
||||
},
|
||||
{
|
||||
"name": "ogormans-deptstack",
|
||||
"id": 208788555,
|
||||
"comment_id": 4077893096,
|
||||
"created_at": "2026-03-17T20:42:42Z",
|
||||
"repoId": 1108837393,
|
||||
"pullRequestNo": 2656
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -10,7 +10,7 @@ Entry point `index.ts` orchestrates 5-step initialization: loadConfig → create
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `index.ts` | Plugin entry, exports `OhMyOpenCodePlugin` |
|
||||
| `index.ts` | Plugin entry, exports `OhMyOpenAgentPlugin` |
|
||||
| `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) |
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,32 +1,20 @@
|
||||
import { afterAll, beforeAll, describe, expect, mock, test } from "bun:test"
|
||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test"
|
||||
import { mkdirSync, rmSync, writeFileSync } from "node:fs"
|
||||
import * as os from "node:os"
|
||||
import { tmpdir } from "node:os"
|
||||
import { homedir, tmpdir } from "node:os"
|
||||
import { join } from "node:path"
|
||||
|
||||
const originalHomedir = os.homedir.bind(os)
|
||||
let mockedHomeDir = ""
|
||||
let moduleImportCounter = 0
|
||||
let resolvePromptAppend: typeof import("./resolve-file-uri").resolvePromptAppend
|
||||
|
||||
mock.module("node:os", () => ({
|
||||
...os,
|
||||
homedir: () => mockedHomeDir || originalHomedir(),
|
||||
}))
|
||||
import { resolvePromptAppend } from "./resolve-file-uri"
|
||||
|
||||
describe("resolvePromptAppend", () => {
|
||||
const fixtureRoot = join(tmpdir(), `resolve-file-uri-${Date.now()}`)
|
||||
const configDir = join(fixtureRoot, "config")
|
||||
const homeFixtureRoot = join(fixtureRoot, "home")
|
||||
const homeFixtureDir = join(homeFixtureRoot, "fixture-home")
|
||||
const homeFixtureDir = join(homedir(), `.resolve-file-uri-home-${Date.now()}`)
|
||||
|
||||
const absoluteFilePath = join(fixtureRoot, "absolute.txt")
|
||||
const relativeFilePath = join(configDir, "relative.txt")
|
||||
const spacedFilePath = join(fixtureRoot, "with space.txt")
|
||||
const homeFilePath = join(homeFixtureDir, "home.txt")
|
||||
|
||||
beforeAll(async () => {
|
||||
mockedHomeDir = homeFixtureRoot
|
||||
beforeAll(() => {
|
||||
mkdirSync(fixtureRoot, { recursive: true })
|
||||
mkdirSync(configDir, { recursive: true })
|
||||
mkdirSync(homeFixtureDir, { recursive: true })
|
||||
@@ -35,14 +23,11 @@ describe("resolvePromptAppend", () => {
|
||||
writeFileSync(relativeFilePath, "relative-content", "utf8")
|
||||
writeFileSync(spacedFilePath, "encoded-content", "utf8")
|
||||
writeFileSync(homeFilePath, "home-content", "utf8")
|
||||
|
||||
moduleImportCounter += 1
|
||||
;({ resolvePromptAppend } = await import(`./resolve-file-uri?test=${moduleImportCounter}`))
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
rmSync(fixtureRoot, { recursive: true, force: true })
|
||||
mock.restore()
|
||||
rmSync(homeFixtureDir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
test("returns non-file URI strings unchanged", () => {
|
||||
@@ -80,7 +65,7 @@ describe("resolvePromptAppend", () => {
|
||||
|
||||
test("resolves home directory URI path", () => {
|
||||
//#given
|
||||
const input = "file://~/fixture-home/home.txt"
|
||||
const input = `file://~/${homeFixtureDir.split("/").pop()}/home.txt`
|
||||
|
||||
//#when
|
||||
const resolved = resolvePromptAppend(input)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -527,7 +527,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,
|
||||
|
||||
@@ -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.**
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -2,63 +2,63 @@
|
||||
|
||||
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",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"explore": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"hephaestus": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"librarian": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"metis": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"momus": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"prometheus": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
},
|
||||
"categories": {
|
||||
"artistry": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"deep": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"quick": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"writing": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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",
|
||||
@@ -83,7 +83,7 @@ exports[`generateModelConfig single native provider uses Claude models when only
|
||||
"variant": "max",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "anthropic/claude-opus-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",
|
||||
@@ -145,7 +145,7 @@ exports[`generateModelConfig single native provider uses Claude models with isMa
|
||||
"variant": "max",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "anthropic/claude-opus-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",
|
||||
@@ -277,7 +277,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",
|
||||
@@ -363,23 +363,23 @@ 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",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"explore": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
},
|
||||
"metis": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"momus": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
"variant": "high",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
@@ -389,7 +389,7 @@ exports[`generateModelConfig single native provider uses Gemini models when only
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
},
|
||||
"categories": {
|
||||
@@ -423,23 +423,23 @@ 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",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"explore": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
},
|
||||
"metis": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"momus": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
"variant": "high",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
@@ -449,7 +449,7 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
},
|
||||
"categories": {
|
||||
@@ -465,7 +465,7 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa
|
||||
"variant": "high",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "google/gemini-3-flash-preview",
|
||||
@@ -483,7 +483,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",
|
||||
@@ -558,7 +558,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",
|
||||
@@ -634,7 +634,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",
|
||||
@@ -709,7 +709,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",
|
||||
@@ -785,7 +785,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",
|
||||
@@ -855,7 +855,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",
|
||||
@@ -926,10 +926,10 @@ 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",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"explore": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
@@ -938,45 +938,45 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian whe
|
||||
"model": "zai-coding-plan/glm-4.7",
|
||||
},
|
||||
"metis": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"momus": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "zai-coding-plan/glm-4.6v",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"prometheus": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"sisyphus": {
|
||||
"model": "zai-coding-plan/glm-5",
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
},
|
||||
"categories": {
|
||||
"quick": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "zai-coding-plan/glm-5",
|
||||
},
|
||||
"writing": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -984,10 +984,10 @@ 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",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"explore": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
@@ -996,45 +996,45 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian wit
|
||||
"model": "zai-coding-plan/glm-4.7",
|
||||
},
|
||||
"metis": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"momus": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "zai-coding-plan/glm-4.6v",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"prometheus": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"sisyphus": {
|
||||
"model": "zai-coding-plan/glm-5",
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
},
|
||||
"categories": {
|
||||
"quick": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "zai-coding-plan/glm-5",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "zai-coding-plan/glm-5",
|
||||
},
|
||||
"writing": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1042,7 +1042,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",
|
||||
@@ -1117,7 +1117,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",
|
||||
@@ -1192,7 +1192,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 +1256,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",
|
||||
@@ -1273,7 +1273,7 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi
|
||||
"variant": "max",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "opencode/gpt-5-nano",
|
||||
"model": "opencode/glm-4.7-free",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
@@ -1322,7 +1322,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",
|
||||
@@ -1400,7 +1400,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",
|
||||
@@ -1478,7 +1478,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",
|
||||
|
||||
@@ -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}`)
|
||||
|
||||
@@ -15,14 +15,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,9 +35,9 @@ 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)
|
||||
@@ -82,20 +82,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 +134,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 +155,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"
|
||||
@@ -180,7 +180,7 @@ 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()
|
||||
})
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `add-plugin-to-opencode-config.ts` | Register `oh-my-opencode` in `.opencode/opencode.json` plugin array |
|
||||
| `add-plugin-to-opencode-config.ts` | Register `oh-my-openagent` in `.opencode/opencode.json` plugin array |
|
||||
| `add-provider-config.ts` | Add provider API key to OpenCode config (user-level) |
|
||||
| `antigravity-provider-configuration.ts` | Handle Antigravity provider setup (special case) |
|
||||
| `auth-plugins.ts` | Detect auth plugin requirements per provider (oauth vs key) |
|
||||
@@ -26,7 +26,7 @@
|
||||
| `opencode-binary.ts` | Detect OpenCode binary location, verify it's installed |
|
||||
| `opencode-config-format.ts` | OpenCode config format constants and type guards |
|
||||
| `parse-opencode-config-file.ts` | Parse opencode.json/opencode.jsonc with fallback |
|
||||
| `plugin-name-with-version.ts` | Resolve `oh-my-opencode@X.Y.Z` for installation |
|
||||
| `plugin-name-with-version.ts` | Resolve `oh-my-openagent@X.Y.Z` for installation |
|
||||
| `write-omo-config.ts` | Write generated config to `.opencode/oh-my-opencode.jsonc` |
|
||||
|
||||
## USAGE PATTERN
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
import { readFileSync, writeFileSync } from "node:fs"
|
||||
import { LEGACY_PLUGIN_NAME, PLUGIN_NAME } from "../../shared"
|
||||
import type { ConfigMergeResult } from "../types"
|
||||
import { getConfigDir } from "./config-context"
|
||||
import { ensureConfigDirectoryExists } from "./ensure-config-directory-exists"
|
||||
@@ -8,16 +7,16 @@ 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
|
||||
const PACKAGE_NAME = "oh-my-opencode"
|
||||
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,20 +41,13 @@ export async function addPluginToOpenCodeConfig(currentVersion: string): Promise
|
||||
|
||||
const config = parseResult.config
|
||||
const plugins = config.plugin ?? []
|
||||
const currentNameIndex = plugins.findIndex(
|
||||
(plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`)
|
||||
)
|
||||
const legacyNameIndex = plugins.findIndex(
|
||||
(plugin) => plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`)
|
||||
)
|
||||
const existingIndex = plugins.findIndex((plugin) => plugin === PACKAGE_NAME || plugin.startsWith(`${PACKAGE_NAME}@`))
|
||||
|
||||
if (currentNameIndex !== -1) {
|
||||
if (plugins[currentNameIndex] === pluginEntry) {
|
||||
if (existingIndex !== -1) {
|
||||
if (plugins[existingIndex] === pluginEntry) {
|
||||
return { success: true, configPath: path }
|
||||
}
|
||||
plugins[currentNameIndex] = pluginEntry
|
||||
} else if (legacyNameIndex !== -1) {
|
||||
plugins[legacyNameIndex] = pluginEntry
|
||||
plugins[existingIndex] = pluginEntry
|
||||
} else {
|
||||
plugins.push(pluginEntry)
|
||||
}
|
||||
@@ -68,7 +60,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 +72,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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ type BunInstallOutputMode = "inherit" | "pipe"
|
||||
|
||||
interface RunBunInstallOptions {
|
||||
outputMode?: BunInstallOutputMode
|
||||
/** Workspace directory to install to. Defaults to cache dir if not provided. */
|
||||
workspaceDir?: string
|
||||
}
|
||||
|
||||
interface BunInstallOutput {
|
||||
@@ -67,7 +65,7 @@ function logCapturedOutputOnFailure(outputMode: BunInstallOutputMode, output: Bu
|
||||
|
||||
export async function runBunInstallWithDetails(options?: RunBunInstallOptions): Promise<BunInstallResult> {
|
||||
const outputMode = options?.outputMode ?? "pipe"
|
||||
const cacheDir = options?.workspaceDir ?? getOpenCodeCacheDir()
|
||||
const cacheDir = getOpenCodeCacheDir()
|
||||
const packageJsonPath = `${cacheDir}/package.json`
|
||||
|
||||
if (!existsSync(packageJsonPath)) {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,5 @@
|
||||
import { existsSync, readFileSync } from "node:fs"
|
||||
import { parseJsonc, LEGACY_PLUGIN_NAME, PLUGIN_NAME } from "../../shared"
|
||||
import { parseJsonc } from "../../shared"
|
||||
import type { DetectedConfig } from "../types"
|
||||
import { getOmoConfigPath } from "./config-context"
|
||||
import { detectConfigFormat } from "./opencode-config-format"
|
||||
@@ -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 {
|
||||
@@ -55,16 +55,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}@`)
|
||||
)
|
||||
}
|
||||
|
||||
export function detectCurrentConfig(): DetectedConfig {
|
||||
const PACKAGE_NAME = "oh-my-opencode"
|
||||
const result: DetectedConfig = {
|
||||
isInstalled: false,
|
||||
hasClaude: true,
|
||||
@@ -90,7 +82,7 @@ export function detectCurrentConfig(): DetectedConfig {
|
||||
|
||||
const openCodeConfig = parseResult.config
|
||||
const plugins = openCodeConfig.plugin ?? []
|
||||
result.isInstalled = plugins.some(isOurPlugin)
|
||||
result.isInstalled = plugins.some((plugin) => plugin.startsWith(PACKAGE_NAME))
|
||||
|
||||
if (!result.isInstalled) {
|
||||
return result
|
||||
|
||||
@@ -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")
|
||||
@@ -88,21 +64,9 @@ describe("detectCurrentConfig - single package detection", () => {
|
||||
expect(result.isInstalled).toBe(false)
|
||||
})
|
||||
|
||||
it("returns false when plugin not present (even with similar name)", () => {
|
||||
// given
|
||||
const config = { plugin: ["oh-my-openagent-extra"] }
|
||||
writeFileSync(testConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
||||
|
||||
// when
|
||||
const result = detectCurrentConfig()
|
||||
|
||||
// then
|
||||
expect(result.isInstalled).toBe(false)
|
||||
})
|
||||
|
||||
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 +101,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 +112,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")
|
||||
@@ -193,9 +126,8 @@ describe("addPluginToOpenCodeConfig - single package writes", () => {
|
||||
// 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-opencode@3.10.0")
|
||||
})
|
||||
|
||||
it("adds new plugin when none exists", async () => {
|
||||
@@ -209,7 +141,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 +155,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) {
|
||||
|
||||
@@ -34,7 +34,7 @@ describe("writeOmoConfig", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
testConfigDir = join(tmpdir(), `omo-write-config-${Date.now()}-${Math.random().toString(36).slice(2)}`)
|
||||
testConfigPath = join(testConfigDir, "oh-my-openagent.json")
|
||||
testConfigPath = join(testConfigDir, "oh-my-opencode.json")
|
||||
|
||||
mkdirSync(testConfigDir, { recursive: true })
|
||||
process.env.OPENCODE_CONFIG_DIR = testConfigDir
|
||||
|
||||
@@ -61,7 +61,7 @@ export function writeOmoConfig(installConfig: InstallConfig): ConfigMergeResult
|
||||
return {
|
||||
success: false,
|
||||
configPath: omoConfigPath,
|
||||
error: formatErrorWithSuggestion(err, "write oh-my-openagent config")
|
||||
error: formatErrorWithSuggestion(err, "write oh-my-opencode config"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user