fix(hooks): remove dead delegate-task-english-directive hook
This commit is contained in:
@@ -92,8 +92,7 @@
|
||||
"write-existing-file-guard",
|
||||
"anthropic-effort",
|
||||
"hashline-read-enhancer",
|
||||
"read-image-resizer",
|
||||
"delegate-task-english-directive"
|
||||
"read-image-resizer"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -92,8 +92,7 @@
|
||||
"write-existing-file-guard",
|
||||
"anthropic-effort",
|
||||
"hashline-read-enhancer",
|
||||
"read-image-resizer",
|
||||
"delegate-task-english-directive"
|
||||
"read-image-resizer"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/// <reference types="bun-types" />
|
||||
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import {
|
||||
AgentOverrideConfigSchema,
|
||||
@@ -405,6 +407,17 @@ describe("HookNameSchema", () => {
|
||||
//#then
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
|
||||
test("rejects removed delegate-task-english-directive hook name", () => {
|
||||
//#given
|
||||
const input = "delegate-task-english-directive"
|
||||
|
||||
//#when
|
||||
const result = HookNameSchema.safeParse(input)
|
||||
|
||||
//#then
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Sisyphus-Junior agent override", () => {
|
||||
|
||||
@@ -51,7 +51,6 @@ export const HookNameSchema = z.enum([
|
||||
"anthropic-effort",
|
||||
"hashline-read-enhancer",
|
||||
"read-image-resizer",
|
||||
"delegate-task-english-directive",
|
||||
])
|
||||
|
||||
export type HookName = z.infer<typeof HookNameSchema>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
export const TARGET_SUBAGENT_TYPES = ["explore", "librarian", "oracle", "plan"] as const
|
||||
|
||||
export const ENGLISH_DIRECTIVE =
|
||||
"**YOU MUST ALWAYS THINK, REASON, AND RESPOND IN ENGLISH REGARDLESS OF THE USER'S QUERY LANGUAGE.**"
|
||||
|
||||
export function createDelegateTaskEnglishDirectiveHook() {
|
||||
return {
|
||||
"tool.execute.before": async (
|
||||
input: { tool: string; sessionID: string; callID: string; input: Record<string, unknown> },
|
||||
_output: { title: string; output: string; metadata: unknown }
|
||||
) => {
|
||||
if (input.tool.toLowerCase() !== "task") return
|
||||
|
||||
const args = input.input
|
||||
const subagentType = args.subagent_type
|
||||
if (typeof subagentType !== "string") return
|
||||
if (!TARGET_SUBAGENT_TYPES.includes(subagentType as (typeof TARGET_SUBAGENT_TYPES)[number])) return
|
||||
|
||||
if (typeof args.prompt === "string") {
|
||||
args.prompt = `${args.prompt}\n\n${ENGLISH_DIRECTIVE}`
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
|
||||
import { createDelegateTaskEnglishDirectiveHook, ENGLISH_DIRECTIVE, TARGET_SUBAGENT_TYPES } from "./index"
|
||||
|
||||
describe("delegate-task-english-directive", () => {
|
||||
const hook = createDelegateTaskEnglishDirectiveHook()
|
||||
const handler = hook["tool.execute.before"]
|
||||
|
||||
describe("#given a task tool call with a targeted subagent_type", () => {
|
||||
const targetTypes = ["explore", "librarian", "oracle", "plan"]
|
||||
|
||||
for (const subagentType of targetTypes) {
|
||||
describe(`#when subagent_type is "${subagentType}"`, () => {
|
||||
it(`#then should append English directive to prompt`, async () => {
|
||||
const originalPrompt = "Find auth patterns in the codebase"
|
||||
const input = { tool: "Task", sessionID: "ses_123", callID: "call_1", input: { subagent_type: subagentType, prompt: originalPrompt } }
|
||||
const output = { title: "", output: "", metadata: undefined }
|
||||
|
||||
await handler(input, output)
|
||||
|
||||
expect(input.input.prompt).toBe(`${originalPrompt}\n\n${ENGLISH_DIRECTIVE}`)
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe("#given a task tool call with a non-targeted subagent_type", () => {
|
||||
describe("#when subagent_type is 'metis'", () => {
|
||||
it("#then should not modify the prompt", async () => {
|
||||
const originalPrompt = "Analyze this request"
|
||||
const input = { tool: "Task", sessionID: "ses_123", callID: "call_1", input: { subagent_type: "metis", prompt: originalPrompt } }
|
||||
const output = { title: "", output: "", metadata: undefined }
|
||||
|
||||
await handler(input, output)
|
||||
|
||||
expect(input.input.prompt).toBe(originalPrompt)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given a task tool call using category instead of subagent_type", () => {
|
||||
describe("#when only category is provided", () => {
|
||||
it("#then should not modify the prompt", async () => {
|
||||
const originalPrompt = "Fix the button styling"
|
||||
const input = { tool: "Task", sessionID: "ses_123", callID: "call_1", input: { category: "visual-engineering", prompt: originalPrompt } }
|
||||
const output = { title: "", output: "", metadata: undefined }
|
||||
|
||||
await handler(input, output)
|
||||
|
||||
expect(input.input.prompt).toBe(originalPrompt)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given a non-task tool call", () => {
|
||||
describe("#when tool is 'Bash'", () => {
|
||||
it("#then should not modify anything", async () => {
|
||||
const input = { tool: "Bash", sessionID: "ses_123", callID: "call_1", input: { command: "ls" } }
|
||||
const output = { title: "", output: "", metadata: undefined }
|
||||
|
||||
await handler(input, output)
|
||||
|
||||
expect(input.input).toEqual({ command: "ls" })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given a task tool call with empty prompt", () => {
|
||||
describe("#when prompt is empty string", () => {
|
||||
it("#then should still append directive", async () => {
|
||||
const input = { tool: "Task", sessionID: "ses_123", callID: "call_1", input: { subagent_type: "explore", prompt: "" } }
|
||||
const output = { title: "", output: "", metadata: undefined }
|
||||
|
||||
await handler(input, output)
|
||||
|
||||
expect(input.input.prompt).toBe(`\n\n${ENGLISH_DIRECTIVE}`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given TARGET_SUBAGENT_TYPES constant", () => {
|
||||
it("#then should contain exactly explore, librarian, oracle, and plan", () => {
|
||||
expect(TARGET_SUBAGENT_TYPES).toEqual(["explore", "librarian", "oracle", "plan"])
|
||||
})
|
||||
})
|
||||
|
||||
describe("#given ENGLISH_DIRECTIVE constant", () => {
|
||||
it("#then should be bold uppercase text", () => {
|
||||
expect(ENGLISH_DIRECTIVE).toContain("**")
|
||||
expect(ENGLISH_DIRECTIVE).toMatch(/[A-Z]/)
|
||||
})
|
||||
|
||||
it("#then should instruct English-only thinking and responding", () => {
|
||||
const lower = ENGLISH_DIRECTIVE.toLowerCase()
|
||||
expect(lower).toContain("english")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1 +0,0 @@
|
||||
export { createDelegateTaskEnglishDirectiveHook, TARGET_SUBAGENT_TYPES, ENGLISH_DIRECTIVE } from "./hook"
|
||||
@@ -52,4 +52,3 @@ export { createWriteExistingFileGuardHook } from "./write-existing-file-guard";
|
||||
export { createHashlineReadEnhancerHook } from "./hashline-read-enhancer";
|
||||
export { createJsonErrorRecoveryHook, JSON_ERROR_TOOL_EXCLUDE_LIST, JSON_ERROR_PATTERNS, JSON_ERROR_REMINDER } from "./json-error-recovery";
|
||||
export { createReadImageResizerHook } from "./read-image-resizer"
|
||||
export { createDelegateTaskEnglishDirectiveHook } from "./delegate-task-english-directive"
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
createRalphLoopHook,
|
||||
createEditErrorRecoveryHook,
|
||||
createDelegateTaskRetryHook,
|
||||
createDelegateTaskEnglishDirectiveHook,
|
||||
createTaskResumeInfoHook,
|
||||
createStartWorkHook,
|
||||
createPrometheusMdOnlyHook,
|
||||
@@ -61,7 +60,6 @@ export type SessionHooks = {
|
||||
taskResumeInfo: ReturnType<typeof createTaskResumeInfoHook> | null
|
||||
anthropicEffort: ReturnType<typeof createAnthropicEffortHook> | null
|
||||
runtimeFallback: ReturnType<typeof createRuntimeFallbackHook> | null
|
||||
delegateTaskEnglishDirective: ReturnType<typeof createDelegateTaskEnglishDirectiveHook> | null
|
||||
}
|
||||
|
||||
export function createSessionHooks(args: {
|
||||
@@ -217,10 +215,6 @@ export function createSessionHooks(args: {
|
||||
? safeHook("delegate-task-retry", () => createDelegateTaskRetryHook(ctx))
|
||||
: null
|
||||
|
||||
const delegateTaskEnglishDirective = isHookEnabled("delegate-task-english-directive")
|
||||
? safeHook("delegate-task-english-directive", () => createDelegateTaskEnglishDirectiveHook())
|
||||
: null
|
||||
|
||||
const startWork = isHookEnabled("start-work")
|
||||
? safeHook("start-work", () => createStartWorkHook(ctx))
|
||||
: null
|
||||
@@ -282,7 +276,6 @@ export function createSessionHooks(args: {
|
||||
ralphLoop,
|
||||
editErrorRecovery,
|
||||
delegateTaskRetry,
|
||||
delegateTaskEnglishDirective,
|
||||
startWork,
|
||||
prometheusMdOnly,
|
||||
sisyphusJuniorNotepad,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/// <reference types="bun-types" />
|
||||
|
||||
import { describe, test, expect, afterEach } from "bun:test"
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
@@ -400,6 +402,17 @@ describe("migrateConfigFile", () => {
|
||||
expect(rawConfig.disabled_hooks).not.toContain("anthropic-auto-compact")
|
||||
})
|
||||
|
||||
test("removes deleted hook names from disabled_hooks", () => {
|
||||
const rawConfig: Record<string, unknown> = {
|
||||
disabled_hooks: ["delegate-task-english-directive", "comment-checker"],
|
||||
}
|
||||
|
||||
const needsWrite = migrateConfigFile(testConfigPath, rawConfig)
|
||||
|
||||
expect(needsWrite).toBe(true)
|
||||
expect(rawConfig.disabled_hooks).toEqual(["comment-checker"])
|
||||
})
|
||||
|
||||
test("does not write if no migration needed", () => {
|
||||
// given: Config with current names
|
||||
const rawConfig: Record<string, unknown> = {
|
||||
|
||||
@@ -9,6 +9,7 @@ export const HOOK_NAME_MAP: Record<string, string | null> = {
|
||||
|
||||
// Removed hooks (v3.0.0) - will be filtered out and user warned
|
||||
"empty-message-sanitizer": null,
|
||||
"delegate-task-english-directive": null,
|
||||
}
|
||||
|
||||
export function migrateHookNames(
|
||||
|
||||
Reference in New Issue
Block a user