Unify locking strategy across the project by using a custom synchronous
file lock (exclusive-create based, with PID stale detection) instead of
the proper-lockfile dependency, matching the pattern in session-write-lock.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace single-retry with while loop that exhausts all candidate profiles
- Add "format" detection to classifyError (400, malformed, bad request, schema)
- Make timeout errors rotatable (some providers hang on rate limit)
- Export classifyError and isRotatableError for testing
- Add error-classification.test.ts with coverage for all failure reasons
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add proper-lockfile for concurrent-safe store updates with fallback
- Add "format" to AuthProfileFailureReason
- Two-level round-robin sort: credential type priority (OAuth > API key), then lastUsed
- Filter out profiles with missing/invalid credentials from candidates
- Add preferredProfile option to resolveAuthProfileOrder
- Export coerceStore and ensureAuthStoreFile for testing
- Add store.test.ts with coerceStore, load/save round-trip, corruption handling
- Update order.test.ts mocks for resolver and registry dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Port from OpenClaw:
- session-write-lock: file-level write lock with atomic creation, reference
counting, stale lock detection, and process cleanup handlers
- session-file-repair: auto-detect and repair malformed JSONL lines with
backup and atomic rename
- session-transcript-repair: fix tool call/result pairing issues including
displaced results, duplicates, orphans, and missing inputs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add minLength:1 to sessions_spawn task parameter to prevent empty
task strings. Remove parentSessionId from AgentOptions as the
subagent registry tracks lineage via requesterSessionId.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Call initSubagentRegistry() after setHub() in Hub constructor to
restore persisted runs. Call shutdownSubagentRegistry() before
closing agents in shutdown() to mark active runs as ended.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace for-await stream consumption in watchChildAgent with
waitForIdle() + onClose() callbacks on AsyncAgent. This prevents
conflict with Hub.consumeAgent() which also reads the Channel.
Add shutdownSubagentRegistry() for clean Hub shutdown, guard
Hub access with isHubInitialized(), and clean resumedRuns in sweep.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extend credentials.ts with llm.order and listProfileIdsForProvider.
Add resolveApiKeyForProfile and resolveApiKeyForProvider to resolver.
Modify runner to support dynamic API key swapping and automatic
rotation on auth/rate_limit/billing errors with retry.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement multi-profile auth system with exponential-backoff cooldowns,
modeled after OpenClaw's auth-profiles system. Includes types, constants,
persistent store (auth-profiles.json), usage tracking with cooldown
calculation, and profile ordering with round-robin and explicit modes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Register sessions_spawn tool in the tool system with TypeBox schema.
Subagents are blocked from spawning nested subagents via both tool
policy (DEFAULT_SUBAGENT_TOOL_DENY) and runtime guard. Add group:subagent
tool group and parentSessionId to AgentOptions.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add global Hub singleton for cross-module access by subagent tools.
Add createSubagent() method to Hub for spawning ephemeral child agents
with isSubagent flag and custom system prompts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement subagent registry, persistence store, and announcement flow
for child agent lifecycle management. Includes types, registry with
auto-archive sweeper, session JSONL reading for result extraction,
and formatted announcement message delivery.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Only forward message_start/update/end (assistant role) and
tool_execution_start/end to clients. Drop agent_start, agent_end,
turn_start, turn_end, and tool_execution_update at the Hub layer.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Next.js MetadataRoute.Manifest types only accept single-value purpose
fields, not space-separated combinations like "any maskable".
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enable the web app to be installed as a standalone PWA on mobile and
desktop. Uses Next.js built-in Metadata API for manifest generation,
a lightweight service worker for navigation offline fallback, and
proper Apple Web App metadata for iOS support.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Expose PiAgentCore events through the full backend pipeline:
- Agent.subscribe() transparently forwards engine events
- AsyncAgent pushes all AgentEvent into Channel alongside error Messages
- Hub discriminates ChannelItem and forwards events via StreamAction
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove template boilerplate (sample SVGs, test IPC message, comments),
add react-router-dom v7 with createHashRouter, scaffold home and chat
pages using @multica/ui components, and add READMEs for desktop, ui,
and store packages documenting import conventions.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add /model command to interactively switch models:
- /model: Show current model and list available models for provider
- /model <name>: Switch to specified model (preserves session)
Example usage:
/model # Shows claude-opus-4-5, claude-sonnet-4-5, etc.
/model claude-sonnet-4-5 # Switch to sonnet model
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move src/agent/oauth/ to src/agent/providers/oauth/ (parent-child structure)
- Delete deprecated oauth/providers.ts re-export file
- Simplify Claude model names: claude-opus-4-5 (without date suffix)
- Update Codex models to current lineup (gpt-5.2, gpt-5.1-codex, etc.)
- Set claude-opus-4-5 as default model for claude-code provider
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create src/agent/providers/ with registry.ts and resolver.ts
- registry.ts: Provider metadata, status checking, login instructions
- resolver.ts: API key resolution, model resolution
- oauth/providers.ts now re-exports from providers/ (deprecated)
- tools.ts: Remove PROVIDER_ALIAS and DEFAULT_MODELS (moved to providers/)
- Update imports in runner.ts and chat.ts
This separates concerns:
- oauth/ only handles OAuth credential reading
- providers/ manages all provider metadata and resolution
Messages store gains streamingIds set and startStream/appendStream/
endStream actions. Gateway store routes stream action payloads to
these new actions. Chat component switches to StreamingMarkdown
for in-progress messages, providing incremental block-level rendering.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AsyncAgent now subscribes to pi-agent-core events (message_start,
message_update, message_end) and forwards incremental text deltas
through a stream callback. Hub registers the callback and sends
stream payloads to the requesting client via Gateway.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add isOAuthProvider() and isProviderAvailable() helpers
- Show login instructions for OAuth providers without credentials
- Show configuration example for API Key providers without keys
- Fail early with helpful error message instead of cryptic API errors
- Add ID column to show actual provider keys for --provider flag
- Add usage examples with actual command syntax
- Improve visual formatting with table headers
- Change package exports from dist/ to src/ (consistent with @multica/store and @multica/ui)
- Add private: true since SDK is an internal monorepo package
- Switch tsconfig from NodeNext to bundler moduleResolution
- Remove .js suffixes from all internal imports for Turbopack compatibility
Eliminates the need to build SDK before running dev server or Next.js build.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The /provider command is now a built-in CLI command in chat.ts,
which directly calls oauth/providers.ts for accurate status.
The skill was redundant and could produce inconsistent results
since it relied on LLM reading files instead of using the API.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Separate OAuth credential reading (external CLI tools) from the main
CredentialManager (API Key configuration in credentials.json5).
- credentials.ts: API Key configuration management
- oauth/: External OAuth credential reading (Claude Code, Codex)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>