@madh-io/alfred-ai 0.7.0 → 0.7.1
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/bundle/index.js +279 -17
- package/package.json +1 -1
package/bundle/index.js
CHANGED
|
@@ -2526,20 +2526,120 @@ var init_skill_registry = __esm({
|
|
|
2526
2526
|
});
|
|
2527
2527
|
|
|
2528
2528
|
// ../skills/dist/skill-sandbox.js
|
|
2529
|
-
var DEFAULT_TIMEOUT_MS, SkillSandbox;
|
|
2529
|
+
var DEFAULT_TIMEOUT_MS, INACTIVITY_THRESHOLD_MS, POLL_INTERVAL_MS, MAX_TOTAL_TIME_MS, SkillSandbox;
|
|
2530
2530
|
var init_skill_sandbox = __esm({
|
|
2531
2531
|
"../skills/dist/skill-sandbox.js"() {
|
|
2532
2532
|
"use strict";
|
|
2533
2533
|
DEFAULT_TIMEOUT_MS = 3e4;
|
|
2534
|
+
INACTIVITY_THRESHOLD_MS = 12e4;
|
|
2535
|
+
POLL_INTERVAL_MS = 1e4;
|
|
2536
|
+
MAX_TOTAL_TIME_MS = 20 * 6e4;
|
|
2534
2537
|
SkillSandbox = class {
|
|
2535
2538
|
logger;
|
|
2536
2539
|
constructor(logger) {
|
|
2537
2540
|
this.logger = logger;
|
|
2538
2541
|
}
|
|
2539
|
-
|
|
2542
|
+
/**
|
|
2543
|
+
* Execute a skill with timeout protection.
|
|
2544
|
+
*
|
|
2545
|
+
* If an ActivityTracker is provided, uses an inactivity-based timeout:
|
|
2546
|
+
* the skill keeps running as long as the tracker receives pings.
|
|
2547
|
+
* Only kills the skill when it goes silent for INACTIVITY_THRESHOLD_MS.
|
|
2548
|
+
*
|
|
2549
|
+
* Without a tracker, falls back to a simple hard timeout.
|
|
2550
|
+
*/
|
|
2551
|
+
async execute(skill, input2, context, timeoutMs, tracker) {
|
|
2540
2552
|
timeoutMs = timeoutMs ?? skill.metadata.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
2541
2553
|
const { name } = skill.metadata;
|
|
2542
2554
|
this.logger.info({ skill: name, input: input2 }, "Skill execution started");
|
|
2555
|
+
if (tracker) {
|
|
2556
|
+
return this.executeWithTracker(skill, input2, context, name, timeoutMs, tracker);
|
|
2557
|
+
}
|
|
2558
|
+
return this.executeWithHardTimeout(skill, input2, context, name, timeoutMs);
|
|
2559
|
+
}
|
|
2560
|
+
/**
|
|
2561
|
+
* Activity-aware timeout: polls the tracker and only kills
|
|
2562
|
+
* the skill when it has been inactive for too long.
|
|
2563
|
+
*/
|
|
2564
|
+
async executeWithTracker(skill, input2, context, name, initialTimeoutMs, tracker) {
|
|
2565
|
+
return new Promise((resolve) => {
|
|
2566
|
+
let settled = false;
|
|
2567
|
+
let pollTimer;
|
|
2568
|
+
let safetyTimer;
|
|
2569
|
+
let initialTimer;
|
|
2570
|
+
const cleanup = () => {
|
|
2571
|
+
if (pollTimer)
|
|
2572
|
+
clearInterval(pollTimer);
|
|
2573
|
+
if (safetyTimer)
|
|
2574
|
+
clearTimeout(safetyTimer);
|
|
2575
|
+
if (initialTimer)
|
|
2576
|
+
clearTimeout(initialTimer);
|
|
2577
|
+
};
|
|
2578
|
+
const finish = (result) => {
|
|
2579
|
+
if (settled)
|
|
2580
|
+
return;
|
|
2581
|
+
settled = true;
|
|
2582
|
+
cleanup();
|
|
2583
|
+
resolve(result);
|
|
2584
|
+
};
|
|
2585
|
+
skill.execute(input2, context).then((result) => {
|
|
2586
|
+
this.logger.info({ skill: name, success: result.success }, "Skill execution completed");
|
|
2587
|
+
finish(result);
|
|
2588
|
+
}, (error) => {
|
|
2589
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2590
|
+
this.logger.error({ skill: name, error: message }, "Skill execution failed");
|
|
2591
|
+
finish({ success: false, error: message });
|
|
2592
|
+
});
|
|
2593
|
+
initialTimer = setTimeout(() => {
|
|
2594
|
+
if (settled)
|
|
2595
|
+
return;
|
|
2596
|
+
const idleMs = tracker.getIdleMs();
|
|
2597
|
+
if (idleMs >= INACTIVITY_THRESHOLD_MS) {
|
|
2598
|
+
const snapshot2 = tracker.getSnapshot();
|
|
2599
|
+
this.logger.warn({ skill: name, idleMs, state: snapshot2.state, iteration: snapshot2.iteration }, "Agent inactive after initial timeout \u2014 aborting");
|
|
2600
|
+
finish({
|
|
2601
|
+
success: false,
|
|
2602
|
+
error: `Skill "${name}" timed out \u2014 inactive for ${Math.round(idleMs / 1e3)}s (last state: ${snapshot2.state})`
|
|
2603
|
+
});
|
|
2604
|
+
return;
|
|
2605
|
+
}
|
|
2606
|
+
const snapshot = tracker.getSnapshot();
|
|
2607
|
+
this.logger.info({ skill: name, idleMs, state: snapshot.state, iteration: snapshot.iteration, totalMs: snapshot.totalElapsedMs }, "Initial timeout reached but agent is active \u2014 extending");
|
|
2608
|
+
pollTimer = setInterval(() => {
|
|
2609
|
+
if (settled) {
|
|
2610
|
+
cleanup();
|
|
2611
|
+
return;
|
|
2612
|
+
}
|
|
2613
|
+
const currentIdleMs = tracker.getIdleMs();
|
|
2614
|
+
const snap = tracker.getSnapshot();
|
|
2615
|
+
if (currentIdleMs >= INACTIVITY_THRESHOLD_MS) {
|
|
2616
|
+
this.logger.warn({ skill: name, idleMs: currentIdleMs, state: snap.state, iteration: snap.iteration, totalMs: snap.totalElapsedMs }, "Agent went inactive \u2014 aborting");
|
|
2617
|
+
finish({
|
|
2618
|
+
success: false,
|
|
2619
|
+
error: `Skill "${name}" killed \u2014 inactive for ${Math.round(currentIdleMs / 1e3)}s (last state: ${snap.state})`
|
|
2620
|
+
});
|
|
2621
|
+
} else {
|
|
2622
|
+
this.logger.debug({ skill: name, idleMs: currentIdleMs, state: snap.state, iteration: snap.iteration }, "Agent still active, continuing...");
|
|
2623
|
+
}
|
|
2624
|
+
}, POLL_INTERVAL_MS);
|
|
2625
|
+
}, initialTimeoutMs);
|
|
2626
|
+
safetyTimer = setTimeout(() => {
|
|
2627
|
+
if (settled)
|
|
2628
|
+
return;
|
|
2629
|
+
const snap = tracker.getSnapshot();
|
|
2630
|
+
this.logger.error({ skill: name, totalMs: snap.totalElapsedMs, state: snap.state, iteration: snap.iteration }, "Absolute time limit reached \u2014 force killing agent");
|
|
2631
|
+
finish({
|
|
2632
|
+
success: false,
|
|
2633
|
+
error: `Skill "${name}" force-killed after ${Math.round(MAX_TOTAL_TIME_MS / 6e4)} minutes (safety limit)`
|
|
2634
|
+
});
|
|
2635
|
+
}, MAX_TOTAL_TIME_MS);
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
/**
|
|
2639
|
+
* Simple hard timeout for skills that don't use a tracker.
|
|
2640
|
+
* This is the legacy behavior.
|
|
2641
|
+
*/
|
|
2642
|
+
async executeWithHardTimeout(skill, input2, context, name, timeoutMs) {
|
|
2543
2643
|
try {
|
|
2544
2644
|
const result = await Promise.race([
|
|
2545
2645
|
skill.execute(input2, context),
|
|
@@ -2562,6 +2662,90 @@ var init_skill_sandbox = __esm({
|
|
|
2562
2662
|
}
|
|
2563
2663
|
});
|
|
2564
2664
|
|
|
2665
|
+
// ../skills/dist/activity-tracker.js
|
|
2666
|
+
var ActivityTracker;
|
|
2667
|
+
var init_activity_tracker = __esm({
|
|
2668
|
+
"../skills/dist/activity-tracker.js"() {
|
|
2669
|
+
"use strict";
|
|
2670
|
+
ActivityTracker = class {
|
|
2671
|
+
state = "starting";
|
|
2672
|
+
iteration = 0;
|
|
2673
|
+
maxIterations = 0;
|
|
2674
|
+
currentTool;
|
|
2675
|
+
lastPingAt;
|
|
2676
|
+
startedAt;
|
|
2677
|
+
history = [];
|
|
2678
|
+
onProgress;
|
|
2679
|
+
constructor(onProgress) {
|
|
2680
|
+
this.startedAt = Date.now();
|
|
2681
|
+
this.lastPingAt = Date.now();
|
|
2682
|
+
this.onProgress = onProgress;
|
|
2683
|
+
}
|
|
2684
|
+
/**
|
|
2685
|
+
* Called by the agent at every meaningful step.
|
|
2686
|
+
* Resets the inactivity timer and reports status upward.
|
|
2687
|
+
*/
|
|
2688
|
+
ping(state, meta) {
|
|
2689
|
+
this.state = state;
|
|
2690
|
+
this.lastPingAt = Date.now();
|
|
2691
|
+
if (meta?.iteration !== void 0)
|
|
2692
|
+
this.iteration = meta.iteration;
|
|
2693
|
+
if (meta?.maxIterations !== void 0)
|
|
2694
|
+
this.maxIterations = meta.maxIterations;
|
|
2695
|
+
this.currentTool = meta?.tool;
|
|
2696
|
+
this.history.push({
|
|
2697
|
+
state,
|
|
2698
|
+
tool: meta?.tool,
|
|
2699
|
+
iteration: this.iteration,
|
|
2700
|
+
timestamp: this.lastPingAt
|
|
2701
|
+
});
|
|
2702
|
+
if (this.onProgress) {
|
|
2703
|
+
this.onProgress(this.formatStatus());
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
/** How long since last activity, in ms. */
|
|
2707
|
+
getIdleMs() {
|
|
2708
|
+
return Date.now() - this.lastPingAt;
|
|
2709
|
+
}
|
|
2710
|
+
/** Total elapsed time since agent started. */
|
|
2711
|
+
getTotalElapsedMs() {
|
|
2712
|
+
return Date.now() - this.startedAt;
|
|
2713
|
+
}
|
|
2714
|
+
/** Current human-readable status string. */
|
|
2715
|
+
formatStatus() {
|
|
2716
|
+
const iter = this.maxIterations > 0 ? ` (${this.iteration}/${this.maxIterations})` : "";
|
|
2717
|
+
switch (this.state) {
|
|
2718
|
+
case "starting":
|
|
2719
|
+
return `Sub-agent starting...`;
|
|
2720
|
+
case "llm_call":
|
|
2721
|
+
return `Sub-agent thinking...${iter}`;
|
|
2722
|
+
case "tool_call":
|
|
2723
|
+
return this.currentTool ? `Sub-agent using ${this.currentTool}${iter}` : `Sub-agent using tool...${iter}`;
|
|
2724
|
+
case "processing":
|
|
2725
|
+
return `Sub-agent processing...${iter}`;
|
|
2726
|
+
case "done":
|
|
2727
|
+
return `Sub-agent done${iter}`;
|
|
2728
|
+
default:
|
|
2729
|
+
return `Sub-agent working...${iter}`;
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
/** Full snapshot for logging / debugging. */
|
|
2733
|
+
getSnapshot() {
|
|
2734
|
+
return {
|
|
2735
|
+
state: this.state,
|
|
2736
|
+
iteration: this.iteration,
|
|
2737
|
+
maxIterations: this.maxIterations,
|
|
2738
|
+
lastPingAt: this.lastPingAt,
|
|
2739
|
+
idleMs: this.getIdleMs(),
|
|
2740
|
+
currentTool: this.currentTool,
|
|
2741
|
+
totalElapsedMs: this.getTotalElapsedMs(),
|
|
2742
|
+
history: [...this.history]
|
|
2743
|
+
};
|
|
2744
|
+
}
|
|
2745
|
+
};
|
|
2746
|
+
}
|
|
2747
|
+
});
|
|
2748
|
+
|
|
2565
2749
|
// ../skills/dist/plugin-loader.js
|
|
2566
2750
|
import fs3 from "node:fs";
|
|
2567
2751
|
import path3 from "node:path";
|
|
@@ -3576,12 +3760,15 @@ ${results.map((r) => `- ${r.key}: "${r.value}" (score: ${r.score.toFixed(2)})`).
|
|
|
3576
3760
|
});
|
|
3577
3761
|
|
|
3578
3762
|
// ../skills/dist/built-in/delegate.js
|
|
3579
|
-
var
|
|
3763
|
+
var DEFAULT_MAX_ITERATIONS, MAX_ALLOWED_ITERATIONS, INITIAL_TIMEOUT_MS, DelegateSkill;
|
|
3580
3764
|
var init_delegate = __esm({
|
|
3581
3765
|
"../skills/dist/built-in/delegate.js"() {
|
|
3582
3766
|
"use strict";
|
|
3583
3767
|
init_skill();
|
|
3584
|
-
|
|
3768
|
+
init_activity_tracker();
|
|
3769
|
+
DEFAULT_MAX_ITERATIONS = 5;
|
|
3770
|
+
MAX_ALLOWED_ITERATIONS = 15;
|
|
3771
|
+
INITIAL_TIMEOUT_MS = 12e4;
|
|
3585
3772
|
DelegateSkill = class extends Skill {
|
|
3586
3773
|
llm;
|
|
3587
3774
|
skillRegistry;
|
|
@@ -3589,11 +3776,10 @@ var init_delegate = __esm({
|
|
|
3589
3776
|
securityManager;
|
|
3590
3777
|
metadata = {
|
|
3591
3778
|
name: "delegate",
|
|
3592
|
-
description: 'Delegate a complex sub-task to an autonomous sub-agent that has full tool access. The sub-agent can use shell, web search, calculator, memory, email, and all other tools. Use when a task is independent enough to run in parallel or when it requires a focused, multi-step workflow (e.g. "research X and summarize", "find all TODO files and list them", "check the weather and draft a packing list").
|
|
3779
|
+
description: 'Delegate a complex sub-task to an autonomous sub-agent that has full tool access. The sub-agent can use shell, web search, calculator, memory, email, and all other tools. Use when a task is independent enough to run in parallel or when it requires a focused, multi-step workflow (e.g. "research X and summarize", "find all TODO files and list them", "check the weather and draft a packing list"). Control depth with max_iterations (default 5, max 15).',
|
|
3593
3780
|
riskLevel: "write",
|
|
3594
|
-
version: "
|
|
3595
|
-
timeoutMs:
|
|
3596
|
-
// 2 minutes — delegate chains multiple LLM calls + tool executions
|
|
3781
|
+
version: "3.0.0",
|
|
3782
|
+
timeoutMs: INITIAL_TIMEOUT_MS,
|
|
3597
3783
|
inputSchema: {
|
|
3598
3784
|
type: "object",
|
|
3599
3785
|
properties: {
|
|
@@ -3604,11 +3790,16 @@ var init_delegate = __esm({
|
|
|
3604
3790
|
context: {
|
|
3605
3791
|
type: "string",
|
|
3606
3792
|
description: "Additional context the sub-agent needs (optional)"
|
|
3793
|
+
},
|
|
3794
|
+
max_iterations: {
|
|
3795
|
+
type: "number",
|
|
3796
|
+
description: "Max tool iterations (1-15). Use higher values for complex multi-step tasks. Default: 5."
|
|
3607
3797
|
}
|
|
3608
3798
|
},
|
|
3609
3799
|
required: ["task"]
|
|
3610
3800
|
}
|
|
3611
3801
|
};
|
|
3802
|
+
onProgress;
|
|
3612
3803
|
constructor(llm, skillRegistry, skillSandbox, securityManager) {
|
|
3613
3804
|
super();
|
|
3614
3805
|
this.llm = llm;
|
|
@@ -3616,6 +3807,21 @@ var init_delegate = __esm({
|
|
|
3616
3807
|
this.skillSandbox = skillSandbox;
|
|
3617
3808
|
this.securityManager = securityManager;
|
|
3618
3809
|
}
|
|
3810
|
+
/**
|
|
3811
|
+
* Set a progress callback before execution.
|
|
3812
|
+
* The pipeline calls this so the user sees live status updates
|
|
3813
|
+
* like "Sub-agent using web_search (2/5)".
|
|
3814
|
+
*/
|
|
3815
|
+
setProgressCallback(cb) {
|
|
3816
|
+
this.onProgress = cb;
|
|
3817
|
+
}
|
|
3818
|
+
/**
|
|
3819
|
+
* Create an ActivityTracker for this execution.
|
|
3820
|
+
* The sandbox uses this to decide whether to extend or kill.
|
|
3821
|
+
*/
|
|
3822
|
+
createTracker() {
|
|
3823
|
+
return new ActivityTracker(this.onProgress);
|
|
3824
|
+
}
|
|
3619
3825
|
async execute(input2, context) {
|
|
3620
3826
|
const task = input2.task;
|
|
3621
3827
|
const additionalContext = input2.context;
|
|
@@ -3625,6 +3831,10 @@ var init_delegate = __esm({
|
|
|
3625
3831
|
error: 'Missing required field "task"'
|
|
3626
3832
|
};
|
|
3627
3833
|
}
|
|
3834
|
+
const requestedIterations = input2.max_iterations;
|
|
3835
|
+
const maxIterations = requestedIterations ? Math.max(1, Math.min(MAX_ALLOWED_ITERATIONS, Math.round(requestedIterations))) : DEFAULT_MAX_ITERATIONS;
|
|
3836
|
+
const tracker = new ActivityTracker(this.onProgress);
|
|
3837
|
+
tracker.ping("starting", { maxIterations });
|
|
3628
3838
|
const tools = this.buildSubAgentTools();
|
|
3629
3839
|
const systemPrompt = "You are a sub-agent of Alfred, a personal AI assistant. Complete the assigned task using the tools available to you. Work step by step: use tools to gather information, then synthesize a clear result. Be concise and return only the final answer when done.";
|
|
3630
3840
|
let userContent = task;
|
|
@@ -3641,6 +3851,7 @@ Additional context: ${additionalContext}`;
|
|
|
3641
3851
|
let totalInputTokens = 0;
|
|
3642
3852
|
let totalOutputTokens = 0;
|
|
3643
3853
|
while (true) {
|
|
3854
|
+
tracker.ping("llm_call", { iteration, maxIterations });
|
|
3644
3855
|
const response = await this.llm.complete({
|
|
3645
3856
|
messages,
|
|
3646
3857
|
system: systemPrompt,
|
|
@@ -3649,7 +3860,9 @@ Additional context: ${additionalContext}`;
|
|
|
3649
3860
|
});
|
|
3650
3861
|
totalInputTokens += response.usage.inputTokens;
|
|
3651
3862
|
totalOutputTokens += response.usage.outputTokens;
|
|
3652
|
-
|
|
3863
|
+
tracker.ping("processing", { iteration, maxIterations });
|
|
3864
|
+
if (!response.toolCalls || response.toolCalls.length === 0 || iteration >= maxIterations) {
|
|
3865
|
+
tracker.ping("done", { iteration, maxIterations });
|
|
3653
3866
|
return {
|
|
3654
3867
|
success: true,
|
|
3655
3868
|
data: {
|
|
@@ -3676,6 +3889,7 @@ Additional context: ${additionalContext}`;
|
|
|
3676
3889
|
messages.push({ role: "assistant", content: assistantContent });
|
|
3677
3890
|
const toolResultBlocks = [];
|
|
3678
3891
|
for (const toolCall of response.toolCalls) {
|
|
3892
|
+
tracker.ping("tool_call", { iteration, maxIterations, tool: toolCall.name });
|
|
3679
3893
|
const result = await this.executeSubAgentTool(toolCall, context);
|
|
3680
3894
|
toolResultBlocks.push({
|
|
3681
3895
|
type: "tool_result",
|
|
@@ -5673,6 +5887,7 @@ var init_dist6 = __esm({
|
|
|
5673
5887
|
init_skill();
|
|
5674
5888
|
init_skill_registry();
|
|
5675
5889
|
init_skill_sandbox();
|
|
5890
|
+
init_activity_tracker();
|
|
5676
5891
|
init_plugin_loader();
|
|
5677
5892
|
init_calculator();
|
|
5678
5893
|
init_system_info();
|
|
@@ -5746,6 +5961,9 @@ var init_message_pipeline = __esm({
|
|
|
5746
5961
|
speechTranscriber;
|
|
5747
5962
|
inboxPath;
|
|
5748
5963
|
embeddingService;
|
|
5964
|
+
/** Registry of currently running delegate agents, keyed by a unique agent ID. */
|
|
5965
|
+
activeAgents = /* @__PURE__ */ new Map();
|
|
5966
|
+
agentIdCounter = 0;
|
|
5749
5967
|
constructor(options) {
|
|
5750
5968
|
this.llm = options.llm;
|
|
5751
5969
|
this.conversationManager = options.conversationManager;
|
|
@@ -5806,11 +6024,15 @@ var init_message_pipeline = __esm({
|
|
|
5806
6024
|
}
|
|
5807
6025
|
const skillMetas = this.skillRegistry ? this.skillRegistry.getAll().map((s) => s.metadata) : void 0;
|
|
5808
6026
|
const tools = skillMetas ? this.promptBuilder.buildTools(skillMetas) : void 0;
|
|
5809
|
-
|
|
6027
|
+
let system = this.promptBuilder.buildSystemPrompt({
|
|
5810
6028
|
memories,
|
|
5811
6029
|
skills: skillMetas,
|
|
5812
6030
|
userProfile
|
|
5813
6031
|
});
|
|
6032
|
+
const agentStatusBlock = this.buildActiveAgentStatus();
|
|
6033
|
+
if (agentStatusBlock) {
|
|
6034
|
+
system += "\n\n" + agentStatusBlock;
|
|
6035
|
+
}
|
|
5814
6036
|
const allMessages = this.promptBuilder.buildMessages(history);
|
|
5815
6037
|
const userContent = await this.buildUserContent(message, onProgress);
|
|
5816
6038
|
allMessages.push({ role: "user", content: userContent });
|
|
@@ -5855,7 +6077,7 @@ var init_message_pipeline = __esm({
|
|
|
5855
6077
|
chatType: message.chatType,
|
|
5856
6078
|
platform: message.platform,
|
|
5857
6079
|
conversationId: conversation.id
|
|
5858
|
-
});
|
|
6080
|
+
}, onProgress);
|
|
5859
6081
|
toolResultBlocks.push({
|
|
5860
6082
|
type: "tool_result",
|
|
5861
6083
|
tool_use_id: toolCall.id,
|
|
@@ -5885,7 +6107,7 @@ var init_message_pipeline = __esm({
|
|
|
5885
6107
|
throw error;
|
|
5886
6108
|
}
|
|
5887
6109
|
}
|
|
5888
|
-
async executeToolCall(toolCall, context) {
|
|
6110
|
+
async executeToolCall(toolCall, context, onProgress) {
|
|
5889
6111
|
const skill = this.skillRegistry?.get(toolCall.name);
|
|
5890
6112
|
if (!skill) {
|
|
5891
6113
|
this.logger.warn({ tool: toolCall.name }, "Unknown skill requested");
|
|
@@ -5909,11 +6131,33 @@ var init_message_pipeline = __esm({
|
|
|
5909
6131
|
}
|
|
5910
6132
|
}
|
|
5911
6133
|
if (this.skillSandbox) {
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
6134
|
+
let tracker;
|
|
6135
|
+
let agentId;
|
|
6136
|
+
if (toolCall.name === "delegate" && "setProgressCallback" in skill && "createTracker" in skill) {
|
|
6137
|
+
const delegateSkill = skill;
|
|
6138
|
+
if (onProgress) {
|
|
6139
|
+
delegateSkill.setProgressCallback(onProgress);
|
|
6140
|
+
}
|
|
6141
|
+
tracker = delegateSkill.createTracker();
|
|
6142
|
+
agentId = `agent-${++this.agentIdCounter}`;
|
|
6143
|
+
this.activeAgents.set(agentId, {
|
|
6144
|
+
chatId: context.chatId,
|
|
6145
|
+
task: String(toolCall.input.task ?? "").slice(0, 200),
|
|
6146
|
+
tracker,
|
|
6147
|
+
startedAt: Date.now()
|
|
6148
|
+
});
|
|
6149
|
+
}
|
|
6150
|
+
try {
|
|
6151
|
+
const result = await this.skillSandbox.execute(skill, toolCall.input, context, void 0, tracker);
|
|
6152
|
+
return {
|
|
6153
|
+
content: result.display ?? (result.success ? JSON.stringify(result.data) : result.error ?? "Unknown error"),
|
|
6154
|
+
isError: !result.success
|
|
6155
|
+
};
|
|
6156
|
+
} finally {
|
|
6157
|
+
if (agentId) {
|
|
6158
|
+
this.activeAgents.delete(agentId);
|
|
6159
|
+
}
|
|
6160
|
+
}
|
|
5917
6161
|
}
|
|
5918
6162
|
try {
|
|
5919
6163
|
const result = await skill.execute(toolCall.input, context);
|
|
@@ -5966,6 +6210,24 @@ var init_message_pipeline = __esm({
|
|
|
5966
6210
|
return `Using ${toolName}...`;
|
|
5967
6211
|
}
|
|
5968
6212
|
}
|
|
6213
|
+
/**
|
|
6214
|
+
* Build a status block describing currently running delegate agents.
|
|
6215
|
+
* Injected into the system prompt so the LLM can answer user questions
|
|
6216
|
+
* like "What is the agent doing right now?".
|
|
6217
|
+
*/
|
|
6218
|
+
buildActiveAgentStatus() {
|
|
6219
|
+
if (this.activeAgents.size === 0)
|
|
6220
|
+
return void 0;
|
|
6221
|
+
const lines = ["## Currently running sub-agents"];
|
|
6222
|
+
for (const [id, agent] of this.activeAgents) {
|
|
6223
|
+
const snapshot = agent.tracker.getSnapshot();
|
|
6224
|
+
const elapsedSec = Math.round(snapshot.totalElapsedMs / 1e3);
|
|
6225
|
+
lines.push(`- **${id}**: "${agent.task}"`, ` Status: ${agent.tracker.formatStatus()}`, ` Running for ${elapsedSec}s | Last activity ${Math.round(snapshot.idleMs / 1e3)}s ago`);
|
|
6226
|
+
}
|
|
6227
|
+
lines.push("");
|
|
6228
|
+
lines.push("If the user asks what you or the agent is doing, describe the above status in natural language.");
|
|
6229
|
+
return lines.join("\n");
|
|
6230
|
+
}
|
|
5969
6231
|
/**
|
|
5970
6232
|
* Trim messages to fit within the LLM's context window.
|
|
5971
6233
|
* Keeps the system prompt, the latest user message, and as many
|