✨ feat(vscode): 重写注释留会话记录、能接着说,允许画原型图
每块的重写记录存进 .spx/comment-rewrites.json(和问答分开,改名、删文件跟着走),块下面同问答区:灰字历史、当前这一轮、输入框;输入框里的话接着这块最近一次重写的会话说,交回新正文照样写回,写回失败也记下原因。 重写跑在 claude --restricted 下:只放开读搜、OpenPencil 的 op、建 prototypes 目录、改草稿目录,写注释的插件单独加载;超时 15 分钟。 进行中的、出错被叫停留着的那一轮记在扩展端,切走标签页再切回来照样接上(问 AI 同一套)。
This commit is contained in:
1 parent
ae4e2160ef
commit
c9f60f5b30
32 files changed
+1654
-860
No files matched your search
@@ -2,13 +2,12 @@ import type { CSSProperties, ReactElement, ReactNode } from 'react'
|
||||
import type { RewriteTool } from './BlockTools'
|
||||
import type { DiffTree, FoldedRuns, PlacedRemoved } from './diffView'
|
||||
import type { GridSlots } from './PropertyGrid'
|
||||
import type { QaState } from './qa'
|
||||
import type { ChatState, QaState } from './qa'
|
||||
import type { PendingImage } from './qaImages'
|
||||
import type { RewriteRun } from './rewriteRun'
|
||||
import type { BlockMarks, BlockView } from './types'
|
||||
import type { BlockMarks, BlockView, ProfileChoice } from './types'
|
||||
import { ChevronDown, ChevronRight, ChevronsUpDown, EyeOff } from 'lucide-react'
|
||||
import { Fragment, useState } from 'react'
|
||||
import { AskThread, RewriteThread } from './AskThread'
|
||||
import { AskThread, REWRITE_THREAD } from './AskThread'
|
||||
import { BlockTools } from './BlockTools'
|
||||
import { CodeEditor } from './CodeEditor'
|
||||
import { DiffText } from './DiffText'
|
||||
@@ -20,7 +19,7 @@ import { TextPreview } from './TextPreview'
|
||||
import { tableId } from './viewState'
|
||||
|
||||
/**
|
||||
* 块树里改代码的那部分:哪些块在编辑、点「编辑」、按注释规范重写。页面上的块树才有;定义卡片浮窗里的块树没有,
|
||||
* 块树里改代码的那部分:哪些块在编辑、点「编辑」。页面上的块树才有;定义卡片浮窗里的块树没有,
|
||||
* 卡片只读,不画右上角的按钮
|
||||
*/
|
||||
export interface EditTree {
|
||||
@@ -30,11 +29,6 @@ export interface EditTree {
|
||||
focusId: string | null
|
||||
onFocused: () => void
|
||||
onToggleEdit: (id: string) => void
|
||||
/** 按注释规范重写的过程,按块的记号。只在这一页上 */
|
||||
rewrites: ReadonlyMap<string, RewriteRun>
|
||||
onRewriteComment: (anchor: string) => void
|
||||
/** 叫停这块正在进行的重写,不写文件 */
|
||||
onStopRewrite: (anchor: string) => void
|
||||
}
|
||||
|
||||
/** 函数、类落在几棵调用树里。定义浮窗不传,跟问 AI 一样不画这排按钮。 */
|
||||
@@ -64,6 +58,8 @@ export interface BlockTreeState {
|
||||
onSetFolds: (folds: Record<string, boolean>) => void
|
||||
/** 问 AI;文件不在工作区文件夹里(问答没地方存)时没有 */
|
||||
qa?: QaTree
|
||||
/** 按注释规范重写;同问 AI,文件不在工作区文件夹里时没有 */
|
||||
rewrite?: RewriteTree
|
||||
/** 代码差异:新增、修改的块和删掉的块;侧栏开着「未提交的更改」或审查工单、基准里有这个文件时才有 */
|
||||
diff?: DiffTree
|
||||
/** 「只看改动」开着时折起来的连着没变的块(见 foldUnchanged);onOpenRun 点开一段(按第一块的 id) */
|
||||
@@ -71,6 +67,21 @@ export interface BlockTreeState {
|
||||
onOpenRun: (id: string) => void
|
||||
}
|
||||
|
||||
/** 重写注释的状态和动作,块按自己的记号(anchor)取;profile 下拉和问 AI 共用 */
|
||||
export interface RewriteTree {
|
||||
state: ChatState
|
||||
profiles: ProfileChoice
|
||||
/** 点了块右上角的按钮:按技能命令重写这块(开新会话),展开它的重写记录 */
|
||||
onRewrite: (anchor: string) => void
|
||||
/** 在输入框里说的修改意见,接着这块最近一次重写的会话说;images 是贴的图片 */
|
||||
onAsk: (anchor: string, request: string, images: PendingImage[]) => void
|
||||
onStop: (askId: string) => void
|
||||
onDelete: (anchor: string, entryId: string) => void
|
||||
onOpen: (anchor: string) => void
|
||||
onClose: (anchor: string) => void
|
||||
onSelectProfile: (id: string) => void
|
||||
}
|
||||
|
||||
/** 问 AI 的状态和动作,块按自己的记号(anchor)取 */
|
||||
export interface QaTree {
|
||||
state: QaState
|
||||
@@ -171,7 +182,7 @@ export function BlockLevel({ blocks, owner, tree, slotted = false }: { blocks: B
|
||||
<BlockCard block={block} tree={tree} />
|
||||
</ChangeRow>
|
||||
{tree.qa && <BlockQa key={block.anchor} anchor={block.anchor} qa={tree.qa} />}
|
||||
{tree.edit && <BlockRewrite anchor={block.anchor} edit={tree.edit} />}
|
||||
{tree.rewrite && <BlockRewrite key={`rewrite ${block.anchor}`} anchor={block.anchor} rewrite={tree.rewrite} />}
|
||||
{hasShownChildren(block, tree) && !tree.collapsed.has(block.id) && (
|
||||
<BlockLevel blocks={block.children} owner={block} tree={tree} />
|
||||
)}
|
||||
@@ -203,11 +214,22 @@ function BlockQa({ anchor, qa }: { anchor: string, qa: QaTree }): ReactElement {
|
||||
)
|
||||
}
|
||||
|
||||
function BlockRewrite({ anchor, edit }: { anchor: string, edit: EditTree }): ReactElement | null {
|
||||
const run = edit.rewrites.get(anchor)
|
||||
if (!run)
|
||||
return null
|
||||
return <RewriteThread run={run} onStop={() => edit.onStopRewrite(anchor)} />
|
||||
/** 块下面的重写记录,紧跟在问答区后面;样子和问答区一样,输入框里说的是对这段注释的修改意见 */
|
||||
function BlockRewrite({ anchor, rewrite }: { anchor: string, rewrite: RewriteTree }): ReactElement | null {
|
||||
return (
|
||||
<AskThread
|
||||
wording={REWRITE_THREAD}
|
||||
history={historyOf(rewrite.state, anchor)}
|
||||
asks={asksOf(rewrite.state, anchor)}
|
||||
open={rewrite.state.open.includes(anchor)}
|
||||
profiles={rewrite.profiles}
|
||||
onSelectProfile={rewrite.onSelectProfile}
|
||||
onAsk={(request, images) => rewrite.onAsk(anchor, request, images)}
|
||||
onStop={rewrite.onStop}
|
||||
onDelete={entryId => rewrite.onDelete(anchor, entryId)}
|
||||
onClose={() => rewrite.onClose(anchor)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,13 +270,23 @@ function callTreeTool(block: BlockView, tree: BlockTreeState) {
|
||||
}
|
||||
}
|
||||
|
||||
function rewriteTool(block: BlockView, edit: EditTree | undefined): RewriteTool | undefined {
|
||||
if (!edit || !block.commentTarget)
|
||||
/**
|
||||
* 这块的「重写注释」按钮:能写注释的块才有。重写过、记录收着时点了先展开记录(好接着说);展开着、或还没重写过时点了按技能命令重写。
|
||||
* 展开着又正在写时不能再点。
|
||||
*/
|
||||
function rewriteTool(block: BlockView, tree: BlockTreeState): RewriteTool | undefined {
|
||||
const { edit, rewrite } = tree
|
||||
if (!edit || !rewrite || !block.commentTarget)
|
||||
return undefined
|
||||
const { anchor } = block
|
||||
const open = rewrite.state.open.includes(anchor)
|
||||
const asks = asksOf(rewrite.state, anchor)
|
||||
const reopen = !open && (asks.length > 0 || historyOf(rewrite.state, anchor).length > 0)
|
||||
return {
|
||||
fresh: block.commentTarget.kind === 'insert',
|
||||
rewriting: edit.rewrites.get(block.anchor)?.status === 'running',
|
||||
onRewrite: () => edit.onRewriteComment(block.anchor),
|
||||
rewriting: open && asks.some(ask => ask.status === 'running'),
|
||||
reopen,
|
||||
onRewrite: () => reopen ? rewrite.onOpen(anchor) : rewrite.onRewrite(anchor),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +371,7 @@ function BlockCard({ block, tree }: { block: BlockView, tree: BlockTreeState }):
|
||||
onToggleEdit={() => edit.onToggleEdit(block.id)}
|
||||
asking={tree.qa?.state.open.includes(block.anchor)}
|
||||
onToggleAsk={tree.qa && (() => tree.qa?.onToggle(block.anchor))}
|
||||
rewrite={rewriteTool(block, edit)}
|
||||
rewrite={rewriteTool(block, tree)}
|
||||
callTree={callTreeTool(block, tree)}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in new issue
Block a user