@pinta-ai/pinta-cc 1.4.0 → 1.5.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/.claude-plugin/plugin.json +1 -1
- package/dist/index.js +14 -71
- package/package.json +10 -2
- package/dist/core/config.d.ts +0 -13
- package/dist/core/config.js +0 -22
- package/dist/core/config.js.map +0 -1
- package/dist/core/env-bridge.d.ts +0 -25
- package/dist/core/env-bridge.js +0 -43
- package/dist/core/env-bridge.js.map +0 -1
- package/dist/core/guard.d.ts +0 -14
- package/dist/core/guard.js +0 -51
- package/dist/core/guard.js.map +0 -1
- package/dist/core/identity.d.ts +0 -1
- package/dist/core/identity.js +0 -3
- package/dist/core/identity.js.map +0 -1
- package/dist/core/otlp.d.ts +0 -59
- package/dist/core/otlp.js +0 -224
- package/dist/core/otlp.js.map +0 -1
- package/dist/core/redact.d.ts +0 -57
- package/dist/core/redact.js +0 -149
- package/dist/core/redact.js.map +0 -1
- package/dist/core/retry-queue.d.ts +0 -26
- package/dist/core/retry-queue.js +0 -127
- package/dist/core/retry-queue.js.map +0 -1
- package/dist/core/trace.d.ts +0 -10
- package/dist/core/trace.js +0 -61
- package/dist/core/trace.js.map +0 -1
- package/dist/core/transport.d.ts +0 -18
- package/dist/core/transport.js +0 -125
- package/dist/core/transport.js.map +0 -1
- package/dist/core/types.d.ts +0 -65
- package/dist/core/types.js +0 -39
- package/dist/core/types.js.map +0 -1
- package/dist/env-file.d.ts +0 -9
- package/dist/env-file.js +0 -85
- package/dist/env-file.js.map +0 -1
- package/dist/handlers/default.d.ts +0 -6
- package/dist/handlers/default.js +0 -11
- package/dist/handlers/default.js.map +0 -1
- package/dist/handlers/permission.d.ts +0 -3
- package/dist/handlers/permission.js +0 -15
- package/dist/handlers/permission.js.map +0 -1
- package/dist/handlers/post-tool-use.d.ts +0 -3
- package/dist/handlers/post-tool-use.js +0 -15
- package/dist/handlers/post-tool-use.js.map +0 -1
- package/dist/handlers/pre-tool-use.d.ts +0 -3
- package/dist/handlers/pre-tool-use.js +0 -40
- package/dist/handlers/pre-tool-use.js.map +0 -1
- package/dist/handlers/session.d.ts +0 -3
- package/dist/handlers/session.js +0 -15
- package/dist/handlers/session.js.map +0 -1
- package/dist/handlers/stop.d.ts +0 -3
- package/dist/handlers/stop.js +0 -15
- package/dist/handlers/stop.js.map +0 -1
- package/dist/handlers/subagent.d.ts +0 -3
- package/dist/handlers/subagent.js +0 -15
- package/dist/handlers/subagent.js.map +0 -1
- package/dist/handlers/user-prompt.d.ts +0 -3
- package/dist/handlers/user-prompt.js +0 -15
- package/dist/handlers/user-prompt.js.map +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js.map +0 -1
|
@@ -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.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
6
6
|
"userConfig": {
|
|
7
7
|
"endpoint": {
|
package/dist/index.js
CHANGED
|
@@ -1,71 +1,14 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const session_js_1 = require("./handlers/session.js");
|
|
16
|
-
const subagent_js_1 = require("./handlers/subagent.js");
|
|
17
|
-
const stop_js_1 = require("./handlers/stop.js");
|
|
18
|
-
const permission_js_1 = require("./handlers/permission.js");
|
|
19
|
-
const default_js_1 = require("./handlers/default.js");
|
|
20
|
-
async function readStdin() {
|
|
21
|
-
const chunks = [];
|
|
22
|
-
for await (const chunk of process.stdin) {
|
|
23
|
-
chunks.push(chunk);
|
|
24
|
-
}
|
|
25
|
-
return Buffer.concat(chunks).toString("utf-8");
|
|
26
|
-
}
|
|
27
|
-
async function main() {
|
|
28
|
-
// Bridge CLAUDE_PLUGIN_OPTION_* → OTEL_EXPORTER_OTLP_* FIRST before any other logic.
|
|
29
|
-
// Explicit OTel env vars take precedence over the bridge.
|
|
30
|
-
(0, env_bridge_js_1.bridgeUserConfigToOtelEnv)();
|
|
31
|
-
let exitCode = 0;
|
|
32
|
-
try {
|
|
33
|
-
const config = (0, config_js_1.loadConfig)();
|
|
34
|
-
const raw = await readStdin();
|
|
35
|
-
const event = JSON.parse(raw);
|
|
36
|
-
if ((0, types_js_1.isSkippedHook)(event)) {
|
|
37
|
-
exitCode = await (0, default_js_1.handleDefault)(event);
|
|
38
|
-
}
|
|
39
|
-
else if ((0, types_js_1.isPreToolUseEvent)(event)) {
|
|
40
|
-
exitCode = await (0, pre_tool_use_js_1.handlePreToolUse)(event, config);
|
|
41
|
-
}
|
|
42
|
-
else if ((0, types_js_1.isPostToolUseEvent)(event)) {
|
|
43
|
-
exitCode = await (0, post_tool_use_js_1.handlePostToolUse)(event, config);
|
|
44
|
-
}
|
|
45
|
-
else if ((0, types_js_1.isUserPromptSubmitEvent)(event)) {
|
|
46
|
-
exitCode = await (0, user_prompt_js_1.handleUserPrompt)(event, config);
|
|
47
|
-
}
|
|
48
|
-
else if ((0, types_js_1.isSessionEvent)(event)) {
|
|
49
|
-
exitCode = await (0, session_js_1.handleSession)(event, config);
|
|
50
|
-
}
|
|
51
|
-
else if ((0, types_js_1.isSubagentEvent)(event)) {
|
|
52
|
-
exitCode = await (0, subagent_js_1.handleSubagent)(event, config);
|
|
53
|
-
}
|
|
54
|
-
else if ((0, types_js_1.isStopEvent)(event)) {
|
|
55
|
-
exitCode = await (0, stop_js_1.handleStop)(event, config);
|
|
56
|
-
}
|
|
57
|
-
else if ((0, types_js_1.isPermissionEvent)(event)) {
|
|
58
|
-
exitCode = await (0, permission_js_1.handlePermission)(event, config);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
exitCode = await (0, default_js_1.handleDefault)(event);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
catch (err) {
|
|
65
|
-
process.stderr.write(`[pinta-cc] error: ${err}\n`);
|
|
66
|
-
exitCode = 0; // top-level catch-all stays fail-open per spec §6
|
|
67
|
-
}
|
|
68
|
-
process.exit(exitCode);
|
|
69
|
-
}
|
|
70
|
-
main();
|
|
71
|
-
//# sourceMappingURL=index.js.map
|
|
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})+`
|
|
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(`
|
|
5
|
+
`)+`
|
|
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}`:""}
|
|
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();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pinta-ai/pinta-cc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Generic OTLP forwarder for Claude Code hook events",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
"url": "https://github.com/pinta-ai/pinta-cc/issues"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
|
-
"
|
|
24
|
+
"bump": "node scripts/bump.mjs",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"build": "tsc --noEmit && esbuild src/index.ts --bundle --platform=node --format=cjs --target=node18 --minify --outfile=dist/index.js",
|
|
25
27
|
"dev": "tsc --watch",
|
|
26
28
|
"test": "vitest run",
|
|
27
29
|
"test:watch": "vitest",
|
|
@@ -29,9 +31,15 @@
|
|
|
29
31
|
"prepublishOnly": "npm run build"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
34
|
+
"@pinta-ai/core": "^0.2.0",
|
|
32
35
|
"@types/node": "^22.0.0",
|
|
36
|
+
"esbuild": "^0.24.0",
|
|
33
37
|
"tsx": "^4.0.0",
|
|
34
38
|
"typescript": "^5.7.0",
|
|
35
39
|
"vitest": "^2.1.0"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"registry": "https://registry.npmjs.org",
|
|
43
|
+
"access": "public"
|
|
36
44
|
}
|
|
37
45
|
}
|
package/dist/core/config.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plugin config — ONLY the bits we actually use after v1.2.
|
|
3
|
-
* Endpoint/headers come from OTEL_EXPORTER_OTLP_* env vars (set by
|
|
4
|
-
* env-bridge.ts at process startup) — they are NOT in this struct.
|
|
5
|
-
*/
|
|
6
|
-
export interface PintaConfig {
|
|
7
|
-
pluginRoot: string;
|
|
8
|
-
pluginData: string;
|
|
9
|
-
tracePath: string;
|
|
10
|
-
}
|
|
11
|
-
export declare function loadConfig(): PintaConfig;
|
|
12
|
-
/** Returns true if OTel endpoint is configured (signal to silently disable telemetry). */
|
|
13
|
-
export declare function hasOtlpEndpoint(): boolean;
|
package/dist/core/config.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.loadConfig = loadConfig;
|
|
7
|
-
exports.hasOtlpEndpoint = hasOtlpEndpoint;
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
function loadConfig() {
|
|
10
|
-
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || process.cwd();
|
|
11
|
-
const pluginData = process.env.CLAUDE_PLUGIN_DATA || path_1.default.join(pluginRoot, ".plugin-data");
|
|
12
|
-
return {
|
|
13
|
-
pluginRoot,
|
|
14
|
-
pluginData,
|
|
15
|
-
tracePath: path_1.default.join(pluginData, "trace.json"),
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
/** Returns true if OTel endpoint is configured (signal to silently disable telemetry). */
|
|
19
|
-
function hasOtlpEndpoint() {
|
|
20
|
-
return Boolean(process.env.OTEL_EXPORTER_OTLP_ENDPOINT);
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=config.js.map
|
package/dist/core/config.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":";;;;;AAaA,gCASC;AAGD,0CAEC;AA3BD,gDAAwB;AAaxB,SAAgB,UAAU;IACxB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACnE,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAC1E,OAAO;QACL,UAAU;QACV,UAAU;QACV,SAAS,EAAE,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC;KAC/C,CAAC;AACJ,CAAC;AAED,0FAA0F;AAC1F,SAAgB,eAAe;IAC7B,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bridge Claude Code's userConfig env vars (CLAUDE_PLUGIN_OPTION_*) to the
|
|
3
|
-
* OTel SDK standard env vars (OTEL_EXPORTER_OTLP_*).
|
|
4
|
-
*
|
|
5
|
-
* Claude Code maps each plugin.json `userConfig.<key>` to a corresponding
|
|
6
|
-
* `CLAUDE_PLUGIN_OPTION_<KEY>` env var on hook spawn. We keep the user-
|
|
7
|
-
* facing names friendly (`endpoint`, `api_key`) and translate them into the
|
|
8
|
-
* canonical OTel env names so transport.ts (and any future OTel SDK adoption)
|
|
9
|
-
* can read them via the OTel-spec names.
|
|
10
|
-
*
|
|
11
|
-
* The user-facing `endpoint` is treated as a *full* OTLP/HTTP traces URL
|
|
12
|
-
* (e.g., `http://127.0.0.1:5147/v1/traces`), so we map it to
|
|
13
|
-
* `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` (signal-specific full URL per OTel
|
|
14
|
-
* spec) rather than `OTEL_EXPORTER_OTLP_ENDPOINT` (which is a base URL the
|
|
15
|
-
* SDK appends `/v1/traces` to). This way both the OTel SDK (when used) and
|
|
16
|
-
* pinta-cc's hand-written transport agree on the URL without any path
|
|
17
|
-
* manipulation downstream.
|
|
18
|
-
*
|
|
19
|
-
* Pinta Manager auto-injects `CLAUDE_PLUGIN_OPTION_*` via Claude Code's
|
|
20
|
-
* settings.json. OSS users fill them in via the `/plugin install` UI.
|
|
21
|
-
*
|
|
22
|
-
* Existing OTEL_EXPORTER_OTLP_TRACES_ENDPOINT / HEADERS take precedence
|
|
23
|
-
* (explicit override).
|
|
24
|
-
*/
|
|
25
|
-
export declare function bridgeUserConfigToOtelEnv(): void;
|
package/dist/core/env-bridge.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bridgeUserConfigToOtelEnv = bridgeUserConfigToOtelEnv;
|
|
4
|
-
/**
|
|
5
|
-
* Bridge Claude Code's userConfig env vars (CLAUDE_PLUGIN_OPTION_*) to the
|
|
6
|
-
* OTel SDK standard env vars (OTEL_EXPORTER_OTLP_*).
|
|
7
|
-
*
|
|
8
|
-
* Claude Code maps each plugin.json `userConfig.<key>` to a corresponding
|
|
9
|
-
* `CLAUDE_PLUGIN_OPTION_<KEY>` env var on hook spawn. We keep the user-
|
|
10
|
-
* facing names friendly (`endpoint`, `api_key`) and translate them into the
|
|
11
|
-
* canonical OTel env names so transport.ts (and any future OTel SDK adoption)
|
|
12
|
-
* can read them via the OTel-spec names.
|
|
13
|
-
*
|
|
14
|
-
* The user-facing `endpoint` is treated as a *full* OTLP/HTTP traces URL
|
|
15
|
-
* (e.g., `http://127.0.0.1:5147/v1/traces`), so we map it to
|
|
16
|
-
* `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` (signal-specific full URL per OTel
|
|
17
|
-
* spec) rather than `OTEL_EXPORTER_OTLP_ENDPOINT` (which is a base URL the
|
|
18
|
-
* SDK appends `/v1/traces` to). This way both the OTel SDK (when used) and
|
|
19
|
-
* pinta-cc's hand-written transport agree on the URL without any path
|
|
20
|
-
* manipulation downstream.
|
|
21
|
-
*
|
|
22
|
-
* Pinta Manager auto-injects `CLAUDE_PLUGIN_OPTION_*` via Claude Code's
|
|
23
|
-
* settings.json. OSS users fill them in via the `/plugin install` UI.
|
|
24
|
-
*
|
|
25
|
-
* Existing OTEL_EXPORTER_OTLP_TRACES_ENDPOINT / HEADERS take precedence
|
|
26
|
-
* (explicit override).
|
|
27
|
-
*/
|
|
28
|
-
function bridgeUserConfigToOtelEnv() {
|
|
29
|
-
if (process.env.CLAUDE_PLUGIN_OPTION_ENDPOINT &&
|
|
30
|
-
!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) {
|
|
31
|
-
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT =
|
|
32
|
-
process.env.CLAUDE_PLUGIN_OPTION_ENDPOINT;
|
|
33
|
-
}
|
|
34
|
-
if (process.env.CLAUDE_PLUGIN_OPTION_API_KEY && !process.env.OTEL_EXPORTER_OTLP_HEADERS) {
|
|
35
|
-
process.env.OTEL_EXPORTER_OTLP_HEADERS =
|
|
36
|
-
`x-pinta-relay-token=${process.env.CLAUDE_PLUGIN_OPTION_API_KEY}`;
|
|
37
|
-
}
|
|
38
|
-
// Expose for guard.ts (~/guard/evaluate auth header)
|
|
39
|
-
if (!process.env.PINTA_RELAY_TOKEN && process.env.CLAUDE_PLUGIN_OPTION_API_KEY) {
|
|
40
|
-
process.env.PINTA_RELAY_TOKEN = process.env.CLAUDE_PLUGIN_OPTION_API_KEY;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=env-bridge.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"env-bridge.js","sourceRoot":"","sources":["../../src/core/env-bridge.ts"],"names":[],"mappings":";;AAwBA,8DAgBC;AAxCD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,yBAAyB;IACvC,IACE,OAAO,CAAC,GAAG,CAAC,6BAA6B;QACzC,CAAC,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAC/C,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,kCAAkC;YAC5C,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC;IAC9C,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,CAAC;QACxF,OAAO,CAAC,GAAG,CAAC,0BAA0B;YACpC,uBAAuB,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,CAAC;IACtE,CAAC;IACD,qDAAqD;IACrD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC;IAC3E,CAAC;AACH,CAAC"}
|
package/dist/core/guard.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export interface GuardInput {
|
|
2
|
-
spanId: string;
|
|
3
|
-
toolName?: string;
|
|
4
|
-
toolInput?: unknown;
|
|
5
|
-
rawTextFields?: Record<string, string>;
|
|
6
|
-
}
|
|
7
|
-
export interface GuardResult {
|
|
8
|
-
decision: 'ALLOW' | 'DENY' | 'REVIEW';
|
|
9
|
-
reason: string | null;
|
|
10
|
-
userMessage: string | null;
|
|
11
|
-
durationMs: number;
|
|
12
|
-
failOpenReason?: 'timeout' | 'refused' | 'error';
|
|
13
|
-
}
|
|
14
|
-
export declare function evaluateGuard(input: GuardInput, endpoint: string | undefined): Promise<GuardResult | null>;
|
package/dist/core/guard.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.evaluateGuard = evaluateGuard;
|
|
4
|
-
const TIMEOUT_MS = 10_000;
|
|
5
|
-
// Self-identify to the manager's guard route so it can attribute calls to this
|
|
6
|
-
// adaptor (the route parses `pinta-*/<version>` out of the User-Agent). Keep the
|
|
7
|
-
// version in sync with package.json.
|
|
8
|
-
const GUARD_UA = 'pinta-cc/1.4.0';
|
|
9
|
-
function sleep(ms) {
|
|
10
|
-
return new Promise((_, reject) => setTimeout(() => {
|
|
11
|
-
const err = new Error('Guard request timed out');
|
|
12
|
-
err.name = 'TimeoutError';
|
|
13
|
-
reject(err);
|
|
14
|
-
}, ms));
|
|
15
|
-
}
|
|
16
|
-
async function evaluateGuard(input, endpoint) {
|
|
17
|
-
if (!endpoint)
|
|
18
|
-
return null;
|
|
19
|
-
if (process.env.PINTA_GUARD_DISABLED === '1')
|
|
20
|
-
return null;
|
|
21
|
-
const start = Date.now();
|
|
22
|
-
try {
|
|
23
|
-
const res = await Promise.race([
|
|
24
|
-
fetch(endpoint, {
|
|
25
|
-
method: 'POST',
|
|
26
|
-
headers: {
|
|
27
|
-
'content-type': 'application/json',
|
|
28
|
-
'user-agent': GUARD_UA,
|
|
29
|
-
'x-pinta-relay-token': process.env.PINTA_RELAY_TOKEN ?? '',
|
|
30
|
-
},
|
|
31
|
-
body: JSON.stringify({ input }),
|
|
32
|
-
}),
|
|
33
|
-
sleep(TIMEOUT_MS),
|
|
34
|
-
]);
|
|
35
|
-
if (res.status !== 200) {
|
|
36
|
-
return { decision: 'ALLOW', reason: null, userMessage: null, durationMs: Date.now() - start, failOpenReason: 'error' };
|
|
37
|
-
}
|
|
38
|
-
const body = (await res.json());
|
|
39
|
-
return {
|
|
40
|
-
decision: body.decision,
|
|
41
|
-
reason: body.reason,
|
|
42
|
-
userMessage: body.userMessage ?? null,
|
|
43
|
-
durationMs: body.durationMs ?? (Date.now() - start),
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
const reason = err.name === 'TimeoutError' ? 'timeout' : 'error';
|
|
48
|
-
return { decision: 'ALLOW', reason: null, userMessage: null, durationMs: Date.now() - start, failOpenReason: reason };
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
//# sourceMappingURL=guard.js.map
|
package/dist/core/guard.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/core/guard.ts"],"names":[],"mappings":";;AAmCA,sCAuCC;AAxDD,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,+EAA+E;AAC/E,iFAAiF;AACjF,qCAAqC;AACrC,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAElC,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjD,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC;IACd,CAAC,EAAE,EAAE,CAAC,CACP,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,aAAa,CACjC,KAAiB,EACjB,QAA4B;IAE5B,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC7B,KAAK,CAAC,QAAQ,EAAE;gBACd,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,YAAY,EAAE,QAAQ;oBACtB,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE;iBAC3D;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;aAChC,CAAC;YACF,KAAK,CAAC,UAAU,CAAC;SAClB,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;QACzH,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAK7B,CAAC;QACF,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI;YACrC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;SACpD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAmC,GAAa,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3G,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;IACxH,CAAC;AACH,CAAC"}
|
package/dist/core/identity.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/core/identity.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/core/identity.ts"],"names":[],"mappings":""}
|
package/dist/core/otlp.d.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { BaseEvent } from "./types.js";
|
|
2
|
-
import type { GuardResult } from "./guard.js";
|
|
3
|
-
export interface OtlpAttribute {
|
|
4
|
-
key: string;
|
|
5
|
-
value: {
|
|
6
|
-
stringValue: string;
|
|
7
|
-
} | {
|
|
8
|
-
intValue: number;
|
|
9
|
-
} | {
|
|
10
|
-
doubleValue: number;
|
|
11
|
-
} | {
|
|
12
|
-
boolValue: boolean;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
export interface OtlpSpan {
|
|
16
|
-
traceId: string;
|
|
17
|
-
spanId: string;
|
|
18
|
-
name: string;
|
|
19
|
-
kind: number;
|
|
20
|
-
startTimeUnixNano: string;
|
|
21
|
-
endTimeUnixNano: string;
|
|
22
|
-
attributes: OtlpAttribute[];
|
|
23
|
-
}
|
|
24
|
-
export interface ResourceSpans {
|
|
25
|
-
resource: {
|
|
26
|
-
attributes: OtlpAttribute[];
|
|
27
|
-
};
|
|
28
|
-
scopeSpans: Array<{
|
|
29
|
-
scope: {
|
|
30
|
-
name: string;
|
|
31
|
-
version: string;
|
|
32
|
-
};
|
|
33
|
-
spans: OtlpSpan[];
|
|
34
|
-
}>;
|
|
35
|
-
}
|
|
36
|
-
export interface OtlpPayload {
|
|
37
|
-
resourceSpans: ResourceSpans[];
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Convert a 26-char Crockford ULID into 32 lowercase hex chars (16 bytes)
|
|
41
|
-
* suitable for an OTLP traceId. Decoding is straightforward because each
|
|
42
|
-
* Crockford char carries 5 bits and 26 chars = 130 bits; we keep the low
|
|
43
|
-
* 128 bits (the spec already pads timestamp+randomness into 128 bits).
|
|
44
|
-
*/
|
|
45
|
-
export declare function ulidToTraceId(ulid: string): string;
|
|
46
|
-
/** Generate a fresh 16-hex-char (8-byte) span ID. */
|
|
47
|
-
export declare function newSpanId(): string;
|
|
48
|
-
export declare function buildOtlpPayload(args: {
|
|
49
|
-
event: BaseEvent;
|
|
50
|
-
traceId: string;
|
|
51
|
-
now?: number;
|
|
52
|
-
guard?: GuardResult | null;
|
|
53
|
-
}): OtlpPayload;
|
|
54
|
-
/**
|
|
55
|
-
* Combine multiple per-hook payloads into a single OTLP payload by
|
|
56
|
-
* concatenating their resourceSpans arrays. aware-backend's parser
|
|
57
|
-
* iterates over resourceSpans natively.
|
|
58
|
-
*/
|
|
59
|
-
export declare function mergeBatch(payloads: OtlpPayload[]): OtlpPayload;
|