@databricks/appkit 0.31.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +54 -1
- package/NOTICE.md +2 -0
- package/dist/agents/databricks.d.ts.map +1 -1
- package/dist/agents/databricks.js +8 -3
- package/dist/agents/databricks.js.map +1 -1
- package/dist/appkit/package.js +1 -1
- package/dist/beta.d.ts +16 -1
- package/dist/beta.js +14 -1
- package/dist/connectors/index.js +3 -0
- package/dist/connectors/mcp/client.d.ts +85 -0
- package/dist/connectors/mcp/client.d.ts.map +1 -0
- package/dist/connectors/mcp/client.js +296 -0
- package/dist/connectors/mcp/client.js.map +1 -0
- package/dist/connectors/mcp/host-policy.d.ts +51 -0
- package/dist/connectors/mcp/host-policy.d.ts.map +1 -0
- package/dist/connectors/mcp/host-policy.js +168 -0
- package/dist/connectors/mcp/host-policy.js.map +1 -0
- package/dist/connectors/mcp/index.d.ts +3 -0
- package/dist/connectors/mcp/index.js +4 -0
- package/dist/connectors/mcp/types.d.ts +16 -0
- package/dist/connectors/mcp/types.d.ts.map +1 -0
- package/dist/context/index.js +1 -1
- package/dist/core/agent/build-toolkit.d.ts +2 -0
- package/dist/core/agent/build-toolkit.js +45 -0
- package/dist/core/agent/build-toolkit.js.map +1 -0
- package/dist/core/agent/consume-adapter-stream.js +33 -0
- package/dist/core/agent/consume-adapter-stream.js.map +1 -0
- package/dist/core/agent/create-agent.d.ts +27 -0
- package/dist/core/agent/create-agent.d.ts.map +1 -0
- package/dist/core/agent/create-agent.js +50 -0
- package/dist/core/agent/create-agent.js.map +1 -0
- package/dist/core/agent/load-agents.d.ts +72 -0
- package/dist/core/agent/load-agents.d.ts.map +1 -0
- package/dist/core/agent/load-agents.js +268 -0
- package/dist/core/agent/load-agents.js.map +1 -0
- package/dist/core/agent/normalize-result.js +39 -0
- package/dist/core/agent/normalize-result.js.map +1 -0
- package/dist/core/agent/plugins-map.js +44 -0
- package/dist/core/agent/plugins-map.js.map +1 -0
- package/dist/core/agent/run-agent.d.ts +58 -0
- package/dist/core/agent/run-agent.d.ts.map +1 -0
- package/dist/core/agent/run-agent.js +257 -0
- package/dist/core/agent/run-agent.js.map +1 -0
- package/dist/core/agent/system-prompt.js +38 -0
- package/dist/core/agent/system-prompt.js.map +1 -0
- package/dist/core/agent/toolkit-options.js +28 -0
- package/dist/core/agent/toolkit-options.js.map +1 -0
- package/dist/core/agent/toolkit-resolver.js +44 -0
- package/dist/core/agent/toolkit-resolver.js.map +1 -0
- package/dist/core/agent/tools/define-tool.d.ts +66 -0
- package/dist/core/agent/tools/define-tool.d.ts.map +1 -0
- package/dist/core/agent/tools/define-tool.js +50 -0
- package/dist/core/agent/tools/define-tool.js.map +1 -0
- package/dist/core/agent/tools/function-tool.d.ts +38 -0
- package/dist/core/agent/tools/function-tool.d.ts.map +1 -0
- package/dist/core/agent/tools/function-tool.js +22 -0
- package/dist/core/agent/tools/function-tool.js.map +1 -0
- package/dist/core/agent/tools/hosted-tools.d.ts +47 -0
- package/dist/core/agent/tools/hosted-tools.d.ts.map +1 -0
- package/dist/core/agent/tools/hosted-tools.js +67 -0
- package/dist/core/agent/tools/hosted-tools.js.map +1 -0
- package/dist/core/agent/tools/index.d.ts +5 -0
- package/dist/core/agent/tools/index.js +7 -0
- package/dist/core/agent/tools/json-schema.js +24 -0
- package/dist/core/agent/tools/json-schema.js.map +1 -0
- package/dist/core/agent/tools/sql-policy.js +256 -0
- package/dist/core/agent/tools/sql-policy.js.map +1 -0
- package/dist/core/agent/tools/tool.d.ts +63 -0
- package/dist/core/agent/tools/tool.d.ts.map +1 -0
- package/dist/core/agent/tools/tool.js +42 -0
- package/dist/core/agent/tools/tool.js.map +1 -0
- package/dist/core/agent/types.d.ts +299 -0
- package/dist/core/agent/types.d.ts.map +1 -0
- package/dist/core/agent/types.js +12 -0
- package/dist/core/agent/types.js.map +1 -0
- package/dist/core/appkit.d.ts +1 -0
- package/dist/core/appkit.d.ts.map +1 -1
- package/dist/core/appkit.js +31 -4
- package/dist/core/appkit.js.map +1 -1
- package/dist/core/plugin-context.d.ts +133 -0
- package/dist/core/plugin-context.d.ts.map +1 -0
- package/dist/core/plugin-context.js +220 -0
- package/dist/core/plugin-context.js.map +1 -0
- package/dist/index.d.ts +11 -11
- package/dist/internal-telemetry/appkit-log.js +19 -0
- package/dist/internal-telemetry/appkit-log.js.map +1 -0
- package/dist/internal-telemetry/config.js +15 -0
- package/dist/internal-telemetry/config.js.map +1 -0
- package/dist/internal-telemetry/index.js +4 -0
- package/dist/internal-telemetry/reporter.js +132 -0
- package/dist/internal-telemetry/reporter.js.map +1 -0
- package/dist/plugin/plugin.d.ts +18 -3
- package/dist/plugin/plugin.d.ts.map +1 -1
- package/dist/plugin/plugin.js +26 -2
- package/dist/plugin/plugin.js.map +1 -1
- package/dist/plugin/to-plugin.d.ts +3 -2
- package/dist/plugin/to-plugin.d.ts.map +1 -1
- package/dist/plugin/to-plugin.js +7 -4
- package/dist/plugin/to-plugin.js.map +1 -1
- package/dist/plugins/agents/agents.d.ts +186 -0
- package/dist/plugins/agents/agents.d.ts.map +1 -0
- package/dist/plugins/agents/agents.js +979 -0
- package/dist/plugins/agents/agents.js.map +1 -0
- package/dist/plugins/agents/defaults.js +13 -0
- package/dist/plugins/agents/defaults.js.map +1 -0
- package/dist/plugins/agents/event-channel.js +64 -0
- package/dist/plugins/agents/event-channel.js.map +1 -0
- package/dist/plugins/agents/event-translator.js +224 -0
- package/dist/plugins/agents/event-translator.js.map +1 -0
- package/dist/plugins/agents/index.d.ts +4 -0
- package/dist/plugins/agents/index.js +6 -0
- package/dist/plugins/agents/manifest.js +26 -0
- package/dist/plugins/agents/manifest.js.map +1 -0
- package/dist/plugins/agents/schemas.js +51 -0
- package/dist/plugins/agents/schemas.js.map +1 -0
- package/dist/plugins/agents/thread-store.js +58 -0
- package/dist/plugins/agents/thread-store.js.map +1 -0
- package/dist/plugins/agents/tool-approval-gate.js +75 -0
- package/dist/plugins/agents/tool-approval-gate.js.map +1 -0
- package/dist/plugins/analytics/analytics.d.ts +15 -1
- package/dist/plugins/analytics/analytics.d.ts.map +1 -1
- package/dist/plugins/analytics/analytics.js +37 -2
- package/dist/plugins/analytics/analytics.js.map +1 -1
- package/dist/plugins/analytics/index.js +1 -0
- package/dist/plugins/analytics/types.js +15 -0
- package/dist/plugins/analytics/types.js.map +1 -0
- package/dist/plugins/beta-exports.generated.d.ts +2 -0
- package/dist/plugins/beta-exports.generated.js +4 -0
- package/dist/plugins/files/plugin.d.ts +20 -2
- package/dist/plugins/files/plugin.d.ts.map +1 -1
- package/dist/plugins/files/plugin.js +120 -2
- package/dist/plugins/files/plugin.js.map +1 -1
- package/dist/plugins/genie/genie.d.ts +17 -3
- package/dist/plugins/genie/genie.d.ts.map +1 -1
- package/dist/plugins/genie/genie.js +61 -2
- package/dist/plugins/genie/genie.js.map +1 -1
- package/dist/plugins/genie/types.d.ts +10 -2
- package/dist/plugins/genie/types.d.ts.map +1 -1
- package/dist/plugins/jobs/plugin.js +1 -1
- package/dist/plugins/lakebase/index.d.ts +2 -2
- package/dist/plugins/lakebase/index.js +1 -1
- package/dist/plugins/lakebase/lakebase.d.ts +31 -3
- package/dist/plugins/lakebase/lakebase.d.ts.map +1 -1
- package/dist/plugins/lakebase/lakebase.js +77 -5
- package/dist/plugins/lakebase/lakebase.js.map +1 -1
- package/dist/plugins/lakebase/types.d.ts +39 -1
- package/dist/plugins/lakebase/types.d.ts.map +1 -1
- package/dist/plugins/server/index.d.ts +12 -0
- package/dist/plugins/server/index.d.ts.map +1 -1
- package/dist/plugins/server/index.js +47 -10
- package/dist/plugins/server/index.js.map +1 -1
- package/dist/plugins/server/types.d.ts +11 -3
- package/dist/plugins/server/types.d.ts.map +1 -1
- package/dist/shared/src/agent.d.ts +75 -1
- package/dist/shared/src/agent.d.ts.map +1 -1
- package/dist/shared/src/index.d.ts +1 -1
- package/dist/shared/src/plugin.d.ts +8 -0
- package/dist/shared/src/plugin.d.ts.map +1 -1
- package/docs/api/appkit/Class.AppKitMcpClient.md +157 -0
- package/docs/api/appkit/Class.DatabricksAdapter.md +151 -0
- package/docs/api/appkit/Class.Plugin.md +65 -23
- package/docs/api/appkit/Function.agentIdFromMarkdownPath.md +18 -0
- package/docs/api/appkit/Function.createAgent.md +33 -0
- package/docs/api/appkit/Function.createApp.md +10 -8
- package/docs/api/appkit/Function.defineTool.md +26 -0
- package/docs/api/appkit/Function.executeFromRegistry.md +25 -0
- package/docs/api/appkit/Function.functionToolToDefinition.md +16 -0
- package/docs/api/appkit/Function.isFunctionTool.md +16 -0
- package/docs/api/appkit/Function.isHostedTool.md +16 -0
- package/docs/api/appkit/Function.isToolkitEntry.md +18 -0
- package/docs/api/appkit/Function.loadAgentFromFile.md +21 -0
- package/docs/api/appkit/Function.loadAgentsFromDir.md +26 -0
- package/docs/api/appkit/Function.mcpServer.md +28 -0
- package/docs/api/appkit/Function.parseTextToolCalls.md +26 -0
- package/docs/api/appkit/Function.resolveHostedTools.md +16 -0
- package/docs/api/appkit/Function.runAgent.md +26 -0
- package/docs/api/appkit/Function.tool.md +28 -0
- package/docs/api/appkit/Function.toolsFromRegistry.md +20 -0
- package/docs/api/appkit/Interface.AgentAdapter.md +21 -0
- package/docs/api/appkit/Interface.AgentDefinition.md +112 -0
- package/docs/api/appkit/Interface.AgentInput.md +37 -0
- package/docs/api/appkit/Interface.AgentRunContext.md +32 -0
- package/docs/api/appkit/Interface.AgentToolDefinition.md +37 -0
- package/docs/api/appkit/Interface.AgentsPluginConfig.md +241 -0
- package/docs/api/appkit/Interface.AutoInheritToolsConfig.md +27 -0
- package/docs/api/appkit/Interface.BasePluginConfig.md +1 -0
- package/docs/api/appkit/Interface.FunctionTool.md +80 -0
- package/docs/api/appkit/Interface.McpConnectAllResult.md +38 -0
- package/docs/api/appkit/Interface.Message.md +55 -0
- package/docs/api/appkit/Interface.PluginToolkitProvider.md +22 -0
- package/docs/api/appkit/Interface.PromptContext.md +30 -0
- package/docs/api/appkit/Interface.RegisteredAgent.md +75 -0
- package/docs/api/appkit/Interface.RunAgentInput.md +34 -0
- package/docs/api/appkit/Interface.RunAgentResult.md +23 -0
- package/docs/api/appkit/Interface.Thread.md +46 -0
- package/docs/api/appkit/Interface.ThreadStore.md +103 -0
- package/docs/api/appkit/Interface.ToolAnnotations.md +56 -0
- package/docs/api/appkit/Interface.ToolConfig.md +72 -0
- package/docs/api/appkit/Interface.ToolEntry.md +73 -0
- package/docs/api/appkit/Interface.ToolProvider.md +38 -0
- package/docs/api/appkit/Interface.ToolkitEntry.md +59 -0
- package/docs/api/appkit/Interface.ToolkitOptions.md +45 -0
- package/docs/api/appkit/TypeAlias.AgentEvent.md +299 -0
- package/docs/api/appkit/TypeAlias.AgentTool.md +11 -0
- package/docs/api/appkit/TypeAlias.AgentTools.md +8 -0
- package/docs/api/appkit/TypeAlias.AgentToolsFn.md +20 -0
- package/docs/api/appkit/TypeAlias.BaseSystemPromptOption.md +9 -0
- package/docs/api/appkit/TypeAlias.HostedTool.md +10 -0
- package/docs/api/appkit/TypeAlias.Plugins.md +26 -0
- package/docs/api/appkit/TypeAlias.ResolvedToolEntry.md +29 -0
- package/docs/api/appkit/TypeAlias.ToolRegistry.md +6 -0
- package/docs/api/appkit/Variable.agents.md +19 -0
- package/docs/api/appkit.md +113 -62
- package/docs/plugins/agents.md +441 -0
- package/docs/privacy.md +41 -0
- package/llms.txt +54 -1
- package/package.json +4 -2
- package/sbom.cdx.json +1 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ToolAnnotations } from "../../../shared/src/agent.js";
|
|
2
|
+
import "../../../shared/src/index.js";
|
|
3
|
+
import { FunctionTool } from "./function-tool.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
//#region src/core/agent/tools/tool.d.ts
|
|
7
|
+
interface ToolConfig<S extends z.ZodType> {
|
|
8
|
+
/**
|
|
9
|
+
* Optional. When the tool is placed in a keyed record (the standard
|
|
10
|
+
* `tools: { my_tool: tool({...}) }` form, or the function form
|
|
11
|
+
* `tools(plugins) => ({ my_tool: tool({...}) })`), the agents plugin
|
|
12
|
+
* overrides the tool's LLM-visible name with the record key. Set
|
|
13
|
+
* `name` explicitly only if you're constructing a `FunctionTool`
|
|
14
|
+
* outside any keyed-record context — otherwise the record key wins.
|
|
15
|
+
*/
|
|
16
|
+
name?: string;
|
|
17
|
+
/**
|
|
18
|
+
* What the tool does, what it expects, and when the LLM should call it.
|
|
19
|
+
* The model reads this verbatim when deciding whether to invoke the tool,
|
|
20
|
+
* so write it for an LLM, not for a human reader of your code: spell out
|
|
21
|
+
* the inputs, the return shape, and any pre-conditions or side effects.
|
|
22
|
+
*
|
|
23
|
+
* Required. Earlier versions silently fell back to the tool's name when
|
|
24
|
+
* omitted, which surfaced cryptic identifiers like `"get_weather"` as the
|
|
25
|
+
* description — the model then had no signal about expected use and
|
|
26
|
+
* either skipped the tool or called it speculatively. Making this
|
|
27
|
+
* mandatory at the type level forces a real description at authoring
|
|
28
|
+
* time instead of debugging a confused agent later.
|
|
29
|
+
*/
|
|
30
|
+
description: string;
|
|
31
|
+
schema: S;
|
|
32
|
+
/**
|
|
33
|
+
* Behavioural hints forwarded to the resolved tool definition. Prefer
|
|
34
|
+
* `effect` (`"read" | "write" | "update" | "destructive"`) — any mutating
|
|
35
|
+
* value forces the agents-plugin approval gate before `execute()` runs
|
|
36
|
+
* and the client's approval card will colour itself accordingly. Legacy
|
|
37
|
+
* `destructive: true` still gates. Dropped silently before the fix that
|
|
38
|
+
* added this field.
|
|
39
|
+
*/
|
|
40
|
+
annotations?: ToolAnnotations;
|
|
41
|
+
/**
|
|
42
|
+
* Returning a non-string value is fine: the agent runtime serializes
|
|
43
|
+
* the result via `normalizeToolResult` before handing it to the LLM
|
|
44
|
+
* (strings pass through; `null` becomes `"null"`; everything else gets
|
|
45
|
+
* `JSON.stringify`'d; `undefined` becomes `""`). Return whatever shape
|
|
46
|
+
* is most natural for your tool — typically an object — and let the
|
|
47
|
+
* runtime handle the wire format.
|
|
48
|
+
*/
|
|
49
|
+
execute: (args: z.infer<S>) => unknown | Promise<unknown>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Factory for defining function tools with Zod schemas.
|
|
53
|
+
*
|
|
54
|
+
* - Generates JSON Schema (for the LLM) from the Zod schema via `z.toJSONSchema()`.
|
|
55
|
+
* - Infers the `execute` argument type from the schema.
|
|
56
|
+
* - Validates tool call arguments at runtime. On validation failure, returns
|
|
57
|
+
* a formatted error string to the LLM instead of throwing, so the model
|
|
58
|
+
* can self-correct on its next turn.
|
|
59
|
+
*/
|
|
60
|
+
declare function tool<S extends z.ZodType>(config: ToolConfig<S>): FunctionTool;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { ToolConfig, tool };
|
|
63
|
+
//# sourceMappingURL=tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.d.ts","names":[],"sources":["../../../../src/core/agent/tools/tool.ts"],"mappings":";;;;;;UAKiB,UAAA,WAAqB,CAAA,CAAE,OAAA;;;AAAxC;;;;;;EASE,IAAA;EAiCkB;;;;;;;;;;;;;EAnBlB,WAAA;EACA,MAAA,EAAQ,CAAA;EAkBU;;;;;;AAYpB;;EArBE,WAAA,GAAc,eAAA;EAqBiB;;;;;;;;EAZ/B,OAAA,GAAU,IAAA,EAAM,CAAA,CAAE,KAAA,CAAM,CAAA,gBAAiB,OAAA;AAAA;;;;;;;;;;iBAY3B,IAAA,WAAe,CAAA,CAAE,OAAA,CAAA,CAAS,MAAA,EAAQ,UAAA,CAAW,CAAA,IAAK,YAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { toToolJSONSchema } from "./json-schema.js";
|
|
2
|
+
|
|
3
|
+
//#region src/core/agent/tools/tool.ts
|
|
4
|
+
/**
|
|
5
|
+
* Factory for defining function tools with Zod schemas.
|
|
6
|
+
*
|
|
7
|
+
* - Generates JSON Schema (for the LLM) from the Zod schema via `z.toJSONSchema()`.
|
|
8
|
+
* - Infers the `execute` argument type from the schema.
|
|
9
|
+
* - Validates tool call arguments at runtime. On validation failure, returns
|
|
10
|
+
* a formatted error string to the LLM instead of throwing, so the model
|
|
11
|
+
* can self-correct on its next turn.
|
|
12
|
+
*/
|
|
13
|
+
function tool(config) {
|
|
14
|
+
const parameters = toToolJSONSchema(config.schema);
|
|
15
|
+
const labelForErrors = config.name ?? "tool";
|
|
16
|
+
return {
|
|
17
|
+
type: "function",
|
|
18
|
+
...config.name !== void 0 ? { name: config.name } : {},
|
|
19
|
+
description: config.description,
|
|
20
|
+
parameters,
|
|
21
|
+
...config.annotations ? { annotations: config.annotations } : {},
|
|
22
|
+
execute: async (args) => {
|
|
23
|
+
const parsed = config.schema.safeParse(args);
|
|
24
|
+
if (!parsed.success) return formatZodError(parsed.error, labelForErrors);
|
|
25
|
+
return config.execute(parsed.data);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Formats a Zod validation error into an LLM-friendly string.
|
|
31
|
+
*
|
|
32
|
+
* Example: `Invalid arguments for get_weather: city: Invalid input: expected string, received undefined`
|
|
33
|
+
*/
|
|
34
|
+
function formatZodError(error, toolName) {
|
|
35
|
+
return `Invalid arguments for ${toolName}: ${error.issues.map((issue) => {
|
|
36
|
+
return `${issue.path.length > 0 ? issue.path.join(".") : "(root)"}: ${issue.message}`;
|
|
37
|
+
}).join("; ")}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { formatZodError, tool };
|
|
42
|
+
//# sourceMappingURL=tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.js","names":[],"sources":["../../../../src/core/agent/tools/tool.ts"],"sourcesContent":["import type { ToolAnnotations } from \"shared\";\nimport type { z } from \"zod\";\nimport type { FunctionTool } from \"./function-tool\";\nimport { toToolJSONSchema } from \"./json-schema\";\n\nexport interface ToolConfig<S extends z.ZodType> {\n /**\n * Optional. When the tool is placed in a keyed record (the standard\n * `tools: { my_tool: tool({...}) }` form, or the function form\n * `tools(plugins) => ({ my_tool: tool({...}) })`), the agents plugin\n * overrides the tool's LLM-visible name with the record key. Set\n * `name` explicitly only if you're constructing a `FunctionTool`\n * outside any keyed-record context — otherwise the record key wins.\n */\n name?: string;\n /**\n * What the tool does, what it expects, and when the LLM should call it.\n * The model reads this verbatim when deciding whether to invoke the tool,\n * so write it for an LLM, not for a human reader of your code: spell out\n * the inputs, the return shape, and any pre-conditions or side effects.\n *\n * Required. Earlier versions silently fell back to the tool's name when\n * omitted, which surfaced cryptic identifiers like `\"get_weather\"` as the\n * description — the model then had no signal about expected use and\n * either skipped the tool or called it speculatively. Making this\n * mandatory at the type level forces a real description at authoring\n * time instead of debugging a confused agent later.\n */\n description: string;\n schema: S;\n /**\n * Behavioural hints forwarded to the resolved tool definition. Prefer\n * `effect` (`\"read\" | \"write\" | \"update\" | \"destructive\"`) — any mutating\n * value forces the agents-plugin approval gate before `execute()` runs\n * and the client's approval card will colour itself accordingly. Legacy\n * `destructive: true` still gates. Dropped silently before the fix that\n * added this field.\n */\n annotations?: ToolAnnotations;\n /**\n * Returning a non-string value is fine: the agent runtime serializes\n * the result via `normalizeToolResult` before handing it to the LLM\n * (strings pass through; `null` becomes `\"null\"`; everything else gets\n * `JSON.stringify`'d; `undefined` becomes `\"\"`). Return whatever shape\n * is most natural for your tool — typically an object — and let the\n * runtime handle the wire format.\n */\n execute: (args: z.infer<S>) => unknown | Promise<unknown>;\n}\n\n/**\n * Factory for defining function tools with Zod schemas.\n *\n * - Generates JSON Schema (for the LLM) from the Zod schema via `z.toJSONSchema()`.\n * - Infers the `execute` argument type from the schema.\n * - Validates tool call arguments at runtime. On validation failure, returns\n * a formatted error string to the LLM instead of throwing, so the model\n * can self-correct on its next turn.\n */\nexport function tool<S extends z.ZodType>(config: ToolConfig<S>): FunctionTool {\n const parameters = toToolJSONSchema(config.schema);\n\n // `name` is only used for the zod-validation error message and the\n // FunctionTool's `name` field; the agents plugin overrides the latter\n // with the record key (`tools: { my_tool: ... }` -> \"my_tool\") at\n // index-build time. Fall back to a generic label so errors are still\n // legible when `name` is omitted.\n const labelForErrors = config.name ?? \"tool\";\n\n return {\n type: \"function\",\n ...(config.name !== undefined ? { name: config.name } : {}),\n description: config.description,\n parameters,\n ...(config.annotations ? { annotations: config.annotations } : {}),\n execute: async (args: Record<string, unknown>) => {\n const parsed = config.schema.safeParse(args);\n if (!parsed.success) {\n return formatZodError(parsed.error, labelForErrors);\n }\n return config.execute(parsed.data as z.infer<S>);\n },\n };\n}\n\n/**\n * Formats a Zod validation error into an LLM-friendly string.\n *\n * Example: `Invalid arguments for get_weather: city: Invalid input: expected string, received undefined`\n */\nexport function formatZodError(error: z.ZodError, toolName: string): string {\n const parts = error.issues.map((issue) => {\n const field = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n return `${field}: ${issue.message}`;\n });\n return `Invalid arguments for ${toolName}: ${parts.join(\"; \")}`;\n}\n"],"mappings":";;;;;;;;;;;;AA2DA,SAAgB,KAA0B,QAAqC;CAC7E,MAAM,aAAa,iBAAiB,OAAO,OAAO;CAOlD,MAAM,iBAAiB,OAAO,QAAQ;AAEtC,QAAO;EACL,MAAM;EACN,GAAI,OAAO,SAAS,SAAY,EAAE,MAAM,OAAO,MAAM,GAAG,EAAE;EAC1D,aAAa,OAAO;EACpB;EACA,GAAI,OAAO,cAAc,EAAE,aAAa,OAAO,aAAa,GAAG,EAAE;EACjE,SAAS,OAAO,SAAkC;GAChD,MAAM,SAAS,OAAO,OAAO,UAAU,KAAK;AAC5C,OAAI,CAAC,OAAO,QACV,QAAO,eAAe,OAAO,OAAO,eAAe;AAErD,UAAO,OAAO,QAAQ,OAAO,KAAmB;;EAEnD;;;;;;;AAQH,SAAgB,eAAe,OAAmB,UAA0B;AAK1E,QAAO,yBAAyB,SAAS,IAJ3B,MAAM,OAAO,KAAK,UAAU;AAExC,SAAO,GADO,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,IAAI,GAAG,SAC7C,IAAI,MAAM;GAC1B,CACiD,KAAK,KAAK"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { AgentAdapter, AgentToolDefinition, ThreadStore, ToolAnnotations } from "../../shared/src/agent.js";
|
|
2
|
+
import { BasePluginConfig } from "../../shared/src/plugin.js";
|
|
3
|
+
import "../../shared/src/index.js";
|
|
4
|
+
import { McpHostPolicyConfig } from "../../connectors/mcp/host-policy.js";
|
|
5
|
+
import "../../connectors/mcp/index.js";
|
|
6
|
+
import { FunctionTool } from "./tools/function-tool.js";
|
|
7
|
+
import { HostedTool } from "./tools/hosted-tools.js";
|
|
8
|
+
|
|
9
|
+
//#region src/core/agent/types.d.ts
|
|
10
|
+
/**
|
|
11
|
+
* A tool reference produced by a plugin's `.toolkit()` call. The agents plugin
|
|
12
|
+
* recognizes the `__toolkitRef` brand and dispatches tool invocations through
|
|
13
|
+
* `PluginContext.executeTool(req, pluginName, localName, ...)`, preserving
|
|
14
|
+
* OBO (asUser) and telemetry spans.
|
|
15
|
+
*/
|
|
16
|
+
interface ToolkitEntry {
|
|
17
|
+
readonly __toolkitRef: true;
|
|
18
|
+
pluginName: string;
|
|
19
|
+
localName: string;
|
|
20
|
+
def: AgentToolDefinition;
|
|
21
|
+
annotations?: ToolAnnotations;
|
|
22
|
+
/**
|
|
23
|
+
* Whether this tool is eligible for `autoInheritTools` spreading. Mirrors
|
|
24
|
+
* {@link ToolEntry.autoInheritable} from the source registry so the agents
|
|
25
|
+
* plugin can filter auto-inherited tools without re-walking the provider's
|
|
26
|
+
* internal registry.
|
|
27
|
+
*/
|
|
28
|
+
autoInheritable?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Any tool an agent can invoke: inline function tools (`tool()`), hosted MCP
|
|
32
|
+
* tools (`mcpServer()` / raw hosted), or toolkit references from plugins
|
|
33
|
+
* (`analytics().toolkit()`).
|
|
34
|
+
*/
|
|
35
|
+
type AgentTool = FunctionTool | HostedTool | ToolkitEntry;
|
|
36
|
+
interface ToolkitOptions {
|
|
37
|
+
/** Key prefix to prepend to each tool's local name. Defaults to `${pluginName}.`. */
|
|
38
|
+
prefix?: string;
|
|
39
|
+
/** Only include tools whose local name matches one of these. */
|
|
40
|
+
only?: string[];
|
|
41
|
+
/** Exclude tools whose local name matches one of these. */
|
|
42
|
+
except?: string[];
|
|
43
|
+
/** Remap specific local names to different keys (applied after prefix). */
|
|
44
|
+
rename?: Record<string, string>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Minimum shape every entry in the {@link Plugins} map must expose. Core
|
|
48
|
+
* plugins (analytics, files, genie, lakebase) implement this directly via
|
|
49
|
+
* their `.toolkit()` method. The agents plugin and standalone `runAgent`
|
|
50
|
+
* synthesize this shape for any registered plugin that doesn't implement
|
|
51
|
+
* `.toolkit()` directly (falling back to `getAgentTools()` walking).
|
|
52
|
+
*/
|
|
53
|
+
interface PluginToolkitProvider {
|
|
54
|
+
toolkit(opts?: ToolkitOptions): Record<string, ToolkitEntry>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Plugin map passed to the function form of {@link AgentDefinition.tools}.
|
|
58
|
+
* Each entry exposes a `.toolkit(opts?)` method that returns a record of
|
|
59
|
+
* {@link ToolkitEntry} markers ready to be spread into a tool record.
|
|
60
|
+
*
|
|
61
|
+
* AppKit does not statically know which plugins the surrounding
|
|
62
|
+
* `createApp` will register, so this is a plain string-keyed record.
|
|
63
|
+
* Refer to plugins by the name used in `createApp({ plugins: [...] })`;
|
|
64
|
+
* unknown names resolve to `undefined` at runtime.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* const support = createAgent({
|
|
69
|
+
* instructions: "...",
|
|
70
|
+
* tools(plugins) {
|
|
71
|
+
* return {
|
|
72
|
+
* get_weather: tool({ ... }),
|
|
73
|
+
* ...plugins.analytics.toolkit(),
|
|
74
|
+
* ...plugins.files.toolkit({ only: ["uploads.read"] }),
|
|
75
|
+
* };
|
|
76
|
+
* },
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
type Plugins = Record<string, PluginToolkitProvider>;
|
|
81
|
+
/**
|
|
82
|
+
* Context passed to `baseSystemPrompt` callbacks.
|
|
83
|
+
*/
|
|
84
|
+
interface PromptContext {
|
|
85
|
+
agentName: string;
|
|
86
|
+
pluginNames: string[];
|
|
87
|
+
toolNames: string[];
|
|
88
|
+
}
|
|
89
|
+
type BaseSystemPromptOption = false | string | ((ctx: PromptContext) => string);
|
|
90
|
+
/**
|
|
91
|
+
* Per-agent tool record. String keys map to inline tools, toolkit entries,
|
|
92
|
+
* hosted tools, etc.
|
|
93
|
+
*/
|
|
94
|
+
type AgentTools = Record<string, AgentTool>;
|
|
95
|
+
/**
|
|
96
|
+
* Function form of `AgentDefinition.tools`. Receives the typed
|
|
97
|
+
* {@link Plugins} map and returns a tool record. Invoked exactly once at
|
|
98
|
+
* setup (or once per `runAgent` call in standalone mode); the result is
|
|
99
|
+
* cached as the agent's resolved tool record.
|
|
100
|
+
*
|
|
101
|
+
* Use the function form when an agent needs tools from registered plugins.
|
|
102
|
+
* The bare object form is fine when an agent only uses inline tools.
|
|
103
|
+
*/
|
|
104
|
+
type AgentToolsFn = (plugins: Plugins) => AgentTools;
|
|
105
|
+
interface AgentDefinition {
|
|
106
|
+
/**
|
|
107
|
+
* Stable identifier for the agent. **Optional and informational** —
|
|
108
|
+
* when the definition is registered via `agents: { foo: def }` (code) or
|
|
109
|
+
* lives at `config/agents/<id>/agent.md` (markdown), the **registry key
|
|
110
|
+
* always wins** and `name` is ignored. The agent will be reachable as
|
|
111
|
+
* `foo` (or `<id>`) regardless of what this field contains.
|
|
112
|
+
*
|
|
113
|
+
* Set `name` when:
|
|
114
|
+
* - Running standalone via `runAgent({ agent: def })`, where there is
|
|
115
|
+
* no enclosing key. The runtime uses it for the agent's slot in
|
|
116
|
+
* error messages and OTel spans.
|
|
117
|
+
* - Building a definition that may be passed to either form and you
|
|
118
|
+
* want a consistent fallback label.
|
|
119
|
+
*
|
|
120
|
+
* Setting `name` to a value that differs from the registry key is
|
|
121
|
+
* harmless but confusing — prefer keeping them aligned or omitting `name`
|
|
122
|
+
* entirely.
|
|
123
|
+
*/
|
|
124
|
+
name?: string;
|
|
125
|
+
/** System prompt body. For markdown-loaded agents this is the file body. */
|
|
126
|
+
instructions: string;
|
|
127
|
+
/**
|
|
128
|
+
* Model adapter (or endpoint-name string sugar for
|
|
129
|
+
* `DatabricksAdapter.fromServingEndpoint({ endpointName })`). Optional —
|
|
130
|
+
* falls back to the plugin's `defaultModel`.
|
|
131
|
+
*/
|
|
132
|
+
model?: AgentAdapter | Promise<AgentAdapter> | string;
|
|
133
|
+
/**
|
|
134
|
+
* Per-agent tool record. Key is the LLM-visible tool-call name.
|
|
135
|
+
*
|
|
136
|
+
* Accepts either a plain record (for agents that only use inline tools)
|
|
137
|
+
* or a function `(plugins) => Record<string, AgentTool>` that receives
|
|
138
|
+
* the typed {@link Plugins} map and returns a tool record (for agents
|
|
139
|
+
* that pull tools from registered plugins).
|
|
140
|
+
*
|
|
141
|
+
* The function is invoked once at agent setup; the result is cached.
|
|
142
|
+
* Don't put per-request logic in there.
|
|
143
|
+
*/
|
|
144
|
+
tools?: AgentTools | AgentToolsFn;
|
|
145
|
+
/** Sub-agents, exposed as `agent-<key>` tools on this agent. */
|
|
146
|
+
agents?: Record<string, AgentDefinition>;
|
|
147
|
+
/** Override the plugin's baseSystemPrompt for this agent only. */
|
|
148
|
+
baseSystemPrompt?: BaseSystemPromptOption;
|
|
149
|
+
maxSteps?: number;
|
|
150
|
+
maxTokens?: number;
|
|
151
|
+
/**
|
|
152
|
+
* When true, the thread used for a chat request against this agent is
|
|
153
|
+
* deleted from `ThreadStore` after the stream completes (success or
|
|
154
|
+
* failure). Use for stateless one-shot agents — e.g. autocomplete, where
|
|
155
|
+
* each request is independent and retaining history would both poison
|
|
156
|
+
* future calls and accumulate unbounded state in the default
|
|
157
|
+
* `InMemoryThreadStore`. Defaults to `false`.
|
|
158
|
+
*/
|
|
159
|
+
ephemeral?: boolean;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Auto-inherit configuration. When enabled for a given agent origin, agents
|
|
163
|
+
* with no explicit `tools:` declaration receive every registered ToolProvider
|
|
164
|
+
* plugin tool whose author marked `autoInheritable: true`. Tools without that
|
|
165
|
+
* flag — destructive, state-mutating, or privilege-sensitive — never spread
|
|
166
|
+
* automatically and must be wired via `tools:` (object or function form in
|
|
167
|
+
* code, `plugin:NAME` entries in markdown frontmatter).
|
|
168
|
+
*
|
|
169
|
+
* Defaults are `false` for both origins (safe-by-default): developers must
|
|
170
|
+
* consciously opt an origin in to any auto-inherit behaviour.
|
|
171
|
+
*/
|
|
172
|
+
interface AutoInheritToolsConfig {
|
|
173
|
+
/** Default for agents loaded from markdown files. Default: `false`. */
|
|
174
|
+
file?: boolean;
|
|
175
|
+
/** Default for code-defined agents (via `agents: { foo: createAgent(...) }`). Default: `false`. */
|
|
176
|
+
code?: boolean;
|
|
177
|
+
}
|
|
178
|
+
interface AgentsPluginConfig extends BasePluginConfig {
|
|
179
|
+
/** Directory of agent packages (`<id>/agent.md` each). Default `./config/agents`. Set to `false` to disable. */
|
|
180
|
+
dir?: string | false;
|
|
181
|
+
/** Code-defined agents, merged with file-loaded ones (code wins on key collision). */
|
|
182
|
+
agents?: Record<string, AgentDefinition>;
|
|
183
|
+
/** Agent used when clients don't specify one. Defaults to the first-registered agent or the file with `default: true` frontmatter. */
|
|
184
|
+
defaultAgent?: string;
|
|
185
|
+
/** Default model for agents that don't specify their own (in code or frontmatter). */
|
|
186
|
+
defaultModel?: AgentAdapter | Promise<AgentAdapter> | string;
|
|
187
|
+
/** Ambient tool library. Keys may be referenced by markdown frontmatter via `tools: [key1, key2]`. */
|
|
188
|
+
tools?: Record<string, AgentTool>;
|
|
189
|
+
/** Whether to auto-inherit every ToolProvider plugin's toolkit. Accepts a boolean shorthand. */
|
|
190
|
+
autoInheritTools?: boolean | AutoInheritToolsConfig;
|
|
191
|
+
/** Persistent thread store. Default: in-memory. */
|
|
192
|
+
threadStore?: ThreadStore;
|
|
193
|
+
/** Customize or disable the AppKit base system prompt. */
|
|
194
|
+
baseSystemPrompt?: BaseSystemPromptOption;
|
|
195
|
+
/**
|
|
196
|
+
* MCP server host policy. By default only same-origin Databricks workspace
|
|
197
|
+
* URLs may be used as MCP endpoints; custom hosts must be explicitly
|
|
198
|
+
* allowlisted here. Workspace credentials (SP / OBO) are never forwarded
|
|
199
|
+
* to non-workspace hosts.
|
|
200
|
+
*/
|
|
201
|
+
mcp?: McpHostPolicyConfig;
|
|
202
|
+
/**
|
|
203
|
+
* Human-in-the-loop approval gate for mutating tool calls. When enabled
|
|
204
|
+
* (the default), the agents plugin emits an `appkit.approval_pending` SSE
|
|
205
|
+
* event before executing any tool whose annotation flags it as mutating —
|
|
206
|
+
* `effect: "write" | "update" | "destructive"` (preferred) or the legacy
|
|
207
|
+
* `destructive: true` boolean — and waits for a `POST /chat/approve`
|
|
208
|
+
* decision from the same user who initiated the stream. A missing decision
|
|
209
|
+
* after `timeoutMs` auto-denies the call.
|
|
210
|
+
*/
|
|
211
|
+
approval?: {
|
|
212
|
+
/**
|
|
213
|
+
* Require human approval for tools that mutate state. Triggered by
|
|
214
|
+
* `effect: "write" | "update" | "destructive"` (preferred) or the legacy
|
|
215
|
+
* `destructive: true` boolean. Default: `true`.
|
|
216
|
+
*/
|
|
217
|
+
requireForDestructive?: boolean; /** Milliseconds to wait before auto-denying. Default: 60_000. */
|
|
218
|
+
timeoutMs?: number;
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* Runtime resource limits applied during agent execution. Defaults are
|
|
222
|
+
* tuned to protect a single-instance deployment from a misbehaving user or
|
|
223
|
+
* a runaway prompt injection; tighten or relax as appropriate for the
|
|
224
|
+
* deployment's scale and trust model. Request-body caps (chat message
|
|
225
|
+
* size, invocations input size / length) are enforced statically by the
|
|
226
|
+
* Zod schemas and are not configurable here.
|
|
227
|
+
*/
|
|
228
|
+
limits?: {
|
|
229
|
+
/**
|
|
230
|
+
* Max concurrent chat streams a single user may have open. Subsequent
|
|
231
|
+
* `POST /chat` requests from that user while at-limit are rejected with
|
|
232
|
+
* HTTP 429. Default: `5`.
|
|
233
|
+
*/
|
|
234
|
+
maxConcurrentStreamsPerUser?: number;
|
|
235
|
+
/**
|
|
236
|
+
* Max tool invocations per agent run (across the full tool-call graph,
|
|
237
|
+
* including sub-agent invocations). A run that exceeds the budget is
|
|
238
|
+
* aborted with a terminal error event. Default: `50`.
|
|
239
|
+
*/
|
|
240
|
+
maxToolCalls?: number;
|
|
241
|
+
/**
|
|
242
|
+
* Max sub-agent recursion depth. Protects against a prompt-injected
|
|
243
|
+
* agent that delegates to a sub-agent which in turn delegates back to
|
|
244
|
+
* itself (directly or transitively). Default: `3`.
|
|
245
|
+
*/
|
|
246
|
+
maxSubAgentDepth?: number;
|
|
247
|
+
/**
|
|
248
|
+
* Per-call timeout for tools dispatched through `PluginContext`
|
|
249
|
+
* (toolkit-routed tools — analytics SQL warehouse queries, Genie
|
|
250
|
+
* messages, Lakebase queries). Independent of `maxToolCalls`: the
|
|
251
|
+
* budget caps how many tools fire per run, this caps how long any
|
|
252
|
+
* single tool call may run. The signal handed to plugin tool
|
|
253
|
+
* implementations combines this timeout with the parent stream's
|
|
254
|
+
* abort signal via `AbortSignal.any`. Function and MCP tools have
|
|
255
|
+
* their own timeouts in their respective adapters and ignore this
|
|
256
|
+
* setting. Default: `300_000` (5 minutes) — generous enough for cold
|
|
257
|
+
* SQL Warehouse round-trips and long Genie conversations.
|
|
258
|
+
*/
|
|
259
|
+
toolCallTimeoutMs?: number;
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/** Internal tool-index entry after a tool record has been resolved to a dispatchable form. */
|
|
263
|
+
type ResolvedToolEntry = {
|
|
264
|
+
source: "toolkit";
|
|
265
|
+
pluginName: string;
|
|
266
|
+
localName: string;
|
|
267
|
+
def: AgentToolDefinition;
|
|
268
|
+
} | {
|
|
269
|
+
source: "function";
|
|
270
|
+
functionTool: FunctionTool;
|
|
271
|
+
def: AgentToolDefinition;
|
|
272
|
+
} | {
|
|
273
|
+
source: "mcp";
|
|
274
|
+
mcpToolName: string;
|
|
275
|
+
def: AgentToolDefinition;
|
|
276
|
+
} | {
|
|
277
|
+
source: "subagent";
|
|
278
|
+
agentName: string;
|
|
279
|
+
def: AgentToolDefinition;
|
|
280
|
+
};
|
|
281
|
+
interface RegisteredAgent {
|
|
282
|
+
name: string;
|
|
283
|
+
instructions: string;
|
|
284
|
+
adapter: AgentAdapter;
|
|
285
|
+
toolIndex: Map<string, ResolvedToolEntry>;
|
|
286
|
+
baseSystemPrompt?: BaseSystemPromptOption;
|
|
287
|
+
maxSteps?: number;
|
|
288
|
+
maxTokens?: number;
|
|
289
|
+
/** Mirrors `AgentDefinition.ephemeral` — skip thread persistence. */
|
|
290
|
+
ephemeral?: boolean;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Type guard for `ToolkitEntry` — used by the agents plugin to differentiate
|
|
294
|
+
* toolkit references from inline tools in a mixed `tools` record.
|
|
295
|
+
*/
|
|
296
|
+
declare function isToolkitEntry(value: unknown): value is ToolkitEntry;
|
|
297
|
+
//#endregion
|
|
298
|
+
export { AgentDefinition, AgentTool, AgentTools, AgentToolsFn, AgentsPluginConfig, AutoInheritToolsConfig, BaseSystemPromptOption, PluginToolkitProvider, Plugins, PromptContext, RegisteredAgent, ResolvedToolEntry, ToolkitEntry, ToolkitOptions, isToolkitEntry };
|
|
299
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/core/agent/types.ts"],"mappings":";;;;;;;;;;;;;;AAiBA;UAAiB,YAAA;EAAA,SACN,YAAA;EACT,UAAA;EACA,SAAA;EACA,GAAA,EAAK,mBAAA;EACL,WAAA,GAAc,eAAA;EADd;;;;;;EAQA,eAAA;AAAA;;;;;;KAQU,SAAA,GAAY,YAAA,GAAe,UAAA,GAAa,YAAA;AAAA,UAEnC,cAAA;EAFO;EAItB,MAAA;EAJkD;EAMlD,IAAA;EAN8D;EAQ9D,MAAA;EAN6B;EAQ7B,MAAA,GAAS,MAAA;AAAA;;;;;;;;UAUM,qBAAA;EACf,OAAA,CAAQ,IAAA,GAAO,cAAA,GAAiB,MAAA,SAAe,YAAA;AAAA;;;;;;;;;;;;;AA2BjD;;;;;AAKA;;;;;;;KALY,OAAA,GAAU,MAAA,SAAe,qBAAA;;AAWrC;;UANiB,aAAA;EACf,SAAA;EACA,WAAA;EACA,SAAA;AAAA;AAAA,KAGU,sBAAA,sBAGN,GAAA,EAAK,aAAA;;;AAiBX;;KAXY,UAAA,GAAa,MAAA,SAAe,SAAA;;;;;;;AAaxC;;;KAFY,YAAA,IAAgB,OAAA,EAAS,OAAA,KAAY,UAAA;AAAA,UAEhC,eAAA;EA2BQ;;;;;;;;;;;;;;;;;;EARvB,IAAA;EAsBwB;EApBxB,YAAA;EAsBmB;;;;;EAhBnB,KAAA,GAAQ,YAAA,GAAe,OAAA,CAAQ,YAAA;EAyChB;;;;;AAOjB;;;;;;EApCE,KAAA,GAAQ,UAAA,GAAa,YAAA;EA4CS;EA1C9B,MAAA,GAAS,MAAA,SAAe,eAAA;EA4ChB;EA1CR,gBAAA,GAAmB,sBAAA;EACnB,QAAA;EACA,SAAA;EAqDM;;;;;;;;EA5CN,SAAA;AAAA;;;;;;;;;;;;UAce,sBAAA;EAuBI;EArBnB,IAAA;EA4BM;EA1BN,IAAA;AAAA;AAAA,UAGe,kBAAA,SAA2B,gBAAA;EAmD1C;EAjDA,GAAA;EA6DE;EA3DF,MAAA,GAAS,MAAA,SAAe,eAAA;EA8EtB;EA5EF,YAAA;EA4EmB;EA1EnB,YAAA,GAAe,YAAA,GAAe,OAAA,CAAQ,YAAA;EA+EX;EA7E3B,KAAA,GAAQ,MAAA,SAAe,SAAA;EAkFd;EAhFT,gBAAA,aAA6B,sBAAA;EAqFpB;EAnFT,WAAA,GAAc,WAAA;EA6FL;EA3FT,gBAAA,GAAmB,sBAAA;EA2FS;;;;;;EApF5B,GAAA,GAAM,mBAAA;EAyEF;;;;;;;;;EA/DJ,QAAA;IA0EI;;;;AAGN;IAvEI,qBAAA,YAuE4B;IArE5B,SAAA;EAAA;EAyES;;;;;;;;EA/DX,MAAA;IA+DW;;;;;IAzDT,2BAAA;IA8DF;;;AAOF;;IA/DI,YAAA;IA+DiE;;;;;IAzDjE,gBAAA;;;;;;;;;;;;;IAaA,iBAAA;EAAA;AAAA;;KAKQ,iBAAA;EAEN,MAAA;EACA,UAAA;EACA,SAAA;EACA,GAAA,EAAK,mBAAA;AAAA;EAGL,MAAA;EACA,YAAA,EAAc,YAAA;EACd,GAAA,EAAK,mBAAA;AAAA;EAGL,MAAA;EACA,WAAA;EACA,GAAA,EAAK,mBAAA;AAAA;EAGL,MAAA;EACA,SAAA;EACA,GAAA,EAAK,mBAAA;AAAA;AAAA,UAGM,eAAA;EACf,IAAA;EACA,YAAA;EACA,OAAA,EAAS,YAAA;EACT,SAAA,EAAW,GAAA,SAAY,iBAAA;EACvB,gBAAA,GAAmB,sBAAA;EACnB,QAAA;EACA,SAAA;;EAEA,SAAA;AAAA;;;;;iBAOc,cAAA,CAAe,KAAA,YAAiB,KAAA,IAAS,YAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/core/agent/types.ts
|
|
2
|
+
/**
|
|
3
|
+
* Type guard for `ToolkitEntry` — used by the agents plugin to differentiate
|
|
4
|
+
* toolkit references from inline tools in a mixed `tools` record.
|
|
5
|
+
*/
|
|
6
|
+
function isToolkitEntry(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && value.__toolkitRef === true;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { isToolkitEntry };
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../src/core/agent/types.ts"],"sourcesContent":["import type {\n AgentAdapter,\n AgentToolDefinition,\n BasePluginConfig,\n ThreadStore,\n ToolAnnotations,\n} from \"shared\";\nimport type { McpHostPolicyConfig } from \"../../connectors/mcp\";\nimport type { FunctionTool } from \"./tools/function-tool\";\nimport type { HostedTool } from \"./tools/hosted-tools\";\n\n/**\n * A tool reference produced by a plugin's `.toolkit()` call. The agents plugin\n * recognizes the `__toolkitRef` brand and dispatches tool invocations through\n * `PluginContext.executeTool(req, pluginName, localName, ...)`, preserving\n * OBO (asUser) and telemetry spans.\n */\nexport interface ToolkitEntry {\n readonly __toolkitRef: true;\n pluginName: string;\n localName: string;\n def: AgentToolDefinition;\n annotations?: ToolAnnotations;\n /**\n * Whether this tool is eligible for `autoInheritTools` spreading. Mirrors\n * {@link ToolEntry.autoInheritable} from the source registry so the agents\n * plugin can filter auto-inherited tools without re-walking the provider's\n * internal registry.\n */\n autoInheritable?: boolean;\n}\n\n/**\n * Any tool an agent can invoke: inline function tools (`tool()`), hosted MCP\n * tools (`mcpServer()` / raw hosted), or toolkit references from plugins\n * (`analytics().toolkit()`).\n */\nexport type AgentTool = FunctionTool | HostedTool | ToolkitEntry;\n\nexport interface ToolkitOptions {\n /** Key prefix to prepend to each tool's local name. Defaults to `${pluginName}.`. */\n prefix?: string;\n /** Only include tools whose local name matches one of these. */\n only?: string[];\n /** Exclude tools whose local name matches one of these. */\n except?: string[];\n /** Remap specific local names to different keys (applied after prefix). */\n rename?: Record<string, string>;\n}\n\n/**\n * Minimum shape every entry in the {@link Plugins} map must expose. Core\n * plugins (analytics, files, genie, lakebase) implement this directly via\n * their `.toolkit()` method. The agents plugin and standalone `runAgent`\n * synthesize this shape for any registered plugin that doesn't implement\n * `.toolkit()` directly (falling back to `getAgentTools()` walking).\n */\nexport interface PluginToolkitProvider {\n toolkit(opts?: ToolkitOptions): Record<string, ToolkitEntry>;\n}\n\n/**\n * Plugin map passed to the function form of {@link AgentDefinition.tools}.\n * Each entry exposes a `.toolkit(opts?)` method that returns a record of\n * {@link ToolkitEntry} markers ready to be spread into a tool record.\n *\n * AppKit does not statically know which plugins the surrounding\n * `createApp` will register, so this is a plain string-keyed record.\n * Refer to plugins by the name used in `createApp({ plugins: [...] })`;\n * unknown names resolve to `undefined` at runtime.\n *\n * @example\n * ```ts\n * const support = createAgent({\n * instructions: \"...\",\n * tools(plugins) {\n * return {\n * get_weather: tool({ ... }),\n * ...plugins.analytics.toolkit(),\n * ...plugins.files.toolkit({ only: [\"uploads.read\"] }),\n * };\n * },\n * });\n * ```\n */\nexport type Plugins = Record<string, PluginToolkitProvider>;\n\n/**\n * Context passed to `baseSystemPrompt` callbacks.\n */\nexport interface PromptContext {\n agentName: string;\n pluginNames: string[];\n toolNames: string[];\n}\n\nexport type BaseSystemPromptOption =\n | false\n | string\n | ((ctx: PromptContext) => string);\n\n/**\n * Per-agent tool record. String keys map to inline tools, toolkit entries,\n * hosted tools, etc.\n */\nexport type AgentTools = Record<string, AgentTool>;\n\n/**\n * Function form of `AgentDefinition.tools`. Receives the typed\n * {@link Plugins} map and returns a tool record. Invoked exactly once at\n * setup (or once per `runAgent` call in standalone mode); the result is\n * cached as the agent's resolved tool record.\n *\n * Use the function form when an agent needs tools from registered plugins.\n * The bare object form is fine when an agent only uses inline tools.\n */\nexport type AgentToolsFn = (plugins: Plugins) => AgentTools;\n\nexport interface AgentDefinition {\n /**\n * Stable identifier for the agent. **Optional and informational** —\n * when the definition is registered via `agents: { foo: def }` (code) or\n * lives at `config/agents/<id>/agent.md` (markdown), the **registry key\n * always wins** and `name` is ignored. The agent will be reachable as\n * `foo` (or `<id>`) regardless of what this field contains.\n *\n * Set `name` when:\n * - Running standalone via `runAgent({ agent: def })`, where there is\n * no enclosing key. The runtime uses it for the agent's slot in\n * error messages and OTel spans.\n * - Building a definition that may be passed to either form and you\n * want a consistent fallback label.\n *\n * Setting `name` to a value that differs from the registry key is\n * harmless but confusing — prefer keeping them aligned or omitting `name`\n * entirely.\n */\n name?: string;\n /** System prompt body. For markdown-loaded agents this is the file body. */\n instructions: string;\n /**\n * Model adapter (or endpoint-name string sugar for\n * `DatabricksAdapter.fromServingEndpoint({ endpointName })`). Optional —\n * falls back to the plugin's `defaultModel`.\n */\n model?: AgentAdapter | Promise<AgentAdapter> | string;\n /**\n * Per-agent tool record. Key is the LLM-visible tool-call name.\n *\n * Accepts either a plain record (for agents that only use inline tools)\n * or a function `(plugins) => Record<string, AgentTool>` that receives\n * the typed {@link Plugins} map and returns a tool record (for agents\n * that pull tools from registered plugins).\n *\n * The function is invoked once at agent setup; the result is cached.\n * Don't put per-request logic in there.\n */\n tools?: AgentTools | AgentToolsFn;\n /** Sub-agents, exposed as `agent-<key>` tools on this agent. */\n agents?: Record<string, AgentDefinition>;\n /** Override the plugin's baseSystemPrompt for this agent only. */\n baseSystemPrompt?: BaseSystemPromptOption;\n maxSteps?: number;\n maxTokens?: number;\n /**\n * When true, the thread used for a chat request against this agent is\n * deleted from `ThreadStore` after the stream completes (success or\n * failure). Use for stateless one-shot agents — e.g. autocomplete, where\n * each request is independent and retaining history would both poison\n * future calls and accumulate unbounded state in the default\n * `InMemoryThreadStore`. Defaults to `false`.\n */\n ephemeral?: boolean;\n}\n\n/**\n * Auto-inherit configuration. When enabled for a given agent origin, agents\n * with no explicit `tools:` declaration receive every registered ToolProvider\n * plugin tool whose author marked `autoInheritable: true`. Tools without that\n * flag — destructive, state-mutating, or privilege-sensitive — never spread\n * automatically and must be wired via `tools:` (object or function form in\n * code, `plugin:NAME` entries in markdown frontmatter).\n *\n * Defaults are `false` for both origins (safe-by-default): developers must\n * consciously opt an origin in to any auto-inherit behaviour.\n */\nexport interface AutoInheritToolsConfig {\n /** Default for agents loaded from markdown files. Default: `false`. */\n file?: boolean;\n /** Default for code-defined agents (via `agents: { foo: createAgent(...) }`). Default: `false`. */\n code?: boolean;\n}\n\nexport interface AgentsPluginConfig extends BasePluginConfig {\n /** Directory of agent packages (`<id>/agent.md` each). Default `./config/agents`. Set to `false` to disable. */\n dir?: string | false;\n /** Code-defined agents, merged with file-loaded ones (code wins on key collision). */\n agents?: Record<string, AgentDefinition>;\n /** Agent used when clients don't specify one. Defaults to the first-registered agent or the file with `default: true` frontmatter. */\n defaultAgent?: string;\n /** Default model for agents that don't specify their own (in code or frontmatter). */\n defaultModel?: AgentAdapter | Promise<AgentAdapter> | string;\n /** Ambient tool library. Keys may be referenced by markdown frontmatter via `tools: [key1, key2]`. */\n tools?: Record<string, AgentTool>;\n /** Whether to auto-inherit every ToolProvider plugin's toolkit. Accepts a boolean shorthand. */\n autoInheritTools?: boolean | AutoInheritToolsConfig;\n /** Persistent thread store. Default: in-memory. */\n threadStore?: ThreadStore;\n /** Customize or disable the AppKit base system prompt. */\n baseSystemPrompt?: BaseSystemPromptOption;\n /**\n * MCP server host policy. By default only same-origin Databricks workspace\n * URLs may be used as MCP endpoints; custom hosts must be explicitly\n * allowlisted here. Workspace credentials (SP / OBO) are never forwarded\n * to non-workspace hosts.\n */\n mcp?: McpHostPolicyConfig;\n /**\n * Human-in-the-loop approval gate for mutating tool calls. When enabled\n * (the default), the agents plugin emits an `appkit.approval_pending` SSE\n * event before executing any tool whose annotation flags it as mutating —\n * `effect: \"write\" | \"update\" | \"destructive\"` (preferred) or the legacy\n * `destructive: true` boolean — and waits for a `POST /chat/approve`\n * decision from the same user who initiated the stream. A missing decision\n * after `timeoutMs` auto-denies the call.\n */\n approval?: {\n /**\n * Require human approval for tools that mutate state. Triggered by\n * `effect: \"write\" | \"update\" | \"destructive\"` (preferred) or the legacy\n * `destructive: true` boolean. Default: `true`.\n */\n requireForDestructive?: boolean;\n /** Milliseconds to wait before auto-denying. Default: 60_000. */\n timeoutMs?: number;\n };\n /**\n * Runtime resource limits applied during agent execution. Defaults are\n * tuned to protect a single-instance deployment from a misbehaving user or\n * a runaway prompt injection; tighten or relax as appropriate for the\n * deployment's scale and trust model. Request-body caps (chat message\n * size, invocations input size / length) are enforced statically by the\n * Zod schemas and are not configurable here.\n */\n limits?: {\n /**\n * Max concurrent chat streams a single user may have open. Subsequent\n * `POST /chat` requests from that user while at-limit are rejected with\n * HTTP 429. Default: `5`.\n */\n maxConcurrentStreamsPerUser?: number;\n /**\n * Max tool invocations per agent run (across the full tool-call graph,\n * including sub-agent invocations). A run that exceeds the budget is\n * aborted with a terminal error event. Default: `50`.\n */\n maxToolCalls?: number;\n /**\n * Max sub-agent recursion depth. Protects against a prompt-injected\n * agent that delegates to a sub-agent which in turn delegates back to\n * itself (directly or transitively). Default: `3`.\n */\n maxSubAgentDepth?: number;\n /**\n * Per-call timeout for tools dispatched through `PluginContext`\n * (toolkit-routed tools — analytics SQL warehouse queries, Genie\n * messages, Lakebase queries). Independent of `maxToolCalls`: the\n * budget caps how many tools fire per run, this caps how long any\n * single tool call may run. The signal handed to plugin tool\n * implementations combines this timeout with the parent stream's\n * abort signal via `AbortSignal.any`. Function and MCP tools have\n * their own timeouts in their respective adapters and ignore this\n * setting. Default: `300_000` (5 minutes) — generous enough for cold\n * SQL Warehouse round-trips and long Genie conversations.\n */\n toolCallTimeoutMs?: number;\n };\n}\n\n/** Internal tool-index entry after a tool record has been resolved to a dispatchable form. */\nexport type ResolvedToolEntry =\n | {\n source: \"toolkit\";\n pluginName: string;\n localName: string;\n def: AgentToolDefinition;\n }\n | {\n source: \"function\";\n functionTool: FunctionTool;\n def: AgentToolDefinition;\n }\n | {\n source: \"mcp\";\n mcpToolName: string;\n def: AgentToolDefinition;\n }\n | {\n source: \"subagent\";\n agentName: string;\n def: AgentToolDefinition;\n };\n\nexport interface RegisteredAgent {\n name: string;\n instructions: string;\n adapter: AgentAdapter;\n toolIndex: Map<string, ResolvedToolEntry>;\n baseSystemPrompt?: BaseSystemPromptOption;\n maxSteps?: number;\n maxTokens?: number;\n /** Mirrors `AgentDefinition.ephemeral` — skip thread persistence. */\n ephemeral?: boolean;\n}\n\n/**\n * Type guard for `ToolkitEntry` — used by the agents plugin to differentiate\n * toolkit references from inline tools in a mixed `tools` record.\n */\nexport function isToolkitEntry(value: unknown): value is ToolkitEntry {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { __toolkitRef?: unknown }).__toolkitRef === true\n );\n}\n"],"mappings":";;;;;AA+TA,SAAgB,eAAe,OAAuC;AACpE,QACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB"}
|
package/dist/core/appkit.d.ts
CHANGED
|
@@ -48,6 +48,7 @@ declare function createApp<T extends PluginData<PluginConstructor, unknown, stri
|
|
|
48
48
|
cache?: CacheConfig;
|
|
49
49
|
client?: WorkspaceClient;
|
|
50
50
|
onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;
|
|
51
|
+
disableInternalTelemetry?: boolean;
|
|
51
52
|
}): Promise<PluginMap<T>>;
|
|
52
53
|
//#endregion
|
|
53
54
|
export { createApp };
|
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2TsB,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/core/appkit.js
CHANGED
|
@@ -2,11 +2,16 @@ import { createLogger } from "../logging/logger.js";
|
|
|
2
2
|
import { TelemetryManager } from "../telemetry/telemetry-manager.js";
|
|
3
3
|
import "../telemetry/index.js";
|
|
4
4
|
import { CacheManager } from "../cache/index.js";
|
|
5
|
+
import { version } from "../appkit/package.js";
|
|
5
6
|
import { ServiceContext } from "../context/service-context.js";
|
|
6
7
|
import { init_context } from "../context/index.js";
|
|
8
|
+
import { isInternalTelemetryEnabled } from "../internal-telemetry/config.js";
|
|
9
|
+
import { TelemetryReporter } from "../internal-telemetry/reporter.js";
|
|
10
|
+
import "../internal-telemetry/index.js";
|
|
7
11
|
import { ResourceType } from "../registry/types.generated.js";
|
|
8
12
|
import { ResourceRegistry } from "../registry/resource-registry.js";
|
|
9
13
|
import "../registry/index.js";
|
|
14
|
+
import { PluginContext, isToolProvider } from "./plugin-context.js";
|
|
10
15
|
|
|
11
16
|
//#region src/core/appkit.ts
|
|
12
17
|
init_context();
|
|
@@ -14,28 +19,37 @@ const logger = createLogger("appkit");
|
|
|
14
19
|
var AppKit = class AppKit {
|
|
15
20
|
#pluginInstances = {};
|
|
16
21
|
#setupPromises = [];
|
|
22
|
+
#context;
|
|
17
23
|
constructor(config) {
|
|
18
24
|
const { plugins, ...globalConfig } = config;
|
|
25
|
+
this.#context = new PluginContext();
|
|
19
26
|
const pluginEntries = Object.entries(plugins);
|
|
20
27
|
const corePlugins = pluginEntries.filter(([_, p]) => {
|
|
21
28
|
return (p?.plugin?.phase ?? "normal") === "core";
|
|
22
29
|
});
|
|
23
30
|
const normalPlugins = pluginEntries.filter(([_, p]) => (p?.plugin?.phase ?? "normal") === "normal");
|
|
24
31
|
const deferredPlugins = pluginEntries.filter(([_, p]) => (p?.plugin?.phase ?? "normal") === "deferred");
|
|
25
|
-
for (const [name, pluginData] of corePlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData);
|
|
26
|
-
for (const [name, pluginData] of normalPlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData);
|
|
27
|
-
for (const [name, pluginData] of deferredPlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData, {
|
|
32
|
+
for (const [name, pluginData] of corePlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData, { context: this.#context });
|
|
33
|
+
for (const [name, pluginData] of normalPlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData, { context: this.#context });
|
|
34
|
+
for (const [name, pluginData] of deferredPlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData, { context: this.#context });
|
|
28
35
|
}
|
|
29
36
|
createAndRegisterPlugin(config, name, pluginData, extraData) {
|
|
30
37
|
const { plugin: Plugin, config: pluginConfig } = pluginData;
|
|
31
|
-
const
|
|
38
|
+
const baseConfig = {
|
|
32
39
|
...config,
|
|
33
40
|
...Plugin.DEFAULT_CONFIG,
|
|
34
41
|
...pluginConfig,
|
|
35
42
|
name,
|
|
36
43
|
...extraData
|
|
44
|
+
};
|
|
45
|
+
const pluginInstance = new Plugin(baseConfig);
|
|
46
|
+
if (typeof pluginInstance.attachContext === "function") pluginInstance.attachContext({
|
|
47
|
+
context: this.#context,
|
|
48
|
+
telemetryConfig: baseConfig.telemetry
|
|
37
49
|
});
|
|
38
50
|
this.#pluginInstances[name] = pluginInstance;
|
|
51
|
+
this.#context.registerPlugin(name, pluginInstance);
|
|
52
|
+
if (isToolProvider(pluginInstance)) this.#context.registerToolProvider(name, pluginInstance);
|
|
39
53
|
this.#setupPromises.push(pluginInstance.setup());
|
|
40
54
|
const self = this;
|
|
41
55
|
Object.defineProperty(this, name, {
|
|
@@ -101,16 +115,29 @@ var AppKit = class AppKit {
|
|
|
101
115
|
registry.enforceValidation();
|
|
102
116
|
const instance = new AppKit({ plugins: AppKit.preparePlugins(rawPlugins) });
|
|
103
117
|
await Promise.all(instance.#setupPromises);
|
|
118
|
+
await instance.#context.emitLifecycle("setup:complete");
|
|
104
119
|
const handle = instance;
|
|
105
120
|
if (config.onPluginsReady) {
|
|
106
121
|
logger.debug("Running onPluginsReady hook");
|
|
107
122
|
await config.onPluginsReady(handle);
|
|
108
123
|
logger.debug("onPluginsReady hook completed");
|
|
109
124
|
}
|
|
125
|
+
if (isInternalTelemetryEnabled(config)) AppKit.bootstrapInternalTelemetry();
|
|
110
126
|
const serverPlugin = instance.#pluginInstances.server;
|
|
111
127
|
if (serverPlugin && typeof serverPlugin.start === "function") await serverPlugin.start();
|
|
112
128
|
return handle;
|
|
113
129
|
}
|
|
130
|
+
static bootstrapInternalTelemetry() {
|
|
131
|
+
const serviceCtx = ServiceContext.get();
|
|
132
|
+
const reporter = TelemetryReporter.initialize({
|
|
133
|
+
workspaceId: serviceCtx.workspaceId,
|
|
134
|
+
client: serviceCtx.client,
|
|
135
|
+
appId: process.env.DATABRICKS_CLIENT_ID || "",
|
|
136
|
+
appkitVersion: version
|
|
137
|
+
});
|
|
138
|
+
reporter.start();
|
|
139
|
+
reporter.sendStartup().catch(() => {});
|
|
140
|
+
}
|
|
114
141
|
static preparePlugins(plugins) {
|
|
115
142
|
const result = {};
|
|
116
143
|
for (const currentPlugin of plugins) result[currentPlugin.name] = {
|
package/dist/core/appkit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appkit.js","names":["#pluginInstances","#setupPromises"],"sources":["../../src/core/appkit.ts"],"sourcesContent":["import type { WorkspaceClient } from \"@databricks/sdk-experimental\";\nimport type {\n BasePlugin,\n CacheConfig,\n InputPluginMap,\n OptionalConfigPluginDef,\n PluginConstructor,\n PluginData,\n PluginMap,\n} from \"shared\";\nimport { CacheManager } from \"../cache\";\nimport { ServiceContext } from \"../context\";\nimport { createLogger } from \"../logging/logger\";\nimport { ResourceRegistry, ResourceType } from \"../registry\";\nimport type { TelemetryConfig } from \"../telemetry\";\nimport { TelemetryManager } from \"../telemetry\";\n\nconst logger = createLogger(\"appkit\");\n\nexport class AppKit<TPlugins extends InputPluginMap> {\n #pluginInstances: Record<string, BasePlugin> = {};\n #setupPromises: Promise<void>[] = [];\n\n private constructor(config: { plugins: TPlugins }) {\n const { plugins, ...globalConfig } = config;\n\n const pluginEntries = Object.entries(plugins);\n\n const corePlugins = pluginEntries.filter(([_, p]) => {\n return (p?.plugin?.phase ?? \"normal\") === \"core\";\n });\n const normalPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"normal\",\n );\n const deferredPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"deferred\",\n );\n\n for (const [name, pluginData] of corePlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of normalPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of deferredPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData, {\n plugins: this.#pluginInstances,\n });\n }\n }\n }\n\n private createAndRegisterPlugin<T extends PluginConstructor>(\n config: Omit<{ plugins: TPlugins }, \"plugins\">,\n name: string,\n pluginData: OptionalConfigPluginDef<T>,\n extraData?: Record<string, unknown>,\n ) {\n const { plugin: Plugin, config: pluginConfig } = pluginData;\n const baseConfig = {\n ...config,\n ...Plugin.DEFAULT_CONFIG,\n ...pluginConfig,\n name,\n ...extraData,\n };\n const pluginInstance = new Plugin(baseConfig);\n\n this.#pluginInstances[name] = pluginInstance;\n\n this.#setupPromises.push(pluginInstance.setup());\n\n const self = this;\n\n Object.defineProperty(this, name, {\n get() {\n const plugin = self.#pluginInstances[name];\n return self.wrapWithAsUser(plugin);\n },\n enumerable: true,\n });\n }\n\n /**\n * Binds all function properties in an exports object to the given context.\n * Recurses into plain objects to handle nested APIs (e.g., volume APIs).\n */\n private bindExportMethods(\n exports: Record<string, unknown>,\n context: BasePlugin,\n ) {\n for (const key in exports) {\n if (!Object.hasOwn(exports, key)) continue;\n const val = exports[key];\n if (typeof val === \"function\") {\n exports[key] = (val as (...args: unknown[]) => unknown).bind(context);\n } else if (AppKit.isPlainObject(val)) {\n this.bindExportMethods(val as Record<string, unknown>, context);\n }\n }\n }\n\n /**\n * Wraps a plugin's exports with an `asUser` method that returns\n * a user-scoped version of the exports.\n *\n * When `exports()` returns a callable (function), it is returned as-is\n * since the plugin manages its own `asUser` per-call (e.g. files plugin).\n * When it returns a plain object, the standard `asUser` wrapper is added.\n */\n private wrapWithAsUser<T extends BasePlugin>(plugin: T) {\n // If plugin doesn't implement exports(), return empty object\n const pluginExports = plugin.exports?.() ?? {};\n\n // If exports is a function, the plugin manages its own asUser pattern\n if (typeof pluginExports === \"function\") {\n return pluginExports;\n }\n\n const objExports = pluginExports as Record<string, unknown>;\n this.bindExportMethods(objExports, plugin);\n\n // If plugin doesn't support asUser (no asUser method), return exports as-is\n if (typeof (plugin as any).asUser !== \"function\") {\n return objExports;\n }\n\n return {\n ...objExports,\n /**\n * Execute operations using the user's identity from the request.\n * Returns user-scoped exports where all methods execute with the\n * user's Databricks credentials instead of the service principal.\n */\n asUser: (req: import(\"express\").Request) => {\n const userPlugin = (plugin as any).asUser(req);\n const userExports = (userPlugin.exports?.() ?? {}) as Record<\n string,\n unknown\n >;\n this.bindExportMethods(userExports, userPlugin);\n return userExports;\n },\n };\n }\n\n /**\n * Returns true if the value is a plain object (not an array, Date, etc.).\n */\n private static isPlainObject(\n value: unknown,\n ): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n }\n\n static async _createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n >(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n client?: WorkspaceClient;\n onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;\n } = {},\n ): Promise<PluginMap<T>> {\n // Initialize core services\n TelemetryManager.initialize(config?.telemetry);\n await CacheManager.getInstance(config?.cache);\n\n const rawPlugins = config.plugins as T;\n\n // Collect manifest resources via registry\n const registry = new ResourceRegistry();\n registry.collectResources(rawPlugins);\n\n // Derive ServiceContext needs from what manifests declared\n const needsWarehouse = registry\n .getRequired()\n .some((r) => r.type === ResourceType.SQL_WAREHOUSE);\n await ServiceContext.initialize(\n { warehouseId: needsWarehouse },\n config?.client,\n );\n\n // Validate env vars\n registry.enforceValidation();\n\n const preparedPlugins = AppKit.preparePlugins(rawPlugins);\n const mergedConfig = {\n plugins: preparedPlugins,\n };\n\n const instance = new AppKit(mergedConfig);\n\n await Promise.all(instance.#setupPromises);\n\n const handle = instance as unknown as PluginMap<T>;\n\n if (config.onPluginsReady) {\n logger.debug(\"Running onPluginsReady hook\");\n await config.onPluginsReady(handle);\n logger.debug(\"onPluginsReady hook completed\");\n }\n\n const serverPlugin = instance.#pluginInstances.server;\n if (serverPlugin && typeof (serverPlugin as any).start === \"function\") {\n await (serverPlugin as any).start();\n }\n\n return handle;\n }\n\n private static preparePlugins(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n ) {\n const result: InputPluginMap = {};\n for (const currentPlugin of plugins) {\n result[currentPlugin.name] = {\n plugin: currentPlugin.plugin,\n config: currentPlugin.config as Record<string, unknown>,\n };\n }\n return result;\n }\n}\n\n/**\n * Bootstraps AppKit with the provided configuration.\n *\n * Initializes telemetry, cache, and service context, then registers plugins\n * in phase order (core, normal, deferred) and awaits their setup.\n * If a `onPluginsReady` callback is provided it runs after plugin setup but\n * before the server starts, giving you access to the full appkit handle\n * for registering custom routes or performing async setup.\n * The returned object maps each plugin name to its `exports()` API,\n * with an `asUser(req)` method for user-scoped execution.\n *\n * @returns A `PluginMap` keyed by plugin name with typed exports\n *\n * @example Minimal server\n * ```ts\n * import { createApp, server } from \"@databricks/appkit\";\n *\n * await createApp({\n * plugins: [server()],\n * });\n * ```\n *\n * @example Server with custom routes via onPluginsReady\n * ```ts\n * import { createApp, server, analytics } from \"@databricks/appkit\";\n *\n * await createApp({\n * plugins: [server(), analytics({})],\n * onPluginsReady(appkit) {\n * appkit.server.extend((app) => {\n * app.get(\"/custom\", (_req, res) => res.json({ ok: true }));\n * });\n * },\n * });\n * ```\n */\nexport async function createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n>(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n client?: WorkspaceClient;\n onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;\n } = {},\n): Promise<PluginMap<T>> {\n return AppKit._createApp(config);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"appkit.js","names":["#context","#pluginInstances","#setupPromises","productVersion"],"sources":["../../src/core/appkit.ts"],"sourcesContent":["import type { WorkspaceClient } from \"@databricks/sdk-experimental\";\nimport type {\n BasePlugin,\n CacheConfig,\n InputPluginMap,\n OptionalConfigPluginDef,\n PluginConstructor,\n PluginData,\n PluginMap,\n} from \"shared\";\nimport { version as productVersion } from \"../../package.json\";\nimport { CacheManager } from \"../cache\";\nimport { ServiceContext } from \"../context\";\nimport {\n isInternalTelemetryEnabled,\n TelemetryReporter,\n} from \"../internal-telemetry\";\nimport { createLogger } from \"../logging/logger\";\nimport { ResourceRegistry, ResourceType } from \"../registry\";\nimport type { TelemetryConfig } from \"../telemetry\";\nimport { TelemetryManager } from \"../telemetry\";\nimport { isToolProvider, PluginContext } from \"./plugin-context\";\n\nconst logger = createLogger(\"appkit\");\n\nexport class AppKit<TPlugins extends InputPluginMap> {\n #pluginInstances: Record<string, BasePlugin> = {};\n #setupPromises: Promise<void>[] = [];\n #context: PluginContext;\n\n private constructor(config: { plugins: TPlugins }) {\n const { plugins, ...globalConfig } = config;\n\n this.#context = new PluginContext();\n\n const pluginEntries = Object.entries(plugins);\n\n const corePlugins = pluginEntries.filter(([_, p]) => {\n return (p?.plugin?.phase ?? \"normal\") === \"core\";\n });\n const normalPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"normal\",\n );\n const deferredPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"deferred\",\n );\n\n for (const [name, pluginData] of corePlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData, {\n context: this.#context,\n });\n }\n }\n\n for (const [name, pluginData] of normalPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData, {\n context: this.#context,\n });\n }\n }\n\n for (const [name, pluginData] of deferredPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData, {\n context: this.#context,\n });\n }\n }\n }\n\n private createAndRegisterPlugin<T extends PluginConstructor>(\n config: Omit<{ plugins: TPlugins }, \"plugins\">,\n name: string,\n pluginData: OptionalConfigPluginDef<T>,\n extraData?: Record<string, unknown>,\n ) {\n const { plugin: Plugin, config: pluginConfig } = pluginData;\n const baseConfig = {\n ...config,\n ...Plugin.DEFAULT_CONFIG,\n ...pluginConfig,\n name,\n ...extraData,\n };\n const pluginInstance = new Plugin(baseConfig);\n\n if (typeof pluginInstance.attachContext === \"function\") {\n pluginInstance.attachContext({\n context: this.#context,\n telemetryConfig: baseConfig.telemetry,\n });\n }\n\n this.#pluginInstances[name] = pluginInstance;\n\n this.#context.registerPlugin(name, pluginInstance);\n if (isToolProvider(pluginInstance)) {\n this.#context.registerToolProvider(name, pluginInstance);\n }\n\n this.#setupPromises.push(pluginInstance.setup());\n\n const self = this;\n\n Object.defineProperty(this, name, {\n get() {\n const plugin = self.#pluginInstances[name];\n return self.wrapWithAsUser(plugin);\n },\n enumerable: true,\n });\n }\n\n /**\n * Binds all function properties in an exports object to the given context.\n * Recurses into plain objects to handle nested APIs (e.g., volume APIs).\n */\n private bindExportMethods(\n exports: Record<string, unknown>,\n context: BasePlugin,\n ) {\n for (const key in exports) {\n if (!Object.hasOwn(exports, key)) continue;\n const val = exports[key];\n if (typeof val === \"function\") {\n exports[key] = (val as (...args: unknown[]) => unknown).bind(context);\n } else if (AppKit.isPlainObject(val)) {\n this.bindExportMethods(val as Record<string, unknown>, context);\n }\n }\n }\n\n /**\n * Wraps a plugin's exports with an `asUser` method that returns\n * a user-scoped version of the exports.\n *\n * When `exports()` returns a callable (function), it is returned as-is\n * since the plugin manages its own `asUser` per-call (e.g. files plugin).\n * When it returns a plain object, the standard `asUser` wrapper is added.\n */\n private wrapWithAsUser<T extends BasePlugin>(plugin: T) {\n // If plugin doesn't implement exports(), return empty object\n const pluginExports = plugin.exports?.() ?? {};\n\n // If exports is a function, the plugin manages its own asUser pattern\n if (typeof pluginExports === \"function\") {\n return pluginExports;\n }\n\n const objExports = pluginExports as Record<string, unknown>;\n this.bindExportMethods(objExports, plugin);\n\n // If plugin doesn't support asUser (no asUser method), return exports as-is\n if (typeof (plugin as any).asUser !== \"function\") {\n return objExports;\n }\n\n return {\n ...objExports,\n /**\n * Execute operations using the user's identity from the request.\n * Returns user-scoped exports where all methods execute with the\n * user's Databricks credentials instead of the service principal.\n */\n asUser: (req: import(\"express\").Request) => {\n const userPlugin = (plugin as any).asUser(req);\n const userExports = (userPlugin.exports?.() ?? {}) as Record<\n string,\n unknown\n >;\n this.bindExportMethods(userExports, userPlugin);\n return userExports;\n },\n };\n }\n\n /**\n * Returns true if the value is a plain object (not an array, Date, etc.).\n */\n private static isPlainObject(\n value: unknown,\n ): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n }\n\n static async _createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n >(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n client?: WorkspaceClient;\n onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;\n disableInternalTelemetry?: boolean;\n } = {},\n ): Promise<PluginMap<T>> {\n // Initialize core services\n TelemetryManager.initialize(config?.telemetry);\n await CacheManager.getInstance(config?.cache);\n\n const rawPlugins = config.plugins as T;\n\n // Collect manifest resources via registry\n const registry = new ResourceRegistry();\n registry.collectResources(rawPlugins);\n\n // Derive ServiceContext needs from what manifests declared\n const needsWarehouse = registry\n .getRequired()\n .some((r) => r.type === ResourceType.SQL_WAREHOUSE);\n await ServiceContext.initialize(\n { warehouseId: needsWarehouse },\n config?.client,\n );\n\n // Validate env vars\n registry.enforceValidation();\n\n const preparedPlugins = AppKit.preparePlugins(rawPlugins);\n const mergedConfig = {\n plugins: preparedPlugins,\n };\n\n const instance = new AppKit(mergedConfig);\n\n await Promise.all(instance.#setupPromises);\n await instance.#context.emitLifecycle(\"setup:complete\");\n\n const handle = instance as unknown as PluginMap<T>;\n\n if (config.onPluginsReady) {\n logger.debug(\"Running onPluginsReady hook\");\n await config.onPluginsReady(handle);\n logger.debug(\"onPluginsReady hook completed\");\n }\n\n if (isInternalTelemetryEnabled(config)) {\n AppKit.bootstrapInternalTelemetry();\n }\n\n const serverPlugin = instance.#pluginInstances.server;\n if (serverPlugin && typeof (serverPlugin as any).start === \"function\") {\n await (serverPlugin as any).start();\n }\n\n return handle;\n }\n\n private static bootstrapInternalTelemetry(): void {\n const serviceCtx = ServiceContext.get();\n const reporter = TelemetryReporter.initialize({\n workspaceId: serviceCtx.workspaceId,\n client: serviceCtx.client,\n appId: process.env.DATABRICKS_CLIENT_ID || \"\",\n appkitVersion: productVersion,\n });\n reporter.start();\n reporter.sendStartup().catch(() => {});\n }\n\n private static preparePlugins(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n ) {\n const result: InputPluginMap = {};\n for (const currentPlugin of plugins) {\n result[currentPlugin.name] = {\n plugin: currentPlugin.plugin,\n config: currentPlugin.config as Record<string, unknown>,\n };\n }\n return result;\n }\n}\n\n/**\n * Bootstraps AppKit with the provided configuration.\n *\n * Initializes telemetry, cache, and service context, then registers plugins\n * in phase order (core, normal, deferred) and awaits their setup.\n * If a `onPluginsReady` callback is provided it runs after plugin setup but\n * before the server starts, giving you access to the full appkit handle\n * for registering custom routes or performing async setup.\n * The returned object maps each plugin name to its `exports()` API,\n * with an `asUser(req)` method for user-scoped execution.\n *\n * @returns A `PluginMap` keyed by plugin name with typed exports\n *\n * @example Minimal server\n * ```ts\n * import { createApp, server } from \"@databricks/appkit\";\n *\n * await createApp({\n * plugins: [server()],\n * });\n * ```\n *\n * @example Server with custom routes via onPluginsReady\n * ```ts\n * import { createApp, server, analytics } from \"@databricks/appkit\";\n *\n * await createApp({\n * plugins: [server(), analytics({})],\n * onPluginsReady(appkit) {\n * appkit.server.extend((app) => {\n * app.get(\"/custom\", (_req, res) => res.json({ ok: true }));\n * });\n * },\n * });\n * ```\n */\nexport async function createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n>(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n client?: WorkspaceClient;\n onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;\n disableInternalTelemetry?: boolean;\n } = {},\n): Promise<PluginMap<T>> {\n return AppKit._createApp(config);\n}\n"],"mappings":"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"}
|