@pinta-ai/pinta-opencode 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/index.mjs +244 -56
- package/dist/plugin.js +17 -10
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
- Bump `@pinta-ai/core` `^0.3.0` → `^0.5.0` (devDependency, bundled
|
|
6
|
+
into `dist/` at build). Pulls in the oversized-flush fix (pinta-manager#180
|
|
7
|
+
follow-up): the in-memory retry buffer now flushes in 900 KiB chunks instead
|
|
8
|
+
of one unbounded POST, spans are capped at 800 KiB at build time, and a
|
|
9
|
+
payload that alone exceeds the POST budget is dropped with a diagnostic
|
|
10
|
+
instead of poisoning every later flush. No adapter source change was needed.
|
|
11
|
+
|
|
3
12
|
## 0.4.0
|
|
4
13
|
|
|
5
14
|
- Consolidate the duplicated low-level utilities (`guard`, `otlp`, `redact`,
|
package/dist/index.mjs
CHANGED
|
@@ -37,19 +37,23 @@ var require_redact = __commonJS({
|
|
|
37
37
|
"use strict";
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.PATTERNS = exports.MAX_BYTES = void 0;
|
|
40
|
+
exports.truncateTo = truncateTo;
|
|
40
41
|
exports.truncate = truncate;
|
|
41
42
|
exports.collectMatches = collectMatches;
|
|
42
43
|
exports.resolveOverlaps = resolveOverlaps;
|
|
43
44
|
exports.applyMatches = applyMatches;
|
|
44
45
|
exports.redact = redact;
|
|
45
46
|
exports.MAX_BYTES = 102400;
|
|
46
|
-
function
|
|
47
|
+
function truncateTo(input, maxBytes) {
|
|
47
48
|
const buf = Buffer.from(input, "utf-8");
|
|
48
|
-
if (buf.length <=
|
|
49
|
+
if (buf.length <= maxBytes)
|
|
49
50
|
return input;
|
|
50
|
-
const head = buf.subarray(0,
|
|
51
|
+
const head = buf.subarray(0, Math.max(0, maxBytes)).toString("utf-8");
|
|
51
52
|
return `${head}\u2026[TRUNCATED:${buf.length}]`;
|
|
52
53
|
}
|
|
54
|
+
function truncate(input) {
|
|
55
|
+
return truncateTo(input, exports.MAX_BYTES);
|
|
56
|
+
}
|
|
53
57
|
exports.PATTERNS = [
|
|
54
58
|
{ type: "aws_access_key", regex: /AKIA[0-9A-Z]{16}/g },
|
|
55
59
|
{
|
|
@@ -175,6 +179,7 @@ var require_otlp = __commonJS({
|
|
|
175
179
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
176
180
|
};
|
|
177
181
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
182
|
+
exports.MAX_SPAN_BYTES = void 0;
|
|
178
183
|
exports.ulidToTraceId = ulidToTraceId2;
|
|
179
184
|
exports.newSpanId = newSpanId;
|
|
180
185
|
exports.snakeCase = snakeCase;
|
|
@@ -182,6 +187,7 @@ var require_otlp = __commonJS({
|
|
|
182
187
|
exports.attrsFromRecord = attrsFromRecord2;
|
|
183
188
|
exports.guardAttrs = guardAttrs;
|
|
184
189
|
exports.clientAttrs = clientAttrs;
|
|
190
|
+
exports.enforceSpanBudget = enforceSpanBudget;
|
|
185
191
|
exports.buildPayload = buildPayload2;
|
|
186
192
|
exports.mergeBatch = mergeBatch2;
|
|
187
193
|
var crypto_1 = __importDefault(__require("crypto"));
|
|
@@ -271,6 +277,35 @@ var require_otlp = __commonJS({
|
|
|
271
277
|
{ key: "pinta.client.op", value: { stringValue: timing.op } }
|
|
272
278
|
];
|
|
273
279
|
}
|
|
280
|
+
exports.MAX_SPAN_BYTES = 800 * 1024;
|
|
281
|
+
function byteLen(value) {
|
|
282
|
+
const json = JSON.stringify(value);
|
|
283
|
+
return json === void 0 ? 0 : Buffer.byteLength(json, "utf-8");
|
|
284
|
+
}
|
|
285
|
+
var MIN_ATTR_KEEP_BYTES = 1024;
|
|
286
|
+
function enforceSpanBudget(span, maxBytes = exports.MAX_SPAN_BYTES) {
|
|
287
|
+
let size = byteLen(span);
|
|
288
|
+
for (let pass = 0; pass < 100 && size > maxBytes; pass++) {
|
|
289
|
+
let largestValue = null;
|
|
290
|
+
let largest = 0;
|
|
291
|
+
for (const attr of span.attributes) {
|
|
292
|
+
if (!("stringValue" in attr.value))
|
|
293
|
+
continue;
|
|
294
|
+
const bytes = Buffer.byteLength(attr.value.stringValue, "utf-8");
|
|
295
|
+
if (bytes > largest) {
|
|
296
|
+
largest = bytes;
|
|
297
|
+
largestValue = attr.value;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (largestValue === null || largest <= MIN_ATTR_KEEP_BYTES)
|
|
301
|
+
break;
|
|
302
|
+
const overshoot = size - maxBytes;
|
|
303
|
+
const target = Math.max(MIN_ATTR_KEEP_BYTES, largest - overshoot - 64);
|
|
304
|
+
largestValue.stringValue = (0, redact_js_1.truncateTo)(largestValue.stringValue, target);
|
|
305
|
+
size = byteLen(span);
|
|
306
|
+
}
|
|
307
|
+
return span;
|
|
308
|
+
}
|
|
274
309
|
function buildPayload2(args) {
|
|
275
310
|
const ts = args.now ?? Date.now();
|
|
276
311
|
const tsNano = (BigInt(ts) * 1000000n).toString();
|
|
@@ -289,6 +324,7 @@ var require_otlp = __commonJS({
|
|
|
289
324
|
endTimeUnixNano: tsNano,
|
|
290
325
|
attributes: attrs
|
|
291
326
|
};
|
|
327
|
+
enforceSpanBudget(span);
|
|
292
328
|
return {
|
|
293
329
|
resourceSpans: [
|
|
294
330
|
{
|
|
@@ -325,13 +361,7 @@ var require_guard = __commonJS({
|
|
|
325
361
|
failOpenReason
|
|
326
362
|
};
|
|
327
363
|
}
|
|
328
|
-
|
|
329
|
-
return new Promise((_, reject) => setTimeout(() => {
|
|
330
|
-
const err = new Error("Guard request timed out");
|
|
331
|
-
err.name = "TimeoutError";
|
|
332
|
-
reject(err);
|
|
333
|
-
}, ms));
|
|
334
|
-
}
|
|
364
|
+
var VALID_DECISIONS = /* @__PURE__ */ new Set(["ALLOW", "DENY", "REVIEW"]);
|
|
335
365
|
async function evaluateGuard2(input, endpoint, opts = {}) {
|
|
336
366
|
if (!endpoint)
|
|
337
367
|
return null;
|
|
@@ -339,39 +369,64 @@ var require_guard = __commonJS({
|
|
|
339
369
|
return null;
|
|
340
370
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
341
371
|
const start = Date.now();
|
|
372
|
+
const controller = new AbortController();
|
|
373
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
342
374
|
try {
|
|
343
|
-
const res = await
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
sleep2(timeoutMs)
|
|
354
|
-
]);
|
|
375
|
+
const res = await fetch(endpoint, {
|
|
376
|
+
method: "POST",
|
|
377
|
+
headers: {
|
|
378
|
+
"content-type": "application/json",
|
|
379
|
+
"user-agent": opts.userAgent ?? DEFAULT_UA,
|
|
380
|
+
"x-pinta-relay-token": opts.token ?? ""
|
|
381
|
+
},
|
|
382
|
+
body: JSON.stringify({ input }),
|
|
383
|
+
signal: controller.signal
|
|
384
|
+
});
|
|
355
385
|
if (res.status !== 200) {
|
|
356
386
|
return failOpen2(Date.now() - start, "error");
|
|
357
387
|
}
|
|
358
388
|
const body = await res.json();
|
|
389
|
+
const durationMsOk = body?.durationMs === void 0 || typeof body.durationMs === "number" && Number.isFinite(body.durationMs);
|
|
390
|
+
if (!body || !VALID_DECISIONS.has(body.decision) || !durationMsOk) {
|
|
391
|
+
return failOpen2(Date.now() - start, "error");
|
|
392
|
+
}
|
|
359
393
|
const clientRttMs = Date.now() - start;
|
|
360
394
|
return {
|
|
361
395
|
decision: body.decision,
|
|
362
|
-
reason: body.reason,
|
|
396
|
+
reason: body.reason ?? null,
|
|
363
397
|
userMessage: body.userMessage ?? null,
|
|
364
398
|
durationMs: body.durationMs ?? clientRttMs,
|
|
365
399
|
clientRttMs
|
|
366
400
|
};
|
|
367
401
|
} catch (err) {
|
|
368
|
-
const
|
|
402
|
+
const name = err.name;
|
|
403
|
+
const reason = name === "AbortError" || name === "TimeoutError" ? "timeout" : "error";
|
|
369
404
|
return failOpen2(Date.now() - start, reason);
|
|
405
|
+
} finally {
|
|
406
|
+
clearTimeout(timer);
|
|
370
407
|
}
|
|
371
408
|
}
|
|
372
409
|
}
|
|
373
410
|
});
|
|
374
411
|
|
|
412
|
+
// node_modules/@pinta-ai/core/dist/atomic-write.js
|
|
413
|
+
var require_atomic_write = __commonJS({
|
|
414
|
+
"node_modules/@pinta-ai/core/dist/atomic-write.js"(exports) {
|
|
415
|
+
"use strict";
|
|
416
|
+
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
417
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
418
|
+
};
|
|
419
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
420
|
+
exports.atomicWriteFileSync = atomicWriteFileSync;
|
|
421
|
+
var fs_1 = __importDefault(__require("fs"));
|
|
422
|
+
function atomicWriteFileSync(finalPath, data) {
|
|
423
|
+
const tmpPath = `${finalPath}.${process.pid}.tmp`;
|
|
424
|
+
fs_1.default.writeFileSync(tmpPath, data);
|
|
425
|
+
fs_1.default.renameSync(tmpPath, finalPath);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
|
|
375
430
|
// node_modules/@pinta-ai/core/dist/retry-queue.js
|
|
376
431
|
var require_retry_queue = __commonJS({
|
|
377
432
|
"node_modules/@pinta-ai/core/dist/retry-queue.js"(exports) {
|
|
@@ -383,6 +438,7 @@ var require_retry_queue = __commonJS({
|
|
|
383
438
|
exports.MemoryRetryQueue = exports.DiskRetryQueue = void 0;
|
|
384
439
|
var fs_1 = __importDefault(__require("fs"));
|
|
385
440
|
var path_1 = __importDefault(__require("path"));
|
|
441
|
+
var atomic_write_js_1 = require_atomic_write();
|
|
386
442
|
var MAX_ENTRIES = 1e3;
|
|
387
443
|
var LOCK_TIMEOUT_MS = 50;
|
|
388
444
|
var LOCK_POLL_MS = 5;
|
|
@@ -419,7 +475,10 @@ var require_retry_queue = __commonJS({
|
|
|
419
475
|
if (!line.trim())
|
|
420
476
|
continue;
|
|
421
477
|
try {
|
|
422
|
-
|
|
478
|
+
const parsed = JSON.parse(line);
|
|
479
|
+
if (Array.isArray(parsed?.payload?.resourceSpans)) {
|
|
480
|
+
out.push(parsed);
|
|
481
|
+
}
|
|
423
482
|
} catch {
|
|
424
483
|
}
|
|
425
484
|
}
|
|
@@ -437,7 +496,7 @@ var require_retry_queue = __commonJS({
|
|
|
437
496
|
return;
|
|
438
497
|
}
|
|
439
498
|
fs_1.default.mkdirSync(path_1.default.dirname(this.filePath), { recursive: true });
|
|
440
|
-
|
|
499
|
+
(0, atomic_write_js_1.atomicWriteFileSync)(this.filePath, entries.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
441
500
|
} catch (err) {
|
|
442
501
|
process.stderr.write(`[${this.logPrefix}] retry-queue rewrite failed: ${err}
|
|
443
502
|
`);
|
|
@@ -449,7 +508,13 @@ var require_retry_queue = __commonJS({
|
|
|
449
508
|
*/
|
|
450
509
|
tryAcquireLock() {
|
|
451
510
|
const start = Date.now();
|
|
452
|
-
|
|
511
|
+
try {
|
|
512
|
+
fs_1.default.mkdirSync(path_1.default.dirname(this.lockPath), { recursive: true });
|
|
513
|
+
} catch (err) {
|
|
514
|
+
process.stderr.write(`[${this.logPrefix}] retry-queue lock mkdir failed: ${err}
|
|
515
|
+
`);
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
453
518
|
while (Date.now() - start < LOCK_TIMEOUT_MS) {
|
|
454
519
|
try {
|
|
455
520
|
const fd = fs_1.default.openSync(this.lockPath, "wx");
|
|
@@ -522,13 +587,41 @@ var require_transport = __commonJS({
|
|
|
522
587
|
"node_modules/@pinta-ai/core/dist/transport.js"(exports) {
|
|
523
588
|
"use strict";
|
|
524
589
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
525
|
-
exports.MemoryTransport = exports.DiskTransport = void 0;
|
|
590
|
+
exports.MemoryTransport = exports.DiskTransport = exports.MAX_POST_BYTES = void 0;
|
|
526
591
|
exports.parseHeadersEnv = parseHeadersEnv2;
|
|
527
592
|
exports.envOptionsResolver = envOptionsResolver;
|
|
528
593
|
exports.postOtlp = postOtlp;
|
|
529
594
|
var retry_queue_js_1 = require_retry_queue();
|
|
530
595
|
var otlp_js_1 = require_otlp();
|
|
531
596
|
var TIMEOUT_MS = 5e3;
|
|
597
|
+
exports.MAX_POST_BYTES = 900 * 1024;
|
|
598
|
+
function payloadBytes(payload) {
|
|
599
|
+
const json = JSON.stringify(payload);
|
|
600
|
+
return json === void 0 ? 0 : Buffer.byteLength(json, "utf-8");
|
|
601
|
+
}
|
|
602
|
+
function chunkByBytes(items, sizeOf, maxBytes) {
|
|
603
|
+
const chunks = [];
|
|
604
|
+
const oversize = [];
|
|
605
|
+
let current = [];
|
|
606
|
+
let currentBytes = 0;
|
|
607
|
+
for (const item of items) {
|
|
608
|
+
const bytes = sizeOf(item);
|
|
609
|
+
if (bytes > maxBytes) {
|
|
610
|
+
oversize.push(item);
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
if (current.length > 0 && currentBytes + bytes > maxBytes) {
|
|
614
|
+
chunks.push(current);
|
|
615
|
+
current = [];
|
|
616
|
+
currentBytes = 0;
|
|
617
|
+
}
|
|
618
|
+
current.push(item);
|
|
619
|
+
currentBytes += bytes;
|
|
620
|
+
}
|
|
621
|
+
if (current.length > 0)
|
|
622
|
+
chunks.push(current);
|
|
623
|
+
return { chunks, oversize };
|
|
624
|
+
}
|
|
532
625
|
function parseHeadersEnv2(raw) {
|
|
533
626
|
if (!raw)
|
|
534
627
|
return {};
|
|
@@ -601,10 +694,18 @@ var require_transport = __commonJS({
|
|
|
601
694
|
const opts = this.resolveOptions();
|
|
602
695
|
if (!opts)
|
|
603
696
|
return;
|
|
697
|
+
if (this.dropIfOversized(payload))
|
|
698
|
+
return;
|
|
604
699
|
const ok = await postOtlp(payload, opts, this.logPrefix);
|
|
605
700
|
if (!ok)
|
|
606
701
|
this.queue.enqueue(payload);
|
|
607
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* Drain the backlog in POST-budget-sized chunks. On a mid-flush failure the
|
|
705
|
+
* unsent tail stays queued for the next flush — earlier chunks that already
|
|
706
|
+
* landed are not re-sent (at-most-once per flush attempt, unchanged from the
|
|
707
|
+
* pre-chunking behavior where the whole batch either landed or stayed).
|
|
708
|
+
*/
|
|
608
709
|
async flush() {
|
|
609
710
|
const opts = this.resolveOptions();
|
|
610
711
|
if (!opts)
|
|
@@ -615,14 +716,36 @@ var require_transport = __commonJS({
|
|
|
615
716
|
const entries = this.queue.readAll();
|
|
616
717
|
if (entries.length === 0)
|
|
617
718
|
return;
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
719
|
+
const { chunks, oversize } = chunkByBytes(entries, (e) => payloadBytes(e.payload), exports.MAX_POST_BYTES);
|
|
720
|
+
if (oversize.length > 0) {
|
|
721
|
+
process.stderr.write(`[${this.logPrefix}] dropping ${oversize.length} oversized retry ${oversize.length === 1 ? "entry" : "entries"} (each > ${exports.MAX_POST_BYTES} bytes \u2014 the backend caps the request body, so they can never be delivered)
|
|
722
|
+
`);
|
|
723
|
+
}
|
|
724
|
+
const ordered = [].concat(...chunks);
|
|
725
|
+
let sent = 0;
|
|
726
|
+
for (const chunk of chunks) {
|
|
727
|
+
const ok = await postOtlp((0, otlp_js_1.mergeBatch)(chunk.map((e) => e.payload)), opts, this.logPrefix);
|
|
728
|
+
if (!ok)
|
|
729
|
+
break;
|
|
730
|
+
sent += chunk.length;
|
|
731
|
+
}
|
|
732
|
+
this.queue.rewrite(ordered.slice(sent));
|
|
733
|
+
} catch (err) {
|
|
734
|
+
process.stderr.write(`[${this.logPrefix}] flush failed: ${err?.message ?? String(err)}
|
|
735
|
+
`);
|
|
622
736
|
} finally {
|
|
623
737
|
this.queue.release();
|
|
624
738
|
}
|
|
625
739
|
}
|
|
740
|
+
/** True (and logged) when the payload alone exceeds the POST budget. */
|
|
741
|
+
dropIfOversized(payload) {
|
|
742
|
+
const bytes = payloadBytes(payload);
|
|
743
|
+
if (bytes <= exports.MAX_POST_BYTES)
|
|
744
|
+
return false;
|
|
745
|
+
process.stderr.write(`[${this.logPrefix}] dropping oversized span payload (${bytes} > ${exports.MAX_POST_BYTES} bytes) \u2014 undeliverable, not queued
|
|
746
|
+
`);
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
626
749
|
};
|
|
627
750
|
exports.DiskTransport = DiskTransport;
|
|
628
751
|
var MemoryTransport2 = class {
|
|
@@ -637,10 +760,16 @@ var require_transport = __commonJS({
|
|
|
637
760
|
const opts = this.resolveOptions();
|
|
638
761
|
if (!opts)
|
|
639
762
|
return;
|
|
763
|
+
if (payloadBytes(payload) > exports.MAX_POST_BYTES) {
|
|
764
|
+
process.stderr.write(`[${this.logPrefix}] dropping oversized span payload (> ${exports.MAX_POST_BYTES} bytes) \u2014 undeliverable, not buffered
|
|
765
|
+
`);
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
640
768
|
const ok = await postOtlp(payload, opts, this.logPrefix);
|
|
641
769
|
if (!ok)
|
|
642
770
|
this.queue.enqueue(payload);
|
|
643
771
|
}
|
|
772
|
+
/** Chunked drain — see DiskTransport.flush; the unsent tail is re-buffered. */
|
|
644
773
|
async flush() {
|
|
645
774
|
const opts = this.resolveOptions();
|
|
646
775
|
if (!opts)
|
|
@@ -648,11 +777,21 @@ var require_transport = __commonJS({
|
|
|
648
777
|
const buffered = this.queue.drain();
|
|
649
778
|
if (buffered.length === 0)
|
|
650
779
|
return;
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
780
|
+
const { chunks, oversize } = chunkByBytes(buffered, payloadBytes, exports.MAX_POST_BYTES);
|
|
781
|
+
if (oversize.length > 0) {
|
|
782
|
+
process.stderr.write(`[${this.logPrefix}] dropping ${oversize.length} oversized buffered ${oversize.length === 1 ? "payload" : "payloads"} (each > ${exports.MAX_POST_BYTES} bytes \u2014 undeliverable)
|
|
783
|
+
`);
|
|
784
|
+
}
|
|
785
|
+
const ordered = [].concat(...chunks);
|
|
786
|
+
let sent = 0;
|
|
787
|
+
for (const chunk of chunks) {
|
|
788
|
+
const ok = await postOtlp((0, otlp_js_1.mergeBatch)(chunk), opts, this.logPrefix);
|
|
789
|
+
if (!ok)
|
|
790
|
+
break;
|
|
791
|
+
sent += chunk.length;
|
|
792
|
+
}
|
|
793
|
+
for (const p of ordered.slice(sent))
|
|
794
|
+
this.queue.enqueue(p);
|
|
656
795
|
}
|
|
657
796
|
};
|
|
658
797
|
exports.MemoryTransport = MemoryTransport2;
|
|
@@ -672,6 +811,7 @@ var require_trace = __commonJS({
|
|
|
672
811
|
var fs_1 = __importDefault(__require("fs"));
|
|
673
812
|
var path_1 = __importDefault(__require("path"));
|
|
674
813
|
var crypto_1 = __importDefault(__require("crypto"));
|
|
814
|
+
var atomic_write_js_1 = require_atomic_write();
|
|
675
815
|
var CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
676
816
|
function generateUlid() {
|
|
677
817
|
const now = Date.now();
|
|
@@ -713,8 +853,13 @@ var require_trace = __commonJS({
|
|
|
713
853
|
return this.newTrace();
|
|
714
854
|
}
|
|
715
855
|
save(traceId) {
|
|
716
|
-
|
|
717
|
-
|
|
856
|
+
try {
|
|
857
|
+
fs_1.default.mkdirSync(path_1.default.dirname(this.tracePath), { recursive: true });
|
|
858
|
+
(0, atomic_write_js_1.atomicWriteFileSync)(this.tracePath, JSON.stringify({ traceId }));
|
|
859
|
+
} catch (err) {
|
|
860
|
+
process.stderr.write(`[pinta-core] trace persistence failed: ${err}
|
|
861
|
+
`);
|
|
862
|
+
}
|
|
718
863
|
}
|
|
719
864
|
};
|
|
720
865
|
exports.TraceManager = TraceManager;
|
|
@@ -733,6 +878,7 @@ var require_session_trace = __commonJS({
|
|
|
733
878
|
var fs_1 = __importDefault(__require("fs"));
|
|
734
879
|
var path_1 = __importDefault(__require("path"));
|
|
735
880
|
var trace_js_1 = require_trace();
|
|
881
|
+
var atomic_write_js_1 = require_atomic_write();
|
|
736
882
|
var DEFAULT_MAX_SESSIONS = 200;
|
|
737
883
|
var DiskSessionTraceManager = class {
|
|
738
884
|
tracePath;
|
|
@@ -756,7 +902,7 @@ var require_session_trace = __commonJS({
|
|
|
756
902
|
fs_1.default.mkdirSync(path_1.default.dirname(this.tracePath), { recursive: true });
|
|
757
903
|
const entries = Object.entries(map);
|
|
758
904
|
const capped = entries.length > this.maxSessions ? Object.fromEntries(entries.slice(-this.maxSessions)) : map;
|
|
759
|
-
|
|
905
|
+
(0, atomic_write_js_1.atomicWriteFileSync)(this.tracePath, JSON.stringify(capped));
|
|
760
906
|
} catch {
|
|
761
907
|
}
|
|
762
908
|
}
|
|
@@ -863,7 +1009,7 @@ var require_dist = __commonJS({
|
|
|
863
1009
|
"node_modules/@pinta-ai/core/dist/index.js"(exports) {
|
|
864
1010
|
"use strict";
|
|
865
1011
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
866
|
-
exports.loadEnvFile = exports.parseEnvFile = exports.envFilePath = exports.MemorySessionTraceManager = exports.DiskSessionTraceManager = exports.generateUlid = exports.TraceManager = exports.parseHeadersEnv = exports.envOptionsResolver = exports.postOtlp = exports.MemoryTransport = exports.DiskTransport = exports.MemoryRetryQueue = exports.DiskRetryQueue = exports.evaluateGuard = exports.mergeBatch = exports.buildPayload = exports.clientAttrs = exports.guardAttrs = exports.attrsFromRecord = exports.toOtlpValue = exports.snakeCase = exports.newSpanId = exports.ulidToTraceId = exports.MAX_BYTES = exports.PATTERNS = exports.applyMatches = exports.resolveOverlaps = exports.collectMatches = exports.truncate = exports.redact = void 0;
|
|
1012
|
+
exports.loadEnvFile = exports.parseEnvFile = exports.envFilePath = exports.MemorySessionTraceManager = exports.DiskSessionTraceManager = exports.generateUlid = exports.TraceManager = exports.MAX_POST_BYTES = exports.parseHeadersEnv = exports.envOptionsResolver = exports.postOtlp = exports.MemoryTransport = exports.DiskTransport = exports.MemoryRetryQueue = exports.DiskRetryQueue = exports.evaluateGuard = exports.MAX_SPAN_BYTES = exports.enforceSpanBudget = exports.mergeBatch = exports.buildPayload = exports.clientAttrs = exports.guardAttrs = exports.attrsFromRecord = exports.toOtlpValue = exports.snakeCase = exports.newSpanId = exports.ulidToTraceId = exports.MAX_BYTES = exports.PATTERNS = exports.applyMatches = exports.resolveOverlaps = exports.collectMatches = exports.truncateTo = exports.truncate = exports.redact = void 0;
|
|
867
1013
|
var redact_js_1 = require_redact();
|
|
868
1014
|
Object.defineProperty(exports, "redact", { enumerable: true, get: function() {
|
|
869
1015
|
return redact_js_1.redact;
|
|
@@ -871,6 +1017,9 @@ var require_dist = __commonJS({
|
|
|
871
1017
|
Object.defineProperty(exports, "truncate", { enumerable: true, get: function() {
|
|
872
1018
|
return redact_js_1.truncate;
|
|
873
1019
|
} });
|
|
1020
|
+
Object.defineProperty(exports, "truncateTo", { enumerable: true, get: function() {
|
|
1021
|
+
return redact_js_1.truncateTo;
|
|
1022
|
+
} });
|
|
874
1023
|
Object.defineProperty(exports, "collectMatches", { enumerable: true, get: function() {
|
|
875
1024
|
return redact_js_1.collectMatches;
|
|
876
1025
|
} });
|
|
@@ -914,6 +1063,12 @@ var require_dist = __commonJS({
|
|
|
914
1063
|
Object.defineProperty(exports, "mergeBatch", { enumerable: true, get: function() {
|
|
915
1064
|
return otlp_js_1.mergeBatch;
|
|
916
1065
|
} });
|
|
1066
|
+
Object.defineProperty(exports, "enforceSpanBudget", { enumerable: true, get: function() {
|
|
1067
|
+
return otlp_js_1.enforceSpanBudget;
|
|
1068
|
+
} });
|
|
1069
|
+
Object.defineProperty(exports, "MAX_SPAN_BYTES", { enumerable: true, get: function() {
|
|
1070
|
+
return otlp_js_1.MAX_SPAN_BYTES;
|
|
1071
|
+
} });
|
|
917
1072
|
var guard_js_1 = require_guard();
|
|
918
1073
|
Object.defineProperty(exports, "evaluateGuard", { enumerable: true, get: function() {
|
|
919
1074
|
return guard_js_1.evaluateGuard;
|
|
@@ -941,6 +1096,9 @@ var require_dist = __commonJS({
|
|
|
941
1096
|
Object.defineProperty(exports, "parseHeadersEnv", { enumerable: true, get: function() {
|
|
942
1097
|
return transport_js_1.parseHeadersEnv;
|
|
943
1098
|
} });
|
|
1099
|
+
Object.defineProperty(exports, "MAX_POST_BYTES", { enumerable: true, get: function() {
|
|
1100
|
+
return transport_js_1.MAX_POST_BYTES;
|
|
1101
|
+
} });
|
|
944
1102
|
var trace_js_1 = require_trace();
|
|
945
1103
|
Object.defineProperty(exports, "TraceManager", { enumerable: true, get: function() {
|
|
946
1104
|
return trace_js_1.TraceManager;
|
|
@@ -1033,7 +1191,7 @@ var import_core4 = __toESM(require_dist(), 1);
|
|
|
1033
1191
|
// src/core/guard.ts
|
|
1034
1192
|
var import_core5 = __toESM(require_dist(), 1);
|
|
1035
1193
|
var DEFAULT_TIMEOUT_MS = 50;
|
|
1036
|
-
var GUARD_UA = "pinta-opencode/0.
|
|
1194
|
+
var GUARD_UA = "pinta-opencode/0.6.0";
|
|
1037
1195
|
function evaluateGuard(input, endpoint, opts = {}) {
|
|
1038
1196
|
return (0, import_core5.evaluateGuard)(input, endpoint, {
|
|
1039
1197
|
timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
@@ -1046,7 +1204,18 @@ function evaluateGuard(input, endpoint, opts = {}) {
|
|
|
1046
1204
|
// src/core/otlp.ts
|
|
1047
1205
|
var import_core6 = __toESM(require_dist(), 1);
|
|
1048
1206
|
import os from "os";
|
|
1049
|
-
var
|
|
1207
|
+
var cachedProcessOwner;
|
|
1208
|
+
function processOwner() {
|
|
1209
|
+
if (cachedProcessOwner === void 0) {
|
|
1210
|
+
try {
|
|
1211
|
+
cachedProcessOwner = os.userInfo().username;
|
|
1212
|
+
} catch {
|
|
1213
|
+
cachedProcessOwner = process.env.USER ?? process.env.LOGNAME ?? (typeof process.getuid === "function" ? String(process.getuid()) : "unknown");
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
return cachedProcessOwner;
|
|
1217
|
+
}
|
|
1218
|
+
var SDK_VERSION = "0.6.0";
|
|
1050
1219
|
var SKIP_REDACT_KEYS = /* @__PURE__ */ new Set([
|
|
1051
1220
|
"opencode.kind",
|
|
1052
1221
|
"opencode.event_type",
|
|
@@ -1084,7 +1253,7 @@ function resourceAttrs(serviceVersion) {
|
|
|
1084
1253
|
{ key: "telemetry.sdk.language", value: { stringValue: "nodejs" } },
|
|
1085
1254
|
{ key: "telemetry.sdk.version", value: { stringValue: SDK_VERSION } },
|
|
1086
1255
|
{ key: "process.pid", value: { intValue: process.pid } },
|
|
1087
|
-
{ key: "process.owner", value: { stringValue:
|
|
1256
|
+
{ key: "process.owner", value: { stringValue: processOwner() } },
|
|
1088
1257
|
{ key: "host.name", value: { stringValue: os.hostname() } },
|
|
1089
1258
|
{ key: "host.arch", value: { stringValue: os.arch() } }
|
|
1090
1259
|
];
|
|
@@ -1176,6 +1345,8 @@ var PintaOpencode = async (_input, options) => {
|
|
|
1176
1345
|
{
|
|
1177
1346
|
spanId: input.sessionID,
|
|
1178
1347
|
toolName: input.tool,
|
|
1348
|
+
method: "tool.execute.before",
|
|
1349
|
+
cwd: process.cwd(),
|
|
1179
1350
|
toolInput: args,
|
|
1180
1351
|
rawTextFields: { toolInput: safeStringify(args) }
|
|
1181
1352
|
},
|
|
@@ -1228,7 +1399,7 @@ import path2 from "node:path";
|
|
|
1228
1399
|
|
|
1229
1400
|
// src/lifecycle/snapshot.ts
|
|
1230
1401
|
import { execFile } from "node:child_process";
|
|
1231
|
-
import { copyFile, mkdtemp, stat } from "node:fs/promises";
|
|
1402
|
+
import { copyFile, mkdtemp, rm, stat } from "node:fs/promises";
|
|
1232
1403
|
import { tmpdir } from "node:os";
|
|
1233
1404
|
import path from "node:path";
|
|
1234
1405
|
import { promisify } from "node:util";
|
|
@@ -1238,7 +1409,10 @@ var DEFAULT_MAX_RETRIES = 3;
|
|
|
1238
1409
|
var sqlite3Probe;
|
|
1239
1410
|
function detectSqlite3() {
|
|
1240
1411
|
if (sqlite3Probe === void 0) {
|
|
1241
|
-
sqlite3Probe = execFileAsync("sqlite3", ["-version"]).then(() => "sqlite3").catch(() => null)
|
|
1412
|
+
sqlite3Probe = execFileAsync("sqlite3", ["-version"]).then(() => "sqlite3").catch(() => null).then((result) => {
|
|
1413
|
+
if (result === null) sqlite3Probe = void 0;
|
|
1414
|
+
return result;
|
|
1415
|
+
});
|
|
1242
1416
|
}
|
|
1243
1417
|
return sqlite3Probe;
|
|
1244
1418
|
}
|
|
@@ -1252,22 +1426,28 @@ async function backupViaCli(sqlite3Path, dbPath, outPath) {
|
|
|
1252
1426
|
const backupCmd = `.backup '${outPath.replace(/'/g, "''")}'`;
|
|
1253
1427
|
await execFileAsync(sqlite3Path, ["-cmd", ".timeout 5000", dbPath, backupCmd]);
|
|
1254
1428
|
}
|
|
1255
|
-
async function quiesceCopy(file, outDir, stableMs, maxRetries) {
|
|
1429
|
+
async function quiesceCopy(file, outDir, stableMs, maxRetries, deadlineMs) {
|
|
1256
1430
|
const dbPath = file.absPath;
|
|
1257
1431
|
const outDbPath = path.join(outDir, path.basename(dbPath));
|
|
1432
|
+
const deadline = Date.now() + deadlineMs;
|
|
1258
1433
|
let lastErr;
|
|
1259
1434
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1260
1435
|
try {
|
|
1261
1436
|
let before = await stat(dbPath);
|
|
1262
|
-
|
|
1437
|
+
let stable = false;
|
|
1438
|
+
while (Date.now() < deadline) {
|
|
1263
1439
|
await sleep(stableMs);
|
|
1264
1440
|
const now = await stat(dbPath);
|
|
1265
|
-
if (now.mtimeMs === before.mtimeMs && now.size === before.size)
|
|
1441
|
+
if (now.mtimeMs === before.mtimeMs && now.size === before.size) {
|
|
1442
|
+
stable = true;
|
|
1443
|
+
break;
|
|
1444
|
+
}
|
|
1266
1445
|
before = now;
|
|
1267
1446
|
}
|
|
1268
1447
|
await copyFile(dbPath, outDbPath);
|
|
1269
1448
|
await copyIfPresent(`${dbPath}-wal`, `${outDbPath}-wal`);
|
|
1270
1449
|
await copyIfPresent(`${dbPath}-shm`, `${outDbPath}-shm`);
|
|
1450
|
+
if (!stable) return outDbPath;
|
|
1271
1451
|
const after = await stat(dbPath);
|
|
1272
1452
|
if (after.mtimeMs === before.mtimeMs && after.size === before.size) {
|
|
1273
1453
|
return outDbPath;
|
|
@@ -1275,6 +1455,7 @@ async function quiesceCopy(file, outDir, stableMs, maxRetries) {
|
|
|
1275
1455
|
} catch (err) {
|
|
1276
1456
|
lastErr = err;
|
|
1277
1457
|
}
|
|
1458
|
+
if (Date.now() >= deadline) break;
|
|
1278
1459
|
}
|
|
1279
1460
|
try {
|
|
1280
1461
|
await stat(outDbPath);
|
|
@@ -1293,17 +1474,24 @@ async function snapshot(file, opts = {}) {
|
|
|
1293
1474
|
const base = opts.tmpDir ?? tmpdir();
|
|
1294
1475
|
const stableMs = opts.stableMs ?? DEFAULT_STABLE_MS;
|
|
1295
1476
|
const maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
1477
|
+
const deadlineMs = opts.deadlineMs ?? Math.max(stableMs * maxRetries * 3, 15e3);
|
|
1296
1478
|
const sqlite3Path = opts.sqlite3Path === void 0 ? await detectSqlite3() : opts.sqlite3Path;
|
|
1297
1479
|
const outDir = await makeSnapshotDir(base);
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1480
|
+
try {
|
|
1481
|
+
if (sqlite3Path) {
|
|
1482
|
+
const outPath = path.join(outDir, `${path.basename(file.absPath)}.snapshot`);
|
|
1483
|
+
try {
|
|
1484
|
+
await backupViaCli(sqlite3Path, file.absPath, outPath);
|
|
1485
|
+
return outPath;
|
|
1486
|
+
} catch {
|
|
1487
|
+
}
|
|
1304
1488
|
}
|
|
1489
|
+
return await quiesceCopy(file, outDir, stableMs, maxRetries, deadlineMs);
|
|
1490
|
+
} catch (err) {
|
|
1491
|
+
await rm(outDir, { recursive: true, force: true }).catch(() => {
|
|
1492
|
+
});
|
|
1493
|
+
throw err;
|
|
1305
1494
|
}
|
|
1306
|
-
return quiesceCopy(file, outDir, stableMs, maxRetries);
|
|
1307
1495
|
}
|
|
1308
1496
|
|
|
1309
1497
|
// src/lifecycle/scanner.ts
|
package/dist/plugin.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { createRequire as __pintaCreateRequire } from 'module'; const require = __pintaCreateRequire(import.meta.url);
|
|
2
|
-
var
|
|
3
|
-
`;
|
|
4
|
-
`)}}readAll(){try{let e=
|
|
5
|
-
`))if(n.trim())try{
|
|
2
|
+
var et=Object.create;var ae=Object.defineProperty;var tt=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames;var nt=Object.getPrototypeOf,st=Object.prototype.hasOwnProperty;var h=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var _=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ot=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of rt(e))!st.call(t,s)&&s!==r&&ae(t,s,{get:()=>e[s],enumerable:!(n=tt(e,s))||n.enumerable});return t};var E=(t,e,r)=>(r=t!=null?et(nt(t)):{},ot(e||!t||!t.__esModule?ae(r,"default",{value:t,enumerable:!0}):r,t));var C=_(f=>{"use strict";Object.defineProperty(f,"__esModule",{value:!0});f.PATTERNS=f.MAX_BYTES=void 0;f.truncateTo=ue;f.truncate=it;f.collectMatches=ce;f.resolveOverlaps=le;f.applyMatches=de;f.redact=at;f.MAX_BYTES=102400;function ue(t,e){let r=Buffer.from(t,"utf-8");return r.length<=e?t:`${r.subarray(0,Math.max(0,e)).toString("utf-8")}\u2026[TRUNCATED:${r.length}]`}function it(t){return ue(t,f.MAX_BYTES)}f.PATTERNS=[{type:"aws_access_key",regex:/AKIA[0-9A-Z]{16}/g},{type:"aws_secret_key",regex:/(?:aws[_-]?secret(?:[_-]?(?:access)?[_-]?key)?)\s*[:=]\s*["']?([A-Za-z0-9/+=]{40})(?![A-Za-z0-9/+=])/gi,captureGroup:1},{type:"gcp_service_account",regex:/\{[\s\S]{0,200}?"type"\s*:\s*"service_account"[\s\S]*?\}/g},{type:"github_token",regex:/gh[pousr]_[A-Za-z0-9]{36,}/g},{type:"gitlab_token",regex:/glpat-[A-Za-z0-9_-]{20}/g},{type:"slack_token",regex:/xox[abrsp]-[0-9A-Za-z-]{10,}/g},{type:"openai_key",regex:/sk-(?:proj-)?[A-Za-z0-9_-]{40,}/g},{type:"anthropic_key",regex:/sk-ant-[A-Za-z0-9_-]{50,}/g},{type:"stripe_key",regex:/(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{20,}/g},{type:"jwt",regex:/eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g},{type:"private_key_block",regex:/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g},{type:"bearer_token",regex:/bearer\s+([A-Za-z0-9._~+/=-]{12,})/gi,captureGroup:1},{type:"basic_auth",regex:/basic\s+([A-Za-z0-9+/=]{12,})/gi,captureGroup:1},{type:"db_url_password",regex:/\b(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|redis):\/\/[^:\s/]+:([^@\s]+)@/gi,captureGroup:1},{type:"cli_password_flag",regex:/(?:--password|--pass|--pwd)[=\s]([^\s'"]+)/g,captureGroup:1},{type:"cli_password_short",regex:/\s-p([^\s'"]+)/g,captureGroup:1,requireContext:"bash"},{type:"env_var_secret",regex:/^(?:export\s+)?([A-Z][A-Z0-9_]*(?:KEY|SECRET|TOKEN|PASSWORD|PASSWD|PWD|API_KEY)[A-Z0-9_]*)\s*=\s*["']?([^\s"'\n]+)/gm,captureGroup:2}];function ce(t,e){let r=[];for(let n of f.PATTERNS){if(n.requireContext&&n.requireContext!==e.context)continue;let s=new RegExp(n.regex.source,n.regex.flags),i;for(;(i=s.exec(t))!==null;){let u=n.captureGroup??0,a=i[u];if(a===void 0){i.index===s.lastIndex&&s.lastIndex++;continue}let c=i.index,d=i.index+i[0].length,P=c+i[0].indexOf(a),Qe=P+a.length;r.push({start:c,end:d,replaceStart:P,replaceEnd:Qe,type:n.type}),i.index===s.lastIndex&&s.lastIndex++}}return r}function le(t){let e=[...t].sort((s,i)=>s.start!==i.start?s.start-i.start:i.end-i.start-(s.end-s.start)),r=[],n=-1;for(let s of e)s.start<n||(r.push(s),n=s.end);return r}function de(t,e){let r=[...e].sort((s,i)=>i.replaceStart-s.replaceStart),n=t;for(let s of r)n=n.slice(0,s.replaceStart)+`[REDACTED:${s.type}]`+n.slice(s.replaceEnd);return n}function at(t,e={}){if(t.length===0)return t;let r=ce(t,e);if(r.length===0)return t;let n=le(r);return de(t,n)}});var V=_(p=>{"use strict";var ut=p&&p.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(p,"__esModule",{value:!0});p.MAX_SPAN_BYTES=void 0;p.ulidToTraceId=he;p.newSpanId=ye;p.snakeCase=dt;p.toOtlpValue=_e;p.attrsFromRecord=pt;p.guardAttrs=me;p.clientAttrs=Te;p.enforceSpanBudget=Oe;p.buildPayload=ft;p.mergeBatch=gt;var ct=ut(h("crypto")),F=C(),lt="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function he(t){if(t.length!==26)throw new Error(`ulidToTraceId: expected 26 chars, got ${t.length}`);let e=0n;for(let n of t){let s=lt.indexOf(n);if(s<0)throw new Error(`ulidToTraceId: invalid Crockford char "${n}"`);e=e<<5n|BigInt(s)}let r=(1n<<128n)-1n;return e&=r,e.toString(16).padStart(32,"0")}function ye(){return ct.default.randomBytes(8).toString("hex")}function dt(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()}var pe=new Set;function x(t,e,r){let n=(0,F.truncate)(e);if((r.skipRedactKeys??pe).has(t))return n;let s=(r.bashContextKeys??pe).has(t)?"bash":void 0;return(0,F.redact)(n,{context:s})}function _e(t,e,r={}){if(e==null)return null;switch(typeof e){case"string":return{stringValue:x(t,e,r)};case"boolean":return{boolValue:e};case"number":return Number.isInteger(e)?{intValue:e}:{doubleValue:e};case"object":try{return{stringValue:x(t,JSON.stringify(e),r)}}catch{return{stringValue:x(t,String(e),r)}}default:return{stringValue:x(t,String(e),r)}}}function pt(t,e,r={}){let n=[];for(let[s,i]of Object.entries(t)){let u=`${e}.${s}`,a=_e(u,i,r);a!==null&&n.push({key:u,value:a})}return n}function me(t){let e=[{key:"pinta.guard.decision",value:{stringValue:t.decision.toLowerCase()}},{key:"pinta.guard.duration_ms",value:{intValue:t.durationMs}}];return t.reason&&e.push({key:"pinta.guard.matched_rule",value:{stringValue:t.reason}}),t.failOpenReason&&e.push({key:"pinta.guard.fail_open_reason",value:{stringValue:t.failOpenReason}}),e}function Te(t){return[{key:"pinta.client.rtt_ms",value:Number.isInteger(t.rttMs)?{intValue:t.rttMs}:{doubleValue:t.rttMs}},{key:"pinta.client.op",value:{stringValue:t.op}}]}p.MAX_SPAN_BYTES=800*1024;function fe(t){let e=JSON.stringify(t);return e===void 0?0:Buffer.byteLength(e,"utf-8")}var ge=1024;function Oe(t,e=p.MAX_SPAN_BYTES){let r=fe(t);for(let n=0;n<100&&r>e;n++){let s=null,i=0;for(let c of t.attributes){if(!("stringValue"in c.value))continue;let d=Buffer.byteLength(c.value.stringValue,"utf-8");d>i&&(i=d,s=c.value)}if(s===null||i<=ge)break;let u=r-e,a=Math.max(ge,i-u-64);s.stringValue=(0,F.truncateTo)(s.stringValue,a),r=fe(t)}return t}function ft(t){let e=t.now??Date.now(),r=(BigInt(e)*1000000n).toString(),n=[...t.attributes];t.guard&&n.push(...me(t.guard));let s=t.clientTiming??(t.guard?.clientRttMs!==void 0?{op:"guard",rttMs:t.guard.clientRttMs}:null);s&&n.push(...Te(s));let i={traceId:he(t.traceId),spanId:ye(),name:t.spanName,kind:t.spanKind??1,startTimeUnixNano:r,endTimeUnixNano:r,attributes:n};return Oe(i),{resourceSpans:[{resource:{attributes:t.resource},scopeSpans:[{scope:t.scope,spans:[i]}]}]}}function gt(t){let e=[];for(let r of t)e.push(...r.resourceSpans);return{resourceSpans:e}}});var Pe=_(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});G.evaluateGuard=mt;var ht=1e4,yt="pinta-core";function L(t,e){return{decision:"ALLOW",reason:null,userMessage:null,durationMs:t,clientRttMs:t,failOpenReason:e}}var _t=new Set(["ALLOW","DENY","REVIEW"]);async function mt(t,e,r={}){if(!e||r.disabled)return null;let n=r.timeoutMs??ht,s=Date.now(),i=new AbortController,u=setTimeout(()=>i.abort(),n);try{let a=await fetch(e,{method:"POST",headers:{"content-type":"application/json","user-agent":r.userAgent??yt,"x-pinta-relay-token":r.token??""},body:JSON.stringify({input:t}),signal:i.signal});if(a.status!==200)return L(Date.now()-s,"error");let c=await a.json(),d=c?.durationMs===void 0||typeof c.durationMs=="number"&&Number.isFinite(c.durationMs);if(!c||!_t.has(c.decision)||!d)return L(Date.now()-s,"error");let P=Date.now()-s;return{decision:c.decision,reason:c.reason??null,userMessage:c.userMessage??null,durationMs:c.durationMs??P,clientRttMs:P}}catch(a){let c=a.name,d=c==="AbortError"||c==="TimeoutError"?"timeout":"error";return L(Date.now()-s,d)}finally{clearTimeout(u)}}});var I=_(w=>{"use strict";var Tt=w&&w.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(w,"__esModule",{value:!0});w.atomicWriteFileSync=Ot;var ve=Tt(h("fs"));function Ot(t,e){let r=`${t}.${process.pid}.tmp`;ve.default.writeFileSync(r,e),ve.default.renameSync(r,t)}});var z=_(m=>{"use strict";var Se=m&&m.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(m,"__esModule",{value:!0});m.MemoryRetryQueue=m.DiskRetryQueue=void 0;var g=Se(h("fs")),D=Se(h("path")),Pt=I(),j=1e3,vt=50,St=5,X=class{filePath;lockPath;logPrefix;constructor(e,r){this.filePath=D.default.join(e,"failed-spans.jsonl"),this.lockPath=this.filePath+".lock",this.logPrefix=r}enqueue(e){try{g.default.mkdirSync(D.default.dirname(this.filePath),{recursive:!0});let r=JSON.stringify({savedAt:new Date().toISOString(),payload:e})+`
|
|
3
|
+
`;g.default.appendFileSync(this.filePath,r),this.trim()}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue enqueue failed: ${r}
|
|
4
|
+
`)}}readAll(){try{let e=g.default.readFileSync(this.filePath,"utf-8"),r=[];for(let n of e.split(`
|
|
5
|
+
`))if(n.trim())try{let s=JSON.parse(n);Array.isArray(s?.payload?.resourceSpans)&&r.push(s)}catch{}return r}catch{return[]}}rewrite(e){try{if(e.length===0){g.default.existsSync(this.filePath)&&g.default.unlinkSync(this.filePath);return}g.default.mkdirSync(D.default.dirname(this.filePath),{recursive:!0}),(0,Pt.atomicWriteFileSync)(this.filePath,e.map(r=>JSON.stringify(r)).join(`
|
|
6
6
|
`)+`
|
|
7
7
|
`)}catch(r){process.stderr.write(`[${this.logPrefix}] retry-queue rewrite failed: ${r}
|
|
8
|
-
`)}}tryAcquireLock(){let e=Date.now();
|
|
9
|
-
`),!1
|
|
10
|
-
`)
|
|
8
|
+
`)}}tryAcquireLock(){let e=Date.now();try{g.default.mkdirSync(D.default.dirname(this.lockPath),{recursive:!0})}catch(r){return process.stderr.write(`[${this.logPrefix}] retry-queue lock mkdir failed: ${r}
|
|
9
|
+
`),!1}for(;Date.now()-e<vt;)try{let r=g.default.openSync(this.lockPath,"wx");return g.default.writeSync(r,String(process.pid)),g.default.closeSync(r),!0}catch(r){if(r?.code!=="EEXIST")return process.stderr.write(`[${this.logPrefix}] retry-queue lock open failed: ${r}
|
|
10
|
+
`),!1;try{let i=g.default.statSync(this.lockPath);if(Date.now()-i.mtimeMs>3e4){g.default.unlinkSync(this.lockPath);continue}}catch{}let n=St,s=Date.now()+n;for(;Date.now()<s;);}return!1}release(){try{g.default.unlinkSync(this.lockPath)}catch{}}trim(){let e=this.readAll();if(e.length<=j)return;let r=e.length-j;process.stderr.write(`[${this.logPrefix}] retry-queue full, dropping ${r} oldest entries
|
|
11
|
+
`),this.rewrite(e.slice(r))}};m.DiskRetryQueue=X;var Y=class{entries=[];enqueue(e){this.entries.push(e),this.entries.length>j&&this.entries.splice(0,this.entries.length-j)}drain(){let e=this.entries;return this.entries=[],e}get size(){return this.entries.length}};m.MemoryRetryQueue=Y});var Me=_(l=>{"use strict";Object.defineProperty(l,"__esModule",{value:!0});l.MemoryTransport=l.DiskTransport=l.MAX_POST_BYTES=void 0;l.parseHeadersEnv=ke;l.envOptionsResolver=we;l.postOtlp=M;var be=z(),Ee=V(),bt=5e3;l.MAX_POST_BYTES=900*1024;function N(t){let e=JSON.stringify(t);return e===void 0?0:Buffer.byteLength(e,"utf-8")}function Ae(t,e,r){let n=[],s=[],i=[],u=0;for(let a of t){let c=e(a);if(c>r){s.push(a);continue}i.length>0&&u+c>r&&(n.push(i),i=[],u=0),i.push(a),u+=c}return i.length>0&&n.push(i),{chunks:n,oversize:s}}function ke(t){if(!t)return{};if(typeof t=="object")return{...t};let e={};for(let r of t.split(",")){let[n,...s]=r.split("=");n&&s.length>0&&(e[n.trim()]=s.join("=").trim())}return e}function we(){let t=process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,e=process.env.OTEL_EXPORTER_OTLP_ENDPOINT,r;return t?r=t.replace(/\/+$/,""):e&&(r=e.replace(/\/+$/,"")+"/v1/traces"),r?{endpoint:r,headers:ke(process.env.OTEL_EXPORTER_OTLP_HEADERS)}:null}async function M(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),bt);try{let i=await fetch(e.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...e.headers},body:JSON.stringify(t),signal:n.signal});if(!i.ok){let u="";try{u=(await i.text()).slice(0,200)}catch{}let a=i.status===401||i.status===403?" \u2014 check OTEL_EXPORTER_OTLP_HEADERS (relay token)":i.status===404?" \u2014 check OTEL_EXPORTER_OTLP_TRACES_ENDPOINT path":i.status>=500?" \u2014 collector may be down":"";return process.stderr.write(`[${r}] OTLP POST ${i.status} ${e.endpoint}${a}${u?` body=${u}`:""}
|
|
11
12
|
`),!1}return!0}catch(i){return process.stderr.write(`[${r}] OTLP POST failed: ${i.message??String(i)}
|
|
12
|
-
`),!1}finally{clearTimeout(s)}}var
|
|
13
|
-
`)
|
|
14
|
-
`)}
|
|
13
|
+
`),!1}finally{clearTimeout(s)}}var U=class{queue;logPrefix;resolveOptions;constructor(e){this.queue=new be.DiskRetryQueue(e.pluginData,e.logPrefix),this.logPrefix=e.logPrefix,this.resolveOptions=e.resolveOptions??we}async send(e){let r=this.resolveOptions();if(!r||this.dropIfOversized(e))return;await M(e,r,this.logPrefix)||this.queue.enqueue(e)}async flush(){let e=this.resolveOptions();if(e&&this.queue.tryAcquireLock())try{let r=this.queue.readAll();if(r.length===0)return;let{chunks:n,oversize:s}=Ae(r,a=>N(a.payload),l.MAX_POST_BYTES);s.length>0&&process.stderr.write(`[${this.logPrefix}] dropping ${s.length} oversized retry ${s.length===1?"entry":"entries"} (each > ${l.MAX_POST_BYTES} bytes \u2014 the backend caps the request body, so they can never be delivered)
|
|
14
|
+
`);let i=[].concat(...n),u=0;for(let a of n){if(!await M((0,Ee.mergeBatch)(a.map(d=>d.payload)),e,this.logPrefix))break;u+=a.length}this.queue.rewrite(i.slice(u))}catch(r){process.stderr.write(`[${this.logPrefix}] flush failed: ${r?.message??String(r)}
|
|
15
|
+
`)}finally{this.queue.release()}}dropIfOversized(e){let r=N(e);return r<=l.MAX_POST_BYTES?!1:(process.stderr.write(`[${this.logPrefix}] dropping oversized span payload (${r} > ${l.MAX_POST_BYTES} bytes) \u2014 undeliverable, not queued
|
|
16
|
+
`),!0)}};l.DiskTransport=U;var Z=class{queue=new be.MemoryRetryQueue;logPrefix;resolveOptions;constructor(e){this.logPrefix=e.logPrefix,this.resolveOptions=e.resolveOptions}async send(e){let r=this.resolveOptions();if(!r)return;if(N(e)>l.MAX_POST_BYTES){process.stderr.write(`[${this.logPrefix}] dropping oversized span payload (> ${l.MAX_POST_BYTES} bytes) \u2014 undeliverable, not buffered
|
|
17
|
+
`);return}await M(e,r,this.logPrefix)||this.queue.enqueue(e)}async flush(){let e=this.resolveOptions();if(!e)return;let r=this.queue.drain();if(r.length===0)return;let{chunks:n,oversize:s}=Ae(r,N,l.MAX_POST_BYTES);s.length>0&&process.stderr.write(`[${this.logPrefix}] dropping ${s.length} oversized buffered ${s.length===1?"payload":"payloads"} (each > ${l.MAX_POST_BYTES} bytes \u2014 undeliverable)
|
|
18
|
+
`);let i=[].concat(...n),u=0;for(let a of n){if(!await M((0,Ee.mergeBatch)(a),e,this.logPrefix))break;u+=a.length}for(let a of i.slice(u))this.queue.enqueue(a)}};l.MemoryTransport=Z});var H=_(v=>{"use strict";var J=v&&v.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(v,"__esModule",{value:!0});v.TraceManager=void 0;v.generateUlid=xe;var Re=J(h("fs")),Et=J(h("path")),At=J(h("crypto")),kt=I(),K="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function xe(){let t=Date.now(),e="",r=t;for(let i=0;i<10;i++)e=K[r&31]+e,r=Math.floor(r/32);let n=At.default.randomBytes(10),s="";for(let i=0;i<10;i++)s+=K[n[i]&31];for(;s.length<16;)s+=K[0];return e+s}var W=class{tracePath;constructor(e){this.tracePath=e}newTrace(){let e=xe();return this.save(e),e}currentTrace(){try{let e=Re.default.readFileSync(this.tracePath,"utf-8"),{traceId:r}=JSON.parse(e);if(r)return r}catch{}return this.newTrace()}save(e){try{Re.default.mkdirSync(Et.default.dirname(this.tracePath),{recursive:!0}),(0,kt.atomicWriteFileSync)(this.tracePath,JSON.stringify({traceId:e}))}catch(r){process.stderr.write(`[pinta-core] trace persistence failed: ${r}
|
|
19
|
+
`)}}};v.TraceManager=W});var Be=_(T=>{"use strict";var De=T&&T.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(T,"__esModule",{value:!0});T.MemorySessionTraceManager=T.DiskSessionTraceManager=void 0;var Ie=De(h("fs")),wt=De(h("path")),je=H(),Mt=I(),Ne=200,Q=class{tracePath;maxSessions;constructor(e,r={}){this.tracePath=e,this.maxSessions=r.maxSessions??Ne}read(){try{let e=JSON.parse(Ie.default.readFileSync(this.tracePath,"utf-8"));if(e&&typeof e=="object"&&!("traceId"in e))return e}catch{}return{}}write(e){try{Ie.default.mkdirSync(wt.default.dirname(this.tracePath),{recursive:!0});let r=Object.entries(e),n=r.length>this.maxSessions?Object.fromEntries(r.slice(-this.maxSessions)):e;(0,Mt.atomicWriteFileSync)(this.tracePath,JSON.stringify(n))}catch{}}newTrace(e){let r=e||"default",n=(0,je.generateUlid)(),s=this.read();return s[r]=n,this.write(s),n}currentTrace(e){let r=e||"default",n=this.read()[r];return n||this.newTrace(r)}};T.DiskSessionTraceManager=Q;var ee=class{map=new Map;maxSessions;constructor(e={}){this.maxSessions=e.maxSessions??Ne}newTrace(e){let r=e||"default",n=(0,je.generateUlid)();if(this.map.set(r,n),this.map.size>this.maxSessions){let s=this.map.keys().next().value;s!==void 0&&this.map.delete(s)}return n}currentTrace(e){let r=e||"default";return this.map.get(r)??this.newTrace(r)}};T.MemorySessionTraceManager=ee});var Ce=_(S=>{"use strict";var te=S&&S.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(S,"__esModule",{value:!0});S.envFilePath=It;S.parseEnvFile=$e;S.loadEnvFile=Dt;var Rt=te(h("node:fs")),xt=te(h("node:os")),qe=te(h("node:path"));function It(t,e,r){let n=r?process.env[r]:void 0,s=n&&n.length>0?n:qe.default.join(xt.default.homedir(),t);return qe.default.join(s,e)}function $e(t){let e={};for(let r of t.split(`
|
|
20
|
+
`)){let n=r.trim();if(!n||n.startsWith("#"))continue;let s=n.indexOf("=");if(s<0)continue;let i=n.slice(0,s).trim(),u=n.slice(s+1).trim();(u.startsWith('"')&&u.endsWith('"')||u.startsWith("'")&&u.endsWith("'"))&&(u=u.slice(1,-1)),i&&(e[i]=u)}return e}function Dt(t){let e;try{e=Rt.default.readFileSync(t,"utf-8")}catch{return}let r=$e(e);for(let[n,s]of Object.entries(r))process.env[n]===void 0&&(process.env[n]=s)}});var b=_(o=>{"use strict";Object.defineProperty(o,"__esModule",{value:!0});o.loadEnvFile=o.parseEnvFile=o.envFilePath=o.MemorySessionTraceManager=o.DiskSessionTraceManager=o.generateUlid=o.TraceManager=o.MAX_POST_BYTES=o.parseHeadersEnv=o.envOptionsResolver=o.postOtlp=o.MemoryTransport=o.DiskTransport=o.MemoryRetryQueue=o.DiskRetryQueue=o.evaluateGuard=o.MAX_SPAN_BYTES=o.enforceSpanBudget=o.mergeBatch=o.buildPayload=o.clientAttrs=o.guardAttrs=o.attrsFromRecord=o.toOtlpValue=o.snakeCase=o.newSpanId=o.ulidToTraceId=o.MAX_BYTES=o.PATTERNS=o.applyMatches=o.resolveOverlaps=o.collectMatches=o.truncateTo=o.truncate=o.redact=void 0;var O=C();Object.defineProperty(o,"redact",{enumerable:!0,get:function(){return O.redact}});Object.defineProperty(o,"truncate",{enumerable:!0,get:function(){return O.truncate}});Object.defineProperty(o,"truncateTo",{enumerable:!0,get:function(){return O.truncateTo}});Object.defineProperty(o,"collectMatches",{enumerable:!0,get:function(){return O.collectMatches}});Object.defineProperty(o,"resolveOverlaps",{enumerable:!0,get:function(){return O.resolveOverlaps}});Object.defineProperty(o,"applyMatches",{enumerable:!0,get:function(){return O.applyMatches}});Object.defineProperty(o,"PATTERNS",{enumerable:!0,get:function(){return O.PATTERNS}});Object.defineProperty(o,"MAX_BYTES",{enumerable:!0,get:function(){return O.MAX_BYTES}});var y=V();Object.defineProperty(o,"ulidToTraceId",{enumerable:!0,get:function(){return y.ulidToTraceId}});Object.defineProperty(o,"newSpanId",{enumerable:!0,get:function(){return y.newSpanId}});Object.defineProperty(o,"snakeCase",{enumerable:!0,get:function(){return y.snakeCase}});Object.defineProperty(o,"toOtlpValue",{enumerable:!0,get:function(){return y.toOtlpValue}});Object.defineProperty(o,"attrsFromRecord",{enumerable:!0,get:function(){return y.attrsFromRecord}});Object.defineProperty(o,"guardAttrs",{enumerable:!0,get:function(){return y.guardAttrs}});Object.defineProperty(o,"clientAttrs",{enumerable:!0,get:function(){return y.clientAttrs}});Object.defineProperty(o,"buildPayload",{enumerable:!0,get:function(){return y.buildPayload}});Object.defineProperty(o,"mergeBatch",{enumerable:!0,get:function(){return y.mergeBatch}});Object.defineProperty(o,"enforceSpanBudget",{enumerable:!0,get:function(){return y.enforceSpanBudget}});Object.defineProperty(o,"MAX_SPAN_BYTES",{enumerable:!0,get:function(){return y.MAX_SPAN_BYTES}});var jt=Pe();Object.defineProperty(o,"evaluateGuard",{enumerable:!0,get:function(){return jt.evaluateGuard}});var Fe=z();Object.defineProperty(o,"DiskRetryQueue",{enumerable:!0,get:function(){return Fe.DiskRetryQueue}});Object.defineProperty(o,"MemoryRetryQueue",{enumerable:!0,get:function(){return Fe.MemoryRetryQueue}});var A=Me();Object.defineProperty(o,"DiskTransport",{enumerable:!0,get:function(){return A.DiskTransport}});Object.defineProperty(o,"MemoryTransport",{enumerable:!0,get:function(){return A.MemoryTransport}});Object.defineProperty(o,"postOtlp",{enumerable:!0,get:function(){return A.postOtlp}});Object.defineProperty(o,"envOptionsResolver",{enumerable:!0,get:function(){return A.envOptionsResolver}});Object.defineProperty(o,"parseHeadersEnv",{enumerable:!0,get:function(){return A.parseHeadersEnv}});Object.defineProperty(o,"MAX_POST_BYTES",{enumerable:!0,get:function(){return A.MAX_POST_BYTES}});var Ve=H();Object.defineProperty(o,"TraceManager",{enumerable:!0,get:function(){return Ve.TraceManager}});Object.defineProperty(o,"generateUlid",{enumerable:!0,get:function(){return Ve.generateUlid}});var Le=Be();Object.defineProperty(o,"DiskSessionTraceManager",{enumerable:!0,get:function(){return Le.DiskSessionTraceManager}});Object.defineProperty(o,"MemorySessionTraceManager",{enumerable:!0,get:function(){return Le.MemorySessionTraceManager}});var re=Ce();Object.defineProperty(o,"envFilePath",{enumerable:!0,get:function(){return re.envFilePath}});Object.defineProperty(o,"parseEnvFile",{enumerable:!0,get:function(){return re.parseEnvFile}});Object.defineProperty(o,"loadEnvFile",{enumerable:!0,get:function(){return re.loadEnvFile}})});var Xe=E(b(),1);var R=E(b(),1);function Nt(){return(0,R.envFilePath)(".config/opencode","pinta-opencode.env","OPENCODE_CONFIG_DIR")}function Ge(t=Nt()){(0,R.loadEnvFile)(t)}function ne(...t){return t.find(e=>e)||void 0}function Bt(t){let e=ne(t.endpoint,process.env.PINTA_OPENCODE_ENDPOINT,process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);if(e)return e.replace(/\/+$/,"");let r=process.env.OTEL_EXPORTER_OTLP_ENDPOINT;if(r)return r.replace(/\/+$/,"")+"/v1/traces"}function Ye(t={}){Ge();let e=ne(t.token,process.env.PINTA_OPENCODE_TOKEN),r=(0,Xe.parseHeadersEnv)(t.headers??process.env.PINTA_OPENCODE_HEADERS??process.env.OTEL_EXPORTER_OTLP_HEADERS);e&&!Object.keys(r).some(s=>s.toLowerCase()==="x-pinta-relay-token")&&(r["x-pinta-relay-token"]=e);let n=t.guardTimeoutMs??(Number(process.env.PINTA_OPENCODE_GUARD_TIMEOUT_MS)||50);return{endpoint:Bt(t),headers:r,guardEndpoint:ne(t.guard,process.env.PINTA_OPENCODE_GUARD),relayToken:e,guardTimeoutMs:n,guardDisabled:process.env.PINTA_OPENCODE_GUARD_DISABLED==="1",serviceVersion:process.env.OPENCODE_VERSION||"unknown"}}var ze=E(b(),1),B=class extends ze.MemoryTransport{constructor(e){super({logPrefix:"pinta-opencode",resolveOptions:()=>e.endpoint?{endpoint:e.endpoint,headers:e.headers}:null})}};var se=E(b(),1);var Ue=E(b(),1),qt=50,$t="pinta-opencode/0.6.0";function Ze(t,e,r={}){return(0,Ue.evaluateGuard)(t,e,{timeoutMs:r.timeoutMs??qt,token:r.token,disabled:r.disabled,userAgent:$t})}var k=E(b(),1);import oe from"os";var q;function Ct(){if(q===void 0)try{q=oe.userInfo().username}catch{q=process.env.USER??process.env.LOGNAME??(typeof process.getuid=="function"?String(process.getuid()):"unknown")}return q}var Ke="0.6.0",Ft=new Set(["opencode.kind","opencode.event_type","opencode.tool","opencode.session_id","opencode.sessionID","opencode.call_id","opencode.callID","opencode.agent","opencode.model","opencode.exit","opencode.truncated","opencode.title"]),Vt=new Set(["opencode.args","opencode.input","opencode.output","opencode.tool_input"]),Lt={skipRedactKeys:Ft,bashContextKeys:Vt};function Gt(t){let e=[{key:"ingest.type",value:{stringValue:"opencode"}}];return e.push(...(0,k.attrsFromRecord)(t,"opencode",Lt)),e}function Xt(t){return[{key:"service.name",value:{stringValue:"opencode"}},{key:"service.version",value:{stringValue:t}},{key:"telemetry.sdk.name",value:{stringValue:"pinta-opencode"}},{key:"telemetry.sdk.language",value:{stringValue:"nodejs"}},{key:"telemetry.sdk.version",value:{stringValue:Ke}},{key:"process.pid",value:{intValue:process.pid}},{key:"process.owner",value:{stringValue:Ct()}},{key:"host.name",value:{stringValue:oe.hostname()}},{key:"host.arch",value:{stringValue:oe.arch()}}]}function We(t){return(0,k.buildPayload)({traceId:t.traceId,spanName:t.name,attributes:Gt(t.fields),resource:Xt(t.serviceVersion),scope:{name:"pinta-opencode",version:Ke},now:t.now,guard:t.guard})}var $=class{constructor(e,r,n){this.transport=e;this.trace=r;this.config=n}async emit(e,r,n,s){let i=this.trace.currentTrace(r),u=We({name:e,traceId:i,fields:n,guard:s,serviceVersion:this.config.serviceVersion});await this.transport.send(u)}async lifecycle(e){let r=e.properties??{},n=typeof r.sessionID=="string"?r.sessionID:void 0;await this.emit(`opencode.event.${e.type??"unknown"}`,n,{kind:"event",event_type:e.type,session_id:n,...r}),e.type==="session.idle"&&await this.transport.flush()}async toolBefore(e,r,n){await this.emit("opencode.tool.before",e.sessionID,{...Je("tool.before",e),args:r},n)}async toolAfter(e,r){let n=r.metadata??{};await this.emit("opencode.tool.after",e.sessionID,{...Je("tool.after",e),title:r.title,output:r.output,exit:n.exit,truncated:n.truncated})}};function Je(t,e){return{kind:t,tool:e.tool,session_id:e.sessionID,call_id:e.callID}}function He(t,e){process.stderr.write(`[pinta-opencode] ${t}: ${e?.message??String(e)}
|
|
21
|
+
`)}function ie(t,e){return async(...r)=>{try{await e(...r)}catch(n){He(t,n)}}}var Yt=async(t,e)=>{let r=Ye(e??{}),n=new B({endpoint:r.endpoint,headers:r.headers}),s=new se.MemorySessionTraceManager,i=new $(n,s,r);async function u(a,c){let d=null;try{d=await Ze({spanId:a.sessionID,toolName:a.tool,method:"tool.execute.before",cwd:process.cwd(),toolInput:c,rawTextFields:{toolInput:zt(c)}},r.guardEndpoint,{timeoutMs:r.guardTimeoutMs,token:r.relayToken,disabled:r.guardDisabled}),await i.toolBefore(a,c,d)}catch(P){He("tool.execute.before",P)}return d}return{"chat.message":ie("chat.message",async a=>{s.newTrace(a?.sessionID)}),event:ie("event",async a=>{a?.event&&await i.lifecycle(a.event)}),"tool.execute.before":async(a,c)=>{let d=await u(a,c?.args);if(d?.decision==="DENY")throw new Error(d.userMessage??d.reason??"guard_deny")},"tool.execute.after":ie("tool.execute.after",(a,c)=>i.toolAfter(a,c))}};function zt(t){try{return typeof t=="string"?t:JSON.stringify(t)??""}catch{return String(t)}}var Tr=Yt;export{Yt as PintaOpencode,Tr as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pinta-ai/pinta-opencode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "OTLP forwarder + guard for opencode (in-process plugin)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/plugin.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"prepublishOnly": "npm run build"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@pinta-ai/core": "^0.
|
|
39
|
+
"@pinta-ai/core": "^0.6.0",
|
|
40
40
|
"@types/node": "^22.0.0",
|
|
41
41
|
"esbuild": "0.24.2",
|
|
42
42
|
"typescript": "^5.7.0",
|