mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 17:17:38 +00:00
* feat(sidebar): the desktop window lists main's sidebar inputs, with its own writes shown until main does (dark) Co-Authored-By: Claude <noreply@anthropic.com> * fix(sidebar): a newer write wins in the pending layer, created rows hold the stamped record, writes name their host (dark) Co-Authored-By: Claude <noreply@anthropic.com> * chore(sidebar): move the focus-read allowance with the window list model it moved into (dark) * perf(sidebar): main's sidebar feed publishes a change after a quiet spell at once, not 50 ms later (dark) * test(e2e): the desktop reads-main spec skips on a switch-off build and waits for a frame after collapse --------- Co-authored-by: Claude <noreply@anthropic.com>
123 lines
5.0 KiB
TypeScript
123 lines
5.0 KiB
TypeScript
import type { FolderWorkspace } from './folder-workspace-types'
|
|
import type { Worktree } from './worktree/types'
|
|
import { folderWorkspaceKey } from './workspace-scope'
|
|
import {
|
|
getConnectionExecutionHostId,
|
|
parseExecutionHostId,
|
|
type ExecutionHostId
|
|
} from './execution-host'
|
|
import { composeWorktreeHostIdentity } from './worktree/host-qualified-identity'
|
|
import { normalizeWorkspaceCreatorProvenance } from './workspace-creator-provenance'
|
|
import { getWorkspaceAttachments } from './workspace-attachments'
|
|
import { normalizeWorkspaceAttachment } from './workspace-attachment-normalization'
|
|
|
|
/**
|
|
* A folder workspace has no git repo, so its synthetic `Worktree` borrows the `repoId` slot to
|
|
* name the PROJECT GROUP it belongs to. The value is never null, so a caller testing `repoId` for
|
|
* absence to detect "no repo" will be wrong for every folder workspace.
|
|
*
|
|
* Minting and recognising it live together here so the two cannot drift.
|
|
*/
|
|
const FOLDER_WORKSPACE_REPO_ID_PREFIX = 'folder-workspace:'
|
|
|
|
export function folderWorkspaceRepoId(projectGroupId: string): string {
|
|
return `${FOLDER_WORKSPACE_REPO_ID_PREFIX}${projectGroupId}`
|
|
}
|
|
|
|
/** The project group a synthetic repoId stands for, or null when it names a real git repo. */
|
|
export function projectGroupIdFromRepoId(repoId: string | null | undefined): string | null {
|
|
if (typeof repoId !== 'string' || !repoId.startsWith(FOLDER_WORKSPACE_REPO_ID_PREFIX)) {
|
|
return null
|
|
}
|
|
const projectGroupId = repoId.slice(FOLDER_WORKSPACE_REPO_ID_PREFIX.length)
|
|
return projectGroupId === '' ? null : projectGroupId
|
|
}
|
|
|
|
export function getFolderWorkspaceWorktreeHostId(
|
|
workspace: Pick<FolderWorkspace, 'executionHostId' | 'connectionId'>
|
|
): ExecutionHostId {
|
|
return workspace.executionHostId ?? getConnectionExecutionHostId(workspace.connectionId)
|
|
}
|
|
|
|
export function getFolderWorkspaceHostIdentity(
|
|
workspace: Pick<FolderWorkspace, 'id' | 'executionHostId' | 'connectionId'>
|
|
): string {
|
|
return composeWorktreeHostIdentity(
|
|
getFolderWorkspaceWorktreeHostId(workspace),
|
|
folderWorkspaceKey(workspace.id)
|
|
)
|
|
}
|
|
|
|
export function folderWorkspaceToWorktree(folderWorkspace: FolderWorkspace): Worktree {
|
|
const linkedTask = folderWorkspace.linkedTask
|
|
const selectedTask = linkedTask
|
|
? normalizeWorkspaceAttachment(linkedTask)
|
|
: getWorkspaceAttachments({
|
|
linkedItems: folderWorkspace.linkedItems
|
|
}).find((item) => item.type === 'issue')
|
|
const creatorProvenance = normalizeWorkspaceCreatorProvenance(folderWorkspace.creatorProvenance)
|
|
const hostId = getFolderWorkspaceWorktreeHostId(folderWorkspace)
|
|
const parsedHost = parseExecutionHostId(hostId)
|
|
return {
|
|
id: folderWorkspaceKey(folderWorkspace.id),
|
|
repoId: folderWorkspaceRepoId(folderWorkspace.projectGroupId),
|
|
...(creatorProvenance ? { creatorProvenance } : {}),
|
|
displayName: folderWorkspace.name,
|
|
comment: folderWorkspace.comment,
|
|
linkedIssue:
|
|
selectedTask?.provider === 'github' && selectedTask.type === 'issue'
|
|
? selectedTask.number
|
|
: null,
|
|
linkedPR: null,
|
|
linkedLinearIssue:
|
|
selectedTask?.provider === 'linear'
|
|
? (selectedTask.identifier ?? selectedTask.linearIdentifier ?? null)
|
|
: null,
|
|
linkedLinearIssueWorkspaceId:
|
|
selectedTask?.provider === 'linear' ? (selectedTask.linearWorkspaceId ?? null) : null,
|
|
linkedLinearIssueOrganizationUrlKey:
|
|
selectedTask?.provider === 'linear' ? (selectedTask.linearOrganizationUrlKey ?? null) : null,
|
|
linkedGitLabMR: null,
|
|
linkedGitLabIssue:
|
|
selectedTask?.provider === 'gitlab' && selectedTask.type === 'issue'
|
|
? selectedTask.number
|
|
: null,
|
|
linkedBitbucketPR: null,
|
|
linkedAzureDevOpsPR: null,
|
|
linkedGiteaPR: null,
|
|
linkedWorkItem: linkedTask,
|
|
...(folderWorkspace.linkedItems !== undefined
|
|
? { linkedItems: folderWorkspace.linkedItems }
|
|
: {}),
|
|
linkedTaskSourceContext: folderWorkspace.linkedTaskSourceContext ?? null,
|
|
isArchived: folderWorkspace.isArchived,
|
|
isUnread: folderWorkspace.isUnread,
|
|
isPinned: folderWorkspace.isPinned,
|
|
sortOrder: folderWorkspace.sortOrder,
|
|
manualOrder: folderWorkspace.manualOrder,
|
|
lastActivityAt: folderWorkspace.lastActivityAt,
|
|
...(folderWorkspace.smartTier !== undefined
|
|
? { smartTier: folderWorkspace.smartTier, smartAt: folderWorkspace.smartAt }
|
|
: {}),
|
|
...(folderWorkspace.lastTerminalUseAt !== undefined
|
|
? { lastTerminalUseAt: folderWorkspace.lastTerminalUseAt }
|
|
: {}),
|
|
createdAt: folderWorkspace.createdAt,
|
|
createdWithAgent: folderWorkspace.createdWithAgent,
|
|
pendingFirstAgentMessageRename: folderWorkspace.pendingFirstAgentMessageRename,
|
|
firstAgentMessageRenameError: folderWorkspace.firstAgentMessageRenameError,
|
|
workspaceStatus: folderWorkspace.workspaceStatus,
|
|
diffComments: folderWorkspace.diffComments,
|
|
path: folderWorkspace.folderPath,
|
|
head: '',
|
|
branch: '',
|
|
isBare: false,
|
|
isSparse: false,
|
|
isMainWorktree: false,
|
|
hostId,
|
|
...(parsedHost?.kind === 'runtime'
|
|
? { runtimeOwnerEnvironmentId: parsedHost.environmentId }
|
|
: {})
|
|
}
|
|
}
|