@databricks/appkit 0.32.0 → 0.33.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.
Files changed (153) hide show
  1. package/CLAUDE.md +53 -1
  2. package/NOTICE.md +1 -0
  3. package/dist/agents/databricks.d.ts.map +1 -1
  4. package/dist/agents/databricks.js +8 -3
  5. package/dist/agents/databricks.js.map +1 -1
  6. package/dist/appkit/package.js +1 -1
  7. package/dist/beta.d.ts +5 -3
  8. package/dist/beta.js +3 -1
  9. package/dist/connectors/mcp/client.d.ts +27 -2
  10. package/dist/connectors/mcp/client.d.ts.map +1 -1
  11. package/dist/connectors/mcp/client.js +117 -18
  12. package/dist/connectors/mcp/client.js.map +1 -1
  13. package/dist/connectors/mcp/index.d.ts +1 -1
  14. package/dist/connectors/mcp/types.d.ts +1 -1
  15. package/dist/core/agent/build-toolkit.js +3 -8
  16. package/dist/core/agent/build-toolkit.js.map +1 -1
  17. package/dist/core/agent/load-agents.d.ts +6 -1
  18. package/dist/core/agent/load-agents.d.ts.map +1 -1
  19. package/dist/core/agent/load-agents.js +67 -27
  20. package/dist/core/agent/load-agents.js.map +1 -1
  21. package/dist/core/agent/plugins-map.js +44 -0
  22. package/dist/core/agent/plugins-map.js.map +1 -0
  23. package/dist/core/agent/run-agent.d.ts +31 -7
  24. package/dist/core/agent/run-agent.d.ts.map +1 -1
  25. package/dist/core/agent/run-agent.js +138 -27
  26. package/dist/core/agent/run-agent.js.map +1 -1
  27. package/dist/core/agent/toolkit-options.js +28 -0
  28. package/dist/core/agent/toolkit-options.js.map +1 -0
  29. package/dist/core/agent/toolkit-resolver.js +44 -0
  30. package/dist/core/agent/toolkit-resolver.js.map +1 -0
  31. package/dist/core/agent/tools/define-tool.d.ts +14 -2
  32. package/dist/core/agent/tools/define-tool.d.ts.map +1 -1
  33. package/dist/core/agent/tools/define-tool.js +1 -1
  34. package/dist/core/agent/tools/define-tool.js.map +1 -1
  35. package/dist/core/agent/tools/function-tool.d.ts +13 -2
  36. package/dist/core/agent/tools/function-tool.d.ts.map +1 -1
  37. package/dist/core/agent/tools/function-tool.js +4 -3
  38. package/dist/core/agent/tools/function-tool.js.map +1 -1
  39. package/dist/core/agent/tools/index.d.ts +1 -1
  40. package/dist/core/agent/tools/tool.d.ts +32 -3
  41. package/dist/core/agent/tools/tool.d.ts.map +1 -1
  42. package/dist/core/agent/tools/tool.js +4 -3
  43. package/dist/core/agent/tools/tool.js.map +1 -1
  44. package/dist/core/agent/types.d.ts +95 -10
  45. package/dist/core/agent/types.d.ts.map +1 -1
  46. package/dist/core/agent/types.js.map +1 -1
  47. package/dist/plugin/index.d.ts +1 -1
  48. package/dist/plugin/to-plugin.d.ts +3 -13
  49. package/dist/plugin/to-plugin.d.ts.map +1 -1
  50. package/dist/plugin/to-plugin.js +1 -8
  51. package/dist/plugin/to-plugin.js.map +1 -1
  52. package/dist/plugins/agents/agents.d.ts +184 -2
  53. package/dist/plugins/agents/agents.d.ts.map +1 -0
  54. package/dist/plugins/agents/agents.js +169 -72
  55. package/dist/plugins/agents/agents.js.map +1 -1
  56. package/dist/plugins/agents/index.d.ts +2 -2
  57. package/dist/plugins/agents/index.js +1 -1
  58. package/dist/plugins/agents/manifest.js +4 -5
  59. package/dist/plugins/agents/tool-approval-gate.js.map +1 -1
  60. package/dist/plugins/analytics/analytics.d.ts +3 -4
  61. package/dist/plugins/analytics/analytics.d.ts.map +1 -1
  62. package/dist/plugins/analytics/analytics.js +8 -6
  63. package/dist/plugins/analytics/analytics.js.map +1 -1
  64. package/dist/plugins/analytics/index.js +1 -0
  65. package/dist/plugins/analytics/types.js +15 -0
  66. package/dist/plugins/analytics/types.js.map +1 -0
  67. package/dist/plugins/beta-exports.generated.d.ts +2 -0
  68. package/dist/plugins/beta-exports.generated.js +4 -0
  69. package/dist/plugins/files/plugin.d.ts +1 -2
  70. package/dist/plugins/files/plugin.d.ts.map +1 -1
  71. package/dist/plugins/files/plugin.js +30 -12
  72. package/dist/plugins/files/plugin.js.map +1 -1
  73. package/dist/plugins/genie/genie.d.ts +5 -4
  74. package/dist/plugins/genie/genie.d.ts.map +1 -1
  75. package/dist/plugins/genie/genie.js +22 -8
  76. package/dist/plugins/genie/genie.js.map +1 -1
  77. package/dist/plugins/genie/types.d.ts +10 -2
  78. package/dist/plugins/genie/types.d.ts.map +1 -1
  79. package/dist/plugins/jobs/plugin.d.ts +1 -2
  80. package/dist/plugins/jobs/plugin.d.ts.map +1 -1
  81. package/dist/plugins/lakebase/lakebase.d.ts +1 -2
  82. package/dist/plugins/lakebase/lakebase.d.ts.map +1 -1
  83. package/dist/plugins/lakebase/lakebase.js +3 -3
  84. package/dist/plugins/lakebase/lakebase.js.map +1 -1
  85. package/dist/plugins/lakebase/types.d.ts +5 -4
  86. package/dist/plugins/lakebase/types.d.ts.map +1 -1
  87. package/dist/plugins/server/index.d.ts +3 -2
  88. package/dist/plugins/server/index.d.ts.map +1 -1
  89. package/dist/plugins/server/index.js +8 -5
  90. package/dist/plugins/server/index.js.map +1 -1
  91. package/dist/plugins/server/types.d.ts +11 -0
  92. package/dist/plugins/server/types.d.ts.map +1 -1
  93. package/dist/plugins/serving/serving.d.ts +1 -2
  94. package/dist/plugins/serving/serving.d.ts.map +1 -1
  95. package/dist/shared/src/agent.d.ts +16 -4
  96. package/dist/shared/src/agent.d.ts.map +1 -1
  97. package/docs/api/appkit/Class.AppKitMcpClient.md +157 -0
  98. package/docs/api/appkit/Class.DatabricksAdapter.md +151 -0
  99. package/docs/api/appkit/Function.agentIdFromMarkdownPath.md +18 -0
  100. package/docs/api/appkit/Function.createAgent.md +33 -0
  101. package/docs/api/appkit/Function.defineTool.md +26 -0
  102. package/docs/api/appkit/Function.executeFromRegistry.md +25 -0
  103. package/docs/api/appkit/Function.functionToolToDefinition.md +16 -0
  104. package/docs/api/appkit/Function.isFunctionTool.md +16 -0
  105. package/docs/api/appkit/Function.isHostedTool.md +16 -0
  106. package/docs/api/appkit/Function.isToolkitEntry.md +18 -0
  107. package/docs/api/appkit/Function.loadAgentFromFile.md +21 -0
  108. package/docs/api/appkit/Function.loadAgentsFromDir.md +26 -0
  109. package/docs/api/appkit/Function.mcpServer.md +28 -0
  110. package/docs/api/appkit/Function.parseTextToolCalls.md +26 -0
  111. package/docs/api/appkit/Function.resolveHostedTools.md +16 -0
  112. package/docs/api/appkit/Function.runAgent.md +26 -0
  113. package/docs/api/appkit/Function.tool.md +28 -0
  114. package/docs/api/appkit/Function.toolsFromRegistry.md +20 -0
  115. package/docs/api/appkit/Interface.AgentAdapter.md +21 -0
  116. package/docs/api/appkit/Interface.AgentDefinition.md +112 -0
  117. package/docs/api/appkit/Interface.AgentInput.md +37 -0
  118. package/docs/api/appkit/Interface.AgentRunContext.md +32 -0
  119. package/docs/api/appkit/Interface.AgentToolDefinition.md +37 -0
  120. package/docs/api/appkit/Interface.AgentsPluginConfig.md +241 -0
  121. package/docs/api/appkit/Interface.AutoInheritToolsConfig.md +27 -0
  122. package/docs/api/appkit/Interface.BasePluginConfig.md +1 -0
  123. package/docs/api/appkit/Interface.FunctionTool.md +80 -0
  124. package/docs/api/appkit/Interface.McpConnectAllResult.md +38 -0
  125. package/docs/api/appkit/Interface.Message.md +55 -0
  126. package/docs/api/appkit/Interface.PluginToolkitProvider.md +22 -0
  127. package/docs/api/appkit/Interface.PromptContext.md +30 -0
  128. package/docs/api/appkit/Interface.RegisteredAgent.md +75 -0
  129. package/docs/api/appkit/Interface.RunAgentInput.md +34 -0
  130. package/docs/api/appkit/Interface.RunAgentResult.md +23 -0
  131. package/docs/api/appkit/Interface.Thread.md +46 -0
  132. package/docs/api/appkit/Interface.ThreadStore.md +103 -0
  133. package/docs/api/appkit/Interface.ToolAnnotations.md +56 -0
  134. package/docs/api/appkit/Interface.ToolConfig.md +72 -0
  135. package/docs/api/appkit/Interface.ToolEntry.md +73 -0
  136. package/docs/api/appkit/Interface.ToolProvider.md +38 -0
  137. package/docs/api/appkit/Interface.ToolkitEntry.md +59 -0
  138. package/docs/api/appkit/Interface.ToolkitOptions.md +45 -0
  139. package/docs/api/appkit/TypeAlias.AgentEvent.md +299 -0
  140. package/docs/api/appkit/TypeAlias.AgentTool.md +11 -0
  141. package/docs/api/appkit/TypeAlias.AgentTools.md +8 -0
  142. package/docs/api/appkit/TypeAlias.AgentToolsFn.md +20 -0
  143. package/docs/api/appkit/TypeAlias.BaseSystemPromptOption.md +9 -0
  144. package/docs/api/appkit/TypeAlias.HostedTool.md +10 -0
  145. package/docs/api/appkit/TypeAlias.Plugins.md +26 -0
  146. package/docs/api/appkit/TypeAlias.ResolvedToolEntry.md +29 -0
  147. package/docs/api/appkit/TypeAlias.ToolRegistry.md +6 -0
  148. package/docs/api/appkit/Variable.agents.md +19 -0
  149. package/docs/api/appkit.md +113 -62
  150. package/docs/plugins/agents.md +441 -0
  151. package/llms.txt +53 -1
  152. package/package.json +1 -1
  153. package/sbom.cdx.json +1 -1
package/CLAUDE.md CHANGED
@@ -43,6 +43,7 @@ npx @databricks/appkit docs <query>
43
43
 
44
44
  ## Plugins
45
45
 
46
+ - [Agents](./docs/plugins/agents.md): This plugin is currently beta. APIs may change between minor releases. Import from @databricks/appkit/beta. See Plugin Stability Tiers.
46
47
  - [Analytics plugin](./docs/plugins/analytics.md): Enables SQL query execution against Databricks SQL Warehouses.
47
48
  - [Caching](./docs/plugins/caching.md): AppKit provides both global and plugin-level caching capabilities.
48
49
  - [Creating custom plugins](./docs/plugins/custom-plugins.md): If you need custom API routes or background logic, implement an AppKit plugin. The fastest way is to use the CLI:
@@ -59,11 +60,13 @@ npx @databricks/appkit docs <query>
59
60
 
60
61
  ## appkit API reference [collapsed]
61
62
 
62
- - [@databricks/appkit](./docs/api/appkit.md): Core library for building Databricks applications with type-safe SQL queries,
63
+ - [@databricks/appkit](./docs/api/appkit.md): Documentation merge entry for Typedoc combines the stable @databricks/appkit
63
64
  - [Abstract Class: AppKitError](./docs/api/appkit/Class.AppKitError.md): Base error class for all AppKit errors.
