Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 2 additions & 50 deletions internal/parser/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,22 +309,6 @@ func ResolveOpenCodeSource(root string) OpenCodeSource {
return resolveOpenCodeFormatSource(openCodeFmt, root)
}

// DiscoverOpenCodeSessions finds all file-backed OpenCode session
// JSON files under storage/session.
func DiscoverOpenCodeSessions(root string) []DiscoveredFile {
return discoverOpenCodeFormatSessions(openCodeFmt, root)
}

// FindOpenCodeSourceFile locates a single OpenCode session source
// path or SQLite backing file by raw session ID. Returns "" when
// the session is not present under this root so the caller
// (Engine.FindSourceFile) can continue searching later configured
// roots — important when an early hybrid root with an unrelated
// opencode.db could otherwise shadow a session in a later root.
func FindOpenCodeSourceFile(root, sessionID string) string {
return findOpenCodeFormatSourceFile(openCodeFmt, root, sessionID)
}

// OpenCodeStorageSessionIDs returns the set of session IDs that
// have a JSON file under storage/session/*/ in the given root.
// Returns nil for non-storage roots. In hybrid roots (storage and
Expand Down Expand Up @@ -353,12 +337,6 @@ func OpenCodeSQLiteVirtualPath(
return dbPath + "#" + sessionID
}

func ParseOpenCodeSQLiteVirtualPath(
sourcePath string,
) (dbPath, sessionID string, ok bool) {
return parseOpenCodeFormatVirtualPath(openCodeFmt.dbName, sourcePath)
}

