Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
54bc076
docs(project): add workspace design research
hifizz Aug 29, 2026
4d9eb5b
docs(project): 补充依赖支线成果交接场景
hifizz Aug 30, 2026
7875a99
docs(project): 收敛引用与 Outcome 初步方案
hifizz Aug 30, 2026
7485666
docs(project): 冻结 Project MVP 范围与开发节奏
hifizz Aug 30, 2026
1675ed3
spec(project): 初始化 Project Workspace MVP OpenSpec
hifizz Aug 30, 2026
bf379eb
spec(project): 添加 Project Workspace MVP proposal
hifizz Aug 30, 2026
0570adb
spec(project): 添加 Project Workspace MVP design
hifizz Aug 30, 2026
ed34702
spec(project): 添加 Project Workspace MVP requirements
hifizz Aug 30, 2026
f63bce6
spec(project): 添加 Project Workspace MVP tasks
hifizz Aug 30, 2026
5e6599e
feat(project): add workspace data contracts
hifizz Aug 30, 2026
1aa1f9f
feat(project): add workspace server APIs
hifizz Aug 30, 2026
07e7891
feat(project): inject contract and project files
hifizz Aug 30, 2026
c170f6a
ci(project): add temporary workspace validation
hifizz Aug 30, 2026
b1e0ce5
feat(project): add workspace client state
hifizz Aug 30, 2026
d7b0381
ci(project): patch legacy workspace fixtures
hifizz Aug 30, 2026
fae299e
test(project): update legacy workspace fixtures [skip ci]
github-actions[bot] Aug 30, 2026
6d727c1
ci(project): rerun workspace validation
hifizz Aug 30, 2026
f3471d7
feat(project): add project file upload client
hifizz Aug 31, 2026
15db869
feat(project): unify project workspace panel
hifizz Aug 31, 2026
afd3837
style(project): add project panel workspace styles
hifizz Aug 31, 2026
4965cfa
feat(project): expose project workspace from topbar
hifizz Aug 31, 2026
0a6ad27
fix(project): keep project panel compatible with workspace shell
hifizz Aug 31, 2026
2b2c48b
fix(project): preserve typed ui messages in attachment context
hifizz Aug 31, 2026
35529bb
ci(project): keep legacy harness compatible with workspace client
hifizz Aug 31, 2026
a1a0e4e
test(project): update legacy workspace fixtures [skip ci]
github-actions[bot] Aug 31, 2026
5225574
docs(openspec): record project workspace ui implementation
hifizz Aug 31, 2026
29eecdf
test(project): complete legacy workspace client mock
hifizz Aug 31, 2026
ac412a4
test(project): complete workspace client fixture [skip ci]
github-actions[bot] Aug 31, 2026
4b6ee46
ci(project): remove one-shot compatibility patch
hifizz Aug 31, 2026
5467b8d
docs(openspec): mark completed project workspace tasks
hifizz Aug 31, 2026
8c19d42
test(project): cover contract generation boundaries
hifizz Aug 31, 2026
33db755
refactor(project): extract attachment content resolver
hifizz Aug 31, 2026
641c2ea
refactor(project): use shared attachment content resolver
hifizz Aug 31, 2026
6d2041d
docs(openspec): complete contract boundary and resolver tasks
hifizz Aug 31, 2026
da14e99
refactor(project): bind project panel to normalized store
hifizz Aug 31, 2026
048907d
feat(project): bind project panel resources to conversation store
hifizz Aug 31, 2026
5488635
ci(project): apply store-bound panel integration
hifizz Aug 31, 2026
13c2803
ci(project): wire store-bound project panel
hifizz Aug 31, 2026
c776880
ci(project): trigger store-bound panel patch
hifizz Aug 31, 2026
7fff1ff
refactor(project): share project panel conversation store
hifizz Aug 31, 2026
1d5f1ff
ci(project): restore read-only workspace validation
hifizz Aug 31, 2026
ed07333
ci(project): remove one-shot panel patch workflow
hifizz Aug 31, 2026
73dfcf0
feat(project): expose stable message anchors for provenance
hifizz Aug 31, 2026
b25d9f7
feat(project): locate and highlight artifact source message
hifizz Aug 31, 2026
eb72c3c
test(project): preserve workspace state across panel refresh
hifizz Aug 31, 2026
84367f2
ci(project): verify project panel workspace isolation
hifizz Aug 31, 2026
6abeeff
docs(openspec): complete project panel workspace tasks
hifizz Aug 31, 2026
4d878a5
test(project): cover workspace schema commands and repositories
hifizz Aug 31, 2026
eed024d
refactor(project): extract deterministic attachment context policy
hifizz Aug 31, 2026
9423d3b
refactor(project): apply pure attachment context policy
hifizz Aug 31, 2026
58fba19
test(project): make pdf retrieval policy injectable
hifizz Aug 31, 2026
07fdd67
test(project): cover deterministic project context policies
hifizz Aug 31, 2026
fddb626
ci(project): run project workspace database acceptance
hifizz Aug 31, 2026
1bdae60
test(project): cover workspace API isolation and bootstrap
hifizz Aug 31, 2026
5276376
ci(project): run workspace API integration
hifizz Aug 31, 2026
1ac26d5
test(project): cover project panel UI contract
hifizz Aug 31, 2026
53bae75
feat(evals): model project workspace context in agent cases
hifizz Aug 31, 2026
77e3bf9
feat(evals): seed project contract and project files
hifizz Aug 31, 2026
fcf62ed
test(evals): add project workspace coverage cases
hifizz Aug 31, 2026
ab35aeb
test(evals): verify project workspace production seed
hifizz Aug 31, 2026
d2efd6a
test(project): fix contract boundary generation setup
hifizz Aug 31, 2026
053d0f3
test(project): verify workspace history stability
hifizz Aug 31, 2026
b5730b0
test(project): prevent implicit artifact cross-thread context
hifizz Aug 31, 2026
e92a827
ci(project): run complete project workspace acceptance suite
hifizz Aug 31, 2026
19f8853
spec(project): clarify bootstrap isolation semantics
hifizz Aug 31, 2026
3c78503
spec(project): preserve empty bootstrap shell semantics
hifizz Aug 31, 2026
1dc0257
test(project): align bootstrap shell isolation semantics
hifizz Aug 31, 2026
fbb14c7
ci(project): run correct agent eval command
hifizz Aug 31, 2026
57bb1e8
eval(project): register workspace cases in manifests
hifizz Aug 31, 2026
2bc3997
spec(project): mark project workspace test suite complete
hifizz Aug 31, 2026
f97a3ea
test(project): verify workspace migration on legacy data
hifizz Aug 31, 2026
55a18c9
ci(project): verify migration compatibility and schema sync
hifizz Aug 31, 2026
2f0f58c
ci(project): capture generated workspace migration snapshot
hifizz Aug 31, 2026
391d83b
ci(project): add one-time drizzle snapshot repair
hifizz Aug 31, 2026
19adc44
fix(db): add project workspace drizzle snapshot
github-actions[bot] Aug 31, 2026
e88aeb2
ci(project): remove one-time snapshot repair
hifizz Aug 31, 2026
8002d59
ci(project): restore migration sync validation
hifizz Aug 31, 2026
0bfda9b
spec(project): mark migration validation complete
hifizz Aug 31, 2026
b5ee42d
ci(project): add release validation gates
hifizz Aug 31, 2026
95dca07
refactor(project): remove obsolete duplicate artifact drawer
hifizz Aug 31, 2026
167017d
refactor(project): remove effect-driven panel state sync
hifizz Aug 31, 2026
0a4a7df
ci(project): lint active project panel implementation
hifizz Aug 31, 2026
4d0713c
refactor(project): add thin legacy harness adapter
hifizz Aug 31, 2026
d402573
ci(project): lint legacy panel adapter too
hifizz Aug 31, 2026
ebf8003
refactor(ai): remove relay legacy environment fallback
hifizz Aug 30, 2026
a30b2c9
feat(chat): group model selector by provider
hifizz Aug 30, 2026
4a1d425
style: compact model selector popover
hifizz Aug 31, 2026
32fe44a
chore(db): remove PR migration artifacts
hifizz Sep 1, 2026
95b3dc6
feat(thread-chat): protect selection bubble draft from lossy dismissal
hifizz Sep 1, 2026
3750019
fix(thread-chat): restore selection bubble focus and entrance
hifizz Sep 1, 2026
2fc186a
style: 优化样式
hifizz Sep 1, 2026
1e58754
style: update markdown style
hifizz Sep 1, 2026
db9a507
style: 优化样式
hifizz Sep 2, 2026
7c359b4
docs(composer): add issue 68 research handoff
hifizz Sep 1, 2026
e0ca368
docs(composer): define attachment demo MVP
hifizz Sep 1, 2026
df60826
spec(composer): scaffold attachment composer demo change
hifizz Sep 1, 2026
65a8380
spec(composer): add attachment demo proposal
hifizz Sep 1, 2026
8ac21df
spec(composer): define attachment demo requirements
hifizz Sep 1, 2026
f3e7e50
spec(composer): add attachment demo design
hifizz Sep 1, 2026
fd9a2e3
spec(composer): add attachment demo tasks
hifizz Sep 1, 2026
dd50fa6
feat(composer): apply attachment demo spec
hifizz Sep 1, 2026
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
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ UMAPIS_BASE_URL=https://www.umapis.com/v1
UMAPIS_API_KEY_CLAUDE=
UMAPIS_API_KEY_GPT=

