Commit Graph

1718 Commits

Author SHA1 Message Date
Levi Neely fbb2a767f6 session: pause/resume persistence, restore paused sessions without spawning processes
- Skip SetupToolServer for paused sessions during restore
- Pause() and Resume() now persist state to disk
- Resume() sets up tool server from scratch for sessions restored paused
- IsConnected() returns false when paused
- Add SetPaused(), SetToolServer() methods
- ProcessKeeper.SetContext() for resume after pause
- Session index sorts active-first, paused-last
- CreateAgent accepts name= parameter
- Remove duplicate SetCwd method
2026-08-04 16:05:22 +02:00
Levi Neely d200fbad05 refactor: promote remote to session level
- CreateEmpty(name, remote) now spawns remote toolsrv when remote is set
- requestSessionNew parses remote= argument
- Add Session.SetRemote() method
- Update kde submodule
2026-08-04 15:22:18 +02:00
Levi Neely e1b732f09a fix: wire up agent state change events to event bus
SetOnStateChange was defined but never called. Now agents publish
state changes to 'session.{sid}.agent.{aid}.state' which eventwait
can receive.
2026-08-04 14:40:30 +02:00
Levi Neely f21cd99845 fix: eventwait should use BlockOnce, not Stream
eventwait returns a single event then closes, like statewait.
Stream is for continuous data like chat.
2026-08-04 14:39:26 +02:00
Levi Neely 86f7c54805 refactor: rename saveSession/flushSave to save/flush, remove legacy restore
- Rename AgentCfg.SaveSession/FlushSave to Save/Flush for brevity
- Remove restoreLegacySession — all sessions now use multi-agent format
- Pass Save/Flush callbacks to agents in CreateAgent and restore paths
- Add AuditLog fallback warning in NewAgent
2026-08-04 14:38:09 +02:00
Levi Neely f348b968a2 fix: wire up event handler so chat stream receives events
After the fs/session refactor, NewEventHandler was defined but never
called. Agents created via session restore or CreateAgent had nil
output handlers, so emit() was a no-op and the chat stream stayed empty.

- Add Agent.SetOutput() to allow setting the event handler post-creation
- Wire up SetOutput(NewEventHandler(al)) in fs/newroot.go for restored sessions
- Wire up SetOutput(NewEventHandler(al)) in fs/handlers.go for new agents
- Also includes expanded UsageStats fields and TaskState persistence
2026-08-04 14:21:45 +02:00
Levi Neely 3cfbd14203 fix: unify session persistence to preserve name on restart
- flushSave and SaveSession now use PersistSession instead of
  agent.SaveFull, ensuring the multi-agent format with Name field
  is consistently written
- Rename now calls PersistSession immediately so renamed sessions
  survive server restart

The previous approach had two save formats (legacy single-agent via
agent.SaveFull, and new multi-agent via PersistSession) writing to
the same file. Since flushSave ran on every turn, it would overwrite
the Name field with the legacy format that didn't preserve it.
2026-08-04 14:11:14 +02:00
Levi Neely 5a9d605840 fix: persist session name correctly
flushSave and SaveSession were passing empty string instead of
a.Name() as the sessionName argument to agent.SaveFull, causing
the session name to be lost on restart.
2026-08-04 14:08:02 +02:00
Levi Neely 5678ee723a remove: acme backend (cmd/Ollie)
Replaced by the 'o' command which provides a simpler interface.
2026-08-04 14:04:26 +02:00
Levi Neely b1c74d3121 refactor: remove fs/persist.go, inline calls to session package
- Delete fs/persist.go (thin wrappers no longer needed)
- handlers.go: call session.PersistSession() directly
- newroot.go: inline restore logic with AgentLog creation
2026-08-04 14:03:23 +02:00
Levi Neely 4ae1584887 refactor: move persistence to session/, support multi-agent sessions
session/persist.go:
- New multi-agent format: PersistedSession with []PersistedAgent
- PersistSession saves ALL agents, not just first
- RestoreAllSessions returns []RestoredSession with []RestoredAgent
- Backward compatible: restores legacy single-agent format

fs/persist.go:
- Thin wrapper that creates AgentLogs for each restored agent
- Delegates to session.PersistSession/RestoreAllSessions

agent/agent.go:
- Added Messages() to get conversation history
- Added Usage() to get token/cost stats

agent/history.go:
- Added RestoreHistoryFromMessages for multi-agent restore

