Skip to content

Commit cd9c0a3

Browse files
committed
Merge branch 'flex' of personal:flexion/opencode into fix/bedrock-pdf-support
2 parents 606576a + c99a0a2 commit cd9c0a3

14 files changed

Lines changed: 600 additions & 45 deletions

File tree

.github/actions/setup-bun/action.yml

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,37 @@ description: "Setup Bun with caching and install dependencies"
33
runs:
44
using: "composite"
55
steps:
6-
- name: Get baseline download URL
6+
- name: Ensure build tools are available
7+
if: runner.os == 'Linux'
8+
shell: bash
9+
# Blacksmith's ARM64 ubuntu-2404 runners ship a minimal image that is missing:
10+
# unzip — needed by oven-sh/setup-bun to extract the downloaded bun zip
11+
# build-essential (make, g++) — needed by node-gyp to compile native addons
12+
# (e.g. tree-sitter-powershell) during `bun install`
13+
run: |
14+
PKGS=()
15+
command -v unzip >/dev/null 2>&1 || PKGS+=(unzip)
16+
command -v make >/dev/null 2>&1 || PKGS+=(build-essential)
17+
[ ${#PKGS[@]} -gt 0 ] && sudo apt-get install -y --no-install-recommends "${PKGS[@]}"
18+
true
19+
20+
- name: Get bun download URL
721
id: bun-url
822
shell: bash
923
run: |
10-
if [ "$RUNNER_ARCH" = "X64" ]; then
11-
V=$(node -p "require('./package.json').packageManager.split('@')[1]")
12-
case "$RUNNER_OS" in
13-
macOS) OS=darwin ;;
14-
Linux) OS=linux ;;
15-
Windows) OS=windows ;;
16-
esac
17-
echo "url=https://github.com/oven-sh/bun/releases/download/bun-v${V}/bun-${OS}-x64-baseline.zip" >> "$GITHUB_OUTPUT"
18-
fi
24+
V=$(node -p "require('./package.json').packageManager.split('@')[1]")
25+
case "$RUNNER_OS" in
26+
macOS) OS=darwin ;;
27+
Linux) OS=linux ;;
28+
Windows) OS=windows ;;
29+
*) exit 0 ;;
30+
esac
31+
case "$RUNNER_ARCH" in
32+
X64) ARCH=x64-baseline ;;
33+
ARM64) ARCH=aarch64 ;;
34+
*) exit 0 ;;
35+
esac
36+
echo "url=https://github.com/oven-sh/bun/releases/download/bun-v${V}/bun-${OS}-${ARCH}.zip" >> "$GITHUB_OUTPUT"
1937
2038
- name: Setup Bun
2139
uses: oven-sh/setup-bun@v2

.github/workflows/test.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,24 @@ jobs:
6363
turbo-${{ runner.os }}-${{ hashFiles('turbo.json', '**/package.json') }}-
6464
turbo-${{ runner.os }}-
6565
66+
- name: Cache npm registry packages
67+
# Plugin integration tests install @opencode-ai/plugin into fresh temp dirs
68+
# using @npmcli/arborist, which fetches from the npm registry and caches
69+
# tarballs in ~/.npm. Without this cache, each test does a full network
70+
# download, easily hitting the 30 s bun test timeout on Blacksmith ARM64.
71+
uses: actions/cache@v4
72+
with:
73+
path: ~/.npm
74+
key: npm-${{ runner.os }}-${{ runner.arch }}-opencode-ai-plugin-${{ hashFiles('**/package.json') }}
75+
restore-keys: |
76+
npm-${{ runner.os }}-${{ runner.arch }}-opencode-ai-plugin-
77+
78+
- name: Warm npm cache for @opencode-ai/plugin
79+
# Pre-populate ~/.npm so arborist can satisfy @opencode-ai/plugin from
80+
# cache during plugin integration tests instead of hitting the registry.
81+
if: runner.os == 'Linux'
82+
run: npm install --prefix /tmp/plugin-warmup @opencode-ai/plugin
83+
6684
- name: Run unit tests
6785
run: bun turbo test:ci
6886
env:

.husky/pre-push

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#!/bin/sh
22
set -e
3+
4+
# Run prek hooks (if installed)
5+
if command -v prek >/dev/null 2>&1; then
6+
prek run --stage pre-push
7+
fi
8+
39
# Check if bun version matches package.json
410
# keep in sync with packages/script/src/index.ts semver qualifier
511
bun -e '
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Session: Bolster Install — Blacksmith ARM64 CI Fixes
2+
3+
**Branch**: chore/bolster-install
4+
**Issue**: N/A
5+
**Created**: 2026-04-22
6+
**Status**: complete — PR #11 open, awaiting merge
7+
8+
## Goal
9+
Harden the `install-flex` automated installer and fix all Blacksmith ARM64 CI
10+
failures that were blocking the unit and e2e test jobs on the Flexion fork.
11+
12+
## Approach
13+
Fix issues in layers as they surfaced during CI runs:
14+
1. Add `install-flex` installer script
15+
2. Pin `OPENCODE_CHANNEL=flex` to prevent per-branch SQLite DB fragmentation
16+
3. Fix missing build tools on Blacksmith ARM64 runners
17+
4. Fix unit test timeouts caused by arborist npm installs during tests
18+
5. Bump individual test timeouts that are tight on ARM64
19+
20+
## Session Log
21+
- 2026-04-22: Session created
22+
- 2026-04-22: Added `install-flex` script (already existed on branch), fixed DB fragmentation
23+
- 2026-04-22: CI round 1 — fixed `unzip` missing (setup-bun)
24+
- 2026-04-22: CI round 2 — fixed `make`/`g++` missing (build-essential for node-gyp)
25+
- 2026-04-22: CI round 3 — 7 test timeouts; root-caused to `@npmcli/arborist.reify()` in tests
26+
- 2026-04-22: CI round 4 — 1 remaining timeout; fixed shell-loop test 3s → 15s
27+
- 2026-04-22: All CI jobs passing. PR updated.
28+
- 2026-04-22: CI round 5 — 1 new timeout; "shell rejects with BusyError when loop running" 3s → 15s
29+
30+
## Key Decisions
31+
32+
### `OPENCODE_CHANNEL=flex` in `install-flex`
33+
OpenCode bakes `InstallationChannel` from the git branch at build time and uses it
34+
as the SQLite DB name suffix (`opencode-<channel>.db`). Without pinning, each
35+
rebuild from a different branch creates a fresh empty database, losing all session
36+
history. Pinning to `"flex"` ensures all Flexion builds share `opencode-flex.db`.
37+
See: `packages/opencode/src/storage/db.ts:getChannelPath()`.
38+
39+
### `OPENCODE_DISABLE_PLUGIN_DEPS_INSTALL` flag
40+
`config.ts` fires a background `@npmcli/arborist.reify()` for `@opencode-ai/plugin`
41+
in every `.opencode/` directory it discovers. In tests, 7 tests were timing out
42+
because: plugin/tool tests called `waitForDependencies()` which joined the arborist
43+
fiber (10–30 s per test on ARM64), and the resulting CPU saturation starved
44+
concurrent session/snapshot tests. The flag skips the install in tests; safe because
45+
bun resolves `@opencode-ai/plugin` from the workspace `node_modules` directly.
46+
Set unconditionally in `test/preload.ts`.
47+
48+
### Blacksmith ARM64 runner gaps
49+
`blacksmith-4vcpu-ubuntu-2404` uses ARM64 and ships a minimal Ubuntu image missing:
50+
- `unzip` — needed by `oven-sh/setup-bun@v2` to extract the downloaded bun zip
51+
- `make`/`g++` (build-essential) — needed by `node-gyp` for `tree-sitter-powershell`
52+
Both now installed in a single `Ensure build tools are available` step in
53+
`.github/actions/setup-bun/action.yml` (Linux only, no-op if already present).
54+
55+
### Test timeout bumps
56+
- `snapshot.test.ts` "revert handles large mixed batches": 30 s → 60 s
57+
(280 files + multiple git commits/patches/reverts on ARM64)
58+
- `prompt-effect.test.ts` "loop waits while shell runs": 3 s → 15 s
59+
(spawns a real `sleep 0.2` subprocess; ARM64 fork/exec overhead exceeds 3 s)
60+
- `prompt-effect.test.ts` "shell rejects with BusyError when loop running": 3 s → 15 s
61+
(fiber fork + session init before `llm.wait(1)` exceeds 3 s on ARM64)
62+
63+
## Files Changed
64+
- `install-flex``OPENCODE_CHANNEL=flex` added to build command
65+
- `.github/actions/setup-bun/action.yml` — build tools prereq + ARM64/X64 URL construction
66+
- `.github/workflows/test.yml` — npm cache + pre-warm step (unit job)
67+
- `packages/opencode/src/flag/flag.ts``OPENCODE_DISABLE_PLUGIN_DEPS_INSTALL` flag
68+
- `packages/opencode/src/config/config.ts` — guard arborist install with new flag
69+
- `packages/opencode/test/preload.ts` — set `OPENCODE_DISABLE_PLUGIN_DEPS_INSTALL=true`
70+
- `packages/opencode/test/snapshot/snapshot.test.ts` — 60 s timeout on 280-file test
71+
- `packages/opencode/test/session/prompt-effect.test.ts` — 15 s timeout on shell-loop test
72+
73+
## Side Effects Applied Outside the Repo
74+
- `~/.opencode/bin/opencode` — rebuilt from this branch with `OPENCODE_CHANNEL=flex`;
75+
now reports `0.0.0-flex-<timestamp>` and uses `~/.local/share/opencode/opencode-flex.db`
76+
77+
## Next Steps
78+
- [ ] Merge PR #11 into flex: https://github.com/flexion/opencode/pull/11
79+
- [ ] After merge, other developers run `install-flex` to pick up all fixes
80+
- [ ] Consider periodically running `install-flex` to stay current with `flex` branch