# === 私有模型中继(独立固定路由;服务端专用) ===
# 可填写服务根地址或 /v1 API 根地址;应用会统一规范为 /v1。
PRIVATE_RELAY_BASE_URL=https://model-relay.internal/v1
PRIVATE_RELAY_API_KEY=

# === 火山方舟 Coding Plan(OpenAI-compatible) ===
# 必须使用 Coding Plan 专用的 /api/coding/v3;普通 /api/v3 会产生套餐外费用。
ARK_CODING_API_KEY=
Expand Down
135 changes: 135 additions & 0 deletions .github/workflows/project-workspace-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
name: Project Workspace CI

on:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

L3-7: delete: 这份 135 行 CI 只监听当前 feature branch,合并后立即失效,并重复 Agent Evals / OpenSpec。把一个 Project Workspace 测试脚本接入现有 pull_request workflow;删除本文件。

push:
branches:
- codex/research-project-workspace-design
workflow_dispatch:

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
services:
postgres:
image: pgvector/pgvector:pg17
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
DIRECT_URL: postgres://postgres:postgres@localhost:5432/postgres
BETTER_AUTH_SECRET: project-workspace-ci-secret-at-least-32-characters
MINIMAX_API_KEY: project-workspace-build-placeholder
MINIMAX_BASE_URL: https://example.invalid/v1
LLM_MODEL_ID: project-workspace-build-model
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Typecheck
run: pnpm typecheck

