Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8b8a06c
feat: enhanced github agent with advanced review rules and self-hoste…
blacksyan Jan 2, 2026
2da9ad8
fix: correct CLI entry point path from src/cli/index.ts to src/index.ts
blacksyan Jan 2, 2026
af88b14
feat: add headless CI entry point to avoid TUI dependencies
blacksyan Jan 2, 2026
c1cb1ad
fix: correct git rev-parse command (remove spaces)
blacksyan Jan 2, 2026
44fec82
feat: implement two-phase review flow (/oc for questions, /oc! for di…
blacksyan Jan 2, 2026
dccc219
fix: /oc with any text now triggers Phase 1 (questions) unless has nu…
blacksyan Jan 2, 2026
2fc5209
fix: add JSON output format instruction to Phase 2 and Direct Review …
blacksyan Jan 2, 2026
6a71e3e
fix: handle Gemini 2.0 step parts in response parsing
blacksyan Jan 2, 2026
6b7813c
docs: update comment to reflect Gemini 3.0 Flash Preview
blacksyan Jan 2, 2026
510653c
feat: smart thread detection - skip Phase 1 for threaded replies, use…
blacksyan Jan 2, 2026
cdd5c8f
feat: implement dynamic checklist with decision support for comprehen…
blacksyan Jan 2, 2026
e0e93a9
feat: Phase 2 enhancements - context_summary, not_reviewed, /oc reche…
blacksyan Jan 2, 2026
70932c0
fix: skip Phase 1 if user previously used /oc! direct review
blacksyan Jan 2, 2026
6a0e58d
fix: strict JSON-only prompts and proper GitHub Actions URL in footer
blacksyan Jan 2, 2026
cb303f8
fix: validate comment paths against PR diff before posting inline review
blacksyan Jan 2, 2026
20fbd90
feat: branch-aware strict review - STRICT_REVIEW_BRANCHES env for con…
blacksyan Jan 3, 2026
19e4f35
debug: add logging for STRICT_REVIEW_BRANCHES comparison
blacksyan Jan 3, 2026
f3799da
fix: add branch-aware strictness to /oc recheck prompt (was missing)
blacksyan Jan 3, 2026
818cf04
fix: explicit non-strict branch behavior - use SKIPPED not FAIL, APPR…
blacksyan Jan 3, 2026
56cbd7c
feat: enhance database-indexes rule with query pattern reasoning fram…
blacksyan Jan 3, 2026
cd4f298
fix: oops
blacksyan Jan 3, 2026
e68af07
fix: restore explicit non-strict behavior in Phase 2 prompt
blacksyan Jan 3, 2026
f9ca1b1
fix: make context injection rules branch-aware - defer to prompt's CO…
blacksyan Jan 3, 2026
cb154cf
fix: strengthen non-strict branch instructions with CRITICAL section …
blacksyan Jan 3, 2026
b1a714f
feat: add RAKAMIND.md and OPENCODE.md to supported project rules files
blacksyan Jan 3, 2026
9b8fcf5
feat: add multi-line comments with committable suggestions in PR reviews
blacksyan Jan 3, 2026
0338937
fix: add explicit instruction to recheck prompt - REVIEW only, do not…
blacksyan Jan 3, 2026
5e3212a
fix: remove auto-push behavior for PR reviews - review-only mode
blacksyan Jan 5, 2026
fac2851
fix: validate inline comment lines against PR diff
blacksyan Jan 5, 2026
5f703d7
fix: normalize null suggestion to undefined using transform
blacksyan Jan 5, 2026
0a563a9
fix: mark schema definitions as skippable when migrations are in anot…
blacksyan Jan 5, 2026
f852d1a
fix: defense-in-depth for suggestion markdown - prompt + sanitization
blacksyan Jan 5, 2026
c7b9284
fix: coerce invalid passed values to null using preprocess
blacksyan Jan 5, 2026
799bc5b
feat: robust PR review capabilities
blacksyan Jan 5, 2026
7d1af83
fix: explicit skip rules for Previous Feedback in non-strict branches
blacksyan Jan 5, 2026
9bef955
fix: robust pre-parse sanitization for markdown in JSON strings
blacksyan Jan 5, 2026
1d48ab8
fix: world-class JSON repair pipeline for LLM output
blacksyan Jan 5, 2026
b49dc0d
feat: native Gemini structured output fallback for PR review
blacksyan Jan 5, 2026
829152c
fix: restore edit/write tool restrictions for review-only mode
blacksyan Jan 5, 2026
1e1dfe4
fix: add ReviewOutputRaw schema for generateObject compatibility
blacksyan Jan 5, 2026
36d74d5
feat: robust PR review test suite and util refactor
blacksyan Jan 5, 2026
3744a8f
test: achieve 100% coverage for PR review utilities
blacksyan Jan 5, 2026
322926c
refactor: extract PR review logic for 100% coverage
blacksyan Jan 5, 2026
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ target
# Local dev files
opencode-dev
logs/
code/
pr_diff.txt
109 changes: 109 additions & 0 deletions packages/opencode/src/ci.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/**
* Headless entry point for GitHub Actions / CI environments
* This avoids loading TUI dependencies (React, SolidJS, etc.)
*/
import yargs from "yargs"
import { hideBin } from "yargs/helpers"
import { Log } from "./util/log"
import { UI } from "./cli/ui"
import { Installation } from "./installation"
import { NamedError } from "@opencode-ai/util/error"
import { FormatError } from "./cli/error"
import { GithubCommand } from "./cli/cmd/github"
import { EOL } from "os"

process.on("unhandledRejection", (e) => {
Log.Default.error("rejection", {
e: e instanceof Error ? e.message : e,
})
})

process.on("uncaughtException", (e) => {
Log.Default.error("exception", {
e: e instanceof Error ? e.message : e,
})
})

const cli = yargs(hideBin(process.argv))
.parserConfiguration({ "populate--": true })
.scriptName("opencode")
.wrap(100)
.help("help", "show help")
.alias("help", "h")
.version("version", "show version number", Installation.VERSION)
.alias("version", "v")
.option("print-logs", {
describe: "print logs to stderr",
type: "boolean",
})
.option("log-level", {
describe: "log level",
type: "string",
choices: ["DEBUG", "INFO", "WARN", "ERROR"],
})
.middleware(async (opts) => {
await Log.init({
print: process.argv.includes("--print-logs"),
dev: Installation.isLocal(),
level: (() => {
if (opts.logLevel) return opts.logLevel as Log.Level
if (Installation.isLocal()) return "DEBUG"
return "INFO"
})(),
})

process.env.AGENT = "1"
process.env.OPENCODE = "1"

Log.Default.info("opencode-ci", {
version: Installation.VERSION,
args: process.argv.slice(2),
})
})
.usage("\nopencode CI/GitHub Actions runner")
.command(GithubCommand)
.demandCommand(1, "You must specify a command")
.strict()

try {
await cli.parse()
} catch (e) {
let data: Record<string, any> = {}
if (e instanceof NamedError) {
const obj = e.toObject()
Object.assign(data, {
...obj.data,
})
}

if (e instanceof Error) {
Object.assign(data, {
name: e.name,
message: e.message,
cause: e.cause?.toString(),
stack: e.stack,
})
}

if (e instanceof ResolveMessage) {
Object.assign(data, {
name: e.name,
message: e.message,
code: e.code,
specifier: e.specifier,
referrer: e.referrer,
position: e.position,
importKind: e.importKind,
})
}
Log.Default.error("fatal", data)
const formatted = FormatError(e)
if (formatted) UI.error(formatted)
if (formatted === undefined) {
UI.error("Unexpected error, check log file at " + Log.file() + " for more details" + EOL)
console.error(e)
}
process.exitCode = 1
} finally {
process.exit()
}
Loading
Loading