@x-otto/hooks 0.0.1-alpha.2 → 0.0.1-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/core/hook-state.ts","../src/hook-spec.ts","../src/hook-registry.ts","../src/core/session/first-message-variant.ts","../src/core/tool-guard/label-truncator.ts","../src/core/tool-guard/output-truncation.ts","../src/core/tool-guard/tool-error-tracker.ts","../src/core/transform/thinking-validator.ts","../src/core/transform/anthropic-effort.ts","../src/core/transform/token-budget.ts","../src/core/quality/comment-checker.ts","../src/core/stream/stream-metrics.ts","../src/core/compaction/compaction-logger.ts","../src/core/edit-files-panel.ts","../src/core/permission/types.ts","../src/core/permission/builtin-policies.ts","../src/core/permission/register-builtin.ts","../src/core/permission/policy-registry.ts","../src/core/permission/audit-log.ts","../src/core/permission/permission-guard.ts","../src/core/permission/baseline-provisioning.ts","../src/core/permission/always-allow.ts","../src/core/permission/command-canonicalize.ts","../src/sandbox-safety.ts","../src/observability/failure-signals.ts","../src/observability/diagnoser.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/hook-spec.ts","../src/core/hook-state.ts","../src/hook-preset.ts","../src/scope.ts","../src/hook-registry.ts","../src/core/session/first-message-variant.ts","../src/core/tool-guard/label-truncator.ts","../src/core/tool-guard/output-truncation.ts","../src/core/tool-guard/tool-error-tracker.ts","../src/core/transform/thinking-validator.ts","../src/core/transform/anthropic-effort.ts","../src/core/transform/token-budget.ts","../src/core/quality/comment-checker.ts","../src/core/stream/stream-metrics.ts","../src/core/compaction/compaction-logger.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,9 +1,4 @@
1
- import{createLogger as e}from"@x-otto/shared";import{normalizeEnv as t}from"@x-otto/env";import{resolve as n}from"node:path";import{realpathSync as r}from"node:fs";const i=[{id:`chat.message.before`,kind:`interceptor`},{id:`chat.message.after`,kind:`interceptor`},{id:`tool.execute.before`,kind:`interceptor`},{id:`tool.execute.after`,kind:`interceptor`},{id:`messages.transform`,kind:`interceptor`},{id:`chat.params`,kind:`interceptor`},{id:`system.prompt.transform`,kind:`interceptor`},{id:`session.created`,kind:`observer`},{id:`session.restored`,kind:`observer`},{id:`session.deleted`,kind:`observer`},{id:`session.idle`,kind:`observer`},{id:`session.error`,kind:`observer`},{id:`stream.start`,kind:`observer`},{id:`stream.end`,kind:`observer`},{id:`compaction.before`,kind:`observer`},{id:`compaction.after`,kind:`observer`},{id:`memory.prune.before`,kind:`interceptor`},{id:`process.spawned`,kind:`observer`},{id:`process.exited`,kind:`observer`},{id:`task.created`,kind:`observer`},{id:`task.started`,kind:`observer`},{id:`task.completed`,kind:`observer`},{id:`task.failed`,kind:`observer`},{id:`task.cancelled`,kind:`observer`},{id:`notification`,kind:`observer`}],a=i.map(e=>e.id),o=new Set(i.filter(e=>e.kind===`interceptor`).map(e=>e.id));function s(){return Object.fromEntries(a.map(e=>[e,[]]))}function c(e){let t={name:e.name,timing:e.timing,priority:e.priority??50,enabled:e.enabled??!0};return o.has(e.timing)?{...t,kind:`interceptor`,handle:e.handle}:{...t,kind:`observer`,handle:e.handle}}function l(e=61440){return c({name:`output-truncation`,timing:`tool.execute.after`,priority:10,handle(t,n){let{content:r}=n.result,i=0;for(let e of r)e.type===`text`&&(i+=e.text.length);if(i<=e)return;let a=e,o=r.map(t=>{if(t.type!==`text`)return t;if(a<=0)return{type:`text`,text:``};if(t.text.length<=a)return a-=t.text.length,t;let n=t.text.slice(0,a);return a=0,{type:`text`,text:`${n}\n\n... [output truncated: ${i} chars → ${e} chars]`}}).filter(e=>e.type!==`text`||e.text.length>0);n.result={...n.result,content:o},n.metadata.truncated=!0,n.metadata.originalSize=i}})}function u(){return c({name:`label-truncator`,timing:`tool.execute.before`,priority:20,handle(e,t){for(let e of[`label`,`description`,`title`]){let n=t.args[e];typeof n==`string`&&n.length>200&&(t.args[e]=`${n.slice(0,200)}...`)}}})}function d(){return c({name:`thinking-validator`,timing:`messages.transform`,priority:20,handle(e,t){t.messages=t.messages.map(e=>{if(!ee(e))return e;let t=e.content;if(!Array.isArray(t))return e;let n=t.filter(e=>!(e.type===`thinking`&&(typeof e.thinking!=`string`||e.thinking.trim()===``)));return{...e,content:n}})}})}function ee(e){return typeof e==`object`&&!!e&&`role`in e&&e.role===`assistant`}function f(){return c({name:`anthropic-effort`,timing:`chat.params`,priority:10,handle(e,t){e.provider===`anthropic`&&(t.thinkingLevel||(e.model.includes(`opus`)?t.thinkingLevel=`high`:e.model.includes(`sonnet`)?t.thinkingLevel=`medium`:e.model.includes(`haiku`)&&(t.thinkingLevel=`low`)))}})}function p(){return c({name:`first-message-variant`,timing:`chat.message.before`,priority:10,handle(e,t){e.isFirstMessage&&(t.metadata.isFirstMessage=!0,t.metadata.variant=`first-message`)}})}const te=[/\/\/\s*TODO:\s*implement/i,/\/\/\s*add\s+(your|the)\s+/i,/\/\/\s*placeholder/i,/\/\/\s*\.\.\.\s*(rest|more|other|remaining)/i,/\/\/\s*handle\s+error\s+here/i,/\/\*\s*\*\//];function m(){return c({name:`comment-checker`,timing:`tool.execute.after`,priority:20,handle(e,t){if(e.readonly)return;let n=re(e.args);if(!n)return;let r=ne(n);if(r.length>0){let e=`\n\n⚠️ AI-style comments detected:\n${r.map(e=>` - Line ${e.line}: "${e.text}"`).join(`
2
- `)}\nPlease replace with meaningful implementation comments.`;t.result={...t.result,content:[...t.result.content,{type:`text`,text:e}]},t.metadata.aiCommentsDetected=r.length}}})}function ne(e){let t=[],n=e.split(`
3
- `);for(let e=0;e<n.length;e++){let r=n[e]??``;for(let n of te)if(n.test(r)){t.push({line:e+1,text:r.trim()});break}}return t}function re(e){return typeof e.content==`string`?e.content:typeof e.newString==`string`?e.newString:typeof e.new_string==`string`?e.new_string:null}const h=e(`@x-otto/hooks:stream-metrics`);function g(e){return c({name:`stream-metrics`,timing:`stream.start`,priority:10,handle(t){let n=e.streamMetrics;n.set(t.sessionId,{startTime:Date.now(),model:t.model,requestCount:(n.get(t.sessionId)?.requestCount??0)+1,lastStopReason:``,totalDurationMs:n.get(t.sessionId)?.totalDurationMs??0}),h.debug(`Stream started: session=%s model=%s`,t.sessionId,t.model)}})}function _(e){return c({name:`stream-end-metrics`,timing:`stream.end`,priority:10,handle(t){let n=e.streamMetrics.get(t.sessionId);if(n){let e=Date.now()-n.startTime;n.totalDurationMs+=e,n.lastStopReason=t.stopReason,h.debug(`Stream ended: session=%s model=%s duration=%dms stopReason=%s total=%dms`,t.sessionId,t.model,e,t.stopReason,n.totalDurationMs)}}})}const v=e(`@x-otto/hooks:compaction`);function y(e){return c({name:`compaction-logger`,timing:`compaction.before`,priority:10,handle(t){let n=e.compactionStats.get(t.sessionId)??{compactionCount:0,totalCompacted:0,lastCompactionTime:0};n.compactionCount++,n.lastCompactionTime=Date.now(),e.compactionStats.set(t.sessionId,n),v.info(`Compaction started: session=%s messageCount=%d compaction#%d`,t.sessionId,t.messageCount,n.compactionCount)}})}function b(e){return c({name:`compaction-after-logger`,timing:`compaction.after`,priority:10,handle(t){let n=e.compactionStats.get(t.sessionId);if(n){let e=Date.now()-n.lastCompactionTime;n.totalCompacted+=t.retainedCount,v.info(`Compaction finished: session=%s retained=%d duration=%dms totalCompactions=%d`,t.sessionId,t.retainedCount,e,n.compactionCount)}}})}const ie=e(`@x-otto/hooks:tool-error-tracker`);function x(e,t){let n=t?.circuitBreakerThreshold??5,r=t?.decayWindowMs??12e4;return c({name:`tool-error-tracker`,timing:`tool.execute.after`,priority:15,handle(t,i){let a=e.toolErrors.get(t.sessionId)??new Map;e.toolErrors.set(t.sessionId,a);let o=a.get(t.toolName);if(o&&Date.now()-o.lastErrorTime>r&&(o=void 0),t.result.isError){if(o||={toolName:t.toolName,errorCount:0,lastErrorTime:0,consecutiveErrors:0},o.errorCount++,o.consecutiveErrors++,o.lastErrorTime=Date.now(),a.set(t.toolName,o),o.consecutiveErrors>=n){let e=`Tool "${t.toolName}" hit circuit-breaker: ${o.consecutiveErrors} consecutive errors`;ie.warn(e),i.metadata.toolCircuitBreaker={toolName:t.toolName,consecutiveErrors:o.consecutiveErrors,tripped:!0}}}else o&&(o.consecutiveErrors=0,a.set(t.toolName,o))}})}const ae=e(`@x-otto/hooks:token-budget`);function S(e){let t=e?.maxOutputTokens??16384;return c({name:`token-budget`,timing:`chat.params`,priority:20,handle(e,n){(!n.maxTokens||n.maxTokens>t)&&(n.maxTokens=t,ae.debug(`Capped maxTokens to %d for model=%s`,t,e.model))}})}var C=class{streamMetrics=new Map;compactionStats=new Map;toolErrors=new Map;clearSession(e){this.streamMetrics.delete(e),this.compactionStats.delete(e),this.toolErrors.delete(e)}};const w=e(`@x-otto/hooks`),oe=new Set([`tool.execute.before`]),T=t(process.env.OTTO_HOOK_TIMEOUT_MS,5e3),se=new Set([`chat.message.before`,`chat.message.after`,`tool.execute.before`,`memory.prune.before`]),ce=new Set([`tool.execute.before`]);var E=class{hooks=s();disabled=new Set;onHookTimeout;state=new C;constructor(e){this.onHookTimeout=e?.onHookTimeout,this.register(c({name:`hook-state-cleanup`,timing:`session.deleted`,priority:90,handle:e=>{this.state.clearSession(e.sessionId)}})),e?.preset&&e.preset!==`none`&&this.applyPreset(e.preset)}register(e){this.hooks[e.timing].push(e),w.debug({hookName:e.name,timing:e.timing,priority:e.priority},`Hook registered`)}registerAll(e){for(let t of e)this.register(t)}on(e,t,n,r=50){return this.register(c({name:t,timing:e,handle:n,priority:r})),this}has(e){return this.getRegistered().some(t=>t.name===e)}unregister(e){let t=!1;for(let n of a){let r=this.hooks[n],i=r.filter(t=>t.name!==e);i.length<r.length&&(this.hooks[n]=i,t=!0,w.debug({hookName:e,timing:n},`Hook unregistered`))}return t}disable(e){this.disabled.add(e),w.debug({hookName:e},`Hook disabled`)}enable(e){this.disabled.delete(e),w.debug({hookName:e},`Hook enabled`)}getRegistered(e){if(e)return this.hooks[e].map(D);let t=[];for(let e of a)t.push(...this.hooks[e].map(D));return t}async execute(e,t,n){let r=this.getSortedInterceptorHooks(e);if(r.length===0)return;let i=!1,a=!1;for(let o of r){let r=await this.runInterceptorWithTimeout(o,e,t,n);if(!r.ok&&oe.has(e)){let e=n;typeof e.cancelled==`boolean`&&(e.cancelled=!0,e.cancelReason=r.timedOut?`hook "${o.name}" timed out after ${T}ms`:`hook "${o.name}" failed: ${r.message}`)}if(se.has(e)){let e=n;e.cancelled===!0&&(i=!0),i&&(e.cancelled=!0)}if(ce.has(e)){let e=n;e.decision===`deny`&&(a=!0),a&&(e.decision=`deny`)}}}async runInterceptorWithTimeout(e,t,n,r){let i;try{return await Promise.race([e.handle(n,r),new Promise((t,n)=>{i=setTimeout(()=>{n(Error(`hook "${e.name}" timed out after ${T}ms`))},T),i.unref?.()})]),{ok:!0}}catch(n){let r=n instanceof Error?n.message:String(n),i=r.includes(`timed out after`);return w.error({name:e.name,timing:t,err:r,timedOut:i},`Hook failed or timed out`),i&&this.onHookTimeout?.({hookName:e.name,timing:t,timeoutMs:T}),{ok:!1,timedOut:i,message:r}}finally{i!==void 0&&clearTimeout(i)}}async runObserverHookWithTimeout(e,t,n){let r;try{await Promise.race([e.handle(n),new Promise((t,n)=>{r=setTimeout(()=>{n(Error(`hook "${e.name}" timed out after ${T}ms`))},T),r.unref?.()})])}catch(n){let r=n instanceof Error?n.message:String(n);w.error({name:e.name,timing:t,err:r},`Hook failed or timed out`)}finally{r!==void 0&&clearTimeout(r)}}sanitizeEmitInput(e,t){if(e!==`session.error`)return t;let n=t;return{sessionId:n.sessionId,metadata:n.metadata,error:n.error instanceof Error?n.error.message:String(n.error)}}async emit(e,t){let n=this.getSortedObserverHooks(e);if(n.length===0)return;let r=this.sanitizeEmitInput(e,t);for(let t of n)await this.runObserverHookWithTimeout(t,e,r)}clear(){for(let e of a)this.hooks[e]=[];this.disabled.clear(),w.debug(`All hooks cleared`)}getSortedInterceptorHooks(e){let t=this.hooks[e];return t?t.filter(e=>e.kind===`interceptor`&&e.enabled&&!this.disabled.has(e.name)).sort((e,t)=>e.priority-t.priority):(w.warn({timing:e},`Unknown hook timing (no bucket) — emit name mismatch with HOOK_NODES?`),[])}getSortedObserverHooks(e){let t=this.hooks[e];return t?t.filter(e=>e.kind===`observer`&&e.enabled&&!this.disabled.has(e.name)).sort((e,t)=>e.priority-t.priority):(w.warn({timing:e},`Unknown hook timing (no bucket) — emit name mismatch with HOOK_NODES?`),[])}applyPreset(e){let t=le(e,this.state);for(let e of t)this.register(e)}};function D(e){return{name:e.name,timing:e.timing,priority:e.priority,enabled:e.enabled}}function le(e,t){switch(e){case`default`:return O(t);case`strict`:return ue(t);case`minimal`:return de();default:return[]}}function O(e){return[l(),u(),d(),f(),p(),g(e),_(e),y(e),b(e),x(e),S()]}function ue(e){return[...O(e),m()]}function de(){return[l()]}function fe(e){return new E(e)}function k(e){return e?(e.endsWith(`
4
- `)?e.slice(0,-1):e).split(`
5
- `).length:0}function pe(e){let{toolCallId:t,args:n}=e,r=typeof n.path==`string`?n.path:void 0;if(!r)return null;let i=typeof n.oldContent==`string`?n.oldContent:void 0,a=typeof n.newContent==`string`?n.newContent:void 0;if(i!==void 0&&a!==void 0){let e=k(i),n=k(a);return{path:r,operation:`edit`,oldContent:i,newContent:a,addedLines:Math.max(0,n-e),removedLines:Math.max(0,e-n),timestamp:Date.now(),toolCallId:t}}let o=typeof n.content==`string`?n.content:void 0;return o===void 0?null:{path:r,operation:`write`,newContent:o,addedLines:k(o),removedLines:0,timestamp:Date.now(),toolCallId:t}}function me(e={}){let{onFileEdited:t,getOnFileEdited:n,dedupCache:r}=e;return c({name:`edit-files-panel`,timing:`tool.execute.after`,priority:90,handle(e){let i=n?.()??t;if(!i||e.readonly)return;let a=pe(e);if(!a)return;let o=a.toolCallId;if(r){if(r.has(o))return;r.add(o)}i(a)}})}const he=[/^\/etc\//,/^\/usr\//,/^\/sys\//,/^\/proc\//,/node_modules\//,/\.git\//,/\.env$/,/\.env\.local$/,/\/\.ssh\//,/\/\.aws\//,/\/\.(bash|zsh)rc$/,/\/\.(bash_profile|zprofile|profile)$/];function ge(e){let t=[],n=``,r=!1,i=!1;for(let a=0;a<e.length;a++){let o=e[a],s=e[a+1];if(r){o===`'`&&(r=!1),n+=o;continue}if(i){o===`"`&&(i=!1),n+=o;continue}if(o===`'`){r=!0,n+=o;continue}if(o===`"`){i=!0,n+=o;continue}if(o===`&`&&s===`&`||o===`|`&&s===`|`){t.push(n),n=``,a++;continue}if(o===`;`||o===`|`||o===`
6
- `||o===`&`){t.push(n),n=``;continue}n+=o}return t.push(n),t.map(e=>e.trim()).filter(Boolean)}function A(e){let t=e.trim();return t.length>=2&&(t[0]===`"`&&t[t.length-1]===`"`||t[0]===`'`&&t[t.length-1]===`'`)?t.slice(1,-1):t}function _e(e){let t=e.match(/^(?:\S*\/)?(?:bash|sh|zsh|dash|ksh|ash|python[0-9.]*|node|nodejs|perl|ruby|php|deno|bun)\b[\s\S]*?\s-[a-z]*[cer]\b\s*([\s\S]+)$/i);return t?A(t[1]):null}function ve(e){let t=e.trim();for(let e=0;e<10;e++){let e=t;if(t=t.replace(/^[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|\S*)\s+/,``),t=t.replace(/^(?:sudo|env|nohup|setsid|ionice)\b(?:\s+-\S+|\s+[A-Za-z_][A-Za-z0-9_]*=\S+)*\s+/i,``),t=t.replace(/^(?:nice|stdbuf)\b(?:\s+-\S+)*\s+/i,``),t=t.replace(/^timeout\b(?:\s+-\S+)*\s+\S+\s+/i,``),t===e)break}return t}function ye(e){let t=[];for(let n=0;n<e.length;n++)if(e[n]===`$`&&e[n+1]===`(`){let r=1,i=n+2,a=i;for(;i<e.length&&r>0;)e[i]===`(`?r++:e[i]===`)`&&r--,i++;r===0&&t.push(e.slice(a,i-1))}let n=e.match(/`([^`]+)`/g);if(n)for(let e of n)t.push(e.slice(1,-1));return t}const be={n:`
7
- `,t:` `,r:`\r`,a:`\x07`,b:`\b`,f:`\f`,v:`\v`,e:`\x1B`,E:`\x1B`,"\\":`\\`,"'":`'`,'"':`"`,"?":`?`};function j(e){return/[0-9a-fA-F]/.test(e)}function xe(e){let t=``,n=0;for(;n<e.length;){if(e[n]!==`\\`){t+=e[n],n++;continue}let r=e[n+1];if(r===void 0){t+=`\\`;break}if(r===`x`){let r=``;for(;r.length<2&&j(e[n+2+r.length]??``);)r+=e[n+2+r.length];if(r){t+=String.fromCharCode(parseInt(r,16)),n+=2+r.length;continue}}if(r===`u`||r===`U`){let i=r===`u`?4:8,a=``;for(;a.length<i&&j(e[n+2+a.length]??``);)a+=e[n+2+a.length];if(a){t+=String.fromCodePoint(parseInt(a,16)),n+=2+a.length;continue}}if(r>=`0`&&r<=`7`){let r=``;for(;r.length<3;){let t=e[n+1+r.length]??``;if(t<`0`||t>`7`)break;r+=t}t+=String.fromCharCode(parseInt(r,8)&255),n+=1+r.length;continue}t+=be[r]??r,n+=2}return t}function Se(e){return e.replace(/\$'((?:\\.|[^'\\])*)'/g,(e,t)=>xe(t))}function Ce(e){return e.replace(/\$\{IFS[^}]*\}/g,` `).replace(/\$IFS\b(?:\$[0-9@*])?/g,` `)}function we(e){return Ce(Se(e))}function M(e){let t=new Set,n=[],r=(e,i)=>{let a=e.trim();if(!a||i>12||t.has(a))return;t.add(a),n.push(a);let o=we(a);o!==a&&r(o,i+1);let s=a.match(/<<<\s*('[^']*'|"[^"]*"|[^\s|;&]+)/)?.[1];s&&r(A(s),i+1);for(let e of ye(a))r(e,i+1);let c=ge(a);if(c.length>1){for(let e of c)r(e,i+1);return}let l=_e(a);l&&r(l,i+1);let u=ve(a);u!==a&&r(u,i+1)};return r(e,0),n}function Te(e){return e.length>=2&&(e[0]===`"`&&e.endsWith(`"`)||e[0]===`'`&&e.endsWith(`'`))?e.slice(1,-1):e}function N(e){let t=[],n=``,r=!1,i=!1;for(let a=0;a<e.length;a++){let o=e[a];if(r){o===`'`?r=!1:n+=o;continue}if(i){o===`"`?i=!1:n+=o;continue}if(o===`'`){r=!0;continue}if(o===`"`){i=!0;continue}if(o===` `||o===` `){n&&=(t.push(n),``);continue}n+=o}return n&&t.push(n),t}const P=/(?:^|[^0-9&>])(?:[0-9]*&?>>?|>\|)\s*('[^']*'|"[^"]*"|[^\s;|&<>]+)/g;function Ee(e){let t=new Set,n=e=>{if(!e)return;let n=Te(e.trim());n&&!n.startsWith(`-`)&&!n.includes(`$`)&&n!==`/dev/null`&&n!==`/dev/stdout`&&n!==`/dev/stderr`&&t.add(n)};for(let t of M(e)){let e;for(P.lastIndex=0;(e=P.exec(t))!==null;)n(e[1]);let r=N(t);if(r.length===0)continue;let i=r[0].replace(/^.*\//,``),a=r.slice(1),o=a.filter(e=>!e.startsWith(`-`));if(i===`tee`)for(let e of o)n(e);else if(i===`cp`||i===`mv`||i===`install`||i===`ln`)o.length>=1&&n(o[o.length-1]);else if(i===`touch`||i===`rm`||i===`rmdir`||i===`mkdir`)for(let e of o)n(e);else if(i===`dd`)for(let e of a)e.startsWith(`of=`)&&n(e.slice(3))}return[...t]}function F(e){return{readonlyTools:new Set(e?.readonlyTools??[]),writeTools:new Set(e?.writeTools??[]),fileWriteTools:new Set(e?.fileWriteTools??[])}}function De(e){let t=new Set,n=new Set,r=new Set;for(let i of e)if(i.name){if(i.readonly===!0){t.add(i.name);continue}if(i.name===`bash`){n.add(i.name);continue}if(i.metadata?.category===`fs`){n.add(i.name),r.add(i.name);continue}i.name.startsWith(`mcp__`)&&n.add(i.name)}return{readonlyTools:t,writeTools:n,fileWriteTools:r}}function I(e){let{fileWriteTools:t}=F(e);return{name:`builtin::file-guard`,priority:10,enabled:!0,safety:!0,scope:{agents:[`*`]},rules:[{name:`protect-system-paths`,effect:`deny`,match:{tools:[...t],paths:he},denyReason:`Write to protected system path is not allowed`}]}}const Oe=/\b(rmdir\b|drop\s+table|git\s+push\s+(?:\S+\s+)*(?:--force\b|-f\b)|git\s+reset\s+--hard|git\s+clean\s+-[a-z]*f|truncate\s+table|dd\s+if=|mkfs\b|>\s*\/dev\/(?:sd|nvme|disk|hd))/i;function ke(e){let t=N(e);return t.length===0||t[0].replace(/^.*\//,``)!==`rm`?!1:t.slice(1).some(e=>e===`--recursive`||e===`--force`?!0:/^-[a-z]*[rf]/i.test(e))}const Ae=/(\beval\s|(?:curl|wget)\b[^|;&]*\|\s*(?:sudo\s+)?(?:ba|z|d)?sh\b|:\s*\(\s*\)\s*\{[^}]*:\s*\|\s*:|base64\s+(?:-d|--decode)\b[^|]*\|)/i,je=/\b(?:python[0-9.]*|pythonw|pypy[0-9]*|node|nodejs|deno|bun|perl|ruby|php|osascript|Rscript|pwsh|powershell(?:\.exe)?)\b[^|;&\n]*?(?:\s-{1,2}(?:c|e|r|E|p|eval|Command|EncodedCommand)\b|\s*<<)/i;function L(e){return e?M(e).some(e=>Oe.test(e)||ke(e)||Ae.test(e)||je.test(e)):!1}function Me(e,t){return e.startsWith(`mcp__`)?Object.values(t).some(e=>typeof e==`string`&&L(e)):!1}const R={name:`builtin::destructive-guard`,priority:15,enabled:!0,safety:!0,scope:{agents:[`*`]},rules:[{name:`ask-destructive-bash`,effect:`ask`,match:{condition:e=>L(String(e.args.command??``))},askPrompt:`This command may be destructive or runs code that cannot be statically checked. Continue?`},{name:`ask-destructive-mcp-args`,effect:`ask`,match:{condition:e=>Me(e.toolName,e.args)},askPrompt:`This MCP tool argument may run a destructive or unverifiable command. Continue?`}]},Ne=[/\/\.ssh(\/|$)/,/\/\.aws(\/|$)/,/\/\.gnupg(\/|$)/,/\/otto\/auth\.json$/],Pe=[/\/\.env(\.[\w.-]+)?$/],z=[/\.ssh(\/|\s|$)/,/\.aws(\/|\s|$)/,/\.gnupg(\/|\s|$)/,/otto\/auth\.json/],Fe=[/\.env(\b|\.[\w-]+)/];function B(e,t){return e?M(e).some(e=>t.some(t=>t.test(e))):!1}function V(e,t,n){if(!e.startsWith(`mcp__`))return!1;for(let e of Object.values(t))if(typeof e==`string`&&B(e,n))return!0;return!1}const H={name:`builtin::credential-guard`,priority:16,enabled:!0,safety:!0,scope:{agents:[`*`]},rules:[{name:`deny-credential-paths`,effect:`deny`,match:{paths:Ne},denyReason:`Reading credential/secret files (~/.ssh, ~/.aws, ~/.gnupg, auth store) is not allowed`},{name:`deny-credential-command`,effect:`deny`,match:{condition:e=>B(String(e.args.command??``),z)},denyReason:`Command references credential/secret paths (~/.ssh, ~/.aws, ~/.gnupg, auth store)`},{name:`ask-dotenv-paths`,effect:`ask`,match:{paths:Pe},askPrompt:`This reads a .env file which may contain secrets. Continue?`},{name:`ask-dotenv-command`,effect:`ask`,match:{condition:e=>B(String(e.args.command??``),Fe)},askPrompt:`This command references a .env file which may contain secrets. Continue?`},{name:`deny-mcp-credential-args`,effect:`deny`,match:{condition:e=>V(e.toolName,e.args,z)},denyReason:`MCP tool argument references credential/secret paths (~/.ssh, ~/.aws, ~/.gnupg, auth store)`},{name:`ask-mcp-dotenv-args`,effect:`ask`,match:{condition:e=>V(e.toolName,e.args,Fe)},askPrompt:`This MCP tool reads a .env file which may contain secrets. Continue?`}]},Ie=[/\.otto\/plugin-trust\.json$/,/\.otto\/claude-trust\.json$/,/\.otto\/config\.json$/,/\.otto\/schedules\//,/\.otto\/plugins\//,/\.otto\/timers\//],Le=[/\.otto\/sessions\//,/\.otto\/.*\.lock$/],Re=[/\.otto\/AGENTS\.md$/,/\.otto\/MEMORY\.md$/,/\.otto\/memory\//,/\.otto\/local\/MEMORY\.md$/,/\.otto\/local\/memory\//,/\.otto\/lessons\.json$/,/\.otto\/local\/lessons\.json$/],ze=[/\.otto\/(plugin-trust|claude-trust|config)\.json/,/\.otto\/(schedules|plugins|timers|sessions)\//,/\.otto\/.*\.lock\b/,/\.otto\/AGENTS\.md/,/\.otto\/(local\/)?MEMORY\.md/,/\.otto\/(local\/)?memory\//,/\.otto\/(local\/)?lessons\.json/];function U(e){let{fileWriteTools:t}=F(e),n=[...t];return{name:`builtin::otto-state-domain-guard`,priority:17,enabled:!0,safety:!0,scope:{agents:[`*`]},rules:[{name:`deny-otto-trust-and-execution-state`,effect:`deny`,match:{tools:n,paths:Ie},denyReason:`Writing to otto trust/config/schedule/plugin state is not allowed via file tools — use the dedicated command (/extension, schedule_create, settings) instead`},{name:`deny-otto-runtime-state`,effect:`deny`,match:{tools:n,paths:Le},denyReason:`otto runtime state (sessions/locks) must not be modified directly`},{name:`deny-otto-memory-state`,effect:`deny`,match:{tools:n,paths:Re},denyReason:`Cross-session memory must be written via the memory_record tool (not edit/write) — use scope: "workspace" | "local" | "project-shared"`},{name:`deny-otto-state-command-reference`,effect:`deny`,match:{condition:e=>B(String(e.args.command??``),ze)},denyReason:`Command references otto trust/config/schedule/plugin/session state — not allowed via bash`}]}}function Be(e){try{return new URL(e).hostname.toLowerCase()}catch{return null}}function Ve(e,t){return t.some(t=>{let n=t.trim().toLowerCase().replace(/^\*?\./,``);return n.length>0&&(e===n||e.endsWith(`.${n}`))})}function He(e){let t=e.map(e=>e.trim().toLowerCase()).filter(Boolean);return{name:`setting::egress-allowlist`,priority:8,enabled:!0,safety:!0,scope:{agents:[`*`]},rules:[{name:`ask-egress-offlist`,effect:`ask`,match:{condition:e=>{let n=e.args.url;if(typeof n!=`string`)return!1;let r=Be(n);return r?!Ve(r,t):!1}},askPrompt:`This requests a host not in the egress allowlist. Continue?`}]}}function Ue(e){return{name:`setting::disabled-tools`,priority:2,enabled:!0,scope:{agents:[`*`]},rules:[{name:`deny-disabled`,effect:`deny`,match:{tools:e},denyReason:`Tool disabled by configuration`}]}}function W(e,t){let{readonlyTools:n,writeTools:r}=F(t);switch(e){case`bypass`:return{name:`mode::bypass`,priority:1,enabled:!0,scope:{agents:[`*`]},rules:[{name:`allow-all`,effect:`allow`,match:{}}]};case`readonly`:return{name:`mode::readonly`,priority:1,enabled:!0,scope:{agents:[`*`]},rules:[{name:`allow-reads`,effect:`allow`,match:{condition:e=>n.has(e.toolName)}},{name:`deny-writes`,effect:`deny`,match:{},fallthrough:!0,denyReason:`Read-only mode: write operations are not allowed`}]};case`confirm`:return{name:`mode::confirm`,priority:1,enabled:!0,scope:{agents:[`*`]},rules:[{name:`allow-reads`,effect:`allow`,match:{condition:e=>n.has(e.toolName)}},{name:`ask-writes`,effect:`ask`,match:{tools:[...r]},askPrompt:`Confirm write operation?`}]};case`strict`:return{name:`mode::strict`,priority:9999,enabled:!0,scope:{agents:[`*`]},rules:[{name:`deny-unmatched`,effect:`deny`,match:{},fallthrough:!0,denyReason:`Strict mode: no matching permission policy`}]};default:return{name:`mode::auto`,priority:1,enabled:!0,scope:{agents:[`*`]},rules:[{name:`allow-reads`,effect:`allow`,match:{condition:e=>n.has(e.toolName)}},{name:`auto-writes`,effect:`allow`,match:{tools:[...r]}}]}}}function We(e,t={}){e.register(W(`auto`,t.toolSets)),e.register(I(t.toolSets)),e.register(R),e.register(H),e.register(U(t.toolSets))}function Ge(e){let t=e.trim(),n=/^([^()\s]+)\((.*)\)$/.exec(t);return n?{toolName:n[1]??t,content:(n[2]??``).trim()}:{toolName:t}}function Ke(e){let t=e.trim();if(!t)return!1;let n=/^([^()\s]+)\((.*)\)$/.exec(t);if(n){let e=(n[1]??``).trim(),t=(n[2]??``).trim();return e.length>0&&t.length>0}return/^[^()\s]+$/.test(t)}function qe(e,t){let n=e.trim(),r=t.trim();return r?n===r||n.startsWith(r+` `):!1}const Je=/^cd\s+\S+$/;function Ye(e,t){let n=t.filter(Boolean);if(n.length===0)return!1;let r=M(e);return r.length===0?!1:r.every(e=>{if(Je.test(e))return!0;let t=e.replace(/^cd\s+\S+\s*&&\s*/,``).trim();return n.some(e=>qe(t,e))})}function Xe(e,t){let n=[];for(let r of t){let t=Ge(r);t.toolName===e.toolName&&n.push(t)}if(n.length===0)return!1;if(n.some(e=>e.content===void 0))return!0;if(e.toolName===`bash`){let t=typeof e.args?.command==`string`?e.args.command:``;return t?Ye(t,n.map(e=>e.content)):!1}return!1}function Ze(e){let t=e.trim().replace(/^cd\s+\S+\s*&&\s*/,``).trim();if(/[;&|]|`|\$\(|<<|\beval\b/.test(t))return null;let n=t.split(/\s+/).filter(Boolean),r=n[0];if(!r||r.includes(`=`))return null;let i=n[1]&&!n[1].startsWith(`-`)?n[1]:null;return i?`${r} ${i}`:r}const G=e(`@x-otto/hooks:permission`);function K(e,t){return!e.agents||e.agents.length===0?!0:e.agents.includes(`*`)||e.agents.includes(t)}function Qe(e,t){return!e.sessions||e.sessions.length===0?!0:e.sessions.includes(`*`)||e.sessions.includes(t)}function $e(e,t){return K(e,t.agentName)&&Qe(e,t.sessionId)}function et(e,t){return!(e.tools&&e.tools.length>0&&!e.tools.includes(t.toolName)||e.paths&&e.paths.length>0&&(!t.filePath||!e.paths.some(e=>e.test(t.filePath)))||e.condition&&!e.condition(t))}const tt={effect:`allow`,policyName:`__default__`,ruleName:`__fallthrough__`,timestamp:0,evaluatedPolicies:0};var q=class{policies=[];alwaysAllow=new Set;sessionAlwaysAllow=new Map;setAlwaysAllow(e){this.alwaysAllow=new Set(e)}addAlwaysAllow(e){this.alwaysAllow.add(e)}getAlwaysAllow(){return[...this.alwaysAllow]}setSessionAlwaysAllow(e,t){if(e){if(t.length===0){this.sessionAlwaysAllow.delete(e);return}this.sessionAlwaysAllow.set(e,new Set(t))}}addSessionAlwaysAllow(e,t){if(!e||!t)return;let n=this.sessionAlwaysAllow.get(e)??new Set;n.add(t),this.sessionAlwaysAllow.set(e,n)}getSessionAlwaysAllow(e){return[...this.sessionAlwaysAllow.get(e)??[]]}clearSessionAlwaysAllow(e){this.sessionAlwaysAllow.delete(e)}register(e){this.unregister(e.name),this.policies.push(e),this.policies.sort((e,t)=>e.priority-t.priority),G.debug({name:e.name,priority:e.priority,rules:e.rules.length},`Permission policy registered`)}registerAll(e){for(let t of e)this.register(t)}unregister(e){let t=this.policies.findIndex(t=>t.name===e);return t>=0?(this.policies.splice(t,1),G.debug({name:e},`Permission policy unregistered`),!0):!1}has(e){return this.policies.some(t=>t.name===e)}evaluate(e){let t=0,n=[];for(let r of this.policies)if(r.enabled&&$e(r.scope,e)){t++;for(let t of r.rules)et(t.match,e)&&n.push({effect:t.effect,policyName:r.name,ruleName:t.name,priority:r.priority,reason:t.effect===`deny`?t.denyReason:t.askPrompt,safety:r.safety===!0,fallthrough:t.fallthrough===!0})}let r=n.some(e=>e.policyName===`mode::auto`||e.policyName===`mode::bypass`),i=(e,n)=>{let r=n.reduce((e,t)=>t.priority<e.priority?t:e);return{effect:e,policyName:r.policyName,ruleName:r.ruleName,reason:r.reason,timestamp:Date.now(),evaluatedPolicies:t,safety:r.safety}},a=n=>{if(n.length===0)return null;let a=n.filter(e=>e.effect===`deny`);if(a.length>0)return i(`deny`,a);let o=n.filter(e=>e.effect===`ask`);if(o.length>0){if(r)return{effect:`allow`,policyName:`mode::auto-override`,ruleName:o[0].ruleName,timestamp:Date.now(),evaluatedPolicies:t};let n=Xe(e,[...this.alwaysAllow,...this.sessionAlwaysAllow.get(e.sessionId)??[]]),a=o.filter(e=>e.safety||!n);return a.length===0?{effect:`allow`,policyName:`user::always-allow`,ruleName:e.toolName,timestamp:Date.now(),evaluatedPolicies:t}:i(`ask`,a)}let s=n.filter(e=>e.effect===`allow`);return s.length>0?i(`allow`,s):null},o=n.filter(e=>!e.fallthrough),s=n.filter(e=>e.fallthrough),c=a(o),l=a(s);return c?.effect===`deny`||c?.effect===`allow`?c:l?.effect===`deny`?l:(c??l)||{...tt,timestamp:Date.now(),evaluatedPolicies:t}}getEffective(e){return this.policies.filter(t=>t.enabled&&K(t.scope,e))}getAll(){return[...this.policies]}clear(){this.policies=[],G.debug(`All permission policies cleared`)}};function J(e={}){let t=new q;return We(t,e),t}const Y=1024,nt=/\([^)]*(?:[*+]|\{\d+,\d*\})[^)]*\)(?:[*+]|\{\d+,\d*\})/;function rt(e,t){if(e.length>Y)return G.warn({rule:t,length:e.length,max:Y},`Permission path pattern exceeds max length — rule skipped (ReDoS guard)`),null;if(nt.test(e))return G.warn({rule:t,pattern:e},`Permission path pattern has nested quantifiers (catastrophic backtracking risk) — rule skipped (ReDoS guard)`),null;try{return new RegExp(e)}catch(n){return G.warn({rule:t,pattern:e,error:n instanceof Error?n.message:String(n)},`Permission path pattern failed to compile — rule skipped`),null}}function it(e){let t=[];for(let n of e.rules){let e;if(n.paths&&n.paths.length>0){let t=[],r=!1;for(let e of n.paths){let i=rt(e,n.name);if(i===null){r=!0;break}t.push(i)}if(r)continue;e=t}t.push({name:n.name,effect:n.effect,match:{tools:n.tools,paths:e},denyReason:n.deny_reason,askPrompt:n.ask_prompt})}return{name:e.name,priority:e.priority??50,enabled:e.enabled??!0,scope:{agents:e.scope?.agents,sessions:e.scope?.sessions},rules:t}}var X=class{entries=[];maxEntries;constructor(e=1e3){this.maxEntries=e}record(e,t){this.entries.push({timestamp:t.timestamp,sessionId:e.sessionId,agentName:e.agentName,toolName:e.toolName,filePath:e.filePath,decision:t}),this.entries.length>this.maxEntries&&this.entries.splice(0,this.entries.length-this.maxEntries)}getEntries(e){let t=this.entries;return e?.sessionId&&(t=t.filter(t=>t.sessionId===e.sessionId)),e?.effect&&(t=t.filter(t=>t.decision.effect===e.effect)),t===this.entries?this.entries.slice():t}getDenyCount(e){return this.getEntries({sessionId:e,effect:`deny`}).length}getAskCount(e){return this.getEntries({sessionId:e,effect:`ask`}).length}clear(e){e?this.entries=this.entries.filter(t=>t.sessionId!==e):this.entries=[]}get size(){return this.entries.length}};function at(e){return e.safety?`high`:`medium`}function ot(e){let t=[];for(let r of e)if(t.push(r),typeof r==`string`){let e=n(r);e!==r&&t.push(e)}return t}var Z=class{name=`permission-guard`;timing=`tool.execute.before`;priority=5;enabled=!0;registry;auditLog;constructor(e,t){this.registry=e,this.auditLog=t}handle=(e,t)=>{let n={timing:`tool.execute.before`,toolName:e.toolName,args:e.args,agentName:e.agentName,sessionId:e.sessionId,metadata:{}},r=ot(e.paths&&e.paths.length>0?e.paths:[void 0]),i=this.registry.evaluate({...n,filePath:r[0]}),a=r[0];for(let e=1;e<r.length;e++){let t=this.registry.evaluate({...n,filePath:r[e]});(t.effect===`deny`||t.effect===`ask`&&i.effect===`allow`)&&(i=t,a=r[e])}let o={...n,filePath:a};if(this.auditLog?.record(o,i),i.effect===`deny`){t.cancelled=!0,t.decision=`deny`,t.decisionReason=i.reason??i.ruleName,t.cancelReason=`Permission denied: ${t.decisionReason}`;return}i.effect===`ask`?(t.decision=`ask`,t.decisionReason=i.reason??`Requires confirmation`,t.risk=at(i)):t.decision!==`ask`&&t.decision!==`deny`&&(t.decision=`allow`)}};function Q(e,t){let n=new Z(e,t);return c({name:n.name,timing:n.timing,priority:n.priority,enabled:n.enabled,handle:n.handle})}const $={fileWriteTools:[`write`,`edit`,`edit-diff`]};function st(e){if(e.has(`permission-guard`))return;let t=J({toolSets:$});return e.register(Q(t,new X)),t}function ct(e){try{return r(e)}catch{return}}function lt(e){let t=new Set;for(let r of e){let e=n(r);t.add(e);let i=ct(e);i&&i!==e&&t.add(i)}return[...t]}function ut(e,t){return e===t||e.startsWith(t.endsWith(`/`)?t:`${t}/`)}function dt(e,t){let n=lt(t);return lt([e]).some(e=>n.some(t=>ut(e,t)))}function ft(e,t){let n=e.writePaths??[],r=e.network===!0;for(let e of n)if(dt(e,t.deniedRoots))return{verdict:`deny`,reason:`write to protected path "${e}" is never allowed (escape guard)`};if(t.mode===`bypass`||n.length===0&&!r)return{verdict:`auto-allow`};let i=n.every(e=>dt(e,t.writableRoots)),a=!r||t.networkAllowed;return i&&a?{verdict:`auto-allow`}:t.mode===`strict`||t.mode===`readonly`?{verdict:`deny`,reason:`${i?`network access`:`write outside the sandbox writable roots`} is not permitted in ${t.mode} mode`}:{verdict:`ask`,reason:`${i?`network access`:`write outside the sandbox writable roots`} requires approval (will run with sandbox bypassed for this operation)`}}function pt(e,t){return[n(e,`.otto`),n(t,`.otto`)]}function mt(e,t,r,i=[]){let a=[n(t),n(r),`/tmp`];if(e!==`strict`&&e!==`readonly`)for(let e of i)a.push(n(e));return[...new Set(a)]}var ht=class{signals=new Map;clock;constructor(e=()=>Date.now()){this.clock=e}record(e,t,n){let r=`${e}:${t}`,i=this.clock(),a=this.signals.get(r);a?(a.count++,a.lastSeen=i,n&&(a.detail=n)):this.signals.set(r,{kind:e,signature:t,count:1,firstSeen:i,lastSeen:i,detail:n})}recurring(e=3){return[...this.signals.values()].filter(t=>t.count>=e).sort((e,t)=>t.count-e.count)}all(){return[...this.signals.values()].sort((e,t)=>t.count-e.count)}clear(){this.signals.clear()}};function gt(e){let t=e.content;if(!Array.isArray(t))return;let n=t.map(e=>e&&typeof e==`object`&&`text`in e?String(e.text??``):``).join(` `).trim();return n?n.split(`
8
- `)[0].slice(0,120):void 0}function _t(e){return c({name:`failure-signal-recorder`,timing:`tool.execute.after`,priority:14,handle(t){t.result?.isError&&e.record(`tool-error`,t.toolName,gt(t.result))}})}function vt(e){return c({name:`failure-signal-permission-deny`,timing:`tool.execute.before`,priority:90,handle(t,n){n?.decision===`deny`&&e.record(`permission-denied`,t.toolName,n.decisionReason)}})}var yt=class{proposed=new Set;minCount;clock;constructor(e,t={}){this.signals=e,this.minCount=t.minCount??3,this.clock=t.clock??(()=>Date.now())}propose(){let e=[];for(let t of this.signals.recurring(this.minCount)){let n=`${t.kind}:${t.signature}`;this.proposed.has(n)||(this.proposed.add(n),e.push({id:n,signature:t.signature,kind:`investigate-fix`,directive:bt(t),evidence:{signalKind:t.kind,count:t.count,detail:t.detail},createdAt:this.clock()}))}return e}reset(){this.proposed.clear()}};function bt(e){return e.kind===`tool-error`?`工具「${e.signature}」反复失败(${e.count} 次${e.detail?`,如「${e.detail}」`:``})。调查根因并修复:定位失败路径、补健壮性或修 bug,跑测试验证。`:`反复出现「${e.kind}: ${e.signature}」(${e.count} 次)。调查并消除。`}export{$ as BASELINE_PERMISSION_TOOL_SETS,H as CREDENTIAL_READ_POLICY,R as DESTRUCTIVE_COMMAND_POLICY,yt as Diagnoser,ht as FailureSignalStore,E as HookRegistry,C as HookState,X as PermissionAuditLog,Z as PermissionGuardHook,q as PermissionPolicyRegistry,ft as assessSandboxSafety,Ze as bashAlwaysAllowPrefix,it as compilePolicyFromSetting,mt as computeSandboxRoots,f as createAnthropicEffortHook,m as createCommentCheckerHook,b as createCompactionAfterHook,y as createCompactionLoggerHook,Ue as createDisabledToolsPolicy,me as createEditFilesPanelHook,He as createEgressAllowlistPolicy,_t as createFailureSignalHook,I as createFileGuardPolicy,p as createFirstMessageVariantHook,fe as createHookRegistry,u as createLabelTruncatorHook,U as createOttoStateDomainPolicy,l as createOutputTruncationHook,vt as createPermissionDenyHook,Q as createPermissionGuardHook,W as createPermissionModePolicy,J as createPermissionRegistry,De as createPermissionToolSetsFromRegistry,_ as createStreamEndMetricsHook,g as createStreamMetricsHook,d as createThinkingValidatorHook,S as createTokenBudgetHook,x as createToolErrorTrackerHook,pt as defaultDeniedRoots,c as defineHook,Ee as extractWriteTargets,Ke as isWellFormedAllowEntry,st as provisionBaselineSecurity};
1
+ import{createLogger as e}from"@x-otto/shared";import{z as t}from"zod";import{normalizeEnv as n}from"@x-otto/env";import{WATERFALL_TIMINGS as r,isWaterfallTiming as i}from"@x-otto/hook-contracts";const a=t.void(),o=t.object({message:t.unknown(),cancelled:t.boolean(),metadata:t.record(t.string(),t.unknown())}),s=t.object({args:t.record(t.string(),t.unknown()),displayArgs:t.record(t.string(),t.unknown()).optional(),cancelled:t.boolean(),cancelReason:t.string().optional(),decision:t.enum([`allow`,`deny`,`ask`]).optional(),decisionReason:t.string().optional(),risk:t.enum([`low`,`medium`,`high`]).optional()}),c=t.object({result:t.unknown(),metadata:t.record(t.string(),t.unknown())}),ee=t.object({messages:t.array(t.unknown())}),te=t.object({temperature:t.number().optional(),maxTokens:t.number().optional(),thinkingLevel:t.string().optional(),metadata:t.record(t.string(),t.unknown())}),l=t.object({systemPrompt:t.string(),systemTail:t.array(t.string()).optional()}),u=t.object({cancelled:t.boolean()}),d={"chat.message.before":o,"chat.message.after":o,"tool.execute.before":s,"tool.execute.after":c,"messages.transform":ee,"chat.params":te,"system.prompt.transform":l,"session.created":a,"session.restored":a,"session.deleted":a,"session.idle":a,"session.error":a,"stream.start":a,"stream.end":a,"compaction.before":a,"compaction.after":a,"memory.prune.before":u,"process.spawned":a,"process.exited":a,"task.created":a,"task.started":a,"task.completed":a,"task.failed":a,"task.cancelled":a,notification:a};function f(e){return e.def?.type===`void`}function p(e,t){if(f(e))return!1;let n=e.def?.shape;return n!==void 0&&t in n}const m=Object.keys(d);function h(e){return f(d[e])?`observer`:`interceptor`}const g=new Set(m.filter(e=>h(e)===`interceptor`));new Set(m.filter(e=>h(e)===`observer`));const _=new Set(m.filter(e=>h(e)===`interceptor`&&p(d[e],`cancelled`))),ne=new Set(m.filter(e=>h(e)===`interceptor`&&p(d[e],`decision`)));function re(){return Object.fromEntries(m.map(e=>[e,[]]))}const v=m,y=g;function b(){return re()}function x(e){let t={name:e.name,timing:e.timing,priority:e.priority??50,enabled:e.enabled??!0};return y.has(e.timing)?{...t,kind:`interceptor`,handle:e.handle}:{...t,kind:`observer`,handle:e.handle}}function S(e,t){if(e!==`session.error`)return t;let n=t;return{sessionId:n.sessionId,metadata:n.metadata,error:n.error instanceof Error?n.error.message:String(n.error)}}const C=e(`@x-otto/hooks`),w=new Set([`tool.execute.before`]),T=n(process.env.OTTO_HOOK_TIMEOUT_MS,5e3),E=_,D=ne;function ie(e){return typeof e==`object`&&!!e&&e.abort===!0}async function ae(e,t,n,r,i){let a;try{return{ok:!0,abort:ie(await Promise.race([e.handle(n,r),new Promise((t,n)=>{a=setTimeout(()=>{n(Error(`hook "${e.name}" timed out after ${T}ms`))},T),a.unref?.()})]))}}catch(n){let r=n instanceof Error?n.message:String(n),a=r.includes(`timed out after`);return C.error({name:e.name,timing:t,err:r,timedOut:a},`Hook failed or timed out`),a&&i?.({hookName:e.name,timing:t,timeoutMs:T}),{ok:!1,timedOut:a,message:r}}finally{a!==void 0&&clearTimeout(a)}}async function oe(e,t,n){let r;try{await Promise.race([e.handle(n),new Promise((t,n)=>{r=setTimeout(()=>{n(Error(`hook "${e.name}" timed out after ${T}ms`))},T),r.unref?.()})])}catch(n){let r=n instanceof Error?n.message:String(n);C.error({name:e.name,timing:t,err:r},`Hook failed or timed out`)}finally{r!==void 0&&clearTimeout(r)}}async function se(e,t,n,r,i){if(t.length===0)return;let a=!1,o=!1;for(let s of t){let t=await ae(s,e,n,r,i);if(!t.ok&&w.has(e)){let e=r;typeof e.cancelled==`boolean`&&(e.cancelled=!0,e.cancelReason=t.timedOut?`hook "${s.name}" timed out after ${T}ms`:`hook "${s.name}" failed: ${t.message}`)}if(E.has(e)){let e=r;e.cancelled===!0&&(a=!0),a&&(e.cancelled=!0)}if(D.has(e)){let e=r;e.decision===`deny`&&(o=!0),o&&(e.decision=`deny`)}if(t.ok&&t.abort)break}}async function ce(e,t,n){if(t.length===0)return;let r=S(e,n);for(let n of t)await oe(n,e,r)}function O(e=61440){return x({name:`output-truncation`,timing:`tool.execute.after`,priority:10,handle(t,n){let{content:r}=n.result,i=0;for(let e of r)e.type===`text`&&(i+=e.text.length);if(i<=e)return;let a=e,o=r.map(t=>{if(t.type!==`text`)return t;if(a<=0)return{type:`text`,text:``};if(t.text.length<=a)return a-=t.text.length,t;let n=t.text.slice(0,a);return a=0,{type:`text`,text:`${n}\n\n... [output truncated: ${i} chars → ${e} chars]`}}).filter(e=>e.type!==`text`||e.text.length>0);n.result={...n.result,content:o},n.metadata.truncated=!0,n.metadata.originalSize=i}})}function k(){return x({name:`label-truncator`,timing:`tool.execute.before`,priority:20,handle(e,t){t.displayArgs||={...t.args};for(let e of[`label`,`description`,`title`]){let n=t.displayArgs[e];typeof n==`string`&&n.length>200&&(t.displayArgs[e]=`${n.slice(0,200)}...`)}}})}function A(){return x({name:`thinking-validator`,timing:`messages.transform`,priority:20,handle(e,t){t.messages=t.messages.map(e=>{if(!j(e))return e;let t=e.content;if(!Array.isArray(t))return e;let n=t.filter(e=>!(e.type===`thinking`&&(typeof e.thinking!=`string`||e.thinking.trim()===``)));return{...e,content:n}})}})}function j(e){return typeof e==`object`&&!!e&&`role`in e&&e.role===`assistant`}function M(){return x({name:`anthropic-effort`,timing:`chat.params`,priority:10,handle(e,t){e.provider===`anthropic`&&(t.thinkingLevel||(e.model.includes(`opus`)?t.thinkingLevel=`high`:e.model.includes(`sonnet`)?t.thinkingLevel=`medium`:e.model.includes(`haiku`)&&(t.thinkingLevel=`low`)))}})}function N(){return x({name:`first-message-variant`,timing:`chat.message.before`,priority:10,handle(e,t){e.isFirstMessage&&(t.metadata.isFirstMessage=!0,t.metadata.variant=`first-message`)}})}const P=[/\/\/\s*TODO:\s*implement/i,/\/\/\s*add\s+(your|the)\s+/i,/\/\/\s*placeholder/i,/\/\/\s*\.\.\.\s*(rest|more|other|remaining)/i,/\/\/\s*handle\s+error\s+here/i,/\/\*\s*\*\//];function F(){return x({name:`comment-checker`,timing:`tool.execute.after`,priority:20,handle(e,t){if(e.readonly)return;let n=L(e.args);if(!n)return;let r=I(n);if(r.length>0){let e=`\n\n⚠️ AI-style comments detected:\n${r.map(e=>` - Line ${e.line}: "${e.text}"`).join(`
2
+ `)}\nPlease replace with meaningful implementation comments.`;t.result={...t.result,content:[...t.result.content,{type:`text`,text:e}]},t.metadata.aiCommentsDetected=r.length}}})}function I(e){let t=[],n=e.split(`
3
+ `);for(let e=0;e<n.length;e++){let r=n[e]??``;for(let n of P)if(n.test(r)){t.push({line:e+1,text:r.trim()});break}}return t}function L(e){return typeof e.content==`string`?e.content:typeof e.newString==`string`?e.newString:typeof e.new_string==`string`?e.new_string:null}const R=e(`@x-otto/hooks:stream-metrics`);function z(e){return x({name:`stream-metrics`,timing:`stream.start`,priority:10,handle(t){let n=e.streamMetrics;n.set(t.sessionId,{startTime:Date.now(),model:t.model,requestCount:(n.get(t.sessionId)?.requestCount??0)+1,lastStopReason:``,totalDurationMs:n.get(t.sessionId)?.totalDurationMs??0}),R.debug(`Stream started: session=%s model=%s`,t.sessionId,t.model)}})}function B(e){return x({name:`stream-end-metrics`,timing:`stream.end`,priority:10,handle(t){let n=e.streamMetrics.get(t.sessionId);if(n){let e=Date.now()-n.startTime;n.totalDurationMs+=e,n.lastStopReason=t.stopReason,R.debug(`Stream ended: session=%s model=%s duration=%dms stopReason=%s total=%dms`,t.sessionId,t.model,e,t.stopReason,n.totalDurationMs)}}})}const V=e(`@x-otto/hooks:compaction`);function H(e){return x({name:`compaction-logger`,timing:`compaction.before`,priority:10,handle(t){let n=e.compactionStats.get(t.sessionId)??{compactionCount:0,totalCompacted:0,lastCompactionTime:0};n.compactionCount++,n.lastCompactionTime=Date.now(),e.compactionStats.set(t.sessionId,n),V.info(`Compaction started: session=%s messageCount=%d compaction#%d`,t.sessionId,t.messageCount,n.compactionCount)}})}function U(e){return x({name:`compaction-after-logger`,timing:`compaction.after`,priority:10,handle(t){let n=e.compactionStats.get(t.sessionId);if(n){let e=Date.now()-n.lastCompactionTime;n.totalCompacted+=t.retainedCount,V.info(`Compaction finished: session=%s retained=%d duration=%dms totalCompactions=%d`,t.sessionId,t.retainedCount,e,n.compactionCount)}}})}const W=e(`@x-otto/hooks:tool-error-tracker`);function G(e,t){let n=t?.circuitBreakerThreshold??5,r=t?.decayWindowMs??12e4;return x({name:`tool-error-tracker`,timing:`tool.execute.after`,priority:15,handle(t,i){let a=e.toolErrors.get(t.sessionId)??new Map;e.toolErrors.set(t.sessionId,a);let o=a.get(t.toolName);if(o&&Date.now()-o.lastErrorTime>r&&(o=void 0),t.result.isError){if(o||={toolName:t.toolName,errorCount:0,lastErrorTime:0,consecutiveErrors:0},o.errorCount++,o.consecutiveErrors++,o.lastErrorTime=Date.now(),a.set(t.toolName,o),o.consecutiveErrors>=n){let e=`Tool "${t.toolName}" hit circuit-breaker: ${o.consecutiveErrors} consecutive errors`;W.warn(e),i.metadata.toolCircuitBreaker={toolName:t.toolName,consecutiveErrors:o.consecutiveErrors,tripped:!0}}}else o&&(o.consecutiveErrors=0,a.set(t.toolName,o))}})}const le=e(`@x-otto/hooks:token-budget`);function K(e){let t=e?.maxOutputTokens??16384;return x({name:`token-budget`,timing:`chat.params`,priority:20,handle(e,n){(!n.maxTokens||n.maxTokens>t)&&(n.maxTokens=t,le.debug(`Capped maxTokens to %d for model=%s`,t,e.model))}})}function ue(e,t){switch(e){case`default`:return q(t);case`strict`:return J(t);case`minimal`:return de();default:return[]}}function q(e){return[O(),k(),A(),M(),N(),z(e),B(e),H(e),U(e),G(e),K()]}function J(e){return[...q(e),F()]}function de(){return[O()]}var Y=class{streamMetrics=new Map;compactionStats=new Map;toolErrors=new Map;clearSession(e){this.streamMetrics.delete(e),this.compactionStats.delete(e),this.toolErrors.delete(e)}},X=class{tokens=[];constructor(e,t){this.registry=e,this.name=t}register(e){let t={...e,name:`${this.name}:${e.name}`},n=this.registry.register(t);return this.tokens.push(n),n}dispose(){for(let e of this.tokens)e.dispose();this.tokens.length=0}};const Z=e(`@x-otto/hooks`);var Q=class{hooks=b();disabled=new Set;onHookTimeout;state=new Y;constructor(e){this.onHookTimeout=e?.onHookTimeout,this.register(x({name:`hook-state-cleanup`,timing:`session.deleted`,priority:90,handle:e=>{this.state.clearSession(e.sessionId)}})),e?.preset&&e.preset!==`none`&&this.applyPreset(e.preset)}register(e){return this.hooks[e.timing].push(e),Z.debug({hookName:e.name,timing:e.timing,priority:e.priority},`Hook registered`),{dispose:()=>{let t=this.hooks[e.timing],n=t.filter(t=>t!==e);n.length<t.length&&(this.hooks[e.timing]=n,Z.debug({hookName:e.name,timing:e.timing},`Hook token disposed`))}}}registerAll(e){let t=[];for(let n of e)t.push(this.register(n));return t}createScope(e){return new X(this,e)}on(e,t,n,r=50){return this.register(x({name:t,timing:e,handle:n,priority:r})),this}has(e){return this.getRegistered().some(t=>t.name===e)}unregister(e){let t=!1;for(let n of v){let r=this.hooks[n],i=r.filter(t=>t.name!==e);i.length<r.length&&(this.hooks[n]=i,t=!0,Z.debug({hookName:e,timing:n},`Hook unregistered`))}return t}disable(e){this.disabled.add(e),Z.debug({hookName:e},`Hook disabled`)}enable(e){this.disabled.delete(e),Z.debug({hookName:e},`Hook enabled`)}getRegistered(e){if(e)return this.hooks[e].map($);let t=[];for(let e of v)t.push(...this.hooks[e].map($));return t}async execute(e,t,n){await se(e,this.getSortedInterceptorHooks(e),t,n,this.onHookTimeout)}async emit(e,t){await ce(e,this.getSortedObserverHooks(e),t)}clear(){for(let e of v)this.hooks[e]=[];this.disabled.clear(),Z.debug(`All hooks cleared`)}getSortedInterceptorHooks(e){let t=this.hooks[e];return t?t.filter(e=>e.kind===`interceptor`&&e.enabled&&!this.disabled.has(e.name)).sort((e,t)=>e.priority-t.priority):(Z.warn({timing:e},`Unknown hook timing (no bucket) — emit name mismatch with HOOK_NODES?`),[])}getSortedObserverHooks(e){let t=this.hooks[e];return t?t.filter(e=>e.kind===`observer`&&e.enabled&&!this.disabled.has(e.name)).sort((e,t)=>e.priority-t.priority):(Z.warn({timing:e},`Unknown hook timing (no bucket) — emit name mismatch with HOOK_NODES?`),[])}applyPreset(e){let t=ue(e,this.state);for(let e of t)this.register(e)}};function $(e){return{name:e.name,timing:e.timing,priority:e.priority,enabled:e.enabled}}function fe(e){return new Q(e)}export{Q as HookRegistry,X as HookScope,Y as HookState,r as WATERFALL_TIMINGS,M as createAnthropicEffortHook,F as createCommentCheckerHook,U as createCompactionAfterHook,H as createCompactionLoggerHook,N as createFirstMessageVariantHook,fe as createHookRegistry,k as createLabelTruncatorHook,O as createOutputTruncationHook,B as createStreamEndMetricsHook,z as createStreamMetricsHook,A as createThinkingValidatorHook,K as createTokenBudgetHook,G as createToolErrorTrackerHook,x as defineHook,i as isWaterfallTiming};
9
4
  //# sourceMappingURL=index.js.map