mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-05-25 16:00:35 +00:00
15a70ac45c
* feat(seahorse): implement short-term memory engine of seahorse Add pkg/seahorse/ module implementing a SQLite-backed DAG-based summary hierarchy for context management, ported from lossless-claw's LCM design: - types.go + short_constants.go: core types (Message, Summary, Conversation, ContextItem) and configuration constants (fanout, token targets, thresholds) - migration.go: idempotent DB schema with FTS5 trigram tokenizer for CJK - store.go: full SQLite CRUD (conversations, messages, summaries DAG, context_items with ordinal gap numbering, FTS5 search) - short_engine.go: Engine lifecycle (NewEngine, Ingest, Assemble, Compact), session pattern filtering (ignore/stateless glob→regex compilation), per-session mutex via sync.Map - short_assembler.go: budget-aware context assembly with fresh tail protection (32 messages), oldest-first eviction, summary XML formatting, RebuildContextItems - short_compaction.go: leaf compaction (messages→summary) and condensed compaction (summaries→higher-level summary), 3-level LLM escalation, CompactUntilUnder for emergency overflow - short_retrieval.go: lookupByID, FTS5/LIKE search, recursive expand with token cap - context_seahorse.go: agent.ContextManager adapter, registered as "seahorse", provider↔seahorse message type conversion (ToolCalls, tool_result) * fix(seahorse): correct 3 adapter bugs in context management - TokenCount: use full message (Content+ToolCalls+Media) instead of Content-only - Empty Content: rebuild Content from tool_result Parts when stored empty - Duplicate summaries: summaries only in Summary field, not in History messages - Grep: fix SearchResult.Snippet→Content for summaries - Schema: fix FTS5 SQL uses VIRTUAL TABLE not TEMP TABLE - TestFTS5SQLConstants: verify FTS5 SQL syntax correctness - Test: fix flaky TestCompactLeaf * fix(agent): ingest steering messages into seahorse SQLite Steering messages were only persisted to session JSONL but not ingested into seahorse SQLite, causing them to be missing from context assembly. Added `ts.ingestMessage(turnCtx, al, pm)` call in the steering message injection block alongside the existing JSONL persistence. Test: TestSeahorseSteeringMessageIngested verifies steering messages appear in seahorse SQLite DB after being processed. * fix(seahorse): address 3 blocking bugs from code review - Fix resequenceContextItemsTx scan error handling (store.go:850) Changed `return err` to `return scanErr` to properly propagate scan errors instead of returning nil (which silently corrupts data) - Fix sql.NullString for INTEGER column (store.go:847) Changed `mid` from sql.NullString to sql.NullInt64 since message_id is INTEGER in schema. Removed unnecessary strconv.ParseInt call. - Fix compactCondensed fallback deleting non-candidate items Added ReplaceContextItemsWithSummary method for per-item deletion when candidates are not contiguous in ordinal space. Optimized to use range deletion when candidates are consecutive. * fix(seahorse): pass Budget to Compact for correct condensed threshold Issue #4 from PR review: When Budget was not passed to seahorse.Compact, it defaulted to `tokensBefore * 0.75`, making `tokensBefore > budget` always true and causing condensed compaction to trigger unnecessarily. Changes: - context_seahorse.go: Forward Budget from CompactRequest to CompactInput - loop.go: Pass Budget (ContextWindow) in all 3 Compact calls - Add test verifying condensed is skipped when tokens < threshold - Fix lint issues in store.go and store_test.go * fix(seahorse): add mutex for assembler lazy initialization Issue #5 from PR review: The check-then-create pattern for e.assembler was a data race when multiple goroutines called Assemble() concurrently: if e.assembler == nil { e.assembler = &Assembler{...} } Changes: - Add assemblerMu sync.Mutex to Engine struct - Add initAssemblerOnce() using double-checked locking (same pattern as initCompactionOnce) - Add TestAssemblerLazyInitRace to verify thread-safety * fix(seahorse): handle non-consecutive depths in selectShallowestCondensationCandidate Issue #8 from PR review: the loop iterated depth 0, 1, 2... assuming consecutive keys, but break when key was missing caused deeper depths to never be checked. Fix: collect all existing depth keys, sort, then iterate in order. * fix(seahorse): wrap DeleteMessagesAfterID and appendContextItems in transactions - DeleteMessagesAfterID: wrap all DELETE operations in a transaction for atomicity, remove redundant manual FTS delete (handled by trigger) - appendContextItems: use transaction to fix read-then-write race condition - Add GetMaxOrdinalTx and resolveItemTokenCountTx for transaction-scoped queries - Remove unused resolveItemTokenCount function Fixes PR review issues 6 and 7. * fix(seahorse): derive readable content from Parts and cap CompactUntilUnder iterations - Derive readable content from MessageParts in AddMessageWithParts so FTS5 indexing and summary formatting can access tool call information - formatMessagesForSummary and truncateSummary now fall back to Parts when Content is empty, fixing blank summaries for Part-based messages - Add MaxCompactIterations (20) to prevent CompactUntilUnder infinite loops; exceeded iterations are logged as warnings
179 lines
3.5 KiB
YAML
179 lines
3.5 KiB
YAML
version: "2"
|
|
|
|
linters:
|
|
default: all
|
|
disable:
|
|
# TODO: Tweak for current project needs
|
|
- containedctx
|
|
- cyclop
|
|
- depguard
|
|
- dupword
|
|
- err113
|
|
- exhaustruct
|
|
- funcorder
|
|
- gochecknoglobals
|
|
- gosmopolitan # Project legitimately uses CJK text in tests (FTS5, token counting)
|
|
- godot
|
|
- intrange
|
|
- ireturn
|
|
- nlreturn
|
|
- noctx
|
|
- noinlineerr
|
|
- nonamedreturns
|
|
- tagliatelle
|
|
- testpackage
|
|
- varnamelen
|
|
- wrapcheck
|
|
- wsl
|
|
- wsl_v5
|
|
|
|
# TODO: Disabled, because they are failing at the moment, we should fix them and enable (step by step)
|
|
- contextcheck
|
|
- embeddedstructfieldcheck
|
|
- errcheck
|
|
- errchkjson
|
|
- errorlint
|
|
- exhaustive
|
|
- forbidigo
|
|
- forcetypeassert
|
|
- funlen
|
|
- gochecknoinits
|
|
- gocognit
|
|
- goconst
|
|
- gocritic
|
|
- gocyclo
|
|
- godox
|
|
- gosec
|
|
- ineffassign
|
|
- lll
|
|
- maintidx
|
|
- mnd
|
|
- modernize
|
|
- nestif
|
|
- nilnil
|
|
- paralleltest
|
|
- perfsprint
|
|
- revive
|
|
- staticcheck
|
|
- tagalign
|
|
- testifylint
|
|
- thelper
|
|
- unparam
|
|
- usestdlibvars
|
|
- usetesting
|
|
settings:
|
|
gomoddirectives:
|
|
replace-allow-list:
|
|
- github.com/bwmarrin/discordgo
|
|
errcheck:
|
|
check-type-assertions: true
|
|
check-blank: true
|
|
exhaustive:
|
|
default-signifies-exhaustive: true
|
|
funlen:
|
|
lines: 120
|
|
statements: 40
|
|
gocognit:
|
|
min-complexity: 25
|
|
gocyclo:
|
|
min-complexity: 20
|
|
govet:
|
|
enable-all: true
|
|
disable:
|
|
- fieldalignment
|
|
lll:
|
|
line-length: 120
|
|
tab-width: 4
|
|
misspell:
|
|
locale: US
|
|
mnd:
|
|
checks:
|
|
- argument
|
|
- assign
|
|
- case
|
|
- condition
|
|
- operation
|
|
- return
|
|
nakedret:
|
|
max-func-lines: 3
|
|
revive:
|
|
enable-all-rules: true
|
|
rules:
|
|
- name: add-constant
|
|
disabled: true
|
|
- name: argument-limit
|
|
arguments:
|
|
- 7
|
|
severity: warning
|
|
- name: banned-characters
|
|
disabled: true
|
|
- name: cognitive-complexity
|
|
disabled: true
|
|
- name: comment-spacings
|
|
arguments:
|
|
- nolint
|
|
severity: warning
|
|
- name: cyclomatic
|
|
disabled: true
|
|
- name: file-header
|
|
disabled: true
|
|
- name: function-result-limit
|
|
arguments:
|
|
- 3
|
|
severity: warning
|
|
- name: function-length
|
|
disabled: true
|
|
- name: line-length-limit
|
|
disabled: true
|
|
- name: max-public-structs
|
|
disabled: true
|
|
- name: modifies-value-receiver
|
|
disabled: true
|
|
- name: package-comments
|
|
disabled: true
|
|
- name: unused-receiver
|
|
disabled: true
|
|
exclusions:
|
|
generated: lax
|
|
rules:
|
|
- linters:
|
|
- lll
|
|
source: '^//go:generate '
|
|
- linters:
|
|
- funlen
|
|
- maintidx
|
|
- gocognit
|
|
- gocyclo
|
|
path: _test\.go$
|
|
- linters:
|
|
- nolintlint
|
|
path: 'pkg/tools/(i2c\.go|spi\.go)$'
|
|
|
|
issues:
|
|
max-issues-per-linter: 0
|
|
max-same-issues: 0
|
|
|
|
formatters:
|
|
enable:
|
|
- gci
|
|
- gofmt
|
|
- gofumpt
|
|
- goimports
|
|
- golines
|
|
settings:
|
|
gci:
|
|
sections:
|
|
- standard
|
|
- default
|
|
- localmodule
|
|
custom-order: true
|
|
gofmt:
|
|
simplify: true
|
|
rewrite-rules:
|
|
- pattern: "interface{}"
|
|
replacement: "any"
|
|
- pattern: "a[b:len(a)]"
|
|
replacement: "a[b:]"
|
|
golines:
|
|
max-len: 120
|