@databricks/appkit 0.82.0 → 0.84.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.
- package/CLAUDE.md +21 -1
- package/dist/agents/databricks.d.ts +15 -3
- package/dist/agents/databricks.d.ts.map +1 -1
- package/dist/agents/databricks.js +25 -8
- package/dist/agents/databricks.js.map +1 -1
- package/dist/appkit/package.js +1 -1
- package/dist/beta.d.ts +2 -2
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +6 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/cli/commands/agent/eval.js +1 -1
- package/dist/cli/commands/generate-types.js +1 -1
- package/dist/cli/commands/plugin/sync/sync.js +28 -15
- package/dist/cli/commands/plugin/sync/sync.js.map +1 -1
- package/dist/cli/commands/registry/add.js +3 -11
- package/dist/cli/commands/registry/add.js.map +1 -1
- package/dist/cli/commands/registry/config-writer.js +1 -1
- package/dist/connectors/lakebase/index.js +1 -1
- package/dist/connectors/lakebase/routing-pool.d.ts +1 -1
- package/dist/connectors/lakebase/routing-pool.d.ts.map +1 -1
- package/dist/connectors/lakebase/routing-pool.js +6 -12
- package/dist/connectors/lakebase/routing-pool.js.map +1 -1
- package/dist/context/caller-context.d.ts +25 -0
- package/dist/context/caller-context.d.ts.map +1 -0
- package/dist/context/caller-context.js +21 -0
- package/dist/context/caller-context.js.map +1 -0
- package/dist/context/deprecation.js +14 -0
- package/dist/context/deprecation.js.map +1 -0
- package/dist/context/execution-context.d.ts +40 -4
- package/dist/context/execution-context.d.ts.map +1 -1
- package/dist/context/execution-context.js +87 -33
- package/dist/context/execution-context.js.map +1 -1
- package/dist/context/index.d.ts +3 -2
- package/dist/context/index.js +3 -1
- package/dist/context/request-scope.d.ts +2 -0
- package/dist/context/request-scope.js +39 -0
- package/dist/context/request-scope.js.map +1 -0
- package/dist/context/resource-capabilities.js +59 -0
- package/dist/context/resource-capabilities.js.map +1 -0
- package/dist/context/scoped-api.js +104 -0
- package/dist/context/scoped-api.js.map +1 -0
- package/dist/context/service-context.d.ts +18 -12
- package/dist/context/service-context.d.ts.map +1 -1
- package/dist/context/service-context.js +45 -55
- package/dist/context/service-context.js.map +1 -1
- package/dist/context/user-context.d.ts +16 -22
- package/dist/context/user-context.d.ts.map +1 -1
- package/dist/context/user-context.js +57 -3
- package/dist/context/user-context.js.map +1 -1
- package/dist/core/agent/load-agents.d.ts.map +1 -1
- package/dist/core/agent/load-agents.js +5 -2
- package/dist/core/agent/load-agents.js.map +1 -1
- package/dist/core/agent/run-agent.d.ts +19 -6
- package/dist/core/agent/run-agent.d.ts.map +1 -1
- package/dist/core/agent/run-agent.js +53 -17
- package/dist/core/agent/run-agent.js.map +1 -1
- package/dist/core/agent/types.d.ts +18 -1
- package/dist/core/agent/types.d.ts.map +1 -1
- package/dist/core/agent/types.js.map +1 -1
- package/dist/core/appkit.d.ts +4 -3
- package/dist/core/appkit.d.ts.map +1 -1
- package/dist/core/appkit.js +34 -11
- package/dist/core/appkit.js.map +1 -1
- package/dist/core/plugin-context.d.ts +14 -15
- package/dist/core/plugin-context.d.ts.map +1 -1
- package/dist/core/plugin-context.js +24 -14
- package/dist/core/plugin-context.js.map +1 -1
- package/dist/errors/base.d.ts +2 -2
- package/dist/errors/base.js +2 -2
- package/dist/errors/base.js.map +1 -1
- package/dist/errors/identity-expired.d.ts +14 -0
- package/dist/errors/identity-expired.d.ts.map +1 -0
- package/dist/errors/identity-expired.js +33 -0
- package/dist/errors/identity-expired.js.map +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/index.d.ts +12 -6
- package/dist/index.js +7 -2
- package/dist/logging/logger.js +1 -1
- package/dist/plugin/execution-result.d.ts +4 -1
- package/dist/plugin/execution-result.d.ts.map +1 -1
- package/dist/plugin/interceptors/telemetry.js +6 -4
- package/dist/plugin/interceptors/telemetry.js.map +1 -1
- package/dist/plugin/plugin.d.ts +14 -22
- package/dist/plugin/plugin.d.ts.map +1 -1
- package/dist/plugin/plugin.js +42 -123
- package/dist/plugin/plugin.js.map +1 -1
- package/dist/plugins/agents/agents.d.ts +13 -1
- package/dist/plugins/agents/agents.d.ts.map +1 -1
- package/dist/plugins/agents/agents.js +65 -15
- package/dist/plugins/agents/agents.js.map +1 -1
- package/dist/plugins/agents/auth-mode.js +42 -0
- package/dist/plugins/agents/auth-mode.js.map +1 -0
- package/dist/plugins/agents/index.d.ts +1 -1
- package/dist/plugins/agents/mlflow.js +11 -3
- package/dist/plugins/agents/mlflow.js.map +1 -1
- package/dist/plugins/agents/tool-dispatch.js +9 -1
- package/dist/plugins/agents/tool-dispatch.js.map +1 -1
- package/dist/plugins/ai-search/ai-search.d.ts +1 -1
- package/dist/plugins/ai-search/ai-search.d.ts.map +1 -1
- package/dist/plugins/ai-search/ai-search.js +4 -4
- package/dist/plugins/ai-search/ai-search.js.map +1 -1
- package/dist/plugins/analytics/analytics.d.ts +3 -3
- package/dist/plugins/analytics/analytics.d.ts.map +1 -1
- package/dist/plugins/analytics/analytics.js +9 -7
- package/dist/plugins/analytics/analytics.js.map +1 -1
- package/dist/plugins/database/crud/contract.js +2 -2
- package/dist/plugins/database/crud/contract.js.map +1 -1
- package/dist/plugins/database/database.d.ts +1 -1
- package/dist/plugins/files/plugin.d.ts +21 -15
- package/dist/plugins/files/plugin.d.ts.map +1 -1
- package/dist/plugins/files/plugin.js +50 -29
- package/dist/plugins/files/plugin.js.map +1 -1
- package/dist/plugins/genie/genie.d.ts +10 -1
- package/dist/plugins/genie/genie.d.ts.map +1 -1
- package/dist/plugins/genie/genie.js +12 -3
- package/dist/plugins/genie/genie.js.map +1 -1
- package/dist/plugins/genie/manifest.js +1 -0
- package/dist/plugins/jobs/plugin.d.ts +1 -1
- package/dist/plugins/jobs/plugin.js +2 -2
- package/dist/plugins/jobs/plugin.js.map +1 -1
- package/dist/plugins/lakebase/lakebase.d.ts +11 -18
- package/dist/plugins/lakebase/lakebase.d.ts.map +1 -1
- package/dist/plugins/lakebase/lakebase.js +16 -21
- package/dist/plugins/lakebase/lakebase.js.map +1 -1
- package/dist/plugins/server/client-config-sanitizer.js +1 -4
- package/dist/plugins/server/client-config-sanitizer.js.map +1 -1
- package/dist/plugins/server/dev-obo-middleware.js +60 -0
- package/dist/plugins/server/dev-obo-middleware.js.map +1 -0
- package/dist/plugins/server/index.d.ts +1 -1
- package/dist/plugins/server/index.d.ts.map +1 -1
- package/dist/plugins/server/index.js +3 -0
- package/dist/plugins/server/index.js.map +1 -1
- package/dist/plugins/serving/manifest.js +1 -0
- package/dist/plugins/serving/serving.d.ts +1 -1
- package/dist/plugins/serving/serving.js +6 -6
- package/dist/plugins/serving/serving.js.map +1 -1
- package/dist/resources/index.d.ts +1 -0
- package/dist/resources/index.js +3 -0
- package/dist/resources/warehouse.d.ts +16 -0
- package/dist/resources/warehouse.d.ts.map +1 -0
- package/dist/resources/warehouse.js +93 -0
- package/dist/resources/warehouse.js.map +1 -0
- package/dist/schemas/manifest.d.ts +44 -1
- package/dist/schemas/manifest.d.ts.map +1 -1
- package/dist/schemas/manifest.js +122 -3
- package/dist/schemas/manifest.js.map +1 -1
- package/dist/shared/src/dev-obo.js +86 -0
- package/dist/shared/src/dev-obo.js.map +1 -0
- package/dist/shared/src/index.d.ts +1 -1
- package/dist/shared/src/plugin.d.ts +12 -1
- package/dist/shared/src/plugin.d.ts.map +1 -1
- package/dist/shared/src/schemas/manifest.d.ts +17 -0
- package/dist/shared/src/schemas/manifest.d.ts.map +1 -1
- package/dist/shared/src/schemas/manifest.js +53 -3
- package/dist/shared/src/schemas/manifest.js.map +1 -1
- package/dist/stream/stream-manager.d.ts.map +1 -1
- package/dist/stream/stream-manager.js +5 -2
- package/dist/stream/stream-manager.js.map +1 -1
- package/dist/telemetry/execution-span-processor.js +21 -0
- package/dist/telemetry/execution-span-processor.js.map +1 -0
- package/dist/telemetry/telemetry-manager.js +2 -1
- package/dist/telemetry/telemetry-manager.js.map +1 -1
- package/dist/testing/create-test-app.d.ts +2 -2
- package/dist/testing/create-test-app.js +2 -2
- package/dist/testing/create-test-app.js.map +1 -1
- package/dist/testing/fixtures.d.ts +3 -2
- package/dist/testing/fixtures.d.ts.map +1 -1
- package/dist/testing/fixtures.js +21 -14
- package/dist/testing/fixtures.js.map +1 -1
- package/dist/testing/reset-singletons.js +1 -1
- package/dist/testing/test-plugin-context.d.ts +3 -12
- package/dist/testing/test-plugin-context.d.ts.map +1 -1
- package/dist/testing/test-plugin-context.js +24 -16
- package/dist/testing/test-plugin-context.js.map +1 -1
- package/dist/utils/is-plain-object.js +11 -0
- package/dist/utils/is-plain-object.js.map +1 -0
- package/docs/api/appkit/Class.AppKitError.md +2 -1
- package/docs/api/appkit/Class.AuthenticationError.md +1 -1
- package/docs/api/appkit/Class.ConfigurationError.md +1 -1
- package/docs/api/appkit/Class.ConnectionError.md +1 -1
- package/docs/api/appkit/Class.DatabaseValidationError.md +1 -1
- package/docs/api/appkit/Class.ExecutionError.md +1 -1
- package/docs/api/appkit/Class.IdentityExpiredError.md +190 -0
- package/docs/api/appkit/Class.InitializationError.md +1 -1
- package/docs/api/appkit/Class.Plugin.md +9 -13
- package/docs/api/appkit/Class.ServerError.md +1 -1
- package/docs/api/appkit/Class.ServiceContext.md +169 -0
- package/docs/api/appkit/Class.TunnelError.md +1 -1
- package/docs/api/appkit/Class.ValidationError.md +1 -1
- package/docs/api/appkit/Function.createApp.md +12 -12
- package/docs/api/appkit/Function.getCallerContext.md +12 -0
- package/docs/api/appkit/Function.getCurrentActorId.md +12 -0
- package/docs/api/appkit/Function.getCurrentPrincipalKey.md +12 -0
- package/docs/api/appkit/Function.getCurrentUserId.md +14 -0
- package/docs/api/appkit/Function.getExecutionContext.md +5 -3
- package/docs/api/appkit/Function.getUserContext.md +16 -0
- package/docs/api/appkit/Function.getWarehouseId.md +20 -0
- package/docs/api/appkit/Function.isInUserContext.md +12 -0
- package/docs/api/appkit/Function.isUserContext.md +20 -0
- package/docs/api/appkit/Function.runAgent.md +1 -1
- package/docs/api/appkit/Function.runInCallerContext.md +27 -0
- package/docs/api/appkit/Function.runInUserContext.md +29 -0
- package/docs/api/appkit/Interface.AgentDefinition.md +11 -0
- package/docs/api/appkit/Interface.AgentsPluginConfig.md +11 -0
- package/docs/api/appkit/Interface.CallerContext.md +54 -0
- package/docs/api/appkit/Interface.IndexConfig.md +1 -1
- package/docs/api/appkit/Interface.PluginManifest.md +33 -2
- package/docs/api/appkit/Interface.RegisteredAgent.md +11 -0
- package/docs/api/appkit/Interface.RunAgentInput.md +45 -1
- package/docs/api/appkit/TypeAlias.AgentAuth.md +8 -0
- package/docs/api/appkit/TypeAlias.AppKitApi.md +35 -0
- package/docs/api/appkit/TypeAlias.CallerPrincipal.md +13 -0
- package/docs/api/appkit/TypeAlias.ExecutionContext.md +9 -0
- package/docs/api/appkit/TypeAlias.ExecutionResult.md +65 -0
- package/docs/api/appkit/TypeAlias.ScopedPluginMap.md +12 -0
- package/docs/api/appkit/TypeAlias.UserContext.md +109 -0
- package/docs/api/appkit/TypeAlias.UserScopedApp.md +39 -0
- package/docs/api/appkit.md +20 -0
- package/docs/plugins/agents.md +45 -0
- package/docs/plugins/analytics.md +8 -0
- package/docs/plugins/execution-context.md +101 -50
- package/docs/plugins/lakebase.md +6 -82
- package/llms.txt +21 -1
- package/package.json +1 -1
- package/sbom.cdx.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -49,7 +49,7 @@ npx @databricks/appkit docs <query>
|
|
|
49
49
|
- [Caching](./docs/plugins/caching.md): AppKit provides both global and plugin-level caching capabilities.
|
|
50
50
|
- [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:
|
|
51
51
|
- [Database plugin](./docs/plugins/database.md): This plugin is currently beta. APIs may change between minor releases. Import from @databricks/appkit/beta. See Plugin Stability Tiers.
|
|
52
|
-
- [Execution context](./docs/plugins/execution-context.md): AppKit
|
|
52
|
+
- [Execution context](./docs/plugins/execution-context.md): AppKit uses the service principal by default. Open a caller scope when an
|
|
53
53
|
- [Files plugin](./docs/plugins/files.md): File operations against Databricks Unity Catalog Volumes. Supports listing, reading, downloading, uploading, deleting, and previewing files with built-in caching, retry, and timeout handling via the execution interceptor pipeline.
|
|
54
54
|
- [Genie plugin](./docs/plugins/genie.md): Integrates Databricks AI/BI Genie spaces into your AppKit application, enabling natural language data queries via a conversational interface.
|
|
55
55
|
- [Jobs plugin](./docs/plugins/jobs.md): Trigger and monitor Databricks Lakeflow Jobs from your AppKit application.
|
|
@@ -72,12 +72,14 @@ npx @databricks/appkit docs <query>
|
|
|
72
72
|
- [Class: DatabaseValidationError](./docs/api/appkit/Class.DatabaseValidationError.md): Deliberate validation failure raised by a database mutation hook. Generated
|
|
73
73
|
- [Class: DatabricksAdapter](./docs/api/appkit/Class.DatabricksAdapter.md): Adapter that talks directly to Databricks Model Serving /invocations endpoint.
|
|
74
74
|
- [Class: ExecutionError](./docs/api/appkit/Class.ExecutionError.md): Error thrown when an operation execution fails.
|
|
75
|
+
- [Class: IdentityExpiredError](./docs/api/appkit/Class.IdentityExpiredError.md): The downstream service rejected the active caller's credentials.
|
|
75
76
|
- [Class: InitializationError](./docs/api/appkit/Class.InitializationError.md): Error thrown when a service or component is not properly initialized.
|
|
76
77
|
- [Class: MlflowClient](./docs/api/appkit/Class.MlflowClient.md): A thin client over the Databricks workspace REST API, owning the host + bearer
|
|
77
78
|
- [Abstract Class: Plugin<TConfig>](./docs/api/appkit/Class.Plugin.md): Base abstract class for creating AppKit plugins.
|
|
78
79
|
- [Class: PolicyDeniedError](./docs/api/appkit/Class.PolicyDeniedError.md): Thrown when a policy denies an action.
|
|
79
80
|
- [Class: ResourceRegistry](./docs/api/appkit/Class.ResourceRegistry.md): Central registry for tracking plugin resource requirements.
|
|
80
81
|
- [Class: ServerError](./docs/api/appkit/Class.ServerError.md): Error thrown when server lifecycle operations fail.
|
|
82
|
+
- [Class: ServiceContext](./docs/api/appkit/Class.ServiceContext.md): ServiceContext is a singleton that manages the service principal's
|
|
81
83
|
- [Class: SupervisorApiAdapter](./docs/api/appkit/Class.SupervisorApiAdapter.md): Adapter that calls the Databricks AI Gateway Responses API
|
|
82
84
|
- [Class: TunnelError](./docs/api/appkit/Class.TunnelError.md): Error thrown when remote tunnel operations fail.
|
|
83
85
|
- [Class: ValidationError](./docs/api/appkit/Class.ValidationError.md): Error thrown when input validation fails.
|
|
@@ -122,22 +124,30 @@ npx @databricks/appkit docs <query>
|
|
|
122
124
|
- [Function: fromSupervisorApi()](./docs/api/appkit/Function.fromSupervisorApi.md): Creates an AgentAdapter backed by the Databricks AI Gateway
|
|
123
125
|
- [Function: functionToolToDefinition()](./docs/api/appkit/Function.functionToolToDefinition.md): Parameters
|
|
124
126
|
- [Function: generateDatabaseCredential()](./docs/api/appkit/Function.generateDatabaseCredential.md): Generate OAuth credentials for Postgres database connection using the proper Postgres API.
|
|
127
|
+
- [Function: getCallerContext()](./docs/api/appkit/Function.getCallerContext.md): Get the caller context if one is active, otherwise undefined.
|
|
128
|
+
- [Function: getCurrentActorId()](./docs/api/appkit/Function.getCurrentActorId.md): The initiating user in a caller scope; no user actor exists in service scope.
|
|
129
|
+
- [Function: getCurrentPrincipalKey()](./docs/api/appkit/Function.getCurrentPrincipalKey.md): Get the principal key for future cache keying.
|
|
130
|
+
- [Function: getCurrentUserId()](./docs/api/appkit/Function.getCurrentUserId.md): Returns
|
|
125
131
|
- [Function: getExecutionContext()](./docs/api/appkit/Function.getExecutionContext.md): Get the current execution context.
|
|
126
132
|
- [Function: getLakebaseOrmConfig()](./docs/api/appkit/Function.getLakebaseOrmConfig.md): Get Lakebase connection configuration for ORMs that don't accept pg.Pool directly.
|
|
127
133
|
- [Function: getLakebasePgConfig()](./docs/api/appkit/Function.getLakebasePgConfig.md): Get Lakebase connection configuration for PostgreSQL clients.
|
|
128
134
|
- [Function: getPluginManifest()](./docs/api/appkit/Function.getPluginManifest.md): Loads and validates the manifest from a plugin constructor.
|
|
129
135
|
- [Function: getResourceRequirements()](./docs/api/appkit/Function.getResourceRequirements.md): Gets the resource requirements from a plugin's manifest.
|
|
136
|
+
- [Function: getUserContext()](./docs/api/appkit/Function.getUserContext.md): Returns
|
|
130
137
|
- [Function: getUsernameWithApiLookup()](./docs/api/appkit/Function.getUsernameWithApiLookup.md): Resolves the PostgreSQL username for a Lakebase connection.
|
|
138
|
+
- [Function: getWarehouseId()](./docs/api/appkit/Function.getWarehouseId.md): Get the configured SQL warehouse ID after app initialization.
|
|
131
139
|
- [Function: getWorkspaceClient()](./docs/api/appkit/Function.getWorkspaceClient.md): Get workspace client from config or SDK default auth chain
|
|
132
140
|
- [Function: id()](./docs/api/appkit/Function.id.md): Returns
|
|
133
141
|
- [Function: includes()](./docs/api/appkit/Function.includes.md): Passes when the value contains substring.
|
|
134
142
|
- [Function: integer()](./docs/api/appkit/Function.integer.md): Returns
|
|
135
143
|
- [Function: isFunctionTool()](./docs/api/appkit/Function.isFunctionTool.md): Parameters
|
|
136
144
|
- [Function: isHostedTool()](./docs/api/appkit/Function.isHostedTool.md): Parameters
|
|
145
|
+
- [Function: isInUserContext()](./docs/api/appkit/Function.isInUserContext.md): Check if currently running in a user context.
|
|
137
146
|
- [Function: isJudgeConfigured()](./docs/api/appkit/Function.isJudgeConfigured.md): Returns
|
|
138
147
|
- [Function: isSQLTypeMarker()](./docs/api/appkit/Function.isSQLTypeMarker.md): Type guard to check if a value is a SQL type marker
|
|
139
148
|
- [Function: isSupervisorTool()](./docs/api/appkit/Function.isSupervisorTool.md): Type guard for HostedSupervisorTool. Used by the agents plugin
|
|
140
149
|
- [Function: isToolkitEntry()](./docs/api/appkit/Function.isToolkitEntry.md): Type guard for ToolkitEntry — used by the agents plugin to differentiate
|
|
150
|
+
- [Function: isUserContext()](./docs/api/appkit/Function.isUserContext.md): Parameters
|
|
141
151
|
- [Function: jsonb()](./docs/api/appkit/Function.jsonb.md): Returns
|
|
142
152
|
- [Function: loadAgentFromFile()](./docs/api/appkit/Function.loadAgentFromFile.md): Loads a single markdown agent file and resolves its frontmatter against
|
|
143
153
|
- [Function: loadAgentsFromDir()](./docs/api/appkit/Function.loadAgentsFromDir.md): Scans a directory for one subdirectory per agent, each containing
|
|
@@ -154,6 +164,8 @@ npx @databricks/appkit docs <query>
|
|
|
154
164
|
- [Function: runAgent()](./docs/api/appkit/Function.runAgent.md): Standalone agent execution without createApp. Resolves the adapter, binds
|
|
155
165
|
- [Function: runEval()](./docs/api/appkit/Function.runEval.md): Run a single eval against a driver. Never throws for assertion or agent
|
|
156
166
|
- [Function: runEvalsInDir()](./docs/api/appkit/Function.runEvalsInDir.md): Discover, load, and run every eval under each agent's evals/ dir, driving
|
|
167
|
+
- [Function: runInCallerContext()](./docs/api/appkit/Function.runInCallerContext.md): Run a function with an immutable snapshot of the caller context.
|
|
168
|
+
- [Function: runInUserContext()](./docs/api/appkit/Function.runInUserContext.md): Type Parameters
|
|
157
169
|
- [Function: runWithRetries()](./docs/api/appkit/Function.runWithRetries.md): Run attempt up to 1 + retries times, stopping as soon as it returns a
|
|
158
170
|
- [Function: summarize()](./docs/api/appkit/Function.summarize.md): Parameters
|
|
159
171
|
- [Function: text()](./docs/api/appkit/Function.text.md): Returns
|
|
@@ -175,6 +187,7 @@ npx @databricks/appkit docs <query>
|
|
|
175
187
|
- [Interface: AutoInheritToolsConfig](./docs/api/appkit/Interface.AutoInheritToolsConfig.md): Auto-inherit configuration. When enabled for a given agent origin, agents
|
|
176
188
|
- [Interface: BasePluginConfig](./docs/api/appkit/Interface.BasePluginConfig.md): Base configuration interface for AppKit plugins
|
|
177
189
|
- [Interface: CacheConfig](./docs/api/appkit/Interface.CacheConfig.md): Configuration for the CacheInterceptor. Controls TTL, size limits, storage backend, and probabilistic cleanup.
|
|
190
|
+
- [Interface: CallerContext](./docs/api/appkit/Interface.CallerContext.md): Caller identity and workspace for one immutable execution scope.
|
|
178
191
|
- [Interface: CustomJudgeSpec](./docs/api/appkit/Interface.CustomJudgeSpec.md): A custom LLM-judge definition: a prompt template and choice→score mapping.
|
|
179
192
|
- [Interface: DatabaseCredential](./docs/api/appkit/Interface.DatabaseCredential.md): Database credentials with OAuth token for Postgres connection
|
|
180
193
|
- [Interface: DatabaseRegistry](./docs/api/appkit/Interface.DatabaseRegistry.md): CANONICAL augmentation target. Empty by default; the generated database.d.ts
|
|
@@ -257,11 +270,14 @@ npx @databricks/appkit docs <query>
|
|
|
257
270
|
- [Interface: WorkspaceClient](./docs/api/appkit/Interface.WorkspaceClient.md): AppKit's workspace client facade. Mirrors the multi-client shape of the
|
|
258
271
|
- [Interface: WorkspaceClientLike](./docs/api/appkit/Interface.WorkspaceClientLike.md): Structural shape of a Databricks SDK client used by fromSupervisorApi.
|
|
259
272
|
- [Interface: WorkspaceClientOptions](./docs/api/appkit/Interface.WorkspaceClientOptions.md): Options used to construct the wrapper. Mirrors the subset of the old SDK's
|
|
273
|
+
- [Type Alias: AgentAuth](./docs/api/appkit/TypeAlias.AgentAuth.md): Identity an agent runs under. The only value is on-behalf-of-user.
|
|
260
274
|
- [Type Alias: AgentEvent](./docs/api/appkit/TypeAlias.AgentEvent.md): Type Declaration
|
|
261
275
|
- [Type Alias: AgentTool](./docs/api/appkit/TypeAlias.AgentTool.md): Any tool an agent can invoke: inline function tools (tool()), hosted MCP
|
|
262
276
|
- [Type Alias: AgentTools](./docs/api/appkit/TypeAlias.AgentTools.md): Per-agent tool record. String keys map to inline tools, toolkit entries,
|
|
263
277
|
- [Type Alias: AgentToolsFn()](./docs/api/appkit/TypeAlias.AgentToolsFn.md): Function form of AgentDefinition.tools. Receives the typed
|
|
278
|
+
- [Type Alias: AppKitApi<U>](./docs/api/appkit/TypeAlias.AppKitApi.md): App instance with plugin exports and an explicit caller-scoped entry point.
|
|
264
279
|
- [Type Alias: BaseSystemPromptOption](./docs/api/appkit/TypeAlias.BaseSystemPromptOption.md)
|
|
280
|
+
- [Type Alias: CallerPrincipal](./docs/api/appkit/TypeAlias.CallerPrincipal.md): The caller identity whose permissions authorize execution, not its resources.
|
|
265
281
|
- [Type Alias: ConfigSchema](./docs/api/appkit/TypeAlias.ConfigSchema.md): Configuration schema definition for plugin config.
|
|
266
282
|
- [Type Alias: DatabaseApiConfig<TSchema>](./docs/api/appkit/TypeAlias.DatabaseApiConfig.md): Full generated CRUD for every declared table by default. Set false to disable
|
|
267
283
|
- [Type Alias: DatabaseApiWriteOperation](./docs/api/appkit/TypeAlias.DatabaseApiWriteOperation.md): Generated HTTP write operations.
|
|
@@ -269,6 +285,7 @@ npx @databricks/appkit docs <query>
|
|
|
269
285
|
- [Type Alias: DatabaseExports](./docs/api/appkit/TypeAlias.DatabaseExports.md): Typed database API published by the plugin.
|
|
270
286
|
- [Type Alias: EntityHooks<TTable>](./docs/api/appkit/TypeAlias.EntityHooks.md): Response shaping and mutation lifecycle declared for one table.
|
|
271
287
|
- [Type Alias: EvalProgress](./docs/api/appkit/TypeAlias.EvalProgress.md)
|
|
288
|
+
- [Type Alias: ExecutionContext](./docs/api/appkit/TypeAlias.ExecutionContext.md)
|
|
272
289
|
- [Type Alias: ExecutionResult<T>](./docs/api/appkit/TypeAlias.ExecutionResult.md): Discriminated union for plugin execution results.
|
|
273
290
|
- [Type Alias: FileAction](./docs/api/appkit/TypeAlias.FileAction.md): Every action the files plugin can perform.
|
|
274
291
|
- [Type Alias: FilePolicy()](./docs/api/appkit/TypeAlias.FilePolicy.md): A policy function that decides whether user may perform action on
|
|
@@ -283,6 +300,7 @@ npx @databricks/appkit docs <query>
|
|
|
283
300
|
- [Type Alias: ResolvedToolEntry](./docs/api/appkit/TypeAlias.ResolvedToolEntry.md): Internal tool-index entry after a tool record has been resolved to a dispatchable form.
|
|
284
301
|
- [Type Alias: ResourceFieldEntry](./docs/api/appkit/TypeAlias.ResourceFieldEntry.md)
|
|
285
302
|
- [Type Alias: ResourcePermission](./docs/api/appkit/TypeAlias.ResourcePermission.md): Union of all possible permission levels across all resource types.
|
|
303
|
+
- [Type Alias: ScopedPluginMap<U>](./docs/api/appkit/TypeAlias.ScopedPluginMap.md): Type Parameters
|
|
286
304
|
- [Type Alias: SearchFilters](./docs/api/appkit/TypeAlias.SearchFilters.md)
|
|
287
305
|
- [Type Alias: ServingFactory](./docs/api/appkit/TypeAlias.ServingFactory.md): Factory function returned by AppKit.serving.
|
|
288
306
|
- [Type Alias: Severity](./docs/api/appkit/TypeAlias.Severity.md): Whether an assertion fails the eval (gate) or is tracked only (soft).
|
|
@@ -290,6 +308,8 @@ npx @databricks/appkit docs <query>
|
|
|
290
308
|
- [Type Alias: ToolRegistry](./docs/api/appkit/TypeAlias.ToolRegistry.md)
|
|
291
309
|
- [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.
|
|
292
310
|
- [Type Alias: TransactionClient](./docs/api/appkit/TypeAlias.TransactionClient.md): Entity and SQL capabilities bound to one transaction.
|
|
311
|
+
- [Type Alias: UserContext](./docs/api/appkit/TypeAlias.UserContext.md): Deprecated
|
|
312
|
+
- [Type Alias: UserScopedApp<U>](./docs/api/appkit/TypeAlias.UserScopedApp.md): Type Declaration
|
|
293
313
|
- [Variable: agents](./docs/api/appkit/Variable.agents.md): Plugin factory for the agents plugin. Discovers agents from
|
|
294
314
|
- [Variable: aiSearch](./docs/api/appkit/Variable.aiSearch.md)
|
|
295
315
|
- [Variable: READ_ACTIONS](./docs/api/appkit/Variable.READ_ACTIONS.md): Actions that only read data.
|
|
@@ -77,8 +77,18 @@ interface WorkspaceClientLike {
|
|
|
77
77
|
request(options: Record<string, unknown>): Promise<unknown>;
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* A fixed client, or a provider resolved on every model call. A provider lets
|
|
82
|
+
* one adapter follow the active execution scope (for example
|
|
83
|
+
* `() => getWorkspaceClient()` for on-behalf-of-user agents).
|
|
84
|
+
*/
|
|
85
|
+
type WorkspaceClientSource = WorkspaceClientLike | (() => WorkspaceClientLike);
|
|
86
|
+
/**
|
|
87
|
+
* @internal True when a Databricks adapter was built with a fixed workspace
|
|
88
|
+
* client, so it cannot follow the caller in an on-behalf-of-user agent.
|
|
89
|
+
*/
|
|
80
90
|
interface ServingEndpointOptions {
|
|
81
|
-
workspaceClient:
|
|
91
|
+
workspaceClient: WorkspaceClientSource;
|
|
82
92
|
endpointName: string;
|
|
83
93
|
maxSteps?: number;
|
|
84
94
|
maxTokens?: number;
|
|
@@ -91,7 +101,7 @@ interface ModelServingOptions {
|
|
|
91
101
|
maxSteps?: number;
|
|
92
102
|
maxTokens?: number;
|
|
93
103
|
generationParams?: GenerationParams;
|
|
94
|
-
workspaceClient?:
|
|
104
|
+
workspaceClient?: WorkspaceClientSource;
|
|
95
105
|
maxSseLineChars?: number;
|
|
96
106
|
maxStreamTextChars?: number;
|
|
97
107
|
maxToolArgumentsChars?: number;
|
|
@@ -107,8 +117,10 @@ interface AiGatewayOptions {
|
|
|
107
117
|
* is created from the ambient client options (SDK credential chain). It is
|
|
108
118
|
* captured once and reused across requests — do not pass a per-request OBO
|
|
109
119
|
* client (it would leak the first request's identity into later ones).
|
|
120
|
+
* To follow the caller per request, pass a provider such as
|
|
121
|
+
* `() => getWorkspaceClient()`; it is resolved on every model call.
|
|
110
122
|
*/
|
|
111
|
-
workspaceClient?:
|
|
123
|
+
workspaceClient?: WorkspaceClientSource;
|
|
112
124
|
maxSteps?: number;
|
|
113
125
|
maxTokens?: number;
|
|
114
126
|
generationParams?: GenerationParams;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"databricks.d.ts","names":[],"sources":["../../src/agents/databricks.ts"],"mappings":";;;;;;;;;;AAyCA;;UAAiB,gBAAA;EAAgB;EAE/B,WAAA;EAEA;EAAA,KAAA;EAIA;EAFA,IAAA;EAIgB;EAFhB,iBAAA;EA6EQ;EA3ER,gBAAA;AAAA;;;;;;UA2EQ,sBAAA;EACR,WAAA;EACA,YAAA,QAAoB,OAAA,CAAQ,MAAA;EAC5B,QAAA;EACA,SAAA;EAAA;;;;;EAMA,KAAA;EAQA;EANA,gBAAA,GAAmB,gBAAA;EAME;EAJrB,eAAA;EAagC;EAXhC,kBAAA;EAiBmC;EAfnC,qBAAA;AAAA;;;;;;;UASQ,wBAAA;EACR,UAAA,EAAY,UAAA;EACZ,QAAA;EACA,SAAA;EASG;EAPH,KAAA;EACA,gBAAA,GAAmB,gBAAA;EACnB,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;AAAA,KAGG,wBAAA,GACD,sBAAA,GACA,wBAAA;;;;;;;;
|
|
1
|
+
{"version":3,"file":"databricks.d.ts","names":[],"sources":["../../src/agents/databricks.ts"],"mappings":";;;;;;;;;;AAyCA;;UAAiB,gBAAA;EAAgB;EAE/B,WAAA;EAEA;EAAA,KAAA;EAIA;EAFA,IAAA;EAIgB;EAFhB,iBAAA;EA6EQ;EA3ER,gBAAA;AAAA;;;;;;UA2EQ,sBAAA;EACR,WAAA;EACA,YAAA,QAAoB,OAAA,CAAQ,MAAA;EAC5B,QAAA;EACA,SAAA;EAAA;;;;;EAMA,KAAA;EAQA;EANA,gBAAA,GAAmB,gBAAA;EAME;EAJrB,eAAA;EAagC;EAXhC,kBAAA;EAiBmC;EAfnC,qBAAA;AAAA;;;;;;;UASQ,wBAAA;EACR,UAAA,EAAY,UAAA;EACZ,QAAA;EACA,SAAA;EASG;EAPH,KAAA;EACA,gBAAA,GAAmB,gBAAA;EACnB,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;AAAA,KAGG,wBAAA,GACD,sBAAA,GACA,wBAAA;;;;;;;;UAea,mBAAA;EACf,SAAA;IACE,OAAA,CAAQ,OAAA,EAAS,MAAA,oBAA0B,OAAA;EAAA;AAAA;;AAkC9C;;;;KAzBI,qBAAA,GAAwB,mBAAA,UAA6B,mBAAA;;;;;UA2BhD,sBAAA;EACR,eAAA,EAAiB,qBAAA;EACjB,YAAA;EACA,QAAA;EACA,SAAA;EACA,gBAAA,GAAmB,gBAAA;EACnB,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;AAAA,UAGQ,mBAAA;EACR,QAAA;EACA,SAAA;EACA,gBAAA,GAAmB,gBAAA;EACnB,eAAA,GAAkB,qBAAA;EAClB,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;AAAA,UAGQ,gBAAA;EAHa;AAAA;;;EAQrB,KAAA;EAAA;;;;;;;;EASA,eAAA,GAAkB,qBAAA;EAClB,QAAA;EACA,SAAA;EACA,gBAAA,GAAmB,gBAAA;EACnB,eAAA;EACA,kBAAA;EACA,qBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAuFW,iBAAA,YAA6B,YAAA;EAAA,QAChC,UAAA;EAAA,QACA,QAAA;EAAA,QACA,SAAA;EAuLG;EAAA,QArLH,KAAA;EAAA,QACA,gBAAA;EAAA,QACA,eAAA;EAAA,QACA,kBAAA;EAAA,QACA,qBAAA;cAEI,OAAA,EAAS,wBAAA;EAoPZ;;;;;;;;EAAA,OAlMI,mBAAA,CACX,OAAA,EAAS,sBAAA,GACR,OAAA,CAAQ,iBAAA;EAwgBH;;;;AA8GV;;;;;;;;;;;;;;;;EA9GU,OAndK,gBAAA,CACX,YAAA,WACA,OAAA,GAAU,mBAAA,GACT,OAAA,CAAQ,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAiEE,aAAA,CACX,OAAA,EAAS,gBAAA,GACR,OAAA,CAAQ,iBAAA;;;;;;;;;;;;;;;;;;;;;;SA6DE,iBAAA,CACX,OAAA,EA9DQ,2BAAA,GA+DP,OAAA,CAAQ,YAAA;EAKJ,GAAA,CACL,KAAA,EAAO,UAAA,EACP,OAAA,EAAS,eAAA,GACR,cAAA,CAAe,UAAA;;UAuDH,iBAAA;EAAA,QA8CA,gBAAA;EAAA,QA6LA,gBAAA;;;;;;UAoCP,aAAA;EAAA,QAgDA,UAAA;AAAA;;;;;;;;iBA8DM,kBAAA,CACd,IAAA,WACC,KAAA;EAAQ,IAAA;EAAc,IAAA;AAAA"}
|
|
@@ -65,6 +65,22 @@ function reasoningPartText(part) {
|
|
|
65
65
|
function isStreamBodyOptions(o) {
|
|
66
66
|
return "streamBody" in o;
|
|
67
67
|
}
|
|
68
|
+
function clientResolver(source) {
|
|
69
|
+
return typeof source === "function" ? source : () => source;
|
|
70
|
+
}
|
|
71
|
+
const fixedClientAdapters = /* @__PURE__ */ new WeakSet();
|
|
72
|
+
/** Record whether an adapter's client is fixed (not a per-call provider). */
|
|
73
|
+
function withClientSource(source, adapter) {
|
|
74
|
+
if (typeof source !== "function") fixedClientAdapters.add(adapter);
|
|
75
|
+
return adapter;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @internal True when a Databricks adapter was built with a fixed workspace
|
|
79
|
+
* client, so it cannot follow the caller in an on-behalf-of-user agent.
|
|
80
|
+
*/
|
|
81
|
+
function hasFixedWorkspaceClient(adapter) {
|
|
82
|
+
return fixedClientAdapters.has(adapter);
|
|
83
|
+
}
|
|
68
84
|
/**
|
|
69
85
|
* Adapter that talks directly to Databricks Model Serving `/invocations` endpoint.
|
|
70
86
|
*
|
|
@@ -160,15 +176,16 @@ var DatabricksAdapter = class DatabricksAdapter {
|
|
|
160
176
|
*/
|
|
161
177
|
static async fromServingEndpoint(options) {
|
|
162
178
|
const { workspaceClient, endpointName, maxSteps, maxTokens, generationParams, maxSseLineChars, maxStreamTextChars, maxToolArgumentsChars } = options;
|
|
163
|
-
|
|
164
|
-
|
|
179
|
+
const resolveClient = clientResolver(workspaceClient);
|
|
180
|
+
return withClientSource(workspaceClient, new DatabricksAdapter({
|
|
181
|
+
streamBody: (body, signal) => stream(resolveClient(), endpointName, body, signal),
|
|
165
182
|
maxSteps,
|
|
166
183
|
maxTokens,
|
|
167
184
|
generationParams,
|
|
168
185
|
maxSseLineChars,
|
|
169
186
|
maxStreamTextChars,
|
|
170
187
|
maxToolArgumentsChars
|
|
171
|
-
});
|
|
188
|
+
}));
|
|
172
189
|
}
|
|
173
190
|
/**
|
|
174
191
|
* Creates a DatabricksAdapter from a Model Serving endpoint name.
|
|
@@ -242,9 +259,9 @@ var DatabricksAdapter = class DatabricksAdapter {
|
|
|
242
259
|
*/
|
|
243
260
|
static async fromAiGateway(options) {
|
|
244
261
|
const { model, workspaceClient, maxSteps, maxTokens, generationParams, maxSseLineChars, maxStreamTextChars, maxToolArgumentsChars } = options;
|
|
245
|
-
const
|
|
246
|
-
return new DatabricksAdapter({
|
|
247
|
-
streamBody: (body, signal) => streamAiGateway(
|
|
262
|
+
const resolveClient = clientResolver(workspaceClient ?? createWorkspaceClient({ clientOptions: getClientOptions() }));
|
|
263
|
+
return withClientSource(workspaceClient, new DatabricksAdapter({
|
|
264
|
+
streamBody: (body, signal) => streamAiGateway(resolveClient(), body, signal),
|
|
248
265
|
model,
|
|
249
266
|
maxSteps,
|
|
250
267
|
maxTokens,
|
|
@@ -252,7 +269,7 @@ var DatabricksAdapter = class DatabricksAdapter {
|
|
|
252
269
|
maxSseLineChars,
|
|
253
270
|
maxStreamTextChars,
|
|
254
271
|
maxToolArgumentsChars
|
|
255
|
-
});
|
|
272
|
+
}));
|
|
256
273
|
}
|
|
257
274
|
/**
|
|
258
275
|
* Discoverability shim for the Supervisor API adapter. Returns an
|
|
@@ -618,5 +635,5 @@ function tryParsePythonStyleToolCalls(text) {
|
|
|
618
635
|
}
|
|
619
636
|
|
|
620
637
|
//#endregion
|
|
621
|
-
export { DatabricksAdapter, adapterFromModelString, parseTextToolCalls };
|
|
638
|
+
export { DatabricksAdapter, adapterFromModelString, hasFixedWorkspaceClient, parseTextToolCalls };
|
|
622
639
|
//# sourceMappingURL=databricks.js.map
|
|
@@ -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\";\n\nimport {\n type StreamBody,\n stream as servingStream,\n streamAiGateway,\n} from \"../connectors/serving/client\";\nimport { APPKIT_USER_AGENT, getClientOptions } from \"../context/client-options\";\nimport { createWorkspaceClient } from \"../workspace-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\n/**\n * Optional generation parameters forwarded to the OpenAI-compatible serving\n * request body. Names match the serving API wire keys. Only keys that are set\n * are sent — undefined values are omitted so the endpoint applies its own\n * defaults. Ranges are not validated here; the serving endpoint validates.\n */\nexport interface GenerationParams {\n /** Sampling temperature. */\n temperature?: number;\n /** Nucleus sampling probability mass (`top_p`). */\n top_p?: number;\n /** Stop sequence(s) that end generation. */\n stop?: string | string[];\n /** Penalize tokens by frequency. */\n frequency_penalty?: number;\n /** Penalize tokens by prior presence. */\n presence_penalty?: number;\n}\n\nconst GENERATION_PARAM_KEYS = [\n \"temperature\",\n \"top_p\",\n \"stop\",\n \"frequency_penalty\",\n \"presence_penalty\",\n] as const satisfies readonly (keyof GenerationParams)[];\n\n/** Copy only the set generation params onto the request body. */\nfunction applyGenerationParams(\n body: Record<string, unknown>,\n params: GenerationParams,\n): void {\n for (const key of GENERATION_PARAM_KEYS) {\n const value = params[key];\n if (value !== undefined) body[key] = value;\n }\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/** Text of a harmony `reasoning` part: `summary[].text` plus an optional `text`. */\nfunction reasoningPartText(part: Record<string, unknown>): string {\n let text = \"\";\n if (Array.isArray(part.summary)) {\n for (const s of part.summary) {\n if (isRecord(s) && typeof s.text === \"string\") text += s.text;\n }\n }\n if (typeof part.text === \"string\") text += part.text;\n return text;\n}\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 /**\n * When set, sent in the request body as `model`. Required by the AI Gateway,\n * which routes by the body's `model` (not the URL). Serving-endpoint paths\n * name the model in the URL and leave this unset.\n */\n model?: string;\n /** Optional generation params forwarded to the serving request body. */\n generationParams?: GenerationParams;\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 /** See {@link RawFetchAdapterOptions.model}. Set by {@link DatabricksAdapter.fromAiGateway}. */\n model?: string;\n generationParams?: GenerationParams;\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 generationParams?: GenerationParams;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ninterface ModelServingOptions {\n maxSteps?: number;\n maxTokens?: number;\n generationParams?: GenerationParams;\n workspaceClient?: WorkspaceClientLike;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ninterface AiGatewayOptions {\n /**\n * Model to name in the request body, e.g. `\"system.ai.claude-opus-5-5\"`.\n * The gateway routes by this value; there is no per-endpoint URL.\n */\n model: string;\n /**\n * Pre-built WorkspaceClient (or structural equivalent). When omitted, one\n * is created from the ambient client options (SDK credential chain). It is\n * captured once and reused across requests — do not pass a per-request OBO\n * client (it would leak the first request's identity into later ones).\n */\n workspaceClient?: WorkspaceClientLike;\n maxSteps?: number;\n maxTokens?: number;\n generationParams?: GenerationParams;\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, createWorkspaceClient } from \"@databricks/appkit\";\n * import { DatabricksAdapter } from \"@databricks/appkit/beta\";\n *\n * const adapter = DatabricksAdapter.fromServingEndpoint({\n * workspaceClient: createWorkspaceClient(),\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 /** UC model name sent in the request body (AI Gateway); unset for serving endpoints. */\n private model?: string;\n private generationParams: GenerationParams;\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.model = options.model;\n this.generationParams = options.generationParams ?? {};\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 \"User-Agent\": APPKIT_USER_AGENT,\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 generationParams,\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 generationParams,\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 workspaceClient = createWorkspaceClient({\n clientOptions: getClientOptions(),\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 generationParams: options?.generationParams,\n maxSseLineChars: options?.maxSseLineChars,\n maxStreamTextChars: options?.maxStreamTextChars,\n maxToolArgumentsChars: options?.maxToolArgumentsChars,\n });\n }\n\n /**\n * Creates a DatabricksAdapter that talks to the Databricks AI Gateway\n * Chat Completions endpoint (`/ai-gateway/mlflow/v1/chat/completions`).\n *\n * Unlike {@link fromModelServing}, the target model is named in the request\n * body (`model`, e.g. `\"system.ai.claude-opus-5-5\"`) rather than in the URL:\n * the gateway is a single fixed path that routes by the body's `model`. Auth\n * and transport reuse the SDK's `apiClient.request`, same as the serving\n * path, so no bespoke `fetch()` + token handling. The request/response wire\n * format and tool-calling loop are identical to the serving path.\n *\n * @example\n * ```ts\n * import { createApp, createAgent } from \"@databricks/appkit\";\n * import { agents, DatabricksAdapter } from \"@databricks/appkit/beta\";\n *\n * const adapter = await DatabricksAdapter.fromAiGateway({\n * model: \"system.ai.claude-opus-5-5\",\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 static async fromAiGateway(\n options: AiGatewayOptions,\n ): Promise<DatabricksAdapter> {\n const {\n model,\n workspaceClient,\n maxSteps,\n maxTokens,\n generationParams,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n } = options;\n\n const client =\n workspaceClient ??\n (createWorkspaceClient({\n clientOptions: getClientOptions(),\n }) as unknown as WorkspaceClientLike);\n\n return new DatabricksAdapter({\n streamBody: (body, signal) =>\n // Same structural cast as `fromServingEndpoint`: the connector types\n // the client as the SDK's `WorkspaceClient`, but we only need\n // `apiClient.request`.\n streamAiGateway(\n client as unknown as Parameters<typeof streamAiGateway>[0],\n body,\n signal,\n ),\n model,\n maxSteps,\n maxTokens,\n generationParams,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n });\n }\n\n /**\n * Discoverability shim for the Supervisor API adapter. Returns an\n * {@link AgentAdapter} (a `SupervisorApiAdapter` at runtime), NOT a\n * {@link DatabricksAdapter} — the two are separate classes (different\n * wire formats, different lifecycle). The return type is the\n * {@link AgentAdapter} interface so callers aren't bound to the concrete\n * class. Surfaced here so application developers see a single\n * `DatabricksAdapter.from*` autocomplete root.\n *\n * Dynamic-imports `./supervisor-api` to avoid forming a load-time cycle:\n * both files share `connectors/serving/client.ts`.\n *\n * @example\n * ```ts\n * import { DatabricksAdapter } from \"@databricks/appkit/beta\";\n *\n * const model = await DatabricksAdapter.fromSupervisorApi({\n * model: \"databricks-claude-sonnet-4-5\",\n * });\n * ```\n */\n static async fromSupervisorApi(\n options: import(\"./supervisor-api\").SupervisorApiAdapterOptions,\n ): Promise<AgentAdapter> {\n const { fromSupervisorApi } = await import(\"./supervisor-api\");\n return fromSupervisorApi(options);\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 // AI Gateway routes by the body's `model`; serving endpoints name it in\n // the URL and leave this unset.\n if (this.model) body.model = this.model;\n\n applyGenerationParams(body, this.generationParams);\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 // gpt-oss (harmony) sends delta.content as an array of parts\n // (text = answer, reasoning = chain-of-thought), not a string.\n const contentUnknown = deltaUnknown.content;\n const parts =\n typeof contentUnknown === \"string\"\n ? [{ type: \"text\", text: contentUnknown }]\n : Array.isArray(contentUnknown)\n ? contentUnknown\n : [];\n\n for (const part of parts) {\n if (!isRecord(part)) continue;\n if (part.type === \"text\" && typeof part.text === \"string\") {\n const content = part.text;\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 } else if (part.type === \"reasoning\") {\n const content = reasoningPartText(part);\n if (content) yield { type: \"thinking\" as const, content };\n }\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 * Adapter knobs an agent definition contributes to string-model resolution.\n * A subset of {@link AiGatewayOptions} / {@link ModelServingOptions} — the two\n * factories accept the same fields, so one object routes to either.\n */\ntype ModelStringOptions = Pick<\n AiGatewayOptions,\n \"maxSteps\" | \"maxTokens\" | \"generationParams\"\n>;\n\n/**\n * Resolves a string `model` to a {@link DatabricksAdapter}, routing by name:\n *\n * - UC model names (`system.*`, e.g. `\"system.ai.claude-opus-5-5\"`) → AI\n * Gateway ({@link DatabricksAdapter.fromAiGateway}); the model is named in\n * the request body.\n * - Everything else — serving-endpoint names like\n * `\"databricks-claude-sonnet-4-5\"` or a custom endpoint → Model Serving\n * ({@link DatabricksAdapter.fromModelServing}); the name goes in the URL.\n *\n * Serving-endpoint names are `[a-zA-Z0-9_-]` (no dots), so the `system.`\n * prefix cleanly separates the two namespaces and no existing endpoint name\n * changes routing. This is the single decision point shared by the agents\n * plugin and standalone `runAgent`, so the two never drift. To force a\n * `system.*` name onto a serving endpoint instead, pass a pre-built adapter\n * (`DatabricksAdapter.fromServingEndpoint(...)`) as the agent's `model`.\n */\nexport function adapterFromModelString(\n model: string,\n options?: ModelStringOptions,\n): Promise<DatabricksAdapter> {\n return model.startsWith(\"system.\")\n ? DatabricksAdapter.fromAiGateway({ model, ...options })\n : DatabricksAdapter.fromModelServing(model, options);\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\";\n\nimport {\n type StreamBody,\n stream as servingStream,\n streamAiGateway,\n} from \"../connectors/serving/client\";\nimport { APPKIT_USER_AGENT, getClientOptions } from \"../context/client-options\";\nimport { createWorkspaceClient } from \"../workspace-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\n/**\n * Optional generation parameters forwarded to the OpenAI-compatible serving\n * request body. Names match the serving API wire keys. Only keys that are set\n * are sent — undefined values are omitted so the endpoint applies its own\n * defaults. Ranges are not validated here; the serving endpoint validates.\n */\nexport interface GenerationParams {\n /** Sampling temperature. */\n temperature?: number;\n /** Nucleus sampling probability mass (`top_p`). */\n top_p?: number;\n /** Stop sequence(s) that end generation. */\n stop?: string | string[];\n /** Penalize tokens by frequency. */\n frequency_penalty?: number;\n /** Penalize tokens by prior presence. */\n presence_penalty?: number;\n}\n\nconst GENERATION_PARAM_KEYS = [\n \"temperature\",\n \"top_p\",\n \"stop\",\n \"frequency_penalty\",\n \"presence_penalty\",\n] as const satisfies readonly (keyof GenerationParams)[];\n\n/** Copy only the set generation params onto the request body. */\nfunction applyGenerationParams(\n body: Record<string, unknown>,\n params: GenerationParams,\n): void {\n for (const key of GENERATION_PARAM_KEYS) {\n const value = params[key];\n if (value !== undefined) body[key] = value;\n }\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/** Text of a harmony `reasoning` part: `summary[].text` plus an optional `text`. */\nfunction reasoningPartText(part: Record<string, unknown>): string {\n let text = \"\";\n if (Array.isArray(part.summary)) {\n for (const s of part.summary) {\n if (isRecord(s) && typeof s.text === \"string\") text += s.text;\n }\n }\n if (typeof part.text === \"string\") text += part.text;\n return text;\n}\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 /**\n * When set, sent in the request body as `model`. Required by the AI Gateway,\n * which routes by the body's `model` (not the URL). Serving-endpoint paths\n * name the model in the URL and leave this unset.\n */\n model?: string;\n /** Optional generation params forwarded to the serving request body. */\n generationParams?: GenerationParams;\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 /** See {@link RawFetchAdapterOptions.model}. Set by {@link DatabricksAdapter.fromAiGateway}. */\n model?: string;\n generationParams?: GenerationParams;\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 */\nexport interface WorkspaceClientLike {\n apiClient: {\n request(options: Record<string, unknown>): Promise<unknown>;\n };\n}\n\n/**\n * A fixed client, or a provider resolved on every model call. A provider lets\n * one adapter follow the active execution scope (for example\n * `() => getWorkspaceClient()` for on-behalf-of-user agents).\n */\ntype WorkspaceClientSource = WorkspaceClientLike | (() => WorkspaceClientLike);\n\nfunction clientResolver(\n source: WorkspaceClientSource,\n): () => WorkspaceClientLike {\n return typeof source === \"function\" ? source : () => source;\n}\n\nconst fixedClientAdapters = new WeakSet<AgentAdapter>();\n\n/** Record whether an adapter's client is fixed (not a per-call provider). */\nfunction withClientSource<T extends AgentAdapter>(\n source: WorkspaceClientSource | undefined,\n adapter: T,\n): T {\n if (typeof source !== \"function\") fixedClientAdapters.add(adapter);\n return adapter;\n}\n\n/**\n * @internal True when a Databricks adapter was built with a fixed workspace\n * client, so it cannot follow the caller in an on-behalf-of-user agent.\n */\nexport function hasFixedWorkspaceClient(adapter: AgentAdapter): boolean {\n return fixedClientAdapters.has(adapter);\n}\n\ninterface ServingEndpointOptions {\n workspaceClient: WorkspaceClientSource;\n endpointName: string;\n maxSteps?: number;\n maxTokens?: number;\n generationParams?: GenerationParams;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ninterface ModelServingOptions {\n maxSteps?: number;\n maxTokens?: number;\n generationParams?: GenerationParams;\n workspaceClient?: WorkspaceClientSource;\n maxSseLineChars?: number;\n maxStreamTextChars?: number;\n maxToolArgumentsChars?: number;\n}\n\ninterface AiGatewayOptions {\n /**\n * Model to name in the request body, e.g. `\"system.ai.claude-opus-5-5\"`.\n * The gateway routes by this value; there is no per-endpoint URL.\n */\n model: string;\n /**\n * Pre-built WorkspaceClient (or structural equivalent). When omitted, one\n * is created from the ambient client options (SDK credential chain). It is\n * captured once and reused across requests — do not pass a per-request OBO\n * client (it would leak the first request's identity into later ones).\n * To follow the caller per request, pass a provider such as\n * `() => getWorkspaceClient()`; it is resolved on every model call.\n */\n workspaceClient?: WorkspaceClientSource;\n maxSteps?: number;\n maxTokens?: number;\n generationParams?: GenerationParams;\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, createWorkspaceClient } from \"@databricks/appkit\";\n * import { DatabricksAdapter } from \"@databricks/appkit/beta\";\n *\n * const adapter = DatabricksAdapter.fromServingEndpoint({\n * workspaceClient: createWorkspaceClient(),\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 /** UC model name sent in the request body (AI Gateway); unset for serving endpoints. */\n private model?: string;\n private generationParams: GenerationParams;\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.model = options.model;\n this.generationParams = options.generationParams ?? {};\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 \"User-Agent\": APPKIT_USER_AGENT,\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 generationParams,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n } = options;\n const resolveClient = clientResolver(workspaceClient);\n const adapter = 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 resolveClient() as unknown as Parameters<typeof servingStream>[0],\n endpointName,\n body,\n signal,\n ),\n maxSteps,\n maxTokens,\n generationParams,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n });\n return withClientSource(workspaceClient, adapter);\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: WorkspaceClientSource | undefined =\n options?.workspaceClient;\n if (!workspaceClient) {\n workspaceClient = createWorkspaceClient({\n clientOptions: getClientOptions(),\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 generationParams: options?.generationParams,\n maxSseLineChars: options?.maxSseLineChars,\n maxStreamTextChars: options?.maxStreamTextChars,\n maxToolArgumentsChars: options?.maxToolArgumentsChars,\n });\n }\n\n /**\n * Creates a DatabricksAdapter that talks to the Databricks AI Gateway\n * Chat Completions endpoint (`/ai-gateway/mlflow/v1/chat/completions`).\n *\n * Unlike {@link fromModelServing}, the target model is named in the request\n * body (`model`, e.g. `\"system.ai.claude-opus-5-5\"`) rather than in the URL:\n * the gateway is a single fixed path that routes by the body's `model`. Auth\n * and transport reuse the SDK's `apiClient.request`, same as the serving\n * path, so no bespoke `fetch()` + token handling. The request/response wire\n * format and tool-calling loop are identical to the serving path.\n *\n * @example\n * ```ts\n * import { createApp, createAgent } from \"@databricks/appkit\";\n * import { agents, DatabricksAdapter } from \"@databricks/appkit/beta\";\n *\n * const adapter = await DatabricksAdapter.fromAiGateway({\n * model: \"system.ai.claude-opus-5-5\",\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 static async fromAiGateway(\n options: AiGatewayOptions,\n ): Promise<DatabricksAdapter> {\n const {\n model,\n workspaceClient,\n maxSteps,\n maxTokens,\n generationParams,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n } = options;\n\n const resolveClient = clientResolver(\n workspaceClient ??\n (createWorkspaceClient({\n clientOptions: getClientOptions(),\n }) as unknown as WorkspaceClientLike),\n );\n\n const adapter = new DatabricksAdapter({\n streamBody: (body, signal) =>\n // Same structural cast as `fromServingEndpoint`: the connector types\n // the client as the SDK's `WorkspaceClient`, but we only need\n // `apiClient.request`.\n streamAiGateway(\n resolveClient() as unknown as Parameters<typeof streamAiGateway>[0],\n body,\n signal,\n ),\n model,\n maxSteps,\n maxTokens,\n generationParams,\n maxSseLineChars,\n maxStreamTextChars,\n maxToolArgumentsChars,\n });\n return withClientSource(workspaceClient, adapter);\n }\n\n /**\n * Discoverability shim for the Supervisor API adapter. Returns an\n * {@link AgentAdapter} (a `SupervisorApiAdapter` at runtime), NOT a\n * {@link DatabricksAdapter} — the two are separate classes (different\n * wire formats, different lifecycle). The return type is the\n * {@link AgentAdapter} interface so callers aren't bound to the concrete\n * class. Surfaced here so application developers see a single\n * `DatabricksAdapter.from*` autocomplete root.\n *\n * Dynamic-imports `./supervisor-api` to avoid forming a load-time cycle:\n * both files share `connectors/serving/client.ts`.\n *\n * @example\n * ```ts\n * import { DatabricksAdapter } from \"@databricks/appkit/beta\";\n *\n * const model = await DatabricksAdapter.fromSupervisorApi({\n * model: \"databricks-claude-sonnet-4-5\",\n * });\n * ```\n */\n static async fromSupervisorApi(\n options: import(\"./supervisor-api\").SupervisorApiAdapterOptions,\n ): Promise<AgentAdapter> {\n const { fromSupervisorApi } = await import(\"./supervisor-api\");\n return fromSupervisorApi(options);\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 // AI Gateway routes by the body's `model`; serving endpoints name it in\n // the URL and leave this unset.\n if (this.model) body.model = this.model;\n\n applyGenerationParams(body, this.generationParams);\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 // gpt-oss (harmony) sends delta.content as an array of parts\n // (text = answer, reasoning = chain-of-thought), not a string.\n const contentUnknown = deltaUnknown.content;\n const parts =\n typeof contentUnknown === \"string\"\n ? [{ type: \"text\", text: contentUnknown }]\n : Array.isArray(contentUnknown)\n ? contentUnknown\n : [];\n\n for (const part of parts) {\n if (!isRecord(part)) continue;\n if (part.type === \"text\" && typeof part.text === \"string\") {\n const content = part.text;\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 } else if (part.type === \"reasoning\") {\n const content = reasoningPartText(part);\n if (content) yield { type: \"thinking\" as const, content };\n }\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 * Adapter knobs an agent definition contributes to string-model resolution.\n * A subset of {@link AiGatewayOptions} / {@link ModelServingOptions} — the two\n * factories accept the same fields, so one object routes to either.\n */\ntype ModelStringOptions = Pick<\n AiGatewayOptions,\n \"maxSteps\" | \"maxTokens\" | \"generationParams\" | \"workspaceClient\"\n>;\n\n/**\n * Resolves a string `model` to a {@link DatabricksAdapter}, routing by name:\n *\n * - UC model names (`system.*`, e.g. `\"system.ai.claude-opus-5-5\"`) → AI\n * Gateway ({@link DatabricksAdapter.fromAiGateway}); the model is named in\n * the request body.\n * - Everything else — serving-endpoint names like\n * `\"databricks-claude-sonnet-4-5\"` or a custom endpoint → Model Serving\n * ({@link DatabricksAdapter.fromModelServing}); the name goes in the URL.\n *\n * Serving-endpoint names are `[a-zA-Z0-9_-]` (no dots), so the `system.`\n * prefix cleanly separates the two namespaces and no existing endpoint name\n * changes routing. This is the single decision point shared by the agents\n * plugin and standalone `runAgent`, so the two never drift. To force a\n * `system.*` name onto a serving endpoint instead, pass a pre-built adapter\n * (`DatabricksAdapter.fromServingEndpoint(...)`) as the agent's `model`.\n */\nexport function adapterFromModelString(\n model: string,\n options?: ModelStringOptions,\n): Promise<DatabricksAdapter> {\n return model.startsWith(\"system.\")\n ? DatabricksAdapter.fromAiGateway({ model, ...options })\n : DatabricksAdapter.fromModelServing(model, options);\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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"}
|
package/dist/appkit/package.js
CHANGED
package/dist/beta.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { DatabricksAdapter, GenerationParams, parseTextToolCalls } from "./agent
|
|
|
5
5
|
import { AppKitMcpClient, McpConnectAllResult } from "./connectors/mcp/client.js";
|
|
6
6
|
import { FunctionTool, functionToolToDefinition, isFunctionTool } from "./core/agent/tools/function-tool.js";
|
|
7
7
|
import { HostedTool, isHostedTool, mcpServer, resolveHostedTools } from "./core/agent/tools/hosted-tools.js";
|
|
8
|
-
import { AgentDefinition, AgentTool, AgentTools, AgentToolsFn, AgentsPluginConfig, AutoInheritToolsConfig, BaseSystemPromptOption, PluginToolkitProvider, Plugins, PromptContext, RegisteredAgent, ResolvedToolEntry, ToolkitEntry, ToolkitOptions, isToolkitEntry } from "./core/agent/types.js";
|
|
8
|
+
import { AgentAuth, AgentDefinition, AgentTool, AgentTools, AgentToolsFn, AgentsPluginConfig, AutoInheritToolsConfig, BaseSystemPromptOption, PluginToolkitProvider, Plugins, PromptContext, RegisteredAgent, ResolvedToolEntry, ToolkitEntry, ToolkitOptions, isToolkitEntry } from "./core/agent/types.js";
|
|
9
9
|
import { createAgent } from "./core/agent/create-agent.js";
|
|
10
10
|
import { RunAgentInput, RunAgentResult, runAgent } from "./core/agent/run-agent.js";
|
|
11
11
|
import { ToolEntry, ToolRegistry, defineTool, executeFromRegistry, toolsFromRegistry } from "./core/agent/tools/define-tool.js";
|
|
@@ -40,4 +40,4 @@ import { EntityMutationHooks, HookApp, HookContext } from "./plugins/database/ho
|
|
|
40
40
|
import { DatabaseApiConfig, DatabaseApiWriteOperation, DatabaseApiWritesConfig, EntityHooks, IDatabaseConfig, ReadSerializer, ReadSerializerContext } from "./plugins/database/types.js";
|
|
41
41
|
import { database } from "./plugins/database/database.js";
|
|
42
42
|
import "./plugins/database/index.js";
|
|
43
|
-
export { type AgentAdapter, type AgentDefinition, type AgentEvent, type AgentInput, type AgentRunContext, type AgentTool, type AgentToolDefinition, type AgentTools, type AgentToolsFn, type AgentsPluginConfig, AppKitMcpClient, AssertionHandle, AssertionResult, Assessment, type AutoInheritToolsConfig, type BaseSystemPromptOption, CustomJudgeSpec, type DatabaseApiConfig, type DatabaseApiWriteOperation, type DatabaseApiWritesConfig, type DatabaseExports, DatabricksAdapter, DatabricksAuth, DatasetRow, DiscoveredEval, DiscoveredEvalConfig, DriveResult, type EntityHooks, type EntityMutationHooks, EvalDefinition, EvalDriver, EvalProgress, EvalResult, EvalRunSummary, EvalSummary, EvalWebServer, type FunctionTool, type GenerationParams, type HookApp, type HookContext, type HostedSupervisorTool, type HostedTool, HttpDriverOptions, type IAiSearchConfig, type IDatabaseConfig, type IndexConfig, JudgeConfig, JudgeScore, MatchResult, Matcher, type McpConnectAllResult, type Message, MlflowClient, type PluginToolkitProvider, type Plugins, PostResult, type PromptContext, ReadEvalDatasetOptions, type ReadSerializer, type ReadSerializerContext, type RegisteredAgent, ReportOutcome, type RerankerConfig, ResolveDatabricksAuthOptions, type ResolvedToolEntry, type RunAgentInput, type RunAgentResult, RunEvalOptions, RunEvalsOptions, SUPERVISOR_EXTENSION_KEY, type Schema, type SearchFilters, type SearchRequest, type SearchResponse, type SearchResult, Severity, SupervisorApiAdapter, type SupervisorApiAdapterOptions, type SupervisorExtension, type SupervisorTool, TestContext, type Thread, type ThreadStore, type ToolAnnotations, type ToolConfig, type ToolEntry, type ToolProvider, type ToolRegistry, type ToolkitEntry, type ToolkitOptions, type TransactionClient, type WorkspaceClientLike, agentIdFromMarkdownPath, agents, aiSearch, bigid, bigint, boolean, buildAssessments, configureJudge, createAgent, createHttpDriver, database, defineEval, defineEvalConfig, defineSchema, defineTool, discoverEvalConfigs, discoverEvalFiles, enumColumn, equals, evalGlyph, executeFromRegistry, findRootEvalConfig, fk, formatEvalDetail, formatEvalHeadline, formatEvalResults, formatResultsJUnit, formatResultsJson, formatSummaryLine, fromSupervisorApi, functionToolToDefinition, id, includes, integer, isFunctionTool, isHostedTool, isJudgeConfigured, isSupervisorTool, isToolkitEntry, jsonb, loadAgentFromFile, loadAgentsFromDir, loadRootEvalConfig, matches, mcpServer, normalizeHost, parseTextToolCalls, readEvalDataset, reportToMlflow, resolveDatabricksAuth, resolveHostedTools, resolveWorkspaceClient, runAgent, runEval, runEvalsInDir, runWithRetries, summarize, supervisorTools, text, timestamp, tool, toolsFromRegistry, userTurns, uuid, varchar };
|
|
43
|
+
export { type AgentAdapter, type AgentAuth, type AgentDefinition, type AgentEvent, type AgentInput, type AgentRunContext, type AgentTool, type AgentToolDefinition, type AgentTools, type AgentToolsFn, type AgentsPluginConfig, AppKitMcpClient, AssertionHandle, AssertionResult, Assessment, type AutoInheritToolsConfig, type BaseSystemPromptOption, CustomJudgeSpec, type DatabaseApiConfig, type DatabaseApiWriteOperation, type DatabaseApiWritesConfig, type DatabaseExports, DatabricksAdapter, DatabricksAuth, DatasetRow, DiscoveredEval, DiscoveredEvalConfig, DriveResult, type EntityHooks, type EntityMutationHooks, EvalDefinition, EvalDriver, EvalProgress, EvalResult, EvalRunSummary, EvalSummary, EvalWebServer, type FunctionTool, type GenerationParams, type HookApp, type HookContext, type HostedSupervisorTool, type HostedTool, HttpDriverOptions, type IAiSearchConfig, type IDatabaseConfig, type IndexConfig, JudgeConfig, JudgeScore, MatchResult, Matcher, type McpConnectAllResult, type Message, MlflowClient, type PluginToolkitProvider, type Plugins, PostResult, type PromptContext, ReadEvalDatasetOptions, type ReadSerializer, type ReadSerializerContext, type RegisteredAgent, ReportOutcome, type RerankerConfig, ResolveDatabricksAuthOptions, type ResolvedToolEntry, type RunAgentInput, type RunAgentResult, RunEvalOptions, RunEvalsOptions, SUPERVISOR_EXTENSION_KEY, type Schema, type SearchFilters, type SearchRequest, type SearchResponse, type SearchResult, Severity, SupervisorApiAdapter, type SupervisorApiAdapterOptions, type SupervisorExtension, type SupervisorTool, TestContext, type Thread, type ThreadStore, type ToolAnnotations, type ToolConfig, type ToolEntry, type ToolProvider, type ToolRegistry, type ToolkitEntry, type ToolkitOptions, type TransactionClient, type WorkspaceClientLike, agentIdFromMarkdownPath, agents, aiSearch, bigid, bigint, boolean, buildAssessments, configureJudge, createAgent, createHttpDriver, database, defineEval, defineEvalConfig, defineSchema, defineTool, discoverEvalConfigs, discoverEvalFiles, enumColumn, equals, evalGlyph, executeFromRegistry, findRootEvalConfig, fk, formatEvalDetail, formatEvalHeadline, formatEvalResults, formatResultsJUnit, formatResultsJson, formatSummaryLine, fromSupervisorApi, functionToolToDefinition, id, includes, integer, isFunctionTool, isHostedTool, isJudgeConfigured, isSupervisorTool, isToolkitEntry, jsonb, loadAgentFromFile, loadAgentsFromDir, loadRootEvalConfig, matches, mcpServer, normalizeHost, parseTextToolCalls, readEvalDataset, reportToMlflow, resolveDatabricksAuth, resolveHostedTools, resolveWorkspaceClient, runAgent, runEval, runEvalsInDir, runWithRetries, summarize, supervisorTools, text, timestamp, tool, toolsFromRegistry, userTurns, uuid, varchar };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/cache/index.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/cache/index.ts"],"mappings":";;;;;;;AAuDA;;;;;;;;;;;cAAa,YAAA;EAAA,wBACa,uBAAA;EAAA,wBACA,qBAAA;EAAA,iBACP,IAAA;EAAA,eACF,QAAA;EAAA,eACA,WAAA;EAAA,QAEP,OAAA;EAAA,QACA,MAAA;EAAA,QACA,gBAAA;EAAA,QACA,iBAAA;EAAA,QACA,kBAAA;EAAA,QAEA,SAAA;EAAA,QACA,gBAAA;EAAA,QAKD,WAAA,CAAA;EAlBiB;;;;;;EAAA,OA+CjB,eAAA,CAAA,GAAmB,YAAA;EAvClB;;;;;;;EAAA,OAyDK,WAAA,CACX,UAAA,GAAa,OAAA,CAAQ,WAAA,IACpB,OAAA,CAAQ,YAAA;EAFE;;;;;;;;;;;;EAAA,eAmCQ,MAAA;EA2EyB;;;;;;;;;;;;;;;;;;;;EAFxC,YAAA,GAAA,CACJ,GAAA,gCACA,EAAA,GAAK,YAAA,GAAe,WAAA,KAAgB,OAAA,CAAQ,CAAA,GAC5C,OAAA,UACA,OAAA;IAAY,GAAA;IAAc,YAAA,GAAe,WAAA;EAAA,IACxC,OAAA,CAAQ,CAAA;EAkRR;;;;;;;EAAA,QA7HK,iBAAA;EA6JgB;;;;;EAhGlB,GAAA,GAAA,CAAO,GAAA,WAAc,OAAA,CAAQ,CAAA;EAkI5B;;;;;;;EAAA,QAjHO,QAAA;;UAYN,YAAA;;;;;;;;EA+BF,GAAA,GAAA,CACJ,GAAA,UACA,KAAA,EAAO,CAAA,EACP,OAAA;IAAY,GAAA;EAAA,IACX,OAAA;;;;;;EAaG,MAAA,CAAO,GAAA,WAAc,OAAA;;EAMrB,KAAA,CAAA,GAAS,OAAA;;;;;;EAaT,GAAA,CAAI,GAAA,WAAc,OAAA;;;;;;;EAaxB,WAAA,CAAY,KAAA,gCAAqC,OAAA;;EAQ3C,KAAA,CAAA,GAAS,OAAA;;;;;;;;;;SAaR,KAAA,CAAA;;;;;EASD,gBAAA,CAAA,GAAoB,OAAA;AAAA"}
|
package/dist/cache/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { ExecutionError } from "../errors/execution.js";
|
|
|
6
6
|
import { InitializationError } from "../errors/initialization.js";
|
|
7
7
|
import "../errors/index.js";
|
|
8
8
|
import { createLogger } from "../logging/logger.js";
|
|
9
|
+
import { getCurrentPrincipalKey } from "../context/execution-context.js";
|
|
9
10
|
import { createLakebasePool } from "../connectors/lakebase/index.js";
|
|
10
11
|
import { TelemetryManager } from "../telemetry/telemetry-manager.js";
|
|
11
12
|
import { SpanStatusCode } from "../telemetry/index.js";
|
|
@@ -375,7 +376,11 @@ var CacheManager = class CacheManager {
|
|
|
375
376
|
* @returns Cache key
|
|
376
377
|
*/
|
|
377
378
|
generateKey(parts, userKey) {
|
|
378
|
-
const allParts = [
|
|
379
|
+
const allParts = [
|
|
380
|
+
getCurrentPrincipalKey(),
|
|
381
|
+
userKey,
|
|
382
|
+
...parts
|
|
383
|
+
];
|
|
379
384
|
const serialized = JSON.stringify(allParts);
|
|
380
385
|
return createHash("sha256").update(serialized).digest("hex");
|
|
381
386
|
}
|