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:
mesalogo
2026-08-17 12:57:12 +08:00
parent f5ee9b2198
commit cbbe30896e
50 changed files with 4077 additions and 605 deletions
+51 -21
View File
@@ -7,16 +7,40 @@ export const releaseVersionSchema = z
'Release version must be a stable semantic version'
)
const localizedReleaseNotesSchema = z
.object({
features: z.array(z.string().trim().min(1).max(240)).max(20),
fixes: z.array(z.string().trim().min(1).max(240)).max(20)
})
.strict()
.refine(
(notes) => notes.features.length > 0 || notes.fixes.length > 0,
'Release notes must contain at least one item'
)
const releaseNoteItemSchema = z.string().trim().min(1).max(500)
const localizedReleaseNotesSchema = z.preprocess(
(value) => {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
return value
}
const notes = value as Record<string, unknown>
if ('highlights' in notes || 'notices' in notes) {
return value
}
return {
highlights: [],
...notes,
notices: []
}
},
z
.object({
highlights: z.array(releaseNoteItemSchema).max(3),
features: z.array(releaseNoteItemSchema).max(20),
fixes: z.array(releaseNoteItemSchema).max(20),
notices: z.array(releaseNoteItemSchema).max(20)
})
.strict()
.refine(
(notes) =>
notes.highlights.length > 0 ||
notes.features.length > 0 ||
notes.fixes.length > 0 ||
notes.notices.length > 0,
'Release notes must contain at least one item'
)
)
export const releaseNoteSchema = z
.object({
@@ -48,17 +72,23 @@ export const releaseNotesFileSchema = z
})
}
versions.add(release.version)
if (
release.notes['zh-CN'].features.length !==
release.notes['en-US'].features.length ||
release.notes['zh-CN'].fixes.length !==
release.notes['en-US'].fixes.length
) {
context.addIssue({
code: 'custom',
message: 'Localized release-note sections must have matching counts',
path: ['releases', index, 'notes']
})
for (const section of [
'highlights',
'features',
'fixes',
'notices'
] as const) {
if (
release.notes['zh-CN'][section].length !==
release.notes['en-US'][section].length
) {
context.addIssue({
code: 'custom',
message:
'Localized release-note sections must have matching counts',
path: ['releases', index, 'notes', section]
})
}
}
}
})