Skip to content

Commit d07be8c

Browse files
Merge branch 'main' into konrad/public-api-auth
2 parents c329028 + 596df83 commit d07be8c

File tree

136 files changed

+5686
-2514
lines changed

Some content is hidden

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

136 files changed

+5686
-2514
lines changed

.env.development

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,5 @@ SOURCEBOT_TELEMETRY_DISABLED=true # Disables telemetry collection
7676
# CONFIG_MAX_REPOS_NO_TOKEN=
7777
NODE_ENV=development
7878
# SOURCEBOT_TENANCY_MODE=single
79+
80+
DEBUG_WRITE_CHAT_MESSAGES_TO_FILE=true
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
name: License Audit
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
paths:
7+
- "yarn.lock"
8+
- "package.json"
9+
- "packages/*/package.json"
10+
- "scripts/fetchLicenses.mjs"
11+
- "scripts/summarizeLicenses.mjs"
12+
- "scripts/npmLicenseMap.json"
13+
- "scripts/licenseAuditPrompt.txt"
14+
- "scripts/runLicenseAudit.sh"
15+
workflow_dispatch:
16+
17+
jobs:
18+
license-audit:
19+
runs-on: ubuntu-latest
20+
permissions:
21+
contents: read
22+
pull-requests: write
23+
id-token: write
24+
steps:
25+
- name: Checkout repository
26+
uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 1
29+
30+
- name: Setup Node.js
31+
uses: actions/setup-node@v4
32+
with:
33+
node-version: "20"
34+
cache: "yarn"
35+
36+
- name: Install dependencies
37+
run: yarn install --frozen-lockfile
38+
39+
- name: Fetch licenses
40+
run: node scripts/fetchLicenses.mjs
41+
42+
- name: Summarize licenses
43+
run: node scripts/summarizeLicenses.mjs
44+
45+
- name: Read audit prompt
46+
id: read-prompt
47+
run: |
48+
{
49+
echo 'PROMPT<<PROMPT_EOF'
50+
cat scripts/licenseAuditPrompt.txt
51+
echo 'PROMPT_EOF'
52+
} >> "$GITHUB_OUTPUT"
53+
54+
- name: Audit licenses with Claude
55+
uses: anthropics/claude-code-action@v1
56+
with:
57+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
58+
claude_args: '--allowedTools "Bash,Read,Write,Glob,Grep,WebFetch"'
59+
prompt: ${{ steps.read-prompt.outputs.PROMPT }}
60+
61+
- name: Validate audit result
62+
run: |
63+
if [ ! -f license-audit-result.json ]; then
64+
echo "::error::license-audit-result.json was not created by the audit step"
65+
exit 1
66+
fi
67+
68+
STATUS=$(node -e "const r = require('./license-audit-result.json'); console.log(r.status)")
69+
UNRESOLVED=$(node -e "const r = require('./license-audit-result.json'); console.log(r.summary.unresolvedCount)")
70+
STRONG=$(node -e "const r = require('./license-audit-result.json'); console.log(r.summary.strongCopyleftCount)")
71+
WEAK=$(node -e "const r = require('./license-audit-result.json'); console.log(r.summary.weakCopyleftCount)")
72+
RESOLVED=$(node -e "const r = require('./license-audit-result.json'); console.log(r.summary.resolvedCount)")
73+
74+
echo "## License Audit Result: $STATUS"
75+
echo ""
76+
echo "- Resolved: $RESOLVED"
77+
echo "- Unresolved: $UNRESOLVED"
78+
echo "- Strong copyleft: $STRONG"
79+
echo "- Weak copyleft: $WEAK"
80+
81+
if [ "$STATUS" = "FAIL" ]; then
82+
echo ""
83+
echo "::error::License audit failed. See details below:"
84+
node -e "const r = require('./license-audit-result.json'); r.failReasons.forEach(r => console.log(' - ' + r))"
85+
exit 1
86+
fi
87+
88+
- name: Comment on PR
89+
if: always() && github.event_name == 'pull_request'
90+
uses: actions/github-script@v7
91+
with:
92+
script: |
93+
const fs = require('fs');
94+
const resultPath = 'license-audit-result.json';
95+
96+
// Determine if we should comment
97+
let shouldComment = false;
98+
let body = '';
99+
100+
if (!fs.existsSync(resultPath)) {
101+
shouldComment = true;
102+
body = `## License Audit\n\n:x: Audit failed to produce results. Check the workflow logs for details.`;
103+
} else {
104+
const result = JSON.parse(fs.readFileSync(resultPath, 'utf-8'));
105+
const hasWeakCopyleft = result.summary.weakCopyleftCount > 0;
106+
const isFail = result.status === 'FAIL';
107+
108+
if (!isFail && !hasWeakCopyleft) {
109+
return;
110+
}
111+
112+
shouldComment = true;
113+
const icon = isFail ? ':x:' : ':warning:';
114+
115+
body = `## License Audit\n\n`;
116+
body += `${icon} **Status: ${result.status}**\n\n`;
117+
body += `| Metric | Count |\n|---|---|\n`;
118+
body += `| Total packages | ${result.summary.totalPackages} |\n`;
119+
body += `| Resolved (non-standard) | ${result.summary.resolvedCount} |\n`;
120+
body += `| Unresolved | ${result.summary.unresolvedCount} |\n`;
121+
body += `| Strong copyleft | ${result.summary.strongCopyleftCount} |\n`;
122+
body += `| Weak copyleft | ${result.summary.weakCopyleftCount} |\n`;
123+
124+
if (result.failReasons && result.failReasons.length > 0) {
125+
body += `\n### Fail Reasons\n\n`;
126+
for (const reason of result.failReasons) {
127+
body += `- ${reason}\n`;
128+
}
129+
}
130+
131+
if (result.unresolved && result.unresolved.length > 0) {
132+
body += `\n### Unresolved Packages\n\n`;
133+
body += `| Package | Version | License | Reason |\n|---|---|---|---|\n`;
134+
for (const pkg of result.unresolved) {
135+
body += `| ${pkg.name} | ${pkg.version} | \`${pkg.license}\` | ${pkg.reason} |\n`;
136+
}
137+
}
138+
139+
if (result.copyleft && result.copyleft.strong && result.copyleft.strong.length > 0) {
140+
body += `\n### Strong Copyleft Packages\n\n`;
141+
body += `| Package | Version | License |\n|---|---|---|\n`;
142+
for (const pkg of result.copyleft.strong) {
143+
body += `| ${pkg.name} | ${pkg.version} | \`${pkg.license}\` |\n`;
144+
}
145+
}
146+
147+
if (result.copyleft && result.copyleft.weak && result.copyleft.weak.length > 0) {
148+
body += `\n### Weak Copyleft Packages (informational)\n\n`;
149+
body += `| Package | Version | License |\n|---|---|---|\n`;
150+
for (const pkg of result.copyleft.weak) {
151+
body += `| ${pkg.name} | ${pkg.version} | \`${pkg.license}\` |\n`;
152+
}
153+
}
154+
155+
if (result.resolved && result.resolved.length > 0) {
156+
body += `\n<details><summary>Resolved Packages (${result.resolved.length})</summary>\n\n`;
157+
body += `| Package | Version | Original | Resolved | Source |\n|---|---|---|---|---|\n`;
158+
for (const pkg of result.resolved) {
159+
body += `| ${pkg.name} | ${pkg.version} | \`${pkg.originalLicense}\` | \`${pkg.resolvedLicense}\` | ${pkg.source} |\n`;
160+
}
161+
body += `\n</details>\n`;
162+
}
163+
}
164+
165+
if (!shouldComment) return;
166+
167+
const comments = await github.rest.issues.listComments({
168+
owner: context.repo.owner,
169+
repo: context.repo.repo,
170+
issue_number: context.issue.number,
171+
});
172+
const existing = comments.data.find(c => c.body.startsWith('## License Audit'));
173+
if (existing) {
174+
await github.rest.issues.updateComment({
175+
owner: context.repo.owner,
176+
repo: context.repo.repo,
177+
comment_id: existing.id,
178+
body,
179+
});
180+
} else {
181+
await github.rest.issues.createComment({
182+
owner: context.repo.owner,
183+
repo: context.repo.repo,
184+
issue_number: context.issue.number,
185+
body,
186+
});
187+
}
188+
189+
- name: Upload artifacts
190+
if: always()
191+
uses: actions/upload-artifact@v4
192+
with:
193+
name: license-audit
194+
path: |
195+
oss-licenses.json
196+
oss-license-summary.json
197+
license-audit-result.json

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,7 @@ dist
163163
.sourcebot
164164
/bin
165165
/config.json
166-
.DS_Store
166+
.DS_Store
167+
oss-licenses.json
168+
oss-license-summary.json
169+
license-audit-result.json

