@dexto/agent-management 1.5.7 → 1.5.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.
- package/dist/config/config-enrichment.cjs +2 -1
- package/dist/config/config-enrichment.d.ts.map +1 -1
- package/dist/config/config-enrichment.js +2 -1
- package/dist/index.cjs +11 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/models/custom-models.cjs +1 -1
- package/dist/models/custom-models.d.ts +7 -7
- package/dist/models/custom-models.d.ts.map +1 -1
- package/dist/models/custom-models.js +1 -1
- package/dist/plugins/discover-skills.cjs +4 -0
- package/dist/plugins/discover-skills.d.ts +6 -3
- package/dist/plugins/discover-skills.d.ts.map +1 -1
- package/dist/plugins/discover-skills.js +4 -0
- package/dist/preferences/errors.cjs +11 -0
- package/dist/preferences/errors.d.ts +1 -0
- package/dist/preferences/errors.d.ts.map +1 -1
- package/dist/preferences/errors.js +11 -0
- package/dist/preferences/loader.cjs +119 -6
- package/dist/preferences/loader.d.ts +21 -1
- package/dist/preferences/loader.d.ts.map +1 -1
- package/dist/preferences/loader.js +102 -1
- package/dist/preferences/schemas.cjs +12 -0
- package/dist/preferences/schemas.d.ts +38 -12
- package/dist/preferences/schemas.d.ts.map +1 -1
- package/dist/preferences/schemas.js +10 -0
- package/dist/tool-provider/llm-resolution.cjs +1 -1
- package/dist/tool-provider/llm-resolution.d.ts +4 -4
- package/dist/tool-provider/llm-resolution.js +1 -1
- package/dist/tool-provider/runtime-service.cjs +90 -13
- package/dist/tool-provider/runtime-service.d.ts +2 -0
- package/dist/tool-provider/runtime-service.d.ts.map +1 -1
- package/dist/tool-provider/runtime-service.js +80 -13
- package/dist/tool-provider/tool-provider.cjs +152 -1
- package/dist/tool-provider/tool-provider.d.ts +7 -1
- package/dist/tool-provider/tool-provider.d.ts.map +1 -1
- package/dist/tool-provider/tool-provider.js +159 -1
- package/dist/utils/api-key-resolver.cjs +1 -1
- package/dist/utils/api-key-resolver.js +1 -1
- package/dist/utils/feature-flags.cjs +3 -1
- package/dist/utils/feature-flags.d.ts +2 -2
- package/dist/utils/feature-flags.d.ts.map +1 -1
- package/dist/utils/feature-flags.js +3 -1
- package/package.json +3 -2
|
@@ -3,6 +3,9 @@ import { AgentRuntime } from "../runtime/AgentRuntime.js";
|
|
|
3
3
|
import { createDelegatingApprovalHandler } from "../runtime/approval-delegation.js";
|
|
4
4
|
import { loadAgentConfig } from "../config/loader.js";
|
|
5
5
|
import { getAgentRegistry } from "../registry/registry.js";
|
|
6
|
+
import { deriveDisplayName } from "../registry/types.js";
|
|
7
|
+
import { resolveBundledScript } from "../utils/path.js";
|
|
8
|
+
import * as path from "path";
|
|
6
9
|
import { resolveSubAgentLLM } from "./llm-resolution.js";
|
|
7
10
|
class RuntimeService {
|
|
8
11
|
runtime;
|
|
@@ -10,6 +13,37 @@ class RuntimeService {
|
|
|
10
13
|
parentAgent;
|
|
11
14
|
config;
|
|
12
15
|
logger;
|
|
16
|
+
resolveBundledAgentConfig(agentId) {
|
|
17
|
+
const baseDir = "agents";
|
|
18
|
+
const normalizedPath = path.relative(baseDir, path.join(baseDir, agentId));
|
|
19
|
+
if (normalizedPath.startsWith("..") || path.isAbsolute(normalizedPath)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const candidates = [
|
|
23
|
+
`agents/${agentId}/${agentId}.yml`,
|
|
24
|
+
`agents/${agentId}/${agentId}.yaml`,
|
|
25
|
+
`agents/${agentId}.yml`,
|
|
26
|
+
`agents/${agentId}.yaml`
|
|
27
|
+
];
|
|
28
|
+
for (const candidate of candidates) {
|
|
29
|
+
try {
|
|
30
|
+
return resolveBundledScript(candidate);
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
createFallbackRegistryEntry(agentId) {
|
|
37
|
+
return {
|
|
38
|
+
id: agentId,
|
|
39
|
+
name: deriveDisplayName(agentId),
|
|
40
|
+
description: "Agent specified in config (registry entry not found)",
|
|
41
|
+
author: "unknown",
|
|
42
|
+
tags: [],
|
|
43
|
+
source: agentId,
|
|
44
|
+
type: "custom"
|
|
45
|
+
};
|
|
46
|
+
}
|
|
13
47
|
constructor(parentAgent, config, logger) {
|
|
14
48
|
this.parentAgent = parentAgent;
|
|
15
49
|
this.config = config;
|
|
@@ -407,12 +441,26 @@ class RuntimeService {
|
|
|
407
441
|
);
|
|
408
442
|
const toolConfirmationMode = autoApprove ? "auto-approve" : "manual";
|
|
409
443
|
if (agentId) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
444
|
+
let configPath = null;
|
|
445
|
+
try {
|
|
446
|
+
const registry = getAgentRegistry();
|
|
447
|
+
if (!registry.hasAgent(agentId)) {
|
|
448
|
+
this.logger.warn(
|
|
449
|
+
`Agent '${agentId}' not found in registry. Trying bundled config paths.`
|
|
450
|
+
);
|
|
451
|
+
} else {
|
|
452
|
+
configPath = await registry.resolveAgent(agentId);
|
|
453
|
+
}
|
|
454
|
+
} catch (error) {
|
|
455
|
+
this.logger.warn(
|
|
456
|
+
`Failed to load agent registry for '${agentId}'. Trying bundled config paths. (${error instanceof Error ? error.message : String(error)})`
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
if (!configPath) {
|
|
460
|
+
configPath = this.resolveBundledAgentConfig(agentId);
|
|
461
|
+
}
|
|
462
|
+
if (configPath) {
|
|
463
|
+
this.logger.debug(`Loading agent config from registry/bundled path: ${configPath}`);
|
|
416
464
|
const loadedConfig = await loadAgentConfig(configPath, this.logger);
|
|
417
465
|
let llmConfig = loadedConfig.llm;
|
|
418
466
|
if (inheritLlm) {
|
|
@@ -429,6 +477,9 @@ class RuntimeService {
|
|
|
429
477
|
this.logger.debug(`Sub-agent LLM resolution: ${resolution.reason}`);
|
|
430
478
|
llmConfig = resolution.llm;
|
|
431
479
|
}
|
|
480
|
+
const filteredCustomTools = loadedConfig.customTools ? loadedConfig.customTools.filter(
|
|
481
|
+
(tool) => typeof tool === "object" && tool !== null && "type" in tool && tool.type !== "agent-spawner"
|
|
482
|
+
) : void 0;
|
|
432
483
|
return {
|
|
433
484
|
...loadedConfig,
|
|
434
485
|
llm: llmConfig,
|
|
@@ -436,6 +487,7 @@ class RuntimeService {
|
|
|
436
487
|
...loadedConfig.toolConfirmation,
|
|
437
488
|
mode: toolConfirmationMode
|
|
438
489
|
},
|
|
490
|
+
customTools: filteredCustomTools,
|
|
439
491
|
// Suppress sub-agent console logs entirely using silent transport
|
|
440
492
|
logger: {
|
|
441
493
|
level: "error",
|
|
@@ -443,6 +495,9 @@ class RuntimeService {
|
|
|
443
495
|
}
|
|
444
496
|
};
|
|
445
497
|
}
|
|
498
|
+
this.logger.warn(
|
|
499
|
+
`Agent '${agentId}' not found in registry or bundled paths. Using default config.`
|
|
500
|
+
);
|
|
446
501
|
}
|
|
447
502
|
const config = {
|
|
448
503
|
llm: { ...currentParentLLM },
|
|
@@ -459,8 +514,11 @@ class RuntimeService {
|
|
|
459
514
|
internalTools: parentConfig.internalTools ? parentConfig.internalTools.filter(
|
|
460
515
|
(tool) => tool !== "ask_user" && tool !== "invoke_skill"
|
|
461
516
|
) : [],
|
|
462
|
-
// Inherit custom tools from parent
|
|
463
|
-
|
|
517
|
+
// Inherit custom tools from parent, excluding agent-spawner to prevent nested spawning (depth=1 limit)
|
|
518
|
+
// - agent-spawner: Sub-agents should not spawn their own sub-agents
|
|
519
|
+
customTools: parentConfig.customTools ? parentConfig.customTools.filter(
|
|
520
|
+
(tool) => typeof tool === "object" && tool !== null && "type" in tool && tool.type !== "agent-spawner"
|
|
521
|
+
) : [],
|
|
464
522
|
// Suppress sub-agent console logs entirely using silent transport
|
|
465
523
|
logger: {
|
|
466
524
|
level: "error",
|
|
@@ -474,15 +532,24 @@ class RuntimeService {
|
|
|
474
532
|
* Returns agent metadata from registry, filtered by allowedAgents if configured.
|
|
475
533
|
*/
|
|
476
534
|
getAvailableAgents() {
|
|
477
|
-
|
|
478
|
-
|
|
535
|
+
let allAgents;
|
|
536
|
+
try {
|
|
537
|
+
const registry = getAgentRegistry();
|
|
538
|
+
allAgents = registry.getAvailableAgents();
|
|
539
|
+
} catch (error) {
|
|
540
|
+
this.logger.warn(
|
|
541
|
+
`Failed to load agent registry for spawn_agent description: ${error instanceof Error ? error.message : String(error)}`
|
|
542
|
+
);
|
|
543
|
+
if (this.config.allowedAgents && this.config.allowedAgents.length > 0) {
|
|
544
|
+
return this.config.allowedAgents.map((id) => this.createFallbackRegistryEntry(id));
|
|
545
|
+
}
|
|
546
|
+
return [];
|
|
547
|
+
}
|
|
479
548
|
if (this.config.allowedAgents && this.config.allowedAgents.length > 0) {
|
|
480
549
|
const result = [];
|
|
481
550
|
for (const id of this.config.allowedAgents) {
|
|
482
551
|
const agent = allAgents[id];
|
|
483
|
-
|
|
484
|
-
result.push(agent);
|
|
485
|
-
}
|
|
552
|
+
result.push(agent ?? this.createFallbackRegistryEntry(id));
|
|
486
553
|
}
|
|
487
554
|
return result;
|
|
488
555
|
}
|
|
@@ -21,18 +21,169 @@ __export(tool_provider_exports, {
|
|
|
21
21
|
agentSpawnerToolsProvider: () => agentSpawnerToolsProvider
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(tool_provider_exports);
|
|
24
|
+
var import_orchestration = require("@dexto/orchestration");
|
|
24
25
|
var import_schemas = require("./schemas.js");
|
|
25
26
|
var import_runtime_service = require("./runtime-service.js");
|
|
26
27
|
var import_spawn_agent_tool = require("./spawn-agent-tool.js");
|
|
28
|
+
function bindOrchestrationTool(tool, context) {
|
|
29
|
+
return {
|
|
30
|
+
id: tool.id,
|
|
31
|
+
description: tool.description,
|
|
32
|
+
inputSchema: tool.inputSchema,
|
|
33
|
+
execute: (input) => tool.execute(input, context)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
27
36
|
const agentSpawnerToolsProvider = {
|
|
28
37
|
type: "agent-spawner",
|
|
29
38
|
configSchema: import_schemas.AgentSpawnerConfigSchema,
|
|
30
39
|
create: (config, context) => {
|
|
31
40
|
const { logger, agent } = context;
|
|
41
|
+
const signalBus = new import_orchestration.SignalBus();
|
|
42
|
+
const taskRegistry = new import_orchestration.TaskRegistry(signalBus);
|
|
43
|
+
const conditionEngine = new import_orchestration.ConditionEngine(taskRegistry, signalBus, logger);
|
|
44
|
+
const toolContext = {
|
|
45
|
+
taskRegistry,
|
|
46
|
+
conditionEngine,
|
|
47
|
+
signalBus
|
|
48
|
+
};
|
|
32
49
|
const service = new import_runtime_service.RuntimeService(agent, config, logger);
|
|
33
50
|
agent.toolManager.setTaskForker(service);
|
|
34
51
|
logger.debug("RuntimeService wired as taskForker for context:fork skill support");
|
|
35
|
-
|
|
52
|
+
const taskSessions = /* @__PURE__ */ new Map();
|
|
53
|
+
const emitTasksUpdate = (sessionId) => {
|
|
54
|
+
const tasks = taskRegistry.list({
|
|
55
|
+
status: ["running", "completed", "failed", "cancelled"]
|
|
56
|
+
});
|
|
57
|
+
const scopedTasks = sessionId ? tasks.filter((task) => taskSessions.get(task.taskId) === sessionId) : tasks;
|
|
58
|
+
const runningCount = scopedTasks.filter((task) => task.status === "running").length;
|
|
59
|
+
agent.agentEventBus.emit("service:event", {
|
|
60
|
+
service: "orchestration",
|
|
61
|
+
event: "tasks-updated",
|
|
62
|
+
sessionId: sessionId ?? "",
|
|
63
|
+
data: {
|
|
64
|
+
runningCount,
|
|
65
|
+
tasks: scopedTasks.map((task) => ({
|
|
66
|
+
taskId: task.taskId,
|
|
67
|
+
status: task.status,
|
|
68
|
+
...task.description !== void 0 && { description: task.description }
|
|
69
|
+
}))
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
const triggerBackgroundCompletion = (taskId, sessionId) => {
|
|
74
|
+
if (!sessionId) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
agent.agentEventBus.emit("tool:background-completed", {
|
|
78
|
+
toolCallId: taskId,
|
|
79
|
+
sessionId
|
|
80
|
+
});
|
|
81
|
+
const taskInfo = taskRegistry.getInfo(taskId);
|
|
82
|
+
const resultText = (() => {
|
|
83
|
+
if (taskInfo?.status === "failed") {
|
|
84
|
+
return taskInfo.error ?? "Unknown error.";
|
|
85
|
+
}
|
|
86
|
+
if (taskInfo?.result !== void 0) {
|
|
87
|
+
if (typeof taskInfo.result === "string") {
|
|
88
|
+
return taskInfo.result;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
return JSON.stringify(taskInfo.result, null, 2);
|
|
92
|
+
} catch {
|
|
93
|
+
return String(taskInfo.result ?? "<unserializable result>");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return "No result available.";
|
|
97
|
+
})();
|
|
98
|
+
const sanitizeCdata = (value) => value.replace(/\]\]>/g, "]]]]><![CDATA[>");
|
|
99
|
+
const safeDescription = taskInfo?.description ? sanitizeCdata(taskInfo.description) : null;
|
|
100
|
+
const safeResultText = sanitizeCdata(resultText);
|
|
101
|
+
const descriptionTag = safeDescription ? ` <description><![CDATA[${safeDescription}]]></description>
|
|
102
|
+
` : "";
|
|
103
|
+
const statusTag = taskInfo?.status ? ` <status>${taskInfo.status}</status>
|
|
104
|
+
` : "";
|
|
105
|
+
const content = [
|
|
106
|
+
{
|
|
107
|
+
type: "text",
|
|
108
|
+
text: `<background-task-completion>
|
|
109
|
+
<origin>task</origin>
|
|
110
|
+
<note>The following response was reported by the background task (not user input).</note>
|
|
111
|
+
<taskId>${taskId}</taskId>
|
|
112
|
+
` + statusTag + descriptionTag + ` <result><![CDATA[${safeResultText}]]></result>
|
|
113
|
+
</background-task-completion>`
|
|
114
|
+
}
|
|
115
|
+
];
|
|
116
|
+
agent.isSessionBusy(sessionId).then((isBusy) => {
|
|
117
|
+
if (isBusy) {
|
|
118
|
+
agent.queueMessage(sessionId, {
|
|
119
|
+
content,
|
|
120
|
+
kind: "background"
|
|
121
|
+
}).catch(() => void 0);
|
|
122
|
+
} else {
|
|
123
|
+
agent.agentEventBus.emit("run:invoke", {
|
|
124
|
+
sessionId,
|
|
125
|
+
content,
|
|
126
|
+
source: "external",
|
|
127
|
+
metadata: { taskId }
|
|
128
|
+
});
|
|
129
|
+
agent.generate(content, sessionId).catch(() => void 0);
|
|
130
|
+
}
|
|
131
|
+
}).catch(() => {
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
const handleBackground = (event) => {
|
|
135
|
+
const taskId = event.toolCallId;
|
|
136
|
+
if (taskRegistry.has(taskId)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (event.sessionId) {
|
|
140
|
+
taskSessions.set(taskId, event.sessionId);
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
taskRegistry.register(
|
|
144
|
+
{
|
|
145
|
+
type: "generic",
|
|
146
|
+
taskId,
|
|
147
|
+
description: event.description ?? `Tool ${event.toolName}`,
|
|
148
|
+
promise: event.promise
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
...event.timeoutMs !== void 0 && { timeout: event.timeoutMs },
|
|
152
|
+
...event.notifyOnComplete !== void 0 && {
|
|
153
|
+
notify: event.notifyOnComplete
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
taskSessions.delete(taskId);
|
|
159
|
+
event.promise.catch(() => void 0);
|
|
160
|
+
logger.warn(
|
|
161
|
+
`Failed to register background task ${taskId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
162
|
+
{ color: "yellow" }
|
|
163
|
+
);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
emitTasksUpdate(event.sessionId);
|
|
167
|
+
event.promise.finally(() => {
|
|
168
|
+
taskSessions.delete(taskId);
|
|
169
|
+
emitTasksUpdate(event.sessionId);
|
|
170
|
+
triggerBackgroundCompletion(taskId, event.sessionId);
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
const backgroundAbortController = new AbortController();
|
|
174
|
+
agent.agentEventBus.on("tool:background", handleBackground, {
|
|
175
|
+
signal: backgroundAbortController.signal
|
|
176
|
+
});
|
|
177
|
+
agent.agentEventBus.on("agent:stopped", () => {
|
|
178
|
+
backgroundAbortController.abort();
|
|
179
|
+
});
|
|
180
|
+
const tool = (0, import_spawn_agent_tool.createSpawnAgentTool)(service);
|
|
181
|
+
return [
|
|
182
|
+
tool,
|
|
183
|
+
bindOrchestrationTool((0, import_orchestration.createWaitForTool)(), toolContext),
|
|
184
|
+
bindOrchestrationTool((0, import_orchestration.createCheckTaskTool)(), toolContext),
|
|
185
|
+
bindOrchestrationTool((0, import_orchestration.createListTasksTool)(), toolContext)
|
|
186
|
+
];
|
|
36
187
|
},
|
|
37
188
|
metadata: {
|
|
38
189
|
displayName: "Agent Spawner",
|
|
@@ -8,7 +8,13 @@ import { type AgentSpawnerConfig } from './schemas.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* Agent Spawner Tools Provider
|
|
10
10
|
*
|
|
11
|
-
* Provides
|
|
11
|
+
* Provides tools for spawning and managing sub-agents:
|
|
12
|
+
* - spawn_agent: Spawn a sub-agent to handle a task
|
|
13
|
+
*
|
|
14
|
+
* Orchestration tools (for background task management):
|
|
15
|
+
* - wait_for: Wait for background task(s) to complete
|
|
16
|
+
* - check_task: Check status of a background task
|
|
17
|
+
* - list_tasks: List all tracked background tasks
|
|
12
18
|
*
|
|
13
19
|
* Configuration:
|
|
14
20
|
* ```yaml
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-provider.d.ts","sourceRoot":"","sources":["../../src/tool-provider/tool-provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-provider.d.ts","sourceRoot":"","sources":["../../src/tool-provider/tool-provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,aAAa,CAAC;AAYpE,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAmBjF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,yBAAyB,EAAE,kBAAkB,CAAC,eAAe,EAAE,kBAAkB,CAsM7F,CAAC"}
|
|
@@ -1,15 +1,173 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConditionEngine,
|
|
3
|
+
SignalBus,
|
|
4
|
+
TaskRegistry,
|
|
5
|
+
createCheckTaskTool,
|
|
6
|
+
createListTasksTool,
|
|
7
|
+
createWaitForTool
|
|
8
|
+
} from "@dexto/orchestration";
|
|
1
9
|
import { AgentSpawnerConfigSchema } from "./schemas.js";
|
|
2
10
|
import { RuntimeService } from "./runtime-service.js";
|
|
3
11
|
import { createSpawnAgentTool } from "./spawn-agent-tool.js";
|
|
12
|
+
function bindOrchestrationTool(tool, context) {
|
|
13
|
+
return {
|
|
14
|
+
id: tool.id,
|
|
15
|
+
description: tool.description,
|
|
16
|
+
inputSchema: tool.inputSchema,
|
|
17
|
+
execute: (input) => tool.execute(input, context)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
4
20
|
const agentSpawnerToolsProvider = {
|
|
5
21
|
type: "agent-spawner",
|
|
6
22
|
configSchema: AgentSpawnerConfigSchema,
|
|
7
23
|
create: (config, context) => {
|
|
8
24
|
const { logger, agent } = context;
|
|
25
|
+
const signalBus = new SignalBus();
|
|
26
|
+
const taskRegistry = new TaskRegistry(signalBus);
|
|
27
|
+
const conditionEngine = new ConditionEngine(taskRegistry, signalBus, logger);
|
|
28
|
+
const toolContext = {
|
|
29
|
+
taskRegistry,
|
|
30
|
+
conditionEngine,
|
|
31
|
+
signalBus
|
|
32
|
+
};
|
|
9
33
|
const service = new RuntimeService(agent, config, logger);
|
|
10
34
|
agent.toolManager.setTaskForker(service);
|
|
11
35
|
logger.debug("RuntimeService wired as taskForker for context:fork skill support");
|
|
12
|
-
|
|
36
|
+
const taskSessions = /* @__PURE__ */ new Map();
|
|
37
|
+
const emitTasksUpdate = (sessionId) => {
|
|
38
|
+
const tasks = taskRegistry.list({
|
|
39
|
+
status: ["running", "completed", "failed", "cancelled"]
|
|
40
|
+
});
|
|
41
|
+
const scopedTasks = sessionId ? tasks.filter((task) => taskSessions.get(task.taskId) === sessionId) : tasks;
|
|
42
|
+
const runningCount = scopedTasks.filter((task) => task.status === "running").length;
|
|
43
|
+
agent.agentEventBus.emit("service:event", {
|
|
44
|
+
service: "orchestration",
|
|
45
|
+
event: "tasks-updated",
|
|
46
|
+
sessionId: sessionId ?? "",
|
|
47
|
+
data: {
|
|
48
|
+
runningCount,
|
|
49
|
+
tasks: scopedTasks.map((task) => ({
|
|
50
|
+
taskId: task.taskId,
|
|
51
|
+
status: task.status,
|
|
52
|
+
...task.description !== void 0 && { description: task.description }
|
|
53
|
+
}))
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
const triggerBackgroundCompletion = (taskId, sessionId) => {
|
|
58
|
+
if (!sessionId) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
agent.agentEventBus.emit("tool:background-completed", {
|
|
62
|
+
toolCallId: taskId,
|
|
63
|
+
sessionId
|
|
64
|
+
});
|
|
65
|
+
const taskInfo = taskRegistry.getInfo(taskId);
|
|
66
|
+
const resultText = (() => {
|
|
67
|
+
if (taskInfo?.status === "failed") {
|
|
68
|
+
return taskInfo.error ?? "Unknown error.";
|
|
69
|
+
}
|
|
70
|
+
if (taskInfo?.result !== void 0) {
|
|
71
|
+
if (typeof taskInfo.result === "string") {
|
|
72
|
+
return taskInfo.result;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
return JSON.stringify(taskInfo.result, null, 2);
|
|
76
|
+
} catch {
|
|
77
|
+
return String(taskInfo.result ?? "<unserializable result>");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return "No result available.";
|
|
81
|
+
})();
|
|
82
|
+
const sanitizeCdata = (value) => value.replace(/\]\]>/g, "]]]]><![CDATA[>");
|
|
83
|
+
const safeDescription = taskInfo?.description ? sanitizeCdata(taskInfo.description) : null;
|
|
84
|
+
const safeResultText = sanitizeCdata(resultText);
|
|
85
|
+
const descriptionTag = safeDescription ? ` <description><![CDATA[${safeDescription}]]></description>
|
|
86
|
+
` : "";
|
|
87
|
+
const statusTag = taskInfo?.status ? ` <status>${taskInfo.status}</status>
|
|
88
|
+
` : "";
|
|
89
|
+
const content = [
|
|
90
|
+
{
|
|
91
|
+
type: "text",
|
|
92
|
+
text: `<background-task-completion>
|
|
93
|
+
<origin>task</origin>
|
|
94
|
+
<note>The following response was reported by the background task (not user input).</note>
|
|
95
|
+
<taskId>${taskId}</taskId>
|
|
96
|
+
` + statusTag + descriptionTag + ` <result><![CDATA[${safeResultText}]]></result>
|
|
97
|
+
</background-task-completion>`
|
|
98
|
+
}
|
|
99
|
+
];
|
|
100
|
+
agent.isSessionBusy(sessionId).then((isBusy) => {
|
|
101
|
+
if (isBusy) {
|
|
102
|
+
agent.queueMessage(sessionId, {
|
|
103
|
+
content,
|
|
104
|
+
kind: "background"
|
|
105
|
+
}).catch(() => void 0);
|
|
106
|
+
} else {
|
|
107
|
+
agent.agentEventBus.emit("run:invoke", {
|
|
108
|
+
sessionId,
|
|
109
|
+
content,
|
|
110
|
+
source: "external",
|
|
111
|
+
metadata: { taskId }
|
|
112
|
+
});
|
|
113
|
+
agent.generate(content, sessionId).catch(() => void 0);
|
|
114
|
+
}
|
|
115
|
+
}).catch(() => {
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
const handleBackground = (event) => {
|
|
119
|
+
const taskId = event.toolCallId;
|
|
120
|
+
if (taskRegistry.has(taskId)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (event.sessionId) {
|
|
124
|
+
taskSessions.set(taskId, event.sessionId);
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
taskRegistry.register(
|
|
128
|
+
{
|
|
129
|
+
type: "generic",
|
|
130
|
+
taskId,
|
|
131
|
+
description: event.description ?? `Tool ${event.toolName}`,
|
|
132
|
+
promise: event.promise
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
...event.timeoutMs !== void 0 && { timeout: event.timeoutMs },
|
|
136
|
+
...event.notifyOnComplete !== void 0 && {
|
|
137
|
+
notify: event.notifyOnComplete
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
taskSessions.delete(taskId);
|
|
143
|
+
event.promise.catch(() => void 0);
|
|
144
|
+
logger.warn(
|
|
145
|
+
`Failed to register background task ${taskId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
146
|
+
{ color: "yellow" }
|
|
147
|
+
);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
emitTasksUpdate(event.sessionId);
|
|
151
|
+
event.promise.finally(() => {
|
|
152
|
+
taskSessions.delete(taskId);
|
|
153
|
+
emitTasksUpdate(event.sessionId);
|
|
154
|
+
triggerBackgroundCompletion(taskId, event.sessionId);
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
const backgroundAbortController = new AbortController();
|
|
158
|
+
agent.agentEventBus.on("tool:background", handleBackground, {
|
|
159
|
+
signal: backgroundAbortController.signal
|
|
160
|
+
});
|
|
161
|
+
agent.agentEventBus.on("agent:stopped", () => {
|
|
162
|
+
backgroundAbortController.abort();
|
|
163
|
+
});
|
|
164
|
+
const tool = createSpawnAgentTool(service);
|
|
165
|
+
return [
|
|
166
|
+
tool,
|
|
167
|
+
bindOrchestrationTool(createWaitForTool(), toolContext),
|
|
168
|
+
bindOrchestrationTool(createCheckTaskTool(), toolContext),
|
|
169
|
+
bindOrchestrationTool(createListTasksTool(), toolContext)
|
|
170
|
+
];
|
|
13
171
|
},
|
|
14
172
|
metadata: {
|
|
15
173
|
displayName: "Agent Spawner",
|
|
@@ -52,7 +52,7 @@ const PROVIDER_API_KEY_MAP = {
|
|
|
52
52
|
ollama: [],
|
|
53
53
|
// Ollama server (may optionally use OLLAMA_API_KEY for remote servers)
|
|
54
54
|
// Dexto gateway - requires key from `dexto login`
|
|
55
|
-
dexto: ["DEXTO_API_KEY"]
|
|
55
|
+
"dexto-nova": ["DEXTO_API_KEY"]
|
|
56
56
|
// perplexity: ['PERPLEXITY_API_KEY'],
|
|
57
57
|
// together: ['TOGETHER_API_KEY'],
|
|
58
58
|
// fireworks: ['FIREWORKS_API_KEY'],
|
|
@@ -27,7 +27,7 @@ const PROVIDER_API_KEY_MAP = {
|
|
|
27
27
|
ollama: [],
|
|
28
28
|
// Ollama server (may optionally use OLLAMA_API_KEY for remote servers)
|
|
29
29
|
// Dexto gateway - requires key from `dexto login`
|
|
30
|
-
dexto: ["DEXTO_API_KEY"]
|
|
30
|
+
"dexto-nova": ["DEXTO_API_KEY"]
|
|
31
31
|
// perplexity: ['PERPLEXITY_API_KEY'],
|
|
32
32
|
// together: ['TOGETHER_API_KEY'],
|
|
33
33
|
// fireworks: ['FIREWORKS_API_KEY'],
|
|
@@ -22,7 +22,9 @@ __export(feature_flags_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(feature_flags_exports);
|
|
24
24
|
function isDextoAuthEnabled() {
|
|
25
|
-
|
|
25
|
+
const flag = process.env.DEXTO_FEATURE_AUTH;
|
|
26
|
+
if (flag === void 0) return true;
|
|
27
|
+
return flag === "true";
|
|
26
28
|
}
|
|
27
29
|
// Annotate the CommonJS export names for ESM import in node:
|
|
28
30
|
0 && (module.exports = {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
/**
|
|
8
8
|
* Check if Dexto authentication/provider is enabled.
|
|
9
9
|
*
|
|
10
|
-
* When disabled (
|
|
10
|
+
* When disabled (set DEXTO_FEATURE_AUTH=false), the Dexto provider option is hidden from:
|
|
11
11
|
* - Onboarding/setup wizard
|
|
12
12
|
* - Model selectors (CLI and WebUI)
|
|
13
13
|
* - LLM catalog API responses
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* The underlying auth commands (dexto login, logout, billing) remain functional
|
|
16
16
|
* for users who need to manage their account.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
18
|
+
* Enabled by default. Set DEXTO_FEATURE_AUTH=false to disable.
|
|
19
19
|
*/
|
|
20
20
|
export declare function isDextoAuthEnabled(): boolean;
|
|
21
21
|
//# sourceMappingURL=feature-flags.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-flags.d.ts","sourceRoot":"","sources":["../../src/utils/feature-flags.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"feature-flags.d.ts","sourceRoot":"","sources":["../../src/utils/feature-flags.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAI5C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dexto/agent-management",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"yaml": "^2.7.1",
|
|
18
18
|
"zod": "^3.25.0",
|
|
19
|
-
"@dexto/core": "1.5.
|
|
19
|
+
"@dexto/core": "1.5.8",
|
|
20
|
+
"@dexto/orchestration": "1.5.8"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@types/node": "^22.13.5"
|