Commit Graph
33 Commits
Author SHA1 Message Date
David Gageot 101a9b39a8 fix(sqlite): avoid WAL journal mode inside docker sandboxes
Assisted-By: Claude
2026-07-09 13:38:08 +02:00
David Gageot 844268da83 fix(memory): open sqlite db under file lock to avoid SQLITE_BUSY races
In ensureDB, OpenDB was called before acquiring the file lock; the first
open of a fresh database converts it to WAL mode which needs an exclusive
lock not covered by busy_timeout, so concurrent first-opens could race.
Moving lock acquisition before OpenDB ensures open + WAL conversion +
schema migration all run under the lock.

Assisted-By: Claude
2026-07-08 15:56:13 +02:00
yunasora 9a985dcbf8 fix(memory): address write serialization review feedback 2026-07-03 18:29:02 +08:00
yunasoraandClaude 8451b7a41d fix(memory): address lint findings for atomic writes
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-03 18:29:02 +08:00
yunasora b1b6e79c4f feat(memory): add cross-process locking and atomic writes for sqlite 2026-07-03 18:29:02 +08:00
David Gageot 69231c755e test: add t.Parallel() to eligible tests
Assisted-By: Claude
2026-06-29 13:39:47 +02:00
David Gageot 994c0806eb refactor(memory): lazy-initialize sqlite database with operation context
Make sqlite.NewMemoryDatabase side-effect-free again: the constructor now records the path only, and the database is opened/migrated lazily from the first ctx-bearing operation. This keeps memory.CreateToolSet as a pure constructor and removes its context.Background root while preserving retry behavior if initialization fails.

Thread context through related DB setup helpers and keep shutdown checkpointing detached via CheckpointAndClose.
2026-06-29 10:17:44 +02:00
David Gageot 0a87da1f97 refactor: thread context through DB and test helper setup
Thread context through sqlite/session/RAG/memory DB setup so constructors and migrations no longer mint fresh roots. Fake proxy cleanup and askpass connection handling now use context providers derived from their startup context. LocalRuntime stores a context provider for tool-change refresh callbacks.

The remaining suppressions are intentionally detached event hooks/MCP supervisor callbacks or compatibility fallbacks.
2026-06-29 10:17:44 +02:00
David Gageot 7ed9f788b8 chore: suppress intentional detached-context roots (Lint/ContextConnectivity)
Annotate the remaining context.Background()/TODO() call sites that are
legitimate independent roots with //rubocop:disable Lint/ContextConnectivity.
These fall into a few categories that cannot (and should not) derive from
the program's root context:

- Bubble Tea event-loop handlers (pkg/tui): Update/Init and tea.Cmd
  callbacks have no context parameter, and appModel deliberately does not
  store the root ctx — threading it would make persistence writes
  cancellable at shutdown.
- runtime.Runtime / interface implementations with fixed signatures
  (remote_runtime, LocalRuntime Steer/FollowUp, accessors).
- Shutdown/flush paths that must outlive the cancelled parent ctx
  (otel providers, HTTP server Shutdown, OAuth callback servers).
- sync.Once / memoized initializers and deliberately detached subprocesses
  (gateway catalog, LSP process, sound, event hooks).
- Test/e2e helpers (pkg/fake, e2e/binary).

No behavior change.
2026-06-29 10:16:55 +02:00
Tomas Dabašinskas 20683a0a4b feat(otel): instrument memory, RAG, sessiontitle, and evaluation
- `pkg/memory/database/sqlite/sqlite.go`: open `memory.{op}` spans on `AddMemory`, `SearchMemories`, etc., with named-return error capture so failures attach to the span via `RecordError`. The search path additionally emits a `retrieval` semconv span for cross-tool dashboards
- `pkg/rag/manager.go`: open `retrieval` (semconv) spans on `Query`, plus `rag.init` / `rag.reindex` / `rag.file_watcher` for lifecycle visibility
- `pkg/sessiontitle/generator.go`: wrap title generation with a `sessiontitle.generate` span; named-return errors fold onto the span on failure
- `pkg/evaluation/judge.go`: emit `gen_ai.evaluation.result` log events from the LLM-as-judge evaluator with score / explanation / error.type, linked to the active span via context for cross-signal join
2026-06-22 12:41:51 +03:00
David Gageot 93986be23d ci: broaden gosec coverage with targeted exclusions and inline silences
Switch gosec from a file-permission allowlist to a broader run that excludes
the systematically noisy rule families and silences the remaining legitimate
exceptions inline.

