@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 +23 -0
- package/dist/index.mjs +60 -29
- package/dist/plugin.js +13 -13
- package/package.json +1 -1
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:
|
|
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.
|
|
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.
|
|
1242
|
+
var SDK_VERSION = "0.7.0";
|
|
1219
1243
|
var SKIP_REDACT_KEYS = /* @__PURE__ */ new Set([
|
|
1220
|
-
"opencode.
|
|
1244
|
+
"opencode.hook",
|
|
1221
1245
|
"opencode.event_type",
|
|
1222
|
-
"opencode.
|
|
1246
|
+
"opencode.tool_name",
|
|
1223
1247
|
"opencode.session_id",
|
|
1224
1248
|
"opencode.sessionID",
|
|
1225
|
-
"opencode.
|
|
1226
|
-
"opencode.
|
|
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.
|
|
1235
|
-
"opencode.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1337
|
+
tool_response: output.output,
|
|
1313
1338
|
exit: meta.exit,
|
|
1314
1339
|
truncated: meta.truncated
|
|
1315
1340
|
});
|
|
1316
1341
|
}
|
|
1317
1342
|
};
|
|
1318
|
-
function toolIdentity(
|
|
1319
|
-
return {
|
|
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
|
|
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
|
|
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(
|
|
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 =
|
|
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 =
|
|
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
|
|
1537
|
+
return path3.join(xdg, "opencode");
|
|
1507
1538
|
}
|
|
1508
|
-
return
|
|
1539
|
+
return path3.join(homedir(), ".local", "share", "opencode");
|
|
1509
1540
|
}
|
|
1510
1541
|
function toPosixRelPath(root, absPath) {
|
|
1511
|
-
return
|
|
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 =
|
|
1558
|
+
const base = path3.posix.basename(relPath);
|
|
1528
1559
|
if (!base.startsWith("ses_")) return void 0;
|
|
1529
|
-
const ext =
|
|
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 =
|
|
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
|
|
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
|
|
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<
|
|
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=
|
|
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
|
|
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(
|
|
14
|
-
`);let i=[].concat(...n),u=0;for(let a of n){if(!await M((0,
|
|
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
|
|
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:
|
|
18
|
-
`);let i=[].concat(...n),u=0;for(let a of n){if(!await M((0,
|
|
19
|
-
`)}}};v.TraceManager=
|
|
20
|
-
`)){let n=r.trim();if(!n||n.startsWith("#"))continue;let
|
|
21
|
-
`)}function
|
|
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};
|