@pinta-ai/pinta-cc 1.5.0 → 1.6.0

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,7 +1,7 @@
1
1
  {
2
2
  "name": "pinta-cc",
3
3
  "description": "Generic OTLP forwarder for Claude Code hook events. Converts hook events into OTLP/HTTP spans and sends them to any OpenTelemetry-compatible collector.",
4
- "version": "1.5.0",
4
+ "version": "1.6.0",
5
5
  "license": "PolyForm-Noncommercial-1.0.0",
6
6
  "userConfig": {
7
7
  "endpoint": {
package/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  All notable changes to pinta-cc are documented here.
4
4
 
5
+ ## [1.5.1] - 2026-07-10
6
+
7
+ ### Changed
8
+
9
+ - `@pinta-ai/core` bumped `^0.2.0` → `^0.3.0` (devDependency, bundled into
10
+ `dist/` at build). The upgrade is additive; no adaptor source change was
11
+ needed.
12
+
13
+ ### Added
14
+
15
+ - `pinta.client.rtt_ms` / `pinta.client.op` span attributes on PreToolUse
16
+ spans. `buildOtlpPayload` already forwards its `guard` result into core's
17
+ `buildPayload`, and core `0.3.0` derives the client-call timing from the
18
+ `GuardResult.clientRttMs` it now measures. The manager can only time its own
19
+ handler, so `clientRttMs - durationMs` gives it the transport overhead.
20
+
21
+ ### Fixed
22
+
23
+ - `tests/core/guard.test.ts` asserted the core `0.2.0` `GuardResult` shape with
24
+ an exhaustive `toEqual` and broke once `clientRttMs` was added. It now matches
25
+ that field by type, since it is a measured wall-clock rather than a value
26
+ echoed from the response body.
27
+
5
28
  ## [1.3.2] - 2026-06-12
6
29
 
7
30
  ### Changed
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
- "use strict";var ot=Object.create;var ne=Object.defineProperty;var st=Object.getOwnPropertyDescriptor;var it=Object.getOwnPropertyNames;var at=Object.getPrototypeOf,ut=Object.prototype.hasOwnProperty;var f=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ct=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of it(e))!ut.call(t,o)&&o!==r&&ne(t,o,{get:()=>e[o],enumerable:!(n=st(e,o))||n.enumerable});return t};var d=(t,e,r)=>(r=t!=null?ot(at(t)):{},ct(e||!t||!t.__esModule?ne(r,"default",{value:t,enumerable:!0}):r,t));var N=f(u=>{"use strict";Object.defineProperty(u,"__esModule",{value:!0});u.PATTERNS=u.MAX_BYTES=void 0;u.truncate=lt;u.collectMatches=oe;u.resolveOverlaps=se;u.applyMatches=ie;u.redact=pt;u.MAX_BYTES=102400;function lt(t){let e=Buffer.from(t,"utf-8");return e.length<=u.MAX_BYTES?t:`${e.subarray(0,u.MAX_BYTES).toString("utf-8")}\u2026[TRUNCATED:${e.length}]`}u.PATTERNS=[{type:"aws_access_key",regex:/AKIA[0-9A-Z]{16}/g},{type:"aws_secret_key",regex:/(?:aws[_-]?secret(?:[_-]?(?:access)?[_-]?key)?)\s*[:=]\s*["']?([A-Za-z0-9/+=]{40})(?![A-Za-z0-9/+=])/gi,captureGroup:1},{type:"gcp_service_account",regex:/\{[\s\S]{0,200}?"type"\s*:\s*"service_account"[\s\S]*?\}/g},{type:"github_token",regex:/gh[pousr]_[A-Za-z0-9]{36,}/g},{type:"gitlab_token",regex:/glpat-[A-Za-z0-9_-]{20}/g},{type:"slack_token",regex:/xox[abrsp]-[0-9A-Za-z-]{10,}/g},{type:"openai_key",regex:/sk-(?:proj-)?[A-Za-z0-9_-]{40,}/g},{type:"anthropic_key",regex:/sk-ant-[A-Za-z0-9_-]{50,}/g},{type:"stripe_key",regex:/(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{20,}/g},{type:"jwt",regex:/eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g},{type:"private_key_block",regex:/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g},{type:"bearer_token",regex:/bearer\s+([A-Za-z0-9._~+/=-]{12,})/gi,captureGroup:1},{type:"basic_auth",regex:/basic\s+([A-Za-z0-9+/=]{12,})/gi,captureGroup:1},{type:"db_url_password",regex:/\b(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|redis):\/\/[^:\s/]+:([^@\s]+)@/gi,captureGroup:1},{type:"cli_password_flag",regex:/(?:--password|--pass|--pwd)[=\s]([^\s'"]+)/g,captureGroup:1},{type:"cli_password_short",regex:/\s-p([^\s'"]+)/g,captureGroup:1,requireContext:"bash"},{type:"env_var_secret",regex:/^(?:export\s+)?([A-Z][A-Z0-9_]*(?:KEY|SECRET|TOKEN|PASSWORD|PASSWD|PWD|API_KEY)[A-Z0-9_]*)\s*=\s*["']?([^\s"'\n]+)/gm,captureGroup:2}];function oe(t,e){let r=[];for(let n of u.PATTERNS){if(n.requireContext&&n.requireContext!==e.context)continue;let o=new RegExp(n.regex.source,n.regex.flags),i;for(;(i=o.exec(t))!==null;){let a=n.captureGroup??0,_=i[a];if(_===void 0){i.index===o.lastIndex&&o.lastIndex++;continue}let te=i.index,rt=i.index+i[0].length,re=te+i[0].indexOf(_),nt=re+_.length;r.push({start:te,end:rt,replaceStart:re,replaceEnd:nt,type:n.type}),i.index===o.lastIndex&&o.lastIndex++}}return r}function se(t){let e=[...t].sort((o,i)=>o.start!==i.start?o.start-i.start:i.end-i.start-(o.end-o.start)),r=[],n=-1;for(let o of e)o.start<n||(r.push(o),n=o.end);return r}function ie(t,e){let r=[...e].sort((o,i)=>i.replaceStart-o.replaceStart),n=t;for(let o of r)n=n.slice(0,o.replaceStart)+`[REDACTED:${o.type}]`+n.slice(o.replaceEnd);return n}function pt(t,e={}){if(t.length===0)return t;let r=oe(t,e);if(r.length===0)return t;let n=se(r);return ie(t,n)}});var C=f(p=>{"use strict";var ft=p&&p.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(p,"__esModule",{value:!0});p.ulidToTraceId=ce;p.newSpanId=le;p.snakeCase=_t;p.toOtlpValue=pe;p.attrsFromRecord=gt;p.guardAttrs=fe;p.buildPayload=ht;p.mergeBatch=yt;var dt=ft(require("crypto")),ae=N(),mt="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function ce(t){if(t.length!==26)throw new Error(`ulidToTraceId: expected 26 chars, got ${t.length}`);let e=0n;for(let n of t){let o=mt.indexOf(n);if(o<0)throw new Error(`ulidToTraceId: invalid Crockford char "${n}"`);e=e<<5n|BigInt(o)}let r=(1n<<128n)-1n;return e&=r,e.toString(16).padStart(32,"0")}function le(){return dt.default.randomBytes(8).toString("hex")}function _t(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()}var ue=new Set;function x(t,e,r){let n=(0,ae.truncate)(e);if((r.skipRedactKeys??ue).has(t))return n;let o=(r.bashContextKeys??ue).has(t)?"bash":void 0;return(0,ae.redact)(n,{context:o})}function pe(t,e,r={}){if(e==null)return null;switch(typeof e){case"string":return{stringValue:x(t,e,r)};case"boolean":return{boolValue:e};case"number":return Number.isInteger(e)?{intValue:e}:{doubleValue:e};case"object":try{return{stringValue:x(t,JSON.stringify(e),r)}}catch{return{stringValue:x(t,String(e),r)}}default:return{stringValue:x(t,String(e),r)}}}function gt(t,e,r={}){let n=[];for(let[o,i]of Object.entries(t)){let a=`${e}.${o}`,_=pe(a,i,r);_!==null&&n.push({key:a,value:_})}return n}function fe(t){let e=[{key:"pinta.guard.decision",value:{stringValue:t.decision.toLowerCase()}},{key:"pinta.guard.duration_ms",value:{intValue:t.durationMs}}];return t.reason&&e.push({key:"pinta.guard.matched_rule",value:{stringValue:t.reason}}),t.failOpenReason&&e.push({key:"pinta.guard.fail_open_reason",value:{stringValue:t.failOpenReason}}),e}function ht(t){let e=t.now??Date.now(),r=(BigInt(e)*1000000n).toString(),n=[...t.attributes];t.guard&&n.push(...fe(t.guard));let o={traceId:ce(t.traceId),spanId:le(),name:t.spanName,kind:t.spanKind??1,startTimeUnixNano:r,endTimeUnixNano:r,attributes:n};return{resourceSpans:[{resource:{attributes:t.resource},scopeSpans:[{scope:t.scope,spans:[o]}]}]}}function yt(t){let e=[];for(let r of t)e.push(...r.resourceSpans);return{resourceSpans:e}}});var de=f(U=>{"use strict";Object.defineProperty(U,"__esModule",{value:!0});U.evaluateGuard=Tt;var Pt=1e4,vt="pinta-core";function Et(t){return new Promise((e,r)=>setTimeout(()=>{let n=new Error("Guard request timed out");n.name="TimeoutError",r(n)},t))}async function Tt(t,e,r={}){if(!e||r.disabled)return null;let n=r.timeoutMs??Pt,o=Date.now();try{let i=await Promise.race([fetch(e,{method:"POST",headers:{"content-type":"application/json","user-agent":r.userAgent??vt,"x-pinta-relay-token":r.token??""},body:JSON.stringify({input:t})}),Et(n)]);if(i.status!==200)return{decision:"ALLOW",reason:null,userMessage:null,durationMs:Date.now()-o,failOpenReason:"error"};let a=await i.json();return{decision:a.decision,reason:a.reason,userMessage:a.userMessage??null,durationMs:a.durationMs??Date.now()-o}}catch(i){let a=i.name==="TimeoutError"?"timeout":"error";return{decision:"ALLOW",reason:null,userMessage:null,durationMs:Date.now()-o,failOpenReason:a}}}});var B=f(g=>{"use strict";var me=g&&g.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(g,"__esModule",{value:!0});g.MemoryRetryQueue=g.DiskRetryQueue=void 0;var c=me(require("fs")),A=me(require("path")),R=1e3,Ot=50,St=5,L=class{filePath;lockPath;logPrefix;constructor(e,r){this.filePath=A.default.join(e,"failed-spans.jsonl"),this.lockPath=this.filePath+".lock",this.logPrefix=r}enqueue(e){try{c.default.mkdirSync(A.default.dirname(this.filePath),{recursive:!0});let r=JSON.stringify({savedAt:new Date().toISOString(),payload:e})+`
1
+ "use strict";var at=Object.create;var ne=Object.defineProperty;var ut=Object.getOwnPropertyDescriptor;var ct=Object.getOwnPropertyNames;var lt=Object.getPrototypeOf,pt=Object.prototype.hasOwnProperty;var d=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var ft=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ct(t))!pt.call(e,o)&&o!==r&&ne(e,o,{get:()=>t[o],enumerable:!(n=ut(t,o))||n.enumerable});return e};var m=(e,t,r)=>(r=e!=null?at(lt(e)):{},ft(t||!e||!e.__esModule?ne(r,"default",{value:e,enumerable:!0}):r,e));var N=d(u=>{"use strict";Object.defineProperty(u,"__esModule",{value:!0});u.PATTERNS=u.MAX_BYTES=void 0;u.truncate=dt;u.collectMatches=oe;u.resolveOverlaps=se;u.applyMatches=ie;u.redact=mt;u.MAX_BYTES=102400;function dt(e){let t=Buffer.from(e,"utf-8");return t.length<=u.MAX_BYTES?e:`${t.subarray(0,u.MAX_BYTES).toString("utf-8")}\u2026[TRUNCATED:${t.length}]`}u.PATTERNS=[{type:"aws_access_key",regex:/AKIA[0-9A-Z]{16}/g},{type:"aws_secret_key",regex:/(?:aws[_-]?secret(?:[_-]?(?:access)?[_-]?key)?)\s*[:=]\s*["']?([A-Za-z0-9/+=]{40})(?![A-Za-z0-9/+=])/gi,captureGroup:1},{type:"gcp_service_account",regex:/\{[\s\S]{0,200}?"type"\s*:\s*"service_account"[\s\S]*?\}/g},{type:"github_token",regex:/gh[pousr]_[A-Za-z0-9]{36,}/g},{type:"gitlab_token",regex:/glpat-[A-Za-z0-9_-]{20}/g},{type:"slack_token",regex:/xox[abrsp]-[0-9A-Za-z-]{10,}/g},{type:"openai_key",regex:/sk-(?:proj-)?[A-Za-z0-9_-]{40,}/g},{type:"anthropic_key",regex:/sk-ant-[A-Za-z0-9_-]{50,}/g},{type:"stripe_key",regex:/(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{20,}/g},{type:"jwt",regex:/eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g},{type:"private_key_block",regex:/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g},{type:"bearer_token",regex:/bearer\s+([A-Za-z0-9._~+/=-]{12,})/gi,captureGroup:1},{type:"basic_auth",regex:/basic\s+([A-Za-z0-9+/=]{12,})/gi,captureGroup:1},{type:"db_url_password",regex:/\b(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|redis):\/\/[^:\s/]+:([^@\s]+)@/gi,captureGroup:1},{type:"cli_password_flag",regex:/(?:--password|--pass|--pwd)[=\s]([^\s'"]+)/g,captureGroup:1},{type:"cli_password_short",regex:/\s-p([^\s'"]+)/g,captureGroup:1,requireContext:"bash"},{type:"env_var_secret",regex:/^(?:export\s+)?([A-Z][A-Z0-9_]*(?:KEY|SECRET|TOKEN|PASSWORD|PASSWD|PWD|API_KEY)[A-Z0-9_]*)\s*=\s*["']?([^\s"'\n]+)/gm,captureGroup:2}];function oe(e,t){let r=[];for(let n of u.PATTERNS){if(n.requireContext&&n.requireContext!==t.context)continue;let o=new RegExp(n.regex.source,n.regex.flags),i;for(;(i=o.exec(e))!==null;){let a=n.captureGroup??0,f=i[a];if(f===void 0){i.index===o.lastIndex&&o.lastIndex++;continue}let te=i.index,st=i.index+i[0].length,re=te+i[0].indexOf(f),it=re+f.length;r.push({start:te,end:st,replaceStart:re,replaceEnd:it,type:n.type}),i.index===o.lastIndex&&o.lastIndex++}}return r}function se(e){let t=[...e].sort((o,i)=>o.start!==i.start?o.start-i.start:i.end-i.start-(o.end-o.start)),r=[],n=-1;for(let o of t)o.start<n||(r.push(o),n=o.end);return r}function ie(e,t){let r=[...t].sort((o,i)=>i.replaceStart-o.replaceStart),n=e;for(let o of r)n=n.slice(0,o.replaceStart)+`[REDACTED:${o.type}]`+n.slice(o.replaceEnd);return n}function mt(e,t={}){if(e.length===0)return e;let r=oe(e,t);if(r.length===0)return e;let n=se(r);return ie(e,n)}});var C=d(p=>{"use strict";var _t=p&&p.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(p,"__esModule",{value:!0});p.ulidToTraceId=ce;p.newSpanId=le;p.snakeCase=yt;p.toOtlpValue=pe;p.attrsFromRecord=Pt;p.guardAttrs=fe;p.clientAttrs=de;p.buildPayload=vt;p.mergeBatch=Et;var gt=_t(require("crypto")),ae=N(),ht="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function ce(e){if(e.length!==26)throw new Error(`ulidToTraceId: expected 26 chars, got ${e.length}`);let t=0n;for(let n of e){let o=ht.indexOf(n);if(o<0)throw new Error(`ulidToTraceId: invalid Crockford char "${n}"`);t=t<<5n|BigInt(o)}let r=(1n<<128n)-1n;return t&=r,t.toString(16).padStart(32,"0")}function le(){return gt.default.randomBytes(8).toString("hex")}function yt(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()}var ue=new Set;function x(e,t,r){let n=(0,ae.truncate)(t);if((r.skipRedactKeys??ue).has(e))return n;let o=(r.bashContextKeys??ue).has(e)?"bash":void 0;return(0,ae.redact)(n,{context:o})}function pe(e,t,r={}){if(t==null)return null;switch(typeof t){case"string":return{stringValue:x(e,t,r)};case"boolean":return{boolValue:t};case"number":return Number.isInteger(t)?{intValue:t}:{doubleValue:t};case"object":try{return{stringValue:x(e,JSON.stringify(t),r)}}catch{return{stringValue:x(e,String(t),r)}}default:return{stringValue:x(e,String(t),r)}}}function Pt(e,t,r={}){let n=[];for(let[o,i]of Object.entries(e)){let a=`${t}.${o}`,f=pe(a,i,r);f!==null&&n.push({key:a,value:f})}return n}function fe(e){let t=[{key:"pinta.guard.decision",value:{stringValue:e.decision.toLowerCase()}},{key:"pinta.guard.duration_ms",value:{intValue:e.durationMs}}];return e.reason&&t.push({key:"pinta.guard.matched_rule",value:{stringValue:e.reason}}),e.failOpenReason&&t.push({key:"pinta.guard.fail_open_reason",value:{stringValue:e.failOpenReason}}),t}function de(e){return[{key:"pinta.client.rtt_ms",value:Number.isInteger(e.rttMs)?{intValue:e.rttMs}:{doubleValue:e.rttMs}},{key:"pinta.client.op",value:{stringValue:e.op}}]}function vt(e){let t=e.now??Date.now(),r=(BigInt(t)*1000000n).toString(),n=[...e.attributes];e.guard&&n.push(...fe(e.guard));let o=e.clientTiming??(e.guard?.clientRttMs!==void 0?{op:"guard",rttMs:e.guard.clientRttMs}:null);o&&n.push(...de(o));let i={traceId:ce(e.traceId),spanId:le(),name:e.spanName,kind:e.spanKind??1,startTimeUnixNano:r,endTimeUnixNano:r,attributes:n};return{resourceSpans:[{resource:{attributes:e.resource},scopeSpans:[{scope:e.scope,spans:[i]}]}]}}function Et(e){let t=[];for(let r of e)t.push(...r.resourceSpans);return{resourceSpans:t}}});var _e=d(U=>{"use strict";Object.defineProperty(U,"__esModule",{value:!0});U.evaluateGuard=bt;var Tt=1e4,St="pinta-core";function me(e,t){return{decision:"ALLOW",reason:null,userMessage:null,durationMs:e,clientRttMs:e,failOpenReason:t}}function Ot(e){return new Promise((t,r)=>setTimeout(()=>{let n=new Error("Guard request timed out");n.name="TimeoutError",r(n)},e))}async function bt(e,t,r={}){if(!t||r.disabled)return null;let n=r.timeoutMs??Tt,o=Date.now();try{let i=await Promise.race([fetch(t,{method:"POST",headers:{"content-type":"application/json","user-agent":r.userAgent??St,"x-pinta-relay-token":r.token??""},body:JSON.stringify({input:e})}),Ot(n)]);if(i.status!==200)return me(Date.now()-o,"error");let a=await i.json(),f=Date.now()-o;return{decision:a.decision,reason:a.reason,userMessage:a.userMessage??null,durationMs:a.durationMs??f,clientRttMs:f}}catch(i){let a=i.name==="TimeoutError"?"timeout":"error";return me(Date.now()-o,a)}}});var B=d(h=>{"use strict";var ge=h&&h.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(h,"__esModule",{value:!0});h.MemoryRetryQueue=h.DiskRetryQueue=void 0;var c=ge(require("fs")),A=ge(require("path")),R=1e3,kt=50,wt=5,L=class{filePath;lockPath;logPrefix;constructor(t,r){this.filePath=A.default.join(t,"failed-spans.jsonl"),this.lockPath=this.filePath+".lock",this.logPrefix=r}enqueue(t){try{c.default.mkdirSync(A.default.dirname(this.filePath),{recursive:!0});let r=JSON.stringify({savedAt:new Date().toISOString(),payload:t})+`
2
2
  `;c.default.appendFileSync(this.filePath,r),this.trim()}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue enqueue failed: ${r}
3
- `)}}readAll(){try{let e=c.default.readFileSync(this.filePath,"utf-8"),r=[];for(let n of e.split(`
4
- `))if(n.trim())try{r.push(JSON.parse(n))}catch{}return r}catch{return[]}}rewrite(e){try{if(e.length===0){c.default.existsSync(this.filePath)&&c.default.unlinkSync(this.filePath);return}c.default.mkdirSync(A.default.dirname(this.filePath),{recursive:!0}),c.default.writeFileSync(this.filePath,e.map(r=>JSON.stringify(r)).join(`
3
+ `)}}readAll(){try{let t=c.default.readFileSync(this.filePath,"utf-8"),r=[];for(let n of t.split(`
4
+ `))if(n.trim())try{r.push(JSON.parse(n))}catch{}return r}catch{return[]}}rewrite(t){try{if(t.length===0){c.default.existsSync(this.filePath)&&c.default.unlinkSync(this.filePath);return}c.default.mkdirSync(A.default.dirname(this.filePath),{recursive:!0}),c.default.writeFileSync(this.filePath,t.map(r=>JSON.stringify(r)).join(`
5
5
  `)+`
6
6
  `)}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue rewrite failed: ${r}
7
- `)}}tryAcquireLock(){let e=Date.now();for(c.default.mkdirSync(A.default.dirname(this.lockPath),{recursive:!0});Date.now()-e<Ot;)try{let r=c.default.openSync(this.lockPath,"wx");return c.default.writeSync(r,String(process.pid)),c.default.closeSync(r),!0}catch(r){if(r?.code!=="EEXIST")return process.stderr.write(`[${this.logPrefix}] retry-queue lock open failed: ${r}
8
- `),!1;try{let i=c.default.statSync(this.lockPath);if(Date.now()-i.mtimeMs>3e4){c.default.unlinkSync(this.lockPath);continue}}catch{}let n=St,o=Date.now()+n;for(;Date.now()<o;);}return!1}release(){try{c.default.unlinkSync(this.lockPath)}catch{}}trim(){let e=this.readAll();if(e.length<=R)return;let r=e.length-R;process.stderr.write(`[${this.logPrefix}] retry-queue full, dropping ${r} oldest entries
9
- `),this.rewrite(e.slice(r))}};g.DiskRetryQueue=L;var q=class{entries=[];enqueue(e){this.entries.push(e),this.entries.length>R&&this.entries.splice(0,this.entries.length-R)}drain(){let e=this.entries;return this.entries=[],e}get size(){return this.entries.length}};g.MemoryRetryQueue=q});var Pe=f(m=>{"use strict";Object.defineProperty(m,"__esModule",{value:!0});m.MemoryTransport=m.DiskTransport=void 0;m.parseHeadersEnv=he;m.envOptionsResolver=ye;m.postOtlp=S;var _e=B(),ge=C(),bt=5e3;function he(t){if(!t)return{};if(typeof t=="object")return{...t};let e={};for(let r of t.split(",")){let[n,...o]=r.split("=");n&&o.length>0&&(e[n.trim()]=o.join("=").trim())}return e}function ye(){let t=process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,e=process.env.OTEL_EXPORTER_OTLP_ENDPOINT,r;return t?r=t.replace(/\/+$/,""):e&&(r=e.replace(/\/+$/,"")+"/v1/traces"),r?{endpoint:r,headers:he(process.env.OTEL_EXPORTER_OTLP_HEADERS)}:null}async function S(t,e,r){let n=new AbortController,o=setTimeout(()=>n.abort(),bt);try{let i=await fetch(e.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...e.headers},body:JSON.stringify(t),signal:n.signal});if(!i.ok){let a="";try{a=(await i.text()).slice(0,200)}catch{}let _=i.status===401||i.status===403?" \u2014 check OTEL_EXPORTER_OTLP_HEADERS (relay token)":i.status===404?" \u2014 check OTEL_EXPORTER_OTLP_TRACES_ENDPOINT path":i.status>=500?" \u2014 collector may be down":"";return process.stderr.write(`[${r}] OTLP POST ${i.status} ${e.endpoint}${_}${a?` body=${a}`:""}
7
+ `)}}tryAcquireLock(){let t=Date.now();for(c.default.mkdirSync(A.default.dirname(this.lockPath),{recursive:!0});Date.now()-t<kt;)try{let r=c.default.openSync(this.lockPath,"wx");return c.default.writeSync(r,String(process.pid)),c.default.closeSync(r),!0}catch(r){if(r?.code!=="EEXIST")return process.stderr.write(`[${this.logPrefix}] retry-queue lock open failed: ${r}
8
+ `),!1;try{let i=c.default.statSync(this.lockPath);if(Date.now()-i.mtimeMs>3e4){c.default.unlinkSync(this.lockPath);continue}}catch{}let n=wt,o=Date.now()+n;for(;Date.now()<o;);}return!1}release(){try{c.default.unlinkSync(this.lockPath)}catch{}}trim(){let t=this.readAll();if(t.length<=R)return;let r=t.length-R;process.stderr.write(`[${this.logPrefix}] retry-queue full, dropping ${r} oldest entries
9
+ `),this.rewrite(t.slice(r))}};h.DiskRetryQueue=L;var q=class{entries=[];enqueue(t){this.entries.push(t),this.entries.length>R&&this.entries.splice(0,this.entries.length-R)}drain(){let t=this.entries;return this.entries=[],t}get size(){return this.entries.length}};h.MemoryRetryQueue=q});var Ee=d(_=>{"use strict";Object.defineProperty(_,"__esModule",{value:!0});_.MemoryTransport=_.DiskTransport=void 0;_.parseHeadersEnv=Pe;_.envOptionsResolver=ve;_.postOtlp=O;var he=B(),ye=C(),xt=5e3;function Pe(e){if(!e)return{};if(typeof e=="object")return{...e};let t={};for(let r of e.split(",")){let[n,...o]=r.split("=");n&&o.length>0&&(t[n.trim()]=o.join("=").trim())}return t}function ve(){let e=process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,t=process.env.OTEL_EXPORTER_OTLP_ENDPOINT,r;return e?r=e.replace(/\/+$/,""):t&&(r=t.replace(/\/+$/,"")+"/v1/traces"),r?{endpoint:r,headers:Pe(process.env.OTEL_EXPORTER_OTLP_HEADERS)}:null}async function O(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),xt);try{let i=await fetch(t.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...t.headers},body:JSON.stringify(e),signal:n.signal});if(!i.ok){let a="";try{a=(await i.text()).slice(0,200)}catch{}let f=i.status===401||i.status===403?" \u2014 check OTEL_EXPORTER_OTLP_HEADERS (relay token)":i.status===404?" \u2014 check OTEL_EXPORTER_OTLP_TRACES_ENDPOINT path":i.status>=500?" \u2014 collector may be down":"";return process.stderr.write(`[${r}] OTLP POST ${i.status} ${t.endpoint}${f}${a?` body=${a}`:""}
10
10
  `),!1}return!0}catch(i){return process.stderr.write(`[${r}] OTLP POST failed: ${i.message??String(i)}
11
- `),!1}finally{clearTimeout(o)}}var F=class{queue;logPrefix;resolveOptions;constructor(e){this.queue=new _e.DiskRetryQueue(e.pluginData,e.logPrefix),this.logPrefix=e.logPrefix,this.resolveOptions=e.resolveOptions??ye}async send(e){let r=this.resolveOptions();if(!r)return;await S(e,r,this.logPrefix)||this.queue.enqueue(e)}async flush(){let e=this.resolveOptions();if(e&&this.queue.tryAcquireLock())try{let r=this.queue.readAll();if(r.length===0)return;let n=(0,ge.mergeBatch)(r.map(i=>i.payload));await S(n,e,this.logPrefix)&&this.queue.rewrite([])}finally{this.queue.release()}}};m.DiskTransport=F;var G=class{queue=new _e.MemoryRetryQueue;logPrefix;resolveOptions;constructor(e){this.logPrefix=e.logPrefix,this.resolveOptions=e.resolveOptions}async send(e){let r=this.resolveOptions();if(!r)return;await S(e,r,this.logPrefix)||this.queue.enqueue(e)}async flush(){let e=this.resolveOptions();if(!e)return;let r=this.queue.drain();if(r.length===0)return;let n=(0,ge.mergeBatch)(r);if(!await S(n,e,this.logPrefix))for(let i of r)this.queue.enqueue(i)}};m.MemoryTransport=G});var Y=f(P=>{"use strict";var X=P&&P.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(P,"__esModule",{value:!0});P.TraceManager=void 0;P.generateUlid=ve;var V=X(require("fs")),kt=X(require("path")),wt=X(require("crypto")),$="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function ve(){let t=Date.now(),e="",r=t;for(let i=0;i<10;i++)e=$[r&31]+e,r=Math.floor(r/32);let n=wt.default.randomBytes(10),o="";for(let i=0;i<10;i++)o+=$[n[i]&31];for(;o.length<16;)o+=$[0];return e+o}var K=class{tracePath;constructor(e){this.tracePath=e}newTrace(){let e=ve();return this.save(e),e}currentTrace(){try{let e=V.default.readFileSync(this.tracePath,"utf-8"),{traceId:r}=JSON.parse(e);if(r)return r}catch{}return this.newTrace()}save(e){V.default.mkdirSync(kt.default.dirname(this.tracePath),{recursive:!0}),V.default.writeFileSync(this.tracePath,JSON.stringify({traceId:e}))}};P.TraceManager=K});var Se=f(h=>{"use strict";var Ee=h&&h.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(h,"__esModule",{value:!0});h.MemorySessionTraceManager=h.DiskSessionTraceManager=void 0;var Z=Ee(require("fs")),xt=Ee(require("path")),Te=Y(),Oe=200,J=class{tracePath;maxSessions;constructor(e,r={}){this.tracePath=e,this.maxSessions=r.maxSessions??Oe}read(){try{let e=JSON.parse(Z.default.readFileSync(this.tracePath,"utf-8"));if(e&&typeof e=="object"&&!("traceId"in e))return e}catch{}return{}}write(e){try{Z.default.mkdirSync(xt.default.dirname(this.tracePath),{recursive:!0});let r=Object.entries(e),n=r.length>this.maxSessions?Object.fromEntries(r.slice(-this.maxSessions)):e;Z.default.writeFileSync(this.tracePath,JSON.stringify(n))}catch{}}newTrace(e){let r=e||"default",n=(0,Te.generateUlid)(),o=this.read();return o[r]=n,this.write(o),n}currentTrace(e){let r=e||"default",n=this.read()[r];return n||this.newTrace(r)}};h.DiskSessionTraceManager=J;var z=class{map=new Map;maxSessions;constructor(e={}){this.maxSessions=e.maxSessions??Oe}newTrace(e){let r=e||"default",n=(0,Te.generateUlid)();if(this.map.set(r,n),this.map.size>this.maxSessions){let o=this.map.keys().next().value;o!==void 0&&this.map.delete(o)}return n}currentTrace(e){let r=e||"default";return this.map.get(r)??this.newTrace(r)}};h.MemorySessionTraceManager=z});var we=f(v=>{"use strict";var H=v&&v.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(v,"__esModule",{value:!0});v.envFilePath=jt;v.parseEnvFile=ke;v.loadEnvFile=Dt;var At=H(require("node:fs")),Rt=H(require("node:os")),be=H(require("node:path"));function jt(t,e,r){let n=r?process.env[r]:void 0,o=n&&n.length>0?n:be.default.join(Rt.default.homedir(),t);return be.default.join(o,e)}function ke(t){let e={};for(let r of t.split(`
12
- `)){let n=r.trim();if(!n||n.startsWith("#"))continue;let o=n.indexOf("=");if(o<0)continue;let i=n.slice(0,o).trim(),a=n.slice(o+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),i&&(e[i]=a)}return e}function Dt(t){let e;try{e=At.default.readFileSync(t,"utf-8")}catch{return}let r=ke(e);for(let[n,o]of Object.entries(r))process.env[n]===void 0&&(process.env[n]=o)}});var T=f(s=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0});s.loadEnvFile=s.parseEnvFile=s.envFilePath=s.MemorySessionTraceManager=s.DiskSessionTraceManager=s.generateUlid=s.TraceManager=s.parseHeadersEnv=s.envOptionsResolver=s.postOtlp=s.MemoryTransport=s.DiskTransport=s.MemoryRetryQueue=s.DiskRetryQueue=s.evaluateGuard=s.mergeBatch=s.buildPayload=s.guardAttrs=s.attrsFromRecord=s.toOtlpValue=s.snakeCase=s.newSpanId=s.ulidToTraceId=s.MAX_BYTES=s.PATTERNS=s.applyMatches=s.resolveOverlaps=s.collectMatches=s.truncate=s.redact=void 0;var E=N();Object.defineProperty(s,"redact",{enumerable:!0,get:function(){return E.redact}});Object.defineProperty(s,"truncate",{enumerable:!0,get:function(){return E.truncate}});Object.defineProperty(s,"collectMatches",{enumerable:!0,get:function(){return E.collectMatches}});Object.defineProperty(s,"resolveOverlaps",{enumerable:!0,get:function(){return E.resolveOverlaps}});Object.defineProperty(s,"applyMatches",{enumerable:!0,get:function(){return E.applyMatches}});Object.defineProperty(s,"PATTERNS",{enumerable:!0,get:function(){return E.PATTERNS}});Object.defineProperty(s,"MAX_BYTES",{enumerable:!0,get:function(){return E.MAX_BYTES}});var y=C();Object.defineProperty(s,"ulidToTraceId",{enumerable:!0,get:function(){return y.ulidToTraceId}});Object.defineProperty(s,"newSpanId",{enumerable:!0,get:function(){return y.newSpanId}});Object.defineProperty(s,"snakeCase",{enumerable:!0,get:function(){return y.snakeCase}});Object.defineProperty(s,"toOtlpValue",{enumerable:!0,get:function(){return y.toOtlpValue}});Object.defineProperty(s,"attrsFromRecord",{enumerable:!0,get:function(){return y.attrsFromRecord}});Object.defineProperty(s,"guardAttrs",{enumerable:!0,get:function(){return y.guardAttrs}});Object.defineProperty(s,"buildPayload",{enumerable:!0,get:function(){return y.buildPayload}});Object.defineProperty(s,"mergeBatch",{enumerable:!0,get:function(){return y.mergeBatch}});var Mt=de();Object.defineProperty(s,"evaluateGuard",{enumerable:!0,get:function(){return Mt.evaluateGuard}});var xe=B();Object.defineProperty(s,"DiskRetryQueue",{enumerable:!0,get:function(){return xe.DiskRetryQueue}});Object.defineProperty(s,"MemoryRetryQueue",{enumerable:!0,get:function(){return xe.MemoryRetryQueue}});var b=Pe();Object.defineProperty(s,"DiskTransport",{enumerable:!0,get:function(){return b.DiskTransport}});Object.defineProperty(s,"MemoryTransport",{enumerable:!0,get:function(){return b.MemoryTransport}});Object.defineProperty(s,"postOtlp",{enumerable:!0,get:function(){return b.postOtlp}});Object.defineProperty(s,"envOptionsResolver",{enumerable:!0,get:function(){return b.envOptionsResolver}});Object.defineProperty(s,"parseHeadersEnv",{enumerable:!0,get:function(){return b.parseHeadersEnv}});var Ae=Y();Object.defineProperty(s,"TraceManager",{enumerable:!0,get:function(){return Ae.TraceManager}});Object.defineProperty(s,"generateUlid",{enumerable:!0,get:function(){return Ae.generateUlid}});var Re=Se();Object.defineProperty(s,"DiskSessionTraceManager",{enumerable:!0,get:function(){return Re.DiskSessionTraceManager}});Object.defineProperty(s,"MemorySessionTraceManager",{enumerable:!0,get:function(){return Re.MemorySessionTraceManager}});var W=we();Object.defineProperty(s,"envFilePath",{enumerable:!0,get:function(){return W.envFilePath}});Object.defineProperty(s,"parseEnvFile",{enumerable:!0,get:function(){return W.parseEnvFile}});Object.defineProperty(s,"loadEnvFile",{enumerable:!0,get:function(){return W.loadEnvFile}})});var k=d(T());function It(){return(0,k.envFilePath)(".claude","pinta-cc.env")}function je(t=It()){(0,k.loadEnvFile)(t)}function De(){process.env.CLAUDE_PLUGIN_OPTION_ENDPOINT&&!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT&&(process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=process.env.CLAUDE_PLUGIN_OPTION_ENDPOINT),process.env.CLAUDE_PLUGIN_OPTION_API_KEY&&!process.env.OTEL_EXPORTER_OTLP_HEADERS&&(process.env.OTEL_EXPORTER_OTLP_HEADERS=`x-pinta-relay-token=${process.env.CLAUDE_PLUGIN_OPTION_API_KEY}`),!process.env.PINTA_RELAY_TOKEN&&process.env.CLAUDE_PLUGIN_OPTION_API_KEY&&(process.env.PINTA_RELAY_TOKEN=process.env.CLAUDE_PLUGIN_OPTION_API_KEY)}var Q=d(require("path"));function Me(){let t=process.env.CLAUDE_PLUGIN_ROOT||process.cwd(),e=process.env.CLAUDE_PLUGIN_DATA||Q.default.join(t,".plugin-data");return{pluginRoot:t,pluginData:e,tracePath:Q.default.join(e,"trace.json")}}function Ie(t){return t.hook_event_name==="PreToolUse"}function Ne(t){return t.hook_event_name==="PostToolUse"||t.hook_event_name==="PostToolUseFailure"}function Ce(t){return t.hook_event_name==="UserPromptSubmit"}function Ue(t){return t.hook_event_name==="SessionStart"||t.hook_event_name==="SessionEnd"}function Le(t){return t.hook_event_name==="SubagentStart"||t.hook_event_name==="SubagentStop"}function qe(t){return t.hook_event_name==="Stop"}function Be(t){return t.hook_event_name==="PermissionRequest"||t.hook_event_name==="PermissionDenied"}var Nt=new Set(["Notification","TaskCreated","TaskCompleted"]);function Fe(t){return Nt.has(t.hook_event_name)}var Ge=d(T()),Ct=1e4,Ut="pinta-cc/1.5.0";function Ve(t,e){return(0,Ge.evaluateGuard)(t,e,{timeoutMs:Ct,token:process.env.PINTA_RELAY_TOKEN??"",disabled:process.env.PINTA_GUARD_DISABLED==="1",userAgent:Ut})}var $e=d(T()),j=class extends $e.DiskTransport{constructor(e){super({pluginData:e.pluginData,logPrefix:"pinta-cc"})}};var Ke=d(T()),D=class extends Ke.TraceManager{constructor(e){super(e.tracePath)}};var Xe=d(require("fs")),I=d(require("os")),w=d(require("path")),O=d(T()),Ye="1.5.0",M=null;function Lt(){return M!==null||(M=Bt()??"unknown"),M}var qt=6;function Bt(){let t=process.env.CLAUDE_CODE_EXECPATH;if(!t)return null;let e=w.default.dirname(t),r=w.default.parse(e).root;for(let n=0;n<qt&&e!==r;n++){let o=w.default.join(e,"package.json");try{let i=Xe.default.readFileSync(o,"utf-8"),a=JSON.parse(i);if(typeof a.name=="string"&&a.name.startsWith("@anthropic-ai/claude-code")&&typeof a.version=="string")return a.version}catch{}e=w.default.dirname(e)}return null}var Ft=new Set(["cc.hook","cc.tool_name","cc.tool_use_id","cc.session_id","cc.transcript_path","cc.cwd","cc.permission_mode"]),Gt=new Set(["cc.tool_input","cc.tool_response"]),Vt={skipRedactKeys:Ft,bashContextKeys:Gt};function $t(t){let e=[];e.push({key:"ingest.type",value:{stringValue:"cc"}}),e.push({key:"cc.hook",value:{stringValue:t.hook_event_name}});let r={};for(let[n,o]of Object.entries(t))n!=="hook_event_name"&&(r[n]=o);return e.push(...(0,O.attrsFromRecord)(r,"cc",Vt)),e}function Kt(){return[{key:"service.name",value:{stringValue:"claude-code"}},{key:"service.version",value:{stringValue:Lt()}},{key:"telemetry.sdk.name",value:{stringValue:"pinta-cc"}},{key:"telemetry.sdk.language",value:{stringValue:"nodejs"}},{key:"telemetry.sdk.version",value:{stringValue:Ye}},{key:"process.pid",value:{intValue:process.pid}},{key:"process.owner",value:{stringValue:I.default.userInfo().username}},{key:"host.name",value:{stringValue:I.default.hostname()}},{key:"host.arch",value:{stringValue:I.default.arch()}}]}function Ze(t){return(0,O.buildPayload)({traceId:t.traceId,spanName:`cc.${(0,O.snakeCase)(t.event.hook_event_name)}`,attributes:$t(t.event),resource:Kt(),scope:{name:"pinta-cc",version:Ye},now:t.now,guard:t.guard})}async function l(t,e,r={}){let n=new j(e);await n.flush();let o=new D(e),i=r.traceMode==="new"?o.newTrace():o.currentTrace(),a=Ze({event:t,traceId:i,guard:r.guard});await n.send(a)}async function Je(t,e){let r=typeof t.tool_input=="string"?t.tool_input:JSON.stringify(t.tool_input),n=await Ve({spanId:t.session_id??"unknown",toolName:t.tool_name,toolInput:t.tool_input,rawTextFields:{toolInput:r}},process.env.PINTA_GUARD_ENDPOINT);if(await l(t,e,{guard:n}),n?.decision==="DENY"){let i={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:n.userMessage??n.reason??"guard_deny"}};process.stdout.write(JSON.stringify(i)+`
13
- `)}return 0}async function ze(t,e){return await l(t,e),0}async function He(t,e){return await l(t,e,{traceMode:"new"}),0}async function We(t,e){return await l(t,e),0}async function Qe(t,e){return await l(t,e),0}async function et(t,e){return await l(t,e),0}async function tt(t,e){return await l(t,e),0}async function ee(t){return 0}je();async function Xt(){let t=[];for await(let e of process.stdin)t.push(e);return Buffer.concat(t).toString("utf-8")}async function Yt(){De();let t=0;try{let e=Me(),r=await Xt(),n=JSON.parse(r);Fe(n)?t=await ee(n):Ie(n)?t=await Je(n,e):Ne(n)?t=await ze(n,e):Ce(n)?t=await He(n,e):Ue(n)?t=await We(n,e):Le(n)?t=await Qe(n,e):qe(n)?t=await et(n,e):Be(n)?t=await tt(n,e):t=await ee(n)}catch(e){process.stderr.write(`[pinta-cc] error: ${e}
14
- `),t=0}process.exit(t)}Yt();
11
+ `),!1}finally{clearTimeout(o)}}var F=class{queue;logPrefix;resolveOptions;constructor(t){this.queue=new he.DiskRetryQueue(t.pluginData,t.logPrefix),this.logPrefix=t.logPrefix,this.resolveOptions=t.resolveOptions??ve}async send(t){let r=this.resolveOptions();if(!r)return;await O(t,r,this.logPrefix)||this.queue.enqueue(t)}async flush(){let t=this.resolveOptions();if(t&&this.queue.tryAcquireLock())try{let r=this.queue.readAll();if(r.length===0)return;let n=(0,ye.mergeBatch)(r.map(i=>i.payload));await O(n,t,this.logPrefix)&&this.queue.rewrite([])}finally{this.queue.release()}}};_.DiskTransport=F;var G=class{queue=new he.MemoryRetryQueue;logPrefix;resolveOptions;constructor(t){this.logPrefix=t.logPrefix,this.resolveOptions=t.resolveOptions}async send(t){let r=this.resolveOptions();if(!r)return;await O(t,r,this.logPrefix)||this.queue.enqueue(t)}async flush(){let t=this.resolveOptions();if(!t)return;let r=this.queue.drain();if(r.length===0)return;let n=(0,ye.mergeBatch)(r);if(!await O(n,t,this.logPrefix))for(let i of r)this.queue.enqueue(i)}};_.MemoryTransport=G});var Y=d(P=>{"use strict";var X=P&&P.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(P,"__esModule",{value:!0});P.TraceManager=void 0;P.generateUlid=Te;var V=X(require("fs")),At=X(require("path")),Rt=X(require("crypto")),$="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function Te(){let e=Date.now(),t="",r=e;for(let i=0;i<10;i++)t=$[r&31]+t,r=Math.floor(r/32);let n=Rt.default.randomBytes(10),o="";for(let i=0;i<10;i++)o+=$[n[i]&31];for(;o.length<16;)o+=$[0];return t+o}var K=class{tracePath;constructor(t){this.tracePath=t}newTrace(){let t=Te();return this.save(t),t}currentTrace(){try{let t=V.default.readFileSync(this.tracePath,"utf-8"),{traceId:r}=JSON.parse(t);if(r)return r}catch{}return this.newTrace()}save(t){V.default.mkdirSync(At.default.dirname(this.tracePath),{recursive:!0}),V.default.writeFileSync(this.tracePath,JSON.stringify({traceId:t}))}};P.TraceManager=K});var ke=d(y=>{"use strict";var Se=y&&y.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(y,"__esModule",{value:!0});y.MemorySessionTraceManager=y.DiskSessionTraceManager=void 0;var Z=Se(require("fs")),jt=Se(require("path")),Oe=Y(),be=200,H=class{tracePath;maxSessions;constructor(t,r={}){this.tracePath=t,this.maxSessions=r.maxSessions??be}read(){try{let t=JSON.parse(Z.default.readFileSync(this.tracePath,"utf-8"));if(t&&typeof t=="object"&&!("traceId"in t))return t}catch{}return{}}write(t){try{Z.default.mkdirSync(jt.default.dirname(this.tracePath),{recursive:!0});let r=Object.entries(t),n=r.length>this.maxSessions?Object.fromEntries(r.slice(-this.maxSessions)):t;Z.default.writeFileSync(this.tracePath,JSON.stringify(n))}catch{}}newTrace(t){let r=t||"default",n=(0,Oe.generateUlid)(),o=this.read();return o[r]=n,this.write(o),n}currentTrace(t){let r=t||"default",n=this.read()[r];return n||this.newTrace(r)}};y.DiskSessionTraceManager=H;var J=class{map=new Map;maxSessions;constructor(t={}){this.maxSessions=t.maxSessions??be}newTrace(t){let r=t||"default",n=(0,Oe.generateUlid)();if(this.map.set(r,n),this.map.size>this.maxSessions){let o=this.map.keys().next().value;o!==void 0&&this.map.delete(o)}return n}currentTrace(t){let r=t||"default";return this.map.get(r)??this.newTrace(r)}};y.MemorySessionTraceManager=J});var Ae=d(v=>{"use strict";var z=v&&v.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(v,"__esModule",{value:!0});v.envFilePath=It;v.parseEnvFile=xe;v.loadEnvFile=Nt;var Mt=z(require("node:fs")),Dt=z(require("node:os")),we=z(require("node:path"));function It(e,t,r){let n=r?process.env[r]:void 0,o=n&&n.length>0?n:we.default.join(Dt.default.homedir(),e);return we.default.join(o,t)}function xe(e){let t={};for(let r of e.split(`
12
+ `)){let n=r.trim();if(!n||n.startsWith("#"))continue;let o=n.indexOf("=");if(o<0)continue;let i=n.slice(0,o).trim(),a=n.slice(o+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),i&&(t[i]=a)}return t}function Nt(e){let t;try{t=Mt.default.readFileSync(e,"utf-8")}catch{return}let r=xe(t);for(let[n,o]of Object.entries(r))process.env[n]===void 0&&(process.env[n]=o)}});var T=d(s=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0});s.loadEnvFile=s.parseEnvFile=s.envFilePath=s.MemorySessionTraceManager=s.DiskSessionTraceManager=s.generateUlid=s.TraceManager=s.parseHeadersEnv=s.envOptionsResolver=s.postOtlp=s.MemoryTransport=s.DiskTransport=s.MemoryRetryQueue=s.DiskRetryQueue=s.evaluateGuard=s.mergeBatch=s.buildPayload=s.clientAttrs=s.guardAttrs=s.attrsFromRecord=s.toOtlpValue=s.snakeCase=s.newSpanId=s.ulidToTraceId=s.MAX_BYTES=s.PATTERNS=s.applyMatches=s.resolveOverlaps=s.collectMatches=s.truncate=s.redact=void 0;var E=N();Object.defineProperty(s,"redact",{enumerable:!0,get:function(){return E.redact}});Object.defineProperty(s,"truncate",{enumerable:!0,get:function(){return E.truncate}});Object.defineProperty(s,"collectMatches",{enumerable:!0,get:function(){return E.collectMatches}});Object.defineProperty(s,"resolveOverlaps",{enumerable:!0,get:function(){return E.resolveOverlaps}});Object.defineProperty(s,"applyMatches",{enumerable:!0,get:function(){return E.applyMatches}});Object.defineProperty(s,"PATTERNS",{enumerable:!0,get:function(){return E.PATTERNS}});Object.defineProperty(s,"MAX_BYTES",{enumerable:!0,get:function(){return E.MAX_BYTES}});var g=C();Object.defineProperty(s,"ulidToTraceId",{enumerable:!0,get:function(){return g.ulidToTraceId}});Object.defineProperty(s,"newSpanId",{enumerable:!0,get:function(){return g.newSpanId}});Object.defineProperty(s,"snakeCase",{enumerable:!0,get:function(){return g.snakeCase}});Object.defineProperty(s,"toOtlpValue",{enumerable:!0,get:function(){return g.toOtlpValue}});Object.defineProperty(s,"attrsFromRecord",{enumerable:!0,get:function(){return g.attrsFromRecord}});Object.defineProperty(s,"guardAttrs",{enumerable:!0,get:function(){return g.guardAttrs}});Object.defineProperty(s,"clientAttrs",{enumerable:!0,get:function(){return g.clientAttrs}});Object.defineProperty(s,"buildPayload",{enumerable:!0,get:function(){return g.buildPayload}});Object.defineProperty(s,"mergeBatch",{enumerable:!0,get:function(){return g.mergeBatch}});var Ct=_e();Object.defineProperty(s,"evaluateGuard",{enumerable:!0,get:function(){return Ct.evaluateGuard}});var Re=B();Object.defineProperty(s,"DiskRetryQueue",{enumerable:!0,get:function(){return Re.DiskRetryQueue}});Object.defineProperty(s,"MemoryRetryQueue",{enumerable:!0,get:function(){return Re.MemoryRetryQueue}});var b=Ee();Object.defineProperty(s,"DiskTransport",{enumerable:!0,get:function(){return b.DiskTransport}});Object.defineProperty(s,"MemoryTransport",{enumerable:!0,get:function(){return b.MemoryTransport}});Object.defineProperty(s,"postOtlp",{enumerable:!0,get:function(){return b.postOtlp}});Object.defineProperty(s,"envOptionsResolver",{enumerable:!0,get:function(){return b.envOptionsResolver}});Object.defineProperty(s,"parseHeadersEnv",{enumerable:!0,get:function(){return b.parseHeadersEnv}});var je=Y();Object.defineProperty(s,"TraceManager",{enumerable:!0,get:function(){return je.TraceManager}});Object.defineProperty(s,"generateUlid",{enumerable:!0,get:function(){return je.generateUlid}});var Me=ke();Object.defineProperty(s,"DiskSessionTraceManager",{enumerable:!0,get:function(){return Me.DiskSessionTraceManager}});Object.defineProperty(s,"MemorySessionTraceManager",{enumerable:!0,get:function(){return Me.MemorySessionTraceManager}});var W=Ae();Object.defineProperty(s,"envFilePath",{enumerable:!0,get:function(){return W.envFilePath}});Object.defineProperty(s,"parseEnvFile",{enumerable:!0,get:function(){return W.parseEnvFile}});Object.defineProperty(s,"loadEnvFile",{enumerable:!0,get:function(){return W.loadEnvFile}})});var k=m(T());function Ut(){return(0,k.envFilePath)(".claude","pinta-cc.env")}function De(e=Ut()){(0,k.loadEnvFile)(e)}function Ie(){process.env.CLAUDE_PLUGIN_OPTION_ENDPOINT&&!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT&&(process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=process.env.CLAUDE_PLUGIN_OPTION_ENDPOINT),process.env.CLAUDE_PLUGIN_OPTION_API_KEY&&!process.env.OTEL_EXPORTER_OTLP_HEADERS&&(process.env.OTEL_EXPORTER_OTLP_HEADERS=`x-pinta-relay-token=${process.env.CLAUDE_PLUGIN_OPTION_API_KEY}`),!process.env.PINTA_RELAY_TOKEN&&process.env.CLAUDE_PLUGIN_OPTION_API_KEY&&(process.env.PINTA_RELAY_TOKEN=process.env.CLAUDE_PLUGIN_OPTION_API_KEY)}var Q=m(require("path"));function Ne(){let e=process.env.CLAUDE_PLUGIN_ROOT||process.cwd(),t=process.env.CLAUDE_PLUGIN_DATA||Q.default.join(e,".plugin-data");return{pluginRoot:e,pluginData:t,tracePath:Q.default.join(t,"trace.json")}}function Ce(e){return e.hook_event_name==="PreToolUse"}function Ue(e){return e.hook_event_name==="PostToolUse"||e.hook_event_name==="PostToolUseFailure"}function Le(e){return e.hook_event_name==="UserPromptSubmit"}function qe(e){return e.hook_event_name==="SessionStart"||e.hook_event_name==="SessionEnd"}function Be(e){return e.hook_event_name==="SubagentStart"||e.hook_event_name==="SubagentStop"}function Fe(e){return e.hook_event_name==="Stop"}function Ge(e){return e.hook_event_name==="PermissionRequest"||e.hook_event_name==="PermissionDenied"}var Lt=new Set(["Notification","TaskCreated","TaskCompleted"]);function Ve(e){return Lt.has(e.hook_event_name)}var $e=m(T()),qt=1e4,Bt="pinta-cc/1.6.0";function Ke(e,t){return(0,$e.evaluateGuard)(e,t,{timeoutMs:qt,token:process.env.PINTA_RELAY_TOKEN??"",disabled:process.env.PINTA_GUARD_DISABLED==="1",userAgent:Bt})}var Xe=m(T()),j=class extends Xe.DiskTransport{constructor(t){super({pluginData:t.pluginData,logPrefix:"pinta-cc"})}};var Ye=m(T()),M=class extends Ye.TraceManager{constructor(t){super(t.tracePath)}};var Ze=m(require("fs")),I=m(require("os")),w=m(require("path")),S=m(T()),He="1.6.0",D=null;function Ft(){return D!==null||(D=Vt()??"unknown"),D}var Gt=6;function Vt(){let e=process.env.CLAUDE_CODE_EXECPATH;if(!e)return null;let t=w.default.dirname(e),r=w.default.parse(t).root;for(let n=0;n<Gt&&t!==r;n++){let o=w.default.join(t,"package.json");try{let i=Ze.default.readFileSync(o,"utf-8"),a=JSON.parse(i);if(typeof a.name=="string"&&a.name.startsWith("@anthropic-ai/claude-code")&&typeof a.version=="string")return a.version}catch{}t=w.default.dirname(t)}return null}var $t=new Set(["cc.hook","cc.tool_name","cc.tool_use_id","cc.session_id","cc.transcript_path","cc.cwd","cc.permission_mode"]),Kt=new Set(["cc.tool_input","cc.tool_response"]),Xt={skipRedactKeys:$t,bashContextKeys:Kt};function Yt(e){let t=[];t.push({key:"ingest.type",value:{stringValue:"cc"}}),t.push({key:"cc.hook",value:{stringValue:e.hook_event_name}});let r={};for(let[n,o]of Object.entries(e))n!=="hook_event_name"&&(r[n]=o);return t.push(...(0,S.attrsFromRecord)(r,"cc",Xt)),t}function Zt(){return[{key:"service.name",value:{stringValue:"claude-code"}},{key:"service.version",value:{stringValue:Ft()}},{key:"telemetry.sdk.name",value:{stringValue:"pinta-cc"}},{key:"telemetry.sdk.language",value:{stringValue:"nodejs"}},{key:"telemetry.sdk.version",value:{stringValue:He}},{key:"process.pid",value:{intValue:process.pid}},{key:"process.owner",value:{stringValue:I.default.userInfo().username}},{key:"host.name",value:{stringValue:I.default.hostname()}},{key:"host.arch",value:{stringValue:I.default.arch()}}]}function Je(e){return(0,S.buildPayload)({traceId:e.traceId,spanName:`cc.${(0,S.snakeCase)(e.event.hook_event_name)}`,attributes:Yt(e.event),resource:Zt(),scope:{name:"pinta-cc",version:He},now:e.now,guard:e.guard})}async function l(e,t,r={}){let n=new j(t);await n.flush();let o=new M(t),i=r.traceMode==="new"?o.newTrace():o.currentTrace(),a=Je({event:e,traceId:i,guard:r.guard});await n.send(a)}async function ze(e,t){let r=typeof e.tool_input=="string"?e.tool_input:JSON.stringify(e.tool_input),n=await Ke({spanId:e.session_id??"unknown",toolName:e.tool_name,toolInput:e.tool_input,rawTextFields:{toolInput:r}},process.env.PINTA_GUARD_ENDPOINT);if(await l(e,t,{guard:n}),n?.decision==="DENY"){let i={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:n.userMessage??n.reason??"guard_deny"}};process.stdout.write(JSON.stringify(i)+`
13
+ `)}return 0}async function We(e,t){return await l(e,t),0}async function Qe(e,t){return await l(e,t,{traceMode:"new"}),0}async function et(e,t){return await l(e,t),0}async function tt(e,t){return await l(e,t),0}async function rt(e,t){return await l(e,t),0}async function nt(e,t){return await l(e,t),0}async function ee(e){return 0}async function Ht(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf-8")}async function ot(){Ie();let e=0;try{let t=Ne(),r=await Ht(),n=JSON.parse(r);Ve(n)?e=await ee(n):Ce(n)?e=await ze(n,t):Ue(n)?e=await We(n,t):Le(n)?e=await Qe(n,t):qe(n)?e=await et(n,t):Be(n)?e=await tt(n,t):Fe(n)?e=await rt(n,t):Ge(n)?e=await nt(n,t):e=await ee(n)}catch(t){process.stderr.write(`[pinta-cc] error: ${t}
14
+ `),e=0}return e}De();async function Jt(){let e=await ot();process.exit(e)}Jt();
package/dist/index.mjs ADDED
@@ -0,0 +1,15 @@
1
+ import{createRequire as __pintaCreateRequire}from 'node:module';const require=__pintaCreateRequire(import.meta.url);
2
+ var pt=Object.create;var oe=Object.defineProperty;var ft=Object.getOwnPropertyDescriptor;var dt=Object.getOwnPropertyNames;var mt=Object.getPrototypeOf,gt=Object.prototype.hasOwnProperty;var d=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var m=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var _t=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of dt(t))!gt.call(e,o)&&o!==r&&oe(e,o,{get:()=>t[o],enumerable:!(n=ft(t,o))||n.enumerable});return e};var O=(e,t,r)=>(r=e!=null?pt(mt(e)):{},_t(t||!e||!e.__esModule?oe(r,"default",{value:e,enumerable:!0}):r,e));var N=m(u=>{"use strict";Object.defineProperty(u,"__esModule",{value:!0});u.PATTERNS=u.MAX_BYTES=void 0;u.truncate=ht;u.collectMatches=se;u.resolveOverlaps=ie;u.applyMatches=ae;u.redact=yt;u.MAX_BYTES=102400;function ht(e){let t=Buffer.from(e,"utf-8");return t.length<=u.MAX_BYTES?e:`${t.subarray(0,u.MAX_BYTES).toString("utf-8")}\u2026[TRUNCATED:${t.length}]`}u.PATTERNS=[{type:"aws_access_key",regex:/AKIA[0-9A-Z]{16}/g},{type:"aws_secret_key",regex:/(?:aws[_-]?secret(?:[_-]?(?:access)?[_-]?key)?)\s*[:=]\s*["']?([A-Za-z0-9/+=]{40})(?![A-Za-z0-9/+=])/gi,captureGroup:1},{type:"gcp_service_account",regex:/\{[\s\S]{0,200}?"type"\s*:\s*"service_account"[\s\S]*?\}/g},{type:"github_token",regex:/gh[pousr]_[A-Za-z0-9]{36,}/g},{type:"gitlab_token",regex:/glpat-[A-Za-z0-9_-]{20}/g},{type:"slack_token",regex:/xox[abrsp]-[0-9A-Za-z-]{10,}/g},{type:"openai_key",regex:/sk-(?:proj-)?[A-Za-z0-9_-]{40,}/g},{type:"anthropic_key",regex:/sk-ant-[A-Za-z0-9_-]{50,}/g},{type:"stripe_key",regex:/(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{20,}/g},{type:"jwt",regex:/eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g},{type:"private_key_block",regex:/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g},{type:"bearer_token",regex:/bearer\s+([A-Za-z0-9._~+/=-]{12,})/gi,captureGroup:1},{type:"basic_auth",regex:/basic\s+([A-Za-z0-9+/=]{12,})/gi,captureGroup:1},{type:"db_url_password",regex:/\b(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|redis):\/\/[^:\s/]+:([^@\s]+)@/gi,captureGroup:1},{type:"cli_password_flag",regex:/(?:--password|--pass|--pwd)[=\s]([^\s'"]+)/g,captureGroup:1},{type:"cli_password_short",regex:/\s-p([^\s'"]+)/g,captureGroup:1,requireContext:"bash"},{type:"env_var_secret",regex:/^(?:export\s+)?([A-Z][A-Z0-9_]*(?:KEY|SECRET|TOKEN|PASSWORD|PASSWD|PWD|API_KEY)[A-Z0-9_]*)\s*=\s*["']?([^\s"'\n]+)/gm,captureGroup:2}];function se(e,t){let r=[];for(let n of u.PATTERNS){if(n.requireContext&&n.requireContext!==t.context)continue;let o=new RegExp(n.regex.source,n.regex.flags),i;for(;(i=o.exec(e))!==null;){let a=n.captureGroup??0,p=i[a];if(p===void 0){i.index===o.lastIndex&&o.lastIndex++;continue}let re=i.index,ct=i.index+i[0].length,ne=re+i[0].indexOf(p),lt=ne+p.length;r.push({start:re,end:ct,replaceStart:ne,replaceEnd:lt,type:n.type}),i.index===o.lastIndex&&o.lastIndex++}}return r}function ie(e){let t=[...e].sort((o,i)=>o.start!==i.start?o.start-i.start:i.end-i.start-(o.end-o.start)),r=[],n=-1;for(let o of t)o.start<n||(r.push(o),n=o.end);return r}function ae(e,t){let r=[...t].sort((o,i)=>i.replaceStart-o.replaceStart),n=e;for(let o of r)n=n.slice(0,o.replaceStart)+`[REDACTED:${o.type}]`+n.slice(o.replaceEnd);return n}function yt(e,t={}){if(e.length===0)return e;let r=se(e,t);if(r.length===0)return e;let n=ie(r);return ae(e,n)}});var U=m(f=>{"use strict";var Pt=f&&f.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(f,"__esModule",{value:!0});f.ulidToTraceId=le;f.newSpanId=pe;f.snakeCase=Tt;f.toOtlpValue=fe;f.attrsFromRecord=St;f.guardAttrs=de;f.clientAttrs=me;f.buildPayload=Ot;f.mergeBatch=bt;var vt=Pt(d("crypto")),ue=N(),Et="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function le(e){if(e.length!==26)throw new Error(`ulidToTraceId: expected 26 chars, got ${e.length}`);let t=0n;for(let n of e){let o=Et.indexOf(n);if(o<0)throw new Error(`ulidToTraceId: invalid Crockford char "${n}"`);t=t<<5n|BigInt(o)}let r=(1n<<128n)-1n;return t&=r,t.toString(16).padStart(32,"0")}function pe(){return vt.default.randomBytes(8).toString("hex")}function Tt(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()}var ce=new Set;function A(e,t,r){let n=(0,ue.truncate)(t);if((r.skipRedactKeys??ce).has(e))return n;let o=(r.bashContextKeys??ce).has(e)?"bash":void 0;return(0,ue.redact)(n,{context:o})}function fe(e,t,r={}){if(t==null)return null;switch(typeof t){case"string":return{stringValue:A(e,t,r)};case"boolean":return{boolValue:t};case"number":return Number.isInteger(t)?{intValue:t}:{doubleValue:t};case"object":try{return{stringValue:A(e,JSON.stringify(t),r)}}catch{return{stringValue:A(e,String(t),r)}}default:return{stringValue:A(e,String(t),r)}}}function St(e,t,r={}){let n=[];for(let[o,i]of Object.entries(e)){let a=`${t}.${o}`,p=fe(a,i,r);p!==null&&n.push({key:a,value:p})}return n}function de(e){let t=[{key:"pinta.guard.decision",value:{stringValue:e.decision.toLowerCase()}},{key:"pinta.guard.duration_ms",value:{intValue:e.durationMs}}];return e.reason&&t.push({key:"pinta.guard.matched_rule",value:{stringValue:e.reason}}),e.failOpenReason&&t.push({key:"pinta.guard.fail_open_reason",value:{stringValue:e.failOpenReason}}),t}function me(e){return[{key:"pinta.client.rtt_ms",value:Number.isInteger(e.rttMs)?{intValue:e.rttMs}:{doubleValue:e.rttMs}},{key:"pinta.client.op",value:{stringValue:e.op}}]}function Ot(e){let t=e.now??Date.now(),r=(BigInt(t)*1000000n).toString(),n=[...e.attributes];e.guard&&n.push(...de(e.guard));let o=e.clientTiming??(e.guard?.clientRttMs!==void 0?{op:"guard",rttMs:e.guard.clientRttMs}:null);o&&n.push(...me(o));let i={traceId:le(e.traceId),spanId:pe(),name:e.spanName,kind:e.spanKind??1,startTimeUnixNano:r,endTimeUnixNano:r,attributes:n};return{resourceSpans:[{resource:{attributes:e.resource},scopeSpans:[{scope:e.scope,spans:[i]}]}]}}function bt(e){let t=[];for(let r of e)t.push(...r.resourceSpans);return{resourceSpans:t}}});var _e=m(L=>{"use strict";Object.defineProperty(L,"__esModule",{value:!0});L.evaluateGuard=At;var kt=1e4,wt="pinta-core";function ge(e,t){return{decision:"ALLOW",reason:null,userMessage:null,durationMs:e,clientRttMs:e,failOpenReason:t}}function xt(e){return new Promise((t,r)=>setTimeout(()=>{let n=new Error("Guard request timed out");n.name="TimeoutError",r(n)},e))}async function At(e,t,r={}){if(!t||r.disabled)return null;let n=r.timeoutMs??kt,o=Date.now();try{let i=await Promise.race([fetch(t,{method:"POST",headers:{"content-type":"application/json","user-agent":r.userAgent??wt,"x-pinta-relay-token":r.token??""},body:JSON.stringify({input:e})}),xt(n)]);if(i.status!==200)return ge(Date.now()-o,"error");let a=await i.json(),p=Date.now()-o;return{decision:a.decision,reason:a.reason,userMessage:a.userMessage??null,durationMs:a.durationMs??p,clientRttMs:p}}catch(i){let a=i.name==="TimeoutError"?"timeout":"error";return ge(Date.now()-o,a)}}});var B=m(h=>{"use strict";var he=h&&h.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(h,"__esModule",{value:!0});h.MemoryRetryQueue=h.DiskRetryQueue=void 0;var c=he(d("fs")),j=he(d("path")),R=1e3,jt=50,Rt=5,F=class{filePath;lockPath;logPrefix;constructor(t,r){this.filePath=j.default.join(t,"failed-spans.jsonl"),this.lockPath=this.filePath+".lock",this.logPrefix=r}enqueue(t){try{c.default.mkdirSync(j.default.dirname(this.filePath),{recursive:!0});let r=JSON.stringify({savedAt:new Date().toISOString(),payload:t})+`
3
+ `;c.default.appendFileSync(this.filePath,r),this.trim()}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue enqueue failed: ${r}
4
+ `)}}readAll(){try{let t=c.default.readFileSync(this.filePath,"utf-8"),r=[];for(let n of t.split(`
5
+ `))if(n.trim())try{r.push(JSON.parse(n))}catch{}return r}catch{return[]}}rewrite(t){try{if(t.length===0){c.default.existsSync(this.filePath)&&c.default.unlinkSync(this.filePath);return}c.default.mkdirSync(j.default.dirname(this.filePath),{recursive:!0}),c.default.writeFileSync(this.filePath,t.map(r=>JSON.stringify(r)).join(`
6
+ `)+`
7
+ `)}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue rewrite failed: ${r}
8
+ `)}}tryAcquireLock(){let t=Date.now();for(c.default.mkdirSync(j.default.dirname(this.lockPath),{recursive:!0});Date.now()-t<jt;)try{let r=c.default.openSync(this.lockPath,"wx");return c.default.writeSync(r,String(process.pid)),c.default.closeSync(r),!0}catch(r){if(r?.code!=="EEXIST")return process.stderr.write(`[${this.logPrefix}] retry-queue lock open failed: ${r}
9
+ `),!1;try{let i=c.default.statSync(this.lockPath);if(Date.now()-i.mtimeMs>3e4){c.default.unlinkSync(this.lockPath);continue}}catch{}let n=Rt,o=Date.now()+n;for(;Date.now()<o;);}return!1}release(){try{c.default.unlinkSync(this.lockPath)}catch{}}trim(){let t=this.readAll();if(t.length<=R)return;let r=t.length-R;process.stderr.write(`[${this.logPrefix}] retry-queue full, dropping ${r} oldest entries
10
+ `),this.rewrite(t.slice(r))}};h.DiskRetryQueue=F;var q=class{entries=[];enqueue(t){this.entries.push(t),this.entries.length>R&&this.entries.splice(0,this.entries.length-R)}drain(){let t=this.entries;return this.entries=[],t}get size(){return this.entries.length}};h.MemoryRetryQueue=q});var Te=m(g=>{"use strict";Object.defineProperty(g,"__esModule",{value:!0});g.MemoryTransport=g.DiskTransport=void 0;g.parseHeadersEnv=ve;g.envOptionsResolver=Ee;g.postOtlp=b;var ye=B(),Pe=U(),Dt=5e3;function ve(e){if(!e)return{};if(typeof e=="object")return{...e};let t={};for(let r of e.split(",")){let[n,...o]=r.split("=");n&&o.length>0&&(t[n.trim()]=o.join("=").trim())}return t}function Ee(){let e=process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,t=process.env.OTEL_EXPORTER_OTLP_ENDPOINT,r;return e?r=e.replace(/\/+$/,""):t&&(r=t.replace(/\/+$/,"")+"/v1/traces"),r?{endpoint:r,headers:ve(process.env.OTEL_EXPORTER_OTLP_HEADERS)}:null}async function b(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),Dt);try{let i=await fetch(t.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...t.headers},body:JSON.stringify(e),signal:n.signal});if(!i.ok){let a="";try{a=(await i.text()).slice(0,200)}catch{}let p=i.status===401||i.status===403?" \u2014 check OTEL_EXPORTER_OTLP_HEADERS (relay token)":i.status===404?" \u2014 check OTEL_EXPORTER_OTLP_TRACES_ENDPOINT path":i.status>=500?" \u2014 collector may be down":"";return process.stderr.write(`[${r}] OTLP POST ${i.status} ${t.endpoint}${p}${a?` body=${a}`:""}
11
+ `),!1}return!0}catch(i){return process.stderr.write(`[${r}] OTLP POST failed: ${i.message??String(i)}
12
+ `),!1}finally{clearTimeout(o)}}var G=class{queue;logPrefix;resolveOptions;constructor(t){this.queue=new ye.DiskRetryQueue(t.pluginData,t.logPrefix),this.logPrefix=t.logPrefix,this.resolveOptions=t.resolveOptions??Ee}async send(t){let r=this.resolveOptions();if(!r)return;await b(t,r,this.logPrefix)||this.queue.enqueue(t)}async flush(){let t=this.resolveOptions();if(t&&this.queue.tryAcquireLock())try{let r=this.queue.readAll();if(r.length===0)return;let n=(0,Pe.mergeBatch)(r.map(i=>i.payload));await b(n,t,this.logPrefix)&&this.queue.rewrite([])}finally{this.queue.release()}}};g.DiskTransport=G;var V=class{queue=new ye.MemoryRetryQueue;logPrefix;resolveOptions;constructor(t){this.logPrefix=t.logPrefix,this.resolveOptions=t.resolveOptions}async send(t){let r=this.resolveOptions();if(!r)return;await b(t,r,this.logPrefix)||this.queue.enqueue(t)}async flush(){let t=this.resolveOptions();if(!t)return;let r=this.queue.drain();if(r.length===0)return;let n=(0,Pe.mergeBatch)(r);if(!await b(n,t,this.logPrefix))for(let i of r)this.queue.enqueue(i)}};g.MemoryTransport=V});var Z=m(P=>{"use strict";var X=P&&P.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(P,"__esModule",{value:!0});P.TraceManager=void 0;P.generateUlid=Se;var K=X(d("fs")),It=X(d("path")),Mt=X(d("crypto")),$="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function Se(){let e=Date.now(),t="",r=e;for(let i=0;i<10;i++)t=$[r&31]+t,r=Math.floor(r/32);let n=Mt.default.randomBytes(10),o="";for(let i=0;i<10;i++)o+=$[n[i]&31];for(;o.length<16;)o+=$[0];return t+o}var Y=class{tracePath;constructor(t){this.tracePath=t}newTrace(){let t=Se();return this.save(t),t}currentTrace(){try{let t=K.default.readFileSync(this.tracePath,"utf-8"),{traceId:r}=JSON.parse(t);if(r)return r}catch{}return this.newTrace()}save(t){K.default.mkdirSync(It.default.dirname(this.tracePath),{recursive:!0}),K.default.writeFileSync(this.tracePath,JSON.stringify({traceId:t}))}};P.TraceManager=Y});var we=m(y=>{"use strict";var Oe=y&&y.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(y,"__esModule",{value:!0});y.MemorySessionTraceManager=y.DiskSessionTraceManager=void 0;var z=Oe(d("fs")),Ct=Oe(d("path")),be=Z(),ke=200,H=class{tracePath;maxSessions;constructor(t,r={}){this.tracePath=t,this.maxSessions=r.maxSessions??ke}read(){try{let t=JSON.parse(z.default.readFileSync(this.tracePath,"utf-8"));if(t&&typeof t=="object"&&!("traceId"in t))return t}catch{}return{}}write(t){try{z.default.mkdirSync(Ct.default.dirname(this.tracePath),{recursive:!0});let r=Object.entries(t),n=r.length>this.maxSessions?Object.fromEntries(r.slice(-this.maxSessions)):t;z.default.writeFileSync(this.tracePath,JSON.stringify(n))}catch{}}newTrace(t){let r=t||"default",n=(0,be.generateUlid)(),o=this.read();return o[r]=n,this.write(o),n}currentTrace(t){let r=t||"default",n=this.read()[r];return n||this.newTrace(r)}};y.DiskSessionTraceManager=H;var J=class{map=new Map;maxSessions;constructor(t={}){this.maxSessions=t.maxSessions??ke}newTrace(t){let r=t||"default",n=(0,be.generateUlid)();if(this.map.set(r,n),this.map.size>this.maxSessions){let o=this.map.keys().next().value;o!==void 0&&this.map.delete(o)}return n}currentTrace(t){let r=t||"default";return this.map.get(r)??this.newTrace(r)}};y.MemorySessionTraceManager=J});var je=m(v=>{"use strict";var W=v&&v.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(v,"__esModule",{value:!0});v.envFilePath=Lt;v.parseEnvFile=Ae;v.loadEnvFile=Ft;var Nt=W(d("node:fs")),Ut=W(d("node:os")),xe=W(d("node:path"));function Lt(e,t,r){let n=r?process.env[r]:void 0,o=n&&n.length>0?n:xe.default.join(Ut.default.homedir(),e);return xe.default.join(o,t)}function Ae(e){let t={};for(let r of e.split(`
13
+ `)){let n=r.trim();if(!n||n.startsWith("#"))continue;let o=n.indexOf("=");if(o<0)continue;let i=n.slice(0,o).trim(),a=n.slice(o+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),i&&(t[i]=a)}return t}function Ft(e){let t;try{t=Nt.default.readFileSync(e,"utf-8")}catch{return}let r=Ae(t);for(let[n,o]of Object.entries(r))process.env[n]===void 0&&(process.env[n]=o)}});var T=m(s=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0});s.loadEnvFile=s.parseEnvFile=s.envFilePath=s.MemorySessionTraceManager=s.DiskSessionTraceManager=s.generateUlid=s.TraceManager=s.parseHeadersEnv=s.envOptionsResolver=s.postOtlp=s.MemoryTransport=s.DiskTransport=s.MemoryRetryQueue=s.DiskRetryQueue=s.evaluateGuard=s.mergeBatch=s.buildPayload=s.clientAttrs=s.guardAttrs=s.attrsFromRecord=s.toOtlpValue=s.snakeCase=s.newSpanId=s.ulidToTraceId=s.MAX_BYTES=s.PATTERNS=s.applyMatches=s.resolveOverlaps=s.collectMatches=s.truncate=s.redact=void 0;var E=N();Object.defineProperty(s,"redact",{enumerable:!0,get:function(){return E.redact}});Object.defineProperty(s,"truncate",{enumerable:!0,get:function(){return E.truncate}});Object.defineProperty(s,"collectMatches",{enumerable:!0,get:function(){return E.collectMatches}});Object.defineProperty(s,"resolveOverlaps",{enumerable:!0,get:function(){return E.resolveOverlaps}});Object.defineProperty(s,"applyMatches",{enumerable:!0,get:function(){return E.applyMatches}});Object.defineProperty(s,"PATTERNS",{enumerable:!0,get:function(){return E.PATTERNS}});Object.defineProperty(s,"MAX_BYTES",{enumerable:!0,get:function(){return E.MAX_BYTES}});var _=U();Object.defineProperty(s,"ulidToTraceId",{enumerable:!0,get:function(){return _.ulidToTraceId}});Object.defineProperty(s,"newSpanId",{enumerable:!0,get:function(){return _.newSpanId}});Object.defineProperty(s,"snakeCase",{enumerable:!0,get:function(){return _.snakeCase}});Object.defineProperty(s,"toOtlpValue",{enumerable:!0,get:function(){return _.toOtlpValue}});Object.defineProperty(s,"attrsFromRecord",{enumerable:!0,get:function(){return _.attrsFromRecord}});Object.defineProperty(s,"guardAttrs",{enumerable:!0,get:function(){return _.guardAttrs}});Object.defineProperty(s,"clientAttrs",{enumerable:!0,get:function(){return _.clientAttrs}});Object.defineProperty(s,"buildPayload",{enumerable:!0,get:function(){return _.buildPayload}});Object.defineProperty(s,"mergeBatch",{enumerable:!0,get:function(){return _.mergeBatch}});var qt=_e();Object.defineProperty(s,"evaluateGuard",{enumerable:!0,get:function(){return qt.evaluateGuard}});var Re=B();Object.defineProperty(s,"DiskRetryQueue",{enumerable:!0,get:function(){return Re.DiskRetryQueue}});Object.defineProperty(s,"MemoryRetryQueue",{enumerable:!0,get:function(){return Re.MemoryRetryQueue}});var k=Te();Object.defineProperty(s,"DiskTransport",{enumerable:!0,get:function(){return k.DiskTransport}});Object.defineProperty(s,"MemoryTransport",{enumerable:!0,get:function(){return k.MemoryTransport}});Object.defineProperty(s,"postOtlp",{enumerable:!0,get:function(){return k.postOtlp}});Object.defineProperty(s,"envOptionsResolver",{enumerable:!0,get:function(){return k.envOptionsResolver}});Object.defineProperty(s,"parseHeadersEnv",{enumerable:!0,get:function(){return k.parseHeadersEnv}});var De=Z();Object.defineProperty(s,"TraceManager",{enumerable:!0,get:function(){return De.TraceManager}});Object.defineProperty(s,"generateUlid",{enumerable:!0,get:function(){return De.generateUlid}});var Ie=we();Object.defineProperty(s,"DiskSessionTraceManager",{enumerable:!0,get:function(){return Ie.DiskSessionTraceManager}});Object.defineProperty(s,"MemorySessionTraceManager",{enumerable:!0,get:function(){return Ie.MemorySessionTraceManager}});var Q=je();Object.defineProperty(s,"envFilePath",{enumerable:!0,get:function(){return Q.envFilePath}});Object.defineProperty(s,"parseEnvFile",{enumerable:!0,get:function(){return Q.parseEnvFile}});Object.defineProperty(s,"loadEnvFile",{enumerable:!0,get:function(){return Q.loadEnvFile}})});import{realpathSync as dr}from"node:fs";import{pathToFileURL as mr}from"node:url";var w=O(T());function Bt(){return(0,w.envFilePath)(".claude","pinta-cc.env")}function Me(e=Bt()){(0,w.loadEnvFile)(e)}function Ce(){process.env.CLAUDE_PLUGIN_OPTION_ENDPOINT&&!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT&&(process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=process.env.CLAUDE_PLUGIN_OPTION_ENDPOINT),process.env.CLAUDE_PLUGIN_OPTION_API_KEY&&!process.env.OTEL_EXPORTER_OTLP_HEADERS&&(process.env.OTEL_EXPORTER_OTLP_HEADERS=`x-pinta-relay-token=${process.env.CLAUDE_PLUGIN_OPTION_API_KEY}`),!process.env.PINTA_RELAY_TOKEN&&process.env.CLAUDE_PLUGIN_OPTION_API_KEY&&(process.env.PINTA_RELAY_TOKEN=process.env.CLAUDE_PLUGIN_OPTION_API_KEY)}import Ne from"path";function Ue(){let e=process.env.CLAUDE_PLUGIN_ROOT||process.cwd(),t=process.env.CLAUDE_PLUGIN_DATA||Ne.join(e,".plugin-data");return{pluginRoot:e,pluginData:t,tracePath:Ne.join(t,"trace.json")}}function Le(e){return e.hook_event_name==="PreToolUse"}function Fe(e){return e.hook_event_name==="PostToolUse"||e.hook_event_name==="PostToolUseFailure"}function qe(e){return e.hook_event_name==="UserPromptSubmit"}function Be(e){return e.hook_event_name==="SessionStart"||e.hook_event_name==="SessionEnd"}function Ge(e){return e.hook_event_name==="SubagentStart"||e.hook_event_name==="SubagentStop"}function Ve(e){return e.hook_event_name==="Stop"}function Ke(e){return e.hook_event_name==="PermissionRequest"||e.hook_event_name==="PermissionDenied"}var Gt=new Set(["Notification","TaskCreated","TaskCompleted"]);function $e(e){return Gt.has(e.hook_event_name)}var Ye=O(T()),Vt=1e4,Kt="pinta-cc/1.6.0";function Xe(e,t){return(0,Ye.evaluateGuard)(e,t,{timeoutMs:Vt,token:process.env.PINTA_RELAY_TOKEN??"",disabled:process.env.PINTA_GUARD_DISABLED==="1",userAgent:Kt})}var Ze=O(T()),D=class extends Ze.DiskTransport{constructor(t){super({pluginData:t.pluginData,logPrefix:"pinta-cc"})}};var ze=O(T()),I=class extends ze.TraceManager{constructor(t){super(t.tracePath)}};var S=O(T());import $t from"fs";import ee from"os";import M from"path";var He="1.6.0",C=null;function Yt(){return C!==null||(C=Zt()??"unknown"),C}var Xt=6;function Zt(){let e=process.env.CLAUDE_CODE_EXECPATH;if(!e)return null;let t=M.dirname(e),r=M.parse(t).root;for(let n=0;n<Xt&&t!==r;n++){let o=M.join(t,"package.json");try{let i=$t.readFileSync(o,"utf-8"),a=JSON.parse(i);if(typeof a.name=="string"&&a.name.startsWith("@anthropic-ai/claude-code")&&typeof a.version=="string")return a.version}catch{}t=M.dirname(t)}return null}var zt=new Set(["cc.hook","cc.tool_name","cc.tool_use_id","cc.session_id","cc.transcript_path","cc.cwd","cc.permission_mode"]),Ht=new Set(["cc.tool_input","cc.tool_response"]),Jt={skipRedactKeys:zt,bashContextKeys:Ht};function Wt(e){let t=[];t.push({key:"ingest.type",value:{stringValue:"cc"}}),t.push({key:"cc.hook",value:{stringValue:e.hook_event_name}});let r={};for(let[n,o]of Object.entries(e))n!=="hook_event_name"&&(r[n]=o);return t.push(...(0,S.attrsFromRecord)(r,"cc",Jt)),t}function Qt(){return[{key:"service.name",value:{stringValue:"claude-code"}},{key:"service.version",value:{stringValue:Yt()}},{key:"telemetry.sdk.name",value:{stringValue:"pinta-cc"}},{key:"telemetry.sdk.language",value:{stringValue:"nodejs"}},{key:"telemetry.sdk.version",value:{stringValue:He}},{key:"process.pid",value:{intValue:process.pid}},{key:"process.owner",value:{stringValue:ee.userInfo().username}},{key:"host.name",value:{stringValue:ee.hostname()}},{key:"host.arch",value:{stringValue:ee.arch()}}]}function Je(e){return(0,S.buildPayload)({traceId:e.traceId,spanName:`cc.${(0,S.snakeCase)(e.event.hook_event_name)}`,attributes:Wt(e.event),resource:Qt(),scope:{name:"pinta-cc",version:He},now:e.now,guard:e.guard})}async function l(e,t,r={}){let n=new D(t);await n.flush();let o=new I(t),i=r.traceMode==="new"?o.newTrace():o.currentTrace(),a=Je({event:e,traceId:i,guard:r.guard});await n.send(a)}async function We(e,t){let r=typeof e.tool_input=="string"?e.tool_input:JSON.stringify(e.tool_input),n=await Xe({spanId:e.session_id??"unknown",toolName:e.tool_name,toolInput:e.tool_input,rawTextFields:{toolInput:r}},process.env.PINTA_GUARD_ENDPOINT);if(await l(e,t,{guard:n}),n?.decision==="DENY"){let i={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:n.userMessage??n.reason??"guard_deny"}};process.stdout.write(JSON.stringify(i)+`
14
+ `)}return 0}async function Qe(e,t){return await l(e,t),0}async function et(e,t){return await l(e,t,{traceMode:"new"}),0}async function tt(e,t){return await l(e,t),0}async function rt(e,t){return await l(e,t),0}async function nt(e,t){return await l(e,t),0}async function ot(e,t){return await l(e,t),0}async function te(e){return 0}async function er(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf-8")}async function st(){Ce();let e=0;try{let t=Ue(),r=await er(),n=JSON.parse(r);$e(n)?e=await te(n):Le(n)?e=await We(n,t):Fe(n)?e=await Qe(n,t):qe(n)?e=await et(n,t):Be(n)?e=await tt(n,t):Ge(n)?e=await rt(n,t):Ve(n)?e=await nt(n,t):Ke(n)?e=await ot(n,t):e=await te(n)}catch(t){process.stderr.write(`[pinta-cc] error: ${t}
15
+ `),e=0}return e}import{opendir as tr,stat as rr}from"node:fs/promises";import{homedir as nr}from"node:os";import x from"node:path";var or="pinta-cc",it="memory";function sr(){let e=process.env.CLAUDE_CONFIG_DIR;return e&&e.length>0?e:x.join(nr(),".claude")}function ir(){return x.join(sr(),"projects")}function ar(e,t){return x.relative(e,t).split(x.sep).join("/")}function ur(e){return e.endsWith(".jsonl")?"append-log":"rewritten-doc"}function cr(e){let t=e.split("/");if(t.length<2)return{};let r=t[0],n=t[1];return t.length===2?n.endsWith(".jsonl")?{projectKey:r,sessionId:n.slice(0,-6)}:{projectKey:r}:n===it?{projectKey:r}:{projectKey:r,sessionId:n}}function lr(e){return e.endsWith(".jsonl")?"session-log":e.split("/")[1]===it?"memory":e.endsWith(".json")?"meta":"other"}async function at(){return[ir()]}async function*ut(e,t){let r;try{r=await tr(t)}catch{return}try{for await(let n of r){let o=x.join(t,n.name);n.isDirectory()?yield*ut(e,o):n.isFile()&&(yield{absPath:o,relPath:ar(e,o)})}}catch{return}}async function*pr(e){let[t]=await at(),r=e.since?.getTime();for await(let{absPath:n,relPath:o}of ut(t,t)){let i;try{i=await rr(n)}catch{continue}if(r!==void 0&&i.mtime.getTime()<=r)continue;let{projectKey:a,sessionId:p}=cr(o);yield{relPath:o,absPath:n,size:i.size,mtime:i.mtime,sessionId:p,projectKey:a,semantics:ur(o)}}}var fr={id:or,roots:at,scan:pr,classify:lr};Me();function gr(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===mr(dr(e)).href}catch{return!1}}async function _r(){let e=await st();process.exit(e)}gr()&&_r();export{fr as lifecycle};
package/package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "name": "@pinta-ai/pinta-cc",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Generic OTLP forwarder for Claude Code hook events",
5
5
  "main": "dist/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./dist/index.mjs",
9
+ "require": "./dist/index.js"
10
+ }
11
+ },
6
12
  "license": "PolyForm-Noncommercial-1.0.0",
7
13
  "files": [
8
14
  "dist",
@@ -23,15 +29,18 @@
23
29
  "scripts": {
24
30
  "bump": "node scripts/bump.mjs",
25
31
  "typecheck": "tsc --noEmit",
26
- "build": "tsc --noEmit && esbuild src/index.ts --bundle --platform=node --format=cjs --target=node18 --minify --outfile=dist/index.js",
32
+ "build": "tsc --noEmit && npm run build:cjs && npm run build:esm",
33
+ "build:cjs": "esbuild src/index.ts --bundle --platform=node --format=cjs --target=node18 --minify --outfile=dist/index.js",
34
+ "build:esm": "esbuild src/index.mts --bundle --platform=node --format=esm --target=node18 --minify --banner:js=\"import{createRequire as __pintaCreateRequire}from 'node:module';const require=__pintaCreateRequire(import.meta.url);\" --outfile=dist/index.mjs",
27
35
  "dev": "tsc --watch",
28
36
  "test": "vitest run",
29
37
  "test:watch": "vitest",
38
+ "smoke:import": "node scripts/smoke-import.mjs",
30
39
  "mock-server": "npx tsx tools/mock-server.ts",
31
40
  "prepublishOnly": "npm run build"
32
41
  },
33
42
  "devDependencies": {
34
- "@pinta-ai/core": "^0.2.0",
43
+ "@pinta-ai/core": "^0.3.0",
35
44
  "@types/node": "^22.0.0",
36
45
  "esbuild": "^0.24.0",
37
46
  "tsx": "^4.0.0",