- name: Targeted ESLint
run: >-
pnpm exec eslint
app/thread-chat/chat/chat-view.tsx
app/thread-chat/core/projections.ts
app/thread-chat/core/store.ts
app/thread-chat/core/types.ts
app/thread-chat/gate-3-harness/mock-v1-runtime.ts
app/thread-chat/net/client.ts
app/thread-chat/net/commands/conversation-commands.ts
app/thread-chat/net/project-file-upload.ts
app/thread-chat/orchestration/artifacts/artifact-drawer.tsx
app/thread-chat/orchestration/artifacts/project-panel.tsx
app/thread-chat/orchestration/artifacts/store-bound-project-panel.tsx
app/thread-chat/orchestration/navigation/thread-chat-topbar.tsx
app/thread-chat/thread-chat-demo.tsx
constants/project-workspace.ts
evals/agent/executors/production-harness.ts
evals/agent/schema.ts
lib/chat/attachment-content-resolver.ts
lib/chat/attachment-context-policy.ts
lib/chat/project-contract.ts
lib/chat/resolve-attachments.ts
lib/db/schema.ts
lib/thread-chat/application/compile-model-context.ts
lib/thread-chat/application/project-mutations.ts
lib/thread-chat/application/queries.ts
lib/thread-chat/contracts/commands.ts
lib/thread-chat/contracts/dto.ts
lib/thread-chat/persistence/artifact-repository.ts
lib/thread-chat/persistence/mappers.ts
lib/thread-chat/persistence/project-file-repository.ts
lib/thread-chat/server/handlers.ts
lib/thread-chat/streaming/finalize.ts
lib/thread-chat/streaming/generation-plan.ts
lib/thread-chat/streaming/run-generation.ts