AGENTS.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Agents
2+
3+
## Cursor Cloud specific instructions
4+
5+
### Overview
6+
7+
Sourcebot is a self-hosted code intelligence platform (code search, navigation, AI Q&A). It's a Yarn 4 monorepo with packages under `packages/` and a vendored Go-based search engine (Zoekt) under `vendor/zoekt`.
8+
9+
### Prerequisites
10+
11+
- **Node.js 24+** (required by the project)
12+
- **Go** (for building Zoekt binaries from `vendor/zoekt`)
13+
- **Docker** (for PostgreSQL 16 and Redis 7 via `docker-compose-dev.yml`)
14+
- **universal-ctags** (used by Zoekt for symbol indexing; pre-installed as `ctags`)
15+
16+
### Services and Ports
17+
18+
| Service | Port | Notes |
19+
|---------|------|-------|
20+
| Web (Next.js) | 3000 | Redirects to `/onboard` on first run |
21+
| Backend worker | 3060 | Express + BullMQ job processor |
22+
| Zoekt WebServer | 6070 | Code search engine (Go binary) |
23+
| PostgreSQL | 5432 | Via `docker-compose-dev.yml` |
24+
| Redis | 6379 | Via `docker-compose-dev.yml` |
25+
26+
### Key Commands
27+
28+
Standard dev commands are documented in `CONTRIBUTING.md` and `package.json`. Key ones:
29+
30+
- **Start all services:** `yarn dev` (runs zoekt, backend, web, mcp watcher, schemas watcher concurrently)
31+
- **Lint:** `yarn workspace @sourcebot/web lint`
32+
- **Test:** `yarn test` (runs all workspace tests)
33+
- **Build deps only:** `yarn build:deps` (builds shared packages: schemas, db, shared, query-language)
34+
- **DB migrations:** `yarn dev:prisma:migrate:dev`
35+
36+
### Deprecated Packages
37+
38+
- **`packages/mcp`** - This standalone MCP package is deprecated. Do NOT modify it. MCP functionality is now handled by the web package at `packages/web/src/features/mcp/`.
39+
40+
### Non-obvious Caveats
41+
42+
- **Docker must be running** before `yarn dev`. Start it with `docker compose -f docker-compose-dev.yml up -d`. The backend will fail to connect to Redis/PostgreSQL otherwise.
43+
- **Zoekt binaries** must be built before `yarn dev`. They live in `./bin/` and are built with `go build -C vendor/zoekt -o $(pwd)/bin ./cmd/...`. The `make zoekt` target does this.
44+
- **Git submodules** must be initialized (`git submodule update --init --recursive`) before building Zoekt.
45+
- **ctags compatibility:** The installed `ctags` may not support `--_interactive=default` (universal-ctags feature). Zoekt logs a warning but continues to index without symbol data. This does not block functionality.
46+
- **First run onboarding:** On a fresh database, the web app redirects to `/onboard` where you create an owner account. Credentials login is enabled by default (`AUTH_CREDENTIALS_LOGIN_ENABLED` defaults to `true`).
47+
- **Config file:** Create a `config.json` at the repo root (referenced by `CONFIG_PATH` in `.env.development`) to configure which repos to index. A minimal example is in `CONTRIBUTING.md`.
48+
- **Environment variables:** `.env.development` has sensible defaults for local dev. Create `.env.development.local` for overrides (it's gitignored).
49+
- The backend worker does not expose a health-check endpoint. Verify it's running by checking its logs or that BullMQ jobs are processing.
50+
51+
### Pull Request Workflow
52+
53+
- **CHANGELOG entry required:** Every PR must include a follow-up commit adding an entry to `CHANGELOG.md` under `[Unreleased]`. The entry must be a single sentence describing the change, followed by a link to the PR in the format `[#<id>](https://github.com/sourcebot-dev/sourcebot/pull/<id>)`. Place new entries at the bottom of the appropriate section (`Added`, `Changed`, `Fixed`, etc.). See `CLAUDE.md` and existing entries in `CHANGELOG.md` for the exact conventions.

CHANGELOG.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,91 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
- Fixed line numbers being selectable in Safari in the lightweight code highlighter. [#1037](https://github.com/sourcebot-dev/sourcebot/pull/1037)
12+
- Fixed GitLab sync deleting repos when the API returns a non-404 error (e.g. 500) during group/user/project fetch. [#1039](https://github.com/sourcebot-dev/sourcebot/pull/1039)
13+
- Fixed React hydration mismatch in `KeyboardShortcutHint` caused by platform detection running at module load time during SSR. [#1041](https://github.com/sourcebot-dev/sourcebot/pull/1041)
14+
- Fixed rendering performance for ask threads, especially when hovering or selecting citations. [#1042](https://github.com/sourcebot-dev/sourcebot/pull/1042)
15+
16+
### Added
17+
- Added optional copy button to the lightweight code highlighter (`isCopyButtonVisible` prop), shown on hover. [#1037](https://github.com/sourcebot-dev/sourcebot/pull/1037)
18+
19+
## [4.16.1] - 2026-03-24
20+
21+
### Fixed
22+
- Fixed scroll position when selecting chat references that point to lines further down in a file. [#1036](https://github.com/sourcebot-dev/sourcebot/pull/1036)
23+
24+
## [4.16.0] - 2026-03-24
25+
26+
### Changed
27+
- Changed language detection to resolve file extensions with multiple language resolutions (e.g., .md) to the most common resolution. [#1026](https://github.com/sourcebot-dev/sourcebot/pull/1026)
28+
- Changed the `webUrl` property of the `/api/repos` api to return a URL rather than just a path. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
29+
- Changed the ask search scope selector to allow submitting questions with no search scope selected. When no selection is made, the agent will be able to search over all repos the user has access to. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
30+
- Renamed the `search_code` tool to `grep` for ask and mcp. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
31+
- Improved auto-scroll behavior in the ask chat thread. [#1031](https://github.com/sourcebot-dev/sourcebot/pull/1031)
32+
33+
### Added
34+
- Added `glob`, `find_symbol_definitions`, and `find_symbol_references` tools to the ask agent and MCP server. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
35+
- Added `list_tree` tool to the ask agent. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
36+
- Added input & output token breakdown in ask details card. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
37+
- Added `path` parameter to the `/api/commits` api to allow filtering commits by paths. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
38+
- Search contexts now support topic-based filtering with new `includeTopics` and `excludeTopics` fields, enabling repository filtering by GitHub/GitLab topics with glob pattern support and case-insensitive matching.[#1028](https://github.com/sourcebot-dev/sourcebot/pull/1028)
39+
40+
### Fixed
41+
- Fixed issue where ask responses would sometimes appear in the details panel while generating. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
42+
- Fixed reference panel overflow issue in the ask UI. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
43+
- Fixed homepage scrolling issue in the ask UI. [#1014](https://github.com/sourcebot-dev/sourcebot/pull/1014)
44+
- Fixed UI freeze when the `grep` tool returns a large number of results with `groupByRepo=true`. [#1032](https://github.com/sourcebot-dev/sourcebot/pull/1032)
45+
- Fixed issue where the search scope selection persisted after a new thread is created. [#1033](https://github.com/sourcebot-dev/sourcebot/pull/1033)
46+
- Fixed inaccurate scroll position when selecting a chat reference in the ask UI. [#1035](https://github.com/sourcebot-dev/sourcebot/pull/1035)
47+
48+
## [4.15.11] - 2026-03-20
49+
50+
### Changed
51+
- Updated JumpCloud SSO documentation to clarify token endpoint authentication method requirement and AUTH_SECRET configuration. [#1022](https://github.com/sourcebot-dev/sourcebot/pull/1022)
52+
- The `ask_codebase` MCP tool is now hidden when no language model providers are configured. [#1018](https://github.com/sourcebot-dev/sourcebot/pull/1018)
53+
54+
## [4.15.10] - 2026-03-20
55+
56+
### Changed
57+
- Increased `SOURCEBOT_CHAT_MAX_STEP_COUNT` default from 20 to 100 to allow agents to perform more autonomous steps. [#1017](https://github.com/sourcebot-dev/sourcebot/pull/1017)
58+
- [EE] Fix error with Jumpcloud SSO state param [#1020](https://github.com/sourcebot-dev/sourcebot/pull/1020)
59+
60+
## [4.15.9] - 2026-03-17
61+
62+
### Added
63+
- Added read-only annotations to MCP tools for compatibility with Cursor Ask mode and other MCP clients that restrict tool usage based on behavior hints. [#1013](https://github.com/sourcebot-dev/sourcebot/pull/1013)
64+
65+
## [4.15.8] - 2026-03-17
66+
67+
### Added
68+
- Added support for connecting to Redis over TLS via `REDIS_TLS_ENABLED` and related environment variables. [#1011](https://github.com/sourcebot-dev/sourcebot/pull/1011)
69+
70+
### Changed
71+
- `filterByFilepaths` in the MCP `search_code` tool now accepts regular expressions matched against the full file path, instead of treating values as escaped literals. [#1008](https://github.com/sourcebot-dev/sourcebot/pull/1008)
72+
73+
### Fixed
74+
- Connection sync job failures now log the actual error reason instead of a generic message. [#1012](https://github.com/sourcebot-dev/sourcebot/pull/1012)
75+
76+
## [4.15.7] - 2026-03-16
77+
78+
### Added
79+
- Added AGENTS.md with Cursor Cloud development environment instructions. [#1001](https://github.com/sourcebot-dev/sourcebot/pull/1001)
80+
- Added support for configuring SMTP via individual environment variables (SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD) as an alternative to SMTP_CONNECTION_URL. [#1002](https://github.com/sourcebot-dev/sourcebot/pull/1002)
81+
- Added `DISABLE_API_KEY_CREATION_FOR_NON_OWNER_USERS` and `DISABLE_API_KEY_USAGE_FOR_NON_OWNER_USERS` environment variables to restrict API key creation and usage to organization owners. [#1007](https://github.com/sourcebot-dev/sourcebot/pull/1007)
82+
83+
### Changed
84+
- Deprecated `EXPERIMENT_DISABLE_API_KEY_CREATION_FOR_NON_ADMIN_USERS` in favour of `DISABLE_API_KEY_CREATION_FOR_NON_OWNER_USERS`. The old variable will continue to work as a fallback. [#1007](https://github.com/sourcebot-dev/sourcebot/pull/1007)
85+
86+
### Modified
87+
- Made OSS license audit runnable locally [#1021](https://github.com/sourcebot-dev/sourcebot/pull/1021)
88+
89+
1090
## [4.15.6] - 2026-03-13
1191

1292
### Added
1393
- Added generated OpenAPI documentation for the public search, repo, and file browsing API surface. [#996](https://github.com/sourcebot-dev/sourcebot/pull/996)
94+
- Added OSS license audit github action. [#1003](https://github.com/sourcebot-dev/sourcebot/pull/1003)
1495

1596
### Fixed
1697
- [EE] Fixed account-driven permission sync silently wiping all Bitbucket Server repository permissions when the OAuth token expires on instances with anonymous access enabled. [#998](https://github.com/sourcebot-dev/sourcebot/pull/998)

CLAUDE.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,25 @@ Exceptions:
3838
- Special files like `README.md`, `CHANGELOG.md`, `LICENSE`
3939
- Next.js conventions: `page.tsx`, `layout.tsx`, `loading.tsx`, etc.
4040

41+
## Code Style
42+
43+
Always use curly braces for `if` statements, with the body on a new line — even for single-line bodies:
44+
45+
```ts
46+
// Correct
47+
if (!value) {
48+
return;
49+
}
50+
if (condition) {
51+
doSomething();
52+
}
53+
54+
// Incorrect
55+
if (!value) return;
56+
if (!value) { return; }
57+
if (condition) doSomething();
58+
```
59+
4160
## Tailwind CSS
4261

4362
Use Tailwind color classes directly instead of CSS variable syntax:
@@ -247,6 +266,5 @@ PR description:
247266

248267
After the PR is created:
249268
- Update CHANGELOG.md with an entry under `[Unreleased]` linking to the new PR. New entries should be placed at the bottom of their section.
250-
- If the change touches `packages/mcp`, update `packages/mcp/CHANGELOG.md` instead
251269
- Do NOT add a CHANGELOG entry for documentation-only changes (e.g., changes only in `docs/`)
252270
- Enterprise-only features (gated by an entitlement) should be prefixed with `[EE]` in the CHANGELOG entry (e.g., `- [EE] Added support for ...`)

0 commit comments

Comments
 (0)