Files
superwork/vscode/src/uri/createSessionUriHandler.ts
T
chehongweo 3621729367 🐛 fix(vscode): 会话终端直接拉起 claude/codex,不再往 shell 里打命令,启动命令不再污染 zsh 历史
新建工单、实施、审查、测试、原型、续聊、冲突解决、会话管理和各种恢复会话,
都改成开终端时直接指定要跑的程序(用户默认 shell 以 -ilc 'exec "$@"' 拉起),
环境变量照常加载,参数原样传入。程序退出时标签页随之关闭。
提示词和配置文件路径里带单引号也不再拒绝执行,相关的转义和拦截全部删掉。
2026-09-29 04:40:35 +08:00

94 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,
})
logger.add({
level: 'info',
source: 'uri',
message: `URI handler 已启动 cc 会话 tab "${created.terminalName}" (profile=${profileName})`,
})
void window.showInformationMessage(`已开 cc 会话 tab "${created.terminalName}"`)
}