f99010fae1
Desktop Artifacts / Desktop Build (Linux) (push) Waiting to run
Desktop Artifacts / Desktop Build (Windows) (push) Waiting to run
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Waiting to run
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
163 lines
4.0 KiB
Go
163 lines
4.0 KiB
Go
package parser
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
var _ Provider = (*cortexProvider)(nil)
|
|
|
|
type cortexProviderFactory struct {
|
|
def AgentDef
|
|
}
|
|
|
|
func newCortexProviderFactory(def AgentDef) ProviderFactory {
|
|
return cortexProviderFactory{def: cloneAgentDef(def)}
|
|
}
|
|
|
|
func (f cortexProviderFactory) Definition() AgentDef {
|
|
return cloneAgentDef(f.def)
|
|
}
|
|
|
|
func (f cortexProviderFactory) Capabilities() Capabilities {
|
|
return cortexProviderCapabilities()
|
|
}
|
|
|
|
func (f cortexProviderFactory) NewProvider(cfg ProviderConfig) Provider {
|
|
cfg = cfg.Clone()
|
|
return &cortexProvider{
|
|
ProviderBase: ProviderBase{
|
|
Def: cloneAgentDef(f.def),
|
|
Caps: cortexProviderCapabilities(),
|
|
Config: cfg,
|
|
},
|
|
sources: newCortexSourceSet(cfg.Roots),
|
|
}
|
|
}
|
|
|
|
type cortexProvider struct {
|
|
ProviderBase
|
|
sources JSONLSourceSet
|
|
}
|
|
|
|
func (p *cortexProvider) Discover(ctx context.Context) ([]SourceRef, error) {
|
|
return p.sources.Discover(ctx)
|
|
}
|
|
|
|
func (p *cortexProvider) WatchPlan(ctx context.Context) (WatchPlan, error) {
|
|
return p.sources.WatchPlan(ctx)
|
|
}
|
|
|
|
func (p *cortexProvider) SourcesForChangedPath(
|
|
ctx context.Context,
|
|
req ChangedPathRequest,
|
|
) ([]SourceRef, error) {
|
|
return p.sources.SourcesForChangedPath(ctx, req)
|
|
}
|
|
|
|
func (p *cortexProvider) FindSource(
|
|
ctx context.Context,
|
|
req FindSourceRequest,
|
|
) (SourceRef, bool, error) {
|
|
return p.sources.FindSource(ctx, ProviderFindRequestWithRawSessionID(p.Def, req))
|
|
}
|
|
|
|
func (p *cortexProvider) Fingerprint(
|
|
ctx context.Context,
|
|
source SourceRef,
|
|
) (SourceFingerprint, error) {
|
|
return p.sources.Fingerprint(ctx, source)
|
|
}
|
|
|
|
func (p *cortexProvider) Parse(
|
|
ctx context.Context,
|
|
req ParseRequest,
|
|
) (ParseOutcome, error) {
|
|
if err := ctx.Err(); err != nil {
|
|
return ParseOutcome{}, err
|
|
}
|
|
path, ok, err := p.sources.pathFromSource(ctx, req.Source)
|
|
if err != nil {
|
|
return ParseOutcome{}, err
|
|
}
|
|
if !ok {
|
|
return ParseOutcome{}, fmt.Errorf("cortex source path unavailable")
|
|
}
|
|
machine := firstNonEmptyJSONLString(req.Machine, p.Config.Machine)
|
|
sess, msgs, err := p.parseSession(path, machine)
|
|
if err != nil {
|
|
return ParseOutcome{}, err
|
|
}
|
|
if sess == nil {
|
|
return ParseOutcome{
|
|
ResultSetComplete: true,
|
|
SkipReason: SkipNoSession,
|
|
}, nil
|
|
}
|
|
if req.Fingerprint.Hash != "" {
|
|
sess.File.Hash = req.Fingerprint.Hash
|
|
}
|
|
return ParseOutcome{
|
|
Results: []ParseResultOutcome{{
|
|
Result: ParseResult{
|
|
Session: *sess,
|
|
Messages: msgs,
|
|
},
|
|
DataVersion: DataVersionCurrent,
|
|
}},
|
|
ResultSetComplete: true,
|
|
}, nil
|
|
}
|
|
|
|
func newCortexSourceSet(roots []string) JSONLSourceSet {
|
|
return NewJSONLSourceSet(AgentCortex, roots,
|
|
WithExtensions(".json"),
|
|
WithFollowSymlinkFiles(),
|
|
WithIncludePath(isCortexSourcePath),
|
|
WithSessionIDFromPath(cortexSessionIDFromPath),
|
|
WithProjectHint(func(root, path string) string { return "" }),
|
|
// Cortex's .history.jsonl sidecar participates in source freshness, so
|
|
// fold it into the shared fingerprint (size, mtime, and content hash)
|
|
// via the framework companion hook instead of a bespoke Fingerprint.
|
|
// WithContentHashing preserves the legacy per-agent file_hash, which a
|
|
// resync would otherwise clear to NULL.
|
|
WithCompanionFiles(func(transcriptPath string) []string {
|
|
return []string{cortexHistoryCompanionPath(transcriptPath)}
|
|
}),
|
|
WithContentHashing(),
|
|
)
|
|
}
|
|
|
|
func isCortexSourcePath(root, path string) bool {
|
|
if !samePath(filepath.Dir(path), filepath.Clean(root)) {
|
|
return false
|
|
}
|
|
return IsCortexSessionFile(filepath.Base(path))
|
|
}
|
|
|
|
func cortexSessionIDFromPath(root, path string) string {
|
|
if !isCortexSourcePath(root, path) {
|
|
return ""
|
|
}
|
|
return strings.TrimSuffix(filepath.Base(path), ".json")
|
|
}
|
|
|
|
func cortexHistoryCompanionPath(path string) string {
|
|
return strings.TrimSuffix(path, ".json") + ".history.jsonl"
|
|
}
|
|
|
|
func cortexProviderCapabilities() Capabilities {
|
|
return Capabilities{
|
|
Source: jsonlFileProviderSourceCapabilities(),
|
|
Content: ContentCapabilities{
|
|
FirstMessage: CapabilitySupported,
|
|
SessionName: CapabilitySupported,
|
|
Cwd: CapabilitySupported,
|
|
ToolCalls: CapabilitySupported,
|
|
ToolResults: CapabilitySupported,
|
|
},
|
|
}
|
|
}
|