mirror of
https://github.com/LerianStudio/ring
synced 2026-04-21 13:37:27 +00:00
Move OpenCode runtime plugin and installer into Ring monorepo under platforms/opencode/. The installer reads skills, agents, and commands directly from the Ring monorepo's canonical directories (default/, dev-team/, pm-team/, etc.) — zero asset duplication. What's included: - installer.sh: reads from Ring dirs, applies frontmatter/tool transforms, installs to ~/.config/opencode/ - plugin/: TypeScript runtime (RingUnifiedPlugin) with hooks, lifecycle, loaders - src/: CLI (doctor, config-manager) - prompts/: session-start and context-injection templates - standards/: coding standards (from dev-team/docs/) - ring.jsonc: default config with full 86-skill/35-agent/33-command inventory What's NOT included (intentionally): - assets/ directory: eliminated, content comes from Ring monorepo - scripts/codereview/: eliminated, replaced by mithril - using-ring-opencode skill: uses canonical using-ring instead Transforms applied by installer: - Agent: type→mode, strip version/changelog/output_schema/input_schema - Skill: keep name+description frontmatter, body unchanged - Command: strip argument-hint (unsupported by OpenCode) - All: normalize tool names (Bash→bash, Read→read, etc.) - All: strip Model Requirement sections from agents Replaces: LerianStudio/ring-for-opencode repository Generated-by: Gandalf AI-Model: claude-opus-4
96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
/**
|
|
* Ring Lifecycle Router
|
|
*
|
|
* Routes OpenCode lifecycle events to Ring's plugin handlers.
|
|
* Maps OpenCode events to Ring hook registry.
|
|
*/
|
|
|
|
import type { RingConfig } from "../config/index.js"
|
|
import { cleanupOldState, deleteState, getSessionId } from "../utils/state.js"
|
|
|
|
/**
|
|
* OpenCode event structure.
|
|
*/
|
|
export interface OpenCodeEvent {
|
|
type: string
|
|
properties?: Record<string, unknown>
|
|
}
|
|
|
|
/**
|
|
* Dependencies for lifecycle router.
|
|
*/
|
|
export interface LifecycleRouterDeps {
|
|
projectRoot: string
|
|
ringConfig: RingConfig
|
|
}
|
|
|
|
/**
|
|
* Create the event handler that routes lifecycle events.
|
|
*
|
|
* Event mappings:
|
|
* - session.created -> Reset context state, cleanup old files
|
|
* - session.idle -> Hook execution (via RingUnifiedPlugin)
|
|
* - session.error -> Hook execution (via RingUnifiedPlugin)
|
|
* - todo.updated -> Task completion hook
|
|
* - experimental.session.compacting -> Context injection
|
|
*/
|
|
export function createLifecycleRouter(deps: LifecycleRouterDeps) {
|
|
const { projectRoot, ringConfig } = deps
|
|
const debug = process.env.RING_DEBUG === "true"
|
|
|
|
if (debug) {
|
|
console.debug("[ring] Lifecycle router initialized", {
|
|
disabledAgents: ringConfig.disabled_agents?.length ?? 0,
|
|
disabledSkills: ringConfig.disabled_skills?.length ?? 0,
|
|
})
|
|
}
|
|
|
|
return async (input: { event: OpenCodeEvent }): Promise<void> => {
|
|
const { event } = input
|
|
const eventType = event.type
|
|
|
|
if (debug) {
|
|
console.debug(`[ring] Event: ${eventType}`)
|
|
}
|
|
|
|
// session.created - Initialize session
|
|
if (eventType === "session.created") {
|
|
const props = event.properties as Record<string, unknown> | undefined
|
|
const eventSessionId = (props?.sessionID as string | undefined) ?? getSessionId()
|
|
|
|
// Reset context usage state for new session
|
|
deleteState(projectRoot, "context-usage", eventSessionId)
|
|
// Clean up old state files (> 7 days)
|
|
cleanupOldState(projectRoot, 7)
|
|
|
|
if (debug) {
|
|
console.debug("[ring] Session initialized, state reset")
|
|
}
|
|
return
|
|
}
|
|
|
|
// session.idle / session.error / todo.updated are handled via hook execution
|
|
// in RingUnifiedPlugin (this router only manages state side effects).
|
|
if (
|
|
eventType === "session.idle" ||
|
|
eventType === "session.error" ||
|
|
eventType === "todo.updated"
|
|
) {
|
|
return
|
|
}
|
|
|
|
// Other events - no action needed
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Event type constants for type safety.
|
|
*/
|
|
export const EVENTS = {
|
|
SESSION_CREATED: "session.created",
|
|
SESSION_IDLE: "session.idle",
|
|
SESSION_ERROR: "session.error",
|
|
SESSION_DELETED: "session.deleted",
|
|
TODO_UPDATED: "todo.updated",
|
|
MESSAGE_PART_UPDATED: "message.part.updated",
|
|
} as const
|