@databricks/appkit 0.59.0 → 0.60.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.
@@ -1,6 +1,6 @@
1
1
  //#region package.json
2
2
  var name = "@databricks/appkit";
3
- var version = "0.59.0";
3
+ var version = "0.60.0";
4
4
 
5
5
  //#endregion
6
6
  export { name, version };
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","names":[],"sources":["../../../src/plugins/agents/agents.ts"],"mappings":";;;;;;;;;;cAsIa,YAAA,SAAqB,MAAA,YAAkB,YAAA;EAAA,OAC3C,QAAA,EAAuB,cAAA;EAAA,OACvB,KAAA,EAAO,WAAA;EAAA,UAEI,MAAA,EAAQ,kBAAA;EAAA,QAElB,MAAA;EAAA,QACA,gBAAA;EAAA,QACA,aAAA;EARgB;;;;;;EAAA,QAkBhB,gBAAA;EAAA,QACA,SAAA;EAAA,QACA,WAAA;EAAA,QACA,YAAA;cAEI,MAAA,EAAQ,kBAAA;EA8rBJ;;;;;;;;;;EAAA,QA/pBR,oBAAA;EAAA,YAKI,sBAAA,CAAA;EA3DoB;EAAA,YAqFpB,cAAA,CAAA;EApFL;EAAA,QAuGC,gBAAA;EAtGD;;;;;;EAAA,QAgHC,WAAA;EAhGA;;;;;EAAA,QAiHA,aAAA;EAYF,KAAA,CAAA,GAAK,OAAA;EAzFH;;;;;;EAuGF,MAAA,CAAA,GAAU,OAAA;EAdL;;;;;EAAA,QAwCG,kBAAA;EAAA,QAmEN,iBAAA;EAAA,QAMM,mBAAA;EAoEA;;;;;;EAAA,QA1CN,mBAAA;EAAA,QAmBM,oBAAA;EAAA,QAuBA,cAAA;EAyUY;;;;;EAAA,QA7RZ,cAAA;EAqWE;;;;;;;;;;;EAAA,QArPR,eAAA;EA6iCM;;;;;;;;;;;;EAAA,QAjhCN,eAAA;EAAA,QAkBM,gBAAA;EAAA,QA0DA,kBAAA;EAiEd,aAAA,CAAA,GAAiB,mBAAA;EAIX,gBAAA,CAAA,GAAoB,OAAA;;;;;;;UAYlB,iBAAA;EAUR,YAAA,CAAa,MAAA,EAAQ,UAAA;EAkDrB,YAAA,CAAA,GAAgB,MAAA;EAAA,QAOF,WAAA;;;;;;;;;;;;UA6EN,gCAAA;;;;;;;;;;;UAuBM,aAAA;EAAA,QAoFA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;UA6LA,qBAAA;;;;;;;;;;;;UA6IA,gBAAA;;;;;;;;;;;;;;;UAyHA,WAAA;EAAA,QAiGA,aAAA;EAAA,QA2BA,cAAA;EAAA,QAuCA,kBAAA;EAAA,QASA,gBAAA;EAAA,QAUA,mBAAA;EAAA,QAaN,YAAA;EAAA,QASA,aAAA;EAgBF,QAAA,CAAA,GAAY,OAAA;EAQlB,OAAA,CAAA;6BAE2B,GAAA,EAAO,eAAA,KAAe,OAAA;;2BAG3B,eAAA;;;oCAGS,OAAA,CAAA,MAAA;EAAA;EAAA,QAIjB,iBAAA;AAAA;;;;;;;;;;;;;;;;cAsJH,MAAA,EAAM,QAAA,QAAA,YAAA,EAAA,kBAAA"}
1
+ {"version":3,"file":"agents.d.ts","names":[],"sources":["../../../src/plugins/agents/agents.ts"],"mappings":";;;;;;;;;;cA6Ia,YAAA,SAAqB,MAAA,YAAkB,YAAA;EAAA,OAK3C,QAAA,EAAkC,cAAA;EAAA,OAClC,KAAA,EAAO,WAAA;EAAA,UAEI,MAAA,EAAQ,kBAAA;EAAA,QAElB,MAAA;EAAA,QACA,gBAAA;EAAA,QACA,aAAA;EAZgB;;;;;;EAAA,QAsBhB,gBAAA;EAAA,QACA,SAAA;EAAA,QACA,WAAA;EAAA,QACA,YAAA;cAEI,MAAA,EAAQ,kBAAA;EA+rBJ;;;;;;;;;;EAAA,QAhqBR,oBAAA;EAAA,YAKI,sBAAA,CAAA;EA/DoB;EAAA,YAyFpB,cAAA,CAAA;EApFL;EAAA,QAuGC,gBAAA;EAtGD;;;;;;EAAA,QAgHC,WAAA;EAhGA;;;;;EAAA,QAiHA,aAAA;EAYF,KAAA,CAAA,GAAK,OAAA;EAzFH;;;;;;EAwGF,MAAA,CAAA,GAAU,OAAA;EAfL;;;;;EAAA,QAyCG,kBAAA;EAAA,QAmEN,iBAAA;EAAA,QAMM,mBAAA;EAoEA;;;;;;EAAA,QA1CN,mBAAA;EAAA,QAmBM,oBAAA;EAAA,QAuBA,cAAA;EAyUY;;;;;EAAA,QA7RZ,cAAA;EAqWE;;;;;;;;;;;EAAA,QArPR,eAAA;EAynCM;;;;;;;;;;;;EAAA,QA7lCN,eAAA;EAAA,QAkBM,gBAAA;EAAA,QA0DA,kBAAA;EAiEd,aAAA,CAAA,GAAiB,mBAAA;EAIX,gBAAA,CAAA,GAAoB,OAAA;;;;;;;UAYlB,iBAAA;EAUR,YAAA,CAAa,MAAA,EAAQ,UAAA;EAkDrB,YAAA,CAAA,GAAgB,MAAA;EAAA,QAOF,WAAA;;;;;;;;;;;;UA6EN,gCAAA;;;;;;;;;;;UAuBM,aAAA;EAAA,QA2FA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;UA2NA,qBAAA;;;;;;;;;;;;UA0KA,gBAAA;;;;;;;;;;;;;;;UAmIA,WAAA;EAAA,QAiGA,aAAA;EAAA,QA2BA,cAAA;EAAA,QAuCA,kBAAA;EAAA,QASA,gBAAA;EAAA,QAUA,mBAAA;EAAA,QAaN,YAAA;EAAA,QASA,aAAA;EAgBF,QAAA,CAAA,GAAY,OAAA;EAQlB,OAAA,CAAA;6BAE2B,GAAA,EAAO,eAAA,KAAe,OAAA;;2BAG3B,eAAA;;;oCAGS,OAAA,CAAA,MAAA;EAAA;EAAA,QAIjB,iBAAA;AAAA;;;;;;;;;;;;;;;;cAsJH,MAAA,EAAM,QAAA,QAAA,YAAA,EAAA,kBAAA"}
@@ -20,6 +20,7 @@ import { agentStreamDefaults } from "./defaults.js";
20
20
  import { EventChannel } from "./event-channel.js";
