- Test release
- Test release
-
60c8ba8: feat(google): Route OAuth requests through Cloud Code API for proper subscription support
When Google OAuth is active, the agent now routes requests through Google's Cloud Code API (
cloudcode-pa.googleapis.com/v1internal) instead of the standard Generative Language API (generativelanguage.googleapis.com).This is the same approach used by the official Gemini CLI and properly supports:
- Google AI Pro/Ultra subscription users
- The
cloud-platformOAuth scope (which is all the OAuth client has registered) - Automatic subscription tier handling (FREE, STANDARD, etc.)
The key insight is that the Gemini CLI doesn't call
generativelanguage.googleapis.comdirectly. Instead, it uses Google's Cloud Code API which:- Accepts
cloud-platformOAuth tokens - Handles subscription tier validation
- Proxies requests to the Generative Language API internally
This fix includes:
- URL transformation from Generative Language API to Cloud Code API
- Request body transformation to Cloud Code API format (wrapping with model/project fields)
- Response body transformation to unwrap Cloud Code API responses
- Streaming response support with proper SSE chunk transformation
- Fallback to API key authentication if Cloud Code API fails
Fixes #100
References:
-
2732471: fix: Resolve 'undefined is not an object (evaluating Log.Default.lazy.info)' error
The error occurred because
Log.Default.lazywas undefined - the Logger interface doesn't have a.lazyproperty. The logging methods (info, debug, warn, error) already support lazy evaluation through callback functions.Changes:
- Fixed
Log.Default.lazy.info()calls in src/index.js to useLog.Default.info()directly - Added backward-compatible
lazyproperty to Logger (self-reference) for any external code using this pattern - Added unit tests for lazy logging callback support
- Fixed
-
c2b3343: fix: Google OAuth 403 restricted_client error from unregistered scopes
When using
agent auth loginwith Google OAuth, users encountered a403: restricted_clienterror with the message "Unregistered scope(s) in the request".Root cause: The
generative-language.tuningandgenerative-language.retrieverOAuth scopes were not registered for the Gemini CLI OAuth client (681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j).This fix removes the unregistered scopes and aligns with the official Gemini CLI implementation, which only uses:
https://www.googleapis.com/auth/cloud-platformhttps://www.googleapis.com/auth/userinfo.emailhttps://www.googleapis.com/auth/userinfo.profile
This fix resolves issue #93 ("agent auth login через Google не работает").
-
52692ba: fix: Google OAuth authentication race condition
Previously, when running
agent auth loginwith Google OAuth, the authentication would fail with a redirect tolocalhost:0because of a race condition in port assignment. The redirect URI was built before the server port was actually assigned.Root cause:
server.listen(0, callback)assigns the port asynchronously in the callback, but the redirect URI was built before the callback fired.Now, when authenticating with Google:
- Port is discovered and assigned before building the redirect URI
- Supports
GOOGLE_OAUTH_CALLBACK_PORTenvironment variable for containers - Follows Google's recommended localhost redirect flow for installed applications
This fix resolves issue #78 ("Не работает авторизация в Google").
-
fe1fff2: feat: Implement JSON lazy logging with log-lazy library
- Added
log-lazydependency from link-foundation for lazy evaluation pattern - Created
src/util/log-lazy.tsmodule for standalone lazy logging with JSON output - Updated
src/util/log.tsto support lazy logging withlazy.{debug,info,warn,error}methods - JSON output wraps all logs in
{ log: { ... } }structure for easy parsing - Logs are written to stderr to avoid mixing with stdout JSON data
- Lazy evaluation prevents expensive string formatting and object serialization when logging is disabled
- Converted existing log calls across the codebase to use lazy pattern for improved performance:
- Session management files (agent.js, compaction.ts, processor.ts, prompt.ts, revert.ts, summary.ts)
- Authentication (claude-oauth.ts, plugins.ts)
- Provider and model handling (provider.ts, models.ts)
- Configuration loading (config.ts)
- File operations (watcher.ts, ripgrep.ts, time.ts)
- MCP client handling (mcp/index.ts)
- Server routing (server.ts)
- Formatting, patching, and project state management
- Added comprehensive tests in tests/log-lazy.test.js
Closes #81
- Added
-
7386896: feat: Add echo and cache synthetic providers for robust dry-run mode
Implements
link-assistant/echoprovider that echoes back user input, andlink-assistant/cacheprovider with Links Notation format for caching API responses. Echo provider is automatically enabled in --dry-run mode for zero-cost testing of round-trips and multi-turn conversations.Closes #89
-
c51e70b: docs: Add interactive mode multi-turn conversation example
Add comprehensive example in
docs/stdin-mode.mdshowing how interactive terminal mode works with multiple sequential inputs.The example demonstrates:
- Initial status message when entering interactive mode
- Complete JSON event stream for two user inputs ("hi" and "who are you?")
- Session persistence across multiple messages
- Plain text input auto-conversion to JSON
- Streaming events (step_start, text, step_finish)
- Token usage tracking in responses
Fixes #86
-
1b83cef: fix: Enable interactive terminal mode when stdin is TTY
Previously, when running
agentin an interactive terminal (TTY), the CLI would immediately show help and exit, not accepting any input. This was a regression from issue #76 fix that treated all TTY connections as "no input expected".Now, when running
agentin a terminal:- Outputs status message indicating interactive terminal mode
- Accepts typed input from the user
- Processes messages in continuous mode with session persistence
- Respects
--verboseand other flags
To get the old behavior (show help and exit), use
--no-always-accept-stdin.Fixes #84
- 5a09d94: feat: Enable continuous listening mode by default
- Add
--always-accept-stdinflag (default: true) for continuous input mode - Add
--compact-jsonflag for machine-to-machine communication - Pretty-print status messages to stderr by default
- Keep session alive between messages for multi-turn conversations
- Handle SIGINT gracefully for clean shutdown
- Add
-
f6f0756: feat: Improve CLI stdin handling with new options and user feedback
- Add
-p/--promptflag to send prompts directly without stdin - Add
--disable-stdinflag to explicitly disable stdin mode - Add
--stdin-stream-timeoutfor optional timeout on stdin reading - Add
--dry-runflag for simulating operations - Output JSON status message when entering stdin listening mode
- Include CTRL+C exit hint and --help guidance
- Show help immediately when running in interactive terminal (TTY)
- Remove default timeout on stdin reading (wait indefinitely by default)
This improves user experience by:
- Never hanging silently - always provide feedback
- Supporting multiple input modes (stdin, direct prompt, help)
- Following CLI best practices from clig.dev guidelines
- Add
-
5680f2e: fix: Add retry logic and serialized installation for reliable provider initialization
Fixes issue #72 where version 0.3.0 appeared "completely broken" due to race conditions in parallel package installations causing Bun cache corruption.
Root Cause:
- When multiple provider packages (e.g., @ai-sdk/openai-compatible, @ai-sdk/openai) are installed concurrently, they can cause race conditions in Bun's package cache
- This leads to "FileNotFound: failed copying files from cache" errors on first run after update
Changes:
- Add write lock to serialize package installations (prevents concurrent bun add commands)
- Add retry logic with up to 3 attempts for cache-related errors
- Improve error detection to catch ENOENT, EACCES, EBUSY errors
- Add delay between retries to allow filesystem operations to complete
Impact:
- opencode/grok-code remains the default provider and works reliably
- Agent handles transient cache issues gracefully with automatic retries
- Better stability during first run after installation/update
-
eb44ccf: Add support for link-assistant-agent branding and improve default model selection
New Features:
- Default model is now
opencode/grok-code(Open Code Zen / Grok Code Fast 1) - Support for
LINK_ASSISTANT_AGENT_*environment variable prefix (backwards compatible withOPENCODE_*) - Support for
.link-assistant-agentconfig directory (backwards compatible with.opencode) - Global config paths now use
link-assistant-agentname
Breaking Changes:
- Global config directory changed from
~/.config/opencode/to~/.config/link-assistant-agent/- Users should manually migrate global configs if needed
Migration:
- Environment variables: New
LINK_ASSISTANT_AGENT_*prefix available; oldOPENCODE_*still works - Project config: Both
.opencode/and.link-assistant-agent/directories supported - Model override: Use
"model": "provider/model-id"in config to override default
- Default model is now
-
d71920e: feat: Add --dry-run mode and enhanced debugging logging
- Added
--dry-runCLI flag to simulate operations without making actual API calls or package installations - Added
OPENCODE_DRY_RUNflag andFlag.setDryRun()function for programmatic control - Enhanced error logging in
BunProc.install()with detailed error messages including stderr/stdout - Enhanced provider initialization logging with detailed context
- Added logging for package installation success/failure
- Added unit tests for dry-run mode functionality
- Improved debugging capabilities to help diagnose package installation failures
Fixes #68
- Added
- 4f5f2a6: Add Google OAuth support for Gemini Pro/Ultra subscriptions
- Implements OAuth 2.0 with PKCE for Google AI subscription authentication
- Uses same public OAuth credentials as official Gemini CLI (installed app flow)
- Adds local HTTP server to automatically capture OAuth redirect
- Supports token refresh with 5-minute expiry buffer
- Zeros out cost tracking for subscription users
- Creates case study documentation in docs/case-studies/issue-66/
- Fixes #66
-
dd0dfdc: Fix empty system message handling for Anthropic OAuth credentials
When using Claude Code OAuth credentials with an empty
--system-message "", the agent now preserves the required "You are Claude Code" header message. This prevents:cache_control cannot be set for empty text blockserrorsThis credential is only authorized for use with Claude Codeerrors
The fix ensures OAuth token authorization works correctly even when users explicitly set an empty system message.
Fixes #62
- 50728b3: fix: Fixed
agent --versioncommand and added logging in--verbosemode- Fixed
--versioncommand that was showing "unknown" instead of the current package version - Added explicit import of
package.jsonusingcreateRequirewith fallback viafs - Added logging of version, command, working directory and script path in
--verbosemode
- Fixed
-
de95398: fix: Pass API key to providers with multiple env var options
Fixes #61 - Error when using google/gemini-3-pro model. When providers have multiple possible environment variables (like Google with GOOGLE_GENERATIVE_AI_API_KEY and GEMINI_API_KEY), the code was finding the API key correctly but then not passing it to mergeProvider.
- 09b6709: Fix GitHub release formatting to remove incorrect title for major/minor/patch versions and properly link related pull requests
-
2bcef5f: Add support for google/gemini-3-pro model alias
- Added
google/gemini-3-proas an alias togemini-3-pro-preview - Updated README.md with Google Gemini usage examples
- Created comprehensive case study in docs/case-studies/issue-53/
- Fixes ProviderModelNotFoundError when using google/gemini-3-pro
This change allows users to use the commonly expected model name
gemini-3-prowhile maintaining compatibility with Google's officialgemini-3-pro-previewidentifier. - Added
- 86f24ac: Add comprehensive image validation to prevent API errors
- Added magic byte validation for PNG, JPEG/JPG, GIF, BMP, WebP, TIFF, SVG, ICO, and AVIF formats
- Prevents "Could not process image" API errors from invalid files
- Added
VERIFY_IMAGES_AT_READ_TOOLenvironment variable for opt-out (enabled by default) - Enhanced error messages with hex dump debugging information
- Comprehensive test suite with 6+ test cases
- Fixes #38 and prevents session crashes from corrupted image files
- 8d3c137: Fix empty string system message override. When --system-message "" is provided, the system now correctly overrides with an empty string instead of falling back to the default system prompt. This was caused by a falsy check (if (input.system)) that evaluated to false for empty strings. Changed to explicit undefined check (if (input.system !== undefined)) to properly distinguish between undefined (use default) and empty string (override with empty).
- 1ace1a9: Add comprehensive Playwright MCP installation instructions to README.md. This includes step-by-step setup guide, complete list of available browser automation tools, usage examples, and links to official documentation. Fixes issue #54.
- 3a5fad7: Fix debug output appearing in CLI commands - logs are now suppressed by default and only shown with --verbose flag. This fixes the issue where commands like
agent auth listdisplayed debug messages that broke the clean CLI UI.
-
07aef38: fix: Use valid placeholder API keys for OAuth providers (Anthropic, GitHub Copilot, OpenAI)
When using
--model anthropic/claude-sonnet-4-5after authenticating withagent auth login(Anthropic > Claude Pro/Max), the command failed withProviderInitErrorat line 732 insrc/provider/provider.ts.The OAuth authentication plugin loaders in
src/auth/plugins.tswere returning empty strings ('') for theapiKeyparameter. The AI SDK providers (e.g.,@ai-sdk/anthropic,@ai-sdk/openai) require a non-emptyapiKeyparameter even when using custom fetch functions for authentication. The empty string failed validation, causing provider initialization to fail.This fix changes the
apiKeyvalue from an empty string to a descriptive placeholder string ('oauth-token-used-via-custom-fetch') for all OAuth loaders (AnthropicPlugin, GitHubCopilotPlugin, and OpenAIPlugin). The placeholder satisfies AI SDK validation requirements while the actual OAuth authentication happens via Bearer tokens in the custom fetch's Authorization header.Fixes #47
- 4b4c0ea: Fix ESC key handling in CLI commands - pressing ESC now exits gracefully without showing error messages or help text
-
c022218: fix: Replace prompts.autocomplete with prompts.select in auth login command
The
agent auth logincommand was failing withTypeError: prompts.autocomplete is not a functionbecause@clack/prompts@0.11.0does not have theautocompletefunction (it was added in v1.0.0-alpha.0).This fix replaces
prompts.autocomplete()withprompts.select()which is available in the stable version.Fixes #43
-
e8e2d03: Fix system message override to use exclusively without additional context for low-limit models. When --system-message flag is provided, the system now returns only that message without adding environment info, custom instructions, or headers. This reduces token usage from ~9,059 to ~30 tokens, enabling support for models with low TPM limits like groq/qwen/qwen3-32b (6K TPM).
Also adds --verbose mode to debug API requests with system prompt content and token estimates.
- 547d73f: Add CI/CD pipeline matching js-ai-driven-development-pipeline-template with changeset support, automated npm publishing, and code quality tools (ESLint, Prettier, Husky)
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.