- name: Verify generated migration is in sync
run: pnpm db:generate && git diff --exit-code -- drizzle

- name: Legacy data migration compatibility
run: node --import tsx e2e/thread-chat/project-workspace-migration-compatibility.test.mjs

- name: Pure project context policies
run: node --import tsx e2e/thread-chat/project-workspace-context.test.mjs

- name: Project panel UI contract
run: node e2e/thread-chat/project-panel-ui-contract.test.mjs

- name: Project panel workspace isolation
run: node --import tsx e2e/thread-chat/project-panel-workspace-state.test.mjs

- name: Project workspace eval harness
run: node --import tsx e2e/observability/project-workspace-eval-harness.test.mjs

- name: Prepare normalized test database
run: pnpm db:test:reset && pnpm db:test:migrate

- name: Project workspace schema and repository acceptance
run: node --import tsx e2e/thread-chat/project-workspace-db.test.mjs

- name: Project workspace API integration
run: node --import tsx e2e/thread-chat/project-workspace-api-db.test.mjs

- name: Project contract generation boundary
run: node --import tsx e2e/thread-chat/project-contract-generation-boundary.test.mjs

- name: Project workspace history stability
run: node --import tsx e2e/thread-chat/project-workspace-history-stability.test.mjs

- name: Project artifact context isolation
run: node --import tsx e2e/thread-chat/project-artifact-context-isolation.test.mjs

- name: Agent eval smoke
run: pnpm eval:agent

- name: Agent eval CI
run: pnpm eval:agent:ci

- name: Production build
run: pnpm build

- name: Validate OpenSpec
run: pnpm openspec:validate
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { RouteContext } from "@/lib/thread-chat/server/route-utils"
import { handleRemoveProjectFile } from "@/lib/thread-chat/server/handlers"

export const dynamic = "force-dynamic"

type Context = RouteContext<{ projectId: string; attachmentId: string }>

export async function DELETE(request: Request, context: Context) {
const { projectId, attachmentId } = await context.params
return handleRemoveProjectFile(request, projectId, attachmentId)
}
11 changes: 11 additions & 0 deletions app/api/thread-chat/v1/projects/[projectId]/files/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { RouteContext } from "@/lib/thread-chat/server/route-utils"
import { handleAddProjectFile } from "@/lib/thread-chat/server/handlers"

export const dynamic = "force-dynamic"

type Context = RouteContext<{ projectId: string }>

export async function POST(request: Request, context: Context) {
const { projectId } = await context.params
return handleAddProjectFile(request, projectId)
}
46 changes: 46 additions & 0 deletions app/thread-chat/attachment-composer-demo/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use client"

import { useCallback, useState } from "react"

import { AttachmentComposerDemo } from "../chat/composer/attachment-composer-demo"
import type { DemoAttachment } from "../chat/composer/attachment-composer-demo-model"

export default function AttachmentComposerDemoPage() {
const [attachments, setAttachments] = useState<DemoAttachment[]>([])

const handleChange = useCallback((nextAttachments: DemoAttachment[]) => {
setAttachments(nextAttachments)
console.log("attachments changed", nextAttachments)
}, [])

return (
<main className="tc min-h-screen bg-background px-4 py-12 text-foreground sm:px-6">
<section className="mx-auto flex w-full max-w-2xl flex-col gap-6">
<header className="space-y-2">
<p className="text-sm font-medium text-muted-foreground">
ThreadChat · Frontend Demo
</p>
<h1 className="text-2xl font-semibold tracking-tight">
Attachment Composer
</h1>
<p className="max-w-xl text-sm leading-6 text-muted-foreground">
通过多选、拖拽或粘贴添加文件。粘贴的纯文本会转换为本地 .txt
文件;所有操作仅保留在当前浏览器页面,不会上传或发送消息。
</p>
</header>

<AttachmentComposerDemo
attachments={attachments}
onChange={handleChange}
/>

<p
data-testid="attachment-count"
className="text-xs text-muted-foreground"
>
当前附件:{attachments.length}
</p>
</section>
</main>
)
}
Loading
Loading