@dexto/core 1.1.7 → 1.1.8

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.
@@ -36,6 +36,8 @@ var import_service_initializer2 = require("../utils/service-initializer.js");
36
36
  var import_schemas2 = require("./schemas.js");
37
37
  var import_path = require("../utils/path.js");
38
38
  var import_safe_stringify = require("../utils/safe-stringify.cjs");
39
+ var import_registry2 = require("./registry/registry.js");
40
+ var import_loader = require("../config/loader.js");
39
41
  const requiredServices = [
40
42
  "mcpManager",
41
43
  "toolManager",
@@ -781,6 +783,138 @@ class DextoAgent {
781
783
  this.ensureStarted();
782
784
  return sessionId ? this.stateManager.getRuntimeConfig(sessionId) : this.stateManager.getRuntimeConfig();
783
785
  }
786
+ // ============= AGENT MANAGEMENT =============
787
+ /**
788
+ * Lists available and installed agents from the registry.
789
+ * Returns a structured object containing both installed and available agents,
790
+ * along with metadata like descriptions, authors, and tags.
791
+ *
792
+ * @returns Promise resolving to object with installed and available agent lists
793
+ *
794
+ * @example
795
+ * ```typescript
796
+ * const agents = await agent.listAgents();
797
+ * console.log(agents.installed); // ['default', 'my-custom-agent']
798
+ * console.log(agents.available); // [{ name: 'productivity', description: '...', ... }]
799
+ * console.log(agents.current?.name); // 'default'
800
+ * ```
801
+ */
802
+ async listAgents() {
803
+ const agentRegistry = (0, import_registry2.getAgentRegistry)();
804
+ const availableMap = agentRegistry.getAvailableAgents();
805
+ const installedNames = await agentRegistry.getInstalledAgents();
806
+ const installed = await Promise.all(
807
+ installedNames.map(async (name) => {
808
+ const registryEntry = availableMap[name];
809
+ if (registryEntry) {
810
+ return {
811
+ name,
812
+ description: registryEntry.description,
813
+ author: registryEntry.author,
814
+ tags: registryEntry.tags
815
+ };
816
+ } else {
817
+ try {
818
+ const config = await (0, import_loader.loadAgentConfig)(name);
819
+ const author = config.agentCard?.provider?.organization;
820
+ const result = {
821
+ name,
822
+ description: config.agentCard?.description || "Local agent",
823
+ tags: []
824
+ };
825
+ if (author) {
826
+ result.author = author;
827
+ }
828
+ return result;
829
+ } catch {
830
+ return {
831
+ name,
832
+ description: "Local agent (config unavailable)",
833
+ tags: []
834
+ };
835
+ }
836
+ }
837
+ })
838
+ );
839
+ const available = Object.entries(availableMap).filter(([name]) => !installedNames.includes(name)).map(([name, entry]) => ({
840
+ name,
841
+ description: entry.description,
842
+ author: entry.author,
843
+ tags: entry.tags
844
+ }));
845
+ return {
846
+ installed,
847
+ available,
848
+ current: { name: null }
849
+ // TODO: Track current agent name
850
+ };
851
+ }
852
+ /**
853
+ * Installs an agent from the registry.
854
+ * Downloads and sets up the specified agent, making it available for use.
855
+ *
856
+ * @param agentName The name of the agent to install from the registry
857
+ * @returns Promise that resolves when installation is complete
858
+ *
859
+ * @throws {AgentError} When agent is not found in registry or installation fails
860
+ *
861
+ * @example
862
+ * ```typescript
863
+ * await agent.installAgent('productivity');
864
+ * console.log('Productivity agent installed successfully');
865
+ * ```
866
+ */
867
+ async installAgent(agentName) {
868
+ const agentRegistry = (0, import_registry2.getAgentRegistry)();
869
+ if (!agentRegistry.hasAgent(agentName)) {
870
+ throw import_errors.AgentError.apiValidationError(`Agent '${agentName}' not found in registry`);
871
+ }
872
+ try {
873
+ await agentRegistry.installAgent(agentName, true);
874
+ import_logger.logger.info(`Successfully installed agent: ${agentName}`);
875
+ } catch (error) {
876
+ import_logger.logger.error(`Failed to install agent ${agentName}:`, error);
877
+ throw import_errors.AgentError.apiValidationError(
878
+ `Installation failed for agent '${agentName}'`,
879
+ error
880
+ );
881
+ }
882
+ }
883
+ /**
884
+ * Creates a new agent instance for the specified agent name.
885
+ * This method resolves the agent (installing if needed), loads its configuration,
886
+ * and returns a new DextoAgent instance ready to be started.
887
+ *
888
+ * This is a factory method that doesn't affect the current agent instance.
889
+ * The caller is responsible for managing the lifecycle of the returned agent.
890
+ *
891
+ * @param agentName The name of the agent to create
892
+ * @returns Promise resolving to a new DextoAgent instance (not started)
893
+ *
894
+ * @throws {AgentError} When agent is not found or creation fails
895
+ *
896
+ * @example
897
+ * ```typescript
898
+ * const newAgent = await DextoAgent.createAgent('productivity');
899
+ * await newAgent.start();
900
+ * ```
901
+ */
902
+ static async createAgent(agentName) {
903
+ const agentRegistry = (0, import_registry2.getAgentRegistry)();
904
+ try {
905
+ const agentPath = await agentRegistry.resolveAgent(agentName, true, true);
906
+ const config = await (0, import_loader.loadAgentConfig)(agentPath);
907
+ import_logger.logger.info(`Creating agent: ${agentName}`);
908
+ const newAgent = new DextoAgent(config, agentPath);
909
+ import_logger.logger.info(`Successfully created agent: ${agentName}`);
910
+ return newAgent;
911
+ } catch (error) {
912
+ import_logger.logger.error(
913
+ `Failed to create agent '${agentName}': ${error instanceof Error ? error.message : String(error)}`
914
+ );
915
+ throw import_errors.AgentError.apiValidationError(`Failed to create agent '${agentName}'`, error);
916
+ }
917
+ }
784
918
  // Future methods could encapsulate more complex agent behaviors:
785
919
  // - Multi-step task execution with progress tracking
786
920
  // - Memory and context management across sessions
@@ -468,6 +468,74 @@ declare class DextoAgent {
468
468
  * @returns The effective configuration object
469
469
  */
470
470
  getEffectiveConfig(sessionId?: string): Readonly<AgentConfig>;
471
+ /**
472
+ * Lists available and installed agents from the registry.
473
+ * Returns a structured object containing both installed and available agents,
474
+ * along with metadata like descriptions, authors, and tags.
475
+ *
476
+ * @returns Promise resolving to object with installed and available agent lists
477
+ *
478
+ * @example
479
+ * ```typescript
480
+ * const agents = await agent.listAgents();
481
+ * console.log(agents.installed); // ['default', 'my-custom-agent']
482
+ * console.log(agents.available); // [{ name: 'productivity', description: '...', ... }]
483
+ * console.log(agents.current?.name); // 'default'
484
+ * ```
485
+ */
486
+ listAgents(): Promise<{
487
+ installed: Array<{
488
+ name: string;
489
+ description: string;
490
+ author?: string;
491
+ tags?: string[];
492
+ }>;
493
+ available: Array<{
494
+ name: string;
495
+ description: string;
496
+ author?: string;
497
+ tags?: string[];
498
+ }>;
499
+ current?: {
500
+ name?: string | null;
501
+ };
502
+ }>;
503
+ /**
504
+ * Installs an agent from the registry.
505
+ * Downloads and sets up the specified agent, making it available for use.
506
+ *
507
+ * @param agentName The name of the agent to install from the registry
508
+ * @returns Promise that resolves when installation is complete
509
+ *
510
+ * @throws {AgentError} When agent is not found in registry or installation fails
511
+ *
512
+ * @example
513
+ * ```typescript
514
+ * await agent.installAgent('productivity');
515
+ * console.log('Productivity agent installed successfully');
516
+ * ```
517
+ */
518
+ installAgent(agentName: string): Promise<void>;
519
+ /**
520
+ * Creates a new agent instance for the specified agent name.
521
+ * This method resolves the agent (installing if needed), loads its configuration,
522
+ * and returns a new DextoAgent instance ready to be started.
523
+ *
524
+ * This is a factory method that doesn't affect the current agent instance.
525
+ * The caller is responsible for managing the lifecycle of the returned agent.
526
+ *
527
+ * @param agentName The name of the agent to create
528
+ * @returns Promise resolving to a new DextoAgent instance (not started)
529
+ *
530
+ * @throws {AgentError} When agent is not found or creation fails
531
+ *
532
+ * @example
533
+ * ```typescript
534
+ * const newAgent = await DextoAgent.createAgent('productivity');
535
+ * await newAgent.start();
536
+ * ```
537
+ */
538
+ static createAgent(agentName: string): Promise<DextoAgent>;
471
539
  }
472
540
 
473
541
  export { DextoAgent };
@@ -468,6 +468,74 @@ declare class DextoAgent {
468
468
  * @returns The effective configuration object
469
469
  */
470
470
  getEffectiveConfig(sessionId?: string): Readonly<AgentConfig>;
471
+ /**
472
+ * Lists available and installed agents from the registry.
473
+ * Returns a structured object containing both installed and available agents,
474
+ * along with metadata like descriptions, authors, and tags.
475
+ *
476
+ * @returns Promise resolving to object with installed and available agent lists
477
+ *
478
+ * @example
479
+ * ```typescript
480
+ * const agents = await agent.listAgents();
481
+ * console.log(agents.installed); // ['default', 'my-custom-agent']
482
+ * console.log(agents.available); // [{ name: 'productivity', description: '...', ... }]
483
+ * console.log(agents.current?.name); // 'default'
484
+ * ```
485
+ */
486
+ listAgents(): Promise<{
487
+ installed: Array<{
488
+ name: string;
489
+ description: string;
490
+ author?: string;
491
+ tags?: string[];
492
+ }>;
493
+ available: Array<{
494
+ name: string;
495
+ description: string;
496
+ author?: string;
497
+ tags?: string[];
498
+ }>;
499
+ current?: {
500
+ name?: string | null;
501
+ };
502
+ }>;
503
+ /**
504
+ * Installs an agent from the registry.
505
+ * Downloads and sets up the specified agent, making it available for use.
506
+ *
507
+ * @param agentName The name of the agent to install from the registry
508
+ * @returns Promise that resolves when installation is complete
509
+ *
510
+ * @throws {AgentError} When agent is not found in registry or installation fails
511
+ *
512
+ * @example
513
+ * ```typescript
514
+ * await agent.installAgent('productivity');
515
+ * console.log('Productivity agent installed successfully');
516
+ * ```
517
+ */
518
+ installAgent(agentName: string): Promise<void>;
519
+ /**
520
+ * Creates a new agent instance for the specified agent name.
521
+ * This method resolves the agent (installing if needed), loads its configuration,
522
+ * and returns a new DextoAgent instance ready to be started.
523
+ *
524
+ * This is a factory method that doesn't affect the current agent instance.
525
+ * The caller is responsible for managing the lifecycle of the returned agent.
526
+ *
527
+ * @param agentName The name of the agent to create
528
+ * @returns Promise resolving to a new DextoAgent instance (not started)
529
+ *
530
+ * @throws {AgentError} When agent is not found or creation fails
531
+ *
532
+ * @example
533
+ * ```typescript
534
+ * const newAgent = await DextoAgent.createAgent('productivity');
535
+ * await newAgent.start();
536
+ * ```
537
+ */
538
+ static createAgent(agentName: string): Promise<DextoAgent>;
471
539
  }
472
540
 
473
541
  export { DextoAgent };
@@ -18,6 +18,8 @@ import { createAgentServices } from "../utils/service-initializer.js";
18
18
  import { AgentConfigSchema } from "./schemas.js";
19
19
  import { getDextoPath } from "../utils/path.js";
20
20
  import { safeStringify } from "../utils/safe-stringify.js";
21
+ import { getAgentRegistry } from "./registry/registry.js";
22
+ import { loadAgentConfig } from "../config/loader.js";
21
23
  const requiredServices = [
22
24
  "mcpManager",
23
25
  "toolManager",
@@ -763,6 +765,138 @@ class DextoAgent {
763
765
  this.ensureStarted();
764
766
  return sessionId ? this.stateManager.getRuntimeConfig(sessionId) : this.stateManager.getRuntimeConfig();
765
767
  }
768
+ // ============= AGENT MANAGEMENT =============
769
+ /**
770
+ * Lists available and installed agents from the registry.
771
+ * Returns a structured object containing both installed and available agents,
772
+ * along with metadata like descriptions, authors, and tags.
773
+ *
774
+ * @returns Promise resolving to object with installed and available agent lists
775
+ *
776
+ * @example
777
+ * ```typescript
778
+ * const agents = await agent.listAgents();
779
+ * console.log(agents.installed); // ['default', 'my-custom-agent']
780
+ * console.log(agents.available); // [{ name: 'productivity', description: '...', ... }]
781
+ * console.log(agents.current?.name); // 'default'
782
+ * ```
783
+ */
784
+ async listAgents() {
785
+ const agentRegistry = getAgentRegistry();
786
+ const availableMap = agentRegistry.getAvailableAgents();
787
+ const installedNames = await agentRegistry.getInstalledAgents();
788
+ const installed = await Promise.all(
789
+ installedNames.map(async (name) => {
790
+ const registryEntry = availableMap[name];
791
+ if (registryEntry) {
792
+ return {
793
+ name,
794
+ description: registryEntry.description,
795
+ author: registryEntry.author,
796
+ tags: registryEntry.tags
797
+ };
798
+ } else {
799
+ try {
800
+ const config = await loadAgentConfig(name);
801
+ const author = config.agentCard?.provider?.organization;
802
+ const result = {
803
+ name,
804
+ description: config.agentCard?.description || "Local agent",
805
+ tags: []
806
+ };
807
+ if (author) {
808
+ result.author = author;
809
+ }
810
+ return result;
811
+ } catch {
812
+ return {
813
+ name,
814
+ description: "Local agent (config unavailable)",
815
+ tags: []
816
+ };
817
+ }
818
+ }
819
+ })
820
+ );
821
+ const available = Object.entries(availableMap).filter(([name]) => !installedNames.includes(name)).map(([name, entry]) => ({
822
+ name,
823
+ description: entry.description,
824
+ author: entry.author,
825
+ tags: entry.tags
826
+ }));
827
+ return {
828
+ installed,
829
+ available,
830
+ current: { name: null }
831
+ // TODO: Track current agent name
832
+ };
833
+ }
834
+ /**
835
+ * Installs an agent from the registry.
836
+ * Downloads and sets up the specified agent, making it available for use.
837
+ *
838
+ * @param agentName The name of the agent to install from the registry
839
+ * @returns Promise that resolves when installation is complete
840
+ *
841
+ * @throws {AgentError} When agent is not found in registry or installation fails
842
+ *
843
+ * @example
844
+ * ```typescript
845
+ * await agent.installAgent('productivity');
846
+ * console.log('Productivity agent installed successfully');
847
+ * ```
848
+ */
849
+ async installAgent(agentName) {
850
+ const agentRegistry = getAgentRegistry();
851
+ if (!agentRegistry.hasAgent(agentName)) {
852
+ throw AgentError.apiValidationError(`Agent '${agentName}' not found in registry`);
853
+ }
854
+ try {
855
+ await agentRegistry.installAgent(agentName, true);
856
+ logger.info(`Successfully installed agent: ${agentName}`);
857
+ } catch (error) {
858
+ logger.error(`Failed to install agent ${agentName}:`, error);
859
+ throw AgentError.apiValidationError(
860
+ `Installation failed for agent '${agentName}'`,
861
+ error
862
+ );
863
+ }
864
+ }
865
+ /**
866
+ * Creates a new agent instance for the specified agent name.
867
+ * This method resolves the agent (installing if needed), loads its configuration,
868
+ * and returns a new DextoAgent instance ready to be started.
869
+ *
870
+ * This is a factory method that doesn't affect the current agent instance.
871
+ * The caller is responsible for managing the lifecycle of the returned agent.
872
+ *
873
+ * @param agentName The name of the agent to create
874
+ * @returns Promise resolving to a new DextoAgent instance (not started)
875
+ *
876
+ * @throws {AgentError} When agent is not found or creation fails
877
+ *
878
+ * @example
879
+ * ```typescript
880
+ * const newAgent = await DextoAgent.createAgent('productivity');
881
+ * await newAgent.start();
882
+ * ```
883
+ */
884
+ static async createAgent(agentName) {
885
+ const agentRegistry = getAgentRegistry();
886
+ try {
887
+ const agentPath = await agentRegistry.resolveAgent(agentName, true, true);
888
+ const config = await loadAgentConfig(agentPath);
889
+ logger.info(`Creating agent: ${agentName}`);
890
+ const newAgent = new DextoAgent(config, agentPath);
891
+ logger.info(`Successfully created agent: ${agentName}`);
892
+ return newAgent;
893
+ } catch (error) {
894
+ logger.error(
895
+ `Failed to create agent '${agentName}': ${error instanceof Error ? error.message : String(error)}`
896
+ );
897
+ throw AgentError.apiValidationError(`Failed to create agent '${agentName}'`, error);
898
+ }
899
+ }
766
900
  // Future methods could encapsulate more complex agent behaviors:
767
901
  // - Multi-step task execution with progress tracking
768
902
  // - Memory and context management across sessions
@@ -77,6 +77,19 @@ class AgentError {
77
77
  "Check logs for initialization errors"
78
78
  );
79
79
  }
80
+ /**
81
+ * API validation error
82
+ */
83
+ static apiValidationError(message, details) {
84
+ return new import_DextoRuntimeError.DextoRuntimeError(
85
+ import_error_codes.AgentErrorCode.API_VALIDATION_ERROR,
86
+ import_types.ErrorScope.AGENT,
87
+ import_types.ErrorType.USER,
88
+ message,
89
+ details,
90
+ "Check the request parameters and try again"
91
+ );
92
+ }
80
93
  }