session/session.go:
- Added Remote() getter
2026-08-04 14:02:15 +02:00
Levi Neely 7fc183c5cb refactor: eliminate Manager type, use package-level session registry
- session/registry.go: package-level vars + functions replace Manager struct
- session.Init() initializes package config
- session.Sessions(), Lookup(), Register(), Kill(), Rename() etc are now top-level
- fs/ calls session.X() directly instead of rs.Manager.X()
- Same thread safety via package-level sync.RWMutex
2026-08-04 13:55:45 +02:00
Levi Neely 2aa7db8445 refactor: split fs/ and session/ packages
session/ now owns all session business logic:
- Manager: session lifecycle (create, kill, rename, lookup)
- CreateAgent: agent creation within sessions
- SetupToolServer, BuildPromptLayers, LoadAutoLoadTools
- PublishEvent for SSE notifications
- NextUname generation

fs/ is now a thin 9P presentation layer:
- SessionNode wraps session.Session, adds AgentLogs and models cache
- RootState caches SessionNodes (GetOrCreateNode pattern)
- Handlers delegate to session.Manager
- persist.go uses session package for restore logic
2026-08-04 13:52:28 +02:00
Levi Neely 757d81a4ba fs: pass sessID and uname to LoadAutoLoadTools for tool server env setup 2026-08-04 13:21:37 +02:00
Levi Neely bf80a63e8a fs: extract session setup, remove dead code and adapter
- Extract SetupToolServer, BuildPromptLayers, LoadAutoLoadTools into setup.go
- Deduplicate session infrastructure setup between CreateAgent and restoreSession
- Delete adapter.go, move HandlerCtx and type aliases into spec.go
- Delete session.go (only contained unused Get/All functions)
- Remove unused: GlobalRootState, PostEvent, LookupByUname, AddSession,
  CreateAgentFromRoot, KillFromRoot, RenameFromRoot, Session.Interrupt,
  Session.SetDisallowTools, Session.RunnableID
- Replace RunnableID() calls with ID()
- Remove comment banners

Net: -131 lines, better DRY compliance
2026-08-04 13:04:31 +02:00
Levi Neely 1f173f1b41 fs: delete redundant tree_test.go (covered by fsedsl) 2026-08-04 12:52:02 +02:00
Levi Neely edc38f7353 fsedsl: simplify README usage section 2026-08-04 12:48:39 +02:00
Levi Neely aaacae40a8 fs: simplify adapter to type aliases only
- Remove wrapper functions from adapter.go (212 → 91 lines)
- Delete redundant adapter_test.go (fsedsl has 94.8% coverage)
- Add local function aliases in spec.go for clean EDSL usage
- Update handlers.go, newroot.go, tree_test.go to use fsedsl directly
- Update fsedsl README with cleaner integration pattern
2026-08-04 12:47:17 +02:00
Levi Neely 19e255c869 fs: remove unnecessary type parameters where inference works
Go can infer [HandlerCtx] from function argument types. Only DirNode
needs explicit type parameter since its args are ...any.
2026-08-04 12:35:50 +02:00
Levi Neely ae6b833d1e fsedsl: remove Adapter, use generic functions directly
The Adapter was pure boilerplate - every method just delegated to the
package-level generic function. Removing it simplifies the API:

- Delete fsedsl/adapter.go
- Update fs/adapter.go to call fsedsl functions directly
- Update README.md to document direct usage
- Remove adapter tests (now redundant)

Coverage remains at 94.8%.
2026-08-04 12:33:03 +02:00
Levi Neely 44f5238538 fsedsl: comprehensive test coverage (95.8%)
- Add tests for Adapter methods (NewAdapter, all wrapper methods)
- Add tests for all NodeOption functions (Stream, BlockOnce, Request,
  CreateFile, RemoveNode, StatOverride, UID, GID, Alias, Bind)
- Add tests for Tree mount/child/split operations
- Add tests for FileConfig methods and mode validation
- Add tests for SyntheticFileInfo and SyntheticEntry
- Add tests for builder delete/rename operations
- Add tests for blocking/streaming read modes in openLeaf
- Add tests for validation panics
- Add tree_test.go for filesystem-backed Tree operations:
  - Create, Delete, Rename, MkdirAll
  - ReadOnly mode enforcement
  - Union directories
  - Child delegation
  - Resolver and opener fallbacks

