@databricks/appkit 0.83.0 → 0.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +15 -1
- package/dist/agents/databricks.d.ts +15 -3
- package/dist/agents/databricks.d.ts.map +1 -1
- package/dist/agents/databricks.js +25 -8
- package/dist/agents/databricks.js.map +1 -1
- package/dist/appkit/package.js +1 -1
- package/dist/beta.d.ts +2 -2
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +6 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/cli/commands/agent/eval.js +1 -1
- package/dist/cli/commands/generate-types.js +1 -1
- package/dist/cli/commands/plugin/sync/sync.js +28 -15
- package/dist/cli/commands/plugin/sync/sync.js.map +1 -1
- package/dist/cli/commands/registry/add.js +3 -11
- package/dist/cli/commands/registry/add.js.map +1 -1
- package/dist/cli/commands/registry/config-writer.js +1 -1
- package/dist/connectors/lakebase/routing-pool.d.ts.map +1 -1
- package/dist/connectors/lakebase/routing-pool.js +4 -10
- package/dist/connectors/lakebase/routing-pool.js.map +1 -1
- package/dist/context/caller-context.d.ts +4 -1
- package/dist/context/caller-context.d.ts.map +1 -1
- package/dist/context/caller-context.js.map +1 -1
- package/dist/context/execution-context.d.ts +29 -1
- package/dist/context/execution-context.d.ts.map +1 -1
- package/dist/context/execution-context.js +60 -8
- package/dist/context/execution-context.js.map +1 -1
- package/dist/context/index.d.ts +2 -2
- package/dist/context/index.js +2 -1
- package/dist/context/request-scope.d.ts +2 -0
- package/dist/context/request-scope.js +39 -0
- package/dist/context/request-scope.js.map +1 -0
- package/dist/context/resource-capabilities.js +59 -0
- package/dist/context/resource-capabilities.js.map +1 -0
- package/dist/context/scoped-api.js +104 -0
- package/dist/context/scoped-api.js.map +1 -0
- package/dist/context/service-context.d.ts.map +1 -1
- package/dist/context/service-context.js +1 -1
- package/dist/context/service-context.js.map +1 -1
- package/dist/context/user-context.d.ts +16 -19
- package/dist/context/user-context.d.ts.map +1 -1
- package/dist/context/user-context.js +30 -3
- package/dist/context/user-context.js.map +1 -1
- package/dist/core/agent/load-agents.d.ts.map +1 -1
- package/dist/core/agent/load-agents.js +5 -2
- package/dist/core/agent/load-agents.js.map +1 -1
- package/dist/core/agent/run-agent.d.ts +19 -6
- package/dist/core/agent/run-agent.d.ts.map +1 -1
- package/dist/core/agent/run-agent.js +53 -17
- package/dist/core/agent/run-agent.js.map +1 -1
- package/dist/core/agent/types.d.ts +18 -1
- package/dist/core/agent/types.d.ts.map +1 -1
- package/dist/core/agent/types.js.map +1 -1
- package/dist/core/appkit.d.ts +4 -3
- package/dist/core/appkit.d.ts.map +1 -1
- package/dist/core/appkit.js +30 -9
- package/dist/core/appkit.js.map +1 -1
- package/dist/core/plugin-context.d.ts +14 -15
- package/dist/core/plugin-context.d.ts.map +1 -1
- package/dist/core/plugin-context.js +24 -14
- package/dist/core/plugin-context.js.map +1 -1
- package/dist/errors/base.d.ts +2 -2
- package/dist/errors/base.js +2 -2
- package/dist/errors/base.js.map +1 -1
- package/dist/errors/identity-expired.d.ts +14 -0
- package/dist/errors/identity-expired.d.ts.map +1 -0
- package/dist/errors/identity-expired.js +33 -0
- package/dist/errors/identity-expired.js.map +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +5 -2
- package/dist/logging/logger.js +1 -1
- package/dist/plugin/execution-result.d.ts +4 -1
- package/dist/plugin/execution-result.d.ts.map +1 -1
- package/dist/plugin/interceptors/telemetry.js +6 -4
- package/dist/plugin/interceptors/telemetry.js.map +1 -1
- package/dist/plugin/plugin.d.ts +13 -21
- package/dist/plugin/plugin.d.ts.map +1 -1
- package/dist/plugin/plugin.js +41 -122
- package/dist/plugin/plugin.js.map +1 -1
- package/dist/plugins/agents/agents.d.ts +12 -0
- package/dist/plugins/agents/agents.d.ts.map +1 -1
- package/dist/plugins/agents/agents.js +65 -15
- package/dist/plugins/agents/agents.js.map +1 -1
- package/dist/plugins/agents/auth-mode.js +42 -0
- package/dist/plugins/agents/auth-mode.js.map +1 -0
- package/dist/plugins/agents/index.d.ts +1 -1
- package/dist/plugins/agents/mlflow.js +11 -3
- package/dist/plugins/agents/mlflow.js.map +1 -1
- package/dist/plugins/agents/tool-dispatch.js +9 -1
- package/dist/plugins/agents/tool-dispatch.js.map +1 -1
- package/dist/plugins/ai-search/ai-search.d.ts.map +1 -1
- package/dist/plugins/ai-search/ai-search.js +4 -4
- package/dist/plugins/ai-search/ai-search.js.map +1 -1
- package/dist/plugins/analytics/analytics.d.ts +2 -2
- package/dist/plugins/analytics/analytics.js +6 -6
- package/dist/plugins/analytics/analytics.js.map +1 -1
- package/dist/plugins/database/crud/contract.js +2 -2
- package/dist/plugins/database/crud/contract.js.map +1 -1
- package/dist/plugins/files/plugin.d.ts +10 -4
- package/dist/plugins/files/plugin.d.ts.map +1 -1
- package/dist/plugins/files/plugin.js +34 -13
- package/dist/plugins/files/plugin.js.map +1 -1
- package/dist/plugins/genie/genie.d.ts +9 -0
- package/dist/plugins/genie/genie.d.ts.map +1 -1
- package/dist/plugins/genie/genie.js +12 -3
- package/dist/plugins/genie/genie.js.map +1 -1
- package/dist/plugins/genie/manifest.js +1 -0
- package/dist/plugins/jobs/plugin.js +2 -2
- package/dist/plugins/jobs/plugin.js.map +1 -1
- package/dist/plugins/lakebase/lakebase.d.ts +10 -17
- package/dist/plugins/lakebase/lakebase.d.ts.map +1 -1
- package/dist/plugins/lakebase/lakebase.js +12 -17
- package/dist/plugins/lakebase/lakebase.js.map +1 -1
- package/dist/plugins/server/client-config-sanitizer.js +1 -4
- package/dist/plugins/server/client-config-sanitizer.js.map +1 -1
- package/dist/plugins/server/dev-obo-middleware.js +60 -0
- package/dist/plugins/server/dev-obo-middleware.js.map +1 -0
- package/dist/plugins/server/index.d.ts.map +1 -1
- package/dist/plugins/server/index.js +5 -2
- package/dist/plugins/server/index.js.map +1 -1
- package/dist/plugins/server/remote-tunnel/remote-tunnel-manager.js +3 -3
- package/dist/plugins/server/remote-tunnel/remote-tunnel-manager.js.map +1 -1
- package/dist/plugins/server/static-server.js +3 -3
- package/dist/plugins/server/static-server.js.map +1 -1
- package/dist/plugins/server/utils.js +3 -3
- package/dist/plugins/server/utils.js.map +1 -1
- package/dist/plugins/server/vite-dev-server.js +4 -4
- package/dist/plugins/server/vite-dev-server.js.map +1 -1
- package/dist/plugins/serving/manifest.js +1 -0
- package/dist/plugins/serving/serving.js +6 -6
- package/dist/plugins/serving/serving.js.map +1 -1
- package/dist/schemas/manifest.d.ts +35 -1
- package/dist/schemas/manifest.d.ts.map +1 -1
- package/dist/schemas/manifest.js +112 -4
- package/dist/schemas/manifest.js.map +1 -1
- package/dist/shared/src/dev-obo.js +86 -0
- package/dist/shared/src/dev-obo.js.map +1 -0
- package/dist/shared/src/index.d.ts +1 -1
- package/dist/shared/src/plugin.d.ts +12 -1
- package/dist/shared/src/plugin.d.ts.map +1 -1
- package/dist/shared/src/schemas/manifest.d.ts +41 -33
- package/dist/shared/src/schemas/manifest.d.ts.map +1 -1
- package/dist/shared/src/schemas/manifest.js +43 -4
- package/dist/shared/src/schemas/manifest.js.map +1 -1
- package/dist/stream/stream-manager.d.ts.map +1 -1
- package/dist/stream/stream-manager.js +5 -2
- package/dist/stream/stream-manager.js.map +1 -1
- package/dist/telemetry/execution-span-processor.js +21 -0
- package/dist/telemetry/execution-span-processor.js.map +1 -0
- package/dist/telemetry/telemetry-manager.js +2 -1
- package/dist/telemetry/telemetry-manager.js.map +1 -1
- package/dist/testing/create-test-app.d.ts +2 -2
- package/dist/testing/create-test-app.js.map +1 -1
- package/dist/testing/test-plugin-context.d.ts +3 -12
- package/dist/testing/test-plugin-context.d.ts.map +1 -1
- package/dist/testing/test-plugin-context.js +24 -16
- package/dist/testing/test-plugin-context.js.map +1 -1
- package/dist/type-generator/database/generate.js +3 -3
- package/dist/type-generator/database/generate.js.map +1 -1
- package/dist/type-generator/migration.js +2 -2
- package/dist/type-generator/migration.js.map +1 -1
- package/dist/type-generator/serving/server-file-extractor.js +3 -3
- package/dist/type-generator/serving/server-file-extractor.js.map +1 -1
- package/dist/utils/is-plain-object.js +11 -0
- package/dist/utils/is-plain-object.js.map +1 -0
- package/docs/api/appkit/Class.AppKitError.md +2 -1
- package/docs/api/appkit/Class.AuthenticationError.md +1 -1
- package/docs/api/appkit/Class.ConfigurationError.md +1 -1
- package/docs/api/appkit/Class.ConnectionError.md +1 -1
- package/docs/api/appkit/Class.DatabaseValidationError.md +1 -1
- package/docs/api/appkit/Class.ExecutionError.md +1 -1
- package/docs/api/appkit/Class.IdentityExpiredError.md +190 -0
- package/docs/api/appkit/Class.InitializationError.md +1 -1
- package/docs/api/appkit/Class.Plugin.md +8 -12
- package/docs/api/appkit/Class.ServerError.md +1 -1
- package/docs/api/appkit/Class.ServiceContext.md +169 -0
- package/docs/api/appkit/Class.TunnelError.md +1 -1
- package/docs/api/appkit/Class.ValidationError.md +1 -1
- package/docs/api/appkit/Function.createApp.md +12 -12
- package/docs/api/appkit/Function.getCallerContext.md +12 -0
- package/docs/api/appkit/Function.getCurrentUserId.md +14 -0
- package/docs/api/appkit/Function.getExecutionContext.md +1 -1
- package/docs/api/appkit/Function.getUserContext.md +16 -0
- package/docs/api/appkit/Function.isInUserContext.md +12 -0
- package/docs/api/appkit/Function.isUserContext.md +20 -0
- package/docs/api/appkit/Function.runAgent.md +1 -1
- package/docs/api/appkit/Function.runInCallerContext.md +27 -0
- package/docs/api/appkit/Function.runInUserContext.md +29 -0
- package/docs/api/appkit/Interface.AgentDefinition.md +11 -0
- package/docs/api/appkit/Interface.AgentsPluginConfig.md +11 -0
- package/docs/api/appkit/Interface.CallerContext.md +13 -0
- package/docs/api/appkit/Interface.IndexConfig.md +1 -1
- package/docs/api/appkit/Interface.PluginManifest.md +9 -1
- package/docs/api/appkit/Interface.RegisteredAgent.md +11 -0
- package/docs/api/appkit/Interface.RunAgentInput.md +45 -1
- package/docs/api/appkit/TypeAlias.AgentAuth.md +8 -0
- package/docs/api/appkit/TypeAlias.AppKitApi.md +35 -0
- package/docs/api/appkit/TypeAlias.ExecutionContext.md +4 -1
- package/docs/api/appkit/TypeAlias.ExecutionResult.md +65 -0
- package/docs/api/appkit/TypeAlias.ScopedPluginMap.md +12 -0
- package/docs/api/appkit/TypeAlias.UserContext.md +109 -0
- package/docs/api/appkit/TypeAlias.UserScopedApp.md +39 -0
- package/docs/api/appkit.md +14 -0
- package/docs/plugins/agents.md +45 -0
- package/docs/plugins/execution-context.md +101 -50
- package/docs/plugins/lakebase.md +6 -82
- package/llms.txt +15 -1
- package/package.json +1 -1
- package/sbom.cdx.json +1 -1
|
@@ -2,6 +2,8 @@ import { AgentEvent, Message } from "../../shared/src/agent.js";
|
|
|
2
2
|
import { PluginConstructor, PluginData } from "../../shared/src/plugin.js";
|
|
3
3
|
import "../../shared/src/index.js";
|
|
4
4
|
import { AgentDefinition } from "./types.js";
|
|
5
|
+
import { CallerPrincipal } from "../../context/caller-context.js";
|
|
6
|
+
import "../../context/index.js";
|
|
5
7
|
|
|
6
8
|
//#region src/core/agent/run-agent.d.ts
|
|
7
9
|
interface RunAgentInput {
|
|
@@ -9,12 +11,23 @@ interface RunAgentInput {
|
|
|
9
11
|
messages: string | Message[];
|
|
10
12
|
/** Abort signal for cancellation. */
|
|
11
13
|
signal?: AbortSignal;
|
|
14
|
+
/**
|
|
15
|
+
* Explicit user credentials for standalone execution. Host and workspace ID
|
|
16
|
+
* are required, so no CLI profile or service-principal identity is selected.
|
|
17
|
+
* Omit to inherit the ambient scope, or use SP when no caller scope is open.
|
|
18
|
+
* Obtain the token through a trusted authentication flow, not model input.
|
|
19
|
+
*/
|
|
20
|
+
caller?: {
|
|
21
|
+
readonly token: string;
|
|
22
|
+
readonly principal: CallerPrincipal;
|
|
23
|
+
readonly host: string;
|
|
24
|
+
readonly workspaceId: string;
|
|
25
|
+
};
|
|
12
26
|
/**
|
|
13
27
|
* Optional plugin list. Required when `def.tools` is the function form
|
|
14
28
|
* `(plugins) => Record<string, AgentTool>` and the function dereferences
|
|
15
29
|
* any plugins. `runAgent` constructs a fresh instance per plugin and
|
|
16
|
-
* dispatches tool calls
|
|
17
|
-
* there is no HTTP request in standalone mode).
|
|
30
|
+
* dispatches tool calls with the run's ambient principal.
|
|
18
31
|
*/
|
|
19
32
|
plugins?: PluginData<PluginConstructor, unknown, string>[];
|
|
20
33
|
}
|
|
@@ -29,12 +42,12 @@ interface RunAgentResult {
|
|
|
29
42
|
* inline tools, and drives the adapter's `run()` loop to completion.
|
|
30
43
|
*
|
|
31
44
|
* Limitations vs. running through the agents() plugin:
|
|
32
|
-
* - **No
|
|
33
|
-
*
|
|
45
|
+
* - **No approval gate**: tools inherit the run's principal, SP by default.
|
|
46
|
+
* Explicit caller credentials enable user execution. The agents-plugin gate
|
|
34
47
|
* that prompts for human confirmation on `effect: "write" | "update" |
|
|
35
48
|
* "destructive"` tools is also absent. LLM-controlled tool arguments
|
|
36
|
-
* flow straight through to the
|
|
37
|
-
* trusted-prompt environment (CI, batch eval, internal scripts)
|
|
49
|
+
* flow straight through to the tools. Treat standalone runAgent as a
|
|
50
|
+
* trusted-prompt environment (CI, batch eval, internal scripts), not
|
|
38
51
|
* as an exposed user-facing surface.
|
|
39
52
|
* - **Hosted tools (MCP) are not supported** — they require a live MCP
|
|
40
53
|
* client that only exists inside the agents plugin's lifecycle.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-agent.d.ts","names":[],"sources":["../../../src/core/agent/run-agent.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-agent.d.ts","names":[],"sources":["../../../src/core/agent/run-agent.ts"],"mappings":";;;;;;;;UAiDiB,aAAA;;EAEf,QAAA,WAAmB,OAAA;;EAEnB,MAAA,GAAS,WAAA;EAJM;;;;;;EAWf,MAAA;IAAA,SACW,KAAA;IAAA,SACA,SAAA,EAAW,eAAA;IAAA,SACX,IAAA;IAAA,SACA,WAAA;EAAA;EAXX;;;;;;EAmBA,OAAA,GAAU,UAAA,CAAW,iBAAA;AAAA;AAAA,UAGN,cAAA;EAHL;EAKV,IAAA;EALsC;EAOtC,MAAA,EAAQ,UAAA;AAAA;;;;;;;;;AA+BV;;;;;;;;;;;;;;;;;;;;iBAAsB,QAAA,CACpB,GAAA,EAAK,eAAA,EACL,KAAA,EAAO,aAAA,GACN,OAAA,CAAQ,cAAA"}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import { createWorkspaceClient } from "../../shared/src/workspace-client/factory.js";
|
|
2
|
+
import { getClientOptions } from "../../context/client-options.js";
|
|
3
|
+
import { AuthenticationError } from "../../errors/authentication.js";
|
|
4
|
+
import { ConfigurationError } from "../../errors/configuration.js";
|
|
5
|
+
import "../../errors/index.js";
|
|
1
6
|
import { createLogger } from "../../logging/logger.js";
|
|
7
|
+
import { getCallerContext, getWorkspaceClient, runInCallerContext } from "../../context/execution-context.js";
|
|
8
|
+
import { assertPluginExecution } from "../../context/resource-capabilities.js";
|
|
9
|
+
import "../../context/index.js";
|
|
2
10
|
import { SUPERVISOR_EXTENSION_KEY, isSupervisorTool } from "../../agents/supervisor-api.js";
|
|
3
11
|
import { consumeAdapterStream } from "./consume-adapter-stream.js";
|
|
4
12
|
import { createPluginsProxy } from "./plugins-map.js";
|
|
@@ -6,7 +14,7 @@ import { resolveToolkitFromProvider } from "./toolkit-resolver.js";
|
|
|
6
14
|
import { functionToolToDefinition, isFunctionTool } from "./tools/function-tool.js";
|
|
7
15
|
import { isHostedTool } from "./tools/hosted-tools.js";
|
|
8
16
|
import { isToolkitEntry } from "./types.js";
|
|
9
|
-
import { randomUUID } from "node:crypto";
|
|
17
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
10
18
|
|
|
11
19
|
//#region src/core/agent/run-agent.ts
|
|
12
20
|
const logger = createLogger("agent:run-agent");
|
|
@@ -15,12 +23,12 @@ const logger = createLogger("agent:run-agent");
|
|
|
15
23
|
* inline tools, and drives the adapter's `run()` loop to completion.
|
|
16
24
|
*
|
|
17
25
|
* Limitations vs. running through the agents() plugin:
|
|
18
|
-
* - **No
|
|
19
|
-
*
|
|
26
|
+
* - **No approval gate**: tools inherit the run's principal, SP by default.
|
|
27
|
+
* Explicit caller credentials enable user execution. The agents-plugin gate
|
|
20
28
|
* that prompts for human confirmation on `effect: "write" | "update" |
|
|
21
29
|
* "destructive"` tools is also absent. LLM-controlled tool arguments
|
|
22
|
-
* flow straight through to the
|
|
23
|
-
* trusted-prompt environment (CI, batch eval, internal scripts)
|
|
30
|
+
* flow straight through to the tools. Treat standalone runAgent as a
|
|
31
|
+
* trusted-prompt environment (CI, batch eval, internal scripts), not
|
|
24
32
|
* as an exposed user-facing surface.
|
|
25
33
|
* - **Hosted tools (MCP) are not supported** — they require a live MCP
|
|
26
34
|
* client that only exists inside the agents plugin's lifecycle.
|
|
@@ -39,12 +47,40 @@ const logger = createLogger("agent:run-agent");
|
|
|
39
47
|
* createApp instead" message — not mid-stream.
|
|
40
48
|
*/
|
|
41
49
|
async function runAgent(def, input) {
|
|
50
|
+
if (def.auth === "on-behalf-of-user" && !input.caller && getCallerContext()?.principal.type !== "user") throw AuthenticationError.missingToken("user token (runAgent caller is required for an on-behalf-of-user agent)");
|
|
51
|
+
if (input.caller) {
|
|
52
|
+
const { principal, host, workspaceId } = input.caller;
|
|
53
|
+
const token = input.caller.token.trim();
|
|
54
|
+
if (!token) throw AuthenticationError.missingToken("user token");
|
|
55
|
+
if (principal.type !== "user" || !principal.userId.trim()) throw AuthenticationError.missingUserId();
|
|
56
|
+
if (!host.trim() || !workspaceId.trim()) throw new ConfigurationError("runAgent caller requires host and workspaceId");
|
|
57
|
+
const caller = {
|
|
58
|
+
principal: {
|
|
59
|
+
...principal,
|
|
60
|
+
userId: principal.userId.trim()
|
|
61
|
+
},
|
|
62
|
+
client: createWorkspaceClient({
|
|
63
|
+
token,
|
|
64
|
+
host,
|
|
65
|
+
authType: "pat",
|
|
66
|
+
clientOptions: getClientOptions()
|
|
67
|
+
}),
|
|
68
|
+
workspaceId: Promise.resolve(workspaceId),
|
|
69
|
+
tokenFingerprint: createHash("sha256").update(token).digest("hex").slice(0, 16)
|
|
70
|
+
};
|
|
71
|
+
const { caller: _credentials, ...scopedInput } = input;
|
|
72
|
+
return runInCallerContext(caller, () => runStandalone(def, scopedInput));
|
|
73
|
+
}
|
|
74
|
+
return runStandalone(def, input);
|
|
75
|
+
}
|
|
76
|
+
async function runStandalone(def, input) {
|
|
42
77
|
const providerCache = /* @__PURE__ */ new Map();
|
|
43
78
|
await initStandalonePlugins(input.plugins ?? [], providerCache);
|
|
44
|
-
return runAgentInternal(def, input, providerCache);
|
|
79
|
+
return runAgentInternal(def, input, providerCache, false);
|
|
45
80
|
}
|
|
46
|
-
async function runAgentInternal(def, input, providerCache) {
|
|
47
|
-
const
|
|
81
|
+
async function runAgentInternal(def, input, providerCache, parentOnBehalfOfUser) {
|
|
82
|
+
const onBehalfOfUser = parentOnBehalfOfUser || def.auth === "on-behalf-of-user";
|
|
83
|
+
const adapter = await resolveAdapter(def, onBehalfOfUser);
|
|
48
84
|
const messages = normalizeMessages(input.messages, def.instructions);
|
|
49
85
|
const toolIndex = buildStandaloneToolIndex(def, input.plugins ?? [], providerCache);
|
|
50
86
|
const tools = Array.from(toolIndex.values()).filter((e) => e.kind !== "hosted-supervisor").map((e) => e.def);
|
|
@@ -54,14 +90,17 @@ async function runAgentInternal(def, input, providerCache) {
|
|
|
54
90
|
const entry = toolIndex.get(name);
|
|
55
91
|
if (!entry) throw new Error(`Unknown tool: ${name}`);
|
|
56
92
|
if (entry.kind === "function") return entry.tool.execute(args);
|
|
57
|
-
if (entry.kind === "toolkit")
|
|
93
|
+
if (entry.kind === "toolkit") {
|
|
94
|
+
assertPluginExecution(entry.provider);
|
|
95
|
+
return entry.provider.executeAgentTool(entry.localName, args, signal);
|
|
96
|
+
}
|
|
58
97
|
if (entry.kind === "subagent") {
|
|
59
98
|
const subInput = {
|
|
60
99
|
messages: typeof args === "object" && args !== null && typeof args.input === "string" ? args.input : JSON.stringify(args),
|
|
61
100
|
signal,
|
|
62
101
|
plugins: input.plugins
|
|
63
102
|
};
|
|
64
|
-
return (await runAgentInternal(entry.agentDef, subInput, providerCache)).text;
|
|
103
|
+
return (await runAgentInternal(entry.agentDef, subInput, providerCache, onBehalfOfUser)).text;
|
|
65
104
|
}
|
|
66
105
|
if (entry.kind === "hosted-supervisor") throw new Error(`runAgent: tool "${name}" is a hosted-supervisor tool, executed server-side by the Databricks AI Gateway. It must not be invoked from the Node process.`);
|
|
67
106
|
throw new Error(`runAgent: tool "${name}" is a ${entry.kind} tool. Hosted/MCP tools are only usable via createApp({ plugins: [..., agents(...)] }).`);
|
|
@@ -120,7 +159,7 @@ async function initStandalonePlugins(plugins, cache) {
|
|
|
120
159
|
cache.set(data.name, instance);
|
|
121
160
|
}
|
|
122
161
|
}
|
|
123
|
-
async function resolveAdapter(def) {
|
|
162
|
+
async function resolveAdapter(def, onBehalfOfUser) {
|
|
124
163
|
const source = def.model ?? process.env.DATABRICKS_SERVING_ENDPOINT_NAME;
|
|
125
164
|
if (!source) {
|
|
126
165
|
const { DatabricksAdapter } = await import("../../agents/databricks.js");
|
|
@@ -128,7 +167,7 @@ async function resolveAdapter(def) {
|
|
|
128
167
|
}
|
|
129
168
|
if (typeof source === "string") {
|
|
130
169
|
const { adapterFromModelString } = await import("../../agents/databricks.js");
|
|
131
|
-
return adapterFromModelString(source);
|
|
170
|
+
return onBehalfOfUser ? adapterFromModelString(source, { workspaceClient: () => getWorkspaceClient() }) : adapterFromModelString(source);
|
|
132
171
|
}
|
|
133
172
|
return await source;
|
|
134
173
|
}
|
|
@@ -289,11 +328,8 @@ function providerCacheLookup(pluginName, cache) {
|
|
|
289
328
|
/**
|
|
290
329
|
* Lightweight `ToolProvider` shape check used by standalone `runAgent`.
|
|
291
330
|
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
* with a live HTTP context). Standalone plugins are constructed without a
|
|
295
|
-
* `WorkspaceClient` and have no request to scope to, so checking only the
|
|
296
|
-
* two `ToolProvider` methods is the right narrowing here.
|
|
331
|
+
* Standalone plugins need only these methods. Execution identity is inherited
|
|
332
|
+
* from the run's caller scope, without requiring a per-plugin asUser helper.
|
|
297
333
|
*/
|
|
298
334
|
function isStandaloneToolProvider(value) {
|
|
299
335
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-agent.js","names":[],"sources":["../../../src/core/agent/run-agent.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport type {\n AgentAdapter,\n AgentEvent,\n AgentToolDefinition,\n Message,\n PluginConstructor,\n PluginData,\n ToolProvider,\n} from \"shared\";\n\nimport {\n isSupervisorTool,\n SUPERVISOR_EXTENSION_KEY,\n type SupervisorTool,\n} from \"../../agents/supervisor-api\";\nimport { createLogger } from \"../../logging/logger\";\nimport { consumeAdapterStream } from \"./consume-adapter-stream\";\nimport { createPluginsProxy } from \"./plugins-map\";\nimport { resolveToolkitFromProvider } from \"./toolkit-resolver\";\nimport {\n type FunctionTool,\n functionToolToDefinition,\n isFunctionTool,\n} from \"./tools/function-tool\";\nimport { isHostedTool } from \"./tools/hosted-tools\";\nimport type {\n AgentDefinition,\n AgentTool,\n AgentTools,\n Plugins,\n PluginToolkitProvider,\n} from \"./types\";\nimport { isToolkitEntry } from \"./types\";\n\nconst logger = createLogger(\"agent:run-agent\");\n\nexport interface RunAgentInput {\n /** Seed messages for the run. Either a single user string or a full message list. */\n messages: string | Message[];\n /** Abort signal for cancellation. */\n signal?: AbortSignal;\n /**\n * Optional plugin list. Required when `def.tools` is the function form\n * `(plugins) => Record<string, AgentTool>` and the function dereferences\n * any plugins. `runAgent` constructs a fresh instance per plugin and\n * dispatches tool calls against it as the service principal (no OBO —\n * there is no HTTP request in standalone mode).\n */\n plugins?: PluginData<PluginConstructor, unknown, string>[];\n}\n\nexport interface RunAgentResult {\n /** Aggregated text output from all `message_delta` events. */\n text: string;\n /** Every event the adapter yielded, in order. Useful for inspection/tests. */\n events: AgentEvent[];\n}\n\n/**\n * Standalone agent execution without `createApp`. Resolves the adapter, binds\n * inline tools, and drives the adapter's `run()` loop to completion.\n *\n * Limitations vs. running through the agents() plugin:\n * - **No OBO and no approval gate** — there is no HTTP request, so plugin\n * tools run as the service principal. The agents-plugin approval gate\n * that prompts for human confirmation on `effect: \"write\" | \"update\" |\n * \"destructive\"` tools is also absent. LLM-controlled tool arguments\n * flow straight through to the SP. Treat standalone runAgent as a\n * trusted-prompt environment (CI, batch eval, internal scripts) — not\n * as an exposed user-facing surface.\n * - **Hosted tools (MCP) are not supported** — they require a live MCP\n * client that only exists inside the agents plugin's lifecycle.\n * `runAgent` rejects them at index-build time with a clear error.\n * - **Sub-agents** (`agents: { ... }` on the def) are executed as nested\n * `runAgent` calls with no shared thread state. Plugin instances ARE\n * shared across the recursion (same cache as the parent).\n * - **Plugin tools** (used inside the function form via\n * `plugins.<name>.toolkit(...)`) require passing `plugins: [...]` via\n * `RunAgentInput`. Each plugin in that array is constructed once,\n * `attachContext({})` and `await setup()` are called eagerly, and the\n * resulting instance is shared across the top-level run and all\n * sub-agent recursions. Plugins whose `setup()` requires runtime that\n * only `createApp` provides (e.g. `WorkspaceClient`, `ServiceContext`,\n * `PluginContext`) throw at standalone-init time with a clear \"use\n * createApp instead\" message — not mid-stream.\n */\nexport async function runAgent(\n def: AgentDefinition,\n input: RunAgentInput,\n): Promise<RunAgentResult> {\n // Single shared cache for the whole call graph: parent + every nested\n // sub-agent dispatch share constructed plugin instances. Without this,\n // each nested `runAgent` would build its own cache, re-instantiate every\n // plugin, and silently diverge in-instance state between parent and child\n // (e.g. query result caches, connection pools).\n const providerCache = new Map<string, ToolProvider>();\n await initStandalonePlugins(input.plugins ?? [], providerCache);\n return runAgentInternal(def, input, providerCache);\n}\n\nasync function runAgentInternal(\n def: AgentDefinition,\n input: RunAgentInput,\n providerCache: Map<string, ToolProvider>,\n): Promise<RunAgentResult> {\n const adapter = await resolveAdapter(def);\n const messages = normalizeMessages(input.messages, def.instructions);\n const toolIndex = buildStandaloneToolIndex(\n def,\n input.plugins ?? [],\n providerCache,\n );\n // Hosted-supervisor entries are routed via `extensions`, not as callable\n // tools — exclude their placeholder `def` from the wire `tools` array.\n const tools = Array.from(toolIndex.values())\n .filter((e) => e.kind !== \"hosted-supervisor\")\n .map((e) => e.def);\n\n warnOnCapabilityMismatch(def.name ?? \"<anonymous>\", adapter, toolIndex);\n\n const signal = input.signal;\n\n const executeTool = async (name: string, args: unknown): Promise<unknown> => {\n const entry = toolIndex.get(name);\n if (!entry) throw new Error(`Unknown tool: ${name}`);\n if (entry.kind === \"function\") {\n return entry.tool.execute(args as Record<string, unknown>);\n }\n if (entry.kind === \"toolkit\") {\n return entry.provider.executeAgentTool(\n entry.localName,\n args as Record<string, unknown>,\n signal,\n );\n }\n if (entry.kind === \"subagent\") {\n const subInput: RunAgentInput = {\n messages:\n typeof args === \"object\" &&\n args !== null &&\n typeof (args as { input?: unknown }).input === \"string\"\n ? (args as { input: string }).input\n : JSON.stringify(args),\n signal,\n plugins: input.plugins,\n };\n // Reuse the same `providerCache` so sub-agent plugin tools dispatch\n // through the same instances the parent constructed.\n const res = await runAgentInternal(\n entry.agentDef,\n subInput,\n providerCache,\n );\n return res.text;\n }\n if (entry.kind === \"hosted-supervisor\") {\n // Defense-in-depth: should never fire. The placeholder def is\n // filtered out of `tools` above, so the model never sees a callable\n // schema for hosted-supervisor entries. If we ever reach here, the\n // model was somehow handed the def and tried to invoke it directly.\n throw new Error(\n `runAgent: tool \"${name}\" is a hosted-supervisor tool, executed server-side by the Databricks AI Gateway. It must not be invoked from the Node process.`,\n );\n }\n throw new Error(\n `runAgent: tool \"${name}\" is a ${entry.kind} tool. ` +\n \"Hosted/MCP tools are only usable via createApp({ plugins: [..., agents(...)] }).\",\n );\n };\n\n const events: AgentEvent[] = [];\n\n const stream = adapter.run(\n {\n messages,\n tools,\n threadId: randomUUID(),\n signal,\n extensions: buildStandaloneExtensions(toolIndex),\n },\n { executeTool, signal },\n );\n\n // Shared accumulation rule (deltas append, `message` replaces). The\n // `events` array is filled via the `onEvent` side effect so callers that\n // inspect the raw stream still get the full record.\n const text = await consumeAdapterStream(stream, {\n signal,\n onEvent: (event) => {\n events.push(event);\n },\n });\n\n return { text, events };\n}\n\n/**\n * Eagerly construct every plugin in `input.plugins`, run the standard\n * AppKit lifecycle (`attachContext({})` + `await setup()`), and populate\n * `cache`. Failures here surface BEFORE any adapter work — mid-stream\n * `getWorkspaceClient is not initialised`-style errors become a clear\n * startup failure naming the plugin and pointing the user at `createApp`.\n *\n * Plugins that don't need runtime context (no overridden `setup`, or one\n * that doesn't dereference `createApp`-only state) initialise cleanly and\n * standalone runAgent works as documented. Plugins like analytics/files\n * that depend on `WorkspaceClient` will throw the underlying error wrapped\n * with the migration hint.\n */\nasync function initStandalonePlugins(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n cache: Map<string, ToolProvider>,\n): Promise<void> {\n for (const data of plugins) {\n if (cache.has(data.name)) continue;\n const instance = new data.plugin({\n ...(data.config ?? {}),\n name: data.name,\n });\n if (!isStandaloneToolProvider(instance)) {\n throw new Error(\n `runAgent: plugin '${data.name}' is not a ToolProvider ` +\n \"(missing getAgentTools/executeAgentTool). Only ToolProvider plugins \" +\n \"are supported in standalone runAgent.\",\n );\n }\n if (\n typeof (instance as { attachContext?: unknown }).attachContext ===\n \"function\"\n ) {\n try {\n (\n instance as { attachContext: (deps: Record<string, unknown>) => void }\n ).attachContext({});\n } catch (err) {\n throw new Error(\n `runAgent: plugin '${data.name}' attachContext() failed in ` +\n \"standalone mode. This plugin probably depends on createApp's \" +\n \"runtime (WorkspaceClient, ServiceContext, PluginContext). Run \" +\n \"via createApp({ plugins: [..., agents(...)] }) instead. \" +\n `Cause: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n }\n if (typeof (instance as { setup?: unknown }).setup === \"function\") {\n try {\n await (instance as { setup: () => Promise<void> | void }).setup();\n } catch (err) {\n throw new Error(\n `runAgent: plugin '${data.name}' setup() failed in standalone ` +\n \"mode. This plugin probably depends on createApp's runtime \" +\n \"(WorkspaceClient, ServiceContext, PluginContext). Run via \" +\n \"createApp({ plugins: [..., agents(...)] }) instead. \" +\n `Cause: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n }\n cache.set(data.name, instance);\n }\n}\n\nasync function resolveAdapter(def: AgentDefinition): Promise<AgentAdapter> {\n // Explicit model wins; otherwise fall back to the\n // DATABRICKS_SERVING_ENDPOINT_NAME env default. A string from either source\n // routes by name (system.* → AI Gateway, else Model Serving).\n const source = def.model ?? process.env.DATABRICKS_SERVING_ENDPOINT_NAME;\n if (!source) {\n // No model and no env default: let fromModelServing() surface the\n // canonical \"set DATABRICKS_SERVING_ENDPOINT_NAME\" error.\n const { DatabricksAdapter } = await import(\"../../agents/databricks\");\n return DatabricksAdapter.fromModelServing();\n }\n if (typeof source === \"string\") {\n const { adapterFromModelString } = await import(\"../../agents/databricks\");\n return adapterFromModelString(source);\n }\n return await source;\n}\n\nfunction normalizeMessages(\n input: string | Message[],\n instructions: string,\n): Message[] {\n const systemMessage: Message = {\n id: \"system\",\n role: \"system\",\n content: instructions,\n createdAt: new Date(),\n };\n if (typeof input === \"string\") {\n return [\n systemMessage,\n {\n id: randomUUID(),\n role: \"user\",\n content: input,\n createdAt: new Date(),\n },\n ];\n }\n return [systemMessage, ...input];\n}\n\ntype StandaloneEntry =\n | {\n kind: \"function\";\n def: AgentToolDefinition;\n tool: FunctionTool;\n }\n | {\n kind: \"subagent\";\n def: AgentToolDefinition;\n agentDef: AgentDefinition;\n }\n | {\n kind: \"toolkit\";\n def: AgentToolDefinition;\n provider: ToolProvider;\n pluginName: string;\n localName: string;\n }\n | {\n kind: \"hosted\";\n def: AgentToolDefinition;\n }\n | {\n /**\n * Adapter-side hosted tool. Standalone `runAgent` accepts these\n * (unlike MCP hosted tools, which need a live MCP client) because\n * the adapter has everything it needs to execute them server-side:\n * the spec travels via `AgentInput.extensions` and the SA endpoint\n * runs the tool loop. Enables batch-eval / CI use of supervisor\n * agents without `createApp`.\n */\n kind: \"hosted-supervisor\";\n def: AgentToolDefinition;\n spec: SupervisorTool;\n };\n\n/**\n * Resolves `def.tools` (object or function form) and `def.agents`\n * (sub-agents) into a flat dispatch index. The function form is invoked\n * once per call against a {@link Plugins} map drawn from the shared\n * `providerCache` populated by {@link initStandalonePlugins}. Missing\n * references throw a named \"not registered\" error via the proxy.\n */\nfunction buildStandaloneToolIndex(\n def: AgentDefinition,\n plugins: PluginData<PluginConstructor, unknown, string>[],\n providerCache: Map<string, ToolProvider>,\n): Map<string, StandaloneEntry> {\n const index = new Map<string, StandaloneEntry>();\n const tools = resolveDefTools(def, plugins, providerCache);\n\n for (const [key, tool] of Object.entries(tools)) {\n index.set(key, classifyTool(key, tool, providerCache));\n }\n\n for (const [childKey, child] of Object.entries(def.agents ?? {})) {\n const toolName = `agent-${childKey}`;\n index.set(toolName, {\n kind: \"subagent\",\n agentDef: { ...child, name: child.name ?? childKey },\n def: {\n name: toolName,\n description:\n child.instructions.slice(0, 120) ||\n `Delegate to the ${childKey} sub-agent`,\n parameters: {\n type: \"object\",\n properties: {\n input: {\n type: \"string\",\n description: \"Message to send to the sub-agent.\",\n },\n },\n required: [\"input\"],\n },\n },\n });\n }\n\n return index;\n}\n\n/**\n * Resolves `def.tools` to a plain record. The function form is invoked\n * with a typed {@link Plugins} map drawn from the pre-populated\n * `providerCache`; each `plugins.foo.toolkit(opts)` lookup hits the cache\n * directly (no construction at toolkit-call time).\n */\nfunction resolveDefTools(\n def: AgentDefinition,\n plugins: PluginData<PluginConstructor, unknown, string>[],\n providerCache: Map<string, ToolProvider>,\n): AgentTools {\n if (typeof def.tools !== \"function\") {\n return def.tools ?? {};\n }\n const pluginsMap = buildStandalonePluginsMap(plugins, providerCache);\n try {\n return def.tools(pluginsMap);\n } catch (err) {\n const name = def.name ?? \"<anonymous>\";\n throw new Error(\n `runAgent: agent '${name}' tools(plugins) callback threw: ${\n err instanceof Error ? err.message : String(err)\n }`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n}\n\n/**\n * Builds the typed {@link Plugins} map passed to the function form of\n * `def.tools` in standalone mode. Reads pre-constructed instances from\n * `providerCache` (populated eagerly by {@link initStandalonePlugins})\n * and wraps the result in a Proxy so unknown plugin names produce a\n * named \"not registered, Available: ...\" error instead of bubbling up a\n * generic `TypeError: Cannot read properties of undefined`.\n */\nfunction buildStandalonePluginsMap(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n providerCache: Map<string, ToolProvider>,\n): Plugins {\n const out: Record<string, PluginToolkitProvider> = {};\n for (const data of plugins) {\n const provider = providerCache.get(data.name);\n if (!provider) continue; // initStandalonePlugins should have set this\n out[data.name] = {\n toolkit: (opts) => resolveToolkitFromProvider(data.name, provider, opts),\n };\n }\n return createPluginsProxy(out, \"runAgent: tools(plugins)\");\n}\n\nfunction classifyTool(\n key: string,\n tool: AgentTool,\n providerCache: Map<string, ToolProvider>,\n): StandaloneEntry {\n if (isToolkitEntry(tool)) {\n // Toolkit entries inside the function form's returned record carry the\n // provider name they came from, so we can resolve the provider on\n // demand and dispatch through it. The cache is shared with the\n // pluginsMap path so the same instance is reused.\n const provider = providerCacheLookup(tool.pluginName, providerCache);\n return {\n kind: \"toolkit\",\n provider,\n pluginName: tool.pluginName,\n localName: tool.localName,\n def: { ...tool.def, name: key },\n };\n }\n if (isFunctionTool(tool)) {\n return {\n kind: \"function\",\n tool,\n def: { ...functionToolToDefinition(tool), name: key },\n };\n }\n // Supervisor-API hosted tools work in standalone mode: the adapter\n // executes them server-side via `AgentInput.extensions`, no MCP client\n // required. Must come BEFORE the `isHostedTool` MCP rejection — the two\n // predicates classify disjoint values (`isSupervisorTool` matches the\n // `__kind` tag; `isHostedTool` matches the wire-format `type` field),\n // but the placement makes the intent explicit.\n if (isSupervisorTool(tool)) {\n return {\n kind: \"hosted-supervisor\",\n spec: tool.spec,\n def: {\n name: key,\n description: supervisorToolDescription(tool.spec),\n parameters: { type: \"object\", properties: {} },\n },\n };\n }\n if (isHostedTool(tool)) {\n // Hosted tools (e.g. MCP `mcpServer(...)`) need a live MCP client that\n // only exists inside the agents plugin's lifecycle. In standalone\n // `runAgent` they would have errored at dispatch time with a confusing\n // mid-conversation failure; reject them up front so misconfiguration\n // surfaces before the adapter sees the tool list.\n throw new Error(\n `runAgent: tool \"${key}\" is a hosted tool (type=\"${tool.type}\") which is only supported via createApp({ plugins: [..., agents(...)] }). Standalone runAgent has no MCP client.`,\n );\n }\n throw new Error(`runAgent: unrecognized tool shape at key \"${key}\"`);\n}\n\n/** Mirrors `agents.ts`'s `supervisorToolDescription`. */\nfunction supervisorToolDescription(spec: SupervisorTool): string {\n switch (spec.type) {\n case \"genie_space\":\n return spec.genie_space.description;\n case \"uc_function\":\n return spec.uc_function.description;\n case \"knowledge_assistant\":\n return spec.knowledge_assistant.description;\n case \"app\":\n return spec.app.description;\n case \"uc_connection\":\n return spec.uc_connection.description;\n }\n}\n\n/** Mirrors `agents.ts`'s `buildAdapterExtensions`. */\nfunction buildStandaloneExtensions(\n toolIndex: Map<string, StandaloneEntry>,\n): Readonly<Record<string, unknown>> | undefined {\n const supervisorSpecs: SupervisorTool[] = [];\n for (const entry of toolIndex.values()) {\n if (entry.kind === \"hosted-supervisor\") {\n supervisorSpecs.push(entry.spec);\n }\n }\n if (supervisorSpecs.length === 0) return undefined;\n return {\n [SUPERVISOR_EXTENSION_KEY]: { hostedTools: supervisorSpecs },\n };\n}\n\n/**\n * Mirrors the agents-plugin capability warning so standalone `runAgent`\n * produces the same diagnostic when adapter capabilities don't match the\n * tool index. Warn-not-throw: doesn't abort batch evals.\n */\nfunction warnOnCapabilityMismatch(\n agentName: string,\n adapter: AgentAdapter,\n toolIndex: Map<string, StandaloneEntry>,\n): void {\n const accepted = new Set(adapter.acceptsExtensions ?? []);\n\n const hostedSupervisorKeys: string[] = [];\n const inputToolKeys: string[] = [];\n for (const [key, entry] of toolIndex) {\n if (entry.kind === \"hosted-supervisor\") {\n hostedSupervisorKeys.push(key);\n } else {\n inputToolKeys.push(key);\n }\n }\n\n if (\n hostedSupervisorKeys.length > 0 &&\n !accepted.has(SUPERVISOR_EXTENSION_KEY)\n ) {\n logger.warn(\n `Agent '${agentName}' declares hosted-supervisor tools (${hostedSupervisorKeys.join(\", \")}) ` +\n \"but its model adapter does not accept the 'databricks.supervisor' extension. \" +\n \"Pair them with `DatabricksAdapter.fromSupervisorApi(...)`, or remove them.\",\n );\n }\n\n if (adapter.consumesInputTools === false && inputToolKeys.length > 0) {\n logger.warn(\n `Agent '${agentName}' declares function tools / sub-agents (${inputToolKeys.join(\", \")}) ` +\n \"but its model adapter does not consume input.tools. These tools will not be exposed to the model.\",\n );\n }\n}\n\nfunction providerCacheLookup(\n pluginName: string,\n cache: Map<string, ToolProvider>,\n): ToolProvider {\n const cached = cache.get(pluginName);\n if (cached) return cached;\n const available = Array.from(cache.keys()).join(\", \") || \"(none)\";\n throw new Error(\n `runAgent: tool refers to plugin '${pluginName}', but no instance was ` +\n \"initialised for that name. Add it to RunAgentInput.plugins, or — if \" +\n \"this came from a hand-rolled ToolkitEntry — go through \" +\n `plugins[name].toolkit() instead. Available: ${available}.`,\n );\n}\n\n/**\n * Lightweight `ToolProvider` shape check used by standalone `runAgent`.\n *\n * Distinct from `core/plugin-context.isToolProvider` which also requires\n * `asUser` (request-scoped, only meaningful when running inside `createApp`\n * with a live HTTP context). Standalone plugins are constructed without a\n * `WorkspaceClient` and have no request to scope to, so checking only the\n * two `ToolProvider` methods is the right narrowing here.\n */\nfunction isStandaloneToolProvider(value: unknown): value is ToolProvider {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.getAgentTools === \"function\" &&\n typeof obj.executeAgentTool === \"function\"\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-agent.js","names":[],"sources":["../../../src/core/agent/run-agent.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\n\nimport type {\n AgentAdapter,\n AgentEvent,\n AgentToolDefinition,\n Message,\n PluginConstructor,\n PluginData,\n ToolProvider,\n} from \"shared\";\n\nimport type { WorkspaceClientLike } from \"../../agents/databricks\";\nimport {\n isSupervisorTool,\n SUPERVISOR_EXTENSION_KEY,\n type SupervisorTool,\n} from \"../../agents/supervisor-api\";\nimport {\n type CallerPrincipal,\n getCallerContext,\n getWorkspaceClient,\n runInCallerContext,\n} from \"../../context\";\nimport { getClientOptions } from \"../../context/client-options\";\nimport { assertPluginExecution } from \"../../context/resource-capabilities\";\nimport { AuthenticationError, ConfigurationError } from \"../../errors\";\nimport { createLogger } from \"../../logging/logger\";\nimport { createWorkspaceClient } from \"../../workspace-client\";\nimport { consumeAdapterStream } from \"./consume-adapter-stream\";\nimport { createPluginsProxy } from \"./plugins-map\";\nimport { resolveToolkitFromProvider } from \"./toolkit-resolver\";\nimport {\n type FunctionTool,\n functionToolToDefinition,\n isFunctionTool,\n} from \"./tools/function-tool\";\nimport { isHostedTool } from \"./tools/hosted-tools\";\nimport type {\n AgentDefinition,\n AgentTool,\n AgentTools,\n Plugins,\n PluginToolkitProvider,\n} from \"./types\";\nimport { isToolkitEntry } from \"./types\";\n\nconst logger = createLogger(\"agent:run-agent\");\n\nexport interface RunAgentInput {\n /** Seed messages for the run. Either a single user string or a full message list. */\n messages: string | Message[];\n /** Abort signal for cancellation. */\n signal?: AbortSignal;\n /**\n * Explicit user credentials for standalone execution. Host and workspace ID\n * are required, so no CLI profile or service-principal identity is selected.\n * Omit to inherit the ambient scope, or use SP when no caller scope is open.\n * Obtain the token through a trusted authentication flow, not model input.\n */\n caller?: {\n readonly token: string;\n readonly principal: CallerPrincipal;\n readonly host: string;\n readonly workspaceId: string;\n };\n /**\n * Optional plugin list. Required when `def.tools` is the function form\n * `(plugins) => Record<string, AgentTool>` and the function dereferences\n * any plugins. `runAgent` constructs a fresh instance per plugin and\n * dispatches tool calls with the run's ambient principal.\n */\n plugins?: PluginData<PluginConstructor, unknown, string>[];\n}\n\nexport interface RunAgentResult {\n /** Aggregated text output from all `message_delta` events. */\n text: string;\n /** Every event the adapter yielded, in order. Useful for inspection/tests. */\n events: AgentEvent[];\n}\n\n/**\n * Standalone agent execution without `createApp`. Resolves the adapter, binds\n * inline tools, and drives the adapter's `run()` loop to completion.\n *\n * Limitations vs. running through the agents() plugin:\n * - **No approval gate**: tools inherit the run's principal, SP by default.\n * Explicit caller credentials enable user execution. The agents-plugin gate\n * that prompts for human confirmation on `effect: \"write\" | \"update\" |\n * \"destructive\"` tools is also absent. LLM-controlled tool arguments\n * flow straight through to the tools. Treat standalone runAgent as a\n * trusted-prompt environment (CI, batch eval, internal scripts), not\n * as an exposed user-facing surface.\n * - **Hosted tools (MCP) are not supported** — they require a live MCP\n * client that only exists inside the agents plugin's lifecycle.\n * `runAgent` rejects them at index-build time with a clear error.\n * - **Sub-agents** (`agents: { ... }` on the def) are executed as nested\n * `runAgent` calls with no shared thread state. Plugin instances ARE\n * shared across the recursion (same cache as the parent).\n * - **Plugin tools** (used inside the function form via\n * `plugins.<name>.toolkit(...)`) require passing `plugins: [...]` via\n * `RunAgentInput`. Each plugin in that array is constructed once,\n * `attachContext({})` and `await setup()` are called eagerly, and the\n * resulting instance is shared across the top-level run and all\n * sub-agent recursions. Plugins whose `setup()` requires runtime that\n * only `createApp` provides (e.g. `WorkspaceClient`, `ServiceContext`,\n * `PluginContext`) throw at standalone-init time with a clear \"use\n * createApp instead\" message — not mid-stream.\n */\nexport async function runAgent(\n def: AgentDefinition,\n input: RunAgentInput,\n): Promise<RunAgentResult> {\n // An ambient user scope (e.g. inside a request) counts as the caller.\n if (\n def.auth === \"on-behalf-of-user\" &&\n !input.caller &&\n getCallerContext()?.principal.type !== \"user\"\n ) {\n throw AuthenticationError.missingToken(\n \"user token (runAgent caller is required for an on-behalf-of-user agent)\",\n );\n }\n if (input.caller) {\n const { principal, host, workspaceId } = input.caller;\n const token = input.caller.token.trim();\n if (!token) throw AuthenticationError.missingToken(\"user token\");\n if (principal.type !== \"user\" || !principal.userId.trim()) {\n throw AuthenticationError.missingUserId();\n }\n if (!host.trim() || !workspaceId.trim()) {\n throw new ConfigurationError(\n \"runAgent caller requires host and workspaceId\",\n );\n }\n const caller = {\n principal: { ...principal, userId: principal.userId.trim() },\n client: createWorkspaceClient({\n token,\n host,\n authType: \"pat\",\n clientOptions: getClientOptions(),\n }),\n workspaceId: Promise.resolve(workspaceId),\n tokenFingerprint: createHash(\"sha256\")\n .update(token)\n .digest(\"hex\")\n .slice(0, 16),\n };\n // Credentials are not carried into adapter inputs, tools, or sub-agent options.\n const { caller: _credentials, ...scopedInput } = input;\n return runInCallerContext(caller, () => runStandalone(def, scopedInput));\n }\n return runStandalone(def, input);\n}\n\nasync function runStandalone(\n def: AgentDefinition,\n input: RunAgentInput,\n): Promise<RunAgentResult> {\n // Single shared cache for the whole call graph: parent + every nested\n // sub-agent dispatch share constructed plugin instances. Without this,\n // each nested `runAgent` would build its own cache, re-instantiate every\n // plugin, and silently diverge in-instance state between parent and child\n // (e.g. query result caches, connection pools).\n const providerCache = new Map<string, ToolProvider>();\n await initStandalonePlugins(input.plugins ?? [], providerCache);\n return runAgentInternal(def, input, providerCache, false);\n}\n\nasync function runAgentInternal(\n def: AgentDefinition,\n input: RunAgentInput,\n providerCache: Map<string, ToolProvider>,\n parentOnBehalfOfUser: boolean,\n): Promise<RunAgentResult> {\n // Never widen: under an on-behalf-of-user parent every child stays the user.\n const onBehalfOfUser =\n parentOnBehalfOfUser || def.auth === \"on-behalf-of-user\";\n const adapter = await resolveAdapter(def, onBehalfOfUser);\n const messages = normalizeMessages(input.messages, def.instructions);\n const toolIndex = buildStandaloneToolIndex(\n def,\n input.plugins ?? [],\n providerCache,\n );\n // Hosted-supervisor entries are routed via `extensions`, not as callable\n // tools — exclude their placeholder `def` from the wire `tools` array.\n const tools = Array.from(toolIndex.values())\n .filter((e) => e.kind !== \"hosted-supervisor\")\n .map((e) => e.def);\n\n warnOnCapabilityMismatch(def.name ?? \"<anonymous>\", adapter, toolIndex);\n\n const signal = input.signal;\n\n const executeTool = async (name: string, args: unknown): Promise<unknown> => {\n const entry = toolIndex.get(name);\n if (!entry) throw new Error(`Unknown tool: ${name}`);\n if (entry.kind === \"function\") {\n return entry.tool.execute(args as Record<string, unknown>);\n }\n if (entry.kind === \"toolkit\") {\n assertPluginExecution(entry.provider);\n return entry.provider.executeAgentTool(\n entry.localName,\n args as Record<string, unknown>,\n signal,\n );\n }\n if (entry.kind === \"subagent\") {\n const subInput: RunAgentInput = {\n messages:\n typeof args === \"object\" &&\n args !== null &&\n typeof (args as { input?: unknown }).input === \"string\"\n ? (args as { input: string }).input\n : JSON.stringify(args),\n signal,\n plugins: input.plugins,\n };\n // Reuse the same `providerCache` so sub-agent plugin tools dispatch\n // through the same instances the parent constructed.\n const res = await runAgentInternal(\n entry.agentDef,\n subInput,\n providerCache,\n onBehalfOfUser,\n );\n return res.text;\n }\n if (entry.kind === \"hosted-supervisor\") {\n // Defense-in-depth: should never fire. The placeholder def is\n // filtered out of `tools` above, so the model never sees a callable\n // schema for hosted-supervisor entries. If we ever reach here, the\n // model was somehow handed the def and tried to invoke it directly.\n throw new Error(\n `runAgent: tool \"${name}\" is a hosted-supervisor tool, executed server-side by the Databricks AI Gateway. It must not be invoked from the Node process.`,\n );\n }\n throw new Error(\n `runAgent: tool \"${name}\" is a ${entry.kind} tool. ` +\n \"Hosted/MCP tools are only usable via createApp({ plugins: [..., agents(...)] }).\",\n );\n };\n\n const events: AgentEvent[] = [];\n\n const stream = adapter.run(\n {\n messages,\n tools,\n threadId: randomUUID(),\n signal,\n extensions: buildStandaloneExtensions(toolIndex),\n },\n { executeTool, signal },\n );\n\n // Shared accumulation rule (deltas append, `message` replaces). The\n // `events` array is filled via the `onEvent` side effect so callers that\n // inspect the raw stream still get the full record.\n const text = await consumeAdapterStream(stream, {\n signal,\n onEvent: (event) => {\n events.push(event);\n },\n });\n\n return { text, events };\n}\n\n/**\n * Eagerly construct every plugin in `input.plugins`, run the standard\n * AppKit lifecycle (`attachContext({})` + `await setup()`), and populate\n * `cache`. Failures here surface BEFORE any adapter work — mid-stream\n * `getWorkspaceClient is not initialised`-style errors become a clear\n * startup failure naming the plugin and pointing the user at `createApp`.\n *\n * Plugins that don't need runtime context (no overridden `setup`, or one\n * that doesn't dereference `createApp`-only state) initialise cleanly and\n * standalone runAgent works as documented. Plugins like analytics/files\n * that depend on `WorkspaceClient` will throw the underlying error wrapped\n * with the migration hint.\n */\nasync function initStandalonePlugins(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n cache: Map<string, ToolProvider>,\n): Promise<void> {\n for (const data of plugins) {\n if (cache.has(data.name)) continue;\n const instance = new data.plugin({\n ...(data.config ?? {}),\n name: data.name,\n });\n if (!isStandaloneToolProvider(instance)) {\n throw new Error(\n `runAgent: plugin '${data.name}' is not a ToolProvider ` +\n \"(missing getAgentTools/executeAgentTool). Only ToolProvider plugins \" +\n \"are supported in standalone runAgent.\",\n );\n }\n if (\n typeof (instance as { attachContext?: unknown }).attachContext ===\n \"function\"\n ) {\n try {\n (\n instance as { attachContext: (deps: Record<string, unknown>) => void }\n ).attachContext({});\n } catch (err) {\n throw new Error(\n `runAgent: plugin '${data.name}' attachContext() failed in ` +\n \"standalone mode. This plugin probably depends on createApp's \" +\n \"runtime (WorkspaceClient, ServiceContext, PluginContext). Run \" +\n \"via createApp({ plugins: [..., agents(...)] }) instead. \" +\n `Cause: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n }\n if (typeof (instance as { setup?: unknown }).setup === \"function\") {\n try {\n await (instance as { setup: () => Promise<void> | void }).setup();\n } catch (err) {\n throw new Error(\n `runAgent: plugin '${data.name}' setup() failed in standalone ` +\n \"mode. This plugin probably depends on createApp's runtime \" +\n \"(WorkspaceClient, ServiceContext, PluginContext). Run via \" +\n \"createApp({ plugins: [..., agents(...)] }) instead. \" +\n `Cause: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n }\n cache.set(data.name, instance);\n }\n}\n\nasync function resolveAdapter(\n def: AgentDefinition,\n onBehalfOfUser: boolean,\n): Promise<AgentAdapter> {\n // Explicit model wins; otherwise fall back to the\n // DATABRICKS_SERVING_ENDPOINT_NAME env default. A string from either source\n // routes by name (system.* → AI Gateway, else Model Serving).\n const source = def.model ?? process.env.DATABRICKS_SERVING_ENDPOINT_NAME;\n if (!source) {\n // No model and no env default: let fromModelServing() surface the\n // canonical \"set DATABRICKS_SERVING_ENDPOINT_NAME\" error.\n const { DatabricksAdapter } = await import(\"../../agents/databricks\");\n return DatabricksAdapter.fromModelServing();\n }\n if (typeof source === \"string\") {\n const { adapterFromModelString } = await import(\"../../agents/databricks\");\n // On behalf of the user the model client is the caller's, per call.\n return onBehalfOfUser\n ? adapterFromModelString(source, {\n workspaceClient: () =>\n getWorkspaceClient() as unknown as WorkspaceClientLike,\n })\n : adapterFromModelString(source);\n }\n return await source;\n}\n\nfunction normalizeMessages(\n input: string | Message[],\n instructions: string,\n): Message[] {\n const systemMessage: Message = {\n id: \"system\",\n role: \"system\",\n content: instructions,\n createdAt: new Date(),\n };\n if (typeof input === \"string\") {\n return [\n systemMessage,\n {\n id: randomUUID(),\n role: \"user\",\n content: input,\n createdAt: new Date(),\n },\n ];\n }\n return [systemMessage, ...input];\n}\n\ntype StandaloneEntry =\n | {\n kind: \"function\";\n def: AgentToolDefinition;\n tool: FunctionTool;\n }\n | {\n kind: \"subagent\";\n def: AgentToolDefinition;\n agentDef: AgentDefinition;\n }\n | {\n kind: \"toolkit\";\n def: AgentToolDefinition;\n provider: ToolProvider;\n pluginName: string;\n localName: string;\n }\n | {\n kind: \"hosted\";\n def: AgentToolDefinition;\n }\n | {\n /**\n * Adapter-side hosted tool. Standalone `runAgent` accepts these\n * (unlike MCP hosted tools, which need a live MCP client) because\n * the adapter has everything it needs to execute them server-side:\n * the spec travels via `AgentInput.extensions` and the SA endpoint\n * runs the tool loop. Enables batch-eval / CI use of supervisor\n * agents without `createApp`.\n */\n kind: \"hosted-supervisor\";\n def: AgentToolDefinition;\n spec: SupervisorTool;\n };\n\n/**\n * Resolves `def.tools` (object or function form) and `def.agents`\n * (sub-agents) into a flat dispatch index. The function form is invoked\n * once per call against a {@link Plugins} map drawn from the shared\n * `providerCache` populated by {@link initStandalonePlugins}. Missing\n * references throw a named \"not registered\" error via the proxy.\n */\nfunction buildStandaloneToolIndex(\n def: AgentDefinition,\n plugins: PluginData<PluginConstructor, unknown, string>[],\n providerCache: Map<string, ToolProvider>,\n): Map<string, StandaloneEntry> {\n const index = new Map<string, StandaloneEntry>();\n const tools = resolveDefTools(def, plugins, providerCache);\n\n for (const [key, tool] of Object.entries(tools)) {\n index.set(key, classifyTool(key, tool, providerCache));\n }\n\n for (const [childKey, child] of Object.entries(def.agents ?? {})) {\n const toolName = `agent-${childKey}`;\n index.set(toolName, {\n kind: \"subagent\",\n agentDef: { ...child, name: child.name ?? childKey },\n def: {\n name: toolName,\n description:\n child.instructions.slice(0, 120) ||\n `Delegate to the ${childKey} sub-agent`,\n parameters: {\n type: \"object\",\n properties: {\n input: {\n type: \"string\",\n description: \"Message to send to the sub-agent.\",\n },\n },\n required: [\"input\"],\n },\n },\n });\n }\n\n return index;\n}\n\n/**\n * Resolves `def.tools` to a plain record. The function form is invoked\n * with a typed {@link Plugins} map drawn from the pre-populated\n * `providerCache`; each `plugins.foo.toolkit(opts)` lookup hits the cache\n * directly (no construction at toolkit-call time).\n */\nfunction resolveDefTools(\n def: AgentDefinition,\n plugins: PluginData<PluginConstructor, unknown, string>[],\n providerCache: Map<string, ToolProvider>,\n): AgentTools {\n if (typeof def.tools !== \"function\") {\n return def.tools ?? {};\n }\n const pluginsMap = buildStandalonePluginsMap(plugins, providerCache);\n try {\n return def.tools(pluginsMap);\n } catch (err) {\n const name = def.name ?? \"<anonymous>\";\n throw new Error(\n `runAgent: agent '${name}' tools(plugins) callback threw: ${\n err instanceof Error ? err.message : String(err)\n }`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n}\n\n/**\n * Builds the typed {@link Plugins} map passed to the function form of\n * `def.tools` in standalone mode. Reads pre-constructed instances from\n * `providerCache` (populated eagerly by {@link initStandalonePlugins})\n * and wraps the result in a Proxy so unknown plugin names produce a\n * named \"not registered, Available: ...\" error instead of bubbling up a\n * generic `TypeError: Cannot read properties of undefined`.\n */\nfunction buildStandalonePluginsMap(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n providerCache: Map<string, ToolProvider>,\n): Plugins {\n const out: Record<string, PluginToolkitProvider> = {};\n for (const data of plugins) {\n const provider = providerCache.get(data.name);\n if (!provider) continue; // initStandalonePlugins should have set this\n out[data.name] = {\n toolkit: (opts) => resolveToolkitFromProvider(data.name, provider, opts),\n };\n }\n return createPluginsProxy(out, \"runAgent: tools(plugins)\");\n}\n\nfunction classifyTool(\n key: string,\n tool: AgentTool,\n providerCache: Map<string, ToolProvider>,\n): StandaloneEntry {\n if (isToolkitEntry(tool)) {\n // Toolkit entries inside the function form's returned record carry the\n // provider name they came from, so we can resolve the provider on\n // demand and dispatch through it. The cache is shared with the\n // pluginsMap path so the same instance is reused.\n const provider = providerCacheLookup(tool.pluginName, providerCache);\n return {\n kind: \"toolkit\",\n provider,\n pluginName: tool.pluginName,\n localName: tool.localName,\n def: { ...tool.def, name: key },\n };\n }\n if (isFunctionTool(tool)) {\n return {\n kind: \"function\",\n tool,\n def: { ...functionToolToDefinition(tool), name: key },\n };\n }\n // Supervisor-API hosted tools work in standalone mode: the adapter\n // executes them server-side via `AgentInput.extensions`, no MCP client\n // required. Must come BEFORE the `isHostedTool` MCP rejection — the two\n // predicates classify disjoint values (`isSupervisorTool` matches the\n // `__kind` tag; `isHostedTool` matches the wire-format `type` field),\n // but the placement makes the intent explicit.\n if (isSupervisorTool(tool)) {\n return {\n kind: \"hosted-supervisor\",\n spec: tool.spec,\n def: {\n name: key,\n description: supervisorToolDescription(tool.spec),\n parameters: { type: \"object\", properties: {} },\n },\n };\n }\n if (isHostedTool(tool)) {\n // Hosted tools (e.g. MCP `mcpServer(...)`) need a live MCP client that\n // only exists inside the agents plugin's lifecycle. In standalone\n // `runAgent` they would have errored at dispatch time with a confusing\n // mid-conversation failure; reject them up front so misconfiguration\n // surfaces before the adapter sees the tool list.\n throw new Error(\n `runAgent: tool \"${key}\" is a hosted tool (type=\"${tool.type}\") which is only supported via createApp({ plugins: [..., agents(...)] }). Standalone runAgent has no MCP client.`,\n );\n }\n throw new Error(`runAgent: unrecognized tool shape at key \"${key}\"`);\n}\n\n/** Mirrors `agents.ts`'s `supervisorToolDescription`. */\nfunction supervisorToolDescription(spec: SupervisorTool): string {\n switch (spec.type) {\n case \"genie_space\":\n return spec.genie_space.description;\n case \"uc_function\":\n return spec.uc_function.description;\n case \"knowledge_assistant\":\n return spec.knowledge_assistant.description;\n case \"app\":\n return spec.app.description;\n case \"uc_connection\":\n return spec.uc_connection.description;\n }\n}\n\n/** Mirrors `agents.ts`'s `buildAdapterExtensions`. */\nfunction buildStandaloneExtensions(\n toolIndex: Map<string, StandaloneEntry>,\n): Readonly<Record<string, unknown>> | undefined {\n const supervisorSpecs: SupervisorTool[] = [];\n for (const entry of toolIndex.values()) {\n if (entry.kind === \"hosted-supervisor\") {\n supervisorSpecs.push(entry.spec);\n }\n }\n if (supervisorSpecs.length === 0) return undefined;\n return {\n [SUPERVISOR_EXTENSION_KEY]: { hostedTools: supervisorSpecs },\n };\n}\n\n/**\n * Mirrors the agents-plugin capability warning so standalone `runAgent`\n * produces the same diagnostic when adapter capabilities don't match the\n * tool index. Warn-not-throw: doesn't abort batch evals.\n */\nfunction warnOnCapabilityMismatch(\n agentName: string,\n adapter: AgentAdapter,\n toolIndex: Map<string, StandaloneEntry>,\n): void {\n const accepted = new Set(adapter.acceptsExtensions ?? []);\n\n const hostedSupervisorKeys: string[] = [];\n const inputToolKeys: string[] = [];\n for (const [key, entry] of toolIndex) {\n if (entry.kind === \"hosted-supervisor\") {\n hostedSupervisorKeys.push(key);\n } else {\n inputToolKeys.push(key);\n }\n }\n\n if (\n hostedSupervisorKeys.length > 0 &&\n !accepted.has(SUPERVISOR_EXTENSION_KEY)\n ) {\n logger.warn(\n `Agent '${agentName}' declares hosted-supervisor tools (${hostedSupervisorKeys.join(\", \")}) ` +\n \"but its model adapter does not accept the 'databricks.supervisor' extension. \" +\n \"Pair them with `DatabricksAdapter.fromSupervisorApi(...)`, or remove them.\",\n );\n }\n\n if (adapter.consumesInputTools === false && inputToolKeys.length > 0) {\n logger.warn(\n `Agent '${agentName}' declares function tools / sub-agents (${inputToolKeys.join(\", \")}) ` +\n \"but its model adapter does not consume input.tools. These tools will not be exposed to the model.\",\n );\n }\n}\n\nfunction providerCacheLookup(\n pluginName: string,\n cache: Map<string, ToolProvider>,\n): ToolProvider {\n const cached = cache.get(pluginName);\n if (cached) return cached;\n const available = Array.from(cache.keys()).join(\", \") || \"(none)\";\n throw new Error(\n `runAgent: tool refers to plugin '${pluginName}', but no instance was ` +\n \"initialised for that name. Add it to RunAgentInput.plugins, or — if \" +\n \"this came from a hand-rolled ToolkitEntry — go through \" +\n `plugins[name].toolkit() instead. Available: ${available}.`,\n );\n}\n\n/**\n * Lightweight `ToolProvider` shape check used by standalone `runAgent`.\n *\n * Standalone plugins need only these methods. Execution identity is inherited\n * from the run's caller scope, without requiring a per-plugin asUser helper.\n */\nfunction isStandaloneToolProvider(value: unknown): value is ToolProvider {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.getAgentTools === \"function\" &&\n typeof obj.executeAgentTool === \"function\"\n );\n}\n"],"mappings":"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"}
|
|
@@ -184,7 +184,17 @@ interface AgentDefinition {
|
|
|
184
184
|
* `InMemoryThreadStore`. Defaults to `false`.
|
|
185
185
|
*/
|
|
186
186
|
ephemeral?: boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Run this agent on behalf of the signed-in user: the model call, plugin
|
|
189
|
+
* tools, hand-rolled tools, and sub-agents all use the user's credentials.
|
|
190
|
+
* Overrides `agents({ auth })` for this agent. Omit for the default, where
|
|
191
|
+
* the model and hand-rolled tools run as the app service principal and
|
|
192
|
+
* plugin tools run as the user.
|
|
193
|
+
*/
|
|
194
|
+
auth?: AgentAuth;
|
|
187
195
|
}
|
|
196
|
+
/** Identity an agent runs under. The only value is on-behalf-of-user. */
|
|
197
|
+
type AgentAuth = "on-behalf-of-user";
|
|
188
198
|
/**
|
|
189
199
|
* Auto-inherit configuration. When enabled for a given agent origin, agents
|
|
190
200
|
* with no explicit `tools:` declaration receive every registered ToolProvider
|
|
@@ -217,6 +227,11 @@ interface AgentsPluginConfig extends BasePluginConfig {
|
|
|
217
227
|
defaultAgent?: string;
|
|
218
228
|
/** Default model for agents that don't specify their own (in code or frontmatter). */
|
|
219
229
|
defaultModel?: AgentAdapter | Promise<AgentAdapter> | string;
|
|
230
|
+
/**
|
|
231
|
+
* Default identity for agents that don't set their own `auth`.
|
|
232
|
+
* `"on-behalf-of-user"` runs the whole agent as the signed-in user.
|
|
233
|
+
*/
|
|
234
|
+
auth?: AgentAuth;
|
|
220
235
|
/** Ambient tool library. Keys may be referenced by markdown frontmatter via `tools: [key1, key2]`. */
|
|
221
236
|
tools?: Record<string, AgentTool>;
|
|
222
237
|
/** Whether to auto-inherit every ToolProvider plugin's toolkit. Accepts a boolean shorthand. */
|
|
@@ -370,6 +385,8 @@ interface RegisteredAgent {
|
|
|
370
385
|
generationParams?: GenerationParams;
|
|
371
386
|
/** Mirrors `AgentDefinition.ephemeral` — skip thread persistence. */
|
|
372
387
|
ephemeral?: boolean;
|
|
388
|
+
/** Effective identity: the agent's `auth`, else the plugin default. */
|
|
389
|
+
auth?: AgentAuth;
|
|
373
390
|
/**
|
|
374
391
|
* Resolved per-agent skill catalog (visibility + collision rules applied).
|
|
375
392
|
* Present when any skill is visible to this agent; drives the always-on
|
|
@@ -383,5 +400,5 @@ interface RegisteredAgent {
|
|
|
383
400
|
*/
|
|
384
401
|
declare function isToolkitEntry(value: unknown): value is ToolkitEntry;
|
|
385
402
|
//#endregion
|
|
386
|
-
export { AgentDefinition, AgentTool, AgentTools, AgentToolsFn, AgentsPluginConfig, AutoInheritToolsConfig, BaseSystemPromptOption, PluginToolkitProvider, Plugins, PromptContext, RegisteredAgent, ResolvedToolEntry, ToolkitEntry, ToolkitOptions, isToolkitEntry };
|
|
403
|
+
export { AgentAuth, AgentDefinition, AgentTool, AgentTools, AgentToolsFn, AgentsPluginConfig, AutoInheritToolsConfig, BaseSystemPromptOption, PluginToolkitProvider, Plugins, PromptContext, RegisteredAgent, ResolvedToolEntry, ToolkitEntry, ToolkitOptions, isToolkitEntry };
|
|
387
404
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/core/agent/types.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAoBiB,YAAA;EAAA,SACN,YAAA;EACT,UAAA;EACA,SAAA;EACA,GAAA,EAAK,mBAAA;EACL,WAAA,GAAc,eAAA;EAFd;;;;;;EASA,eAAA;AAAA;AASF;;;;;;AAAA,KAAY,SAAA,GACR,YAAA,GACA,UAAA,GACA,YAAA,GAAY,oBAAA;AAAA,UAGC,cAAA;EAF6C;EAI5D,MAAA;EANE;EAQF,IAAA;EAPc;EASd,MAAA;EATc;EAWd,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;;;;UAKpB,aAAA;EACf,SAAA;EACA,WAAA;EACA,SAAA;AAAA;AAAA,KAGU,sBAAA,sBAGN,GAAA,EAAK,aAAA;;;;;KAMC,UAAA,GAAa,MAAA,SAAe,SAAA;;;;;;;;;AAaxC;KAFY,YAAA,IAAgB,OAAA,EAAS,OAAA,KAAY,UAAA;AAAA,UAEhC,eAAA;EAmCP;;;;;;;;;;;;;;;;;;EAhBR,IAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/core/agent/types.ts"],"mappings":"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"}
|
|
@@ -1 +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\";\n\nimport type { GenerationParams } from \"../../agents/databricks\";\nimport type { McpHostPolicyConfig } from \"../../connectors/mcp\";\nimport type { ResolvedSkillCatalog } from \"./skills/types\";\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), toolkit references from plugins\n * (`analytics().toolkit()`), or adapter-hosted Supervisor-API tools\n * (`supervisorTools.*`).\n */\nexport type AgentTool =\n | FunctionTool\n | HostedTool\n | ToolkitEntry\n | import(\"../../agents/supervisor-api\").HostedSupervisorTool;\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 `server/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 /**\n * Marks this agent as the default one chosen when a client doesn't name an\n * agent. Mirrors markdown frontmatter `default: true`. When several agents\n * set it, a code (discovered) agent wins over a markdown one, then the\n * lowest id; an explicit `agents({ defaultAgent })` always overrides it.\n * Defaults to `false`.\n */\n default?: boolean;\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 /**\n * Names of global skills (shared `skills/` pool or catalog volume) to make\n * visible to this agent. Per-agent skills under `<id>/skills/` are always\n * visible and need not be listed. Ignored when the plugin's\n * `autoInheritSkills` makes every global skill visible.\n */\n skills?: string[];\n /** Override the plugin's baseSystemPrompt for this agent only. */\n baseSystemPrompt?: BaseSystemPromptOption;\n maxSteps?: number;\n maxTokens?: number;\n /**\n * Optional generation parameters (`temperature`, `top_p`, `stop`,\n * `frequency_penalty`, `presence_penalty`) forwarded to the OpenAI-compatible\n * serving request body. Only set keys are sent. Applied only when AppKit\n * builds the adapter itself (string or omitted `model`); when you pass a\n * pre-built `AgentAdapter`, configure generation params on it directly.\n */\n generationParams?: GenerationParams;\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 /**\n * @deprecated Put each code agent in its own folder under\n * `server/agents/<id>/agent.ts` (`export default createAgent({ ... })`); it is\n * discovered automatically at startup and the call collapses to\n * `agents({ ... })` with no map. Still honored for backward compatibility\n * (emits a one-time deprecation warning) but will be removed in a future\n * minor. If both discovery and this map define the same id, discovery wins\n * and the map entry is ignored.\n */\n agents?: Record<string, AgentDefinition>;\n /** Agent used when clients don't specify one. Precedence: this value, else a code agent with `default: true`, else a markdown agent with `default: true`, else the first-registered agent. */\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 /**\n * Whether every global skill (shared `skills/` pool or catalog volume) is\n * visible to an agent without listing it in `skills:` frontmatter. Off by\n * default so each agent's always-on skill catalog stays lean; accepts a\n * boolean shorthand or a per-origin `{ file, code }` config, mirroring\n * {@link autoInheritTools}.\n */\n autoInheritSkills?: boolean | AutoInheritToolsConfig;\n /**\n * Unity Catalog Volume path for catalog-sourced skills (e.g.\n * `/Volumes/<catalog>/<schema>/<volume>`). Falls back to the\n * `DATABRICKS_VOLUME_AGENT_SKILLS` env var. Skills at `<volume>/<name>/SKILL.md`\n * are discovered at boot and on `reload()` and read as the service principal.\n */\n skillsVolume?: string;\n /**\n * Identity used to read catalog (volume) skills. v1 supports `\"sp\"` (default —\n * a shared, service-principal-readable curated pool). `\"obo\"` is the reserved\n * switch point for per-user skill volumes and is not wired yet (falls back to\n * `\"sp\"` with a warning).\n */\n skillCredentialMode?: \"sp\" | \"obo\";\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 /api/agents/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 | {\n /**\n * Adapter-side hosted tool (executed by the model-host, not by the\n * Node process). Today: Supervisor API hosted tools (Genie spaces,\n * UC functions, etc.). The `spec` is opaque to the agents plugin —\n * it routes the entry into `AgentInput.extensions` for the adapter\n * that declared the matching `acceptsExtensions` key. `def` is a\n * synthetic placeholder kept so the index has a uniform shape; it\n * is intentionally NOT included in the `tools` array passed to\n * `adapter.run()` (those entries are not callable functions).\n */\n source: \"hosted-supervisor\";\n spec: import(\"../../agents/supervisor-api\").SupervisorTool;\n def: AgentToolDefinition;\n }\n | {\n /**\n * Built-in skill tools (`load_skill`, `read_skill_file`) injected into\n * any agent that has a visible skill catalog. Executed in-process by the\n * agents plugin against the agent's resolved catalog; read-only, so they\n * bypass the approval gate.\n */\n source: \"skill\";\n builtin: \"load_skill\" | \"read_skill_file\";\n catalog: ResolvedSkillCatalog;\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.generationParams`. */\n generationParams?: GenerationParams;\n /** Mirrors `AgentDefinition.ephemeral` — skip thread persistence. */\n ephemeral?: boolean;\n /**\n * Resolved per-agent skill catalog (visibility + collision rules applied).\n * Present when any skill is visible to this agent; drives the always-on\n * prompt catalog and `load_skill` dispatch.\n */\n skills?: ResolvedSkillCatalog;\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":";;;;;AA6ZA,SAAgB,eAAe,OAAuC;AACpE,QACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB"}
|
|
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\";\n\nimport type { GenerationParams } from \"../../agents/databricks\";\nimport type { McpHostPolicyConfig } from \"../../connectors/mcp\";\nimport type { ResolvedSkillCatalog } from \"./skills/types\";\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), toolkit references from plugins\n * (`analytics().toolkit()`), or adapter-hosted Supervisor-API tools\n * (`supervisorTools.*`).\n */\nexport type AgentTool =\n | FunctionTool\n | HostedTool\n | ToolkitEntry\n | import(\"../../agents/supervisor-api\").HostedSupervisorTool;\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 `server/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 /**\n * Marks this agent as the default one chosen when a client doesn't name an\n * agent. Mirrors markdown frontmatter `default: true`. When several agents\n * set it, a code (discovered) agent wins over a markdown one, then the\n * lowest id; an explicit `agents({ defaultAgent })` always overrides it.\n * Defaults to `false`.\n */\n default?: boolean;\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 /**\n * Names of global skills (shared `skills/` pool or catalog volume) to make\n * visible to this agent. Per-agent skills under `<id>/skills/` are always\n * visible and need not be listed. Ignored when the plugin's\n * `autoInheritSkills` makes every global skill visible.\n */\n skills?: string[];\n /** Override the plugin's baseSystemPrompt for this agent only. */\n baseSystemPrompt?: BaseSystemPromptOption;\n maxSteps?: number;\n maxTokens?: number;\n /**\n * Optional generation parameters (`temperature`, `top_p`, `stop`,\n * `frequency_penalty`, `presence_penalty`) forwarded to the OpenAI-compatible\n * serving request body. Only set keys are sent. Applied only when AppKit\n * builds the adapter itself (string or omitted `model`); when you pass a\n * pre-built `AgentAdapter`, configure generation params on it directly.\n */\n generationParams?: GenerationParams;\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 * Run this agent on behalf of the signed-in user: the model call, plugin\n * tools, hand-rolled tools, and sub-agents all use the user's credentials.\n * Overrides `agents({ auth })` for this agent. Omit for the default, where\n * the model and hand-rolled tools run as the app service principal and\n * plugin tools run as the user.\n */\n auth?: AgentAuth;\n}\n\n/** Identity an agent runs under. The only value is on-behalf-of-user. */\nexport type AgentAuth = \"on-behalf-of-user\";\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 /**\n * @deprecated Put each code agent in its own folder under\n * `server/agents/<id>/agent.ts` (`export default createAgent({ ... })`); it is\n * discovered automatically at startup and the call collapses to\n * `agents({ ... })` with no map. Still honored for backward compatibility\n * (emits a one-time deprecation warning) but will be removed in a future\n * minor. If both discovery and this map define the same id, discovery wins\n * and the map entry is ignored.\n */\n agents?: Record<string, AgentDefinition>;\n /** Agent used when clients don't specify one. Precedence: this value, else a code agent with `default: true`, else a markdown agent with `default: true`, else the first-registered agent. */\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 /**\n * Default identity for agents that don't set their own `auth`.\n * `\"on-behalf-of-user\"` runs the whole agent as the signed-in user.\n */\n auth?: AgentAuth;\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 /**\n * Whether every global skill (shared `skills/` pool or catalog volume) is\n * visible to an agent without listing it in `skills:` frontmatter. Off by\n * default so each agent's always-on skill catalog stays lean; accepts a\n * boolean shorthand or a per-origin `{ file, code }` config, mirroring\n * {@link autoInheritTools}.\n */\n autoInheritSkills?: boolean | AutoInheritToolsConfig;\n /**\n * Unity Catalog Volume path for catalog-sourced skills (e.g.\n * `/Volumes/<catalog>/<schema>/<volume>`). Falls back to the\n * `DATABRICKS_VOLUME_AGENT_SKILLS` env var. Skills at `<volume>/<name>/SKILL.md`\n * are discovered at boot and on `reload()` and read as the service principal.\n */\n skillsVolume?: string;\n /**\n * Identity used to read catalog (volume) skills. v1 supports `\"sp\"` (default —\n * a shared, service-principal-readable curated pool). `\"obo\"` is the reserved\n * switch point for per-user skill volumes and is not wired yet (falls back to\n * `\"sp\"` with a warning).\n */\n skillCredentialMode?: \"sp\" | \"obo\";\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 /api/agents/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 | {\n /**\n * Adapter-side hosted tool (executed by the model-host, not by the\n * Node process). Today: Supervisor API hosted tools (Genie spaces,\n * UC functions, etc.). The `spec` is opaque to the agents plugin —\n * it routes the entry into `AgentInput.extensions` for the adapter\n * that declared the matching `acceptsExtensions` key. `def` is a\n * synthetic placeholder kept so the index has a uniform shape; it\n * is intentionally NOT included in the `tools` array passed to\n * `adapter.run()` (those entries are not callable functions).\n */\n source: \"hosted-supervisor\";\n spec: import(\"../../agents/supervisor-api\").SupervisorTool;\n def: AgentToolDefinition;\n }\n | {\n /**\n * Built-in skill tools (`load_skill`, `read_skill_file`) injected into\n * any agent that has a visible skill catalog. Executed in-process by the\n * agents plugin against the agent's resolved catalog; read-only, so they\n * bypass the approval gate.\n */\n source: \"skill\";\n builtin: \"load_skill\" | \"read_skill_file\";\n catalog: ResolvedSkillCatalog;\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.generationParams`. */\n generationParams?: GenerationParams;\n /** Mirrors `AgentDefinition.ephemeral` — skip thread persistence. */\n ephemeral?: boolean;\n /** Effective identity: the agent's `auth`, else the plugin default. */\n auth?: AgentAuth;\n /**\n * Resolved per-agent skill catalog (visibility + collision rules applied).\n * Present when any skill is visible to this agent; drives the always-on\n * prompt catalog and `load_skill` dispatch.\n */\n skills?: ResolvedSkillCatalog;\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+aA,SAAgB,eAAe,OAAuC;AACpE,QACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB"}
|
package/dist/core/appkit.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { PluginConstructor, PluginData
|
|
1
|
+
import { AppKitApi, PluginConstructor, PluginData } from "../shared/src/plugin.js";
|
|
2
2
|
import { CacheConfig } from "../shared/src/cache.js";
|
|
3
3
|
import "../shared/src/index.js";
|
|
4
4
|
import { WorkspaceClient } from "../workspace-client/index.js";
|
|
5
5
|
import { TelemetryConfig } from "../telemetry/types.js";
|
|
6
6
|
import "../telemetry/index.js";
|
|
7
|
+
import "express";
|
|
7
8
|
|
|
8
9
|
//#region src/core/appkit.d.ts
|
|
9
10
|
/**
|
|
@@ -47,9 +48,9 @@ declare function createApp<T extends PluginData<PluginConstructor, unknown, stri
|
|
|
47
48
|
telemetry?: TelemetryConfig;
|
|
48
49
|
cache?: CacheConfig;
|
|
49
50
|
client?: WorkspaceClient; /** Runs after plugin setup but **before** the server starts. */
|
|
50
|
-
onPluginsReady?: (appkit:
|
|
51
|
+
onPluginsReady?: (appkit: AppKitApi<T>) => void | Promise<void>;
|
|
51
52
|
disableInternalTelemetry?: boolean;
|
|
52
|
-
}): Promise<
|
|
53
|
+
}): Promise<AppKitApi<T>>;
|
|
53
54
|
//#endregion
|
|
54
55
|
export { createApp };
|
|
55
56
|
//# sourceMappingURL=appkit.d.ts.map
|
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4dsB,SAAA,WACV,UAAA,CAAW,iBAAA,qBAAA,CAErB,MAAA;EACE,OAAA,GAAU,CAAA;EACV,SAAA,GAAY,eAAA;EACZ,KAAA,GAAQ,WAAA;EACR,MAAA,GAAS,eAAA;EAET,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,14 +2,17 @@ import { version } from "../appkit/package.js";
|
|
|
2
2
|
import { getConfiguredWarehouseId } from "../resources/warehouse.js";
|
|
3
3
|
import { createLogger } from "../logging/logger.js";
|
|
4
4
|
import { ServiceContext } from "../context/service-context.js";
|
|
5
|
+
import { isPlainObject } from "../utils/is-plain-object.js";
|
|
6
|
+
import { scopeApi } from "../context/scoped-api.js";
|
|
7
|
+
import { assertPluginExecution, getPluginResourceTypes, guardPluginApi } from "../context/resource-capabilities.js";
|
|
5
8
|
import { TelemetryManager } from "../telemetry/telemetry-manager.js";
|
|
6
9
|
import "../telemetry/index.js";
|
|
7
10
|
import { CacheManager } from "../cache/index.js";
|
|
8
11
|
import "../context/index.js";
|
|
12
|
+
import { createRequestScope } from "../context/request-scope.js";
|
|
9
13
|
import { isInternalTelemetryEnabled } from "../internal-telemetry/config.js";
|
|
10
14
|
import { TelemetryReporter } from "../internal-telemetry/reporter.js";
|
|
11
15
|
import "../internal-telemetry/index.js";
|
|
12
|
-
import { isPlainObject } from "../plugin/plugin.js";
|
|
13
16
|
import { ResourceType } from "../registry/types.generated.js";
|
|
14
17
|
import { ResourceRegistry } from "../registry/resource-registry.js";
|
|
15
18
|
import "../registry/index.js";
|
|
@@ -32,6 +35,24 @@ var AppKit = class AppKit {
|
|
|
32
35
|
#context;
|
|
33
36
|
/** Owns the shutdown sequence; assigned once every plugin has started. */
|
|
34
37
|
#lifecycle;
|
|
38
|
+
/** Execute a block or a single plugin call as the requesting user. */
|
|
39
|
+
asUser(req) {
|
|
40
|
+
const scope = createRequestScope(req, Object.values(this.#pluginInstances).flatMap(getPluginResourceTypes));
|
|
41
|
+
const kit = Object.create(null);
|
|
42
|
+
const scopedExports = /* @__PURE__ */ new Map();
|
|
43
|
+
for (const [name, plugin] of Object.entries(this.#pluginInstances)) Object.defineProperty(kit, name, {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: () => {
|
|
46
|
+
if (!scopedExports.has(name)) scopedExports.set(name, scopeApi(scope.run(() => {
|
|
47
|
+
assertPluginExecution(plugin, true);
|
|
48
|
+
return plugin.exports?.() ?? {};
|
|
49
|
+
}), scope, plugin));
|
|
50
|
+
return scopedExports.get(name);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
Object.defineProperty(kit, "run", { value: async (fn) => scope.run(() => fn(kit)) });
|
|
54
|
+
return Object.freeze(kit);
|
|
55
|
+
}
|
|
35
56
|
constructor(config) {
|
|
36
57
|
const { plugins, ...globalConfig } = config;
|
|
37
58
|
this.#context = new PluginContext();
|
|
@@ -46,6 +67,7 @@ var AppKit = class AppKit {
|
|
|
46
67
|
for (const [name, pluginData] of deferredPlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData, { context: this.#context });
|
|
47
68
|
}
|
|
48
69
|
createAndRegisterPlugin(config, name, pluginData, extraData) {
|
|
70
|
+
if (name === "run" || /^as[A-Z]/.test(name)) throw new Error(`Plugin name "${name}" is reserved for execution scoping`);
|
|
49
71
|
const { plugin: Plugin, config: pluginConfig } = pluginData;
|
|
50
72
|
const baseConfig = {
|
|
51
73
|
...config,
|
|
@@ -92,21 +114,20 @@ var AppKit = class AppKit {
|
|
|
92
114
|
* since the plugin manages its own `asUser` per-call (e.g. files plugin).
|
|
93
115
|
* When it returns a plain object, the standard `asUser` wrapper is added.
|
|
94
116
|
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* run inside the user's AsyncLocalStorage scope. AppKit only adapts the
|
|
98
|
-
* shape; it does not own the user-context concept.
|
|
117
|
+
* This preserves the deprecated per-plugin API. Both entry points delegate
|
|
118
|
+
* to the shared request scope; new code should use the app-level API.
|
|
99
119
|
*/
|
|
100
120
|
wrapWithAsUser(plugin) {
|
|
121
|
+
assertPluginExecution(plugin);
|
|
101
122
|
const pluginExports = plugin.exports?.() ?? {};
|
|
102
|
-
if (typeof pluginExports === "function") return pluginExports;
|
|
123
|
+
if (typeof pluginExports === "function") return guardPluginApi(plugin, pluginExports);
|
|
103
124
|
const objExports = pluginExports;
|
|
104
125
|
this.bindExportMethods(objExports, plugin);
|
|
105
|
-
if (typeof plugin.asUser !== "function") return objExports;
|
|
106
|
-
return {
|
|
126
|
+
if (typeof plugin.asUser !== "function") return guardPluginApi(plugin, objExports);
|
|
127
|
+
return guardPluginApi(plugin, {
|
|
107
128
|
...objExports,
|
|
108
129
|
asUser: (req) => plugin.asUser(req).exports()
|
|
109
|
-
};
|
|
130
|
+
});
|
|
110
131
|
}
|
|
111
132
|
static async _createApp(config = {}) {
|
|
112
133
|
TelemetryManager.initialize(config?.telemetry);
|