Skip to content

feat: add AI chat sidebar for log analysis#312

Merged
erickzhao merged 10 commits intomainfrom
gxu-sleuth-pilot
May 6, 2026
Merged

feat: add AI chat sidebar for log analysis#312
erickzhao merged 10 commits intomainfrom
gxu-sleuth-pilot

Conversation

@georgexu99
Copy link
Copy Markdown
Contributor

@georgexu99 georgexu99 commented Apr 9, 2026

This PR adds an AI assistant sidebar powered by Claude via AWS Bedrock that helps engineers find and diagnose bugs in Slack desktop log files.

The assistant can search/read loaded logs, read state files, search configured codebase directories, and pull in architectural context from webapp, slack-desktop, and electron repos.

Screenshare.-.2026-04-08.5_37_47.PM.mp4

yarn lock is 5k lines due to the anthropic sdk, the bedrock sdk and some remark and markdown plugins

things that we have added:

  • AI chat panel with streaming responses and markdown rendering
  • tools that our ai can use: list_log_files, read/search_log_entries, read_state_file as well as read_repo_context tool with local-first + GitHub remote fallback (for electron/electron and other public repos)
  • Codebase search/read tools gated behind Preferences directory config: users can manually add folders in which the ai can search within
  • auth: this uses AWS SSO auth via fma-sso-assume-role just like slack claude/slack tend. This whole feature is hidden from users if they don't have the necessary toggles/roles
  • Resizable sidebar, keyboard shortcut (Cmd+L), menu item.
  • claude and i also added a preferences button at the bottom left of the app.

🤖 Generated with Claude Code

@georgexu99 georgexu99 requested a review from erickzhao April 9, 2026 00:38
Comment thread src/renderer/state/ai-store.ts
Comment on lines +171 to +185
for (const file of allLogFiles) {
context.files.push({
fileName: file.logFile.fileName,
logType: file.logType,
entryCount: file.logEntries.length,
entries: file.logEntries.map((e) => ({
timestamp: e.timestamp,
level: e.level,
message: e.message,
line: e.line,
sourceFile: e.sourceFile,
})),
});
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: what's the intent behind this custom mapping? Are we dropping specific fields on purpose? It'd be good to document the decisions behind this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a jsdoc to address this

Comment thread src/renderer/state/ai-store.ts Outdated
Comment thread src/renderer/state/ai-store.ts Outdated
Comment thread src/renderer/state/ai-store.ts Outdated
Comment thread src/renderer/state/ai-store.ts
Comment thread src/renderer/state/ai-store.ts Outdated
Comment thread src/renderer/state/ai-store.ts Outdated
Add an AI assistant sidebar powered by Claude via AWS Bedrock that helps
engineers find and diagnose bugs in Slack desktop log files. The assistant
can search/read loaded logs, read state files, search configured codebase
directories, and pull in architectural context from webapp, slack-desktop,
and electron repos.

- AI chat panel with streaming responses and markdown rendering
- Tool-use loop: list_log_files, read/search_log_entries, read_state_file
- read_repo_context tool with local-first + GitHub remote fallback
- Codebase search/read tools gated behind Preferences directory config
- AWS SSO auth via fma-sso-assume-role (feature hidden from external users)
- Resizable sidebar, keyboard shortcut (Cmd+L), menu item

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Stop auto-scrolling when the user scrolls up during streaming, so they
can read earlier content without being pulled to the bottom. A floating
arrow button appears to jump back to the latest output. Auto-scroll
resumes automatically when a new user message is sent.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Cache serialized log context (immutable after processing)
- Split RendererAiMessage into UserAiMessage/AssistantAiMessage types
- Remove unnecessary JSON.parse(JSON.stringify()) deep clone
- Add @action and try/catch to sendMessage
- Validate and clear corrupt localStorage in loadCodebasePaths
- Document intentional field mapping in serializeAllLogs

🤖 Generated with [Claude Code](https://claude.com/claude-code)
During streaming, every chunk triggers a re-render of the full message
list. Without memoization, ReactMarkdown re-parses all previous messages
on every chunk. Now completed messages are wrapped in React.memo so only
the actively streaming message re-renders.

Also hoist the remarkPlugins array to module scope to avoid creating a
new array reference on every render.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Keep meta (stack traces, extended JSON payloads) and repeated (collapsed
duplicate lines) in the serialized log context — both carry diagnostic
value for the AI. Search also matches against meta content now.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Move sensitive infrastructure identifiers out of source code per security
review. The AI feature now reads from:
- SLEUTH_AI_FMA_ROLE: full fma-sso-assume-role role path
- SLEUTH_AI_MODEL: Bedrock model ID
- SLEUTH_AI_AWS_REGION: AWS region (defaults to us-east-1)

When SLEUTH_AI_FMA_ROLE is unset, checkAiAvailable() returns false and
the feature is completely hidden.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Add ai-config.ts that reads FMA role and model from a config file,
  with env vars as optional overrides. This allows the packaged Electron
  app to work without relying on shell environment variables (which
  aren't available to GUI apps launched from Finder/Spotlight).
- Fix crash in serializeAllLogs when installer array contains raw
  UnzippedFile entries that lack a .logFile property.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@erickzhao erickzhao self-requested a review April 29, 2026 19:34
checkAiAvailable() silently stayed false if the IPC call rejected.
Add catch handler with up to 2 retries (3s apart) and a console warning.
Comment thread src/main/ai/ai-service.ts Outdated
}));

