Files
superwork/vscode/src/uri/createSessionUriHandler.ts
T
cruldra b182e0ac5b ✨ feat(vscode): URI 开的会话不再登记进会话管理列表
delegate-fix 等外部方通过 create-session URI 开的一次性会话,
不写入 .spx/session-names.json,也跳过 sessionId 轮询捕获;
面板内手动创建的会话仍照常登记。

Claude-Session: https://claude.ai/code/session_01Kgmb1LvrPmFX3NoUDB4zZC
2026-09-13 10:07:30 +08:00

96 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ExtensionContext, Uri } from 'vscode'
import { promises as fsp } from 'node:fs'
import { window, workspace } from 'vscode'
import { listClaudeProfiles } from '../cc/profiles'
import { logger } from '../logging/logger'
import { createCcSessionTab } from '../panel/handlers/managedSessions'
/**
* 外部触发开 cc 会话 tab 的 URI 入口(供 delegate-fix skill 等外部方调用):
*
* vscode://clurdra.superpowers-vscode-clurdra/create-session
* ?profile=<profile 名,不带 .json>
* &name=<终端 tab 名,如 fix:fable5>
* &prompt=<初始 prompt>
* &cwd=<绝对路径,可选,缺省用 workspaceRoot>
*
* 编码契约:VS Code 把外部 URI 交给扩展前会对 query 整体做一次 percent-decode
* (vs/base/common/uri.ts 的 URI.parse),这里的 URLSearchParams 是第二次 decode。
* 因此发送方对参数值必须做两层 urlencode,值里的 & = % + 等字符才能安全通过。
*/
export function registerCreateSessionUriHandler(context: ExtensionContext): void {
context.subscriptions.push(window.registerUriHandler({
handleUri: (uri: Uri): void => {
void handleCreateSessionUri(uri).catch((err) => {
void window.showErrorMessage(`处理 create-session URI 失败:${err instanceof Error ? err.message : String(err)}`)
})
},
}))
}
async function handleCreateSessionUri(uri: Uri): Promise<void> {
if (uri.path !== '/create-session') {
void window.showErrorMessage(`未知的 superpowers URI path: ${uri.path}`)
return
}
const params = new URLSearchParams(uri.query)
const profileName = (params.get('profile') ?? '').trim()
const name = (params.get('name') ?? '').trim()
const prompt = (params.get('prompt') ?? '').trim()
const cwdParam = (params.get('cwd') ?? '').trim()
if (!profileName) {
void window.showErrorMessage('create-session URI 缺少 profile 参数')
return
}
if (!prompt) {
void window.showErrorMessage('create-session URI 缺少 prompt 参数')
return
}
const profiles = await listClaudeProfiles()
const profile = profiles.find(p => p.name === profileName)
if (!profile) {
void window.showErrorMessage(
`create-session URI:找不到 profile "${profileName}"(可用:${profiles.map(p => p.name).join(', ') || '无'})`,
)
return
}
const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath
if (!workspaceRoot) {
void window.showErrorMessage('请先打开一个工作区文件夹')
return
}
let cwd = workspaceRoot
if (cwdParam) {
const stat = await fsp.stat(cwdParam).catch(() => undefined)
if (!stat?.isDirectory()) {
void window.showErrorMessage(`create-session URI:cwd 不存在或不是目录 (${cwdParam})`)
return
}
cwd = cwdParam
}
const created = await createCcSessionTab({
workspaceRoot,
profilePath: profile.path,
name,
prompt,
cwd,
panel: null,
register: false,
})
if (!created)
return
logger.add({
level: 'info',
source: 'uri',
message: `URI handler 已启动 cc 会话 tab "${created.terminalName}" (profile=${profileName})`,
})
void window.showInformationMessage(`已开 cc 会话 tab "${created.terminalName}"`)
}