Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dist/
node_modules/
coverage/
.serena/
assets/
docs/
spec/
47 changes: 47 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/** @type {import("eslint").Linter.Config} */
module.exports = {
root: true,
env: {
node: true,
es2022: true,
},
parser: "@typescript-eslint/parser",
parserOptions: {
// Keep this simple for now; add `project` later if you want type-aware rules
ecmaVersion: 2022,
sourceType: "module",
},
plugins: ["@typescript-eslint", "sonarjs"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:sonarjs/recommended",
],
rules: {
// Sonar-style cognitive complexity (adjust threshold if needed)
"sonarjs/cognitive-complexity": ["warn", 20],

// You can tune or turn off rules as needed; start conservative
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "off",
},
overrides: [
{
files: ["test/**/*.ts"],
env: {
node: true,
},
globals: {
describe: "readonly",
it: "readonly",
test: "readonly",
expect: "readonly",
beforeAll: "readonly",
afterAll: "readonly",
beforeEach: "readonly",
afterEach: "readonly",
vi: "readonly",
},
},
],
};
19 changes: 9 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: CI
on:
push:
branches:
- '**'
- "**"
pull_request:

jobs:
Expand All @@ -28,8 +28,8 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run lint
run: pnpm lint
- name: Run ESLint
run: pnpm lint:eslint

- name: Run typecheck
run: pnpm typecheck
Expand Down Expand Up @@ -131,19 +131,19 @@ jobs:

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Validate release secrets
run: |
if [ -z "$NPM_TOKEN" ]; then
echo "NPM_TOKEN secret is required to publish" >&2
exit 1
fi

- name: Configure npm auth

run: |
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc

- name: Read release metadata
id: release_meta
run: |
Expand All @@ -165,19 +165,18 @@ jobs:
cat "$NOTES_FILE"
echo "${NOTES_DELIM}"
} >> "$GITHUB_OUTPUT"

- name: Build package
run: pnpm run build

- name: Publish to npm
env:
NODE_AUTH_TOKEN: ${{ env.NPM_TOKEN }}
run: pnpm publish --access public

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.release_meta.outputs.version }}
name: Release ${{ steps.release_meta.outputs.version }}
body: ${{ steps.release_meta.outputs.notes }}

45 changes: 45 additions & 0 deletions .github/workflows/formatting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Auto Formatting

on:
push:
branches:
- "**"

jobs:
format:
name: Auto Format
runs-on: ubuntu-latest
permissions:
contents: write
workflows: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10.15.0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22.x
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run Prettier (write)
run: pnpm format:write

- name: Verify formatting
run: pnpm format:check

- name: Commit formatted changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "style: apply prettier formatting"
branch: ${{ github.ref }}
1 change: 1 addition & 0 deletions .github/workflows/main-merge-guard.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Main Merge Guard

on:
workflow_call:
pull_request:
branches:
- main
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/opencode.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: opencode

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
pull_request_review:
types: [submitted]

jobs:
opencode:
if: |
contains(github.event.comment.body, ' /oc') ||
startsWith(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, ' /opencode') ||
startsWith(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: read
issues: read
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Run opencode
uses: sst/opencode/github@latest
env:
ZHIPU_API_KEY: ${{ secrets.ZHIPU_API_KEY }}
with:
model: zai-coding-plan/glm-4.6
26 changes: 26 additions & 0 deletions .github/workflows/pr-auto-base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: PR Auto Base

on:
pull_request:
types: [opened]

permissions:
pull-requests: write

jobs:
retarget:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Retarget PR to staging unless from staging
run: |
if [ "${GITHUB_BASE_REF}" = "staging" ]; then
echo "PR already targets staging."; exit 0
fi
BRANCH="${GITHUB_HEAD_REF}"
if [ "$BRANCH" = "staging" ]; then
echo "Staging PRs can target main."; exit 0
fi
echo "Retargeting PR #${GITHUB_EVENT_PULL_REQUEST_NUMBER} to staging"
gh pr edit "$GITHUB_EVENT_PULL_REQUEST_NUMBER" --base staging
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ tmp
.nx/

.stryker-tmp/
.worktrees/
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist/
node_modules/
coverage/
.serena/
.stryker-tmp/
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"printWidth": 100,
"singleQuote": false,
"trailingComma": "all"
}
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,17 @@ This plugin enables opencode to use OpenAI's Codex backend via ChatGPT Plus/Pro

