Skip to content

refactor(agent): consolidate Agent model - Phase 1 complete#1894

Merged
yinwm merged 81 commits intomainfrom
refactor/agent
Mar 22, 2026
Merged

refactor(agent): consolidate Agent model - Phase 1 complete#1894
yinwm merged 81 commits intomainfrom
refactor/agent

Conversation

@yinwm
Copy link
Collaborator

@yinwm yinwm commented Mar 22, 2026

Summary

This PR consolidates the Agent refactor from the refactor/agent branch into main. It represents the completion of Phase 1 of the Agent refactor tracked in #1216.

Core Implementations

Module Files Description
Agent abstraction pkg/agent/definition.go AGENT.md format with YAML frontmatter, backward compatible with AGENTS.md
AgentLoop pkg/agent/loop.go, pkg/agent/turn.go Lifecycle management, input/output boundaries, panic recovery
Event model pkg/agent/eventbus.go, pkg/agent/events.go 18 event types for observability
Context management pkg/agent/context.go, pkg/agent/context_budget.go Boundary detection, proactive budget check, safe compression
Hooks pkg/agent/hooks.go, pkg/agent/hook_*.go Event-driven hook system
Steering pkg/agent/steering.go Scoped steering injection
SubTurn pkg/agent/subturn.go Subagent coordination with concurrency control

Workspace Changes

  • AGENTS.mdAGENT.md (new format with YAML frontmatter)
  • IDENTITY.md removed (consolidated into AGENT.md)
  • SOUL.md, USER.md updated for new format

Documentation

  • docs/agent-refactor/README.md
  • docs/agent-refactor/context.md
  • docs/hooks/README.md, docs/hooks/README.zh.md
  • docs/steering.md
  • docs/subturn.md

Merged PRs

Additional Changes

  • Merged main into refactor/agent to include recent updates:
    • WeChat channel (pkg/channels/weixin/)
    • QQ audio duration handling
    • Frontend fixes
  • Fixed flaky gateway tests (TestGatewayStatusReturnsRestartingDuringRestartGap, TestGatewayRestartReturnsErrorStatusWhenReplacementFailsToStart)

Tracking

Resolves #1316
Refs #1216

Remaining Work (Phase 2)

The following tasks have code implemented but need specification documentation:

  • Persona / identity assembly rules documentation
  • Subagent coordination rules documentation

Test plan

  • All existing tests pass
  • Gateway test flakiness fixed
  • Agent package tests cover new functionality

🤖 Generated with Claude Code

afjcjsbx and others added 30 commits March 16, 2026 00:08
* feat(agent): steering

* fix loop

* fix lint

* fix lint
- Replace duplicate types (ToolResult/Session/Message) with real project types
- Implement ephemeralSessionStore satisfying session.SessionStore interface
- Connect runTurn to real AgentLoop via runAgentLoop + AgentInstance
- Fix subturn_test.go to match updated signatures and types

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
…and safe compression

Separate context_window from max_tokens — they serve different purposes
(input capacity vs output generation limit). The previous conflation caused
premature summarization or missed compression triggers.

Changes:
- Add context_window field to AgentDefaults config (default: 4x max_tokens)
- Extract boundary-safe truncation helpers (isSafeBoundary, findSafeBoundary)
  into context_budget.go — pure functions with no AgentLoop dependency
- forceCompression: align split to safe boundary so tool-call sequences
  (assistant+ToolCalls → tool results) are never torn apart
- summarizeSession: use findSafeBoundary instead of hardcoded keep-last-4
- estimateTokens: count ToolCalls arguments and ToolCallID metadata,
  not just Content — fixes systematic undercounting in tool-heavy sessions
- Add proactive context budget check before LLM call in runAgentLoop,
  preventing 400 context-length errors instead of reacting to them
- Add estimateToolDefsTokens for tool definition token cost

