@warlock.js/ai-panoptic 5.30.0 → 5.32.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 +25 -3
- package/README.md +2 -2
- package/cjs/index.cjs +38 -84
- package/cjs/index.cjs.map +1 -1
- package/esm/collector/collector.d.mts +3 -5
- package/esm/collector/collector.d.mts.map +1 -1
- package/esm/collector/content-capture.type.d.mts +4 -5
- package/esm/collector/content-capture.type.d.mts.map +1 -1
- package/esm/collector/extract-span-attributes.d.mts +1 -3
- package/esm/collector/extract-span-attributes.d.mts.map +1 -1
- package/esm/collector/extract-span-attributes.mjs +2 -4
- package/esm/collector/extract-span-attributes.mjs.map +1 -1
- package/esm/collector/index.d.mts +2 -1
- package/esm/collector/index.mjs +1 -1
- package/esm/collector/normalize-error.d.mts +1 -3
- package/esm/collector/normalize-error.d.mts.map +1 -1
- package/esm/collector/report-to-span.d.mts +1 -3
- package/esm/collector/report-to-span.d.mts.map +1 -1
- package/esm/collector/report-to-span.mjs.map +1 -1
- package/esm/collector/report-to-trace.d.mts +1 -3
- package/esm/collector/report-to-trace.d.mts.map +1 -1
- package/esm/config/apply-panoptic-config.d.mts +2 -3
- package/esm/config/apply-panoptic-config.d.mts.map +1 -1
- package/esm/config/apply-panoptic-config.mjs.map +1 -1
- package/esm/config/index.d.mts +2 -1
- package/esm/config/index.mjs +1 -1
- package/esm/config/panoptic-config.type.d.mts +2 -4
- package/esm/config/panoptic-config.type.d.mts.map +1 -1
- package/esm/contracts/collector.contract.d.mts +1 -3
- package/esm/contracts/collector.contract.d.mts.map +1 -1
- package/esm/contracts/exporter.contract.d.mts +1 -3
- package/esm/contracts/exporter.contract.d.mts.map +1 -1
- package/esm/contracts/index.d.mts +2 -1
- package/esm/contracts/trace.type.d.mts +35 -20
- package/esm/contracts/trace.type.d.mts.map +1 -1
- package/esm/dashboard/dashboard.d.mts +1 -3
- package/esm/dashboard/dashboard.d.mts.map +1 -1
- package/esm/dashboard/dashboard.mjs +3 -2
- package/esm/dashboard/dashboard.mjs.map +1 -1
- package/esm/dashboard/dashboard.type.d.mts +9 -7
- package/esm/dashboard/dashboard.type.d.mts.map +1 -1
- package/esm/dashboard/index.d.mts +4 -1
- package/esm/dashboard/index.mjs +1 -1
- package/esm/dashboard/parse-query.d.mts +1 -1
- package/esm/dashboard/parse-query.mjs +1 -0
- package/esm/dashboard/parse-query.mjs.map +1 -1
- package/esm/dashboard/serve.d.mts +2 -1
- package/esm/dashboard/serve.mjs +1 -1
- package/esm/dashboard/serve.mjs.map +1 -1
- package/esm/dashboard/trace-filter.d.mts +44 -32
- package/esm/dashboard/trace-filter.d.mts.map +1 -1
- package/esm/dashboard/trace-filter.mjs +1 -1
- package/esm/dashboard/trace-filter.mjs.map +1 -1
- package/esm/dashboard/ui.html.mjs +5 -4
- package/esm/dashboard/ui.html.mjs.map +1 -1
- package/esm/evaluate/evaluate-system-prompt.d.mts +1 -3
- package/esm/evaluate/evaluate-system-prompt.d.mts.map +1 -1
- package/esm/evaluate/evaluate-system-prompt.mjs +3 -1
- package/esm/evaluate/evaluate-system-prompt.mjs.map +1 -1
- package/esm/evaluate/evaluate.type.d.mts +2 -4
- package/esm/evaluate/evaluate.type.d.mts.map +1 -1
- package/esm/evaluate/extract-last-system-prompt.d.mts +1 -3
- package/esm/evaluate/extract-last-system-prompt.d.mts.map +1 -1
- package/esm/evaluate/find-span-by-id.d.mts +1 -3
- package/esm/evaluate/find-span-by-id.d.mts.map +1 -1
- package/esm/evaluate/index.d.mts +2 -1
- package/esm/evaluate/index.mjs +1 -1
- package/esm/exporters/console/console-exporter.d.mts +2 -3
- package/esm/exporters/console/console-exporter.d.mts.map +1 -1
- package/esm/exporters/console/console-exporter.mjs +4 -3
- package/esm/exporters/console/console-exporter.mjs.map +1 -1
- package/esm/exporters/console/console-exporter.type.d.mts +2 -3
- package/esm/exporters/console/console-exporter.type.d.mts.map +1 -1
- package/esm/exporters/console/format-span-io.d.mts +2 -2
- package/esm/exporters/console/format-span-io.d.mts.map +1 -1
- package/esm/exporters/console/format-span-io.mjs.map +1 -1
- package/esm/exporters/console/format-span-line.d.mts +2 -2
- package/esm/exporters/console/format-span-line.d.mts.map +1 -1
- package/esm/exporters/console/format-span-line.mjs +2 -0
- package/esm/exporters/console/format-span-line.mjs.map +1 -1
- package/esm/exporters/console/index.d.mts +2 -1
- package/esm/exporters/console/index.mjs +5 -0
- package/esm/exporters/file/file-exporter.d.mts +2 -3
- package/esm/exporters/file/file-exporter.d.mts.map +1 -1
- package/esm/exporters/file/file-exporter.mjs.map +1 -1
- package/esm/exporters/file/file-exporter.type.d.mts +8 -5
- package/esm/exporters/file/file-exporter.type.d.mts.map +1 -1
- package/esm/exporters/file/index.d.mts +2 -1
- package/esm/exporters/index.d.mts +7 -1
- package/esm/exporters/index.mjs +3 -1
- package/esm/exporters/langfuse/index.d.mts +2 -1
- package/esm/exporters/langfuse/index.mjs +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.d.mts +2 -3
- package/esm/exporters/langfuse/langfuse-exporter.d.mts.map +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.mjs +4 -3
- package/esm/exporters/langfuse/langfuse-exporter.mjs.map +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.type.d.mts +23 -17
- package/esm/exporters/langfuse/langfuse-exporter.type.d.mts.map +1 -1
- package/esm/exporters/otel/index.d.mts +2 -1
- package/esm/exporters/otel/index.mjs +1 -1
- package/esm/exporters/otel/otel-api.shim.type.d.mts +6 -7
- package/esm/exporters/otel/otel-api.shim.type.d.mts.map +1 -1
- package/esm/exporters/otel/otel-exporter.d.mts +2 -3
- package/esm/exporters/otel/otel-exporter.d.mts.map +1 -1
- package/esm/exporters/otel/otel-exporter.mjs +2 -1
- package/esm/exporters/otel/otel-exporter.mjs.map +1 -1
- package/esm/exporters/otel/otel-exporter.type.d.mts +1 -3
- package/esm/exporters/otel/otel-exporter.type.d.mts.map +1 -1
- package/esm/exporters/utils/gen-ai-attributes.d.mts +9 -7
- package/esm/exporters/utils/gen-ai-attributes.d.mts.map +1 -1
- package/esm/exporters/utils/index.d.mts +2 -1
- package/esm/exporters/utils/index.mjs +5 -0
- package/esm/exporters/utils/total-cost.d.mts +3 -7
- package/esm/exporters/utils/total-cost.d.mts.map +1 -1
- package/esm/exporters/utils/total-cost.mjs +5 -7
- package/esm/exporters/utils/total-cost.mjs.map +1 -1
- package/esm/exporters/utils/walk-spans.d.mts +2 -2
- package/esm/exporters/utils/walk-spans.d.mts.map +1 -1
- package/esm/index.d.mts +8 -0
- package/esm/panoptic/index.d.mts +2 -1
- package/esm/panoptic/index.mjs +1 -1
- package/esm/panoptic/panoptic-middleware.d.mts +1 -3
- package/esm/panoptic/panoptic-middleware.d.mts.map +1 -1
- package/esm/panoptic/panoptic-middleware.mjs.map +1 -1
- package/esm/panoptic/panoptic-target.type.d.mts +4 -5
- package/esm/panoptic/panoptic-target.type.d.mts.map +1 -1
- package/esm/panoptic/panoptic.d.mts +1 -3
- package/esm/panoptic/panoptic.d.mts.map +1 -1
- package/esm/panoptic/panoptic.mjs.map +1 -1
- package/esm/panoptic/panoptic.type.d.mts +8 -7
- package/esm/panoptic/panoptic.type.d.mts.map +1 -1
- package/esm/store/cache-trace-store.d.mts +4 -6
- package/esm/store/cache-trace-store.d.mts.map +1 -1
- package/esm/store/cache-trace-store.mjs +2 -4
- package/esm/store/cache-trace-store.mjs.map +1 -1
- package/esm/store/in-memory-trace-store.d.mts +2 -4
- package/esm/store/in-memory-trace-store.d.mts.map +1 -1
- package/esm/store/in-memory-trace-store.mjs +4 -5
- package/esm/store/in-memory-trace-store.mjs.map +1 -1
- package/esm/store/index.d.mts +2 -1
- package/esm/store/index.mjs +1 -1
- package/esm/store/match-trace.d.mts +1 -3
- package/esm/store/match-trace.d.mts.map +1 -1
- package/esm/store/sum-usage.d.mts +4 -30
- package/esm/store/sum-usage.d.mts.map +1 -1
- package/esm/store/sum-usage.mjs +6 -49
- package/esm/store/sum-usage.mjs.map +1 -1
- package/esm/store/trace-aggregate.type.d.mts +13 -14
- package/esm/store/trace-aggregate.type.d.mts.map +1 -1
- package/esm/store/trace-query.type.d.mts +5 -5
- package/esm/store/trace-query.type.d.mts.map +1 -1
- package/esm/store/trace-store.contract.d.mts +1 -3
- package/esm/store/trace-store.contract.d.mts.map +1 -1
- package/llms-full.txt +148 -117
- package/package.json +4 -4
- package/skills/evaluate-system-prompt/SKILL.md +21 -17
- package/skills/export-traces/SKILL.md +32 -24
- package/skills/index.md +3 -0
- package/skills/observe-with-panoptic/SKILL.md +18 -18
- package/skills/query-traces/SKILL.md +45 -33
- package/skills/use-local-dashboard/SKILL.md +33 -26
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@ All notable changes to `@warlock.js/ai-panoptic` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.32.0 - 2026-10-18
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Pin the package development compiler to TypeScript 7.0.2 and use explicit Node types and source roots with supported module resolution.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Use the canonical usage rollup for trace aggregates, retaining hosted-tool counters and historical request fees alongside cache lifetime and mixed-provider cache semantics.
|
|
16
|
+
|
|
17
|
+
## 5.31.0 - 2026-10-18
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Trace cost totals (exporters, the dashboard and trace filters) include the new cache-write cost channel.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Tool spans carry the provider's tool-call id as the `tool.callId` attribute.
|
|
26
|
+
- Agent runs with `status: "incomplete"` (their final answer was cut off) are exported as errors: OTel `ERROR` status, Langfuse level `ERROR`, the console exporter's error stream (marked `INCOMPLETE`), the dashboard's error filter, and the `failed` count of trace-store aggregates. `?status=incomplete` is accepted by the dashboard API.
|
|
27
|
+
|
|
7
28
|
## 5.30.0 - 2026-10-16
|
|
8
29
|
|
|
9
30
|
### Changed
|
|
@@ -81,6 +102,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
81
102
|
### Changed
|
|
82
103
|
|
|
83
104
|
- Lockstep release maintenance and dependency refresh.
|
|
105
|
+
|
|
84
106
|
## 5.20.0 - 2026-09-24
|
|
85
107
|
|
|
86
108
|
### Changed
|
|
@@ -146,9 +168,9 @@ changelogs.
|
|
|
146
168
|
|
|
147
169
|
- **Dashboard stored XSS via `javascript:` markdown links — fixed.** The dashboard's markdown link renderer (`mdInline` in `ui.html.ts`) rewrote `[text](url)` into a live `<a href>` without validating the URL scheme, so a `javascript:` URL embedded in captured trace content (`span.input` / `span.output` under `captureContent` — i.e. prompt-injected model output or attacker-controlled tool results) became a stored XSS that fired when an operator clicked the link; the page's CSP (`script-src 'unsafe-inline'`) permits `javascript:` URI execution and does not restrict top-level navigation, putting the in-page bearer token in reach. Link URLs are now checked against a scheme allowlist (`http:`, `https:`, `mailto:`, plus relative/anchor URLs) after normalizing the URL the way a browser will — attribute-entity decode, strip of ignored control chars/whitespace (`java\tscript:`), lowercase — and scheme-relative `//host` links are rejected too; a rejected URL renders its label as plain text with no `href` at all. Regression-tested by executing the actual inlined client renderer against `javascript:`/`data:`/`vbscript:` payloads and their case/whitespace/entity obfuscations (`ui.html.md-links.spec.ts`)
|
|
148
170
|
- **Dashboard token-handling hardening (3 residual findings from the same audit as the XSS above).** None of these are exploitable on their own today, but each widened the blast radius of a future bug:
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
171
|
+
- _Bearer token no longer a page-global._ `ui.html.ts`'s client script kept `TOKEN` as a `var` shared across its whole ~1000-line closure. It's now sealed inside its own inner IIFE that exposes only the `fetchAuthed` helper — code elsewhere in that closure (present or future) can no longer read the raw token by name.
|
|
172
|
+
- _Constant-time token comparison._ `serve.ts`'s `isAuthorized` compared the header/query token with plain `===`, which short-circuits on the first differing byte and is a textbook timing side-channel — the one scenario the package's own docs call out as realistic (`authToken` is required specifically when bound off-loopback, i.e. reachable over a network). Both the header and query-string checks now go through `crypto.timingSafeEqual` on length-checked, equal-length buffers.
|
|
173
|
+
- _Token-in-URL narrowed to the one route that needs it._ `?token=` is no longer accepted on the JSON API routes, only on the HTML page route. The page's own polling already re-sends the token as an `Authorization` header (fixed in 4.8.2), so the only request that structurally _can't_ carry a header is the initial browser navigation that loads the HTML shell — that's the sole remaining query-string exposure, narrowing the token's footprint in access/proxy logs and browser history from every poll to one request.
|
|
152
174
|
|
|
153
175
|
## 4.12.0
|
|
154
176
|
|
package/README.md
CHANGED
|
@@ -81,8 +81,8 @@ Four exporters ship today, each a factory returning an `ExporterContract`:
|
|
|
81
81
|
```ts
|
|
82
82
|
import {
|
|
83
83
|
consoleExporter, // zero-dep — print trace summary or full span tree
|
|
84
|
-
fileExporter,
|
|
85
|
-
otelExporter,
|
|
84
|
+
fileExporter, // zero-dep — append traces as JSON Lines, buffered
|
|
85
|
+
otelExporter, // OpenTelemetry — gen_ai.* semantic conventions (lazy @opentelemetry/api)
|
|
86
86
|
langfuseExporter, // Langfuse — traces + generations (lazy langfuse)
|
|
87
87
|
} from "@warlock.js/ai-panoptic";
|
|
88
88
|
|
package/cjs/index.cjs
CHANGED
|
@@ -114,10 +114,7 @@ function extractSpanAttributes(report) {
|
|
|
114
114
|
case "orchestrator":
|
|
115
115
|
addOrchestratorAttributes(attributes, extensions);
|
|
116
116
|
break;
|
|
117
|
-
case "tool":
|
|
118
|
-
addToolAttributes(attributes, extensions);
|
|
119
|
-
break;
|
|
120
|
-
default: break;
|
|
117
|
+
case "tool": addToolAttributes(attributes, extensions);
|
|
121
118
|
}
|
|
122
119
|
if (Object.keys(attributes).length === 0) return;
|
|
123
120
|
return attributes;
|
|
@@ -146,6 +143,7 @@ function addOrchestratorAttributes(attributes, extensions) {
|
|
|
146
143
|
}
|
|
147
144
|
function addToolAttributes(attributes, extensions) {
|
|
148
145
|
if (extensions.tripIndex !== void 0) attributes["tool.tripIndex"] = extensions.tripIndex;
|
|
146
|
+
if (extensions.callId !== void 0) attributes["tool.callId"] = extensions.callId;
|
|
149
147
|
if (extensions.recoveredFrom !== void 0) attributes["tool.recoveredFrom"] = extensions.recoveredFrom;
|
|
150
148
|
}
|
|
151
149
|
|
|
@@ -501,48 +499,14 @@ function toEpoch(bound) {
|
|
|
501
499
|
|
|
502
500
|
//#endregion
|
|
503
501
|
//#region ../../packages/ai-panoptic/src/store/sum-usage.ts
|
|
504
|
-
/**
|
|
505
|
-
* Fold a child {@link Usage} into a running accumulator. Token channels
|
|
506
|
-
* (`input` / `output` / `total`) always sum; the optional cache /
|
|
507
|
-
* reasoning channels (`cachedTokens` / `cacheWriteTokens` /
|
|
508
|
-
* `reasoningTokens`) sum only when at least one side reported them, so
|
|
509
|
-
* a provider that never meters a channel doesn't fabricate a `0` for
|
|
510
|
-
* it. The `cost` breakdown is merged with the core framework's
|
|
511
|
-
* {@link accumulateCost}, keeping cost-rollup semantics identical to a
|
|
512
|
-
* native report tree — an unpriced contributor never erases a priced
|
|
513
|
-
* one.
|
|
514
|
-
*
|
|
515
|
-
* Pure: returns a fresh `Usage`, never mutates either argument. Seed an
|
|
516
|
-
* aggregation with {@link emptyUsage}.
|
|
517
|
-
*
|
|
518
|
-
* @example
|
|
519
|
-
* let total = emptyUsage();
|
|
520
|
-
* for (const trace of traces) {
|
|
521
|
-
* total = sumUsage(total, trace.usage);
|
|
522
|
-
* }
|
|
523
|
-
*/
|
|
502
|
+
/** Return an independent all-channel usage rollup, preserving hosted-tool counters. */
|
|
524
503
|
function sumUsage(accumulator, next) {
|
|
525
|
-
const merged =
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
total: accumulator.total + next.total
|
|
529
|
-
};
|
|
530
|
-
const cachedTokens = sumOptional(accumulator.cachedTokens, next.cachedTokens);
|
|
531
|
-
if (cachedTokens !== void 0) merged.cachedTokens = cachedTokens;
|
|
532
|
-
const cacheWriteTokens = sumOptional(accumulator.cacheWriteTokens, next.cacheWriteTokens);
|
|
533
|
-
if (cacheWriteTokens !== void 0) merged.cacheWriteTokens = cacheWriteTokens;
|
|
534
|
-
const reasoningTokens = sumOptional(accumulator.reasoningTokens, next.reasoningTokens);
|
|
535
|
-
if (reasoningTokens !== void 0) merged.reasoningTokens = reasoningTokens;
|
|
536
|
-
const cost = (0, _warlock_js_ai.accumulateCost)(accumulator.cost, next.cost);
|
|
537
|
-
if (cost !== void 0) merged.cost = cost;
|
|
504
|
+
const merged = emptyUsage();
|
|
505
|
+
(0, _warlock_js_ai.mergeUsage)(merged, accumulator);
|
|
506
|
+
(0, _warlock_js_ai.mergeUsage)(merged, next);
|
|
538
507
|
return merged;
|
|
539
508
|
}
|
|
540
|
-
/**
|
|
541
|
-
* A zero-valued {@link Usage} to seed an aggregation. Only the required
|
|
542
|
-
* token channels are set; optional channels stay absent until a
|
|
543
|
-
* contributor reports them, preserving the "never reported" vs
|
|
544
|
-
* "reported as 0" distinction.
|
|
545
|
-
*/
|
|
509
|
+
/** Seed an aggregation without claiming any optional counter was reported. */
|
|
546
510
|
function emptyUsage() {
|
|
547
511
|
return {
|
|
548
512
|
input: 0,
|
|
@@ -550,15 +514,6 @@ function emptyUsage() {
|
|
|
550
514
|
total: 0
|
|
551
515
|
};
|
|
552
516
|
}
|
|
553
|
-
/**
|
|
554
|
-
* Add two optional token counts, treating either side's `undefined` as
|
|
555
|
-
* zero — but return `undefined` when both are absent, so an unreported
|
|
556
|
-
* channel stays unreported rather than collapsing to `0`.
|
|
557
|
-
*/
|
|
558
|
-
function sumOptional(accumulator, next) {
|
|
559
|
-
if (accumulator === void 0 && next === void 0) return;
|
|
560
|
-
return (accumulator ?? 0) + (next ?? 0);
|
|
561
|
-
}
|
|
562
517
|
|
|
563
518
|
//#endregion
|
|
564
519
|
//#region ../../packages/ai-panoptic/src/store/cache-trace-store.ts
|
|
@@ -781,12 +736,10 @@ var CacheTraceStore = class {
|
|
|
781
736
|
aggregate.completed += 1;
|
|
782
737
|
break;
|
|
783
738
|
case "failed":
|
|
739
|
+
case "incomplete":
|
|
784
740
|
aggregate.failed += 1;
|
|
785
741
|
break;
|
|
786
|
-
case "cancelled":
|
|
787
|
-
aggregate.cancelled += 1;
|
|
788
|
-
break;
|
|
789
|
-
default: break;
|
|
742
|
+
case "cancelled": aggregate.cancelled += 1;
|
|
790
743
|
}
|
|
791
744
|
}
|
|
792
745
|
/**
|
|
@@ -927,7 +880,8 @@ var InMemoryTraceStore = class {
|
|
|
927
880
|
* Non-terminal statuses (`awaiting-input`, `max-iterations`) are
|
|
928
881
|
* counted in `traces` but tracked by none of the three headline
|
|
929
882
|
* counters — intentional, those three answer the common
|
|
930
|
-
* "succeeded / errored / aborted" question.
|
|
883
|
+
* "succeeded / errored / aborted" question. An `incomplete` agent run
|
|
884
|
+
* (its answer was cut off) errored, so it counts as `failed`.
|
|
931
885
|
*/
|
|
932
886
|
countStatus(aggregate, trace) {
|
|
933
887
|
switch (trace.root.status) {
|
|
@@ -935,12 +889,10 @@ var InMemoryTraceStore = class {
|
|
|
935
889
|
aggregate.completed += 1;
|
|
936
890
|
break;
|
|
937
891
|
case "failed":
|
|
892
|
+
case "incomplete":
|
|
938
893
|
aggregate.failed += 1;
|
|
939
894
|
break;
|
|
940
|
-
case "cancelled":
|
|
941
|
-
aggregate.cancelled += 1;
|
|
942
|
-
break;
|
|
943
|
-
default: break;
|
|
895
|
+
case "cancelled": aggregate.cancelled += 1;
|
|
944
896
|
}
|
|
945
897
|
}
|
|
946
898
|
/**
|
|
@@ -985,10 +937,8 @@ function createInMemoryTraceStore(options) {
|
|
|
985
937
|
//#region ../../packages/ai-panoptic/src/exporters/utils/total-cost.ts
|
|
986
938
|
/**
|
|
987
939
|
* Collapse a {@link Usage.cost} breakdown into a single USD scalar by
|
|
988
|
-
* summing every populated
|
|
989
|
-
*
|
|
990
|
-
* folds in `reasoning` for forward-safety when a provider prices
|
|
991
|
-
* reasoning tokens as a separate channel. Returns `undefined` when no
|
|
940
|
+
* summing every populated channel (input, output, cache reads, cache
|
|
941
|
+
* writes, reasoning) via `totalCost` from `@warlock.js/ai`. Returns `undefined` when no
|
|
992
942
|
* pricing was attached, so exporters can omit the cost attribute
|
|
993
943
|
* entirely rather than reporting a misleading `0`.
|
|
994
944
|
*
|
|
@@ -997,9 +947,7 @@ function createInMemoryTraceStore(options) {
|
|
|
997
947
|
* // => 0.05
|
|
998
948
|
*/
|
|
999
949
|
function totalCostUsd(usage) {
|
|
1000
|
-
|
|
1001
|
-
if (!cost) return;
|
|
1002
|
-
return (cost.input ?? 0) + (cost.output ?? 0) + (cost.cachedInput ?? 0) + (cost.cachedOutput ?? 0) + (cost.reasoning ?? 0);
|
|
950
|
+
return (0, _warlock_js_ai.totalCost)(usage.cost);
|
|
1003
951
|
}
|
|
1004
952
|
|
|
1005
953
|
//#endregion
|
|
@@ -1171,6 +1119,7 @@ function statusMarker(status) {
|
|
|
1171
1119
|
case "completed": return "ok";
|
|
1172
1120
|
case "failed": return "ERR";
|
|
1173
1121
|
case "cancelled": return "cancel";
|
|
1122
|
+
case "incomplete": return "INCOMPLETE";
|
|
1174
1123
|
case "max-iterations": return "max-iter";
|
|
1175
1124
|
case "awaiting-input": return "await";
|
|
1176
1125
|
default: return status;
|
|
@@ -1245,11 +1194,11 @@ function writeSpan(sink, span, depth, io, ioMaxChars) {
|
|
|
1245
1194
|
if (io) for (const line of formatSpanIO(span, depth, ioMaxChars)) writeAtSeverity(sink, span.status, line);
|
|
1246
1195
|
}
|
|
1247
1196
|
/**
|
|
1248
|
-
* Route a line to `error` when the span failed/cancelled,
|
|
1249
|
-
* `log`. Keeps healthy traces out of the error stream.
|
|
1197
|
+
* Route a line to `error` when the span failed/cancelled/incomplete,
|
|
1198
|
+
* otherwise to `log`. Keeps healthy traces out of the error stream.
|
|
1250
1199
|
*/
|
|
1251
1200
|
function writeAtSeverity(sink, status, line) {
|
|
1252
|
-
if (status === "failed" || status === "cancelled") {
|
|
1201
|
+
if (status === "failed" || status === "cancelled" || status === "incomplete") {
|
|
1253
1202
|
sink.error(line);
|
|
1254
1203
|
return;
|
|
1255
1204
|
}
|
|
@@ -1534,7 +1483,7 @@ function ownUsage(span) {
|
|
|
1534
1483
|
* rolled-up subtree totals next to an own-usage `usage` block. Cost is
|
|
1535
1484
|
* omitted for the same reason; Langfuse prices the own tokens itself.
|
|
1536
1485
|
*/
|
|
1537
|
-
const LANGFUSE_METADATA_OMIT = new Set([
|
|
1486
|
+
const LANGFUSE_METADATA_OMIT = /* @__PURE__ */ new Set([
|
|
1538
1487
|
GEN_AI_ATTRIBUTES.usageInputTokens,
|
|
1539
1488
|
GEN_AI_ATTRIBUTES.usageOutputTokens,
|
|
1540
1489
|
WARLOCK_ATTRIBUTES.totalTokens,
|
|
@@ -1556,10 +1505,10 @@ function langfuseMetadata(span) {
|
|
|
1556
1505
|
}
|
|
1557
1506
|
/**
|
|
1558
1507
|
* Map the Panoptic span status onto a Langfuse observation level —
|
|
1559
|
-
* failed/cancelled spans surface as `ERROR`, everything else `DEFAULT`.
|
|
1508
|
+
* failed/cancelled/incomplete spans surface as `ERROR`, everything else `DEFAULT`.
|
|
1560
1509
|
*/
|
|
1561
1510
|
function toLevel(span) {
|
|
1562
|
-
if (span.status === "failed" || span.status === "cancelled") return "ERROR";
|
|
1511
|
+
if (span.status === "failed" || span.status === "cancelled" || span.status === "incomplete") return "ERROR";
|
|
1563
1512
|
return "DEFAULT";
|
|
1564
1513
|
}
|
|
1565
1514
|
|
|
@@ -1692,7 +1641,7 @@ function applyStatus(otelSpan, span) {
|
|
|
1692
1641
|
message: span.error.message,
|
|
1693
1642
|
stack: span.error.stack
|
|
1694
1643
|
});
|
|
1695
|
-
if (span.status === "failed" || span.status === "cancelled") {
|
|
1644
|
+
if (span.status === "failed" || span.status === "cancelled" || span.status === "incomplete") {
|
|
1696
1645
|
otelSpan.setStatus({
|
|
1697
1646
|
code: codes.ERROR,
|
|
1698
1647
|
message: span.error?.message
|
|
@@ -1934,7 +1883,9 @@ function panoptic(options = {}) {
|
|
|
1934
1883
|
* the caller (the dashboard route) is expected to catch.
|
|
1935
1884
|
*/
|
|
1936
1885
|
async function evaluateSystemPrompt(systemPrompt, config, instructionsOverride) {
|
|
1937
|
-
|
|
1886
|
+
const model = typeof config.model === "function" ? await config.model() : config.model;
|
|
1887
|
+
const instructions = instructionsOverride?.trim() || config.instructions;
|
|
1888
|
+
return (0, _warlock_js_ai.judgePromptBody)(systemPrompt, model, instructions);
|
|
1938
1889
|
}
|
|
1939
1890
|
|
|
1940
1891
|
//#endregion
|
|
@@ -1980,6 +1931,7 @@ const KNOWN_STATUSES = [
|
|
|
1980
1931
|
"completed",
|
|
1981
1932
|
"failed",
|
|
1982
1933
|
"cancelled",
|
|
1934
|
+
"incomplete",
|
|
1983
1935
|
"max-iterations",
|
|
1984
1936
|
"awaiting-input",
|
|
1985
1937
|
"awaiting-approval"
|
|
@@ -2370,13 +2322,14 @@ function dashboardHtml(basePath, title, evaluateEnabled = false, evaluateDefault
|
|
|
2370
2322
|
|
|
2371
2323
|
var STATUS_FILTERS = ["completed", "failed", "cancelled"];
|
|
2372
2324
|
var TYPE_FILTERS = ["agent", "tool", "model", "supervisor", "team", "workflow", "orchestrator", "planner", "batch", "callback"];
|
|
2373
|
-
var ERROR_STATUSES = { failed: 1, cancelled: 1 };
|
|
2325
|
+
var ERROR_STATUSES = { failed: 1, cancelled: 1, incomplete: 1 };
|
|
2374
2326
|
var NO_SESSION_KEY = "(no session)";
|
|
2375
2327
|
var NO_PROMPT_KEY = "(no prompt)";
|
|
2376
2328
|
var NO_TYPE_KEY = "(no type)";
|
|
2377
2329
|
|
|
2378
2330
|
var statusClass = function (s) {
|
|
2379
2331
|
if (s === "completed" || s === "failed" || s === "cancelled") return s;
|
|
2332
|
+
if (s === "incomplete") return "failed";
|
|
2380
2333
|
return "other";
|
|
2381
2334
|
};
|
|
2382
2335
|
var esc = function (v) {
|
|
@@ -2464,7 +2417,7 @@ function dashboardHtml(basePath, title, evaluateEnabled = false, evaluateDefault
|
|
|
2464
2417
|
// Sum every priced lane of a cost object into one USD number.
|
|
2465
2418
|
function costSumObj(c) {
|
|
2466
2419
|
if (!c) return 0;
|
|
2467
|
-
return (c.input || 0) + (c.output || 0) + (c.cachedInput || 0) + (c.cachedOutput || 0) + (c.reasoning || 0);
|
|
2420
|
+
return (c.input || 0) + (c.output || 0) + (c.cachedInput || 0) + (c.cacheWrite || 0) + (c.cachedOutput || 0) + (c.reasoning || 0);
|
|
2468
2421
|
}
|
|
2469
2422
|
// The cost a single span directly carries (on its rolled-up usage).
|
|
2470
2423
|
function usageCost(usage) { return usage ? costSumObj(usage.cost) : 0; }
|
|
@@ -2798,7 +2751,7 @@ function dashboardHtml(basePath, title, evaluateEnabled = false, evaluateDefault
|
|
|
2798
2751
|
}
|
|
2799
2752
|
|
|
2800
2753
|
function renderStats(a) {
|
|
2801
|
-
var cost = a.cost ? (((a.cost.input || 0) + (a.cost.output || 0) + (a.cost.cachedInput || 0) + (a.cost.cachedOutput || 0)).toFixed(4)) : "—";
|
|
2754
|
+
var cost = a.cost ? (((a.cost.input || 0) + (a.cost.output || 0) + (a.cost.cachedInput || 0) + (a.cost.cacheWrite || 0) + (a.cost.cachedOutput || 0) + (a.cost.reasoning || 0)).toFixed(4)) : "—";
|
|
2802
2755
|
var u = a.usage || {};
|
|
2803
2756
|
var cells = [
|
|
2804
2757
|
["traces", num(a.traces), null],
|
|
@@ -3055,7 +3008,7 @@ function dashboardHtml(basePath, title, evaluateEnabled = false, evaluateDefault
|
|
|
3055
3008
|
// "Supervisor Terminated By", "span id" → "Span ID", "agent.trips" →
|
|
3056
3009
|
// "Agent Trips". Underlying attribute keys are untouched.
|
|
3057
3010
|
// NB: this whole script is a template literal — regex backslash classes
|
|
3058
|
-
// MUST be double-escaped (\\s
|
|
3011
|
+
// MUST be double-escaped (\\s) so the rendered script retains its backslash.
|
|
3059
3012
|
function humanizeKey(key) {
|
|
3060
3013
|
return String(key).split(/[.\\s]+/).map(function (seg) {
|
|
3061
3014
|
return seg.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/\\s+/).map(function (w) {
|
|
@@ -3521,7 +3474,7 @@ function encodeForInlineScript(value) {
|
|
|
3521
3474
|
//#endregion
|
|
3522
3475
|
//#region ../../packages/ai-panoptic/src/dashboard/serve.ts
|
|
3523
3476
|
/** Hard cap on the evaluate route's request body — well beyond a real instructions string. */
|
|
3524
|
-
const MAX_EVALUATE_BODY_BYTES =
|
|
3477
|
+
const MAX_EVALUATE_BODY_BYTES = 65536;
|
|
3525
3478
|
/**
|
|
3526
3479
|
* Security response headers added to every dashboard response (S4):
|
|
3527
3480
|
* block MIME-sniffing, framing, referrer leakage, and lock the page's
|
|
@@ -3803,13 +3756,14 @@ function dashboard(store, options = {}) {
|
|
|
3803
3756
|
const basePath = normalizeBasePath(options.basePath);
|
|
3804
3757
|
if (!isLoopbackHost(host) && !options.authToken) return Promise.reject(/* @__PURE__ */ new Error(`Panoptic dashboard: binding to a non-loopback host ("${host}") requires an \`authToken\` (the dashboard exposes raw prompt content). Pass \`authToken\`, or bind to 127.0.0.1.`));
|
|
3805
3758
|
const allowedHosts = (options.allowedHosts ?? defaultAllowedHosts(host)).map((h) => h.toLowerCase());
|
|
3806
|
-
const
|
|
3759
|
+
const handler = createRequestHandler(store, {
|
|
3807
3760
|
basePath,
|
|
3808
3761
|
title,
|
|
3809
3762
|
authToken: options.authToken,
|
|
3810
3763
|
allowedHosts,
|
|
3811
3764
|
evaluate: options.evaluate
|
|
3812
|
-
})
|
|
3765
|
+
});
|
|
3766
|
+
const server = (0, node_http.createServer)(handler);
|
|
3813
3767
|
return new Promise((resolve, reject) => {
|
|
3814
3768
|
const onError = (error) => {
|
|
3815
3769
|
server.off("error", onError);
|
|
@@ -4124,7 +4078,7 @@ function aggregateByType(traces) {
|
|
|
4124
4078
|
*/
|
|
4125
4079
|
function costSumObj(cost) {
|
|
4126
4080
|
if (cost === void 0) return 0;
|
|
4127
|
-
return (cost.input ?? 0) + (cost.output ?? 0) + (cost.cachedInput ?? 0) + (cost.cachedOutput ?? 0) + (cost.reasoning ?? 0);
|
|
4081
|
+
return (cost.input ?? 0) + (cost.output ?? 0) + (cost.cachedInput ?? 0) + (cost.cacheWrite ?? 0) + (cost.cachedOutput ?? 0) + (cost.reasoning ?? 0);
|
|
4128
4082
|
}
|
|
4129
4083
|
/**
|
|
4130
4084
|
* Rollup-aware subtree cost: a node's own cost when it carries one
|