func openCodeSessionProject(path string) string {
data, err := os.ReadFile(path)
if err == nil {
Expand All @@ -381,14 +359,6 @@ func ResolveKiloSource(root string) OpenCodeSource {
return resolveOpenCodeFormatSource(kiloFmt, root)
}

func DiscoverKiloSessions(root string) []DiscoveredFile {
return discoverOpenCodeFormatSessions(kiloFmt, root)
}

func FindKiloSourceFile(root, sessionID string) string {
return findOpenCodeFormatSourceFile(kiloFmt, root, sessionID)
}

func KiloStorageSessionIDs(root string) map[string]struct{} {
return openCodeFormatStorageSessionIDs(kiloFmt, root)
}
Expand All @@ -401,12 +371,8 @@ func KiloSQLiteVirtualPath(dbPath, sessionID string) string {
return OpenCodeSQLiteVirtualPath(dbPath, sessionID)
}

func ParseKiloSQLiteVirtualPath(
sourcePath string,
) (dbPath, sessionID string, ok bool) {
return parseOpenCodeFormatVirtualPath(kiloFmt.dbName, sourcePath)
}

// ResolveIcodemateSource detects whether an Icodemate root is using
// file-backed storage or legacy SQLite storage.
func ResolveIcodemateSource(root string) OpenCodeSource {
return resolveOpenCodeFormatSource(icodemateFmt, root)
}
Expand Down Expand Up @@ -443,14 +409,6 @@ func ResolveMiMoCodeSource(root string) OpenCodeSource {
return resolveOpenCodeFormatSource(mimoFmt, root)
}

func DiscoverMiMoCodeSessions(root string) []DiscoveredFile {
return discoverOpenCodeFormatSessions(mimoFmt, root)
}

func FindMiMoCodeSourceFile(root, sessionID string) string {
return findOpenCodeFormatSourceFile(mimoFmt, root, sessionID)
}

func MiMoCodeStorageSessionIDs(root string) map[string]struct{} {
return openCodeFormatStorageSessionIDs(mimoFmt, root)
}
Expand All @@ -463,12 +421,6 @@ func MiMoCodeSQLiteVirtualPath(dbPath, sessionID string) string {
return OpenCodeSQLiteVirtualPath(dbPath, sessionID)
}

func ParseMiMoCodeSQLiteVirtualPath(
sourcePath string,
) (dbPath, sessionID string, ok bool) {
return parseOpenCodeFormatVirtualPath(mimoFmt.dbName, sourcePath)
}

// ResolveCodexShallowWatchRoots returns directories that should be watched
// shallowly (root only) for live Codex updates, in addition to the recursive
// watch on the configured sessions root. Codex writes title renames to
Expand Down
29 changes: 5 additions & 24 deletions internal/parser/icodemate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,11 @@ package parser

import "strings"

// Icodemate uses OpenCode's storage format, and is exposed as a distinct
// agent with the icodemate: ID prefix.
func ParseIcodemateFile(
sessionPath, machine string,
) (*ParsedSession, []ParsedMessage, error) {
sess, msgs, err := ParseOpenCodeFile(sessionPath, machine)
if err != nil || sess == nil {
return sess, msgs, err
}
relabelOpenCodeSessionAsIcodemate(sess)
return sess, msgs, nil
}

func ParseIcodemateSession(
dbPath, sessionID, machine string,
) (*ParsedSession, []ParsedMessage, error) {
sess, msgs, err := ParseOpenCodeSession(dbPath, sessionID, machine)
if err != nil || sess == nil {
return sess, msgs, err
}
relabelOpenCodeSessionAsIcodemate(sess)
return sess, msgs, nil
}

// Icodemate uses OpenCode's storage format and is exposed as a distinct
// agent with the icodemate: ID prefix. Discovery and parsing run through
// the shared OpenCode-format provider (openCodeProviderSpecForAgent); the
// helpers below adapt the shared SQLite metadata reader, source mtime, and
// session relabeling to Icodemate.
func ListIcodemateSessionMeta(dbPath string) ([]OpenCodeSessionMeta, error) {
metas, err := ListOpenCodeSessionMeta(dbPath)
if err != nil {
Expand Down
26 changes: 23 additions & 3 deletions internal/parser/icodemate_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package parser

import (
"context"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestParseIcodemateFileRelabelsOpenCodeSession(t *testing.T) {
// TestIcodemateProviderParseRelabelsOpenCodeSession exercises the migrated
// path: IcodeMate is provider-authoritative and reuses the shared
// OpenCode-format provider, which parses the storage session and relabels
// it onto the icodemate: ID prefix.
func TestIcodemateProviderParseRelabelsOpenCodeSession(t *testing.T) {
root := t.TempDir()
sessionPath := filepath.Join(
root, "storage", "session_diff", "global", "ses_icode.json",
Expand Down Expand Up @@ -46,9 +51,24 @@ func TestParseIcodemateFileRelabelsOpenCodeSession(t *testing.T) {
},
})

sess, msgs, err := ParseIcodemateFile(sessionPath, "testmachine")
provider, ok := NewProvider(AgentIcodemate, ProviderConfig{
Roots: []string{root},
Machine: "testmachine",
})
require.True(t, ok)

sources, err := provider.Discover(context.Background())
require.NoError(t, err)
require.NotNil(t, sess)
require.Len(t, sources, 1)

outcome, err := provider.Parse(context.Background(), ParseRequest{
Source: sources[0],
})
require.NoError(t, err)
require.Len(t, outcome.Results, 1)

sess := outcome.Results[0].Result.Session
msgs := outcome.Results[0].Result.Messages
require.Len(t, msgs, 1)

assert.Equal(t, "icodemate:ses_icode", sess.ID)
Expand Down
28 changes: 5 additions & 23 deletions internal/parser/kilo.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,8 @@ package parser
import "strings"

// Kilo uses OpenCode's storage format, but sessions are exposed as a
// distinct agent with the kilo: ID prefix.
func ParseKiloFile(
sessionPath, machine string,
) (*ParsedSession, []ParsedMessage, error) {
sess, msgs, err := ParseOpenCodeFile(sessionPath, machine)
if err != nil || sess == nil {
return sess, msgs, err
}
relabelOpenCodeSessionAsKilo(sess)
return sess, msgs, nil
}

func ParseKiloSession(
dbPath, sessionID, machine string,
) (*ParsedSession, []ParsedMessage, error) {
sess, msgs, err := ParseOpenCodeSession(dbPath, sessionID, machine)
if err != nil || sess == nil {
return sess, msgs, err
}
relabelOpenCodeSessionAsKilo(sess)
return sess, msgs, nil
}
// distinct agent with the kilo: ID prefix. The OpenCode-format provider
// owns parsing and relabels results through relabelOpenCodeSessionAsKilo.

func ListKiloSessionMeta(dbPath string) ([]OpenCodeSessionMeta, error) {
metas, err := ListOpenCodeSessionMeta(dbPath)
Expand All @@ -43,7 +23,9 @@ func KiloSourceMtime(sourcePath string) (int64, error) {
if sourcePath == "" {
return 0, nil
}
if dbPath, sessionID, ok := ParseKiloSQLiteVirtualPath(sourcePath); ok {
if dbPath, sessionID, ok := parseOpenCodeFormatVirtualPath(
kiloFmt.dbName, sourcePath,
); ok {
return openCodeSQLiteSessionMtime(dbPath, sessionID)
}
return openCodeStorageSessionMtime(sourcePath)
Expand Down
49 changes: 35 additions & 14 deletions internal/parser/kilo_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package parser

import (
"context"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestParseKiloFileRelabelsOpenCodeSession(t *testing.T) {
func TestKiloProviderParseRelabelsOpenCodeSession(t *testing.T) {
root := t.TempDir()
sessionPath := filepath.Join(
root, "storage", "session", "global", "ses_kilo.json",
Expand Down Expand Up @@ -46,9 +47,25 @@ func TestParseKiloFileRelabelsOpenCodeSession(t *testing.T) {
},
})

sess, msgs, err := ParseKiloFile(sessionPath, "testmachine")
provider, ok := NewProvider(AgentKilo, ProviderConfig{
Roots: []string{root},
Machine: "testmachine",
})
require.True(t, ok)
source, found, err := provider.FindSource(context.Background(), FindSourceRequest{
FullSessionID: "kilo:ses_kilo",
})
require.NoError(t, err)
require.True(t, found)

outcome, err := provider.Parse(context.Background(), ParseRequest{
Source: source,
Machine: "testmachine",
})
require.NoError(t, err)
require.NotNil(t, sess)
require.Len(t, outcome.Results, 1)
sess := outcome.Results[0].Result.Session
msgs := outcome.Results[0].Result.Messages
require.Len(t, msgs, 1)

assert.Equal(t, "kilo:ses_kilo", sess.ID)
Expand All @@ -58,7 +75,7 @@ func TestParseKiloFileRelabelsOpenCodeSession(t *testing.T) {
assert.Equal(t, "Hello from Kilo", msgs[0].Content)
}

func TestDiscoverKiloSessions(t *testing.T) {
func TestKiloProviderDiscoversSessions(t *testing.T) {
root := t.TempDir()
sessionPath := filepath.Join(
root, "storage", "session", "global", "ses_kilo.json",
Expand All @@ -72,24 +89,28 @@ func TestDiscoverKiloSessions(t *testing.T) {
},
})

files := DiscoverKiloSessions(root)
require.Len(t, files, 1)
provider, ok := NewProvider(AgentKilo, ProviderConfig{Roots: []string{root}})
require.True(t, ok)
sources, err := provider.Discover(context.Background())
require.NoError(t, err)
require.Len(t, sources, 1)

assert.Equal(t, sessionPath, files[0].Path)
assert.Equal(t, "kiloapp", files[0].Project)
assert.Equal(t, AgentKilo, files[0].Agent)
assert.Equal(t, sessionPath, sources[0].DisplayPath)
assert.Equal(t, "kiloapp", sources[0].ProjectHint)
assert.Equal(t, AgentKilo, sources[0].Provider)
}

func TestParseKiloSQLiteVirtualPath(t *testing.T) {
func TestKiloSQLiteVirtualPathRoundTrips(t *testing.T) {
wantDBPath := filepath.Join(t.TempDir(), "kilo.db")
virtual := wantDBPath + "#ses_kilo"
dbPath, sessionID, ok := ParseKiloSQLiteVirtualPath(virtual)
virtual := KiloSQLiteVirtualPath(wantDBPath, "ses_kilo")
dbPath, sessionID, ok := parseOpenCodeFormatVirtualPath(kiloFmt.dbName, virtual)
require.True(t, ok)
assert.Equal(t, wantDBPath, dbPath)
assert.Equal(t, "ses_kilo", sessionID)

_, _, ok = ParseKiloSQLiteVirtualPath(
filepath.Join(t.TempDir(), "opencode.db") + "#ses_kilo",
_, _, ok = parseOpenCodeFormatVirtualPath(
kiloFmt.dbName,
filepath.Join(t.TempDir(), "opencode.db")+"#ses_kilo",
)
assert.False(t, ok)
}
28 changes: 5 additions & 23 deletions internal/parser/mimocode.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,8 @@ import "strings"

// MiMoCode uses OpenCode's storage format, but stores sessions under
// storage/session_diff and is exposed as a distinct agent with the
// mimocode: ID prefix.
func ParseMiMoCodeFile(
sessionPath, machine string,
) (*ParsedSession, []ParsedMessage, error) {
sess, msgs, err := ParseOpenCodeFile(sessionPath, machine)
if err != nil || sess == nil {
return sess, msgs, err
}
relabelOpenCodeSessionAsMiMoCode(sess)
return sess, msgs, nil
}

func ParseMiMoCodeSession(
dbPath, sessionID, machine string,
) (*ParsedSession, []ParsedMessage, error) {
sess, msgs, err := ParseOpenCodeSession(dbPath, sessionID, machine)
if err != nil || sess == nil {
return sess, msgs, err
}
relabelOpenCodeSessionAsMiMoCode(sess)
return sess, msgs, nil
}
// mimocode: ID prefix. The OpenCode-format provider owns parsing and
// relabels results through relabelOpenCodeSessionAsMiMoCode.

func ListMiMoCodeSessionMeta(dbPath string) ([]OpenCodeSessionMeta, error) {
metas, err := ListOpenCodeSessionMeta(dbPath)
Expand All @@ -44,7 +24,9 @@ func MiMoCodeSourceMtime(sourcePath string) (int64, error) {
if sourcePath == "" {
return 0, nil
}
if dbPath, sessionID, ok := ParseMiMoCodeSQLiteVirtualPath(sourcePath); ok {
if dbPath, sessionID, ok := parseOpenCodeFormatVirtualPath(
mimoFmt.dbName, sourcePath,
); ok {
return openCodeSQLiteSessionMtime(dbPath, sessionID)
}
return openCodeStorageSessionMtime(sourcePath)
Expand Down
Loading
Loading