81
94
  // Annotate the CommonJS export names for ESM import in node:
82
95
  0 && (module.exports = {
@@ -35,6 +35,10 @@ declare class AgentError {
35
35
  * Agent initialization failed
36
36
  */
37
37
  static initializationFailed(reason: string, details?: unknown): DextoRuntimeError<unknown>;
38
+ /**
39
+ * API validation error
40
+ */
41
+ static apiValidationError(message: string, details?: unknown): DextoRuntimeError<unknown>;
38
42
  }
39
43
 
40
44
  export { AgentError };
@@ -35,6 +35,10 @@ declare class AgentError {
35
35
  * Agent initialization failed
36
36
  */
37
37
  static initializationFailed(reason: string, details?: unknown): DextoRuntimeError<unknown>;
38
+ /**
39
+ * API validation error
40
+ */
41
+ static apiValidationError(message: string, details?: unknown): DextoRuntimeError<unknown>;
38
42
  }
39
43
 
40
44
  export { AgentError };
@@ -54,6 +54,19 @@ class AgentError {
54
54
  "Check logs for initialization errors"
55
55
  );
56
56
  }
57
+ /**
58
+ * API validation error
59
+ */
60
+ static apiValidationError(message, details) {
61
+ return new DextoRuntimeError(
62
+ AgentErrorCode.API_VALIDATION_ERROR,
63
+ ErrorScope.AGENT,
64
+ ErrorType.USER,
65
+ message,
66
+ details,
67
+ "Check the request parameters and try again"
68
+ );
69
+ }
57
70
  }
58
71
  export {
59
72
  AgentError
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexto/core",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",