9p: add chat.search file for block lookup by ID
Write a block ID to chat.search, read the block content back. Returns error if block not found.
This commit is contained in:
parent
46aa901763
commit
c8f42b2400
|
|
@ -7,6 +7,7 @@
|
|||
package agent
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
|
@ -99,6 +100,43 @@ func (ag *Agent) ChatRead(base string) ([]byte, string, error) {
|
|||
return data, fmt.Sprintf("%d", newOffset), nil
|
||||
}
|
||||
|
||||
// ChatSearchByID returns the block content for the given block ID.
|
||||
// Returns the block text (without markers) and true if found, empty and false otherwise.
|
||||
func (ag *Agent) ChatSearchByID(blockID string) ([]byte, bool) {
|
||||
if blockID == "" {
|
||||
return nil, false
|
||||
}
|
||||
ag.chatMu.RLock()
|
||||
log := ag.chatLog
|
||||
ag.chatMu.RUnlock()
|
||||
|
||||
// Parse blocks looking for the target ID
|
||||
// Format: [[[role:name#id]]] ... [[[end]]]
|
||||
target := "#" + blockID + "]]]"
|
||||
idx := bytes.Index(log, []byte(target))
|
||||
if idx < 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Find the start of this block header
|
||||
headerStart := bytes.LastIndex(log[:idx], []byte("[[["))
|
||||
if headerStart < 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Find [[[end]]] after the header
|
||||
endMarker := []byte("[[[end]]]")
|
||||
endIdx := bytes.Index(log[idx:], endMarker)
|
||||
if endIdx < 0 {
|
||||
return nil, false
|
||||
}
|
||||
blockEnd := idx + endIdx + len(endMarker)
|
||||
|
||||
// Extract block including header and end marker
|
||||
block := log[headerStart:blockEnd]
|
||||
return block, true
|
||||
}
|
||||
|
||||
// --- Plan methods ---
|
||||
|
||||
// Plan returns a copy of the plan.
|
||||
|
|
|
|||
|
|
@ -851,8 +851,19 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
|
|||
return data, nil
|
||||
}),
|
||||
virtfs.Stream(a.ChatRead, a.ChatSignal),
|
||||
),
|
||||
virtfs.FileNode("state", 0444, // world-readable (non-sensitive)
|
||||
),
|
||||
virtfs.FileNode("chat.search", 0660, // rdwr - write blockId, read block
|
||||
virtfs.Doc("Search chat by block ID. Write ID, read block content."),
|
||||
virtfs.Rdwr(func(_ context.Context, data []byte) ([]byte, error) {
|
||||
blockID := strings.TrimSpace(string(data))
|
||||
block, found := a.ChatSearchByID(blockID)
|
||||
if !found {
|
||||
return nil, fmt.Errorf("block not found: %s", blockID)
|
||||
}
|
||||
return block, nil
|
||||
}),
|
||||
),
|
||||
virtfs.FileNode("state", 0444, // world-readable (non-sensitive)
|
||||
virtfs.Doc("Current agent state (idle, calling, thinking, paused)"),
|
||||
virtfs.Read(func() ([]byte, error) {
|
||||
return []byte(a.State() + "\n"), nil
|
||||
|
|
|
|||
Loading…
Reference in New Issue