@scrylog/cli 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/highlights-eq9cgrbb.scm +604 -0
- package/dist/assets/highlights-ghv9g403.scm +205 -0
- package/dist/assets/highlights-hk7bwhj4.scm +284 -0
- package/dist/assets/highlights-r812a2qc.scm +150 -0
- package/dist/assets/highlights-x6tmsnaa.scm +115 -0
- package/dist/assets/injections-73j83es3.scm +27 -0
- package/dist/assets/parser.worker-xyhf83rf.js +4563 -0
- package/dist/assets/tree-sitter-3jzf13jk.wasm +0 -0
- package/dist/assets/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
- package/dist/assets/tree-sitter-markdown-411r6y9b.wasm +0 -0
- package/dist/assets/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
- package/dist/assets/tree-sitter-typescript-zxjzwt75.wasm +0 -0
- package/dist/assets/tree-sitter-zig-e78zbjpm.wasm +0 -0
- package/dist/cli/index.js +499 -0
- package/dist/cli/index.js.map +61 -0
- package/dist/daemon/index.js +670 -0
- package/dist/daemon/index.js.map +1475 -0
- package/dist/hooks/claude.js +6 -0
- package/dist/hooks/claude.js.map +11 -0
- package/dist/hooks/codex.js +10 -0
- package/dist/hooks/codex.js.map +11 -0
- package/dist/mcp/index.js +100 -0
- package/dist/mcp/index.js.map +231 -0
- package/dist/oc/index.js +21 -0
- package/dist/oc/index.js.map +10 -0
- package/package.json +16 -13
- package/src/api/docs/sessions.keys.ts +0 -6
- package/src/api/docs/sessions.ts +0 -82
- package/src/api/docs/system.keys.ts +0 -5
- package/src/api/docs/system.ts +0 -69
- package/src/api/docs/usage.keys.ts +0 -3
- package/src/api/docs/usage.ts +0 -24
- package/src/api/docs/webhooks.keys.ts +0 -5
- package/src/api/docs/webhooks.ts +0 -78
- package/src/api/index.ts +0 -18
- package/src/api/lib/auth.ts +0 -43
- package/src/api/lib/errors.ts +0 -28
- package/src/api/lib/route.ts +0 -18
- package/src/api/models/claude.ts +0 -4
- package/src/api/models/codex.ts +0 -4
- package/src/api/models/opencode.ts +0 -11
- package/src/api/routes/sessions.ts +0 -51
- package/src/api/routes/system.ts +0 -106
- package/src/api/routes/usage.ts +0 -15
- package/src/api/routes/webhooks/claude.ts +0 -149
- package/src/api/routes/webhooks/codex.ts +0 -175
- package/src/api/routes/webhooks/opencode.ts +0 -112
- package/src/api/routes.ts +0 -93
- package/src/api/schemas/common.ts +0 -29
- package/src/api/schemas/sessions.ts +0 -86
- package/src/api/schemas/usage.ts +0 -51
- package/src/api/schemas/webhooks/claude.ts +0 -32
- package/src/api/schemas/webhooks/codex.ts +0 -34
- package/src/api/schemas/webhooks/opencode.ts +0 -29
- package/src/api/services/claude-session.ts +0 -9
- package/src/api/services/codex-session.ts +0 -8
- package/src/api/services/opencode-session.ts +0 -73
- package/src/classifier.ts +0 -206
- package/src/cli/commands.ts +0 -714
- package/src/cli/index.ts +0 -18
- package/src/cli/program.ts +0 -175
- package/src/cli/prompt.ts +0 -44
- package/src/daemon/cli.ts +0 -27
- package/src/daemon/collectors/claude/README.md +0 -108
- package/src/daemon/collectors/claude/collector.ts +0 -423
- package/src/daemon/collectors/claude/discovery.ts +0 -127
- package/src/daemon/collectors/claude/hooks.ts +0 -181
- package/src/daemon/collectors/claude/index.ts +0 -8
- package/src/daemon/collectors/claude/jsonl.ts +0 -85
- package/src/daemon/collectors/claude/transcript.ts +0 -246
- package/src/daemon/collectors/codex/README.md +0 -147
- package/src/daemon/collectors/codex/collector.ts +0 -661
- package/src/daemon/collectors/codex/discovery.ts +0 -104
- package/src/daemon/collectors/codex/hooks.ts +0 -179
- package/src/daemon/collectors/codex/index.ts +0 -7
- package/src/daemon/collectors/codex/jsonl.ts +0 -108
- package/src/daemon/collectors/codex/transcript.ts +0 -299
- package/src/daemon/collectors/git.ts +0 -353
- package/src/daemon/collectors/herdr/collector.ts +0 -128
- package/src/daemon/collectors/herdr/index.ts +0 -2
- package/src/daemon/collectors/herdr/normalization.ts +0 -111
- package/src/daemon/collectors/opencode/README.md +0 -106
- package/src/daemon/collectors/opencode/collector.ts +0 -545
- package/src/daemon/collectors/opencode/discovery.ts +0 -257
- package/src/daemon/collectors/opencode/index.ts +0 -5
- package/src/daemon/collectors/opencode/session-builder.ts +0 -59
- package/src/daemon/collectors/opencode-db.ts +0 -294
- package/src/daemon/collectors/process.ts +0 -201
- package/src/daemon/collectors/tmux/README.md +0 -128
- package/src/daemon/collectors/tmux/collector.ts +0 -492
- package/src/daemon/collectors/tmux/enrichment.ts +0 -242
- package/src/daemon/collectors/tmux/index.ts +0 -4
- package/src/daemon/collectors/tmux/parse.ts +0 -128
- package/src/daemon/collectors/usage.ts +0 -259
- package/src/daemon/index.ts +0 -209
- package/src/daemon/scheduler.ts +0 -86
- package/src/daemon/store.ts +0 -630
- package/src/detect.ts +0 -143
- package/src/hooks/claude.ts +0 -596
- package/src/hooks/codex.ts +0 -517
- package/src/legacy/classifier.ts +0 -215
- package/src/legacy/detect.ts +0 -143
- package/src/mcp/client-server.ts +0 -21
- package/src/mcp/http-handler.ts +0 -126
- package/src/mcp/index.ts +0 -61
- package/src/mcp/resources/config-current.ts +0 -19
- package/src/mcp/resources/index.ts +0 -11
- package/src/mcp/resources/sessions-active.ts +0 -19
- package/src/mcp/resources/sessions-all.ts +0 -19
- package/src/mcp/schemas/sessions.ts +0 -3
- package/src/mcp/server.ts +0 -17
- package/src/mcp/services/api-adapter.ts +0 -48
- package/src/mcp/services/data-source.ts +0 -22
- package/src/mcp/services/store-adapter.ts +0 -40
- package/src/mcp/tools/get-active-sessions.ts +0 -16
- package/src/mcp/tools/get-session-children.ts +0 -24
- package/src/mcp/tools/get-session-messages.ts +0 -24
- package/src/mcp/tools/get-session.ts +0 -23
- package/src/mcp/tools/index.ts +0 -15
- package/src/mcp/tools/list-sessions.ts +0 -16
- package/src/oc/index.ts +0 -302
- package/src/service/manager.ts +0 -284
- package/src/shared/config.ts +0 -511
- package/src/shared/ipc.ts +0 -80
- package/src/shared/logger.ts +0 -248
- package/src/shared/paths.ts +0 -73
- package/src/shared/platform.ts +0 -110
- package/src/shared/session-exclusions.ts +0 -5
- package/src/shared/session-view.ts +0 -302
- package/src/shared/terminal-capabilities.ts +0 -130
- package/src/shared/types.ts +0 -330
- package/src/shared/utils.ts +0 -339
- package/src/shared/version.ts +0 -44
- package/src/tui/App.tsx +0 -240
- package/src/tui/client.ts +0 -163
- package/src/tui/components/BindingsModal.tsx +0 -82
- package/src/tui/components/DashboardHeader.tsx +0 -256
- package/src/tui/components/KeyBar.tsx +0 -67
- package/src/tui/components/SessionDetailModal.tsx +0 -169
- package/src/tui/components/SessionsView.tsx +0 -184
- package/src/tui/components/TabBar.tsx +0 -40
- package/src/tui/components/UsageSummaryPane.tsx +0 -272
- package/src/tui/components/UsageView.tsx +0 -242
- package/src/tui/components/tool-icons.ts +0 -24
- package/src/tui/index.tsx +0 -106
- package/src/tui/keybindings.ts +0 -49
- package/src/tui/model.ts +0 -295
- package/src/tui/state.ts +0 -77
- package/src/tui/theme.ts +0 -110
- package/src/types.ts +0 -113
- package/src/usage/README.md +0 -323
- package/src/usage/api.ts +0 -99
- package/src/usage/client.ts +0 -3
- package/src/usage/clients/anthropic-oauth-usage.ts +0 -258
- package/src/usage/clients/anthropic-web-usage.ts +0 -329
- package/src/usage/clients/claude-cli-probe.ts +0 -513
- package/src/usage/clients/codex-app-server.ts +0 -354
- package/src/usage/clients/codex-oauth-usage.ts +0 -240
- package/src/usage/clients/opencode-go-api.ts +0 -100
- package/src/usage/clients/opencode-go-usage.ts +0 -577
- package/src/usage/errors.ts +0 -33
- package/src/usage/index.ts +0 -20
- package/src/usage/local/opencode-go-local.ts +0 -194
- package/src/usage/mappers.ts +0 -282
- package/src/usage/planner.ts +0 -118
- package/src/usage/providers/claude.ts +0 -233
- package/src/usage/providers/codex.ts +0 -115
- package/src/usage/providers/opencode-go.ts +0 -115
- package/src/usage/resolver.ts +0 -4
- package/src/usage/resolvers/browser-cookies.ts +0 -808
- package/src/usage/resolvers/claude-auth.ts +0 -208
- package/src/usage/resolvers/claude-cli.ts +0 -24
- package/src/usage/resolvers/claude-desktop-auth.ts +0 -170
- package/src/usage/resolvers/claude-web.ts +0 -82
- package/src/usage/resolvers/codex-auth.ts +0 -174
- package/src/usage/resolvers/keychain-coordinator.ts +0 -397
- package/src/usage/resolvers/opencode-go-web.ts +0 -55
- package/src/usage/types.ts +0 -225
- package/src/usage/web-session-cache.ts +0 -37
- /package/{src/tui → dist/cli}/assets/providers/SOURCES.md +0 -0
- /package/{src/tui → dist/cli}/assets/providers/claude-terminal.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/claude-terminal.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/claude.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/copilot.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/copilot.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/openai-terminal.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/openai-terminal.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/openai.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/opencode-terminal.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/opencode-terminal.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/opencode.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/shell.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/shell.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/unknown.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/unknown.svg +0 -0
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import type { ScrylogConfig } from "./config";
|
|
2
|
-
import type { ProjectInfo, SessionModel, SessionState, SessionTool } from "./types";
|
|
3
|
-
|
|
4
|
-
export interface SessionListProjectInfo {
|
|
5
|
-
displayName: string;
|
|
6
|
-
compactLabel: string;
|
|
7
|
-
branch?: string;
|
|
8
|
-
isGitRepository?: boolean;
|
|
9
|
-
sourcePath?: string;
|
|
10
|
-
gitRootPath?: string;
|
|
11
|
-
repositoryIdentityPath?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface SessionListTmuxInfo {
|
|
15
|
-
session: string;
|
|
16
|
-
window: string;
|
|
17
|
-
pane: string;
|
|
18
|
-
windowName?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface SessionListHerdrInfo {
|
|
22
|
-
paneId: string;
|
|
23
|
-
terminalId?: string;
|
|
24
|
-
workspaceId?: string;
|
|
25
|
-
workspace?: string;
|
|
26
|
-
tabId?: string;
|
|
27
|
-
tab?: string;
|
|
28
|
-
name?: string;
|
|
29
|
-
agent?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface SessionListItem {
|
|
33
|
-
id: string;
|
|
34
|
-
source: SessionModel["source"];
|
|
35
|
-
tool: SessionTool;
|
|
36
|
-
state: SessionState;
|
|
37
|
-
summary: string;
|
|
38
|
-
lastActivity: number;
|
|
39
|
-
stableForMs?: number;
|
|
40
|
-
hasAttention?: boolean;
|
|
41
|
-
detectionSource?: SessionModel["detectionSource"];
|
|
42
|
-
parentSessionId?: string;
|
|
43
|
-
/** Human label for the session row: pane title > window/tab name > tmux session name */
|
|
44
|
-
displayName?: string;
|
|
45
|
-
project?: SessionListProjectInfo;
|
|
46
|
-
tmux?: SessionListTmuxInfo;
|
|
47
|
-
herdr?: SessionListHerdrInfo;
|
|
48
|
-
currentPath?: string;
|
|
49
|
-
activeTool?: string;
|
|
50
|
-
childCount?: number;
|
|
51
|
-
activeChildCount?: number;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface SessionTreeItem extends SessionListItem {
|
|
55
|
-
children: SessionListItem[];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface SessionViewCounts {
|
|
59
|
-
total: number;
|
|
60
|
-
visible: number;
|
|
61
|
-
rootsVisible: number;
|
|
62
|
-
childrenVisible: number;
|
|
63
|
-
byState: Record<SessionState, number>;
|
|
64
|
-
byTool: Record<SessionTool, number>;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface SessionView {
|
|
68
|
-
counts: SessionViewCounts;
|
|
69
|
-
sessions: SessionTreeItem[];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface SessionViewOptions {
|
|
73
|
-
includeUnknown?: boolean;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function makeStateCounts(): Record<SessionState, number> {
|
|
77
|
-
return {
|
|
78
|
-
working: 0,
|
|
79
|
-
idle: 0,
|
|
80
|
-
"waiting-input": 0,
|
|
81
|
-
error: 0,
|
|
82
|
-
shell: 0,
|
|
83
|
-
unknown: 0,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function makeToolCounts(): Record<SessionTool, number> {
|
|
88
|
-
return {
|
|
89
|
-
opencode: 0,
|
|
90
|
-
claude: 0,
|
|
91
|
-
codex: 0,
|
|
92
|
-
copilotcli: 0,
|
|
93
|
-
shell: 0,
|
|
94
|
-
unknown: 0,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const CODEX_ROOT_EPHEMERAL_GRACE_MS = 30_000;
|
|
99
|
-
|
|
100
|
-
function isEphemeralCodexRootSession(session: SessionModel, now: number): boolean {
|
|
101
|
-
return session.tool === "codex"
|
|
102
|
-
&& session.source === "standalone"
|
|
103
|
-
&& session.detectionSource === "codex-hook"
|
|
104
|
-
&& session.state === "idle"
|
|
105
|
-
&& session.currentPath === "/"
|
|
106
|
-
&& !session.codex?.transcriptPath
|
|
107
|
-
&& !session.parentSessionId
|
|
108
|
-
&& (session.childSessionIds?.length ?? 0) === 0
|
|
109
|
-
&& now - session.lastActivity > CODEX_ROOT_EPHEMERAL_GRACE_MS;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function isCanonicallyVisible(
|
|
113
|
-
session: SessionModel,
|
|
114
|
-
config: ScrylogConfig,
|
|
115
|
-
now: number,
|
|
116
|
-
options: SessionViewOptions,
|
|
117
|
-
): boolean {
|
|
118
|
-
if (session.tool === "unknown" && !options.includeUnknown) {
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (session.parentSessionId) {
|
|
123
|
-
return session.state === "working" || session.state === "waiting-input";
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (isEphemeralCodexRootSession(session, now)) {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const cutoff = config.tui.standaloneMaxAgeHours > 0
|
|
131
|
-
? now - config.tui.standaloneMaxAgeHours * 3_600_000
|
|
132
|
-
: 0;
|
|
133
|
-
|
|
134
|
-
if (cutoff > 0 && session.source === "standalone" && session.lastActivity < cutoff) {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function toProject(project?: ProjectInfo): SessionListProjectInfo | undefined {
|
|
142
|
-
if (!project) return undefined;
|
|
143
|
-
return {
|
|
144
|
-
displayName: project.displayName,
|
|
145
|
-
compactLabel: project.compactLabel,
|
|
146
|
-
branch: project.branch,
|
|
147
|
-
isGitRepository: project.isGitRepository,
|
|
148
|
-
sourcePath: project.sourcePath,
|
|
149
|
-
gitRootPath: project.gitRootPath,
|
|
150
|
-
repositoryIdentityPath: project.repositoryIdentityPath,
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const GRACE_PERIOD_MS = 1500;
|
|
155
|
-
|
|
156
|
-
function resolveDisplayName(session: SessionModel): string | undefined {
|
|
157
|
-
if (session.tmux) {
|
|
158
|
-
return session.paneTitle?.trim()
|
|
159
|
-
|| session.tmux.windowName?.trim()
|
|
160
|
-
|| session.tmux.session?.trim()
|
|
161
|
-
|| undefined;
|
|
162
|
-
}
|
|
163
|
-
if (session.herdr) {
|
|
164
|
-
return session.herdr.name?.trim()
|
|
165
|
-
|| session.herdr.tab?.trim()
|
|
166
|
-
|| session.herdr.agent?.trim()
|
|
167
|
-
|| session.herdr.paneId
|
|
168
|
-
|| undefined;
|
|
169
|
-
}
|
|
170
|
-
return undefined;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function effectiveState(session: SessionModel, activeChildCount: number, now: number): SessionState {
|
|
174
|
-
if (session.state === "idle" && !session.parentSessionId) {
|
|
175
|
-
if (activeChildCount > 0) {
|
|
176
|
-
return "working";
|
|
177
|
-
}
|
|
178
|
-
if (session.lastChildActiveAt && (now - session.lastChildActiveAt) < GRACE_PERIOD_MS) {
|
|
179
|
-
return "working";
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return session.state;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function stableDuration(session: SessionModel, effective: SessionState, now: number): number {
|
|
186
|
-
if (effective === "working" && session.lastWorkingChangedAt) {
|
|
187
|
-
return Math.max(0, now - session.lastWorkingChangedAt);
|
|
188
|
-
}
|
|
189
|
-
if (session.stateChangedAt) {
|
|
190
|
-
return Math.max(0, now - session.stateChangedAt);
|
|
191
|
-
}
|
|
192
|
-
return session.stableForMs ?? Math.max(0, now - session.lastActivity);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function toListItem(session: SessionModel, childCount: number, activeChildCount: number, now: number): SessionListItem {
|
|
196
|
-
const effective = effectiveState(session, activeChildCount, now);
|
|
197
|
-
return {
|
|
198
|
-
id: session.id,
|
|
199
|
-
source: session.source,
|
|
200
|
-
tool: session.tool,
|
|
201
|
-
state: effective,
|
|
202
|
-
summary: session.summary,
|
|
203
|
-
lastActivity: session.lastActivity,
|
|
204
|
-
stableForMs: stableDuration(session, effective, now),
|
|
205
|
-
hasAttention: session.hasAttention,
|
|
206
|
-
detectionSource: session.detectionSource,
|
|
207
|
-
parentSessionId: session.parentSessionId,
|
|
208
|
-
displayName: resolveDisplayName(session),
|
|
209
|
-
project: toProject(session.project),
|
|
210
|
-
tmux: session.tmux ? { ...session.tmux } : undefined,
|
|
211
|
-
herdr: session.herdr ? {
|
|
212
|
-
paneId: session.herdr.paneId,
|
|
213
|
-
terminalId: session.herdr.terminalId,
|
|
214
|
-
workspaceId: session.herdr.workspaceId,
|
|
215
|
-
workspace: session.herdr.workspace,
|
|
216
|
-
tabId: session.herdr.tabId,
|
|
217
|
-
tab: session.herdr.tab,
|
|
218
|
-
name: session.herdr.name,
|
|
219
|
-
agent: session.herdr.agent,
|
|
220
|
-
} : undefined,
|
|
221
|
-
currentPath: session.currentPath,
|
|
222
|
-
activeTool: session.activeTool,
|
|
223
|
-
childCount,
|
|
224
|
-
activeChildCount,
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export function flattenSessionTree(sessions: SessionTreeItem[]): SessionListItem[] {
|
|
229
|
-
const flat: SessionListItem[] = [];
|
|
230
|
-
for (const session of sessions) {
|
|
231
|
-
const { children: _children, ...root } = session;
|
|
232
|
-
flat.push(root);
|
|
233
|
-
flat.push(...session.children);
|
|
234
|
-
}
|
|
235
|
-
return flat;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
export function buildSessionView(
|
|
239
|
-
sessions: SessionModel[],
|
|
240
|
-
config: ScrylogConfig,
|
|
241
|
-
now = Date.now(),
|
|
242
|
-
options: SessionViewOptions = {},
|
|
243
|
-
): SessionView {
|
|
244
|
-
const byId = new Map(sessions.map((session) => [session.id, session]));
|
|
245
|
-
const allChildren = new Map<string, SessionModel[]>();
|
|
246
|
-
const visibleChildren = new Map<string, SessionModel[]>();
|
|
247
|
-
const visibleRoots = new Map<string, SessionModel>();
|
|
248
|
-
|
|
249
|
-
for (const session of sessions) {
|
|
250
|
-
if (session.parentSessionId) {
|
|
251
|
-
const arr = allChildren.get(session.parentSessionId) ?? [];
|
|
252
|
-
arr.push(session);
|
|
253
|
-
allChildren.set(session.parentSessionId, arr);
|
|
254
|
-
|
|
255
|
-
if (isCanonicallyVisible(session, config, now, options)) {
|
|
256
|
-
const visibleArr = visibleChildren.get(session.parentSessionId) ?? [];
|
|
257
|
-
visibleArr.push(session);
|
|
258
|
-
visibleChildren.set(session.parentSessionId, visibleArr);
|
|
259
|
-
|
|
260
|
-
const parent = byId.get(session.parentSessionId);
|
|
261
|
-
if (parent && isCanonicallyVisible(parent, config, now, options)) {
|
|
262
|
-
visibleRoots.set(parent.id, parent);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (isCanonicallyVisible(session, config, now, options)) {
|
|
269
|
-
visibleRoots.set(session.id, session);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
const sortedRoots = [...visibleRoots.values()].sort((a, b) => b.lastActivity - a.lastActivity);
|
|
274
|
-
const tree: SessionTreeItem[] = sortedRoots.map((root) => {
|
|
275
|
-
const activeChildren = (visibleChildren.get(root.id) ?? []).sort((a, b) => b.lastActivity - a.lastActivity);
|
|
276
|
-
const allDirectChildren = allChildren.get(root.id) ?? [];
|
|
277
|
-
return {
|
|
278
|
-
...toListItem(root, allDirectChildren.length, activeChildren.length, now),
|
|
279
|
-
children: activeChildren.map((child) => toListItem(child, 0, 0, now)),
|
|
280
|
-
};
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
const flatVisible = flattenSessionTree(tree);
|
|
284
|
-
const byState = makeStateCounts();
|
|
285
|
-
const byTool = makeToolCounts();
|
|
286
|
-
for (const session of flatVisible) {
|
|
287
|
-
byState[session.state] += 1;
|
|
288
|
-
byTool[session.tool] += 1;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return {
|
|
292
|
-
counts: {
|
|
293
|
-
total: sessions.length,
|
|
294
|
-
visible: flatVisible.length,
|
|
295
|
-
rootsVisible: tree.length,
|
|
296
|
-
childrenVisible: flatVisible.filter((session) => Boolean(session.parentSessionId)).length,
|
|
297
|
-
byState,
|
|
298
|
-
byTool,
|
|
299
|
-
},
|
|
300
|
-
sessions: tree,
|
|
301
|
-
};
|
|
302
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { stdin as input, stdout as output } from "node:process";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Non-invasive terminal capability probes used by `scrylog doctor` to explain
|
|
5
|
-
* how provider icons negotiate graphics. Mirrors the response formats OpenTUI's
|
|
6
|
-
* detector expects, but never enters the alternate screen and always restores
|
|
7
|
-
* the terminal to its original state (`finally`).
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export interface TerminalGraphicsCapabilities {
|
|
11
|
-
/** Terminal identification from XTVERSION (e.g. "ghostty(1.2.3)"), if answered. */
|
|
12
|
-
terminalName: string | null;
|
|
13
|
-
/** Outer multiplexer detected from the environment ("tmux" | "zellij" | "none"). */
|
|
14
|
-
multiplexer: "tmux" | "zellij" | "none";
|
|
15
|
-
/** Terminal answered a kitty graphics protocol query. */
|
|
16
|
-
kittyGraphics: boolean;
|
|
17
|
-
/** DA1 primary response advertises sixel (attribute 4). */
|
|
18
|
-
sixel: boolean;
|
|
19
|
-
/** Window pixel resolution from `CSI 14t`. */
|
|
20
|
-
pixelResolution: { width: number; height: number } | null;
|
|
21
|
-
/** stdin was not a TTY (SSH without tty, pipes) or raw mode was unavailable. */
|
|
22
|
-
probeFailed: boolean;
|
|
23
|
-
/** Why the probe did not run or answer. */
|
|
24
|
-
probeFailedReason: "not-a-tty" | "raw-unavailable" | "no-answer" | null;
|
|
25
|
-
/** TERM value, useful for manual triage. */
|
|
26
|
-
term: string | null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const PROBE_TIMEOUT_MS = 300;
|
|
30
|
-
|
|
31
|
-
const XTVERSION_PROBE = "\x1bP>0q\x1b\\";
|
|
32
|
-
const DA1_PROBE = "\x1b[c";
|
|
33
|
-
const KITTY_PROBE = "\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\";
|
|
34
|
-
const PIXEL_RES_PROBE = "\x1b[14t";
|
|
35
|
-
|
|
36
|
-
/** Visible attributes in a DA1 primary response (e.g. `ESC[?6;22;4c`). Sixel is attribute 4. */
|
|
37
|
-
const DA1_RESPONSE = /\x1b\[\?(\d+(?:;\d+)*)c/g;
|
|
38
|
-
const XTVERSION_RESPONSE = /\x1bP>[|]([^\x1b]+)\x1b\\/;
|
|
39
|
-
const KITTY_RESPONSE = /\x1b_Gi=31;([^\x1b]*)\x1b\\/;
|
|
40
|
-
const PIXEL_RES_RESPONSE = /\x1b\[4;(\d+);(\d+)t/;
|
|
41
|
-
|
|
42
|
-
export function detectMultiplexer(): "tmux" | "zellij" | "none" {
|
|
43
|
-
if (process.env["TMUX"]) return "tmux";
|
|
44
|
-
if (process.env["ZELLIJ"]) return "zellij";
|
|
45
|
-
return "none";
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function parseResponses(sequence: string): Partial<TerminalGraphicsCapabilities> {
|
|
49
|
-
const result: Partial<TerminalGraphicsCapabilities> = {};
|
|
50
|
-
const version = sequence.match(XTVERSION_RESPONSE)?.[1];
|
|
51
|
-
if (version) result.terminalName = version.trim();
|
|
52
|
-
for (const da1 of sequence.matchAll(DA1_RESPONSE)) {
|
|
53
|
-
if (da1[1]!.split(";").includes("4")) result.sixel = true;
|
|
54
|
-
}
|
|
55
|
-
const kitty = sequence.match(KITTY_RESPONSE);
|
|
56
|
-
if (kitty) result.kittyGraphics = !(kitty[1] ?? "").startsWith("E:");
|
|
57
|
-
const res = sequence.match(PIXEL_RES_RESPONSE);
|
|
58
|
-
if (res) result.pixelResolution = { width: Number(res[2]), height: Number(res[1]) };
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function probeTerminalGraphics(): Promise<TerminalGraphicsCapabilities> {
|
|
63
|
-
const probe: TerminalGraphicsCapabilities = {
|
|
64
|
-
terminalName: null,
|
|
65
|
-
multiplexer: detectMultiplexer(),
|
|
66
|
-
kittyGraphics: false,
|
|
67
|
-
sixel: false,
|
|
68
|
-
pixelResolution: null,
|
|
69
|
-
probeFailed: true,
|
|
70
|
-
probeFailedReason: null,
|
|
71
|
-
term: process.env["TERM"] ?? null,
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
if (!input.isTTY || typeof input.setRawMode !== "function") {
|
|
75
|
-
return Promise.resolve({ ...probe, probeFailedReason: "not-a-tty" });
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return new Promise((resolve) => {
|
|
79
|
-
const rawActive = input.isRaw === true;
|
|
80
|
-
const restore = () => {
|
|
81
|
-
try { input.setRawMode(rawActive); } catch { /* restore best effort */ }
|
|
82
|
-
};
|
|
83
|
-
let buffer = "";
|
|
84
|
-
let settleTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
85
|
-
let done = false;
|
|
86
|
-
const stop = () => {
|
|
87
|
-
if (done) return;
|
|
88
|
-
done = true;
|
|
89
|
-
clearTimeout(settleTimeout!);
|
|
90
|
-
input.removeListener("data", onData);
|
|
91
|
-
restore();
|
|
92
|
-
};
|
|
93
|
-
const settle = () => {
|
|
94
|
-
stop();
|
|
95
|
-
const parsed = parseResponses(buffer);
|
|
96
|
-
const failed = Object.keys(parsed).length === 0;
|
|
97
|
-
resolve({
|
|
98
|
-
...probe,
|
|
99
|
-
...parsed,
|
|
100
|
-
probeFailed: failed,
|
|
101
|
-
probeFailedReason: failed ? "no-answer" : null,
|
|
102
|
-
});
|
|
103
|
-
};
|
|
104
|
-
const onData = (chunk: Buffer | string) => {
|
|
105
|
-
buffer += typeof chunk === "string" ? chunk : chunk.toString("latin1");
|
|
106
|
-
clearTimeout(settleTimeout!);
|
|
107
|
-
settleTimeout = setTimeout(settle, 80);
|
|
108
|
-
};
|
|
109
|
-
try {
|
|
110
|
-
input.setRawMode(true);
|
|
111
|
-
} catch {
|
|
112
|
-
resolve({ ...probe, probeFailedReason: "raw-unavailable" });
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
input.on("data", onData);
|
|
116
|
-
settleTimeout = setTimeout(settle, PROBE_TIMEOUT_MS);
|
|
117
|
-
output.write(XTVERSION_PROBE + DA1_PROBE + KITTY_PROBE + PIXEL_RES_PROBE);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export type ProviderIconAdvice = "graphics" | "kitty" | "sixel" | "blocks";
|
|
122
|
-
|
|
123
|
-
/** Maps probed capabilities to the recommended `tui.providerIcons` value. */
|
|
124
|
-
export function adviseProviderIcons(capabilities: TerminalGraphicsCapabilities): ProviderIconAdvice {
|
|
125
|
-
if (capabilities.multiplexer === "tmux" || capabilities.multiplexer === "zellij") return "blocks";
|
|
126
|
-
if (capabilities.kittyGraphics) return "graphics";
|
|
127
|
-
if (capabilities.sixel && capabilities.pixelResolution) return "graphics";
|
|
128
|
-
if (capabilities.sixel) return "sixel";
|
|
129
|
-
return "blocks";
|
|
130
|
-
}
|