@databricks/appkit 0.59.0 → 0.61.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/NOTICE.md +11 -10
- package/dist/agents/databricks.js +1 -2
- package/dist/agents/databricks.js.map +1 -1
- package/dist/agents/supervisor-api.js +1 -2
- package/dist/agents/supervisor-api.js.map +1 -1
- package/dist/appkit/package.js +1 -1
- package/dist/cache/index.js +2 -3
- package/dist/cache/index.js.map +1 -1
- package/dist/cli/commands/doctor/bundle.js +3 -11
- package/dist/cli/commands/doctor/bundle.js.map +1 -1
- package/dist/cli/commands/doctor/databricks-client.js +18 -22
- package/dist/cli/commands/doctor/databricks-client.js.map +1 -1
- package/dist/cli/commands/registry/add.js +410 -0
- package/dist/cli/commands/registry/add.js.map +1 -0
- package/dist/cli/commands/registry/client.js +94 -0
- package/dist/cli/commands/registry/client.js.map +1 -0
- package/dist/cli/commands/registry/config-plan.js +110 -0
- package/dist/cli/commands/registry/config-plan.js.map +1 -0
- package/dist/cli/commands/registry/config-writer.js +176 -0
- package/dist/cli/commands/registry/config-writer.js.map +1 -0
- package/dist/cli/commands/registry/constants.js +62 -0
- package/dist/cli/commands/registry/constants.js.map +1 -0
- package/dist/cli/commands/registry/env-reconcile.js +116 -0
- package/dist/cli/commands/registry/env-reconcile.js.map +1 -0
- package/dist/cli/commands/registry/env-writer.js +198 -0
- package/dist/cli/commands/registry/env-writer.js.map +1 -0
- package/dist/cli/commands/registry/index.js +25 -0
- package/dist/cli/commands/registry/index.js.map +1 -0
- package/dist/cli/commands/registry/info.js +45 -0
- package/dist/cli/commands/registry/info.js.map +1 -0
- package/dist/cli/commands/registry/list.js +130 -0
- package/dist/cli/commands/registry/list.js.map +1 -0
- package/dist/cli/commands/registry/requirements.js +92 -0
- package/dist/cli/commands/registry/requirements.js.map +1 -0
- package/dist/cli/commands/registry/server-register.js +124 -0
- package/dist/cli/commands/registry/server-register.js.map +1 -0
- package/dist/cli/commands/registry/workspace-picker.js +353 -0
- package/dist/cli/commands/registry/workspace-picker.js.map +1 -0
- package/dist/cli/deploy-config.js +36 -0
- package/dist/cli/deploy-config.js.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/connectors/context.js +1 -2
- package/dist/connectors/context.js.map +1 -1
- package/dist/connectors/files/client.js +1 -2
- package/dist/connectors/files/client.js.map +1 -1
- package/dist/connectors/genie/client.js +1 -2
- package/dist/connectors/genie/client.js.map +1 -1
- package/dist/connectors/jobs/client.js +1 -2
- package/dist/connectors/jobs/client.js.map +1 -1
- package/dist/connectors/sql-warehouse/client.js +1 -2
- package/dist/connectors/sql-warehouse/client.js.map +1 -1
- package/dist/context/execution-context.d.ts +0 -1
- package/dist/context/execution-context.d.ts.map +1 -1
- package/dist/context/service-context.d.ts +1 -2
- package/dist/context/service-context.d.ts.map +1 -1
- package/dist/context/service-context.js +2 -3
- package/dist/context/service-context.js.map +1 -1
- package/dist/core/appkit.d.ts +1 -2
- package/dist/core/appkit.d.ts.map +1 -1
- package/dist/index.d.ts +3 -5
- package/dist/index.js +2 -3
- package/dist/plugins/agents/agents.d.ts.map +1 -1
- package/dist/plugins/agents/agents.js +117 -80
- package/dist/plugins/agents/agents.js.map +1 -1
- package/dist/plugins/agents/manifest.js +10 -0
- package/dist/plugins/agents/mlflow.js +123 -0
- package/dist/plugins/agents/mlflow.js.map +1 -0
- package/dist/plugins/agents/schemas.js +4 -2
- package/dist/plugins/agents/schemas.js.map +1 -1
- package/dist/plugins/files/plugin.js +1 -2
- package/dist/plugins/files/plugin.js.map +1 -1
- package/dist/plugins/files/types.d.ts +1 -2
- package/dist/plugins/files/types.d.ts.map +1 -1
- package/dist/plugins/jobs/types.d.ts +1 -2
- package/dist/plugins/jobs/types.d.ts.map +1 -1
- package/dist/plugins/lakebase/lakebase.js +1 -2
- package/dist/plugins/lakebase/lakebase.js.map +1 -1
- package/dist/schemas/manifest.js +4 -4
- package/dist/schemas/manifest.js.map +1 -1
- package/dist/shared/src/index.d.ts +4 -1
- package/dist/shared/src/schemas/manifest.d.ts +6 -6
- package/dist/shared/src/workspace-client/client.js +57 -0
- package/dist/shared/src/workspace-client/client.js.map +1 -0
- package/dist/shared/src/workspace-client/errors.d.ts +2 -0
- package/dist/shared/src/workspace-client/errors.js +3 -0
- package/dist/shared/src/workspace-client/factory.d.ts +19 -0
- package/dist/shared/src/workspace-client/factory.d.ts.map +1 -0
- package/dist/shared/src/workspace-client/factory.js +24 -0
- package/dist/shared/src/workspace-client/factory.js.map +1 -0
- package/dist/shared/src/workspace-client/index.d.ts +4 -0
- package/dist/shared/src/workspace-client/legacy.d.ts +31 -0
- package/dist/shared/src/workspace-client/legacy.d.ts.map +1 -0
- package/dist/shared/src/workspace-client/legacy.js +23 -0
- package/dist/shared/src/workspace-client/legacy.js.map +1 -0
- package/dist/shared/src/workspace-client/types.d.ts +49 -0
- package/dist/shared/src/workspace-client/types.d.ts.map +1 -0
- package/dist/type-generator/index.js +1 -2
- package/dist/type-generator/index.js.map +1 -1
- package/dist/type-generator/query-registry.js +1 -2
- package/dist/type-generator/query-registry.js.map +1 -1
- package/dist/type-generator/serving/fetcher.js +1 -2
- package/dist/type-generator/serving/fetcher.js.map +1 -1
- package/dist/type-generator/serving/generator.js +1 -2
- package/dist/type-generator/serving/generator.js.map +1 -1
- package/dist/type-generator/vite-plugin.js +1 -2
- package/dist/type-generator/vite-plugin.js.map +1 -1
- package/dist/workspace-client/index.d.ts +4 -3
- package/dist/workspace-client/index.js +2 -2
- package/dist/workspace-client/legacy.d.ts +9 -4
- package/dist/workspace-client/legacy.d.ts.map +1 -1
- package/dist/workspace-client/legacy.js +3 -3
- package/dist/workspace-client/legacy.js.map +1 -1
- package/dist/workspace-client/types.d.ts +2 -2
- package/docs/api/appkit/Function.createWorkspaceClient.md +4 -4
- package/docs/api/appkit/Interface.WorkspaceClientOptions.md +11 -0
- package/package.json +6 -4
- package/sbom.cdx.json +1 -1
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import { ConfigError } from "../shared/src/workspace-client/legacy.js";
|
|
2
|
+
import { createWorkspaceClient } from "../shared/src/workspace-client/factory.js";
|
|
1
3
|
import { AuthenticationError } from "../errors/authentication.js";
|
|
2
4
|
import { ConfigurationError } from "../errors/configuration.js";
|
|
3
5
|
import { InitializationError } from "../errors/initialization.js";
|
|
4
6
|
import "../errors/index.js";
|
|
5
|
-
import { ConfigError } from "../workspace-client/legacy.js";
|
|
6
|
-
import { createWorkspaceClient } from "../workspace-client/factory.js";
|
|
7
|
-
import "../workspace-client/index.js";
|
|
8
7
|
import { getClientOptions } from "./client-options.js";
|
|
9
8
|
import { createHash } from "node:crypto";
|
|
10
9
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-context.js","names":[],"sources":["../../src/context/service-context.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport {\n AuthenticationError,\n ConfigurationError,\n InitializationError,\n} from \"../errors\";\nimport {\n type ClientOptions,\n ConfigError,\n createWorkspaceClient,\n type sql,\n type WorkspaceClient,\n} from \"../workspace-client\";\nimport { getClientOptions } from \"./client-options\";\nimport type { UserContext } from \"./user-context\";\n\n/**\n * Service context holds the service principal client and shared resources.\n * This is initialized once at app startup and shared across all requests.\n */\nexport interface ServiceContextState {\n /** WorkspaceClient authenticated as the service principal */\n client: WorkspaceClient;\n /** The service principal's user ID */\n serviceUserId: string;\n /** Promise that resolves to the warehouse ID (only present when a plugin requires `SQL_WAREHOUSE` resource) */\n warehouseId?: Promise<string>;\n /** Promise that resolves to the workspace ID */\n workspaceId: Promise<string>;\n}\n\n/**\n * ServiceContext is a singleton that manages the service principal's\n * WorkspaceClient and shared resources like warehouse/workspace IDs.\n *\n * It's initialized once at app startup and provides the foundation\n * for both service principal and user context execution.\n */\nexport class ServiceContext {\n private static instance: ServiceContextState | null = null;\n private static initPromise: Promise<ServiceContextState> | null = null;\n\n /**\n * Initialize the service context. Should be called once at app startup.\n * Safe to call multiple times - will return the same instance.\n *\n * @param options - Which shared resources to resolve (derived from plugin manifests).\n * @param client - Optional pre-configured WorkspaceClient to use instead\n * of creating one from environment credentials.\n */\n static async initialize(\n options?: { warehouseId?: boolean },\n client?: WorkspaceClient,\n ): Promise<ServiceContextState> {\n if (ServiceContext.instance) {\n return ServiceContext.instance;\n }\n\n if (ServiceContext.initPromise) {\n return ServiceContext.initPromise;\n }\n\n ServiceContext.initPromise = ServiceContext.createContext(options, client);\n ServiceContext.instance = await ServiceContext.initPromise;\n return ServiceContext.instance;\n }\n\n /**\n * Get the initialized service context.\n * @throws Error if not initialized\n */\n static get(): ServiceContextState {\n if (!ServiceContext.instance) {\n throw InitializationError.notInitialized(\n \"ServiceContext\",\n \"Call ServiceContext.initialize() first\",\n );\n }\n return ServiceContext.instance;\n }\n\n /**\n * Check if the service context has been initialized.\n */\n static isInitialized(): boolean {\n return ServiceContext.instance !== null;\n }\n\n /**\n * Create a user context from request headers.\n *\n * @param token - The user's access token from x-forwarded-access-token header\n * @param userId - The user's ID from x-forwarded-user header\n * @param userName - Optional user name\n * @throws Error if token is not provided\n */\n static createUserContext(\n token: string,\n userId: string,\n userName?: string,\n userEmail?: string,\n ): UserContext {\n if (!token) {\n throw AuthenticationError.missingToken(\"user token\");\n }\n\n const host = process.env.DATABRICKS_HOST;\n if (!host) {\n throw ConfigurationError.missingEnvVar(\"DATABRICKS_HOST\");\n }\n\n const serviceCtx = ServiceContext.get();\n\n // Create user client with the OAuth token from Databricks Apps\n // Note: We use authType: \"pat\" because the token is passed as a Bearer token\n // just like a PAT, even though it's technically an OAuth token\n const userClient = createWorkspaceClient({\n token,\n host,\n authType: \"pat\",\n clientOptions: getClientOptions(),\n });\n\n const tokenFingerprint = createHash(\"sha256\")\n .update(token)\n .digest(\"hex\")\n .slice(0, 16);\n\n return {\n client: userClient,\n userId,\n userName,\n userEmail,\n tokenFingerprint,\n warehouseId: serviceCtx.warehouseId,\n workspaceId: serviceCtx.workspaceId,\n isUserContext: true,\n };\n }\n\n /**\n * Get the client options for WorkspaceClient.\n * Exposed for testing purposes.\n */\n static getClientOptions(): ClientOptions {\n return getClientOptions();\n }\n\n private static async createContext(\n options?: { warehouseId?: boolean },\n client?: WorkspaceClient,\n ): Promise<ServiceContextState> {\n try {\n const wsClient =\n client ?? createWorkspaceClient({ clientOptions: getClientOptions() });\n\n const [resolvedWorkspaceId, currentUser, resolvedWarehouseId] =\n await Promise.all([\n ServiceContext.getWorkspaceId(wsClient),\n wsClient.currentUser.me(),\n options?.warehouseId\n ? ServiceContext.getWarehouseId(wsClient)\n : Promise.resolve(undefined as string | undefined),\n ]);\n\n if (!currentUser.id) {\n throw ConfigurationError.resourceNotFound(\"Service user ID\");\n }\n\n const warehouseId =\n options?.warehouseId && resolvedWarehouseId !== undefined\n ? Promise.resolve(resolvedWarehouseId)\n : undefined;\n\n return {\n client: wsClient,\n serviceUserId: currentUser.id,\n warehouseId,\n workspaceId: Promise.resolve(resolvedWorkspaceId),\n };\n } catch (e) {\n if (e instanceof ConfigError) {\n throw ConfigurationError.databricksAuthenticationSetupFailed(\n e.baseMessage,\n { cause: e },\n );\n }\n throw e;\n }\n }\n\n private static async getWorkspaceId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WORKSPACE_ID) {\n return process.env.DATABRICKS_WORKSPACE_ID;\n }\n\n const response = (await client.apiClient.request({\n path: \"/api/2.0/preview/scim/v2/Me\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {},\n responseHeaders: [\"x-databricks-org-id\"],\n })) as { \"x-databricks-org-id\": string };\n\n if (!response[\"x-databricks-org-id\"]) {\n throw ConfigurationError.resourceNotFound(\"Workspace ID\");\n }\n\n return response[\"x-databricks-org-id\"];\n }\n\n private static async getWarehouseId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WAREHOUSE_ID) {\n return process.env.DATABRICKS_WAREHOUSE_ID;\n }\n\n const agenticMode =\n process.env.DATABRICKS_APPS_AGENTIC_MODE === \"true\" ||\n process.env.DATABRICKS_APPS_AGENTIC_MODE === \"1\";\n\n if (process.env.NODE_ENV === \"development\" && !agenticMode) {\n const response = (await client.apiClient.request({\n path: \"/api/2.0/sql/warehouses\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {\n skip_cannot_use: \"true\",\n },\n })) as { warehouses: sql.EndpointInfo[] };\n\n const priorities: Record<sql.State, number> = {\n RUNNING: 0,\n STOPPED: 1,\n STARTING: 2,\n STOPPING: 3,\n DELETED: 99,\n DELETING: 99,\n };\n\n const warehouses = (response.warehouses || []).sort((a, b) => {\n return (\n priorities[a.state as sql.State] - priorities[b.state as sql.State]\n );\n });\n\n if (response.warehouses.length === 0) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n const firstWarehouse = warehouses[0];\n if (\n firstWarehouse.state === \"DELETED\" ||\n firstWarehouse.state === \"DELETING\" ||\n !firstWarehouse.id\n ) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n return firstWarehouse.id;\n }\n\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n /**\n * Reset the service context. Only for testing purposes.\n */\n static reset(): void {\n ServiceContext.instance = null;\n ServiceContext.initPromise = null;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service-context.js","names":[],"sources":["../../src/context/service-context.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport {\n AuthenticationError,\n ConfigurationError,\n InitializationError,\n} from \"../errors\";\nimport {\n type ClientOptions,\n ConfigError,\n createWorkspaceClient,\n type sql,\n type WorkspaceClient,\n} from \"../workspace-client\";\nimport { getClientOptions } from \"./client-options\";\nimport type { UserContext } from \"./user-context\";\n\n/**\n * Service context holds the service principal client and shared resources.\n * This is initialized once at app startup and shared across all requests.\n */\nexport interface ServiceContextState {\n /** WorkspaceClient authenticated as the service principal */\n client: WorkspaceClient;\n /** The service principal's user ID */\n serviceUserId: string;\n /** Promise that resolves to the warehouse ID (only present when a plugin requires `SQL_WAREHOUSE` resource) */\n warehouseId?: Promise<string>;\n /** Promise that resolves to the workspace ID */\n workspaceId: Promise<string>;\n}\n\n/**\n * ServiceContext is a singleton that manages the service principal's\n * WorkspaceClient and shared resources like warehouse/workspace IDs.\n *\n * It's initialized once at app startup and provides the foundation\n * for both service principal and user context execution.\n */\nexport class ServiceContext {\n private static instance: ServiceContextState | null = null;\n private static initPromise: Promise<ServiceContextState> | null = null;\n\n /**\n * Initialize the service context. Should be called once at app startup.\n * Safe to call multiple times - will return the same instance.\n *\n * @param options - Which shared resources to resolve (derived from plugin manifests).\n * @param client - Optional pre-configured WorkspaceClient to use instead\n * of creating one from environment credentials.\n */\n static async initialize(\n options?: { warehouseId?: boolean },\n client?: WorkspaceClient,\n ): Promise<ServiceContextState> {\n if (ServiceContext.instance) {\n return ServiceContext.instance;\n }\n\n if (ServiceContext.initPromise) {\n return ServiceContext.initPromise;\n }\n\n ServiceContext.initPromise = ServiceContext.createContext(options, client);\n ServiceContext.instance = await ServiceContext.initPromise;\n return ServiceContext.instance;\n }\n\n /**\n * Get the initialized service context.\n * @throws Error if not initialized\n */\n static get(): ServiceContextState {\n if (!ServiceContext.instance) {\n throw InitializationError.notInitialized(\n \"ServiceContext\",\n \"Call ServiceContext.initialize() first\",\n );\n }\n return ServiceContext.instance;\n }\n\n /**\n * Check if the service context has been initialized.\n */\n static isInitialized(): boolean {\n return ServiceContext.instance !== null;\n }\n\n /**\n * Create a user context from request headers.\n *\n * @param token - The user's access token from x-forwarded-access-token header\n * @param userId - The user's ID from x-forwarded-user header\n * @param userName - Optional user name\n * @throws Error if token is not provided\n */\n static createUserContext(\n token: string,\n userId: string,\n userName?: string,\n userEmail?: string,\n ): UserContext {\n if (!token) {\n throw AuthenticationError.missingToken(\"user token\");\n }\n\n const host = process.env.DATABRICKS_HOST;\n if (!host) {\n throw ConfigurationError.missingEnvVar(\"DATABRICKS_HOST\");\n }\n\n const serviceCtx = ServiceContext.get();\n\n // Create user client with the OAuth token from Databricks Apps\n // Note: We use authType: \"pat\" because the token is passed as a Bearer token\n // just like a PAT, even though it's technically an OAuth token\n const userClient = createWorkspaceClient({\n token,\n host,\n authType: \"pat\",\n clientOptions: getClientOptions(),\n });\n\n const tokenFingerprint = createHash(\"sha256\")\n .update(token)\n .digest(\"hex\")\n .slice(0, 16);\n\n return {\n client: userClient,\n userId,\n userName,\n userEmail,\n tokenFingerprint,\n warehouseId: serviceCtx.warehouseId,\n workspaceId: serviceCtx.workspaceId,\n isUserContext: true,\n };\n }\n\n /**\n * Get the client options for WorkspaceClient.\n * Exposed for testing purposes.\n */\n static getClientOptions(): ClientOptions {\n return getClientOptions();\n }\n\n private static async createContext(\n options?: { warehouseId?: boolean },\n client?: WorkspaceClient,\n ): Promise<ServiceContextState> {\n try {\n const wsClient =\n client ?? createWorkspaceClient({ clientOptions: getClientOptions() });\n\n const [resolvedWorkspaceId, currentUser, resolvedWarehouseId] =\n await Promise.all([\n ServiceContext.getWorkspaceId(wsClient),\n wsClient.currentUser.me(),\n options?.warehouseId\n ? ServiceContext.getWarehouseId(wsClient)\n : Promise.resolve(undefined as string | undefined),\n ]);\n\n if (!currentUser.id) {\n throw ConfigurationError.resourceNotFound(\"Service user ID\");\n }\n\n const warehouseId =\n options?.warehouseId && resolvedWarehouseId !== undefined\n ? Promise.resolve(resolvedWarehouseId)\n : undefined;\n\n return {\n client: wsClient,\n serviceUserId: currentUser.id,\n warehouseId,\n workspaceId: Promise.resolve(resolvedWorkspaceId),\n };\n } catch (e) {\n if (e instanceof ConfigError) {\n throw ConfigurationError.databricksAuthenticationSetupFailed(\n e.baseMessage,\n { cause: e },\n );\n }\n throw e;\n }\n }\n\n private static async getWorkspaceId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WORKSPACE_ID) {\n return process.env.DATABRICKS_WORKSPACE_ID;\n }\n\n const response = (await client.apiClient.request({\n path: \"/api/2.0/preview/scim/v2/Me\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {},\n responseHeaders: [\"x-databricks-org-id\"],\n })) as { \"x-databricks-org-id\": string };\n\n if (!response[\"x-databricks-org-id\"]) {\n throw ConfigurationError.resourceNotFound(\"Workspace ID\");\n }\n\n return response[\"x-databricks-org-id\"];\n }\n\n private static async getWarehouseId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WAREHOUSE_ID) {\n return process.env.DATABRICKS_WAREHOUSE_ID;\n }\n\n const agenticMode =\n process.env.DATABRICKS_APPS_AGENTIC_MODE === \"true\" ||\n process.env.DATABRICKS_APPS_AGENTIC_MODE === \"1\";\n\n if (process.env.NODE_ENV === \"development\" && !agenticMode) {\n const response = (await client.apiClient.request({\n path: \"/api/2.0/sql/warehouses\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {\n skip_cannot_use: \"true\",\n },\n })) as { warehouses: sql.EndpointInfo[] };\n\n const priorities: Record<sql.State, number> = {\n RUNNING: 0,\n STOPPED: 1,\n STARTING: 2,\n STOPPING: 3,\n DELETED: 99,\n DELETING: 99,\n };\n\n const warehouses = (response.warehouses || []).sort((a, b) => {\n return (\n priorities[a.state as sql.State] - priorities[b.state as sql.State]\n );\n });\n\n if (response.warehouses.length === 0) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n const firstWarehouse = warehouses[0];\n if (\n firstWarehouse.state === \"DELETED\" ||\n firstWarehouse.state === \"DELETING\" ||\n !firstWarehouse.id\n ) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n return firstWarehouse.id;\n }\n\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n /**\n * Reset the service context. Only for testing purposes.\n */\n static reset(): void {\n ServiceContext.instance = null;\n ServiceContext.initPromise = null;\n }\n}\n"],"mappings":"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"}
|
package/dist/core/appkit.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { PluginConstructor, PluginData, PluginMap } from "../shared/src/plugin.js";
|
|
2
2
|
import { CacheConfig } from "../shared/src/cache.js";
|
|
3
3
|
import "../shared/src/index.js";
|
|
4
|
-
import { WorkspaceClient } from "../workspace-client/
|
|
5
|
-
import "../workspace-client/index.js";
|
|
4
|
+
import { WorkspaceClient } from "../workspace-client/index.js";
|
|
6
5
|
import { TelemetryConfig } from "../telemetry/types.js";
|
|
7
6
|
import "../telemetry/index.js";
|
|
8
7
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appkit.d.ts","names":[],"sources":["../../src/core/appkit.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"appkit.d.ts","names":[],"sources":["../../src/core/appkit.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuXsB,SAAA,WACV,UAAA,CAAW,iBAAA,qBAAA,CAErB,MAAA;EACE,OAAA,GAAU,CAAA;EACV,SAAA,GAAY,eAAA;EACZ,KAAA,GAAQ,WAAA;EACR,MAAA,GAAS,eAAA;EACT,cAAA,IAAkB,MAAA,EAAQ,SAAA,CAAU,CAAA,aAAc,OAAA;EAClD,wBAAA;AAAA,IAED,OAAA,CAAQ,SAAA,CAAU,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,12 +3,10 @@ import { BasePluginConfig, IAppRouter, PluginData, ToPlugin } from "./shared/src
|
|
|
3
3
|
import { CacheConfig } from "./shared/src/cache.js";
|
|
4
4
|
import { StreamExecutionSettings } from "./shared/src/execute.js";
|
|
5
5
|
import { isSQLTypeMarker, sql } from "./shared/src/sql/helpers.js";
|
|
6
|
+
import { ApiError } from "./shared/src/workspace-client/errors.js";
|
|
7
|
+
import { createWorkspaceClient } from "./shared/src/workspace-client/factory.js";
|
|
6
8
|
import "./shared/src/index.js";
|
|
7
|
-
import {
|
|
8
|
-
import { WorkspaceClientOptions } from "./workspace-client/legacy.js";
|
|
9
|
-
import { WorkspaceClient } from "./workspace-client/types.js";
|
|
10
|
-
import { createWorkspaceClient } from "./workspace-client/factory.js";
|
|
11
|
-
import "./workspace-client/index.js";
|
|
9
|
+
import { WorkspaceClient, WorkspaceClientOptions } from "./workspace-client/index.js";
|
|
12
10
|
import { ExecutionResult } from "./plugin/execution-result.js";
|
|
13
11
|
import { CacheManager } from "./cache/index.js";
|
|
14
12
|
import { ITelemetry, TelemetryConfig } from "./telemetry/types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { isSQLTypeMarker, sql } from "./shared/src/sql/helpers.js";
|
|
2
|
+
import { ApiError } from "./shared/src/workspace-client/errors.js";
|
|
3
|
+
import { createWorkspaceClient } from "./shared/src/workspace-client/factory.js";
|
|
2
4
|
import { createLakebasePoolManager } from "./connectors/lakebase/pool-manager.js";
|
|
3
5
|
import { AppKitError } from "./errors/base.js";
|
|
4
6
|
import { AuthenticationError } from "./errors/authentication.js";
|
|
@@ -10,9 +12,6 @@ import { ServerError } from "./errors/server.js";
|
|
|
10
12
|
import { TunnelError } from "./errors/tunnel.js";
|
|
11
13
|
import { ValidationError } from "./errors/validation.js";
|
|
12
14
|
import "./errors/index.js";
|
|
13
|
-
import { ApiError } from "./workspace-client/errors.js";
|
|
14
|
-
import { createWorkspaceClient } from "./workspace-client/factory.js";
|
|
15
|
-
import "./workspace-client/index.js";
|
|
16
15
|
import { getExecutionContext } from "./context/execution-context.js";
|
|
17
16
|
import { RequestedClaimsPermissionSet, createLakebasePool, generateDatabaseCredential, getLakebaseOrmConfig, getLakebasePgConfig, getUsernameWithApiLookup, getWorkspaceClient } from "./connectors/lakebase/index.js";
|
|
18
17
|
import { SeverityNumber, SpanStatusCode } from "./telemetry/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","names":[],"sources":["../../../src/plugins/agents/agents.ts"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"agents.d.ts","names":[],"sources":["../../../src/plugins/agents/agents.ts"],"mappings":";;;;;;;;;;cA6Ia,YAAA,SAAqB,MAAA,YAAkB,YAAA;EAAA,OAK3C,QAAA,EAAkC,cAAA;EAAA,OAClC,KAAA,EAAO,WAAA;EAAA,UAEI,MAAA,EAAQ,kBAAA;EAAA,QAElB,MAAA;EAAA,QACA,gBAAA;EAAA,QACA,aAAA;EAZgB;;;;;;EAAA,QAsBhB,gBAAA;EAAA,QACA,SAAA;EAAA,QACA,WAAA;EAAA,QACA,YAAA;cAEI,MAAA,EAAQ,kBAAA;EA+rBJ;;;;;;;;;;EAAA,QAhqBR,oBAAA;EAAA,YAKI,sBAAA,CAAA;EA/DoB;EAAA,YAyFpB,cAAA,CAAA;EApFL;EAAA,QAuGC,gBAAA;EAtGD;;;;;;EAAA,QAgHC,WAAA;EAhGA;;;;;EAAA,QAiHA,aAAA;EAYF,KAAA,CAAA,GAAK,OAAA;EAzFH;;;;;;EAwGF,MAAA,CAAA,GAAU,OAAA;EAfL;;;;;EAAA,QAyCG,kBAAA;EAAA,QAmEN,iBAAA;EAAA,QAMM,mBAAA;EAoEA;;;;;;EAAA,QA1CN,mBAAA;EAAA,QAmBM,oBAAA;EAAA,QAuBA,cAAA;EAyUY;;;;;EAAA,QA7RZ,cAAA;EAqWE;;;;;;;;;;;EAAA,QArPR,eAAA;EAynCM;;;;;;;;;;;;EAAA,QA7lCN,eAAA;EAAA,QAkBM,gBAAA;EAAA,QA0DA,kBAAA;EAiEd,aAAA,CAAA,GAAiB,mBAAA;EAIX,gBAAA,CAAA,GAAoB,OAAA;;;;;;;UAYlB,iBAAA;EAUR,YAAA,CAAa,MAAA,EAAQ,UAAA;EAkDrB,YAAA,CAAA,GAAgB,MAAA;EAAA,QAOF,WAAA;;;;;;;;;;;;UA6EN,gCAAA;;;;;;;;;;;UAuBM,aAAA;EAAA,QA2FA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;UA2NA,qBAAA;;;;;;;;;;;;UA0KA,gBAAA;;;;;;;;;;;;;;;UAmIA,WAAA;EAAA,QAiGA,aAAA;EAAA,QA2BA,cAAA;EAAA,QAuCA,kBAAA;EAAA,QASA,gBAAA;EAAA,QAUA,mBAAA;EAAA,QAaN,YAAA;EAAA,QASA,aAAA;EAgBF,QAAA,CAAA,GAAY,OAAA;EAQlB,OAAA,CAAA;6BAE2B,GAAA,EAAO,eAAA,KAAe,OAAA;;2BAG3B,eAAA;;;oCAGS,OAAA,CAAA,MAAA;EAAA;EAAA,QAIjB,iBAAA;AAAA;;;;;;;;;;;;;;;;cAsJH,MAAA,EAAM,QAAA,QAAA,YAAA,EAAA,kBAAA"}
|
|
@@ -20,6 +20,7 @@ import { agentStreamDefaults } from "./defaults.js";
|
|
|
20
20
|
import { EventChannel } from "./event-channel.js";
|
|
21
21
|
import { AgentEventTranslator } from "./event-translator.js";
|
|
22
22
|
import manifest_default from "./manifest.js";
|
|
23
|
+
import { currentTraceId, initAgentTracing, linkTraceToRun, traceAgent, traceTool } from "./mlflow.js";
|
|
23
24
|
import { approvalRequestSchema, cancelRequestSchema, chatRequestSchema, invocationsRequestSchema } from "./schemas.js";
|
|
24
25
|
import { InMemoryThreadStore } from "./thread-store.js";
|
|
25
26
|
import { ToolApprovalGate } from "./tool-approval-gate.js";
|
|
@@ -147,6 +148,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
147
148
|
else this.userStreamCounts.set(entry.userId, next);
|
|
148
149
|
}
|
|
149
150
|
async setup() {
|
|
151
|
+
await initAgentTracing();
|
|
150
152
|
const { agents, defaultAgentName } = await this.buildAgentRegistry();
|
|
151
153
|
this.agents = agents;
|
|
152
154
|
this.defaultAgentName = defaultAgentName;
|
|
@@ -550,7 +552,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
550
552
|
});
|
|
551
553
|
return;
|
|
552
554
|
}
|
|
553
|
-
const { message, threadId, agent: agentName } = parsed.data;
|
|
555
|
+
const { message, threadId, agent: agentName, mlflowRunId } = parsed.data;
|
|
554
556
|
const registered = this.resolveAgent(agentName);
|
|
555
557
|
if (!registered) {
|
|
556
558
|
res.status(400).json({ error: agentName ? `Agent "${agentName}" not found` : "No agent registered" });
|
|
@@ -583,7 +585,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
583
585
|
res.status(500).json({ error: "Thread operation failed" });
|
|
584
586
|
return;
|
|
585
587
|
}
|
|
586
|
-
return this._streamAgent(req, res, registered, thread, userId);
|
|
588
|
+
return this._streamAgent(req, res, registered, thread, userId, mlflowRunId);
|
|
587
589
|
}
|
|
588
590
|
/**
|
|
589
591
|
* Returns the names of tools in `registered.toolIndex` whose annotations
|
|
@@ -621,7 +623,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
621
623
|
});
|
|
622
624
|
return;
|
|
623
625
|
}
|
|
624
|
-
const { input } = parsed.data;
|
|
626
|
+
const { input, mlflowRunId } = parsed.data;
|
|
625
627
|
const registered = this.resolveAgent();
|
|
626
628
|
if (!registered) {
|
|
627
629
|
res.status(400).json({ error: "No agent registered" });
|
|
@@ -664,9 +666,9 @@ var AgentsPlugin = class extends Plugin {
|
|
|
664
666
|
res.status(500).json({ error: "Thread operation failed" });
|
|
665
667
|
return;
|
|
666
668
|
}
|
|
667
|
-
return this._runAgentNonStreaming(req, res, registered, thread, userId);
|
|
669
|
+
return this._runAgentNonStreaming(req, res, registered, thread, userId, mlflowRunId);
|
|
668
670
|
}
|
|
669
|
-
async _streamAgent(req, res, registered, thread, userId) {
|
|
671
|
+
async _streamAgent(req, res, registered, thread, userId, mlflowRunId) {
|
|
670
672
|
const abortController = new AbortController();
|
|
671
673
|
const signal = abortController.signal;
|
|
672
674
|
const requestId = randomUUID();
|
|
@@ -695,37 +697,54 @@ var AgentsPlugin = class extends Plugin {
|
|
|
695
697
|
type: "metadata",
|
|
696
698
|
data: { threadId: thread.id }
|
|
697
699
|
})) outboundEvents.push(evt);
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
700
|
+
await traceAgent(registered.name ?? "agent", { messages: thread.messages.map((m) => ({
|
|
701
|
+
role: m.role,
|
|
702
|
+
content: m.content
|
|
703
|
+
})) }, async (span) => {
|
|
704
|
+
if (mlflowRunId) linkTraceToRun(mlflowRunId);
|
|
705
|
+
const pluginNames = this.context ? this.context.getPluginNames().filter((n) => n !== this.name && n !== "server") : [];
|
|
706
|
+
const messagesWithSystem = [{
|
|
707
|
+
id: "system",
|
|
708
|
+
role: "system",
|
|
709
|
+
content: composePromptForAgent(registered, this.config.baseSystemPrompt, {
|
|
710
|
+
agentName: registered.name,
|
|
711
|
+
pluginNames,
|
|
712
|
+
toolNames: tools.map((t) => t.name)
|
|
713
|
+
}),
|
|
714
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
715
|
+
}, ...thread.messages];
|
|
716
|
+
const fullContent = await consumeAdapterStream(registered.adapter.run({
|
|
717
|
+
messages: messagesWithSystem,
|
|
718
|
+
tools,
|
|
719
|
+
threadId: thread.id,
|
|
720
|
+
signal,
|
|
721
|
+
extensions: buildAdapterExtensions(registered.toolIndex)
|
|
722
|
+
}, {
|
|
723
|
+
executeTool,
|
|
724
|
+
signal
|
|
725
|
+
}), {
|
|
726
|
+
signal,
|
|
727
|
+
onEvent: (event) => {
|
|
728
|
+
for (const translated of translator.translate(event)) outboundEvents.push(translated);
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
if (fullContent) {
|
|
732
|
+
span.setOutputs({
|
|
733
|
+
role: "assistant",
|
|
734
|
+
content: fullContent
|
|
735
|
+
});
|
|
736
|
+
await this.threadStore.addMessage(thread.id, userId, {
|
|
737
|
+
id: randomUUID(),
|
|
738
|
+
role: "assistant",
|
|
739
|
+
content: fullContent,
|
|
740
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
741
|
+
});
|
|
722
742
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
743
|
+
const mlflowTraceId = currentTraceId();
|
|
744
|
+
if (mlflowTraceId) for (const evt of translator.translate({
|
|
745
|
+
type: "metadata",
|
|
746
|
+
data: { mlflowTraceId }
|
|
747
|
+
})) outboundEvents.push(evt);
|
|
729
748
|
});
|
|
730
749
|
for (const evt of translator.finalize()) outboundEvents.push(evt);
|
|
731
750
|
} catch (error) {
|
|
@@ -784,12 +803,14 @@ var AgentsPlugin = class extends Plugin {
|
|
|
784
803
|
* synthesis (which would have been a coding bug given the precheck) is
|
|
785
804
|
* a dropped no-op instead of a runtime crash.
|
|
786
805
|
*/
|
|
787
|
-
async _runAgentNonStreaming(req, res, registered, thread, userId) {
|
|
806
|
+
async _runAgentNonStreaming(req, res, registered, thread, userId, mlflowRunId) {
|
|
788
807
|
const abortController = new AbortController();
|
|
789
808
|
const signal = abortController.signal;
|
|
790
809
|
const requestId = randomUUID();
|
|
791
810
|
this.trackStream(requestId, userId, abortController);
|
|
792
811
|
const tools = Array.from(registered.toolIndex.values()).map((e) => e.def);
|
|
812
|
+
const limits = this.resolvedLimits;
|
|
813
|
+
let mlflowTraceId;
|
|
793
814
|
const runState = {
|
|
794
815
|
req,
|
|
795
816
|
userId,
|
|
@@ -800,7 +821,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
800
821
|
requireForDestructive: false,
|
|
801
822
|
timeoutMs: 0
|
|
802
823
|
},
|
|
803
|
-
limits
|
|
824
|
+
limits,
|
|
804
825
|
translator: new AgentEventTranslator(),
|
|
805
826
|
outboundEvents: new EventChannel(),
|
|
806
827
|
toolCallsUsed: { count: 0 }
|
|
@@ -808,31 +829,44 @@ var AgentsPlugin = class extends Plugin {
|
|
|
808
829
|
const executeTool = (name, args) => this.dispatchToolCall(runState, registered.toolIndex, name, args, 0);
|
|
809
830
|
let fullContent = "";
|
|
810
831
|
try {
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
832
|
+
await traceAgent(registered.name ?? "agent", { messages: thread.messages.map((m) => ({
|
|
833
|
+
role: m.role,
|
|
834
|
+
content: m.content
|
|
835
|
+
})) }, async (span) => {
|
|
836
|
+
if (mlflowRunId) linkTraceToRun(mlflowRunId);
|
|
837
|
+
const pluginNames = this.context ? this.context.getPluginNames().filter((n) => n !== this.name && n !== "server") : [];
|
|
838
|
+
const messagesWithSystem = [{
|
|
839
|
+
id: "system",
|
|
840
|
+
role: "system",
|
|
841
|
+
content: composePromptForAgent(registered, this.config.baseSystemPrompt, {
|
|
842
|
+
agentName: registered.name,
|
|
843
|
+
pluginNames,
|
|
844
|
+
toolNames: tools.map((t) => t.name)
|
|
845
|
+
}),
|
|
846
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
847
|
+
}, ...thread.messages];
|
|
848
|
+
fullContent = await consumeAdapterStream(registered.adapter.run({
|
|
849
|
+
messages: messagesWithSystem,
|
|
850
|
+
tools,
|
|
851
|
+
threadId: thread.id,
|
|
852
|
+
signal
|
|
853
|
+
}, {
|
|
854
|
+
executeTool,
|
|
855
|
+
signal
|
|
856
|
+
}), { signal });
|
|
857
|
+
if (fullContent) {
|
|
858
|
+
span.setOutputs({
|
|
859
|
+
role: "assistant",
|
|
860
|
+
content: fullContent
|
|
861
|
+
});
|
|
862
|
+
await this.threadStore.addMessage(thread.id, userId, {
|
|
863
|
+
id: randomUUID(),
|
|
864
|
+
role: "assistant",
|
|
865
|
+
content: fullContent,
|
|
866
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
mlflowTraceId = currentTraceId();
|
|
836
870
|
});
|
|
837
871
|
} catch (error) {
|
|
838
872
|
if (signal.aborted) {
|
|
@@ -869,6 +903,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
869
903
|
created_at: Math.floor(Date.now() / 1e3),
|
|
870
904
|
status: "completed",
|
|
871
905
|
thread_id: thread.id,
|
|
906
|
+
...mlflowTraceId ? { mlflow_trace_id: mlflowTraceId } : {},
|
|
872
907
|
output: [message]
|
|
873
908
|
});
|
|
874
909
|
}
|
|
@@ -908,24 +943,26 @@ var AgentsPlugin = class extends Plugin {
|
|
|
908
943
|
timeoutMs: runState.approvalPolicy.timeoutMs
|
|
909
944
|
}) === "deny") return `Tool execution denied by user approval gate (tool: ${name}).`;
|
|
910
945
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
if (
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
if (
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
946
|
+
return normalizeToolResult(await traceTool(name, args, async () => {
|
|
947
|
+
let result;
|
|
948
|
+
if (entry.source === "toolkit") {
|
|
949
|
+
if (!this.context) throw new Error("Plugin tool execution requires PluginContext; this should never happen through createApp");
|
|
950
|
+
result = await this.context.executeTool(runState.req, entry.pluginName, entry.localName, args, runState.signal, runState.limits.toolCallTimeoutMs);
|
|
951
|
+
} else if (entry.source === "function") {
|
|
952
|
+
if (typeof args !== "object" || args === null || Array.isArray(args)) throw new Error(`Function tool '${name}' received non-object arguments (got ${args === null ? "null" : Array.isArray(args) ? "array" : typeof args}); expected a JSON object.`);
|
|
953
|
+
result = await entry.functionTool.execute(args);
|
|
954
|
+
} else if (entry.source === "mcp") {
|
|
955
|
+
if (!this.mcpClient) throw new Error("MCP client not connected");
|
|
956
|
+
const oboToken = runState.req.headers["x-forwarded-access-token"];
|
|
957
|
+
const mcpAuth = typeof oboToken === "string" ? { Authorization: `Bearer ${oboToken}` } : void 0;
|
|
958
|
+
result = await this.mcpClient.callTool(entry.mcpToolName, args, mcpAuth);
|
|
959
|
+
} else if (entry.source === "subagent") {
|
|
960
|
+
const childAgent = this.agents.get(entry.agentName);
|
|
961
|
+
if (!childAgent) throw new Error(`Sub-agent not found: ${entry.agentName}`);
|
|
962
|
+
result = await this.runSubAgent(runState, childAgent, args, depth + 1);
|
|
963
|
+
} else if (entry.source === "hosted-supervisor") throw new Error(`Tool '${name}' is a hosted-supervisor tool and cannot be invoked from the Node process. It is executed server-side by the Databricks AI Gateway and is only reachable when the agent's model is a Supervisor API adapter.`);
|
|
964
|
+
return result;
|
|
965
|
+
}));
|
|
929
966
|
}
|
|
930
967
|
/**
|
|
931
968
|
* Runs a sub-agent in response to an `agent-<key>` tool call. Returns the
|