✨ feat(vscode): 多人协作二期:状态分层/写校验/签名/团队视图
- 本机状态(会话id/worktree/profile/prDiffFile)迁 workspaceState, 共享 state JSON 只留团队字段;读侧本地记录叠加,旧数据兜底 - mergeStateJsonComment 写后读回校验,并发覆盖时在最新状态上重放一次 - webhook 支持 Gitea secret,校验 X-Gitea-Signature(HMAC-SHA256), 不匹配 401;设置面板新增 Webhook Secret 字段 - 看板新增 我的/全部 范围切换(团队视图),按工作区持久化
This commit is contained in:
1 parent
c370214d12
commit
faf227412e
18 files changed
+665
-202
No files matched your search
@@ -6,15 +6,16 @@ import * as fs from 'node:fs'
|
||||
import { promises as fsp } from 'node:fs'
|
||||
import * as os from 'node:os'
|
||||
import * as path from 'node:path'
|
||||
import { killProcessesUsingWorktree, removeWorktreeDir, resolveWorktreePath } from '../../git/worktree'
|
||||
import { commands, env, ThemeColor, Uri, window, workspace } from 'vscode'
|
||||
import { getToken } from '../../auth/secrets'
|
||||
import { buildCcCommand } from '../../cc/ccCommand'
|
||||
import { getDefaultProfilePath, getPrDiffSummaryProfilePath } from '../../cc/profiles'
|
||||
import { getBrainstormPrompt } from '../../cc/prompts'
|
||||
import { projectsDirFor, watchForNewSession } from '../../cc/sessionWatcher'
|
||||
import { spawnClaude } from '../../cc/spawnClaude'
|
||||
import { gitFetch, resolveFeatureBranch } from '../../git/branchSync'
|
||||
import { detectRepo } from '../../git/remote'
|
||||
import { killProcessesUsingWorktree, removeWorktreeDir, resolveWorktreePath } from '../../git/worktree'
|
||||
import {
|
||||
addDependency,
|
||||
closeIssue,
|
||||
@@ -31,7 +32,6 @@ import { logger } from '../../logging/logger'
|
||||
import { getSettings } from '../../settings/store'
|
||||
import { webhookCoordinator } from '../../webhook/coordinator'
|
||||
import { pickRandomIssueColor, themeColorIdToIconUri } from '../issueColor'
|
||||
import { getDefaultProfilePath, getPrDiffSummaryProfilePath } from '../../cc/profiles'
|
||||
import { makeNonce } from '../KanbanPanel'
|
||||
import { cleanupFeatureBranch } from './branchCleanup'
|
||||
import * as sessions from './sessions'
|
||||
@@ -345,22 +345,16 @@ export async function handleColumnChange(panel: KanbanWebviewPanel, issueNumber:
|
||||
}
|
||||
}
|
||||
|
||||
// 4. PR is merged — persist column='done' + prMerged=true + 清空 worktreePath
|
||||
// 到 state JSON。state JSON 用空字符串清空(loader 把 length===0 视为 unset)。
|
||||
// 4. PR is merged — persist column='done' + prMerged=true + 清空 worktreePath。
|
||||
// 走 mergeIssueState 漏斗:worktreePath 是本机字段落 workspaceState,
|
||||
// 其余共享字段进 state JSON(空字符串清空,loader 把 length===0 视为 unset)。
|
||||
try {
|
||||
await mergeStateJsonComment({
|
||||
host: remote.host,
|
||||
owner: remote.owner,
|
||||
repo: remote.repo,
|
||||
token,
|
||||
issueNumber,
|
||||
extra: {
|
||||
column: 'done',
|
||||
worktreePath: '',
|
||||
branch: '',
|
||||
prMerged: true,
|
||||
prMergedAt: pullRequest.merged_at ?? new Date().toISOString(),
|
||||
},
|
||||
await panel.mergeIssueState(issueNumber, {
|
||||
column: 'done',
|
||||
worktreePath: '',
|
||||
branch: '',
|
||||
prMerged: true,
|
||||
prMergedAt: pullRequest.merged_at ?? new Date().toISOString(),
|
||||
})
|
||||
logger.add({
|
||||
level: 'info',
|
||||
@@ -2035,14 +2029,8 @@ export async function handleGeneratePrDiffSummary(panel: KanbanWebviewPanel, iss
|
||||
fs.mkdirSync(path.dirname(outputAbsPath), { recursive: true })
|
||||
fs.writeFileSync(outputAbsPath, summary, 'utf8')
|
||||
|
||||
await mergeStateJsonComment({
|
||||
host: remote.host,
|
||||
owner: remote.owner,
|
||||
repo: remote.repo,
|
||||
token,
|
||||
issueNumber,
|
||||
extra: { prDiffFile: outputRelPath },
|
||||
})
|
||||
// prDiffFile 是本机生成的文件路径,经漏斗落 workspaceState,不进共享评论。
|
||||
await panel.mergeIssueState(issueNumber, { prDiffFile: outputRelPath })
|
||||
panel.postMessage({
|
||||
type: 'issue/patch',
|
||||
issueNumber,
|
||||
|
||||
@@ -20,6 +20,7 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
|
||||
host: string
|
||||
token: string
|
||||
webhookPort: number
|
||||
webhookSecret: string
|
||||
brainstormPrompt: string
|
||||
brainstormContinuePrompt: string
|
||||
implementPlanPrompt: string
|
||||
@@ -90,6 +91,7 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
|
||||
errorMessage: 'Host 和 Token 都不能为空',
|
||||
tokenSaved: !!oldToken,
|
||||
webhookPort: payload.webhookPort,
|
||||
webhookSecret: payload.webhookSecret,
|
||||
brainstormPrompt: payload.brainstormPrompt || prev.brainstormPrompt,
|
||||
brainstormContinuePrompt: payload.brainstormContinuePrompt || prev.brainstormContinuePrompt,
|
||||
implementPlanPrompt: payload.implementPlanPrompt || prev.implementPlanPrompt,
|
||||
@@ -114,6 +116,7 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
|
||||
}
|
||||
await saveSettings(panel.context, {
|
||||
webhookPort: payload.webhookPort,
|
||||
webhookSecret: payload.webhookSecret.trim(),
|
||||
brainstormPrompt: payload.brainstormPrompt,
|
||||
brainstormContinuePrompt: payload.brainstormContinuePrompt,
|
||||
implementPlanPrompt: payload.implementPlanPrompt,
|
||||
@@ -164,6 +167,7 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
|
||||
message: `端口配置变更,重启监听 :${newPort}`,
|
||||
})
|
||||
}
|
||||
webhookCoordinator.ensureSecret(getSettings(panel.context).webhookSecret)
|
||||
try {
|
||||
await webhookCoordinator.ensurePort(newPort)
|
||||
}
|
||||
@@ -216,6 +220,7 @@ export async function handleEditSettingsRequest(panel: KanbanWebviewPanel): Prom
|
||||
canCancel: true,
|
||||
tokenSaved,
|
||||
webhookPort: s.webhookPort,
|
||||
webhookSecret: s.webhookSecret,
|
||||
brainstormPrompt: s.brainstormPrompt,
|
||||
brainstormContinuePrompt: s.brainstormContinuePrompt,
|
||||
implementPlanPrompt: s.implementPlanPrompt,
|
||||
@@ -310,12 +315,52 @@ export async function handleProfilesList(panel: KanbanWebviewPanel): Promise<voi
|
||||
* are treated as text too — is handed to the OS default application.
|
||||
*/
|
||||
const TEXT_OPEN_EXTENSIONS = new Set([
|
||||
'.md', '.markdown', '.txt', '.text', '.csv', '.tsv', '.json', '.jsonc',
|
||||
'.yaml', '.yml', '.toml', '.ini', '.conf', '.cfg', '.log', '.xml', '.html',
|
||||
'.htm', '.css', '.scss', '.js', '.mjs', '.cjs', '.ts', '.tsx', '.jsx',
|
||||
'.vue', '.py', '.go', '.rs', '.java', '.kt', '.c', '.h', '.cpp', '.hpp',
|
||||
'.cc', '.sh', '.bash', '.zsh', '.sql', '.env', '.properties', '.gradle',
|
||||
'.dockerfile', '.gitignore',
|
||||
'.md',
|
||||
'.markdown',
|
||||
'.txt',
|
||||
'.text',
|
||||
'.csv',
|
||||
'.tsv',
|
||||
'.json',
|
||||
'.jsonc',
|
||||
'.yaml',
|
||||
'.yml',
|
||||
'.toml',
|
||||
'.ini',
|
||||
'.conf',
|
||||
'.cfg',
|
||||
'.log',
|
||||
'.xml',
|
||||
'.html',
|
||||
'.htm',
|
||||
'.css',
|
||||
'.scss',
|
||||
'.js',
|
||||
'.mjs',
|
||||
'.cjs',
|
||||
'.ts',
|
||||
'.tsx',
|
||||
'.jsx',
|
||||
'.vue',
|
||||
'.py',
|
||||
'.go',
|
||||
'.rs',
|
||||
'.java',
|
||||
'.kt',
|
||||
'.c',
|
||||
'.h',
|
||||
'.cpp',
|
||||
'.hpp',
|
||||
'.cc',
|
||||
'.sh',
|
||||
'.bash',
|
||||
'.zsh',
|
||||
'.sql',
|
||||
'.env',
|
||||
'.properties',
|
||||
'.gradle',
|
||||
'.dockerfile',
|
||||
'.gitignore',
|
||||
])
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user