Skip to content

Commit ed874bc

Browse files
authored
Merge pull request #6 from otto-assistant/feat/unmerged-consolidate-36eb
feat: consolidate unmerged docs, CI, tests, and dynamic proxy port
2 parents 611fb87 + 5373a1e commit ed874bc

11 files changed

Lines changed: 1359 additions & 67 deletions

File tree

.github/workflows/release.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ jobs:
5050
run: |
5151
set -euo pipefail
5252
if [[ -n "$INPUT_VERSION" ]]; then
53+
# Validate semver
5354
if ! echo "$INPUT_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
5455
echo "Error: version must be in semver format X.Y.Z"
5556
exit 1
@@ -65,6 +66,12 @@ jobs:
6566
esac
6667
fi
6768
69+
- name: Show version info
70+
run: |
71+
echo "Current version: ${{ steps.current_version.outputs.version }}"
72+
echo "New version: ${{ steps.version.outputs.version }}"
73+
echo "Dry run: ${{ github.event.inputs.dry_run == 'true' && 'yes' || 'no' }}"
74+
6875
- name: Update package.json version
6976
run: |
7077
node -e "
@@ -121,3 +128,59 @@ jobs:
121128
name: v${{ steps.version.outputs.version }}
122129
env:
123130
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
131+
132+
- name: Send Discord notification
133+
if: ${{ github.event.inputs.dry_run != 'true' }}
134+
env:
135+
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
136+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137+
VERSION: ${{ steps.version.outputs.version }}
138+
REPOSITORY: ${{ github.repository }}
139+
run: |
140+
if [ -z "$DISCORD_WEBHOOK_URL" ]; then
141+
echo "DISCORD_WEBHOOK_URL not set; skipping Discord notification."
142+
exit 0
143+
fi
144+
node - <<'NODE'
145+
(async () => {
146+
const tag = `v${process.env.VERSION}`;
147+
const repo = process.env.REPOSITORY;
148+
const releaseRes = await fetch(`https://api.github.com/repos/${repo}/releases/tags/${tag}`, {
149+
headers: {
150+
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
151+
Accept: 'application/vnd.github+json',
152+
},
153+
});
154+
if (!releaseRes.ok) {
155+
const body = await releaseRes.text();
156+
throw new Error(`Failed to fetch release ${tag}: ${releaseRes.status} ${body}`);
157+
}
158+
const release = await releaseRes.json();
159+
const description = (release.body || `opencode-commandcode ${tag} released.`).slice(0, 4096);
160+
const payload = {
161+
username: 'opencode-commandcode Releases',
162+
embeds: [
163+
{
164+
title: release.name || `opencode-commandcode ${tag}`,
165+
url: release.html_url,
166+
description,
167+
color: 8244896,
168+
footer: { text: 'opencode-commandcode Changelog' },
169+
},
170+
],
171+
};
172+
const discordRes = await fetch(process.env.DISCORD_WEBHOOK_URL, {
173+
method: 'POST',
174+
headers: { 'content-type': 'application/json' },
175+
body: JSON.stringify(payload),
176+
});
177+
if (!discordRes.ok) {
178+
const body = await discordRes.text();
179+
throw new Error(`Failed to send Discord notification: ${discordRes.status} ${body}`);
180+
}
181+
console.log('Discord notification sent successfully');
182+
})().catch((error) => {
183+
console.error(error);
184+
process.exit(1);
185+
});
186+
NODE

README.md

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,25 @@
44

55
<p align="center">
66
<a href="https://www.npmjs.com/package/@otto-assistant/opencode-commandcode"><img src="https://img.shields.io/npm/v/%40otto-assistant%2Fopencode-commandcode?style=flat-square&color=7dcea0&labelColor=0c1412&label=npm" alt="npm version"></a>
7+
<a href="https://www.npmjs.com/package/@otto-assistant/opencode-commandcode"><img src="https://img.shields.io/npm/dm/%40otto-assistant%2Fopencode-commandcode?style=flat-square&color=7dcea0&labelColor=0c1412" alt="npm downloads"></a>
78
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-7dcea0?style=flat-square&labelColor=0c1412" alt="MIT license"></a>
89
<img src="https://img.shields.io/badge/linux%20·%20macos%20·%20windows-7dcea0?style=flat-square&labelColor=0c1412" alt="linux, macos, windows">
10+
<a href="https://github.com/otto-assistant/opencode-commandcode/releases"><img src="https://img.shields.io/github/v/release/otto-assistant/opencode-commandcode?style=flat-square&color=e8b86d&labelColor=0c1412&label=release" alt="latest release"></a>
911
</p>
1012

