fix(team-mode): gate status injection by keyword
This commit is contained in:
@@ -3,7 +3,7 @@ import { describe, expect, it } from "bun:test"
|
||||
import { TeamModeConfigSchema } from "../../config/schema/team-mode"
|
||||
import { createTeamModeStatusInjector } from "./hook"
|
||||
|
||||
function createOutput(sessionID: string): {
|
||||
function createOutput(sessionID: string, text = "original message"): {
|
||||
messages: Array<{
|
||||
info: { role: string; sessionID: string }
|
||||
parts: Array<{ type: string; text?: string; synthetic?: boolean }>
|
||||
@@ -16,7 +16,7 @@ function createOutput(sessionID: string): {
|
||||
role: "user",
|
||||
sessionID,
|
||||
},
|
||||
parts: [{ type: "text", text: "original message" }],
|
||||
parts: [{ type: "text", text }],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -26,7 +26,7 @@ describe("createTeamModeStatusInjector", () => {
|
||||
it("injects a one-time team mode enabled message before the latest user message", async () => {
|
||||
// given
|
||||
const hook = createTeamModeStatusInjector(TeamModeConfigSchema.parse({ enabled: true }))
|
||||
const output = createOutput("session-team-mode")
|
||||
const output = createOutput("session-team-mode", "team mode please")
|
||||
|
||||
// when
|
||||
await hook["experimental.chat.messages.transform"]?.(
|
||||
@@ -49,14 +49,14 @@ describe("createTeamModeStatusInjector", () => {
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(output.messages[1]?.parts[0]?.text).toBe("original message")
|
||||
expect(output.messages[1]?.parts[0]?.text).toBe("team mode please")
|
||||
})
|
||||
|
||||
it("does not inject again when the team mode status was already added", async () => {
|
||||
// given
|
||||
const hook = createTeamModeStatusInjector(TeamModeConfigSchema.parse({ enabled: true }))
|
||||
const firstOutput = createOutput("session-team-mode")
|
||||
const secondOutput = createOutput("session-team-mode")
|
||||
const firstOutput = createOutput("session-team-mode", "team mode please")
|
||||
const secondOutput = createOutput("session-team-mode", "team mode please")
|
||||
|
||||
// when
|
||||
await hook["experimental.chat.messages.transform"]?.(
|
||||
@@ -94,4 +94,39 @@ describe("createTeamModeStatusInjector", () => {
|
||||
expect(output.messages).toHaveLength(1)
|
||||
expect(output.messages[0]?.parts[0]?.text).toBe("original message")
|
||||
})
|
||||
|
||||
it("does not inject team mode status for punctuation-only prompts", async () => {
|
||||
// given
|
||||
const hook = createTeamModeStatusInjector(TeamModeConfigSchema.parse({ enabled: true }))
|
||||
const output = createOutput("session-team-mode", ".")
|
||||
|
||||
// when
|
||||
await hook["experimental.chat.messages.transform"]?.(
|
||||
{ sessionID: "session-team-mode" },
|
||||
output,
|
||||
)
|
||||
|
||||
// then
|
||||
expect(output.messages).toHaveLength(1)
|
||||
expect(output.messages[0]?.parts[0]?.text).toBe(".")
|
||||
})
|
||||
|
||||
it("does not inject team mode status when the team keyword is disabled", async () => {
|
||||
// given
|
||||
const hook = createTeamModeStatusInjector(
|
||||
TeamModeConfigSchema.parse({ enabled: true }),
|
||||
{ disabled_keywords: ["team"] },
|
||||
)
|
||||
const output = createOutput("session-team-mode", "team mode please")
|
||||
|
||||
// when
|
||||
await hook["experimental.chat.messages.transform"]?.(
|
||||
{ sessionID: "session-team-mode" },
|
||||
output,
|
||||
)
|
||||
|
||||
// then
|
||||
expect(output.messages).toHaveLength(1)
|
||||
expect(output.messages[0]?.parts[0]?.text).toBe("team mode please")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { TeamModeConfig } from "../../config/schema/team-mode"
|
||||
import type { KeywordDetectorConfig } from "../../config/schema/keyword-detector"
|
||||
import { detectKeywordsWithType, extractPromptText } from "../keyword-detector/detector"
|
||||
|
||||
type TransformPart = {
|
||||
type: string
|
||||
@@ -72,6 +74,25 @@ function hasInjectedTeamModeStatus(messages: MessageWithParts[]): boolean {
|
||||
)
|
||||
}
|
||||
|
||||
function latestUserMessageRequestsTeamMode(
|
||||
messages: MessageWithParts[],
|
||||
userMessageIndex: number,
|
||||
keywordDetectorConfig?: KeywordDetectorConfig,
|
||||
): boolean {
|
||||
const message = messages[userMessageIndex]
|
||||
if (message === undefined) {
|
||||
return false
|
||||
}
|
||||
|
||||
const promptText = extractPromptText(message.parts)
|
||||
return detectKeywordsWithType(
|
||||
promptText,
|
||||
undefined,
|
||||
undefined,
|
||||
keywordDetectorConfig?.disabled_keywords,
|
||||
).some((keyword) => keyword.type === "team")
|
||||
}
|
||||
|
||||
function buildTeamModeStatusContent(): string {
|
||||
return `${TEAM_MODE_STATUS_MARKER}
|
||||
Team mode is ENABLED for this session.
|
||||
@@ -93,6 +114,7 @@ function createInjectedMessage(sessionID: string): MessageWithParts {
|
||||
|
||||
export function createTeamModeStatusInjector(
|
||||
config: TeamModeConfig,
|
||||
keywordDetectorConfig?: KeywordDetectorConfig,
|
||||
): TeamModeStatusInjectorHook {
|
||||
return {
|
||||
"experimental.chat.messages.transform": async (
|
||||
@@ -113,13 +135,12 @@ export function createTeamModeStatusInjector(
|
||||
}
|
||||
|
||||
const lastUserMessageIndex = findLastUserMessageIndex(output.messages)
|
||||
const injectedMessage = createInjectedMessage(sessionID)
|
||||
|
||||
if (lastUserMessageIndex === -1) {
|
||||
output.messages.unshift(injectedMessage)
|
||||
if (!latestUserMessageRequestsTeamMode(output.messages, lastUserMessageIndex, keywordDetectorConfig)) {
|
||||
return
|
||||
}
|
||||
|
||||
const injectedMessage = createInjectedMessage(sessionID)
|
||||
|
||||
output.messages.splice(lastUserMessageIndex, 0, injectedMessage)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ export function createTransformHooks(args: {
|
||||
const teamModeStatusInjector = teamModeConfig?.enabled
|
||||
? safeCreateHook(
|
||||
"team-mode-status-injector",
|
||||
() => createTeamModeStatusInjector(teamModeConfig),
|
||||
() => createTeamModeStatusInjector(teamModeConfig, pluginConfig.keyword_detector),
|
||||
{ enabled: safeHookEnabled },
|
||||
)
|
||||
: null
|
||||
|
||||
Reference in New Issue
Block a user