@distri/core 0.3.1 → 0.3.3

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/dist/index.js CHANGED
@@ -29,6 +29,7 @@ __export(index_exports, {
29
29
  DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
30
30
  DistriClient: () => DistriClient,
31
31
  DistriError: () => DistriError,
32
+ ExternalToolValidationError: () => ExternalToolValidationError,
32
33
  convertA2AMessageToDistri: () => convertA2AMessageToDistri,
33
34
  convertA2APartToDistri: () => convertA2APartToDistri,
34
35
  convertA2AStatusUpdateToDistri: () => convertA2AStatusUpdateToDistri,
@@ -729,6 +730,17 @@ function convertA2AStatusUpdateToDistri(statusUpdate) {
729
730
  };
730
731
  return hookRequested;
731
732
  }
733
+ case "browser_session_started": {
734
+ const browserSessionStarted = {
735
+ type: "browser_session_started",
736
+ data: {
737
+ session_id: metadata.session_id || "",
738
+ viewer_url: metadata.viewer_url,
739
+ stream_url: metadata.stream_url
740
+ }
741
+ };
742
+ return browserSessionStarted;
743
+ }
732
744
  default: {
733
745
  console.warn(`Unhandled status update metadata type: ${metadata.type}`, metadata);
734
746
  const defaultResult = {
@@ -807,6 +819,7 @@ function convertDistriMessageToA2A(distriMessage, context) {
807
819
  break;
808
820
  case "system":
809
821
  case "tool":
822
+ case "developer":
810
823
  role = "user";
811
824
  break;
812
825
  default:
@@ -903,26 +916,56 @@ var _DistriClient = class _DistriClient {
903
916
  constructor(config) {
904
917
  this.agentClients = /* @__PURE__ */ new Map();
905
918
  const headers = { ...config.headers };
919
+ if (config.workspaceId) {
920
+ headers["X-Workspace-Id"] = config.workspaceId;
921
+ }
906
922
  this.accessToken = config.accessToken;
907
923
  this.refreshToken = config.refreshToken;
908
924
  this.tokenRefreshSkewMs = config.tokenRefreshSkewMs ?? 6e4;
909
925
  this.onTokenRefresh = config.onTokenRefresh;
910
926
  this.config = {
911
- baseUrl: config.baseUrl.replace(/\/$/, ""),
927
+ baseUrl: config.baseUrl?.replace(/\/$/, "") || DEFAULT_BASE_URL,
912
928
  apiVersion: config.apiVersion || "v1",
913
- timeout: config.timeout || 3e4,
914
- retryAttempts: config.retryAttempts || 3,
915
- retryDelay: config.retryDelay || 1e3,
916
- debug: config.debug || false,
929
+ timeout: config.timeout ?? 3e4,
930
+ retryAttempts: config.retryAttempts ?? 3,
931
+ retryDelay: config.retryDelay ?? 1e3,
932
+ debug: config.debug ?? false,
917
933
  headers,
918
- interceptor: config.interceptor || ((init) => Promise.resolve(init))
934
+ interceptor: config.interceptor ?? (async (init) => Promise.resolve(init)),
935
+ onTokenRefresh: config.onTokenRefresh,
936
+ clientId: config.clientId,
937
+ workspaceId: config.workspaceId
919
938
  };
920
- this.debug("DistriClient initialized with config:", {
921
- baseUrl: this.config.baseUrl,
922
- hasAccessToken: !!this.accessToken,
923
- hasRefreshToken: !!this.refreshToken,
924
- timeout: this.config.timeout
925
- });
939
+ }
940
+ /**
941
+ * Get the configured client ID.
942
+ */
943
+ get clientId() {
944
+ return this.config.clientId;
945
+ }
946
+ /**
947
+ * Set the client ID for embed token issuance.
948
+ */
949
+ set clientId(value) {
950
+ this.config.clientId = value;
951
+ }
952
+ /**
953
+ * Get the configured workspace ID.
954
+ */
955
+ get workspaceId() {
956
+ return this.config.workspaceId;
957
+ }
958
+ /**
959
+ * Set the workspace ID for multi-tenant support.
960
+ * Updates the X-Workspace-Id header for all subsequent requests.
961
+ */
962
+ set workspaceId(value) {
963
+ this.config.workspaceId = value;
964
+ if (value) {
965
+ this.config.headers["X-Workspace-Id"] = value;
966
+ } else {
967
+ delete this.config.headers["X-Workspace-Id"];
968
+ }
926
969
  }
927
970
  /**
928
971
  * Create a client with default cloud configuration.
@@ -955,7 +998,7 @@ var _DistriClient = class _DistriClient {
955
998
  if (expiry) {
956
999
  body.expiry = typeof expiry === "string" ? expiry : expiry.toISOString();
957
1000
  }
958
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}/values`, {
1001
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}/values`, {
959
1002
  method: "POST",
960
1003
  headers: {
961
1004
  "Content-Type": "application/json",
@@ -972,7 +1015,7 @@ var _DistriClient = class _DistriClient {
972
1015
  * Session store: get a single value
973
1016
  */
974
1017
  async getSessionValue(sessionId, key) {
975
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}/values/${encodeURIComponent(key)}`, {
1018
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}/values/${encodeURIComponent(key)}`, {
976
1019
  method: "GET",
977
1020
  headers: {
978
1021
  ...this.config.headers
@@ -989,7 +1032,7 @@ var _DistriClient = class _DistriClient {
989
1032
  * Session store: get all values in a session
990
1033
  */
991
1034
  async getSessionValues(sessionId) {
992
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}/values`, {
1035
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}/values`, {
993
1036
  method: "GET",
994
1037
  headers: {
995
1038
  ...this.config.headers
@@ -1006,7 +1049,7 @@ var _DistriClient = class _DistriClient {
1006
1049
  * Session store: delete a single key
1007
1050
  */
1008
1051
  async deleteSessionValue(sessionId, key) {
1009
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}/values/${encodeURIComponent(key)}`, {
1052
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}/values/${encodeURIComponent(key)}`, {
1010
1053
  method: "DELETE",
1011
1054
  headers: {
1012
1055
  ...this.config.headers
@@ -1021,7 +1064,7 @@ var _DistriClient = class _DistriClient {
1021
1064
  * Session store: clear all keys in a session
1022
1065
  */
1023
1066
  async clearSession(sessionId) {
1024
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}`, {
1067
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}`, {
1025
1068
  method: "DELETE",
1026
1069
  headers: {
1027
1070
  ...this.config.headers
@@ -1032,30 +1075,6 @@ var _DistriClient = class _DistriClient {
1032
1075
  throw new ApiError(errorData.error || "Failed to clear session", resp.status);
1033
1076
  }
1034
1077
  }
1035
- /**
1036
- * Set additional user message parts for the next agent iteration.
1037
- * These parts will be appended to the user message in the prompt.
1038
- * @param sessionId - The thread/session ID
1039
- * @param parts - Array of DistriPart objects to append to user message
1040
- */
1041
- async setAdditionalUserParts(sessionId, parts) {
1042
- await this.setSessionValue(sessionId, _DistriClient.ADDITIONAL_PARTS_KEY, parts);
1043
- }
1044
- /**
1045
- * Get the current additional user message parts.
1046
- * @param sessionId - The thread/session ID
1047
- * @returns Array of DistriPart objects or null if not set
1048
- */
1049
- async getAdditionalUserParts(sessionId) {
1050
- return this.getSessionValue(sessionId, _DistriClient.ADDITIONAL_PARTS_KEY);
1051
- }
1052
- /**
1053
- * Clear/delete the additional user message parts.
1054
- * @param sessionId - The thread/session ID
1055
- */
1056
- async clearAdditionalUserParts(sessionId) {
1057
- await this.deleteSessionValue(sessionId, _DistriClient.ADDITIONAL_PARTS_KEY);
1058
- }
1059
1078
  /**
1060
1079
  * Issue an access token + refresh token for temporary authentication.
1061
1080
  * Requires an existing authenticated session (bearer token).
@@ -1085,7 +1104,7 @@ var _DistriClient = class _DistriClient {
1085
1104
  if (!tokens?.access_token || !tokens?.refresh_token || typeof tokens?.expires_at !== "number") {
1086
1105
  throw new ApiError("Invalid token response", response.status);
1087
1106
  }
1088
- this.applyTokens(tokens.access_token, tokens.refresh_token, false);
1107
+ this.applyTokens(tokens.access_token, tokens.refresh_token);
1089
1108
  return tokens;
1090
1109
  }
1091
1110
  /**
@@ -1098,13 +1117,18 @@ var _DistriClient = class _DistriClient {
1098
1117
  * Update the access/refresh tokens in memory.
1099
1118
  */
1100
1119
  setTokens(tokens) {
1101
- if (tokens.accessToken !== void 0) {
1102
- this.accessToken = tokens.accessToken;
1103
- }
1104
- if (tokens.refreshToken !== void 0) {
1120
+ this.accessToken = tokens.accessToken;
1121
+ if (tokens.refreshToken) {
1105
1122
  this.refreshToken = tokens.refreshToken;
1106
1123
  }
1107
1124
  }
1125
+ /**
1126
+ * Reset all authentication tokens.
1127
+ */
1128
+ resetTokens() {
1129
+ this.accessToken = void 0;
1130
+ this.refreshToken = void 0;
1131
+ }
1108
1132
  /**
1109
1133
  * Start streaming speech-to-text transcription via WebSocket
1110
1134
  */
@@ -1322,6 +1346,31 @@ var _DistriClient = class _DistriClient {
1322
1346
  throw new DistriError(`Failed to fetch agent ${agentId}`, "FETCH_ERROR", error);
1323
1347
  }
1324
1348
  }
1349
+ /**
1350
+ * Update an agent's definition (markdown only)
1351
+ */
1352
+ async updateAgent(agentId, update) {
1353
+ try {
1354
+ const response = await this.fetch(`/agents/${agentId}`, {
1355
+ method: "PUT",
1356
+ headers: {
1357
+ "Content-Type": "application/json",
1358
+ ...this.config.headers
1359
+ },
1360
+ body: JSON.stringify(update)
1361
+ });
1362
+ if (!response.ok) {
1363
+ if (response.status === 404) {
1364
+ throw new ApiError(`Agent not found: ${agentId}`, 404);
1365
+ }
1366
+ throw new ApiError(`Failed to update agent: ${response.statusText}`, response.status);
1367
+ }
1368
+ return await response.json();
1369
+ } catch (error) {
1370
+ if (error instanceof ApiError) throw error;
1371
+ throw new DistriError(`Failed to update agent ${agentId}`, "UPDATE_ERROR", error);
1372
+ }
1373
+ }
1325
1374
  /**
1326
1375
  * Get or create A2AClient for an agent
1327
1376
  */
@@ -1370,8 +1419,46 @@ var _DistriClient = class _DistriClient {
1370
1419
  yield* await client.sendMessageStream(params);
1371
1420
  } catch (error) {
1372
1421
  console.error(error);
1373
- throw new DistriError(`Failed to stream message to agent ${agentId}`, "STREAM_MESSAGE_ERROR", error);
1422
+ const errorMessage = this.extractErrorMessage(error);
1423
+ throw new DistriError(errorMessage, "STREAM_MESSAGE_ERROR", error);
1424
+ }
1425
+ }
1426
+ /**
1427
+ * Extract a user-friendly error message from potentially nested errors
1428
+ */
1429
+ extractErrorMessage(error) {
1430
+ if (!error) return "Unknown error occurred";
1431
+ if (typeof error === "object" && error !== null) {
1432
+ const err = error;
1433
+ if (err.error && typeof err.error === "object") {
1434
+ const jsonRpcError = err.error;
1435
+ if (typeof jsonRpcError.message === "string") {
1436
+ return jsonRpcError.message;
1437
+ }
1438
+ }
1439
+ if (err.message && typeof err.message === "string") {
1440
+ return err.message;
1441
+ }
1442
+ if (err.details && typeof err.details === "object") {
1443
+ const details = err.details;
1444
+ if (details.message && typeof details.message === "string") {
1445
+ return details.message;
1446
+ }
1447
+ if (details.error && typeof details.error === "object") {
1448
+ const nestedError = details.error;
1449
+ if (typeof nestedError.message === "string") {
1450
+ return nestedError.message;
1451
+ }
1452
+ }
1453
+ }
1454
+ if (err.cause && typeof err.cause === "object") {
1455
+ return this.extractErrorMessage(err.cause);
1456
+ }
1457
+ }
1458
+ if (error instanceof Error) {
1459
+ return error.message;
1374
1460
  }
1461
+ return String(error);
1375
1462
  }
1376
1463
  /**
1377
1464
  * Get task details
@@ -1407,11 +1494,22 @@ var _DistriClient = class _DistriClient {
1407
1494
  }
1408
1495
  }
1409
1496
  /**
1410
- * Get threads from Distri server
1497
+ * Get threads from Distri server with filtering and pagination
1411
1498
  */
1412
- async getThreads() {
1499
+ async getThreads(params = {}) {
1413
1500
  try {
1414
- const response = await this.fetch(`/threads`);
1501
+ const searchParams = new URLSearchParams();
1502
+ if (params.agent_id) searchParams.set("agent_id", params.agent_id);
1503
+ if (params.external_id) searchParams.set("external_id", params.external_id);
1504
+ if (params.search) searchParams.set("search", params.search);
1505
+ if (params.from_date) searchParams.set("from_date", params.from_date);
1506
+ if (params.to_date) searchParams.set("to_date", params.to_date);
1507
+ if (params.tags?.length) searchParams.set("tags", params.tags.join(","));
1508
+ if (params.limit !== void 0) searchParams.set("limit", params.limit.toString());
1509
+ if (params.offset !== void 0) searchParams.set("offset", params.offset.toString());
1510
+ const queryString = searchParams.toString();
1511
+ const url = queryString ? `/threads?${queryString}` : "/threads";
1512
+ const response = await this.fetch(url);
1415
1513
  if (!response.ok) {
1416
1514
  throw new ApiError(`Failed to fetch threads: ${response.statusText}`, response.status);
1417
1515
  }
@@ -1421,6 +1519,39 @@ var _DistriClient = class _DistriClient {
1421
1519
  throw new DistriError("Failed to fetch threads", "FETCH_ERROR", error);
1422
1520
  }
1423
1521
  }
1522
+ /**
1523
+ * Get agents sorted by thread count (most active first)
1524
+ */
1525
+ async getAgentsByUsage() {
1526
+ try {
1527
+ const response = await this.fetch("/threads/agents");
1528
+ if (!response.ok) {
1529
+ throw new ApiError(`Failed to fetch agents by usage: ${response.statusText}`, response.status);
1530
+ }
1531
+ return await response.json();
1532
+ } catch (error) {
1533
+ if (error instanceof ApiError) throw error;
1534
+ throw new DistriError("Failed to fetch agents by usage", "FETCH_ERROR", error);
1535
+ }
1536
+ }
1537
+ /**
1538
+ * Create a new browser session
1539
+ * Returns session info including viewer_url and stream_url from browsr
1540
+ */
1541
+ async createBrowserSession() {
1542
+ try {
1543
+ const response = await this.fetch("/browser/session", {
1544
+ method: "POST"
1545
+ });
1546
+ if (!response.ok) {
1547
+ throw new ApiError(`Failed to create browser session: ${response.statusText}`, response.status);
1548
+ }
1549
+ return await response.json();
1550
+ } catch (error) {
1551
+ if (error instanceof ApiError) throw error;
1552
+ throw new DistriError("Failed to create browser session", "FETCH_ERROR", error);
1553
+ }
1554
+ }
1424
1555
  async getThread(threadId) {
1425
1556
  try {
1426
1557
  const response = await this.fetch(`/threads/${threadId}`);
@@ -1520,15 +1651,17 @@ var _DistriClient = class _DistriClient {
1520
1651
  get baseUrl() {
1521
1652
  return this.config.baseUrl;
1522
1653
  }
1523
- applyTokens(accessToken, refreshToken, notify) {
1654
+ applyTokens(accessToken, refreshToken) {
1524
1655
  this.accessToken = accessToken;
1525
- this.refreshToken = refreshToken;
1526
- if (notify && this.onTokenRefresh) {
1527
- this.onTokenRefresh({ accessToken, refreshToken });
1656
+ if (refreshToken) {
1657
+ this.refreshToken = refreshToken;
1528
1658
  }
1529
1659
  }
1660
+ /**
1661
+ * Ensure access token is valid, refreshing if necessary
1662
+ */
1530
1663
  async ensureAccessToken() {
1531
- if (!this.refreshToken) {
1664
+ if (!this.refreshToken && !this.onTokenRefresh) {
1532
1665
  return;
1533
1666
  }
1534
1667
  if (!this.accessToken || this.isTokenExpiring(this.accessToken)) {
@@ -1540,7 +1673,7 @@ var _DistriClient = class _DistriClient {
1540
1673
  }
1541
1674
  }
1542
1675
  async refreshTokens() {
1543
- if (!this.refreshToken) {
1676
+ if (!this.refreshToken && !this.onTokenRefresh) {
1544
1677
  return;
1545
1678
  }
1546
1679
  if (!this.refreshPromise) {
@@ -1551,6 +1684,17 @@ var _DistriClient = class _DistriClient {
1551
1684
  return this.refreshPromise;
1552
1685
  }
1553
1686
  async performTokenRefresh() {
1687
+ if (this.onTokenRefresh) {
1688
+ this.accessToken = void 0;
1689
+ const newToken = await this.onTokenRefresh();
1690
+ if (newToken) {
1691
+ this.applyTokens(newToken);
1692
+ return;
1693
+ }
1694
+ }
1695
+ if (!this.refreshToken) {
1696
+ return;
1697
+ }
1554
1698
  const response = await this.fetchAbsolute(
1555
1699
  `${this.config.baseUrl}/token`,
1556
1700
  {
@@ -1574,7 +1718,7 @@ var _DistriClient = class _DistriClient {
1574
1718
  if (!tokens?.access_token || !tokens?.refresh_token) {
1575
1719
  throw new ApiError("Invalid token response", response.status);
1576
1720
  }
1577
- this.applyTokens(tokens.access_token, tokens.refresh_token, true);
1721
+ this.applyTokens(tokens.access_token, tokens.refresh_token);
1578
1722
  }
1579
1723
  isTokenExpiring(token) {
1580
1724
  const expiresAt = this.getTokenExpiry(token);
@@ -1669,7 +1813,7 @@ var _DistriClient = class _DistriClient {
1669
1813
  headers
1670
1814
  });
1671
1815
  clearTimeout(timeoutId);
1672
- if (!skipAuth && retryOnAuth && response.status === 401 && this.refreshToken) {
1816
+ if (!skipAuth && retryOnAuth && response.status === 401 && (this.refreshToken || this.onTokenRefresh)) {
1673
1817
  const refreshed = await this.refreshTokens().then(() => true).catch(() => false);
1674
1818
  if (refreshed) {
1675
1819
  return this.fetchAbsolute(url, initialInit, { skipAuth, retryOnAuth: false });
@@ -1687,7 +1831,8 @@ var _DistriClient = class _DistriClient {
1687
1831
  throw lastError;
1688
1832
  }
1689
1833
  /**
1690
- * Enhanced fetch with retry logic
1834
+ * Enhanced fetch with retry logic and auth headers.
1835
+ * Exposed publicly for extensions like DistriHomeClient.
1691
1836
  */
1692
1837
  async fetch(input, initialInit) {
1693
1838
  const url = `${this.config.baseUrl}${input}`;
@@ -1760,13 +1905,6 @@ var _DistriClient = class _DistriClient {
1760
1905
  }
1761
1906
  };
1762
1907
  // ============================================================
1763
- // Additional User Message Parts API
1764
- // ============================================================
1765
- // These methods allow external tools to append parts (text, images)
1766
- // to the user message in the next agent iteration.
1767
- // The parts are stored under the key "__additional_user_parts".
1768
- _DistriClient.ADDITIONAL_PARTS_KEY = "__additional_user_parts";
1769
- // ============================================================
1770
1908
  // Token API
1771
1909
  // ============================================================
1772
1910
  // Issue access + refresh tokens for temporary authentication (e.g., frontend use)
@@ -1792,6 +1930,25 @@ function uuidv4() {
1792
1930
  }
1793
1931
 
1794
1932
  // src/agent.ts
1933
+ var ExternalToolValidationError = class extends DistriError {
1934
+ constructor(agentName, result) {
1935
+ super(
1936
+ result.message || "Missing required external tools for agent invocation.",
1937
+ "EXTERNAL_TOOL_VALIDATION_ERROR",
1938
+ {
1939
+ agentName,
1940
+ missingTools: result.missingTools,
1941
+ requiredTools: result.requiredTools,
1942
+ providedTools: result.providedTools
1943
+ }
1944
+ );
1945
+ this.name = "ExternalToolValidationError";
1946
+ this.agentName = agentName;
1947
+ this.missingTools = result.missingTools;
1948
+ this.requiredTools = result.requiredTools;
1949
+ this.providedTools = result.providedTools;
1950
+ }
1951
+ };
1795
1952
  var Agent = class _Agent {
1796
1953
  constructor(agentDefinition, client) {
1797
1954
  this.hookHandlers = /* @__PURE__ */ new Map();
@@ -1812,7 +1969,7 @@ var Agent = class _Agent {
1812
1969
  return this.agentDefinition.description;
1813
1970
  }
1814
1971
  get agentType() {
1815
- return this.agentDefinition.agent_type ?? this.agentDefinition.agentType;
1972
+ return this.agentDefinition.agent_type;
1816
1973
  }
1817
1974
  get iconUrl() {
1818
1975
  return this.agentDefinition.icon_url;
@@ -1849,7 +2006,7 @@ var Agent = class _Agent {
1849
2006
  const enhancedParams = this.enhanceParamsWithTools(params, tools);
1850
2007
  const a2aStream = this.client.sendMessageStream(this.agentDefinition.id, enhancedParams);
1851
2008
  const self = this;
1852
- return (async function* () {
2009
+ return async function* () {
1853
2010
  for await (const event of a2aStream) {
1854
2011
  const converted = decodeA2AStreamEvent(event);
1855
2012
  if (converted && converted.type === "inline_hook_requested") {
@@ -1870,12 +2027,38 @@ var Agent = class _Agent {
1870
2027
  yield converted;
1871
2028
  }
1872
2029
  }
1873
- })();
2030
+ }();
2031
+ }
2032
+ /**
2033
+ * Validate that required external tools are registered before invoking.
2034
+ */
2035
+ validateExternalTools(tools = []) {
2036
+ const requiredTools = this.getRequiredExternalTools();
2037
+ const providedTools = tools.map((tool) => tool.name);
2038
+ if (requiredTools.length === 0) {
2039
+ return {
2040
+ isValid: true,
2041
+ requiredTools: [],
2042
+ providedTools,
2043
+ missingTools: []
2044
+ };
2045
+ }
2046
+ const providedSet = new Set(providedTools);
2047
+ const missingTools = requiredTools.filter((tool) => !providedSet.has(tool));
2048
+ const isValid = missingTools.length === 0;
2049
+ return {
2050
+ isValid,
2051
+ requiredTools,
2052
+ providedTools,
2053
+ missingTools,
2054
+ message: isValid ? void 0 : this.formatExternalToolValidationMessage(requiredTools, missingTools)
2055
+ };
1874
2056
  }
1875
2057
  /**
1876
2058
  * Enhance message params with tool definitions
1877
2059
  */
1878
2060
  enhanceParamsWithTools(params, tools) {
2061
+ this.assertExternalTools(tools);
1879
2062
  const metadata = {
1880
2063
  ...params.metadata,
1881
2064
  external_tools: tools?.map((tool) => ({
@@ -1890,6 +2073,39 @@ var Agent = class _Agent {
1890
2073
  metadata
1891
2074
  };
1892
2075
  }
2076
+ assertExternalTools(tools) {
2077
+ const result = this.validateExternalTools(tools ?? []);
2078
+ if (!result.isValid) {
2079
+ throw new ExternalToolValidationError(this.agentDefinition.name || this.agentDefinition.id, result);
2080
+ }
2081
+ }
2082
+ getRequiredExternalTools() {
2083
+ const toolConfig = this.resolveToolConfig();
2084
+ if (!toolConfig?.external || !Array.isArray(toolConfig.external)) {
2085
+ return [];
2086
+ }
2087
+ if (toolConfig.external.includes("*")) {
2088
+ return [];
2089
+ }
2090
+ return toolConfig.external.filter((tool) => typeof tool === "string" && tool.trim().length > 0);
2091
+ }
2092
+ resolveToolConfig() {
2093
+ const root = this.agentDefinition;
2094
+ return this.extractToolConfig(root) || this.extractToolConfig(root?.agent) || this.extractToolConfig(root?.definition);
2095
+ }
2096
+ extractToolConfig(candidate) {
2097
+ if (!candidate) return null;
2098
+ const tools = candidate.tools;
2099
+ if (!tools || Array.isArray(tools) || typeof tools !== "object") {
2100
+ return null;
2101
+ }
2102
+ return tools;
2103
+ }
2104
+ formatExternalToolValidationMessage(requiredTools, missingTools) {
2105
+ const requiredList = requiredTools.join(", ");
2106
+ const missingList = missingTools.join(", ");
2107
+ return `Agent has external tools that are not registered: ${missingList}. This is an embedded agent that can run within the parent application. Register DistriWidget for embedding the parent component. Required tools: ${requiredList}.`;
2108
+ }
1893
2109
  /**
1894
2110
  * Register multiple hooks at once.
1895
2111
  */
@@ -1906,12 +2122,13 @@ var Agent = class _Agent {
1906
2122
  */
1907
2123
  static async create(agentIdOrDef, client) {
1908
2124
  const agentDefinition = typeof agentIdOrDef === "string" ? await client.getAgent(agentIdOrDef) : agentIdOrDef;
2125
+ const tools = agentDefinition?.resolved_tools || [];
1909
2126
  console.log("\u{1F916} Agent definition loaded:", {
1910
2127
  id: agentDefinition.id,
1911
2128
  name: agentDefinition.name,
1912
- tools: agentDefinition.tools?.map((t) => ({
2129
+ tools: tools.map((t) => ({
1913
2130
  name: t.name,
1914
- type: t.type || "function"
2131
+ type: "function"
1915
2132
  })) || [],
1916
2133
  toolCount: agentDefinition.tools?.length || 0
1917
2134
  });
@@ -1940,6 +2157,7 @@ var Agent = class _Agent {
1940
2157
  DEFAULT_BASE_URL,
1941
2158
  DistriClient,
1942
2159
  DistriError,
2160
+ ExternalToolValidationError,
1943
2161
  convertA2AMessageToDistri,
1944
2162
  convertA2APartToDistri,
1945
2163
  convertA2AStatusUpdateToDistri,