@usejarvis/brain 0.1.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 +278 -0
- package/bin/jarvis.ts +413 -0
- package/package.json +74 -0
- package/scripts/ensure-bun.cjs +8 -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 +252 -0
- package/src/actions/browser/session.ts +437 -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 +321 -0
- package/src/actions/tools/builtin.ts +846 -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/goals.ts +376 -0
- package/src/actions/tools/local-tools-guard.ts +20 -0
- package/src/actions/tools/registry.ts +171 -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 +576 -0
- package/src/agents/role-discovery.ts +61 -0
- package/src/agents/sub-agent-runner.ts +307 -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 +297 -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 +241 -0
- package/src/cli/deps.ts +449 -0
- package/src/cli/doctor.ts +230 -0
- package/src/cli/helpers.ts +401 -0
- package/src/cli/onboard.ts +580 -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/desktop-notify.ts +114 -0
- package/src/comms/example.ts +129 -0
- package/src/comms/index.ts +129 -0
- package/src/comms/streaming.ts +142 -0
- package/src/comms/voice.test.ts +152 -0
- package/src/comms/voice.ts +291 -0
- package/src/comms/websocket.test.ts +409 -0
- package/src/comms/websocket.ts +473 -0
- package/src/config/README.md +387 -0
- package/src/config/index.ts +6 -0
- package/src/config/loader.test.ts +137 -0
- package/src/config/loader.ts +142 -0
- package/src/config/types.ts +260 -0
- package/src/daemon/README.md +232 -0
- package/src/daemon/agent-service-interface.ts +9 -0
- package/src/daemon/agent-service.ts +600 -0
- package/src/daemon/api-routes.ts +2119 -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/event-classifier.ts +239 -0
- package/src/daemon/event-coalescer.ts +123 -0
- package/src/daemon/event-reactor.ts +214 -0
- package/src/daemon/health.ts +220 -0
- package/src/daemon/index.ts +1004 -0
- package/src/daemon/llm-settings.ts +316 -0
- package/src/daemon/observer-service.ts +150 -0
- package/src/daemon/pid.ts +98 -0
- package/src/daemon/research-queue.ts +155 -0
- package/src/daemon/services.ts +175 -0
- package/src/daemon/ws-service.ts +788 -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 +348 -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 +386 -0
- package/src/llm/gemini.ts +371 -0
- package/src/llm/index.ts +19 -0
- package/src/llm/manager.ts +153 -0
- package/src/llm/ollama.ts +307 -0
- package/src/llm/openai.ts +350 -0
- package/src/llm/provider.test.ts +231 -0
- package/src/llm/provider.ts +60 -0
- package/src/llm/test.ts +87 -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 +119 -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 +194 -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 +190 -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/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 +260 -0
- package/src/vault/conversations.ts +173 -0
- package/src/vault/entities.ts +180 -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 +126 -0
- package/src/vault/retrieval.ts +227 -0
- package/src/vault/schema.ts +658 -0
- package/src/vault/settings.ts +38 -0
- package/src/vault/vectors.ts +92 -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-j75njzc1.css +1199 -0
- package/ui/dist/index-p2zh407q.js +80603 -0
- package/ui/dist/index.html +13 -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,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
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { AgentInstance } from './agent.ts';
|
|
2
|
+
|
|
3
|
+
export type AgentTreeNode = {
|
|
4
|
+
agent: AgentInstance;
|
|
5
|
+
children: AgentTreeNode[];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export class AgentHierarchy {
|
|
9
|
+
private agents: Map<string, AgentInstance>;
|
|
10
|
+
private children: Map<string, Set<string>>; // parent_id -> child_ids
|
|
11
|
+
|
|
12
|
+
constructor() {
|
|
13
|
+
this.agents = new Map();
|
|
14
|
+
this.children = new Map();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
addAgent(agent: AgentInstance): void {
|
|
18
|
+
this.agents.set(agent.id, agent);
|
|
19
|
+
|
|
20
|
+
// Track parent-child relationship
|
|
21
|
+
const parentId = agent.agent.parent_id;
|
|
22
|
+
if (parentId) {
|
|
23
|
+
if (!this.children.has(parentId)) {
|
|
24
|
+
this.children.set(parentId, new Set());
|
|
25
|
+
}
|
|
26
|
+
this.children.get(parentId)!.add(agent.id);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
removeAgent(agentId: string): void {
|
|
31
|
+
const agent = this.agents.get(agentId);
|
|
32
|
+
if (!agent) return;
|
|
33
|
+
|
|
34
|
+
// Recursively remove all children first
|
|
35
|
+
const childIds = this.children.get(agentId);
|
|
36
|
+
if (childIds) {
|
|
37
|
+
for (const childId of Array.from(childIds)) {
|
|
38
|
+
this.removeAgent(childId);
|
|
39
|
+
}
|
|
40
|
+
this.children.delete(agentId);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Remove from parent's children set
|
|
44
|
+
const parentId = agent.agent.parent_id;
|
|
45
|
+
if (parentId) {
|
|
46
|
+
const siblings = this.children.get(parentId);
|
|
47
|
+
if (siblings) {
|
|
48
|
+
siblings.delete(agentId);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Remove the agent
|
|
53
|
+
this.agents.delete(agentId);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
getAgent(agentId: string): AgentInstance | undefined {
|
|
57
|
+
return this.agents.get(agentId);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getChildren(agentId: string): AgentInstance[] {
|
|
61
|
+
const childIds = this.children.get(agentId);
|
|
62
|
+
if (!childIds) return [];
|
|
63
|
+
|
|
64
|
+
return Array.from(childIds)
|
|
65
|
+
.map((id) => this.agents.get(id))
|
|
66
|
+
.filter((agent): agent is AgentInstance => agent !== undefined);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getParent(agentId: string): AgentInstance | undefined {
|
|
70
|
+
const agent = this.agents.get(agentId);
|
|
71
|
+
if (!agent?.agent.parent_id) return undefined;
|
|
72
|
+
|
|
73
|
+
return this.agents.get(agent.agent.parent_id);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getPrimary(): AgentInstance | undefined {
|
|
77
|
+
// Find the agent with no parent
|
|
78
|
+
for (const agent of this.agents.values()) {
|
|
79
|
+
if (agent.agent.parent_id === null) {
|
|
80
|
+
return agent;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getAllAgents(): AgentInstance[] {
|
|
87
|
+
return Array.from(this.agents.values());
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getActiveAgents(): AgentInstance[] {
|
|
91
|
+
return this.getAllAgents().filter((agent) => agent.status === 'active');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get the full tree structure for display
|
|
96
|
+
*/
|
|
97
|
+
getTree(): AgentTreeNode {
|
|
98
|
+
const primary = this.getPrimary();
|
|
99
|
+
if (!primary) {
|
|
100
|
+
throw new Error('No primary agent found in hierarchy');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return this.buildTreeNode(primary);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private buildTreeNode(agent: AgentInstance): AgentTreeNode {
|
|
107
|
+
const children = this.getChildren(agent.id);
|
|
108
|
+
return {
|
|
109
|
+
agent,
|
|
110
|
+
children: children.map((child) => this.buildTreeNode(child)),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Agent lifecycle
|
|
2
|
+
export { AgentInstance } from './agent.ts';
|
|
3
|
+
export type { Agent, AgentStatus, AuthorityBounds } from './agent.ts';
|
|
4
|
+
|
|
5
|
+
// Inter-agent communication
|
|
6
|
+
export { sendMessage, getMessages, getPendingMessages } from './messaging.ts';
|
|
7
|
+
export type { AgentMessage, MessageType, MessagePriority } from './messaging.ts';
|
|
8
|
+
|
|
9
|
+
// Task delegation
|
|
10
|
+
export { delegateTask, reportCompletion } from './delegation.ts';
|
|
11
|
+
export type { DelegationResult } from './delegation.ts';
|
|
12
|
+
|
|
13
|
+
// Hierarchy management
|
|
14
|
+
export { AgentHierarchy } from './hierarchy.ts';
|
|
15
|
+
export type { AgentTreeNode } from './hierarchy.ts';
|
|
16
|
+
|
|
17
|
+
// Main orchestrator
|
|
18
|
+
export { AgentOrchestrator } from './orchestrator.ts';
|
|
19
|
+
export type { LLMManager } from '../llm/manager.ts';
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { getDb, generateId } from '../vault/schema.ts';
|
|
2
|
+
|
|
3
|
+
export type MessageType = 'task' | 'report' | 'question' | 'escalation';
|
|
4
|
+
export type MessagePriority = 'low' | 'normal' | 'high' | 'urgent';
|
|
5
|
+
|
|
6
|
+
export type AgentMessage = {
|
|
7
|
+
id: string;
|
|
8
|
+
from_agent: string;
|
|
9
|
+
to_agent: string;
|
|
10
|
+
type: MessageType;
|
|
11
|
+
content: string;
|
|
12
|
+
priority: MessagePriority;
|
|
13
|
+
requires_response: boolean;
|
|
14
|
+
deadline: number | null;
|
|
15
|
+
created_at: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type MessageRow = {
|
|
19
|
+
id: string;
|
|
20
|
+
from_agent: string;
|
|
21
|
+
to_agent: string;
|
|
22
|
+
type: MessageType;
|
|
23
|
+
content: string;
|
|
24
|
+
priority: MessagePriority;
|
|
25
|
+
requires_response: number;
|
|
26
|
+
deadline: number | null;
|
|
27
|
+
created_at: number;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Convert database row to AgentMessage
|
|
32
|
+
*/
|
|
33
|
+
function parseMessage(row: MessageRow): AgentMessage {
|
|
34
|
+
return {
|
|
35
|
+
...row,
|
|
36
|
+
requires_response: row.requires_response === 1,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Send a message between agents (persisted to SQLite)
|
|
42
|
+
*/
|
|
43
|
+
export function sendMessage(
|
|
44
|
+
from: string,
|
|
45
|
+
to: string,
|
|
46
|
+
type: MessageType,
|
|
47
|
+
content: string,
|
|
48
|
+
opts?: {
|
|
49
|
+
priority?: MessagePriority;
|
|
50
|
+
requires_response?: boolean;
|
|
51
|
+
deadline?: number;
|
|
52
|
+
}
|
|
53
|
+
): AgentMessage {
|
|
54
|
+
const db = getDb();
|
|
55
|
+
const id = generateId();
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
const priority = opts?.priority ?? 'normal';
|
|
58
|
+
const requiresResponse = opts?.requires_response ?? false;
|
|
59
|
+
const deadline = opts?.deadline ?? null;
|
|
60
|
+
|
|
61
|
+
const stmt = db.prepare(
|
|
62
|
+
'INSERT INTO agent_messages (id, from_agent, to_agent, type, content, priority, requires_response, deadline, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
stmt.run(
|
|
66
|
+
id,
|
|
67
|
+
from,
|
|
68
|
+
to,
|
|
69
|
+
type,
|
|
70
|
+
content,
|
|
71
|
+
priority,
|
|
72
|
+
requiresResponse ? 1 : 0,
|
|
73
|
+
deadline,
|
|
74
|
+
now
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
id,
|
|
79
|
+
from_agent: from,
|
|
80
|
+
to_agent: to,
|
|
81
|
+
type,
|
|
82
|
+
content,
|
|
83
|
+
priority,
|
|
84
|
+
requires_response: requiresResponse,
|
|
85
|
+
deadline,
|
|
86
|
+
created_at: now,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get messages for an agent
|
|
92
|
+
*/
|
|
93
|
+
export function getMessages(
|
|
94
|
+
agentId: string,
|
|
95
|
+
opts?: {
|
|
96
|
+
type?: MessageType;
|
|
97
|
+
limit?: number;
|
|
98
|
+
}
|
|
99
|
+
): AgentMessage[] {
|
|
100
|
+
const db = getDb();
|
|
101
|
+
const conditions: string[] = ['to_agent = ?'];
|
|
102
|
+
const params: unknown[] = [agentId];
|
|
103
|
+
|
|
104
|
+
if (opts?.type) {
|
|
105
|
+
conditions.push('type = ?');
|
|
106
|
+
params.push(opts.type);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const where = conditions.join(' AND ');
|
|
110
|
+
const limitClause = opts?.limit ? `LIMIT ${opts.limit}` : '';
|
|
111
|
+
|
|
112
|
+
const stmt = db.prepare(
|
|
113
|
+
`SELECT * FROM agent_messages WHERE ${where} ORDER BY created_at DESC ${limitClause}`
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const rows = stmt.all(...params as string[]) as MessageRow[];
|
|
117
|
+
return rows.map(parseMessage);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get unread/pending messages (all messages for now - could add read tracking)
|
|
122
|
+
*/
|
|
123
|
+
export function getPendingMessages(agentId: string): AgentMessage[] {
|
|
124
|
+
return getMessages(agentId);
|
|
125
|
+
}
|