2026-01-01 20:58:02 +09:00
|
|
|
import type { PluginInput } from "@opencode-ai/plugin"
|
2026-01-05 02:37:01 +09:00
|
|
|
import { detectKeywordsWithType, extractPromptText, removeCodeBlocks } from "./detector"
|
2025-12-14 11:38:33 +09:00
|
|
|
import { log } from "../../shared"
|
|
|
|
|
|
|
|
|
|
export * from "./detector"
|
|
|
|
|
export * from "./constants"
|
|
|
|
|
export * from "./types"
|
|
|
|
|
|
2026-01-01 20:58:02 +09:00
|
|
|
export function createKeywordDetectorHook(ctx: PluginInput) {
|
2025-12-14 11:38:33 +09:00
|
|
|
return {
|
|
|
|
|
"chat.message": async (
|
|
|
|
|
input: {
|
|
|
|
|
sessionID: string
|
|
|
|
|
agent?: string
|
|
|
|
|
model?: { providerID: string; modelID: string }
|
|
|
|
|
messageID?: string
|
|
|
|
|
},
|
|
|
|
|
output: {
|
|
|
|
|
message: Record<string, unknown>
|
|
|
|
|
parts: Array<{ type: string; text?: string; [key: string]: unknown }>
|
|
|
|
|
}
|
|
|
|
|
): Promise<void> => {
|
|
|
|
|
const promptText = extractPromptText(output.parts)
|
2026-01-07 01:41:42 +09:00
|
|
|
let detectedKeywords = detectKeywordsWithType(removeCodeBlocks(promptText), input.agent)
|
2025-12-14 11:38:33 +09:00
|
|
|
|
2026-01-05 02:37:01 +09:00
|
|
|
if (detectedKeywords.length === 0) {
|
2025-12-14 11:38:33 +09:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-07 01:41:42 +09:00
|
|
|
// Check if this is a subagent session (has parent)
|
|
|
|
|
// Only ultrawork keywords work in subagent sessions
|
|
|
|
|
// Other keywords (search, analyze, etc.) only work in main sessions
|
|
|
|
|
try {
|
|
|
|
|
const sessionInfo = await ctx.client.session.get({ path: { id: input.sessionID } })
|
|
|
|
|
const isSubagentSession = !!sessionInfo.data?.parentID
|
|
|
|
|
|
|
|
|
|
if (isSubagentSession) {
|
|
|
|
|
// Filter to only ultrawork keywords in subagent sessions
|
|
|
|
|
detectedKeywords = detectedKeywords.filter((k) => k.type === "ultrawork")
|
|
|
|
|
if (detectedKeywords.length === 0) {
|
|
|
|
|
log(`[keyword-detector] Skipping non-ultrawork keywords in subagent session`, {
|
|
|
|
|
sessionID: input.sessionID,
|
|
|
|
|
parentID: sessionInfo.data?.parentID,
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
log(`[keyword-detector] Failed to get session info, proceeding with all keywords`, {
|
|
|
|
|
error: err,
|
|
|
|
|
sessionID: input.sessionID,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-01 20:58:02 +09:00
|
|
|
const hasUltrawork = detectedKeywords.some((k) => k.type === "ultrawork")
|
2026-01-05 02:46:01 +09:00
|
|
|
if (hasUltrawork) {
|
2026-01-01 20:58:02 +09:00
|
|
|
log(`[keyword-detector] Ultrawork mode activated`, { sessionID: input.sessionID })
|
|
|
|
|
|
2026-01-05 14:52:08 +09:00
|
|
|
output.message.variant = "max"
|
|
|
|
|
|
2026-01-04 18:12:48 +09:00
|
|
|
ctx.client.tui
|
|
|
|
|
.showToast({
|
|
|
|
|
body: {
|
|
|
|
|
title: "Ultrawork Mode Activated",
|
|
|
|
|
message: "Maximum precision engaged. All agents at your disposal.",
|
|
|
|
|
variant: "success" as const,
|
|
|
|
|
duration: 3000,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
.catch((err) =>
|
|
|
|
|
log(`[keyword-detector] Failed to show toast`, { error: err, sessionID: input.sessionID })
|
|
|
|
|
)
|
2025-12-23 14:25:49 +09:00
|
|
|
}
|
|
|
|
|
|
2026-01-05 02:37:01 +09:00
|
|
|
log(`[keyword-detector] Detected ${detectedKeywords.length} keywords`, {
|
2026-01-04 18:12:48 +09:00
|
|
|
sessionID: input.sessionID,
|
2026-01-05 02:37:01 +09:00
|
|
|
types: detectedKeywords.map((k) => k.type),
|
2025-12-14 11:38:33 +09:00
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|