21
21
  import { AgentEventTranslator } from "./event-translator.js";
22
22
  import manifest_default from "./manifest.js";
23
+ import { currentTraceId, initAgentTracing, linkTraceToRun, traceAgent, traceTool } from "./mlflow.js";
23
24
  import { approvalRequestSchema, cancelRequestSchema, chatRequestSchema, invocationsRequestSchema } from "./schemas.js";
24
25
  import { InMemoryThreadStore } from "./thread-store.js";
25
26
  import { ToolApprovalGate } from "./tool-approval-gate.js";
@@ -147,6 +148,7 @@ var AgentsPlugin = class extends Plugin {
147
148
  else this.userStreamCounts.set(entry.userId, next);
148
149
  }
149
150
  async setup() {
151
+ await initAgentTracing();
150
152
  const { agents, defaultAgentName } = await this.buildAgentRegistry();
151
153
  this.agents = agents;
152
154
  this.defaultAgentName = defaultAgentName;
@@ -550,7 +552,7 @@ var AgentsPlugin = class extends Plugin {
550
552
  });
551
553
  return;
552
554
  }
553
- const { message, threadId, agent: agentName } = parsed.data;
555
+ const { message, threadId, agent: agentName, mlflowRunId } = parsed.data;
554
556
  const registered = this.resolveAgent(agentName);
555
557
  if (!registered) {
556
558
  res.status(400).json({ error: agentName ? `Agent "${agentName}" not found` : "No agent registered" });
@@ -583,7 +585,7 @@ var AgentsPlugin = class extends Plugin {
583
585
  res.status(500).json({ error: "Thread operation failed" });
584
586
  return;
585
587
  }
586
- return this._streamAgent(req, res, registered, thread, userId);
588
+ return this._streamAgent(req, res, registered, thread, userId, mlflowRunId);
587
589
  }