// Tool-use loop
while (true) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: is it possible for this to just get stuck and loop infinitely? Should there be a max tool usage here?

Copy link
Copy Markdown
Contributor Author

@georgexu99 georgexu99 May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a cap of 20 tool iterations in ai-service.ts. When the limit is hit, we emit a message to the chat explaining that we stopped early and finish the stream cleanly 👍

<Divider />
<Typography.Title level={5}>AI Settings</Typography.Title>
<Form.Item layout="vertical" label="Codebase Directories">
<Space direction="vertical" style={{ width: '100%' }}>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<Space direction="vertical" style={{ width: '100%' }}>
<Space orientation="vertical" style={{ width: '100%' }}>

sorry, deprecation warning in antd 6

return (
<div className="MacTitlebar" onDoubleClick={handleDoubleClick}>
<span>{getWindowTitle(state.source)}</span>
{state.isAiAvailable && (
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be hidden if you're in the welcome screen.

Image

Comment thread src/main/ai/tools.ts
Comment on lines +519 to +527
if (
res.statusCode &&
res.statusCode >= 300 &&
res.statusCode < 400 &&
res.headers.location
) {
fetchUrl(res.headers.location).then(resolve, reject);
return;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Infinite recursion possible if we hit a redirect loop

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a MAX_REDIRECTS cap of 5 and threaded the remaining count through the recursive call; throws a clear error if exceeded.

Comment thread src/main/ai/tools.ts Outdated
@@ -0,0 +1,646 @@
import os from 'node:os';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused import

Comment thread package.json Outdated
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-json-tree": "0.18.0",
"react-markdown": "^8",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: although this is valid, we generally use the full semver string

Suggested change
"react-markdown": "^8",
"react-markdown": "^8.0.0",

Comment thread package.json Outdated
georgexu99 and others added 2 commits May 4, 2026 15:36
Co-authored-by: Erick Zhao <ezhao@slack-corp.com>
- Cap AI tool-use loop at 20 iterations to bound cost and prevent runaway loops
- Cap fetchUrl redirect chain at 5 to prevent infinite recursion
- Hide AI titlebar button on welcome screen (when no log bundle is loaded)
- Restore antd Space orientation prop and expand semver ranges
- Regenerate yarn.lock to match package.json
- Remove unused os import
Copy link
Copy Markdown
Member

@erickzhao erickzhao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@erickzhao erickzhao merged commit 4f651ba into main May 6, 2026
6 checks passed
@erickzhao erickzhao deleted the gxu-sleuth-pilot branch May 6, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants