@databricks/appkit 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +53 -1
- package/NOTICE.md +1 -0
- package/dist/agents/databricks.d.ts.map +1 -1
- package/dist/agents/databricks.js +8 -3
- package/dist/agents/databricks.js.map +1 -1
- package/dist/appkit/package.js +1 -1
- package/dist/beta.d.ts +5 -3
- package/dist/beta.js +3 -1
- package/dist/connectors/mcp/client.d.ts +27 -2
- package/dist/connectors/mcp/client.d.ts.map +1 -1
- package/dist/connectors/mcp/client.js +117 -18
- package/dist/connectors/mcp/client.js.map +1 -1
- package/dist/connectors/mcp/index.d.ts +1 -1
- package/dist/connectors/mcp/types.d.ts +1 -1
- package/dist/core/agent/build-toolkit.js +3 -8
- package/dist/core/agent/build-toolkit.js.map +1 -1
- package/dist/core/agent/load-agents.d.ts +6 -1
- package/dist/core/agent/load-agents.d.ts.map +1 -1
- package/dist/core/agent/load-agents.js +67 -27
- package/dist/core/agent/load-agents.js.map +1 -1
- package/dist/core/agent/plugins-map.js +44 -0
- package/dist/core/agent/plugins-map.js.map +1 -0
- package/dist/core/agent/run-agent.d.ts +31 -7
- package/dist/core/agent/run-agent.d.ts.map +1 -1
- package/dist/core/agent/run-agent.js +138 -27
- package/dist/core/agent/run-agent.js.map +1 -1
- package/dist/core/agent/toolkit-options.js +28 -0
- package/dist/core/agent/toolkit-options.js.map +1 -0
- package/dist/core/agent/toolkit-resolver.js +44 -0
- package/dist/core/agent/toolkit-resolver.js.map +1 -0
- package/dist/core/agent/tools/define-tool.d.ts +14 -2
- package/dist/core/agent/tools/define-tool.d.ts.map +1 -1
- package/dist/core/agent/tools/define-tool.js +1 -1
- package/dist/core/agent/tools/define-tool.js.map +1 -1
- package/dist/core/agent/tools/function-tool.d.ts +13 -2
- package/dist/core/agent/tools/function-tool.d.ts.map +1 -1
- package/dist/core/agent/tools/function-tool.js +4 -3
- package/dist/core/agent/tools/function-tool.js.map +1 -1
- package/dist/core/agent/tools/index.d.ts +1 -1
- package/dist/core/agent/tools/tool.d.ts +32 -3
- package/dist/core/agent/tools/tool.d.ts.map +1 -1
- package/dist/core/agent/tools/tool.js +4 -3
- package/dist/core/agent/tools/tool.js.map +1 -1
- package/dist/core/agent/types.d.ts +95 -10
- package/dist/core/agent/types.d.ts.map +1 -1
- package/dist/core/agent/types.js.map +1 -1
- package/dist/plugin/index.d.ts +1 -1
- package/dist/plugin/to-plugin.d.ts +3 -13
- package/dist/plugin/to-plugin.d.ts.map +1 -1
- package/dist/plugin/to-plugin.js +1 -8
- package/dist/plugin/to-plugin.js.map +1 -1
- package/dist/plugins/agents/agents.d.ts +184 -2
- package/dist/plugins/agents/agents.d.ts.map +1 -0
- package/dist/plugins/agents/agents.js +169 -72
- package/dist/plugins/agents/agents.js.map +1 -1
- package/dist/plugins/agents/index.d.ts +2 -2
- package/dist/plugins/agents/index.js +1 -1
- package/dist/plugins/agents/manifest.js +4 -5
- package/dist/plugins/agents/tool-approval-gate.js.map +1 -1
- package/dist/plugins/analytics/analytics.d.ts +3 -4
- package/dist/plugins/analytics/analytics.d.ts.map +1 -1
- package/dist/plugins/analytics/analytics.js +8 -6
- package/dist/plugins/analytics/analytics.js.map +1 -1
- package/dist/plugins/analytics/index.js +1 -0
- package/dist/plugins/analytics/types.js +15 -0
- package/dist/plugins/analytics/types.js.map +1 -0
- package/dist/plugins/beta-exports.generated.d.ts +2 -0
- package/dist/plugins/beta-exports.generated.js +4 -0
- package/dist/plugins/files/plugin.d.ts +1 -2
- package/dist/plugins/files/plugin.d.ts.map +1 -1
- package/dist/plugins/files/plugin.js +30 -12
- package/dist/plugins/files/plugin.js.map +1 -1
- package/dist/plugins/genie/genie.d.ts +5 -4
- package/dist/plugins/genie/genie.d.ts.map +1 -1
- package/dist/plugins/genie/genie.js +22 -8
- package/dist/plugins/genie/genie.js.map +1 -1
- package/dist/plugins/genie/types.d.ts +10 -2
- package/dist/plugins/genie/types.d.ts.map +1 -1
- package/dist/plugins/jobs/plugin.d.ts +1 -2
- package/dist/plugins/jobs/plugin.d.ts.map +1 -1
- package/dist/plugins/lakebase/lakebase.d.ts +1 -2
- package/dist/plugins/lakebase/lakebase.d.ts.map +1 -1
- package/dist/plugins/lakebase/lakebase.js +3 -3
- package/dist/plugins/lakebase/lakebase.js.map +1 -1
- package/dist/plugins/lakebase/types.d.ts +5 -4
- package/dist/plugins/lakebase/types.d.ts.map +1 -1
- package/dist/plugins/server/index.d.ts +3 -2
- package/dist/plugins/server/index.d.ts.map +1 -1
- package/dist/plugins/server/index.js +8 -5
- package/dist/plugins/server/index.js.map +1 -1
- package/dist/plugins/server/types.d.ts +11 -0
- package/dist/plugins/server/types.d.ts.map +1 -1
- package/dist/plugins/serving/serving.d.ts +1 -2
- package/dist/plugins/serving/serving.d.ts.map +1 -1
- package/dist/shared/src/agent.d.ts +16 -4
- package/dist/shared/src/agent.d.ts.map +1 -1
- package/docs/api/appkit/Class.AppKitMcpClient.md +157 -0
- package/docs/api/appkit/Class.DatabricksAdapter.md +151 -0
- package/docs/api/appkit/Function.agentIdFromMarkdownPath.md +18 -0
- package/docs/api/appkit/Function.createAgent.md +33 -0
- package/docs/api/appkit/Function.defineTool.md +26 -0
- package/docs/api/appkit/Function.executeFromRegistry.md +25 -0
- package/docs/api/appkit/Function.functionToolToDefinition.md +16 -0
- package/docs/api/appkit/Function.isFunctionTool.md +16 -0
- package/docs/api/appkit/Function.isHostedTool.md +16 -0
- package/docs/api/appkit/Function.isToolkitEntry.md +18 -0
- package/docs/api/appkit/Function.loadAgentFromFile.md +21 -0
- package/docs/api/appkit/Function.loadAgentsFromDir.md +26 -0
- package/docs/api/appkit/Function.mcpServer.md +28 -0
- package/docs/api/appkit/Function.parseTextToolCalls.md +26 -0
- package/docs/api/appkit/Function.resolveHostedTools.md +16 -0
- package/docs/api/appkit/Function.runAgent.md +26 -0
- package/docs/api/appkit/Function.tool.md +28 -0
- package/docs/api/appkit/Function.toolsFromRegistry.md +20 -0
- package/docs/api/appkit/Interface.AgentAdapter.md +21 -0
- package/docs/api/appkit/Interface.AgentDefinition.md +112 -0
- package/docs/api/appkit/Interface.AgentInput.md +37 -0
- package/docs/api/appkit/Interface.AgentRunContext.md +32 -0
- package/docs/api/appkit/Interface.AgentToolDefinition.md +37 -0
- package/docs/api/appkit/Interface.AgentsPluginConfig.md +241 -0
- package/docs/api/appkit/Interface.AutoInheritToolsConfig.md +27 -0
- package/docs/api/appkit/Interface.BasePluginConfig.md +1 -0
- package/docs/api/appkit/Interface.FunctionTool.md +80 -0
- package/docs/api/appkit/Interface.McpConnectAllResult.md +38 -0
- package/docs/api/appkit/Interface.Message.md +55 -0
- package/docs/api/appkit/Interface.PluginToolkitProvider.md +22 -0
- package/docs/api/appkit/Interface.PromptContext.md +30 -0
- package/docs/api/appkit/Interface.RegisteredAgent.md +75 -0
- package/docs/api/appkit/Interface.RunAgentInput.md +34 -0
- package/docs/api/appkit/Interface.RunAgentResult.md +23 -0
- package/docs/api/appkit/Interface.Thread.md +46 -0
- package/docs/api/appkit/Interface.ThreadStore.md +103 -0
- package/docs/api/appkit/Interface.ToolAnnotations.md +56 -0
- package/docs/api/appkit/Interface.ToolConfig.md +72 -0
- package/docs/api/appkit/Interface.ToolEntry.md +73 -0
- package/docs/api/appkit/Interface.ToolProvider.md +38 -0
- package/docs/api/appkit/Interface.ToolkitEntry.md +59 -0
- package/docs/api/appkit/Interface.ToolkitOptions.md +45 -0
- package/docs/api/appkit/TypeAlias.AgentEvent.md +299 -0
- package/docs/api/appkit/TypeAlias.AgentTool.md +11 -0
- package/docs/api/appkit/TypeAlias.AgentTools.md +8 -0
- package/docs/api/appkit/TypeAlias.AgentToolsFn.md +20 -0
- package/docs/api/appkit/TypeAlias.BaseSystemPromptOption.md +9 -0
- package/docs/api/appkit/TypeAlias.HostedTool.md +10 -0
- package/docs/api/appkit/TypeAlias.Plugins.md +26 -0
- package/docs/api/appkit/TypeAlias.ResolvedToolEntry.md +29 -0
- package/docs/api/appkit/TypeAlias.ToolRegistry.md +6 -0
- package/docs/api/appkit/Variable.agents.md +19 -0
- package/docs/api/appkit.md +113 -62
- package/docs/plugins/agents.md +441 -0
- package/llms.txt +53 -1
- package/package.json +1 -1
- package/sbom.cdx.json +1 -1
|
@@ -6,6 +6,8 @@ import { buildMcpHostPolicy } from "../../connectors/mcp/host-policy.js";
|
|
|
6
6
|
import { AppKitMcpClient } from "../../connectors/mcp/client.js";
|
|
7
7
|
import "../../connectors/mcp/index.js";
|
|
8
8
|
import { consumeAdapterStream } from "../../core/agent/consume-adapter-stream.js";
|
|
9
|
+
import { createPluginsProxy } from "../../core/agent/plugins-map.js";
|
|
10
|
+
import { resolveToolkitFromProvider } from "../../core/agent/toolkit-resolver.js";
|
|
9
11
|
import { functionToolToDefinition, isFunctionTool } from "../../core/agent/tools/function-tool.js";
|
|
10
12
|
import { isHostedTool, resolveHostedTools } from "../../core/agent/tools/hosted-tools.js";
|
|
11
13
|
import { isToolkitEntry } from "../../core/agent/types.js";
|
|
@@ -56,6 +58,13 @@ var AgentsPlugin = class extends Plugin {
|
|
|
56
58
|
agents = /* @__PURE__ */ new Map();
|
|
57
59
|
defaultAgentName = null;
|
|
58
60
|
activeStreams = /* @__PURE__ */ new Map();
|
|
61
|
+
/**
|
|
62
|
+
* Per-user stream count, kept in sync with `activeStreams` so the
|
|
63
|
+
* concurrent-stream rate limit check is O(1) instead of O(n) over every
|
|
64
|
+
* active stream on every request. Mutated only via {@link trackStream}
|
|
65
|
+
* and {@link untrackStream}.
|
|
66
|
+
*/
|
|
67
|
+
userStreamCounts = /* @__PURE__ */ new Map();
|
|
59
68
|
mcpClient = null;
|
|
60
69
|
threadStore;
|
|
61
70
|
approvalGate = new ToolApprovalGate();
|
|
@@ -69,13 +78,32 @@ var AgentsPlugin = class extends Plugin {
|
|
|
69
78
|
else logger.info("Using default InMemoryThreadStore (dev-only — threads are lost on restart and grow without bound).");
|
|
70
79
|
}
|
|
71
80
|
}
|
|
72
|
-
/**
|
|
81
|
+
/**
|
|
82
|
+
* Effective approval policy with defaults applied. Memoised so the
|
|
83
|
+
* `timeoutMs` validation warning fires at most once per plugin instance —
|
|
84
|
+
* `resolvedApprovalPolicy` gets hit on every chat stream and a noisy
|
|
85
|
+
* misconfig would otherwise spam the logs.
|
|
86
|
+
*
|
|
87
|
+
* `timeoutMs` is clamped to a 1s floor so a misconfigured value (`0`,
|
|
88
|
+
* negative, or `NaN`) can't degrade into immediate auto-denial of every
|
|
89
|
+
* mutating tool call.
|
|
90
|
+
*/
|
|
91
|
+
cachedApprovalPolicy = null;
|
|
73
92
|
get resolvedApprovalPolicy() {
|
|
93
|
+
if (this.cachedApprovalPolicy) return this.cachedApprovalPolicy;
|
|
74
94
|
const cfg = this.config.approval ?? {};
|
|
75
|
-
|
|
95
|
+
const APPROVAL_TIMEOUT_FLOOR_MS = 1e3;
|
|
96
|
+
const APPROVAL_TIMEOUT_DEFAULT_MS = 6e4;
|
|
97
|
+
let timeoutMs = cfg.timeoutMs ?? APPROVAL_TIMEOUT_DEFAULT_MS;
|
|
98
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < APPROVAL_TIMEOUT_FLOOR_MS) {
|
|
99
|
+
logger.warn("approval.timeoutMs=%s is below the %sms floor; using default %sms instead. Mutating tool calls would otherwise auto-deny before any UI could respond.", cfg.timeoutMs, APPROVAL_TIMEOUT_FLOOR_MS, APPROVAL_TIMEOUT_DEFAULT_MS);
|
|
100
|
+
timeoutMs = APPROVAL_TIMEOUT_DEFAULT_MS;
|
|
101
|
+
}
|
|
102
|
+
this.cachedApprovalPolicy = {
|
|
76
103
|
requireForDestructive: cfg.requireForDestructive ?? true,
|
|
77
|
-
timeoutMs
|
|
104
|
+
timeoutMs
|
|
78
105
|
};
|
|
106
|
+
return this.cachedApprovalPolicy;
|
|
79
107
|
}
|
|
80
108
|
/** Effective DoS limits with defaults applied. */
|
|
81
109
|
get resolvedLimits() {
|
|
@@ -87,11 +115,35 @@ var AgentsPlugin = class extends Plugin {
|
|
|
87
115
|
toolCallTimeoutMs: cfg.toolCallTimeoutMs ?? 3e5
|
|
88
116
|
};
|
|
89
117
|
}
|
|
90
|
-
/** Count active streams owned by a given user. */
|
|
118
|
+
/** Count active streams owned by a given user. O(1). */
|
|
91
119
|
countUserStreams(userId) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
120
|
+
return this.userStreamCounts.get(userId) ?? 0;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Register a stream for `userId` and bump the per-user counter. Paired
|
|
124
|
+
* with {@link untrackStream}; the two helpers are the only writers to
|
|
125
|
+
* `activeStreams` + `userStreamCounts`, so the counter cannot drift from
|
|
126
|
+
* the map.
|
|
127
|
+
*/
|
|
128
|
+
trackStream(requestId, userId, controller) {
|
|
129
|
+
this.activeStreams.set(requestId, {
|
|
130
|
+
controller,
|
|
131
|
+
userId
|
|
132
|
+
});
|
|
133
|
+
this.userStreamCounts.set(userId, (this.userStreamCounts.get(userId) ?? 0) + 1);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Remove a stream from the active map and decrement the per-user
|
|
137
|
+
* counter. Idempotent — calling twice for the same `requestId` is a
|
|
138
|
+
* no-op (the second call sees no entry and returns early).
|
|
139
|
+
*/
|
|
140
|
+
untrackStream(requestId) {
|
|
141
|
+
const entry = this.activeStreams.get(requestId);
|
|
142
|
+
if (!entry) return;
|
|
143
|
+
this.activeStreams.delete(requestId);
|
|
144
|
+
const next = (this.userStreamCounts.get(entry.userId) ?? 0) - 1;
|
|
145
|
+
if (next <= 0) this.userStreamCounts.delete(entry.userId);
|
|
146
|
+
else this.userStreamCounts.set(entry.userId, next);
|
|
95
147
|
}
|
|
96
148
|
async setup() {
|
|
97
149
|
const { agents, defaultAgentName } = await this.buildAgentRegistry();
|
|
@@ -108,10 +160,6 @@ var AgentsPlugin = class extends Plugin {
|
|
|
108
160
|
*/
|
|
109
161
|
async reload() {
|
|
110
162
|
const next = await this.buildAgentRegistry();
|
|
111
|
-
if (this.mcpClient) {
|
|
112
|
-
await this.mcpClient.close();
|
|
113
|
-
this.mcpClient = null;
|
|
114
|
-
}
|
|
115
163
|
this.agents = next.agents;
|
|
116
164
|
this.defaultAgentName = next.defaultAgentName;
|
|
117
165
|
}
|
|
@@ -180,7 +228,9 @@ var AgentsPlugin = class extends Plugin {
|
|
|
180
228
|
}
|
|
181
229
|
/**
|
|
182
230
|
* Builds the map of plugin-name → toolkit that the markdown loader consults
|
|
183
|
-
* when resolving `
|
|
231
|
+
* when resolving `plugin:NAME` entries in the unified `tools:` frontmatter
|
|
232
|
+
* list (and, equivalently, that the code form passes as the `plugins`
|
|
233
|
+
* argument to `tools(plugins) => Record<...>`).
|
|
184
234
|
*/
|
|
185
235
|
pluginProviderIndex() {
|
|
186
236
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -215,7 +265,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
215
265
|
try {
|
|
216
266
|
return await DatabricksAdapter.fromModelServing(void 0, adapterOptions);
|
|
217
267
|
} catch (err) {
|
|
218
|
-
throw new Error(`Agent '${name}' has no model configured and no
|
|
268
|
+
throw new Error(`Agent '${name}' has no model configured and no DATABRICKS_SERVING_ENDPOINT_NAME default available`, { cause: err instanceof Error ? err : void 0 });
|
|
219
269
|
}
|
|
220
270
|
}
|
|
221
271
|
if (typeof source === "string") {
|
|
@@ -231,10 +281,11 @@ var AgentsPlugin = class extends Plugin {
|
|
|
231
281
|
*/
|
|
232
282
|
async buildToolIndex(agentName, def, src) {
|
|
233
283
|
const index = /* @__PURE__ */ new Map();
|
|
234
|
-
const
|
|
284
|
+
const hasDeclaredTools = def.tools !== void 0;
|
|
285
|
+
const toolsRecord = this.resolveDefTools(agentName, def);
|
|
235
286
|
const hasExplicitSubAgents = def.agents && Object.keys(def.agents).length > 0;
|
|
236
287
|
const inheritDefaults = normalizeAutoInherit(this.config.autoInheritTools);
|
|
237
|
-
if (!
|
|
288
|
+
if (!hasDeclaredTools && !hasExplicitSubAgents && (src.origin === "file" ? inheritDefaults.file : inheritDefaults.code)) await this.applyAutoInherit(agentName, index);
|
|
238
289
|
for (const [childKey, childDef] of Object.entries(def.agents ?? {})) {
|
|
239
290
|
const toolName = `agent-${childKey}`;
|
|
240
291
|
index.set(toolName, {
|
|
@@ -255,7 +306,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
255
306
|
});
|
|
256
307
|
}
|
|
257
308
|
const hostedToCollect = [];
|
|
258
|
-
for (const [key, tool] of Object.entries(
|
|
309
|
+
for (const [key, tool] of Object.entries(toolsRecord)) {
|
|
259
310
|
if (isToolkitEntry(tool)) {
|
|
260
311
|
index.set(key, {
|
|
261
312
|
source: "toolkit",
|
|
@@ -288,6 +339,44 @@ var AgentsPlugin = class extends Plugin {
|
|
|
288
339
|
if (hostedToCollect.length > 0) await this.connectHostedTools(hostedToCollect, index);
|
|
289
340
|
return index;
|
|
290
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* Resolves an `AgentDefinition.tools` field to a plain tool record. The
|
|
344
|
+
* function form is invoked exactly once at agent setup with the typed
|
|
345
|
+
* {@link Plugins} map; the result replaces the function reference for the
|
|
346
|
+
* remainder of the registered agent's lifetime.
|
|
347
|
+
*
|
|
348
|
+
* Plain object form is returned as-is; an undefined `tools` returns an
|
|
349
|
+
* empty record. The function form is wrapped in a try/catch so a thrown
|
|
350
|
+
* callback fails registration with a useful message instead of leaking
|
|
351
|
+
* the raw stack.
|
|
352
|
+
*/
|
|
353
|
+
resolveDefTools(agentName, def) {
|
|
354
|
+
if (typeof def.tools !== "function") return def.tools ?? {};
|
|
355
|
+
try {
|
|
356
|
+
return def.tools(this.buildPluginsMap());
|
|
357
|
+
} catch (err) {
|
|
358
|
+
throw new Error(`Agent '${agentName}': tools(plugins) callback threw: ${err instanceof Error ? err.message : String(err)}`, { cause: err instanceof Error ? err : void 0 });
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Builds the typed {@link Plugins} map passed to the function form of
|
|
363
|
+
* `AgentDefinition.tools`. Each entry exposes the plugin instance directly
|
|
364
|
+
* (so user code can call typed instance methods including `.toolkit()`);
|
|
365
|
+
* plugins missing `.toolkit()` get a synthesized fallback that walks
|
|
366
|
+
* `getAgentTools()` via `resolveToolkitFromProvider`.
|
|
367
|
+
*
|
|
368
|
+
* Wrapped in {@link createPluginsProxy} so that accessing an unknown
|
|
369
|
+
* plugin name throws a named "not registered, Available: ..." error
|
|
370
|
+
* instead of bubbling up a generic `Cannot read properties of undefined`
|
|
371
|
+
* from the agent's `tools(plugins)` callback.
|
|
372
|
+
*/
|
|
373
|
+
buildPluginsMap() {
|
|
374
|
+
const out = {};
|
|
375
|
+
if (!this.context) return createPluginsProxy(out, `Agent '${this.name}': tools(plugins)`);
|
|
376
|
+
for (const { name, provider } of this.context.getToolProviders()) if (typeof provider.toolkit === "function") out[name] = provider;
|
|
377
|
+
else out[name] = { toolkit: (opts) => resolveToolkitFromProvider(name, provider, opts) };
|
|
378
|
+
return createPluginsProxy(out, `Agent '${this.name}': tools(plugins)`);
|
|
379
|
+
}
|
|
291
380
|
async applyAutoInherit(agentName, index) {
|
|
292
381
|
if (!this.context) return;
|
|
293
382
|
const inherited = [];
|
|
@@ -299,29 +388,23 @@ var AgentsPlugin = class extends Plugin {
|
|
|
299
388
|
};
|
|
300
389
|
for (const { name: pluginName, provider } of this.context.getToolProviders()) {
|
|
301
390
|
if (pluginName === this.name) continue;
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (maybeEntry.autoInheritable !== true) {
|
|
308
|
-
recordSkip(maybeEntry.pluginName, maybeEntry.localName);
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
index.set(key, {
|
|
312
|
-
source: "toolkit",
|
|
313
|
-
pluginName: maybeEntry.pluginName,
|
|
314
|
-
localName: maybeEntry.localName,
|
|
315
|
-
def: {
|
|
316
|
-
...maybeEntry.def,
|
|
317
|
-
name: key
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
inherited.push(key);
|
|
391
|
+
const entries = resolveToolkitFromProvider(pluginName, provider);
|
|
392
|
+
for (const [key, entry] of Object.entries(entries)) {
|
|
393
|
+
if (entry.autoInheritable !== true) {
|
|
394
|
+
recordSkip(entry.pluginName, entry.localName);
|
|
395
|
+
continue;
|
|
321
396
|
}
|
|
322
|
-
|
|
397
|
+
index.set(key, {
|
|
398
|
+
source: "toolkit",
|
|
399
|
+
pluginName: entry.pluginName,
|
|
400
|
+
localName: entry.localName,
|
|
401
|
+
def: {
|
|
402
|
+
...entry.def,
|
|
403
|
+
name: key
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
inherited.push(key);
|
|
323
407
|
}
|
|
324
|
-
for (const tool of provider.getAgentTools()) recordSkip(pluginName, tool.name);
|
|
325
408
|
}
|
|
326
409
|
if (inherited.length > 0) logger.info("[agent %s] auto-inherited %d tool(s): %s", agentName, inherited.length, inherited.join(", "));
|
|
327
410
|
if (skippedByPlugin.size > 0) {
|
|
@@ -358,7 +441,8 @@ var AgentsPlugin = class extends Plugin {
|
|
|
358
441
|
this.mcpClient = new AppKitMcpClient(host, authenticate, policy);
|
|
359
442
|
}
|
|
360
443
|
const endpoints = resolveHostedTools(hostedTools);
|
|
361
|
-
await this.mcpClient.connectAll(endpoints);
|
|
444
|
+
const result = await this.mcpClient.connectAll(endpoints);
|
|
445
|
+
if (result.failed.length > 0) logger.warn("MCP: %s of %s endpoints failed to connect (%s). Agents that reference these endpoints will boot without their hosted tools.", result.failed.length, endpoints.length, result.failed.map((f) => f.name).join(", "));
|
|
362
446
|
for (const def of this.mcpClient.getAllToolDefinitions()) index.set(def.name, {
|
|
363
447
|
source: "mcp",
|
|
364
448
|
mcpToolName: def.name,
|
|
@@ -454,19 +538,26 @@ var AgentsPlugin = class extends Plugin {
|
|
|
454
538
|
res.status(429).json({ error: `Too many concurrent streams for this user (limit ${limits.maxConcurrentStreamsPerUser}). Wait for an existing stream to complete before starting another.` });
|
|
455
539
|
return;
|
|
456
540
|
}
|
|
457
|
-
let thread
|
|
458
|
-
|
|
459
|
-
|
|
541
|
+
let thread;
|
|
542
|
+
try {
|
|
543
|
+
const existing = threadId ? await this.threadStore.get(threadId, userId) : null;
|
|
544
|
+
if (threadId && !existing) {
|
|
545
|
+
res.status(404).json({ error: `Thread ${threadId} not found` });
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
thread = existing ?? await this.threadStore.create(userId);
|
|
549
|
+
const userMessage = {
|
|
550
|
+
id: randomUUID(),
|
|
551
|
+
role: "user",
|
|
552
|
+
content: message,
|
|
553
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
554
|
+
};
|
|
555
|
+
await this.threadStore.addMessage(thread.id, userId, userMessage);
|
|
556
|
+
} catch (err) {
|
|
557
|
+
logger.error("threadStore failed in /chat: %O", err);
|
|
558
|
+
res.status(500).json({ error: "Thread operation failed" });
|
|
460
559
|
return;
|
|
461
560
|
}
|
|
462
|
-
if (!thread) thread = await this.threadStore.create(userId);
|
|
463
|
-
const userMessage = {
|
|
464
|
-
id: randomUUID(),
|
|
465
|
-
role: "user",
|
|
466
|
-
content: message,
|
|
467
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
468
|
-
};
|
|
469
|
-
await this.threadStore.addMessage(thread.id, userId, userMessage);
|
|
470
561
|
return this._streamAgent(req, res, registered, thread, userId);
|
|
471
562
|
}
|
|
472
563
|
async _handleInvocations(req, res) {
|
|
@@ -491,23 +582,30 @@ var AgentsPlugin = class extends Plugin {
|
|
|
491
582
|
res.status(429).json({ error: `Too many concurrent streams for this user (limit ${limits.maxConcurrentStreamsPerUser}). Wait for an existing stream to complete before starting another.` });
|
|
492
583
|
return;
|
|
493
584
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
content: input,
|
|
499
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
500
|
-
});
|
|
501
|
-
else for (const item of input) {
|
|
502
|
-
const role = item.role ?? "user";
|
|
503
|
-
const content = typeof item.content === "string" ? item.content : JSON.stringify(item.content ?? "");
|
|
504
|
-
if (!content) continue;
|
|
505
|
-
await this.threadStore.addMessage(thread.id, userId, {
|
|
585
|
+
let thread;
|
|
586
|
+
try {
|
|
587
|
+
thread = await this.threadStore.create(userId);
|
|
588
|
+
if (typeof input === "string") await this.threadStore.addMessage(thread.id, userId, {
|
|
506
589
|
id: randomUUID(),
|
|
507
|
-
role,
|
|
508
|
-
content,
|
|
590
|
+
role: "user",
|
|
591
|
+
content: input,
|
|
509
592
|
createdAt: /* @__PURE__ */ new Date()
|
|
510
593
|
});
|
|
594
|
+
else for (const item of input) {
|
|
595
|
+
const role = item.role ?? "user";
|
|
596
|
+
const content = typeof item.content === "string" ? item.content : JSON.stringify(item.content ?? "");
|
|
597
|
+
if (!content) continue;
|
|
598
|
+
await this.threadStore.addMessage(thread.id, userId, {
|
|
599
|
+
id: randomUUID(),
|
|
600
|
+
role,
|
|
601
|
+
content,
|
|
602
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
} catch (err) {
|
|
606
|
+
logger.error("threadStore failed in /invocations: %O", err);
|
|
607
|
+
res.status(500).json({ error: "Thread operation failed" });
|
|
608
|
+
return;
|
|
511
609
|
}
|
|
512
610
|
return this._streamAgent(req, res, registered, thread, userId);
|
|
513
611
|
}
|
|
@@ -515,10 +613,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
515
613
|
const abortController = new AbortController();
|
|
516
614
|
const signal = abortController.signal;
|
|
517
615
|
const requestId = randomUUID();
|
|
518
|
-
this.
|
|
519
|
-
controller: abortController,
|
|
520
|
-
userId
|
|
521
|
-
});
|
|
616
|
+
this.trackStream(requestId, userId, abortController);
|
|
522
617
|
const tools = Array.from(registered.toolIndex.values()).map((e) => e.def);
|
|
523
618
|
const approvalPolicy = this.resolvedApprovalPolicy;
|
|
524
619
|
const limits = this.resolvedLimits;
|
|
@@ -585,7 +680,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
585
680
|
return;
|
|
586
681
|
} finally {
|
|
587
682
|
this.approvalGate.abortStream(requestId);
|
|
588
|
-
this.
|
|
683
|
+
this.untrackStream(requestId);
|
|
589
684
|
if (registered.ephemeral) try {
|
|
590
685
|
await this.threadStore.delete(thread.id, userId);
|
|
591
686
|
} catch (err) {
|
|
@@ -648,8 +743,10 @@ var AgentsPlugin = class extends Plugin {
|
|
|
648
743
|
if (entry.source === "toolkit") {
|
|
649
744
|
if (!this.context) throw new Error("Plugin tool execution requires PluginContext; this should never happen through createApp");
|
|
650
745
|
result = await this.context.executeTool(runState.req, entry.pluginName, entry.localName, args, runState.signal, runState.limits.toolCallTimeoutMs);
|
|
651
|
-
} else if (entry.source === "function")
|
|
652
|
-
|
|
746
|
+
} else if (entry.source === "function") {
|
|
747
|
+
if (typeof args !== "object" || args === null || Array.isArray(args)) throw new Error(`Function tool '${name}' received non-object arguments (got ${args === null ? "null" : Array.isArray(args) ? "array" : typeof args}); expected a JSON object.`);
|
|
748
|
+
result = await entry.functionTool.execute(args);
|
|
749
|
+
} else if (entry.source === "mcp") {
|
|
653
750
|
if (!this.mcpClient) throw new Error("MCP client not connected");
|
|
654
751
|
const oboToken = runState.req.headers["x-forwarded-access-token"];
|
|
655
752
|
const mcpAuth = typeof oboToken === "string" ? { Authorization: `Bearer ${oboToken}` } : void 0;
|
|
@@ -734,7 +831,7 @@ var AgentsPlugin = class extends Plugin {
|
|
|
734
831
|
return;
|
|
735
832
|
}
|
|
736
833
|
entry.controller.abort("Cancelled by user");
|
|
737
|
-
this.
|
|
834
|
+
this.untrackStream(streamId);
|
|
738
835
|
this.approvalGate.abortStream(streamId);
|
|
739
836
|
res.json({ cancelled: true });
|
|
740
837
|
}
|
|
@@ -878,5 +975,5 @@ function composePromptForAgent(registered, pluginLevel, ctx) {
|
|
|
878
975
|
const agents = toPlugin(AgentsPlugin);
|
|
879
976
|
|
|
880
977
|
//#endregion
|
|
881
|
-
export { AgentsPlugin };
|
|
978
|
+
export { AgentsPlugin, agents };
|
|
882
979
|
//# sourceMappingURL=agents.js.map
|