psyclaw 0.30.2 → 0.30.3
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/README.md +5 -5
- package/dist/apps/panel/observability.js +6 -3
- package/dist/src/adapters/pi/extension.js +16 -6
- package/dist/src/adapters/pi/extension.js.map +1 -1
- package/dist/src/adapters/pi/model.js +28 -2
- package/dist/src/adapters/pi/model.js.map +1 -1
- package/dist/src/cli.js +4 -4
- package/dist/src/cli.js.map +1 -1
- package/dist/src/observability/config.d.ts +6 -0
- package/dist/src/observability/config.js +36 -5
- package/dist/src/observability/config.js.map +1 -1
- package/dist/src/observability/error-context.d.ts +20 -0
- package/dist/src/observability/error-context.js +104 -0
- package/dist/src/observability/error-context.js.map +1 -0
- package/dist/src/observability/expected.d.ts +10 -0
- package/dist/src/observability/expected.js +37 -0
- package/dist/src/observability/expected.js.map +1 -0
- package/dist/src/observability/identity.d.ts +10 -0
- package/dist/src/observability/identity.js +24 -0
- package/dist/src/observability/identity.js.map +1 -0
- package/dist/src/observability/index.d.ts +12 -2
- package/dist/src/observability/index.js +67 -9
- package/dist/src/observability/index.js.map +1 -1
- package/dist/src/observability/langfuse.d.ts +27 -0
- package/dist/src/observability/langfuse.js +65 -0
- package/dist/src/observability/langfuse.js.map +1 -0
- package/dist/src/observability/llm.d.ts +105 -0
- package/dist/src/observability/llm.js +185 -0
- package/dist/src/observability/llm.js.map +1 -0
- package/dist/src/observability/node-sdks.d.ts +9 -0
- package/dist/src/observability/node-sdks.js +80 -10
- package/dist/src/observability/node-sdks.js.map +1 -1
- package/dist/src/observability/notice.js +1 -1
- package/dist/src/observability/notice.js.map +1 -1
- package/dist/src/observability/preference.d.ts +3 -0
- package/dist/src/observability/preference.js +13 -0
- package/dist/src/observability/preference.js.map +1 -1
- package/dist/src/orchestration/pi-executor.js +10 -1
- package/dist/src/orchestration/pi-executor.js.map +1 -1
- package/dist/src/orchestration/runner.js +3 -3
- package/dist/src/orchestration/runner.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
import { arch, platform } from "node:os";
|
|
2
|
+
import { PSYCLAW_VERSION } from "../branding.js";
|
|
1
3
|
import { observabilityEnabled, readNodeObservabilityConfig, sanitizeAgentEventProperties, } from "./config.js";
|
|
4
|
+
import { filesystemErrorContext, redactUserPath } from "./error-context.js";
|
|
5
|
+
import { ensureAnonymousDistinctId, newAnonymousDistinctId } from "./identity.js";
|
|
6
|
+
import { isExpectedUserError } from "./expected.js";
|
|
2
7
|
import { readTelemetryPreference, resolveTelemetryEnabled, telemetryPreferenceOptions } from "./preference.js";
|
|
3
|
-
export { DEFAULT_POSTHOG_HOST, OBS_CONFIG_SCRIPT_ID, browserConfigForPreference, emptyBrowserObservabilityConfig, injectBrowserObservabilityConfig, observabilityEnabled, readBrowserObservabilityConfig, readNodeObservabilityConfig, sanitizeAgentEventProperties, } from "./config.js";
|
|
4
|
-
export { DEFAULT_TELEMETRY_PREFERENCE, parseTelemetryPreference, psyclawSettingsPath, readTelemetryEnvOverride, readTelemetryPreference, resolveTelemetryEnabled, shouldShowTelemetryNotice, telemetryPreferenceOptions, writeTelemetryPreference, } from "./preference.js";
|
|
8
|
+
export { DEFAULT_LANGFUSE_HOST, DEFAULT_POSTHOG_HOST, OBS_CONFIG_SCRIPT_ID, browserConfigForPreference, emptyBrowserObservabilityConfig, injectBrowserObservabilityConfig, observabilityEnabled, readBrowserObservabilityConfig, readNodeObservabilityConfig, sanitizeAgentEventProperties, } from "./config.js";
|
|
9
|
+
export { DEFAULT_TELEMETRY_PREFERENCE, parseAnonymousDistinctId, parseTelemetryPreference, psyclawSettingsPath, readTelemetryEnvOverride, readTelemetryPreference, resolveTelemetryEnabled, shouldShowTelemetryNotice, telemetryPreferenceOptions, writeTelemetryPreference, } from "./preference.js";
|
|
5
10
|
export { maybeShowTelemetryNotice } from "./notice.js";
|
|
11
|
+
export { ensureAnonymousDistinctId, newAnonymousDistinctId } from "./identity.js";
|
|
12
|
+
export { filesystemErrorContext, fsWriteErrorMessage, redactUserPath } from "./error-context.js";
|
|
13
|
+
export { extractPiGeneration, lastPiGeneration, posthogAiGenerationProperties } from "./llm.js";
|
|
14
|
+
export { readLangfuseConfig } from "./langfuse.js";
|
|
15
|
+
export { ExpectedUserError, isExpectedUserError, isExpectedUserErrorMessage } from "./expected.js";
|
|
6
16
|
let bootPromise;
|
|
7
17
|
let handle;
|
|
8
18
|
async function defaultBoot(config) {
|
|
@@ -20,7 +30,15 @@ export async function initNodeObservability(options = {}) {
|
|
|
20
30
|
if (!resolveTelemetryEnabled(preference, env)) {
|
|
21
31
|
return handle !== undefined;
|
|
22
32
|
}
|
|
23
|
-
const
|
|
33
|
+
const distinctId = preference.anonymousId
|
|
34
|
+
?? env.PSYCLAW_DISTINCT_ID?.trim()
|
|
35
|
+
?? (options.preference !== undefined && options.settingsPath === undefined
|
|
36
|
+
? newAnonymousDistinctId()
|
|
37
|
+
: await ensureAnonymousDistinctId(telemetryPreferenceOptions(options.settingsPath)));
|
|
38
|
+
const config = {
|
|
39
|
+
...readNodeObservabilityConfig(env),
|
|
40
|
+
distinctId,
|
|
41
|
+
};
|
|
24
42
|
// Disabled must not latch the singleton: tests and a later enable in the
|
|
25
43
|
// same process still need to be able to boot.
|
|
26
44
|
if (!observabilityEnabled(config)) {
|
|
@@ -44,16 +62,51 @@ export function trackAgentEvent(name, properties = {}) {
|
|
|
44
62
|
return emitWhenReady((active) => active.captureEvent(name, safe));
|
|
45
63
|
}
|
|
46
64
|
export function captureAgentError(error, context = {}) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
if (isExpectedUserError(error))
|
|
66
|
+
return Promise.resolve();
|
|
67
|
+
const extracted = filesystemErrorContext(error);
|
|
68
|
+
const safeContext = {
|
|
69
|
+
package_version: PSYCLAW_VERSION,
|
|
70
|
+
os_platform: platform(),
|
|
71
|
+
os_arch: arch(),
|
|
72
|
+
};
|
|
73
|
+
for (const [key, value] of Object.entries({ ...extracted, ...context })) {
|
|
74
|
+
if (typeof value === "string" && value.trim()) {
|
|
75
|
+
const limit = key === "failed_path" || key === "cwd" ? 240 : 80;
|
|
76
|
+
const next = key === "failed_path" || key === "cwd" ? redactUserPath(value.trim()) : value.trim();
|
|
77
|
+
safeContext[key] = next.slice(0, limit);
|
|
78
|
+
}
|
|
51
79
|
}
|
|
52
80
|
return emitWhenReady((active) => active.captureError(error, safeContext));
|
|
53
81
|
}
|
|
54
82
|
export function trackGateWaiting(gate) {
|
|
55
83
|
return trackAgentEvent("gate_waiting_for_human", { phase: "gate", gate, status: "waiting" });
|
|
56
84
|
}
|
|
85
|
+
export function trackSkillInstall(status, properties = {}) {
|
|
86
|
+
return trackAgentEvent(`skill_install_${status === "queued" ? "queued" : status === "started" ? "started" : status === "error" ? "failed" : "finished"}`, {
|
|
87
|
+
phase: "skill_install",
|
|
88
|
+
status,
|
|
89
|
+
...properties,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
export function trackLlmGeneration(input) {
|
|
93
|
+
return emitWhenReady((active) => {
|
|
94
|
+
if (typeof active.captureLlmGeneration === "function")
|
|
95
|
+
active.captureLlmGeneration(input);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
export async function withAgentSpan(name, attributes, fn) {
|
|
99
|
+
try {
|
|
100
|
+
if (bootPromise)
|
|
101
|
+
await bootPromise;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
/* telemetry boot failure must not block the agent */
|
|
105
|
+
}
|
|
106
|
+
if (handle && typeof handle.runSpan === "function")
|
|
107
|
+
return handle.runSpan(name, attributes, fn);
|
|
108
|
+
return fn();
|
|
109
|
+
}
|
|
57
110
|
export async function shutdownObservability() {
|
|
58
111
|
const active = handle;
|
|
59
112
|
handle = undefined;
|
|
@@ -67,8 +120,13 @@ export function setObservabilityHandleForTests(next) {
|
|
|
67
120
|
bootPromise = Promise.resolve(next);
|
|
68
121
|
}
|
|
69
122
|
async function emitWhenReady(fn) {
|
|
70
|
-
|
|
71
|
-
|
|
123
|
+
try {
|
|
124
|
+
if (bootPromise)
|
|
125
|
+
await bootPromise;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
72
130
|
if (handle)
|
|
73
131
|
fn(handle);
|
|
74
132
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,4BAA4B,GAE7B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/observability/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional Langfuse Cloud tracing via the public ingestion API.
|
|
3
|
+
*
|
|
4
|
+
* Sentry Performance already owns the global OpenTelemetry TracerProvider
|
|
5
|
+
* (`@sentry/node` init). Langfuse is therefore a separate REST client: no
|
|
6
|
+
* second NodeSDK / TracerProvider is registered. When LANGFUSE_PUBLIC_KEY or
|
|
7
|
+
* LANGFUSE_SECRET_KEY is unset, every call is a no-op.
|
|
8
|
+
*/
|
|
9
|
+
import { DEFAULT_LANGFUSE_HOST } from "./config.js";
|
|
10
|
+
import type { LlmGenerationInput } from "./llm.js";
|
|
11
|
+
export { DEFAULT_LANGFUSE_HOST };
|
|
12
|
+
export interface LangfuseConfig {
|
|
13
|
+
publicKey: string;
|
|
14
|
+
secretKey: string;
|
|
15
|
+
host: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function readLangfuseConfig(env?: NodeJS.ProcessEnv): LangfuseConfig | undefined;
|
|
18
|
+
export interface LangfuseHandle {
|
|
19
|
+
captureGeneration(input: LlmGenerationInput, options: {
|
|
20
|
+
sessionId: string;
|
|
21
|
+
userId: string;
|
|
22
|
+
}): void;
|
|
23
|
+
flush(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare function createLangfuseHandle(config: LangfuseConfig, options?: {
|
|
26
|
+
fetchImpl?: typeof fetch;
|
|
27
|
+
}): LangfuseHandle;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional Langfuse Cloud tracing via the public ingestion API.
|
|
3
|
+
*
|
|
4
|
+
* Sentry Performance already owns the global OpenTelemetry TracerProvider
|
|
5
|
+
* (`@sentry/node` init). Langfuse is therefore a separate REST client: no
|
|
6
|
+
* second NodeSDK / TracerProvider is registered. When LANGFUSE_PUBLIC_KEY or
|
|
7
|
+
* LANGFUSE_SECRET_KEY is unset, every call is a no-op.
|
|
8
|
+
*/
|
|
9
|
+
import { PSYCLAW_VERSION } from "../branding.js";
|
|
10
|
+
import { DEFAULT_LANGFUSE_HOST } from "./config.js";
|
|
11
|
+
import { langfuseGenerationBody } from "./llm.js";
|
|
12
|
+
export { DEFAULT_LANGFUSE_HOST };
|
|
13
|
+
function trimEnv(value) {
|
|
14
|
+
const trimmed = value?.trim();
|
|
15
|
+
return trimmed ? trimmed : undefined;
|
|
16
|
+
}
|
|
17
|
+
export function readLangfuseConfig(env = process.env) {
|
|
18
|
+
const publicKey = trimEnv(env.LANGFUSE_PUBLIC_KEY);
|
|
19
|
+
const secretKey = trimEnv(env.LANGFUSE_SECRET_KEY);
|
|
20
|
+
if (!publicKey || !secretKey)
|
|
21
|
+
return undefined;
|
|
22
|
+
const host = (trimEnv(env.LANGFUSE_HOST) ?? trimEnv(env.LANGFUSE_BASE_URL) ?? DEFAULT_LANGFUSE_HOST)
|
|
23
|
+
.replace(/\/+$/, "");
|
|
24
|
+
return { publicKey, secretKey, host };
|
|
25
|
+
}
|
|
26
|
+
export function createLangfuseHandle(config, options = {}) {
|
|
27
|
+
const pending = new Set();
|
|
28
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
29
|
+
const authorization = `Basic ${Buffer.from(`${config.publicKey}:${config.secretKey}`).toString("base64")}`;
|
|
30
|
+
const enqueue = (batch) => {
|
|
31
|
+
const job = fetchImpl(`${config.host}/api/public/ingestion`, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: {
|
|
34
|
+
"content-type": "application/json",
|
|
35
|
+
authorization,
|
|
36
|
+
"x-langfuse-sdk-name": "psyclaw",
|
|
37
|
+
"x-langfuse-sdk-version": PSYCLAW_VERSION,
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify({
|
|
40
|
+
batch,
|
|
41
|
+
metadata: { batch_size: Array.isArray(batch) ? batch.length : 1, sdk_integration: "psyclaw" },
|
|
42
|
+
}),
|
|
43
|
+
}).then((response) => {
|
|
44
|
+
if (!response.ok)
|
|
45
|
+
return undefined;
|
|
46
|
+
return undefined;
|
|
47
|
+
}).catch(() => undefined).then(() => undefined);
|
|
48
|
+
pending.add(job);
|
|
49
|
+
void job.finally(() => pending.delete(job));
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
captureGeneration(input, ids) {
|
|
53
|
+
try {
|
|
54
|
+
enqueue(langfuseGenerationBody(input, ids).ingest.batch);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
/* never break the agent on telemetry */
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
async flush() {
|
|
61
|
+
await Promise.allSettled([...pending]);
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=langfuse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"langfuse.js","sourceRoot":"","sources":["../../../src/observability/langfuse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostHog LLM analytics + Langfuse generation payloads for the Pi stack.
|
|
3
|
+
*
|
|
4
|
+
* PsyClaw talks to models through `@earendil-works/pi-ai` / pi-coding-agent,
|
|
5
|
+
* not OpenAI/LangChain SDKs. Official PostHog guidance for that harness is
|
|
6
|
+
* either `@posthog/pi` or manual `$ai_generation` capture. We capture manually
|
|
7
|
+
* so events stay behind PsyClaw telemetry consent, share the CLI/panel
|
|
8
|
+
* distinct_id, and never include prompts, completions, or tool I/O.
|
|
9
|
+
*/
|
|
10
|
+
export interface LlmUsage {
|
|
11
|
+
input?: number;
|
|
12
|
+
output?: number;
|
|
13
|
+
cacheRead?: number;
|
|
14
|
+
cacheWrite?: number;
|
|
15
|
+
cost?: {
|
|
16
|
+
total?: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface LlmGenerationInput {
|
|
20
|
+
provider?: string;
|
|
21
|
+
model?: string;
|
|
22
|
+
usage?: LlmUsage;
|
|
23
|
+
latencyMs?: number;
|
|
24
|
+
error?: boolean;
|
|
25
|
+
errorName?: string;
|
|
26
|
+
httpStatus?: number;
|
|
27
|
+
stream?: boolean;
|
|
28
|
+
traceId?: string;
|
|
29
|
+
sessionId?: string;
|
|
30
|
+
spanName?: string;
|
|
31
|
+
surface?: string;
|
|
32
|
+
}
|
|
33
|
+
export type PosthogAiPropertyValue = string | number | boolean;
|
|
34
|
+
export declare function usageFromUnknown(value: unknown): LlmUsage | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Pull token usage out of a Pi session / RPC event without reading message
|
|
37
|
+
* content. Matches the shapes already used by the panel usage aggregator.
|
|
38
|
+
*/
|
|
39
|
+
export declare function extractPiGeneration(entry: unknown): LlmGenerationInput | undefined;
|
|
40
|
+
export declare function lastPiGeneration(entries: readonly unknown[]): LlmGenerationInput | undefined;
|
|
41
|
+
/** PostHog `$ai_generation` properties. Prompt/completion fields are omitted on purpose. */
|
|
42
|
+
export declare function posthogAiGenerationProperties(input: LlmGenerationInput, options: {
|
|
43
|
+
distinctId: string;
|
|
44
|
+
sessionId: string;
|
|
45
|
+
}): Record<string, PosthogAiPropertyValue>;
|
|
46
|
+
export declare function langfuseGenerationBody(input: LlmGenerationInput, options: {
|
|
47
|
+
sessionId: string;
|
|
48
|
+
userId: string;
|
|
49
|
+
}): {
|
|
50
|
+
traceId: string;
|
|
51
|
+
observationId: `${string}-${string}-${string}-${string}-${string}`;
|
|
52
|
+
started: string;
|
|
53
|
+
ended: string;
|
|
54
|
+
ingest: {
|
|
55
|
+
batch: ({
|
|
56
|
+
id: `${string}-${string}-${string}-${string}-${string}`;
|
|
57
|
+
timestamp: string;
|
|
58
|
+
type: string;
|
|
59
|
+
body: {
|
|
60
|
+
id: string;
|
|
61
|
+
timestamp: string;
|
|
62
|
+
name: string;
|
|
63
|
+
sessionId: string;
|
|
64
|
+
userId: string;
|
|
65
|
+
metadata: {
|
|
66
|
+
provider: string;
|
|
67
|
+
surface: string;
|
|
68
|
+
privacyMode: boolean;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
} | {
|
|
72
|
+
id: `${string}-${string}-${string}-${string}-${string}`;
|
|
73
|
+
timestamp: string;
|
|
74
|
+
type: string;
|
|
75
|
+
body: {
|
|
76
|
+
metadata: {
|
|
77
|
+
provider: string;
|
|
78
|
+
surface: string;
|
|
79
|
+
privacyMode: boolean;
|
|
80
|
+
};
|
|
81
|
+
statusMessage?: string;
|
|
82
|
+
level: string;
|
|
83
|
+
costDetails?: {
|
|
84
|
+
total: number;
|
|
85
|
+
};
|
|
86
|
+
id: `${string}-${string}-${string}-${string}-${string}`;
|
|
87
|
+
traceId: string;
|
|
88
|
+
name: string;
|
|
89
|
+
startTime: string;
|
|
90
|
+
endTime: string;
|
|
91
|
+
model: string;
|
|
92
|
+
usageDetails: {
|
|
93
|
+
input: number;
|
|
94
|
+
output: number;
|
|
95
|
+
total: number;
|
|
96
|
+
cache_read: number;
|
|
97
|
+
cache_write: number;
|
|
98
|
+
};
|
|
99
|
+
timestamp?: never;
|
|
100
|
+
sessionId?: never;
|
|
101
|
+
userId?: never;
|
|
102
|
+
};
|
|
103
|
+
})[];
|
|
104
|
+
};
|
|
105
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostHog LLM analytics + Langfuse generation payloads for the Pi stack.
|
|
3
|
+
*
|
|
4
|
+
* PsyClaw talks to models through `@earendil-works/pi-ai` / pi-coding-agent,
|
|
5
|
+
* not OpenAI/LangChain SDKs. Official PostHog guidance for that harness is
|
|
6
|
+
* either `@posthog/pi` or manual `$ai_generation` capture. We capture manually
|
|
7
|
+
* so events stay behind PsyClaw telemetry consent, share the CLI/panel
|
|
8
|
+
* distinct_id, and never include prompts, completions, or tool I/O.
|
|
9
|
+
*/
|
|
10
|
+
import { randomUUID } from "node:crypto";
|
|
11
|
+
import { estimateUsageCost } from "../core/pricing.js";
|
|
12
|
+
function finiteNumber(value) {
|
|
13
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
14
|
+
}
|
|
15
|
+
export function usageFromUnknown(value) {
|
|
16
|
+
if (!value || typeof value !== "object")
|
|
17
|
+
return undefined;
|
|
18
|
+
const record = value;
|
|
19
|
+
if (finiteNumber(record.input) === undefined
|
|
20
|
+
&& finiteNumber(record.output) === undefined
|
|
21
|
+
&& finiteNumber(record.cacheRead) === undefined) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
return record;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Pull token usage out of a Pi session / RPC event without reading message
|
|
28
|
+
* content. Matches the shapes already used by the panel usage aggregator.
|
|
29
|
+
*/
|
|
30
|
+
export function extractPiGeneration(entry) {
|
|
31
|
+
if (!entry || typeof entry !== "object")
|
|
32
|
+
return undefined;
|
|
33
|
+
const record = entry;
|
|
34
|
+
if (record.type === "message" && record.message && typeof record.message === "object") {
|
|
35
|
+
const message = record.message;
|
|
36
|
+
const usage = usageFromUnknown(message.usage);
|
|
37
|
+
if (!usage)
|
|
38
|
+
return undefined;
|
|
39
|
+
const provider = typeof message.provider === "string" ? message.provider : undefined;
|
|
40
|
+
const model = typeof message.responseModel === "string"
|
|
41
|
+
? message.responseModel
|
|
42
|
+
: typeof message.model === "string"
|
|
43
|
+
? message.model
|
|
44
|
+
: undefined;
|
|
45
|
+
const error = Boolean(message.errorMessage) || Boolean(message.error);
|
|
46
|
+
return {
|
|
47
|
+
...(provider === undefined ? {} : { provider }),
|
|
48
|
+
...(model === undefined ? {} : { model }),
|
|
49
|
+
usage,
|
|
50
|
+
error,
|
|
51
|
+
spanName: "pi-message",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if ((record.type === "agent_end" || record.type === "agent_settled") && record.message && typeof record.message === "object") {
|
|
55
|
+
return extractPiGeneration({ type: "message", message: record.message });
|
|
56
|
+
}
|
|
57
|
+
if ((record.type === "branch_summary" || record.type === "compaction") && record.usage) {
|
|
58
|
+
const usage = usageFromUnknown(record.usage);
|
|
59
|
+
if (!usage)
|
|
60
|
+
return undefined;
|
|
61
|
+
return { provider: "summaries", model: "summaries", usage, spanName: String(record.type) };
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
export function lastPiGeneration(entries) {
|
|
66
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
67
|
+
const found = extractPiGeneration(entries[index]);
|
|
68
|
+
if (found)
|
|
69
|
+
return found;
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
/** PostHog `$ai_generation` properties. Prompt/completion fields are omitted on purpose. */
|
|
74
|
+
export function posthogAiGenerationProperties(input, options) {
|
|
75
|
+
const provider = input.provider?.trim().slice(0, 80) || "unknown";
|
|
76
|
+
const model = input.model?.trim().slice(0, 120) || "unknown";
|
|
77
|
+
const usage = input.usage ?? {};
|
|
78
|
+
const inputTokens = finiteNumber(usage.input) ?? 0;
|
|
79
|
+
const outputTokens = finiteNumber(usage.output) ?? 0;
|
|
80
|
+
const cacheRead = finiteNumber(usage.cacheRead) ?? 0;
|
|
81
|
+
const cacheWrite = finiteNumber(usage.cacheWrite) ?? 0;
|
|
82
|
+
const reportedCost = finiteNumber(usage.cost?.total);
|
|
83
|
+
const estimatedCost = estimateUsageCost(usage, provider, model);
|
|
84
|
+
const latencySeconds = finiteNumber(input.latencyMs) !== undefined
|
|
85
|
+
? Number((input.latencyMs / 1000).toFixed(4))
|
|
86
|
+
: undefined;
|
|
87
|
+
const properties = {
|
|
88
|
+
$ai_trace_id: (input.traceId ?? randomUUID()).slice(0, 80),
|
|
89
|
+
$ai_session_id: (input.sessionId ?? options.sessionId).slice(0, 80),
|
|
90
|
+
$ai_span_name: (input.spanName ?? "pi-generation").slice(0, 80),
|
|
91
|
+
$ai_model: model,
|
|
92
|
+
$ai_provider: provider,
|
|
93
|
+
$ai_input_tokens: inputTokens,
|
|
94
|
+
$ai_output_tokens: outputTokens,
|
|
95
|
+
$ai_cache_read_tokens: cacheRead,
|
|
96
|
+
$ai_cache_write_tokens: cacheWrite,
|
|
97
|
+
$ai_http_status: input.httpStatus ?? (input.error ? 500 : 200),
|
|
98
|
+
$ai_is_error: input.error === true,
|
|
99
|
+
$ai_stream: input.stream === true,
|
|
100
|
+
$ai_privacy_mode: true,
|
|
101
|
+
surface: (input.surface ?? "cli").slice(0, 32),
|
|
102
|
+
$process_person_profile: false,
|
|
103
|
+
};
|
|
104
|
+
if (latencySeconds !== undefined)
|
|
105
|
+
properties.$ai_latency = latencySeconds;
|
|
106
|
+
if (reportedCost !== undefined)
|
|
107
|
+
properties.$ai_total_cost_usd = reportedCost;
|
|
108
|
+
else if (estimatedCost > 0)
|
|
109
|
+
properties.$ai_total_cost_usd = estimatedCost;
|
|
110
|
+
if (input.errorName)
|
|
111
|
+
properties.$ai_error = input.errorName.slice(0, 80);
|
|
112
|
+
return properties;
|
|
113
|
+
}
|
|
114
|
+
export function langfuseGenerationBody(input, options) {
|
|
115
|
+
const provider = input.provider?.trim().slice(0, 80) || "unknown";
|
|
116
|
+
const model = input.model?.trim().slice(0, 120) || "unknown";
|
|
117
|
+
const usage = input.usage ?? {};
|
|
118
|
+
const inputTokens = finiteNumber(usage.input) ?? 0;
|
|
119
|
+
const outputTokens = finiteNumber(usage.output) ?? 0;
|
|
120
|
+
const cacheRead = finiteNumber(usage.cacheRead) ?? 0;
|
|
121
|
+
const cacheWrite = finiteNumber(usage.cacheWrite) ?? 0;
|
|
122
|
+
const started = new Date(Date.now() - (finiteNumber(input.latencyMs) ?? 0)).toISOString();
|
|
123
|
+
const ended = new Date().toISOString();
|
|
124
|
+
const traceId = input.traceId ?? randomUUID();
|
|
125
|
+
const observationId = randomUUID();
|
|
126
|
+
const reportedCost = finiteNumber(usage.cost?.total);
|
|
127
|
+
const estimatedCost = estimateUsageCost(usage, provider, model);
|
|
128
|
+
const cost = reportedCost ?? (estimatedCost > 0 ? estimatedCost : undefined);
|
|
129
|
+
return {
|
|
130
|
+
traceId,
|
|
131
|
+
observationId,
|
|
132
|
+
started,
|
|
133
|
+
ended,
|
|
134
|
+
ingest: {
|
|
135
|
+
batch: [
|
|
136
|
+
{
|
|
137
|
+
id: randomUUID(),
|
|
138
|
+
timestamp: ended,
|
|
139
|
+
type: "trace-create",
|
|
140
|
+
body: {
|
|
141
|
+
id: traceId,
|
|
142
|
+
timestamp: started,
|
|
143
|
+
name: input.spanName ?? "pi-generation",
|
|
144
|
+
sessionId: options.sessionId,
|
|
145
|
+
userId: options.userId,
|
|
146
|
+
metadata: {
|
|
147
|
+
provider,
|
|
148
|
+
surface: input.surface ?? "cli",
|
|
149
|
+
privacyMode: true,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: randomUUID(),
|
|
155
|
+
timestamp: ended,
|
|
156
|
+
type: "generation-create",
|
|
157
|
+
body: {
|
|
158
|
+
id: observationId,
|
|
159
|
+
traceId,
|
|
160
|
+
name: input.spanName ?? "pi-generation",
|
|
161
|
+
startTime: started,
|
|
162
|
+
endTime: ended,
|
|
163
|
+
model,
|
|
164
|
+
usageDetails: {
|
|
165
|
+
input: inputTokens,
|
|
166
|
+
output: outputTokens,
|
|
167
|
+
total: inputTokens + outputTokens + cacheRead + cacheWrite,
|
|
168
|
+
cache_read: cacheRead,
|
|
169
|
+
cache_write: cacheWrite,
|
|
170
|
+
},
|
|
171
|
+
...(cost === undefined ? {} : { costDetails: { total: cost } }),
|
|
172
|
+
level: input.error ? "ERROR" : "DEFAULT",
|
|
173
|
+
...(input.errorName === undefined ? {} : { statusMessage: input.errorName.slice(0, 200) }),
|
|
174
|
+
metadata: {
|
|
175
|
+
provider,
|
|
176
|
+
surface: input.surface ?? "cli",
|
|
177
|
+
privacyMode: true,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../../src/observability/llm.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Loaded only after telemetry is confirmed enabled. Importing this file will
|
|
3
3
|
* pull in Sentry/PostHog; callers must keep that behind the preference gate.
|
|
4
|
+
*
|
|
5
|
+
* Init order (documented in docs/telemetry.md):
|
|
6
|
+
* 1. Sentry.init — owns the global OpenTelemetry TracerProvider for Performance.
|
|
7
|
+
* 2. PostHog Node client — product events + `$ai_generation`.
|
|
8
|
+
* 3. Langfuse REST ingestion — optional, isolated from OTel (no second TracerProvider).
|
|
4
9
|
*/
|
|
5
10
|
import type { AgentEventPropertyValue, NodeObservabilityConfig } from "./config.js";
|
|
11
|
+
import { type LlmGenerationInput } from "./llm.js";
|
|
6
12
|
export interface ObservabilityHandle {
|
|
13
|
+
readonly distinctId?: string;
|
|
7
14
|
captureEvent(name: string, properties: Record<string, AgentEventPropertyValue>): void;
|
|
8
15
|
captureError(error: unknown, context?: Record<string, string>): void;
|
|
16
|
+
captureLlmGeneration?(input: LlmGenerationInput): void;
|
|
17
|
+
runSpan?<T>(name: string, attributes: Record<string, string>, fn: () => Promise<T>): Promise<T>;
|
|
9
18
|
flush(): Promise<void>;
|
|
10
19
|
}
|
|
11
20
|
export declare function bootNodeSdks(config: NodeObservabilityConfig): Promise<ObservabilityHandle>;
|