@dexto/agent-management 1.5.2 → 1.5.4

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.
Files changed (87) hide show
  1. package/dist/config/config-enrichment.d.ts +4 -3
  2. package/dist/config/config-enrichment.d.ts.map +1 -1
  3. package/dist/config/discover-prompts.cjs +24 -19
  4. package/dist/config/discover-prompts.d.ts +13 -5
  5. package/dist/config/discover-prompts.d.ts.map +1 -1
  6. package/dist/config/discover-prompts.js +24 -19
  7. package/dist/index.cjs +6 -1
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +2 -0
  11. package/dist/preferences/index.cjs +2 -0
  12. package/dist/preferences/index.d.ts +2 -2
  13. package/dist/preferences/index.d.ts.map +1 -1
  14. package/dist/preferences/index.js +3 -1
  15. package/dist/preferences/loader.cjs +39 -41
  16. package/dist/preferences/loader.d.ts +7 -5
  17. package/dist/preferences/loader.d.ts.map +1 -1
  18. package/dist/preferences/loader.js +39 -41
  19. package/dist/preferences/schemas.cjs +14 -2
  20. package/dist/preferences/schemas.d.ts +37 -0
  21. package/dist/preferences/schemas.d.ts.map +1 -1
  22. package/dist/preferences/schemas.js +12 -1
  23. package/dist/runtime/AgentPool.cjs +181 -0
  24. package/dist/runtime/AgentPool.d.ts +76 -0
  25. package/dist/runtime/AgentPool.d.ts.map +1 -0
  26. package/dist/runtime/AgentPool.js +160 -0
  27. package/dist/runtime/AgentRuntime.cjs +225 -0
  28. package/dist/runtime/AgentRuntime.d.ts +77 -0
  29. package/dist/runtime/AgentRuntime.d.ts.map +1 -0
  30. package/dist/runtime/AgentRuntime.js +201 -0
  31. package/dist/runtime/approval-delegation.cjs +97 -0
  32. package/dist/runtime/approval-delegation.d.ts +30 -0
  33. package/dist/runtime/approval-delegation.d.ts.map +1 -0
  34. package/dist/runtime/approval-delegation.js +73 -0
  35. package/dist/runtime/error-codes.cjs +40 -0
  36. package/dist/runtime/error-codes.d.ts +17 -0
  37. package/dist/runtime/error-codes.d.ts.map +1 -0
  38. package/dist/runtime/error-codes.js +16 -0
  39. package/dist/runtime/errors.cjs +135 -0
  40. package/dist/runtime/errors.d.ts +40 -0
  41. package/dist/runtime/errors.d.ts.map +1 -0
  42. package/dist/runtime/errors.js +111 -0
  43. package/dist/runtime/index.cjs +53 -0
  44. package/dist/runtime/index.d.ts +19 -0
  45. package/dist/runtime/index.d.ts.map +1 -0
  46. package/dist/runtime/index.js +26 -0
  47. package/dist/runtime/schemas.cjs +64 -0
  48. package/dist/runtime/schemas.d.ts +69 -0
  49. package/dist/runtime/schemas.d.ts.map +1 -0
  50. package/dist/runtime/schemas.js +35 -0
  51. package/dist/runtime/types.cjs +16 -0
  52. package/dist/runtime/types.d.ts +94 -0
  53. package/dist/runtime/types.d.ts.map +1 -0
  54. package/dist/runtime/types.js +0 -0
  55. package/dist/tool-provider/error-codes.cjs +35 -0
  56. package/dist/tool-provider/error-codes.d.ts +11 -0
  57. package/dist/tool-provider/error-codes.d.ts.map +1 -0
  58. package/dist/tool-provider/error-codes.js +11 -0
  59. package/dist/tool-provider/errors.cjs +81 -0
  60. package/dist/tool-provider/errors.d.ts +19 -0
  61. package/dist/tool-provider/errors.d.ts.map +1 -0
  62. package/dist/tool-provider/errors.js +57 -0
  63. package/dist/tool-provider/index.cjs +46 -0
  64. package/dist/tool-provider/index.d.ts +16 -0
  65. package/dist/tool-provider/index.d.ts.map +1 -0
  66. package/dist/tool-provider/index.js +16 -0
  67. package/dist/tool-provider/runtime-service.cjs +390 -0
  68. package/dist/tool-provider/runtime-service.d.ts +83 -0
  69. package/dist/tool-provider/runtime-service.d.ts.map +1 -0
  70. package/dist/tool-provider/runtime-service.js +366 -0
  71. package/dist/tool-provider/schemas.cjs +73 -0
  72. package/dist/tool-provider/schemas.d.ts +83 -0
  73. package/dist/tool-provider/schemas.d.ts.map +1 -0
  74. package/dist/tool-provider/schemas.js +48 -0
  75. package/dist/tool-provider/spawn-agent-tool.cjs +89 -0
  76. package/dist/tool-provider/spawn-agent-tool.d.ts +10 -0
  77. package/dist/tool-provider/spawn-agent-tool.d.ts.map +1 -0
  78. package/dist/tool-provider/spawn-agent-tool.js +65 -0
  79. package/dist/tool-provider/tool-provider.cjs +44 -0
  80. package/dist/tool-provider/tool-provider.d.ts +24 -0
  81. package/dist/tool-provider/tool-provider.d.ts.map +1 -0
  82. package/dist/tool-provider/tool-provider.js +20 -0
  83. package/dist/tool-provider/types.cjs +16 -0
  84. package/dist/tool-provider/types.d.ts +17 -0
  85. package/dist/tool-provider/types.d.ts.map +1 -0
  86. package/dist/tool-provider/types.js +0 -0
  87. package/package.json +2 -2
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var AgentRuntime_exports = {};
20
+ __export(AgentRuntime_exports, {
21
+ AgentRuntime: () => AgentRuntime
22
+ });
23
+ module.exports = __toCommonJS(AgentRuntime_exports);
24
+ var import_crypto = require("crypto");
25
+ var import_core = require("@dexto/core");
26
+ var import_config = require("../config/index.js");
27
+ var import_AgentPool = require("./AgentPool.js");
28
+ var import_errors = require("./errors.js");
29
+ var import_schemas = require("./schemas.js");
30
+ class AgentRuntime {
31
+ pool;
32
+ config;
33
+ logger;
34
+ constructor(options) {
35
+ this.config = import_schemas.AgentRuntimeConfigSchema.parse(options.config ?? {});
36
+ this.logger = options.logger;
37
+ this.pool = new import_AgentPool.AgentPool(this.config, this.logger);
38
+ this.logger.debug("AgentRuntime initialized", {
39
+ maxAgents: this.config.maxAgents,
40
+ defaultTaskTimeout: this.config.defaultTaskTimeout
41
+ });
42
+ }
43
+ /**
44
+ * Spawn a new agent
45
+ *
46
+ * @param config - Configuration for the agent
47
+ * @returns Handle to the spawned agent
48
+ */
49
+ async spawnAgent(config) {
50
+ if (!this.pool.canSpawn()) {
51
+ throw import_errors.RuntimeError.maxAgentsExceeded(this.pool.size, this.config.maxAgents);
52
+ }
53
+ const agentId = config.agentId ?? `agent-${(0, import_crypto.randomUUID)().slice(0, 8)}`;
54
+ if (this.pool.has(agentId)) {
55
+ throw import_errors.RuntimeError.agentAlreadyExists(agentId);
56
+ }
57
+ try {
58
+ const enrichedConfig = (0, import_config.enrichAgentConfig)(
59
+ config.agentConfig,
60
+ void 0,
61
+ // No config path
62
+ false
63
+ // Not interactive CLI
64
+ );
65
+ enrichedConfig.agentId = agentId;
66
+ const agent = new import_core.DextoAgent(enrichedConfig);
67
+ const sessionId = `session-${(0, import_crypto.randomUUID)().slice(0, 8)}`;
68
+ const handle = {
69
+ agentId,
70
+ agent,
71
+ status: "starting",
72
+ ephemeral: config.ephemeral ?? true,
73
+ createdAt: /* @__PURE__ */ new Date(),
74
+ sessionId
75
+ };
76
+ if (config.group !== void 0) {
77
+ handle.group = config.group;
78
+ }
79
+ if (config.metadata !== void 0) {
80
+ handle.metadata = config.metadata;
81
+ }
82
+ this.pool.add(handle);
83
+ if (config.onBeforeStart) {
84
+ await config.onBeforeStart(agent);
85
+ }
86
+ await agent.start();
87
+ this.pool.updateStatus(agentId, "idle");
88
+ this.logger.info(
89
+ `Spawned agent '${agentId}'${handle.group ? ` (group: ${handle.group})` : ""} (ephemeral: ${handle.ephemeral})`
90
+ );
91
+ return handle;
92
+ } catch (error) {
93
+ this.pool.remove(agentId);
94
+ const errorMessage = error instanceof Error ? error.message : String(error);
95
+ throw import_errors.RuntimeError.spawnFailed(errorMessage, agentId);
96
+ }
97
+ }
98
+ /**
99
+ * Execute a task on an agent
100
+ *
101
+ * @param agentId - ID of the agent
102
+ * @param task - Task description to execute
103
+ * @param timeout - Optional timeout in milliseconds
104
+ * @returns Task result with response or error
105
+ */
106
+ async executeTask(agentId, task, timeout) {
107
+ const handle = this.pool.get(agentId);
108
+ if (!handle) {
109
+ throw import_errors.RuntimeError.agentNotFound(agentId);
110
+ }
111
+ if (handle.status === "stopped" || handle.status === "error") {
112
+ throw import_errors.RuntimeError.agentAlreadyStopped(agentId);
113
+ }
114
+ const taskTimeout = timeout ?? this.config.defaultTaskTimeout;
115
+ this.pool.updateStatus(agentId, "running");
116
+ try {
117
+ const timeoutPromise = new Promise((_, reject) => {
118
+ setTimeout(() => {
119
+ reject(import_errors.RuntimeError.taskTimeout(agentId, taskTimeout));
120
+ }, taskTimeout);
121
+ });
122
+ const generatePromise = handle.agent.generate(task, handle.sessionId);
123
+ const response = await Promise.race([
124
+ generatePromise,
125
+ timeoutPromise
126
+ ]);
127
+ this.pool.updateStatus(agentId, "idle");
128
+ const result = {
129
+ success: true,
130
+ response: response.content,
131
+ agentId,
132
+ tokenUsage: {
133
+ input: response.usage.inputTokens,
134
+ output: response.usage.outputTokens,
135
+ total: response.usage.totalTokens
136
+ }
137
+ };
138
+ this.logger.debug(`Task completed for agent '${agentId}'`);
139
+ return result;
140
+ } catch (error) {
141
+ const errorMessage = error instanceof Error ? error.message : String(error);
142
+ this.pool.updateStatus(agentId, "error", errorMessage);
143
+ if (error instanceof Error && error.message.includes("Task execution timed out")) {
144
+ return {
145
+ success: false,
146
+ error: errorMessage,
147
+ agentId
148
+ };
149
+ }
150
+ throw import_errors.RuntimeError.taskFailed(agentId, errorMessage);
151
+ }
152
+ }
153
+ /**
154
+ * Get an agent handle by ID
155
+ */
156
+ getAgent(agentId) {
157
+ return this.pool.get(agentId);
158
+ }
159
+ /**
160
+ * List agents matching the given filter
161
+ */
162
+ listAgents(filter) {
163
+ return this.pool.list(filter);
164
+ }
165
+ /**
166
+ * Stop a specific agent
167
+ */
168
+ async stopAgent(agentId) {
169
+ const handle = this.pool.get(agentId);
170
+ if (!handle) {
171
+ throw import_errors.RuntimeError.agentNotFound(agentId);
172
+ }
173
+ if (handle.status === "stopped") {
174
+ this.logger.debug(`Agent '${agentId}' already stopped`);
175
+ return;
176
+ }
177
+ this.pool.updateStatus(agentId, "stopping");
178
+ try {
179
+ handle.agent.services.approvalManager.cancelAllApprovals();
180
+ await handle.agent.stop();
181
+ this.pool.updateStatus(agentId, "stopped");
182
+ this.logger.debug(`Stopped agent '${agentId}'`);
183
+ if (handle.ephemeral) {
184
+ this.pool.remove(agentId);
185
+ this.logger.debug(`Removed ephemeral agent '${agentId}' from pool`);
186
+ }
187
+ } catch (error) {
188
+ const errorMessage = error instanceof Error ? error.message : String(error);
189
+ this.pool.updateStatus(agentId, "error", errorMessage);
190
+ this.logger.error(`Failed to stop agent '${agentId}': ${errorMessage}`);
191
+ }
192
+ }
193
+ /**
194
+ * Stop all agents matching the given filter
195
+ */
196
+ async stopAll(filter) {
197
+ const agents = this.pool.list(filter);
198
+ this.logger.debug(`Stopping ${agents.length} agents`);
199
+ await Promise.allSettled(agents.map((handle) => this.stopAgent(handle.agentId)));
200
+ }
201
+ /**
202
+ * Get the runtime configuration
203
+ */
204
+ getConfig() {
205
+ return { ...this.config };
206
+ }
207
+ /**
208
+ * Get statistics about the runtime
209
+ */
210
+ getStats() {
211
+ const agents = this.pool.getAll();
212
+ const byStatus = {};
213
+ for (const agent of agents) {
214
+ byStatus[agent.status] = (byStatus[agent.status] ?? 0) + 1;
215
+ }
216
+ return {
217
+ totalAgents: agents.length,
218
+ byStatus
219
+ };
220
+ }
221
+ }
222
+ // Annotate the CommonJS export names for ESM import in node:
223
+ 0 && (module.exports = {
224
+ AgentRuntime
225
+ });
@@ -0,0 +1,77 @@
1
+ /**
2
+ * AgentRuntime - General-Purpose Agent Lifecycle Manager
3
+ *
4
+ * Manages the lifecycle of multiple agent instances. Can be used for:
5
+ * - Dashboard spawning multiple independent agents
6
+ * - Agent task delegation (parent spawns sub-agents)
7
+ * - Test harnesses managing multiple agents
8
+ * - Any scenario requiring multiple concurrent agents
9
+ *
10
+ * Key responsibilities:
11
+ * - Spawn and manage agents with configurable limits
12
+ * - Execute tasks on agents with timeout handling
13
+ * - Track agent status and lifecycle
14
+ * - Clean up agents when no longer needed
15
+ */
16
+ import { type IDextoLogger } from '@dexto/core';
17
+ import type { AgentRuntimeConfig, SpawnConfig, AgentHandle, TaskResult, AgentFilter } from './types.js';
18
+ import { type ValidatedAgentRuntimeConfig } from './schemas.js';
19
+ /**
20
+ * Options for creating an AgentRuntime
21
+ */
22
+ export interface AgentRuntimeOptions {
23
+ /** Runtime configuration */
24
+ config?: AgentRuntimeConfig;
25
+ /** Logger instance */
26
+ logger: IDextoLogger;
27
+ }
28
+ export declare class AgentRuntime {
29
+ private pool;
30
+ private config;
31
+ private logger;
32
+ constructor(options: AgentRuntimeOptions);
33
+ /**
34
+ * Spawn a new agent
35
+ *
36
+ * @param config - Configuration for the agent
37
+ * @returns Handle to the spawned agent
38
+ */
39
+ spawnAgent(config: SpawnConfig): Promise<AgentHandle>;
40
+ /**
41
+ * Execute a task on an agent
42
+ *
43
+ * @param agentId - ID of the agent
44
+ * @param task - Task description to execute
45
+ * @param timeout - Optional timeout in milliseconds
46
+ * @returns Task result with response or error
47
+ */
48
+ executeTask(agentId: string, task: string, timeout?: number): Promise<TaskResult>;
49
+ /**
50
+ * Get an agent handle by ID
51
+ */
52
+ getAgent(agentId: string): AgentHandle | undefined;
53
+ /**
54
+ * List agents matching the given filter
55
+ */
56
+ listAgents(filter?: AgentFilter): AgentHandle[];
57
+ /**
58
+ * Stop a specific agent
59
+ */
60
+ stopAgent(agentId: string): Promise<void>;
61
+ /**
62
+ * Stop all agents matching the given filter
63
+ */
64
+ stopAll(filter?: AgentFilter): Promise<void>;
65
+ /**
66
+ * Get the runtime configuration
67
+ */
68
+ getConfig(): ValidatedAgentRuntimeConfig;
69
+ /**
70
+ * Get statistics about the runtime
71
+ */
72
+ getStats(): {
73
+ totalAgents: number;
74
+ byStatus: Record<string, number>;
75
+ };
76
+ }
77
+ //# sourceMappingURL=AgentRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentRuntime.d.ts","sourceRoot":"","sources":["../../src/runtime/AgentRuntime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAc,KAAK,YAAY,EAAyB,MAAM,aAAa,CAAC;AAInF,OAAO,KAAK,EACR,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAA4B,KAAK,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAE1F;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,4BAA4B;IAC5B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,sBAAsB;IACtB,MAAM,EAAE,YAAY,CAAC;CACxB;AAED,qBAAa,YAAY;IACrB,OAAO,CAAC,IAAI,CAAY;IACxB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,MAAM,CAAe;gBAEjB,OAAO,EAAE,mBAAmB;IAYxC;;;;;OAKG;IACG,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IA0E3D;;;;;;;OAOG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAoEvF;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAIlD;;OAEG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE;IAI/C;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC/C;;OAEG;IACG,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IASlD;;OAEG;IACH,SAAS,IAAI,2BAA2B;IAIxC;;OAEG;IACH,QAAQ,IAAI;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE;CAaxE"}
@@ -0,0 +1,201 @@
1
+ import { randomUUID } from "crypto";
2
+ import { DextoAgent } from "@dexto/core";
3
+ import { enrichAgentConfig } from "../config/index.js";
4
+ import { AgentPool } from "./AgentPool.js";
5
+ import { RuntimeError } from "./errors.js";
6
+ import { AgentRuntimeConfigSchema } from "./schemas.js";
7
+ class AgentRuntime {
8
+ pool;
9
+ config;
10
+ logger;
11
+ constructor(options) {
12
+ this.config = AgentRuntimeConfigSchema.parse(options.config ?? {});
13
+ this.logger = options.logger;
14
+ this.pool = new AgentPool(this.config, this.logger);
15
+ this.logger.debug("AgentRuntime initialized", {
16
+ maxAgents: this.config.maxAgents,
17
+ defaultTaskTimeout: this.config.defaultTaskTimeout
18
+ });
19
+ }
20
+ /**
21
+ * Spawn a new agent
22
+ *
23
+ * @param config - Configuration for the agent
24
+ * @returns Handle to the spawned agent
25
+ */
26
+ async spawnAgent(config) {
27
+ if (!this.pool.canSpawn()) {
28
+ throw RuntimeError.maxAgentsExceeded(this.pool.size, this.config.maxAgents);
29
+ }
30
+ const agentId = config.agentId ?? `agent-${randomUUID().slice(0, 8)}`;
31
+ if (this.pool.has(agentId)) {
32
+ throw RuntimeError.agentAlreadyExists(agentId);
33
+ }
34
+ try {
35
+ const enrichedConfig = enrichAgentConfig(
36
+ config.agentConfig,
37
+ void 0,
38
+ // No config path
39
+ false
40
+ // Not interactive CLI
41
+ );
42
+ enrichedConfig.agentId = agentId;
43
+ const agent = new DextoAgent(enrichedConfig);
44
+ const sessionId = `session-${randomUUID().slice(0, 8)}`;
45
+ const handle = {
46
+ agentId,
47
+ agent,
48
+ status: "starting",
49
+ ephemeral: config.ephemeral ?? true,
50
+ createdAt: /* @__PURE__ */ new Date(),
51
+ sessionId
52
+ };
53
+ if (config.group !== void 0) {
54
+ handle.group = config.group;
55
+ }
56
+ if (config.metadata !== void 0) {
57
+ handle.metadata = config.metadata;
58
+ }
59
+ this.pool.add(handle);
60
+ if (config.onBeforeStart) {
61
+ await config.onBeforeStart(agent);
62
+ }
63
+ await agent.start();
64
+ this.pool.updateStatus(agentId, "idle");
65
+ this.logger.info(
66
+ `Spawned agent '${agentId}'${handle.group ? ` (group: ${handle.group})` : ""} (ephemeral: ${handle.ephemeral})`
67
+ );
68
+ return handle;
69
+ } catch (error) {
70
+ this.pool.remove(agentId);
71
+ const errorMessage = error instanceof Error ? error.message : String(error);
72
+ throw RuntimeError.spawnFailed(errorMessage, agentId);
73
+ }
74
+ }
75
+ /**
76
+ * Execute a task on an agent
77
+ *
78
+ * @param agentId - ID of the agent
79
+ * @param task - Task description to execute
80
+ * @param timeout - Optional timeout in milliseconds
81
+ * @returns Task result with response or error
82
+ */
83
+ async executeTask(agentId, task, timeout) {
84
+ const handle = this.pool.get(agentId);
85
+ if (!handle) {
86
+ throw RuntimeError.agentNotFound(agentId);
87
+ }
88
+ if (handle.status === "stopped" || handle.status === "error") {
89
+ throw RuntimeError.agentAlreadyStopped(agentId);
90
+ }
91
+ const taskTimeout = timeout ?? this.config.defaultTaskTimeout;
92
+ this.pool.updateStatus(agentId, "running");
93
+ try {
94
+ const timeoutPromise = new Promise((_, reject) => {
95
+ setTimeout(() => {
96
+ reject(RuntimeError.taskTimeout(agentId, taskTimeout));
97
+ }, taskTimeout);
98
+ });
99
+ const generatePromise = handle.agent.generate(task, handle.sessionId);
100
+ const response = await Promise.race([
101
+ generatePromise,
102
+ timeoutPromise
103
+ ]);
104
+ this.pool.updateStatus(agentId, "idle");
105
+ const result = {
106
+ success: true,
107
+ response: response.content,
108
+ agentId,
109
+ tokenUsage: {
110
+ input: response.usage.inputTokens,
111
+ output: response.usage.outputTokens,
112
+ total: response.usage.totalTokens
113
+ }
114
+ };
115
+ this.logger.debug(`Task completed for agent '${agentId}'`);
116
+ return result;
117
+ } catch (error) {
118
+ const errorMessage = error instanceof Error ? error.message : String(error);
119
+ this.pool.updateStatus(agentId, "error", errorMessage);
120
+ if (error instanceof Error && error.message.includes("Task execution timed out")) {
121
+ return {
122
+ success: false,
123
+ error: errorMessage,
124
+ agentId
125
+ };
126
+ }
127
+ throw RuntimeError.taskFailed(agentId, errorMessage);
128
+ }
129
+ }
130
+ /**
131
+ * Get an agent handle by ID
132
+ */
133
+ getAgent(agentId) {
134
+ return this.pool.get(agentId);
135
+ }
136
+ /**
137
+ * List agents matching the given filter
138
+ */
139
+ listAgents(filter) {
140
+ return this.pool.list(filter);
141
+ }
142
+ /**
143
+ * Stop a specific agent
144
+ */
145
+ async stopAgent(agentId) {
146
+ const handle = this.pool.get(agentId);
147
+ if (!handle) {
148
+ throw RuntimeError.agentNotFound(agentId);
149
+ }
150
+ if (handle.status === "stopped") {
151
+ this.logger.debug(`Agent '${agentId}' already stopped`);
152
+ return;
153
+ }
154
+ this.pool.updateStatus(agentId, "stopping");
155
+ try {
156
+ handle.agent.services.approvalManager.cancelAllApprovals();
157
+ await handle.agent.stop();
158
+ this.pool.updateStatus(agentId, "stopped");
159
+ this.logger.debug(`Stopped agent '${agentId}'`);
160
+ if (handle.ephemeral) {
161
+ this.pool.remove(agentId);
162
+ this.logger.debug(`Removed ephemeral agent '${agentId}' from pool`);
163
+ }
164
+ } catch (error) {
165
+ const errorMessage = error instanceof Error ? error.message : String(error);
166
+ this.pool.updateStatus(agentId, "error", errorMessage);
167
+ this.logger.error(`Failed to stop agent '${agentId}': ${errorMessage}`);
168
+ }
169
+ }
170
+ /**
171
+ * Stop all agents matching the given filter
172
+ */
173
+ async stopAll(filter) {
174
+ const agents = this.pool.list(filter);
175
+ this.logger.debug(`Stopping ${agents.length} agents`);
176
+ await Promise.allSettled(agents.map((handle) => this.stopAgent(handle.agentId)));
177
+ }
178
+ /**
179
+ * Get the runtime configuration
180
+ */
181
+ getConfig() {
182
+ return { ...this.config };
183
+ }
184
+ /**
185
+ * Get statistics about the runtime
186
+ */
187
+ getStats() {
188
+ const agents = this.pool.getAll();
189
+ const byStatus = {};
190
+ for (const agent of agents) {
191
+ byStatus[agent.status] = (byStatus[agent.status] ?? 0) + 1;
192
+ }
193
+ return {
194
+ totalAgents: agents.length,
195
+ byStatus
196
+ };
197
+ }
198
+ }
199
+ export {
200
+ AgentRuntime
201
+ };
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var approval_delegation_exports = {};
20
+ __export(approval_delegation_exports, {
21
+ createDelegatingApprovalHandler: () => createDelegatingApprovalHandler
22
+ });
23
+ module.exports = __toCommonJS(approval_delegation_exports);
24
+ function createDelegatingApprovalHandler(parentApprovalManager, subAgentId, logger) {
25
+ const pendingApprovalIds = /* @__PURE__ */ new Set();
26
+ const handler = Object.assign(
27
+ async (request) => {
28
+ logger.debug(
29
+ `Delegating approval '${request.approvalId}' (type: ${request.type}) from sub-agent '${subAgentId}'`
30
+ );
31
+ pendingApprovalIds.add(request.approvalId);
32
+ try {
33
+ const delegatedDetails = {
34
+ type: request.type,
35
+ timeout: request.timeout,
36
+ sessionId: request.sessionId,
37
+ metadata: {
38
+ ...request.metadata,
39
+ delegatedFromAgent: subAgentId
40
+ }
41
+ };
42
+ const response = await parentApprovalManager.requestApproval(delegatedDetails);
43
+ logger.debug(
44
+ `Approval '${request.approvalId}' delegated response: ${response.status}`
45
+ );
46
+ return response;
47
+ } finally {
48
+ pendingApprovalIds.delete(request.approvalId);
49
+ }
50
+ },
51
+ {
52
+ /**
53
+ * Cancel a specific pending approval request
54
+ */
55
+ cancel: (approvalId) => {
56
+ if (pendingApprovalIds.has(approvalId)) {
57
+ logger.debug(
58
+ `Cancelling delegated approval '${approvalId}' for sub-agent '${subAgentId}'`
59
+ );
60
+ parentApprovalManager.cancelApproval(approvalId);
61
+ pendingApprovalIds.delete(approvalId);
62
+ }
63
+ },
64
+ /**
65
+ * Cancel all pending approval requests for this sub-agent
66
+ */
67
+ cancelAll: () => {
68
+ if (pendingApprovalIds.size > 0) {
69
+ logger.debug(
70
+ `Cancelling all ${pendingApprovalIds.size} delegated approvals for sub-agent '${subAgentId}'`
71
+ );
72
+ for (const approvalId of pendingApprovalIds) {
73
+ parentApprovalManager.cancelApproval(approvalId);
74
+ }
75
+ pendingApprovalIds.clear();
76
+ }
77
+ },
78
+ /**
79
+ * Get list of pending approval IDs for this sub-agent
80
+ */
81
+ getPending: () => {
82
+ return Array.from(pendingApprovalIds);
83
+ },
84
+ /**
85
+ * Get pending approval requests (not available for delegated handlers)
86
+ */
87
+ getPendingRequests: () => {
88
+ return [];
89
+ }
90
+ }
91
+ );
92
+ return handler;
93
+ }
94
+ // Annotate the CommonJS export names for ESM import in node:
95
+ 0 && (module.exports = {
96
+ createDelegatingApprovalHandler
97
+ });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Approval Delegation for Sub-Agents
3
+ *
4
+ * Creates ApprovalHandler instances that delegate approval requests
5
+ * from sub-agents to the parent agent's approval system.
6
+ */
7
+ import type { ApprovalHandler, ApprovalManager, IDextoLogger } from '@dexto/core';
8
+ /**
9
+ * Creates an ApprovalHandler that delegates requests to a parent's ApprovalManager.
10
+ *
11
+ * This allows sub-agent tool approvals to flow through the parent's approval system,
12
+ * ensuring the user sees a unified approval UI regardless of which agent made the request.
13
+ *
14
+ * @param parentApprovalManager - The parent agent's ApprovalManager
15
+ * @param subAgentId - ID of the sub-agent for tracking
16
+ * @param logger - Logger for debugging
17
+ * @returns An ApprovalHandler that can be set on the sub-agent's ApprovalManager
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const delegatingHandler = createDelegatingApprovalHandler(
22
+ * parentAgent.services.approvalManager,
23
+ * subAgentId,
24
+ * logger
25
+ * );
26
+ * subAgent.services.approvalManager.setHandler(delegatingHandler);
27
+ * ```
28
+ */
29
+ export declare function createDelegatingApprovalHandler(parentApprovalManager: ApprovalManager, subAgentId: string, logger: IDextoLogger): ApprovalHandler;
30
+ //# sourceMappingURL=approval-delegation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-delegation.d.ts","sourceRoot":"","sources":["../../src/runtime/approval-delegation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACR,eAAe,EAIf,eAAe,EACf,YAAY,EACf,MAAM,aAAa,CAAC;AAYrB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,+BAA+B,CAC3C,qBAAqB,EAAE,eAAe,EACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,YAAY,GACrB,eAAe,CAqFjB"}