Excluded rule families (rationale in .golangci.yml):

- G101 (hardcoded credentials): false-positives on tool-name constants and
  shipped public client telemetry keys; secretsscan covers real cases.
- G104 (errors unhandled): errcheck is already enabled and matches the
  patterns we care about; gosec flags many legitimate Close-on-error-path
  callsites.
- G204 (subprocess with variable): docker-agent intentionally launches
  user-configured commands (LSP servers, hooks, agents, editors).
- G304 (file inclusion via variable): paths come from CLI flags, validated
  config, and tempdirs throughout the codebase.
- G404 (weak RNG): math/rand is used for jitter, model selection, and
  spinner animations — never for security.
- G602 (slice bounds): false-positive on dynamically-validated indices.
- G702/G703/G704 (taint analysis): paths, URLs, and commands are derived
  from validated config or user-set environment.

Real fixes uncovered by the broader run:

- pkg/mcp/server.go, pkg/server/server.go: add ReadHeaderTimeout to harden
  against Slowloris (G112).
- pkg/tui/tui.go: explicitly discard ignored Close/Remove return values via
  '_ =' (G104) — better Go style and self-documents the intent.

Inline //nolint:gosec with one-line reasons for the rules we keep enabled:

- G115 (int overflow conversions): bounded values from validated YAML
  schemas and model API constraints — frozen pre-latest config versions
  and the model providers' MaxTokens / ThinkingBudget.
- G117 (JSON 'access_token' marshaling): intentional in OAuth token storage
  and the debug command that prints (truncated) tokens.
- G118 (goroutine context detached): three deliberate fire-and-forget
  patterns — telemetry events, OTel SDK shutdown, and post-request
  StreamStoppedEvent forwarding.
- G201/G202 (SQL formatting/concatenation): rag/strategy queries embed
  internal table names; values are always bound parameters.
- G203 (template HTML auto-escape): pkg/app/export/html.go renders content
  that has already been escaped by sub-templates or is a constant SVG/CSS
  asset embedded at build time.
2026-05-09 15:41:56 +02:00
David Gageot d7e406c9bf Enable modernize and perfsprint linters, fix all findings
Add modernize and perfsprint to .golangci.yml and resolve all lint
issues across 97 files:

- Replace fmt.Errorf with errors.New where no format verbs are used
- Replace fmt.Sprintf(%d) with strconv.Itoa for int conversions
- Replace redundant fmt.Sprintf(%s) with direct string values
- Use slices.Contains instead of manual loops (SkillsConfig.HasLocal)
- Use omitzero instead of omitempty on struct fields (time.Time, SkillsConfig)
- Inline boolPtr helpers to new(bool) and remove unused functions
- Replace string concatenation in loops with strings.Builder
- Use fmt.Fprintf instead of WriteString(fmt.Sprintf(...))

Assisted-By: docker-agent
2026-03-10 11:57:30 +01:00
David Gageot cb001a241b Remove package to github.com/docker/docker-agent
Signed-off-by: David Gageot <david.gageot@docker.com>
2026-03-09 12:04:59 +01:00
NunoandClaude Opus 4.6 b7719a6a0a Address review comments: path traversal, SQL escaping, migration errors, config collisions
- Reject ".." in configNameFromSource to prevent directory traversal
- Escape SQL wildcards (%, _, \) in LIKE patterns with ESCAPE clause
- Only ignore "duplicate column name" errors during migration, surface real failures
- Append short SHA-256 hash of full source path to config name to prevent collisions
  between identically named configs in different directories

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-06 15:55:23 +00:00
NunoandClaude Opus 4.6 c2520db0a0 Fix lint issues: paramTypeCombine, importShadow, gofumpt, testifylint
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-06 15:45:34 +00:00
NunoandClaude Opus 4.6 0633f9e04a Add search, update, categories, and default path to memory tool
- Add search_memories tool (keyword search with AND logic, optional category filter)
- Add update_memory tool (edit existing memories by ID)
- Add optional category field to memories for organization
- Default memory path to ~/.cagent/memory/<config-name>/memory.db (per-user, per-agent-config)
- Make path optional in config validation (was required, now defaults)
- Add configName parameter to ToolsetCreator for per-config-file identity
- SQLite migration adds category column transparently to existing databases
- Expand tool instructions with guidance on search vs get_all, update vs create

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-06 15:26:05 +00:00
David Gageot a1a2764f1b Enable rowserrcheck linter and fix 3 missing rows.Err() checks
Add rows.Err() checks after row iteration loops in:
- memory/database/sqlite/sqlite.go (GetMemories)
- session/migrations.go (GetAppliedMigrations)
- session/store.go (GetSessionSummaries)

