mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
This bundles the pending desktop/server team-session fixes with the local adapter recovery changes already in the worktree. The team path now keeps teammate membership stable under concurrent spawns, surfaces real teammate identities in the desktop UI, and allows direct interaction with member transcripts. The adapter changes recover automatically when stale thinking signatures invalidate an existing session. Constraint: Team config writes can happen concurrently while multiple reviewers spawn in parallel Constraint: Desktop member views must follow mailbox/transcript semantics rather than hijacking teammate runtime sessions Rejected: Keep relying on config.json alone for member discovery | in-process teammates can be lost after concurrent writes Rejected: Open teammate sessionIds as normal desktop sessions | would attach a second CLI instead of the running teammate Confidence: medium Scope-risk: moderate Reversibility: clean Directive: Preserve locked team-file mutation for any future teammate registration path and keep teammate labels sourced from member names before agent types Tested: bun test src/server/__tests__/teams.test.ts src/server/__tests__/team-watcher.test.ts Tested: cd desktop && bun run test --run src/stores/chatStore.test.ts src/pages/ActiveSession.test.tsx Tested: cd desktop && bun run lint Tested: cd desktop && bun run build Not-tested: Manual end-to-end validation against a live Agent Teams run in the desktop app
45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { api } from './client'
|
|
import type { TeamSummary, TeamDetail } from '../types/team'
|
|
|
|
type TeamsResponse = { teams: TeamSummary[] }
|
|
|
|
type TranscriptMessage = {
|
|
id: string
|
|
type: string
|
|
content: unknown
|
|
timestamp: string
|
|
model?: string
|
|
parentToolUseId?: string
|
|
}
|
|
|
|
type TranscriptResponse = { messages: TranscriptMessage[] }
|
|
|
|
export type { TranscriptMessage }
|
|
|
|
export const teamsApi = {
|
|
list() {
|
|
return api.get<TeamsResponse>('/api/teams')
|
|
},
|
|
|
|
get(name: string) {
|
|
return api.get<TeamDetail>(`/api/teams/${encodeURIComponent(name)}`)
|
|
},
|
|
|
|
getMemberTranscript(teamName: string, agentId: string) {
|
|
return api.get<TranscriptResponse>(
|
|
`/api/teams/${encodeURIComponent(teamName)}/members/${encodeURIComponent(agentId)}/transcript`,
|
|
)
|
|
},
|
|
|
|
sendMemberMessage(teamName: string, agentId: string, content: string) {
|
|
return api.post<{ ok: true }>(
|
|
`/api/teams/${encodeURIComponent(teamName)}/members/${encodeURIComponent(agentId)}/messages`,
|
|
{ content },
|
|
)
|
|
},
|
|
|
|
delete(name: string) {
|
|
return api.delete<{ ok: true }>(`/api/teams/${encodeURIComponent(name)}`)
|
|
},
|
|
}
|