9p: expose offset file in session directory
Records the byte position of chat EOF immediately before each prompt is submitted. Clients can read offset after a turn completes and use tail -c +$((offset+1)) to extract just the new output without needing a dedicated reply file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e277937619
commit
de1bf9612d
|
|
@ -83,8 +83,9 @@ type session struct {
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
// chatLog is an append-only record of the conversation. Reads are served
|
// chatLog is an append-only record of the conversation. Reads are served
|
||||||
// directly from this buffer by offset, so tail -f works via polling.
|
// directly from this buffer by offset, so tail -f works via polling.
|
||||||
chatLog []byte
|
chatLog []byte
|
||||||
chatVers uint32 // incremented on each append; used as Qid.Vers
|
chatVers uint32 // incremented on each append; used as Qid.Vers
|
||||||
|
chatOffset int // byte position of chat EOF immediately before last prompt submit
|
||||||
// mutableVers tracks changes to tailable mutable-state files
|
// mutableVers tracks changes to tailable mutable-state files
|
||||||
// (state, backend, agent, model, usage, cwd). Bumped on change;
|
// (state, backend, agent, model, usage, cwd). Bumped on change;
|
||||||
// reported via Qid.Vers in stat so tail -f detects truncation/rewrite.
|
// reported via Qid.Vers in stat so tail -f detects truncation/rewrite.
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ var sessionFileList = []struct {
|
||||||
{"enqueue", 0200},
|
{"enqueue", 0200},
|
||||||
{"dequeue", 0444},
|
{"dequeue", 0444},
|
||||||
{"chat", 0444},
|
{"chat", 0444},
|
||||||
|
{"offset", 0444},
|
||||||
{"state", 0444},
|
{"state", 0444},
|
||||||
{"backend", 0666},
|
{"backend", 0666},
|
||||||
{"agent", 0666},
|
{"agent", 0666},
|
||||||
|
|
@ -78,6 +79,8 @@ func (s *SessionFileStore) Get(name string) ([]byte, error) {
|
||||||
copy(data, s.sess.chatLog)
|
copy(data, s.sess.chatLog)
|
||||||
s.sess.mu.RUnlock()
|
s.sess.mu.RUnlock()
|
||||||
return data, nil
|
return data, nil
|
||||||
|
case "offset":
|
||||||
|
return []byte(s.content("offset")), nil
|
||||||
case "dequeue":
|
case "dequeue":
|
||||||
item, ok := s.sess.core.PopQueue()
|
item, ok := s.sess.core.PopQueue()
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -101,6 +104,9 @@ func (s *SessionFileStore) Put(name string, data []byte) error {
|
||||||
}
|
}
|
||||||
switch name {
|
switch name {
|
||||||
case "prompt":
|
case "prompt":
|
||||||
|
s.sess.mu.Lock()
|
||||||
|
s.sess.chatOffset = len(s.sess.chatLog)
|
||||||
|
s.sess.mu.Unlock()
|
||||||
s.sess.core.Submit(s.sess.ctx, input, s.makePublish())
|
s.sess.core.Submit(s.sess.ctx, input, s.makePublish())
|
||||||
s.sess.trackMutable()
|
s.sess.trackMutable()
|
||||||
|
|
||||||
|
|
@ -174,6 +180,8 @@ func (s *SessionFileStore) content(name string) string {
|
||||||
return s.sess.core.ListServers() + "\n"
|
return s.sess.core.ListServers() + "\n"
|
||||||
case "systemprompt":
|
case "systemprompt":
|
||||||
return s.sess.core.SystemPrompt()
|
return s.sess.core.SystemPrompt()
|
||||||
|
case "offset":
|
||||||
|
return fmt.Sprintf("%d\n", s.sess.chatOffset)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Reference in New Issue