feat: expand multi-runtime workflows for 0.10.0
GoodBuddy previously exposed Runtime capabilities, MCP assignments, plugin controls, context compaction, usage reporting, and task-completion behavior through incomplete or inconsistent paths. This release unifies managed OpenCode, Continue, and DeepSeek Harness controls; adds DSH plugin and image workflows; strengthens MCP and Runtime lifecycle bounds; fixes Windows notification activation; validates cross-architecture packages; and presents the approved bilingual four-section release notes. The DSH plugin marketplace remains a default-off preview whose trusted third-party code runs with current-user permissions. Ask remains read-only, Execute keeps approval controls, and context compaction may use the selected model without deleting GoodBuddy chat history. Release note: GoodBuddy 0.10.0 重点完善多 Runtime 工作流,统一 OpenCode、Continue 与 DeepSeek Harness 的能力、MCP、插件和上下文管理,并提升长对话、多会话与任务通知的连贯性。
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
import {
|
||||
mkdtemp,
|
||||
rm,
|
||||
writeFile
|
||||
} from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import type { ShortcutDetails } from 'electron'
|
||||
import {
|
||||
afterEach,
|
||||
describe,
|
||||
expect,
|
||||
it,
|
||||
vi
|
||||
} from 'vitest'
|
||||
import {
|
||||
isInstalledWindowsBuild,
|
||||
repairStaleWindowsNotificationShortcuts,
|
||||
resolveWindowsAppUserModelId,
|
||||
WINDOWS_APP_USER_MODEL_ID
|
||||
} from './windows-notification-identity'
|
||||
|
||||
const temporaryDirectories: string[] = []
|
||||
|
||||
async function createTemporaryDirectory(): Promise<string> {
|
||||
const directory = await mkdtemp(
|
||||
join(tmpdir(), 'goodbuddy-notification-identity-')
|
||||
)
|
||||
temporaryDirectories.push(directory)
|
||||
return directory
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
temporaryDirectories
|
||||
.splice(0)
|
||||
.map((directory) =>
|
||||
rm(directory, { recursive: true, force: true })
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
describe('Windows notification identity', () => {
|
||||
it('reserves the production AUMID for an installed build', () => {
|
||||
expect(
|
||||
resolveWindowsAppUserModelId({
|
||||
installed: true,
|
||||
executablePath: 'C:\\Program Files\\GoodBuddy\\GoodBuddy.exe'
|
||||
})
|
||||
).toBe(WINDOWS_APP_USER_MODEL_ID)
|
||||
})
|
||||
|
||||
it('uses stable path-scoped identities for standalone builds', () => {
|
||||
const first = resolveWindowsAppUserModelId({
|
||||
installed: false,
|
||||
executablePath: 'D:\\repo\\GoodBuddy.exe'
|
||||
})
|
||||
|
||||
expect(first).not.toBe(WINDOWS_APP_USER_MODEL_ID)
|
||||
expect(
|
||||
resolveWindowsAppUserModelId({
|
||||
installed: false,
|
||||
executablePath: 'd:\\REPO\\goodbuddy.exe'
|
||||
})
|
||||
).toBe(first)
|
||||
expect(
|
||||
resolveWindowsAppUserModelId({
|
||||
installed: false,
|
||||
executablePath: 'D:\\other\\GoodBuddy.exe'
|
||||
})
|
||||
).not.toBe(first)
|
||||
})
|
||||
|
||||
it('recognizes only packaged Windows layouts with an uninstaller', async () => {
|
||||
const directory = await createTemporaryDirectory()
|
||||
const executablePath = join(directory, 'GoodBuddy.exe')
|
||||
await writeFile(join(directory, 'Uninstall GoodBuddy.exe'), '')
|
||||
|
||||
expect(
|
||||
isInstalledWindowsBuild({
|
||||
packaged: true,
|
||||
platform: 'win32',
|
||||
executablePath
|
||||
})
|
||||
).toBe(true)
|
||||
expect(
|
||||
isInstalledWindowsBuild({
|
||||
packaged: false,
|
||||
platform: 'win32',
|
||||
executablePath
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isInstalledWindowsBuild({
|
||||
packaged: true,
|
||||
platform: 'linux',
|
||||
executablePath
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isInstalledWindowsBuild({
|
||||
packaged: true,
|
||||
platform: 'win32',
|
||||
executablePath: '\0'
|
||||
})
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('moves stale shortcuts off the production identity without changing their targets', async () => {
|
||||
const programsDirectory = await createTemporaryDirectory()
|
||||
const stalePath = join(programsDirectory, 'Electron.lnk')
|
||||
const currentPath = join(programsDirectory, 'GoodBuddy.lnk')
|
||||
await Promise.all([
|
||||
writeFile(stalePath, ''),
|
||||
writeFile(currentPath, '')
|
||||
])
|
||||
|
||||
const staleDetails: ShortcutDetails = {
|
||||
target: 'D:\\repo\\node_modules\\electron\\electron.exe',
|
||||
appUserModelId: WINDOWS_APP_USER_MODEL_ID,
|
||||
toastActivatorClsid:
|
||||
'{6D4C974B-001A-47E5-AE4B-F8F12FFDA281}'
|
||||
}
|
||||
const details = new Map<string, ShortcutDetails>([
|
||||
[stalePath, staleDetails],
|
||||
[
|
||||
currentPath,
|
||||
{
|
||||
target:
|
||||
'C:\\Program Files\\GoodBuddy\\GoodBuddy.exe',
|
||||
appUserModelId: WINDOWS_APP_USER_MODEL_ID
|
||||
}
|
||||
]
|
||||
])
|
||||
const writeShortcutLink = vi.fn(() => true)
|
||||
|
||||
await expect(
|
||||
repairStaleWindowsNotificationShortcuts({
|
||||
platform: 'win32',
|
||||
installed: true,
|
||||
executablePath:
|
||||
'C:\\Program Files\\GoodBuddy\\GoodBuddy.exe',
|
||||
programsDirectory,
|
||||
shortcutAccess: {
|
||||
readShortcutLink: (shortcutPath) =>
|
||||
details.get(shortcutPath)!,
|
||||
writeShortcutLink
|
||||
}
|
||||
})
|
||||
).resolves.toEqual({
|
||||
scanned: 2,
|
||||
repaired: 1,
|
||||
failed: 0
|
||||
})
|
||||
expect(writeShortcutLink).toHaveBeenCalledOnce()
|
||||
expect(writeShortcutLink).toHaveBeenCalledWith(
|
||||
stalePath,
|
||||
'update',
|
||||
expect.objectContaining({
|
||||
target: staleDetails.target,
|
||||
toastActivatorClsid: staleDetails.toastActivatorClsid,
|
||||
appUserModelId: expect.not.stringMatching(
|
||||
/^live\.digiman\.goodbuddy$/u
|
||||
)
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('does not touch shortcuts from development or portable builds', async () => {
|
||||
const programsDirectory = await createTemporaryDirectory()
|
||||
await writeFile(join(programsDirectory, 'Electron.lnk'), '')
|
||||
const readShortcutLink = vi.fn()
|
||||
const writeShortcutLink = vi.fn()
|
||||
|
||||
await expect(
|
||||
repairStaleWindowsNotificationShortcuts({
|
||||
platform: 'win32',
|
||||
installed: false,
|
||||
executablePath: 'D:\\repo\\GoodBuddy.exe',
|
||||
programsDirectory,
|
||||
shortcutAccess: {
|
||||
readShortcutLink,
|
||||
writeShortcutLink
|
||||
}
|
||||
})
|
||||
).resolves.toEqual({
|
||||
scanned: 0,
|
||||
repaired: 0,
|
||||
failed: 0
|
||||
})
|
||||
expect(readShortcutLink).not.toHaveBeenCalled()
|
||||
expect(writeShortcutLink).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user