@pinta-ai/pinta-opencode 0.6.0 → 0.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0
4
+
5
+ - Telemetry now names each tool span by the opencode hook it arrived on
6
+ (`opencode.hook` = `tool.execute.before` / `tool.execute.after` / `event`) —
7
+ the same string the guard leg already sends as `method` — and reports
8
+ `opencode.cwd`, which the guard leg already sent and this leg never did.
9
+
10
+ Before this, the two halves of one tool call described it differently
11
+ (`kind: "tool.before"` vs `method: "tool.execute.before"`) and the ingest
12
+ parser dropped **every** span this plugin emitted, so opencode activity was
13
+ guarded but never recorded. The parser side was widened first
14
+ (`@pinta-ai/guard-runtime` 0.27.0) so already-installed copies of this plugin
15
+ are recorded too; this release makes new installs speak the aligned names
16
+ from the start.
17
+
18
+ Tool fields follow the same vocabulary as the other adapters:
19
+ `tool_name` / `tool_input` / `tool_response` / `tool_use_id`. Nothing is sent
20
+ under two names — the parser accepts the old spelling on behalf of installed
21
+ copies, and a field carried twice is a field whose copies can disagree.
22
+
23
+ The redaction policy tracks the renamed keys, so shell secrets in
24
+ `tool_input` / `tool_response` are still masked.
25
+
3
26
  ## 0.5.1
4
27
 
