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:
@@ -110,41 +110,74 @@ function flattenContinueSegment(value: string): string {
|
||||
.trim()
|
||||
}
|
||||
|
||||
function hasValidCompressionPrefix(
|
||||
function getCurrentCompressionPrefixLength(
|
||||
request: AgentExecutionRequest
|
||||
): boolean {
|
||||
): number | undefined {
|
||||
const state = request.contextCompressionState
|
||||
const history = request.history
|
||||
if (
|
||||
!state ||
|
||||
!history ||
|
||||
state.coveredMessageCount <= 0 ||
|
||||
state.coveredMessageCount > history.length
|
||||
state.coveredMessageCount <= 0
|
||||
) {
|
||||
return false
|
||||
}
|
||||
const coveredHistory = history.slice(0, state.coveredMessageCount)
|
||||
if (
|
||||
createHash('sha256')
|
||||
.update(JSON.stringify(coveredHistory))
|
||||
.digest('hex') !== state.coveredHistoryDigest
|
||||
) {
|
||||
return false
|
||||
return undefined
|
||||
}
|
||||
const ids = request.historyMessageIds
|
||||
if (
|
||||
(state.coveredFromMessageId || state.coveredThroughMessageId) &&
|
||||
(!ids || ids.length !== history.length)
|
||||
) {
|
||||
return false
|
||||
return undefined
|
||||
}
|
||||
return (
|
||||
(!state.coveredFromMessageId ||
|
||||
ids?.[0] === state.coveredFromMessageId) &&
|
||||
(!state.coveredThroughMessageId ||
|
||||
ids?.[state.coveredMessageCount - 1] ===
|
||||
state.coveredThroughMessageId)
|
||||
|
||||
if (state.coveredMessageCount <= history.length) {
|
||||
const coveredHistory = history.slice(
|
||||
0,
|
||||
state.coveredMessageCount
|
||||
)
|
||||
const digestMatches =
|
||||
createHash('sha256')
|
||||
.update(JSON.stringify(coveredHistory))
|
||||
.digest('hex') === state.coveredHistoryDigest
|
||||
const boundariesMatch =
|
||||
(!state.coveredFromMessageId ||
|
||||
ids?.[0] === state.coveredFromMessageId) &&
|
||||
(!state.coveredThroughMessageId ||
|
||||
ids?.[state.coveredMessageCount - 1] ===
|
||||
state.coveredThroughMessageId)
|
||||
if (digestMatches && boundariesMatch) {
|
||||
return state.coveredMessageCount
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!ids ||
|
||||
!state.coveredFromMessageId ||
|
||||
!state.coveredThroughMessageId
|
||||
) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const coveredFromIndex = ids.indexOf(
|
||||
state.coveredFromMessageId
|
||||
)
|
||||
const coveredThroughIndex = ids.indexOf(
|
||||
state.coveredThroughMessageId
|
||||
)
|
||||
if (
|
||||
coveredFromIndex === -1 &&
|
||||
coveredThroughIndex >= 0 &&
|
||||
coveredThroughIndex < state.coveredMessageCount - 1
|
||||
) {
|
||||
return coveredThroughIndex + 1
|
||||
}
|
||||
if (
|
||||
coveredFromIndex === -1 &&
|
||||
coveredThroughIndex === -1
|
||||
) {
|
||||
return 0
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function buildContinuePrompt(
|
||||
@@ -176,7 +209,9 @@ export function buildContinuePrompt(
|
||||
'Answer the CURRENT USER REQUEST now.'
|
||||
].join(' | ')
|
||||
|
||||
if (hasValidCompressionPrefix(request)) {
|
||||
const compressionPrefixLength =
|
||||
getCurrentCompressionPrefixLength(request)
|
||||
if (compressionPrefixLength !== undefined) {
|
||||
const state = request.contextCompressionState!
|
||||
const summaryEnvelope = {
|
||||
role: 'user' as const,
|
||||
@@ -207,9 +242,7 @@ export function buildContinuePrompt(
|
||||
}
|
||||
if (compose(summaryPair).length <= MAX_CONTINUE_PROMPT_CHARACTERS) {
|
||||
const retained = [...summaryPair]
|
||||
const recent = request.history!.slice(
|
||||
state.coveredMessageCount
|
||||
)
|
||||
const recent = request.history!.slice(compressionPrefixLength)
|
||||
for (const message of recent.slice(-18).reverse()) {
|
||||
const candidate = [
|
||||
...summaryPair,
|
||||
|
||||
Reference in New Issue
Block a user