Closes #556, closes #665
Ref #1439
Session history (GetHistory) contains only user/assistant/tool messages.
The system prompt is built dynamically by BuildMessages and is never
stored in session. The previous code incorrectly treated history[0] as
a system prompt, skipping the first user message and appending a
compression note to it.

Fix: operate on the full history slice, and record the compression
note in the session summary (which BuildMessages already injects into
the system prompt) rather than modifying any history message.
estimateMessageTokens now counts ReasoningContent (extended thinking /
chain-of-thought) which can be substantial and is persisted in session
history. Media items get a fixed per-item overhead (256 tokens) since
actual cost depends on provider-specific image tokenization.
Add context_window to config.example.json, the web configuration page
(form model, input field, save handler), and i18n strings (en/zh).
The field is optional — leaving it empty falls back to the 4x max_tokens
heuristic.
Add tests that reflect actual session data shape: history starts with
user messages (no system prompt), includes chained tool-call sequences,
reasoning content, and media items. Exercises the proactive budget check
path with BuildMessages-style assembled messages.
Fixes prealloc lint warning by using make() with capacity hint.
Introduce parseTurnBoundaries() which identifies each Turn start index
in the session history. A Turn is a complete "user input → LLM iterations
→ final response" cycle (as defined in the agent refactor design #1316).

findSafeBoundary now uses Turn boundaries instead of raw role-scanning,
making the intent explicit: "find the nearest Turn boundary."

forceCompression drops the oldest half of Turns (not arbitrary messages),
which is simpler and more intuitive. The Turn-based approach naturally
prevents splitting tool-call sequences since each Turn is atomic.
Two estimation bugs fixed:

1. Media tokens were added to the chars accumulator before the chars*2/5
   conversion, resulting in 256*2/5=102 tokens per item instead of 256.
   Fix: add media tokens directly to the final token count, bypassing
   the character-based heuristic.

2. estimateMessageTokens counted both tc.Name and tc.Function.Name for
   tool calls, but providers only send one (OpenAI-compat uses
   function.name, Anthropic uses tc.Name). Fix: count tc.Function.Name
   when Function is present, fall back to tc.Name only otherwise.

Also fix i18n hint text: "auto-detect" was misleading — the backend
uses a 4x max_tokens heuristic, not actual model detection.
When the entire history is a single Turn (one user message followed by
tool calls and responses, no subsequent user message), the only Turn
boundary is at index 0. Previously the fallback returned targetIndex,
which could land on a tool or assistant message — splitting the Turn.

Return 0 instead, so callers (forceCompression, summarizeSession) see
mid <= 0 and skip compression rather than cutting inside the Turn.
Session history only stores user/assistant/tool messages — the system
prompt is built dynamically by BuildMessages. Remove the incorrect
system message from TestAgentLoop_ContextExhaustionRetry test data
to match the real data model that forceCompression operates on.
Document the semantic boundaries of context management as called for
in the agent-refactor README (suggested document split, item 5):