1113
<p align="center">
1214
<strong>Command Code inside OpenCode</strong> — Go-plan ($1) browser login,<br>
1315
gateway proxy, free Laguna S 2.1, tools/MCP, attachments, compact, usage.
1416
</p>
1517

18+
<p align="center">
19+
<a href="#install">Install</a> ·
20+
<a href="#authenticate">Authenticate</a> ·
21+
<a href="#why-this-plugin">Why this plugin</a> ·
22+
<a href="#architecture">Architecture</a> ·
23+
<a href="CHANGELOG.md">Changelog</a>
24+
</p>
25+
1626
---
1727

1828
Run [Command Code](https://commandcode.ai) models from OpenCode by proxying the same gateway that `npm i -g command-code@latest` uses (`POST /alpha/generate`). Default and exclusive live-test target: **Laguna S 2.1 free** (`poolside/laguna-s-2.1-free`, 256k context, $0).
@@ -21,15 +31,18 @@ Plugin shape mirrors [@otto-assistant/opencode-claude](https://github.com/otto-a
2131

2232
## Install
2333

34+
`command-code` is **not** a built-in OpenCode provider. Install the plugin first, or
35+
`opencode auth login --provider command-code` fails with `Unknown provider "command-code"`.
36+
2437
```bash
2538
# global (recommended)
2639
opencode plugin @otto-assistant/opencode-commandcode -g
2740

28-
# or project-local
41+
# or project-local (writes .opencode/opencode.json)
2942
opencode plugin @otto-assistant/opencode-commandcode
3043
```
3144

32-
Optional provider naming:
45+
Optional provider naming (also seeded when the plugin loads):
3346

3447
```jsonc
3548
{
@@ -41,7 +54,7 @@ Optional provider naming:
4154
}
4255
```
4356

44-
From source:
57+
Or build from source:
4558

4659
```bash
4760
git clone https://github.com/otto-assistant/opencode-commandcode.git
@@ -52,17 +65,21 @@ opencode plugin file://$PWD
5265

5366
## Authenticate
5467

55-
Uses the **Command Code Go plan ($1/mo)** — same browser login as `cmd login`. No Studio API key.
68+
Requires the plugin to be installed (see above). Uses the **Command Code Go plan ($1/mo)** — same browser login as `cmd login`. No Studio API key.
5669

5770
```bash
71+
# Option A — sync from Command Code CLI (recommended)
5872
npm i -g command-code@latest
5973
cmd login # browser → Studio CLI auth (Go plan). Laguna S 2.1 is $0 credits.
74+
opencode auth login --provider command-code
75+
# pick "Use existing cmd login session"
6076

77+
# Option B — browser OAuth (Go $1)
6178
opencode auth login --provider command-code
62-
# pick "Login with Command Code (Go $1)" — or "Use existing cmd login session"
79+
# pick "Login with Command Code (Go $1)"
6380
```
6481

65-
Then:
82+
Then start OpenCode, pick provider **command-code**, and choose Laguna S 2.1 free:
6683

6784
```bash
6885
opencode run "Summarise this repository in five bullets." --model command-code/laguna-s-2.1-free
@@ -74,28 +91,32 @@ Laguna S 2.1 free requires an active Go (or higher) account with credits on file
7491

7592
| | |
7693
|---|---|
77-
| **Gateway proxy** | Talks to `api.commandcode.ai/alpha/generate` — same transport as the `cmd` CLI. |
78-
| **Laguna S 2.1 free** | 256k context, reasoning, $0 while the deal lasts. |
79-
| **Go-plan auth** | Browser OAuth like `cmd login` ($1/mo). Syncs `~/.commandcode/auth.json`. No API key. |
94+
| **Gateway proxy** | Talks to `api.commandcode.ai/alpha/generate` — same transport as the `cmd` CLI (`mode=agent`). |
95+
| **Laguna S 2.1 free** | 256k context, reasoning, $0 while the deal lasts. Default aliases resolve here. |
96+
| **Go-plan auth** | Browser OAuth like `cmd login` ($1/mo). Syncs `~/.commandcode/auth.json`. No Studio API key. |
8097
| **Agent-grade tools** | OpenCode tool calls park and resume; MCP-prefixed tools are tracked separately. |
8198
| **Attachments** | Images, PDFs, text/binary files from OpenCode. Text-only models get image placeholders (Command Code behavior). |
82-
| **Compact** | Context-fraction tips + tiered client compact before the 256k window overflows. |
99+
| **Auto-compact** | Context-fraction tips + tiered client compact before the 256k window overflows. |
83100
| **Usage** | Per-turn and session totals via SSE `usage` + `GET /v1/usage`. |
84101

85102
## Architecture
86103

87104
```text
88105
OpenCode
89106
└─ /v1/chat/completions
90-
└─ Bun.serve proxy (port 8797)
107+
└─ Bun.serve proxy (dynamic port, prefer 8797)
91108
└─ POST https://api.commandcode.ai/alpha/generate
92109
└─ poolside/laguna-s-2.1-free (default)
93110
```
94111

112+
Model catalog: aliases `laguna-s-2.1-free` / `laguna` / `default` (and siblings) map to
113+
`poolside/laguna-s-2.1-free`. Auth credentials are mirrored between OpenCode `auth.json`
114+
and `~/.commandcode/auth.json`.
115+
95116
## Requirements
96117

97118
- [OpenCode](https://opencode.ai)
98-
- [Command Code CLI](https://www.npmjs.com/package/command-code) (`npm i -g command-code@latest`) and a free account
119+
- [Command Code CLI](https://www.npmjs.com/package/command-code) (`npm i -g command-code@latest`) and a Go-plan account
99120
- Bun (plugin runtime) · Node.js ≥ 18 (CLI needs ≥ 22)
100121

101122
## Development
@@ -107,13 +128,45 @@ bun run test # mocked gateway — attachments, tools, compact, usage
107128
bun run test:live # live Laguna S 2.1 (needs `cmd login` / Go plan session)
108129
```
109130

110-
Debug: `OPENCODE_COMMANDCODE_DEBUG=1`.
131+
Debug logging: `OPENCODE_COMMANDCODE_DEBUG=1`.
111132

112133
Optional knobs:
113134

114-
- `OPENCODE_COMMANDCODE_PROXY_PORT` — fixed local proxy port (default `8797`)
135+
- `OPENCODE_COMMANDCODE_PROXY_PORT`pin a fixed local proxy port (otherwise dynamic: prefer `8797`, then scan upward / ephemeral)
115136
- `OPENCODE_COMMANDCODE_CWD` — working directory reported to the gateway
116-
- `COMMANDCODE_API_URL` — override API base (default `https://api.commandcode.ai`)
137+
- `COMMANDCODE_API_URL` / `OPENCODE_COMMANDCODE_API_URL` — override API base (default `https://api.commandcode.ai`)
138+
139+
## Release
140+
141+
Publish via GitHub Actions → **Actions → Release → Run workflow**:
142+
143+
| Input | Purpose |
144+
|---|---|
145+
| `version` | Explicit semver (`0.2.0`). Empty → use bump |
146+
| `bump` | `minor` (default) / `patch` / `major` |
147+
| `dry_run` | Skip npm publish; create a draft GitHub release |
148+
149+
Requires repo secrets: `NPM_TOKEN`, optional `DISCORD_WEBHOOK_URL`.
150+
151+
Local pin refresh after a release:
152+
153+
```bash
154+
./scripts/update-plugin.sh
155+
```
156+
157+
## FAQ
158+
159+
**Do I need a Studio API key?**
160+
No. Use Go-plan browser login (or sync from `cmd login`).
161+
162+
**Is Laguna free?**
163+
Yes — `poolside/laguna-s-2.1-free` is the default free model ($0 while the deal lasts).
164+
165+
**Why isn’t Command Code listed without the plugin?**
166+
OpenCode doesn’t ship Command Code as a built-in provider; this plugin registers it.
167+
168+
**Where are releases?**
169+
[GitHub Releases](https://github.com/otto-assistant/opencode-commandcode/releases) · [npm](https://www.npmjs.com/package/@otto-assistant/opencode-commandcode) · [Changelog](CHANGELOG.md)
117170

118171
## License
119172

docs/header.svg

Lines changed: 80 additions & 9 deletions
Loading

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"build": "tsc -p tsconfig.json",
2323
"test": "bun test/smoke.ts",
2424
"test:live": "bun test/live-laguna.ts",
25+
"test:live:matrix": "bun test/live-matrix.ts",
26+
"test:opencode": "bash test/opencode-e2e.sh",
2527
"prepublishOnly": "npm run build"
2628
},
2729
"repository": {

0 commit comments

Comments
 (0)