65
+ - [Class: AppKitMcpClient](./docs/api/appkit/Class.AppKitMcpClient.md): Lightweight MCP client for Databricks-hosted MCP servers.
64
66
  - [Class: AuthenticationError](./docs/api/appkit/Class.AuthenticationError.md): Error thrown when authentication fails.
65
67
  - [Class: ConfigurationError](./docs/api/appkit/Class.ConfigurationError.md): Error thrown when configuration is missing or invalid.
66
68
  - [Class: ConnectionError](./docs/api/appkit/Class.ConnectionError.md): Error thrown when a connection or network operation fails.
69
+ - [Class: DatabricksAdapter](./docs/api/appkit/Class.DatabricksAdapter.md): Adapter that talks directly to Databricks Model Serving /invocations endpoint.
67
70
  - [Class: ExecutionError](./docs/api/appkit/Class.ExecutionError.md): Error thrown when an operation execution fails.
68
71
  - [Class: InitializationError](./docs/api/appkit/Class.InitializationError.md): Error thrown when a service or component is not properly initialized.
69
72
  - [Abstract Class: Plugin<TConfig>](./docs/api/appkit/Class.Plugin.md): Base abstract class for creating AppKit plugins.
@@ -74,12 +77,17 @@ npx @databricks/appkit docs <query>
74
77
  - [Class: ValidationError](./docs/api/appkit/Class.ValidationError.md): Error thrown when input validation fails.
75
78
  - [Enumeration: RequestedClaimsPermissionSet](./docs/api/appkit/Enumeration.RequestedClaimsPermissionSet.md): Permission set for Unity Catalog table access
76
79
  - [Enumeration: ResourceType](./docs/api/appkit/Enumeration.ResourceType.md): Resource types from schema $defs.resourceType.enum
80
+ - [Function: agentIdFromMarkdownPath()](./docs/api/appkit/Function.agentIdFromMarkdownPath.md): Derives the logical agent id from a markdown path. When the file is named
77
81
  - [Function: appKitServingTypesPlugin()](./docs/api/appkit/Function.appKitServingTypesPlugin.md): Vite plugin to generate TypeScript types for AppKit serving endpoints.
78
82
  - [Function: appKitTypesPlugin()](./docs/api/appkit/Function.appKitTypesPlugin.md): Vite plugin to generate types for AppKit queries.
83
+ - [Function: createAgent()](./docs/api/appkit/Function.createAgent.md): Pure factory for agent definitions. Returns the passed-in definition after
79
84
  - [Function: createApp()](./docs/api/appkit/Function.createApp.md): Bootstraps AppKit with the provided configuration.
80
85
  - [Function: createLakebasePool()](./docs/api/appkit/Function.createLakebasePool.md): Create a Lakebase pool with appkit's logger integration.
86
+ - [Function: defineTool()](./docs/api/appkit/Function.defineTool.md): Defines a single tool entry for a plugin's internal registry.
87
+ - [Function: executeFromRegistry()](./docs/api/appkit/Function.executeFromRegistry.md): Validates tool-call arguments against the entry's schema and invokes its
81
88
  - [Function: extractServingEndpoints()](./docs/api/appkit/Function.extractServingEndpoints.md): Extract serving endpoint config from a server file by AST-parsing it.
82
89
  - [Function: findServerFile()](./docs/api/appkit/Function.findServerFile.md): Find the server entry file by checking candidate paths in order.
90
+ - [Function: functionToolToDefinition()](./docs/api/appkit/Function.functionToolToDefinition.md): Parameters
83
91
  - [Function: generateDatabaseCredential()](./docs/api/appkit/Function.generateDatabaseCredential.md): Generate OAuth credentials for Postgres database connection using the proper Postgres API.
84
92
  - [Function: getExecutionContext()](./docs/api/appkit/Function.getExecutionContext.md): Get the current execution context.
85
93
  - [Function: getLakebaseOrmConfig()](./docs/api/appkit/Function.getLakebaseOrmConfig.md): Get Lakebase connection configuration for ORMs that don't accept pg.Pool directly.
@@ -88,13 +96,32 @@ npx @databricks/appkit docs <query>
88
96
  - [Function: getResourceRequirements()](./docs/api/appkit/Function.getResourceRequirements.md): Gets the resource requirements from a plugin's manifest.
89
97
  - [Function: getUsernameWithApiLookup()](./docs/api/appkit/Function.getUsernameWithApiLookup.md): Resolves the PostgreSQL username for a Lakebase connection.
90
98
  - [Function: getWorkspaceClient()](./docs/api/appkit/Function.getWorkspaceClient.md): Get workspace client from config or SDK default auth chain
99
+ - [Function: isFunctionTool()](./docs/api/appkit/Function.isFunctionTool.md): Parameters
100
+ - [Function: isHostedTool()](./docs/api/appkit/Function.isHostedTool.md): Parameters
91
101
  - [Function: isSQLTypeMarker()](./docs/api/appkit/Function.isSQLTypeMarker.md): Type guard to check if a value is a SQL type marker
102
+ - [Function: isToolkitEntry()](./docs/api/appkit/Function.isToolkitEntry.md): Type guard for ToolkitEntry — used by the agents plugin to differentiate
103
+ - [Function: loadAgentFromFile()](./docs/api/appkit/Function.loadAgentFromFile.md): Loads a single markdown agent file and resolves its frontmatter against
104
+ - [Function: loadAgentsFromDir()](./docs/api/appkit/Function.loadAgentsFromDir.md): Scans a directory for one subdirectory per agent, each containing
105
+ - [Function: mcpServer()](./docs/api/appkit/Function.mcpServer.md): Factory for declaring a custom MCP server tool.
106
+ - [Function: parseTextToolCalls()](./docs/api/appkit/Function.parseTextToolCalls.md): Parses text-based tool calls from model output.
107
+ - [Function: resolveHostedTools()](./docs/api/appkit/Function.resolveHostedTools.md): Parameters
108
+ - [Function: runAgent()](./docs/api/appkit/Function.runAgent.md): Standalone agent execution without createApp. Resolves the adapter, binds
109
+ - [Function: tool()](./docs/api/appkit/Function.tool.md): Factory for defining function tools with Zod schemas.
110
+ - [Function: toolsFromRegistry()](./docs/api/appkit/Function.toolsFromRegistry.md): Produces the AgentToolDefinition[] a ToolProvider exposes to the LLM,
111
+ - [Interface: AgentAdapter](./docs/api/appkit/Interface.AgentAdapter.md): Methods
112
+ - [Interface: AgentDefinition](./docs/api/appkit/Interface.AgentDefinition.md): Properties
113
+ - [Interface: AgentInput](./docs/api/appkit/Interface.AgentInput.md): Properties
114
+ - [Interface: AgentRunContext](./docs/api/appkit/Interface.AgentRunContext.md): Properties
115
+ - [Interface: AgentsPluginConfig](./docs/api/appkit/Interface.AgentsPluginConfig.md): Base configuration interface for AppKit plugins
116
+ - [Interface: AgentToolDefinition](./docs/api/appkit/Interface.AgentToolDefinition.md): Properties
117
+ - [Interface: AutoInheritToolsConfig](./docs/api/appkit/Interface.AutoInheritToolsConfig.md): Auto-inherit configuration. When enabled for a given agent origin, agents
92
118
  - [Interface: BasePluginConfig](./docs/api/appkit/Interface.BasePluginConfig.md): Base configuration interface for AppKit plugins
93
119
  - [Interface: CacheConfig](./docs/api/appkit/Interface.CacheConfig.md): Configuration for the CacheInterceptor. Controls TTL, size limits, storage backend, and probabilistic cleanup.
94
120
  - [Interface: DatabaseCredential](./docs/api/appkit/Interface.DatabaseCredential.md): Database credentials with OAuth token for Postgres connection
95
121
  - [Interface: EndpointConfig](./docs/api/appkit/Interface.EndpointConfig.md): Properties
96
122
  - [Interface: FilePolicyUser](./docs/api/appkit/Interface.FilePolicyUser.md): Minimal user identity passed to the policy function.
97
123
  - [Interface: FileResource](./docs/api/appkit/Interface.FileResource.md): Describes the file or directory being acted upon.
124
+ - [Interface: FunctionTool](./docs/api/appkit/Interface.FunctionTool.md): Properties
98
125
  - [Interface: GenerateDatabaseCredentialRequest](./docs/api/appkit/Interface.GenerateDatabaseCredentialRequest.md): Request parameters for generating database OAuth credentials
99
126
  - [Interface: IJobsConfig](./docs/api/appkit/Interface.IJobsConfig.md): Configuration for the Jobs plugin.
100
127
  - [Interface: ITelemetry](./docs/api/appkit/Interface.ITelemetry.md): Plugin-facing interface for OpenTelemetry instrumentation.
@@ -102,28 +129,53 @@ npx @databricks/appkit docs <query>
102
129
  - [Interface: JobConfig](./docs/api/appkit/Interface.JobConfig.md): Per-job configuration options.
103
130
  - [Interface: JobsConnectorConfig](./docs/api/appkit/Interface.JobsConnectorConfig.md): Properties
104
131
  - [Interface: LakebasePoolConfig](./docs/api/appkit/Interface.LakebasePoolConfig.md): Configuration for creating a Lakebase connection pool