- context window region definitions and history budget formula
- ContextWindow vs MaxTokens distinction
- session history contents (no system prompt stored)
- Turn as the atomic compression unit (#1316)
- three compression paths and their ordering
- token estimation approach and its limitations
- interface boundaries between budget functions and BuildMessages

Also documents known gaps: summarization trigger not using the full
budget formula, heuristic-only token estimation, and reactive retry
not preserving media references.

Ref #1439
- Add subTurnResults sync.Map to AgentLoop for per-session channel tracking
- Add register/unregister/dequeue methods in steering.go
- Poll SubTurn results in runLLMIteration at loop start and after each tool,
  injecting results as [SubTurn Result] messages into parent conversation
- Initialize root turnState in runAgentLoop, propagate via context
  (withTurnState/turnStateFromContext), call rootTS.Finish() on completion
- Wire Spawn Tool to spawnSubTurn via SetSpawner in registerSharedTools,
  recovering parentTS from context for proper turn hierarchy
- Refactor subagent.go to use SetSpawner pattern
- Add TestSubTurnResultChannelRegistration and TestDequeuePendingSubTurnResults
- Add maxConcurrentSubTurns constant (5) and concurrencySem channel to turnState
- Acquire/release semaphore in spawnSubTurn to limit concurrent child turns per parent
- Add activeTurnStates sync.Map to AgentLoop for tracking root turn states by session
- Implement HardAbort(sessionKey) method to trigger cascading cancellation via turnState.Finish()
- Register/unregister root turnState in runAgentLoop for hard abort lookup
- Add TestSubTurnConcurrencySemaphore to verify semaphore capacity enforcement
- Add TestHardAbortCascading to verify context cancellation propagates to child turns
- Add initialHistoryLength field to turnState to snapshot session state at turn start
- Save initial history length in runAgentLoop when creating root turnState
- Implement session rollback in HardAbort via SetHistory, truncating to initial length
- Add TestHardAbortSessionRollback to verify history rollback after abort
- Import providers package in subturn_test.go for Message type

This ensures that when a user triggers hard abort, all messages added during
the aborted turn are discarded, restoring the session to its pre-turn state.
…bTurn

- Fix turnState hierarchy corruption when SubTurns recursively call runAgentLoop
  by checking context for existing turnState before creating new root
- Fix deadlock risk in deliverSubTurnResult by separating lock and channel operations
- Fix session rollback race in HardAbort by calling Finish() before rollback
- Fix resource leak by closing pendingResults channel in Finish() with panic recovery
- Add thread-safety documentation for childTurnIDs and isFinished fields
- Move globalTurnCounter to AgentLoop.subTurnCounter to prevent ID conflicts
- Improve semaphore acquisition to ensure release even on early validation failures
- Document design choice: ephemeral sessions start empty for complete isolation
- Add 5 new tests: hierarchy, deadlock, order, channel close, and semaphore
Critical fixes (5):
- Fix turnState hierarchy corruption in nested SubTurns by checking context
  before creating new root turnState in runAgentLoop
- Fix deadlock risk in deliverSubTurnResult by separating lock and channel ops
- Fix session rollback race in HardAbort by calling Finish() before rollback
- Fix resource leak by closing pendingResults channel in Finish() with recovery
- Add thread-safety docs for childTurnIDs and isFinished fields

Medium priority fixes (5):
- Move globalTurnCounter to AgentLoop.subTurnCounter to prevent ID conflicts
- Improve semaphore acquisition to ensure release even on early validation failures
- Document design choice: ephemeral sessions start empty for complete isolation
- Add final poll before Finish() to capture late-arriving SubTurn results
- Remove duplicate channel registration in spawnSubTurn to fix timing issues

Testing:
- Add 6 new tests covering hierarchy, deadlock, ordering, channel lifecycle,
  final poll, and semaphore behavior
- All 12 SubTurn tests passing with race detector

This resolves 10 critical and medium issues (5 race conditions, 2 resource leaks,
3 timing issues) identified in code review, bringing SubTurn to production-ready state.
- Fix synchronous SubTurn calls placing results in pendingResults channel,
  causing double delivery. Now only async calls (Async=true) use the channel.
- Move deliverSubTurnResult into defer to ensure result delivery even when
  runTurn panics. Add TestSpawnSubTurn_PanicRecovery to verify.
- Fix ContextWindow incorrectly set to MaxTokens; now inherits from
  parentAgent.ContextWindow.
- Add TestSpawnSubTurn_ResultDeliverySync to verify sync behavior.
When the entire session history is a single Turn (e.g. one user message
followed by a massive tool response), findSafeBoundary returns 0 and
forceCompression previously did nothing — leaving the agent stuck in
a context-exceeded retry loop.

Now falls back to keeping only the most recent user message when no
safe Turn boundary exists. This breaks Turn atomicity as a last resort
but guarantees the agent can recover.

Also updates docs/agent-refactor/context.md to document this behavior.

Ref #1490
Major improvements to SubTurn implementation:

**Fixes:**
- Channel close race condition (sync.Once)
- Semaphore blocking timeout (30s)
- Redundant context wrapping
- Memory accumulation (auto-truncate at 50 msgs)
- Channel draining on Finish()
- Missing depth limit logging
- Model validation

**Enhancements:**
- Comprehensive documentation (150+ lines)
- 11 new tests covering edge cases
- Improved error messages

All tests pass. Production-ready.

Related: #1316
…go file

  Created /pkg/agent/turn_state.go (246 lines) containing:
  - turnStateKeyType and context key management
  - turnState struct definition
  - TurnInfo struct and GetActiveTurn() method
  - newTurnState(), Finish(), and drainPendingResults() methods
  - ephemeralSessionStore implementation
  - All context helper functions (withTurnState, TurnStateFromContext, etc.)

  Updated /pkg/agent/subturn.go (428 lines) by:
  - Removing the moved turnState struct and methods
  - Removing unused imports (sync, session)
  - Keeping SubTurn spawning logic, config, events, and result delivery

  All tests pass and the code compiles successfully.
  - Fix context cancellation check order in concurrency timeout
  - Add structured logging for panic recovery
  - Replace println with proper logger for channel full warning
  - Simplify tool registry initialization logic
  - Remove unused ErrConcurrencyLimitExceeded error
Includes JSONL session persistence (#1170), spawn_status tool, Azure provider,
credential encryption, and various fixes. SubTurn features preserved and
integrated with new spawn_status functionality.
finishes early - identified need for Critical+heartbeat+timeout mechanism.
…cycle

Problem:
When parent turn finishes early, all child SubTurns receive "context canceled"
error,because child context was derived from parent context.

Solution:
Implement a lifecycle management system that distinguishes between:
- Graceful finish (Finish(false)): signals parentEnded, children continue
- Hard abort (Finish(true)): immediately cancels all children

Changes:
- turn_state.go:
  - Add parentEnded atomic.Bool to signal parent completion
  - Add parentTurnState reference for IsParentEnded() checks
  - Modify Finish(isHardAbort bool) to distinguish abort types

- subturn.go:
  - Add Critical bool to SubTurnConfig (Critical SubTurns continue after parent ends)
  - Add Timeout time.Duration for SubTurn self-protection
  - Use independent context (context.Background()) instead of derived context
  - SubTurns check IsParentEnded() to decide whether to continue or exit

- loop.go:
  - Call Finish(false) for normal completion (graceful)
  - Add IsParentEnded() check in LLM iteration loop

- steering.go:
  - HardAbort calls Finish(true) to immediately cancel children

Behavior:
- Normal finish: parentEnded=true, children continue, orphan results delivered
- Hard abort: all children cancelled immediately via context
- Critical SubTurns: continue running after parent finishes gracefully
- Non-Critical SubTurns: can exit gracefully when IsParentEnded() returns true
refactor(agent): context boundary detection, proactive budget check, and safe compression
Problem:
During subturn context limit or truncation recoveries, the recovery loops repeatedly
called `runAgentLoop` with the same or modified `UserMessage`. Because `runAgentLoop`
unconditionally adds the `UserMessage` to the session history, this resulted in:
1. Duplicate User Messages polluting the history upon `context_length_exceeded` retries.
2. The possibility of injecting empty User Messages if `opts.UserMessage` was artificially blanked out to work around the duplication.
3. Messy or duplicate entries during `finish_reason="truncated"` recovery injections.

Solution:
- Introduce `SkipAddUserMessage` boolean to `processOptions` to explicitly control whether the agent loop should write the user prompt to history.
- Add an explicit `opts.UserMessage != ""` check in `runAgentLoop` to prevent polluting history with empty message content.
- In `subturn.go`'s recovery loop, set `SkipAddUserMessage: contextRetryCount > 0` to skip writing the user message on context
lppp04808 and others added 15 commits March 21, 2026 18:24
…bus exit

- spawnSubTurn: set result=nil on panic instead of constructing a non-nil ToolResult
- HardAbort: roll back session history to initialHistoryLength after Finish()
- drainBusToSteering: switch to non-blocking reads after first message so function
  returns promptly when the inbound channel is empty
- remove obsolete documentation files
Two gateway tests were flaky due to race conditions:
- TestGatewayStatusReturnsRestartingDuringRestartGap
- TestGatewayRestartReturnsErrorStatusWhenReplacementFailsToStart

The handleGatewayStatus function calls getGatewayHealth which can
override the test's expected status. By mocking gatewayHealthGet
to return an error, the tests now reliably verify the expected
status values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 22, 2026 14:37
@yinwm yinwm mentioned this pull request Mar 22, 2026
7 tasks
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Consolidates Phase 1 of the Agent refactor into main, introducing a structured Agent definition format, an event-driven hook system (in-process + stdio JSON-RPC), and expanded observability/interruptibility primitives (steering, active turn tracking, SubTurn).

Changes:

  • Add hooks configuration + auto-mounting (builtins + external process hooks) with defaults and tests.
  • Introduce turn state tracking / steering improvements and new /subagents command for runtime observability.
  • Update Agent definition loading to support AGENT.md YAML frontmatter with legacy fallback, plus new context budget utilities/docs.

Reviewed changes

Copilot reviewed 43 out of 64 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
pkg/config/config_test.go Adds default + load tests for new hooks config surface.
pkg/config/config.go Introduces HooksConfig, SubTurn defaults, steering mode, and context window settings.
pkg/commands/runtime.go Extends runtime interface to expose active turn info to commands.
pkg/commands/cmd_subagents.go Adds /subagents command for viewing active subagent activity.
pkg/commands/builtin.go Registers the new subagents built-in command.
pkg/agent/turn.go Adds active turn tracking + SubTurn-related state helpers, finishing/abort behavior.
pkg/agent/steering.go Implements scoped steering queues, Continue(), and hard abort behavior.
pkg/agent/loop_test.go Updates context exhaustion test assumptions re: session history composition.
pkg/agent/instance.go Separates ContextWindow from MaxTokens with a default heuristic.
pkg/agent/hooks_test.go Adds tests for in-process hook observation and interception.
pkg/agent/hook_process_test.go Adds integration tests for stdio JSON-RPC process hooks.
pkg/agent/hook_process.go Implements stdio JSON-RPC process hook client and mounting.
pkg/agent/hook_mount_test.go Adds tests for config-driven auto-mounting of builtin/process hooks.
pkg/agent/hook_mount.go Adds hook registry + config-driven auto-mount + env/observe validation helpers.
pkg/agent/events.go Defines structured event kinds + payload types for observability.
pkg/agent/eventbus.go Adds lightweight fan-out event bus with dropped-event metrics.
pkg/agent/definition_test.go Adds tests for AGENT.md frontmatter parsing and legacy fallback behavior.
pkg/agent/definition.go Implements AGENT.md YAML frontmatter parsing + tracked paths for cache invalidation.
pkg/agent/context_cache_test.go Updates cache tests to use AGENT.md instead of IDENTITY.md.
pkg/agent/context_budget.go Adds context budget estimation + safe turn-boundary compression helpers.
pkg/agent/context.go Updates bootstrap loading + cache invalidation to follow new agent definition model.
docs/subturn.md Documents SubTurn semantics, lifecycle, events, and operational constraints.
docs/steering.md Documents scoped steering queues, Continue(), and interrupt behavior.
docs/design/steering-spec.md Design spec for steering queue, bus drain, and loop integration.
docs/design/hook-system-design.zh.md Chinese design doc for hook system layering and IPC strategy.
docs/agent-refactor/context.md Documents context budgeting, compression paths, and token estimation model.
config/config.example.json Adds context_window and hooks example configuration.
cmd/picoclaw/internal/onboard/helpers_test.go Updates onboarding tests for structured agent bootstrap files.
README.zh.md Updates README content but currently contains unresolved merge conflict markers.
README.vi.md Updates README content but currently contains unresolved merge conflict markers.
README.pt-br.md Updates README content but currently contains unresolved merge conflict markers.
README.fr.md Updates README content but currently contains unresolved merge conflict markers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +406 to +413
ts.mu.RLock()
children := append([]string(nil), ts.childTurnIDs...)
ts.mu.RUnlock()
for _, childID := range children {
if val, ok := ts.al.activeTurnStates.Load(childID); ok {
val.(*turnState).Finish(true)
}
}
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

activeTurnStates is keyed by sessionKey in registerActiveTurn, but hard-abort cascading here looks up children by childID (which appears to be a turn ID). This makes cascading abort unreliable (children won't be found, or the wrong entry could be finished). Align the keying strategy (e.g., store turnStates by turnID for all turns, or keep a separate map for turnID → turnState, or ensure childTurnIDs stores the same key used in activeTurnStates).

Suggested change
ts.mu.RLock()
children := append([]string(nil), ts.childTurnIDs...)
ts.mu.RUnlock()
for _, childID := range children {
if val, ok := ts.al.activeTurnStates.Load(childID); ok {
val.(*turnState).Finish(true)
}
}
// We don't rely on the key type of activeTurnStates (which may be session keys);
// instead, we find children by their parentTurnState pointer.
ts.al.activeTurnStates.Range(func(_ any, value any) bool {
childTS, ok := value.(*turnState)
if !ok {
return true
}
if childTS.parentTurnState == ts {
childTS.Finish(true)
}
return true
})

Copilot uses AI. Check for mistakes.
//
// If no steering messages are pending, it returns an empty string.
func (al *AgentLoop) Continue(ctx context.Context, sessionKey, channel, chatID string) (string, error) {
if active := al.GetActiveTurn(); active != nil {
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Continue() currently refuses to run if any active turn exists (since GetActiveTurn() returns the first active turn found). In the new architecture that supports multiple concurrent turns, this can incorrectly block Continue() for an idle session if another session is still active. Consider checking activity for the requested session scope (e.g., GetActiveTurnBySession(sessionKey) or getActiveTurnState(sessionKey)) instead of a global 'any active turn' check.

Suggested change
if active := al.GetActiveTurn(); active != nil {
if active := al.GetActiveTurnBySession(sessionKey); active != nil {

Copilot uses AI. Check for mistakes.
Comment on lines +478 to +481
// TurnStateFromContext retrieves turnState from context (exported for tools)
func TurnStateFromContext(ctx context.Context) *turnState {
return turnStateFromContext(ctx)
}
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This exported API returns an unexported concrete type (*turnState). That makes the API awkward for external packages and tightly couples them to internal implementation details. Prefer returning an exported interface (e.g., TurnState with only the safe methods) or an exported struct snapshot type, and keep turnState unexported.

Copilot uses AI. Check for mistakes.
ListAgentIDs func() []string
ListDefinitions func() []Definition
GetEnabledChannels func() []string
GetActiveTurn func() any // Returning any to avoid circular dependency with agent package
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning any here forces command handlers to use type assertions and makes the runtime contract ambiguous. A maintainable alternative is to define a small shared struct/interface in pkg/commands (or a tiny pkg/runtime/pkg/observer package) that both commands and agent can depend on without circular imports (e.g., type ActiveTurnView struct { ... } or type ActiveTurnProvider interface { ActiveTurnTree() (string, bool) }).

Copilot uses AI. Check for mistakes.
Comment on lines +379 to +393
done := make(chan error, 1)
go func() {
_, writeErr := ph.stdin.Write(body)
done <- writeErr
}()

select {
case err := <-done:
if err != nil {
return fmt.Errorf("write process hook %q message: %w", ph.name, err)
}
return nil
case <-ctx.Done():
return ctx.Err()
}
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spawning a goroutine per outbound message can become costly under high event/intercept rates, and if ctx is canceled while stdin.Write blocks, the goroutine may linger until the write unblocks. Consider a single dedicated writer goroutine with a buffered channel (or reuse the existing writeMu and perform a direct write with bounded timeouts at higher call sites), so cancellation doesn't create unbounded goroutines.

Suggested change
done := make(chan error, 1)
go func() {
_, writeErr := ph.stdin.Write(body)
done <- writeErr
}()
select {
case err := <-done:
if err != nil {
return fmt.Errorf("write process hook %q message: %w", ph.name, err)
}
return nil
case <-ctx.Done():
return ctx.Err()
}
if _, err := ph.stdin.Write(body); err != nil {
return fmt.Errorf("write process hook %q message: %w", ph.name, err)
}
return nil

Copilot uses AI. Check for mistakes.
README.pt-br.md Outdated
| `picoclaw migrate` | Migrar dados de versões anteriores |
| `picoclaw auth login` | Autenticar com provedores |
| `picoclaw model` | Ver ou trocar o modelo padrão |
=======
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file contains unresolved Git merge conflict markers (<<<<<<<, =======, >>>>>>>). Resolve the conflicts and remove all markers.

Suggested change
=======

Copilot uses AI. Check for mistakes.
README.pt-br.md Outdated
| `picoclaw status` | Mostrar status |
| `picoclaw cron list` | Listar todas as tarefas agendadas |
| `picoclaw cron add ...` | Adicionar uma tarefa agendada |
>>>>>>> refactor/agent
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file contains unresolved Git merge conflict markers (<<<<<<<, =======, >>>>>>>). Resolve the conflicts and remove all markers.

Suggested change
>>>>>>> refactor/agent

Copilot uses AI. Check for mistakes.
README.fr.md Outdated

**Lisez `https://clawdchat.ai/skill.md` et suivez les instructions pour rejoindre [ClawdChat.ai](https://clawdchat.ai)**

<<<<<<< HEAD
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file contains unresolved Git merge conflict markers (<<<<<<<, =======, >>>>>>>). Resolve conflicts and remove all markers prior to merge.

Suggested change
<<<<<<< HEAD

Copilot uses AI. Check for mistakes.
README.fr.md Outdated
| `picoclaw migrate` | Migrer les données des anciennes versions |
| `picoclaw auth login` | S'authentifier auprès des fournisseurs |
| `picoclaw model` | Voir ou changer le modèle par défaut |
=======
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file contains unresolved Git merge conflict markers (<<<<<<<, =======, >>>>>>>). Resolve conflicts and remove all markers prior to merge.

Suggested change
=======

Copilot uses AI. Check for mistakes.
README.fr.md Outdated
| `picoclaw status` | Afficher le statut |
| `picoclaw cron list` | Lister toutes les tâches planifiées |
| `picoclaw cron add ...` | Ajouter une tâche planifiée |
>>>>>>> refactor/agent
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file contains unresolved Git merge conflict markers (<<<<<<<, =======, >>>>>>>). Resolve conflicts and remove all markers prior to merge.

Suggested change
>>>>>>> refactor/agent

Copilot uses AI. Check for mistakes.
@sipeed-bot sipeed-bot bot added type: enhancement New feature or request domain: agent labels Mar 22, 2026
yinwm added 4 commits March 22, 2026 22:41
Use main branch versions which have complete content.
The model command was missing from the README CLI Reference table.
- Add `picoclaw model` command to English README
- Add `picoclaw model` command to Indonesian README

All other translations already had the command.
@yinwm yinwm merged commit 4d84bd9 into main Mar 22, 2026
4 checks passed
@yinwm yinwm deleted the refactor/agent branch March 22, 2026 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Agent refactor] Event-driven agent loop with hooks, interrupts, and steering

6 participants