Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ jobs:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify packaged DuckDB VSS for Windows
shell: bash
Expand Down Expand Up @@ -169,7 +168,6 @@ jobs:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify packaged DuckDB VSS for Linux
shell: bash
Expand Down Expand Up @@ -263,7 +261,6 @@ jobs:
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
NODE_OPTIONS: '--max-old-space-size=4096'
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify packaged DuckDB VSS for macOS
shell: bash
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/prcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,3 @@ jobs:
- name: Build
run: pnpm run build
env:
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}
3 changes: 0 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ jobs:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify packaged DuckDB VSS for Windows
shell: bash
Expand Down Expand Up @@ -263,7 +262,6 @@ jobs:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify packaged DuckDB VSS for Linux
shell: bash
Expand Down Expand Up @@ -360,7 +358,6 @@ jobs:
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
NODE_OPTIONS: '--max-old-space-size=4096'
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify packaged DuckDB VSS for macOS
shell: bash
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/windows-arm64-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ jobs:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify bundled plugins
shell: bash
Expand Down
34 changes: 34 additions & 0 deletions docs/architecture/dead-code-cleanup-2026-06/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Dead Code Cleanup 2026-06 - Spec

## Problem

Two confirmed dead-code candidates remain:

- `readDirectoryTree` in `src/main/presenter/workspacePresenter/directoryReader.ts`
- `src/renderer/src/composables/usePageCapture.example.ts`

They are not used by production code or tests except for self-reference/commented example references.

## Goal

Remove confirmed dead code without changing runtime behavior.

## Evidence

- `rg readDirectoryTree src test docs` only finds the deprecated function and its recursive self-call.
- Production message capture imports `@/composables/message/useMessageCapture`, not `usePageCapture.example`.
- `usePageCapture.example.ts` is an example file under `src/renderer/src`, which keeps it in source search/typecheck scope.

## Acceptance Criteria

1. `rg readDirectoryTree src test docs` returns no live production/test references after cleanup.
2. `rg usePageCapture.example src test docs` returns no live production/test references after cleanup.
3. No runtime imports are changed except removing dead exports/files.
4. Typecheck and lint pass.

## Non-Goals

- Do not run a broad dead-code sweep.
- Do not refactor workspace directory loading.
- Do not rewrite page capture implementation.

21 changes: 21 additions & 0 deletions docs/architecture/provider-db-github-source/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Provider DB GitHub Source - Spec

## Problem

Release builds can inject `VITE_PROVIDER_DB_URL` from `CDN_PROVIDER_DB_URL`, while local/test builds use the GitHub-hosted provider database. The CDN is being retired, so builds and runtime refreshes must stop depending on CDN injection.

## Goal

Use the GitHub provider database URL everywhere and remove provider DB URL override support from build workflows and runtime code.

## Acceptance Criteria

1. CI/release workflows no longer inject `CDN_PROVIDER_DB_URL` or `VITE_PROVIDER_DB_URL`.
2. Runtime provider DB refresh always uses the GitHub default URL.
3. Build-time provider DB fetch always uses the GitHub default URL.
4. Type declarations no longer expose `VITE_PROVIDER_DB_URL`.
5. The retired CDN hostname has no repository references.

## Non-Goals

- Do not remove unrelated `deepchatai.cn` official website, OAuth callback, or referer usage.
51 changes: 51 additions & 0 deletions docs/features/sidebar-chat-section-actions/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Sidebar Section New Chat Actions - Spec

## Problem

The sidebar Chat section header still shows a leading message icon and has no local new-chat action. Project folder headers also require the same local new-chat affordance, but only when the sidebar is grouped by project folders.

## Goal

Make Chat and Project folder headers use the same compact row interaction: hover covers the whole row, `+` appears inside the row action area, and new chats start with the matching workspace selected.

## UI Shape

Chat:

```text
Chat [+]
Chat session
Chat session
```

Project folder mode:

```text
folder design [+] [...]
Project session
```

Time grouping:

```text
Today
Project session
```

## Acceptance Criteria

1. The Chat section title no longer renders a leading icon.
2. Clicking the Chat title still collapses and expands Chat sessions.
3. Hovering the Chat row covers the title and `+` action area as one row.
4. Clicking the Chat `+` selects the Chat workspace and starts a new chat through the existing route/new-conversation path.
5. Clicking the Chat `+` does not toggle the Chat section collapse state.
6. Project folder rows show a `+` action before the existing `...` action when grouped by project.
7. Clicking a Project folder `+` selects that project workspace and starts a new chat.
8. Time-grouped rows do not show folder `+` actions.
9. No new user-facing strings are introduced.

## Non-Goals

- Do not redesign Workspace grouping.
- Do not change how sessions are persisted or created from `NewThreadPage`.
- Do not change Remote features.
30 changes: 30 additions & 0 deletions docs/issues/settings-window-overflow/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Settings Window Overflow - Spec

