@poncho-ai/harness 0.59.9 → 0.59.10
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/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +12 -0
- package/dist/index.js +33 -3
- package/package.json +1 -1
- package/src/harness.ts +45 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/harness@0.59.
|
|
2
|
+
> @poncho-ai/harness@0.59.10 build /home/runner/work/poncho-ai/poncho-ai/packages/harness
|
|
3
3
|
> node scripts/embed-docs.js && tsup src/index.ts --format esm --dts
|
|
4
4
|
|
|
5
5
|
[embed-docs] Generated poncho-docs.ts with 4 topics
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
[34mCLI[39m tsup v8.5.1
|
|
9
9
|
[34mCLI[39m Target: es2022
|
|
10
10
|
[34mESM[39m Build start
|
|
11
|
-
[32mESM[39m [1mdist/index.js [22m[32m558.75 KB[39m
|
|
12
11
|
[32mESM[39m [1mdist/isolate-F2PPSUL6.js [22m[32m53.82 KB[39m
|
|
13
|
-
[32mESM[39m
|
|
12
|
+
[32mESM[39m [1mdist/index.js [22m[32m559.89 KB[39m
|
|
13
|
+
[32mESM[39m ⚡️ Build success in 238ms
|
|
14
14
|
[34mDTS[39m Build start
|
|
15
|
-
[32mDTS[39m ⚡️ Build success in
|
|
15
|
+
[32mDTS[39m ⚡️ Build success in 7368ms
|
|
16
16
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m102.06 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @poncho-ai/harness
|
|
2
2
|
|
|
3
|
+
## 0.59.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`fad3918`](https://github.com/cesr/poncho-ai/commit/fad3918302114f76a29080cf28e9c003c61ef0d9) Thanks [@cesr](https://github.com/cesr)! - Stamp `session.id` / `user.id` on EVERY span, not just the invoke_agent
|
|
8
|
+
root. Observability backends resolve a span's identity from its own
|
|
9
|
+
attributes — Latitude's console session/conversation views key on the LLM
|
|
10
|
+
generation spans, so root-only attributes grouped the API-level trace but
|
|
11
|
+
left the console showing one session per turn and no user. The identity now
|
|
12
|
+
rides the OTel Context and an IdentityAttributeSpanProcessor injects it
|
|
13
|
+
into every descendant span (LLM steps, tool executions) at start.
|
|
14
|
+
|
|
3
15
|
## 0.59.9
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -8745,7 +8745,7 @@ var createSubagentTools = (manager) => [
|
|
|
8745
8745
|
];
|
|
8746
8746
|
|
|
8747
8747
|
// src/harness.ts
|
|
8748
|
-
import { trace, context as otelContext, SpanStatusCode, SpanKind, diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
|
|
8748
|
+
import { trace, context as otelContext, createContextKey, SpanStatusCode, SpanKind, diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
|
|
8749
8749
|
import { NodeTracerProvider, BatchSpanProcessor } from "@opentelemetry/sdk-trace-node";
|
|
8750
8750
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
8751
8751
|
|
|
@@ -8928,6 +8928,28 @@ var telemetryLog2 = createLogger7("telemetry");
|
|
|
8928
8928
|
var costLog = createLogger7("cost");
|
|
8929
8929
|
var mcpLog2 = createLogger7("mcp");
|
|
8930
8930
|
var modelLog = createLogger7("model");
|
|
8931
|
+
var TELEMETRY_SESSION_ID_KEY = createContextKey("poncho.telemetry.session_id");
|
|
8932
|
+
var TELEMETRY_USER_ID_KEY = createContextKey("poncho.telemetry.user_id");
|
|
8933
|
+
var IdentityAttributeSpanProcessor = class {
|
|
8934
|
+
onStart(span, parentContext) {
|
|
8935
|
+
const sessionId = parentContext.getValue(TELEMETRY_SESSION_ID_KEY);
|
|
8936
|
+
if (typeof sessionId === "string" && sessionId) {
|
|
8937
|
+
span.setAttribute("session.id", sessionId);
|
|
8938
|
+
}
|
|
8939
|
+
const userId = parentContext.getValue(TELEMETRY_USER_ID_KEY);
|
|
8940
|
+
if (typeof userId === "string" && userId) {
|
|
8941
|
+
span.setAttribute("user.id", userId);
|
|
8942
|
+
}
|
|
8943
|
+
}
|
|
8944
|
+
onEnd() {
|
|
8945
|
+
}
|
|
8946
|
+
forceFlush() {
|
|
8947
|
+
return Promise.resolve();
|
|
8948
|
+
}
|
|
8949
|
+
shutdown() {
|
|
8950
|
+
return Promise.resolve();
|
|
8951
|
+
}
|
|
8952
|
+
};
|
|
8931
8953
|
function formatOtlpError(err) {
|
|
8932
8954
|
if (!(err instanceof Error)) return String(err);
|
|
8933
8955
|
const parts = [];
|
|
@@ -10339,7 +10361,9 @@ var AgentHarness = class _AgentHarness {
|
|
|
10339
10361
|
const processor = new BatchSpanProcessor(exporter);
|
|
10340
10362
|
this.otlpSpanProcessor = processor;
|
|
10341
10363
|
const provider2 = new NodeTracerProvider({
|
|
10342
|
-
|
|
10364
|
+
// Identity injector FIRST so every span (root, LLM steps, tool
|
|
10365
|
+
// executions) carries session.id/user.id before batching/export.
|
|
10366
|
+
spanProcessors: [new IdentityAttributeSpanProcessor(), processor]
|
|
10343
10367
|
});
|
|
10344
10368
|
provider2.register();
|
|
10345
10369
|
this.otlpTracerProvider = provider2;
|
|
@@ -10506,7 +10530,13 @@ var AgentHarness = class _AgentHarness {
|
|
|
10506
10530
|
...input.tenantId ? { "tenant.id": input.tenantId } : {}
|
|
10507
10531
|
}
|
|
10508
10532
|
});
|
|
10509
|
-
|
|
10533
|
+
let spanContext = trace.setSpan(otelContext.active(), rootSpan);
|
|
10534
|
+
if (input.conversationId) {
|
|
10535
|
+
spanContext = spanContext.setValue(TELEMETRY_SESSION_ID_KEY, input.conversationId);
|
|
10536
|
+
}
|
|
10537
|
+
if (this.telemetryUserId) {
|
|
10538
|
+
spanContext = spanContext.setValue(TELEMETRY_USER_ID_KEY, this.telemetryUserId);
|
|
10539
|
+
}
|
|
10510
10540
|
try {
|
|
10511
10541
|
const gen = this.run(input);
|
|
10512
10542
|
let next;
|
package/package.json
CHANGED
package/src/harness.ts
CHANGED
|
@@ -67,9 +67,41 @@ import { createSkillTools, normalizeScriptPolicyPath } from "./skill-tools.js";
|
|
|
67
67
|
import { createSearchTools } from "./search-tools.js";
|
|
68
68
|
import { createSubagentTools } from "./subagent-tools.js";
|
|
69
69
|
import type { SubagentManager } from "./subagent-manager.js";
|
|
70
|
-
import { trace, context as otelContext, SpanStatusCode, SpanKind, diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
|
|
70
|
+
import { trace, context as otelContext, createContextKey, type Context as OtelContextType, SpanStatusCode, SpanKind, diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
|
|
71
|
+
import type { Span as OtelSdkSpan, SpanProcessor } from "@opentelemetry/sdk-trace-node";
|
|
71
72
|
import { NodeTracerProvider, BatchSpanProcessor } from "@opentelemetry/sdk-trace-node";
|
|
72
73
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
74
|
+
|
|
75
|
+
// ── Telemetry identity propagation ──────────────────────────────────────────
|
|
76
|
+
// Observability backends (Latitude) resolve a span's session/user from the
|
|
77
|
+
// span's OWN attributes — the console's session & conversation views key on
|
|
78
|
+
// the LLM generation spans, not the root span. So stamping `session.id` /
|
|
79
|
+
// `user.id` only on the invoke_agent root groups the API-level trace but
|
|
80
|
+
// leaves the console treating every turn as its own session. The fix is the
|
|
81
|
+
// same one vendor SDKs use: carry the identity in the OTel Context and have
|
|
82
|
+
// a SpanProcessor stamp it onto EVERY span at start.
|
|
83
|
+
const TELEMETRY_SESSION_ID_KEY = createContextKey("poncho.telemetry.session_id");
|
|
84
|
+
const TELEMETRY_USER_ID_KEY = createContextKey("poncho.telemetry.user_id");
|
|
85
|
+
|
|
86
|
+
class IdentityAttributeSpanProcessor implements SpanProcessor {
|
|
87
|
+
onStart(span: OtelSdkSpan, parentContext: OtelContextType): void {
|
|
88
|
+
const sessionId = parentContext.getValue(TELEMETRY_SESSION_ID_KEY);
|
|
89
|
+
if (typeof sessionId === "string" && sessionId) {
|
|
90
|
+
span.setAttribute("session.id", sessionId);
|
|
91
|
+
}
|
|
92
|
+
const userId = parentContext.getValue(TELEMETRY_USER_ID_KEY);
|
|
93
|
+
if (typeof userId === "string" && userId) {
|
|
94
|
+
span.setAttribute("user.id", userId);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
onEnd(): void {}
|
|
98
|
+
forceFlush(): Promise<void> {
|
|
99
|
+
return Promise.resolve();
|
|
100
|
+
}
|
|
101
|
+
shutdown(): Promise<void> {
|
|
102
|
+
return Promise.resolve();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
73
105
|
import { normalizeOtlp } from "./telemetry.js";
|
|
74
106
|
|
|
75
107
|
/** Extract useful details from OTLPExporterError (has .code + .data) or plain Error. */
|
|
@@ -1883,7 +1915,9 @@ export class AgentHarness {
|
|
|
1883
1915
|
const processor = new BatchSpanProcessor(exporter);
|
|
1884
1916
|
this.otlpSpanProcessor = processor;
|
|
1885
1917
|
const provider = new NodeTracerProvider({
|
|
1886
|
-
|
|
1918
|
+
// Identity injector FIRST so every span (root, LLM steps, tool
|
|
1919
|
+
// executions) carries session.id/user.id before batching/export.
|
|
1920
|
+
spanProcessors: [new IdentityAttributeSpanProcessor(), processor],
|
|
1887
1921
|
});
|
|
1888
1922
|
provider.register();
|
|
1889
1923
|
this.otlpTracerProvider = provider;
|
|
@@ -2074,7 +2108,15 @@ export class AgentHarness {
|
|
|
2074
2108
|
},
|
|
2075
2109
|
});
|
|
2076
2110
|
|
|
2077
|
-
|
|
2111
|
+
let spanContext = trace.setSpan(otelContext.active(), rootSpan);
|
|
2112
|
+
// Identity rides the context so IdentityAttributeSpanProcessor stamps
|
|
2113
|
+
// session.id/user.id on every descendant span (see processor docs).
|
|
2114
|
+
if (input.conversationId) {
|
|
2115
|
+
spanContext = spanContext.setValue(TELEMETRY_SESSION_ID_KEY, input.conversationId);
|
|
2116
|
+
}
|
|
2117
|
+
if (this.telemetryUserId) {
|
|
2118
|
+
spanContext = spanContext.setValue(TELEMETRY_USER_ID_KEY, this.telemetryUserId);
|
|
2119
|
+
}
|
|
2078
2120
|
|
|
2079
2121
|
try {
|
|
2080
2122
|
const gen = this.run(input);
|