@friskai/frisk-js 0.3.0 → 0.3.2

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.
Files changed (32) hide show
  1. package/dist/adapters/langchain/frisk-callback-handler.d.ts +80 -3
  2. package/dist/adapters/langchain/frisk-callback-handler.d.ts.map +1 -1
  3. package/dist/adapters/langchain/index.js +564 -238
  4. package/dist/adapters/langchain/index.js.map +1 -453
  5. package/dist/core/frisk-session.d.ts +43 -10
  6. package/dist/core/frisk-session.d.ts.map +1 -1
  7. package/dist/core/llm-reasoning/extractLlmReasoning.d.ts +8 -0
  8. package/dist/core/llm-reasoning/extractLlmReasoning.d.ts.map +1 -0
  9. package/dist/core/spans/frisk-span.d.ts +38 -0
  10. package/dist/core/spans/frisk-span.d.ts.map +1 -0
  11. package/dist/core/spans/index.d.ts +7 -0
  12. package/dist/core/spans/index.d.ts.map +1 -0
  13. package/dist/core/spans/llm-call-span.d.ts +23 -0
  14. package/dist/core/spans/llm-call-span.d.ts.map +1 -0
  15. package/dist/core/spans/operation-span.d.ts +13 -0
  16. package/dist/core/spans/operation-span.d.ts.map +1 -0
  17. package/dist/core/spans/session-span.d.ts +20 -0
  18. package/dist/core/spans/session-span.d.ts.map +1 -0
  19. package/dist/core/spans/tool-call-decision-span.d.ts +27 -0
  20. package/dist/core/spans/tool-call-decision-span.d.ts.map +1 -0
  21. package/dist/core/spans/tool-call-observation-span.d.ts +28 -0
  22. package/dist/core/spans/tool-call-observation-span.d.ts.map +1 -0
  23. package/dist/generated/sdk-meta.d.ts +1 -1
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +318 -171
  27. package/dist/index.js.map +1 -439
  28. package/dist/telemetry/constants.d.ts +24 -0
  29. package/dist/telemetry/constants.d.ts.map +1 -1
  30. package/package.json +2 -1
  31. package/dist/core/tool-call-span.d.ts +0 -102
  32. package/dist/core/tool-call-span.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -43602,13 +43602,6 @@ class MissingToolPoliciesExtensionError extends FriskError {
43602
43602
  }
43603
43603
  }
43604
43604
 
43605
- class ToolCallSpanNotInitializedError extends Error {
43606
- constructor(message = "Tool call span has not been initialized. Call enter() first.") {
43607
- super(message);
43608
- this.name = "ToolCallSpanNotInitializedError";
43609
- }
43610
- }
43611
-
43612
43605
  // src/logging/console-logger.ts
