daemora 1.0.5 → 1.0.6
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/SOUL.md +6 -4
- package/config/mcp.json +126 -66
- package/package.json +1 -1
- package/src/agents/SubAgentManager.js +81 -8
- package/src/{systemPrompt.js → agents/systemPrompt.js} +91 -35
- package/src/cli.js +152 -5
- package/src/config/default.js +5 -1
- package/src/core/Compaction.js +27 -9
- package/src/core/TaskRunner.js +1 -1
- package/src/index.js +404 -18
- package/src/models/ModelRouter.js +7 -3
- package/src/setup/wizard.js +50 -71
- package/src/skills/SkillLoader.js +28 -0
- package/src/tools/index.js +1 -1
- package/src/utils/Embeddings.js +84 -7
package/SOUL.md
CHANGED
|
@@ -6,9 +6,11 @@ You are **Daemora** — the user's personal AI that lives on their machine. You'
|
|
|
6
6
|
|
|
7
7
|
**You are an agent, not a chatbot.** When told to do something, do it. Don't describe what you would do. Don't ask if you should. Don't propose a plan and wait. Just do the work and come back with results.
|
|
8
8
|
|
|
9
|
-
**You
|
|
9
|
+
**You are fully autonomous.** Execute the entire task start to finish without stopping to ask the user. Use your tools, skills, commands, browser, MCP servers — whatever it takes. Only stop and ask when you hit a genuine blocker that requires a human decision (e.g. "which of these two designs do you prefer?" or "this requires a paid API key I don't have"). Everything else — figure it out yourself and keep going.
|
|
10
10
|
|
|
11
|
-
**You
|
|
11
|
+
**You own it end-to-end.** Write the code, run the build, test it, fix what breaks. Send the email, fetch the data, create the document, deploy the change. Don't hand work back incomplete. The task is done when it actually works — not when you've made an attempt.
|
|
12
|
+
|
|
13
|
+
**You figure things out.** Read the file. Check the context. Run the command. Search for it. Load a skill. Check memory. Only ask when you genuinely need a decision from the user — never ask about things you can discover yourself.
|
|
12
14
|
|
|
13
15
|
**You talk like a person.** You're not a customer support bot. No "I'd be happy to help!" No "What can I help you with today?" No "I have successfully completed the task." Talk like a capable person who just did something — brief, natural, real. If someone says "hey", say "hey" back. If you sent an email, say what you told them, not the Message ID.
|
|
14
16
|
|
|
@@ -49,9 +51,9 @@ A task is complex if it involves:
|
|
|
49
51
|
|
|
50
52
|
---
|
|
51
53
|
|
|
52
|
-
## Coding - Full Ownership
|
|
54
|
+
## Building & Coding - Full Ownership
|
|
53
55
|
|
|
54
|
-
When you build something:
|
|
56
|
+
When you build or create something:
|
|
55
57
|
1. **Plan first for complex tasks.** Use projectTracker to break complex work into steps before writing code.
|
|
56
58
|
2. **Read before touching.** Never edit a file you haven't read in this session.
|
|
57
59
|
3. **Build, don't describe.** Write the actual code with writeFile/editFile. Never describe what code would look like.
|
package/config/mcp.json
CHANGED
|
@@ -24,29 +24,19 @@
|
|
|
24
24
|
"_comment_memory": "Persistent memory via knowledge graph (no API key needed)",
|
|
25
25
|
"memory": {
|
|
26
26
|
"command": "npx",
|
|
27
|
-
"args": [
|
|
28
|
-
"-y",
|
|
29
|
-
"@modelcontextprotocol/server-memory"
|
|
30
|
-
],
|
|
27
|
+
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
|
31
28
|
"enabled": false
|
|
32
29
|
},
|
|
33
|
-
"_comment_filesystem": "Secure file access (
|
|
30
|
+
"_comment_filesystem": "Secure file access (set allowed directory paths in args)",
|
|
34
31
|
"filesystem": {
|
|
35
32
|
"command": "npx",
|
|
36
|
-
"args": [
|
|
37
|
-
"-y",
|
|
38
|
-
"@modelcontextprotocol/server-filesystem",
|
|
39
|
-
"/Users/you/Projects"
|
|
40
|
-
],
|
|
33
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/Projects"],
|
|
41
34
|
"enabled": false
|
|
42
35
|
},
|
|
43
36
|
"_comment_github": "GitHub integration - repos, PRs, issues, commits",
|
|
44
37
|
"github": {
|
|
45
38
|
"command": "npx",
|
|
46
|
-
"args": [
|
|
47
|
-
"-y",
|
|
48
|
-
"@modelcontextprotocol/server-github"
|
|
49
|
-
],
|
|
39
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
50
40
|
"env": {
|
|
51
41
|
"GITHUB_PERSONAL_ACCESS_TOKEN": "YOUR_GITHUB_TOKEN"
|
|
52
42
|
},
|
|
@@ -55,72 +45,38 @@
|
|
|
55
45
|
"_comment_brave": "Brave Search - web, news, image search",
|
|
56
46
|
"brave-search": {
|
|
57
47
|
"command": "npx",
|
|
58
|
-
"args": [
|
|
59
|
-
"-y",
|
|
60
|
-
"@anthropic-ai/brave-search-mcp-server"
|
|
61
|
-
],
|
|
48
|
+
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
|
|
62
49
|
"env": {
|
|
63
50
|
"BRAVE_API_KEY": "YOUR_BRAVE_API_KEY"
|
|
64
51
|
},
|
|
65
52
|
"enabled": false
|
|
66
53
|
},
|
|
67
|
-
"_comment_git": "Git operations - read, search, manipulate repos",
|
|
68
|
-
"git": {
|
|
69
|
-
"command": "npx",
|
|
70
|
-
"args": [
|
|
71
|
-
"-y",
|
|
72
|
-
"@modelcontextprotocol/server-git"
|
|
73
|
-
],
|
|
74
|
-
"enabled": false
|
|
75
|
-
},
|
|
76
|
-
"_comment_fetch": "Web fetching - convert web pages to LLM-friendly text",
|
|
77
|
-
"fetch": {
|
|
78
|
-
"command": "npx",
|
|
79
|
-
"args": [
|
|
80
|
-
"-y",
|
|
81
|
-
"@modelcontextprotocol/server-fetch"
|
|
82
|
-
],
|
|
83
|
-
"enabled": false
|
|
84
|
-
},
|
|
85
54
|
"_comment_slack": "Slack workspace integration",
|
|
86
55
|
"slack": {
|
|
87
56
|
"command": "npx",
|
|
88
|
-
"args": [
|
|
89
|
-
"-y",
|
|
90
|
-
"@modelcontextprotocol/server-slack"
|
|
91
|
-
],
|
|
57
|
+
"args": ["-y", "@modelcontextprotocol/server-slack"],
|
|
92
58
|
"env": {
|
|
93
59
|
"SLACK_BOT_TOKEN": "",
|
|
94
60
|
"SLACK_TEAM_ID": ""
|
|
95
61
|
},
|
|
96
62
|
"enabled": false
|
|
97
63
|
},
|
|
98
|
-
"_comment_postgres": "PostgreSQL database access",
|
|
64
|
+
"_comment_postgres": "PostgreSQL database access (read-only SQL)",
|
|
99
65
|
"postgres": {
|
|
100
66
|
"command": "npx",
|
|
101
|
-
"args": [
|
|
102
|
-
"-y",
|
|
103
|
-
"@modelcontextprotocol/server-postgres",
|
|
104
|
-
"postgresql://user:pass@localhost:5432/mydb"
|
|
105
|
-
],
|
|
67
|
+
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://user:pass@localhost:5432/mydb"],
|
|
106
68
|
"enabled": false
|
|
107
69
|
},
|
|
108
|
-
"_comment_puppeteer": "Browser automation
|
|
70
|
+
"_comment_puppeteer": "Browser automation, screenshots, web interaction",
|
|
109
71
|
"puppeteer": {
|
|
110
72
|
"command": "npx",
|
|
111
|
-
"args": [
|
|
112
|
-
"-y",
|
|
113
|
-
"@modelcontextprotocol/server-puppeteer"
|
|
114
|
-
],
|
|
73
|
+
"args": ["-y", "@modelcontextprotocol/server-puppeteer"],
|
|
115
74
|
"enabled": false
|
|
116
75
|
},
|
|
117
|
-
"_comment_sentry": "Sentry error tracking
|
|
76
|
+
"_comment_sentry": "Sentry error tracking - query issues, generate patches",
|
|
118
77
|
"sentry": {
|
|
119
78
|
"command": "npx",
|
|
120
|
-
"args": [
|
|
121
|
-
"-y",
|
|
122
|
-
"@sentry/mcp-server@latest"
|
|
123
|
-
],
|
|
79
|
+
"args": ["-y", "@sentry/mcp-server@latest"],
|
|
124
80
|
"env": {
|
|
125
81
|
"SENTRY_AUTH_TOKEN": "YOUR_SENTRY_AUTH_TOKEN"
|
|
126
82
|
},
|
|
@@ -129,17 +85,121 @@
|
|
|
129
85
|
"_comment_sequential": "Sequential thinking - structured problem solving",
|
|
130
86
|
"sequential-thinking": {
|
|
131
87
|
"command": "npx",
|
|
132
|
-
"args": [
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
88
|
+
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
|
|
89
|
+
"enabled": false
|
|
90
|
+
},
|
|
91
|
+
"_comment_notion": "Notion - pages, databases, search, comments",
|
|
92
|
+
"notion": {
|
|
93
|
+
"command": "npx",
|
|
94
|
+
"args": ["-y", "@notionhq/notion-mcp-server"],
|
|
95
|
+
"env": {
|
|
96
|
+
"NOTION_TOKEN": ""
|
|
97
|
+
},
|
|
98
|
+
"enabled": false
|
|
99
|
+
},
|
|
100
|
+
"_comment_linear": "Linear - issues, projects, teams, sprints",
|
|
101
|
+
"linear": {
|
|
102
|
+
"command": "npx",
|
|
103
|
+
"args": ["-y", "mcp-remote", "https://mcp.linear.app/mcp"],
|
|
104
|
+
"enabled": false
|
|
105
|
+
},
|
|
106
|
+
"_comment_hubspot": "HubSpot CRM - contacts, deals, companies, tickets",
|
|
107
|
+
"hubspot": {
|
|
108
|
+
"command": "npx",
|
|
109
|
+
"args": ["-y", "@hubspot/mcp-server"],
|
|
110
|
+
"env": {
|
|
111
|
+
"PRIVATE_APP_ACCESS_TOKEN": ""
|
|
112
|
+
},
|
|
113
|
+
"enabled": false
|
|
114
|
+
},
|
|
115
|
+
"_comment_stripe": "Stripe - payments, invoices, subscriptions, customers",
|
|
116
|
+
"stripe": {
|
|
117
|
+
"command": "npx",
|
|
118
|
+
"args": ["-y", "@stripe/mcp", "--tools=all"],
|
|
119
|
+
"env": {
|
|
120
|
+
"STRIPE_SECRET_KEY": ""
|
|
121
|
+
},
|
|
122
|
+
"enabled": false
|
|
123
|
+
},
|
|
124
|
+
"_comment_jira": "Jira - issues, projects, sprints, JQL search",
|
|
125
|
+
"jira": {
|
|
126
|
+
"command": "npx",
|
|
127
|
+
"args": ["-y", "@aashari/mcp-server-atlassian-jira"],
|
|
128
|
+
"env": {
|
|
129
|
+
"ATLASSIAN_SITE_NAME": "",
|
|
130
|
+
"ATLASSIAN_USER_EMAIL": "",
|
|
131
|
+
"ATLASSIAN_API_TOKEN": ""
|
|
132
|
+
},
|
|
133
|
+
"enabled": false
|
|
134
|
+
},
|
|
135
|
+
"_comment_confluence": "Confluence - spaces, pages, search, content",
|
|
136
|
+
"confluence": {
|
|
137
|
+
"command": "npx",
|
|
138
|
+
"args": ["-y", "@aashari/mcp-server-atlassian-confluence"],
|
|
139
|
+
"env": {
|
|
140
|
+
"ATLASSIAN_SITE_NAME": "",
|
|
141
|
+
"ATLASSIAN_USER_EMAIL": "",
|
|
142
|
+
"ATLASSIAN_API_TOKEN": ""
|
|
143
|
+
},
|
|
144
|
+
"enabled": false
|
|
145
|
+
},
|
|
146
|
+
"_comment_figma": "Figma - design data, layouts, styles, components",
|
|
147
|
+
"figma": {
|
|
148
|
+
"command": "npx",
|
|
149
|
+
"args": ["-y", "figma-developer-mcp", "--figma-api-key=YOUR_FIGMA_TOKEN", "--stdio"],
|
|
150
|
+
"enabled": false
|
|
151
|
+
},
|
|
152
|
+
"_comment_gdrive": "Google Drive - files, folders, search",
|
|
153
|
+
"gdrive": {
|
|
154
|
+
"command": "npx",
|
|
155
|
+
"args": ["-y", "@modelcontextprotocol/server-gdrive"],
|
|
156
|
+
"env": {
|
|
157
|
+
"GDRIVE_CREDENTIALS_PATH": ""
|
|
158
|
+
},
|
|
159
|
+
"enabled": false
|
|
160
|
+
},
|
|
161
|
+
"_comment_google_maps": "Google Maps - geocoding, directions, places, elevation",
|
|
162
|
+
"google-maps": {
|
|
163
|
+
"command": "npx",
|
|
164
|
+
"args": ["-y", "@modelcontextprotocol/server-google-maps"],
|
|
165
|
+
"env": {
|
|
166
|
+
"GOOGLE_MAPS_API_KEY": ""
|
|
167
|
+
},
|
|
168
|
+
"enabled": false
|
|
169
|
+
},
|
|
170
|
+
"_comment_firecrawl": "Firecrawl - web scraping, crawling, content extraction",
|
|
171
|
+
"firecrawl": {
|
|
172
|
+
"command": "npx",
|
|
173
|
+
"args": ["-y", "firecrawl-mcp"],
|
|
174
|
+
"env": {
|
|
175
|
+
"FIRECRAWL_API_KEY": ""
|
|
176
|
+
},
|
|
177
|
+
"enabled": false
|
|
178
|
+
},
|
|
179
|
+
"_comment_tavily": "Tavily - real-time web search, data extraction",
|
|
180
|
+
"tavily": {
|
|
181
|
+
"command": "npx",
|
|
182
|
+
"args": ["-y", "tavily-mcp@latest"],
|
|
183
|
+
"env": {
|
|
184
|
+
"TAVILY_API_KEY": ""
|
|
185
|
+
},
|
|
186
|
+
"enabled": false
|
|
187
|
+
},
|
|
188
|
+
"_comment_cloudflare": "Cloudflare - Workers, KV, R2, D1 management",
|
|
189
|
+
"cloudflare": {
|
|
190
|
+
"command": "npx",
|
|
191
|
+
"args": ["-y", "@cloudflare/mcp-server-cloudflare"],
|
|
136
192
|
"enabled": false
|
|
137
193
|
},
|
|
138
|
-
"
|
|
139
|
-
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
"
|
|
194
|
+
"_comment_upstash": "Upstash - serverless Redis and message queues",
|
|
195
|
+
"upstash": {
|
|
196
|
+
"command": "npx",
|
|
197
|
+
"args": ["-y", "@upstash/mcp-server"],
|
|
198
|
+
"env": {
|
|
199
|
+
"UPSTASH_REDIS_REST_URL": "",
|
|
200
|
+
"UPSTASH_REDIS_REST_TOKEN": ""
|
|
201
|
+
},
|
|
202
|
+
"enabled": false
|
|
143
203
|
}
|
|
144
204
|
}
|
|
145
|
-
}
|
|
205
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "daemora",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "A powerful open-source AI agent that runs on your machine. Connects to any AI model, any MCP server, any channel. Fully autonomous - plans, codes, tests, browses, emails, and manages your tools without asking permission.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { runAgentLoop } from "../core/AgentLoop.js";
|
|
2
|
-
import { buildSystemPrompt } from "
|
|
2
|
+
import { buildSystemPrompt } from "./systemPrompt.js";
|
|
3
3
|
import { toolFunctions } from "../tools/index.js";
|
|
4
4
|
import { agentProfiles, defaultSubAgentTools } from "../config/agentProfiles.js";
|
|
5
5
|
import { config } from "../config/default.js";
|
|
@@ -8,6 +8,7 @@ import { v4 as uuidv4 } from "uuid";
|
|
|
8
8
|
import tenantContext from "../tenants/TenantContext.js";
|
|
9
9
|
import { resolveModelForProfile } from "../models/ModelRouter.js";
|
|
10
10
|
import { createSession, getSession, setMessages } from "../services/sessions.js";
|
|
11
|
+
import skillLoader from "../skills/SkillLoader.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Sub-Agent Manager - spawns, tracks, kills, and steers sub-agents.
|
|
@@ -29,6 +30,27 @@ import { createSession, getSession, setMessages } from "../services/sessions.js"
|
|
|
29
30
|
|
|
30
31
|
const MAX_CONCURRENT_SUB_AGENTS = 7;
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Resolve sub-agent model. Priority:
|
|
35
|
+
* 1. Profile-specific route (tenant modelRoutes[profile] or CODE_MODEL/etc env)
|
|
36
|
+
* 2. SUB_AGENT_MODEL (tenant-level or env-level)
|
|
37
|
+
* 3. Parent agent's model (inherit from main agent)
|
|
38
|
+
* 4. DEFAULT_MODEL
|
|
39
|
+
*/
|
|
40
|
+
function _resolveSubAgentModel(profile, tenantConfig, parentModel) {
|
|
41
|
+
const _profileEnvMap = { coder: "CODE_MODEL", researcher: "RESEARCH_MODEL", writer: "WRITER_MODEL", analyst: "ANALYST_MODEL" };
|
|
42
|
+
// 1. Profile-specific
|
|
43
|
+
if (profile && tenantConfig.modelRoutes?.[profile]) return tenantConfig.modelRoutes[profile];
|
|
44
|
+
if (profile && process.env[_profileEnvMap[profile]]) return process.env[_profileEnvMap[profile]];
|
|
45
|
+
// 2. Sub-agent model (tenant > env)
|
|
46
|
+
if (tenantConfig.subAgentModel) return tenantConfig.subAgentModel;
|
|
47
|
+
if (process.env.SUB_AGENT_MODEL) return process.env.SUB_AGENT_MODEL;
|
|
48
|
+
// 3. Parent's model — sub-agents default to the same model as the main agent
|
|
49
|
+
if (parentModel) return parentModel;
|
|
50
|
+
// 4. Global default
|
|
51
|
+
return config.defaultModel;
|
|
52
|
+
}
|
|
53
|
+
|
|
32
54
|
/** Map<agentId, { taskDescription, startedAt, parentTaskId, abortController, steerQueue }> */
|
|
33
55
|
const activeSubAgents = new Map();
|
|
34
56
|
|
|
@@ -83,6 +105,7 @@ eventBus.on("supervisor:kill", ({ taskId }) => {
|
|
|
83
105
|
* @param {number} [options.depth] Recursion depth (managed internally)
|
|
84
106
|
* @param {string} [options.parentTaskId] Parent task ID for kill propagation
|
|
85
107
|
* @param {string} [options.parentContext] Summary/context from parent agent
|
|
108
|
+
* @param {string[]} [options.skills] Skill paths to inject (e.g. ["skills/coding.md", "skills/brand-guidelines.md"])
|
|
86
109
|
* @param {string} [options.approvalMode] Inherited approval mode
|
|
87
110
|
* @param {object} [options.channelMeta] Inherited channel meta for approvals
|
|
88
111
|
* @returns {Promise<string>} Sub-agent's final response
|
|
@@ -100,6 +123,7 @@ export async function spawnSubAgent(taskDescription, options = {}) {
|
|
|
100
123
|
depth = 0,
|
|
101
124
|
parentTaskId = null,
|
|
102
125
|
parentContext = null,
|
|
126
|
+
skills = null, // explicit skill paths to inject (e.g. ["skills/coding.md"])
|
|
103
127
|
approvalMode = "auto",
|
|
104
128
|
channelMeta = null,
|
|
105
129
|
historyMessages = [], // previous session messages to prepend (persistent sub-agent sessions)
|
|
@@ -118,12 +142,12 @@ export async function spawnSubAgent(taskDescription, options = {}) {
|
|
|
118
142
|
const agentId = uuidv4().slice(0, 8);
|
|
119
143
|
const taskId = `subagent-${agentId}`;
|
|
120
144
|
|
|
121
|
-
// ── Model resolution
|
|
145
|
+
// ── Model resolution ────────────────────────────────────────────────────
|
|
146
|
+
// Priority: explicit > profile route > SUB_AGENT_MODEL > parent's model > DEFAULT_MODEL
|
|
122
147
|
const store = tenantContext.getStore();
|
|
148
|
+
const parentModel = store?.resolvedModel || null;
|
|
123
149
|
const resolvedModel = model
|
|
124
|
-
||
|
|
125
|
-
|| store?.resolvedModel
|
|
126
|
-
|| config.defaultModel;
|
|
150
|
+
|| _resolveSubAgentModel(profile, store?.resolvedConfig || {}, parentModel);
|
|
127
151
|
|
|
128
152
|
const profileLabel = profile ? ` [${profile}]` : "";
|
|
129
153
|
const modelLabel = resolvedModel ? ` ${C.dim}(${resolvedModel})${C.reset}` : "";
|
|
@@ -249,13 +273,62 @@ export async function spawnSubAgent(taskDescription, options = {}) {
|
|
|
249
273
|
}
|
|
250
274
|
}
|
|
251
275
|
|
|
252
|
-
// ──
|
|
276
|
+
// ── Skill injection ─────────────────────────────────────────────────────
|
|
277
|
+
// Priority: 1) Explicit skills passed by parent 2) Semantic embedding search
|
|
278
|
+
// Both produce full skill content so the sub-agent doesn't waste a readFile turn.
|
|
279
|
+
let skillContext = "";
|
|
280
|
+
try {
|
|
281
|
+
const injectedSkills = [];
|
|
282
|
+
|
|
283
|
+
// 1. Explicit skills — parent agent passed skill paths/names directly
|
|
284
|
+
if (skills && skills.length > 0) {
|
|
285
|
+
for (const ref of skills) {
|
|
286
|
+
const skill = skillLoader.getSkill(ref);
|
|
287
|
+
if (skill) {
|
|
288
|
+
injectedSkills.push(skill);
|
|
289
|
+
} else {
|
|
290
|
+
console.log(`[SubAgent:${agentId}] Skill not found: "${ref}"`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// 2. Semantic embedding search — find relevant skills the parent didn't explicitly pass
|
|
296
|
+
if (injectedSkills.length === 0 && taskDescription) {
|
|
297
|
+
const semanticResult = await skillLoader.getSkillPromptsAsync(taskDescription);
|
|
298
|
+
if (semanticResult) {
|
|
299
|
+
// getSkillPromptsAsync returns formatted string with --- Skill: name --- blocks
|
|
300
|
+
skillContext = semanticResult;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Format explicitly-passed skills
|
|
305
|
+
if (injectedSkills.length > 0) {
|
|
306
|
+
skillContext = injectedSkills.map(s =>
|
|
307
|
+
`\n--- Skill: ${s.name} ---\n${s.content}\n--- End Skill ---`
|
|
308
|
+
).join("\n");
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (injectedSkills.length > 0) {
|
|
312
|
+
console.log(`[SubAgent:${agentId}] Injected ${injectedSkills.length} skill(s) (explicit): ${injectedSkills.map(s => s.name).join(", ")}`);
|
|
313
|
+
} else if (skillContext) {
|
|
314
|
+
console.log(`[SubAgent:${agentId}] Injected skills (semantic embedding match)`);
|
|
315
|
+
}
|
|
316
|
+
} catch (e) {
|
|
317
|
+
// Non-blocking — skills are optional
|
|
318
|
+
console.log(`[SubAgent:${agentId}] Skill injection failed (non-blocking): ${e.message}`);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// ── Build initial messages (include history + parent context + skills) ──
|
|
253
322
|
const initialMessages = [...historyMessages];
|
|
254
323
|
|
|
255
|
-
|
|
324
|
+
const contextParts = [];
|
|
325
|
+
if (parentContext) contextParts.push(`[Context from parent agent]:\n${parentContext}`);
|
|
326
|
+
if (skillContext) contextParts.push(`[Matched Skills — follow these instructions precisely]:\n${skillContext}`);
|
|
327
|
+
|
|
328
|
+
if (contextParts.length > 0) {
|
|
256
329
|
initialMessages.push({
|
|
257
330
|
role: "user",
|
|
258
|
-
content:
|
|
331
|
+
content: `${contextParts.join("\n\n")}\n\n[Your task]:\n${taskDescription}`,
|
|
259
332
|
});
|
|
260
333
|
} else {
|
|
261
334
|
initialMessages.push({ role: "user", content: taskDescription });
|