Files
superwork/vscode/src/extension.ts
T
cruldra 7bac5c8b03 ✨ feat(vscode): 七份提示词统一走 Handlebars,头脑风暴三档合一
- 模板引擎换成 Handlebars(noEscape,提示词是纯文本不能被转义),单花括号写法彻底退场
- brainstorm-continue / brainstorm-continue-prototype 两份并进 brainstorm.md,
  用 {{#if issueNumber}} 分新建 / 续聊,续聊里用 {{#if prototypeFile}} 嵌原型段落,
  设置面板对应的两个 textarea 一并删掉
- 模板上下文 = 工单 state JSON 全量字段 + issueNumber / userRequest / nonce /
  planFile / prNumber / prRef,以后模板想用新字段不用改扩展代码
- 各会话入口共用一条 state 读取路径,读失败只记 warn 按空状态继续,不拦开会话
- 升级后首次启动把存量自定义提示词迁到双花括号并合并成一份,改写前把
  settings.json 备份成 settings.json.bak-<时间戳>,迁移动作全写日志
- 装 handlebars 时给 vsce 传递依赖的老 semver 加 trustPolicyExclude 豁免,
  否则 no-downgrade 策略卡住整个装包

Claude-Session: https://claude.ai/code/session_01Kgmb1LvrPmFX3NoUDB4zZC
2026-09-15 00:44:28 +08:00

103 lines
3.6 KiB
TypeScript

import type {
Event,
ExtensionContext,
TreeDataProvider,
TreeItem,
} from 'vscode'
import { commands, EventEmitter, window } from 'vscode'
import { initIdentity } from './auth/identity'
import { setProfilesDirOverride } from './cc/profiles'
import { logger } from './logging/logger'
import { KanbanWebviewPanel } from './panel/KanbanPanel'
import { getSettings, migratePromptTemplates, persistSeededProfiles } from './settings/store'
import { registerCreateSessionUriHandler } from './uri/createSessionUriHandler'
import { webhookCoordinator } from './webhook/coordinator'
/**
* 侧边栏 TreeView 永远没有 item —— 它存在的唯一目的是接住活动栏图标
* 点击事件,触发"开 Kanban panel + 切回 File Explorer"的自动跳转。
*/
class EmptyTreeProvider implements TreeDataProvider<never> {
private readonly _onDidChangeTreeData = new EventEmitter<void>()
readonly onDidChangeTreeData: Event<void> = this._onDidChangeTreeData.event
getTreeItem(): TreeItem {
throw new Error('unreachable')
}
getChildren(): never[] {
return []
}
}
export function activate(context: ExtensionContext): void {
// Profiles 目录 override 在 panel 未打开时也要生效(list / launch 共用)。
setProfilesDirOverride(getSettings(context).profilesDirectory || undefined)
// 存量提示词先迁到 Handlebars,再让 persistSeededProfiles 在迁移结果上补 seed。
for (const note of migratePromptTemplates(context))
logger.add({ level: note.level, source: 'settings', message: note.message })
void persistSeededProfiles(context)
// Start the webhook server immediately so PR callbacks are received even
// when the Kanban panel is closed. Disposed automatically via subscriptions.
webhookCoordinator.init(context)
context.subscriptions.push(logger, {
dispose: () => { void webhookCoordinator.dispose() },
})
// 状态栏常驻展示当前 Gitea 身份;token 用错人(同步/复制)时第一眼能看出来。
void initIdentity(context)
// vscode://clurdra.superpowers-vscode-clurdra/create-session 外部触发开 cc 会话 tab。
registerCreateSessionUriHandler(context)
const treeView = window.createTreeView('superpowers.kanban', {
treeDataProvider: new EmptyTreeProvider(),
showCollapseAll: false,
})
let wasVisible = treeView.visible
let isAutoOpening = false
const autoOpenPanelFromActivityBar = async (): Promise<void> => {
if (isAutoOpening)
return
isAutoOpening = true
try {
KanbanWebviewPanel.createOrShow(context)
// 立刻把 sidebar 切回 File Explorer,让 superpowers 的空 sidebar 一闪而过
try {
await commands.executeCommand('workbench.view.explorer')
}
catch {
// 不存在 explorer 视图时静默忽略
}
}
finally {
isAutoOpening = false
}
}
treeView.onDidChangeVisibility(async (e) => {
const isVisible = e.visible
// 仅当从不可见变可见(即用户点击了活动栏图标)时触发
if (isVisible && !wasVisible && !isAutoOpening)
await autoOpenPanelFromActivityBar()
wasVisible = isVisible
})
context.subscriptions.push(
treeView,
commands.registerCommand('superpowers.openKanban', () => {
KanbanWebviewPanel.createOrShow(context)
}),
commands.registerCommand('superpowers.refresh', () => {
KanbanWebviewPanel.refresh()
}),
commands.registerCommand('superpowers.setGiteaToken', () => {
KanbanWebviewPanel.createOrShow(context)
KanbanWebviewPanel.requestEditAuth()
}),
)
}
export function deactivate(): void {}