### Built-in Codex Commands

These commands are typed as normal chat messages (no slash required). The plugin intercepts them before any network call, so they **do not** send prompts to OpenAI:
These commands are typed as normal chat messages (no slash required). `codex-metrics`/`codex-inspect` run entirely inside the plugin. `codex-compact` issues a Codex summarization request, stores the summary, and trims future turns to keep prompts short.

| Command | Aliases | Description |
|---------|---------|-------------|
| `codex-metrics` | `?codex-metrics`, `codexmetrics`, `/codex-metrics`* | Shows cache stats, recent prompt-cache sessions, and cache-warm status |
| `codex-inspect` | `?codex-inspect`, `codexinspect`, `/codex-inspect`* | Dumps the pending request configuration (model, prompt cache key, tools, reasoning/text settings) |
| `codex-compact` | `/codex-compact`, `compact`, `codexcompact` | Runs the Codex CLI compaction flow: summarizes the current conversation, replies with the summary, and resets Codex-side context to that summary |

> \*Slash-prefixed variants only work in environments that allow arbitrary `/` commands. In the opencode TUI, stick to `codex-metrics` / `codex-inspect` so the message is treated as normal chat text.
> \*Slash-prefixed variants only work in environments that allow arbitrary `/` commands. In the opencode TUI, stick to `codex-metrics` / `codex-inspect` / `codex-compact` so the message is treated as normal chat text.

**Auto compaction:** Configure `autoCompactTokenLimit`/`autoCompactMinMessages` in `~/.opencode/openhax-codex-config.json` to run compaction automatically when conversations grow long. When triggered, the plugin replies with the Codex summary and a note reminding you to resend the paused instruction; subsequent turns start from that summary instead of the entire backlog.

### How Caching Works

Expand Down Expand Up @@ -531,6 +534,9 @@ Set these in `~/.opencode/openhax-codex-config.json`:

- `codexMode` (default `true`): enable the Codex ↔ OpenCode bridge prompt
- `enablePromptCaching` (default `true`): keep a stable `prompt_cache_key` and preserved message IDs so Codex can reuse cached prompts, reducing token usage and costs
- `enableCodexCompaction` (default `true`): expose `/codex-compact` and allow the plugin to rewrite history based on Codex summaries
- `autoCompactTokenLimit` (default unset): when set, triggers Codex compaction once the approximate token count exceeds this value
- `autoCompactMinMessages` (default `8`): minimum number of conversation turns before auto-compaction is considered

#### Global Configuration Example

Expand Down Expand Up @@ -777,3 +783,19 @@ Based on research and working implementations from:
## License

GPL-3.0 — see [LICENSE](./LICENSE) for details.

<!-- PACKAGE-DOC-MATRIX:START -->

> This section is auto-generated by scripts/package-doc-matrix.ts. Do not edit manually.

## Internal Dependencies

_None (external-only)._

## Internal Dependents

_None (external-only)._

_Last updated: 2025-11-16T11:25:38.889Z_

<!-- PACKAGE-DOC-MATRIX:END -->
14 changes: 8 additions & 6 deletions biome.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.5/schema.json",
"files": {
"includes": ["scripts/**/*.mjs"]
"includes": ["lib/**/*.ts", "test/**/*.ts"],
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"lineWidth": 110
"lineWidth": 110,
"formatWithErrors": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
"enabled": false
},
"javascript": {
"globals": ["globalThis"]
}
}
Loading
Loading