@dexto/agent-management 1.6.0 → 1.6.2

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 (69) hide show
  1. package/dist/agent-creation.cjs +2 -1
  2. package/dist/agent-creation.d.ts.map +1 -1
  3. package/dist/agent-creation.js +2 -1
  4. package/dist/config/config-enrichment.cjs +8 -3
  5. package/dist/config/config-enrichment.d.ts +6 -0
  6. package/dist/config/config-enrichment.d.ts.map +1 -1
  7. package/dist/config/config-enrichment.js +8 -3
  8. package/dist/index.cjs +3 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -0
  12. package/dist/models/custom-models.cjs +4 -3
  13. package/dist/models/custom-models.d.ts +26 -5
  14. package/dist/models/custom-models.d.ts.map +1 -1
  15. package/dist/models/custom-models.js +4 -3
  16. package/dist/preferences/loader.cjs +23 -8
  17. package/dist/preferences/loader.d.ts +7 -3
  18. package/dist/preferences/loader.d.ts.map +1 -1
  19. package/dist/preferences/loader.js +23 -8
  20. package/dist/preferences/schemas.cjs +47 -12
  21. package/dist/preferences/schemas.d.ts +92 -12
  22. package/dist/preferences/schemas.d.ts.map +1 -1
  23. package/dist/preferences/schemas.js +48 -8
  24. package/dist/registry/types.cjs +4 -0
  25. package/dist/registry/types.d.ts +8 -0
  26. package/dist/registry/types.d.ts.map +1 -1
  27. package/dist/registry/types.js +4 -0
  28. package/dist/runtime/AgentRuntime.cjs +23 -15
  29. package/dist/runtime/AgentRuntime.d.ts.map +1 -1
  30. package/dist/runtime/AgentRuntime.js +23 -15
  31. package/dist/runtime/approval-delegation.cjs +6 -3
  32. package/dist/runtime/approval-delegation.d.ts +2 -1
  33. package/dist/runtime/approval-delegation.d.ts.map +1 -1
  34. package/dist/runtime/approval-delegation.js +6 -3
  35. package/dist/runtime/schemas.cjs +1 -1
  36. package/dist/runtime/schemas.js +1 -1
  37. package/dist/runtime/types.d.ts +1 -1
  38. package/dist/runtime/types.d.ts.map +1 -1
  39. package/dist/tool-factories/agent-spawner/factory.cjs +63 -26
  40. package/dist/tool-factories/agent-spawner/factory.d.ts.map +1 -1
  41. package/dist/tool-factories/agent-spawner/factory.js +61 -24
  42. package/dist/tool-factories/agent-spawner/runtime.cjs +166 -15
  43. package/dist/tool-factories/agent-spawner/runtime.d.ts +8 -1
  44. package/dist/tool-factories/agent-spawner/runtime.d.ts.map +1 -1
  45. package/dist/tool-factories/agent-spawner/runtime.js +173 -17
  46. package/dist/tool-factories/agent-spawner/schemas.cjs +14 -2
  47. package/dist/tool-factories/agent-spawner/schemas.d.ts +10 -1
  48. package/dist/tool-factories/agent-spawner/schemas.d.ts.map +1 -1
  49. package/dist/tool-factories/agent-spawner/schemas.js +12 -2
  50. package/dist/tool-factories/agent-spawner/spawn-agent-tool.cjs +10 -1
  51. package/dist/tool-factories/agent-spawner/spawn-agent-tool.d.ts.map +1 -1
  52. package/dist/tool-factories/agent-spawner/spawn-agent-tool.js +10 -1
  53. package/dist/tool-factories/creator-tools/factory.cjs +434 -0
  54. package/dist/tool-factories/creator-tools/factory.d.ts +4 -0
  55. package/dist/tool-factories/creator-tools/factory.d.ts.map +1 -0
  56. package/dist/tool-factories/creator-tools/factory.js +407 -0
  57. package/dist/tool-factories/creator-tools/index.cjs +33 -0
  58. package/dist/tool-factories/creator-tools/index.d.ts +3 -0
  59. package/dist/tool-factories/creator-tools/index.d.ts.map +1 -0
  60. package/dist/tool-factories/creator-tools/index.js +10 -0
  61. package/dist/tool-factories/creator-tools/schemas.cjs +41 -0
  62. package/dist/tool-factories/creator-tools/schemas.d.ts +15 -0
  63. package/dist/tool-factories/creator-tools/schemas.d.ts.map +1 -0
  64. package/dist/tool-factories/creator-tools/schemas.js +16 -0
  65. package/dist/utils/path.cjs +10 -1
  66. package/dist/utils/path.d.ts +5 -2
  67. package/dist/utils/path.d.ts.map +1 -1
  68. package/dist/utils/path.js +10 -1
  69. package/package.json +6 -6