43613
43606
  var LEVEL_PRIORITY = {
43614
43607
  error: 0,
@@ -44102,7 +44095,18 @@ var TRACER_NAME = "frisk_js_sdk";
44102
44095
  var TRACER_VERSION = "0.1.0";
44103
44096
  var SPAN_NAME_DECIDE_TOOL_CALL = "frisk.tool_call.decide";
44104
44097
  var SPAN_NAME_OBSERVE_TOOL_CALL = "frisk.tool_call.observation";
44098
+ var SPAN_NAME_LLM_CALL = "frisk.llm_call";
44099
+ var SPAN_NAME_OPERATION = "frisk.operation";
44105
44100
  var SPAN_NAME_FRISK_SESSION = "frisk.session";
44101
+ var ATTRIBUTE_NAME_LLM_CALL_SPAN_ID = "frisk.tool_call.llm_call_span_id";
44102
+ var ATTRIBUTE_NAME_LLM_CALL_PROMPTS_JSON = "frisk.llm_call.prompts.json";
44103
+ var ATTRIBUTE_NAME_LLM_CALL_RESPONSES_JSON = "frisk.llm_call.responses.json";
44104
+ var ATTRIBUTE_NAME_LLM_CALL_TOOL_CALLS_JSON = "frisk.llm_call.tool_calls.json";
44105
+ var ATTRIBUTE_NAME_MODEL_NAME = "frisk.model.name";
44106
+ var ATTRIBUTE_NAME_MODEL_PROVIDER = "frisk.model.provider";
44107
+ var ATTRIBUTE_NAME_TOKEN_USAGE_INPUT_TOKENS = "frisk.token_usage.input_tokens";
44108
+ var ATTRIBUTE_NAME_TOKEN_USAGE_OUTPUT_TOKENS = "frisk.token_usage.output_tokens";
44109
+ var ATTRIBUTE_NAME_TOKEN_USAGE_TOTAL_TOKENS = "frisk.token_usage.total_tokens";
44106
44110
  var ATTRIBUTE_NAME_SESSION_PROMPT = "frisk.session.prompt";
44107
44111
  var ATTRIBUTE_NAME_SESSION_ID = "frisk.session.id";
44108
44112
  var ATTRIBUTE_NAME_REMOTE_SESSION_ID = "frisk.session.remote_id";
@@ -48466,6 +48470,18 @@ var llmReasoningZodShape = {
48466
48470
  [LLM_REASONING_ARG_NAME]: string2().describe(LLM_REASONING_ARG_DESCRIPTION)
48467
48471
  };
48468
48472
 
48473
+ // src/core/llm-reasoning/extractLlmReasoning.ts
48474
+ function extractLlmReasoning(toolArgs) {
48475
+ if (typeof toolArgs !== "object" || toolArgs === null || Array.isArray(toolArgs)) {
48476
+ return null;
48477
+ }
48478
+ const rawReasoning = toolArgs[LLM_REASONING_ARG_NAME];
48479
+ if (rawReasoning === null || rawReasoning === undefined) {
48480
+ return null;
48481
+ }
48482
+ return String(rawReasoning);
48483
+ }
48484
+
48469
48485
  // src/core/llm-reasoning/removeLlmReasoningArg.ts
48470
48486
  function removeLlmReasoningArg(input) {
48471
48487
  if (!(LLM_REASONING_ARG_NAME in input)) {
@@ -48511,136 +48527,186 @@ class SessionRegistry {
48511
48527
  }
48512
48528
  }
48513
48529
 
48514
- // src/core/tool-call-span.ts
48530
+ // src/core/spans/frisk-span.ts
48515
48531
  var import_api = __toESM(require_src4(), 1);
48516
48532
 
48517
- // src/core/redaction-options.ts
48518
- function resolveRedactionOptions(options) {
48519
- return {
48520
- redactToolArgs: options?.redactToolArgs ?? false,
48521
- redactAgentState: options?.redactAgentState ?? false
48522
- };
48523
- }
48524
-
48525
- // src/core/tool-call-span.ts
48526
- class ToolCallSpan {
48527
- adapter;
48528
- toolCall;
48529
- friskToolId;
48530
- agentState;
48531
- parent;
48532
- tracer;
48533
- redaction;
48534
- _span = null;
48535
- _traceContextCarrier = null;
48536
- sessionId;
48537
- friskToolVersionId;
48533
+ class FriskSpan {
48534
+ _spanName;
48535
+ _attributeFields;
48536
+ _otelSpan;
48537
+ _attributes = {};
48538
+ _ended = false;
48538
48539
  constructor({
48539
- sessionId,
48540
- adapter,
48541
- toolCall,
48542
- friskToolId,
48543
- friskToolVersionId,
48544
- agentState,
48545
- parent,
48546
48540
  tracer,
48547
- redact
48541
+ parent,
48542
+ spanName,
48543
+ attributeFields
48548
48544
  }) {
48549
- this.sessionId = sessionId;
48550
- this.adapter = adapter;
48551
- this.toolCall = toolCall;
48552
- this.friskToolId = friskToolId ?? null;
48553
- this.friskToolVersionId = friskToolVersionId ?? null;
48554
- this.agentState = agentState;
48555
- this.parent = parent;
48556
- this.tracer = tracer;
48557
- this.redaction = resolveRedactionOptions(redact);
48545
+ this._spanName = spanName;
48546
+ this._attributeFields = attributeFields;
48547
+ const parentContext = parent ? import_api.trace.setSpan(import_api.context.active(), parent.otelSpan) : import_api.context.active();
48548
+ this._otelSpan = tracer.startSpan(this._spanName, undefined, parentContext);
48558
48549
  }
48559
- get span() {
48560
- if (!this._span) {
48561
- throw new ToolCallSpanNotInitializedError;
48562
- }
48563
- return this._span;
48550
+ get otelSpan() {
48551
+ return this._otelSpan;
48564
48552
  }
48565
- get traceContextCarrier() {
48566
- return this._traceContextCarrier;
48553
+ get spanId() {
48554
+ return this._otelSpan.spanContext().spanId;
48567
48555
  }
48568
- run(callback) {
48569
- this.enter();
48570
- try {
48571
- return callback(this);
48572
- } finally {
48573
- this.exit();
48556
+ setAttribute(field, value) {
48557
+ this.setAttributesByField({ [field]: value });
48558
+ }
48559
+ getAttribute(field) {
48560
+ return this._attributes[this.constantFor(field)];
48561
+ }
48562
+ end() {
48563
+ if (this._ended) {
48564
+ return;
48574
48565
  }
48566
+ this._ended = true;
48567
+ this._otelSpan.end();
48575
48568
  }
48576
- async runAsync(callback) {
48577
- this.enter();
48578
- try {
48579
- return await callback(this);
48580
- } finally {
48581
- this.exit();
48569
+ setAttributesByField(values) {
48570
+ for (const [field, value] of Object.entries(values)) {
48571
+ const constant = this.constantFor(field);
48572
+ if (value === null || value === undefined) {
48573
+ continue;
48574
+ }
48575
+ this._attributes[constant] = value;
48576
+ this._otelSpan.setAttribute(constant, value);
48582
48577
  }
48583
48578
  }
48584
- setAttribute(key, value) {
48585
- this.span.setAttribute(key, value);
48579
+ constantFor(field) {
48580
+ const constant = this._attributeFields[field];
48581
+ if (constant === undefined) {
48582
+ throw new Error(`Unknown attribute '${field}' for ${this.constructor.name}`);
48583
+ }
48584
+ return constant;
48586
48585
  }
48587
- setAttributes(attributes) {
48588
- this.span.setAttributes(attributes);
48586
+ }
48587
+ // src/core/spans/llm-call-span.ts
48588
+ var FIELDS = {
48589
+ sessionId: ATTRIBUTE_NAME_SESSION_ID,
48590
+ promptsJson: ATTRIBUTE_NAME_LLM_CALL_PROMPTS_JSON,
48591
+ responsesJson: ATTRIBUTE_NAME_LLM_CALL_RESPONSES_JSON,
48592
+ toolCallsJson: ATTRIBUTE_NAME_LLM_CALL_TOOL_CALLS_JSON,
48593
+ modelName: ATTRIBUTE_NAME_MODEL_NAME,
48594
+ modelProvider: ATTRIBUTE_NAME_MODEL_PROVIDER,
48595
+ inputTokens: ATTRIBUTE_NAME_TOKEN_USAGE_INPUT_TOKENS,
48596
+ outputTokens: ATTRIBUTE_NAME_TOKEN_USAGE_OUTPUT_TOKENS,
48597
+ totalTokens: ATTRIBUTE_NAME_TOKEN_USAGE_TOTAL_TOKENS,
48598
+ errorType: ATTRIBUTE_NAME_ERROR_TYPE,
48599
+ errorMessage: ATTRIBUTE_NAME_ERROR_MESSAGE
48600
+ };
48601
+
48602
+ class LlmCallSpan extends FriskSpan {
48603
+ constructor(args) {
48604
+ super({ ...args, spanName: SPAN_NAME_LLM_CALL, attributeFields: FIELDS });
48589
48605
  }
48590
- saveResult(decision) {
48591
- if (!this.span) {
48592
- return;
48593
- }
48594
- this.setAttributes({
48595
- [ATTRIBUTE_NAME_DECISION_OUTCOME]: decision.outcome,
48596
- [ATTRIBUTE_NAME_DECISION_MATCHED_RULE_COUNT]: Number(decision.rulesMatchedCount)
48606
+ setAttributes(values) {
48607
+ this.setAttributesByField(values);
48608
+ }
48609
+ }
48610
+ // src/core/spans/operation-span.ts
48611
+ var FIELDS2 = {
48612
+ sessionId: ATTRIBUTE_NAME_SESSION_ID
48613
+ };
48614
+
48615
+ class OperationSpan extends FriskSpan {
48616
+ constructor(args) {
48617
+ super({ ...args, spanName: SPAN_NAME_OPERATION, attributeFields: FIELDS2 });
48618
+ }
48619
+ setAttributes(values) {
48620
+ this.setAttributesByField(values);
48621
+ }
48622
+ }
48623
+ // src/core/spans/session-span.ts
48624
+ var FIELDS3 = {
48625
+ sessionId: ATTRIBUTE_NAME_SESSION_ID,
48626
+ remoteSessionId: ATTRIBUTE_NAME_REMOTE_SESSION_ID,
48627
+ prompt: ATTRIBUTE_NAME_SESSION_PROMPT,
48628
+ toolCallCount: ATTRIBUTE_NAME_TOOL_CALL_COUNT,
48629
+ toolCallErrorCount: ATTRIBUTE_NAME_TOOL_CALL_ERROR_COUNT,
48630
+ inputTokens: ATTRIBUTE_NAME_TOKEN_USAGE_INPUT_TOKENS,
48631
+ outputTokens: ATTRIBUTE_NAME_TOKEN_USAGE_OUTPUT_TOKENS,
48632
+ totalTokens: ATTRIBUTE_NAME_TOKEN_USAGE_TOTAL_TOKENS
48633
+ };
48634
+
48635
+ class SessionSpan extends FriskSpan {
48636
+ constructor(args) {
48637
+ super({
48638
+ ...args,
48639
+ spanName: SPAN_NAME_FRISK_SESSION,
48640
+ attributeFields: FIELDS3
48597
48641
  });
48598
- if (decision.reason) {
48599
- this.setAttribute(ATTRIBUTE_NAME_DECISION_REASON, decision.reason);
48600
- }
48601
48642
  }
48602
- saveError(error) {
48603
- if (!this.span) {
48604
- return;
48605
- }
48606
- const errorMessage = error instanceof Error ? error.message : String(error);
48607
- const errorType = error instanceof Error ? error.constructor.name : typeof error;
48608
- this.setAttributes({
48609
- [ATTRIBUTE_NAME_ERROR_TYPE]: errorType,
48610
- [ATTRIBUTE_NAME_ERROR_MESSAGE]: errorMessage
48643
+ setAttributes(values) {
48644
+ this.setAttributesByField(values);
48645
+ }
48646
+ }
48647
+ // src/core/spans/tool-call-decision-span.ts
48648
+ var FIELDS4 = {
48649
+ sessionId: ATTRIBUTE_NAME_SESSION_ID,
48650
+ toolName: ATTRIBUTE_NAME_TOOL_NAME,
48651
+ toolCallId: ATTRIBUTE_NAME_TOOL_CALL_ID,
48652
+ toolArgsJson: ATTRIBUTE_NAME_TOOL_ARGS_JSON,
48653
+ toolArgsRedactedPathsJson: ATTRIBUTE_NAME_TOOL_ARGS_REDACTED_PATHS_JSON,
48654
+ agentStateJson: ATTRIBUTE_NAME_AGENT_STATE_JSON,
48655
+ agentStateRedactedPathsJson: ATTRIBUTE_NAME_AGENT_STATE_REDACTED_PATHS_JSON,
48656
+ friskToolId: ATTRIBUTE_NAME_FRISK_TOOL_ID,
48657
+ friskToolVersionId: ATTRIBUTE_NAME_FRISK_TOOL_VERSION_ID,
48658
+ llmReasoning: ATTRIBUTE_NAME_LLM_REASONING,
48659
+ decisionOutcome: ATTRIBUTE_NAME_DECISION_OUTCOME,
48660
+ decisionMatchedRuleCount: ATTRIBUTE_NAME_DECISION_MATCHED_RULE_COUNT,
48661
+ decisionReason: ATTRIBUTE_NAME_DECISION_REASON,
48662
+ errorType: ATTRIBUTE_NAME_ERROR_TYPE,
48663
+ errorMessage: ATTRIBUTE_NAME_ERROR_MESSAGE
48664
+ };
48665
+
48666
+ class ToolCallDecisionSpan extends FriskSpan {
48667
+ constructor(args) {
48668
+ super({
48669
+ ...args,
48670
+ spanName: SPAN_NAME_DECIDE_TOOL_CALL,
48671
+ attributeFields: FIELDS4
48611
48672
  });
48612
48673
  }
48613
- enter() {
48614
- const parentContext = this.parent ? import_api.trace.setSpan(import_api.context.active(), this.parent) : import_api.context.active();
48615
- const redactedToolArgsResult = this.adapter.serializeToolArgs(removeLlmReasoningArg(this.toolCall.args), { redact: this.redaction.redactToolArgs });
48616
- const redactedAgentStateResult = this.adapter.serializeAgentState(this.agentState, { redact: this.redaction.redactAgentState });
48617
- this._span = this.tracer.startSpan(SPAN_NAME_DECIDE_TOOL_CALL, {
48618
- attributes: {
48619
- [ATTRIBUTE_NAME_SESSION_ID]: this.sessionId,
48620
- [ATTRIBUTE_NAME_TOOL_NAME]: this.toolCall.name,
48621
- ...this.friskToolId !== null ? { [ATTRIBUTE_NAME_FRISK_TOOL_ID]: this.friskToolId } : {},
48622
- ...this.friskToolVersionId !== null ? {
48623
- [ATTRIBUTE_NAME_FRISK_TOOL_VERSION_ID]: this.friskToolVersionId
48624
- } : {},
48625
- [ATTRIBUTE_NAME_TOOL_CALL_ID]: this.toolCall.id,
48626
- [ATTRIBUTE_NAME_TOOL_ARGS_JSON]: redactedToolArgsResult.value ?? "",
48627
- [ATTRIBUTE_NAME_TOOL_ARGS_REDACTED_PATHS_JSON]: JSON.stringify(redactedToolArgsResult.redactedPaths),
48628
- [ATTRIBUTE_NAME_AGENT_STATE_JSON]: redactedAgentStateResult.value ?? "",
48629
- [ATTRIBUTE_NAME_AGENT_STATE_REDACTED_PATHS_JSON]: JSON.stringify(redactedAgentStateResult.redactedPaths)
48630
- }
48631
- }, parentContext);
48632
- this._traceContextCarrier = {};
48633
- const spanContext = import_api.trace.setSpan(import_api.context.active(), this.span);
48634
- import_api.propagation.inject(spanContext, this._traceContextCarrier);
48635
- }
48636
- exit() {
48637
- if (!this.span) {
48638
- return;
48639
- }
48640
- this.span.end();
48674
+ setAttributes(values) {
48675
+ this.setAttributesByField(values);
48641
48676
  }
48642
48677
  }
48678
+ // src/core/spans/tool-call-observation-span.ts
48679
+ var FIELDS5 = {
48680
+ sessionId: ATTRIBUTE_NAME_SESSION_ID,
48681
+ toolName: ATTRIBUTE_NAME_TOOL_NAME,
48682
+ toolCallId: ATTRIBUTE_NAME_TOOL_CALL_ID,
48683
+ toolArgsJson: ATTRIBUTE_NAME_TOOL_ARGS_JSON,
48684
+ toolArgsRedactedPathsJson: ATTRIBUTE_NAME_TOOL_ARGS_REDACTED_PATHS_JSON,
48685
+ agentStateJson: ATTRIBUTE_NAME_AGENT_STATE_JSON,
48686
+ agentStateRedactedPathsJson: ATTRIBUTE_NAME_AGENT_STATE_REDACTED_PATHS_JSON,
48687
+ toolCallSequenceNumber: ATTRIBUTE_NAME_TOOL_CALL_SEQUENCE_NUMBER,
48688
+ friskToolId: ATTRIBUTE_NAME_FRISK_TOOL_ID,
48689
+ friskToolVersionId: ATTRIBUTE_NAME_FRISK_TOOL_VERSION_ID,
48690
+ llmReasoning: ATTRIBUTE_NAME_LLM_REASONING,
48691
+ isSuccess: ATTRIBUTE_NAME_TOOL_CALL_IS_SUCCESS,
48692
+ isError: ATTRIBUTE_NAME_TOOL_CALL_IS_ERROR,
48693
+ errorMessage: ATTRIBUTE_NAME_ERROR_MESSAGE,
48694
+ errorType: ATTRIBUTE_NAME_ERROR_TYPE,
48695
+ llmCallSpanId: ATTRIBUTE_NAME_LLM_CALL_SPAN_ID
48696
+ };
48643
48697
 
48698
+ class ToolCallObservationSpan extends FriskSpan {
48699
+ constructor(args) {
48700
+ super({
48701
+ ...args,
48702
+ spanName: SPAN_NAME_OBSERVE_TOOL_CALL,
48703
+ attributeFields: FIELDS5
48704
+ });
48705
+ }
48706
+ setAttributes(values) {
48707
+ this.setAttributesByField(values);
48708
+ }
48709
+ }
48644
48710
  // src/core/types.ts
48645
48711
  var DecisionOutcome;
48646
48712
  ((DecisionOutcome2) => {
@@ -48664,6 +48730,9 @@ class FriskSession {
48664
48730
  toolCallSequenceNumber = 0;
48665
48731
  toolCallSequenceGenerator = this.createToolCallSequenceGenerator();
48666
48732
  toolCallErrorCount = 0;
48733
+ tokenUsageInput = 0;
48734
+ tokenUsageOutput = 0;
48735
+ tokenUsageTotal = 0;
48667
48736
  constructor({ frisk, redact, tracer, logging }) {
48668
48737
  const sessionId = this.constructor.generateSessionId();
48669
48738
  this.logger = deriveSdkLogger(logging, {
@@ -48686,12 +48755,34 @@ class FriskSession {
48686
48755
  get rootRunId() {
48687
48756
  return this._rootRunId;
48688
48757
  }
48758
+ createLlmCallSpan({
48759
+ parent
48760
+ } = {}) {
48761
+ const span = new LlmCallSpan({
48762
+ tracer: this.tracer,
48763
+ parent: parent ?? this._rootSpan
48764
+ });
48765
+ span.setAttributes({ sessionId: this.id });
48766
+ return span;
48767
+ }
48768
+ createOperationSpan({
48769
+ parent
48770
+ } = {}) {
48771
+ const span = new OperationSpan({
48772
+ tracer: this.tracer,
48773
+ parent: parent ?? this._rootSpan
48774
+ });
48775
+ span.setAttributes({ sessionId: this.id });
48776
+ return span;
48777
+ }
48689
48778
  async createToolCallSpan({
48690
48779
  name,
48691
48780
  args: toolArgsInput,
48692
- agentState
48781
+ agentState,
48782
+ parent
48693
48783
  }) {
48694
48784
  const toolArgs = this.validateToolArgs(toolArgsInput);
48785
+ const llmReasoning = extractLlmReasoning(toolArgs);
48695
48786
  const redactedToolArgsResult = this.frisk.adapter?.serializeToolArgs(removeLlmReasoningArg(toolArgs), { redact: this.redaction.redactToolArgs }) ?? {
48696
48787
  value: "{}",
48697
48788
  redactedPaths: []
@@ -48701,26 +48792,30 @@ class FriskSession {
48701
48792
  value: "{}",
48702
48793
  redactedPaths: []
48703
48794
  };
48704
- const sessionSpan = this.rootSpan;
48705
- const parentContext = sessionSpan ? import_api2.trace.setSpan(import_api2.context.active(), sessionSpan) : import_api2.context.active();
48706
- const spanAttributes = {
48707
- [ATTRIBUTE_NAME_SESSION_ID]: this.id,
48708
- [ATTRIBUTE_NAME_TOOL_NAME]: name,
48709
- [ATTRIBUTE_NAME_TOOL_ARGS_JSON]: redactedToolArgsResult.value,
48710
- [ATTRIBUTE_NAME_TOOL_ARGS_REDACTED_PATHS_JSON]: JSON.stringify(redactedToolArgsResult.redactedPaths),
48711
- [ATTRIBUTE_NAME_AGENT_STATE_JSON]: redactedAgentStateResult.value ?? "{}",
48712
- [ATTRIBUTE_NAME_AGENT_STATE_REDACTED_PATHS_JSON]: JSON.stringify(redactedAgentStateResult.redactedPaths),
48713
- [ATTRIBUTE_NAME_TOOL_CALL_SEQUENCE_NUMBER]: this.toolCallSequenceGenerator.next().value
48714
- };
48795
+ const span = new ToolCallObservationSpan({
48796
+ tracer: this.tracer,
48797
+ parent: parent ?? this._rootSpan
48798
+ });
48799
+ span.setAttributes({
48800
+ sessionId: this.id,
48801
+ toolName: name,
48802
+ toolArgsJson: redactedToolArgsResult.value ?? "{}",
48803
+ toolArgsRedactedPathsJson: JSON.stringify(redactedToolArgsResult.redactedPaths),
48804
+ agentStateJson: redactedAgentStateResult.value ?? "{}",
48805
+ agentStateRedactedPathsJson: JSON.stringify(redactedAgentStateResult.redactedPaths),
48806
+ toolCallSequenceNumber: this.toolCallSequenceGenerator.next().value
48807
+ });
48715
48808
  await this.frisk.toolRegistrationComplete;
48716
48809
  const registeredTool = this.frisk.getRegisteredTool(name);
48717
48810
  if (registeredTool) {
48718
- spanAttributes[ATTRIBUTE_NAME_FRISK_TOOL_ID] = registeredTool.id;
48719
- spanAttributes[ATTRIBUTE_NAME_FRISK_TOOL_VERSION_ID] = registeredTool.versionId;
48811
+ span.setAttributes({
48812
+ friskToolId: registeredTool.id,
48813
+ friskToolVersionId: registeredTool.versionId
48814
+ });
48815
+ }
48816
+ if (llmReasoning !== null) {
48817
+ span.setAttributes({ llmReasoning });
48720
48818
  }
48721
- const span = this.getTracer().startSpan(SPAN_NAME_OBSERVE_TOOL_CALL, {
48722
- attributes: spanAttributes
48723
- }, parentContext);
48724
48819
  return span;
48725
48820
  }
48726
48821
  closeToolCallSpan({
@@ -48730,19 +48825,19 @@ class FriskSession {
48730
48825
  status
48731
48826
  }) {
48732
48827
  if (toolCallId) {
48733
- span.setAttribute(ATTRIBUTE_NAME_TOOL_CALL_ID, toolCallId);
48828
+ span.setAttributes({ toolCallId });
48734
48829
  }
48735
48830
  if (status === "error" /* Error */ || !!err) {
48736
48831
  this.incrementToolCallErrors();
48737
- span.setAttribute(ATTRIBUTE_NAME_TOOL_CALL_IS_ERROR, true);
48738
- span.setAttribute(ATTRIBUTE_NAME_TOOL_CALL_IS_SUCCESS, false);
48832
+ span.setAttributes({ isError: true, isSuccess: false });
48739
48833
  } else if (status === "success" /* Success */) {
48740
- span.setAttribute(ATTRIBUTE_NAME_TOOL_CALL_IS_SUCCESS, true);
48741
- span.setAttribute(ATTRIBUTE_NAME_TOOL_CALL_IS_ERROR, false);
48834
+ span.setAttributes({ isSuccess: true, isError: false });
48742
48835
  }
48743
- if (err && err instanceof Error) {
48744
- span.setAttribute(ATTRIBUTE_NAME_ERROR_MESSAGE, `${err}`);
48745
- span.setAttribute(ATTRIBUTE_NAME_ERROR_TYPE, `${err.constructor.name}`);
48836
+ if (err instanceof Error) {
48837
+ span.setAttributes({
48838
+ errorMessage: `${err}`,
48839
+ errorType: `${err.constructor.name}`
48840
+ });
48746
48841
  }
48747
48842
  span.end();
48748
48843
  }
@@ -48756,32 +48851,37 @@ class FriskSession {
48756
48851
  agentState
48757
48852
  }) {
48758
48853
  const registeredTool = this.frisk.getRegisteredTool(toolCall.name);
48759
- const toolCallSpan = new ToolCallSpan({
48760
- sessionId: this.id,
48761
- adapter: this.frisk.adapter,
48762
- toolCall,
48763
- friskToolId: registeredTool?.id ?? null,
48764
- friskToolVersionId: registeredTool?.versionId ?? null,
48765
- agentState,
48766
- parent: this._rootSpan,
48854
+ const redactedToolArgs = this.frisk.adapter.serializeToolArgs(removeLlmReasoningArg(toolCall.args), { redact: this.redaction.redactToolArgs });
48855
+ const redactedAgentState = this.frisk.adapter.serializeAgentState(agentState, { redact: this.redaction.redactAgentState });
48856
+ const llmReasoning = extractLlmReasoning(toolCall.args);
48857
+ const span = new ToolCallDecisionSpan({
48767
48858
  tracer: this.tracer,
48768
- redact: this.redaction
48859
+ parent: this._rootSpan
48769
48860
  });
48770
- const toolArgs = toolCall.args;
48771
- return toolCallSpan.run((span) => {
48861
+ try {
48862
+ span.setAttributes({
48863
+ sessionId: this.id,
48864
+ toolName: toolCall.name,
48865
+ toolCallId: toolCall.id,
48866
+ toolArgsJson: redactedToolArgs.value ?? "{}",
48867
+ toolArgsRedactedPathsJson: JSON.stringify(redactedToolArgs.redactedPaths),
48868
+ agentStateJson: redactedAgentState.value ?? "{}",
48869
+ agentStateRedactedPathsJson: JSON.stringify(redactedAgentState.redactedPaths),
48870
+ friskToolId: registeredTool?.id,
48871
+ friskToolVersionId: registeredTool?.versionId,
48872
+ llmReasoning: llmReasoning ?? undefined
48873
+ });
48874
+ const spanContext = import_api2.trace.setSpan(import_api2.context.active(), span.otelSpan);
48875
+ const traceContextCarrier = {};
48876
+ import_api2.propagation.inject(spanContext, traceContextCarrier);
48772
48877
  try {
48773
- if (LLM_REASONING_ARG_NAME in toolArgs) {
48774
- const llmReasoning = toolArgs[LLM_REASONING_ARG_NAME];
48775
- span.setAttribute(ATTRIBUTE_NAME_LLM_REASONING, llmReasoning);
48776
- }
48777
- const baseToolCallArgs = removeLlmReasoningArg(toolCall.args);
48778
48878
  const coreResult = this.frisk.decideToolCall({
48779
48879
  toolCall: {
48780
48880
  ...toolCall,
48781
- args: baseToolCallArgs
48881
+ args: removeLlmReasoningArg(toolCall.args)
48782
48882
  },
48783
48883
  agentState,
48784
- traceContextCarrier: span.traceContextCarrier ?? undefined
48884
+ traceContextCarrier
48785
48885
  });
48786
48886
  const result = {
48787
48887
  outcome: coreResult.outcome,
@@ -48790,7 +48890,11 @@ class FriskSession {
48790
48890
  policyId: coreResult.policyId,
48791
48891
  policyVersionId: coreResult.policyVersionId
48792
48892
  };
48793
- span.saveResult(result);
48893
+ span.setAttributes({
48894
+ decisionOutcome: result.outcome,
48895
+ decisionMatchedRuleCount: Number(result.rulesMatchedCount),
48896
+ decisionReason: result.reason ?? undefined
48897
+ });
48794
48898
  return result;
48795
48899
  } catch (error) {
48796
48900
  const wrapped = new ToolCallEvaluationError(error);
@@ -48798,14 +48902,19 @@ class FriskSession {
48798
48902
  toolName: toolCall.name,
48799
48903
  toolCallId: toolCall.id
48800
48904
  });
48801
- span.saveError(wrapped);
48905
+ span.setAttributes({
48906
+ errorType: wrapped.constructor.name,
48907
+ errorMessage: wrapped.message
48908
+ });
48802
48909
  return {
48803
48910
  outcome: "error" /* ERROR */,
48804
48911
  rulesMatchedCount: 0,
48805
48912
  reason: wrapped.message
48806
48913
  };
48807
48914
  }
48808
- });
48915
+ } finally {
48916
+ span.end();
48917
+ }
48809
48918
  }
48810
48919
  *createToolCallSequenceGenerator() {
48811
48920
  while (true) {
@@ -48821,24 +48930,49 @@ class FriskSession {
48821
48930
  getToolCallErrorCount() {
48822
48931
  return this.toolCallErrorCount;
48823
48932
  }
48933
+ recordTokenUsage({
48934
+ inputTokens = 0,
48935
+ outputTokens = 0,
48936
+ totalTokens = 0
48937
+ }) {
48938
+ this.tokenUsageInput += inputTokens;
48939
+ this.tokenUsageOutput += outputTokens;
48940
+ this.tokenUsageTotal += totalTokens;
48941
+ this._rootSpan?.setAttributes({
48942
+ inputTokens: this.tokenUsageInput,
48943
+ outputTokens: this.tokenUsageOutput,
48944
+ totalTokens: this.tokenUsageTotal
48945
+ });
48946
+ }
48947
+ getTokenUsage() {
48948
+ return {
48949
+ inputTokens: this.tokenUsageInput,
48950
+ outputTokens: this.tokenUsageOutput,
48951
+ totalTokens: this.tokenUsageTotal
48952
+ };
48953
+ }
48824
48954
  initTracing({ runId, agentState }) {
48825
48955
  this._rootRunId = runId;
48826
48956
  this._isTracing = true;
48827
48957
  this._agentState = agentState;
48828
- const span = this.tracer.startSpan(SPAN_NAME_FRISK_SESSION);
48829
- span.setAttribute(ATTRIBUTE_NAME_SESSION_ID, this.id);
48830
- span.setAttribute(ATTRIBUTE_NAME_REMOTE_SESSION_ID, runId);
48958
+ const span = new SessionSpan({ tracer: this.tracer });
48959
+ span.setAttributes({ sessionId: this.id, remoteSessionId: runId });
48831
48960
  const userPrompt = this.frisk.adapter.extractPrompt?.(agentState);
48832
48961
  if (userPrompt) {
48833
- span.setAttribute(ATTRIBUTE_NAME_SESSION_PROMPT, userPrompt);
48962
+ span.setAttributes({ prompt: userPrompt });
48834
48963
  }
48835
48964
  this.setRootSpan(span);
48836
48965
  return span;
48837
48966
  }
48838
48967
  endTracing() {
48839
48968
  if (this._rootSpan) {
48840
- this._rootSpan.setAttribute(ATTRIBUTE_NAME_TOOL_CALL_COUNT, this.getToolCallCount());
48841
- this._rootSpan.setAttribute(ATTRIBUTE_NAME_TOOL_CALL_ERROR_COUNT, this.getToolCallErrorCount());
48969
+ this._rootSpan.setAttributes({
48970
+ toolCallCount: this.getToolCallCount(),
48971
+ toolCallErrorCount: this.getToolCallErrorCount(),
48972
+ inputTokens: this.tokenUsageInput,
48973
+ outputTokens: this.tokenUsageOutput,
48974
+ totalTokens: this.tokenUsageTotal
48975
+ });
48842
48976
  this._rootSpan.end();
48843
48977
  }
48844
48978
  this._isTracing = false;
@@ -48853,6 +48987,14 @@ class FriskSession {
48853
48987
  }
48854
48988
  }
48855
48989
 
48990
+ // src/core/redaction-options.ts
48991
+ function resolveRedactionOptions(options) {
48992
+ return {
48993
+ redactToolArgs: options?.redactToolArgs ?? false,
48994
+ redactAgentState: options?.redactAgentState ?? false
48995
+ };
48996
+ }
48997
+
48856
48998
  // src/core/sdk-attributes/detect-runtime.ts
48857
48999
  function detectRuntime() {
48858
49000
  const g = globalThis;
@@ -48893,7 +49035,7 @@ import { fileURLToPath } from "node:url";
48893
49035
 
48894
49036
  // src/generated/sdk-meta.ts
48895
49037
  var SDK_NAME = "@friskai/frisk-js";
48896
- var SDK_VERSION = "0.3.0";
49038
+ var SDK_VERSION = "0.3.2";
48897
49039
 
48898
49040
  // src/core/sdk-attributes/read-sdk-meta.ts
48899
49041
  function getSdkMeta() {
@@ -49561,16 +49703,21 @@ export {
49561
49703
  getEnv,
49562
49704
  combineRedactOptions,
49563
49705
  UnexpectedFriskServerResponseError,
49564
- ToolCallSpan,
49706
+ ToolCallObservationSpan,
49707
+ ToolCallDecisionSpan,
49565
49708
  ToolApprovalStatus,
49709
+ SessionSpan,
49566
49710
  SessionRegistry,
49567
49711
  SessionNotFoundError,
49712
+ OperationSpan,
49568
49713
  MissingOtlpEndpointError,
49569
49714
  MissingFriskSessionContextError,
49570
49715
  MissingBaseURLError,
49571
49716
  MissingAPIKeyError,
49717
+ LlmCallSpan,
49572
49718
  InvalidFriskSessionError,
49573
49719
  InvalidAccessTokenError,
49720
+ FriskSpan,
49574
49721
  FriskSession,
49575
49722
  FriskInvalidAPIKeyError,
49576
49723
  FriskError,
@@ -49586,5 +49733,5 @@ export {
49586
49733
  AccessTokenProvider
49587
49734
  };
49588
49735
 
49589
- //# debugId=2B56BC442CE3397564756E2164756E21
49736
+ //# debugId=B3770FB94B39213764756E2164756E21
49590
49737
  //# sourceMappingURL=index.js.map