@shykaruu/jarvis-brain 0.4.0
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/LICENSE +153 -0
- package/README.md +428 -0
- package/bin/jarvis.ts +449 -0
- package/package.json +79 -0
- package/roles/activity-observer.yaml +60 -0
- package/roles/ceo-founder.yaml +144 -0
- package/roles/chief-of-staff.yaml +158 -0
- package/roles/dev-lead.yaml +182 -0
- package/roles/executive-assistant.yaml +77 -0
- package/roles/marketing-director.yaml +168 -0
- package/roles/personal-assistant.yaml +266 -0
- package/roles/research-specialist.yaml +60 -0
- package/roles/specialists/content-writer.yaml +53 -0
- package/roles/specialists/customer-support.yaml +57 -0
- package/roles/specialists/data-analyst.yaml +57 -0
- package/roles/specialists/financial-analyst.yaml +56 -0
- package/roles/specialists/hr-specialist.yaml +55 -0
- package/roles/specialists/legal-advisor.yaml +58 -0
- package/roles/specialists/marketing-strategist.yaml +56 -0
- package/roles/specialists/project-coordinator.yaml +55 -0
- package/roles/specialists/research-analyst.yaml +58 -0
- package/roles/specialists/software-engineer.yaml +57 -0
- package/roles/specialists/system-administrator.yaml +57 -0
- package/roles/system-admin.yaml +76 -0
- package/scripts/ensure-bun.cjs +16 -0
- package/src/actions/README.md +421 -0
- package/src/actions/app-control/desktop-controller.test.ts +26 -0
- package/src/actions/app-control/desktop-controller.ts +438 -0
- package/src/actions/app-control/interface.ts +64 -0
- package/src/actions/app-control/linux.ts +273 -0
- package/src/actions/app-control/macos.ts +54 -0
- package/src/actions/app-control/sidecar-launcher.test.ts +23 -0
- package/src/actions/app-control/sidecar-launcher.ts +286 -0
- package/src/actions/app-control/windows.ts +44 -0
- package/src/actions/browser/cdp.ts +138 -0
- package/src/actions/browser/chrome-launcher.ts +261 -0
- package/src/actions/browser/session.ts +506 -0
- package/src/actions/browser/stealth.ts +49 -0
- package/src/actions/index.ts +20 -0
- package/src/actions/terminal/executor.ts +157 -0
- package/src/actions/terminal/wsl-bridge.ts +126 -0
- package/src/actions/test.ts +93 -0
- package/src/actions/tools/agents.ts +363 -0
- package/src/actions/tools/builtin.ts +950 -0
- package/src/actions/tools/commitments.ts +192 -0
- package/src/actions/tools/content.ts +217 -0
- package/src/actions/tools/delegate.ts +147 -0
- package/src/actions/tools/desktop.test.ts +55 -0
- package/src/actions/tools/desktop.ts +305 -0
- package/src/actions/tools/documents.ts +169 -0
- package/src/actions/tools/goals.ts +376 -0
- package/src/actions/tools/local-tools-guard.ts +31 -0
- package/src/actions/tools/registry.ts +173 -0
- package/src/actions/tools/research.ts +111 -0
- package/src/actions/tools/sidecar-list.ts +57 -0
- package/src/actions/tools/sidecar-route.ts +105 -0
- package/src/actions/tools/workflows.ts +216 -0
- package/src/agents/agent.ts +132 -0
- package/src/agents/delegation.ts +107 -0
- package/src/agents/hierarchy.ts +113 -0
- package/src/agents/index.ts +19 -0
- package/src/agents/messaging.ts +125 -0
- package/src/agents/orchestrator.ts +592 -0
- package/src/agents/role-discovery.ts +61 -0
- package/src/agents/sub-agent-runner.ts +309 -0
- package/src/agents/task-manager.ts +151 -0
- package/src/authority/approval-delivery.ts +59 -0
- package/src/authority/approval.ts +196 -0
- package/src/authority/audit.ts +158 -0
- package/src/authority/authority.test.ts +519 -0
- package/src/authority/deferred-executor.ts +103 -0
- package/src/authority/emergency.ts +66 -0
- package/src/authority/engine.ts +301 -0
- package/src/authority/index.ts +12 -0
- package/src/authority/learning.ts +111 -0
- package/src/authority/tool-action-map.ts +74 -0
- package/src/awareness/analytics.ts +466 -0
- package/src/awareness/awareness.test.ts +332 -0
- package/src/awareness/capture-engine.ts +305 -0
- package/src/awareness/context-graph.ts +130 -0
- package/src/awareness/context-tracker.ts +349 -0
- package/src/awareness/index.ts +25 -0
- package/src/awareness/intelligence.ts +321 -0
- package/src/awareness/ocr-engine.ts +88 -0
- package/src/awareness/service.ts +528 -0
- package/src/awareness/struggle-detector.ts +342 -0
- package/src/awareness/suggestion-engine.ts +476 -0
- package/src/awareness/types.ts +201 -0
- package/src/cli/autostart.ts +417 -0
- package/src/cli/deps.ts +449 -0
- package/src/cli/doctor.ts +238 -0
- package/src/cli/helpers.ts +401 -0
- package/src/cli/onboard.ts +827 -0
- package/src/cli/uninstall.test.ts +37 -0
- package/src/cli/uninstall.ts +202 -0
- package/src/comms/README.md +329 -0
- package/src/comms/auth-error.html +48 -0
- package/src/comms/channels/discord.ts +228 -0
- package/src/comms/channels/signal.ts +56 -0
- package/src/comms/channels/telegram.ts +316 -0
- package/src/comms/channels/whatsapp.ts +60 -0
- package/src/comms/channels.test.ts +173 -0
- package/src/comms/dashboard-auth.ts +75 -0
- package/src/comms/desktop-notify.ts +114 -0
- package/src/comms/example.ts +129 -0
- package/src/comms/index.ts +129 -0
- package/src/comms/streaming.ts +149 -0
- package/src/comms/voice.test.ts +504 -0
- package/src/comms/voice.ts +341 -0
- package/src/comms/websocket.test.ts +409 -0
- package/src/comms/websocket.ts +669 -0
- package/src/config/README.md +389 -0
- package/src/config/index.ts +6 -0
- package/src/config/loader.test.ts +183 -0
- package/src/config/loader.ts +148 -0
- package/src/config/types.ts +293 -0
- package/src/daemon/README.md +232 -0
- package/src/daemon/agent-service-interface.ts +9 -0
- package/src/daemon/agent-service.ts +667 -0
- package/src/daemon/api-routes.ts +3067 -0
- package/src/daemon/background-agent-service.ts +396 -0
- package/src/daemon/background-agent.test.ts +78 -0
- package/src/daemon/channel-service.ts +201 -0
- package/src/daemon/commitment-executor.ts +297 -0
- package/src/daemon/dashboard-auth.test.ts +170 -0
- package/src/daemon/event-classifier.ts +239 -0
- package/src/daemon/event-coalescer.ts +123 -0
- package/src/daemon/event-reactor.ts +214 -0
- package/src/daemon/flock.c +7 -0
- package/src/daemon/health.ts +220 -0
- package/src/daemon/index.ts +1070 -0
- package/src/daemon/llm-settings.test.ts +78 -0
- package/src/daemon/llm-settings.ts +450 -0
- package/src/daemon/observer-service.ts +150 -0
- package/src/daemon/pid.test.ts +283 -0
- package/src/daemon/pid.ts +224 -0
- package/src/daemon/research-queue.ts +155 -0
- package/src/daemon/services.ts +175 -0
- package/src/daemon/ws-service.ts +926 -0
- package/src/global.d.ts +4 -0
- package/src/goals/accountability.ts +240 -0
- package/src/goals/awareness-bridge.ts +185 -0
- package/src/goals/estimator.ts +185 -0
- package/src/goals/events.ts +28 -0
- package/src/goals/goals.test.ts +400 -0
- package/src/goals/integration.test.ts +329 -0
- package/src/goals/nl-builder.test.ts +220 -0
- package/src/goals/nl-builder.ts +256 -0
- package/src/goals/rhythm.test.ts +177 -0
- package/src/goals/rhythm.ts +275 -0
- package/src/goals/service.test.ts +135 -0
- package/src/goals/service.ts +407 -0
- package/src/goals/types.ts +106 -0
- package/src/goals/workflow-bridge.ts +96 -0
- package/src/integrations/google-api.ts +134 -0
- package/src/integrations/google-auth.ts +175 -0
- package/src/llm/README.md +291 -0
- package/src/llm/anthropic.ts +400 -0
- package/src/llm/gemini.ts +380 -0
- package/src/llm/groq.ts +406 -0
- package/src/llm/history.ts +147 -0
- package/src/llm/index.ts +21 -0
- package/src/llm/manager.ts +226 -0
- package/src/llm/ollama.ts +316 -0
- package/src/llm/openai.ts +411 -0
- package/src/llm/openrouter.ts +390 -0
- package/src/llm/provider.test.ts +487 -0
- package/src/llm/provider.ts +61 -0
- package/src/llm/test.ts +88 -0
- package/src/observers/README.md +278 -0
- package/src/observers/calendar.ts +113 -0
- package/src/observers/clipboard.ts +136 -0
- package/src/observers/email.ts +109 -0
- package/src/observers/example.ts +58 -0
- package/src/observers/file-watcher.ts +124 -0
- package/src/observers/index.ts +159 -0
- package/src/observers/notifications.ts +197 -0
- package/src/observers/observers.test.ts +203 -0
- package/src/observers/processes.ts +225 -0
- package/src/personality/README.md +61 -0
- package/src/personality/adapter.ts +196 -0
- package/src/personality/index.ts +20 -0
- package/src/personality/learner.ts +209 -0
- package/src/personality/model.ts +132 -0
- package/src/personality/personality.test.ts +236 -0
- package/src/roles/README.md +252 -0
- package/src/roles/authority.ts +120 -0
- package/src/roles/example-usage.ts +198 -0
- package/src/roles/index.ts +42 -0
- package/src/roles/loader.ts +143 -0
- package/src/roles/prompt-builder.ts +218 -0
- package/src/roles/test-multi.ts +102 -0
- package/src/roles/test-role.yaml +77 -0
- package/src/roles/test-utils.ts +93 -0
- package/src/roles/test.ts +106 -0
- package/src/roles/tool-guide.ts +195 -0
- package/src/roles/types.ts +36 -0
- package/src/roles/utils.ts +200 -0
- package/src/scripts/google-setup.ts +168 -0
- package/src/sidecar/connection.ts +179 -0
- package/src/sidecar/index.ts +6 -0
- package/src/sidecar/manager.ts +542 -0
- package/src/sidecar/protocol.ts +85 -0
- package/src/sidecar/rpc.ts +161 -0
- package/src/sidecar/scheduler.ts +136 -0
- package/src/sidecar/types.ts +112 -0
- package/src/sidecar/validator.ts +144 -0
- package/src/sites/builder-tools.ts +215 -0
- package/src/sites/dev-server-manager.ts +286 -0
- package/src/sites/fixtures/security-test-site/.jarvis-project.json +6 -0
- package/src/sites/fixtures/security-test-site/Makefile +15 -0
- package/src/sites/fixtures/security-test-site/README.md +18 -0
- package/src/sites/fixtures/security-test-site/index.html +12 -0
- package/src/sites/fixtures/security-test-site/index.ts +16 -0
- package/src/sites/fixtures/security-test-site/package.json +13 -0
- package/src/sites/fixtures/security-test-site/src/app.tsx +780 -0
- package/src/sites/fixtures/security-test-site/tsconfig.json +10 -0
- package/src/sites/git-manager.ts +240 -0
- package/src/sites/github-manager.ts +355 -0
- package/src/sites/index.ts +25 -0
- package/src/sites/project-manager.ts +389 -0
- package/src/sites/proxy.ts +133 -0
- package/src/sites/service.ts +136 -0
- package/src/sites/templates.ts +169 -0
- package/src/sites/types.ts +89 -0
- package/src/user/profile-followup.test.ts +84 -0
- package/src/user/profile-followup.ts +185 -0
- package/src/user/profile.ts +224 -0
- package/src/vault/README.md +110 -0
- package/src/vault/awareness.ts +341 -0
- package/src/vault/commitments.ts +299 -0
- package/src/vault/content-pipeline.ts +270 -0
- package/src/vault/conversations.ts +173 -0
- package/src/vault/dashboard-sessions.ts +44 -0
- package/src/vault/documents.ts +130 -0
- package/src/vault/entities.ts +185 -0
- package/src/vault/extractor.test.ts +356 -0
- package/src/vault/extractor.ts +345 -0
- package/src/vault/facts.ts +190 -0
- package/src/vault/goals.ts +477 -0
- package/src/vault/index.ts +87 -0
- package/src/vault/keychain.ts +99 -0
- package/src/vault/observations.ts +115 -0
- package/src/vault/relationships.ts +178 -0
- package/src/vault/retrieval.test.ts +139 -0
- package/src/vault/retrieval.ts +258 -0
- package/src/vault/schema.ts +709 -0
- package/src/vault/settings.ts +38 -0
- package/src/vault/user-profile.test.ts +113 -0
- package/src/vault/user-profile.ts +176 -0
- package/src/vault/vectors.ts +92 -0
- package/src/vault/webapp-template-seeds.ts +116 -0
- package/src/vault/webapp-templates.ts +244 -0
- package/src/vault/workflows.ts +403 -0
- package/src/workflows/auto-suggest.ts +290 -0
- package/src/workflows/engine.ts +366 -0
- package/src/workflows/events.ts +24 -0
- package/src/workflows/executor.ts +207 -0
- package/src/workflows/nl-builder.ts +198 -0
- package/src/workflows/nodes/actions/agent-task.ts +73 -0
- package/src/workflows/nodes/actions/calendar-action.ts +85 -0
- package/src/workflows/nodes/actions/code-execution.ts +73 -0
- package/src/workflows/nodes/actions/discord.ts +77 -0
- package/src/workflows/nodes/actions/file-write.ts +73 -0
- package/src/workflows/nodes/actions/gmail.ts +69 -0
- package/src/workflows/nodes/actions/http-request.ts +117 -0
- package/src/workflows/nodes/actions/notification.ts +85 -0
- package/src/workflows/nodes/actions/run-tool.ts +55 -0
- package/src/workflows/nodes/actions/send-message.ts +82 -0
- package/src/workflows/nodes/actions/shell-command.ts +76 -0
- package/src/workflows/nodes/actions/telegram.ts +60 -0
- package/src/workflows/nodes/builtin.ts +119 -0
- package/src/workflows/nodes/error/error-handler.ts +37 -0
- package/src/workflows/nodes/error/fallback.ts +47 -0
- package/src/workflows/nodes/error/retry.ts +82 -0
- package/src/workflows/nodes/logic/delay.ts +42 -0
- package/src/workflows/nodes/logic/if-else.ts +41 -0
- package/src/workflows/nodes/logic/loop.ts +90 -0
- package/src/workflows/nodes/logic/merge.ts +38 -0
- package/src/workflows/nodes/logic/race.ts +40 -0
- package/src/workflows/nodes/logic/switch.ts +59 -0
- package/src/workflows/nodes/logic/template-render.ts +53 -0
- package/src/workflows/nodes/logic/variable-get.ts +37 -0
- package/src/workflows/nodes/logic/variable-set.ts +59 -0
- package/src/workflows/nodes/registry.ts +99 -0
- package/src/workflows/nodes/transform/aggregate.ts +99 -0
- package/src/workflows/nodes/transform/csv-parse.ts +70 -0
- package/src/workflows/nodes/transform/json-parse.ts +63 -0
- package/src/workflows/nodes/transform/map-filter.ts +84 -0
- package/src/workflows/nodes/transform/regex-match.ts +89 -0
- package/src/workflows/nodes/triggers/calendar.ts +33 -0
- package/src/workflows/nodes/triggers/clipboard.ts +32 -0
- package/src/workflows/nodes/triggers/cron.ts +40 -0
- package/src/workflows/nodes/triggers/email.ts +40 -0
- package/src/workflows/nodes/triggers/file-change.ts +45 -0
- package/src/workflows/nodes/triggers/git.ts +46 -0
- package/src/workflows/nodes/triggers/manual.ts +23 -0
- package/src/workflows/nodes/triggers/poll.ts +81 -0
- package/src/workflows/nodes/triggers/process.ts +44 -0
- package/src/workflows/nodes/triggers/screen-event.ts +37 -0
- package/src/workflows/nodes/triggers/webhook.ts +39 -0
- package/src/workflows/safe-eval.ts +139 -0
- package/src/workflows/template.ts +118 -0
- package/src/workflows/triggers/cron.ts +311 -0
- package/src/workflows/triggers/manager.ts +285 -0
- package/src/workflows/triggers/observer-bridge.ts +172 -0
- package/src/workflows/triggers/poller.ts +201 -0
- package/src/workflows/triggers/screen-condition.ts +218 -0
- package/src/workflows/triggers/triggers.test.ts +740 -0
- package/src/workflows/triggers/webhook.ts +191 -0
- package/src/workflows/types.ts +133 -0
- package/src/workflows/variables.ts +72 -0
- package/src/workflows/workflows.test.ts +383 -0
- package/src/workflows/yaml.ts +104 -0
- package/ui/dist/index-3gr23jt9.js +112614 -0
- package/ui/dist/index-9vmj8127.css +14239 -0
- package/ui/dist/index-hy9pc1gm.js +112873 -0
- package/ui/dist/index-j2ep5d1w.js +112374 -0
- package/ui/dist/index-jt00vjqs.js +112858 -0
- package/ui/dist/index-k9ymx5qb.js +112374 -0
- package/ui/dist/index.html +16 -0
- package/ui/public/audio/pcm-capture-processor.js +11 -0
- package/ui/public/openwakeword/models/embedding_model.onnx +0 -0
- package/ui/public/openwakeword/models/hey_jarvis_v0.1.onnx +0 -0
- package/ui/public/openwakeword/models/melspectrogram.onnx +0 -0
- package/ui/public/openwakeword/models/silero_vad.onnx +0 -0
- package/ui/public/ort/ort-wasm-simd-threaded.jsep.mjs +106 -0
- package/ui/public/ort/ort-wasm-simd-threaded.jsep.wasm +0 -0
- package/ui/public/ort/ort-wasm-simd-threaded.mjs +59 -0
- package/ui/public/ort/ort-wasm-simd-threaded.wasm +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List Sidecars Tool
|
|
3
|
+
*
|
|
4
|
+
* Returns live sidecar connection status. The AI calls this
|
|
5
|
+
* before routing commands to a remote machine via the `target` param.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ToolDefinition } from './registry.ts';
|
|
9
|
+
import { getSidecarManager } from './sidecar-route.ts';
|
|
10
|
+
|
|
11
|
+
export const listSidecarsTool: ToolDefinition = {
|
|
12
|
+
name: 'list_sidecars',
|
|
13
|
+
description: 'List enrolled sidecar machines with live connection status, capabilities, and system info. Use this to discover available remote targets before using run_command, read_file, write_file, or list_directory with a "target" parameter.',
|
|
14
|
+
category: 'sidecar',
|
|
15
|
+
parameters: {
|
|
16
|
+
filter: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
description: 'Optional filter string — only sidecars whose name or ID contain this string are returned (case-insensitive). Omit to list all.',
|
|
19
|
+
required: false,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
execute: async (params) => {
|
|
23
|
+
const manager = getSidecarManager();
|
|
24
|
+
if (!manager) {
|
|
25
|
+
return 'Sidecar system not initialized.';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const filter = (params.filter as string | undefined)?.trim().toLowerCase();
|
|
29
|
+
let sidecars = manager.listSidecars();
|
|
30
|
+
|
|
31
|
+
if (filter) {
|
|
32
|
+
sidecars = sidecars.filter(
|
|
33
|
+
(s) => s.name.toLowerCase().includes(filter) || s.id.toLowerCase().includes(filter),
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (sidecars.length === 0) {
|
|
38
|
+
return filter
|
|
39
|
+
? `No sidecars matching "${filter}".`
|
|
40
|
+
: 'No sidecars enrolled.';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return sidecars.map((s) => {
|
|
44
|
+
const status = s.connected ? 'CONNECTED' : 'OFFLINE';
|
|
45
|
+
const caps = s.capabilities?.length ? s.capabilities.join(', ') : 'none';
|
|
46
|
+
const host = s.hostname ?? 'unknown';
|
|
47
|
+
const os = s.os ?? 'unknown';
|
|
48
|
+
const lastSeen = s.last_seen_at ?? 'never';
|
|
49
|
+
let line = `[${status}] ${s.name} (${s.id})\n Host: ${host} | OS: ${os} | Capabilities: ${caps} | Last seen: ${lastSeen}`;
|
|
50
|
+
if (s.unavailable_capabilities?.length) {
|
|
51
|
+
const unavailLines = s.unavailable_capabilities.map(u => ` - ${u.name}: ${u.reason}`);
|
|
52
|
+
line += `\n Unavailable (missing deps):\n${unavailLines.join('\n')}`;
|
|
53
|
+
}
|
|
54
|
+
return line;
|
|
55
|
+
}).join('\n\n');
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidecar Routing — Transparent Remote Execution
|
|
3
|
+
*
|
|
4
|
+
* Holds a reference to the SidecarManager and provides a helper
|
|
5
|
+
* that existing tools call when a `target` parameter is present.
|
|
6
|
+
* The AI decides where to run a command by specifying (or omitting) a target.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { SidecarManager } from '../../sidecar/manager.ts';
|
|
10
|
+
import type { SidecarCapability, SidecarInfo } from '../../sidecar/types.ts';
|
|
11
|
+
|
|
12
|
+
let sidecarManager: SidecarManager | null = null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Inject the sidecar manager at startup. Called once from the daemon.
|
|
16
|
+
*/
|
|
17
|
+
export function setSidecarManagerRef(manager: SidecarManager): void {
|
|
18
|
+
sidecarManager = manager;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getSidecarManager(): SidecarManager | null {
|
|
22
|
+
return sidecarManager;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Find a sidecar by name or ID.
|
|
27
|
+
* Priority: exact ID → exact name (case-insensitive) → contains match.
|
|
28
|
+
*/
|
|
29
|
+
function findSidecar(nameOrId: string, sidecars: SidecarInfo[]): SidecarInfo | null {
|
|
30
|
+
const query = nameOrId.trim();
|
|
31
|
+
if (!query) return null;
|
|
32
|
+
|
|
33
|
+
// Exact ID match
|
|
34
|
+
const byId = sidecars.find((s) => s.id === query);
|
|
35
|
+
if (byId) return byId;
|
|
36
|
+
|
|
37
|
+
// Exact name (case-insensitive)
|
|
38
|
+
const lower = query.toLowerCase();
|
|
39
|
+
const byName = sidecars.find((s) => s.name.toLowerCase() === lower);
|
|
40
|
+
if (byName) return byName;
|
|
41
|
+
|
|
42
|
+
// Contains match
|
|
43
|
+
const byContains = sidecars.find((s) => s.name.toLowerCase().includes(lower));
|
|
44
|
+
return byContains ?? null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Route an RPC call to a sidecar. Returns the result string, or an error message.
|
|
49
|
+
*
|
|
50
|
+
* @param target - Sidecar name or ID
|
|
51
|
+
* @param method - RPC method name (e.g. "run_command", "read_file")
|
|
52
|
+
* @param params - RPC parameters
|
|
53
|
+
* @param requiredCapability - The sidecar must advertise this capability
|
|
54
|
+
*/
|
|
55
|
+
export async function routeToSidecar(
|
|
56
|
+
target: string,
|
|
57
|
+
method: string,
|
|
58
|
+
params: Record<string, unknown>,
|
|
59
|
+
requiredCapability: SidecarCapability,
|
|
60
|
+
): Promise<string> {
|
|
61
|
+
if (!sidecarManager) {
|
|
62
|
+
return 'Error: Sidecar system not initialized.';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const sidecars = sidecarManager.listSidecars();
|
|
66
|
+
const sidecar = findSidecar(target, sidecars);
|
|
67
|
+
|
|
68
|
+
if (!sidecar) {
|
|
69
|
+
const available = sidecars.map((s) => s.name).join(', ') || 'none';
|
|
70
|
+
return `Error: No sidecar found matching "${target}". Available: ${available}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!sidecar.connected) {
|
|
74
|
+
return `Error: Sidecar "${sidecar.name}" is offline.`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Check if capability is enabled but unavailable (missing system dependencies)
|
|
78
|
+
const unavail = sidecar.unavailable_capabilities?.find(u => u.name === requiredCapability);
|
|
79
|
+
if (unavail) {
|
|
80
|
+
return `Error: Sidecar "${sidecar.name}" has "${requiredCapability}" enabled but it is unavailable: ${unavail.reason}. Do NOT retry.`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (sidecar.capabilities && !sidecar.capabilities.includes(requiredCapability)) {
|
|
84
|
+
return `Error: Sidecar "${sidecar.name}" does not have the "${requiredCapability}" capability enabled. Available capabilities: ${sidecar.capabilities.join(', ')}. Do NOT retry — ask the user to enable it in the sidecar's config if needed.`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const result = await sidecarManager.dispatchRPC(sidecar.id, method, params);
|
|
89
|
+
|
|
90
|
+
if (result === 'detached') {
|
|
91
|
+
return `Task dispatched to "${sidecar.name}" and running in the background.`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
97
|
+
|
|
98
|
+
// METHOD_NOT_FOUND means the capability is disabled — tell the LLM not to retry
|
|
99
|
+
if (msg.includes('METHOD_NOT_FOUND')) {
|
|
100
|
+
return `Error [${sidecar.name}]: Method "${method}" is not available. The "${requiredCapability}" capability is not enabled on this sidecar. Do NOT retry this call — ask the user to enable the capability in the sidecar's config if needed.`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return `Error [${sidecar.name}]: ${msg}`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manage Workflow Tool — Chat-Driven Workflow Automation
|
|
3
|
+
*
|
|
4
|
+
* Allows the primary agent to create, list, run, delete, enable/disable,
|
|
5
|
+
* and describe workflows directly from natural language chat.
|
|
6
|
+
* Uses the NLWorkflowBuilder to parse descriptions into workflow definitions.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ToolDefinition } from './registry.ts';
|
|
10
|
+
import type { WorkflowEngine } from '../../workflows/engine.ts';
|
|
11
|
+
import type { NLWorkflowBuilder } from '../../workflows/nl-builder.ts';
|
|
12
|
+
import type { TriggerManager } from '../../workflows/triggers/manager.ts';
|
|
13
|
+
import * as vault from '../../vault/workflows.ts';
|
|
14
|
+
|
|
15
|
+
export type WorkflowToolDeps = {
|
|
16
|
+
workflowEngine: WorkflowEngine;
|
|
17
|
+
nlBuilder: NLWorkflowBuilder;
|
|
18
|
+
triggerManager: TriggerManager;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function createManageWorkflowTool(deps: WorkflowToolDeps): ToolDefinition {
|
|
22
|
+
return {
|
|
23
|
+
name: 'manage_workflow',
|
|
24
|
+
description: [
|
|
25
|
+
'Create, list, run, delete, enable/disable, and inspect workflow automations.',
|
|
26
|
+
'Workflows are event-driven: "when X happens, do Y". They support triggers (cron, webhook, file changes, screen events),',
|
|
27
|
+
'actions (HTTP requests, send messages, run tools, agent tasks), logic (if/else, loops, delays), and error handling.',
|
|
28
|
+
'',
|
|
29
|
+
'Actions: create, list, run, delete, enable, disable, describe',
|
|
30
|
+
].join('\n'),
|
|
31
|
+
category: 'automation',
|
|
32
|
+
parameters: {
|
|
33
|
+
action: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
description: 'The action: "create", "list", "run", "delete", "enable", "disable", "describe"',
|
|
36
|
+
required: true,
|
|
37
|
+
},
|
|
38
|
+
name: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: 'Workflow name (required for "create")',
|
|
41
|
+
required: false,
|
|
42
|
+
},
|
|
43
|
+
description: {
|
|
44
|
+
type: 'string',
|
|
45
|
+
description: 'Natural language description of what the workflow should do (for "create"). Example: "Every morning at 9am, check my email and send a Telegram summary"',
|
|
46
|
+
required: false,
|
|
47
|
+
},
|
|
48
|
+
workflow_id: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'Target workflow ID (for "run", "delete", "enable", "disable", "describe")',
|
|
51
|
+
required: false,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
execute: async (params) => {
|
|
55
|
+
const action = String(params.action ?? '').toLowerCase();
|
|
56
|
+
|
|
57
|
+
switch (action) {
|
|
58
|
+
case 'create': {
|
|
59
|
+
const name = params.name as string;
|
|
60
|
+
const description = params.description as string;
|
|
61
|
+
if (!description) return 'Error: "description" is required for create. Describe what the workflow should do in natural language.';
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
// Use NL builder to parse description into a workflow definition
|
|
65
|
+
const definition = await deps.nlBuilder.parseDescription(description);
|
|
66
|
+
|
|
67
|
+
// Create the workflow in vault
|
|
68
|
+
const workflow = vault.createWorkflow(
|
|
69
|
+
name || 'Untitled Workflow',
|
|
70
|
+
{ description },
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// Create first version with the generated definition
|
|
74
|
+
vault.createVersion(workflow.id, definition, 'Created via chat');
|
|
75
|
+
|
|
76
|
+
// Register triggers so cron/webhook/poll triggers activate
|
|
77
|
+
try {
|
|
78
|
+
deps.triggerManager.registerWorkflow(workflow.id, definition);
|
|
79
|
+
} catch {
|
|
80
|
+
// Non-fatal — triggers can be registered later
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const nodeTypes = definition.nodes.map(n => n.type).join(', ');
|
|
84
|
+
return `Workflow created successfully!\n\n` +
|
|
85
|
+
`- **ID**: ${workflow.id}\n` +
|
|
86
|
+
`- **Name**: ${name || 'Untitled Workflow'}\n` +
|
|
87
|
+
`- **Nodes**: ${definition.nodes.length} (${nodeTypes})\n` +
|
|
88
|
+
`- **Edges**: ${definition.edges.length}\n` +
|
|
89
|
+
`- **Version**: 1\n\n` +
|
|
90
|
+
`The workflow is enabled and its triggers are active. ` +
|
|
91
|
+
`You can view and edit it in the Workflows dashboard, or run it manually.`;
|
|
92
|
+
} catch (err) {
|
|
93
|
+
return `Failed to create workflow: ${err instanceof Error ? err.message : err}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
case 'list': {
|
|
98
|
+
const workflows = vault.findWorkflows();
|
|
99
|
+
if (workflows.length === 0) {
|
|
100
|
+
return 'No workflows found. Use action "create" with a description to create one.';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const lines = workflows.map(wf => {
|
|
104
|
+
const status = wf.enabled ? 'Active' : 'Disabled';
|
|
105
|
+
const lastRun = wf.last_executed_at
|
|
106
|
+
? new Date(wf.last_executed_at).toLocaleString()
|
|
107
|
+
: 'Never';
|
|
108
|
+
return `- **${wf.name}** (${wf.id})\n Status: ${status} | v${wf.current_version} | ${wf.execution_count} runs | Last: ${lastRun}`;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return `Found ${workflows.length} workflow(s):\n\n${lines.join('\n\n')}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
case 'run': {
|
|
115
|
+
const id = params.workflow_id as string;
|
|
116
|
+
if (!id) return 'Error: "workflow_id" is required for run.';
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const execution = await deps.workflowEngine.execute(id, 'manual');
|
|
120
|
+
return `Workflow execution started.\n\n- **Execution ID**: ${execution.id}\n- **Status**: ${execution.status}\n\nThe workflow is running in the background. Check the Workflows dashboard for real-time progress.`;
|
|
121
|
+
} catch (err) {
|
|
122
|
+
return `Failed to run workflow: ${err instanceof Error ? err.message : err}`;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
case 'delete': {
|
|
127
|
+
const id = params.workflow_id as string;
|
|
128
|
+
if (!id) return 'Error: "workflow_id" is required for delete.';
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const wf = vault.getWorkflow(id);
|
|
132
|
+
if (!wf) return `Workflow "${id}" not found.`;
|
|
133
|
+
|
|
134
|
+
deps.triggerManager.unregisterWorkflow(id);
|
|
135
|
+
vault.deleteWorkflow(id);
|
|
136
|
+
return `Workflow "${wf.name}" (${id}) has been deleted.`;
|
|
137
|
+
} catch (err) {
|
|
138
|
+
return `Failed to delete workflow: ${err instanceof Error ? err.message : err}`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
case 'enable': {
|
|
143
|
+
const id = params.workflow_id as string;
|
|
144
|
+
if (!id) return 'Error: "workflow_id" is required for enable.';
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
vault.updateWorkflow(id, { enabled: true });
|
|
148
|
+
const version = vault.getLatestVersion(id);
|
|
149
|
+
if (version) {
|
|
150
|
+
deps.triggerManager.registerWorkflow(id, version.definition);
|
|
151
|
+
}
|
|
152
|
+
return `Workflow "${id}" is now enabled. Triggers are active.`;
|
|
153
|
+
} catch (err) {
|
|
154
|
+
return `Failed to enable workflow: ${err instanceof Error ? err.message : err}`;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
case 'disable': {
|
|
159
|
+
const id = params.workflow_id as string;
|
|
160
|
+
if (!id) return 'Error: "workflow_id" is required for disable.';
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
vault.updateWorkflow(id, { enabled: false });
|
|
164
|
+
deps.triggerManager.unregisterWorkflow(id);
|
|
165
|
+
return `Workflow "${id}" is now disabled. Triggers are deactivated.`;
|
|
166
|
+
} catch (err) {
|
|
167
|
+
return `Failed to disable workflow: ${err instanceof Error ? err.message : err}`;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
case 'describe': {
|
|
172
|
+
const id = params.workflow_id as string;
|
|
173
|
+
if (!id) return 'Error: "workflow_id" is required for describe.';
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
const wf = vault.getWorkflow(id);
|
|
177
|
+
if (!wf) return `Workflow "${id}" not found.`;
|
|
178
|
+
|
|
179
|
+
const version = vault.getLatestVersion(id);
|
|
180
|
+
const def = version?.definition;
|
|
181
|
+
|
|
182
|
+
let result = `**${wf.name}** (${wf.id})\n\n`;
|
|
183
|
+
if (wf.description) result += `${wf.description}\n\n`;
|
|
184
|
+
result += `- Status: ${wf.enabled ? 'Active' : 'Disabled'}\n`;
|
|
185
|
+
result += `- Version: ${wf.current_version}\n`;
|
|
186
|
+
result += `- Executions: ${wf.execution_count}\n`;
|
|
187
|
+
if (wf.tags.length > 0) result += `- Tags: ${wf.tags.join(', ')}\n`;
|
|
188
|
+
|
|
189
|
+
if (def) {
|
|
190
|
+
result += `\n**Nodes (${def.nodes.length}):**\n`;
|
|
191
|
+
for (const node of def.nodes) {
|
|
192
|
+
result += ` - ${node.label} (${node.type})\n`;
|
|
193
|
+
}
|
|
194
|
+
result += `\n**Connections (${def.edges.length}):**\n`;
|
|
195
|
+
for (const edge of def.edges) {
|
|
196
|
+
const srcNode = def.nodes.find(n => n.id === edge.source);
|
|
197
|
+
const tgtNode = def.nodes.find(n => n.id === edge.target);
|
|
198
|
+
result += ` - ${srcNode?.label ?? edge.source} → ${tgtNode?.label ?? edge.target}`;
|
|
199
|
+
if (edge.sourceHandle) result += ` [${edge.sourceHandle}]`;
|
|
200
|
+
result += '\n';
|
|
201
|
+
}
|
|
202
|
+
result += `\n**Settings:** retries=${def.settings.maxRetries}, timeout=${def.settings.timeoutMs}ms, onError=${def.settings.onError}`;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return result;
|
|
206
|
+
} catch (err) {
|
|
207
|
+
return `Failed to describe workflow: ${err instanceof Error ? err.message : err}`;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
default:
|
|
212
|
+
return `Unknown action "${action}". Available actions: create, list, run, delete, enable, disable, describe`;
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { RoleDefinition } from '../roles/types.ts';
|
|
2
|
+
import type { LLMMessage } from '../llm/provider.ts';
|
|
3
|
+
|
|
4
|
+
export type AgentStatus = 'active' | 'idle' | 'terminated';
|
|
5
|
+
|
|
6
|
+
export type AuthorityBounds = {
|
|
7
|
+
max_authority_level: number;
|
|
8
|
+
allowed_tools: string[];
|
|
9
|
+
denied_tools: string[];
|
|
10
|
+
max_token_budget: number;
|
|
11
|
+
can_spawn_children: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type Agent = {
|
|
15
|
+
id: string;
|
|
16
|
+
role: RoleDefinition;
|
|
17
|
+
parent_id: string | null;
|
|
18
|
+
status: AgentStatus;
|
|
19
|
+
session_id: string;
|
|
20
|
+
current_task: string | null;
|
|
21
|
+
authority: AuthorityBounds;
|
|
22
|
+
memory_scope: string[];
|
|
23
|
+
created_at: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default authority bounds for an agent
|
|
28
|
+
*/
|
|
29
|
+
function getDefaultAuthority(role: RoleDefinition): AuthorityBounds {
|
|
30
|
+
return {
|
|
31
|
+
max_authority_level: role.authority_level,
|
|
32
|
+
allowed_tools: role.tools,
|
|
33
|
+
denied_tools: [],
|
|
34
|
+
max_token_budget: 100000,
|
|
35
|
+
can_spawn_children: role.sub_roles.length > 0,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Merge custom authority bounds with defaults
|
|
41
|
+
*/
|
|
42
|
+
function mergeAuthority(
|
|
43
|
+
defaultAuth: AuthorityBounds,
|
|
44
|
+
custom?: Partial<AuthorityBounds>
|
|
45
|
+
): AuthorityBounds {
|
|
46
|
+
if (!custom) return defaultAuth;
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
max_authority_level: custom.max_authority_level ?? defaultAuth.max_authority_level,
|
|
50
|
+
allowed_tools: custom.allowed_tools ?? defaultAuth.allowed_tools,
|
|
51
|
+
denied_tools: custom.denied_tools ?? defaultAuth.denied_tools,
|
|
52
|
+
max_token_budget: custom.max_token_budget ?? defaultAuth.max_token_budget,
|
|
53
|
+
can_spawn_children: custom.can_spawn_children ?? defaultAuth.can_spawn_children,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class AgentInstance {
|
|
58
|
+
public readonly agent: Agent;
|
|
59
|
+
private messageHistory: LLMMessage[];
|
|
60
|
+
|
|
61
|
+
constructor(
|
|
62
|
+
role: RoleDefinition,
|
|
63
|
+
opts?: {
|
|
64
|
+
parent_id?: string;
|
|
65
|
+
authority?: Partial<AuthorityBounds>;
|
|
66
|
+
memory_scope?: string[];
|
|
67
|
+
}
|
|
68
|
+
) {
|
|
69
|
+
const defaultAuth = getDefaultAuthority(role);
|
|
70
|
+
const authority = mergeAuthority(defaultAuth, opts?.authority);
|
|
71
|
+
|
|
72
|
+
this.agent = {
|
|
73
|
+
id: crypto.randomUUID(),
|
|
74
|
+
role,
|
|
75
|
+
parent_id: opts?.parent_id ?? null,
|
|
76
|
+
status: 'active',
|
|
77
|
+
session_id: crypto.randomUUID(),
|
|
78
|
+
current_task: null,
|
|
79
|
+
authority,
|
|
80
|
+
memory_scope: opts?.memory_scope ?? [],
|
|
81
|
+
created_at: Date.now(),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
this.messageHistory = [];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get id(): string {
|
|
88
|
+
return this.agent.id;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get status(): AgentStatus {
|
|
92
|
+
return this.agent.status;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
setTask(taskDescription: string): void {
|
|
96
|
+
this.agent.current_task = taskDescription;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
clearTask(): void {
|
|
100
|
+
this.agent.current_task = null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
addMessage(role: 'user' | 'assistant' | 'system', content: string): void {
|
|
104
|
+
this.messageHistory.push({ role, content });
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
getMessages(): LLMMessage[] {
|
|
108
|
+
return [...this.messageHistory];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
terminate(): void {
|
|
112
|
+
this.agent.status = 'terminated';
|
|
113
|
+
this.clearTask();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
activate(): void {
|
|
117
|
+
if (this.agent.status !== 'terminated') {
|
|
118
|
+
this.agent.status = 'active';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
idle(): void {
|
|
123
|
+
if (this.agent.status !== 'terminated') {
|
|
124
|
+
this.agent.status = 'idle';
|
|
125
|
+
this.clearTask();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
toJSON(): Agent {
|
|
130
|
+
return { ...this.agent };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { AgentInstance } from './agent.ts';
|
|
2
|
+
import type { Commitment } from '../vault/commitments.ts';
|
|
3
|
+
import { createCommitment } from '../vault/commitments.ts';
|
|
4
|
+
import { sendMessage, type MessagePriority } from './messaging.ts';
|
|
5
|
+
|
|
6
|
+
export type DelegationResult = {
|
|
7
|
+
success: boolean;
|
|
8
|
+
agent_id: string;
|
|
9
|
+
commitment_id: string;
|
|
10
|
+
message?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Delegate a task from parent to child agent
|
|
15
|
+
*/
|
|
16
|
+
export function delegateTask(
|
|
17
|
+
parent: AgentInstance,
|
|
18
|
+
child: AgentInstance,
|
|
19
|
+
task: {
|
|
20
|
+
what: string;
|
|
21
|
+
context: string;
|
|
22
|
+
priority?: 'low' | 'normal' | 'high' | 'critical';
|
|
23
|
+
deadline?: number;
|
|
24
|
+
}
|
|
25
|
+
): DelegationResult {
|
|
26
|
+
// Verify parent-child relationship
|
|
27
|
+
if (child.agent.parent_id !== parent.id) {
|
|
28
|
+
return {
|
|
29
|
+
success: false,
|
|
30
|
+
agent_id: child.id,
|
|
31
|
+
commitment_id: '',
|
|
32
|
+
message: 'Agent is not a child of the parent agent',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Verify parent has authority to spawn children
|
|
37
|
+
if (!parent.agent.authority.can_spawn_children) {
|
|
38
|
+
return {
|
|
39
|
+
success: false,
|
|
40
|
+
agent_id: child.id,
|
|
41
|
+
commitment_id: '',
|
|
42
|
+
message: 'Parent agent does not have authority to delegate tasks',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Create a commitment for the child agent
|
|
47
|
+
const commitment = createCommitment(task.what, {
|
|
48
|
+
context: task.context,
|
|
49
|
+
priority: task.priority ?? 'normal',
|
|
50
|
+
when_due: task.deadline,
|
|
51
|
+
assigned_to: child.id,
|
|
52
|
+
created_from: parent.id,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Send a task message to the child
|
|
56
|
+
const message = sendMessage(parent.id, child.id, 'task', task.what, {
|
|
57
|
+
priority: (task.priority === 'critical' ? 'urgent' : task.priority ?? 'normal') as MessagePriority,
|
|
58
|
+
requires_response: true,
|
|
59
|
+
deadline: task.deadline,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Set the task on the child agent
|
|
63
|
+
child.setTask(task.what);
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
success: true,
|
|
67
|
+
agent_id: child.id,
|
|
68
|
+
commitment_id: commitment.id,
|
|
69
|
+
message: `Task delegated successfully (message: ${message.id})`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Report task completion back to parent
|
|
75
|
+
*/
|
|
76
|
+
export function reportCompletion(
|
|
77
|
+
child: AgentInstance,
|
|
78
|
+
parent: AgentInstance,
|
|
79
|
+
result: {
|
|
80
|
+
success: boolean;
|
|
81
|
+
summary: string;
|
|
82
|
+
details?: string;
|
|
83
|
+
}
|
|
84
|
+
): void {
|
|
85
|
+
// Verify parent-child relationship
|
|
86
|
+
if (child.agent.parent_id !== parent.id) {
|
|
87
|
+
throw new Error('Agent is not a child of the specified parent');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Build report content
|
|
91
|
+
const content = JSON.stringify({
|
|
92
|
+
task: child.agent.current_task,
|
|
93
|
+
success: result.success,
|
|
94
|
+
summary: result.summary,
|
|
95
|
+
details: result.details,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Send a report message to the parent
|
|
99
|
+
sendMessage(child.id, parent.id, 'report', content, {
|
|
100
|
+
priority: result.success ? 'normal' : 'high',
|
|
101
|
+
requires_response: false,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Clear the child's current task
|
|
105
|
+
child.clearTask();
|
|
106
|
+
child.idle();
|
|
107
|
+
}
|