Skip to content

Commit d841238

Browse files
committed
feat: session viewer
Got rid of the legacy logs viewerer. Instead made sessions folder which relies on the new message format.
1 parent 212e8dd commit d841238

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2268
-2696
lines changed

apps/array/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
"@radix-ui/react-icons": "^1.3.2",
102102
"@radix-ui/themes": "^3.2.1",
103103
"@tanstack/react-query": "^5.90.2",
104+
"@tanstack/react-virtual": "^3.13.12",
104105
"@tiptap/core": "^3.11.0",
105106
"@tiptap/extension-link": "^3.11.0",
106107
"@tiptap/extension-mention": "^3.11.0",
@@ -136,6 +137,7 @@
136137
"react-hotkeys-hook": "^4.4.4",
137138
"react-markdown": "^10.1.0",
138139
"react-resizable-panels": "^3.0.6",
140+
"remark-gfm": "^4.0.1",
139141
"sonner": "^2.0.7",
140142
"uuid": "^9.0.1",
141143
"zod": "^4.1.12",

apps/array/src/main/services/git.ts

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,31 @@ const log = logger.scope("git");
1212
const execAsync = promisify(exec);
1313
const fsPromises = fs.promises;
1414

15+
const getAllFilesInDirectory = async (
16+
directoryPath: string,
17+
basePath: string,
18+
): Promise<string[]> => {
19+
const files: string[] = [];
20+
const entries = await fsPromises.readdir(path.join(directoryPath, basePath), {
21+
withFileTypes: true,
22+
});
23+
24+
for (const entry of entries) {
25+
const relativePath = path.join(basePath, entry.name);
26+
if (entry.isDirectory()) {
27+
const subFiles = await getAllFilesInDirectory(
28+
directoryPath,
29+
relativePath,
30+
);
31+
files.push(...subFiles);
32+
} else {
33+
files.push(relativePath);
34+
}
35+
}
36+
37+
return files;
38+
};
39+
1540
const CLONE_MAX_BUFFER = 10 * 1024 * 1024;
1641

1742
export interface GitHubRepo {
@@ -215,7 +240,25 @@ const getChangedFilesAgainstHead = async (
215240

216241
// Only add untracked files not already seen
217242
if (statusCode === "??" && !seenPaths.has(filePath)) {
218-
files.push({ path: filePath, status: "untracked" });
243+
// Check if it's a directory (git shows directories with trailing /)
244+
if (filePath.endsWith("/")) {
245+
const dirPath = filePath.slice(0, -1);
246+
try {
247+
const dirFiles = await getAllFilesInDirectory(
248+
directoryPath,
249+
dirPath,
250+
);
251+
for (const file of dirFiles) {
252+
if (!seenPaths.has(file)) {
253+
files.push({ path: file, status: "untracked" });
254+
}
255+
}
256+
} catch {
257+
// Directory might not exist or be inaccessible
258+
}
259+
} else {
260+
files.push({ path: filePath, status: "untracked" });
261+
}
219262
}
220263
}
221264

@@ -274,20 +317,40 @@ const getDiffStats = async (directoryPath: string): Promise<DiffStats> => {
274317
cwd: directoryPath,
275318
});
276319