@@ -1,18 +1,70 @@
1
- import { DextoRuntimeError, ErrorType } from "@dexto/core";
1
+ import { randomUUID } from "crypto";
2
+ import {
3
+ DextoRuntimeError,
4
+ ErrorType,
5
+ getReasoningProfile,
6
+ supportsReasoningVariant
7
+ } from "@dexto/core";
2
8
  import { AgentRuntime } from "../../runtime/AgentRuntime.js";
3
9
  import { createDelegatingApprovalHandler } from "../../runtime/approval-delegation.js";
4
10
  import { loadAgentConfig } from "../../config/loader.js";
5
11
  import { getAgentRegistry } from "../../registry/registry.js";
6
12
  import { deriveDisplayName } from "../../registry/types.js";
7
- import { resolveBundledScript } from "../../utils/path.js";
13
+ import { getDextoPath, resolveBundledScript } from "../../utils/path.js";
8
14
  import * as path from "path";
9
15
  import { resolveSubAgentLLM } from "./llm-resolution.js";
16
+ const REASONING_VARIANT_FALLBACK_ORDER = [
17
+ "disabled",
18
+ "none",
19
+ "minimal",
20
+ "low",
21
+ "enabled",
22
+ "medium",
23
+ "high",
24
+ "max",
25
+ "xhigh"
26
+ ];
10
27
  class AgentSpawnerRuntime {
11
28
  runtime;
12
29
  parentId;
13
30
  parentAgent;
14
31
  config;
15
32
  logger;
33
+ selectLowestReasoningVariant(provider, model, preferredVariant) {
34
+ const profile = getReasoningProfile(provider, model);
35
+ if (!profile.capable || profile.supportedVariants.length === 0) {
36
+ return void 0;
37
+ }
38
+ if (supportsReasoningVariant(profile, preferredVariant)) {
39
+ return preferredVariant;
40
+ }
41
+ for (const variant of REASONING_VARIANT_FALLBACK_ORDER) {
42
+ if (supportsReasoningVariant(profile, variant)) {
43
+ return variant;
44
+ }
45
+ }
46
+ return profile.defaultVariant ?? profile.supportedVariants[0];
47
+ }
48
+ applySubAgentLlmPolicy(llm) {
49
+ const maxIterationsCap = this.config.subAgentMaxIterations;
50
+ const preferredReasoningVariant = this.config.subAgentReasoningVariant;
51
+ const reasoningVariant = this.selectLowestReasoningVariant(
52
+ llm.provider,
53
+ llm.model,
54
+ preferredReasoningVariant
55
+ );
56
+ const existingMaxIterations = llm.maxIterations;
57
+ const cappedMaxIterations = typeof existingMaxIterations === "number" ? Math.min(existingMaxIterations, maxIterationsCap) : maxIterationsCap;
58
+ const adjusted = {
59
+ ...llm,
60
+ maxIterations: cappedMaxIterations,
61
+ ...reasoningVariant !== void 0 ? { reasoning: { variant: reasoningVariant } } : { reasoning: void 0 }
62
+ };
63
+ this.logger.debug(
64
+ `[AgentSpawnerRuntime] Applied sub-agent LLM policy: maxIterations=${adjusted.maxIterations}, preferredReasoning=${preferredReasoningVariant}, selectedReasoning=${reasoningVariant ?? "none"}`
65
+ );
66
+ return adjusted;
67
+ }
16
68
  resolveBundledAgentConfig(agentId) {
17
69
  const baseDir = "agents";
18
70
  const normalizedPath = path.relative(baseDir, path.join(baseDir, agentId));
@@ -154,6 +206,10 @@ class AgentSpawnerRuntime {
154
206
  const tokenUsage = { input: 0, output: 0, total: 0 };
155
207
  let currentTool = "";
156
208
  const emitProgress = (tool, args) => {
209
+ const subAgentLogFilePath = this.getSubAgentLogFilePath({
210
+ runtimeAgentId: subAgentHandle.agentId,
211
+ sessionId
212
+ });
157
213
  this.parentAgent.emit("service:event", {
158
214
  service: "agent-spawner",
159
215
  event: "progress",
@@ -162,6 +218,8 @@ class AgentSpawnerRuntime {
162
218
  data: {
163
219
  task: input.task,
164
220
  agentId: input.agentId ?? "default",
221
+ runtimeAgentId: subAgentHandle.agentId,
222
+ ...subAgentLogFilePath ? { subAgentLogFilePath } : {},
165
223
  toolsCalled: toolCount,
166
224
  currentTool: tool,
167
225
  currentArgs: args,
@@ -201,6 +259,44 @@ class AgentSpawnerRuntime {
201
259
  subAgentHandle.agent.off("llm:response", responseHandler);
202
260
  };
203
261
  }
262
+ /**
263
+ * Ensure spawned agent inherits the parent's workspace context.
264
+ */
265
+ async applyParentWorkspace(agent) {
266
+ let parentWorkspace;
267
+ try {
268
+ parentWorkspace = await this.parentAgent.getWorkspace();
269
+ } catch (error) {
270
+ this.logger.warn(
271
+ `Failed to read parent workspace for sub-agent: ${error instanceof Error ? error.message : String(error)}`
272
+ );
273
+ return;
274
+ }
275
+ if (!parentWorkspace?.path) {
276
+ return;
277
+ }
278
+ try {
279
+ await agent.setWorkspace({
280
+ path: parentWorkspace.path,
281
+ ...parentWorkspace.name ? { name: parentWorkspace.name } : {}
282
+ });
283
+ } catch (error) {
284
+ this.logger.warn(
285
+ `Failed to apply parent workspace to sub-agent: ${error instanceof Error ? error.message : String(error)}`
286
+ );
287
+ }
288
+ }
289
+ getSubAgentLogFilePath(options) {
290
+ const { runtimeAgentId, sessionId } = options;
291
+ if (!sessionId) {
292
+ return null;
293
+ }
294
+ const safeSessionId = sessionId.replace(/[^a-zA-Z0-9._-]/g, "_");
295
+ return getDextoPath(
296
+ "logs",
297
+ path.join(this.parentId, `${safeSessionId}.subagent.${runtimeAgentId}.log`)
298
+ );
299
+ }
204
300
  /**
205
301
  * Check if an error is LLM-related (API errors, credit issues, model not found, etc.)
206
302
  */
@@ -222,7 +318,10 @@ class AgentSpawnerRuntime {
222
318
  let llmMode = "subagent";
223
319
  let cleanupProgressTracking;
224
320
  try {
225
- const buildOptions = {};
321
+ const buildOptions = {
322
+ // Pre-generate the runtime agentId so we can deterministically route logs.
323
+ runtimeAgentId: `agent-${randomUUID().slice(0, 8)}`
324
+ };
226
325
  if (input.agentId !== void 0) {
227
326
  buildOptions.agentId = input.agentId;
228
327
  }
@@ -233,6 +332,7 @@ class AgentSpawnerRuntime {
233
332
  let handle;
234
333
  try {
235
334
  handle = await this.runtime.spawnAgent({
335
+ agentId: buildOptions.runtimeAgentId,
236
336
  agentConfig: subAgentConfig,
237
337
  ephemeral: true,
238
338
  group: this.parentId,
@@ -247,6 +347,7 @@ class AgentSpawnerRuntime {
247
347
  const delegatingHandler = createDelegatingApprovalHandler(
248
348
  this.parentAgent.services.approvalManager,
249
349
  agent.config.agentId ?? "unknown",
350
+ sessionId,
250
351
  this.logger
251
352
  );
252
353
  agent.setApprovalHandler(delegatingHandler);
@@ -254,6 +355,7 @@ class AgentSpawnerRuntime {
254
355
  }
255
356
  });
256
357
  spawnedAgentId = handle.agentId;
358
+ await this.applyParentWorkspace(handle.agent);
257
359
  } catch (spawnError) {
258
360
  const isLlmError = this.isLLMError(spawnError);
259
361
  if (isLlmError && input.agentId && llmMode === "subagent") {
@@ -265,6 +367,7 @@ class AgentSpawnerRuntime {
265
367
  buildOptions.inheritLlm = true;
266
368
  subAgentConfig = await this.buildSubAgentConfig(buildOptions, sessionId);
267
369
  handle = await this.runtime.spawnAgent({
370
+ agentId: buildOptions.runtimeAgentId,
268
371
  agentConfig: subAgentConfig,
269
372
  ephemeral: true,
270
373
  group: this.parentId,
@@ -281,6 +384,7 @@ class AgentSpawnerRuntime {
281
384
  const delegatingHandler = createDelegatingApprovalHandler(
282
385
  this.parentAgent.services.approvalManager,
283
386
  agent.config.agentId ?? "unknown",
387
+ sessionId,
284
388
  this.logger
285
389
  );
286
390
  agent.setApprovalHandler(delegatingHandler);
@@ -288,6 +392,7 @@ class AgentSpawnerRuntime {
288
392
  }
289
393
  });
290
394
  spawnedAgentId = handle.agentId;
395
+ await this.applyParentWorkspace(handle.agent);
291
396
  } else {
292
397
  throw spawnError;
293
398
  }
@@ -295,6 +400,23 @@ class AgentSpawnerRuntime {
295
400
  this.logger.info(
296
401
  `Spawned sub-agent '${spawnedAgentId}' for task: ${input.task}${autoApprove ? " (auto-approve)" : ""}${llmMode === "parent" ? " (using parent LLM)" : ""}`
297
402
  );
403
+ const subAgentLogFilePath = this.getSubAgentLogFilePath(
404
+ sessionId ? { runtimeAgentId: buildOptions.runtimeAgentId, sessionId } : { runtimeAgentId: buildOptions.runtimeAgentId }
405
+ );
406
+ if (subAgentLogFilePath) {
407
+ this.logger.info(`Sub-agent logs: ${subAgentLogFilePath}`);
408
+ }
409
+ if (sessionId) {
410
+ const parentSession = await this.parentAgent.getSession(sessionId);
411
+ if (parentSession) {
412
+ parentSession.logger.info("Sub-agent spawned", {
413
+ runtimeAgentId: spawnedAgentId,
414
+ registryAgentId: input.agentId ?? "default",
415
+ task: input.task,
416
+ ...subAgentLogFilePath ? { subAgentLogFilePath } : {}
417
+ });
418
+ }
419
+ }
298
420
  cleanupProgressTracking = this.setupProgressTracking(
299
421
  handle,
300
422
  input,
@@ -328,6 +450,7 @@ class AgentSpawnerRuntime {
328
450
  buildOptions.inheritLlm = true;
329
451
  subAgentConfig = await this.buildSubAgentConfig(buildOptions, sessionId);
330
452
  handle = await this.runtime.spawnAgent({
453
+ agentId: buildOptions.runtimeAgentId,
331
454
  agentConfig: subAgentConfig,
332
455
  ephemeral: true,
333
456
  group: this.parentId,
@@ -344,6 +467,7 @@ class AgentSpawnerRuntime {
344
467
  const delegatingHandler = createDelegatingApprovalHandler(
345
468
  this.parentAgent.services.approvalManager,
346
469
  agent.config.agentId ?? "unknown",
470
+ sessionId,
347
471
  this.logger
348
472
  );
349
473
  agent.setApprovalHandler(delegatingHandler);
@@ -351,6 +475,7 @@ class AgentSpawnerRuntime {
351
475
  }
352
476
  });
353
477
  spawnedAgentId = handle.agentId;
478
+ await this.applyParentWorkspace(handle.agent);
354
479
  this.logger.info(
355
480
  `Re-spawned sub-agent '${spawnedAgentId}' for task: ${input.task} (using parent LLM)`
356
481
  );
@@ -410,13 +535,49 @@ class AgentSpawnerRuntime {
410
535
  * @param sessionId - Optional session ID to get session-specific LLM config
411
536
  */
412
537
  async buildSubAgentConfig(options, sessionId) {
413
- const { agentId, inheritLlm, autoApprove } = options;
538
+ const { agentId, inheritLlm, autoApprove, runtimeAgentId } = options;
414
539
  const parentSettings = this.parentAgent.config;
415
540
  const currentParentLLM = this.parentAgent.getCurrentLLMConfig(sessionId);
416
541
  this.logger.debug(
417
542
  `[AgentSpawnerRuntime] Building sub-agent config with LLM: ${currentParentLLM.provider}/${currentParentLLM.model}` + (sessionId ? ` (sessionId: ${sessionId})` : " (no sessionId)")
418
543
  );
419
544
  const permissionsMode = autoApprove ? "auto-approve" : "manual";
545
+ const parentToolPolicies = parentSettings.permissions?.toolPolicies;
546
+ const mergeToolPolicies = (subAgentPolicies) => {
547
+ const alwaysAllow = [
548
+ ...parentToolPolicies?.alwaysAllow ?? [],
549
+ ...subAgentPolicies?.alwaysAllow ?? []
550
+ ];
551
+ const alwaysDeny = [
552
+ ...parentToolPolicies?.alwaysDeny ?? [],
553
+ ...subAgentPolicies?.alwaysDeny ?? []
554
+ ];
555
+ return {
556
+ alwaysAllow: Array.from(new Set(alwaysAllow)),
557
+ alwaysDeny: Array.from(new Set(alwaysDeny))
558
+ };
559
+ };
560
+ const inheritedLoggerConfig = await (async () => {
561
+ if (!sessionId) {
562
+ return void 0;
563
+ }
564
+ const session = await this.parentAgent.getSession(sessionId);
565
+ if (!session) {
566
+ return void 0;
567
+ }
568
+ const parentSessionLogPath = session.logger.getLogFilePath();
569
+ if (!parentSessionLogPath) {
570
+ return void 0;
571
+ }
572
+ const subAgentLogFilePath = this.getSubAgentLogFilePath({ runtimeAgentId, sessionId });
573
+ if (!subAgentLogFilePath) {
574
+ return void 0;
575
+ }
576
+ return {
577
+ level: session.logger.getLevel(),
578
+ transports: [{ type: "file", path: subAgentLogFilePath }]
579
+ };
580
+ })();
420
581
  if (agentId) {
421
582
  let configPath = null;
422
583
  try {
@@ -454,18 +615,16 @@ class AgentSpawnerRuntime {
454
615
  this.logger.debug(`Sub-agent LLM resolution: ${resolution.reason}`);
455
616
  llmConfig = resolution.llm;
456
617
  }
618
+ llmConfig = this.applySubAgentLlmPolicy(llmConfig);
457
619
  return {
458
620
  ...loadedConfig,
459
621
  llm: llmConfig,
460
622
  permissions: {
461
623
  ...loadedConfig.permissions,
462
- mode: permissionsMode
624
+ mode: permissionsMode,
625
+ toolPolicies: mergeToolPolicies(loadedConfig.permissions?.toolPolicies)
463
626
  },
464
- // Suppress sub-agent console logs entirely using silent transport
465
- logger: {
466
- level: "error",
467
- transports: [{ type: "silent" }]
468
- }
627
+ ...inheritedLoggerConfig !== void 0 && { logger: inheritedLoggerConfig }
469
628
  };
470
629
  }
471
630
  this.logger.warn(
@@ -473,19 +632,16 @@ class AgentSpawnerRuntime {
473
632
  );
474
633
  }
475
634
  const config = {
476
- llm: { ...currentParentLLM },
635
+ llm: this.applySubAgentLlmPolicy({ ...currentParentLLM }),
477
636
  // Default system prompt for sub-agents
478
637
  systemPrompt: "You are a helpful sub-agent. Complete the task given to you efficiently and concisely.",
479
638
  permissions: {
480
- mode: permissionsMode
639
+ mode: permissionsMode,
640
+ toolPolicies: mergeToolPolicies(void 0)
481
641
  },
482
642
  // Inherit MCP servers from parent so subagent has tool access
483
643
  mcpServers: parentSettings.mcpServers ? { ...parentSettings.mcpServers } : {},
484
- // Suppress sub-agent console logs entirely using silent transport
485
- logger: {
486
- level: "error",
487
- transports: [{ type: "silent" }]
488
- }
644
+ ...inheritedLoggerConfig !== void 0 && { logger: inheritedLoggerConfig }
489
645
  };
490
646
  return config;
491
647
  }
@@ -19,17 +19,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var schemas_exports = {};
20
20
  __export(schemas_exports, {
21
21
  AgentSpawnerConfigSchema: () => AgentSpawnerConfigSchema,
22
+ DEFAULT_SUB_AGENT_MAX_ITERATIONS: () => DEFAULT_SUB_AGENT_MAX_ITERATIONS,
23
+ DEFAULT_SUB_AGENT_REASONING_VARIANT: () => DEFAULT_SUB_AGENT_REASONING_VARIANT,
22
24
  SpawnAgentInputSchema: () => SpawnAgentInputSchema
23
25
  });
24
26
  module.exports = __toCommonJS(schemas_exports);
25
27
  var import_zod = require("zod");
28
+ const DEFAULT_SUB_AGENT_MAX_ITERATIONS = 100;
29
+ const DEFAULT_SUB_AGENT_REASONING_VARIANT = "disabled";
26
30
  const AgentSpawnerConfigSchema = import_zod.z.object({
27
31
  /** Type discriminator for the factory */
28
32
  type: import_zod.z.literal("agent-spawner"),
29
33
  /** Maximum concurrent sub-agents this parent can spawn (default: 5) */
30
34
  maxConcurrentAgents: import_zod.z.number().int().positive().default(5).describe("Maximum concurrent sub-agents"),
31
- /** Default timeout for task execution in milliseconds (default: 300000 = 5 min) */
32
- defaultTimeout: import_zod.z.number().int().positive().default(3e5).describe("Default task timeout in milliseconds"),
35
+ /** Default timeout for task execution in milliseconds (default: 3600000 = 1 hour) */
36
+ defaultTimeout: import_zod.z.number().int().nonnegative().default(36e5).describe("Default task timeout in milliseconds (0 = no timeout)"),
37
+ subAgentMaxIterations: import_zod.z.number().int().positive().default(DEFAULT_SUB_AGENT_MAX_ITERATIONS).describe(
38
+ "Max outer-loop tool-call iterations for spawned sub-agents. Acts as a safety cap to prevent runaway exploration."
39
+ ),
40
+ subAgentReasoningVariant: import_zod.z.string().trim().min(1).default(DEFAULT_SUB_AGENT_REASONING_VARIANT).describe(
41
+ "Preferred reasoning variant for spawned sub-agents. Default is 'disabled'. If unsupported by the resolved model, Dexto falls back to the lowest available variant."
42
+ ),
33
43
  /** Whether spawning is enabled (default: true) */
34
44
  allowSpawning: import_zod.z.boolean().default(true).describe("Whether agent spawning is enabled"),
35
45
  /**
@@ -69,5 +79,7 @@ const SpawnAgentInputSchema = import_zod.z.object({
69
79
  // Annotate the CommonJS export names for ESM import in node:
70
80
  0 && (module.exports = {
71
81
  AgentSpawnerConfigSchema,
82
+ DEFAULT_SUB_AGENT_MAX_ITERATIONS,
83
+ DEFAULT_SUB_AGENT_REASONING_VARIANT,
72
84
  SpawnAgentInputSchema
73
85
  });
@@ -3,7 +3,10 @@
3
3
  *
4
4
  * Zod schemas for the agent spawner tools factory configuration and inputs.
5
5
  */
6
+ import type { ReasoningVariant } from '@dexto/core';
6
7
  import { z } from 'zod';
8
+ export declare const DEFAULT_SUB_AGENT_MAX_ITERATIONS = 100;
9
+ export declare const DEFAULT_SUB_AGENT_REASONING_VARIANT: ReasoningVariant;
7
10
  /**
8
11
  * Configuration schema for the agent spawner tools factory.
9
12
  */
@@ -12,8 +15,10 @@ export declare const AgentSpawnerConfigSchema: z.ZodObject<{
12
15
  type: z.ZodLiteral<"agent-spawner">;
13
16
  /** Maximum concurrent sub-agents this parent can spawn (default: 5) */
14
17
  maxConcurrentAgents: z.ZodDefault<z.ZodNumber>;
15
- /** Default timeout for task execution in milliseconds (default: 300000 = 5 min) */
18
+ /** Default timeout for task execution in milliseconds (default: 3600000 = 1 hour) */
16
19
  defaultTimeout: z.ZodDefault<z.ZodNumber>;
20
+ subAgentMaxIterations: z.ZodDefault<z.ZodNumber>;
21
+ subAgentReasoningVariant: z.ZodDefault<z.ZodString>;
17
22
  /** Whether spawning is enabled (default: true) */
18
23
  allowSpawning: z.ZodDefault<z.ZodBoolean>;
19
24
  /**
@@ -45,6 +50,8 @@ export declare const AgentSpawnerConfigSchema: z.ZodObject<{
45
50
  type: "agent-spawner";
46
51
  maxConcurrentAgents: number;
47
52
  defaultTimeout: number;
53
+ subAgentMaxIterations: number;
54
+ subAgentReasoningVariant: string;
48
55
  allowSpawning: boolean;
49
56
  allowedAgents?: string[] | undefined;
50
57
  autoApproveAgents?: string[] | undefined;
@@ -52,6 +59,8 @@ export declare const AgentSpawnerConfigSchema: z.ZodObject<{
52
59
  type: "agent-spawner";
53
60
  maxConcurrentAgents?: number | undefined;
54
61
  defaultTimeout?: number | undefined;
62
+ subAgentMaxIterations?: number | undefined;
63
+ subAgentReasoningVariant?: string | undefined;
55
64
  allowSpawning?: boolean | undefined;
56
65
  allowedAgents?: string[] | undefined;
57
66
  autoApproveAgents?: string[] | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/agent-spawner/schemas.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;GAEG;AACH,eAAO,MAAM,wBAAwB;IAE7B,yCAAyC;;IAGzC,uEAAuE;;IAQvE,mFAAmF;;IAQnF,kDAAkD;;IAGlD;;;;;;;;;;OAUG;;IAMH;;;;;;;;;;;OAWG;;;;;;;;;;;;;;;;EAOuD,CAAC;AAEnE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAM3E;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;IAE1B,gDAAgD;;IAGhD,8CAA8C;;IAM9C,qFAAqF;;;;;;;;;;EAGhF,CAAC;AAEd,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/agent-spawner/schemas.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,mCAAmC,EAAE,gBAA6B,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,wBAAwB;IAE7B,yCAAyC;;IAGzC,uEAAuE;;IAQvE,qFAAqF;;;;IA4BrF,kDAAkD;;IAGlD;;;;;;;;;;OAUG;;IAMH;;;;;;;;;;;OAWG;;;;;;;;;;;;;;;;;;;;EAOuD,CAAC;AAEnE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAM3E;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;IAE1B,gDAAgD;;IAGhD,8CAA8C;;IAM9C,qFAAqF;;;;;;;;;;EAGhF,CAAC;AAEd,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -1,11 +1,19 @@
1
1
  import { z } from "zod";
2
+ const DEFAULT_SUB_AGENT_MAX_ITERATIONS = 100;
3
+ const DEFAULT_SUB_AGENT_REASONING_VARIANT = "disabled";
2
4
  const AgentSpawnerConfigSchema = z.object({
3
5
  /** Type discriminator for the factory */
4
6
  type: z.literal("agent-spawner"),
5
7
  /** Maximum concurrent sub-agents this parent can spawn (default: 5) */
6
8
  maxConcurrentAgents: z.number().int().positive().default(5).describe("Maximum concurrent sub-agents"),
7
- /** Default timeout for task execution in milliseconds (default: 300000 = 5 min) */
8
- defaultTimeout: z.number().int().positive().default(3e5).describe("Default task timeout in milliseconds"),
9
+ /** Default timeout for task execution in milliseconds (default: 3600000 = 1 hour) */
10
+ defaultTimeout: z.number().int().nonnegative().default(36e5).describe("Default task timeout in milliseconds (0 = no timeout)"),
11
+ subAgentMaxIterations: z.number().int().positive().default(DEFAULT_SUB_AGENT_MAX_ITERATIONS).describe(
12
+ "Max outer-loop tool-call iterations for spawned sub-agents. Acts as a safety cap to prevent runaway exploration."
13
+ ),
14
+ subAgentReasoningVariant: z.string().trim().min(1).default(DEFAULT_SUB_AGENT_REASONING_VARIANT).describe(
15
+ "Preferred reasoning variant for spawned sub-agents. Default is 'disabled'. If unsupported by the resolved model, Dexto falls back to the lowest available variant."
16
+ ),
9
17
  /** Whether spawning is enabled (default: true) */
10
18
  allowSpawning: z.boolean().default(true).describe("Whether agent spawning is enabled"),
11
19
  /**
@@ -44,5 +52,7 @@ const SpawnAgentInputSchema = z.object({
44
52
  }).strict();
45
53
  export {
46
54
  AgentSpawnerConfigSchema,
55
+ DEFAULT_SUB_AGENT_MAX_ITERATIONS,
56
+ DEFAULT_SUB_AGENT_REASONING_VARIANT,
47
57
  SpawnAgentInputSchema
48
58
  };
@@ -21,6 +21,7 @@ __export(spawn_agent_tool_exports, {
21
21
  createSpawnAgentTool: () => createSpawnAgentTool
22
22
  });
23
23
  module.exports = __toCommonJS(spawn_agent_tool_exports);
24
+ var import_core = require("@dexto/core");
24
25
  var import_schemas = require("./schemas.js");
25
26
  function buildDescription(service) {
26
27
  const availableAgents = service.getAvailableAgents();
@@ -57,9 +58,17 @@ ${agentsList}
57
58
  function createSpawnAgentTool(service) {
58
59
  return {
59
60
  id: "spawn_agent",
60
- displayName: "Agent",
61
61
  aliases: ["task"],
62
62
  description: buildDescription(service),
63
+ presentation: {
64
+ describeHeader: (input) => {
65
+ const agentLabel = input.agentId ? input.agentId.replace(/-agent$/, "") : null;
66
+ const title = agentLabel ? agentLabel.charAt(0).toUpperCase() + agentLabel.slice(1) : "Agent";
67
+ const task = typeof input.task === "string" ? input.task : "";
68
+ const argsText = task ? (0, import_core.truncateForHeader)(task, 120) : void 0;
69
+ return (0, import_core.createLocalToolCallHeader)({ title, ...argsText ? { argsText } : {} });
70
+ }
71
+ },
63
72
  inputSchema: import_schemas.SpawnAgentInputSchema,
64
73
  execute: async (input, context) => {
65
74
  const options = {
@@ -1 +1 @@
1
- {"version":3,"file":"spawn-agent-tool.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/agent-spawner/spawn-agent-tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AA4CxD,wBAAgB,oBAAoB,CAChC,OAAO,EAAE,mBAAmB,GAC7B,IAAI,CAAC,OAAO,qBAAqB,CAAC,CA0CpC"}
1
+ {"version":3,"file":"spawn-agent-tool.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/agent-spawner/spawn-agent-tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AA4CxD,wBAAgB,oBAAoB,CAChC,OAAO,EAAE,mBAAmB,GAC7B,IAAI,CAAC,OAAO,qBAAqB,CAAC,CAuDpC"}
@@ -1,3 +1,4 @@
1
+ import { createLocalToolCallHeader, truncateForHeader } from "@dexto/core";
1
2
  import { SpawnAgentInputSchema } from "./schemas.js";
2
3
  function buildDescription(service) {
3
4
  const availableAgents = service.getAvailableAgents();
@@ -34,9 +35,17 @@ ${agentsList}
34
35
  function createSpawnAgentTool(service) {
35
36
  return {
36
37
  id: "spawn_agent",
37
- displayName: "Agent",
38
38
  aliases: ["task"],
39
39
  description: buildDescription(service),
40
+ presentation: {
41
+ describeHeader: (input) => {
42
+ const agentLabel = input.agentId ? input.agentId.replace(/-agent$/, "") : null;
43
+ const title = agentLabel ? agentLabel.charAt(0).toUpperCase() + agentLabel.slice(1) : "Agent";
44
+ const task = typeof input.task === "string" ? input.task : "";
45
+ const argsText = task ? truncateForHeader(task, 120) : void 0;
46
+ return createLocalToolCallHeader({ title, ...argsText ? { argsText } : {} });
47
+ }
48
+ },
40
49
  inputSchema: SpawnAgentInputSchema,
41
50
  execute: async (input, context) => {
42
51
  const options = {