mirror of
https://github.com/Gitlawb/openclaude.git
synced 2026-08-27 18:24:27 -05:00
main
72
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
787f2a9390 |
refactor(cli): commander-authoritative argv handling for SSH / cc:// and remote bypass (recovery of #1939) (#2098)
* fix(cli): mirror programmatic args onto process.argv (hardened) Address CodeRabbit's Critical finding: cliMain() parses process.argv directly, so a programmatic main(args) call must reflect args there or it silently runs the host's argv. Restores the args->argv sync but hardened against the three bugs the multi-agent review confirmed in the earlier scoped/serialized version: - no restore (was F3: a finally-restore flipped argv out from under the SIGINT handler and bypass-safety notice while the session was live) - length-guarded exec/script slots (was F4: <2 host argv entries, e.g. node -e, dropped the flag past commander's argv.slice(2)) - no serialization chain (was F2: overlapping calls hung indefinitely) For the normal binary launch (args defaulted from process.argv.slice(2)) the assignment is a value-identical no-op. Tests: programmatic args reach cliMain, argv is not restored, and the exec/script slots are padded under a short host argv. Verified: 48 entrypoint+safety tests, tsc, build, and e2e re-probes of all former --yolo bug scenarios on the built binary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): ssh strip-all dangerous-skip tokens; docs+tests for native alias Address the latest Copilot + CodeRabbit findings on the native-alias PR: - ssh argv pre-scan removed only the first dangerous-skip token, so `ssh --yolo --dangerously-skip-permissions host` (or a repeat) left a survivor that re-enabled bypass after the ssh rewrite. Strip every matching token. (connect already used the filter helper.) [Copilot] - web/src/data/cliFlags.ts: list the flag as '--yolo, --dangerously-skip-permissions' to match the commander registration, not just the description. [Copilot] - Replace the source-string-count registration test with (a) a behavioral test that the built CLI lists the alias in --help — proving the main-command registration is live, not dead code or the wrong command — and (b) a structured .option() assertion plus a check that the ssh pre-scan handles the alias (ssh --help renders root help, so the ssh --yolo path is the pre-scan, not the commander option). [CodeRabbit] - PR description rewritten to describe the native alias instead of the removed argv rewrite. [Copilot] Verified: 23 cli + 10 safety tests, tsc, build, e2e (--yolo --help lists the alias; ssh --help; mcp add --yolo names the typed flag). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(cli): runtime coverage for dangerous-skip strip; share one helper CodeRabbit (approved, follow-up): the strip-all fix was only source- checked, so the strip loop could regress unnoticed. Extract the argv scanners into src/utils/dangerousSkipFlags.ts (isDangerousSkipFlag / hasDangerousSkipFlag / stripDangerousSkipFlags) and unit-test them at runtime: both spellings detected, every token stripped (canonical + --yolo + repeats), input not mutated. Both the direct-connect and ssh rewrites in main.tsx now use the shared stripDangerousSkipFlags — the ssh path's bespoke single-splice while loop (the original survivor bug) is gone, replaced by an in-place splice(0, len, ...strip). One tested code path instead of two. Verified: helper + 23 cli + 10 safety tests, tsc, build, e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style(cli): semicolon + strip both spellings in safety-test reset Copilot review nits: - statusNoticeDefinitions.tsx: add the trailing semicolon to the parenthesized return to match the file's semicolon style. - safety.test.tsx: the beforeEach argv reset filtered only --dangerously-skip-permissions; strip --yolo too so the 'without the flag' cases can't go order-dependent if the runner is invoked with --yolo in argv. - PR description re-synced to the native-alias approach (the earlier edit had reverted to the old 'normalize via argv rewrite' wording). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): notice names --yolo; move import out of boot-critical block Both bots on 50772d28: - The bypass-safety notice fires for --yolo but its text named only '--dangerously-skip-permissions is active'. Reword to '... (alias --yolo) is active' so the message matches what the user typed. Add a rendered-notice regression assertion for the --yolo case. [CodeRabbit + Copilot] - Move the dangerousSkipFlags import out of the boot-critical header block (it ran before profileCheckpoint('main_tsx_entry'), adding pre-checkpoint work in the order-preserving bundle) down to the regular internal-import group. [Copilot] Verified: 39 cli+safety+helper tests, tsc, build, e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): honor -- end-of-options in the raw-argv dangerous-skip scanners Copilot (3x on 5cd0e304): the pre-commander scanners matched --yolo / --dangerously-skip-permissions anywhere in argv, so a positional after the -- marker (openclaude -p -- --yolo, cc://… -- --yolo, ssh host -- --yolo) was misread as the bypass flag — enabling bypass / stripping the token / false-firing the safety notice, even though commander treats it as positional. Pre-existing for the canonical flag, but the short alias makes it far likelier. Make the shared helpers --aware in one place: hasDangerousSkipFlag and stripDangerousSkipFlags only consider option-position tokens (before the first --) and preserve everything from -- onward. Route the safety notice's hasDangerouslySkipPermissionsArg through the same helper. Regression tests: helper ignores/preserves post-- tokens; the notice does not fire for -p -- --yolo. Verified: 41 helper+safety+cli tests, tsc, build, e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(cli): don't leak args via process.argv; stop simulating commander in the scanner Address jatmn's two P1 findings, both by removing a band-aid rather than adding another: - P1a: main() no longer mirrors its args onto the process-global process.argv. Verified there is no production or SDK caller that passes custom args (the sole entry is the no-arg auto-run), so the mirror only risked leaking a programmatic invocation's args (including a bypass flag) into an overlapping call or the host process. Back to the baseline signature; cliMain parses the real process.argv. - P1b: revert the end-of-options ("--") handling in the dangerous-skip scanner. As jatmn notes, correctly classifying "--yolo" (it can be a required option value like "--system-prompt --yolo", or follow a "--" consumed as a variadic value) requires commander's option-arity state machine, the exact simulation this feature was reworked to delete. The scanner now mirrors the canonical --dangerously-skip-permissions presence check exactly: both spellings behave identically, and the approximation is documented as a pre-existing limitation of pre-commander scanning. Net: every difference between --yolo and the canonical flag is now either native-commander-correct (the registration) or an identical approximation (the raw scanners). No new argv mutation, no parser simulation. Verified: 38 cli+helper+safety tests, tsc, build, e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(cli): clarify main() argv comment — skills/--update do rewrite argv Copilot: the "does not mirror args onto process.argv" comment was misleading — the skills and --update fast-paths reassign process.argv to re-route to their subcommand. Note the exception; the no-mirror rule is about not injecting the caller's args into the general cliMain flow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(setup): name the --yolo alias in the root/sudo bypass error Copilot: the root/sudo safety error printed only --dangerously-skip-permissions; a user who typed --yolo saw a flag they didn't use. Mention both spellings, matching the ssh help and cliFlags. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(cli): import Command from @commander-js/extra-typings, matching prod Copilot: the alias behavioral test built its probe Command from 'commander', but production registers options via @commander-js/extra-typings. Use the same package so the test exercises the exact parser prod uses. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ssh): don't treat an option value as the permission-bypass alias jatmn P1: `ssh host --permission-mode --yolo` stripped --yolo as a bypass flag (enabling bypass) and left --permission-mode valueless, whereas commander parses --yolo as the (invalid) mode value and rejects it — a silent privilege escalation. Same class affected --model / --resume / --fallback-model. Reorder the ssh pre-parser so value-taking flags consume their value — including a dangerous-skip token in the value slot — BEFORE the dangerous-skip strip runs. Extract the whole flag pre-parse into a pure, unit-tested helper (parseSshFlags) so the security-sensitive arity handling has regression coverage: escalation guards for --permission-mode/--model + a value of --yolo, plus genuine standalone --yolo still enabling bypass. Verified: 6 ssh + dangerousSkipFlags + cli tests, tsc, build, e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(cli): update ssh-path source assertion for parseSshFlags extraction Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(cli): revert unrelated --bare doc; drop stray blank line CodeRabbit/Copilot on the rebased branch: - Revert the --bare help rewrite (background prefetches / CLAUDE_CODE_SIMPLE / expanded flag list) in main.tsx and web/src/data/cliFlags.ts — it is unrelated to the --yolo alias and broadens scope. cliFlags.ts now changes only the --yolo alias line. - Remove the stray double blank line before cliMain. Skipped CodeRabbit's "alias order breaks property naming" (Major): verified against @commander-js/extra-typings that '--yolo, --dangerously-skip- permissions' maps BOTH spellings to opts().dangerouslySkipPermissions (commander keys off the last long flag); opts().yolo is undefined. Bypass is not broken. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ssh): honor the -- end-of-options marker in the ssh pre-parser CodeRabbit Critical + jatmn P1 ("respect option arity/end-of-options semantics"): `ssh host -- --yolo` (or `-- --local`, `-- --permission-mode x`) parsed the post-`--` tokens as flags, so a positional --yolo escalated to bypass. parseSshFlags now parses only the prefix before `--` and keeps everything from `--` on positional. This is unambiguous here because the ssh subcommand registers no variadic options that could consume `--` as a value. The connect (cc://) path is deliberately left plain and documented: it rewrites to the main command, which HAS variadic options (--add-dir …) that commander lets consume `--` as a value, so a naive `--` split there would be the incomplete simulation flagged in P1b. That false-positive is pre-existing for the canonical flag. Skipped (both pre-existing, ported verbatim / out of scope): extractFlag mixed `--flag=x --flag y` precedence, and the setup.ts root/sudo message not naming --allow-dangerously-skip-permissions. Verified: 8 ssh + cli tests, tsc, build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: make --yolo/bypass Commander-authoritative on cc:// connect + notice * fixup! address CodeRabbit/Copilot review findings on #2098 - Restore parseMaxTurnsCommanderArgument for --max-turns validation. - Generalize root/sudo error message for all bypass modes/flags. - Clarify cli.tsx comment about main() not leaking args into process.argv. - Detect -p/--print in all commander-accepted forms (including --print= and -p<value>). - Correct dangerousSkipFlags.ts doc: SSH strips, cc:// preserves for Commander. - Extend live help test to ssh and open subcommands. * fixup! extract hasPrintFlag helper + regression tests - Move print-flag detection to src/utils/printFlag.ts so it is unit-testable. - Add regression tests for -p, --print, --print=prompt, -pprompt, and -- separator. - Import the helper in main.tsx and drop the local copy. * fixup! use hasPrintFlag in every startup print-mode check - Replace exact-string includes in the SSH headless rejection and the main print-mode gate with the shared hasPrintFlag predicate. - Add source assertions confirming cc:// rewrite, SSH rejection, and main print-mode gate all use the same helper. * fixup! align dangerously-skip notice comment with commander-authoritative mode - Remove stale 'reads from process.argv' text; the notice now keys off the resolved permissionMode. * fixup! add SIGINT handler to hasPrintFlag source assertions - Include the SIGINT print-mode gate in the source-level consistency check. * fixup! restore maxTurns forwarding dropped during rebase - Re-add options.maxTurns to sessionConfig and the interactive REPL props for direct-connect, SSH, remote viewer, and remote creation paths (matches main). * fixup! address Copilot suppressed comments on #2098 - parseSshFlags now consumes required-arg values unconditionally, matching commander and preventing flag-like values from leaking into later guards. - Drop the now-unused isDangerousSkipFlag import from sshPreParse.ts. - Make the dangerously-skip notice text mode-agnostic so settings-driven bypassPermissions is not mislabeled as a CLI flag. * fixup: left-to-right SSH parse and fullAccess sandbox warning - Rewrite parseSshFlags as a single left-to-right arity-aware scan. Value-taking flags now consume every occurrence (including equals forms) and always consume the next token as their value, even if it resembles a flag (e.g. --permission-mode --local or --model --yolo value). - Cover fullAccess with the dangerously-skip-permissions sandbox warning and add focused regression tests for bypassPermissions/fullAccess rendering. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fixup: preserve missing SSH option values and embedded equals - Keep value-taking SSH flags in remaining when they have no available value (last token before -- or trailing), letting commander report the missing required argument. - Use slice after the prefix for equals-form values so embedded '=' characters are preserved (e.g. --model=provider=model). - Add regression tests for last-token, before--, and embedded-equals cases. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fixup: arity-aware print detection and optional --resume for SSH - hasPrintFlag now skips tokens consumed as values by preceding value-taking options (required, optional, and variadic), so --system-prompt --print=custom is no longer misclassified as print mode. - parseSshFlags treats --resume as an optional-value option: a bare --resume is forwarded, a non-option value is consumed, and following flags (e.g. --yolo) remain available for their own parsing. - Added focused regression tests for both fixes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fixup: handle inline values and -- in hasPrintFlag - Do not advance past a following flag when a required/optional/variadic option already provided its value inline via =. - Stop the scan when a value-taking option is immediately followed by --. - Added regression tests for --model=foo --print and --model -- --print. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fixup! address jatmn review: arity-aware print/SSH parsing + fullAccess notice Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fixup! correct bypassPermissions notice wording Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Address remaining CodeRabbit findings on #2098 - Sync hasPrintFlag with all root-command required/variadic/optional options, including hidden/feature-gated flags (--agent-id, --sdk-url, --channels, etc.). - Treat the SDK 'full-access' spelling as fullAccess in the dangerous-skip-permissions status notice so the stronger warning is shown. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): make hasPrintFlag the single pre-Commander print classifier - Replace all startup .includes('-p')/.includes('--print') checks with the arity-aware hasPrintFlag() predicate so value-consumed tokens are not misclassified as print mode. - Centralize SSH headless detection in sshArgvImpliesHeadless(), covering both tail argv after host/cwd and flags forwarded via extraCliArgs (e.g. --resume=--print). - Soften the fullAccess status-notice wording to match runtime behavior: most consent checks are bypassed, but hard deny rules and user-interaction prompts still apply. - Add/extend tests for interactivity, SSH flag pre-parsing, status notices, and a regression check that prevents naive print-token checks from re-entering. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(ssh): preserve --resume= values and run headless guard before host extraction - Keep the inline value attached when forwarding --resume=... extraCliArgs so optional-value semantics are preserved (e.g. --resume=--print resumes a conversation named "--print", it does not enable print mode). - Move the SSH headless guard before host/cwd extraction in main.tsx so print flags that appear before the host are rejected. - Update tests: --resume=--print is no longer headless, required-value options like --model -p remain non-headless, and add coverage for print flags before the host. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): remove repeatable single-value options from VARIADIC_OPTIONS --plugin-dir and --provider-env-file are registered as repeatable single-value options, not variadic. Keeping them in VARIADIC_OPTIONS made the arity model wrong and could consume extra tokens if check order changed. They are already covered by REQUIRED_VALUE_OPTIONS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
294bd9a1df |
Add optional Sentry error reporting (env-driven, opt-in) (#2139)
* Add optional Sentry error reporting (env-driven, opt-in) * Fix Sentry init to use dynamic import instead of require (ESM compatibility) * Document SENTRY_DSN setup in advanced-setup docs * Disable Sentry default integrations; document runtime install requirement * Wire reportErrorToSentry into top-level error handlers; add sentry.test.ts |
||
|
|
108a413493 |
fix(bg): preserve detached session terminal outcomes (#2133)
* fix(bg): preserve detached session terminal outcomes * fix(bg): harden terminal outcome routing |
||
|
|
c30578819e |
diagnostics(query): trace interruption causality (#2111)
* diagnostics(issue-1830): trace interruption causality * test(issue-1830): lock interruption ownership matrix * fix(codex): preserve stream deadline contract * fix(diagnostics): harden interruption trace lifecycle Refs #1830 * fix(diagnostics): harden interruption trace settlement Refs #1830 * fix(diagnostics): preserve interruption causality * fix(diagnostics): address interruption trace review * fix(diagnostics): preserve tracing observer contracts * fix(diagnostics): preserve interruption trace contracts * test(permissions): cover interactive hook interrupts |
||
|
|
d834904e5a |
fix(session): make transcript replacements crash-safe (#2094)
* fix(session): make transcript replacements crash-safe Complete transcript rewrites could truncate live JSONL files before preserved data was durable, risking unrecoverable resume history after an interrupted write. Commit replacements through exclusive sibling temp files and serialize them with all transcript append paths so readers observe either the old file or the complete replacement. * fix(session): preserve concurrent transcript updates Abort tombstone commits when the scanned transcript changes before replacement, and keep existing local history when remote foreground hydration returns no entries. Harden the associated portability, option coverage, queue timing, and diagnostics. * test(session): match hydration reader signature Pass the explicit optional subagent reader in the empty-hydration regression so a fresh TypeScript build sees the complete helper signature. * fix(session): coordinate transcript writers across processes Hold a same-directory cooperative lock across transcript replacement and final-line truncation, and make session plus SDK append paths participate. Exercise the post-validation/pre-rename race deterministically so external appends land after the complete commit. * test(session): provide empty hydration subagent reader * fix(session): scope transcript lock ownership Separate async and synchronous lock ownership so unrelated sync appends cannot bypass an in-flight replacement. Route aliased in-process appends through the queue, propagate lock compromise through AbortSignal, and cover both symlink-alias and rename-boundary races. |
||
|
|
95eeb0bde3 |
feat(cli): add --yolo alias for --dangerously-skip-permissions (#2097)
Register the alias on the main command and the ssh stub. Recognize it in the cc:// and ssh raw-argv scans, and in both skills pre-parse boolean sets (leading and trailing), so and route correctly. Update the web flags docs. Includes source-scan + help-text tests proving the alias is wired through. The SSH/argv refactor remains on the existing feat/yolo-flag branch for a separate follow-up PR. |
||
|
|
580a6b1197 |
fix(sdk): report a permission timeout as a timeout (#2028)
* fix(sdk): report a permission timeout as a timeout
On timeout the handler called denyPendingPermission and then fell through
to the fallback. The deny resolves the promise registered by
registerPendingPermission, but Promise.race has already settled with
{timedOut: true}, so nothing is awaiting it and the decision is discarded.
The fallback is createDefaultCanUseTool, whose contract is that the host
supplied no permission callback at all. A host that wired up
onPermissionRequest and simply answered too slowly therefore got the tool
result 'no canUseTool or onPermissionRequest callback provided. Pass
canUseTool in options', plus the matching warning on stderr -- both false,
and both pointing at a configuration problem that does not exist. It also
consumed the one-shot warning latch, so a genuinely misconfigured later
query in the same process is never warned.
Return the timeout decision directly. The permission_timeout event and the
existing deny are unchanged.
* test(sdk): move the timeout cases into the existing permissions suite
tests/sdk/permissions.test.ts pinned the old behavior -- it asserted the
timeout result was the fallback's message, with a comment describing the
fall-through as intended. It is not: that message claims no permission
callback was provided, which is false whenever onPermissionRequest is
wired up. Assert the timeout reports itself instead.
The new cases live in that suite rather than a new file: a separate test
file adds a slot to bun's sequential file ordering, which shifted which
suite runs before which and surfaced an unrelated mock leak in CI
(taskReport git metadata and the /ads command).
* test(sdk): drive the permission-timeout case off a mocked clock
The no-callback-fallback-on-timeout test relied on a real 10ms wait, so
the deny hinged on scheduling. Use fake timers and advance the clock by
the timeout window instead, making the timer the deterministic cause of
the denial.
|
||
|
|
1f20e92c2e |
fix(permissions): enforce read-only plan mode (#1938)
* fix(permissions): enforce read-only plan mode * fix(permissions): narrow hook approval types * fix(permissions): harden plan-mode decision boundaries * fix(permissions): close plan-mode hook races * test(permissions): clarify platform path case coverage * fix(permissions): guard permission hook rewrites * fix(permissions): close remaining plan-mode escapes * test(speculation): satisfy strict context typing * fix(permissions): close hook update race windows * fix(permissions): close plan approval races * fix(permissions): align prompt decision type * fix(permissions): close plan transition races |
||
|
|
0dc622e129 |
test(cli): clean skills temp directories (#1946)
* test(cli): clean skills temp directories * test(cli): handle stream cancellation errors |
||
|
|
fb1137275a |
feat: add ultrathink keyword detection and ultracode effort level (#1551) (#1630)
* feat: add ultrathink keyword detection and ultracode effort level Rebased onto current main so the diff contains only these changes — #1780's model-level effort routing now comes from main rather than being duplicated. - ultrathink: a `\bultrathink\b` keyword in a prompt injects a high-effort reminder, gated behind the isUltrathinkEnabled() rollout flag. - ultracode: a new session-only EffortLevel that maps to xhigh (or high) on the wire and grants a standing multi-agent orchestration permission. First-party only, suppressed under a per-agent providerOverride, and gated to xhigh-capable models. Honors CLAUDE_CODE_EFFORT_LEVEL precedence across the API path, the permission attachment, and the display surfaces; rejected from every agent-definition input (markdown/skill/plugin frontmatter, SDK, and JSON). Closes #1551 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(effort): clamp ultracode display availability * fix(effort): report effective effort overrides * test(model): avoid catalog-dependent effort label * fix(model): resolve current effort against session model * fix(spinner): resolve effort suffix against session model --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: jatmn <the@jat.mn> |
||
|
|
f292b057b5 | fix: await main() in cli entrypoint to prevent premature exit in Node 24.x (#1697) | ||
|
|
1bd273d4d3 |
fix: isolate OpenClaude config from Claude Code (#1875)
* Rename .claude paths to .openclaude * test: update skill watcher paths for openclaude * fix: preserve default secure storage key Co-authored-by: Cursor <cursoragent@cursor.com> * chore: address config isolation review comments * fix: canonicalize secure storage config paths * test: isolate secure storage config override * Fix keychain service name config dir handling Update macOS keychain service naming to honor `OPENCLAUDE_CONFIG_DIR` by resolving the env override directly before falling back to the default config home lookup. Adjust secure storage platform tests to import `envUtils` and keychain helpers dynamically with the same module suffix and restore module mocks correctly, keeping test state isolated and consistent. * Align diagnostics and keychain with OpenClaude Updates several utilities to use OpenClaude defaults and naming consistently. Doctor diagnostics now always checks a package name (falling back to `@gitlawb/openclaude`), macOS secure storage service names and related tests now use `OpenClaude`, and keychain prefetch docs were updated to match. This also removes an unused `homeDir` option from local install dir candidates and treats `.claude.json` as a dangerous filesystem target. * Fix doctor npm uninstall package fallback Update doctor diagnostics to generate npm global uninstall guidance using a single package-name variable. When `MACRO.PACKAGE_URL` is not set, it now falls back to `@gitlawb/openclaude` instead of `openclaude`, so the suggested cleanup command matches the scoped package install. * Protect legacy .claude paths from writes Add .claude to DANGEROUS_DIRECTORIES and sandbox denyWrite lists, extend isClaudeSettingsPath to cover legacy .claude/settings.json paths, and update README to clarify CLAUDE_CONFIG_DIR is not used for background-session storage. * Protect custom Claude config dir from sandbox writes * Protect legacy Claude config roots --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
214ee3dd2e |
feat(skills): add local skill CLI support (#1162)
* Add inspectable local skill CLI support OpenClaude Skill Hub needs the runtime repo to treat project skills as first-class local assets before registry installation exists. This wires native .openclaude skill directories into discovery, preserves .claude compatibility, and adds list/show subcommands so users can inspect resolved local skills. Constraint: Keep registry install, website catalog, and community governance out of this first runtime slice. Rejected: Replace the existing skills loader wholesale | the repo already has working bundled, plugin, MCP, dynamic, and legacy command skill paths. Confidence: medium Scope-risk: moderate Directive: Keep .claude skill loading compatible while .openclaude adoption rolls out. Tested: bun test src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: node dist/cli.mjs --bare skills list Tested: node dist/cli.mjs --bare skills show debug Tested: git diff --check * Add local skill validation and removal Skill Hub needs local package hygiene before registry install can be safe. This adds validation for SKILL.md directories and local removal for project or user skills without introducing remote registry behavior yet. Constraint: Registry install and update flows are still out of scope for this slice. Rejected: Implement install first | install needs the same validation and local removal semantics to avoid copying unsafe or unmanageable skill folders. Confidence: medium Scope-risk: moderate Directive: Keep validation conservative; loosen individual checks only with explicit registry policy coverage. Tested: bun test src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: node dist/cli.mjs skills validate .openclaude/skills/demo-skill Tested: node dist/cli.mjs skills list Tested: node dist/cli.mjs skills show demo-skill Tested: node dist/cli.mjs skills remove demo-skill Tested: git diff --check * Suppress startup banner for skills CLI Skills management commands are meant to be script-friendly inspection operations. Printing the interactive startup screen before the list/show/validate output makes the command noisy and hard to read. Constraint: Keep the interactive startup screen for normal OpenClaude sessions. Confidence: high Scope-risk: narrow Tested: bun run build Tested: node dist/cli.mjs skills list Tested: git diff --check * Make skills list readable for daily CLI use The default skills list output was a metadata-heavy dump, which made bundled and local skills difficult to scan. This changes the human formatter to an aligned table with wrapped descriptions while keeping machine-readable metadata behind --json. Constraint: Default list output must stay compact and human-readable while JSON remains script-friendly. Rejected: Keep version and trust columns in the default table | those fields add noise and remain available through --json/show. Confidence: high Scope-risk: narrow Directive: Keep the default list formatter focused on scanability; add metadata to --json or detail commands instead of widening the daily table. Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: node dist/cli.mjs skills list Tested: node dist/cli.mjs skills list --json * Stabilize skills tests under CI The PR introduced skills tests that passed in focused runs but failed under the full GitHub Actions Bun test job. The formatter test now uses bun:test consistently, and skill directory tests explicitly restore the setting-source state they rely on. Constraint: CI runs the full Bun suite, so tests must avoid node:test interop and shared setting-source leakage. Confidence: medium Scope-risk: narrow Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: git diff --check Not-tested: Full local bun test still has unrelated provider/OAuth failures on this machine. * Isolate user skill precedence test state The full CI suite can mutate process-wide config state while this test is running, so the user-vs-project precedence assertion now runs in a child Bun process with its own CLAUDE_CONFIG_DIR. Constraint: getSkillDirCommands reads global config/env state, so this precedence test needs process isolation under the full suite. Confidence: medium Scope-risk: narrow Tested: bun test src/skills/loadSkillsDir.test.ts src/cli/handlers/skills.test.ts src/commands.test.ts Tested: git diff --check * Stabilize conversation arc perf checks The CI runner was failing the conversation arc benchmarks because they used shared persisted knowledge graph state and strict wall-clock thresholds. The tests now isolate graph storage in a temporary config directory and keep only coarse regression limits suitable for noisy shared runners. Constraint: GitHub Actions shared runners can have variable storage/indexing latency. Rejected: Remove the benchmark coverage entirely | the tests still provide useful regression signals when isolated and coarse-grained. Confidence: medium Scope-risk: narrow Directive: Keep performance tests isolated from persisted user/project graph state. Tested: bun test src/utils/conversationArc.perf.test.ts src/skills/loadSkillsDir.test.ts src/cli/handlers/skills.test.ts src/commands.test.ts Tested: bun run smoke * Let users install skills from registries and local sources The skill hub CLI could list, inspect, validate, and remove local skills, but it had no supported install path. This adds a project/global install command that accepts local directories, raw SKILL.md files or URLs, and registry IDs with checksum validation when registry metadata provides one. Constraint: The companion openclaude-skills repository currently publishes SKILL.md files without riskLevel metadata, so validation keeps riskLevel optional while preserving required identity/source fields. Rejected: Require the external skills repository to be cloned into openclaude | install should work from registry metadata or explicit local paths without coupling the repos. Confidence: high Scope-risk: moderate Directive: Keep --json/list behavior machine-compatible; install output should remain human-readable and validation should not reject normal security-review prose. Tested: bun test src/cli/handlers/skillsInstall.test.ts src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: bun run smoke * Stabilize skills install tests in the full suite The install tests used shared console and cwd globals, which passed in isolation but raced with unrelated test files under Bun's full parallel suite. This makes the tests assert on installed files directly and injects the project directory into the handler for deterministic test isolation. Constraint: The CLI still resolves project installs from the runtime cwd; projectDir is only used by direct handler tests. Confidence: high Scope-risk: narrow Tested: bun test src/cli/handlers/skillsInstall.test.ts src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: bun run smoke * Keep skills install coverage in the existing skills suite The new standalone install test file changed Bun's parallel test scheduling and exposed unrelated global-state races in CI. Moving the coverage into the existing skills handler test file keeps the install behavior covered without adding another parallel test unit. Constraint: Some existing tests mutate cwd/config globals under full-suite parallelism. Confidence: medium Scope-risk: narrow Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: git diff --check * Harden skill install paths before validation The install path used registry or SKILL.md names to create temporary and target directories before validation rejected unsafe names. This validates the install name before path construction, keeps the temp root as an explicit cleanup target, and resolves install targets under the selected skills root before copy or force removal. Constraint: Registry and raw SKILL.md sources are untrusted until validation completes. Rejected: Rely on validateSkillPath after temp construction | unsafe names can affect filesystem paths before validation runs. Confidence: high Scope-risk: narrow Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: bun run smoke Tested: git diff --check * Hide bundled skills from human skills list The default skills list is meant for skills users can inspect and manage in the current environment. Bundled skills remain available internally and in JSON metadata, but the human table now omits bundled rows and removes the Source column. Constraint: --json remains machine-readable with full source metadata. Confidence: high Scope-risk: narrow Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: node dist/cli.mjs skills list Tested: node dist/cli.mjs skills list --json Tested: git diff --check Tested: bun run smoke * Include home dir in config cache key Tests can mock homedir while leaving CLAUDE_CONFIG_DIR unset, so caching only by the env override can leak a temporary .openclaude root into later config/profile tests. Include homedir in the memoization key so config path resolution follows both inputs. Constraint: Keep getClaudeConfigHomeDir memoized for hot callers. Confidence: high Scope-risk: narrow Tested: bun test --max-concurrency=1 src/utils/openclaudePaths.test.ts src/utils/providerProfile.test.ts src/utils/knowledgeGraph.stress.test.ts tests/sdk/sdk-context-isolation.test.ts Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: node dist/cli.mjs skills list Tested: bun run smoke Tested: git diff --check * Hide bundled skills from public skills commands Bundled skills are internal helpers, so the public skills CLI should only expose installed skills that users can inspect or manage. Filter bundled skills from JSON output and command lookups, and use a generic not-found response for hidden bundled names. Constraint: Installed project and user skills remain listed, inspectable, removable, and available in JSON. Confidence: high Scope-risk: narrow Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: node dist/cli.mjs skills list --json Tested: node dist/cli.mjs skills show batch Tested: node dist/cli.mjs skills remove batch Tested: bun run smoke Tested: git diff --check * Stop config path leaks across tests The full PR check can load config-path helpers after tests have mocked homedir or changed global session state. Explicit CLAUDE_CONFIG_DIR now bypasses the default-home memoization cache, and SDK contexts now treat sessionProjectDir: null as an intentional context value instead of falling back to stale global state. Constraint: Keep default config-home resolution memoized for hot callers. Confidence: high Scope-risk: narrow Tested: bun test --max-concurrency=1 src/utils/openclaudePaths.test.ts src/utils/providerProfile.test.ts src/utils/knowledgeGraph.stress.test.ts tests/sdk/sdk-context-isolation.test.ts Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: bun run smoke Tested: git diff --check * Stabilize config-sensitive tests in CI The PR check showed provider profile tests sharing process.env/CWD-sensitive state and a knowledge graph stress test assuming a fixed config-root persistence path. Mark the profile tests that mutate global process state as non-concurrent and assert the corrupted Orama rename relative to the actual persistence path under test. Constraint: Production behavior is unchanged; this only tightens test isolation. Confidence: high Scope-risk: narrow Tested: bun test --max-concurrency=1 src/utils/openclaudePaths.test.ts src/utils/providerProfile.test.ts src/utils/knowledgeGraph.stress.test.ts tests/sdk/sdk-context-isolation.test.ts Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: git diff --check * Explain skill remove scope mismatches Removing a user-global skill without --global looked like a missing skill even though skills list showed it. Detect when the requested skill exists in the other local scope and print the exact removal command hint while keeping bundled/internal skills hidden as generic not found. Constraint: Bundled skills remain hidden from public skills commands. Confidence: high Scope-risk: narrow Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: node dist/cli.mjs skills remove pr-review Tested: node dist/cli.mjs skills remove batch Tested: bun run smoke Tested: git diff --check * Clarify empty skills list state The public skills list now hides bundled/internal skills, so an empty result means there are no installed user or project skills. Use clearer copy to avoid implying internal skills do not exist. Constraint: Bundled skills remain hidden from public skills commands. Confidence: high Scope-risk: narrow Tested: bun test src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: node /home/anaxy/Projects/openclaude/dist/cli.mjs skills list from empty temp project Tested: bun run smoke Tested: git diff --check * fix(skills): preserve namespaced local installs * Keep skills CLI independent of provider startup Skills management commands need to work when provider configuration is broken, because they are local/script-friendly maintenance commands. Route skills subcommands before provider profile hydration and validation, including supported leading global flags such as --bare. Constraint: Provider startup validation must still run for normal interactive and provider-backed commands. Rejected: Import full main.tsx for the skills fast path | that loads optional bundled Chrome modules and re-couples the local skills path to interactive startup. Confidence: high Scope-risk: narrow Tested: bun test src/entrypoints/cli.skills.test.ts src/cli/handlers/skills.test.ts src/skills/loadSkillsDir.test.ts src/commands.test.ts Tested: bun run build Tested: CLAUDE_CODE_USE_OPENAI=1 OPENAI_BASE_URL=https://api.openai.com/v1 OPENAI_API_KEY= node dist/cli.mjs skills list Tested: CLAUDE_CODE_USE_OPENAI=1 OPENAI_BASE_URL=https://api.openai.com/v1 OPENAI_API_KEY= node dist/cli.mjs --bare skills list Tested: bun run smoke Tested: git diff --check * Preserve reviewed skill install hardening after rebase Rebasing PR #1162 onto current main flattened an earlier merge commit that carried reviewed Skill Hub hardening and regression coverage. This restores those final-tree changes as a normal linear commit so the rebased PR keeps the same behavior reviewers approved without retaining merge commits or mainline noise. Constraint: Keep the PR branch linear for maintainer review while preserving the reviewed final tree from the conflict-resolved integration branch. Rejected: Push the plain rebase result | it would drop registry sha256/version/trust metadata handling and associated tests from the reviewed PR state. Confidence: high Scope-risk: narrow Directive: Do not remove the registry sha256 requirement or install-path regression tests without another security review. Tested: final tree compared against fix-pr-1162-conflicts before verification * Fix skills CLI review follow-ups * Fix skills CLI review findings * Address skills CLI review follow-ups * Fix skills tests under bare-mode CI state * Clear bare argv in skills tests * Harden skills remove and loader tests * Pin cwd state in skills remove test * Use explicit project dir for skills removal * Avoid skill remove test name collision * Use fs abstraction for skills removal * fix skills CLI review findings * Fix skills CLI startup bypass and test isolation * Fix skills CLI review findings * Fix remaining skills CLI review findings * Fix skills CLI review findings --------- Co-authored-by: OpenClaude Worker 3 <worker-3@openclaude.local> Co-authored-by: jatmn <the@jat.mn> |
||
|
|
1827d84709 |
feat(agents): add per-agent step limits (#1815)
* feat(agents): add per-agent step limits Add maxSteps agent configuration for markdown, JSON, plugin, and SDK agent definitions. Enforce the limit in subagent query execution by blocking over-limit tool calls, preserving a no-tool summary turn, and recording an agent_step_limit terminal reason. Add focused coverage for default behavior, invalid values, multi-turn accumulation, plugin parsing, failure-loop interaction, and summary-tool blocking. * test(agents): isolate agent loader fixtures * test(agents): stabilize agent loader config fixtures * fix(agents): harden step-limit summaries * fix(sdk): harden agent injection follow-up * fix(sdk): report invalid agent step limits |
||
|
|
eea0a1a740 |
feat(cli): add headless heartbeat for print mode (#1789)
* feat(cli): add headless heartbeat for print mode * fix(cli): harden heartbeat validation and predicates * fix(cli): align print heartbeat phases * fix(cli): keep heartbeat payloads schema-valid * fix(cli): delay stream-json heartbeat until drain * test(sdk): cover heartbeat placeholder identifiers * fix(cli): clamp heartbeat durations * fix(cli): ignore file persistence final events * test(cli): cover post-turn final filtering * fix(cli): harden headless heartbeat follow-up Export the heartbeat SDK message type from generated core types. Keep heartbeat cleanup paired with setup and streaming failures, and cover timing/count edge cases with focused regression tests. * test(sdk): exercise generated heartbeat types Expose the SDK type generator as a pure helper so tests compare fresh output with the checked-in generated artifact. * fix(scripts): canonicalize sdk type generator entrypoint Compare real paths for direct script execution so symlinked invocations still run the generator. * test(sdk): harden generator import coverage Normalize generated type freshness checks across line endings and keep the SDK type generator import-safe for non-file entrypoints. * test(sdk): assert generator import has no write side effects Snapshot the generated SDK type artifact around the non-file import regression so importing the generator cannot silently rewrite the committed output. |
||
|
|
5af6f95c46 |
feat(config): add explicit provider env-file loading (#1668)
* feat(config): add explicit provider env-file loading * fix(config): handle escaped quotes in provider env files * fix(config): polish env-file parser review feedback * fix(config): preserve provider env-file precedence * test(config): cover provider env-file precedence * fix(config): preserve provider env-file values * fix(config): allow documented env-file setup vars * fix(config): preserve provider flag precedence |
||
|
|
544b857876 |
fix(settings): correct stale settings path references (#1666)
* fix(settings): correct OpenClaude settings paths * fix(settings): address review path clarity * fix(sandbox): protect OpenClaude settings in changed cwd |
||
|
|
a1b3346f65 |
feat(cli): add local background sessions (#1642)
* feat(cli): add local background sessions Add local detached background sessions backed by an OpenClaude-owned registry under the resolved config directory. - implement --bg spawning plus ps, logs, logs -f, kill, and an explicit attach limitation - harden registry metadata validation, atomic writes, ID/name collision handling, and terminal-name reuse - precreate child log files with precise ownership cleanup and register metadata only after spawn succeeds - verify live PIDs against the session command before treating registry entries as running - wait for process-tree termination and escalate to SIGKILL before marking sessions killed - skip live local background sessions during --continue transcript selection - preserve Node heap flags for detached children while avoiding stale launcher relaunch state - handle -- separators so dash-prefixed prompts remain positional - document storage, safety model, name reuse, and the current attach limitation Validation: - bun test - bun run typecheck - bun run smoke - isolated built-CLI --bg/ps/logs/kill smoke - CodeRabbit review findings addressed * test(utils): prevent bg registry mock leakage Restore complete bg registry and UDS module mocks after conversation recovery tests so Bun's process-global mock.module registry cannot leak partial module exports into later CLI tests. CI exposed this under Bun 1.3.13 when conversationRecovery.test ran before the bgRegistry and bg CLI test files. * test(utils): exercise bg registry without global mock Replace the conversation recovery bgRegistry module mock with real registry metadata backed by a short-lived live child process. This keeps UDS as the only mocked boundary and avoids leaking a mocked registry module into later CLI registry tests under Bun 1.3.13. * test(utils): isolate background registry state Stop the conversation recovery test from using process-wide bgRegistry mocks or real child processes by injecting the live-session dependencies directly. Pin and serialize the bg registry test config directory through the shared env mutation lock so path/cache state cannot leak from neighboring tests under Bun CI ordering. * test(utils): document Bun mock restoration Explain why conversation recovery tests re-register full module exports after mock.restore(), matching the CodeRabbit-requested Bun 1.3.13 isolation workaround. * test(cli): isolate background registry root Avoid relying on process-wide CLAUDE_CONFIG_DIR state in bgRegistry tests. Use a registry-local test root override so CI file ordering and mocked path modules cannot redirect background session metadata into another test's temp directory. * test(utils): cover live session fallback paths Add focused coverage for collectLiveBackgroundSessionIds when UDS discovery fails but registry data remains available, and when registry refresh fails but UDS data remains available. * fix(cli): harden background session management Validate persisted and newly-created background session PIDs before exposing them to management commands. Reserve named live sessions with an atomic registry write, release reservations when sessions become terminal, and cover concurrent duplicate-name attempts. Split local session management dispatch from background spawning so ps/logs/attach/kill avoid provider startup while --bg still inherits profile routing. * fix(cli): address background session review findings Preserve positional prompts when --bg is combined with optional-value flags such as --debug. Recover stale name reservations whose owner metadata is missing or terminal while preserving in-flight reservations from live creators. Cover both reviewer findings with focused parser and registry regression tests. * fix(cli): respect delimiter for background flags Limit background and print-mode flag detection to arguments before the -- delimiter so flag-shaped prompts remain positional. Keep optional resume/from-pr flags out of the required-value table and add regressions for delimiter and optional-flag prompt handling. * refactor(cli): share delimiter argument helper Move args-before-delimiter handling into the existing dependency-free CLI args utility. Use a dynamic import from the entrypoint so background flag routing shares the helper without adding top-level module load to version and management fast paths. * test(cli): cover background entrypoint routing Export the CLI entrypoint for controlled tests and add isolated importer injection so runtime routing tests do not leak global module mocks. Replace the delimiter source-layout assertion with execution-level coverage for management commands, real background flags, and flag-shaped prompt text after --. * fix(cli): preserve background resume selectors Keep space-separated --resume, -r, and --from-pr values attached when building background child args. Mark live background sessions stale when PID command identity cannot be read, avoiding termination of reused unrelated PIDs. * fix(cli): track unknown background session identity Represent unreadable live PID identity as a non-terminal unknown state so active sessions stay excluded from resume selection. Refuse to terminate unknown live PIDs because the process command cannot be positively matched to the background session. * fix(cli): honor background resume selectors Avoid adding a generated --session-id to non-forked background resume launches so the spawned print-mode child satisfies the existing resume/session-id contract. Pass --from-pr through headless print mode and resolve PR-linked sessions through the shared conversation recovery path. Add regression coverage for background resume launch args and PR selector matching. * fix(cli): treat PR resume as headless resume source Include --from-pr in print-mode resume guards so PR-linked headless resumes can run without a prompt and share resume-only options. Skip eager startup hooks for headless PR resumes and add explicit --session-id launch coverage. * fix(cli): keep background PR resumes live Resolve non-forked --from-pr background launches to the selected transcript id before writing registry metadata. Preserve PID identity refresh for PR-resume children by matching the stored invocation when argv does not carry the transcript id. Add regressions for launch registration and registry refresh. * test(cli): cover PR resume lookup failures Add regression coverage for non-forked background --from-pr launches when the selector cannot be resolved. Verify the launch planner returns the same clear error used by handleBgFlag(). |
||
|
|
650fae952d |
fix(sdk): make stub-leak detection TDZ-safe + defer to next microtask (#1287) (#1398)
* fix(sdk): make stub-leak detection TDZ-safe + defer to next microtask (#1287) `bun run scripts/start-grpc.ts` crashed at startup with: ReferenceError: Cannot access 'QueryEngine' before initialization. at detectStubLeaks (src/entrypoints/sdk/index.ts:29:33) at src/entrypoints/sdk/index.ts:47:1 The detector ran at module-load time and read each critical import directly. When the start script's circular-import chain reached the SDK barrel before `QueryEngine.js` had finished initializing its own export bindings, the QueryEngine reference at line 29 hit the temporal dead zone and threw. Stub-leak detection is meant to catch `__stub: true` markers from the esbuild plugin — TDZ is a different bug class (an uninitialized binding can't carry `__stub`), so the detector should treat the access failure as 'nothing to check here' rather than crashing the entire SDK entry. Two changes: 1. Wrap each import read in safelyAccess(() => binding) so a TDZ ReferenceError on one returns undefined and the loop continues. Real stub markers still surface as the explicit SDK init error. 2. Defer detectStubLeaks() from module-load to queueMicrotask, so every same-tick init in the circular chain (start-grpc.ts → SDK index → QueryEngine → ... → SDK index) completes before we read bindings. Microtask runs before any actual SDK usage, so a real stub leak still surfaces well before the first query() call. Tests (3): SDK barrel imports without throwing, anti-regression on real __stub: true bindings, TDZ-shaped access returns undefined. * test(sdk): exercise the real stub-leak detector with stubbed fixtures (#1287) The regression test asserted only that a local object literal had __stub === true and re-implemented safelyAccess inline, so it never ran the real detector: removing queueMicrotask(detectStubLeaks), dropping the loop, or swallowing the __stub case would all still pass. Split the detection primitives (safelyAccess + the critical-import scan) into src/entrypoints/sdk/stubLeakDetection.ts and have the SDK entry point import them. The test now feeds stub-shaped fixtures through the real checkCriticalImportsForStubs / safelyAccess and asserts: a real __stub: true binding throws the explicit SDK init error; non-stub modules pass; a TDZ ReferenceError is tolerated (skipped) without crashing; a stub behind a skipped TDZ access is still caught; and the SDK barrel import never throws on its own load. Detector runtime behavior is unchanged. |
||
|
|
b036e9fa7c |
fix: startup provider validation fallback (#1658)
* fix startup provider validation fallback * test startup provider behavior |
||
|
|
d8dbf274b4 |
chore(runtime): align Node.js minimum version (#1644)
* chore(runtime): align Node.js runtime requirements * test(runtime): cover prefixed Node versions * fix(runtime): check node executable in doctor |
||
|
|
f4c3be850e |
chore: remove dead code and add knip gate to CI check (#1612)
Delete 32 unreferenced source files (~4,000 lines) verified dead by import-specifier grep and knip: test-only token utilities, orphaned hooks (useTaskListWatcher, useSkillImprovementSurvey + its component), the removed DevBar and ConfigTool UIs, unregistered bundled skills (stuck, verifyContent), unused analytics sinks, the benchmark command, and stale migrations/helpers. Remove unused dependencies code-excerpt, stack-utils, and tsx from package.json plus their entries in build stub/external lists. Add knip with a tuned knip.json (entrypoints, build-time stub targets, subprocess-launched fixtures, and runtime-string-imported SDKs ignored; providerAutoDetect kept intentionally as provider pre-wiring) and wire `bun run deadcode` into the `check` script so dead code stays dead. Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
a3a3c3659d |
perf(cli): restore --version fast path with dynamic provider imports (#1611)
The static imports of providerProfile.js and providerValidation.js at the top of cli.tsx side-effect-loaded the entire integrations graph (~11.7k lines of vendor/gateway/model descriptors) at module evaluation, defeating the zero-import --version fast path. Convert them to dynamic imports at their use sites, matching the file's existing convention. --version: ~0.47s median (0.35-0.60s) -> steady 0.26s. Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
89d05317b6 |
feat: add Vietnamese i18n for slash command descriptions (#1431)
* feat: add Vietnamese i18n support for slash command descriptions
Add a simple i18n helper that reads the `language` setting from config
to display localized skill descriptions. Currently supports English
(default) and Vietnamese.
To switch to Vietnamese, set in ~/.claude/settings.json:
{ "language": "vietnamese" }
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
* feat(i18n): add Vietnamese translations for all 85 command descriptions
- Fix detectLocale() to read ~/.claude/settings.json directly via
readFileSync instead of broken require('../../utils/config.js')
- Add commandDescVi translation map with 85 Vietnamese descriptions
- Export translateCommandDescription() for use in command rendering
- Modify formatDescriptionWithSource() to translate descriptions
when language is set to "vietnamese"
- Bump version to 0.15.1
* fix: add prepare script for git-based installs
When installing via `npm install -g git+https://...`, npm runs the
`prepare` script automatically. This ensures the CLI is built from
source during installation.
Requires Bun to be installed globally.
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
* fix(i18n): read locale from merged settings
* feat(i18n): translate all prompt-type commands + add env validation + node version files
## Changes
### 1. Fix prompt-type command translations (src/commands.ts)
- `formatDescriptionWithSource()` now calls `translateCommandDescription()` for ALL command types
- Previously only translated `builtin`/`mcp` source commands
- Now translates: workflow, plugin, bundled, and default cases
- Fixes: /review, /insights, and other prompt-type commands now display Vietnamese
### 2. Add missing Vietnamese translations (src/skills/bundled/i18n.ts)
Added 17 new command translations:
- /btw: "Đặt câu hỏi nhanh bên lề mà không làm gián đoạn cuộc hội thoại chính"
- /compact: "Xóa lịch sử hội thoại nhưng giữ tóm tắt trong ngữ cảnh"
- /auto-fix: "Cấu hình tự động sửa: chạy lint/test sau khi AI chỉnh sửa"
- /bridge-kick: "Chèn trạng thái lỗi bridge để kiểm thử khôi phục thủ công"
- /review: "Hoàn thành đánh giá bảo mật cho các thay đổi đang chờ trên nhánh hiện tại"
- +12 more commands
### 3. Add Zod env validation at startup (src/utils/envValidation.ts)
- New file: validates critical env vars using Zod at startup
- Crashes immediately if invalid (instead of wasting time)
- Validated vars: ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, CLAUDE_CONFIG_DIR, HTTP_PROXY, HTTPS_PROXY, NODE_EXTRA_CA_CERTS
- Integrated into src/entrypoints/init.ts
### 4. Add node version files
- .nvmrc: Node 22
- .node-version: Node 22
- Matches Dockerfile (node:22-slim) and package.json engines (>=22.0.0)
## Test Results
- 3007 pass, 11 fail (all in changeDetector.test.ts - pre-existing, unrelated to i18n)
Co-Authored-By: OpenClaude <noreply@openclaude.ai>
* fix: restore validateBoundedIntEnvVar in envValidation.ts
* Localize bundled skills descriptions at read time
* fix(i18n): localize slash command suggestions
Search rendered localized command descriptions and rebuild the Fuse index when language-sensitive text changes.
Preserve Unicode letters and numbers for Vietnamese slash queries, localize the remaining requested command descriptions, and keep exact slash command submission from following a stale highlighted suggestion.
Tests: bun test src/commands.test.ts; bun test src/utils/suggestions/commandSuggestions.test.ts; bun test src/utils/envValidation.test.ts
Thanks to @jatmn for the patient review and guidance.
* fix(i18n): tighten slash command localization scope
* fix(i18n): centralize localization and preserve external metadata
* fix(commands): scope localized descriptions to OpenClaude-owned commands
* fix(i18n): read session language before initial settings
* fix(i18n): prefer whenToUse localization keys
---------
Co-authored-by: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Co-authored-by: OpenClaude <noreply@openclaude.ai>
Co-authored-by: lht3003-rgb <lht3003-rgb@users.noreply.github.com>
|
||
|
|
9755550137 |
Typecheck/zero tsc errors (#1597)
* ci(typecheck): add error-count ratchet toward zero tsc errors tsc --noEmit currently reports 697 pre-existing errors (issue #473), so PRs cannot be gated on a clean typecheck yet. This adds scripts/typecheck-ratchet.ts and a per-file baseline: CI fails when the count rises above the baseline (listing exactly which files regressed), passes at or below it, and --update lowers the baseline to lock in gains. Wired into pr-checks as its own step; once the baseline reaches zero the step becomes a plain `bun run typecheck`. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * fix(typecheck): mechanical sweep — 697 → 624 tsc errors Type-only fixes with no runtime behavior change, except the deliberate NODE_ENV restorations: - Restore process.env.NODE_ENV comparisons that the source snapshot had baked into the literal "production", making the conditions constant (AutoUpdater dev/test skip, useTypeahead, ink devtools injection, interactiveHelpers onboarding skip, TestingPermissionTool.isEnabled — the last now correctly enables under bun test, +3 tests run green) - Type stream read helpers in openaiShim/codexShim as Bun.ReadableStreamDefaultReadResult<Uint8Array<ArrayBuffer>> and annotate throwClassifiedTransportError as never-returning, clearing the reader/response undefined cascades (29 errors) - Delete 14 stale @ts-expect-error directives - Widen useState/useRef/array generics inferred from null/[] literals - as-const notification priority/color literals to match Priority - Accept readonly Tool[] in checkLocalModelContextLoad/getCombinedTools Baseline lowered via typecheck:ratchet --update; full suite green (3690 tests), smoke + bundle guard green. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * fix(typecheck): recreate missing modules — 624 → 415 tsc errors The open snapshot never mirrored ~60 modules; the bundler noop-stubs them at build time (() => null named exports), so every recreated module here is runtime-inert by construction: no import-time side effects, gated features stay off (isAssistantMode/isSkillSearchEnabled → false, tools isEnabled → false, dialogs render null), lookups return empty, telemetry no-ops. Types are honest and derived from importer usage — no any. Highlights: - sdk: runtimeTypes re-exports/aliases, sdkUtilityTypes (NonNullableUsage), settingsTypes.generated; coreTypes.generated usage fields regenerated as a self-contained structural type (the consumer package ships without sdkUtilityTypes/@anthropic-ai/sdk, so the generated file must stay dependency-free — generator override updated to match, package-consumer-types tests green) - services: contextCollapse operations/persist/stats, compact cachedMicrocompact state/types + reactiveCompact, skillSearch (7 modules), oauth/types, lsp/types, sessionTranscript - cli/server/daemon: Transport interface, parseConnectUrl, server/* (7), daemon/*, bg/templateJobs/runners; assistant/* (KAIROS), ssh/* - tools/components: WorkflowTool trio, ReviewArtifact pair, OverflowTest/TerminalCapture/VerifyPlanExecution/DiscoverSkills, WebBrowserPanel, task dialogs, message variants, ink events/cursor - types: statusLine, fileSuggestion, notebook, messageQueueTypes; SerializedMessage rebuilt as distributed Omit-union so transcript guards narrow again; vitest-compat.d.ts mirrors Bun's runtime 'vitest' → 'bun:test' aliasing - TS2304 names: ant-model helpers imported from existing antModels.ts, inert Ultraplan/Gates/LogoV2 stubs, PromiseWithResolvers local type - build.ts: ACCEPTABLE_RUNTIME_STUBS emptied — both grandfathered bundle-reaching stubs (MonitorMcpDetailDialog, VerifyPlanExecutionTool/constants) are now real typed modules, so the degrade-on-use debt the guard tracked is retired Validation: full suite 3690 green, smoke + bundle guard green, typecheck:type-tests green, sdk package-consumer tests green; baseline lowered via typecheck:ratchet --update. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * fix(typecheck): reconstruct Message discriminated union — 415 → 342 tsc errors src/types/message.ts was a stub where all ~40 message type aliases were 'export type X = any'. Bare-any aliases break the one thing the union is for: narrowing. Type predicates like isHookAttachmentMessage collapsed to 'never' in guard chains, cascading TS2339/TS2345 through utils/messages.ts, messageFilters.ts, groupToolUses.ts, collapseReadSearch.ts, REPL.tsx, compact.ts, stopHooks.ts and the message components. Envelope design (permissive-body discriminated union): - Each variant declares its literal discriminant(s) — message.type for the envelope union (user/assistant/attachment/progress/system), subtype for the 17-variant System family — plus the properties constructor functions in utils/messages.ts actually populate, with '[key: string]: any' as an escape hatch so unreconstructed properties never error. - UserMessage<C> / AssistantMessage<T> are generic over content shape so NormalizedUserMessage / NormalizedAssistantMessage<T> reuse the envelope without Omit (Omit over an index-signature type collapses keyof to string and silently drops the discriminant, breaking narrowing). - AssistantMessage.message is a structural AssistantMessageContent<T>, not the SDK's BetaMessage: synthetic constructors don't populate every SDK-required field (stop_details), and SDK-facing consumers need assignability to Record<string, unknown>-style bodies. - AttachmentMessage<T = Attachment> / ProgressMessage<T = Progress> stay generic over their payloads (utils/attachments.ts and Tool.ts types). - UI wrappers (GroupedToolUseMessage, CollapsedReadSearchGroup, CollapsibleMessage, RenderableMessage) and stream/control envelopes (StreamEvent over BetaRawMessageStreamEvent, RequestStartEvent, TombstoneMessage, ToolUseSummaryMessage) reconstructed from call sites. - logs.ts SerializedMessage switched from the Omit<Message, never> trick (only sound against an any stub) to an Extract-based distributed union, keeping TranscriptMessage assignable to Message. All other touched files are type-level-only adjustments (annotations on evolving arrays that inferred never[], predicate types, casts in SDK wire adapters and test fixtures) — no runtime logic changed anywhere; the full bun test suite passes 3690/0 before and after. Result: 415 → 342 tsc errors, every never-cascade in the message pipeline resolved, no file above its per-file baseline (ratchet updated). Part of issue #473. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * fix(typecheck): narrow unknowns and fix signature drift — 342 → 94 tsc errors Clears every remaining non-test error. Honest fixes dominate: evolving array/let/useState/useRef annotations (the repo's noImplicitAny:false disables evolving types), real type guards over unknown wire payloads, hoisted react-compiler-style params annotated with their components' real Props, and callee signature corrections (useRegisterOverlay optional param, generic useVoiceState<T>, growthbook shim's accepted refresh-interval param) that each cleared several call sites. Targeted reason-commented casts only at SDK/stub/wire boundaries; no any, no new suppressions. Runtime deviations are confined to already-broken paths: benchmark.ts imported a function name that never existed (module-load crash), caches.ts called stub methods unguarded (TypeError for ant-gated users), messageActions returned undefined from a string function; CACHE_EDITING_BETA_HEADER is a best-effort reconstruction of a squash-lost constant, reachable only behind feature-gated first-party paths (flagged for review). Also: ConnectorTextBlock gains its wire-proven optional signature field; MCP server factory ambient types gain close(); ink render-node-to-output's nodeType cast fixed (intersection was collapsing the intended widening); upstreamproxy relay normalizes the socket data union. Validation: full suite 3690 green, smoke + bundle guard green; remaining 94 errors are all in test files (PR 5). Baseline lowered via typecheck:ratchet --update. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * fix(typecheck): clean test typing, gate CI on zero tsc errors — 94 → 0 Closes the typecheck burn-down (issue #473): bun run typecheck now exits 0 across the whole repo and CI fails on any new error. Test typing: new src/test/typedMocks.ts centralizes the two bun:test gaps (asMockFetch — Mock<T> lacks fetch.preconnect; callArgs — argless-signature mocks collapse mock.calls to []). Beyond the helpers, fixes are honest: discriminated-union narrowing before member access, fixture typing with boundary casts, assertion-type corrections, and two tests realigned to production signatures they had drifted from (requestLogging logApiCallEnd args, incrementalTokenCounter tokenBudget rename) with identical assert outcomes. No assertion semantics changed; all touched suites pass. CI: the ratchet served its purpose and is retired — pr-checks now runs a plain `bun run typecheck` step; ratchet script and baseline deleted. Burn-down summary across the series: 697 → 624 (mechanical sweep) → 415 (recreate ~60 missing modules) → 342 (Message discriminated union) → 94 (narrowing + signature drift) → 0 (this PR). Validation: tsc --noEmit exit 0, full suite 3690 green, smoke + bundle guard green. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * fix(typecheck): reconcile with upstream parallel typecheck fixes Upstream landed #1591/#1592/#1595 while this series was in flight, fixing some of the same errors differently. Rebase resolutions prefer upstream where it is authoritative: their CACHE_EDITING_BETA_HEADER value ('cache-editing-2025-12-01', unconditional) replaces this series' feature-gated reconstruction; their cachedMicrocompact stub shapes (with their new test file) replace ours, with boundary casts in claude.ts where the stub's unknown[] edits meet the local pinned delete-edit shape; their reader/ReadResult stream typing in openaiShim replaces ours. MessageWithoutProgress now matches its name (Exclude<NormalizedMessage, ProgressMessage>), reconciling upstream's RenderableMessage GroupingResult with this series' message union; the @ts-expect-error upstream added for settingsTypes.generated is removed since the module now exists. tsc exit 0; full suite 3697 green (incl. upstream's new cachedMicrocompact tests); smoke + bundle guard green. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * fix(sdk): keep result usage counters required, fix assistant stub exports Addresses jatmn's and chioarub's review on the typecheck PR: 1. SDK usage contract restored: the generated result types' usage now keeps input_tokens, output_tokens, cache_creation_input_tokens, and cache_read_input_tokens as REQUIRED numbers — result messages are populated from QueryEngine.totalUsage (initialized from EMPTY_USAGE), so they are always present at runtime and strict consumers may sum them without undefined guards. The richer nested metadata (cache_creation, server_tool_use, service_tier) is modeled explicitly instead of hiding behind the index signature; the nested objects carry no index signature so the SDK's interface types stay assignable. Generator override updated and artifacts regenerated; a new package-consumer type test sums the counters and reads the nested fields so this contract cannot silently regress. The sessionHistory test fixture now carries all four counters, matching runtime shape. 2. Assistant install wizard stub mismatch fixed: dialogLaunchers imported NewInstallWizard/computeDefaultInstallDir through a module shape cast, but the assistant stub only exported default — a guaranteed runtime crash if the gated path lit up. The stub now provides real typed exports: a wizard that cancels immediately (so the launcher resolves null/user-cancelled instead of hanging on an empty dialog) and an inert computeDefaultInstallDir; the unsafe cast in dialogLaunchers is gone. Validation: tsc exit 0; full suite 3698 green (incl. the new consumer counters test); smoke + bundle guard green. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> --------- Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
bb19392e69 |
fix(typecheck): expand cachedMicrocompact stub exports (#1591)
* fix(typecheck): expand cachedMicrocompact stub exports The cachedMicrocompact module is a feature-gated stub that only exported 3 functions, but microCompact.ts expected 10+ exports including types and state management functions. Changes: - Add missing type exports: CachedMCState, CacheEditsBlock, PinnedCacheEdits, CachedMCConfig - Add missing function stubs: createCachedMCState, markToolsSentToAPI, resetCachedMCState, registerToolResult, registerToolMessage, getToolResultsToDelete, createCacheEditsBlock - Add null guard in cachedMicrocompactPath for config - Add comprehensive tests for stub behavior Resolves 15 typecheck errors in microCompact.ts: - TS2694: Namespace has no exported member (10 errors) - TS2339: Property does not exist (5 errors) - TS18047: possibly null (2 errors) Testing: - bun test src/services/compact/cachedMicrocompact.test.ts: 7/7 pass - bun test src/services/compact/: 61/61 pass - bun run smoke: pass - Typecheck errors: 697 → 682 (-15) * fix(typecheck): address CodeRabbit review feedback - Add missing fields to CachedMCConfig type: enabled, supportedModels, systemPromptSuggestSummaries (used by prompts.ts and claude.ts) - Replace silent fallback with explicit error throw in cachedMicrocompactPath to enforce the invariant that isCachedMicrocompactEnabled() === true implies getCachedMCConfig() !== null, preventing potential recursion in future non-stub implementations * test: prevent CI state leaks |
||
|
|
9db9427f29 |
fix(typecheck): reduce error baseline by 89 across 8 files (#1595)
* fix: resolve 28 typecheck errors in openaiShim.ts Add null guards for nullable `reader`, `response`, and `responsesResponse` variables, and use type assertions to bridge Node vs Web ReadableStream type mismatches in stream processing helpers. * fix(typecheck): resolve 17 errors in agentSdkTypes.ts - Add @ts-expect-error for settingsTypes.generated.js (generated at build time) - Fix type imports: redirect 5 types from ./sdk/runtimeTypes.js to ./sdk/shared.js - Remove 11 unused type imports that don't exist (AnyZodRawShape, InferShape, etc.) * fix(typecheck): resolve 26 errors in openaiShim.ts — nullable guards, ReadableStream types * fix(typecheck): resolve 23 errors in messages.ts + groupToolUses.ts MessageWithoutProgress resolved to `never` because all message types are `any` stubs, making `Exclude<any, any>` = `never`. Widen types and use boolean wrappers to avoid type-predicate narrowing. Add missing return in getToolUseID switch statement. * fix(typecheck): resolve 14 errors in toolExecution.ts — fix never[] inference * fix(typecheck): resolve type errors in claude.ts - Cast nested block params to BetaContentBlockParam for SDK type union mismatch - Add missing CACHE_EDITING_BETA_HEADER constant to betas.ts - Type-assert getCachedMCConfig() return for supportedModels access - Add missing imports: getContextWindowForModel, COMPACT_MAX_OUTPUT_TOKENS, getSdkBetas - Fix model variable reference to use options.model in compact context - Add optional signature property to ConnectorTextBlock type * ci: re-trigger checks * fix: address CodeRabbit review feedback - Throw error instead of silent return when response body is not readable - Clamp hybrid context budget to non-negative floor (Math.max(0, ...)) - Remove unused isResult wrapper in messages.ts |
||
|
|
286d403093 |
Update(zen-go): add claude-opus-4-8, minimax-m3, mimo-v2.5-free models and proper effort level integration for Zen/Go models (#1505)
* feat(provider): add OpenCode Zen/Go subscription support
Add OpenCode as a first-class provider, enabling users to connect their
Zen (pay-as-you-go) and Go ($10/mo) subscriptions via the /provider command.
New integration descriptors:
- vendors/opencode.ts — OpenCode Zen vendor (41 models)
- gateways/opencode-go.ts — OpenCode Go gateway (12 models)
- brands/opencode.ts — brand descriptor
- models/opencode.ts — full model catalog (GPT, Claude, Gemini, Qwen,
GLM, Kimi, MiniMax, Grok, DeepSeek, MiMo, Nemotron)
Modified files:
- integrationArtifacts.generated.ts — register descriptors and presets
- providerProfile.ts — add OPENCODE_API_KEY env/secret key, 'opencode'
profile type, and buildLaunchEnv handler
- providerConfig.ts — add DEFAULT_OPENCODE_BASE_URL constants
Auth: OPENCODE_API_KEY env var or interactive key entry in /provider
Transport: openai-compatible (chat_completions)
Base URLs: https://opencode.ai/zen/v1 (Zen), /zen/go/v1 (Go)
* feat(provider): add [Zen]/[Go] tags to OpenCode preset labels
Add visual tags in the /provider preset selection to distinguish
OpenCode Zen (pay-as-you-go) from OpenCode Go (subscription).
* feat(provider): enable dynamic model discovery for OpenCode
Switch OpenCode vendor and Go gateway from static to hybrid model
catalog with openai-compatible discovery. Models are fetched from
/v1/models on startup and cached for 1 hour. Manual refresh is
supported via the /provider UI.
Static model list is preserved as fallback when discovery fails.
* test(provider): add comprehensive OpenCode Zen/Go test suite
97 tests across 2 files covering:
Integration tests (72 tests):
- Vendor descriptor: id, label, classification, base URL, model, auth,
transport, preset, validation, catalog, discovery, usage metadata
- Gateway descriptor: id, label, vendorId, category, base URL, model,
auth, transport, preset, catalog, discovery
- Brand descriptor: id, label, canonicalVendorId, capabilities, modelIds
- Model catalog: registration, vendor/gateway associations, required
fields, valid classifications, reasoning/coding tags, no duplicates,
model counts (41 Zen, 12 Go), modelDescriptorId consistency
- Cross-reference: brand↔model, vendor↔model, gateway↔model,
shared OPENCODE_API_KEY
- Registry validation: no errors, no preset conflicts
- Edge cases: unique ids, unique apiNames, non-empty labels, valid
contextWindow/maxOutputTokens, valid defaultModel format, validation
message content, discovery config
Profile tests (25 tests):
- Type guard: isProviderProfile('opencode'), rejects invalid values
- buildLaunchEnv: persisted env, defaults, process env precedence,
OPENCODE_API_KEY mapping, whitespace/null/undefined/empty handling,
very long keys, special characters, concurrent access, boundary
values, no credential leakage
* fix(provider): add per-model endpoint routing (P1)
Add endpointPath field to OpenAIShimTransportConfig so catalog entries
can specify which API path to use per model. This addresses the
maintainer's [P1] finding that all models were routed to
/chat/completions regardless of their upstream endpoint.
Changes:
- descriptors.ts: add endpointPath?: string to OpenAIShimTransportConfig
- openaiShim.ts: buildRequestUrl checks shimConfig.endpointPath first
- vendors/opencode.ts: add transportOverrides to 31 catalog entries
(GPT→/responses, Claude/Qwen→/messages, Gemini→/models/<id>)
+ switch to source: 'static' to prevent free models from live API
- gateways/opencode-go.ts: add transportOverrides to 4 entries
(MiniMax/Qwen→/messages) + switch to source: 'static'
- opencode.test.ts: update tests for static source, remove discovery tests
* refactor(opencode): model OpenCode Zen/Go as gateways (P2)
* docs(provider): document OpenCode setup and move badge metadata to descriptors
- Add OpenCode Zen/Go rows to README supported providers table
- Add OpenCode Zen/Go examples and OPENCODE_API_KEY to advanced-setup.md
- Add PresetBadge type to descriptor/manifest with badge propagation in
artifact generator
- Move 4 hard-coded preset badges ([FREE], [Sponsor], [Zen], [Go]) from
ProviderManager.tsx into descriptor preset metadata
- Add badge field to providerUiMetadata so UI components read from manifest
- Update integration overview docs to recommend preset.badge for future
gateways
* fix(provider): match request body to endpoint format for OpenCode /messages and /responses (P1)
Extend the openaiShim transport so that endpointPath overrides select
both the URL and the correct body/response format:
- /responses → OpenAI Responses API body (input, max_output_tokens)
- /messages → Anthropic Messages API body (content blocks, system, max_tokens)
Also fixes: abort listener leak in SSE passthrough, system prompt
content-block flattening, and removes [Zen]/[Go] badge entries (P3).
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
* fix(provider): add Google AI SDK body/response format for OpenCode Zen Gemini models (P1)
The three Gemini models in the OpenCode Zen catalog (gemini-3.5-flash,
gemini-3.1-pro, gemini-3-flash) were sending chat-completions body to
the /models/gemini-* endpoint, which expects Google AI SDK format.
- effectiveTransport now detects /models/gemini- endpointPath → 'gemini'
- buildGeminiBody() converts Anthropic messages → Google contents[]
with role mapping, systemInstruction, generationConfig, functionDeclarations
- geminiSseToAnthropic() parses Google SSE frames → Anthropic stream events
with text deltas, functionCall tool_use, finishReason mapping
- _convertGeminiToAnthropicResponse() for non-streaming responses
- Streaming/non-streaming routing via URL detection (/models/gemini-)
- serializeBody(), hasToolsPayload, omitGeminiTools all updated
* fix: prevent OpenCode model descriptors from shadowing canonical limits
P1: Prefix all defaultModel values in opencode.ts with 'opencode-'
so the fallback findModelDescriptorForApiName() doesn't match
canonical model names. The OpenCode descriptors are still found
via catalog entry lookup when the OpenCode route is active.
P2: Add 'OpenCode Go' and 'OpenCode Zen' to PRESET_ORDER in
ProviderManager.test.tsx between 'OpenAI' and 'OpenRouter'
so navigateToPreset() sends the correct number of j keypresses.
* fix: align OpenCode Go descriptor metadata with Zen
- category: 'hosted' → 'aggregating' (both are aggregating gateways)
- add validation block with OPENCODE_API_KEY guidance
- update test assertion from 'hosted' to 'aggregating'
* fix: accept OPENAI_API_KEY as fallback in OpenCode validation
When users set up OpenCode Zen/Go via /provider, the key is saved as
OPENAI_API_KEY (via buildCompatibilityProcessEnv). The validation block
only checked OPENCODE_API_KEY, causing a startup warning even though
the runtime auth header had the key it needed.
Add OPENAI_API_KEY to validation.credentialEnvVars for both gateways,
matching the pattern used by Hicap and Gitlawb Opengateway.
* chore: trigger mergeability recheck
* feat(shim): forward effort/thinking to OpenCode Zen/Go endpoints
- buildResponsesBody: add reasoning_effort + reasoning_summary + include
- buildAnthropicMessagesBody: add thinking config (adaptive/enabled/budget)
- buildGeminiBody: add thinkingConfig with thinkingLevel mapping
- modelSupportsEffort: allow OpenCode Claude and Gemini models
- modelSupportsMaxEffort: add opus-4-7
- getAvailableEffortLevels: show standard levels for OpenCode native models
- opencode-go: add missing validation block
* feat: update OpenCode Zen and Go model counts, add new models, and enhance effort level handling
* feat: implement xhigh effort support for specific models and adjust effort level handling
* fix(effort): address reviewer feedback on xhigh + new models
- docs/advanced-setup.md: bump OpenCode Go count 12 → 13
- openaiShim.ts: include opus-4-8 / opus-4.8 in the adaptive thinking
detection so the new model uses the adaptive + effort path instead
of falling back to budgetTokens
- effort.ts: modelUsesOpenAIEffort now also rejects models that include
'claude-' or 'gemini-' — without this, OpenCode Claude/Gemini
routes (provider=openai) were misclassified as OpenAI-style and
could leak xhigh past the new gate
- effort.codex.test.ts: lock in the new exclusion with a regression
test against the openai provider
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(effort): address reviewer feedback on xhigh effort + new models
Closes the three P2 findings from PR #1505 review:
1. Settings schema now accepts 'xhigh' so a persisted xhigh survives
restart instead of being silently dropped by .catch(undefined).
2. ModelPicker /effort cycle is driven by getAvailableEffortLevels(model)
instead of a boolean includeMax, so models supporting xhigh
(opus-4-7/4-8, OpenAI/Codex) can actually select it from the picker.
displayEffort clamp now uses the available levels list, so stale
xhigh also clamps to high when the focused model doesn't support it.
3. SDK/control metadata uses getAvailableEffortLevels(model) instead of
the EFFORT_LEVELS fallback that advertised xhigh to every max-capable
model. SDK schema + generated types extended to include 'xhigh'.
Also fixes a latent generator bug: the array case in generate-sdk-types
now parenthesizes union/intersection elements so the trailing [] binds
the whole type, e.g. ("a"|"b")[] rather than "a"|"b[]. Without this,
the regenerated xhigh levels ended up typed as the single-literal
"xhigh"[] and broke the modelInfo assignability check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(effort): order xhigh before max in EFFORT_LEVELS
EFFORT_LEVELS now matches getAvailableEffortLevels() output order
(['low', 'medium', 'high', 'xhigh', 'max']), and the order asserted by
the existing effort.codex.test.ts tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(effort): order xhigh before max in settings + SDK schemas
Matches the EFFORT_LEVELS / getAvailableEffortLevels order from the
previous commit. The Zod enum order doesn't affect runtime validation,
but keeps the source consistent and avoids confusion if anyone reads
the enum literal to infer display order.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(effort): clamp ModelPicker selection and mark xhigh as current
- ModelPicker.handleSelect: clamp the emitted/persisted effort to the
focused model's available levels so a toggled-but-unsupported level
(e.g. 'xhigh' on a model that doesn't support it) is never written
to settings.json or handed to the consumer. Add focusedAvailableLevels
+ focusedDefaultEffort to the memo guard so the function regenerates
when the focused model changes.
- EffortPicker: compare the xhigh option against the persisted 'xhigh'
level directly. The 'max' alias path is kept only for legacy
settings.json values that still hold 'max' from before xhigh was
introduced.
* docs(effort): fix stale EffortPicker comment about xhigh normalization
openAIEffortToStandard is a type cast that passes 'xhigh' through as a
first-class EffortLevel — the shim only converts to 'max' at the
Anthropic request boundary, not here. Update the comment to match.
* docs(effort): update /effort help to match xhigh support matrix
The /effort --help output still described max as "Opus 4.6 only" and
xhigh as an "alias for max", but this PR promotes xhigh to a first-class
EffortLevel and allows it for OpenCode Claude Opus 4.7/4.8 (with max
also allowed for those Opus variants). Update the help so it matches
the picker/runtime behavior:
- max: "(Opus 4.6+)"
- xhigh: "(OpenAI/Codex and Opus 4.7+)"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(sdk): address reviewer P2 — sync xhigh across override union, schemas, CLI
- Add 'xhigh_effort' to ModelCapabilityOverride union so the new
call at effort.ts:93 typechecks (P2 finding 1).
- Add 'xhigh' to AgentDefinition.effort enum (coreSchemas.ts) and
control.applied.effort enum (controlSchemas.ts), then regenerate
coreTypes.generated.ts so the SDK public contract matches the
first-class effort level (P2 finding 2).
- Add 'xhigh' to the --effort CLI flag allowed list and help text
(main.tsx:945-951) so users can actually pass --effort xhigh
instead of hitting "It must be one of: low, medium, high, max".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(effort): narrow allowlist to shim-serialized models; sync max description
Address reviewer findings on PR #1505:
P2: The broad `m.includes('opus-4') || m.includes('sonnet-4')` branch
made older variants (claude-opus-4-1, claude-sonnet-4-5) advertise
effort support, but the Anthropic /messages shim only serializes
low/medium as anthropicBody.effort for the isAdaptive || isOpus45
set (opus-4-5/4-6/4-7/4-8, sonnet-4-6). For other models the shim
only emits thinking for high/max, so low/medium on those models
was silently dropped on the wire. Collapse the two 4-model branches
into one that matches the shim's serialization set; the substring
match still covers prefix variations (claude-, opencode-claude-).
P3: getEffortLevelDescription('max') said "Opus 4.6 only" but
modelSupportsMaxEffort now allows opus-4-6, opus-4-7, opus-4-8.
Update the shared description to "Opus 4.6+" so the picker and
/effort confirmation agree with the new support matrix (matching
the /effort --help text from
|
||
|
|
754cb61d17 | fix(provider): preserve explicit startup env (#1560) | ||
|
|
3a308c11d4 |
fix(typecheck): restore control protocol type exports (#1497)
* fix(typecheck): restore control protocol type exports * fix(sdk): align control initialize contract * fix(sdk): expose control initialize response types |
||
|
|
3be54de16b |
Make OpenGateway the default startup provider (#1493)
Default fresh installs to the Gitlawb OpenGateway profile, keep validation behavior for saved profiles, and mark OpenGateway as the recommended provider in the picker. Update setup docs and generated integration metadata to reflect the API-key-backed OpenGateway route, and add coverage for the fresh-install startup environment. |
||
|
|
cfcc5d06bd |
Fix OpenGateway provider flag API key routing (#1466)
* fix(provider): route OpenGateway provider credentials * fix(provider): preserve CLI provider after settings env * test: stabilize attribution settings mocks * fix(provider): preserve OPENAI_API_BASE overrides |
||
|
|
a8632b4cc3 |
fix(agents): route configured agent model overrides (#1390)
* fix(agents): route configured agent model overrides * fix(agents): preserve routed teammate providers * test: isolate attribution provider env * test: harden attribution fixture isolation * fix(agents): load flag settings before teammate routing |
||
|
|
4a4f379b8c |
Add full access mode and fix bypass commit prompts (Issue 1097) (#1110)
* Add full access permission mode Introduce a Full Access mode as a second-level dangerous permission option that bypasses normal confirmation prompts and hard safety-check prompts while still preserving deny decisions. Wire fullAccess through permission mode types, SDK schemas/types, CLI and REPL control paths, settings, mode cycling, spawned teammate inheritance, prompt speculation, and setup safety checks. Update permission handling so Full Access skips ask rules, requiresUserInteraction prompts, content-specific ask results, safety-check asks, and hook-forced asks while preserving updatedInput from tool permission checks. Add a separate Full Access warning acknowledgement and render Full Access selections in red to make the higher-risk mode visually distinct. Allow the project-local .git/OPENCLAUDE_COMMIT_MSG helper file in dangerous modes for /commit while keeping default mode and other .git paths protected by safety prompts. Add focused regression tests for Full Access prompt bypass behavior, hook ask handling, commit message file permissions, mode cycling, spawned teammate propagation, and SDK permission mappings. * fix: restore sdk permission fail-closed behavior Preserve host canUseTool and onPermissionRequest enforcement in fullAccess instead of short-circuiting around SDK policy callbacks. Keep the default SDK permission path fail-closed when no host callback is configured, while still allowing interactive tools to surface guidance prompts under fullAccess. Add focused regression coverage for SDK permission routing and fullAccess user-interaction behavior, plus filesystem coverage for the project-local OPENCLAUDE_COMMIT_MSG path. * fix: complete full access permission mode integrations - keep Full Access out of persisted default permission mode settings - sync Full Access to Claude in Chrome skip-all permission mode - restore Full Access correctly when exiting plan mode - add regression coverage for settings, Chrome sync, and plan-mode exit * test: harden dangerous mode startup flow * feat: add permission mode management tab Add a dedicated permission mode tab for switching session modes from the permissions UI. Keep dangerous modes visible when currently active, route dangerous mode changes through the confirmation dialog without exiting settings, and surface availability errors for auto or bypass modes. Also add focused tests for permission mode option visibility. * feat: add full access approval flows Add fullAccess as an approval option across file, shell, skill, monitor, web fetch, fallback, and plan-exit permission prompts. Introduce a shared dangerous-mode confirmation hook, wire fullAccess session mode updates through the permission handlers, and gate the new option on dangerous-mode availability. Also fix the plan-exit follow-up review findings by preserving hook order around the dangerous-mode dialog and restoring Shift+Tab to the explicit accept-edits approval path. Verified with focused permission tests and Bun module import smoke checks. * Harden dangerous permission mode boundaries Tighten fullAccess and bypassPermissions entry paths so elevated mode always respects explicit local confirmation and authoritative org policy gates. This hardens SDK and bridge activation, Chrome integration, session resume and rewind restoration, team and plan mode transitions, and shared permission update handling. It also keeps session dangerous-mode state in sync and adds focused regression coverage for permission setup, killswitch behavior, conversation recovery, and SDK permission flows. * refactor: centralize permission mode transitions Route permission mode changes through shared decision and live-transition helpers so dangerous/full-access confirmation, plan/auto side effects, and mode application stay aligned across CLI, REPL, prompts, and swarm surfaces. Add a shared UI request hook for resolved dangerous-mode confirmations, persist in-session dangerous-mode acceptance, and remove duplicated request/confirm/apply flows from prompt input, teams, plan exit, and permission settings. Also fix follow-up correctness issues by validating all setMode updates consistently, applying live permission updates before persisting them, and rebasing those live updates on the latest permission context to avoid partial commits or stale-state overwrites. * refactor: simplify permission request flows Centralize permission mode changes behind requestPermissionModeChange and reuse it from the CLI, REPL bridge, inbox poller, and UI callers. Consolidate duplicated permission request behavior by introducing shared shell and simple permission helpers, routing file permission actions through a shared executor, and unifying remote permission queue-item construction. Add a shared PermissionScaffold for the common dialog frame, remove redundant shell option/helper modules, and keep focused permission mode transition coverage in permissionSetup tests. * Enable full access from the permissions UI Expose bypass/full-access modes in the /permissions picker so dangerous modes can be enabled in-session instead of only via launch flags. Propagate a session-only bypass-enable signal through the permission mode change flow, preserve the existing dangerous-mode confirmation and policy checks, and keep the session marked as bypass-capable after the user enables one of the dangerous modes. Also add targeted tests covering picker visibility, local session unlock behavior, and the post-enable session state. * Refine bypass permissions warning copy * fix(powershell): anchor commit message .git exception to project root Align the PowerShell .git write safety exception for .git/OPENCLAUDE_COMMIT_MSG with the shared filesystem permission rule. The PowerShell helper was resolving the path from the mutable shell cwd, which made the bypassPermissions and fullAccess cases order-sensitive in the full test suite. Resolve the exception from getOriginalCwd() instead so the temp commit message file is only exempted inside the project root .git directory while other .git writes still require a safety prompt. Verified with: - bun test src/tools/PowerShellTool/powershellPermissions.test.ts --max-concurrency=1 - bun test src/utils/permissions/filesystem.test.ts --max-concurrency=1 - bun test src/tools/PowerShellTool src/utils/permissions --max-concurrency=1 * test: fix dangerous mode prompt suite hang * Fix monitor permission test isolation * Harden monitor permission state selector --------- Co-authored-by: JATMN <12479882+jatmn@users.noreply.github.com> Co-authored-by: TechBrewBoss <dash@hicap.ai> |
||
|
|
9190bd0c50 |
Harden test isolation and smoke checks (#1440)
* fix(test): isolate provider-related attribution and preconnect tests
Remove process-global provider mocks from apiPreconnect tests and exercise real env-based provider resolution with hermetic first-party setup.
Reset bootstrap/settings state around attribution tests and reload the attribution module per test so provider and client state cannot leak across suites.
Verification: bun test --max-concurrency=1 src/utils/apiPreconnect.test.ts src/utils/attribution.test.ts
* Fix full local check failures
Add a check script that runs smoke plus the full single-concurrency Bun test suite, and wire it into CONTRIBUTING, the PR template, and PR checks.
Fix Windows/full-suite failures by preferring Git Bash over the WSL bash launcher, normalizing settings paths before source matching, making path and warning-glyph tests platform-aware, and restoring persistent Bun module mocks for AgentTool and hook-chain tests.
Verified with bun test src\tools\BashTool\BashTool.errorOutput.test.ts --max-concurrency=1 and bun run check.
* fix(test): eliminate mock.module() leaks and platform-specific test failures
## Problem
The full test suite (bun test --max-concurrency=1) had 10 failing tests on
Windows. Investigation revealed 4 distinct root causes, all stemming from
bun's mock.module() not being fully reversible by mock.restore(). When a
test file replaces a shared module via mock.module(), stale bindings persist
in already-imported modules even after mock.restore() is called. This is a
known bun limitation.
The CI (Ubuntu) only showed 1 consistent failure (the attribution test),
but the Windows-local failures exposed real bugs that could surface in CI
under different test ordering.
## Changes
### src/utils/hookChains.integration.test.ts (root polluter)
This file was the biggest source of test pollution with 9 mock.module()
calls replacing shared modules (analytics, growthbook, policyLimits,
teammateMailbox, teammate, AgentTool, replBridge, etc.) with partial
surfaces. For example, the teammateMailbox mock only exported writeToMailbox
but the real module has 20+ exports including isIdleNotification,
createIdleNotification, readMailbox, etc. When mock.restore() didn't fully
undo these mocks, downstream tests got undefined for missing exports.
Fix: Import real modules via cache-busted dynamic imports before setting up
mocks, then spread the real module surface into each mock.module() call.
This way even if the mock leaks, downstream tests see the full module
surface with only the intended overrides. All 9 mock.module calls now
spread their real module counterparts.
Also fixed: the test was failing in isolation with SyntaxError because
attachments.ts transitively imports isIdleNotification from
teammateMailbox.js, which was missing from the partial mock.
### src/utils/settings/changeDetector.test.ts (Windows path normalization)
4 tests failed because getSourceForPath() normalizes paths using
path.normalize() which converts forward slashes to backslashes on Windows.
The test hardcoded Unix-style paths (/tmp/openclaude/user/settings.json)
but path.normalize produces \tmp\openclaude\user\settings.json on
Windows. The path comparison always failed, so handleChange() returned
early without triggering any callbacks or debounce timers.
Fix: Import normalize from 'path' and apply it to all test path constants
(pathsBySource, getManagedSettingsDropInDir). This matches what the
production code does.
### src/utils/exportFormats.test.ts (Windows path separator)
resolveExportFilepath() uses path.join() which produces backslash-separated
paths on Windows. The test expected forward-slash paths.
Fix: Import join from 'path' and use it in the expected value so the
assertion is platform-agnostic.
### src/utils/file.test.ts (growthbook mock leak)
importFileModuleWithKillswitchEnabled() mocked growthbook.js with only
getFeatureValue_CACHED_MAY_BE_STALE: () => killswitchEnabled. When
killswitchEnabled was false, this poisoned isAgentSwarmsEnabled() for all
downstream tests because agentSwarmsEnabled.ts has a static import of
getFeatureValue_CACHED_MAY_BE_STALE that captured the mock binding.
Fix: Import the real growthbook module and spread it into the mock, so
all exports remain available even if the mock leaks.
### src/utils/plugins/officialMarketplaceStartupCheck.test.ts (same pattern)
Same growthbook mock leak pattern. Top-level mock.module with only
getFeatureValue_CACHED_MAY_BE_STALE: () => true.
Fix: Import real growthbook module and spread into mock.
### src/tools/AgentTool/AgentTool.teammateModel.test.ts (transitive mock binding)
4 tests failed with 'Agent Teams is not yet available on your plan' because
isAgentSwarmsEnabled() returned false. The function checks
getFeatureValue_CACHED_MAY_BE_STALE('tengu_amber_flint', true) from
growthbook.js, but the static import binding in agentSwarmsEnabled.ts was
captured from a leaked mock that returned false.
Cache-busting the AgentTool.js import doesn't help because
agentSwarmsEnabled.ts is a transitive dependency that keeps its
already-loaded (mocked) growthbook binding.
Fix: Add mock.module for agentSwarmsEnabled.js in importAgentToolWithSpawnMock()
to pin isAgentSwarmsEnabled to true, matching the test's intent (it sets
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1).
## Verification
- bun run smoke: passes
- bun test --max-concurrency=1: 3019 pass, 0 fail (verified twice)
- No skipped tests (test.skip/it.skip/describe.skip), no test.todo,
no flaky markers, no test exclusions in config
## Known remaining risks
6 test files still have partial mock.module() calls on providers.js
(withRetry, officialRegistry, domainCheck, conversationRecovery, fastMode)
that don't spread the real module. These don't cause failures under current
test ordering but are latent risks if bun changes file execution order.
* Fix remaining provider mock leak risks
Address the known remaining risks from
|
||
|
|
cb666c85d0 |
Fix launcher heap setup for long sessions (#1242)
Relaunch the package executable before loading dist/cli.mjs so OpenClaude starts with an effective V8 heap cap instead of setting NODE_OPTIONS after the current process has already started. The launcher now adds a default 8192 MB max-old-space-size and --expose-gc when they are missing, preserves flags supplied through process.execArgv or NODE_OPTIONS, and provides OPENCLAUDE_DISABLE_HEAP_RELAUNCH plus OPENCLAUDE_NODE_MAX_OLD_SPACE_SIZE_MB escape hatches. Update the headless loop GC hook to use Node global.gc when the launcher exposed it, while preserving the existing Bun.gc path. Clarify the entrypoint NODE_OPTIONS comment so it reflects child-process propagation rather than current-process heap sizing. Add scripts/openclaude-bin-heap.test.ts to guard launcher ordering and user override handling. Validation: bun test scripts/openclaude-bin-heap.test.ts src/entrypoints/cli.test.ts; node bin/openclaude --version returned 0.13.0 (OpenClaude). Earlier full build passed after bun install --frozen-lockfile. bun run typecheck remains blocked by existing repo-wide type errors unrelated to this change. |
||
|
|
4d0603e990 |
fix(entrypoint): apply --max-old-space-size=8192 universally, not just CCR (#1191)
Closes #402 — JavaScript heap OOM during large tasks. The CLI entry point only set --max-old-space-size=8192 when CLAUDE_CODE_REMOTE=true, leaving local users with V8's ~2 GB default ceiling. Long agentic tasks (multi-file refactors, large prompts, tool loops) hit that ceiling and abort with: FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory Fix: remove the CCR gate and apply the 8 GB cap unconditionally, with a user-override guard -- if the runner already set NODE_OPTIONS --max-old-space-size to an explicit value, their setting is preserved (no silent clobbering). Files changed: - src/entrypoints/cli.tsx — remove CLAUDE_CODE_REMOTE guard, add user-override predicate, update comments - src/entrypoints/cli.test.ts — 6 regression tests (new file) |
||
|
|
f12eb1c9e8 |
Harden test isolation for smoke stability (#1192)
* Fix flaky smoke build checks Replace feature-flag build preprocessing with a Bun onLoad transform so smoke/build no longer rewrites tracked src files while tests may be reading them. Keep telemetry stubs ahead of the feature transform in both CLI and SDK builds, preserve non-empty text token counts in hybrid context splitting, and make the corrupted Orama stress test assert against the actual project directory used by the test. Verified with bun run smoke, bun test src/utils/hybridContextStrategy.test.ts, bun test src/utils/knowledgeGraph.stress.test.ts --rerun-each 3, and bun test --max-concurrency=1. * Harden KnowledgeGraph smoke stress isolation Give each KnowledgeGraph stress test its own temporary config directory and remove it during teardown so Orama, SQLite, and corrupted-file state cannot bleed between stress cases or later PR test runs. Reviewed at least 20 open PRs and found the recurring smoke-and-tests failure cluster is the full unit suite, especially KnowledgeGraph corrupted Orama recovery. Verified with bun test src/utils/knowledgeGraph.stress.test.ts --rerun-each 5, bun test --max-concurrency=1, and bun run smoke. * Harden smoke test isolation Audit and harden broad smoke-adjacent test suites for process-global leaks, including env/config restoration, shared registry/module mock cleanup, fetch/axios/mock restoration, and global MACRO/platform/sandbox mutations. Replace fragile render sleeps in interactive tests with output-driven waits, and isolate provider/model/profile tests behind the shared mutation lock so unrelated PRs do not inherit stale process state. Make SQLite knowledge graph cleanup clear closed on-disk databases before best-effort file cleanup, with coverage for the stale database reset path. Verified: bun run smoke; bun test --max-concurrency=1; python -m pytest -q python/tests; bun run security:pr-scan -- --base origin/main; bun run test:provider; npm run test:provider-recommendation. * Harden test isolation across smoke suite Guard process-global test mutations with the shared mutation lock across env, module mock, config cache, and storage tests.\n\nDeep-copy global config snapshots, restore transient globals precisely, and make plugin/LSP mocks expose compatible export surfaces so concurrent test loading does not poison unrelated suites.\n\nReplace fixed SDK cleanup sleeps with call polling to remove timing sensitivity.\n\nVerification:\n- bun test --max-concurrency=1\n- bun run smoke\n- python -m pytest -q python/tests\n- bun run test:provider\n- npm run test:provider-recommendation\n- bun run security:pr-scan -- --base origin/main\n- git diff --check * Close remaining test global-state leaks Guard remaining cache, plugin, console, and VS Code module-mock tests with the shared mutation lock.\n\nThis follow-up audit covers non-env process-global state that can leak across test files: tool schema cache, cache stats tracker state, plugin loader caches, console.error replacement, and VS Code mock.module usage.\n\nVerification:\n- leak-surface scans for env/global/mock.module/cache outliers\n- duplicate top-level mock collision cluster\n- affected tests cluster\n- bun test --max-concurrency=1\n- bun run smoke\n- git diff --check * Guard remaining mock restore cleanup Lock tests that call bun:test mock.restore without installing module mocks themselves.\n\nmock.restore is process-global, so these cleanup hooks can still tear down another test file's active module mocks when files run concurrently.\n\nVerification:\n- expanded leak scans for env, globals, module mocks, mock.restore, timers, argv, and caches\n- bun test src/components/useCodexOAuthFlow.test.tsx src/services/github/deviceFlow.test.ts\n- bun test --max-concurrency=1\n- bun run smoke\n- git diff --check * Harden test isolation for smoke stability Serialize tests that mutate process-global state behind the shared mutation lock, including process.env, transient globals, global config/cache state, storage mocks, and Bun module mocks. Add isolated env mutex instances for SDK mutex tests so timeout coverage no longer manipulates the live process-global mutex. Move top-level mock.module setup behind lock acquisition and restore mocks before releasing locks to prevent cross-file leakage under parallel smoke runs. Verified with: bun test --max-concurrency=1; bun test; bun run smoke. |
||
|
|
4d2de51679 |
Fix provider profile startup precedence (#1157)
Prevent the legacy .openclaude-profile.json fallback from overriding startup env when a modern configured provider profile has already selected a concrete provider configuration. Thread the configured-profile signal from CLI bootstrap into buildStartupEnvFromProfile(), add a concrete-selection helper for the new guard, and preserve the legacy file as a first-run fallback when startup env is incomplete. Also fix the follow-up falsey-flag regression so disabled CLAUDE_CODE_USE_* values do not count as active startup selections, and add regression tests covering stale legacy overrides, incomplete startup env, and falsey provider flags. Verified with: bun test src/utils/providerProfile.test.ts --test-name-pattern " buildStartupEnvFromProfile\ |
||
|
|
2c71e09394 |
chore(build): clean up external dependency validation warnings (#1124)
* chore(build): clean up external dependency validation warnings Remove 2 unused externals (@opentelemetry/sdk-trace-node, ink) and add 12 missing packages to package.json that are dynamically imported at runtime but weren't declared as dependencies. Also remove the unused @opentelemetry/sdk-trace-node dependency. This eliminates all 13 build validation warnings: - 8 missing OTel exporter deps (http, proto, grpc variants + prometheus) - 4 missing AWS SDK deps (bedrock, bedrock-runtime, sts, credential-providers) - 1 missing Azure dep (@azure/identity) - ink external pointed to local reimplementation, not npm package - sdk-trace-node was declared external but never imported Build validation now passes cleanly with 0 warnings. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * chore(build): eliminate external validation warnings Remove unused @opentelemetry/sdk-trace-node from externals and package.json (it's not imported anywhere in src/). Remove ink from SDK_ONLY_EXTERNALS (the project reimplements ink locally at src/ink/). Add OPTIONAL_RUNTIME_EXTERNALS list for packages that are dynamically imported but intentionally not direct deps — OTel protocol exporters and cloud provider SDKs are resolved from transitive deps or installed by users who need them. Validation now passes with 0 warnings instead of 13. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * feat(telemetry): full OpenTelemetry purge — remove all tracking dependencies Replace all @opentelemetry/* runtime dependencies with no-op stubs, delete OTel-only source modules, and remove 10 @opentelemetry packages from package.json plus @growthbook/growthbook. Key changes: - Delete 5 OTel-only modules (instrumentation, betaSessionTracing, bigqueryExporter, logger, firstPartyEventLoggingExporter) - Replace 9 modules with no-op stubs (sessionTracing, events, telemetryAttributes, firstPartyEventLogger, growthbook, index, sink, datadog, sinkKillswitch, perfettoTracing) - Remove all @opentelemetry/* imports from bootstrap/state.ts, entrypoints/init.ts, and ~20 caller files - Remove all OTel counter types, meter/provider state from state.ts - Clean externals.ts: remove 27 @opentelemetry/* entries - Clean build.ts: remove OTel native-stub namespace exports - Simplify no-telemetry-plugin.ts: remove redundant source-level stubs - Remove 10 @opentelemetry/* + @growthbook/growthbook from package.json - GrowthBook stub reads local ~/.claude/feature-flags.json for overrides Co-Authored-By: OpenClaude (zai-org-glm-5-1) <openclaude@gitlawb.com> * fix format * chore: regenerate lockfile after OTel dependency removal Co-Authored-By: OpenClaude (zai-org-glm-5-1) <openclaude@gitlawb.com> * fix(growthbook): route gate helpers through local flag overrides checkStatsigFeatureGate_CACHED_MAY_BE_STALE() and checkGate_CACHED_OR_BLOCKING() now resolve from ~/.claude/feature-flags.json like getFeatureValue_* does, so gates like tengu_thinkback, tengu_ccr_bridge, and VS Code upsells can be flipped on locally. Security gates (checkSecurityRestrictionGate) remain hard-false. Also adds 5 tests covering gate helper override behavior and unifies JSDoc wording for _getFlagValue-routed functions. Co-Authored-By: OpenClaude (zai-org-glm-5-1) <openclaude@gitlawb.com> --------- Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
7cfc8d5dad |
feat(cli): honor --model alone without requiring --provider (#854)
Closes #808. Today `openclaude --model <name>` is parsed by Commander inside main.tsx but the startup banner and any provider-env-reading code run first, so the override is invisible until request time and saved-profile users see their stale model in the banner. Add applyModelFlagFromArgs that runs after saved-profile env application and before the banner. It routes the value to the env var matching the already-active provider (OPENAI_MODEL / GEMINI_MODEL / MISTRAL_MODEL / ANTHROPIC_MODEL) so the banner, resolution, and request payload all agree. Skipped when --provider is also present; that path is still handled by applyProviderFlagFromArgs. No writes to .openclaude-profile.json — override is process-scoped. |
||
|
|
60c76b6599 |
feat: SDK Runtime — Query Engine, Sessions, and Build Pipeline (#984)
* feat(sdk): add SDK foundation — type declarations, errors, and utilities Adds standalone SDK building blocks with no SDK source dependencies: - sdk.d.ts: ambient type declarations for SDK bundle - coreSchemas.ts + coreTypes.generated.ts: Zod schemas and generated types - errors.ts: SDK-specific error classes - validation.ts: input validation utilities - messageFilters.ts: extracted message filter logic - handlePromptSubmit.ts: imports from messageFilters - 16 generated-types tests * fix(sdk): narrow assertFunction type from broad Function to callable signature Code review finding: assertFunction used `asserts value is Function` which accepts any function-like value without narrowing. Changed to `(...args: any[]) => any` for better type safety. * fix(sdk): update sdk.d.ts header — manually maintained, not generated Reviewer noted the header said "Generated from index.ts" but no generator produces this file. Updated to "Manually maintained — keep in sync with index.ts". Drift detection added in validate-externals.ts (PR 3). * fix(sdk): align sdk.d.ts types with canonical coreTypes.generated.ts Tighten SDK public type contract to resolve reviewer blockers: - PermissionResult: unknown[] → precise 6-shape discriminated union (addRules/replaceRules/removeRules/setMode/addDirectories/removeDirectories) - SDKSessionInfo: snake_case → camelCase (sessionId, lastModified, etc.) - ForkSessionResult: session_id → sessionId - SDKPermissionRequestMessage: uuid + session_id now required - SDKPermissionTimeoutMessage: added uuid + session_id - SessionMessage: parent_uuid → parentUuid - SDKMessage/SDKUserMessage/SDKResultMessage: replaced loose inline definitions with re-exports from coreTypes.generated.ts * feat(sdk): wire existing code modules + SDK shared utilities Modifies core modules for SDK integration: - QueryEngine, tools, state, commands: SDK type hooks - SDK shared utilities (shared.ts, permissions.ts) - 21 SDK tests (shared-utils, permissions) Stack: main ← pr1-foundation ← pr2-sdk-core * feat(sdk): add snake_case ↔ camelCase key mapping utilities casing.ts provides recursive key transformation for the SDK boundary layer. Internal runtime uses snake_case; public API exposes camelCase. Will be used by shared.ts, sessions.ts, query.ts at export boundaries. * test(sdk): add tests for snake_case ↔ camelCase mapping utilities Covers snakeToCamel, camelToSnake, mapKeysToCamel, mapKeysToSnake including nested objects, arrays, null/undefined, and round-trips. * feat(sdk): add SDK runtime — query engine, sessions, build pipeline Completes the SDK implementation: - SDK build target (dist/sdk.mjs) with TUI dependency stubbing - External dependency lists (scripts/externals.ts) - SDK type generation from Zod schemas (scripts/generate-sdk-types.ts) - External validation (scripts/validate-externals.ts) - SDK source: index, query, v2, sessions modules - agentSdkTypes: re-exports SDK functions (query, createSession, etc.) - 136 SDK tests + 7 build scanner tests Stack: main ← pr1-foundation ← pr2-sdk-core ← pr3-sdk-runtime * fix(sdk): align internal SDK types with camelCase public contract shared.ts: SDKSessionInfo, ForkSessionResult, SessionMessage fields now use camelCase matching sdk.d.ts. SDKPermissionRequestMessage and SDKPermissionTimeoutMessage gain required uuid + session_id fields. permissions.ts: onPermissionRequest/onTimeout callbacks now include uuid and session_id in emitted messages. * fix(sdk): update runtime modules to use camelCase field names sessions.ts: toSDKSessionInfo outputs camelCase keys, entryToSessionMessage uses parentUuid, forkSession returns sessionId. query.ts: reads sessionId from listSessions/forkSession results instead of snake_case session_id. * fix(test): update session tests to use camelCase field names session_id → sessionId in forkSession result assertions and getSessionMessages calls. * fix(sdk): prevent permission timeout race condition with once-only resolve wrapper Add createOnceOnlyResolve utility to prevent double-resolution of promises when timeout and host response happen simultaneously. This ensures deterministic behavior in the permission handling flow. * fix(sdk): improve race condition test robustness * fix(sdk): handle consecutive underscores in snakeToCamel conversion Changes: - Use _+([a-z]) regex to match multiple consecutive underscores before letters - Add lookahead (?=. ) to preserve underscore-letter pairs at string end - Handle dunder names (__proto__, __typename) by stripping wrapper and capitalizing - Add tests for consecutive underscores and trailing underscore preservation * fix(sdk): include original error message in permission callback denial When a canUseTool callback throws an error, the catch block now includes the original error message in the denial message, making debugging easier for SDK consumers. * feat(sdk): add optional timeout to env mutex for deadlock prevention Add timeout parameter to acquireEnvMutex() to prevent infinite waits in deadlock scenarios. The timeout is optional and defaults to no timeout (wait forever) for backward compatibility. Returns a MutexAcquireResult object with acquired status and optional timeout reason for failed acquisitions. * fix(sdk): remove timed-out callback from mutex queue to prevent deadlock * test(sdk): add missing error path and timeout scenario tests Add tests for timeout scenarios when host doesn't respond to permission requests, fallback behavior when no onPermissionRequest callback, and MCP connection edge cases for undefined/empty config. * fix(sdk): address code review issues - race conditions, validation, error handling - Add createPermissionTarget() factory that applies onceOnlyResolve at registration time, fixing race condition where timeout and host response could both try to resolve the same promise - Add try-catch to releaseEnvMutex() to prevent permanent lock if callback throws - Extract DEFAULT_PERMISSION_TIMEOUT_MS constant (30 seconds) - Add MCP config validation rejecting null, non-objects, and arrays - Preserve error stack traces in MCP connection failures - Add runtime validation to mapMessageToSDK for null/non-object/invalid type - Update tests to use createPermissionTarget and add validation tests * fix(sdk): syntax fixes and MCP connection error handling - Remove extra closing parenthesis in permissions.ts - Remove extra closing braces in shared.ts type definitions - Wrap MCP connection in try/catch to continue without MCP tools on failure * fix(sdk): syntax fixes, MCP error handling, and logic clarity - Remove extra closing parenthesis in permissions.ts - Remove extra closing braces in shared.ts type definitions - Wrap MCP connection in try/catch to continue without MCP tools on failure - Clarify thinkingConfig logic: use ?? true instead of !== false - Add explanatory comment about thinkingEnabled default behavior - Apply createOnceOnlyResolve wrapper in QueryImpl.registerPendingPermission * fix(sdk): comprehensive error handling and resource cleanup - Add try-catch around injectAgents() to gracefully handle plugin agent tool validation failures (prevents test crashes from unknown 'LS' tool) - Add console.warn logging to agent loading/injection catch blocks for debugging visibility (matches v2.ts pattern) - Add pendingPermissionPrompts.clear() to close() and interrupt() methods in both query.ts and v2.ts to prevent memory accumulation - Add close() method to SDKSession interface and SDKSessionImpl - Wrap MCP connection in query.ts with try-catch (matches v2.ts behavior) - Add timeoutQueue cleanup in finally blocks (query.ts + v2.ts) - Remove error.stack from MCP error messages to prevent internal path leak All 208 SDK tests pass. TypeScript errors are pre-existing. * fix(sdk): address code review non-blocking issues - Add SDKAgentLoadFailureMessage type for agent load failure events - Emit agent definition/injection failures to SDK message stream - Add tool name to permission timeout denial message - Replace 'as any' casts with proper typed state access - Fix supportedCommands to use correct mcp.commands/plugins.commands paths - Update test for correct AppState structure * fix(sdk): address code review blocking and non-blocking issues Blocking Issues Fixed: - MCP cleanup missing on session/query close - now disconnects MCP clients to prevent resource leaks in long-running processes with multiple sessions - Engine reference not cleared on close - now sets _engine = null to prevent memory leaks - Added MCP cleanup tests (9 new tests covering cleanup scenarios) Non-Blocking Issues Fixed: - Removed redundant catch block that just rethrew errors (query.ts) - Fixed inconsistent timeout denial message format (permissions.ts) - Fixed hardcoded tool name 'Bash' in test (permissions.test.ts) - Exported PermissionResolveDecision type for SDK consumers (index.ts) All 217 SDK tests pass. * fix(sdk): address code review type consistency issues - Add close() method to SDKSession interface (documented but missing from type) - Fix SDKSessionInfo, ForkSessionResult, SessionMessage field naming: snake_case → camelCase to match sdk.d.ts public contract and implementation - Add uuid and session_id to SDKPermissionTimeoutMessage for correlation - Fix JSDoc comment in forkSession to use sessionId (not session_id) These changes align internal types (shared.ts) with the public SDK contract (sdk.d.ts) and actual implementation output. The merge from origin/main introduced snake_case types that mismatched camelCase implementation and tests. * fix: restore openclaude.json comment in REPL.tsx Merge |
||
|
|
a46b31c3ec |
feat: SDK Core — Permission System, Async Context, and Engine Extensions (#951)
* feat(sdk): add SDK foundation — type declarations, errors, and utilities
Adds standalone SDK building blocks with no SDK source dependencies:
- sdk.d.ts: ambient type declarations for SDK bundle
- coreSchemas.ts + coreTypes.generated.ts: Zod schemas and generated types
- errors.ts: SDK-specific error classes
- validation.ts: input validation utilities
- messageFilters.ts: extracted message filter logic
- handlePromptSubmit.ts: imports from messageFilters
- 16 generated-types tests
* fix(sdk): narrow assertFunction type from broad Function to callable signature
Code review finding: assertFunction used `asserts value is Function` which
accepts any function-like value without narrowing. Changed to
`(...args: any[]) => any` for better type safety.
* fix(sdk): update sdk.d.ts header — manually maintained, not generated
Reviewer noted the header said "Generated from index.ts" but no generator
produces this file. Updated to "Manually maintained — keep in sync with
index.ts". Drift detection added in validate-externals.ts (PR 3).
* fix(sdk): align sdk.d.ts types with canonical coreTypes.generated.ts
Tighten SDK public type contract to resolve reviewer blockers:
- PermissionResult: unknown[] → precise 6-shape discriminated union
(addRules/replaceRules/removeRules/setMode/addDirectories/removeDirectories)
- SDKSessionInfo: snake_case → camelCase (sessionId, lastModified, etc.)
- ForkSessionResult: session_id → sessionId
- SDKPermissionRequestMessage: uuid + session_id now required
- SDKPermissionTimeoutMessage: added uuid + session_id
- SessionMessage: parent_uuid → parentUuid
- SDKMessage/SDKUserMessage/SDKResultMessage: replaced loose inline
definitions with re-exports from coreTypes.generated.ts
* feat(sdk): wire existing code modules + SDK shared utilities
Modifies core modules for SDK integration:
- QueryEngine, tools, state, commands: SDK type hooks
- SDK shared utilities (shared.ts, permissions.ts)
- 21 SDK tests (shared-utils, permissions)
Stack: main ← pr1-foundation ← pr2-sdk-core
* feat(sdk): add snake_case ↔ camelCase key mapping utilities
casing.ts provides recursive key transformation for the SDK boundary
layer. Internal runtime uses snake_case; public API exposes camelCase.
Will be used by shared.ts, sessions.ts, query.ts at export boundaries.
* test(sdk): add tests for snake_case ↔ camelCase mapping utilities
Covers snakeToCamel, camelToSnake, mapKeysToCamel, mapKeysToSnake
including nested objects, arrays, null/undefined, and round-trips.
* fix(sdk): prevent permission timeout race condition with once-only resolve wrapper
Add createOnceOnlyResolve utility to prevent double-resolution of promises
when timeout and host response happen simultaneously. This ensures
deterministic behavior in the permission handling flow.
* fix(sdk): improve race condition test robustness
* fix(sdk): handle consecutive underscores in snakeToCamel conversion
Changes:
- Use _+([a-z]) regex to match multiple consecutive underscores before letters
- Add lookahead (?=. ) to preserve underscore-letter pairs at string end
- Handle dunder names (__proto__, __typename) by stripping wrapper and capitalizing
- Add tests for consecutive underscores and trailing underscore preservation
* fix(sdk): include original error message in permission callback denial
When a canUseTool callback throws an error, the catch block now
includes the original error message in the denial message, making
debugging easier for SDK consumers.
* feat(sdk): add optional timeout to env mutex for deadlock prevention
Add timeout parameter to acquireEnvMutex() to prevent infinite waits
in deadlock scenarios. The timeout is optional and defaults to no timeout
(wait forever) for backward compatibility.
Returns a MutexAcquireResult object with acquired status and optional
timeout reason for failed acquisitions.
* fix(sdk): remove timed-out callback from mutex queue to prevent deadlock
* test(sdk): add missing error path and timeout scenario tests
Add tests for timeout scenarios when host doesn't respond to permission
requests, fallback behavior when no onPermissionRequest callback, and
MCP connection edge cases for undefined/empty config.
* fix(sdk): address code review issues - race conditions, validation, error handling
- Add createPermissionTarget() factory that applies onceOnlyResolve at
registration time, fixing race condition where timeout and host response
could both try to resolve the same promise
- Add try-catch to releaseEnvMutex() to prevent permanent lock if callback throws
- Extract DEFAULT_PERMISSION_TIMEOUT_MS constant (30 seconds)
- Add MCP config validation rejecting null, non-objects, and arrays
- Preserve error stack traces in MCP connection failures
- Add runtime validation to mapMessageToSDK for null/non-object/invalid type
- Update tests to use createPermissionTarget and add validation tests
* test(sdk): add sequential timeout-then-host-response race condition tests
Adds two tests addressing reviewer request for proof that host response
after SDK timeout is safely handled with no double-resolve or leaked listener:
1. Integration test: stale host resolve called after timeout deny —
verifies no error, no mutation, map cleanup
2. Unit test: raw resolve called exactly once when timeout wins —
directly proves createOnceOnlyResolve prevents second execution
* fix: restore openclaude.json comment in REPL.tsx
Reviewer caught that the comment was incorrectly changed to
~/.claude.json during merge — project has already migrated to
~/.openclaude.json.
* fix(sdk): register pending permission before emitting onPermissionRequest
The previous code emitted onPermissionRequest before calling
registerPendingPermission, so a host responding synchronously from
the callback would find an empty map and its response was lost.
Swap the order so registration happens first.
Adds a regression test for the synchronous host response path.
* fix(sdk): make state setters context-aware for SDK isolation
When running inside runWithSdkContext(), setter functions (regenerateSessionId,
switchSession, setCwdState, setOriginalCwd) now write to the AsyncLocalStorage
context instead of global STATE. This prevents cross-session state leakage in
multi-session SDK scenarios.
Reads were already context-aware; this completes the isolation by making writes
consistent. Outside of SDK context, behavior is unchanged — all writes go to
global STATE as before.
* test(sdk): add context-aware state isolation tests
Tests verify that setters within runWithSdkContext() write to the SDK
context (not global STATE) and that parallel async contexts do not leak
state between sessions. Covers setCwdState, setOriginalCwd,
regenerateSessionId, switchSession, and an end-to-end parallel session
scenario.
* fix(sdk): selective tool schema cache invalidation for multi-engine isolation
Replace global clearToolSchemaCache() in QueryEngine.updateTools() with
selective invalidation that only removes cache entries for tools no longer
in the tool set. This preserves cached schemas for tools that remain,
avoiding unnecessary recomputation for concurrent QueryEngine instances
in multi-session SDK scenarios.
New function invalidateRemovedToolSchemas() handles both simple tool name
keys and schema-variant keys (format: "toolName:{...schemaJSON...}").
* docs(sdk): address PR2 non-blocking documentation and logging issues
- Document request_id vs tool_use_id relationship in shared.ts
(request_id for response correlation, tool_use_id for tracking)
- Add injectable SDKLogger interface to permissions.ts, replacing
direct console.warn calls with logger.warn (hosts can control noise)
- Document Node.js-only AsyncLocalStorage requirement in state.ts
(requires Node.js 12.17.0+ or 14.0.0+)
- Clarify env-mutex is host utility (SDK doesn't mutate process.env)
* fix(sdk): handle throwing onPermissionRequest and fix permission request shape
- Wrap onPermissionRequest in try-catch to clean up pending resolver on throw
- Add uuid and session_id to permission_request message to match SDK schema
- Add regression tests for throwing callback and message shape validation
* fix(sdk): use explicit no-session placeholder for standalone permission prompts
- Add NO_SESSION_PLACEHOLDER constant ('no-session') for permission requests
- Update SDKPermissionRequestMessage doc to explain session_id semantics
- Replace empty string fallback with explicit placeholder
- Add test verifying placeholder behavior when sessionId omitted
* docs(sdk): add example code to permission denial warning
Include canUseTool example in warning message to improve developer
experience and make SDK usage more discoverable for new users.
* fix(sdk): scope parentSessionId to SDK context for parallel isolation
regenerateSessionId({ setCurrentAsParent: true }) was writing to the
process-global STATE.parentSessionId even inside runWithSdkContext(),
allowing one SDK context to overwrite another's parent-session metadata.
Add parentSessionId to the SdkContext type and update both
regenerateSessionId and getParentSessionId to read/write from the
active context when one exists, using an explicit if-else pattern
rather than ?? to avoid undefined fallback leaking across contexts.
The non-SDK CLI path (no active context) continues to use STATE
directly, preserving existing behavior.
---------
Co-authored-by: Ali Alakbarli <ali.alakbarli@users.noreply.github.com>
|
||
|
|
91f93ce615 |
feat: SDK Foundation — Type Declarations, Errors, and Utilities (#866)
* feat(sdk): add SDK foundation — type declarations, errors, and utilities Adds standalone SDK building blocks with no SDK source dependencies: - sdk.d.ts: ambient type declarations for SDK bundle - coreSchemas.ts + coreTypes.generated.ts: Zod schemas and generated types - errors.ts: SDK-specific error classes - validation.ts: input validation utilities - messageFilters.ts: extracted message filter logic - handlePromptSubmit.ts: imports from messageFilters - 16 generated-types tests * fix(sdk): narrow assertFunction type from broad Function to callable signature Code review finding: assertFunction used `asserts value is Function` which accepts any function-like value without narrowing. Changed to `(...args: any[]) => any` for better type safety. * fix(sdk): update sdk.d.ts header — manually maintained, not generated Reviewer noted the header said "Generated from index.ts" but no generator produces this file. Updated to "Manually maintained — keep in sync with index.ts". Drift detection added in validate-externals.ts (PR 3). * fix(sdk): align sdk.d.ts types with canonical coreTypes.generated.ts Tighten SDK public type contract to resolve reviewer blockers: - PermissionResult: unknown[] → precise 6-shape discriminated union (addRules/replaceRules/removeRules/setMode/addDirectories/removeDirectories) - SDKSessionInfo: snake_case → camelCase (sessionId, lastModified, etc.) - ForkSessionResult: session_id → sessionId - SDKPermissionRequestMessage: uuid + session_id now required - SDKPermissionTimeoutMessage: added uuid + session_id - SessionMessage: parent_uuid → parentUuid - SDKMessage/SDKUserMessage/SDKResultMessage: replaced loose inline definitions with re-exports from coreTypes.generated.ts --------- Co-authored-by: Ali Alakbarli <ali.alakbarli@users.noreply.github.com> |
||
|
|
8106880855 |
fix(typecheck): make bun run typecheck actionable on main (#473) (#938)
Issue #473 reported that `bun run typecheck` fails on main with ~4400 errors due to repo-foundation drift, masking branch-specific regressions. Per kevincodex1's guidance ("lets narrow the typecheck scope for now and then we expand step by step") this PR addresses the foundational root causes and brings the error count down 60% so the gate is actionable for branch reviews. Changes: - tsconfig.json: bump target to ES2023 + add lib ["ES2023", "DOM"] so Array.findLast / findLastIndex resolve (kills 41 TS2550 errors). Add `noEmit: true` for typecheck-only mode and `allowImportingTsExtensions: true` (kills 40 TS5097 errors). Set `noImplicitAny: false` because cleaning up TSX-component implicit any is explicitly out of scope per the issue. - src/global.d.ts: ambient declaration for the build-time MACRO global injected by scripts/build.ts via Bun's `define` option (kills 9 TS2304 'Cannot find name MACRO' errors). - src/types/{message,utils,tools}.ts: stubs for the highest-impact missing modules from the partial source snapshot (~21 importers for message alone). Document the snapshot caveat at the top of each stub and reference issue #473 so future readers know they're placeholders. - src/entrypoints/sdk/controlTypes.ts and src/constants/querySource.ts: similar one-file stubs unblocking 18 + 19 importers respectively. - src/entrypoints/agentSdkTypes.ts: append `any`-typed aliases for ~70 SDK names that callers expect on the public surface but that live in stubbed sub-files (PermissionMode, SDKCompactBoundaryMessage, HookEvent, ModelUsage, ModelInfo, etc. — exactly the list from auriti's bug-report enumeration). Verified locally on Linux: - baseline `bunx tsc --noEmit` on stashed main: 4434 errors - with PR applied: 1782 errors (60% drop) - `bun run build`: passes (v0.7.0) - `bun test`: 1632 pass; the 4 remaining failures (StartupScreen, thinking) reproduce on main and are unrelated. - TS2550 (lib): 41 → 0 - TS5097 (.ts imports): 40 → 0 - TS2304 'MACRO': 9 → 0 - TS2307 missing modules: 587 → 325 Remaining errors are localized to specific stubbed modules and can be addressed in smaller follow-up issues, matching the issue's "Definition of done" criterion. |
||
|
|
46a9d3eec4 |
chore: rebrand user-facing copy to OpenClaude (#851)
* chore: rebrand user-facing copy to OpenClaude Replace lingering Claude Code branding in CLI, tips, and runtime UI with OpenClaude/openclaude, including the startup tip Gitlawb mention. Co-Authored-By: Claude GPT-5.4 <noreply@openclaude.dev> * chore: address branding-sweep review feedback - PermissionRequest.tsx: rebrand the two remaining "Claude needs your approval/permission" notifications to OpenClaude (review-artifact and generic tool permission paths). - main.tsx, teleport.tsx, session.tsx, WebFetchTool/utils.ts, skills/bundled/{debug,updateConfig}.ts: replace leftover `claude --…` CLI hints and "Claude Code" labels missed by the original sweep. - main.tsx: drop the inline gitlawb.com marketing copy from the stale-prompt tip; keep it a pure rebrand. - auth.ts: finish the half-rename so both `claude setup-token` and `claude auth login` references in the same error block now read `openclaude …`. - mcp/client.ts: keep `name: 'claude-code'` for MCP server allowlist compatibility (now explicit via comment) and replace the "Anthropic's agentic coding tool" description with an OpenClaude one. - MCPSettings.tsx: point the empty-server-list hint at https://github.com/Gitlawb/openclaude instead of code.claude.com. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: replace help link with OpenClaude repo URL Replace https://code.claude.com/docs/en/overview with https://github.com/Gitlawb/openclaude in the help screen. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> --------- Co-authored-by: Claude GPT-5.4 <noreply@openclaude.dev> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
d45628c413 |
fix(startup): show --model flag override on startup screen (#898)
The startup screen was only reading model from env vars and settings, ignoring the --model CLI flag since it's parsed by Commander.js after the banner prints. Now eagerly parses --model from argv before rendering so the displayed model matches what the session will actually use. |
||
|
|
aab489055c | fix: require trusted approval for sandbox override (#778) | ||
|
|
f828171ef1 | fix: allow provider recovery during startup (#765) | ||
|
|
77083d769b |
Fix/MCP exposure v2 TODO's (#675)
* fix: OAuth tokens secure storage for Windows & Linux * fix(mcp): MCP Tool Re-exposure & Strict Input Validation Fixes the MCP re-exposure bug by correctly handling tool deduplication, input validation with Ajv, and structured output (including images). Also disables experimental API betas by default to prevent 500 errors on external accounts. * fix(mcp): skip official registry prefetch in non-first-party mode Prevents unnecessary calls to Anthropic's MCP registry when using other API providers. * fix(cli): disable experimental API betas by default This prevents 500 errors from Anthropic's API when tool-calling with non-Anthropic accounts or models that don't support certain beta features. * fix: issues raised in the PR review for #675 |