.pre-commit-config.yaml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# See https://pre-commit.com for more information
2+
# See https://pre-commit.com/hooks.html for more hooks
3+
repos:
4+
# Standard pre-commit hooks
5+
- repo: https://github.com/pre-commit/pre-commit-hooks
6+
rev: v6.0.0
7+
hooks:
8+
- id: trailing-whitespace
9+
- id: end-of-file-fixer
10+
- id: check-yaml
11+
- id: check-json
12+
exclude: 'tsconfig\.json$|\.oxlintrc\.json$'
13+
- id: check-toml
14+
- id: check-added-large-files
15+
args: [ "--maxkb=1000" ]
16+
- id: detect-aws-credentials
17+
args: [ '--allow-missing-credentials' ]
18+
19+
# Detect secrets with GitLeaks
20+
- repo: https://github.com/zricethezav/gitleaks
21+
rev: v8.30.1
22+
hooks:
23+
- id: gitleaks-docker
24+
25+
# Lint GitHub Actions
26+
- repo: https://github.com/rhysd/actionlint
27+
rev: v1.7.10
28+
hooks:
29+
- id: actionlint-docker
30+
31+
- repo: https://github.com/lalten/check-gha-pinning
32+
rev: v1.3.1
33+
hooks:
34+
- id: check-gha-pinning
35+
36+
# Block forbidden files (.env, etc.)
37+
- repo: local
38+
hooks:
39+
- id: block-env-files
40+
name: Block .env files
41+
entry: scripts/block-env-files.sh
42+
language: script
43+
pass_filenames: false
44+
always_run: true

