@pinta-ai/pinta-opencode 0.4.0 → 0.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.
package/dist/plugin.js CHANGED
@@ -1,14 +1,21 @@
1
1
  import { createRequire as __pintaCreateRequire } from 'module'; const require = __pintaCreateRequire(import.meta.url);
2
- var Ue=Object.create;var ne=Object.defineProperty;var Ze=Object.getOwnPropertyDescriptor;var Ke=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Ye=Object.prototype.hasOwnProperty;var p=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var y=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ze=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Ke(e))!Ye.call(t,s)&&s!==r&&ne(t,s,{get:()=>e[s],enumerable:!(n=Ze(e,s))||n.enumerable});return t};var b=(t,e,r)=>(r=t!=null?Ue(Xe(t)):{},ze(e||!t||!t.__esModule?ne(r,"default",{value:t,enumerable:!0}):r,t));var N=y(c=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});c.PATTERNS=c.MAX_BYTES=void 0;c.truncate=Je;c.collectMatches=se;c.resolveOverlaps=oe;c.applyMatches=ie;c.redact=He;c.MAX_BYTES=102400;function Je(t){let e=Buffer.from(t,"utf-8");return e.length<=c.MAX_BYTES?t:`${e.subarray(0,c.MAX_BYTES).toString("utf-8")}\u2026[TRUNCATED:${e.length}]`}c.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(t,e){let r=[];for(let n of c.PATTERNS){if(n.requireContext&&n.requireContext!==e.context)continue;let s=new RegExp(n.regex.source,n.regex.flags),i;for(;(i=s.exec(t))!==null;){let a=n.captureGroup??0,u=i[a];if(u===void 0){i.index===s.lastIndex&&s.lastIndex++;continue}let f=i.index,g=i.index+i[0].length,M=f+i[0].indexOf(u),$e=M+u.length;r.push({start:f,end:g,replaceStart:M,replaceEnd:$e,type:n.type}),i.index===s.lastIndex&&s.lastIndex++}}return r}function oe(t){let e=[...t].sort((s,i)=>s.start!==i.start?s.start-i.start:i.end-i.start-(s.end-s.start)),r=[],n=-1;for(let s of e)s.start<n||(r.push(s),n=s.end);return r}function ie(t,e){let r=[...e].sort((s,i)=>i.replaceStart-s.replaceStart),n=t;for(let s of r)n=n.slice(0,s.replaceStart)+`[REDACTED:${s.type}]`+n.slice(s.replaceEnd);return n}function He(t,e={}){if(t.length===0)return t;let r=se(t,e);if(r.length===0)return t;let n=oe(r);return ie(t,n)}});var q=y(d=>{"use strict";var Qe=d&&d.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(d,"__esModule",{value:!0});d.ulidToTraceId=ce;d.newSpanId=le;d.snakeCase=tt;d.toOtlpValue=de;d.attrsFromRecord=rt;d.guardAttrs=pe;d.clientAttrs=fe;d.buildPayload=nt;d.mergeBatch=st;var We=Qe(p("crypto")),ae=N(),et="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 s=et.indexOf(n);if(s<0)throw new Error(`ulidToTraceId: invalid Crockford char "${n}"`);e=e<<5n|BigInt(s)}let r=(1n<<128n)-1n;return e&=r,e.toString(16).padStart(32,"0")}function le(){return We.default.randomBytes(8).toString("hex")}function tt(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 R(t,e,r){let n=(0,ae.truncate)(e);if((r.skipRedactKeys??ue).has(t))return n;let s=(r.bashContextKeys??ue).has(t)?"bash":void 0;return(0,ae.redact)(n,{context:s})}function de(t,e,r={}){if(e==null)return null;switch(typeof e){case"string":return{stringValue:R(t,e,r)};case"boolean":return{boolValue:e};case"number":return Number.isInteger(e)?{intValue:e}:{doubleValue:e};case"object":try{return{stringValue:R(t,JSON.stringify(e),r)}}catch{return{stringValue:R(t,String(e),r)}}default:return{stringValue:R(t,String(e),r)}}}function rt(t,e,r={}){let n=[];for(let[s,i]of Object.entries(t)){let a=`${e}.${s}`,u=de(a,i,r);u!==null&&n.push({key:a,value:u})}return n}function pe(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 fe(t){return[{key:"pinta.client.rtt_ms",value:Number.isInteger(t.rttMs)?{intValue:t.rttMs}:{doubleValue:t.rttMs}},{key:"pinta.client.op",value:{stringValue:t.op}}]}function nt(t){let e=t.now??Date.now(),r=(BigInt(e)*1000000n).toString(),n=[...t.attributes];t.guard&&n.push(...pe(t.guard));let s=t.clientTiming??(t.guard?.clientRttMs!==void 0?{op:"guard",rttMs:t.guard.clientRttMs}:null);s&&n.push(...fe(s));let i={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:[i]}]}]}}function st(t){let e=[];for(let r of t)e.push(...r.resourceSpans);return{resourceSpans:e}}});var ye=y(C=>{"use strict";Object.defineProperty(C,"__esModule",{value:!0});C.evaluateGuard=ut;var ot=1e4,it="pinta-core";function ge(t,e){return{decision:"ALLOW",reason:null,userMessage:null,durationMs:t,clientRttMs:t,failOpenReason:e}}function at(t){return new Promise((e,r)=>setTimeout(()=>{let n=new Error("Guard request timed out");n.name="TimeoutError",r(n)},t))}async function ut(t,e,r={}){if(!e||r.disabled)return null;let n=r.timeoutMs??ot,s=Date.now();try{let i=await Promise.race([fetch(e,{method:"POST",headers:{"content-type":"application/json","user-agent":r.userAgent??it,"x-pinta-relay-token":r.token??""},body:JSON.stringify({input:t})}),at(n)]);if(i.status!==200)return ge(Date.now()-s,"error");let a=await i.json(),u=Date.now()-s;return{decision:a.decision,reason:a.reason,userMessage:a.userMessage??null,durationMs:a.durationMs??u,clientRttMs:u}}catch(i){let a=i.name==="TimeoutError"?"timeout":"error";return ge(Date.now()-s,a)}}});var V=y(m=>{"use strict";var he=m&&m.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(m,"__esModule",{value:!0});m.MemoryRetryQueue=m.DiskRetryQueue=void 0;var l=he(p("fs")),x=he(p("path")),I=1e3,ct=50,lt=5,F=class{filePath;lockPath;logPrefix;constructor(e,r){this.filePath=x.default.join(e,"failed-spans.jsonl"),this.lockPath=this.filePath+".lock",this.logPrefix=r}enqueue(e){try{l.default.mkdirSync(x.default.dirname(this.filePath),{recursive:!0});let r=JSON.stringify({savedAt:new Date().toISOString(),payload:e})+`
3
- `;l.default.appendFileSync(this.filePath,r),this.trim()}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue enqueue failed: ${r}
4
- `)}}readAll(){try{let e=l.default.readFileSync(this.filePath,"utf-8"),r=[];for(let n of e.split(`
5
- `))if(n.trim())try{r.push(JSON.parse(n))}catch{}return r}catch{return[]}}rewrite(e){try{if(e.length===0){l.default.existsSync(this.filePath)&&l.default.unlinkSync(this.filePath);return}l.default.mkdirSync(x.default.dirname(this.filePath),{recursive:!0}),l.default.writeFileSync(this.filePath,e.map(r=>JSON.stringify(r)).join(`
2
+ var et=Object.create;var ae=Object.defineProperty;var tt=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames;var nt=Object.getPrototypeOf,st=Object.prototype.hasOwnProperty;var h=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var _=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ot=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of rt(e))!st.call(t,s)&&s!==r&&ae(t,s,{get:()=>e[s],enumerable:!(n=tt(e,s))||n.enumerable});return t};var E=(t,e,r)=>(r=t!=null?et(nt(t)):{},ot(e||!t||!t.__esModule?ae(r,"default",{value:t,enumerable:!0}):r,t));var C=_(f=>{"use strict";Object.defineProperty(f,"__esModule",{value:!0});f.PATTERNS=f.MAX_BYTES=void 0;f.truncateTo=ue;f.truncate=it;f.collectMatches=ce;f.resolveOverlaps=le;f.applyMatches=de;f.redact=at;f.MAX_BYTES=102400;function ue(t,e){let r=Buffer.from(t,"utf-8");return r.length<=e?t:`${r.subarray(0,Math.max(0,e)).toString("utf-8")}\u2026[TRUNCATED:${r.length}]`}function it(t){return ue(t,f.MAX_BYTES)}f.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 ce(t,e){let r=[];for(let n of f.PATTERNS){if(n.requireContext&&n.requireContext!==e.context)continue;let s=new RegExp(n.regex.source,n.regex.flags),i;for(;(i=s.exec(t))!==null;){let u=n.captureGroup??0,a=i[u];if(a===void 0){i.index===s.lastIndex&&s.lastIndex++;continue}let c=i.index,d=i.index+i[0].length,P=c+i[0].indexOf(a),Qe=P+a.length;r.push({start:c,end:d,replaceStart:P,replaceEnd:Qe,type:n.type}),i.index===s.lastIndex&&s.lastIndex++}}return r}function le(t){let e=[...t].sort((s,i)=>s.start!==i.start?s.start-i.start:i.end-i.start-(s.end-s.start)),r=[],n=-1;for(let s of e)s.start<n||(r.push(s),n=s.end);return r}function de(t,e){let r=[...e].sort((s,i)=>i.replaceStart-s.replaceStart),n=t;for(let s of r)n=n.slice(0,s.replaceStart)+`[REDACTED:${s.type}]`+n.slice(s.replaceEnd);return n}function at(t,e={}){if(t.length===0)return t;let r=ce(t,e);if(r.length===0)return t;let n=le(r);return de(t,n)}});var V=_(p=>{"use strict";var ut=p&&p.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(p,"__esModule",{value:!0});p.MAX_SPAN_BYTES=void 0;p.ulidToTraceId=he;p.newSpanId=ye;p.snakeCase=dt;p.toOtlpValue=_e;p.attrsFromRecord=pt;p.guardAttrs=me;p.clientAttrs=Te;p.enforceSpanBudget=Oe;p.buildPayload=ft;p.mergeBatch=gt;var ct=ut(h("crypto")),F=C(),lt="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function he(t){if(t.length!==26)throw new Error(`ulidToTraceId: expected 26 chars, got ${t.length}`);let e=0n;for(let n of t){let s=lt.indexOf(n);if(s<0)throw new Error(`ulidToTraceId: invalid Crockford char "${n}"`);e=e<<5n|BigInt(s)}let r=(1n<<128n)-1n;return e&=r,e.toString(16).padStart(32,"0")}function ye(){return ct.default.randomBytes(8).toString("hex")}function dt(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()}var pe=new Set;function x(t,e,r){let n=(0,F.truncate)(e);if((r.skipRedactKeys??pe).has(t))return n;let s=(r.bashContextKeys??pe).has(t)?"bash":void 0;return(0,F.redact)(n,{context:s})}function _e(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 pt(t,e,r={}){let n=[];for(let[s,i]of Object.entries(t)){let u=`${e}.${s}`,a=_e(u,i,r);a!==null&&n.push({key:u,value:a})}return n}function me(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 Te(t){return[{key:"pinta.client.rtt_ms",value:Number.isInteger(t.rttMs)?{intValue:t.rttMs}:{doubleValue:t.rttMs}},{key:"pinta.client.op",value:{stringValue:t.op}}]}p.MAX_SPAN_BYTES=800*1024;function fe(t){let e=JSON.stringify(t);return e===void 0?0:Buffer.byteLength(e,"utf-8")}var ge=1024;function Oe(t,e=p.MAX_SPAN_BYTES){let r=fe(t);for(let n=0;n<100&&r>e;n++){let s=null,i=0;for(let c of t.attributes){if(!("stringValue"in c.value))continue;let d=Buffer.byteLength(c.value.stringValue,"utf-8");d>i&&(i=d,s=c.value)}if(s===null||i<=ge)break;let u=r-e,a=Math.max(ge,i-u-64);s.stringValue=(0,F.truncateTo)(s.stringValue,a),r=fe(t)}return t}function ft(t){let e=t.now??Date.now(),r=(BigInt(e)*1000000n).toString(),n=[...t.attributes];t.guard&&n.push(...me(t.guard));let s=t.clientTiming??(t.guard?.clientRttMs!==void 0?{op:"guard",rttMs:t.guard.clientRttMs}:null);s&&n.push(...Te(s));let i={traceId:he(t.traceId),spanId:ye(),name:t.spanName,kind:t.spanKind??1,startTimeUnixNano:r,endTimeUnixNano:r,attributes:n};return Oe(i),{resourceSpans:[{resource:{attributes:t.resource},scopeSpans:[{scope:t.scope,spans:[i]}]}]}}function gt(t){let e=[];for(let r of t)e.push(...r.resourceSpans);return{resourceSpans:e}}});var Pe=_(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});G.evaluateGuard=mt;var ht=1e4,yt="pinta-core";function L(t,e){return{decision:"ALLOW",reason:null,userMessage:null,durationMs:t,clientRttMs:t,failOpenReason:e}}var _t=new Set(["ALLOW","DENY","REVIEW"]);async function mt(t,e,r={}){if(!e||r.disabled)return null;let n=r.timeoutMs??ht,s=Date.now(),i=new AbortController,u=setTimeout(()=>i.abort(),n);try{let a=await fetch(e,{method:"POST",headers:{"content-type":"application/json","user-agent":r.userAgent??yt,"x-pinta-relay-token":r.token??""},body:JSON.stringify({input:t}),signal:i.signal});if(a.status!==200)return L(Date.now()-s,"error");let c=await a.json(),d=c?.durationMs===void 0||typeof c.durationMs=="number"&&Number.isFinite(c.durationMs);if(!c||!_t.has(c.decision)||!d)return L(Date.now()-s,"error");let P=Date.now()-s;return{decision:c.decision,reason:c.reason??null,userMessage:c.userMessage??null,durationMs:c.durationMs??P,clientRttMs:P}}catch(a){let c=a.name,d=c==="AbortError"||c==="TimeoutError"?"timeout":"error";return L(Date.now()-s,d)}finally{clearTimeout(u)}}});var I=_(w=>{"use strict";var Tt=w&&w.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(w,"__esModule",{value:!0});w.atomicWriteFileSync=Ot;var ve=Tt(h("fs"));function Ot(t,e){let r=`${t}.${process.pid}.tmp`;ve.default.writeFileSync(r,e),ve.default.renameSync(r,t)}});var z=_(m=>{"use strict";var Se=m&&m.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(m,"__esModule",{value:!0});m.MemoryRetryQueue=m.DiskRetryQueue=void 0;var g=Se(h("fs")),D=Se(h("path")),Pt=I(),j=1e3,vt=50,St=5,X=class{filePath;lockPath;logPrefix;constructor(e,r){this.filePath=D.default.join(e,"failed-spans.jsonl"),this.lockPath=this.filePath+".lock",this.logPrefix=r}enqueue(e){try{g.default.mkdirSync(D.default.dirname(this.filePath),{recursive:!0});let r=JSON.stringify({savedAt:new Date().toISOString(),payload:e})+`
3
+ `;g.default.appendFileSync(this.filePath,r),this.trim()}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue enqueue failed: ${r}
4
+ `)}}readAll(){try{let e=g.default.readFileSync(this.filePath,"utf-8"),r=[];for(let n of e.split(`
5
+ `))if(n.trim())try{let s=JSON.parse(n);Array.isArray(s?.payload?.resourceSpans)&&r.push(s)}catch{}return r}catch{return[]}}rewrite(e){try{if(e.length===0){g.default.existsSync(this.filePath)&&g.default.unlinkSync(this.filePath);return}g.default.mkdirSync(D.default.dirname(this.filePath),{recursive:!0}),(0,Pt.atomicWriteFileSync)(this.filePath,e.map(r=>JSON.stringify(r)).join(`
6
6
  `)+`
7
7
  `)}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue rewrite failed: ${r}
8
- `)}}tryAcquireLock(){let e=Date.now();for(l.default.mkdirSync(x.default.dirname(this.lockPath),{recursive:!0});Date.now()-e<ct;)try{let r=l.default.openSync(this.lockPath,"wx");return l.default.writeSync(r,String(process.pid)),l.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=l.default.statSync(this.lockPath);if(Date.now()-i.mtimeMs>3e4){l.default.unlinkSync(this.lockPath);continue}}catch{}let n=lt,s=Date.now()+n;for(;Date.now()<s;);}return!1}release(){try{l.default.unlinkSync(this.lockPath)}catch{}}trim(){let e=this.readAll();if(e.length<=I)return;let r=e.length-I;process.stderr.write(`[${this.logPrefix}] retry-queue full, dropping ${r} oldest entries
10
- `),this.rewrite(e.slice(r))}};m.DiskRetryQueue=F;var G=class{entries=[];enqueue(e){this.entries.push(e),this.entries.length>I&&this.entries.splice(0,this.entries.length-I)}drain(){let e=this.entries;return this.entries=[],e}get size(){return this.entries.length}};m.MemoryRetryQueue=G});var Pe=y(h=>{"use strict";Object.defineProperty(h,"__esModule",{value:!0});h.MemoryTransport=h.DiskTransport=void 0;h.parseHeadersEnv=Oe;h.envOptionsResolver=Te;h.postOtlp=k;var _e=V(),me=q(),dt=5e3;function Oe(t){if(!t)return{};if(typeof t=="object")return{...t};let e={};for(let r of t.split(",")){let[n,...s]=r.split("=");n&&s.length>0&&(e[n.trim()]=s.join("=").trim())}return e}function Te(){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:Oe(process.env.OTEL_EXPORTER_OTLP_HEADERS)}:null}async function k(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),dt);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 u=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}${u}${a?` body=${a}`:""}
8
+ `)}}tryAcquireLock(){let e=Date.now();try{g.default.mkdirSync(D.default.dirname(this.lockPath),{recursive:!0})}catch(r){return process.stderr.write(`[${this.logPrefix}] retry-queue lock mkdir failed: ${r}
9
+ `),!1}for(;Date.now()-e<vt;)try{let r=g.default.openSync(this.lockPath,"wx");return g.default.writeSync(r,String(process.pid)),g.default.closeSync(r),!0}catch(r){if(r?.code!=="EEXIST")return process.stderr.write(`[${this.logPrefix}] retry-queue lock open failed: ${r}
10
+ `),!1;try{let i=g.default.statSync(this.lockPath);if(Date.now()-i.mtimeMs>3e4){g.default.unlinkSync(this.lockPath);continue}}catch{}let n=St,s=Date.now()+n;for(;Date.now()<s;);}return!1}release(){try{g.default.unlinkSync(this.lockPath)}catch{}}trim(){let e=this.readAll();if(e.length<=j)return;let r=e.length-j;process.stderr.write(`[${this.logPrefix}] retry-queue full, dropping ${r} oldest entries
11
+ `),this.rewrite(e.slice(r))}};m.DiskRetryQueue=X;var Y=class{entries=[];enqueue(e){this.entries.push(e),this.entries.length>j&&this.entries.splice(0,this.entries.length-j)}drain(){let e=this.entries;return this.entries=[],e}get size(){return this.entries.length}};m.MemoryRetryQueue=Y});var Me=_(l=>{"use strict";Object.defineProperty(l,"__esModule",{value:!0});l.MemoryTransport=l.DiskTransport=l.MAX_POST_BYTES=void 0;l.parseHeadersEnv=ke;l.envOptionsResolver=we;l.postOtlp=M;var be=z(),Ee=V(),bt=5e3;l.MAX_POST_BYTES=900*1024;function N(t){let e=JSON.stringify(t);return e===void 0?0:Buffer.byteLength(e,"utf-8")}function Ae(t,e,r){let n=[],s=[],i=[],u=0;for(let a of t){let c=e(a);if(c>r){s.push(a);continue}i.length>0&&u+c>r&&(n.push(i),i=[],u=0),i.push(a),u+=c}return i.length>0&&n.push(i),{chunks:n,oversize:s}}function ke(t){if(!t)return{};if(typeof t=="object")return{...t};let e={};for(let r of t.split(",")){let[n,...s]=r.split("=");n&&s.length>0&&(e[n.trim()]=s.join("=").trim())}return e}function we(){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:ke(process.env.OTEL_EXPORTER_OTLP_HEADERS)}:null}async function M(t,e,r){let n=new AbortController,s=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 u="";try{u=(await i.text()).slice(0,200)}catch{}let a=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}${u?` body=${u}`:""}
11
12
  `),!1}return!0}catch(i){return process.stderr.write(`[${r}] OTLP POST failed: ${i.message??String(i)}
12
- `),!1}finally{clearTimeout(s)}}var L=class{queue;logPrefix;resolveOptions;constructor(e){this.queue=new _e.DiskRetryQueue(e.pluginData,e.logPrefix),this.logPrefix=e.logPrefix,this.resolveOptions=e.resolveOptions??Te}async send(e){let r=this.resolveOptions();if(!r)return;await k(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,me.mergeBatch)(r.map(i=>i.payload));await k(n,e,this.logPrefix)&&this.queue.rewrite([])}finally{this.queue.release()}}};h.DiskTransport=L;var B=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 k(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,me.mergeBatch)(r);if(!await k(n,e,this.logPrefix))for(let i of r)this.queue.enqueue(i)}};h.MemoryTransport=B});var X=y(T=>{"use strict";var K=T&&T.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(T,"__esModule",{value:!0});T.TraceManager=void 0;T.generateUlid=ve;var $=K(p("fs")),pt=K(p("path")),ft=K(p("crypto")),U="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function ve(){let t=Date.now(),e="",r=t;for(let i=0;i<10;i++)e=U[r&31]+e,r=Math.floor(r/32);let n=ft.default.randomBytes(10),s="";for(let i=0;i<10;i++)s+=U[n[i]&31];for(;s.length<16;)s+=U[0];return e+s}var Z=class{tracePath;constructor(e){this.tracePath=e}newTrace(){let e=ve();return this.save(e),e}currentTrace(){try{let e=$.default.readFileSync(this.tracePath,"utf-8"),{traceId:r}=JSON.parse(e);if(r)return r}catch{}return this.newTrace()}save(e){$.default.mkdirSync(pt.default.dirname(this.tracePath),{recursive:!0}),$.default.writeFileSync(this.tracePath,JSON.stringify({traceId:e}))}};T.TraceManager=Z});var ke=y(O=>{"use strict";var Ee=O&&O.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(O,"__esModule",{value:!0});O.MemorySessionTraceManager=O.DiskSessionTraceManager=void 0;var Y=Ee(p("fs")),gt=Ee(p("path")),be=X(),Se=200,z=class{tracePath;maxSessions;constructor(e,r={}){this.tracePath=e,this.maxSessions=r.maxSessions??Se}read(){try{let e=JSON.parse(Y.default.readFileSync(this.tracePath,"utf-8"));if(e&&typeof e=="object"&&!("traceId"in e))return e}catch{}return{}}write(e){try{Y.default.mkdirSync(gt.default.dirname(this.tracePath),{recursive:!0});let r=Object.entries(e),n=r.length>this.maxSessions?Object.fromEntries(r.slice(-this.maxSessions)):e;Y.default.writeFileSync(this.tracePath,JSON.stringify(n))}catch{}}newTrace(e){let r=e||"default",n=(0,be.generateUlid)(),s=this.read();return s[r]=n,this.write(s),n}currentTrace(e){let r=e||"default",n=this.read()[r];return n||this.newTrace(r)}};O.DiskSessionTraceManager=z;var J=class{map=new Map;maxSessions;constructor(e={}){this.maxSessions=e.maxSessions??Se}newTrace(e){let r=e||"default",n=(0,be.generateUlid)();if(this.map.set(r,n),this.map.size>this.maxSessions){let s=this.map.keys().next().value;s!==void 0&&this.map.delete(s)}return n}currentTrace(e){let r=e||"default";return this.map.get(r)??this.newTrace(r)}};O.MemorySessionTraceManager=J});var Me=y(P=>{"use strict";var H=P&&P.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(P,"__esModule",{value:!0});P.envFilePath=_t;P.parseEnvFile=Ae;P.loadEnvFile=mt;var yt=H(p("node:fs")),ht=H(p("node:os")),we=H(p("node:path"));function _t(t,e,r){let n=r?process.env[r]:void 0,s=n&&n.length>0?n:we.default.join(ht.default.homedir(),t);return we.default.join(s,e)}function Ae(t){let e={};for(let r of t.split(`
13
- `)){let n=r.trim();if(!n||n.startsWith("#"))continue;let s=n.indexOf("=");if(s<0)continue;let i=n.slice(0,s).trim(),a=n.slice(s+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),i&&(e[i]=a)}return e}function mt(t){let e;try{e=yt.default.readFileSync(t,"utf-8")}catch{return}let r=Ae(e);for(let[n,s]of Object.entries(r))process.env[n]===void 0&&(process.env[n]=s)}});var E=y(o=>{"use strict";Object.defineProperty(o,"__esModule",{value:!0});o.loadEnvFile=o.parseEnvFile=o.envFilePath=o.MemorySessionTraceManager=o.DiskSessionTraceManager=o.generateUlid=o.TraceManager=o.parseHeadersEnv=o.envOptionsResolver=o.postOtlp=o.MemoryTransport=o.DiskTransport=o.MemoryRetryQueue=o.DiskRetryQueue=o.evaluateGuard=o.mergeBatch=o.buildPayload=o.clientAttrs=o.guardAttrs=o.attrsFromRecord=o.toOtlpValue=o.snakeCase=o.newSpanId=o.ulidToTraceId=o.MAX_BYTES=o.PATTERNS=o.applyMatches=o.resolveOverlaps=o.collectMatches=o.truncate=o.redact=void 0;var v=N();Object.defineProperty(o,"redact",{enumerable:!0,get:function(){return v.redact}});Object.defineProperty(o,"truncate",{enumerable:!0,get:function(){return v.truncate}});Object.defineProperty(o,"collectMatches",{enumerable:!0,get:function(){return v.collectMatches}});Object.defineProperty(o,"resolveOverlaps",{enumerable:!0,get:function(){return v.resolveOverlaps}});Object.defineProperty(o,"applyMatches",{enumerable:!0,get:function(){return v.applyMatches}});Object.defineProperty(o,"PATTERNS",{enumerable:!0,get:function(){return v.PATTERNS}});Object.defineProperty(o,"MAX_BYTES",{enumerable:!0,get:function(){return v.MAX_BYTES}});var _=q();Object.defineProperty(o,"ulidToTraceId",{enumerable:!0,get:function(){return _.ulidToTraceId}});Object.defineProperty(o,"newSpanId",{enumerable:!0,get:function(){return _.newSpanId}});Object.defineProperty(o,"snakeCase",{enumerable:!0,get:function(){return _.snakeCase}});Object.defineProperty(o,"toOtlpValue",{enumerable:!0,get:function(){return _.toOtlpValue}});Object.defineProperty(o,"attrsFromRecord",{enumerable:!0,get:function(){return _.attrsFromRecord}});Object.defineProperty(o,"guardAttrs",{enumerable:!0,get:function(){return _.guardAttrs}});Object.defineProperty(o,"clientAttrs",{enumerable:!0,get:function(){return _.clientAttrs}});Object.defineProperty(o,"buildPayload",{enumerable:!0,get:function(){return _.buildPayload}});Object.defineProperty(o,"mergeBatch",{enumerable:!0,get:function(){return _.mergeBatch}});var Ot=ye();Object.defineProperty(o,"evaluateGuard",{enumerable:!0,get:function(){return Ot.evaluateGuard}});var Re=V();Object.defineProperty(o,"DiskRetryQueue",{enumerable:!0,get:function(){return Re.DiskRetryQueue}});Object.defineProperty(o,"MemoryRetryQueue",{enumerable:!0,get:function(){return Re.MemoryRetryQueue}});var w=Pe();Object.defineProperty(o,"DiskTransport",{enumerable:!0,get:function(){return w.DiskTransport}});Object.defineProperty(o,"MemoryTransport",{enumerable:!0,get:function(){return w.MemoryTransport}});Object.defineProperty(o,"postOtlp",{enumerable:!0,get:function(){return w.postOtlp}});Object.defineProperty(o,"envOptionsResolver",{enumerable:!0,get:function(){return w.envOptionsResolver}});Object.defineProperty(o,"parseHeadersEnv",{enumerable:!0,get:function(){return w.parseHeadersEnv}});var xe=X();Object.defineProperty(o,"TraceManager",{enumerable:!0,get:function(){return xe.TraceManager}});Object.defineProperty(o,"generateUlid",{enumerable:!0,get:function(){return xe.generateUlid}});var Ie=ke();Object.defineProperty(o,"DiskSessionTraceManager",{enumerable:!0,get:function(){return Ie.DiskSessionTraceManager}});Object.defineProperty(o,"MemorySessionTraceManager",{enumerable:!0,get:function(){return Ie.MemorySessionTraceManager}});var Q=Me();Object.defineProperty(o,"envFilePath",{enumerable:!0,get:function(){return Q.envFilePath}});Object.defineProperty(o,"parseEnvFile",{enumerable:!0,get:function(){return Q.parseEnvFile}});Object.defineProperty(o,"loadEnvFile",{enumerable:!0,get:function(){return Q.loadEnvFile}})});var je=b(E(),1);var A=b(E(),1);function Tt(){return(0,A.envFilePath)(".config/opencode","pinta-opencode.env","OPENCODE_CONFIG_DIR")}function De(t=Tt()){(0,A.loadEnvFile)(t)}function W(...t){return t.find(e=>e)||void 0}function Pt(t){let e=W(t.endpoint,process.env.PINTA_OPENCODE_ENDPOINT,process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);if(e)return e.replace(/\/+$/,"");let r=process.env.OTEL_EXPORTER_OTLP_ENDPOINT;if(r)return r.replace(/\/+$/,"")+"/v1/traces"}function Ne(t={}){De();let e=W(t.token,process.env.PINTA_OPENCODE_TOKEN),r=(0,je.parseHeadersEnv)(t.headers??process.env.PINTA_OPENCODE_HEADERS??process.env.OTEL_EXPORTER_OTLP_HEADERS);e&&!Object.keys(r).some(s=>s.toLowerCase()==="x-pinta-relay-token")&&(r["x-pinta-relay-token"]=e);let n=t.guardTimeoutMs??(Number(process.env.PINTA_OPENCODE_GUARD_TIMEOUT_MS)||50);return{endpoint:Pt(t),headers:r,guardEndpoint:W(t.guard,process.env.PINTA_OPENCODE_GUARD),relayToken:e,guardTimeoutMs:n,guardDisabled:process.env.PINTA_OPENCODE_GUARD_DISABLED==="1",serviceVersion:process.env.OPENCODE_VERSION||"unknown"}}var qe=b(E(),1),D=class extends qe.MemoryTransport{constructor(e){super({logPrefix:"pinta-opencode",resolveOptions:()=>e.endpoint?{endpoint:e.endpoint,headers:e.headers}:null})}};var ee=b(E(),1);var Ce=b(E(),1),vt=50,Et="pinta-opencode/0.4.0";function Fe(t,e,r={}){return(0,Ce.evaluateGuard)(t,e,{timeoutMs:r.timeoutMs??vt,token:r.token,disabled:r.disabled,userAgent:Et})}var S=b(E(),1);import te from"os";var Ge="0.4.0",bt=new Set(["opencode.kind","opencode.event_type","opencode.tool","opencode.session_id","opencode.sessionID","opencode.call_id","opencode.callID","opencode.agent","opencode.model","opencode.exit","opencode.truncated","opencode.title"]),St=new Set(["opencode.args","opencode.input","opencode.output","opencode.tool_input"]),kt={skipRedactKeys:bt,bashContextKeys:St};function wt(t){let e=[{key:"ingest.type",value:{stringValue:"opencode"}}];return e.push(...(0,S.attrsFromRecord)(t,"opencode",kt)),e}function At(t){return[{key:"service.name",value:{stringValue:"opencode"}},{key:"service.version",value:{stringValue:t}},{key:"telemetry.sdk.name",value:{stringValue:"pinta-opencode"}},{key:"telemetry.sdk.language",value:{stringValue:"nodejs"}},{key:"telemetry.sdk.version",value:{stringValue:Ge}},{key:"process.pid",value:{intValue:process.pid}},{key:"process.owner",value:{stringValue:te.userInfo().username}},{key:"host.name",value:{stringValue:te.hostname()}},{key:"host.arch",value:{stringValue:te.arch()}}]}function Ve(t){return(0,S.buildPayload)({traceId:t.traceId,spanName:t.name,attributes:wt(t.fields),resource:At(t.serviceVersion),scope:{name:"pinta-opencode",version:Ge},now:t.now,guard:t.guard})}var j=class{constructor(e,r,n){this.transport=e;this.trace=r;this.config=n}async emit(e,r,n,s){let i=this.trace.currentTrace(r),a=Ve({name:e,traceId:i,fields:n,guard:s,serviceVersion:this.config.serviceVersion});await this.transport.send(a)}async lifecycle(e){let r=e.properties??{},n=typeof r.sessionID=="string"?r.sessionID:void 0;await this.emit(`opencode.event.${e.type??"unknown"}`,n,{kind:"event",event_type:e.type,session_id:n,...r}),e.type==="session.idle"&&await this.transport.flush()}async toolBefore(e,r,n){await this.emit("opencode.tool.before",e.sessionID,{...Le("tool.before",e),args:r},n)}async toolAfter(e,r){let n=r.metadata??{};await this.emit("opencode.tool.after",e.sessionID,{...Le("tool.after",e),title:r.title,output:r.output,exit:n.exit,truncated:n.truncated})}};function Le(t,e){return{kind:t,tool:e.tool,session_id:e.sessionID,call_id:e.callID}}function Be(t,e){process.stderr.write(`[pinta-opencode] ${t}: ${e?.message??String(e)}
14
- `)}function re(t,e){return async(...r)=>{try{await e(...r)}catch(n){Be(t,n)}}}var Mt=async(t,e)=>{let r=Ne(e??{}),n=new D({endpoint:r.endpoint,headers:r.headers}),s=new ee.MemorySessionTraceManager,i=new j(n,s,r);async function a(u,f){let g=null;try{g=await Fe({spanId:u.sessionID,toolName:u.tool,toolInput:f,rawTextFields:{toolInput:Rt(f)}},r.guardEndpoint,{timeoutMs:r.guardTimeoutMs,token:r.relayToken,disabled:r.guardDisabled}),await i.toolBefore(u,f,g)}catch(M){Be("tool.execute.before",M)}return g}return{"chat.message":re("chat.message",async u=>{s.newTrace(u?.sessionID)}),event:re("event",async u=>{u?.event&&await i.lifecycle(u.event)}),"tool.execute.before":async(u,f)=>{let g=await a(u,f?.args);if(g?.decision==="DENY")throw new Error(g.userMessage??g.reason??"guard_deny")},"tool.execute.after":re("tool.execute.after",(u,f)=>i.toolAfter(u,f))}};function Rt(t){try{return typeof t=="string"?t:JSON.stringify(t)??""}catch{return String(t)}}var rr=Mt;export{Mt as PintaOpencode,rr as default};
13
+ `),!1}finally{clearTimeout(s)}}var U=class{queue;logPrefix;resolveOptions;constructor(e){this.queue=new be.DiskRetryQueue(e.pluginData,e.logPrefix),this.logPrefix=e.logPrefix,this.resolveOptions=e.resolveOptions??we}async send(e){let r=this.resolveOptions();if(!r||this.dropIfOversized(e))return;await M(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{chunks:n,oversize:s}=Ae(r,a=>N(a.payload),l.MAX_POST_BYTES);s.length>0&&process.stderr.write(`[${this.logPrefix}] dropping ${s.length} oversized retry ${s.length===1?"entry":"entries"} (each > ${l.MAX_POST_BYTES} bytes \u2014 the backend caps the request body, so they can never be delivered)
14
+ `);let i=[].concat(...n),u=0;for(let a of n){if(!await M((0,Ee.mergeBatch)(a.map(d=>d.payload)),e,this.logPrefix))break;u+=a.length}this.queue.rewrite(i.slice(u))}catch(r){process.stderr.write(`[${this.logPrefix}] flush failed: ${r?.message??String(r)}
15
+ `)}finally{this.queue.release()}}dropIfOversized(e){let r=N(e);return r<=l.MAX_POST_BYTES?!1:(process.stderr.write(`[${this.logPrefix}] dropping oversized span payload (${r} > ${l.MAX_POST_BYTES} bytes) \u2014 undeliverable, not queued
16
+ `),!0)}};l.DiskTransport=U;var Z=class{queue=new be.MemoryRetryQueue;logPrefix;resolveOptions;constructor(e){this.logPrefix=e.logPrefix,this.resolveOptions=e.resolveOptions}async send(e){let r=this.resolveOptions();if(!r)return;if(N(e)>l.MAX_POST_BYTES){process.stderr.write(`[${this.logPrefix}] dropping oversized span payload (> ${l.MAX_POST_BYTES} bytes) \u2014 undeliverable, not buffered
17
+ `);return}await M(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{chunks:n,oversize:s}=Ae(r,N,l.MAX_POST_BYTES);s.length>0&&process.stderr.write(`[${this.logPrefix}] dropping ${s.length} oversized buffered ${s.length===1?"payload":"payloads"} (each > ${l.MAX_POST_BYTES} bytes \u2014 undeliverable)
18
+ `);let i=[].concat(...n),u=0;for(let a of n){if(!await M((0,Ee.mergeBatch)(a),e,this.logPrefix))break;u+=a.length}for(let a of i.slice(u))this.queue.enqueue(a)}};l.MemoryTransport=Z});var H=_(v=>{"use strict";var J=v&&v.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(v,"__esModule",{value:!0});v.TraceManager=void 0;v.generateUlid=xe;var Re=J(h("fs")),Et=J(h("path")),At=J(h("crypto")),kt=I(),K="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function xe(){let t=Date.now(),e="",r=t;for(let i=0;i<10;i++)e=K[r&31]+e,r=Math.floor(r/32);let n=At.default.randomBytes(10),s="";for(let i=0;i<10;i++)s+=K[n[i]&31];for(;s.length<16;)s+=K[0];return e+s}var W=class{tracePath;constructor(e){this.tracePath=e}newTrace(){let e=xe();return this.save(e),e}currentTrace(){try{let e=Re.default.readFileSync(this.tracePath,"utf-8"),{traceId:r}=JSON.parse(e);if(r)return r}catch{}return this.newTrace()}save(e){try{Re.default.mkdirSync(Et.default.dirname(this.tracePath),{recursive:!0}),(0,kt.atomicWriteFileSync)(this.tracePath,JSON.stringify({traceId:e}))}catch(r){process.stderr.write(`[pinta-core] trace persistence failed: ${r}
19
+ `)}}};v.TraceManager=W});var Be=_(T=>{"use strict";var De=T&&T.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(T,"__esModule",{value:!0});T.MemorySessionTraceManager=T.DiskSessionTraceManager=void 0;var Ie=De(h("fs")),wt=De(h("path")),je=H(),Mt=I(),Ne=200,Q=class{tracePath;maxSessions;constructor(e,r={}){this.tracePath=e,this.maxSessions=r.maxSessions??Ne}read(){try{let e=JSON.parse(Ie.default.readFileSync(this.tracePath,"utf-8"));if(e&&typeof e=="object"&&!("traceId"in e))return e}catch{}return{}}write(e){try{Ie.default.mkdirSync(wt.default.dirname(this.tracePath),{recursive:!0});let r=Object.entries(e),n=r.length>this.maxSessions?Object.fromEntries(r.slice(-this.maxSessions)):e;(0,Mt.atomicWriteFileSync)(this.tracePath,JSON.stringify(n))}catch{}}newTrace(e){let r=e||"default",n=(0,je.generateUlid)(),s=this.read();return s[r]=n,this.write(s),n}currentTrace(e){let r=e||"default",n=this.read()[r];return n||this.newTrace(r)}};T.DiskSessionTraceManager=Q;var ee=class{map=new Map;maxSessions;constructor(e={}){this.maxSessions=e.maxSessions??Ne}newTrace(e){let r=e||"default",n=(0,je.generateUlid)();if(this.map.set(r,n),this.map.size>this.maxSessions){let s=this.map.keys().next().value;s!==void 0&&this.map.delete(s)}return n}currentTrace(e){let r=e||"default";return this.map.get(r)??this.newTrace(r)}};T.MemorySessionTraceManager=ee});var Ce=_(S=>{"use strict";var te=S&&S.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(S,"__esModule",{value:!0});S.envFilePath=It;S.parseEnvFile=$e;S.loadEnvFile=Dt;var Rt=te(h("node:fs")),xt=te(h("node:os")),qe=te(h("node:path"));function It(t,e,r){let n=r?process.env[r]:void 0,s=n&&n.length>0?n:qe.default.join(xt.default.homedir(),t);return qe.default.join(s,e)}function $e(t){let e={};for(let r of t.split(`
20
+ `)){let n=r.trim();if(!n||n.startsWith("#"))continue;let s=n.indexOf("=");if(s<0)continue;let i=n.slice(0,s).trim(),u=n.slice(s+1).trim();(u.startsWith('"')&&u.endsWith('"')||u.startsWith("'")&&u.endsWith("'"))&&(u=u.slice(1,-1)),i&&(e[i]=u)}return e}function Dt(t){let e;try{e=Rt.default.readFileSync(t,"utf-8")}catch{return}let r=$e(e);for(let[n,s]of Object.entries(r))process.env[n]===void 0&&(process.env[n]=s)}});var b=_(o=>{"use strict";Object.defineProperty(o,"__esModule",{value:!0});o.loadEnvFile=o.parseEnvFile=o.envFilePath=o.MemorySessionTraceManager=o.DiskSessionTraceManager=o.generateUlid=o.TraceManager=o.MAX_POST_BYTES=o.parseHeadersEnv=o.envOptionsResolver=o.postOtlp=o.MemoryTransport=o.DiskTransport=o.MemoryRetryQueue=o.DiskRetryQueue=o.evaluateGuard=o.MAX_SPAN_BYTES=o.enforceSpanBudget=o.mergeBatch=o.buildPayload=o.clientAttrs=o.guardAttrs=o.attrsFromRecord=o.toOtlpValue=o.snakeCase=o.newSpanId=o.ulidToTraceId=o.MAX_BYTES=o.PATTERNS=o.applyMatches=o.resolveOverlaps=o.collectMatches=o.truncateTo=o.truncate=o.redact=void 0;var O=C();Object.defineProperty(o,"redact",{enumerable:!0,get:function(){return O.redact}});Object.defineProperty(o,"truncate",{enumerable:!0,get:function(){return O.truncate}});Object.defineProperty(o,"truncateTo",{enumerable:!0,get:function(){return O.truncateTo}});Object.defineProperty(o,"collectMatches",{enumerable:!0,get:function(){return O.collectMatches}});Object.defineProperty(o,"resolveOverlaps",{enumerable:!0,get:function(){return O.resolveOverlaps}});Object.defineProperty(o,"applyMatches",{enumerable:!0,get:function(){return O.applyMatches}});Object.defineProperty(o,"PATTERNS",{enumerable:!0,get:function(){return O.PATTERNS}});Object.defineProperty(o,"MAX_BYTES",{enumerable:!0,get:function(){return O.MAX_BYTES}});var y=V();Object.defineProperty(o,"ulidToTraceId",{enumerable:!0,get:function(){return y.ulidToTraceId}});Object.defineProperty(o,"newSpanId",{enumerable:!0,get:function(){return y.newSpanId}});Object.defineProperty(o,"snakeCase",{enumerable:!0,get:function(){return y.snakeCase}});Object.defineProperty(o,"toOtlpValue",{enumerable:!0,get:function(){return y.toOtlpValue}});Object.defineProperty(o,"attrsFromRecord",{enumerable:!0,get:function(){return y.attrsFromRecord}});Object.defineProperty(o,"guardAttrs",{enumerable:!0,get:function(){return y.guardAttrs}});Object.defineProperty(o,"clientAttrs",{enumerable:!0,get:function(){return y.clientAttrs}});Object.defineProperty(o,"buildPayload",{enumerable:!0,get:function(){return y.buildPayload}});Object.defineProperty(o,"mergeBatch",{enumerable:!0,get:function(){return y.mergeBatch}});Object.defineProperty(o,"enforceSpanBudget",{enumerable:!0,get:function(){return y.enforceSpanBudget}});Object.defineProperty(o,"MAX_SPAN_BYTES",{enumerable:!0,get:function(){return y.MAX_SPAN_BYTES}});var jt=Pe();Object.defineProperty(o,"evaluateGuard",{enumerable:!0,get:function(){return jt.evaluateGuard}});var Fe=z();Object.defineProperty(o,"DiskRetryQueue",{enumerable:!0,get:function(){return Fe.DiskRetryQueue}});Object.defineProperty(o,"MemoryRetryQueue",{enumerable:!0,get:function(){return Fe.MemoryRetryQueue}});var A=Me();Object.defineProperty(o,"DiskTransport",{enumerable:!0,get:function(){return A.DiskTransport}});Object.defineProperty(o,"MemoryTransport",{enumerable:!0,get:function(){return A.MemoryTransport}});Object.defineProperty(o,"postOtlp",{enumerable:!0,get:function(){return A.postOtlp}});Object.defineProperty(o,"envOptionsResolver",{enumerable:!0,get:function(){return A.envOptionsResolver}});Object.defineProperty(o,"parseHeadersEnv",{enumerable:!0,get:function(){return A.parseHeadersEnv}});Object.defineProperty(o,"MAX_POST_BYTES",{enumerable:!0,get:function(){return A.MAX_POST_BYTES}});var Ve=H();Object.defineProperty(o,"TraceManager",{enumerable:!0,get:function(){return Ve.TraceManager}});Object.defineProperty(o,"generateUlid",{enumerable:!0,get:function(){return Ve.generateUlid}});var Le=Be();Object.defineProperty(o,"DiskSessionTraceManager",{enumerable:!0,get:function(){return Le.DiskSessionTraceManager}});Object.defineProperty(o,"MemorySessionTraceManager",{enumerable:!0,get:function(){return Le.MemorySessionTraceManager}});var re=Ce();Object.defineProperty(o,"envFilePath",{enumerable:!0,get:function(){return re.envFilePath}});Object.defineProperty(o,"parseEnvFile",{enumerable:!0,get:function(){return re.parseEnvFile}});Object.defineProperty(o,"loadEnvFile",{enumerable:!0,get:function(){return re.loadEnvFile}})});var Xe=E(b(),1);var R=E(b(),1);function Nt(){return(0,R.envFilePath)(".config/opencode","pinta-opencode.env","OPENCODE_CONFIG_DIR")}function Ge(t=Nt()){(0,R.loadEnvFile)(t)}function ne(...t){return t.find(e=>e)||void 0}function Bt(t){let e=ne(t.endpoint,process.env.PINTA_OPENCODE_ENDPOINT,process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);if(e)return e.replace(/\/+$/,"");let r=process.env.OTEL_EXPORTER_OTLP_ENDPOINT;if(r)return r.replace(/\/+$/,"")+"/v1/traces"}function Ye(t={}){Ge();let e=ne(t.token,process.env.PINTA_OPENCODE_TOKEN),r=(0,Xe.parseHeadersEnv)(t.headers??process.env.PINTA_OPENCODE_HEADERS??process.env.OTEL_EXPORTER_OTLP_HEADERS);e&&!Object.keys(r).some(s=>s.toLowerCase()==="x-pinta-relay-token")&&(r["x-pinta-relay-token"]=e);let n=t.guardTimeoutMs??(Number(process.env.PINTA_OPENCODE_GUARD_TIMEOUT_MS)||50);return{endpoint:Bt(t),headers:r,guardEndpoint:ne(t.guard,process.env.PINTA_OPENCODE_GUARD),relayToken:e,guardTimeoutMs:n,guardDisabled:process.env.PINTA_OPENCODE_GUARD_DISABLED==="1",serviceVersion:process.env.OPENCODE_VERSION||"unknown"}}var ze=E(b(),1),B=class extends ze.MemoryTransport{constructor(e){super({logPrefix:"pinta-opencode",resolveOptions:()=>e.endpoint?{endpoint:e.endpoint,headers:e.headers}:null})}};var se=E(b(),1);var Ue=E(b(),1),qt=50,$t="pinta-opencode/0.6.0";function Ze(t,e,r={}){return(0,Ue.evaluateGuard)(t,e,{timeoutMs:r.timeoutMs??qt,token:r.token,disabled:r.disabled,userAgent:$t})}var k=E(b(),1);import oe from"os";var q;function Ct(){if(q===void 0)try{q=oe.userInfo().username}catch{q=process.env.USER??process.env.LOGNAME??(typeof process.getuid=="function"?String(process.getuid()):"unknown")}return q}var Ke="0.6.0",Ft=new Set(["opencode.kind","opencode.event_type","opencode.tool","opencode.session_id","opencode.sessionID","opencode.call_id","opencode.callID","opencode.agent","opencode.model","opencode.exit","opencode.truncated","opencode.title"]),Vt=new Set(["opencode.args","opencode.input","opencode.output","opencode.tool_input"]),Lt={skipRedactKeys:Ft,bashContextKeys:Vt};function Gt(t){let e=[{key:"ingest.type",value:{stringValue:"opencode"}}];return e.push(...(0,k.attrsFromRecord)(t,"opencode",Lt)),e}function Xt(t){return[{key:"service.name",value:{stringValue:"opencode"}},{key:"service.version",value:{stringValue:t}},{key:"telemetry.sdk.name",value:{stringValue:"pinta-opencode"}},{key:"telemetry.sdk.language",value:{stringValue:"nodejs"}},{key:"telemetry.sdk.version",value:{stringValue:Ke}},{key:"process.pid",value:{intValue:process.pid}},{key:"process.owner",value:{stringValue:Ct()}},{key:"host.name",value:{stringValue:oe.hostname()}},{key:"host.arch",value:{stringValue:oe.arch()}}]}function We(t){return(0,k.buildPayload)({traceId:t.traceId,spanName:t.name,attributes:Gt(t.fields),resource:Xt(t.serviceVersion),scope:{name:"pinta-opencode",version:Ke},now:t.now,guard:t.guard})}var $=class{constructor(e,r,n){this.transport=e;this.trace=r;this.config=n}async emit(e,r,n,s){let i=this.trace.currentTrace(r),u=We({name:e,traceId:i,fields:n,guard:s,serviceVersion:this.config.serviceVersion});await this.transport.send(u)}async lifecycle(e){let r=e.properties??{},n=typeof r.sessionID=="string"?r.sessionID:void 0;await this.emit(`opencode.event.${e.type??"unknown"}`,n,{kind:"event",event_type:e.type,session_id:n,...r}),e.type==="session.idle"&&await this.transport.flush()}async toolBefore(e,r,n){await this.emit("opencode.tool.before",e.sessionID,{...Je("tool.before",e),args:r},n)}async toolAfter(e,r){let n=r.metadata??{};await this.emit("opencode.tool.after",e.sessionID,{...Je("tool.after",e),title:r.title,output:r.output,exit:n.exit,truncated:n.truncated})}};function Je(t,e){return{kind:t,tool:e.tool,session_id:e.sessionID,call_id:e.callID}}function He(t,e){process.stderr.write(`[pinta-opencode] ${t}: ${e?.message??String(e)}
21
+ `)}function ie(t,e){return async(...r)=>{try{await e(...r)}catch(n){He(t,n)}}}var Yt=async(t,e)=>{let r=Ye(e??{}),n=new B({endpoint:r.endpoint,headers:r.headers}),s=new se.MemorySessionTraceManager,i=new $(n,s,r);async function u(a,c){let d=null;try{d=await Ze({spanId:a.sessionID,toolName:a.tool,method:"tool.execute.before",cwd:process.cwd(),toolInput:c,rawTextFields:{toolInput:zt(c)}},r.guardEndpoint,{timeoutMs:r.guardTimeoutMs,token:r.relayToken,disabled:r.guardDisabled}),await i.toolBefore(a,c,d)}catch(P){He("tool.execute.before",P)}return d}return{"chat.message":ie("chat.message",async a=>{s.newTrace(a?.sessionID)}),event:ie("event",async a=>{a?.event&&await i.lifecycle(a.event)}),"tool.execute.before":async(a,c)=>{let d=await u(a,c?.args);if(d?.decision==="DENY")throw new Error(d.userMessage??d.reason??"guard_deny")},"tool.execute.after":ie("tool.execute.after",(a,c)=>i.toolAfter(a,c))}};function zt(t){try{return typeof t=="string"?t:JSON.stringify(t)??""}catch{return String(t)}}var Tr=Yt;export{Yt as PintaOpencode,Tr as default};
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@pinta-ai/pinta-opencode",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "OTLP forwarder + guard for opencode (in-process plugin)",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.js",
7
7
  "exports": {
8
- ".": "./dist/plugin.js"
8
+ ".": "./dist/plugin.js",
9
+ "./lifecycle": "./dist/index.mjs"
9
10
  },
10
11
  "license": "PolyForm-Noncommercial-1.0.0",
11
12
  "engines": {
@@ -27,14 +28,15 @@
27
28
  },
28
29
  "scripts": {
29
30
  "bump": "node scripts/bump.mjs",
30
- "build": "tsc --noEmit && esbuild src/plugin.ts --bundle --platform=node --format=esm --target=node18 --minify --outfile=dist/plugin.js --banner:js=\"import { createRequire as __pintaCreateRequire } from 'module'; const require = __pintaCreateRequire(import.meta.url);\"",
31
+ "build": "tsc --noEmit && esbuild src/plugin.ts --bundle --platform=node --format=esm --target=node18 --minify --outfile=dist/plugin.js --banner:js=\"import { createRequire as __pintaCreateRequire } from 'module'; const require = __pintaCreateRequire(import.meta.url);\" && esbuild src/index.ts --bundle --platform=node --format=esm --target=node18 --outfile=dist/index.mjs --banner:js=\"import { createRequire as __pintaCreateRequire } from 'module'; const require = __pintaCreateRequire(import.meta.url);\"",
31
32
  "dev": "tsc --watch",
32
33
  "test": "vitest run",
33
34
  "test:watch": "vitest",
35
+ "smoke": "node scripts/smoke.mjs",
34
36
  "prepublishOnly": "npm run build"
35
37
  },
36
38
  "devDependencies": {
37
- "@pinta-ai/core": "^0.3.0",
39
+ "@pinta-ai/core": "^0.6.0",
38
40
  "@types/node": "^22.0.0",
39
41
  "esbuild": "0.24.2",
40
42
  "typescript": "^5.7.0",