These are correctness bugs: without checking rows.Err(), I/O errors
during iteration would be silently ignored.

Assisted-By: cagent
2026-02-06 17:30:28 +01:00
David Gageot c37dfa34d6 fix(sqlite): verify connection in OpenDB
Adds a Ping() call to sqliteutil.OpenDB to ensure the database connection is valid and the file can be opened.

This ensures that file permission or missing directory errors are caught and diagnosed immediately.

Assisted-By: cagent
2026-01-05 07:58:47 +01:00
David Gageot 78c9113fa3 refactor(sqlite): centralize connection logic in pkg/sqliteutil
Creates a new pkg/sqliteutil package to handle SQLite connection opening with consistent pragmas.

Enables foreign key support (_pragma=foreign_keys(1)) globally, fixing ignored cascade deletes in RAG strategies.

Refactors pkg/memory, pkg/session, and pkg/rag to use the new utility.

Fixes a resource leak in NewMemoryDatabase where the connection wasn't closed on table creation failure.

Assisted-By: cagent
2026-01-05 07:46:58 +01:00
David Gageot 897fda38ff fix(sqlite): use _pragma for connection parameters
Updates SQLite connection strings to use _pragma query parameters for busy_timeout and journal_mode configuration in both memory database and session store.

Removes redundant manual file cleanup in sqlite tests.

Assisted-By: cagent
2026-01-05 07:42:45 +01:00
David Gageot 20cb811892 Remove useless comments
Signed-off-by: David Gageot <david.gageot@docker.com>
2025-11-06 19:59:37 +01:00
David Gageot 653070dcba Remove dead code
Signed-off-by: David Gageot <david.gageot@docker.com>
2025-10-20 15:38:34 +02:00
Trung Nguyen 77ae3630cf Fix SQLite database locking issues with concurrent access
Configure SQLite connections with proper concurrency handling to prevent
"database is locked" errors when multiple operations access the database
simultaneously.

Changes:
- Add busy_timeout (5s) to wait for locks instead of failing immediately
- Enable WAL mode for better concurrent read/write performance
- Configure connection pool to serialize writes (SQLite best practice)

Fixes session store and memory database SQLite implementations.
2025-10-17 11:20:05 +02:00
David Gageot cb2be5733b Start adding ouput schemas to builtin tools
Signed-off-by: David Gageot <david.gageot@docker.com>
2025-10-01 17:48:51 +02:00
David Gageot 1c394cc871 Also lint tests
Signed-off-by: David Gageot <david.gageot@docker.com>
2025-09-30 18:35:27 +02:00
CrazyMax 968c0d7d6f switch to modernc.org/sqlite
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2025-09-15 11:52:52 +02:00
David Gageot b7d70acbdb Use t.Context()
Signed-off-by: David Gageot <david.gageot@docker.com>
2025-09-01 17:08:02 +02:00
David Gageot 9e37ffa0a1 Better assertions
Signed-off-by: David Gageot <david.gageot@docker.com>
2025-07-28 15:42:52 +02:00
David Gageot 5d1441a1af Format code
Signed-off-by: David Gageot <david.gageot@docker.com>
2025-07-18 13:37:26 +02:00
Djordje Lukic b5ae4cff7f Rename rumpl/cagent to docker/cagent
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2025-07-17 11:02:24 +02:00
Djordje Lukic 2fa0f6b696 Add tests for sqlite
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2025-06-12 22:59:03 +02:00
Djordje LukicandClaude 6188fa83d4 Fix lint warning: rename SqliteMemoryDatabase to MemoryDatabase
Addresses revive linter warning about stuttering type name.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2025-06-12 17:49:55 +02:00
Djordje LukicandClaude f4e8ddb9b5 Add memory system with SQLite database support
Introduces comprehensive memory management capabilities including:
- Memory database interface with SQLite implementation
- Memory manager for storing and retrieving agent memories
- Memory tool for agent interaction with memory system

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2025-06-12 17:43:35 +02:00