CONTRIBUTING.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,46 @@ https://github.com/anomalyco/models.dev
3939
bun dev
4040
```
4141

42+
### Setting Up Pre-Commit Hooks
43+
44+
Pre-commit hooks automatically validate code before pushing. This includes:
45+
- Secret detection (GitLeaks)
46+
- GitHub Actions linting (actionlint, GHA pinning)
47+
- Standard checks (trailing whitespace, JSON/YAML validation, etc.)
48+
- `.env` file protection
49+
50+
We use [prek](https://prek.j178.dev/), a fast Rust-based drop-in replacement for pre-commit.
51+
52+
To install prek:
53+
54+
```bash
55+
# Using uv (recommended)
56+
uv tool install prek
57+
58+
# Using pip
59+
pip install prek
60+
61+
# Using Homebrew
62+
brew install prek
63+
64+
# Or via standalone installer
65+
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/j178/prek/releases/latest/download/prek-installer.sh | sh
66+
```
67+
68+
Then install the git hooks:
69+
70+
```bash
71+
prek install
72+
```
73+
74+
This integrates prek into the `pre-push` Husky hook. Hooks will run automatically when you push. To manually run:
75+
76+
```bash
77+
prek run --stage pre-push # Run all hooks
78+
prek run --stage pre-push --files <file> # Run on specific file
79+
prek run gitleaks-docker --stage pre-push # Run single hook
80+
```
81+
4282
### Running against a different directory
4383

4484
By default, `bun dev` runs OpenCode in the `packages/opencode` directory. To run it against a different directory or repository:

LOCAL_AWS_SETUP.md

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@
22

33
Instructions for cloning, building, and running the Flexion fork of opencode with AWS Bedrock.
44

5+
## Quick Install
6+
7+
The installer handles all steps below automatically:
8+
9+
```bash
10+
curl -fsSL https://raw.githubusercontent.com/flexion/opencode/flex/install-flex | bash
11+
```
12+
13+
You will be prompted for:
14+
- **Clone directory** (default: `~/opencode`)
15+
- **AWS account ID** (your personal Flexion account)
16+
- **Preferred AWS region** (default: `us-east-1`)
17+
18+
Everything else — AWS SSO profile, opencode config, and the `opencode-work` shell function — is written automatically. Skip to [Usage](#4-usage) once the installer finishes.
19+
20+
---
21+
22+
## Manual Setup
23+
24+
Follow these steps if you prefer to configure things yourself.
25+
526
## Prerequisites
627

728
- [Bun](https://bun.sh) v1.3+
@@ -46,11 +67,11 @@ Add to `~/.aws/config`:
4667

4768
```ini
4869
[profile ClaudeCodeAccess]
49-
sso_start_url = <your-sso-start-url>
50-
sso_region = <your-sso-region>
70+
sso_start_url = https://identitycenter.amazonaws.com/ssoins-6684680a9b285ea2
71+
sso_region = us-east-2
5172
sso_account_id = <your-account-id>
52-
sso_role_name = AdministratorAccess
53-
region = <your-preferred-region>
73+
sso_role_name = ClaudeCodeAccess
74+
region = <your-preferred-region>
5475
```
5576

5677
### 2. Configure opencode for Bedrock
@@ -90,12 +111,12 @@ Create `~/.config/opencode/opencode.json`:
90111
"tool_call": false,
91112
"limit": { "context": 128000, "output": 8192 }
92113
},
93-
"meta.llama4-maverick-17b-instruct-v1:0": {
114+
"us.meta.llama4-maverick-17b-instruct-v1:0": {
94115
"name": "Meta Llama 4 Maverick 17B",
95116
"tool_call": false,
96117
"limit": { "context": 1000000, "output": 8192 }
97118
},
98-
"meta.llama4-scout-17b-instruct-v1:0": {
119+
"us.meta.llama4-scout-17b-instruct-v1:0": {
99120
"name": "Meta Llama 4 Scout 17B",
100121
"tool_call": false,
101122
"limit": { "context": 10000000, "output": 8192 }
@@ -118,20 +139,24 @@ Create `~/.config/opencode/opencode.json`:
118139
119140
### 3. Shell alias
120141

121-
Add to `~/.zshrc` or `~/.bashrc`:
142+
Add to `~/.zshrc` or `~/.bashrc` (replace `~/opencode` with your actual clone path if different):
122143

123144
```bash
145+
# ── Flexion opencode launcher ─────────────────────────────────────────────────
124146
opencode-work() {
125147
local profile="ClaudeCodeAccess"
148+
local arch os
149+
case "$(uname -m)" in arm64|aarch64) arch="arm64" ;; *) arch="x64" ;; esac
150+
case "$(uname -s)" in Darwin) os="darwin" ;; Linux) os="linux" ;; *)
151+
echo "Unsupported OS: $(uname -s)" && return 1 ;; esac
126152
echo "Logging in to AWS SSO ($profile)..."
127153
aws sso login --profile "$profile" || return 1
128154
eval "$(aws configure export-credentials --profile "$profile" --format env)"
129-
/path/to/opencode/packages/opencode/dist/opencode-darwin-arm64/bin/opencode "${opencode_args[@]}"
155+
"$HOME/opencode/packages/opencode/dist/opencode-${os}-${arch}/bin/opencode" "$@"
130156
}
157+
# ─────────────────────────────────────────────────────────────────────────────
131158
```
132159

133-
Replace `/path/to/opencode` with where you cloned the repo (e.g. `~/Code/personal/flexion-work-items/flexchat-stack/opencode`).
134-
135160
### 4. Usage
136161

137162
```bash
@@ -174,6 +199,7 @@ See [flexion/opencode#2](https://github.com/flexion/opencode/pull/2) for the ful
174199
| Strip reasoning from history for non-reasoning models | `packages/opencode/src/provider/transform.ts` | Removes reasoning content parts from assistant message history before sending to models with `reasoning: false` — fixes Bedrock rejections when switching from a reasoning model |
175200
| Exclude palmyra from reasoning variant generation | `packages/opencode/src/provider/transform.ts` | Prevents unsupported `reasoningConfig` parameters from being sent to Writer Palmyra models |
176201
| Local build & AWS Bedrock setup docs | `LOCAL_AWS_SETUP.md` | This file |
202+
| Automated installer | `install-flex` | Single-command installer for the entire setup |
177203

178204
Full details and upstream tracking: [flexion/opencode#2](https://github.com/flexion/opencode/pull/2)
179205

0 commit comments

Comments
 (0)