Documentation
¶
Index ¶
- func ClaudeSessionTitleByID(sessionID string) string
- func CodexSessionTitleByID(sessionID string) string
- func EvictMetaCacheEntry(path string)
- func GrokSessionTitleByID(sessionID string) string
- func InitMetaCache()
- func InitStatsCache()
- func LatestCodexSessionForCwd(cwd string) string
- func LatestGrokSessionForCwd(cwd string) string
- func LatestPiSessionForCwd(cwd string) string
- func MetaCacheCounters() (hits, misses, parses uint64)
- func PiSessionTitleByID(sessionID string) string
- func RegisterSessionTitleResolver(agent string, fn func(sessionID string) string)
- func SessionTitleForAgent(agent, sessionID string) string
- type Known
- type ListResult
- type MetaCache
- type Override
- type Overrides
- type Session
- type Stats
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ClaudeSessionTitleByID ¶
ClaudeSessionTitleByID resolves the AUTHORITATIVE display title of a Claude session from its transcript by session id: custom-title → ai-title → summary ONLY, dropping the first-user-message fallback. Used by the daemon on SessionStart to title a resumed tab. Skipping the fallback is deliberate:// feeding the first prompt here would lock the tab's naming lifecycle (SetSessionTitle → Meaningful=true) and suppress the daemon's AI title derivation (Phase B), leaving the tab stuck on the first prompt. An unnamed session (no custom/ai/summary) returns "" so Phase B derives a meaningful name. The Projects list keeps the fallback via extractCwdAndTitle.
func CodexSessionTitleByID ¶
CodexSessionTitleByID resolves the display title of a Codex rollout by session id (first real user prompt). Confirms the id via readCodexMeta so a coincidental filename suffix can't mis-attribute. Used on SessionStart.
func EvictMetaCacheEntry ¶
func EvictMetaCacheEntry(path string)
EvictMetaCacheEntry drops one entry by transcript path — used by the delete handler when a Claude transcript is removed (path is known). Codex/Grok deletes rely on the background reap-missing sweep (their paths aren't known at delete time). No-op if the path was never cached.
func GrokSessionTitleByID ¶
GrokSessionTitleByID resolves the display title of a Grok session from its summary.json by session id (session_summary). Used on SessionStart.
func InitMetaCache ¶
func InitMetaCache()
InitMetaCache loads the persisted cache into the package singleton and starts the background persist+GC+reap tick. Call once at daemon startup alongside LoadKnown. Idempotent (sync.Once).
func InitStatsCache ¶
func InitStatsCache()
InitStatsCache loads the persisted stats cache into the package map + starts the persist/GC tick. Call once at daemon startup alongside InitMetaCache. Idempotent (sync.Once).
func LatestCodexSessionForCwd ¶
LatestCodexSessionForCwd returns the session id of the most recently modified codex rollout whose session_meta.cwd matches cwd (case-insensitive). Codex stores rollouts at ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl; the first line is {"type":"session_meta","payload":{"id":"<uuid>","cwd":"…"}}. Returns "" if no recent match is found.
func LatestGrokSessionForCwd ¶
LatestGrokSessionForCwd returns the session id of the most recently modified grok session directory under the URL-encoded cwd. Grok stores sessions at ~/.grok/sessions/<url-encoded-cwd>/<session-uuid>/. Returns "" if no recent match is found.
func LatestPiSessionForCwd ¶
LatestPiSessionForCwd returns the session id of the most recently modified pi session whose header cwd matches cwd (case-insensitive), within the discovery recent-cutoff. Hookless-agent discovery (pi has no SessionStart hook) — matches LatestCodex/LatestGrokSessionForCwd. Returns "" if none.
func MetaCacheCounters ¶
func MetaCacheCounters() (hits, misses, parses uint64)
MetaCacheCounters exposes (hits, misses, parses) for the warm-skip / "N devices → 1 parse" acceptance checks + debug.
func PiSessionTitleByID ¶
PiSessionTitleByID resolves the AUTHORITATIVE display name of a pi session from its transcript by session id: the latest session_info.name ONLY (the user/agent-set name), NOT the first-user-message fallback. Used by the daemon on SessionStart to title a tab that just resumed/loaded a session.
Deliberately skips the first-message fallback (unlike readPiMeta, which the Projects list uses for display): feeding the first prompt here would lock the tab's naming lifecycle (SetSessionTitle → Meaningful=true) and suppress the daemon's AI title derivation (Phase B), leaving the tab stuck on the first prompt. An unnamed session returns "" so Phase B derives a meaningful name instead. Returns "" if the file isn't found or has no session_info.name.
func RegisterSessionTitleResolver ¶
RegisterSessionTitleResolver registers a transcript-title resolver for an agent (called from each agent's unified package init). Idempotent; a later registration overrides (useful for tests).
func SessionTitleForAgent ¶
SessionTitleForAgent resolves the display title of an agent's session from its own transcript store, generic over the agent id via the registry. Used by the daemon on SessionStart (after an agent-forwarded name, if any) to title a tab that just loaded/resumed a session, so the tab + Live Now match the Projects list instead of showing the shell name. Returns "" when the agent has no resolver registered or the session has no nameable content.
Types ¶
type Known ¶
type Known struct {
// contains filtered or unexported fields
}
Known is the goroutine-safe set of daemon-owned agent session ids.
func LoadKnown ¶
func LoadKnown() *Known
LoadKnown reads (or initializes) the known-id store from $RMOTE_AGENT_DIR/sessions_known.json. A missing file is not an error — returns an empty store (the backfill then populates it on first run).
func (*Known) BackfillOnce ¶
func (k *Known) BackfillOnce()
BackfillOnce seeds the store with every agent session id currently discoverable on disk, but only on the first run after the known-filter ships (presence of the marker file gates it). This adopts existing history so the Sessions Panel does not go empty when the filter activates. Safe to call at daemon startup; no-op on every subsequent boot.
type ListResult ¶
type ListResult struct {
Sessions []Session `json:"sessions"`
Total int `json:"total"`
Page int `json:"page"`
PerPage int `json:"per_page"`
HasMore bool `json:"has_more"`
ProjectCounts map[string]int `json:"project_counts,omitempty"`
}
ListResult is the response shape for GET /api/sessions/unified. Matches iOS's UnifiedSessionsResponse Codable.
func List ¶
func List(search, project, marker string, openIDs, knownIDs map[string]bool, overrides *Overrides, modelTitles map[string]string) (*ListResult, error)
List walks ~/.claude/projects + ~/.codex/sessions + ~/.grok/sessions and returns the unified list. Search/project filter the results; openIDs marks rows whose agent session is currently live on the daemon (is_open=true). knownIDs gates which rows appear at all — only daemon-owned ids (or live ones) survive, mirroring the macOS server's OverlayStore.known so the panel is not polluted by foreign-CLI transcripts. The result is sorted by mtime desc + capped per-project to 3 entries for the main list (when project=="" and marker!="favorite"), matching the Mac's "show top 3 per project" policy. marker=="favorite" filters to pinned rows only (uncapped, global) — the Mac-side favorite filter; the daemon previously ignored the param and returned everything. Per-project pagination is the caller's job (slice the returned slice).
type MetaCache ¶
type MetaCache struct {
// contains filtered or unexported fields
}
MetaCache memoizes transcript parses keyed by transcript path. Goroutine-safe.
func LoadMetaCache ¶
func LoadMetaCache() *MetaCache
LoadMetaCache reads sessions_meta.json (missing/unreadable/corrupt file → empty cache, never an error). Always returns a usable (possibly cold) cache.
func (*MetaCache) Counters ¶
Counters returns (hits, misses, parses) for acceptance/debug inspection.
func (*MetaCache) Evict ¶
Evict drops one entry by path. Used by handleUnifiedDelete when the transcript path is known (Claude branch). Codex/Grok rely on reapMissing.
func (*MetaCache) PersistNow ¶
func (c *MetaCache) PersistNow()
PersistNow writes the cache atomically (tmp + rename), mirroring known.persist. No-op when nothing changed since the last persist (dirty flag). Called by the background tick + on demand.
type Override ¶
type Override struct {
Pinned bool `json:"pinned,omitempty"`
CustomName string `json:"custom_name,omitempty"`
}
Override is one session's user-mutable state.
type Overrides ¶
type Overrides struct {
// contains filtered or unexported fields
}
Overrides is the in-memory + on-disk store. Goroutine-safe.
func LoadOverrides ¶
LoadOverrides reads (or initializes) the override store from $RMOTE_AGENT_DIR/sessions_overrides.json. A missing file is not an error — returns an empty store.
func (*Overrides) SetCustomName ¶
SetCustomName sets/clears the custom name + persists. Empty name clears the field (and if pinned is also false, removes the entry).
type Session ¶
type Session struct {
ID string `json:"id"`
Name string `json:"name"`
ProjectPath string `json:"project_path"`
LastActive string `json:"last_active"` // RFC3339
Labels []string `json:"labels"`
IsPinned bool `json:"is_pinned"`
IsOpen bool `json:"is_open"`
Agent string `json:"agent"`
// Internal-only fields below — never serialized. Used by the server
// handler to compute per-session stats lazily (only for the returned
// slice, not every row in the unified list).
TranscriptPath string `json:"-"`
SortTs int64 `json:"-"`
}
Session is one row in the unified list. JSON tags match iOS's UnifiedSession Codable. `Agent` is always "claude" in v1.
type Stats ¶
type Stats struct {
Turns int `json:"turns"`
InputTokens int64 `json:"input_tokens"`
CacheCreationInputTokens int64 `json:"cache_creation_input_tokens"`
CacheReadInputTokens int64 `json:"cache_read_input_tokens"`
OutputTokens int64 `json:"output_tokens"`
TotalTokens int64 `json:"total_tokens"`
Messages int `json:"messages"`
Model string `json:"model,omitempty"`
}
Stats is the per-session rollup. JSON tags match iOS's SessionStats Codable field-for-field. `Model` is the most-recently-seen model on an assistant turn (Claude can switch mid-session; we report the last one as canonical).
func ComputeStats ¶
ComputeStats returns the stats rollup for one session's transcript, using the cached entry when the file's mtime hasn't changed. `agent` selects the transcript format ("claude" / "codex" / "grok"); unknown agents return nil.
`path` is the transcript location — for Claude/Codex it's the .jsonl file; for Grok it's the session directory (we look up summary.json inside).