Coverage improved from 45.5% to 95.8%
2026-08-04 12:27:47 +02:00
Levi Neely 2c8cbe23ca Rename fs/edsl_test.go -> fs/adapter_test.go 2026-08-04 12:15:43 +02:00
Levi Neely 6b5b2830ef Make fsedsl description protocol-agnostic
The EDSL is not specific to 9P - it produces a generic Tree
that works with any filesystem protocol or as in-memory storage.
2026-08-04 12:11:36 +02:00
Levi Neely 0d50898bd7 Fix fsedsl installation instructions
The library is embedded in ollie, not published separately yet.
Document how to use replace directives to import it.
2026-08-04 12:10:01 +02:00
Levi Neely 5ec5f31135 Update fsedsl README with integration guide
- Add step-by-step integration guide for other projects
- Document the adapter pattern with complete examples
- Add API reference with tables for constructors and options
- Document Binding struct and Tree operations
- Link to ollie/fs/adapter.go as real-world example
2026-08-04 12:09:33 +02:00
Levi Neely 94d0c18b01 Rename fs/edsl.go -> fs/adapter.go
The file builds an fsedsl adapter - the name should reflect that.
2026-08-04 12:07:40 +02:00
Levi Neely 6c232c7bb7 Add explicit Adapter pattern to fsedsl
- Add Adapter[Ctx] type that provides all EDSL methods specialized for a context type
- NewAdapter[Ctx]() creates an adapter instance
- Update ollie/fs/edsl.go to use the adapter explicitly
- Update README with adapter-based examples

The adapter makes it explicit that we're building a type-specialized
interface to the generic EDSL library.
2026-08-04 12:06:44 +02:00
Levi Neely b1802ca28c Remove dead code: unused BlockFn type and deprecated BindTarget constants 2026-08-04 12:03:56 +02:00
Levi Neely 882fc598d4 Extract EDSL to fsedsl/ library
- Create fsedsl/ as embedded library with generic types:
  - FsNodeDecl[Ctx], Binding[Ctx], NodeOption[Ctx]
  - BuildTree[Ctx], GenerateHelp[Ctx]
  - Tree, File, FileConfig, SyntheticFileInfo

- Update ollie/fs to use fsedsl via type aliases:
  - type FsNodeDecl = fsedsl.FsNodeDecl[HandlerCtx]
  - Wrapper functions for constructors and options

- Migrate binding functions to Applier pattern:
  - Binding.Applier replaces direct field assignment
  - Cleanly separates EDSL mechanics from domain types

- Add replace directive in go.mod for local module

The library can be extracted to a separate repo later by
changing the module path and removing the replace directive.
2026-08-04 12:02:32 +02:00
Levi Neely 2ae89134d4 update kde submodule: fix ESC stop race condition 2026-08-04 11:51:14 +02:00
Levi Neely a72554f9b1 remove doc/help.md: help is now generated from spec 2026-08-04 11:45:57 +02:00
Levi Neely 3a1c16878f fs: generate /help dynamically from Doc() strings
Add self-documenting filesystem:
- Doc() option on FsNodeDecl for human-readable descriptions
- /help now generated from spec at runtime, not loaded from file
- Every file/directory in spec.go has documentation

Also fix file-template Each nodes:
- Each without children but with Read/Write creates files, not dirs
- Update validator, listDir, statDir to recognize file templates
- Fix elevate/{reqid} and proc/{pid} to use file-template pattern
2026-08-04 11:43:14 +02:00
Levi Neely 0fa9dd5694 fs: remove comment banners
The code structure is self-evident. Banners add noise without value.
2026-08-04 11:32:09 +02:00
Levi Neely 6ea5b54940 fs: add comprehensive documentation to all file nodes
Add Doc() EDSL option and Desc field to FsNodeDecl for self-documenting
filesystem specification. Every file and directory now has a human-readable
description explaining its purpose, format, and usage.

Documentation covers:
- Root-level files (backends, models, agents, tools, ctl, etc.)
- Elevate broker (policy, pending requests)
- Session management (new, idx, per-session files)
- Agent management (prompt, chat, state, config, tools, proc)

This makes spec.go the single source of truth for both structure and
documentation. The Desc field can be used to generate help text or
API documentation programmatically.
2026-08-04 11:30:19 +02:00
Levi Neely b47792d8be fs: restructure package into logical files
Split fs/ package for better organization:
- edsl.go: EDSL types and constructors (HandlerCtx, FsNodeDecl, Binding, etc.)
- cache.go: ModelCache for backend model list caching
- file.go: File/FileTree interfaces (renamed from fs.go)
- handlers.go: all handler functions (extracted from spec.go)
- spec.go: filesystem declaration only

Renames:
- fsnode.go -> edsl.go (consolidated EDSL types)
- fs.go -> file.go (clearer name)
- each_test.go -> edsl_test.go
- fs_test.go -> tree_test.go, renamed TestFlatDir* -> TestTree*

