refactor: standardize naming conventions across agents, tools, and hooks
- Rename agent "OpenCode-Builder" to "opencode-builder" (kebab-case) - Rename tool "slashcommand" to "slash_command" (snake_case) - Add "Hook" suffix to 3 factory functions: - createCompactionContextInjector → createCompactionContextInjectorHook - createSessionNotification → createSessionNotificationHook - createTodoContinuationEnforcer → createTodoContinuationEnforcerHook - Rename createCommentCheckerHooks → createCommentCheckerHook (singular) BREAKING CHANGE: Config files using "OpenCode-Builder" must update to "opencode-builder". BREAKING CHANGE: Agent prompts referencing "slashcommand" must update to "slash_command".
This commit is contained in:
@@ -781,7 +781,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"OpenCode-Builder": {
|
"opencode-builder": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"model": {
|
"model": {
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ Configure git-master skill behavior:
|
|||||||
When enabled (default), Sisyphus provides a powerful orchestrator with optional specialized agents:
|
When enabled (default), Sisyphus provides a powerful orchestrator with optional specialized agents:
|
||||||
|
|
||||||
- **Sisyphus**: Primary orchestrator agent (Claude Opus 4.5)
|
- **Sisyphus**: Primary orchestrator agent (Claude Opus 4.5)
|
||||||
- **OpenCode-Builder**: OpenCode's default build agent, renamed due to SDK limitations (disabled by default)
|
- **opencode-builder**: OpenCode's default build agent, renamed due to SDK limitations (disabled by default)
|
||||||
- **Prometheus (Planner)**: OpenCode's default plan agent with work-planner methodology (enabled by default)
|
- **Prometheus (Planner)**: OpenCode's default plan agent with work-planner methodology (enabled by default)
|
||||||
- **Metis (Plan Consultant)**: Pre-planning analysis agent that identifies hidden requirements and AI failure points
|
- **Metis (Plan Consultant)**: Pre-planning analysis agent that identifies hidden requirements and AI failure points
|
||||||
|
|
||||||
@@ -627,7 +627,7 @@ When enabled (default), Sisyphus provides a powerful orchestrator with optional
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example: Enable OpenCode-Builder:**
|
**Example: Enable opencode-builder:**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -637,7 +637,7 @@ When enabled (default), Sisyphus provides a powerful orchestrator with optional
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This enables OpenCode-Builder agent alongside Sisyphus. The default build agent is always demoted to subagent mode when Sisyphus is enabled.
|
This enables opencode-builder agent alongside Sisyphus. The default build agent is always demoted to subagent mode when Sisyphus is enabled.
|
||||||
|
|
||||||
**Example: Disable all Sisyphus orchestration:**
|
**Example: Disable all Sisyphus orchestration:**
|
||||||
|
|
||||||
@@ -658,7 +658,7 @@ You can also customize Sisyphus agents like other agents:
|
|||||||
"model": "anthropic/claude-sonnet-4",
|
"model": "anthropic/claude-sonnet-4",
|
||||||
"temperature": 0.3
|
"temperature": 0.3
|
||||||
},
|
},
|
||||||
"OpenCode-Builder": {
|
"opencode-builder": {
|
||||||
"model": "anthropic/claude-opus-4"
|
"model": "anthropic/claude-opus-4"
|
||||||
},
|
},
|
||||||
"Prometheus (Planner)": {
|
"Prometheus (Planner)": {
|
||||||
@@ -674,7 +674,7 @@ You can also customize Sisyphus agents like other agents:
|
|||||||
| Option | Default | Description |
|
| Option | Default | Description |
|
||||||
| ------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `disabled` | `false` | When `true`, disables all Sisyphus orchestration and restores original build/plan as primary. |
|
| `disabled` | `false` | When `true`, disables all Sisyphus orchestration and restores original build/plan as primary. |
|
||||||
| `default_builder_enabled` | `false` | When `true`, enables OpenCode-Builder agent (same as OpenCode build, renamed due to SDK limitations). Disabled by default. |
|
| `default_builder_enabled` | `false` | When `true`, enables opencode-builder agent (same as OpenCode build, renamed due to SDK limitations). Disabled by default. |
|
||||||
| `planner_enabled` | `true` | When `true`, enables Prometheus (Planner) agent with work-planner methodology. Enabled by default. |
|
| `planner_enabled` | `true` | When `true`, enables Prometheus (Planner) agent with work-planner methodology. Enabled by default. |
|
||||||
| `replace_plan` | `true` | When `true`, demotes default plan agent to subagent mode. Set to `false` to keep both Prometheus (Planner) and default plan available. |
|
| `replace_plan` | `true` | When `true`, demotes default plan agent to subagent mode. Set to `false` to keep both Prometheus (Planner) and default plan available. |
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export function categorizeTools(toolNames: string[]): AvailableTool[] {
|
|||||||
category = "search"
|
category = "search"
|
||||||
} else if (name.startsWith("session_")) {
|
} else if (name.startsWith("session_")) {
|
||||||
category = "session"
|
category = "session"
|
||||||
} else if (name === "slashcommand") {
|
} else if (name === "slash_command") {
|
||||||
category = "command"
|
category = "command"
|
||||||
}
|
}
|
||||||
return { name, category }
|
return { name, category }
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const OverridableAgentNameSchema = z.enum([
|
|||||||
"plan",
|
"plan",
|
||||||
"sisyphus",
|
"sisyphus",
|
||||||
"sisyphus-junior",
|
"sisyphus-junior",
|
||||||
"OpenCode-Builder",
|
"opencode-builder",
|
||||||
"prometheus",
|
"prometheus",
|
||||||
"metis",
|
"metis",
|
||||||
"momus",
|
"momus",
|
||||||
@@ -136,7 +136,7 @@ export const AgentOverridesSchema = z.object({
|
|||||||
plan: AgentOverrideConfigSchema.optional(),
|
plan: AgentOverrideConfigSchema.optional(),
|
||||||
sisyphus: AgentOverrideConfigSchema.optional(),
|
sisyphus: AgentOverrideConfigSchema.optional(),
|
||||||
"sisyphus-junior": AgentOverrideConfigSchema.optional(),
|
"sisyphus-junior": AgentOverrideConfigSchema.optional(),
|
||||||
"OpenCode-Builder": AgentOverrideConfigSchema.optional(),
|
"opencode-builder": AgentOverrideConfigSchema.optional(),
|
||||||
prometheus: AgentOverrideConfigSchema.optional(),
|
prometheus: AgentOverrideConfigSchema.optional(),
|
||||||
metis: AgentOverrideConfigSchema.optional(),
|
metis: AgentOverrideConfigSchema.optional(),
|
||||||
momus: AgentOverrideConfigSchema.optional(),
|
momus: AgentOverrideConfigSchema.optional(),
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ export async function executeSlashCommand(parsed: ParsedSlashCommand, options?:
|
|||||||
if (!command) {
|
if (!command) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: `Command "/${parsed.command}" not found. Use the slashcommand tool to list available commands.`,
|
error: `Command "/${parsed.command}" not found. Use the slash_command tool to list available commands.`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ function cleanupOldPendingCalls(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCommentCheckerHooks(config?: CommentCheckerConfig) {
|
export function createCommentCheckerHook(config?: CommentCheckerConfig) {
|
||||||
debugLog("createCommentCheckerHooks called", { config })
|
debugLog("createCommentCheckerHook called", { config })
|
||||||
|
|
||||||
if (!cleanupIntervalStarted) {
|
if (!cleanupIntervalStarted) {
|
||||||
cleanupIntervalStarted = true
|
cleanupIntervalStarted = true
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ mock.module("../../shared/system-directive", () => ({
|
|||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
import { createCompactionContextInjector } from "./index"
|
import { createCompactionContextInjectorHook } from "./index"
|
||||||
import type { SummarizeContext } from "./index"
|
import type { SummarizeContext } from "./index"
|
||||||
|
|
||||||
describe("createCompactionContextInjector", () => {
|
describe("createCompactionContextInjector", () => {
|
||||||
@@ -35,7 +35,7 @@ describe("createCompactionContextInjector", () => {
|
|||||||
describe("Agent Verification State preservation", () => {
|
describe("Agent Verification State preservation", () => {
|
||||||
it("includes Agent Verification State section in compaction prompt", async () => {
|
it("includes Agent Verification State section in compaction prompt", async () => {
|
||||||
// given
|
// given
|
||||||
const injector = createCompactionContextInjector()
|
const injector = createCompactionContextInjectorHook()
|
||||||
const context: SummarizeContext = {
|
const context: SummarizeContext = {
|
||||||
sessionID: "test-session",
|
sessionID: "test-session",
|
||||||
providerID: "anthropic",
|
providerID: "anthropic",
|
||||||
@@ -58,7 +58,7 @@ describe("createCompactionContextInjector", () => {
|
|||||||
|
|
||||||
it("includes Momus-specific context for reviewer agents", async () => {
|
it("includes Momus-specific context for reviewer agents", async () => {
|
||||||
// given
|
// given
|
||||||
const injector = createCompactionContextInjector()
|
const injector = createCompactionContextInjectorHook()
|
||||||
const context: SummarizeContext = {
|
const context: SummarizeContext = {
|
||||||
sessionID: "test-session",
|
sessionID: "test-session",
|
||||||
providerID: "anthropic",
|
providerID: "anthropic",
|
||||||
@@ -80,7 +80,7 @@ describe("createCompactionContextInjector", () => {
|
|||||||
|
|
||||||
it("preserves file verification progress in compaction prompt", async () => {
|
it("preserves file verification progress in compaction prompt", async () => {
|
||||||
// given
|
// given
|
||||||
const injector = createCompactionContextInjector()
|
const injector = createCompactionContextInjectorHook()
|
||||||
const context: SummarizeContext = {
|
const context: SummarizeContext = {
|
||||||
sessionID: "test-session",
|
sessionID: "test-session",
|
||||||
providerID: "anthropic",
|
providerID: "anthropic",
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ This section is CRITICAL for reviewer agents (momus, oracle) to maintain continu
|
|||||||
This context is critical for maintaining continuity after compaction.
|
This context is critical for maintaining continuity after compaction.
|
||||||
`
|
`
|
||||||
|
|
||||||
export function createCompactionContextInjector() {
|
export function createCompactionContextInjectorHook() {
|
||||||
return async (ctx: SummarizeContext): Promise<void> => {
|
return async (ctx: SummarizeContext): Promise<void> => {
|
||||||
log("[compaction-context-injector] injecting context", { sessionID: ctx.sessionID })
|
log("[compaction-context-injector] injecting context", { sessionID: ctx.sessionID })
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
export { createTodoContinuationEnforcer, type TodoContinuationEnforcer } from "./todo-continuation-enforcer";
|
export { createTodoContinuationEnforcerHook as createTodoContinuationEnforcer, type TodoContinuationEnforcer } from "./todo-continuation-enforcer";
|
||||||
export { createContextWindowMonitorHook } from "./context-window-monitor";
|
export { createContextWindowMonitorHook } from "./context-window-monitor";
|
||||||
export { createSessionNotification } from "./session-notification";
|
export { createSessionNotificationHook as createSessionNotification } from "./session-notification";
|
||||||
export { createSessionRecoveryHook, type SessionRecoveryHook, type SessionRecoveryOptions } from "./session-recovery";
|
export { createSessionRecoveryHook, type SessionRecoveryHook, type SessionRecoveryOptions } from "./session-recovery";
|
||||||
export { createCommentCheckerHooks } from "./comment-checker";
|
export { createCommentCheckerHook as createCommentCheckerHooks } from "./comment-checker";
|
||||||
export { createToolOutputTruncatorHook } from "./tool-output-truncator";
|
export { createToolOutputTruncatorHook } from "./tool-output-truncator";
|
||||||
export { createDirectoryAgentsInjectorHook } from "./directory-agents-injector";
|
export { createDirectoryAgentsInjectorHook } from "./directory-agents-injector";
|
||||||
export { createDirectoryReadmeInjectorHook } from "./directory-readme-injector";
|
export { createDirectoryReadmeInjectorHook } from "./directory-readme-injector";
|
||||||
export { createEmptyTaskResponseDetectorHook } from "./empty-task-response-detector";
|
export { createEmptyTaskResponseDetectorHook } from "./empty-task-response-detector";
|
||||||
export { createAnthropicContextWindowLimitRecoveryHook, type AnthropicContextWindowLimitRecoveryOptions } from "./anthropic-context-window-limit-recovery";
|
export { createAnthropicContextWindowLimitRecoveryHook, type AnthropicContextWindowLimitRecoveryOptions } from "./anthropic-context-window-limit-recovery";
|
||||||
|
|
||||||
export { createCompactionContextInjector } from "./compaction-context-injector";
|
export { createCompactionContextInjectorHook as createCompactionContextInjector } from "./compaction-context-injector";
|
||||||
export { createThinkModeHook } from "./think-mode";
|
export { createThinkModeHook } from "./think-mode";
|
||||||
export { createClaudeCodeHooksHook } from "./claude-code-hooks";
|
export { createClaudeCodeHooksHook } from "./claude-code-hooks";
|
||||||
export { createRulesInjectorHook } from "./rules-injector";
|
export { createRulesInjectorHook } from "./rules-injector";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, test, beforeEach, afterEach, spyOn } from "bun:test"
|
import { describe, expect, test, beforeEach, afterEach, spyOn } from "bun:test"
|
||||||
|
|
||||||
import { createSessionNotification } from "./session-notification"
|
import { createSessionNotificationHook } from "./session-notification"
|
||||||
import { setMainSession, subagentSessions, _resetForTesting } from "../features/claude-code-session-state"
|
import { setMainSession, subagentSessions, _resetForTesting } from "../features/claude-code-session-state"
|
||||||
import * as utils from "./session-notification-utils"
|
import * as utils from "./session-notification-utils"
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ describe("session-notification", () => {
|
|||||||
const subagentSessionID = "subagent-123"
|
const subagentSessionID = "subagent-123"
|
||||||
subagentSessions.add(subagentSessionID)
|
subagentSessions.add(subagentSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 0,
|
idleConfirmationDelay: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ describe("session-notification", () => {
|
|||||||
const otherSessionID = "other-456"
|
const otherSessionID = "other-456"
|
||||||
setMainSession(mainSessionID)
|
setMainSession(mainSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 0,
|
idleConfirmationDelay: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ describe("session-notification", () => {
|
|||||||
const mainSessionID = "main-789"
|
const mainSessionID = "main-789"
|
||||||
setMainSession(mainSessionID)
|
setMainSession(mainSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 10,
|
idleConfirmationDelay: 10,
|
||||||
skipIfIncompleteTodos: false,
|
skipIfIncompleteTodos: false,
|
||||||
})
|
})
|
||||||
@@ -129,7 +129,7 @@ describe("session-notification", () => {
|
|||||||
setMainSession(mainSessionID)
|
setMainSession(mainSessionID)
|
||||||
subagentSessions.add(subagentSessionID)
|
subagentSessions.add(subagentSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 0,
|
idleConfirmationDelay: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ describe("session-notification", () => {
|
|||||||
setMainSession(mainSessionID)
|
setMainSession(mainSessionID)
|
||||||
subagentSessions.add(subagentSessionID)
|
subagentSessions.add(subagentSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 0,
|
idleConfirmationDelay: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ describe("session-notification", () => {
|
|||||||
const mainSessionID = "main-cancel"
|
const mainSessionID = "main-cancel"
|
||||||
setMainSession(mainSessionID)
|
setMainSession(mainSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 100, // Long delay
|
idleConfirmationDelay: 100, // Long delay
|
||||||
skipIfIncompleteTodos: false,
|
skipIfIncompleteTodos: false,
|
||||||
})
|
})
|
||||||
@@ -218,7 +218,7 @@ describe("session-notification", () => {
|
|||||||
|
|
||||||
test("should handle session.created event without notification", async () => {
|
test("should handle session.created event without notification", async () => {
|
||||||
// #given - a new session is created
|
// #given - a new session is created
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {})
|
const hook = createSessionNotificationHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session.created event fires
|
// #when - session.created event fires
|
||||||
await hook({
|
await hook({
|
||||||
@@ -239,7 +239,7 @@ describe("session-notification", () => {
|
|||||||
|
|
||||||
test("should handle session.deleted event and cleanup state", async () => {
|
test("should handle session.deleted event and cleanup state", async () => {
|
||||||
// #given - a session exists
|
// #given - a session exists
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {})
|
const hook = createSessionNotificationHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session.deleted event fires
|
// #when - session.deleted event fires
|
||||||
await hook({
|
await hook({
|
||||||
@@ -263,7 +263,7 @@ describe("session-notification", () => {
|
|||||||
const mainSessionID = "main-message"
|
const mainSessionID = "main-message"
|
||||||
setMainSession(mainSessionID)
|
setMainSession(mainSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 50,
|
idleConfirmationDelay: 50,
|
||||||
skipIfIncompleteTodos: false,
|
skipIfIncompleteTodos: false,
|
||||||
})
|
})
|
||||||
@@ -297,7 +297,7 @@ describe("session-notification", () => {
|
|||||||
const mainSessionID = "main-tool"
|
const mainSessionID = "main-tool"
|
||||||
setMainSession(mainSessionID)
|
setMainSession(mainSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 50,
|
idleConfirmationDelay: 50,
|
||||||
skipIfIncompleteTodos: false,
|
skipIfIncompleteTodos: false,
|
||||||
})
|
})
|
||||||
@@ -329,7 +329,7 @@ describe("session-notification", () => {
|
|||||||
const mainSessionID = "main-dup"
|
const mainSessionID = "main-dup"
|
||||||
setMainSession(mainSessionID)
|
setMainSession(mainSessionID)
|
||||||
|
|
||||||
const hook = createSessionNotification(createMockPluginInput(), {
|
const hook = createSessionNotificationHook(createMockPluginInput(), {
|
||||||
idleConfirmationDelay: 10,
|
idleConfirmationDelay: 10,
|
||||||
skipIfIncompleteTodos: false,
|
skipIfIncompleteTodos: false,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ async function hasIncompleteTodos(ctx: PluginInput, sessionID: string): Promise<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSessionNotification(
|
export function createSessionNotificationHook(
|
||||||
ctx: PluginInput,
|
ctx: PluginInput,
|
||||||
config: SessionNotificationConfig = {}
|
config: SessionNotificationConfig = {}
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
|||||||
|
|
||||||
import type { BackgroundManager } from "../features/background-agent"
|
import type { BackgroundManager } from "../features/background-agent"
|
||||||
import { setMainSession, subagentSessions, _resetForTesting } from "../features/claude-code-session-state"
|
import { setMainSession, subagentSessions, _resetForTesting } from "../features/claude-code-session-state"
|
||||||
import { createTodoContinuationEnforcer } from "./todo-continuation-enforcer"
|
import { createTodoContinuationEnforcerHook } from "./todo-continuation-enforcer"
|
||||||
|
|
||||||
type TimerCallback = (...args: any[]) => void
|
type TimerCallback = (...args: any[]) => void
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-123"
|
const sessionID = "main-123"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {
|
||||||
backgroundManager: createMockBackgroundManager(false),
|
backgroundManager: createMockBackgroundManager(false),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ id: "1", content: "Task 1", status: "completed", priority: "high" },
|
{ id: "1", content: "Task 1", status: "completed", priority: "high" },
|
||||||
]})
|
]})
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(mockInput, {})
|
const hook = createTodoContinuationEnforcerHook(mockInput, {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -239,7 +239,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-789"
|
const sessionID = "main-789"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {
|
||||||
backgroundManager: createMockBackgroundManager(true),
|
backgroundManager: createMockBackgroundManager(true),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
setMainSession("main-session")
|
setMainSession("main-session")
|
||||||
const otherSession = "other-session"
|
const otherSession = "other-session"
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - non-main session goes idle
|
// #when - non-main session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -278,7 +278,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const bgTaskSession = "bg-task-session"
|
const bgTaskSession = "bg-task-session"
|
||||||
subagentSessions.add(bgTaskSession)
|
subagentSessions.add(bgTaskSession)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - background task session goes idle
|
// #when - background task session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -298,7 +298,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-cancel"
|
const sessionID = "main-cancel"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -324,7 +324,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-grace"
|
const sessionID = "main-grace"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -350,7 +350,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-assistant"
|
const sessionID = "main-assistant"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -377,7 +377,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-tool"
|
const sessionID = "main-tool"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -401,7 +401,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-recovery"
|
const sessionID = "main-recovery"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - mark as recovering
|
// #when - mark as recovering
|
||||||
hook.markRecovering(sessionID)
|
hook.markRecovering(sessionID)
|
||||||
@@ -422,7 +422,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-recovery-done"
|
const sessionID = "main-recovery-done"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - mark as recovering then complete
|
// #when - mark as recovering then complete
|
||||||
hook.markRecovering(sessionID)
|
hook.markRecovering(sessionID)
|
||||||
@@ -444,7 +444,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-delete"
|
const sessionID = "main-delete"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -469,7 +469,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
// #when - create hook with skipAgents option (should not throw)
|
// #when - create hook with skipAgents option (should not throw)
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {
|
||||||
skipAgents: ["Prometheus (Planner)", "custom-agent"],
|
skipAgents: ["Prometheus (Planner)", "custom-agent"],
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -487,7 +487,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-toast"
|
const sessionID = "main-toast"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -505,7 +505,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-no-throttle"
|
const sessionID = "main-no-throttle"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - first idle cycle completes
|
// #when - first idle cycle completes
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -537,7 +537,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-noabort-error"
|
const sessionID = "main-noabort-error"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - non-abort error occurs (e.g., network error, API error)
|
// #when - non-abort error occurs (e.g., network error, API error)
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -581,7 +581,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant", error: { name: "MessageAbortedError", data: { message: "The operation was aborted" } } } },
|
{ info: { id: "msg-2", role: "assistant", error: { name: "MessageAbortedError", data: { message: "The operation was aborted" } } } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -604,7 +604,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant" } },
|
{ info: { id: "msg-2", role: "assistant" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -627,7 +627,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "user" } },
|
{ info: { id: "msg-2", role: "user" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -650,7 +650,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant", error: { name: "AbortError" } } },
|
{ info: { id: "msg-2", role: "assistant", error: { name: "AbortError" } } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -672,7 +672,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant" } },
|
{ info: { id: "msg-2", role: "assistant" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - abort error event fires
|
// #when - abort error event fires
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -702,7 +702,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant" } },
|
{ info: { id: "msg-2", role: "assistant" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - AbortError event fires
|
// #when - AbortError event fires
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -732,7 +732,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant" } },
|
{ info: { id: "msg-2", role: "assistant" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - abort error fires
|
// #when - abort error fires
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -764,7 +764,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant" } },
|
{ info: { id: "msg-2", role: "assistant" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - abort error fires
|
// #when - abort error fires
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -803,7 +803,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant" } },
|
{ info: { id: "msg-2", role: "assistant" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - abort error fires
|
// #when - abort error fires
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -841,7 +841,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant" } },
|
{ info: { id: "msg-2", role: "assistant" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - abort error fires
|
// #when - abort error fires
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -879,7 +879,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant" } },
|
{ info: { id: "msg-2", role: "assistant" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - abort error event fires (but API doesn't have it yet)
|
// #when - abort error event fires (but API doesn't have it yet)
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -909,7 +909,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
{ info: { id: "msg-2", role: "assistant", error: { name: "MessageAbortedError" } } },
|
{ info: { id: "msg-2", role: "assistant", error: { name: "MessageAbortedError" } } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {})
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {})
|
||||||
|
|
||||||
// #when - session goes idle without prior session.error event
|
// #when - session goes idle without prior session.error event
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -927,7 +927,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
const sessionID = "main-model-preserve"
|
const sessionID = "main-model-preserve"
|
||||||
setMainSession(sessionID)
|
setMainSession(sessionID)
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(createMockPluginInput(), {
|
const hook = createTodoContinuationEnforcerHook(createMockPluginInput(), {
|
||||||
backgroundManager: createMockBackgroundManager(false),
|
backgroundManager: createMockBackgroundManager(false),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -977,7 +977,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
directory: "/tmp/test",
|
directory: "/tmp/test",
|
||||||
} as any
|
} as any
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(mockInput, {
|
const hook = createTodoContinuationEnforcerHook(mockInput, {
|
||||||
backgroundManager: createMockBackgroundManager(false),
|
backgroundManager: createMockBackgroundManager(false),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1029,7 +1029,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
directory: "/tmp/test",
|
directory: "/tmp/test",
|
||||||
} as any
|
} as any
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(mockInput, {
|
const hook = createTodoContinuationEnforcerHook(mockInput, {
|
||||||
backgroundManager: createMockBackgroundManager(false),
|
backgroundManager: createMockBackgroundManager(false),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1073,7 +1073,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
directory: "/tmp/test",
|
directory: "/tmp/test",
|
||||||
} as any
|
} as any
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(mockInput, {})
|
const hook = createTodoContinuationEnforcerHook(mockInput, {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -1119,7 +1119,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
directory: "/tmp/test",
|
directory: "/tmp/test",
|
||||||
} as any
|
} as any
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(mockInput, {})
|
const hook = createTodoContinuationEnforcerHook(mockInput, {})
|
||||||
|
|
||||||
// #when - session goes idle
|
// #when - session goes idle
|
||||||
await hook.handler({
|
await hook.handler({
|
||||||
@@ -1164,7 +1164,7 @@ describe("todo-continuation-enforcer", () => {
|
|||||||
directory: "/tmp/test",
|
directory: "/tmp/test",
|
||||||
} as any
|
} as any
|
||||||
|
|
||||||
const hook = createTodoContinuationEnforcer(mockInput, {
|
const hook = createTodoContinuationEnforcerHook(mockInput, {
|
||||||
skipAgents: [],
|
skipAgents: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ function isLastAssistantMessageAborted(messages: Array<{ info?: MessageInfo }>):
|
|||||||
return errorName === "MessageAbortedError" || errorName === "AbortError"
|
return errorName === "MessageAbortedError" || errorName === "AbortError"
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTodoContinuationEnforcer(
|
export function createTodoContinuationEnforcerHook(
|
||||||
ctx: PluginInput,
|
ctx: PluginInput,
|
||||||
options: TodoContinuationEnforcerOptions = {}
|
options: TodoContinuationEnforcerOptions = {}
|
||||||
): TodoContinuationEnforcer {
|
): TodoContinuationEnforcer {
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const commands = discoverCommandsSync();
|
const commands = discoverCommandsSync();
|
||||||
const slashcommandTool = createSlashcommandTool({
|
const slash_commandTool = createSlashcommandTool({
|
||||||
commands,
|
commands,
|
||||||
skills: mergedSkills,
|
skills: mergedSkills,
|
||||||
});
|
});
|
||||||
@@ -391,7 +391,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
|||||||
delegate_task: delegateTask,
|
delegate_task: delegateTask,
|
||||||
skill: skillTool,
|
skill: skillTool,
|
||||||
skill_mcp: skillMcpTool,
|
skill_mcp: skillMcpTool,
|
||||||
slashcommand: slashcommandTool,
|
slash_command: slash_commandTool,
|
||||||
interactive_bash,
|
interactive_bash,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -622,7 +622,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ralphLoop && input.tool === "slashcommand") {
|
if (ralphLoop && input.tool === "slash_command") {
|
||||||
const args = output.args as { command?: string } | undefined;
|
const args = output.args as { command?: string } | undefined;
|
||||||
const command = args?.command?.replace(/^\//, "").toLowerCase();
|
const command = args?.command?.replace(/^\//, "").toLowerCase();
|
||||||
const sessionID = input.sessionID || getMainSessionID();
|
const sessionID = input.sessionID || getMainSessionID();
|
||||||
|
|||||||
@@ -208,13 +208,13 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
|
|||||||
buildConfigWithoutName as Record<string, unknown>
|
buildConfigWithoutName as Record<string, unknown>
|
||||||
);
|
);
|
||||||
const openCodeBuilderOverride =
|
const openCodeBuilderOverride =
|
||||||
pluginConfig.agents?.["OpenCode-Builder"];
|
pluginConfig.agents?.["opencode-builder"];
|
||||||
const openCodeBuilderBase = {
|
const openCodeBuilderBase = {
|
||||||
...migratedBuildConfig,
|
...migratedBuildConfig,
|
||||||
description: `${configAgent?.build?.description ?? "Build agent"} (OpenCode default)`,
|
description: `${configAgent?.build?.description ?? "Build agent"} (OpenCode default)`,
|
||||||
};
|
};
|
||||||
|
|
||||||
agentConfig["OpenCode-Builder"] = openCodeBuilderOverride
|
agentConfig["opencode-builder"] = openCodeBuilderOverride
|
||||||
? { ...openCodeBuilderBase, ...openCodeBuilderOverride }
|
? { ...openCodeBuilderBase, ...openCodeBuilderOverride }
|
||||||
: openCodeBuilderBase;
|
: openCodeBuilderBase;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export * from "./types"
|
export * from "./types"
|
||||||
export { slashcommand, createSlashcommandTool, discoverCommandsSync } from "./tools"
|
export { slash_command, createSlashcommandTool, discoverCommandsSync } from "./tools"
|
||||||
|
|||||||
@@ -269,4 +269,4 @@ export function createSlashcommandTool(options: SlashcommandToolOptions = {}): T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default instance for backward compatibility (lazy loading)
|
// Default instance for backward compatibility (lazy loading)
|
||||||
export const slashcommand: ToolDefinition = createSlashcommandTool()
|
export const slash_command: ToolDefinition = createSlashcommandTool()
|
||||||
|
|||||||
Reference in New Issue
Block a user