132
+ - [Interface: McpConnectAllResult](./docs/api/appkit/Interface.McpConnectAllResult.md): Per-endpoint outcome of AppKitMcpClient.connectAll. Callers (the
133
+ - [Interface: Message](./docs/api/appkit/Interface.Message.md): Properties
105
134
  - [Interface: PluginManifest<TName>](./docs/api/appkit/Interface.PluginManifest.md): Plugin manifest that declares metadata and resource requirements.
135
+ - [Interface: PluginToolkitProvider](./docs/api/appkit/Interface.PluginToolkitProvider.md): Minimum shape every entry in the Plugins map must expose. Core
136
+ - [Interface: PromptContext](./docs/api/appkit/Interface.PromptContext.md): Context passed to baseSystemPrompt callbacks.
137
+ - [Interface: RegisteredAgent](./docs/api/appkit/Interface.RegisteredAgent.md): Properties
106
138
  - [Interface: RequestedClaims](./docs/api/appkit/Interface.RequestedClaims.md): Optional claims for fine-grained Unity Catalog table permissions
107
139
  - [Interface: RequestedResource](./docs/api/appkit/Interface.RequestedResource.md): Resource to request permissions for in Unity Catalog
108
140
  - [Interface: ResourceEntry](./docs/api/appkit/Interface.ResourceEntry.md): Internal representation of a resource in the registry.
109
141
  - [Interface: ResourceFieldEntry](./docs/api/appkit/Interface.ResourceFieldEntry.md): Defines a single field for a resource. Each field has its own environment variable and optional description. Single-value types use one key (e.g. id); multi-value types (database, secret) use multiple (e.g. instancename, databasename or scope, key).
110
142
  - [Interface: ResourceRequirement](./docs/api/appkit/Interface.ResourceRequirement.md): Declares a resource requirement for a plugin.
143
+ - [Interface: RunAgentInput](./docs/api/appkit/Interface.RunAgentInput.md): Properties
144
+ - [Interface: RunAgentResult](./docs/api/appkit/Interface.RunAgentResult.md): Properties
111
145
  - [Interface: ServingEndpointEntry](./docs/api/appkit/Interface.ServingEndpointEntry.md): Shape of a single registry entry.
112
146
  - [Interface: ServingEndpointRegistry](./docs/api/appkit/Interface.ServingEndpointRegistry.md): Registry interface for serving endpoint type generation.
113
147
  - [Interface: StreamExecutionSettings](./docs/api/appkit/Interface.StreamExecutionSettings.md): Execution settings for streaming endpoints. Extends PluginExecutionSettings with SSE stream configuration.
114
148
  - [Interface: TelemetryConfig](./docs/api/appkit/Interface.TelemetryConfig.md): OpenTelemetry configuration for AppKit applications
149
+ - [Interface: Thread](./docs/api/appkit/Interface.Thread.md): Properties
150
+ - [Interface: ThreadStore](./docs/api/appkit/Interface.ThreadStore.md): Methods
151
+ - [Interface: ToolAnnotations](./docs/api/appkit/Interface.ToolAnnotations.md): Properties
152
+ - [Interface: ToolConfig<S>](./docs/api/appkit/Interface.ToolConfig.md): Type Parameters
153
+ - [Interface: ToolEntry<S>](./docs/api/appkit/Interface.ToolEntry.md): Single-tool entry for a plugin's internal tool registry.
154
+ - [Interface: ToolkitEntry](./docs/api/appkit/Interface.ToolkitEntry.md): A tool reference produced by a plugin's .toolkit() call. The agents plugin
155
+ - [Interface: ToolkitOptions](./docs/api/appkit/Interface.ToolkitOptions.md): Properties
156
+ - [Interface: ToolProvider](./docs/api/appkit/Interface.ToolProvider.md): Methods
115
157
  - [Interface: ValidationResult](./docs/api/appkit/Interface.ValidationResult.md): Result of validating all registered resources against the environment.
158
+ - [Type Alias: AgentEvent](./docs/api/appkit/TypeAlias.AgentEvent.md): Type Declaration
159
+ - [Type Alias: AgentTool](./docs/api/appkit/TypeAlias.AgentTool.md): Any tool an agent can invoke: inline function tools (tool()), hosted MCP
160
+ - [Type Alias: AgentTools](./docs/api/appkit/TypeAlias.AgentTools.md): Per-agent tool record. String keys map to inline tools, toolkit entries,
161
+ - [Type Alias: AgentToolsFn()](./docs/api/appkit/TypeAlias.AgentToolsFn.md): Function form of AgentDefinition.tools. Receives the typed
162
+ - [Type Alias: BaseSystemPromptOption](./docs/api/appkit/TypeAlias.BaseSystemPromptOption.md)
116
163
  - [Type Alias: ConfigSchema](./docs/api/appkit/TypeAlias.ConfigSchema.md): Configuration schema definition for plugin config.
117
164
  - [Type Alias: ExecutionResult<T>](./docs/api/appkit/TypeAlias.ExecutionResult.md): Discriminated union for plugin execution results.
118
165
  - [Type Alias: FileAction](./docs/api/appkit/TypeAlias.FileAction.md): Every action the files plugin can perform.
119
166
  - [Type Alias: FilePolicy()](./docs/api/appkit/TypeAlias.FilePolicy.md): A policy function that decides whether user may perform action on
167
+ - [Type Alias: HostedTool](./docs/api/appkit/TypeAlias.HostedTool.md)
120
168
  - [Type Alias: IAppRouter](./docs/api/appkit/TypeAlias.IAppRouter.md): Express router type for plugin route registration
121
169
  - [Type Alias: JobHandle](./docs/api/appkit/TypeAlias.JobHandle.md): Job handle returned by appkit.jobs("etl").
122
170
  - [Type Alias: JobsExport()](./docs/api/appkit/TypeAlias.JobsExport.md): Public API shape of the jobs plugin.
123
171
  - [Type Alias: PluginData<T, U, N>](./docs/api/appkit/TypeAlias.PluginData.md): Tuple of plugin class, config, and name. Created by toPlugin() and passed to createApp().
172
+ - [Type Alias: Plugins](./docs/api/appkit/TypeAlias.Plugins.md): Plugin map passed to the function form of AgentDefinition.tools.
173
+ - [Type Alias: ResolvedToolEntry](./docs/api/appkit/TypeAlias.ResolvedToolEntry.md): Internal tool-index entry after a tool record has been resolved to a dispatchable form.
124
174
  - [Type Alias: ResourcePermission](./docs/api/appkit/TypeAlias.ResourcePermission.md): Union of all possible permission levels across all resource types.
125
175
  - [Type Alias: ServingFactory](./docs/api/appkit/TypeAlias.ServingFactory.md): Factory function returned by AppKit.serving.
176
+ - [Type Alias: ToolRegistry](./docs/api/appkit/TypeAlias.ToolRegistry.md)
126
177
  - [Type Alias: ToPlugin()<T, U, N>](./docs/api/appkit/TypeAlias.ToPlugin.md): Factory function type returned by toPlugin(). Accepts optional config and returns a PluginData tuple.
178
+ - [Variable: agents](./docs/api/appkit/Variable.agents.md): Plugin factory for the agents plugin. Reads config/agents/*.md by default,
127
179
  - [Variable: READ_ACTIONS](./docs/api/appkit/Variable.READ_ACTIONS.md): Actions that only read data.
128
180
  - [Variable: sql](./docs/api/appkit/Variable.sql.md): SQL helper namespace
129
181
  - [Variable: WRITE_ACTIONS](./docs/api/appkit/Variable.WRITE_ACTIONS.md): Actions that mutate data.
package/NOTICE.md CHANGED
@@ -66,6 +66,7 @@ This Software contains code from the following open source projects:
66
66
  | [express](https://www.npmjs.com/package/express) | 4.22.0 | MIT | http://expressjs.com/ |
67
67
  | [get-port](https://www.npmjs.com/package/get-port) | 7.2.0 | MIT | https://github.com/sindresorhus/get-port#readme |
68
68
  | [input-otp](https://www.npmjs.com/package/input-otp) | 1.4.2 | MIT | https://input-otp.rodz.dev/ |
69
+ | [js-yaml](https://www.npmjs.com/package/js-yaml) | 3.14.2, 4.1.1 | MIT | https://github.com/nodeca/js-yaml#readme |
69
70
  | [lucide-react](https://www.npmjs.com/package/lucide-react) | 0.554.0 | ISC | https://lucide.dev |
70
71
  | [marked](https://www.npmjs.com/package/marked) | 16.4.2, 17.0.3 | MIT | https://marked.js.org |
71
72
  | [next-themes](https://www.npmjs.com/package/next-themes) | 0.4.6 | MIT | https://github.com/pacocoursey/next-themes#readme |
@@ -1 +1 @@
1
- {"version":3,"file":"databricks.d.ts","names":[],"sources":["../../src/agents/databricks.ts"],"mappings":";;;;;;;AAMgB;;;KAgEX,UAAA,IACH,IAAA,EAAM,MAAA,mBACN,MAAA,GAAS,WAAA,KACN,OAAA,CAAQ,cAAA,CAAe,UAAA;;;;;;UAOlB,sBAAA;EACR,WAAA;EACA,YAAA,QAAoB,OAAA,CAAQ,MAAA;EAC5B,QAAA;EACA,SAAA;EAXG;EAaH,eAAA;EAb0B;EAe1B,kBAAA;EAfoC;EAiBpC,qBAAA;AAAA;;;;;;;UASQ,wBAAA;EACR,UAAA,EAAY,UAAA;EACZ,QAAA;EACA,SAAA;EACA,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;AAAA,KAGG,wBAAA,GACD,sBAAA,GACA,wBAAA;;;;;;;;UAeM,mBAAA;EACR,SAAA;IACE,OAAA,CAAQ,OAAA,EAAS,MAAA,oBAA0B,OAAA;EAAA;AAAA;AAAA,UAIrC,sBAAA;EACR,eAAA,EAAiB,mBAAA;EACjB,YAAA;EACA,QAAA;EACA,SAAA;EACA,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;AAAA,UAGQ,mBAAA;EACR,QAAA;EACA,SAAA;EACA,eAAA,GAAkB,mBAAA;EAClB,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;;;;;;;;;;;;;AATqB;;;;;;;;;;;;;AAoFvB;;;;;;;;;;;;;;;;;;cAAa,iBAAA,YAA6B,YAAA;EAAA,QAChC,UAAA;EAAA,QACA,QAAA;EAAA,QACA,SAAA;EAAA,QACA,eAAA;EAAA,QACA,kBAAA;EAAA,QACA,qBAAA;cAEI,OAAA,EAAS,wBAAA;EAAT;;;;;;;;EAAA,OA+CC,mBAAA,CACX,OAAA,EAAS,sBAAA,GACR,OAAA,CAAQ,iBAAA;EAmDT;;;;;;;;;;;;;;;;;AA+YJ;;;EA/YI,OAFW,gBAAA,CACX,YAAA,WACA,OAAA,GAAU,mBAAA,GACT,OAAA,CAAQ,iBAAA;EA+BJ,GAAA,CACL,KAAA,EAAO,UAAA,EACP,OAAA,EAAS,eAAA,GACR,cAAA,CAAe,UAAA;EA8WjB;EAAA,QAvTc,iBAAA;EAAA,QA8CA,gBAAA;EAAA,QA4JA,gBAAA;EA6GY;;;;;EAAA,QAzEnB,aAAA;EAAA,QA6CA,UAAA;AAAA;;;;;;;;iBA0BM,kBAAA,CACd,IAAA,WACC,KAAA;EAAQ,IAAA;EAAc,IAAA;AAAA"}
1
+ {"version":3,"file":"databricks.d.ts","names":[],"sources":["../../src/agents/databricks.ts"],"mappings":";;;;;;;AAMgB;;;KAgEX,UAAA,IACH,IAAA,EAAM,MAAA,mBACN,MAAA,GAAS,WAAA,KACN,OAAA,CAAQ,cAAA,CAAe,UAAA;;;;;;UAOlB,sBAAA;EACR,WAAA;EACA,YAAA,QAAoB,OAAA,CAAQ,MAAA;EAC5B,QAAA;EACA,SAAA;EAXG;EAaH,eAAA;EAb0B;EAe1B,kBAAA;EAfoC;EAiBpC,qBAAA;AAAA;;;;;;;UASQ,wBAAA;EACR,UAAA,EAAY,UAAA;EACZ,QAAA;EACA,SAAA;EACA,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;AAAA,KAGG,wBAAA,GACD,sBAAA,GACA,wBAAA;;;;;;;;UAeM,mBAAA;EACR,SAAA;IACE,OAAA,CAAQ,OAAA,EAAS,MAAA,oBAA0B,OAAA;EAAA;AAAA;AAAA,UAIrC,sBAAA;EACR,eAAA,EAAiB,mBAAA;EACjB,YAAA;EACA,QAAA;EACA,SAAA;EACA,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;AAAA,UAGQ,mBAAA;EACR,QAAA;EACA,SAAA;EACA,eAAA,GAAkB,mBAAA;EAClB,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;;;;;;;;;;;;;AATqB;;;;;;;;;;;;;AAiGvB;;;;;;;;;;;;;;;;;;cAAa,iBAAA,YAA6B,YAAA;EAAA,QAChC,UAAA;EAAA,QACA,QAAA;EAAA,QACA,SAAA;EAAA,QACA,eAAA;EAAA,QACA,kBAAA;EAAA,QACA,qBAAA;cAEI,OAAA,EAAS,wBAAA;EAAT;;;;;;;;EAAA,OA+CC,mBAAA,CACX,OAAA,EAAS,sBAAA,GACR,OAAA,CAAQ,iBAAA;EAmDT;;;;;;;;;;;;;;;;;AA6ZJ;;;EA7ZI,OAFW,gBAAA,CACX,YAAA,WACA,OAAA,GAAU,mBAAA,GACT,OAAA,CAAQ,iBAAA;EA+BJ,GAAA,CACL,KAAA,EAAO,UAAA,EACP,OAAA,EAAS,eAAA,GACR,cAAA,CAAe,UAAA;EA4XjB;EAAA,QArUc,iBAAA;EAAA,QA8CA,gBAAA;EAAA,QAuKA,gBAAA;EAgHY;;;;;EAAA,QA5EnB,aAAA;EAAA,QAgDA,UAAA;AAAA;;;;;;;;iBA0BM,kBAAA,CACd,IAAA,WACC,KAAA;EAAQ,IAAA;EAAc,IAAA;AAAA"}
@@ -314,19 +314,22 @@ var DatabricksAdapter = class DatabricksAdapter {
314
314
  if (!Array.isArray(toolCallsRaw)) continue;
315
315
  for (const tc of toolCallsRaw) {
316
316
  if (!isStreamingDeltaToolCall(tc)) continue;
317
+ const sig = tc.thoughtSignature;
317
318
  const existing = toolCallAccumulator.get(tc.index);
318
319
  if (existing) {
319
320
  if (tc.function?.arguments) {
320
321
  throwIfExceedsStreamLimit("tool call arguments", existing.arguments.length, tc.function.arguments, this.maxToolArgumentsChars);
321
322
  existing.arguments += tc.function.arguments;
322
323
  }
324
+ if (sig && !existing.thoughtSignature) existing.thoughtSignature = sig;
323
325
  } else {
324
326
  const initial = tc.function?.arguments ?? "";
325
327
  if (initial.length > this.maxToolArgumentsChars) throw new Error(`DatabricksAdapter: tool call arguments exceed configured limit (${this.maxToolArgumentsChars} UTF-16 code units)`);
326
328
  toolCallAccumulator.set(tc.index, {
327
329
  id: tc.id ?? `call_${tc.index}`,
328
330
  name: tc.function?.name ?? "",
329
- arguments: initial
331
+ arguments: initial,
332
+ ...sig ? { thoughtSignature: sig } : {}
330
333
  });
331
334
  }
332
335
  }
@@ -350,7 +353,8 @@ var DatabricksAdapter = class DatabricksAdapter {
350
353
  function: {
351
354
  name: tc.name,
352
355
  arguments: tc.arguments || "{}"
353
- }
356
+ },
357
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
354
358
  }));
355
359
  return {
356
360
  text: fullText,
@@ -399,7 +403,8 @@ var DatabricksAdapter = class DatabricksAdapter {
399
403
  function: {
400
404
  name: wireToolName(tc.name),
401
405
  arguments: typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args ?? {})
402
- }
406
+ },
407
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
403
408
  }));
404
409
  return out;
405
410
  });
@@ -1 +1 @@
1
- {"version":3,"file":"databricks.js","names":["servingStream"],"sources":["../../src/agents/databricks.ts"],"sourcesContent":["import type {\n AgentAdapter,\n AgentEvent,\n AgentInput,\n AgentRunContext,\n AgentToolDefinition,\n} from \"shared\";\nimport { stream as servingStream } from \"../connectors/serving/client\";\n\n/** Default cap for a single incomplete SSE line tail (DoS guard). */\nconst DEFAULT_MAX_SSE_LINE_CHARS = 1024 * 1024;\n\n/** Default cap for accumulated assistant text from `delta.content`. */\nconst DEFAULT_MAX_STREAM_TEXT_CHARS = 4 * 1024 * 1024;\n\n/** Default cap for accumulated JSON arguments per streamed tool call index. */\nconst DEFAULT_MAX_TOOL_ARGUMENT_CHARS = 2 * 1024 * 1024;\n\n/** Cap text length before running Python-style tool-call regex (ReDoS guard). */\nconst PYTHON_STYLE_TOOL_PARSE_MAX_INPUT = 64 * 1024;\n\n/** Fallback HTTP timeout when the raw fetch adapter path receives no AbortSignal from the runner. */\nconst RAW_FETCH_DEFAULT_TIMEOUT_MS = 120_000;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction extractLlamaToolJsonSlice(text: string): string | undefined {\n const start = text.indexOf(\"[{\");\n if (start < 0) return undefined;\n const endBracket = text.lastIndexOf(\"}]\");\n if (endBracket < start) return undefined;\n return text.slice(start, endBracket + 2);\n}\n\n/** OpenAI SSE payload: `{ choices: [{ delta }] }`. */\nfunction openAiChoicesDelta(parsed: unknown): unknown {\n if (!isRecord(parsed)) return undefined;\n const choices = parsed.choices;\n if (!Array.isArray(choices) || choices.length < 1) return undefined;\n const first = choices[0];\n if (!isRecord(first)) return undefined;\n return first.delta;\n}\n\nfunction isStreamingDeltaToolCall(value: unknown): value is DeltaToolCall {\n if (!isRecord(value)) return false;\n return typeof value.index === \"number\";\n}\n\nfunction throwIfExceedsStreamLimit(\n label: string,\n currentLength: number,\n chunk: string,\n max: number,\n): void {\n if (currentLength + chunk.length > max) {\n throw new Error(\n `DatabricksAdapter: ${label} exceeds configured limit (${max} UTF-16 code units)`,\n );\n }\n}\n\n/**\n * Transport shim: given an OpenAI-compatible request body, returns the raw\n * SSE byte stream from the serving endpoint. Injected at construction time so\n * callers can swap in the workspace SDK (factory paths), a bare `fetch`\n * (the raw constructor), or a test fake.\n */\ntype StreamBody = (\n body: Record<string, unknown>,\n signal?: AbortSignal,\n) => Promise<ReadableStream<Uint8Array>>;\n\n/**\n * Escape-hatch options: provide an `endpointUrl` + `authenticate()` and the\n * adapter uses a bare `fetch()` to call it. Useful for tests and for pointing\n * the adapter at non-workspace endpoints (reverse proxies, mocks).\n */\ninterface RawFetchAdapterOptions {\n endpointUrl: string;\n authenticate: () => Promise<Record<string, string>>;\n maxSteps?: number;\n maxTokens?: number;\n /** Max length of one SSE line (including an incomplete tail in the buffer). */\n maxSseLineChars?: number;\n /** Max total length of assistant `delta.content` across the stream. */\n maxStreamTextChars?: number;\n /** Max length of streamed `function.arguments` per tool call index. */\n maxToolArgumentsChars?: number;\n}\n\n/**\n * Preferred options: caller provides the transport function directly.\n * The `fromServingEndpoint` / `fromModelServing` factories use this to route\n * through `connectors/serving/stream`, which centralises URL encoding, auth\n * via the SDK's `apiClient.request`, and any future retries/telemetry.\n */\ninterface StreamBodyAdapterOptions {\n streamBody: StreamBody;\n maxSteps?: number;\n maxTokens?: number;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ntype DatabricksAdapterOptions =\n | RawFetchAdapterOptions\n | StreamBodyAdapterOptions;\n\nfunction isStreamBodyOptions(\n o: DatabricksAdapterOptions,\n): o is StreamBodyAdapterOptions {\n return \"streamBody\" in o;\n}\n\n/**\n * Duck-typed subset of the Databricks SDK `WorkspaceClient`. Callers of\n * `fromServingEndpoint` and `fromModelServing` pass a real `WorkspaceClient`,\n * but we only need the `apiClient.request` surface — so we declare the minimal\n * interface rather than importing the SDK type directly. This keeps the adapter\n * free of a hard compile-time dependency on `@databricks/sdk-experimental`.\n */\ninterface WorkspaceClientLike {\n apiClient: {\n request(options: Record<string, unknown>): Promise<unknown>;\n };\n}\n\ninterface ServingEndpointOptions {\n workspaceClient: WorkspaceClientLike;\n endpointName: string;\n maxSteps?: number;\n maxTokens?: number;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ninterface ModelServingOptions {\n maxSteps?: number;\n maxTokens?: number;\n workspaceClient?: WorkspaceClientLike;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ninterface OpenAIMessage {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string | null;\n tool_calls?: OpenAIToolCall[];\n tool_call_id?: string;\n}\n\ninterface OpenAIToolCall {\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n}\n\ninterface OpenAITool {\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: unknown;\n };\n}\n\ninterface DeltaToolCall {\n index: number;\n id?: string;\n type?: string;\n function?: { name?: string; arguments?: string };\n}\n\n/**\n * Adapter that talks directly to Databricks Model Serving `/invocations` endpoint.\n *\n * No dependency on the Vercel AI SDK or LangChain. Uses raw `fetch()` to POST\n * OpenAI-compatible payloads and parses the SSE stream itself. Calls\n * `authenticate()` per-request so tokens are always fresh.\n *\n * Handles both structured `tool_calls` responses and text-based tool call\n * fallback parsing for models that output tool calls as text.\n *\n * @example Using the factory (recommended)\n * ```ts\n * import { createApp, createAgent, agents } from \"@databricks/appkit\";\n * import { DatabricksAdapter } from \"@databricks/appkit/beta\";\n * import { WorkspaceClient } from \"@databricks/sdk-experimental\";\n *\n * const adapter = DatabricksAdapter.fromServingEndpoint({\n * workspaceClient: new WorkspaceClient({}),\n * endpointName: \"my-endpoint\",\n * });\n *\n * await createApp({\n * plugins: [\n * agents({\n * agents: {\n * assistant: createAgent({\n * instructions: \"You are a helpful assistant.\",\n * model: adapter,\n * }),\n * },\n * }),\n * ],\n * });\n * ```\n *\n * @example Using the raw constructor\n * ```ts\n * const adapter = new DatabricksAdapter({\n * endpointUrl: \"https://host/serving-endpoints/my-endpoint/invocations\",\n * authenticate: async () => ({ Authorization: `Bearer ${token}` }),\n * });\n * ```\n */\nexport class DatabricksAdapter implements AgentAdapter {\n private streamBody: StreamBody;\n private maxSteps: number;\n private maxTokens: number;\n private maxSseLineChars: number;\n private maxStreamTextChars: number;\n private maxToolArgumentsChars: number;\n\n constructor(options: DatabricksAdapterOptions) {\n this.maxSteps = options.maxSteps ?? 10;\n this.maxTokens = options.maxTokens ?? 4096;\n this.maxSseLineChars =\n options.maxSseLineChars ?? DEFAULT_MAX_SSE_LINE_CHARS;\n this.maxStreamTextChars =\n options.maxStreamTextChars ?? DEFAULT_MAX_STREAM_TEXT_CHARS;\n this.maxToolArgumentsChars =\n options.maxToolArgumentsChars ?? DEFAULT_MAX_TOOL_ARGUMENT_CHARS;\n\n if (isStreamBodyOptions(options)) {\n this.streamBody = options.streamBody;\n } else {\n const { endpointUrl, authenticate } = options;\n this.streamBody = async (body, signal) => {\n const fetchSignal =\n signal ?? AbortSignal.timeout(RAW_FETCH_DEFAULT_TIMEOUT_MS);\n const authHeaders = await authenticate();\n const response = await fetch(endpointUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...authHeaders,\n },\n body: JSON.stringify(body),\n signal: fetchSignal,\n });\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"Unknown error\");\n throw new Error(\n `Databricks API error (${response.status}): ${errorText}`,\n );\n }\n if (!response.body) throw new Error(\"No response body\");\n return response.body;\n };\n }\n }\n\n /**\n * Creates a DatabricksAdapter for a Databricks Model Serving endpoint.\n *\n * Routes through the shared `connectors/serving/stream` helper, which\n * delegates to the SDK's `apiClient.request({ raw: true })`. That gives the\n * adapter centralised URL encoding + authentication with the rest of the\n * serving surface — no bespoke `fetch()` + `authenticate()` plumbing.\n */\n static async fromServingEndpoint(\n options: ServingEndpointOptions,\n ): Promise<DatabricksAdapter> {\n const {\n workspaceClient,\n endpointName,\n maxSteps,\n maxTokens,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n } = options;\n return new DatabricksAdapter({\n streamBody: (body, signal) =>\n // Cast through the structural shape: the connector types\n // `workspaceClient` as the SDK's concrete `WorkspaceClient`, but we\n // only need `apiClient.request`.\n servingStream(\n workspaceClient as unknown as Parameters<typeof servingStream>[0],\n endpointName,\n body,\n signal,\n ),\n maxSteps,\n maxTokens,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n });\n }\n\n /**\n * Creates a DatabricksAdapter from a Model Serving endpoint name.\n * Auto-creates a WorkspaceClient internally. Reads the endpoint name\n * from the argument or the `DATABRICKS_SERVING_ENDPOINT_NAME` env var.\n *\n * @example\n * ```ts\n * // Reads endpoint from DATABRICKS_SERVING_ENDPOINT_NAME env var\n * const adapter = await DatabricksAdapter.fromModelServing();\n *\n * // Explicit endpoint\n * const adapter = await DatabricksAdapter.fromModelServing(\"my-endpoint\");\n *\n * // With options\n * const adapter = await DatabricksAdapter.fromModelServing(\"my-endpoint\", {\n * maxSteps: 5,\n * maxTokens: 2048,\n * });\n * ```\n */\n static async fromModelServing(\n endpointName?: string,\n options?: ModelServingOptions,\n ): Promise<DatabricksAdapter> {\n const resolvedEndpoint =\n endpointName ?? process.env.DATABRICKS_SERVING_ENDPOINT_NAME;\n\n if (!resolvedEndpoint) {\n throw new Error(\n \"No endpoint name provided and DATABRICKS_SERVING_ENDPOINT_NAME env var is not set. \" +\n \"Pass an endpoint name or set DATABRICKS_SERVING_ENDPOINT_NAME.\",\n );\n }\n\n let workspaceClient: WorkspaceClientLike | undefined =\n options?.workspaceClient;\n if (!workspaceClient) {\n const sdk = await import(\"@databricks/sdk-experimental\");\n workspaceClient = new sdk.WorkspaceClient(\n {},\n ) as unknown as WorkspaceClientLike;\n }\n\n return DatabricksAdapter.fromServingEndpoint({\n workspaceClient,\n endpointName: resolvedEndpoint,\n maxSteps: options?.maxSteps,\n maxTokens: options?.maxTokens,\n maxSseLineChars: options?.maxSseLineChars,\n maxStreamTextChars: options?.maxStreamTextChars,\n maxToolArgumentsChars: options?.maxToolArgumentsChars,\n });\n }\n\n async *run(\n input: AgentInput,\n context: AgentRunContext,\n ): AsyncGenerator<AgentEvent, void, unknown> {\n // Databricks API requires tool names to match [a-zA-Z0-9_-].\n // Our tool names use dots (e.g. \"analytics.query\"), so we swap dots\n // for double-underscores in the wire format and map back on receipt.\n const nameToWire = new Map<string, string>();\n const wireToName = new Map<string, string>();\n for (const tool of input.tools) {\n const wire = tool.name.replace(/\\./g, \"__\");\n if (wireToName.has(wire) && wireToName.get(wire) !== tool.name) {\n throw new Error(\n `Tool name collision: '${tool.name}' and '${wireToName.get(wire)}' both map to wire name '${wire}'`,\n );\n }\n nameToWire.set(tool.name, wire);\n wireToName.set(wire, tool.name);\n }\n\n const tools = this.buildTools(input.tools, nameToWire);\n const messages = this.buildMessages(input.messages, nameToWire);\n\n yield { type: \"status\", status: \"running\" };\n\n for (let step = 0; step < this.maxSteps; step++) {\n if (context.signal?.aborted) break;\n\n const { text, toolCalls } = yield* this.streamCompletion(\n messages,\n tools,\n context,\n );\n\n if (toolCalls.length === 0) {\n const parsed = parseTextToolCalls(text);\n if (parsed.length > 0) {\n yield* this.executeToolCalls(parsed, messages, context, nameToWire);\n continue;\n }\n break;\n }\n\n messages.push({\n role: \"assistant\",\n content: text || null,\n tool_calls: toolCalls,\n });\n\n for (const tc of toolCalls) {\n const wireName = tc.function.name;\n const originalName = wireToName.get(wireName) ?? wireName;\n yield* this.executeSingleTool(tc, originalName, messages, context);\n }\n }\n }\n\n /** Parse wire arguments, emit tool_call / tool_result, append tool messages. */\n private async *executeSingleTool(\n tc: OpenAIToolCall,\n originalName: string,\n messages: OpenAIMessage[],\n context: AgentRunContext,\n ): AsyncGenerator<AgentEvent, void, unknown> {\n let args: unknown;\n try {\n args = JSON.parse(tc.function.arguments);\n } catch {\n args = {};\n }\n\n yield { type: \"tool_call\", callId: tc.id, name: originalName, args };\n\n try {\n const result = await context.executeTool(originalName, args);\n const resultStr =\n typeof result === \"string\" ? result : JSON.stringify(result);\n\n yield { type: \"tool_result\", callId: tc.id, result };\n\n messages.push({\n role: \"tool\",\n content: resultStr,\n tool_call_id: tc.id,\n });\n } catch (error) {\n const errMsg =\n error instanceof Error ? error.message : \"Tool execution failed\";\n\n yield {\n type: \"tool_result\",\n callId: tc.id,\n result: null,\n error: errMsg,\n };\n\n messages.push({\n role: \"tool\",\n content: JSON.stringify({ error: errMsg }),\n tool_call_id: tc.id,\n });\n }\n }\n\n private async *streamCompletion(\n messages: OpenAIMessage[],\n tools: OpenAITool[],\n context: AgentRunContext,\n ): AsyncGenerator<\n AgentEvent,\n { text: string; toolCalls: OpenAIToolCall[] },\n unknown\n > {\n const body: Record<string, unknown> = {\n messages,\n stream: true,\n max_tokens: this.maxTokens,\n };\n\n if (tools.length > 0) {\n body.tools = tools;\n }\n\n let responseBody: ReadableStream<Uint8Array>;\n try {\n responseBody = await this.streamBody(body, context.signal);\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Stream request failed\";\n yield { type: \"status\", status: \"error\", error: msg };\n throw err;\n }\n\n const reader = responseBody.getReader();\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let fullText = \"\";\n const toolCallAccumulator = new Map<\n number,\n { id: string; name: string; arguments: string }\n >();\n\n try {\n while (true) {\n if (context.signal?.aborted) break;\n\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n if (buffer.length > this.maxSseLineChars) {\n throw new Error(\n `DatabricksAdapter: SSE line buffer exceeds configured limit (${this.maxSseLineChars} UTF-16 code units)`,\n );\n }\n\n for (const line of lines) {\n if (line.length > this.maxSseLineChars) {\n throw new Error(\n `DatabricksAdapter: SSE line exceeds configured limit (${this.maxSseLineChars} UTF-16 code units)`,\n );\n }\n\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"data: \")) continue;\n const data = trimmed.slice(6);\n if (data === \"[DONE]\") continue;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(data);\n } catch (parseErr) {\n console.debug(\n \"[DatabricksAdapter] malformed SSE data line JSON\",\n { line: `${data.slice(0, 256)}${data.length > 256 ? \"…\" : \"\"}` },\n parseErr,\n );\n continue;\n }\n\n const deltaUnknown = openAiChoicesDelta(parsed);\n if (!isRecord(deltaUnknown)) continue;\n\n if (typeof deltaUnknown.content === \"string\") {\n const content = deltaUnknown.content;\n throwIfExceedsStreamLimit(\n \"streamed assistant text\",\n fullText.length,\n content,\n this.maxStreamTextChars,\n );\n fullText += content;\n yield { type: \"message_delta\" as const, content };\n }\n\n const toolCallsRaw = deltaUnknown.tool_calls;\n if (!Array.isArray(toolCallsRaw)) continue;\n\n for (const tc of toolCallsRaw) {\n if (!isStreamingDeltaToolCall(tc)) continue;\n const existing = toolCallAccumulator.get(tc.index);\n if (existing) {\n if (tc.function?.arguments) {\n throwIfExceedsStreamLimit(\n \"tool call arguments\",\n existing.arguments.length,\n tc.function.arguments,\n this.maxToolArgumentsChars,\n );\n existing.arguments += tc.function.arguments;\n }\n } else {\n const initial = tc.function?.arguments ?? \"\";\n if (initial.length > this.maxToolArgumentsChars) {\n throw new Error(\n `DatabricksAdapter: tool call arguments exceed configured limit (${this.maxToolArgumentsChars} UTF-16 code units)`,\n );\n }\n toolCallAccumulator.set(tc.index, {\n id: tc.id ?? `call_${tc.index}`,\n name: tc.function?.name ?? \"\",\n arguments: initial,\n });\n }\n }\n }\n }\n } finally {\n try {\n await reader.cancel();\n } catch (cancelErr) {\n console.debug(\n \"[DatabricksAdapter] reader.cancel() failed during teardown\",\n cancelErr,\n );\n }\n try {\n reader.releaseLock();\n } catch (unlockErr) {\n console.debug(\n \"[DatabricksAdapter] reader.releaseLock() failed during teardown\",\n unlockErr,\n );\n }\n }\n\n const toolCalls: OpenAIToolCall[] = Array.from(\n toolCallAccumulator.values(),\n ).map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: { name: tc.name, arguments: tc.arguments || \"{}\" },\n }));\n\n return { text: fullText, toolCalls };\n }\n\n private async *executeToolCalls(\n calls: Array<{ name: string; args: unknown }>,\n messages: OpenAIMessage[],\n context: AgentRunContext,\n nameToWire: Map<string, string>,\n ): AsyncGenerator<AgentEvent, void, unknown> {\n const wireToolName = (name: string) =>\n nameToWire.get(name) ?? name.replace(/\\./g, \"__\");\n\n const toolCallObjs: OpenAIToolCall[] = calls.map((c, i) => ({\n id: `text_call_${i}`,\n type: \"function\" as const,\n function: {\n name: wireToolName(c.name),\n arguments: JSON.stringify(c.args),\n },\n }));\n\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: toolCallObjs,\n });\n\n for (let i = 0; i < toolCallObjs.length; i++) {\n const tc = toolCallObjs[i];\n const originalName = calls[i]?.name ?? tc.function.name;\n yield* this.executeSingleTool(tc, originalName, messages, context);\n }\n }\n\n /**\n * Maps AppKit {@link AgentInput} messages into OpenAI-compatible wire messages.\n * Preserves multi-turn tool state (`toolCalls` → `tool_calls`, `toolCallId` →\n * `tool_call_id`) so resumed threads and hydrated history reach the model.\n */\n private buildMessages(\n messages: AgentInput[\"messages\"],\n nameToWire: Map<string, string>,\n ): OpenAIMessage[] {\n const wireToolName = (name: string) =>\n nameToWire.get(name) ?? name.replace(/\\./g, \"__\");\n\n return messages.map((m) => {\n let content: string | null = m.content;\n if (\n m.role === \"assistant\" &&\n m.toolCalls &&\n m.toolCalls.length > 0 &&\n (!m.content || m.content.trim() === \"\")\n ) {\n content = null;\n }\n\n const out: OpenAIMessage = {\n role: m.role as OpenAIMessage[\"role\"],\n content,\n };\n\n if (m.toolCallId) {\n out.tool_call_id = m.toolCallId;\n }\n\n if (m.toolCalls && m.toolCalls.length > 0) {\n out.tool_calls = m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: {\n name: wireToolName(tc.name),\n arguments:\n typeof tc.args === \"string\"\n ? tc.args\n : JSON.stringify(tc.args ?? {}),\n },\n }));\n }\n\n return out;\n });\n }\n\n private buildTools(\n definitions: AgentToolDefinition[],\n nameToWire: Map<string, string>,\n ): OpenAITool[] {\n return definitions.map((def) => ({\n type: \"function\" as const,\n function: {\n name: nameToWire.get(def.name) ?? def.name,\n description: def.description,\n parameters: def.parameters,\n },\n }));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Text-based tool call parsing (fallback)\n// ---------------------------------------------------------------------------\n\n/**\n * Parses text-based tool calls from model output.\n *\n * Handles two formats:\n * 1. Llama native: `[{\"name\": \"tool_name\", \"parameters\": {\"arg\": \"val\"}}]`\n * 2. Python-style: `[tool_name(arg1='val1', arg2='val2')]`\n */\nexport function parseTextToolCalls(\n text: string,\n): Array<{ name: string; args: unknown }> {\n const trimmed = text.trim();\n\n const jsonResult = tryParseLlamaJsonToolCalls(trimmed);\n if (jsonResult.length > 0) return jsonResult;\n\n const pyResult = tryParsePythonStyleToolCalls(trimmed);\n if (pyResult.length > 0) return pyResult;\n\n return [];\n}\n\nfunction isLlamaToolJsonItem(value: unknown): value is Record<\n string,\n unknown\n> & {\n name: string;\n} {\n if (!isRecord(value)) return false;\n return typeof value.name === \"string\";\n}\n\nfunction tryParseLlamaJsonToolCalls(\n text: string,\n): Array<{ name: string; args: unknown }> {\n const slice = extractLlamaToolJsonSlice(text);\n if (!slice) return [];\n\n try {\n const parsed: unknown = JSON.parse(slice);\n if (!Array.isArray(parsed)) return [];\n\n return parsed.filter(isLlamaToolJsonItem).map((item) => ({\n name: item.name,\n args: item.parameters ?? item.arguments ?? item.args ?? {},\n }));\n } catch {\n return [];\n }\n}\n\nfunction tryParsePythonStyleToolCalls(\n text: string,\n): Array<{ name: string; args: unknown }> {\n if (text.length > PYTHON_STYLE_TOOL_PARSE_MAX_INPUT) {\n return [];\n }\n\n const pattern = /\\[?([a-zA-Z_][\\w.]*)\\(([^)]*)\\)\\]?/g;\n const results: Array<{ name: string; args: unknown }> = [];\n\n for (const match of text.matchAll(pattern)) {\n const name = match[1];\n const argsStr = match[2];\n\n const args: Record<string, unknown> = {};\n const argPattern = /(\\w+)\\s*=\\s*(?:'([^']*)'|\"([^\"]*)\"|(\\S+))/g;\n for (const argMatch of argsStr.matchAll(argPattern)) {\n const key = argMatch[1];\n const value = argMatch[2] ?? argMatch[3] ?? argMatch[4];\n args[key] = value;\n }\n\n results.push({ name, args });\n }\n\n return results;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"databricks.js","names":["servingStream"],"sources":["../../src/agents/databricks.ts"],"sourcesContent":["import type {\n AgentAdapter,\n AgentEvent,\n AgentInput,\n AgentRunContext,\n AgentToolDefinition,\n} from \"shared\";\nimport { stream as servingStream } from \"../connectors/serving/client\";\n\n/** Default cap for a single incomplete SSE line tail (DoS guard). */\nconst DEFAULT_MAX_SSE_LINE_CHARS = 1024 * 1024;\n\n/** Default cap for accumulated assistant text from `delta.content`. */\nconst DEFAULT_MAX_STREAM_TEXT_CHARS = 4 * 1024 * 1024;\n\n/** Default cap for accumulated JSON arguments per streamed tool call index. */\nconst DEFAULT_MAX_TOOL_ARGUMENT_CHARS = 2 * 1024 * 1024;\n\n/** Cap text length before running Python-style tool-call regex (ReDoS guard). */\nconst PYTHON_STYLE_TOOL_PARSE_MAX_INPUT = 64 * 1024;\n\n/** Fallback HTTP timeout when the raw fetch adapter path receives no AbortSignal from the runner. */\nconst RAW_FETCH_DEFAULT_TIMEOUT_MS = 120_000;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction extractLlamaToolJsonSlice(text: string): string | undefined {\n const start = text.indexOf(\"[{\");\n if (start < 0) return undefined;\n const endBracket = text.lastIndexOf(\"}]\");\n if (endBracket < start) return undefined;\n return text.slice(start, endBracket + 2);\n}\n\n/** OpenAI SSE payload: `{ choices: [{ delta }] }`. */\nfunction openAiChoicesDelta(parsed: unknown): unknown {\n if (!isRecord(parsed)) return undefined;\n const choices = parsed.choices;\n if (!Array.isArray(choices) || choices.length < 1) return undefined;\n const first = choices[0];\n if (!isRecord(first)) return undefined;\n return first.delta;\n}\n\nfunction isStreamingDeltaToolCall(value: unknown): value is DeltaToolCall {\n if (!isRecord(value)) return false;\n return typeof value.index === \"number\";\n}\n\nfunction throwIfExceedsStreamLimit(\n label: string,\n currentLength: number,\n chunk: string,\n max: number,\n): void {\n if (currentLength + chunk.length > max) {\n throw new Error(\n `DatabricksAdapter: ${label} exceeds configured limit (${max} UTF-16 code units)`,\n );\n }\n}\n\n/**\n * Transport shim: given an OpenAI-compatible request body, returns the raw\n * SSE byte stream from the serving endpoint. Injected at construction time so\n * callers can swap in the workspace SDK (factory paths), a bare `fetch`\n * (the raw constructor), or a test fake.\n */\ntype StreamBody = (\n body: Record<string, unknown>,\n signal?: AbortSignal,\n) => Promise<ReadableStream<Uint8Array>>;\n\n/**\n * Escape-hatch options: provide an `endpointUrl` + `authenticate()` and the\n * adapter uses a bare `fetch()` to call it. Useful for tests and for pointing\n * the adapter at non-workspace endpoints (reverse proxies, mocks).\n */\ninterface RawFetchAdapterOptions {\n endpointUrl: string;\n authenticate: () => Promise<Record<string, string>>;\n maxSteps?: number;\n maxTokens?: number;\n /** Max length of one SSE line (including an incomplete tail in the buffer). */\n maxSseLineChars?: number;\n /** Max total length of assistant `delta.content` across the stream. */\n maxStreamTextChars?: number;\n /** Max length of streamed `function.arguments` per tool call index. */\n maxToolArgumentsChars?: number;\n}\n\n/**\n * Preferred options: caller provides the transport function directly.\n * The `fromServingEndpoint` / `fromModelServing` factories use this to route\n * through `connectors/serving/stream`, which centralises URL encoding, auth\n * via the SDK's `apiClient.request`, and any future retries/telemetry.\n */\ninterface StreamBodyAdapterOptions {\n streamBody: StreamBody;\n maxSteps?: number;\n maxTokens?: number;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ntype DatabricksAdapterOptions =\n | RawFetchAdapterOptions\n | StreamBodyAdapterOptions;\n\nfunction isStreamBodyOptions(\n o: DatabricksAdapterOptions,\n): o is StreamBodyAdapterOptions {\n return \"streamBody\" in o;\n}\n\n/**\n * Duck-typed subset of the Databricks SDK `WorkspaceClient`. Callers of\n * `fromServingEndpoint` and `fromModelServing` pass a real `WorkspaceClient`,\n * but we only need the `apiClient.request` surface — so we declare the minimal\n * interface rather than importing the SDK type directly. This keeps the adapter\n * free of a hard compile-time dependency on `@databricks/sdk-experimental`.\n */\ninterface WorkspaceClientLike {\n apiClient: {\n request(options: Record<string, unknown>): Promise<unknown>;\n };\n}\n\ninterface ServingEndpointOptions {\n workspaceClient: WorkspaceClientLike;\n endpointName: string;\n maxSteps?: number;\n maxTokens?: number;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ninterface ModelServingOptions {\n maxSteps?: number;\n maxTokens?: number;\n workspaceClient?: WorkspaceClientLike;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ninterface OpenAIMessage {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string | null;\n tool_calls?: OpenAIToolCall[];\n tool_call_id?: string;\n}\n\ninterface OpenAIToolCall {\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n /**\n * Opaque Vertex/Gemini \"thought signature\" blob the request must echo\n * back verbatim on the next turn. Vertex's OpenAI-compat proxy emits\n * this as `thoughtSignature` (camelCase) at the top level of the\n * tool_call delta (verified against `gemini-3.1-flash-lite-preview`),\n * and accepts the same spelling back on outbound. Non-Gemini endpoints\n * (Claude on Databricks, external OpenAI-compat models, Llama, etc.)\n * leave this undefined and the serializer omits the key.\n * See https://docs.cloud.google.com/vertex-ai/generative-ai/docs/thought-signatures\n */\n thoughtSignature?: string;\n}\n\ninterface OpenAITool {\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: unknown;\n };\n}\n\ninterface DeltaToolCall {\n index: number;\n id?: string;\n type?: string;\n function?: { name?: string; arguments?: string };\n /** See {@link OpenAIToolCall.thoughtSignature}. */\n thoughtSignature?: string;\n}\n\n/**\n * Adapter that talks directly to Databricks Model Serving `/invocations` endpoint.\n *\n * No dependency on the Vercel AI SDK or LangChain. Uses raw `fetch()` to POST\n * OpenAI-compatible payloads and parses the SSE stream itself. Calls\n * `authenticate()` per-request so tokens are always fresh.\n *\n * Handles both structured `tool_calls` responses and text-based tool call\n * fallback parsing for models that output tool calls as text.\n *\n * @example Using the factory (recommended)\n * ```ts\n * import { createApp, createAgent, agents } from \"@databricks/appkit\";\n * import { DatabricksAdapter } from \"@databricks/appkit/beta\";\n * import { WorkspaceClient } from \"@databricks/sdk-experimental\";\n *\n * const adapter = DatabricksAdapter.fromServingEndpoint({\n * workspaceClient: new WorkspaceClient({}),\n * endpointName: \"my-endpoint\",\n * });\n *\n * await createApp({\n * plugins: [\n * agents({\n * agents: {\n * assistant: createAgent({\n * instructions: \"You are a helpful assistant.\",\n * model: adapter,\n * }),\n * },\n * }),\n * ],\n * });\n * ```\n *\n * @example Using the raw constructor\n * ```ts\n * const adapter = new DatabricksAdapter({\n * endpointUrl: \"https://host/serving-endpoints/my-endpoint/invocations\",\n * authenticate: async () => ({ Authorization: `Bearer ${token}` }),\n * });\n * ```\n */\nexport class DatabricksAdapter implements AgentAdapter {\n private streamBody: StreamBody;\n private maxSteps: number;\n private maxTokens: number;\n private maxSseLineChars: number;\n private maxStreamTextChars: number;\n private maxToolArgumentsChars: number;\n\n constructor(options: DatabricksAdapterOptions) {\n this.maxSteps = options.maxSteps ?? 10;\n this.maxTokens = options.maxTokens ?? 4096;\n this.maxSseLineChars =\n options.maxSseLineChars ?? DEFAULT_MAX_SSE_LINE_CHARS;\n this.maxStreamTextChars =\n options.maxStreamTextChars ?? DEFAULT_MAX_STREAM_TEXT_CHARS;\n this.maxToolArgumentsChars =\n options.maxToolArgumentsChars ?? DEFAULT_MAX_TOOL_ARGUMENT_CHARS;\n\n if (isStreamBodyOptions(options)) {\n this.streamBody = options.streamBody;\n } else {\n const { endpointUrl, authenticate } = options;\n this.streamBody = async (body, signal) => {\n const fetchSignal =\n signal ?? AbortSignal.timeout(RAW_FETCH_DEFAULT_TIMEOUT_MS);\n const authHeaders = await authenticate();\n const response = await fetch(endpointUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...authHeaders,\n },\n body: JSON.stringify(body),\n signal: fetchSignal,\n });\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"Unknown error\");\n throw new Error(\n `Databricks API error (${response.status}): ${errorText}`,\n );\n }\n if (!response.body) throw new Error(\"No response body\");\n return response.body;\n };\n }\n }\n\n /**\n * Creates a DatabricksAdapter for a Databricks Model Serving endpoint.\n *\n * Routes through the shared `connectors/serving/stream` helper, which\n * delegates to the SDK's `apiClient.request({ raw: true })`. That gives the\n * adapter centralised URL encoding + authentication with the rest of the\n * serving surface — no bespoke `fetch()` + `authenticate()` plumbing.\n */\n static async fromServingEndpoint(\n options: ServingEndpointOptions,\n ): Promise<DatabricksAdapter> {\n const {\n workspaceClient,\n endpointName,\n maxSteps,\n maxTokens,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n } = options;\n return new DatabricksAdapter({\n streamBody: (body, signal) =>\n // Cast through the structural shape: the connector types\n // `workspaceClient` as the SDK's concrete `WorkspaceClient`, but we\n // only need `apiClient.request`.\n servingStream(\n workspaceClient as unknown as Parameters<typeof servingStream>[0],\n endpointName,\n body,\n signal,\n ),\n maxSteps,\n maxTokens,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n });\n }\n\n /**\n * Creates a DatabricksAdapter from a Model Serving endpoint name.\n * Auto-creates a WorkspaceClient internally. Reads the endpoint name\n * from the argument or the `DATABRICKS_SERVING_ENDPOINT_NAME` env var.\n *\n * @example\n * ```ts\n * // Reads endpoint from DATABRICKS_SERVING_ENDPOINT_NAME env var\n * const adapter = await DatabricksAdapter.fromModelServing();\n *\n * // Explicit endpoint\n * const adapter = await DatabricksAdapter.fromModelServing(\"my-endpoint\");\n *\n * // With options\n * const adapter = await DatabricksAdapter.fromModelServing(\"my-endpoint\", {\n * maxSteps: 5,\n * maxTokens: 2048,\n * });\n * ```\n */\n static async fromModelServing(\n endpointName?: string,\n options?: ModelServingOptions,\n ): Promise<DatabricksAdapter> {\n const resolvedEndpoint =\n endpointName ?? process.env.DATABRICKS_SERVING_ENDPOINT_NAME;\n\n if (!resolvedEndpoint) {\n throw new Error(\n \"No endpoint name provided and DATABRICKS_SERVING_ENDPOINT_NAME env var is not set. \" +\n \"Pass an endpoint name or set DATABRICKS_SERVING_ENDPOINT_NAME.\",\n );\n }\n\n let workspaceClient: WorkspaceClientLike | undefined =\n options?.workspaceClient;\n if (!workspaceClient) {\n const sdk = await import(\"@databricks/sdk-experimental\");\n workspaceClient = new sdk.WorkspaceClient(\n {},\n ) as unknown as WorkspaceClientLike;\n }\n\n return DatabricksAdapter.fromServingEndpoint({\n workspaceClient,\n endpointName: resolvedEndpoint,\n maxSteps: options?.maxSteps,\n maxTokens: options?.maxTokens,\n maxSseLineChars: options?.maxSseLineChars,\n maxStreamTextChars: options?.maxStreamTextChars,\n maxToolArgumentsChars: options?.maxToolArgumentsChars,\n });\n }\n\n async *run(\n input: AgentInput,\n context: AgentRunContext,\n ): AsyncGenerator<AgentEvent, void, unknown> {\n // Databricks API requires tool names to match [a-zA-Z0-9_-].\n // Our tool names use dots (e.g. \"analytics.query\"), so we swap dots\n // for double-underscores in the wire format and map back on receipt.\n const nameToWire = new Map<string, string>();\n const wireToName = new Map<string, string>();\n for (const tool of input.tools) {\n const wire = tool.name.replace(/\\./g, \"__\");\n if (wireToName.has(wire) && wireToName.get(wire) !== tool.name) {\n throw new Error(\n `Tool name collision: '${tool.name}' and '${wireToName.get(wire)}' both map to wire name '${wire}'`,\n );\n }\n nameToWire.set(tool.name, wire);\n wireToName.set(wire, tool.name);\n }\n\n const tools = this.buildTools(input.tools, nameToWire);\n const messages = this.buildMessages(input.messages, nameToWire);\n\n yield { type: \"status\", status: \"running\" };\n\n for (let step = 0; step < this.maxSteps; step++) {\n if (context.signal?.aborted) break;\n\n const { text, toolCalls } = yield* this.streamCompletion(\n messages,\n tools,\n context,\n );\n\n if (toolCalls.length === 0) {\n const parsed = parseTextToolCalls(text);\n if (parsed.length > 0) {\n yield* this.executeToolCalls(parsed, messages, context, nameToWire);\n continue;\n }\n break;\n }\n\n messages.push({\n role: \"assistant\",\n content: text || null,\n tool_calls: toolCalls,\n });\n\n for (const tc of toolCalls) {\n const wireName = tc.function.name;\n const originalName = wireToName.get(wireName) ?? wireName;\n yield* this.executeSingleTool(tc, originalName, messages, context);\n }\n }\n }\n\n /** Parse wire arguments, emit tool_call / tool_result, append tool messages. */\n private async *executeSingleTool(\n tc: OpenAIToolCall,\n originalName: string,\n messages: OpenAIMessage[],\n context: AgentRunContext,\n ): AsyncGenerator<AgentEvent, void, unknown> {\n let args: unknown;\n try {\n args = JSON.parse(tc.function.arguments);\n } catch {\n args = {};\n }\n\n yield { type: \"tool_call\", callId: tc.id, name: originalName, args };\n\n try {\n const result = await context.executeTool(originalName, args);\n const resultStr =\n typeof result === \"string\" ? result : JSON.stringify(result);\n\n yield { type: \"tool_result\", callId: tc.id, result };\n\n messages.push({\n role: \"tool\",\n content: resultStr,\n tool_call_id: tc.id,\n });\n } catch (error) {\n const errMsg =\n error instanceof Error ? error.message : \"Tool execution failed\";\n\n yield {\n type: \"tool_result\",\n callId: tc.id,\n result: null,\n error: errMsg,\n };\n\n messages.push({\n role: \"tool\",\n content: JSON.stringify({ error: errMsg }),\n tool_call_id: tc.id,\n });\n }\n }\n\n private async *streamCompletion(\n messages: OpenAIMessage[],\n tools: OpenAITool[],\n context: AgentRunContext,\n ): AsyncGenerator<\n AgentEvent,\n { text: string; toolCalls: OpenAIToolCall[] },\n unknown\n > {\n const body: Record<string, unknown> = {\n messages,\n stream: true,\n max_tokens: this.maxTokens,\n };\n\n if (tools.length > 0) {\n body.tools = tools;\n }\n\n let responseBody: ReadableStream<Uint8Array>;\n try {\n responseBody = await this.streamBody(body, context.signal);\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Stream request failed\";\n yield { type: \"status\", status: \"error\", error: msg };\n throw err;\n }\n\n const reader = responseBody.getReader();\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let fullText = \"\";\n const toolCallAccumulator = new Map<\n number,\n {\n id: string;\n name: string;\n arguments: string;\n thoughtSignature?: string;\n }\n >();\n\n try {\n while (true) {\n if (context.signal?.aborted) break;\n\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n if (buffer.length > this.maxSseLineChars) {\n throw new Error(\n `DatabricksAdapter: SSE line buffer exceeds configured limit (${this.maxSseLineChars} UTF-16 code units)`,\n );\n }\n\n for (const line of lines) {\n if (line.length > this.maxSseLineChars) {\n throw new Error(\n `DatabricksAdapter: SSE line exceeds configured limit (${this.maxSseLineChars} UTF-16 code units)`,\n );\n }\n\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"data: \")) continue;\n const data = trimmed.slice(6);\n if (data === \"[DONE]\") continue;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(data);\n } catch (parseErr) {\n console.debug(\n \"[DatabricksAdapter] malformed SSE data line JSON\",\n { line: `${data.slice(0, 256)}${data.length > 256 ? \"…\" : \"\"}` },\n parseErr,\n );\n continue;\n }\n\n const deltaUnknown = openAiChoicesDelta(parsed);\n if (!isRecord(deltaUnknown)) continue;\n\n if (typeof deltaUnknown.content === \"string\") {\n const content = deltaUnknown.content;\n throwIfExceedsStreamLimit(\n \"streamed assistant text\",\n fullText.length,\n content,\n this.maxStreamTextChars,\n );\n fullText += content;\n yield { type: \"message_delta\" as const, content };\n }\n\n const toolCallsRaw = deltaUnknown.tool_calls;\n if (!Array.isArray(toolCallsRaw)) continue;\n\n for (const tc of toolCallsRaw) {\n if (!isStreamingDeltaToolCall(tc)) continue;\n const sig = tc.thoughtSignature;\n const existing = toolCallAccumulator.get(tc.index);\n if (existing) {\n if (tc.function?.arguments) {\n throwIfExceedsStreamLimit(\n \"tool call arguments\",\n existing.arguments.length,\n tc.function.arguments,\n this.maxToolArgumentsChars,\n );\n existing.arguments += tc.function.arguments;\n }\n if (sig && !existing.thoughtSignature) {\n existing.thoughtSignature = sig;\n }\n } else {\n const initial = tc.function?.arguments ?? \"\";\n if (initial.length > this.maxToolArgumentsChars) {\n throw new Error(\n `DatabricksAdapter: tool call arguments exceed configured limit (${this.maxToolArgumentsChars} UTF-16 code units)`,\n );\n }\n toolCallAccumulator.set(tc.index, {\n id: tc.id ?? `call_${tc.index}`,\n name: tc.function?.name ?? \"\",\n arguments: initial,\n ...(sig ? { thoughtSignature: sig } : {}),\n });\n }\n }\n }\n }\n } finally {\n try {\n await reader.cancel();\n } catch (cancelErr) {\n console.debug(\n \"[DatabricksAdapter] reader.cancel() failed during teardown\",\n cancelErr,\n );\n }\n try {\n reader.releaseLock();\n } catch (unlockErr) {\n console.debug(\n \"[DatabricksAdapter] reader.releaseLock() failed during teardown\",\n unlockErr,\n );\n }\n }\n\n const toolCalls: OpenAIToolCall[] = Array.from(\n toolCallAccumulator.values(),\n ).map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: { name: tc.name, arguments: tc.arguments || \"{}\" },\n ...(tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}),\n }));\n\n return { text: fullText, toolCalls };\n }\n\n private async *executeToolCalls(\n calls: Array<{ name: string; args: unknown }>,\n messages: OpenAIMessage[],\n context: AgentRunContext,\n nameToWire: Map<string, string>,\n ): AsyncGenerator<AgentEvent, void, unknown> {\n const wireToolName = (name: string) =>\n nameToWire.get(name) ?? name.replace(/\\./g, \"__\");\n\n const toolCallObjs: OpenAIToolCall[] = calls.map((c, i) => ({\n id: `text_call_${i}`,\n type: \"function\" as const,\n function: {\n name: wireToolName(c.name),\n arguments: JSON.stringify(c.args),\n },\n }));\n\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: toolCallObjs,\n });\n\n for (let i = 0; i < toolCallObjs.length; i++) {\n const tc = toolCallObjs[i];\n const originalName = calls[i]?.name ?? tc.function.name;\n yield* this.executeSingleTool(tc, originalName, messages, context);\n }\n }\n\n /**\n * Maps AppKit {@link AgentInput} messages into OpenAI-compatible wire messages.\n * Preserves multi-turn tool state (`toolCalls` → `tool_calls`, `toolCallId` →\n * `tool_call_id`) so resumed threads and hydrated history reach the model.\n */\n private buildMessages(\n messages: AgentInput[\"messages\"],\n nameToWire: Map<string, string>,\n ): OpenAIMessage[] {\n const wireToolName = (name: string) =>\n nameToWire.get(name) ?? name.replace(/\\./g, \"__\");\n\n return messages.map((m) => {\n let content: string | null = m.content;\n if (\n m.role === \"assistant\" &&\n m.toolCalls &&\n m.toolCalls.length > 0 &&\n (!m.content || m.content.trim() === \"\")\n ) {\n content = null;\n }\n\n const out: OpenAIMessage = {\n role: m.role as OpenAIMessage[\"role\"],\n content,\n };\n\n if (m.toolCallId) {\n out.tool_call_id = m.toolCallId;\n }\n\n if (m.toolCalls && m.toolCalls.length > 0) {\n out.tool_calls = m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: {\n name: wireToolName(tc.name),\n arguments:\n typeof tc.args === \"string\"\n ? tc.args\n : JSON.stringify(tc.args ?? {}),\n },\n ...(tc.thoughtSignature\n ? { thoughtSignature: tc.thoughtSignature }\n : {}),\n }));\n }\n\n return out;\n });\n }\n\n private buildTools(\n definitions: AgentToolDefinition[],\n nameToWire: Map<string, string>,\n ): OpenAITool[] {\n return definitions.map((def) => ({\n type: \"function\" as const,\n function: {\n name: nameToWire.get(def.name) ?? def.name,\n description: def.description,\n parameters: def.parameters,\n },\n }));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Text-based tool call parsing (fallback)\n// ---------------------------------------------------------------------------\n\n/**\n * Parses text-based tool calls from model output.\n *\n * Handles two formats:\n * 1. Llama native: `[{\"name\": \"tool_name\", \"parameters\": {\"arg\": \"val\"}}]`\n * 2. Python-style: `[tool_name(arg1='val1', arg2='val2')]`\n */\nexport function parseTextToolCalls(\n text: string,\n): Array<{ name: string; args: unknown }> {\n const trimmed = text.trim();\n\n const jsonResult = tryParseLlamaJsonToolCalls(trimmed);\n if (jsonResult.length > 0) return jsonResult;\n\n const pyResult = tryParsePythonStyleToolCalls(trimmed);\n if (pyResult.length > 0) return pyResult;\n\n return [];\n}\n\nfunction isLlamaToolJsonItem(value: unknown): value is Record<\n string,\n unknown\n> & {\n name: string;\n} {\n if (!isRecord(value)) return false;\n return typeof value.name === \"string\";\n}\n\nfunction tryParseLlamaJsonToolCalls(\n text: string,\n): Array<{ name: string; args: unknown }> {\n const slice = extractLlamaToolJsonSlice(text);\n if (!slice) return [];\n\n try {\n const parsed: unknown = JSON.parse(slice);\n if (!Array.isArray(parsed)) return [];\n\n return parsed.filter(isLlamaToolJsonItem).map((item) => ({\n name: item.name,\n args: item.parameters ?? item.arguments ?? item.args ?? {},\n }));\n } catch {\n return [];\n }\n}\n\nfunction tryParsePythonStyleToolCalls(\n text: string,\n): Array<{ name: string; args: unknown }> {\n if (text.length > PYTHON_STYLE_TOOL_PARSE_MAX_INPUT) {\n return [];\n }\n\n const pattern = /\\[?([a-zA-Z_][\\w.]*)\\(([^)]*)\\)\\]?/g;\n const results: Array<{ name: string; args: unknown }> = [];\n\n for (const match of text.matchAll(pattern)) {\n const name = match[1];\n const argsStr = match[2];\n\n const args: Record<string, unknown> = {};\n const argPattern = /(\\w+)\\s*=\\s*(?:'([^']*)'|\"([^\"]*)\"|(\\S+))/g;\n for (const argMatch of argsStr.matchAll(argPattern)) {\n const key = argMatch[1];\n const value = argMatch[2] ?? argMatch[3] ?? argMatch[4];\n args[key] = value;\n }\n\n results.push({ name, args });\n }\n\n return results;\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  //#region package.json
2
2
  var name = "@databricks/appkit";
3
- var version = "0.32.0";
3
+ var version = "0.33.0";
4
4
 
5
5
  //#endregion
6
6
  export { name, version };
package/dist/beta.d.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  import { AgentAdapter, AgentEvent, AgentInput, AgentRunContext, AgentToolDefinition, Message, Thread, ThreadStore, ToolAnnotations, ToolProvider } from "./shared/src/agent.js";
2
2
  import "./shared/src/index.js";
3
3
  import { DatabricksAdapter, parseTextToolCalls } from "./agents/databricks.js";
4
- import { AppKitMcpClient } from "./connectors/mcp/client.js";
4
+ import { AppKitMcpClient, McpConnectAllResult } from "./connectors/mcp/client.js";
5
5
  import { FunctionTool, functionToolToDefinition, isFunctionTool } from "./core/agent/tools/function-tool.js";
6
6
  import { HostedTool, isHostedTool, mcpServer, resolveHostedTools } from "./core/agent/tools/hosted-tools.js";
7
- import { AgentDefinition, AgentTool, AgentsPluginConfig, AutoInheritToolsConfig, BaseSystemPromptOption, PromptContext, RegisteredAgent, ResolvedToolEntry, ToolkitEntry, ToolkitOptions, isToolkitEntry } from "./core/agent/types.js";
7
+ import { AgentDefinition, AgentTool, AgentTools, AgentToolsFn, AgentsPluginConfig, AutoInheritToolsConfig, BaseSystemPromptOption, PluginToolkitProvider, Plugins, PromptContext, RegisteredAgent, ResolvedToolEntry, ToolkitEntry, ToolkitOptions, isToolkitEntry } from "./core/agent/types.js";
8
8
  import { createAgent } from "./core/agent/create-agent.js";
9
9
  import { RunAgentInput, RunAgentResult, runAgent } from "./core/agent/run-agent.js";
10
10
  import { ToolEntry, ToolRegistry, defineTool, executeFromRegistry, toolsFromRegistry } from "./core/agent/tools/define-tool.js";
11
11
  import { ToolConfig, tool } from "./core/agent/tools/tool.js";
12
12
  import "./core/agent/tools/index.js";
13
13
  import { agentIdFromMarkdownPath, loadAgentFromFile, loadAgentsFromDir } from "./core/agent/load-agents.js";
14
+ import { agents } from "./plugins/agents/agents.js";
14
15
  import "./plugins/agents/index.js";
15
- export { type AgentAdapter, type AgentDefinition, type AgentEvent, type AgentInput, type AgentRunContext, type AgentTool, type AgentToolDefinition, type AgentsPluginConfig, AppKitMcpClient, type AutoInheritToolsConfig, type BaseSystemPromptOption, DatabricksAdapter, type FunctionTool, type HostedTool, type Message, type PromptContext, type RegisteredAgent, type ResolvedToolEntry, type RunAgentInput, type RunAgentResult, type Thread, type ThreadStore, type ToolAnnotations, type ToolConfig, type ToolEntry, type ToolProvider, type ToolRegistry, type ToolkitEntry, type ToolkitOptions, agentIdFromMarkdownPath, createAgent, defineTool, executeFromRegistry, functionToolToDefinition, isFunctionTool, isHostedTool, isToolkitEntry, loadAgentFromFile, loadAgentsFromDir, mcpServer, parseTextToolCalls, resolveHostedTools, runAgent, tool, toolsFromRegistry };
16
+ import "./plugins/beta-exports.generated.js";
17
+ export { type AgentAdapter, type AgentDefinition, type AgentEvent, type AgentInput, type AgentRunContext, type AgentTool, type AgentToolDefinition, type AgentTools, type AgentToolsFn, type AgentsPluginConfig, AppKitMcpClient, type AutoInheritToolsConfig, type BaseSystemPromptOption, DatabricksAdapter, type FunctionTool, type HostedTool, type McpConnectAllResult, type Message, type PluginToolkitProvider, type Plugins, type PromptContext, type RegisteredAgent, type ResolvedToolEntry, type RunAgentInput, type RunAgentResult, type Thread, type ThreadStore, type ToolAnnotations, type ToolConfig, type ToolEntry, type ToolProvider, type ToolRegistry, type ToolkitEntry, type ToolkitOptions, agentIdFromMarkdownPath, agents, createAgent, defineTool, executeFromRegistry, functionToolToDefinition, isFunctionTool, isHostedTool, isToolkitEntry, loadAgentFromFile, loadAgentsFromDir, mcpServer, parseTextToolCalls, resolveHostedTools, runAgent, tool, toolsFromRegistry };
package/dist/beta.js CHANGED
@@ -9,6 +9,8 @@ import { isToolkitEntry } from "./core/agent/types.js";
9
9
  import { runAgent } from "./core/agent/run-agent.js";
10
10
  import "./core/agent/tools/index.js";
11
11
  import { agentIdFromMarkdownPath, loadAgentFromFile, loadAgentsFromDir } from "./core/agent/load-agents.js";
12
+ import { agents } from "./plugins/agents/agents.js";
12
13
  import "./plugins/agents/index.js";
14
+ import "./plugins/beta-exports.generated.js";
13
15
 
14
- export { AppKitMcpClient, DatabricksAdapter, agentIdFromMarkdownPath, createAgent, defineTool, executeFromRegistry, functionToolToDefinition, isFunctionTool, isHostedTool, isToolkitEntry, loadAgentFromFile, loadAgentsFromDir, mcpServer, parseTextToolCalls, resolveHostedTools, runAgent, tool, toolsFromRegistry };
16
+ export { AppKitMcpClient, DatabricksAdapter, agentIdFromMarkdownPath, agents, createAgent, defineTool, executeFromRegistry, functionToolToDefinition, isFunctionTool, isHostedTool, isToolkitEntry, loadAgentFromFile, loadAgentsFromDir, mcpServer, parseTextToolCalls, resolveHostedTools, runAgent, tool, toolsFromRegistry };
@@ -4,6 +4,18 @@ import { DnsLookup, McpHostPolicy } from "./host-policy.js";
4
4
  import { McpEndpointConfig } from "./types.js";
5
5
 
6
6
  //#region src/connectors/mcp/client.d.ts
7
+ /**
8
+ * Per-endpoint outcome of {@link AppKitMcpClient.connectAll}. Callers (the
9
+ * agents plugin in particular) use the split to warn at startup when some
10
+ * MCP servers are unreachable without aborting boot for the rest.
11
+ */
12
+ interface McpConnectAllResult {
13
+ connected: string[];
14
+ failed: Array<{
15
+ name: string;
16
+ error: Error;
17
+ }>;
18
+ }
7
19
  /**
8
20
  * Lightweight MCP client for Databricks-hosted MCP servers.
9
21
  *
@@ -33,7 +45,20 @@ declare class AppKitMcpClient {
33
45
  dnsLookup?: DnsLookup;
34
46
  fetchImpl?: typeof fetch;
35
47
  });
36
- connectAll(endpoints: McpEndpointConfig[]): Promise<void>;
48
+ /**
49
+ * Connects every endpoint in parallel and returns a structured summary so
50
+ * callers can distinguish "all connected" from "some failed".
51
+ *
52
+ * Returning the result instead of throwing is deliberate: one
53
+ * misconfigured MCP server should not take down the entire agents plugin
54
+ * at boot, and the agents plugin uses the summary to warn at startup with
55
+ * the failed-endpoint names. Errors are also logged here so a caller
56
+ * that ignores the return still gets per-endpoint diagnostics.
57
+ *
58
+ * @returns `connected` lists the endpoint names that initialised
59
+ * successfully; `failed` carries `{ name, error }` for the rest.
60
+ */
61
+ connectAll(endpoints: McpEndpointConfig[]): Promise<McpConnectAllResult>;
37
62
  private resolveUrl;
38
63
  connect(endpoint: McpEndpointConfig): Promise<void>;
39
64
  getAllToolDefinitions(): AgentToolDefinition[];
@@ -56,5 +81,5 @@ declare class AppKitMcpClient {
56
81
  private resolveAuthHeaders;
57
82
  }
58
83
  //#endregion
59
- export { AppKitMcpClient };
84
+ export { AppKitMcpClient, McpConnectAllResult };
60
85
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","names":[],"sources":["../../../src/connectors/mcp/client.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;cAyFa,eAAA;EAAA,QAOD,aAAA;EAAA,QACA,YAAA;EAAA,QACA,MAAA;EAAA,QACA,OAAA;EAAA,QATF,WAAA;EAAA,QACA,UAAA;EAAA,QACA,SAAA;EAAA,QACA,MAAA;cAGE,aAAA,UACA,YAAA,QAAoB,OAAA,CAAQ,MAAA,mBAC5B,MAAA,EAAQ,aAAA,EACR,OAAA;IAAW,SAAA,GAAY,SAAA;IAAW,SAAA,UAAmB,KAAA;EAAA;EAGzD,UAAA,CAAW,SAAA,EAAW,iBAAA,KAAsB,OAAA;EAAA,QAe1C,UAAA;EAUF,OAAA,CAAQ,QAAA,EAAU,iBAAA,GAAoB,OAAA;EAqE5C,qBAAA,CAAA,GAAyB,mBAAA;EA8BvB;;;;;;EANF,uBAAA,CAAwB,UAAA;EAIlB,QAAA,CACJ,aAAA,UACA,IAAA,WACA,WAAA,GAAc,MAAA,kBACd,YAAA,GAAe,WAAA,GACd,OAAA;EAgDG,KAAA,CAAA,GAAS,OAAA;EAAA,QAMD,OAAA;EAAA,QA8EA,gBAAA;EAkCkB;;;;;EAAA,QAAlB,kBAAA;AAAA"}
1
+ {"version":3,"file":"client.d.ts","names":[],"sources":["../../../src/connectors/mcp/client.ts"],"mappings":";;;;;;;;;;;UAsJiB,mBAAA;EACf,SAAA;EACA,MAAA,EAAQ,KAAA;IAAQ,IAAA;IAAc,KAAA,EAAO,KAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;cA+B1B,eAAA;EAAA,QAOD,aAAA;EAAA,QACA,YAAA;EAAA,QACA,MAAA;EAAA,QACA,OAAA;EAAA,QATF,WAAA;EAAA,QACA,UAAA;EAAA,QACA,SAAA;EAAA,QACA,MAAA;cAGE,aAAA,UACA,YAAA,QAAoB,OAAA,CAAQ,MAAA,mBAC5B,MAAA,EAAQ,aAAA,EACR,OAAA;IAAW,SAAA,GAAY,SAAA;IAAW,SAAA,UAAmB,KAAA;EAAA;EAqH/D;;;;;;;;;;;;;EArGM,UAAA,CACJ,SAAA,EAAW,iBAAA,KACV,OAAA,CAAQ,mBAAA;EAAA,QAoBH,UAAA;EAUF,OAAA,CAAQ,QAAA,EAAU,iBAAA,GAAoB,OAAA;EAqE5C,qBAAA,CAAA,GAAyB,mBAAA;EA2OO;;;;;;EAvNhC,uBAAA,CAAwB,UAAA;EAIlB,QAAA,CACJ,aAAA,UACA,IAAA,WACA,WAAA,GAAc,MAAA,kBACd,YAAA,GAAe,WAAA,GACd,OAAA;EAoDG,KAAA,CAAA,GAAS,OAAA;EAAA,QAMD,OAAA;EAAA,QA0FA,gBAAA;;;;;;UA0DA,kBAAA;AAAA"}