## Problem

Settings can be resized below the width assumed by several fixed-width rows. The window state persists user size, but `createSettingsWindow` sets no minimum size. A narrow Settings window can squeeze the fixed `w-60` sidebar plus rows that combine `min-w-[220px]` labels and `w-[320px]` controls.

## Goal

Prevent Settings content from overflowing horizontally at the smallest supported Settings window size.

## Evidence

- `src/main/presenter/windowPresenter/index.ts` creates the Settings `BrowserWindow` with default size only.
- `src/renderer/settings/App.vue` uses a fixed `w-60` sidebar.
- `src/renderer/settings/components/common/DefaultModelSettingsSection.vue` and `ProxySettingsSection.vue` use fixed 220px labels plus 320px controls.
- `src/renderer/settings/components/MemoryConfigPanel.vue` already shows the preferred responsive control pattern: `w-full min-w-0 ... md:w-[320px]`.

## Acceptance Criteria

1. A Settings window cannot be resized or restored narrower than the width required by current fixed rows.
2. At the minimum width, Settings pages do not show horizontal document overflow.
3. No new user-facing strings are introduced.
4. Existing Settings window state restore behavior still works for valid saved sizes.

## Non-Goals

- Do not redesign Settings layout.
- Do not rewrite every Settings row in this pass.
- Do not change main-window Plugins pages.

2 changes: 1 addition & 1 deletion scripts/fetch-provider-db.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ function sanitizeAggregateJson(json) {
}

async function main() {
const url = process.env.PROVIDER_DB_URL || DEFAULT_URL
const url = DEFAULT_URL
const outDir = path.resolve(process.cwd(), 'resources', 'model-db')
const outFile = path.join(outDir, 'providers.json')
const tmpFile = outFile + '.tmp'
Expand Down
1 change: 0 additions & 1 deletion src/main/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ interface ImportMetaEnv {
readonly VITE_LOG_IPC_CALL: string
readonly VITE_AGENT_PRESENTER_DEBUG?: string
readonly VITE_APP_LIFECYCLE_HOOK_DELAY?: string
readonly VITE_PROVIDER_DB_URL?: string
}

interface ImportMeta {
Expand Down
6 changes: 0 additions & 6 deletions src/main/presenter/configPresenter/providerDbLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,6 @@ export class ProviderDbLoader {
}

private getProviderDbUrl(): string {
const value = import.meta.env.VITE_PROVIDER_DB_URL
if (typeof value === 'string') {
const trimmed = value.trim()
if (trimmed.length > 0) return trimmed
}

return DEFAULT_PROVIDER_DB_URL
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/presenter/windowPresenter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,8 @@ export class WindowPresenter implements IWindowPresenter {
y: settingsWindowState.y,
width: settingsWindowState.width,
height: settingsWindowState.height,
minWidth: 900,
minHeight: 640,
show: false,
autoHideMenuBar: true,
fullscreenable: false,
Expand Down
60 changes: 0 additions & 60 deletions src/main/presenter/workspacePresenter/directoryReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,63 +71,3 @@ export async function readDirectoryShallow(dirPath: string): Promise<WorkspaceFi
return []
}
}

/**
* Recursively read directory structure (deprecated, use readDirectoryShallow for lazy loading)
* @param dirPath Directory path
* @param currentDepth Current depth
* @param maxDepth Maximum depth
*/
export async function readDirectoryTree(
dirPath: string,
currentDepth: number = 0,
maxDepth: number = 3
): Promise<WorkspaceFileNode[]> {
// Boundary check: depth limit
if (currentDepth >= maxDepth) {
return []
}

try {
const entries = await fs.readdir(dirPath, { withFileTypes: true })
const nodes: WorkspaceFileNode[] = []

for (const entry of entries) {
// Skip ignored files/directories
if (IGNORED_PATTERNS.includes(entry.name)) {
continue
}

// Skip hidden files (starting with .)
if (entry.name.startsWith('.')) {
continue
}

const fullPath = path.join(dirPath, entry.name)
const node: WorkspaceFileNode = {
name: entry.name,
path: fullPath,
isDirectory: entry.isDirectory()
}

// Recursively read subdirectories
if (entry.isDirectory()) {
node.children = await readDirectoryTree(fullPath, currentDepth + 1, maxDepth)
node.expanded = false // Default collapsed
}

nodes.push(node)
}

// Sort: directories first, files second, same type sorted by name
return nodes.sort((a, b) => {
if (a.isDirectory !== b.isDirectory) {
return a.isDirectory ? -1 : 1
}
return a.name.localeCompare(b.name)
})
} catch (error) {
console.error(`[Workspace] Failed to read directory ${dirPath}:`, error)
return []
}
}
Loading