Resolves all merge conflicts, preserving our split module structure while integrating all dev changes: - Custom agent summaries support (parseRegisteredAgentSummaries) - Background notification queue (enqueueNotificationForParent) - Atlas shared git-worktree module (collectGitDiffStats, formatFileChanges) - Ralph-loop withTimeout + DEFAULT_API_TIMEOUT=5000 - Session recovery assistant_prefill_unsupported error type - Atlas agentOverrides forwarding - Config handler plan model demotion (buildPlanDemoteConfig) - Delegate-task agentOverrides, promptSyncWithModelSuggestionRetry, variant - LSP init timeout + stale init detection - isPlanFamily function + task-continuation-enforcer hook - Handoff command
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import type { PluginInput } from "@opencode-ai/plugin"
|
|
import { log } from "../../shared/logger"
|
|
import { findNearestMessageWithFields } from "../../features/hook-message-injector"
|
|
import { getMessageDir } from "./message-storage-directory"
|
|
import { withTimeout } from "./with-timeout"
|
|
|
|
type MessageInfo = {
|
|
agent?: string
|
|
model?: { providerID: string; modelID: string }
|
|
modelID?: string
|
|
providerID?: string
|
|
}
|
|
|
|
export async function injectContinuationPrompt(
|
|
ctx: PluginInput,
|
|
options: { sessionID: string; prompt: string; directory: string; apiTimeoutMs: number },
|
|
): Promise<void> {
|
|
let agent: string | undefined
|
|
let model: { providerID: string; modelID: string } | undefined
|
|
|
|
try {
|
|
const messagesResp = await withTimeout(
|
|
ctx.client.session.messages({
|
|
path: { id: options.sessionID },
|
|
}),
|
|
options.apiTimeoutMs,
|
|
)
|
|
const messages = (messagesResp.data ?? []) as Array<{ info?: MessageInfo }>
|
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
const info = messages[i]?.info
|
|
if (info?.agent || info?.model || (info?.modelID && info?.providerID)) {
|
|
agent = info.agent
|
|
model =
|
|
info.model ??
|
|
(info.providerID && info.modelID
|
|
? { providerID: info.providerID, modelID: info.modelID }
|
|
: undefined)
|
|
break
|
|
}
|
|
}
|
|
} catch {
|
|
const messageDir = getMessageDir(options.sessionID)
|
|
const currentMessage = messageDir ? findNearestMessageWithFields(messageDir) : null
|
|
agent = currentMessage?.agent
|
|
model =
|
|
currentMessage?.model?.providerID && currentMessage?.model?.modelID
|
|
? {
|
|
providerID: currentMessage.model.providerID,
|
|
modelID: currentMessage.model.modelID,
|
|
}
|
|
: undefined
|
|
}
|
|
|
|
await ctx.client.session.promptAsync({
|
|
path: { id: options.sessionID },
|
|
body: {
|
|
...(agent !== undefined ? { agent } : {}),
|
|
...(model !== undefined ? { model } : {}),
|
|
parts: [{ type: "text", text: options.prompt }],
|
|
},
|
|
query: { directory: options.directory },
|
|
})
|
|
|
|
log("[ralph-loop] continuation injected", { sessionID: options.sessionID })
|
|
}
|