320+
const countLinesInFile = async (filePath: string): Promise<number> => {
321+
try {
322+
const { stdout: wcOutput } = await execAsync(`wc -l < "${filePath}"`, {
323+
cwd: directoryPath,
324+
});
325+
return parseInt(wcOutput.trim(), 10) || 0;
326+
} catch {
327+
return 0;
328+
}
329+
};
330+
277331
for (const line of statusOutput.trim().split("\n").filter(Boolean)) {
278332
const statusCode = line.substring(0, 2);
279333
if (statusCode === "??") {
280-
filesChanged++;
281-
// Count lines in untracked file
282334
const filePath = line.substring(3);
283-
try {
284-
const { stdout: wcOutput } = await execAsync(
285-
`wc -l < "${filePath}"`,
286-
{ cwd: directoryPath },
287-
);
288-
linesAdded += parseInt(wcOutput.trim(), 10) || 0;
289-
} catch {
290-
// File might be binary or inaccessible
335+
336+
// Check if it's a directory (git shows directories with trailing /)
337+
if (filePath.endsWith("/")) {
338+
const dirPath = filePath.slice(0, -1);
339+
try {
340+
const dirFiles = await getAllFilesInDirectory(
341+
directoryPath,
342+
dirPath,
343+
);
344+
for (const file of dirFiles) {
345+
filesChanged++;
346+
linesAdded += await countLinesInFile(file);
347+
}
348+
} catch {
349+
// Directory might not exist or be inaccessible
350+
}
351+
} else {
352+
filesChanged++;
353+
linesAdded += await countLinesInFile(filePath);
291354
}
292355
}
293356
}

apps/array/src/main/services/session-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ export class SessionManager {
337337
process.env.ANTHROPIC_API_KEY = credentials.apiKey;
338338
process.env.ANTHROPIC_AUTH_TOKEN = credentials.apiKey;
339339
process.env.ANTHROPIC_BASE_URL = `${credentials.apiHost}/api/projects/${credentials.projectId}/llm_gateway`;
340-
process.env.ELECTRON_RUN_AS_NODE = "1";
340+
// process.env.ELECTRON_RUN_AS_NODE = "1";
341341
process.env.CLAUDE_CODE_EXECUTABLE = getClaudeCliPath();
342342

343343
// Set env vars for SessionStore in agent package
Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { AsciiArt } from "@components/AsciiArt";
21
import { Box } from "@radix-ui/themes";
32
import type React from "react";
43

@@ -9,14 +8,5 @@ interface BackgroundWrapperProps {
98
export const BackgroundWrapper: React.FC<BackgroundWrapperProps> = ({
109
children,
1110
}) => {
12-
return (
13-
<Box height="100%" position="relative">
14-
<Box style={{ position: "absolute", inset: 0, zIndex: 0 }}>
15-
<AsciiArt scale={1} opacity={0.1} />
16-
</Box>
17-
<Box style={{ position: "relative", zIndex: 1, height: "100%" }}>
18-
{children}
19-
</Box>
20-
</Box>
21-
);
11+
return <Box height="100%">{children}</Box>;
2212
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import type { ReactNode } from "react";
2+
3+
type CodeBlockSize = "1" | "1.5" | "2" | "3";
4+
5+
interface CodeBlockProps {
6+
children: ReactNode;
7+
size?: CodeBlockSize;
8+
}
9+
10+
const sizeStyles: Record<
11+
CodeBlockSize,
12+
{ fontSize: string; lineHeight: string }
13+
> = {
14+
"1": {
15+
fontSize: "var(--font-size-1)",
16+
lineHeight: "var(--line-height-1)",
17+
},
18+
"1.5": {
19+
fontSize: "var(--font-size-1-5)",
20+
lineHeight: "var(--line-height-1-5)",
21+
},
22+
"2": {
23+
fontSize: "var(--font-size-2)",
24+
lineHeight: "var(--line-height-2)",
25+
},
26+
"3": {
27+
fontSize: "var(--font-size-3)",
28+
lineHeight: "var(--line-height-3)",
29+
},
30+
};
31+
32+
export function CodeBlock({ children, size = "1" }: CodeBlockProps) {
33+
const styles = sizeStyles[size];
34+
35+
return (
36+
<pre
37+
style={{
38+
margin: 0,
39+
marginBottom: "var(--space-3)",
40+
padding: "var(--space-3)",
41+
backgroundColor: "var(--gray-2)",
42+
borderRadius: "var(--radius-2)",
43+
border: "1px solid var(--gray-4)",
44+
fontFamily: "var(--code-font-family)",
45+
fontSize: styles.fontSize,
46+
lineHeight: styles.lineHeight,
47+
color: "var(--gray-12)",
48+
overflowX: "auto",
49+
whiteSpace: "pre",
50+
}}
51+
>
52+
{children}
53+
</pre>
54+
);
55+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
type DividerSize = "1" | "2" | "3";
2+
3+
interface DividerProps {
4+
size?: DividerSize;
5+
}
6+
7+
const sizeStyles: Record<DividerSize, { marginY: string }> = {
8+
"1": { marginY: "var(--space-2)" },
9+
"2": { marginY: "var(--space-3)" },
10+
"3": { marginY: "var(--space-4)" },
11+
};
12+
13+
export function Divider({ size = "2" }: DividerProps) {
14+
const styles = sizeStyles[size];
15+
16+
return (
17+
<hr
18+
style={{
19+
border: "none",
20+
borderTop: "1px solid var(--gray-6)",
21+
marginTop: styles.marginY,
22+
marginBottom: styles.marginY,
23+
}}
24+
/>
25+
);
26+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import type { ReactNode } from "react";
2+
3+
type ListSize = "1" | "1.5" | "2" | "3";
4+
5+
interface ListProps {
6+
children: ReactNode;
7+
size?: ListSize;
8+
as?: "ul" | "ol";
9+
}
10+
11+
interface ListItemProps {
12+
children: ReactNode;
13+
size?: ListSize;
14+
}
15+
16+
const sizeStyles: Record<
17+
ListSize,
18+
{ fontSize: string; lineHeight: string; spacing: string }
19+
> = {
20+
"1": {
21+
fontSize: "var(--font-size-1)",
22+
lineHeight: "var(--line-height-1)",
23+
spacing: "var(--space-1)",
24+
},
25+
"1.5": {
26+
fontSize: "var(--font-size-1-5)",
27+
lineHeight: "var(--line-height-1-5)",
28+
spacing: "var(--space-1)",
29+
},
30+
"2": {
31+
fontSize: "var(--font-size-2)",
32+
lineHeight: "var(--line-height-2)",
33+
spacing: "var(--space-1)",
34+
},
35+
"3": {
36+
fontSize: "var(--font-size-3)",
37+
lineHeight: "var(--line-height-3)",
38+
spacing: "var(--space-2)",
39+
},
40+
};
41+
42+
export function List({ children, as = "ul" }: ListProps) {
43+
const Component = as;
44+
45+
return (
46+
<Component
47+
style={{
48+
margin: 0,
49+
marginTop: "var(--space-2)",
50+
paddingLeft: as === "ol" ? "var(--space-5)" : "var(--space-4)",
51+
marginBottom: "var(--space-3)",
52+
listStyleType: as === "ol" ? "decimal" : "disc",
53+
listStylePosition: "outside",
54+
}}
55+
>
56+
{children}
57+
</Component>
58+
);
59+
}
60+
61+
export function ListItem({ children, size = "2" }: ListItemProps) {
62+
const styles = sizeStyles[size];
63+
64+
return (
65+
<li
66+
style={{
67+
fontSize: styles.fontSize,
68+
lineHeight: styles.lineHeight,
69+
marginBottom: styles.spacing,
70+
color: "var(--gray-12)",
71+
}}
72+
>
73+
{children}
74+
</li>
75+
);
76+
}

apps/array/src/renderer/features/auth/components/AuthScreen.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,10 @@ export function AuthScreen() {
135135
>
136136
<Select.Trigger />
137137
<Select.Content>
138-
<Select.Item value="us">🇺🇸 US Cloud</Select.Item>
139-
<Select.Item value="eu">🇪🇺 EU Cloud</Select.Item>
138+
<Select.Item value="us">US Cloud</Select.Item>
139+
<Select.Item value="eu">EU Cloud</Select.Item>
140140
{IS_DEV && (
141-
<Select.Item value="dev">🔧 Development</Select.Item>
141+
<Select.Item value="dev">Development</Select.Item>
142142
)}
143143
</Select.Content>
144144
</Select.Root>

0 commit comments

Comments
 (0)