5
28
  - Bump `@pinta-ai/core` `^0.3.0` → `^0.5.0` (devDependency, bundled
package/dist/index.mjs CHANGED
@@ -1128,6 +1128,8 @@ var require_dist = __commonJS({
1128
1128
 
1129
1129
  // src/config.ts
1130
1130
  var import_core2 = __toESM(require_dist(), 1);
1131
+ import fs from "node:fs";
1132
+ import path from "node:path";
1131
1133
 
1132
1134
  // src/env-file.ts
1133
1135
  var import_core = __toESM(require_dist(), 1);
@@ -1153,6 +1155,28 @@ function resolveEndpoint(options) {
1153
1155
  if (base) return base.replace(/\/+$/, "") + "/v1/traces";
1154
1156
  return void 0;
1155
1157
  }
1158
+ var OPENCODE_PACKAGE_NAME = "opencode-ai";
1159
+ function versionFromExecPath() {
1160
+ let dir = path.dirname(process.execPath);
1161
+ for (let i = 0; i < 5; i++) {
1162
+ try {
1163
+ const pkg = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf8"));
1164
+ if (pkg.name === OPENCODE_PACKAGE_NAME && typeof pkg.version === "string" && pkg.version) {
1165
+ return pkg.version;
1166
+ }
1167
+ } catch {
1168
+ }
1169
+ const parent = path.dirname(dir);
1170
+ if (parent === dir) break;
1171
+ dir = parent;
1172
+ }
1173
+ return void 0;
1174
+ }
1175
+ function resolveServiceVersion() {
1176
+ const explicit = process.env.OPENCODE_VERSION?.trim();
1177
+ if (explicit) return explicit;
1178
+ return versionFromExecPath();
1179
+ }
1156
1180
  function resolveConfig(options = {}) {
1157
1181
  loadEnvFile();
1158
1182
  const relayToken = firstSet(options.token, process.env.PINTA_OPENCODE_TOKEN);
@@ -1170,7 +1194,7 @@ function resolveConfig(options = {}) {
1170
1194
  relayToken,
1171
1195
  guardTimeoutMs,
1172
1196
  guardDisabled: process.env.PINTA_OPENCODE_GUARD_DISABLED === "1",
1173
- serviceVersion: process.env.OPENCODE_VERSION || "unknown"
1197
+ serviceVersion: resolveServiceVersion()
1174
1198
  };
1175
1199
  }
1176
1200
 
@@ -1191,7 +1215,7 @@ var import_core4 = __toESM(require_dist(), 1);
1191
1215
  // src/core/guard.ts
1192
1216
  var import_core5 = __toESM(require_dist(), 1);
1193
1217
  var DEFAULT_TIMEOUT_MS = 50;
1194
- var GUARD_UA = "pinta-opencode/0.6.0";
1218
+ var GUARD_UA = "pinta-opencode/0.7.0";
1195
1219
  function evaluateGuard(input, endpoint, opts = {}) {
1196
1220
  return (0, import_core5.evaluateGuard)(input, endpoint, {
1197
1221
  timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
@@ -1215,15 +1239,15 @@ function processOwner() {
1215
1239
  }
1216
1240
  return cachedProcessOwner;
1217
1241
  }
1218
- var SDK_VERSION = "0.6.0";
1242
+ var SDK_VERSION = "0.7.0";
1219
1243
  var SKIP_REDACT_KEYS = /* @__PURE__ */ new Set([
1220
- "opencode.kind",
1244
+ "opencode.hook",
1221
1245
  "opencode.event_type",
1222
- "opencode.tool",
1246
+ "opencode.tool_name",
1223
1247
  "opencode.session_id",
1224
1248
  "opencode.sessionID",
1225
- "opencode.call_id",
1226
- "opencode.callID",
1249
+ "opencode.tool_use_id",
1250
+ "opencode.cwd",
1227
1251
  "opencode.agent",
1228
1252
  "opencode.model",
1229
1253
  "opencode.exit",
@@ -1231,10 +1255,8 @@ var SKIP_REDACT_KEYS = /* @__PURE__ */ new Set([
1231
1255
  "opencode.title"
1232
1256
  ]);
1233
1257
  var BASH_CONTEXT_KEYS = /* @__PURE__ */ new Set([
1234
- "opencode.args",
1235
- "opencode.input",
1236
- "opencode.output",
1237
- "opencode.tool_input"
1258
+ "opencode.tool_input",
1259
+ "opencode.tool_response"
1238
1260
  ]);
1239
1261
  var ATTR_POLICY = {
1240
1262
  skipRedactKeys: SKIP_REDACT_KEYS,
@@ -1248,7 +1270,9 @@ function flattenFields(fields) {
1248
1270
  function resourceAttrs(serviceVersion) {
1249
1271
  return [
1250
1272
  { key: "service.name", value: { stringValue: "opencode" } },
1251
- { key: "service.version", value: { stringValue: serviceVersion } },
1273
+ // Omitted when unresolved — the absence is the honest signal, not "unknown".
1274
+ // A placeholder is indistinguishable from a real value downstream (PTA-347).
1275
+ ...serviceVersion ? [{ key: "service.version", value: { stringValue: serviceVersion } }] : [],
1252
1276
  { key: "telemetry.sdk.name", value: { stringValue: "pinta-opencode" } },
1253
1277
  { key: "telemetry.sdk.language", value: { stringValue: "nodejs" } },
1254
1278
  { key: "telemetry.sdk.version", value: { stringValue: SDK_VERSION } },
@@ -1287,9 +1311,10 @@ var Telemetry = class {
1287
1311
  const props = ev.properties ?? {};
1288
1312
  const sessionId = typeof props.sessionID === "string" ? props.sessionID : void 0;
1289
1313
  await this.emit(`opencode.event.${ev.type ?? "unknown"}`, sessionId, {
1290
- kind: "event",
1314
+ hook: "event",
1291
1315
  event_type: ev.type,
1292
1316
  session_id: sessionId,
1317
+ cwd: process.cwd(),
1293
1318
  ...props
1294
1319
  });
1295
1320
  if (ev.type === "session.idle") await this.transport.flush();
@@ -1299,7 +1324,7 @@ var Telemetry = class {
1299
1324
  await this.emit(
1300
1325
  "opencode.tool.before",
1301
1326
  input.sessionID,
1302
- { ...toolIdentity("tool.before", input), args },
1327
+ { ...toolIdentity("tool.execute.before", input), tool_input: args },
1303
1328
  guard
1304
1329
  );
1305
1330
  }
@@ -1307,16 +1332,22 @@ var Telemetry = class {
1307
1332
  async toolAfter(input, output) {
1308
1333
  const meta = output.metadata ?? {};
1309
1334
  await this.emit("opencode.tool.after", input.sessionID, {
1310
- ...toolIdentity("tool.after", input),
1335
+ ...toolIdentity("tool.execute.after", input),
1311
1336
  title: output.title,
1312
- output: output.output,
1337
+ tool_response: output.output,
1313
1338
  exit: meta.exit,
1314
1339
  truncated: meta.truncated
1315
1340
  });
1316
1341
  }
1317
1342
  };
1318
- function toolIdentity(kind, input) {
1319
- return { kind, tool: input.tool, session_id: input.sessionID, call_id: input.callID };
1343
+ function toolIdentity(hook, input) {
1344
+ return {
1345
+ hook,
1346
+ tool_name: input.tool,
1347
+ session_id: input.sessionID,
1348
+ tool_use_id: input.callID,
1349
+ cwd: process.cwd()
1350
+ };
1320
1351
  }
1321
1352
 
1322
1353
  // src/plugin.ts
@@ -1395,13 +1426,13 @@ var plugin_default = PintaOpencode;
1395
1426
  // src/lifecycle/scanner.ts
1396
1427
  import { opendir, stat as stat2 } from "node:fs/promises";
1397
1428
  import { homedir } from "node:os";
1398
- import path2 from "node:path";
1429
+ import path3 from "node:path";
1399
1430
 
1400
1431
  // src/lifecycle/snapshot.ts
1401
1432
  import { execFile } from "node:child_process";
1402
1433
  import { copyFile, mkdtemp, rm, stat } from "node:fs/promises";
1403
1434
  import { tmpdir } from "node:os";
1404
- import path from "node:path";
1435
+ import path2 from "node:path";
1405
1436
  import { promisify } from "node:util";
1406
1437
  var execFileAsync = promisify(execFile);
1407
1438
  var DEFAULT_STABLE_MS = 2e3;
@@ -1420,7 +1451,7 @@ async function sleep(ms) {
1420
1451
  await new Promise((resolve) => setTimeout(resolve, ms));
1421
1452
  }
1422
1453
  async function makeSnapshotDir(base) {
1423
- return mkdtemp(path.join(base, "pinta-opencode-snap-"));
1454
+ return mkdtemp(path2.join(base, "pinta-opencode-snap-"));
1424
1455
  }
1425
1456
  async function backupViaCli(sqlite3Path, dbPath, outPath) {
1426
1457
  const backupCmd = `.backup '${outPath.replace(/'/g, "''")}'`;
@@ -1428,7 +1459,7 @@ async function backupViaCli(sqlite3Path, dbPath, outPath) {
1428
1459
  }
1429
1460
  async function quiesceCopy(file, outDir, stableMs, maxRetries, deadlineMs) {
1430
1461
  const dbPath = file.absPath;
1431
- const outDbPath = path.join(outDir, path.basename(dbPath));
1462
+ const outDbPath = path2.join(outDir, path2.basename(dbPath));
1432
1463
  const deadline = Date.now() + deadlineMs;
1433
1464
  let lastErr;
1434
1465
  for (let attempt = 0; attempt < maxRetries; attempt++) {
@@ -1479,7 +1510,7 @@ async function snapshot(file, opts = {}) {
1479
1510
  const outDir = await makeSnapshotDir(base);
1480
1511
  try {
1481
1512
  if (sqlite3Path) {
1482
- const outPath = path.join(outDir, `${path.basename(file.absPath)}.snapshot`);
1513
+ const outPath = path2.join(outDir, `${path2.basename(file.absPath)}.snapshot`);
1483
1514
  try {
1484
1515
  await backupViaCli(sqlite3Path, file.absPath, outPath);
1485
1516
  return outPath;
@@ -1503,12 +1534,12 @@ function dataRoot() {
1503
1534
  }
1504
1535
  const xdg = process.env.XDG_DATA_HOME;
1505
1536
  if (xdg && xdg.length > 0) {
1506
- return path2.join(xdg, "opencode");
1537
+ return path3.join(xdg, "opencode");
1507
1538
  }
1508
- return path2.join(homedir(), ".local", "share", "opencode");
1539
+ return path3.join(homedir(), ".local", "share", "opencode");
1509
1540
  }
1510
1541
  function toPosixRelPath(root, absPath) {
1511
- return path2.relative(root, absPath).split(path2.sep).join("/");
1542
+ return path3.relative(root, absPath).split(path3.sep).join("/");
1512
1543
  }
1513
1544
  function isExcluded(relPath) {
1514
1545
  if (relPath === "auth.json") return true;
@@ -1524,9 +1555,9 @@ function semanticsFor(relPath) {
1524
1555
  return relPath.endsWith(".db") ? "database" : "rewritten-doc";
1525
1556
  }
1526
1557
  function sessionIdFor(relPath) {
1527
- const base = path2.posix.basename(relPath);
1558
+ const base = path3.posix.basename(relPath);
1528
1559
  if (!base.startsWith("ses_")) return void 0;
1529
- const ext = path2.posix.extname(base);
1560
+ const ext = path3.posix.extname(base);
1530
1561
  return ext ? base.slice(0, -ext.length) : base;
1531
1562
  }
1532
1563
  function classify(relPath) {
@@ -1550,7 +1581,7 @@ async function* walkFiles(root, dir) {
1550
1581
  }
1551
1582
  try {
1552
1583
  for await (const entry of entries) {
1553
- const absPath = path2.join(dir, entry.name);
1584
+ const absPath = path3.join(dir, entry.name);
1554
1585
  const relPath = toPosixRelPath(root, absPath);
1555
1586
  if (entry.isDirectory()) {
1556
1587
  if (isExcludedDir(relPath)) continue;
package/dist/plugin.js CHANGED
@@ -1,21 +1,21 @@
1
1
  import { createRequire as __pintaCreateRequire } from 'module'; const require = __pintaCreateRequire(import.meta.url);
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})+`
2
+ var tt=Object.create;var ue=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var nt=Object.getOwnPropertyNames;var ot=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 it=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of nt(e))!st.call(t,o)&&o!==r&&ue(t,o,{get:()=>e[o],enumerable:!(n=rt(e,o))||n.enumerable});return t};var E=(t,e,r)=>(r=t!=null?tt(ot(t)):{},it(e||!t||!t.__esModule?ue(r,"default",{value:t,enumerable:!0}):r,t));var F=_(p=>{"use strict";Object.defineProperty(p,"__esModule",{value:!0});p.PATTERNS=p.MAX_BYTES=void 0;p.truncateTo=ce;p.truncate=at;p.collectMatches=le;p.resolveOverlaps=de;p.applyMatches=fe;p.redact=ut;p.MAX_BYTES=102400;function ce(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 at(t){return ce(t,p.MAX_BYTES)}p.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 le(t,e){let r=[];for(let n of p.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 u=n.captureGroup??0,a=i[u];if(a===void 0){i.index===o.lastIndex&&o.lastIndex++;continue}let c=i.index,d=i.index+i[0].length,P=c+i[0].indexOf(a),et=P+a.length;r.push({start:c,end:d,replaceStart:P,replaceEnd:et,type:n.type}),i.index===o.lastIndex&&o.lastIndex++}}return r}function de(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 fe(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 ut(t,e={}){if(t.length===0)return t;let r=le(t,e);if(r.length===0)return t;let n=de(r);return fe(t,n)}});var V=_(f=>{"use strict";var ct=f&&f.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(f,"__esModule",{value:!0});f.MAX_SPAN_BYTES=void 0;f.ulidToTraceId=ye;f.newSpanId=_e;f.snakeCase=ft;f.toOtlpValue=me;f.attrsFromRecord=pt;f.guardAttrs=Oe;f.clientAttrs=Te;f.enforceSpanBudget=Pe;f.buildPayload=gt;f.mergeBatch=ht;var lt=ct(h("crypto")),$=F(),dt="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function ye(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=dt.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 _e(){return lt.default.randomBytes(8).toString("hex")}function ft(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 R(t,e,r){let n=(0,$.truncate)(e);if((r.skipRedactKeys??pe).has(t))return n;let o=(r.bashContextKeys??pe).has(t)?"bash":void 0;return(0,$.redact)(n,{context:o})}function me(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 pt(t,e,r={}){let n=[];for(let[o,i]of Object.entries(t)){let u=`${e}.${o}`,a=me(u,i,r);a!==null&&n.push({key:u,value:a})}return n}function Oe(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}}]}f.MAX_SPAN_BYTES=800*1024;function ge(t){let e=JSON.stringify(t);return e===void 0?0:Buffer.byteLength(e,"utf-8")}var he=1024;function Pe(t,e=f.MAX_SPAN_BYTES){let r=ge(t);for(let n=0;n<100&&r>e;n++){let o=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,o=c.value)}if(o===null||i<=he)break;let u=r-e,a=Math.max(he,i-u-64);o.stringValue=(0,$.truncateTo)(o.stringValue,a),r=ge(t)}return t}function gt(t){let e=t.now??Date.now(),r=(BigInt(e)*1000000n).toString(),n=[...t.attributes];t.guard&&n.push(...Oe(t.guard));let o=t.clientTiming??(t.guard?.clientRttMs!==void 0?{op:"guard",rttMs:t.guard.clientRttMs}:null);o&&n.push(...Te(o));let i={traceId:ye(t.traceId),spanId:_e(),name:t.spanName,kind:t.spanKind??1,startTimeUnixNano:r,endTimeUnixNano:r,attributes:n};return Pe(i),{resourceSpans:[{resource:{attributes:t.resource},scopeSpans:[{scope:t.scope,spans:[i]}]}]}}function ht(t){let e=[];for(let r of t)e.push(...r.resourceSpans);return{resourceSpans:e}}});var ve=_(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});G.evaluateGuard=Ot;var yt=1e4,_t="pinta-core";function L(t,e){return{decision:"ALLOW",reason:null,userMessage:null,durationMs:t,clientRttMs:t,failOpenReason:e}}var mt=new Set(["ALLOW","DENY","REVIEW"]);async function Ot(t,e,r={}){if(!e||r.disabled)return null;let n=r.timeoutMs??yt,o=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??_t,"x-pinta-relay-token":r.token??""},body:JSON.stringify({input:t}),signal:i.signal});if(a.status!==200)return L(Date.now()-o,"error");let c=await a.json(),d=c?.durationMs===void 0||typeof c.durationMs=="number"&&Number.isFinite(c.durationMs);if(!c||!mt.has(c.decision)||!d)return L(Date.now()-o,"error");let P=Date.now()-o;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()-o,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=Pt;var Se=Tt(h("fs"));function Pt(t,e){let r=`${t}.${process.pid}.tmp`;Se.default.writeFileSync(r,e),Se.default.renameSync(r,t)}});var z=_(m=>{"use strict";var be=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=be(h("fs")),D=be(h("path")),vt=I(),j=1e3,St=50,bt=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
3
  `;g.default.appendFileSync(this.filePath,r),this.trim()}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue enqueue failed: ${r}
4
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(`
5
+ `))if(n.trim())try{let o=JSON.parse(n);Array.isArray(o?.payload?.resourceSpans)&&r.push(o)}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,vt.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
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}`:""}
9
+ `),!1}for(;Date.now()-e<St;)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=bt,o=Date.now()+n;for(;Date.now()<o;);}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 xe=_(l=>{"use strict";Object.defineProperty(l,"__esModule",{value:!0});l.MemoryTransport=l.DiskTransport=l.MAX_POST_BYTES=void 0;l.parseHeadersEnv=we;l.envOptionsResolver=Me;l.postOtlp=M;var Ee=z(),Ae=V(),Et=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 ke(t,e,r){let n=[],o=[],i=[],u=0;for(let a of t){let c=e(a);if(c>r){o.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:o}}function we(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 Me(){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:we(process.env.OTEL_EXPORTER_OTLP_HEADERS)}:null}async function M(t,e,r){let n=new AbortController,o=setTimeout(()=>n.abort(),Et);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}`:""}
12
12
  `),!1}return!0}catch(i){return process.stderr.write(`[${r}] OTLP POST failed: ${i.message??String(i)}
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)}
13
+ `),!1}finally{clearTimeout(o)}}var U=class{queue;logPrefix;resolveOptions;constructor(e){this.queue=new Ee.DiskRetryQueue(e.pluginData,e.logPrefix),this.logPrefix=e.logPrefix,this.resolveOptions=e.resolveOptions??Me}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:o}=ke(r,a=>N(a.payload),l.MAX_POST_BYTES);o.length>0&&process.stderr.write(`[${this.logPrefix}] dropping ${o.length} oversized retry ${o.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,Ae.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
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};
16
+ `),!0)}};l.DiskTransport=U;var K=class{queue=new Ee.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:o}=ke(r,N,l.MAX_POST_BYTES);o.length>0&&process.stderr.write(`[${this.logPrefix}] dropping ${o.length} oversized buffered ${o.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,Ae.mergeBatch)(a),e,this.logPrefix))break;u+=a.length}for(let a of i.slice(u))this.queue.enqueue(a)}};l.MemoryTransport=K});var H=_(v=>{"use strict";var W=v&&v.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(v,"__esModule",{value:!0});v.TraceManager=void 0;v.generateUlid=Ie;var Re=W(h("fs")),At=W(h("path")),kt=W(h("crypto")),wt=I(),Z="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function Ie(){let t=Date.now(),e="",r=t;for(let i=0;i<10;i++)e=Z[r&31]+e,r=Math.floor(r/32);let n=kt.default.randomBytes(10),o="";for(let i=0;i<10;i++)o+=Z[n[i]&31];for(;o.length<16;)o+=Z[0];return e+o}var J=class{tracePath;constructor(e){this.tracePath=e}newTrace(){let e=Ie();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(At.default.dirname(this.tracePath),{recursive:!0}),(0,wt.atomicWriteFileSync)(this.tracePath,JSON.stringify({traceId:e}))}catch(r){process.stderr.write(`[pinta-core] trace persistence failed: ${r}
19
+ `)}}};v.TraceManager=J});var qe=_(O=>{"use strict";var je=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 De=je(h("fs")),Mt=je(h("path")),Ne=H(),xt=I(),Be=200,Q=class{tracePath;maxSessions;constructor(e,r={}){this.tracePath=e,this.maxSessions=r.maxSessions??Be}read(){try{let e=JSON.parse(De.default.readFileSync(this.tracePath,"utf-8"));if(e&&typeof e=="object"&&!("traceId"in e))return e}catch{}return{}}write(e){try{De.default.mkdirSync(Mt.default.dirname(this.tracePath),{recursive:!0});let r=Object.entries(e),n=r.length>this.maxSessions?Object.fromEntries(r.slice(-this.maxSessions)):e;(0,xt.atomicWriteFileSync)(this.tracePath,JSON.stringify(n))}catch{}}newTrace(e){let r=e||"default",n=(0,Ne.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)}};O.DiskSessionTraceManager=Q;var ee=class{map=new Map;maxSessions;constructor(e={}){this.maxSessions=e.maxSessions??Be}newTrace(e){let r=e||"default",n=(0,Ne.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)}};O.MemorySessionTraceManager=ee});var $e=_(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=Dt;S.parseEnvFile=Fe;S.loadEnvFile=jt;var Rt=te(h("node:fs")),It=te(h("node:os")),Ce=te(h("node:path"));function Dt(t,e,r){let n=r?process.env[r]:void 0,o=n&&n.length>0?n:Ce.default.join(It.default.homedir(),t);return Ce.default.join(o,e)}function Fe(t){let e={};for(let r of t.split(`
20
+ `)){let n=r.trim();if(!n||n.startsWith("#"))continue;let o=n.indexOf("=");if(o<0)continue;let i=n.slice(0,o).trim(),u=n.slice(o+1).trim();(u.startsWith('"')&&u.endsWith('"')||u.startsWith("'")&&u.endsWith("'"))&&(u=u.slice(1,-1)),i&&(e[i]=u)}return e}function jt(t){let e;try{e=Rt.default.readFileSync(t,"utf-8")}catch{return}let r=Fe(e);for(let[n,o]of Object.entries(r))process.env[n]===void 0&&(process.env[n]=o)}});var b=_(s=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0});s.loadEnvFile=s.parseEnvFile=s.envFilePath=s.MemorySessionTraceManager=s.DiskSessionTraceManager=s.generateUlid=s.TraceManager=s.MAX_POST_BYTES=s.parseHeadersEnv=s.envOptionsResolver=s.postOtlp=s.MemoryTransport=s.DiskTransport=s.MemoryRetryQueue=s.DiskRetryQueue=s.evaluateGuard=s.MAX_SPAN_BYTES=s.enforceSpanBudget=s.mergeBatch=s.buildPayload=s.clientAttrs=s.guardAttrs=s.attrsFromRecord=s.toOtlpValue=s.snakeCase=s.newSpanId=s.ulidToTraceId=s.MAX_BYTES=s.PATTERNS=s.applyMatches=s.resolveOverlaps=s.collectMatches=s.truncateTo=s.truncate=s.redact=void 0;var T=F();Object.defineProperty(s,"redact",{enumerable:!0,get:function(){return T.redact}});Object.defineProperty(s,"truncate",{enumerable:!0,get:function(){return T.truncate}});Object.defineProperty(s,"truncateTo",{enumerable:!0,get:function(){return T.truncateTo}});Object.defineProperty(s,"collectMatches",{enumerable:!0,get:function(){return T.collectMatches}});Object.defineProperty(s,"resolveOverlaps",{enumerable:!0,get:function(){return T.resolveOverlaps}});Object.defineProperty(s,"applyMatches",{enumerable:!0,get:function(){return T.applyMatches}});Object.defineProperty(s,"PATTERNS",{enumerable:!0,get:function(){return T.PATTERNS}});Object.defineProperty(s,"MAX_BYTES",{enumerable:!0,get:function(){return T.MAX_BYTES}});var y=V();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,"clientAttrs",{enumerable:!0,get:function(){return y.clientAttrs}});Object.defineProperty(s,"buildPayload",{enumerable:!0,get:function(){return y.buildPayload}});Object.defineProperty(s,"mergeBatch",{enumerable:!0,get:function(){return y.mergeBatch}});Object.defineProperty(s,"enforceSpanBudget",{enumerable:!0,get:function(){return y.enforceSpanBudget}});Object.defineProperty(s,"MAX_SPAN_BYTES",{enumerable:!0,get:function(){return y.MAX_SPAN_BYTES}});var Nt=ve();Object.defineProperty(s,"evaluateGuard",{enumerable:!0,get:function(){return Nt.evaluateGuard}});var Ve=z();Object.defineProperty(s,"DiskRetryQueue",{enumerable:!0,get:function(){return Ve.DiskRetryQueue}});Object.defineProperty(s,"MemoryRetryQueue",{enumerable:!0,get:function(){return Ve.MemoryRetryQueue}});var A=xe();Object.defineProperty(s,"DiskTransport",{enumerable:!0,get:function(){return A.DiskTransport}});Object.defineProperty(s,"MemoryTransport",{enumerable:!0,get:function(){return A.MemoryTransport}});Object.defineProperty(s,"postOtlp",{enumerable:!0,get:function(){return A.postOtlp}});Object.defineProperty(s,"envOptionsResolver",{enumerable:!0,get:function(){return A.envOptionsResolver}});Object.defineProperty(s,"parseHeadersEnv",{enumerable:!0,get:function(){return A.parseHeadersEnv}});Object.defineProperty(s,"MAX_POST_BYTES",{enumerable:!0,get:function(){return A.MAX_POST_BYTES}});var Le=H();Object.defineProperty(s,"TraceManager",{enumerable:!0,get:function(){return Le.TraceManager}});Object.defineProperty(s,"generateUlid",{enumerable:!0,get:function(){return Le.generateUlid}});var Ge=qe();Object.defineProperty(s,"DiskSessionTraceManager",{enumerable:!0,get:function(){return Ge.DiskSessionTraceManager}});Object.defineProperty(s,"MemorySessionTraceManager",{enumerable:!0,get:function(){return Ge.MemorySessionTraceManager}});var re=$e();Object.defineProperty(s,"envFilePath",{enumerable:!0,get:function(){return re.envFilePath}});Object.defineProperty(s,"parseEnvFile",{enumerable:!0,get:function(){return re.parseEnvFile}});Object.defineProperty(s,"loadEnvFile",{enumerable:!0,get:function(){return re.loadEnvFile}})});var Ye=E(b(),1);import qt from"node:fs";import ne from"node:path";var x=E(b(),1);function Bt(){return(0,x.envFilePath)(".config/opencode","pinta-opencode.env","OPENCODE_CONFIG_DIR")}function Xe(t=Bt()){(0,x.loadEnvFile)(t)}function oe(...t){return t.find(e=>e)||void 0}function Ct(t){let e=oe(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"}var Ft="opencode-ai";function $t(){let t=ne.dirname(process.execPath);for(let e=0;e<5;e++){try{let n=JSON.parse(qt.readFileSync(ne.join(t,"package.json"),"utf8"));if(n.name===Ft&&typeof n.version=="string"&&n.version)return n.version}catch{}let r=ne.dirname(t);if(r===t)break;t=r}}function Vt(){let t=process.env.OPENCODE_VERSION?.trim();return t||$t()}function ze(t={}){Xe();let e=oe(t.token,process.env.PINTA_OPENCODE_TOKEN),r=(0,Ye.parseHeadersEnv)(t.headers??process.env.PINTA_OPENCODE_HEADERS??process.env.OTEL_EXPORTER_OTLP_HEADERS);e&&!Object.keys(r).some(o=>o.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:Ct(t),headers:r,guardEndpoint:oe(t.guard,process.env.PINTA_OPENCODE_GUARD),relayToken:e,guardTimeoutMs:n,guardDisabled:process.env.PINTA_OPENCODE_GUARD_DISABLED==="1",serviceVersion:Vt()}}var Ue=E(b(),1),B=class extends Ue.MemoryTransport{constructor(e){super({logPrefix:"pinta-opencode",resolveOptions:()=>e.endpoint?{endpoint:e.endpoint,headers:e.headers}:null})}};var se=E(b(),1);var Ke=E(b(),1),Lt=50,Gt="pinta-opencode/0.7.0";function Ze(t,e,r={}){return(0,Ke.evaluateGuard)(t,e,{timeoutMs:r.timeoutMs??Lt,token:r.token,disabled:r.disabled,userAgent:Gt})}var k=E(b(),1);import ie from"os";var q;function Xt(){if(q===void 0)try{q=ie.userInfo().username}catch{q=process.env.USER??process.env.LOGNAME??(typeof process.getuid=="function"?String(process.getuid()):"unknown")}return q}var Je="0.7.0",Yt=new Set(["opencode.hook","opencode.event_type","opencode.tool_name","opencode.session_id","opencode.sessionID","opencode.tool_use_id","opencode.cwd","opencode.agent","opencode.model","opencode.exit","opencode.truncated","opencode.title"]),zt=new Set(["opencode.tool_input","opencode.tool_response"]),Ut={skipRedactKeys:Yt,bashContextKeys:zt};function Kt(t){let e=[{key:"ingest.type",value:{stringValue:"opencode"}}];return e.push(...(0,k.attrsFromRecord)(t,"opencode",Ut)),e}function Zt(t){return[{key:"service.name",value:{stringValue:"opencode"}},...t?[{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:Je}},{key:"process.pid",value:{intValue:process.pid}},{key:"process.owner",value:{stringValue:Xt()}},{key:"host.name",value:{stringValue:ie.hostname()}},{key:"host.arch",value:{stringValue:ie.arch()}}]}function We(t){return(0,k.buildPayload)({traceId:t.traceId,spanName:t.name,attributes:Kt(t.fields),resource:Zt(t.serviceVersion),scope:{name:"pinta-opencode",version:Je},now:t.now,guard:t.guard})}var C=class{constructor(e,r,n){this.transport=e;this.trace=r;this.config=n}async emit(e,r,n,o){let i=this.trace.currentTrace(r),u=We({name:e,traceId:i,fields:n,guard:o,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,{hook:"event",event_type:e.type,session_id:n,cwd:process.cwd(),...r}),e.type==="session.idle"&&await this.transport.flush()}async toolBefore(e,r,n){await this.emit("opencode.tool.before",e.sessionID,{...He("tool.execute.before",e),tool_input:r},n)}async toolAfter(e,r){let n=r.metadata??{};await this.emit("opencode.tool.after",e.sessionID,{...He("tool.execute.after",e),title:r.title,tool_response:r.output,exit:n.exit,truncated:n.truncated})}};function He(t,e){return{hook:t,tool_name:e.tool,session_id:e.sessionID,tool_use_id:e.callID,cwd:process.cwd()}}function Qe(t,e){process.stderr.write(`[pinta-opencode] ${t}: ${e?.message??String(e)}
21
+ `)}function ae(t,e){return async(...r)=>{try{await e(...r)}catch(n){Qe(t,n)}}}var Jt=async(t,e)=>{let r=ze(e??{}),n=new B({endpoint:r.endpoint,headers:r.headers}),o=new se.MemorySessionTraceManager,i=new C(n,o,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:Wt(c)}},r.guardEndpoint,{timeoutMs:r.guardTimeoutMs,token:r.relayToken,disabled:r.guardDisabled}),await i.toolBefore(a,c,d)}catch(P){Qe("tool.execute.before",P)}return d}return{"chat.message":ae("chat.message",async a=>{o.newTrace(a?.sessionID)}),event:ae("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":ae("tool.execute.after",(a,c)=>i.toolAfter(a,c))}};function Wt(t){try{return typeof t=="string"?t:JSON.stringify(t)??""}catch{return String(t)}}var Ar=Jt;export{Jt as PintaOpencode,Ar as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pinta-ai/pinta-opencode",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "OTLP forwarder + guard for opencode (in-process plugin)",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.js",