- होम
- Documentation
- कॉन्फ़िगरेशन
- हुक्स
हुक्स
यह दस्तावेज़ src/extensibility/hooks/* में वर्तमान हुक सबसिस्टम कोड का वर्णन करता है।
रनटाइम में वर्तमान स्थिति
Section titled “रनटाइम में वर्तमान स्थिति”हुक पैकेज (src/extensibility/hooks/) अभी भी एक API सतह के रूप में निर्यातित और उपयोग योग्य है, लेकिन डिफ़ॉल्ट CLI रनटाइम अब एक्सटेंशन रनर पथ को प्रारंभ करता है। वर्तमान स्टार्टअप प्रवाह में:
--hookको--extensionके लिए एक उपनाम के रूप में माना जाता है (CLI पथadditionalExtensionPathsमें मर्ज किए जाते हैं)- उपकरण
HookToolWrapperसे नहीं, बल्किExtensionToolWrapperद्वारा लपेटे जाते हैं - संदर्भ रूपांतरण और जीवनचक्र उत्सर्जन
ExtensionRunnerके माध्यम से होते हैं
अतः यह फ़ाइल हुक सबसिस्टम कार्यान्वयन (types/loader/runner/wrapper) का दस्तावेज़ीकरण करती है, जिसमें लीगेसी व्यवहार और बाधाएं शामिल हैं।
मुख्य फ़ाइलें
Section titled “मुख्य फ़ाइलें”src/extensibility/hooks/types.ts— हुक संदर्भ, इवेंट प्रकार, और परिणाम अनुबंधsrc/extensibility/hooks/loader.ts— मॉड्यूल लोडिंग और हुक डिस्कवरी ब्रिजsrc/extensibility/hooks/runner.ts— इवेंट डिस्पैच, कमांड लुकअप, एरर सिग्नलिंगsrc/extensibility/hooks/tool-wrapper.ts— प्री/पोस्ट टूल इंटरसेप्शन रैपरsrc/extensibility/hooks/index.ts— निर्यात/पुनः-निर्यात
हुक मॉड्यूल क्या होता है
Section titled “हुक मॉड्यूल क्या होता है”एक हुक मॉड्यूल को एक फ़ैक्टरी डिफ़ॉल्ट-एक्सपोर्ट करनी होती है:
import type { HookAPI } from "@f5-sales-demo/xcsh/hooks";
export default function hook(pi: HookAPI): void { pi.on("tool_call", async (event, ctx) => { if (event.toolName === "bash" && String(event.input.command ?? "").includes("rm -rf")) { return { block: true, reason: "blocked by policy" }; } });}फ़ैक्टरी यह कर सकती है:
pi.on(...)के साथ इवेंट हैंडलर पंजीकृत करनाpi.sendMessage(...)से स्थायी कस्टम संदेश भेजनाpi.appendEntry(...)से गैर-LLM स्थिति बनाए रखनाpi.registerCommand(...)के माध्यम से स्लैश कमांड पंजीकृत करनाpi.registerMessageRenderer(...)के माध्यम से कस्टम संदेश रेंडरर पंजीकृत करनाpi.exec(...)के माध्यम से शेल कमांड चलाना
डिस्कवरी और लोडिंग
Section titled “डिस्कवरी और लोडिंग”discoverAndLoadHooks(configuredPaths, cwd) निम्नलिखित करता है:
- क्षमता रजिस्ट्री से खोजे गए हुक लोड करता है (
loadCapability("hooks")) - स्पष्ट रूप से कॉन्फ़िगर किए गए पथ जोड़ता है (पूर्ण पथ द्वारा डीडुप्ड)
loadHooks(allPaths, cwd)को कॉल करता है
loadHooks फिर प्रत्येक पथ को आयात करता है और एक default फ़ंक्शन की अपेक्षा करता है।
पथ समाधान
Section titled “पथ समाधान”loader.ts हुक पथों को इस प्रकार हल करता है:
- पूर्ण पथ: जैसा है वैसा उपयोग किया जाता है
~पथ: विस्तारित किया जाता है- सापेक्ष पथ:
cwdके सापेक्ष हल किया जाता है
महत्वपूर्ण लीगेसी बेमेल
Section titled “महत्वपूर्ण लीगेसी बेमेल”hookCapability के लिए डिस्कवरी प्रोवाइडर अभी भी प्री/पोस्ट शेल-स्टाइल हुक फ़ाइलों को मॉडल करते हैं (उदाहरण के लिए .claude/hooks/pre/*, .xcsh/.../hooks/pre/*)।
यहाँ हुक लोडर डायनामिक मॉड्यूल इम्पोर्ट का उपयोग करता है और एक डिफ़ॉल्ट JS/TS हुक फ़ैक्टरी की आवश्यकता होती है। यदि कोई खोजा गया हुक पथ मॉड्यूल के रूप में आयात योग्य नहीं है, तो लोड विफल हो जाता है और LoadHooksResult.errors में रिपोर्ट किया जाता है।
इवेंट सतहें
Section titled “इवेंट सतहें”हुक इवेंट types.ts में दृढ़ता से टाइप किए गए हैं।
सत्र इवेंट
Section titled “सत्र इवेंट”session_startsession_before_switch→{ cancel?: boolean }लौटा सकता हैsession_switchsession_before_branch→{ cancel?: boolean; skipConversationRestore?: boolean }लौटा सकता हैsession_branchsession_before_compact→{ cancel?: boolean; compaction?: CompactionResult }लौटा सकता हैsession.compacting→{ context?: string[]; prompt?: string; preserveData?: Record<string, unknown> }लौटा सकता हैsession_compactsession_before_tree→{ cancel?: boolean; summary?: { summary: string; details?: unknown } }लौटा सकता हैsession_treesession_shutdown
एजेंट/संदर्भ इवेंट
Section titled “एजेंट/संदर्भ इवेंट”context→{ messages?: Message[] }लौटा सकता हैbefore_agent_start→{ message?: { customType; content; display; details } }लौटा सकता हैagent_startagent_endturn_startturn_endauto_compaction_startauto_compaction_endauto_retry_startauto_retry_endttsr_triggeredtodo_reminder
टूल इवेंट (प्री/पोस्ट मॉडल)
Section titled “टूल इवेंट (प्री/पोस्ट मॉडल)”tool_call(पूर्व-निष्पादन) →{ block?: boolean; reason?: string }लौटा सकता हैtool_result(पश्च-निष्पादन) →{ content?; details?; isError? }लौटा सकता है
यह हुक सबसिस्टम का मूल प्री/पोस्ट इंटरसेप्शन मॉडल है।
Hook tool interception flow
tool_call handlers │ ├─ any { block: true }? ── yes ──> throw (tool blocked) │ └─ no │ ▼ execute underlying tool │ ├─ success ──> tool_result handlers can override { content, details } │ └─ error ──> emit tool_result(isError=true) then rethrow original errorनिष्पादन मॉडल और म्यूटेशन सिमेंटिक्स
Section titled “निष्पादन मॉडल और म्यूटेशन सिमेंटिक्स”1) पूर्व-निष्पादन: tool_call
Section titled “1) पूर्व-निष्पादन: tool_call”HookToolWrapper.execute() टूल निष्पादन से पहले tool_call उत्सर्जित करता है।
- यदि कोई भी हैंडलर
{ block: true }लौटाता है, तो निष्पादन रुक जाता है - यदि हैंडलर थ्रो करता है, तो रैपर विफल हो जाता है और निष्पादन को ब्लॉक करता है
- लौटाया गया
reasonथ्रो किए गए एरर टेक्स्ट बन जाता है
2) टूल निष्पादन
Section titled “2) टूल निष्पादन”यदि ब्लॉक नहीं किया गया है तो अंतर्निहित टूल सामान्य रूप से निष्पादित होता है।
3) पश्च-निष्पादन: tool_result
Section titled “3) पश्च-निष्पादन: tool_result”सफलता के बाद, रैपर tool_result उत्सर्जित करता है:
toolName,toolCallId,inputcontentdetailsisError: false
यदि हैंडलर ओवरराइड लौटाता है:
contentपरिणाम सामग्री को प्रतिस्थापित कर सकता हैdetailsपरिणाम विवरण को प्रतिस्थापित कर सकता है
टूल विफलता पर, रैपर isError: true और एरर टेक्स्ट सामग्री के साथ tool_result उत्सर्जित करता है, फिर मूल एरर को पुनः थ्रो करता है।
हुक क्या म्यूटेट कर सकते हैं
Section titled “हुक क्या म्यूटेट कर सकते हैं”contextके माध्यम से एकल कॉल के लिए LLM संदर्भ (messagesप्रतिस्थापन श्रृंखला)- सफल टूल कॉल पर टूल आउटपुट content/details (
tool_resultपथ) before_agent_startके माध्यम से प्री-एजेंट इंजेक्टेड संदेशsession_before_*औरsession.compactingके माध्यम से रद्दीकरण/कस्टम कॉम्पैक्शन/ट्री व्यवहार
इस कार्यान्वयन में हुक क्या म्यूटेट नहीं कर सकते
Section titled “इस कार्यान्वयन में हुक क्या म्यूटेट नहीं कर सकते”- कच्चे टूल इनपुट पैरामीटर इन-प्लेस (केवल
tool_callपर ब्लॉक/अनुमति) - थ्रो किए गए टूल एरर के बाद निष्पादन जारी रखना (एरर पथ पुनः थ्रो करता है)
- रैपर व्यवहार में अंतिम सफलता/एरर स्थिति (लौटाया गया
isErrorटाइप किया गया है लेकिनHookToolWrapperद्वारा लागू नहीं किया जाता)
क्रम और टकराव व्यवहार
Section titled “क्रम और टकराव व्यवहार”डिस्कवरी-स्तर क्रम
Section titled “डिस्कवरी-स्तर क्रम”क्षमता प्रोवाइडर प्राथमिकता-क्रमबद्ध होते हैं (पहले उच्च)। डीडुप्लीकेशन क्षमता कुंजी द्वारा होती है, पहले वाला जीतता है।
hooks के लिए, क्षमता कुंजी ${type}:${tool}:${name} है। निम्न-प्राथमिकता प्रोवाइडरों से छाया किए गए डुप्लीकेट चिह्नित किए जाते हैं और प्रभावी खोजी गई सूची से बाहर किए जाते हैं।
लोड क्रम
Section titled “लोड क्रम”discoverAndLoadHooks एक फ्लैट allPaths सूची बनाता है, हल किए गए पूर्ण पथ द्वारा डीडुप्ड, फिर loadHooks उस क्रम में पुनरावृत्त करता है।
प्रत्येक खोजी गई डायरेक्टरी के भीतर फ़ाइल क्रम readdir आउटपुट पर निर्भर करता है; हुक लोडर अतिरिक्त सॉर्टिंग नहीं करता।
रनटाइम हैंडलर क्रम
Section titled “रनटाइम हैंडलर क्रम”HookRunner के अंदर, क्रम पंजीकरण अनुक्रम द्वारा निर्धारक होता है:
- हुक्स सरणी क्रम
- हुक/इवेंट प्रति हैंडलर पंजीकरण क्रम
इवेंट प्रकार के अनुसार टकराव व्यवहार:
tool_call: अंतिम लौटाया गया परिणाम जीतता है जब तक कोई हैंडलर ब्लॉक न करे; पहला ब्लॉक शॉर्ट-सर्किट करता हैtool_result: अंतिम लौटाया गया ओवरराइड जीतता है (कोई शॉर्ट-सर्किट नहीं)context: श्रृंखलाबद्ध; प्रत्येक हैंडलर पूर्व हैंडलर का संदेश आउटपुट प्राप्त करता हैbefore_agent_start: पहला लौटाया गया संदेश रखा जाता है; बाद के संदेश अनदेखे किए जाते हैंsession_before_*: नवीनतम लौटाया गया परिणाम ट्रैक किया जाता है;cancel: trueतुरंत शॉर्ट-सर्किट करता हैsession.compacting: नवीनतम लौटाया गया परिणाम जीतता है
कमांड/रेंडरर टकराव:
getCommand(name)हुक्स में पहला मेल लौटाता है (पहले लोड किया गया जीतता है)getMessageRenderer(customType)पहला मेल लौटाता हैgetRegisteredCommands()सभी कमांड लौटाता है (कोई डीडुप्लीकेशन नहीं)
UI इंटरेक्शन (HookContext.ui)
Section titled “UI इंटरेक्शन (HookContext.ui)”HookUIContext में शामिल हैं:
select,confirm,input,editornotifysetStatuscustomsetEditorText,getEditorTextthemeगेटर
ctx.hasUI इंगित करता है कि इंटरैक्टिव UI उपलब्ध है या नहीं।
बिना UI के चलाते समय, डिफ़ॉल्ट नो-ऑप संदर्भ व्यवहार है:
select/input/editorundefinedलौटाते हैंconfirmfalseलौटाता हैnotify,setStatus,setEditorTextनो-ऑप हैंgetEditorText""लौटाता है
स्टेटस लाइन व्यवहार
Section titled “स्टेटस लाइन व्यवहार”ctx.ui.setStatus(key, text) के माध्यम से सेट किया गया हुक स्टेटस टेक्स्ट:
- प्रति कुंजी संग्रहीत होता है
- कुंजी नाम द्वारा क्रमबद्ध होता है
- सैनिटाइज़ किया जाता है (
\r,\n,\t→ स्पेस; बार-बार आने वाले स्पेस संकुचित होते हैं) - प्रदर्शन के लिए जोड़ा और चौड़ाई-छंटनी किया जाता है
एरर प्रसार और फ़ॉलबैक
Section titled “एरर प्रसार और फ़ॉलबैक”लोड-समय
Section titled “लोड-समय”- अमान्य मॉड्यूल या गुम डिफ़ॉल्ट एक्सपोर्ट →
LoadHooksResult.errorsमें कैप्चर किया जाता है - अन्य हुक्स के लिए लोडिंग जारी रहती है
इवेंट-समय
Section titled “इवेंट-समय”HookRunner.emit(...) अधिकांश इवेंट के लिए हैंडलर एरर को पकड़ता है और श्रोताओं को HookError (hookPath, event, error) उत्सर्जित करता है, फिर जारी रहता है।
emitToolCall(...) अधिक सख्त है: हैंडलर एरर वहाँ निगले नहीं जाते; वे कॉलर तक प्रसारित होते हैं। HookToolWrapper में, यह टूल कॉल को ब्लॉक करता है (फेल-सेफ)।
वास्तविक API उदाहरण
Section titled “वास्तविक API उदाहरण”असुरक्षित बैश कमांड ब्लॉक करें
Section titled “असुरक्षित बैश कमांड ब्लॉक करें”import type { HookAPI } from "@f5-sales-demo/xcsh/hooks";
export default function (pi: HookAPI): void { pi.on("tool_call", async (event, ctx) => { if (event.toolName !== "bash") return; const cmd = String(event.input.command ?? ""); if (!cmd.includes("rm -rf")) return;
if (!ctx.hasUI) return { block: true, reason: "rm -rf blocked (no UI)" }; const ok = await ctx.ui.confirm("Dangerous command", `Allow: ${cmd}`); if (!ok) return { block: true, reason: "user denied command" }; });}पश्च-निष्पादन पर टूल आउटपुट रिडैक्ट करें
Section titled “पश्च-निष्पादन पर टूल आउटपुट रिडैक्ट करें”import type { HookAPI } from "@f5-sales-demo/xcsh/hooks";
export default function (pi: HookAPI): void { pi.on("tool_result", async event => { if (event.toolName !== "read" || event.isError) return;
const redacted = event.content.map(chunk => { if (chunk.type !== "text") return chunk; return { ...chunk, text: chunk.text.replaceAll(/API_KEY=\S+/g, "API_KEY=[REDACTED]") }; });
return { content: redacted }; });}प्रति LLM कॉल मॉडल संदर्भ संशोधित करें
Section titled “प्रति LLM कॉल मॉडल संदर्भ संशोधित करें”import type { HookAPI } from "@f5-sales-demo/xcsh/hooks";
export default function (pi: HookAPI): void { pi.on("context", async event => { const filtered = event.messages.filter(msg => !(msg.role === "custom" && msg.customType === "debug-only")); return { messages: filtered }; });}कमांड-सेफ संदर्भ विधियों के साथ स्लैश कमांड पंजीकृत करें
Section titled “कमांड-सेफ संदर्भ विधियों के साथ स्लैश कमांड पंजीकृत करें”import type { HookAPI } from "@f5-sales-demo/xcsh/hooks";
export default function (pi: HookAPI): void { pi.registerCommand("handoff", { description: "Create a new session with setup message", handler: async (_args, ctx) => { await ctx.waitForIdle(); await ctx.newSession({ parentSession: ctx.sessionManager.getSessionFile(), setup: async sm => { sm.appendMessage({ role: "user", content: [{ type: "text", text: "Continue from prior session summary." }], timestamp: Date.now(), }); }, }); }, });}निर्यात सतह
Section titled “निर्यात सतह”src/extensibility/hooks/index.ts निर्यात करता है:
- लोडिंग API (
discoverAndLoadHooks,loadHooks) - रनर और रैपर (
HookRunner,HookToolWrapper) - सभी हुक प्रकार
execCommandपुनः-निर्यात
और पैकेज रूट (src/index.ts) लीगेसी संगतता सतह के रूप में हुक प्रकार पुनः-निर्यात करता है।