✨ feat(vscode): 工单移交的会话包改走阿里云 OSS、换 xz 压缩,两边进度一步步显示
- 会话包传到 OSS 的 spx-handoff/<owner>/<repo>/issue-<N>-<时间>.tar.xz,上传时对象设成私有;不再挂 Gitea 工单附件 - 新命令「配置移交存储」:endpoint、bucket 存扩展设置,AccessKey 存密钥存储;没配时移交 / 接管直接提示,什么都不改 - 共享 state 字段 handoffAttachmentId 改名 handoffBundleKey(含 spx CLI 与 schema) - 打包换成 xz 1 级(tar -cJf),去掉 100MB 上限检查和先试压一遍的重复压缩 - 发送方提示打包 / 上传了多少 MB;接管方同一条提示依次显示下载、解包、建 worktree、装会话,完成前不消失 - 会话交接(单会话)仍走 Gitea 附件,Gitea 附件白名单没有 .xz,单独保留 gzip 打包
This commit is contained in:
1 parent
a33d3d2251
commit
499cfad7d7
39 files changed
+1039
-526
No files matched your search
@@ -539,7 +539,7 @@ export function App() {
|
||||
<HandoffModal
|
||||
open={handoffIssue !== null}
|
||||
title={handoffIssue !== null ? `移交 #${handoffIssue}` : '移交'}
|
||||
description="会把本机的 worktree 删除、会话记录打包挂到工单附件,并把工单指派给对方。移交前分支必须已全部 push。"
|
||||
description="会把本机的 worktree 删除、会话记录打包传到移交存储(阿里云 OSS),并把工单指派给对方。移交前分支必须已全部 push。"
|
||||
users={handoffUsers && handoffUsers.issueNumber === handoffIssue ? handoffUsers.users : null}
|
||||
onCancel={() => setHandoffIssue(null)}
|
||||
onSubmit={(to) => {
|
||||
|
||||
@@ -129,7 +129,7 @@ export const IssueCard = forwardRef<HTMLDivElement, IssueCardProps>(
|
||||
: null}
|
||||
{readOnly && ownerLogin ? <OwnerBadge login={ownerLogin} avatar={ownerAvatar} /> : null}
|
||||
</div>
|
||||
{issue.handoffAttachmentId
|
||||
{issue.handoffBundleKey
|
||||
? (
|
||||
<span
|
||||
className="absolute bottom-1 right-1.5 rounded border border-blue-400/50 bg-blue-400/10 px-1 text-[9px] text-blue-400"
|
||||
|
||||
@@ -918,7 +918,7 @@ export function IssueDetailPanel({
|
||||
avoid acting on a gitea issue of the same number. */}
|
||||
{issue.source !== 'youtrack' && !readOnly && (
|
||||
<>
|
||||
{issue.handoffAttachmentId && me !== undefined && (issue.assignees ?? []).includes(me) && (
|
||||
{issue.handoffBundleKey && me !== undefined && (issue.assignees ?? []).includes(me) && (
|
||||
<button
|
||||
type="button"
|
||||
data-tooltip={`接管 ${issue.handoffFrom ?? '?'} 的移交`}
|
||||
@@ -930,7 +930,7 @@ export function IssueDetailPanel({
|
||||
{isHandoffRunning(issue.number) ? <Loader2 className="size-3.5 animate-spin" /> : <Download className="size-3.5" />}
|
||||
</button>
|
||||
)}
|
||||
{!issue.handoffAttachmentId && issue.column !== 'done' && ((issue.assignees ?? []).length === 0 || (me !== undefined && (issue.assignees ?? []).includes(me))) && (
|
||||
{!issue.handoffBundleKey && issue.column !== 'done' && ((issue.assignees ?? []).length === 0 || (me !== undefined && (issue.assignees ?? []).includes(me))) && (
|
||||
<button
|
||||
type="button"
|
||||
data-tooltip="移交给同事"
|
||||
@@ -942,7 +942,7 @@ export function IssueDetailPanel({
|
||||
{isHandoffRunning(issue.number) ? <Loader2 className="size-3.5 animate-spin" /> : <ArrowRightLeft className="size-3.5" />}
|
||||
</button>
|
||||
)}
|
||||
{issue.handoffAttachmentId && !(me !== undefined && (issue.assignees ?? []).includes(me)) && (
|
||||
{issue.handoffBundleKey && !(me !== undefined && (issue.assignees ?? []).includes(me)) && (
|
||||
<span
|
||||
className="inline-flex shrink-0 items-center justify-center rounded border border-[var(--vscode-panel-border)] p-1 text-xs opacity-70"
|
||||
data-tooltip={`${issue.handoffFrom ?? '?'} 已移交,等 ${(issue.assignees ?? []).join(', ') || '?'} 接管`}
|
||||
|
||||
@@ -320,9 +320,9 @@ export interface UseIssuesResult {
|
||||
handoffUsers: { issueNumber: number, users: string[] } | null
|
||||
/** 拉取某工单可移交的候选用户列表,结果通过 `handoffUsers` 返回。 */
|
||||
requestHandoffUsers: (issueNumber: number) => void
|
||||
/** 发起移交:删本机 worktree、打包会话记录挂到附件、把工单指派给对方。 */
|
||||
/** 发起移交:删本机 worktree、打包会话记录传到 OSS、把工单指派给对方。 */
|
||||
startHandoff: (issueNumber: number, to: string) => void
|
||||
/** 接管一个待接管工单:拉取移交附件、恢复会话与 worktree。 */
|
||||
/** 接管一个待接管工单:从 OSS 下载会话包、恢复会话与 worktree。 */
|
||||
acceptHandoff: (issueNumber: number) => void
|
||||
/** 审查列里向同事申请把工单移交给自己。 */
|
||||
askHandoff: (issueNumber: number) => void
|
||||
|
||||
@@ -93,7 +93,7 @@ export type ExtensionToWebview
|
||||
| { type: 'issues/loaded' }
|
||||
| { type: 'issues/update', issues: Issue[], scope: 'mine' | 'all', globalAutoReview: boolean, youtrackConfigured: boolean, me?: string, avatars?: Record<string, string> }
|
||||
| { type: 'issues/error', message: string }
|
||||
| { type: 'issue/patch', issueNumber: number, patch: { autoReview?: boolean, reviewPassed?: boolean, specFile?: string, planFile?: string, prototypeFile?: string, prDiffFile?: string | null, sessionId?: string | null, implementSessionId?: string | null, reviewSessionId?: string | null, missingSessionIds?: string[], testSessionId?: string | null, prototypeSessionId?: string | null, pr?: string | null, implementStatus?: 'running' | 'done' | 'failed' | null, column?: IssueColumn, worktreePath?: string | null, prMerged?: boolean, prMergedAt?: string | null, branch?: string | null, color?: string, worktreeExists?: boolean, brainstormTabOpen?: boolean, implementTabOpen?: boolean, reviewTabOpen?: boolean, testTabOpen?: boolean, prototypeTabOpen?: boolean, profilePath?: string | null, brainstormProfilePath?: string | null, testProfilePath?: string | null, prototypeProfilePath?: string | null, assignees?: string[], handoffAttachmentId?: string | null, handoffFrom?: string | null, handoffRequestFrom?: string | null, handoffRequestError?: string | null } }
|
||||
| { type: 'issue/patch', issueNumber: number, patch: { autoReview?: boolean, reviewPassed?: boolean, specFile?: string, planFile?: string, prototypeFile?: string, prDiffFile?: string | null, sessionId?: string | null, implementSessionId?: string | null, reviewSessionId?: string | null, missingSessionIds?: string[], testSessionId?: string | null, prototypeSessionId?: string | null, pr?: string | null, implementStatus?: 'running' | 'done' | 'failed' | null, column?: IssueColumn, worktreePath?: string | null, prMerged?: boolean, prMergedAt?: string | null, branch?: string | null, color?: string, worktreeExists?: boolean, brainstormTabOpen?: boolean, implementTabOpen?: boolean, reviewTabOpen?: boolean, testTabOpen?: boolean, prototypeTabOpen?: boolean, profilePath?: string | null, brainstormProfilePath?: string | null, testProfilePath?: string | null, prototypeProfilePath?: string | null, assignees?: string[], handoffBundleKey?: string | null, handoffFrom?: string | null, handoffRequestFrom?: string | null, handoffRequestError?: string | null } }
|
||||
/** 某个会话 id 的开 tab 请求已处理完(开成、复用或被拒都算),webview 据此停掉行内 spinner。 */
|
||||
| { type: 'session/tab-settled', sessionId: string }
|
||||
| { type: 'issue/pr-diff-summary-done', issueNumber: number }
|
||||
|
||||
@@ -101,8 +101,8 @@ export interface Issue {
|
||||
assignees?: string[]
|
||||
/** Gitea 工单创建者 login;无 assignee 的工单靠它判定归属与卡片头像。 */
|
||||
poster?: string
|
||||
/** 移交会话包的 Gitea 附件 id(字符串);存在即「待接管」。 */
|
||||
handoffAttachmentId?: string
|
||||
/** 移交会话包在 OSS 上的对象 key;存在即「待接管」。 */
|
||||
handoffBundleKey?: string
|
||||
/** 发起移交的 Gitea login。 */
|
||||
handoffFrom?: string
|
||||
/** 谁在申请把这个审查工单移交给自己。 */
|
||||
|
||||
Reference in new issue
Block a user