@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.mjs CHANGED
@@ -681,6 +681,17 @@ function convertA2AStatusUpdateToDistri(statusUpdate) {
681
681
  };
682
682
  return hookRequested;
683
683
  }
684
+ case "browser_session_started": {
685
+ const browserSessionStarted = {
686
+ type: "browser_session_started",
687
+ data: {
688
+ session_id: metadata.session_id || "",
689
+ viewer_url: metadata.viewer_url,
690
+ stream_url: metadata.stream_url
691
+ }
692
+ };
693
+ return browserSessionStarted;
694
+ }
684
695
  default: {
685
696
  console.warn(`Unhandled status update metadata type: ${metadata.type}`, metadata);
686
697
  const defaultResult = {
@@ -759,6 +770,7 @@ function convertDistriMessageToA2A(distriMessage, context) {
759
770
  break;
760
771
  case "system":
761
772
  case "tool":
773
+ case "developer":
762
774
  role = "user";
763
775
  break;
764
776
  default:
@@ -855,26 +867,56 @@ var _DistriClient = class _DistriClient {
855
867
  constructor(config) {
856
868
  this.agentClients = /* @__PURE__ */ new Map();
857
869
  const headers = { ...config.headers };
870
+ if (config.workspaceId) {
871
+ headers["X-Workspace-Id"] = config.workspaceId;
872
+ }
858
873
  this.accessToken = config.accessToken;
859
874
  this.refreshToken = config.refreshToken;
860
875
  this.tokenRefreshSkewMs = config.tokenRefreshSkewMs ?? 6e4;
861
876
  this.onTokenRefresh = config.onTokenRefresh;
862
877
  this.config = {
863
- baseUrl: config.baseUrl.replace(/\/$/, ""),
878
+ baseUrl: config.baseUrl?.replace(/\/$/, "") || DEFAULT_BASE_URL,
864
879
  apiVersion: config.apiVersion || "v1",
865
- timeout: config.timeout || 3e4,
866
- retryAttempts: config.retryAttempts || 3,
867
- retryDelay: config.retryDelay || 1e3,
868
- debug: config.debug || false,
880
+ timeout: config.timeout ?? 3e4,
881
+ retryAttempts: config.retryAttempts ?? 3,
882
+ retryDelay: config.retryDelay ?? 1e3,
883
+ debug: config.debug ?? false,
869
884
  headers,
870
- interceptor: config.interceptor || ((init) => Promise.resolve(init))
885
+ interceptor: config.interceptor ?? (async (init) => Promise.resolve(init)),
886
+ onTokenRefresh: config.onTokenRefresh,
887
+ clientId: config.clientId,
888
+ workspaceId: config.workspaceId
871
889
  };
872
- this.debug("DistriClient initialized with config:", {
873
- baseUrl: this.config.baseUrl,
874
- hasAccessToken: !!this.accessToken,
875
- hasRefreshToken: !!this.refreshToken,
876
- timeout: this.config.timeout
877
- });
890
+ }
891
+ /**
892
+ * Get the configured client ID.
893
+ */
894
+ get clientId() {
895
+ return this.config.clientId;
896
+ }
897
+ /**
898
+ * Set the client ID for embed token issuance.
899
+ */
900
+ set clientId(value) {
901
+ this.config.clientId = value;
902
+ }
903
+ /**
904
+ * Get the configured workspace ID.
905
+ */
906
+ get workspaceId() {
907
+ return this.config.workspaceId;
908
+ }
909
+ /**
910
+ * Set the workspace ID for multi-tenant support.
911
+ * Updates the X-Workspace-Id header for all subsequent requests.
912
+ */
913
+ set workspaceId(value) {
914
+ this.config.workspaceId = value;
915
+ if (value) {
916
+ this.config.headers["X-Workspace-Id"] = value;
917
+ } else {
918
+ delete this.config.headers["X-Workspace-Id"];
919
+ }
878
920
  }
879
921
  /**
880
922
  * Create a client with default cloud configuration.
@@ -907,7 +949,7 @@ var _DistriClient = class _DistriClient {
907
949
  if (expiry) {
908
950
  body.expiry = typeof expiry === "string" ? expiry : expiry.toISOString();
909
951
  }
910
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}/values`, {
952
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}/values`, {
911
953
  method: "POST",
912
954
  headers: {
913
955
  "Content-Type": "application/json",
@@ -924,7 +966,7 @@ var _DistriClient = class _DistriClient {
924
966
  * Session store: get a single value
925
967
  */
926
968
  async getSessionValue(sessionId, key) {
927
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}/values/${encodeURIComponent(key)}`, {
969
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}/values/${encodeURIComponent(key)}`, {
928
970
  method: "GET",
929
971
  headers: {
930
972
  ...this.config.headers
@@ -941,7 +983,7 @@ var _DistriClient = class _DistriClient {
941
983
  * Session store: get all values in a session
942
984
  */
943
985
  async getSessionValues(sessionId) {
944
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}/values`, {
986
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}/values`, {
945
987
  method: "GET",
946
988
  headers: {
947
989
  ...this.config.headers
@@ -958,7 +1000,7 @@ var _DistriClient = class _DistriClient {
958
1000
  * Session store: delete a single key
959
1001
  */
960
1002
  async deleteSessionValue(sessionId, key) {
961
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}/values/${encodeURIComponent(key)}`, {
1003
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}/values/${encodeURIComponent(key)}`, {
962
1004
  method: "DELETE",
963
1005
  headers: {
964
1006
  ...this.config.headers
@@ -973,7 +1015,7 @@ var _DistriClient = class _DistriClient {
973
1015
  * Session store: clear all keys in a session
974
1016
  */
975
1017
  async clearSession(sessionId) {
976
- const resp = await this.fetch(`/session/${encodeURIComponent(sessionId)}`, {
1018
+ const resp = await this.fetch(`/sessions/${encodeURIComponent(sessionId)}`, {
977
1019
  method: "DELETE",
978
1020
  headers: {
979
1021
  ...this.config.headers
@@ -984,30 +1026,6 @@ var _DistriClient = class _DistriClient {
984
1026
  throw new ApiError(errorData.error || "Failed to clear session", resp.status);
985
1027
  }
986
1028
  }
987
- /**
988
- * Set additional user message parts for the next agent iteration.
989
- * These parts will be appended to the user message in the prompt.
990
- * @param sessionId - The thread/session ID
991
- * @param parts - Array of DistriPart objects to append to user message
992
- */
993
- async setAdditionalUserParts(sessionId, parts) {
994
- await this.setSessionValue(sessionId, _DistriClient.ADDITIONAL_PARTS_KEY, parts);
995
- }
996
- /**
997
- * Get the current additional user message parts.
998
- * @param sessionId - The thread/session ID
999
- * @returns Array of DistriPart objects or null if not set
1000
- */
1001
- async getAdditionalUserParts(sessionId) {
1002
- return this.getSessionValue(sessionId, _DistriClient.ADDITIONAL_PARTS_KEY);
1003
- }
1004
- /**
1005
- * Clear/delete the additional user message parts.
1006
- * @param sessionId - The thread/session ID
1007
- */
1008
- async clearAdditionalUserParts(sessionId) {
1009
- await this.deleteSessionValue(sessionId, _DistriClient.ADDITIONAL_PARTS_KEY);
1010
- }
1011
1029
  /**
1012
1030
  * Issue an access token + refresh token for temporary authentication.
1013
1031
  * Requires an existing authenticated session (bearer token).
@@ -1037,7 +1055,7 @@ var _DistriClient = class _DistriClient {
1037
1055
  if (!tokens?.access_token || !tokens?.refresh_token || typeof tokens?.expires_at !== "number") {
1038
1056
  throw new ApiError("Invalid token response", response.status);
1039
1057
  }
1040
- this.applyTokens(tokens.access_token, tokens.refresh_token, false);
1058
+ this.applyTokens(tokens.access_token, tokens.refresh_token);
1041
1059
  return tokens;
1042
1060
  }
1043
1061
  /**
@@ -1050,13 +1068,18 @@ var _DistriClient = class _DistriClient {
1050
1068
  * Update the access/refresh tokens in memory.
1051
1069
  */
1052
1070
  setTokens(tokens) {
1053
- if (tokens.accessToken !== void 0) {
1054
- this.accessToken = tokens.accessToken;
1055
- }
1056
- if (tokens.refreshToken !== void 0) {
1071
+ this.accessToken = tokens.accessToken;
1072
+ if (tokens.refreshToken) {
1057
1073
  this.refreshToken = tokens.refreshToken;
1058
1074
  }
1059
1075
  }
1076
+ /**
1077
+ * Reset all authentication tokens.
1078
+ */
1079
+ resetTokens() {
1080
+ this.accessToken = void 0;
1081
+ this.refreshToken = void 0;
1082
+ }
1060
1083
  /**
1061
1084
  * Start streaming speech-to-text transcription via WebSocket
1062
1085
  */
@@ -1274,6 +1297,31 @@ var _DistriClient = class _DistriClient {
1274
1297
  throw new DistriError(`Failed to fetch agent ${agentId}`, "FETCH_ERROR", error);
1275
1298
  }
1276
1299
  }
1300
+ /**
1301
+ * Update an agent's definition (markdown only)
1302
+ */
1303
+ async updateAgent(agentId, update) {
1304
+ try {
1305
+ const response = await this.fetch(`/agents/${agentId}`, {
1306
+ method: "PUT",
1307
+ headers: {
1308
+ "Content-Type": "application/json",
1309
+ ...this.config.headers
1310
+ },
1311
+ body: JSON.stringify(update)
1312
+ });
1313
+ if (!response.ok) {
1314
+ if (response.status === 404) {
1315
+ throw new ApiError(`Agent not found: ${agentId}`, 404);
1316
+ }
1317
+ throw new ApiError(`Failed to update agent: ${response.statusText}`, response.status);
1318
+ }
1319
+ return await response.json();
1320
+ } catch (error) {
1321
+ if (error instanceof ApiError) throw error;
1322
+ throw new DistriError(`Failed to update agent ${agentId}`, "UPDATE_ERROR", error);
1323
+ }
1324
+ }
1277
1325
  /**
1278
1326
  * Get or create A2AClient for an agent
1279
1327
  */
@@ -1322,8 +1370,46 @@ var _DistriClient = class _DistriClient {
1322
1370
  yield* await client.sendMessageStream(params);
1323
1371
  } catch (error) {
1324
1372
  console.error(error);
1325
- throw new DistriError(`Failed to stream message to agent ${agentId}`, "STREAM_MESSAGE_ERROR", error);
1373
+ const errorMessage = this.extractErrorMessage(error);
1374
+ throw new DistriError(errorMessage, "STREAM_MESSAGE_ERROR", error);
1375
+ }
1376
+ }
1377
+ /**
1378
+ * Extract a user-friendly error message from potentially nested errors
1379
+ */
1380
+ extractErrorMessage(error) {
1381
+ if (!error) return "Unknown error occurred";
1382
+ if (typeof error === "object" && error !== null) {
1383
+ const err = error;
1384
+ if (err.error && typeof err.error === "object") {
1385
+ const jsonRpcError = err.error;
1386
+ if (typeof jsonRpcError.message === "string") {
1387
+ return jsonRpcError.message;
1388
+ }
1389
+ }
1390
+ if (err.message && typeof err.message === "string") {
1391
+ return err.message;
1392
+ }
1393
+ if (err.details && typeof err.details === "object") {
1394
+ const details = err.details;
1395
+ if (details.message && typeof details.message === "string") {
1396
+ return details.message;
1397
+ }
1398
+ if (details.error && typeof details.error === "object") {
1399
+ const nestedError = details.error;
1400
+ if (typeof nestedError.message === "string") {
1401
+ return nestedError.message;
1402
+ }
1403
+ }
1404
+ }
1405
+ if (err.cause && typeof err.cause === "object") {
1406
+ return this.extractErrorMessage(err.cause);
1407
+ }
1408
+ }
1409
+ if (error instanceof Error) {
1410
+ return error.message;
1326
1411
  }
1412
+ return String(error);
1327
1413
  }
1328
1414
  /**
1329
1415
  * Get task details
@@ -1359,11 +1445,22 @@ var _DistriClient = class _DistriClient {
1359
1445
  }
1360
1446
  }
1361
1447
  /**
1362
- * Get threads from Distri server
1448
+ * Get threads from Distri server with filtering and pagination
1363
1449
  */
1364
- async getThreads() {
1450
+ async getThreads(params = {}) {
1365
1451
  try {
1366
- const response = await this.fetch(`/threads`);
1452
+ const searchParams = new URLSearchParams();
1453
+ if (params.agent_id) searchParams.set("agent_id", params.agent_id);
1454
+ if (params.external_id) searchParams.set("external_id", params.external_id);
1455
+ if (params.search) searchParams.set("search", params.search);
1456
+ if (params.from_date) searchParams.set("from_date", params.from_date);
1457
+ if (params.to_date) searchParams.set("to_date", params.to_date);
1458
+ if (params.tags?.length) searchParams.set("tags", params.tags.join(","));
1459
+ if (params.limit !== void 0) searchParams.set("limit", params.limit.toString());
1460
+ if (params.offset !== void 0) searchParams.set("offset", params.offset.toString());
1461
+ const queryString = searchParams.toString();
1462
+ const url = queryString ? `/threads?${queryString}` : "/threads";
1463
+ const response = await this.fetch(url);
1367
1464
  if (!response.ok) {
1368
1465
  throw new ApiError(`Failed to fetch threads: ${response.statusText}`, response.status);
1369
1466
  }
@@ -1373,6 +1470,39 @@ var _DistriClient = class _DistriClient {
1373
1470
  throw new DistriError("Failed to fetch threads", "FETCH_ERROR", error);
1374
1471
  }
1375
1472
  }
1473
+ /**
1474
+ * Get agents sorted by thread count (most active first)
1475
+ */
1476
+ async getAgentsByUsage() {
1477
+ try {
1478
+ const response = await this.fetch("/threads/agents");
1479
+ if (!response.ok) {
1480
+ throw new ApiError(`Failed to fetch agents by usage: ${response.statusText}`, response.status);
1481
+ }
1482
+ return await response.json();
1483
+ } catch (error) {
1484
+ if (error instanceof ApiError) throw error;
1485
+ throw new DistriError("Failed to fetch agents by usage", "FETCH_ERROR", error);
1486
+ }
1487
+ }
1488
+ /**
1489
+ * Create a new browser session
1490
+ * Returns session info including viewer_url and stream_url from browsr
1491
+ */
1492
+ async createBrowserSession() {
1493
+ try {
1494
+ const response = await this.fetch("/browser/session", {
1495
+ method: "POST"
1496
+ });
1497
+ if (!response.ok) {
1498
+ throw new ApiError(`Failed to create browser session: ${response.statusText}`, response.status);
1499
+ }
1500
+ return await response.json();
1501
+ } catch (error) {
1502
+ if (error instanceof ApiError) throw error;
1503
+ throw new DistriError("Failed to create browser session", "FETCH_ERROR", error);
1504
+ }
1505
+ }
1376
1506
  async getThread(threadId) {
1377
1507
  try {
1378
1508
  const response = await this.fetch(`/threads/${threadId}`);
@@ -1472,15 +1602,17 @@ var _DistriClient = class _DistriClient {
1472
1602
  get baseUrl() {
1473
1603
  return this.config.baseUrl;
1474
1604
  }
1475
- applyTokens(accessToken, refreshToken, notify) {
1605
+ applyTokens(accessToken, refreshToken) {
1476
1606
  this.accessToken = accessToken;
1477
- this.refreshToken = refreshToken;
1478
- if (notify && this.onTokenRefresh) {
1479
- this.onTokenRefresh({ accessToken, refreshToken });
1607
+ if (refreshToken) {
1608
+ this.refreshToken = refreshToken;
1480
1609
  }
1481
1610
  }
1611
+ /**
1612
+ * Ensure access token is valid, refreshing if necessary
1613
+ */
1482
1614
  async ensureAccessToken() {
1483
- if (!this.refreshToken) {
1615
+ if (!this.refreshToken && !this.onTokenRefresh) {
1484
1616
  return;
1485
1617
  }
1486
1618
  if (!this.accessToken || this.isTokenExpiring(this.accessToken)) {
@@ -1492,7 +1624,7 @@ var _DistriClient = class _DistriClient {
1492
1624
  }
1493
1625
  }
1494
1626
  async refreshTokens() {
1495
- if (!this.refreshToken) {
1627
+ if (!this.refreshToken && !this.onTokenRefresh) {
1496
1628
  return;
1497
1629
  }
1498
1630
  if (!this.refreshPromise) {
@@ -1503,6 +1635,17 @@ var _DistriClient = class _DistriClient {
1503
1635
  return this.refreshPromise;
1504
1636
  }
1505
1637
  async performTokenRefresh() {
1638
+ if (this.onTokenRefresh) {
1639
+ this.accessToken = void 0;
1640
+ const newToken = await this.onTokenRefresh();
1641
+ if (newToken) {
1642
+ this.applyTokens(newToken);
1643
+ return;
1644
+ }
1645
+ }
1646
+ if (!this.refreshToken) {
1647
+ return;
1648
+ }
1506
1649
  const response = await this.fetchAbsolute(
1507
1650
  `${this.config.baseUrl}/token`,
1508
1651
  {
@@ -1526,7 +1669,7 @@ var _DistriClient = class _DistriClient {
1526
1669
  if (!tokens?.access_token || !tokens?.refresh_token) {
1527
1670
  throw new ApiError("Invalid token response", response.status);
1528
1671
  }
1529
- this.applyTokens(tokens.access_token, tokens.refresh_token, true);
1672
+ this.applyTokens(tokens.access_token, tokens.refresh_token);
1530
1673
  }
1531
1674
  isTokenExpiring(token) {
1532
1675
  const expiresAt = this.getTokenExpiry(token);
@@ -1621,7 +1764,7 @@ var _DistriClient = class _DistriClient {
1621
1764
  headers
1622
1765
  });
1623
1766
  clearTimeout(timeoutId);
1624
- if (!skipAuth && retryOnAuth && response.status === 401 && this.refreshToken) {
1767
+ if (!skipAuth && retryOnAuth && response.status === 401 && (this.refreshToken || this.onTokenRefresh)) {
1625
1768
  const refreshed = await this.refreshTokens().then(() => true).catch(() => false);
1626
1769
  if (refreshed) {
1627
1770
  return this.fetchAbsolute(url, initialInit, { skipAuth, retryOnAuth: false });
@@ -1639,7 +1782,8 @@ var _DistriClient = class _DistriClient {
1639
1782
  throw lastError;
1640
1783
  }
1641
1784
  /**
1642
- * Enhanced fetch with retry logic
1785
+ * Enhanced fetch with retry logic and auth headers.
1786
+ * Exposed publicly for extensions like DistriHomeClient.
1643
1787
  */
1644
1788
  async fetch(input, initialInit) {
1645
1789
  const url = `${this.config.baseUrl}${input}`;
@@ -1712,13 +1856,6 @@ var _DistriClient = class _DistriClient {
1712
1856
  }
1713
1857
  };
1714
1858
  // ============================================================
1715
- // Additional User Message Parts API
1716
- // ============================================================
1717
- // These methods allow external tools to append parts (text, images)
1718
- // to the user message in the next agent iteration.
1719
- // The parts are stored under the key "__additional_user_parts".
1720
- _DistriClient.ADDITIONAL_PARTS_KEY = "__additional_user_parts";
1721
- // ============================================================
1722
1859
  // Token API
1723
1860
  // ============================================================
1724
1861
  // Issue access + refresh tokens for temporary authentication (e.g., frontend use)
@@ -1744,6 +1881,25 @@ function uuidv4() {
1744
1881
  }
1745
1882
 
1746
1883
  // src/agent.ts
1884
+ var ExternalToolValidationError = class extends DistriError {
1885
+ constructor(agentName, result) {
1886
+ super(
1887
+ result.message || "Missing required external tools for agent invocation.",
1888
+ "EXTERNAL_TOOL_VALIDATION_ERROR",
1889
+ {
1890
+ agentName,
1891
+ missingTools: result.missingTools,
1892
+ requiredTools: result.requiredTools,
1893
+ providedTools: result.providedTools
1894
+ }
1895
+ );
1896
+ this.name = "ExternalToolValidationError";
1897
+ this.agentName = agentName;
1898
+ this.missingTools = result.missingTools;
1899
+ this.requiredTools = result.requiredTools;
1900
+ this.providedTools = result.providedTools;
1901
+ }
1902
+ };
1747
1903
  var Agent = class _Agent {
1748
1904
  constructor(agentDefinition, client) {
1749
1905
  this.hookHandlers = /* @__PURE__ */ new Map();
@@ -1764,7 +1920,7 @@ var Agent = class _Agent {
1764
1920
  return this.agentDefinition.description;
1765
1921
  }
1766
1922
  get agentType() {
1767
- return this.agentDefinition.agent_type ?? this.agentDefinition.agentType;
1923
+ return this.agentDefinition.agent_type;
1768
1924
  }
1769
1925
  get iconUrl() {
1770
1926
  return this.agentDefinition.icon_url;
@@ -1801,7 +1957,7 @@ var Agent = class _Agent {
1801
1957
  const enhancedParams = this.enhanceParamsWithTools(params, tools);
1802
1958
  const a2aStream = this.client.sendMessageStream(this.agentDefinition.id, enhancedParams);
1803
1959
  const self = this;
1804
- return (async function* () {
1960
+ return async function* () {
1805
1961
  for await (const event of a2aStream) {
1806
1962
  const converted = decodeA2AStreamEvent(event);
1807
1963
  if (converted && converted.type === "inline_hook_requested") {
@@ -1822,12 +1978,38 @@ var Agent = class _Agent {
1822
1978
  yield converted;
1823
1979
  }
1824
1980
  }
1825
- })();
1981
+ }();
1982
+ }
1983
+ /**
1984
+ * Validate that required external tools are registered before invoking.
1985
+ */
1986
+ validateExternalTools(tools = []) {
1987
+ const requiredTools = this.getRequiredExternalTools();
1988
+ const providedTools = tools.map((tool) => tool.name);
1989
+ if (requiredTools.length === 0) {
1990
+ return {
1991
+ isValid: true,
1992
+ requiredTools: [],
1993
+ providedTools,
1994
+ missingTools: []
1995
+ };
1996
+ }
1997
+ const providedSet = new Set(providedTools);
1998
+ const missingTools = requiredTools.filter((tool) => !providedSet.has(tool));
1999
+ const isValid = missingTools.length === 0;
2000
+ return {
2001
+ isValid,
2002
+ requiredTools,
2003
+ providedTools,
2004
+ missingTools,
2005
+ message: isValid ? void 0 : this.formatExternalToolValidationMessage(requiredTools, missingTools)
2006
+ };
1826
2007
  }
1827
2008
  /**
1828
2009
  * Enhance message params with tool definitions
1829
2010
  */
1830
2011
  enhanceParamsWithTools(params, tools) {
2012
+ this.assertExternalTools(tools);
1831
2013
  const metadata = {
1832
2014
  ...params.metadata,
1833
2015
  external_tools: tools?.map((tool) => ({
@@ -1842,6 +2024,39 @@ var Agent = class _Agent {
1842
2024
  metadata
1843
2025
  };
1844
2026
  }
2027
+ assertExternalTools(tools) {
2028
+ const result = this.validateExternalTools(tools ?? []);
2029
+ if (!result.isValid) {
2030
+ throw new ExternalToolValidationError(this.agentDefinition.name || this.agentDefinition.id, result);
2031
+ }
2032
+ }
2033
+ getRequiredExternalTools() {
2034
+ const toolConfig = this.resolveToolConfig();
2035
+ if (!toolConfig?.external || !Array.isArray(toolConfig.external)) {
2036
+ return [];
2037
+ }
2038
+ if (toolConfig.external.includes("*")) {
2039
+ return [];
2040
+ }
2041
+ return toolConfig.external.filter((tool) => typeof tool === "string" && tool.trim().length > 0);
2042
+ }
2043
+ resolveToolConfig() {
2044
+ const root = this.agentDefinition;
2045
+ return this.extractToolConfig(root) || this.extractToolConfig(root?.agent) || this.extractToolConfig(root?.definition);
2046
+ }
2047
+ extractToolConfig(candidate) {
2048
+ if (!candidate) return null;
2049
+ const tools = candidate.tools;
2050
+ if (!tools || Array.isArray(tools) || typeof tools !== "object") {
2051
+ return null;
2052
+ }
2053
+ return tools;
2054
+ }
2055
+ formatExternalToolValidationMessage(requiredTools, missingTools) {
2056
+ const requiredList = requiredTools.join(", ");
2057
+ const missingList = missingTools.join(", ");
2058
+ 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}.`;
2059
+ }
1845
2060
  /**
1846
2061
  * Register multiple hooks at once.
1847
2062
  */
@@ -1858,12 +2073,13 @@ var Agent = class _Agent {
1858
2073
  */
1859
2074
  static async create(agentIdOrDef, client) {
1860
2075
  const agentDefinition = typeof agentIdOrDef === "string" ? await client.getAgent(agentIdOrDef) : agentIdOrDef;
2076
+ const tools = agentDefinition?.resolved_tools || [];
1861
2077
  console.log("\u{1F916} Agent definition loaded:", {
1862
2078
  id: agentDefinition.id,
1863
2079
  name: agentDefinition.name,
1864
- tools: agentDefinition.tools?.map((t) => ({
2080
+ tools: tools.map((t) => ({
1865
2081
  name: t.name,
1866
- type: t.type || "function"
2082
+ type: "function"
1867
2083
  })) || [],
1868
2084
  toolCount: agentDefinition.tools?.length || 0
1869
2085
  });
@@ -1891,6 +2107,7 @@ export {
1891
2107
  DEFAULT_BASE_URL,
1892
2108
  DistriClient,
1893
2109
  DistriError,
2110
+ ExternalToolValidationError,
1894
2111
  convertA2AMessageToDistri,
1895
2112
  convertA2APartToDistri,
1896
2113
  convertA2AStatusUpdateToDistri,