✨ feat(vscode): 历史会话可换 profile 恢复
This commit is contained in:
@@ -556,7 +556,7 @@ export class KanbanWebviewPanel {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (msg.type === 'managed-sessions/resume') {
|
if (msg.type === 'managed-sessions/resume') {
|
||||||
void managedSessions.handleManagedSessionsResume(this, msg.sessionId)
|
void managedSessions.handleManagedSessionsResume(this, msg.sessionId, msg.profilePath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (msg.type === 'managed-sessions/delete') {
|
if (msg.type === 'managed-sessions/delete') {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { buildCcCommand } from '../../cc/ccCommand'
|
|||||||
import { pollForNewSession, projectsDirFor } from '../../cc/sessionWatcher'
|
import { pollForNewSession, projectsDirFor } from '../../cc/sessionWatcher'
|
||||||
import { logger } from '../../logging/logger'
|
import { logger } from '../../logging/logger'
|
||||||
import { listImportableNamedSessions } from '../../sessions/importableNamedSessions'
|
import { listImportableNamedSessions } from '../../sessions/importableNamedSessions'
|
||||||
|
import { decideManagedResumeProfile } from '../../sessions/managedResumeProfile'
|
||||||
import { readManagedSessions, writeManagedSessions } from '../../sessions/managedStore'
|
import { readManagedSessions, writeManagedSessions } from '../../sessions/managedStore'
|
||||||
import { inferProfilePathForSession } from '../../sessions/sessionProfileInference'
|
import { inferProfilePathForSession } from '../../sessions/sessionProfileInference'
|
||||||
import { resolveProfilePath } from '../../cc/profiles'
|
import { resolveProfilePath } from '../../cc/profiles'
|
||||||
@@ -225,7 +226,7 @@ export async function handleManagedSessionsRename(panel: KanbanWebviewPanel, ses
|
|||||||
* 恢复一个受管理会话:在新终端 tab 里跑 `claude ... --resume <id>`,
|
* 恢复一个受管理会话:在新终端 tab 里跑 `claude ... --resume <id>`,
|
||||||
* cwd = workspaceRoot。in-flight 锁防止重复点击重复 createTerminal。
|
* cwd = workspaceRoot。in-flight 锁防止重复点击重复 createTerminal。
|
||||||
*/
|
*/
|
||||||
export async function handleManagedSessionsResume(panel: KanbanWebviewPanel, sessionId: string): Promise<void> {
|
export async function handleManagedSessionsResume(panel: KanbanWebviewPanel, sessionId: string, profilePath?: string): Promise<void> {
|
||||||
const lockKey = `managed:${sessionId}`
|
const lockKey = `managed:${sessionId}`
|
||||||
if (panel.resumeInFlight.has(lockKey)) {
|
if (panel.resumeInFlight.has(lockKey)) {
|
||||||
logger.add({
|
logger.add({
|
||||||
@@ -244,29 +245,35 @@ export async function handleManagedSessionsResume(panel: KanbanWebviewPanel, ses
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = await readManagedSessions(workspaceRoot)
|
||||||
|
const target = data.sessions.find(s => s.id === sessionId)
|
||||||
|
|
||||||
|
const override = profilePath?.trim() || undefined
|
||||||
|
let inferred: string | null = null
|
||||||
|
if (!override && (!target?.profilePath || target.profilePath.trim() === '') && target) {
|
||||||
|
inferred = await inferProfilePathForSession(sessionId, projectsDirFor(workspaceRoot))
|
||||||
|
}
|
||||||
|
|
||||||
|
const decided = decideManagedResumeProfile({
|
||||||
|
storedProfile: target?.profilePath,
|
||||||
|
overrideProfile: profilePath,
|
||||||
|
inferredProfile: inferred,
|
||||||
|
})
|
||||||
|
if (decided.persist && target) {
|
||||||
|
target.profilePath = decided.persist
|
||||||
|
await writeManagedSessions(workspaceRoot, data)
|
||||||
|
}
|
||||||
|
|
||||||
// 已有该会话的存活终端,直接聚焦、不再开新的(防重复)。
|
// 已有该会话的存活终端,直接聚焦、不再开新的(防重复)。
|
||||||
const existing = panel.managedTerminals.get(sessionId)
|
const existing = panel.managedTerminals.get(sessionId)
|
||||||
if (existing) {
|
if (existing) {
|
||||||
|
if (decided.persist)
|
||||||
|
await pushManagedSessions(panel)
|
||||||
existing.show(false)
|
existing.show(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await readManagedSessions(workspaceRoot)
|
const effectiveProfilePath = resolveProfilePath(decided.effective)
|
||||||
const target = data.sessions.find(s => s.id === sessionId)
|
|
||||||
|
|
||||||
// store 缺 profilePath 时从 transcript 推断并回写,避免 resume 落到 default profile。
|
|
||||||
let storedProfile = target?.profilePath
|
|
||||||
if ((!storedProfile || storedProfile.trim() === '') && target) {
|
|
||||||
const inferred = await inferProfilePathForSession(sessionId, projectsDirFor(workspaceRoot))
|
|
||||||
if (inferred) {
|
|
||||||
storedProfile = inferred
|
|
||||||
target.profilePath = inferred
|
|
||||||
await writeManagedSessions(workspaceRoot, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const effectiveProfilePath = resolveProfilePath(
|
|
||||||
storedProfile && storedProfile.trim() !== '' ? storedProfile : undefined,
|
|
||||||
)
|
|
||||||
if (effectiveProfilePath.includes('\'')) {
|
if (effectiveProfilePath.includes('\'')) {
|
||||||
void window.showErrorMessage(
|
void window.showErrorMessage(
|
||||||
`resume 失败:profilePath 含单引号,拒绝执行 (${effectiveProfilePath})`,
|
`resume 失败:profilePath 含单引号,拒绝执行 (${effectiveProfilePath})`,
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ export type WebviewToExtension
|
|||||||
| { type: 'managed-sessions/get' }
|
| { type: 'managed-sessions/get' }
|
||||||
| { type: 'managed-sessions/create', profilePath: string, name?: string, prompt?: string }
|
| { type: 'managed-sessions/create', profilePath: string, name?: string, prompt?: string }
|
||||||
| { type: 'managed-sessions/rename', sessionId: string, name: string }
|
| { type: 'managed-sessions/rename', sessionId: string, name: string }
|
||||||
| { type: 'managed-sessions/resume', sessionId: string }
|
| { type: 'managed-sessions/resume', sessionId: string, profilePath?: string }
|
||||||
| { type: 'managed-sessions/delete', sessionId: string }
|
| { type: 'managed-sessions/delete', sessionId: string }
|
||||||
| { type: 'managed-sessions/close-tab', sessionId: string }
|
| { type: 'managed-sessions/close-tab', sessionId: string }
|
||||||
| { type: 'managed-sessions/list-importable' }
|
| { type: 'managed-sessions/list-importable' }
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { decideManagedResumeProfile } from './managedResumeProfile'
|
||||||
|
|
||||||
|
describe('decideManagedResumeProfile', () => {
|
||||||
|
it('override 非空时用 override,与 stored 不同则写回', () => {
|
||||||
|
expect(decideManagedResumeProfile({
|
||||||
|
storedProfile: '/profiles/grok-4.5.json',
|
||||||
|
overrideProfile: '/profiles/opus.json',
|
||||||
|
inferredProfile: '/profiles/from-jsonl.json',
|
||||||
|
})).toEqual({
|
||||||
|
effective: '/profiles/opus.json',
|
||||||
|
persist: '/profiles/opus.json',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('override 与 stored trim 后相同则不写回,且忽略 inferred', () => {
|
||||||
|
expect(decideManagedResumeProfile({
|
||||||
|
storedProfile: ' /profiles/grok-4.5.json ',
|
||||||
|
overrideProfile: '/profiles/grok-4.5.json',
|
||||||
|
inferredProfile: '/profiles/from-jsonl.json',
|
||||||
|
})).toEqual({
|
||||||
|
effective: '/profiles/grok-4.5.json',
|
||||||
|
persist: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('空白 override 视为未提供,回落到 stored', () => {
|
||||||
|
expect(decideManagedResumeProfile({
|
||||||
|
storedProfile: '/profiles/grok-4.5.json',
|
||||||
|
overrideProfile: ' ',
|
||||||
|
inferredProfile: '/profiles/from-jsonl.json',
|
||||||
|
})).toEqual({
|
||||||
|
effective: '/profiles/grok-4.5.json',
|
||||||
|
persist: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('无 override 时用 stored,不写回也不用 inferred', () => {
|
||||||
|
expect(decideManagedResumeProfile({
|
||||||
|
storedProfile: '/profiles/grok-4.5.json',
|
||||||
|
overrideProfile: undefined,
|
||||||
|
inferredProfile: '/profiles/from-jsonl.json',
|
||||||
|
})).toEqual({
|
||||||
|
effective: '/profiles/grok-4.5.json',
|
||||||
|
persist: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('override 与 stored 都空时用 inferred 并写回', () => {
|
||||||
|
expect(decideManagedResumeProfile({
|
||||||
|
storedProfile: ' ',
|
||||||
|
overrideProfile: undefined,
|
||||||
|
inferredProfile: '/profiles/from-jsonl.json',
|
||||||
|
})).toEqual({
|
||||||
|
effective: '/profiles/from-jsonl.json',
|
||||||
|
persist: '/profiles/from-jsonl.json',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('三者都空则 effective 与 persist 都为 undefined', () => {
|
||||||
|
expect(decideManagedResumeProfile({
|
||||||
|
storedProfile: undefined,
|
||||||
|
overrideProfile: '',
|
||||||
|
inferredProfile: null,
|
||||||
|
})).toEqual({
|
||||||
|
effective: undefined,
|
||||||
|
persist: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export function decideManagedResumeProfile(input: {
|
||||||
|
storedProfile: string | undefined
|
||||||
|
overrideProfile: string | undefined
|
||||||
|
inferredProfile: string | null
|
||||||
|
}): { effective: string | undefined, persist: string | undefined } {
|
||||||
|
const override = input.overrideProfile?.trim() || undefined
|
||||||
|
const stored = input.storedProfile?.trim() || undefined
|
||||||
|
|
||||||
|
if (override) { // ① 行内覆盖:与 store 不同才写回;忽略 jsonl 推断
|
||||||
|
return {
|
||||||
|
effective: override,
|
||||||
|
persist: override !== stored ? override : undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stored) // ② store 已有 → 沿用,不写回
|
||||||
|
return { effective: stored, persist: undefined }
|
||||||
|
if (input.inferredProfile) // ③ 缺 profile 才用 jsonl 回填并写回
|
||||||
|
return { effective: input.inferredProfile, persist: input.inferredProfile }
|
||||||
|
return { effective: undefined, persist: undefined }
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@ interface BottomTabsProps {
|
|||||||
profiles: ClaudeProfile[]
|
profiles: ClaudeProfile[]
|
||||||
onManagedSessionCreate: (profilePath: string, name?: string, prompt?: string) => void
|
onManagedSessionCreate: (profilePath: string, name?: string, prompt?: string) => void
|
||||||
onManagedSessionRename: (id: string, name: string) => void
|
onManagedSessionRename: (id: string, name: string) => void
|
||||||
onManagedSessionResume: (id: string) => void
|
onManagedSessionResume: (id: string, profilePath?: string) => void
|
||||||
onManagedSessionDelete: (id: string) => void
|
onManagedSessionDelete: (id: string) => void
|
||||||
onManagedSessionCloseTab: (id: string) => void
|
onManagedSessionCloseTab: (id: string) => void
|
||||||
importableSessions: Array<{ id: string, name: string, mtimeMs: number }>
|
importableSessions: Array<{ id: string, name: string, mtimeMs: number }>
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
*
|
*
|
||||||
* - 上方表单:选 profile(下拉,复用 useIssues 的 ClaudeProfile 列表)+ 首个提示词
|
* - 上方表单:选 profile(下拉,复用 useIssues 的 ClaudeProfile 列表)+ 首个提示词
|
||||||
* (可选,多行)+「创建」按钮 → 主进程开一个 cc 终端 tab 并捕获会话。
|
* (可选,多行)+「创建」按钮 → 主进程开一个 cc 终端 tab 并捕获会话。
|
||||||
* - 下方列表:每行显示名字(双击行内改名,Enter 提交、Esc 取消)、profile 文件名、
|
* - 下方列表:每行显示名字(双击行内改名,Enter 提交、Esc 取消)、行内可改 profile、
|
||||||
* 创建时间;点击行(非编辑区)→ 主进程新终端 resume;行尾删除按钮(仅移除记录)。
|
* 创建时间;点行用该 profile resume 并写回;行尾删除按钮(仅移除记录)。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ClaudeProfile } from '../hooks/useIssues'
|
import type { ClaudeProfile } from '../hooks/useIssues'
|
||||||
@@ -17,7 +17,7 @@ interface ManagedSessionsPanelProps {
|
|||||||
profiles: ClaudeProfile[]
|
profiles: ClaudeProfile[]
|
||||||
onCreate: (profilePath: string, name?: string, prompt?: string) => void
|
onCreate: (profilePath: string, name?: string, prompt?: string) => void
|
||||||
onRename: (id: string, name: string) => void
|
onRename: (id: string, name: string) => void
|
||||||
onResume: (id: string) => void
|
onResume: (id: string, profilePath?: string) => void
|
||||||
onDelete: (id: string) => void
|
onDelete: (id: string) => void
|
||||||
onCloseTab: (id: string) => void
|
onCloseTab: (id: string) => void
|
||||||
importableSessions: Array<{ id: string, name: string, mtimeMs: number }>
|
importableSessions: Array<{ id: string, name: string, mtimeMs: number }>
|
||||||
@@ -33,6 +33,16 @@ function basename(p?: string): string {
|
|||||||
return idx >= 0 ? p.slice(idx + 1) : p
|
return idx >= 0 ? p.slice(idx + 1) : p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function matchStoredProfile(stored: string | undefined, profiles: ClaudeProfile[]): string {
|
||||||
|
if (!stored)
|
||||||
|
return ''
|
||||||
|
if (profiles.some(p => p.path === stored))
|
||||||
|
return stored
|
||||||
|
const storedBase = basename(stored)
|
||||||
|
const fuzzy = profiles.find(p => basename(p.path) === storedBase || p.name === storedBase)
|
||||||
|
return fuzzy?.path ?? stored
|
||||||
|
}
|
||||||
|
|
||||||
function formatTime(ts: number): string {
|
function formatTime(ts: number): string {
|
||||||
if (!ts)
|
if (!ts)
|
||||||
return ''
|
return ''
|
||||||
@@ -246,6 +256,7 @@ export function ManagedSessionsPanel({
|
|||||||
<SessionRow
|
<SessionRow
|
||||||
key={s.id}
|
key={s.id}
|
||||||
session={s}
|
session={s}
|
||||||
|
profiles={profiles}
|
||||||
onRename={onRename}
|
onRename={onRename}
|
||||||
onResume={onResume}
|
onResume={onResume}
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
@@ -261,16 +272,19 @@ export function ManagedSessionsPanel({
|
|||||||
|
|
||||||
interface SessionRowProps {
|
interface SessionRowProps {
|
||||||
session: ManagedSession
|
session: ManagedSession
|
||||||
|
profiles: ClaudeProfile[]
|
||||||
onRename: (id: string, name: string) => void
|
onRename: (id: string, name: string) => void
|
||||||
onResume: (id: string) => void
|
onResume: (id: string, profilePath?: string) => void
|
||||||
onDelete: (id: string) => void
|
onDelete: (id: string) => void
|
||||||
onCloseTab: (id: string) => void
|
onCloseTab: (id: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function SessionRow({ session, onRename, onResume, onDelete, onCloseTab }: SessionRowProps) {
|
function SessionRow({ session, profiles, onRename, onResume, onDelete, onCloseTab }: SessionRowProps) {
|
||||||
const [editing, setEditing] = useState(false)
|
const [editing, setEditing] = useState(false)
|
||||||
const [draft, setDraft] = useState(session.name)
|
const [draft, setDraft] = useState(session.name)
|
||||||
|
const [userPicked, setUserPicked] = useState<string | undefined>(undefined)
|
||||||
const inputRef = useRef<HTMLInputElement | null>(null)
|
const inputRef = useRef<HTMLInputElement | null>(null)
|
||||||
|
const pickedProfile = userPicked ?? matchStoredProfile(session.profilePath, profiles)
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (!editing)
|
if (!editing)
|
||||||
@@ -282,6 +296,10 @@ function SessionRow({ session, onRename, onResume, onDelete, onCloseTab }: Sessi
|
|||||||
el.select()
|
el.select()
|
||||||
}, [editing])
|
}, [editing])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setUserPicked(undefined)
|
||||||
|
}, [session.profilePath])
|
||||||
|
|
||||||
const beginEdit = useCallback((): void => {
|
const beginEdit = useCallback((): void => {
|
||||||
setDraft(session.name)
|
setDraft(session.name)
|
||||||
setEditing(true)
|
setEditing(true)
|
||||||
@@ -299,8 +317,12 @@ function SessionRow({ session, onRename, onResume, onDelete, onCloseTab }: Sessi
|
|||||||
setDraft(session.name)
|
setDraft(session.name)
|
||||||
}, [session.name])
|
}, [session.name])
|
||||||
|
|
||||||
const profileName = basename(session.profilePath)
|
const resume = useCallback((): void => {
|
||||||
|
onResume(session.id, pickedProfile || session.profilePath)
|
||||||
|
}, [onResume, session.id, session.profilePath, pickedProfile])
|
||||||
|
|
||||||
const created = formatTime(session.createdAt)
|
const created = formatTime(session.createdAt)
|
||||||
|
const storedMissing = !profiles.some(p => p.path === pickedProfile)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
@@ -308,7 +330,7 @@ function SessionRow({ session, onRename, onResume, onDelete, onCloseTab }: Sessi
|
|||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => onResume(session.id)}
|
onClick={resume}
|
||||||
title="点击恢复会话(新终端 resume)"
|
title="点击恢复会话(新终端 resume)"
|
||||||
className="grid size-6 shrink-0 place-items-center rounded text-[var(--vscode-descriptionForeground)] hover:bg-[var(--vscode-toolbar-hoverBackground,var(--vscode-list-hoverBackground))] hover:text-[var(--vscode-foreground)]"
|
className="grid size-6 shrink-0 place-items-center rounded text-[var(--vscode-descriptionForeground)] hover:bg-[var(--vscode-toolbar-hoverBackground,var(--vscode-list-hoverBackground))] hover:text-[var(--vscode-foreground)]"
|
||||||
aria-label="恢复会话"
|
aria-label="恢复会话"
|
||||||
@@ -320,7 +342,7 @@ function SessionRow({ session, onRename, onResume, onDelete, onCloseTab }: Sessi
|
|||||||
className="min-w-0 flex-1 cursor-pointer"
|
className="min-w-0 flex-1 cursor-pointer"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!editing)
|
if (!editing)
|
||||||
onResume(session.id)
|
resume()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{editing
|
{editing
|
||||||
@@ -357,8 +379,32 @@ function SessionRow({ session, onRename, onResume, onDelete, onCloseTab }: Sessi
|
|||||||
>
|
>
|
||||||
{session.name || <span className="opacity-40">(未命名)</span>}
|
{session.name || <span className="opacity-40">(未命名)</span>}
|
||||||
</span>
|
</span>
|
||||||
<span className="truncate text-[10px] text-[var(--vscode-descriptionForeground)]">
|
<span className="flex min-w-0 items-center text-[10px] text-[var(--vscode-descriptionForeground)]">
|
||||||
{[profileName, created].filter(Boolean).join(' · ')}
|
{profiles.length === 0
|
||||||
|
? (
|
||||||
|
<span className="truncate">{basename(session.profilePath)}</span>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<select
|
||||||
|
value={pickedProfile}
|
||||||
|
title="换 profile 后点行打开;已打开的终端下次才生效"
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
onMouseDown={e => e.stopPropagation()}
|
||||||
|
onChange={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setUserPicked(e.target.value)
|
||||||
|
}}
|
||||||
|
className="min-w-0 bg-transparent py-0 pr-1 text-[10px] text-[var(--vscode-descriptionForeground)] outline-none focus:ring-1 focus:ring-inset focus:ring-[var(--vscode-focusBorder)]"
|
||||||
|
>
|
||||||
|
{storedMissing && (
|
||||||
|
<option value={pickedProfile}>{basename(pickedProfile) || '(未设置)'}</option>
|
||||||
|
)}
|
||||||
|
{profiles.map(p => (
|
||||||
|
<option key={p.path} value={p.path}>{p.name}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
)}
|
||||||
|
{created ? <span className="shrink-0">{(profiles.length > 0 || Boolean(basename(session.profilePath))) ? ' · ' : ''}{created}</span> : null}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export interface UseManagedSessionsResult {
|
|||||||
managedSessions: ManagedSessionsData
|
managedSessions: ManagedSessionsData
|
||||||
createManagedSession: (profilePath: string, name?: string, prompt?: string) => void
|
createManagedSession: (profilePath: string, name?: string, prompt?: string) => void
|
||||||
renameManagedSession: (id: string, name: string) => void
|
renameManagedSession: (id: string, name: string) => void
|
||||||
resumeManagedSession: (id: string) => void
|
resumeManagedSession: (id: string, profilePath?: string) => void
|
||||||
deleteManagedSession: (id: string) => void
|
deleteManagedSession: (id: string) => void
|
||||||
closeManagedSessionTab: (id: string) => void
|
closeManagedSessionTab: (id: string) => void
|
||||||
listImportableNamedSessions: () => void
|
listImportableNamedSessions: () => void
|
||||||
@@ -57,8 +57,8 @@ export function useManagedSessions(): UseManagedSessionsResult {
|
|||||||
postMessage({ type: 'managed-sessions/rename', sessionId: id, name })
|
postMessage({ type: 'managed-sessions/rename', sessionId: id, name })
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const resumeManagedSession = useCallback((id: string): void => {
|
const resumeManagedSession = useCallback((id: string, profilePath?: string): void => {
|
||||||
postMessage({ type: 'managed-sessions/resume', sessionId: id })
|
postMessage({ type: 'managed-sessions/resume', sessionId: id, profilePath })
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const deleteManagedSession = useCallback((id: string): void => {
|
const deleteManagedSession = useCallback((id: string): void => {
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ export type WebviewToExtension
|
|||||||
| { type: 'managed-sessions/get' }
|
| { type: 'managed-sessions/get' }
|
||||||
| { type: 'managed-sessions/create', profilePath: string, name?: string, prompt?: string }
|
| { type: 'managed-sessions/create', profilePath: string, name?: string, prompt?: string }
|
||||||
| { type: 'managed-sessions/rename', sessionId: string, name: string }
|
| { type: 'managed-sessions/rename', sessionId: string, name: string }
|
||||||
| { type: 'managed-sessions/resume', sessionId: string }
|
| { type: 'managed-sessions/resume', sessionId: string, profilePath?: string }
|
||||||
| { type: 'managed-sessions/delete', sessionId: string }
|
| { type: 'managed-sessions/delete', sessionId: string }
|
||||||
| { type: 'managed-sessions/close-tab', sessionId: string }
|
| { type: 'managed-sessions/close-tab', sessionId: string }
|
||||||
| { type: 'managed-sessions/list-importable' }
|
| { type: 'managed-sessions/list-importable' }
|
||||||
|
|||||||
Reference in New Issue
Block a user