Skip to content
Closed
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
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
# Changelog

## Unreleased

### Public Upstream Sync - 2026-04-11

#### Included in this upstream-safe branch
- Chat composer queue and steer workflow:
- Added durable queued-turn data structures and queue reconciliation helpers.
- Added steer promotion, paused queue handling, queued-turn resume, and queue cleanup after turn settlement.
- Added queue/session-scope tests for `codexQueue`, `sessionLoadGuards`, `sessionSnapshotCache`, and `sessionScope`.
- Session stability and protocol hardening:
- Added explicit WebSocket lifecycle protocol messages: `session-accepted`, `session-busy`, `session-state-changed`.
- Added project-scoped event enrichment for session lifecycle payloads to avoid cross-session/cross-project ambiguity.
- Added lifecycle projection from provider completion/error messages into normalized session-state events.
- Added session-created `projectName` metadata for Claude/Cursor/Gemini session initialization paths.
- Removed unused `projectPath` from `session-accepted` payloads; downstream should rely on `projectName` + scoped identifiers.
- Nano chain compatibility:
- UI provider/model selection no longer surfaces Nano by default in the upstream-safe branch, while server-side `nano-command` handling remains for compatibility.
- Preserved Nano command path and active session reporting in WebSocket session status flows.
- Ensured session lifecycle protocol is emitted consistently for Nano just like other providers.

#### Migration notes
- **Message cache key change**: Session message cache keys are now scoped by provider (`chat_messages_{project}_{provider}_{session}`). Existing localStorage entries keyed the old way (`chat_messages_{project}_{session}`) will not be read by default. To migrate, set `allowLegacyFallback: true` when calling `getSessionMessageCacheKeys()`. Users upgrading from builds prior to this sync may see empty transcript history on first load for previously-active sessions; the data is still in localStorage and can be recovered by enabling the legacy fallback or manually re-keying the entries.

#### Explicitly excluded (local/private only, not part of upstream PR)
- Codex-only product strategy and provider lock-in controls.
- External auth / license refresh-heartbeat-offline-grace stack.
- Project root hard-cut and Codex session backfill private policy behavior.
- LingZhi/LingzhiLab branding replacements and private demo/link route changes.

#### Cross-platform notes
- No platform-specific server behavior was hardcoded for this sync.
- Session protocol additions are transport-level and provider-agnostic; Windows-specific stability paths do not alter macOS behavior.

#### Validation
- Passed: `node --check server/index.js`
- Passed: `node --check server/claude-sdk.js`
- Passed: `node --check server/cursor-cli.js`
- Passed: `node --check server/gemini-cli.js`
- Not runnable in current environment (missing local dev dependencies): `vitest`, `tsc`

## Dr. Claw v1.1.1 - 2026-03-30

### Highlights
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ When you first open Dr. Claw you will see the **Projects** sidebar. You have two
- **Open an existing project** — Dr. Claw auto-discovers registered projects and linked sessions from Claude Code, Codex, and Gemini.
- **Create a new project** — Click the **"+"** button, choose a directory on your machine, and Dr. Claw will set up the workspace: agent folders such as `.claude/`, `.agents/`, `.gemini/`, standard workspace metadata, linked `skills/` directories, preset research dirs (`Survey/references`, `Survey/reports`, `Ideation/ideas`, `Ideation/references`, `Experiment/code_references`, `Experiment/datasets`, `Experiment/core_code`, `Experiment/analysis`, `Publication/paper`, `Promotion/homepage`, `Promotion/slides`, `Promotion/audio`, `Promotion/video`), and **instance.json** at the project root with absolute paths for those directories. Cursor agent support is coming soon.

> **Default project storage path:** New projects are stored under `~/dr-claw` by default. You can change this in **Settings → Appearance → Default Project Path**, or set the `WORKSPACES_ROOT` environment variable. The setting is persisted in `~/.claude/project-config.json`.
> **Default project storage path:** New projects are stored under `~/dr-claw` by default. You can change this in **Settings → Appearance → Default Project Path**, or set the `WORKSPACES_ROOT` environment variable. The setting is persisted in `~/.dr-claw/project-config.json` (with automatic one-time migration from `~/.claude/project-config.json`).

</details>

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ Dr. Claw 的核心功能是 **Research Lab**。
- **打开已有项目** — Dr. Claw 会自动发现已注册项目,以及来自 Claude Code、Codex、Gemini 的关联会话。
- **创建新项目** — 点击 **"+"** 按钮,选择本机的一个目录,Dr. Claw 会创建:`.claude/`、`.agents/`、`.gemini/` 等 Agent 目录、标准工作区元数据、链接的 `skills/` 目录、预设研究目录(`Survey/references`、`Survey/reports`、`Ideation/ideas`、`Ideation/references`、`Experiment/code_references`、`Experiment/datasets`、`Experiment/core_code`、`Experiment/analysis`、`Publication/paper`、`Promotion/homepage`、`Promotion/slides`、`Promotion/audio`、`Promotion/video`),以及项目根目录下的 **instance.json**(上述目录的绝对路径写入其中)。Cursor Agent 支持即将推出。

> **默认项目存储路径:** 新项目默认存储在 `~/dr-claw` 目录下。可在 **Settings → Appearance → Default Project Path** 中修改,也可通过环境变量 `WORKSPACES_ROOT` 设置。该配置持久化在 `~/.claude/project-config.json` 中。
> **默认项目存储路径:** 新项目默认存储在 `~/dr-claw` 目录下。可在 **Settings → Appearance → Default Project Path** 中修改,也可通过环境变量 `WORKSPACES_ROOT` 设置。该配置持久化在 `~/.dr-claw/project-config.json` 中(会自动一次性迁移 `~/.claude/project-config.json`)

</details>

Expand Down
24 changes: 24 additions & 0 deletions src/components/chat/hooks/__tests__/useChatSessionState.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, expect, it } from 'vitest';

import {
hasPendingOptimisticSessionState,
hasTemporaryProcessingSessionKeys,
} from '../useChatSessionState';

describe('useChatSessionState temporary session helpers', () => {
it('treats temp sessions as pending optimistic sessions', () => {
expect(hasPendingOptimisticSessionState(null, 'new-session-123')).toBe(true);
expect(hasPendingOptimisticSessionState(null, 'temp-123')).toBe(true);
expect(hasPendingOptimisticSessionState({ sessionId: null, startedAt: Date.now() }, null)).toBe(true);
expect(hasPendingOptimisticSessionState(null, 'sess-123')).toBe(false);
});

it('detects temporary processing keys for both raw and scoped temp ids', () => {
expect(hasTemporaryProcessingSessionKeys(new Set(['new-session-1']))).toBe(true);
expect(hasTemporaryProcessingSessionKeys(new Set(['temp-1']))).toBe(true);
expect(hasTemporaryProcessingSessionKeys(new Set(['proj-a::codex::new-session-2']))).toBe(true);
expect(hasTemporaryProcessingSessionKeys(new Set(['proj-a::codex::temp-2']))).toBe(true);
expect(hasTemporaryProcessingSessionKeys(new Set(['proj-a::codex::sess-2']))).toBe(false);
expect(hasTemporaryProcessingSessionKeys(new Set(['sess-2']))).toBe(false);
});
});
Loading