588
590
  /**
589
591
  * Returns the names of tools in `registered.toolIndex` whose annotations
@@ -621,7 +623,7 @@ var AgentsPlugin = class extends Plugin {
621
623
  });
622
624
  return;
623
625
  }
624
- const { input } = parsed.data;
626
+ const { input, mlflowRunId } = parsed.data;
625
627
  const registered = this.resolveAgent();
626
628
  if (!registered) {
627
629
  res.status(400).json({ error: "No agent registered" });
@@ -664,9 +666,9 @@ var AgentsPlugin = class extends Plugin {
664
666
  res.status(500).json({ error: "Thread operation failed" });
665
667
  return;
666
668
  }
667
- return this._runAgentNonStreaming(req, res, registered, thread, userId);
669
+ return this._runAgentNonStreaming(req, res, registered, thread, userId, mlflowRunId);
668
670
  }
669
- async _streamAgent(req, res, registered, thread, userId) {
671
+ async _streamAgent(req, res, registered, thread, userId, mlflowRunId) {
670
672
  const abortController = new AbortController();
671
673
  const signal = abortController.signal;
672
674
  const requestId = randomUUID();
@@ -695,37 +697,54 @@ var AgentsPlugin = class extends Plugin {
695
697
  type: "metadata",
696
698
  data: { threadId: thread.id }
697
699
  })) outboundEvents.push(evt);
698
- const pluginNames = this.context ? this.context.getPluginNames().filter((n) => n !== this.name && n !== "server") : [];
699
- const messagesWithSystem = [{
700
- id: "system",
701
- role: "system",
702
- content: composePromptForAgent(registered, this.config.baseSystemPrompt, {
703
- agentName: registered.name,
704
- pluginNames,
705
- toolNames: tools.map((t) => t.name)
706
- }),
707
- createdAt: /* @__PURE__ */ new Date()
708
- }, ...thread.messages];
709
- const fullContent = await consumeAdapterStream(registered.adapter.run({
710
- messages: messagesWithSystem,
711
- tools,
712
- threadId: thread.id,
713
- signal,
714
- extensions: buildAdapterExtensions(registered.toolIndex)
715
- }, {
716
- executeTool,
717
- signal
718
- }), {
719
- signal,
720
- onEvent: (event) => {
721
- for (const translated of translator.translate(event)) outboundEvents.push(translated);
700
+ await traceAgent(registered.name ?? "agent", { messages: thread.messages.map((m) => ({
701
+ role: m.role,
702
+ content: m.content
703
+ })) }, async (span) => {
704
+ if (mlflowRunId) linkTraceToRun(mlflowRunId);
705
+ const pluginNames = this.context ? this.context.getPluginNames().filter((n) => n !== this.name && n !== "server") : [];
706
+ const messagesWithSystem = [{
707
+ id: "system",
708
+ role: "system",
709
+ content: composePromptForAgent(registered, this.config.baseSystemPrompt, {
710
+ agentName: registered.name,
711
+ pluginNames,
712
+ toolNames: tools.map((t) => t.name)
713
+ }),
714
+ createdAt: /* @__PURE__ */ new Date()
715
+ }, ...thread.messages];
716
+ const fullContent = await consumeAdapterStream(registered.adapter.run({
717
+ messages: messagesWithSystem,
718
+ tools,
719
+ threadId: thread.id,
720
+ signal,
721
+ extensions: buildAdapterExtensions(registered.toolIndex)
722
+ }, {
723
+ executeTool,
724
+ signal
725
+ }), {
726
+ signal,
727
+ onEvent: (event) => {
728
+ for (const translated of translator.translate(event)) outboundEvents.push(translated);
729
+ }
730
+ });
731
+ if (fullContent) {
732
+ span.setOutputs({
733
+ role: "assistant",
734
+ content: fullContent
735
+ });
736
+ await this.threadStore.addMessage(thread.id, userId, {
737
+ id: randomUUID(),
738
+ role: "assistant",
739
+ content: fullContent,
740
+ createdAt: /* @__PURE__ */ new Date()
741
+ });
722
742
  }
723
- });
724
- if (fullContent) await this.threadStore.addMessage(thread.id, userId, {
725
- id: randomUUID(),
726
- role: "assistant",
727
- content: fullContent,
728
- createdAt: /* @__PURE__ */ new Date()
743
+ const mlflowTraceId = currentTraceId();
744
+ if (mlflowTraceId) for (const evt of translator.translate({
745
+ type: "metadata",
746
+ data: { mlflowTraceId }
747
+ })) outboundEvents.push(evt);
729
748
  });
730
749
  for (const evt of translator.finalize()) outboundEvents.push(evt);
731
750
  } catch (error) {
@@ -784,12 +803,14 @@ var AgentsPlugin = class extends Plugin {
784
803
  * synthesis (which would have been a coding bug given the precheck) is
785
804
  * a dropped no-op instead of a runtime crash.
786
805
  */
787
- async _runAgentNonStreaming(req, res, registered, thread, userId) {
806
+ async _runAgentNonStreaming(req, res, registered, thread, userId, mlflowRunId) {
788
807
  const abortController = new AbortController();
789
808
  const signal = abortController.signal;
790
809
  const requestId = randomUUID();
791
810
  this.trackStream(requestId, userId, abortController);
792
811
  const tools = Array.from(registered.toolIndex.values()).map((e) => e.def);
812
+ const limits = this.resolvedLimits;
813
+ let mlflowTraceId;
793
814
  const runState = {
794
815
  req,
795
816
  userId,
@@ -800,7 +821,7 @@ var AgentsPlugin = class extends Plugin {
800
821
  requireForDestructive: false,
801
822
  timeoutMs: 0
802
823
  },
803
- limits: this.resolvedLimits,
824
+ limits,
804
825
  translator: new AgentEventTranslator(),
805
826
  outboundEvents: new EventChannel(),
806
827
  toolCallsUsed: { count: 0 }
@@ -808,31 +829,44 @@ var AgentsPlugin = class extends Plugin {
808
829
  const executeTool = (name, args) => this.dispatchToolCall(runState, registered.toolIndex, name, args, 0);
809
830
  let fullContent = "";
810
831
  try {
811
- const pluginNames = this.context ? this.context.getPluginNames().filter((n) => n !== this.name && n !== "server") : [];
812
- const messagesWithSystem = [{
813
- id: "system",
814
- role: "system",
815
- content: composePromptForAgent(registered, this.config.baseSystemPrompt, {
816
- agentName: registered.name,
817
- pluginNames,
818
- toolNames: tools.map((t) => t.name)
819
- }),
820
- createdAt: /* @__PURE__ */ new Date()
821
- }, ...thread.messages];
822
- fullContent = await consumeAdapterStream(registered.adapter.run({
823
- messages: messagesWithSystem,
824
- tools,
825
- threadId: thread.id,
826
- signal
827
- }, {
828
- executeTool,
829
- signal
830
- }), { signal });
831
- if (fullContent) await this.threadStore.addMessage(thread.id, userId, {
832
- id: randomUUID(),
833
- role: "assistant",
834
- content: fullContent,
835
- createdAt: /* @__PURE__ */ new Date()
832
+ await traceAgent(registered.name ?? "agent", { messages: thread.messages.map((m) => ({
833
+ role: m.role,
834
+ content: m.content
835
+ })) }, async (span) => {
836
+ if (mlflowRunId) linkTraceToRun(mlflowRunId);
837
+ const pluginNames = this.context ? this.context.getPluginNames().filter((n) => n !== this.name && n !== "server") : [];
838
+ const messagesWithSystem = [{
839
+ id: "system",
840
+ role: "system",
841
+ content: composePromptForAgent(registered, this.config.baseSystemPrompt, {
842
+ agentName: registered.name,
843
+ pluginNames,
844
+ toolNames: tools.map((t) => t.name)
845
+ }),
846
+ createdAt: /* @__PURE__ */ new Date()
847
+ }, ...thread.messages];
848
+ fullContent = await consumeAdapterStream(registered.adapter.run({
849
+ messages: messagesWithSystem,
850
+ tools,
851
+ threadId: thread.id,
852
+ signal
853
+ }, {
854
+ executeTool,
855
+ signal
856
+ }), { signal });
857
+ if (fullContent) {
858
+ span.setOutputs({
859
+ role: "assistant",
860
+ content: fullContent
861
+ });
862
+ await this.threadStore.addMessage(thread.id, userId, {
863
+ id: randomUUID(),
864
+ role: "assistant",
865
+ content: fullContent,
866
+ createdAt: /* @__PURE__ */ new Date()
867
+ });
868
+ }
869
+ mlflowTraceId = currentTraceId();
836
870
  });
837
871
  } catch (error) {
838
872
  if (signal.aborted) {
@@ -869,6 +903,7 @@ var AgentsPlugin = class extends Plugin {
869
903
  created_at: Math.floor(Date.now() / 1e3),
870
904
  status: "completed",
871
905
  thread_id: thread.id,
906
+ ...mlflowTraceId ? { mlflow_trace_id: mlflowTraceId } : {},
872
907
  output: [message]
873
908
  });
874
909
  }
@@ -908,24 +943,26 @@ var AgentsPlugin = class extends Plugin {
908
943
  timeoutMs: runState.approvalPolicy.timeoutMs
909
944
  }) === "deny") return `Tool execution denied by user approval gate (tool: ${name}).`;
910
945
  }
911
- let result;
912
- if (entry.source === "toolkit") {
913
- if (!this.context) throw new Error("Plugin tool execution requires PluginContext; this should never happen through createApp");
914
- result = await this.context.executeTool(runState.req, entry.pluginName, entry.localName, args, runState.signal, runState.limits.toolCallTimeoutMs);
915
- } else if (entry.source === "function") {
916
- if (typeof args !== "object" || args === null || Array.isArray(args)) throw new Error(`Function tool '${name}' received non-object arguments (got ${args === null ? "null" : Array.isArray(args) ? "array" : typeof args}); expected a JSON object.`);
917
- result = await entry.functionTool.execute(args);
918
- } else if (entry.source === "mcp") {
919
- if (!this.mcpClient) throw new Error("MCP client not connected");
920
- const oboToken = runState.req.headers["x-forwarded-access-token"];
921
- const mcpAuth = typeof oboToken === "string" ? { Authorization: `Bearer ${oboToken}` } : void 0;
922
- result = await this.mcpClient.callTool(entry.mcpToolName, args, mcpAuth);
923
- } else if (entry.source === "subagent") {
924
- const childAgent = this.agents.get(entry.agentName);
925
- if (!childAgent) throw new Error(`Sub-agent not found: ${entry.agentName}`);
926
- result = await this.runSubAgent(runState, childAgent, args, depth + 1);
927
- } else if (entry.source === "hosted-supervisor") throw new Error(`Tool '${name}' is a hosted-supervisor tool and cannot be invoked from the Node process. It is executed server-side by the Databricks AI Gateway and is only reachable when the agent's model is a Supervisor API adapter.`);
928
- return normalizeToolResult(result);
946
+ return normalizeToolResult(await traceTool(name, args, async () => {
947
+ let result;
948
+ if (entry.source === "toolkit") {
949
+ if (!this.context) throw new Error("Plugin tool execution requires PluginContext; this should never happen through createApp");
950
+ result = await this.context.executeTool(runState.req, entry.pluginName, entry.localName, args, runState.signal, runState.limits.toolCallTimeoutMs);
951
+ } else if (entry.source === "function") {
952
+ if (typeof args !== "object" || args === null || Array.isArray(args)) throw new Error(`Function tool '${name}' received non-object arguments (got ${args === null ? "null" : Array.isArray(args) ? "array" : typeof args}); expected a JSON object.`);
953
+ result = await entry.functionTool.execute(args);
954
+ } else if (entry.source === "mcp") {
955
+ if (!this.mcpClient) throw new Error("MCP client not connected");
956
+ const oboToken = runState.req.headers["x-forwarded-access-token"];
957
+ const mcpAuth = typeof oboToken === "string" ? { Authorization: `Bearer ${oboToken}` } : void 0;
958
+ result = await this.mcpClient.callTool(entry.mcpToolName, args, mcpAuth);
959
+ } else if (entry.source === "subagent") {
960
+ const childAgent = this.agents.get(entry.agentName);
961
+ if (!childAgent) throw new Error(`Sub-agent not found: ${entry.agentName}`);
962
+ result = await this.runSubAgent(runState, childAgent, args, depth + 1);
963
+ } else if (entry.source === "hosted-supervisor") throw new Error(`Tool '${name}' is a hosted-supervisor tool and cannot be invoked from the Node process. It is executed server-side by the Databricks AI Gateway and is only reachable when the agent's model is a Supervisor API adapter.`);
964
+ return result;
965
+ }));
929
966
  }
930
967
  /**
931
968
  * Runs a sub-agent in response to an `agent-<key>` tool call. Returns the