Exports for potential future use:
- RootState (was rootState)
- GlobalRootState() getter
- BuildIndex() (was buildIndex)
2026-08-04 11:27:28 +02:00
Levi Neely ad286834f4 fix template names: {sname} and {aname}
The primary directory name comes from Instance.Name (session/agent name),
not the ID. The ID is just an alias for lookup.
2026-08-04 10:48:46 +02:00
Levi Neely 013d894ad8 rename Dynamic → Each
Each says exactly what it does: for each item in a collection,
create this directory structure.

DirNode, FileNode, Each - the EDSL is now clear and declarative.
2026-08-04 10:47:58 +02:00
Levi Neely 7c6dff4a01 rename EDSL constructors for clarity
- Leaf → FileNode (file node)
- Dir → DirNode (directory node)
- Blueprint → Dynamic (state-dependent directory)

The names now clearly indicate what they create:
- FileNode: a file
- DirNode: a directory
- Dynamic: a directory whose children depend on runtime state
2026-08-04 10:45:28 +02:00
Levi Neely 99e88ef407 add Blueprint pattern unit tests
Test coverage for:
- Basic Blueprint: structure declaration, instance resolution, aliases
- Nested Blueprints: session/{id}/agent/{aid} pattern
- Context propagation: handlers called with bound context
- UID/GID inheritance: custom vs inherited ownership
- Rename callback: instance rename via Rename func
- Empty instances: graceful handling of no instances
- Mixed static/dynamic: Blueprint alongside static children
- File modes: correct permissions on blueprint files

Also fix validation to accept template nodes with Instances (not just List).
2026-08-04 10:38:56 +02:00
Levi Neely 3a920998bd implement Blueprint pattern for EDSL
New EDSL construct: Blueprint(name, instancesFn, ...children)
- Declares static structure in treeSpec
- InstanceFn returns identity info (name, aliases, UID/GID, data binding)
- Handlers access instance data via ctx.Session/Agent/AgentLog
- No more closure captures for session/agent data

Changes:
- Add Instance type and InstanceFn to fsnode.go
- Add Blueprint() constructor
- Update builder.go to handle blueprint node expansion
- Convert session/{id} to Blueprint with sessionInstances
- Convert agent/{aid} to Blueprint with agentInstances
- Convert all handlers to use ctx fields instead of closures

Benefits:
- Full namespace structure visible in treeSpec at top of spec.go
- Handlers are stateless functions (easier to test/reason about)
- Less memory (no closure allocations per instance)
- Cleaner separation: structure vs data binding vs handlers
2026-08-04 10:35:18 +02:00
Levi Neely b6e2f9048b consolidate fs handlers into spec.go
Single source of truth for the 9P namespace:
- Move rootfiles.go handlers into spec.go
- Move sessionfiles.go (listSessions) into spec.go
- Move agentfiles.go (listAgents) into spec.go
- Move procfiles.go (listProcesses) into spec.go
- Move elevatefiles.go handlers into spec.go

The full namespace structure is now visible in one file with
structure comments documenting the layout of dynamic subtrees.

No functional changes - just reorganization.
2026-08-04 10:24:26 +02:00
Levi Neely 66850e822f cleanup: remove dead code from olliesrv
- Remove unused GroupTable.Remove() method, rename Add to Populate
- Remove unused toolPrompt field from Server struct and Config
- Remove unused ModelCache type alias
- Remove unused toolsrv import
- Flatten if true {} blocks (debugging remnants)
- Convert fcallTypeName switch to map lookup
- Remove unused Tree.Unmount() method

-44 lines
2026-08-04 10:19:12 +02:00
Levi Neely 0c6dd5b32a update kde submodule: cleanup debug logging 2026-08-03 20:44:27 +02:00
Levi Neely ae2ee819f1 update kde submodule: fix state role binding 2026-08-03 20:31:25 +02:00
Levi Neely cc5c682109 update kde submodule: targeted state dot updates in render path 2026-08-03 20:29:47 +02:00
Levi Neely d3a7a50845 update kde submodule: fast path for active agent state changes 2026-08-03 20:27:54 +02:00
Levi Neely c5bc73ecd7 update kde submodule: optimize handleEvent() hot path 2026-08-03 20:22:27 +02:00
Levi Neely 65c14ee37b update kde submodule: single-pass session parsing 2026-08-03 20:16:18 +02:00
Levi Neely 8257bf4584 update kde submodule: eliminate C++ calls in QML update loop 2026-08-03 20:13:45 +02:00
Levi Neely 1b0a000a13 update kde submodule: remove per-agent connection polling 2026-08-03 20:11:00 +02:00