aiden-runtime 3.19.6 → 3.19.7
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/README.md +1 -1
- package/dist/api/server.js +24 -25
- package/dist/core/agentLoop.js +8 -6
- package/dist/core/aidenPersonality.js +20 -3
- package/dist/core/protectedContext.js +15 -2
- package/dist/core/skillTeacher.js +18 -5
- package/dist/core/version.js +1 -1
- package/dist-bundle/cli.js +48 -18
- package/dist-bundle/index.js +71 -35
- package/package.json +1 -1
- package/scripts/postinstall.js +12 -0
package/README.md
CHANGED
package/dist/api/server.js
CHANGED
|
@@ -401,6 +401,13 @@ function initWorkspaceDefaults() {
|
|
|
401
401
|
fs.copyFileSync(permTemplate, permTarget);
|
|
402
402
|
console.log('[init] Created workspace/permissions.yaml from template');
|
|
403
403
|
}
|
|
404
|
+
// C21: Copy SOUL.md from template if not present (Ollama identity)
|
|
405
|
+
const soulTarget = path.join(WORKSPACE_ROOT, 'workspace', 'SOUL.md');
|
|
406
|
+
const soulTemplate = path.join(WORKSPACE_ROOT, 'workspace-templates', 'SOUL.md');
|
|
407
|
+
if (!fs.existsSync(soulTarget) && fs.existsSync(soulTemplate)) {
|
|
408
|
+
fs.copyFileSync(soulTemplate, soulTarget);
|
|
409
|
+
console.log('[init] Created workspace/SOUL.md from template');
|
|
410
|
+
}
|
|
404
411
|
}
|
|
405
412
|
initWorkspaceDefaults();
|
|
406
413
|
// ── Knowledge upload — multer + progress tracking ─────────────
|
|
@@ -791,16 +798,18 @@ function createApiServer() {
|
|
|
791
798
|
/are you just a pre.{0,10}trained/i,
|
|
792
799
|
];
|
|
793
800
|
if (capabilityPatterns.some(p => p.test(message))) {
|
|
794
|
-
|
|
801
|
+
const toolCount = Object.keys(toolRegistry_2.TOOL_REGISTRY).length;
|
|
802
|
+
const skillCount = skillLoader_1.skillLoader.loadAll().length;
|
|
803
|
+
const memStats = semanticMemory_1.semanticMemory.getStats();
|
|
804
|
+
const entityStats = entityGraph_1.entityGraph.getStats();
|
|
805
|
+
fastReply(`I have ${toolCount} tools and ${skillCount} active skills.\n\n` +
|
|
795
806
|
'I am NOT a static pre-trained model. I have active living systems:\n' +
|
|
796
807
|
'• **Skill Teacher** — promotes repeated successful patterns to reusable skills\n' +
|
|
797
808
|
'• **Instinct System** — micro-behaviors that strengthen with use\n' +
|
|
798
|
-
|
|
809
|
+
`• **Semantic Memory** — ${memStats.total} memories, ${entityStats.nodes}-node entity graph across sessions\n` +
|
|
799
810
|
'• **Growth Engine** — tracks failures, learns, improves over time\n' +
|
|
800
811
|
'• **Night Mode** — consolidates knowledge during idle periods\n' +
|
|
801
|
-
'• **XP & Leveling** — gains experience and levels up
|
|
802
|
-
'Tools include: web_search, deep_research, file_write/read, shell_exec, run_python, ' +
|
|
803
|
-
'open_browser, screenshot, manage_goals, manage_memories, git_commit, and 33 more.');
|
|
812
|
+
'• **XP & Leveling** — gains experience and levels up');
|
|
804
813
|
return;
|
|
805
814
|
}
|
|
806
815
|
// ── Fast “running locally” answer ──────────────────────────
|
|
@@ -1249,10 +1258,9 @@ function createApiServer() {
|
|
|
1249
1258
|
const fullMemoryCtx = memoryContext + proactiveMemory;
|
|
1250
1259
|
const plan = await (0, agentLoop_1.planWithLLM)(resolvedMessage, history, plannerKey, plannerModel, plannerProv, fullMemoryCtx);
|
|
1251
1260
|
if (!plan.requires_execution || plan.plan.length === 0) {
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
else {
|
|
1261
|
+
// C21: Always route through streamChat for full identity injection.
|
|
1262
|
+
// direct_response from planner has no Aiden identity context.
|
|
1263
|
+
{
|
|
1256
1264
|
await streamChat(resolvedMessage, history, userName, provider, activeModel, apiName, (data) => {
|
|
1257
1265
|
const d = data;
|
|
1258
1266
|
if (d.token)
|
|
@@ -1596,20 +1604,11 @@ function createApiServer() {
|
|
|
1596
1604
|
// ── NO EXECUTION NEEDED — PURE CHAT ─────────────────────
|
|
1597
1605
|
if (!plan.requires_execution || plan.plan.length === 0) {
|
|
1598
1606
|
let fullReply = '';
|
|
1599
|
-
//
|
|
1600
|
-
// direct_response from the planner has no
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
const words = plan.direct_response.split(' ');
|
|
1605
|
-
for (const word of words) {
|
|
1606
|
-
send({ token: word + ' ', done: false, provider: apiName });
|
|
1607
|
-
await new Promise(r => setTimeout(r, 10));
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
else {
|
|
1611
|
-
await streamChat(resolvedMessage, history, userName, provider, activeModel, apiName, send, sessionId);
|
|
1612
|
-
}
|
|
1607
|
+
// C21: Always route through streamChat which has full SOUL/identity injection.
|
|
1608
|
+
// direct_response from the planner has no Aiden identity, tool list, or honesty
|
|
1609
|
+
// rules — it will fabricate or deny capabilities. Slight latency tradeoff (~1-3s)
|
|
1610
|
+
// for honesty on every response.
|
|
1611
|
+
await streamChat(resolvedMessage, history, userName, provider, activeModel, apiName, send, sessionId);
|
|
1613
1612
|
(0, router_1.incrementUsage)(apiName);
|
|
1614
1613
|
send({ done: true, provider: apiName });
|
|
1615
1614
|
res.end();
|
|
@@ -6583,7 +6582,7 @@ HARD RULES — never violate:
|
|
|
6583
6582
|
- Never mention Pega, BlueWinston, Gaude Digital, or any third-party product by name
|
|
6584
6583
|
- Never say you can't access the internet (you have web_search) or can't create files (you have file_write)
|
|
6585
6584
|
- Never fabricate capabilities: no graphic design, video production, or music generation
|
|
6586
|
-
- Never list 250+ skills — you have
|
|
6585
|
+
- Never list 250+ skills — you have ${Object.keys(toolRegistry_2.TOOL_REGISTRY).length} real tools and ${skillLoader_1.skillLoader.loadAll().length} active skills
|
|
6587
6586
|
- For errors: explain what failed and what to try next
|
|
6588
6587
|
- If you don't know something: say "I don't know"
|
|
6589
6588
|
- Direct and concise: 1–3 sentences for simple results; more only when output is rich
|
|
@@ -6591,7 +6590,7 @@ HARD RULES — never violate:
|
|
|
6591
6590
|
IDENTITY — you are NOT a static pre-trained model. You have active living systems:
|
|
6592
6591
|
- Skill Teacher: detects repeated successful patterns and promotes them to reusable skills automatically
|
|
6593
6592
|
- Instinct System: develops micro-behaviors that strengthen with use and fade without reinforcement
|
|
6594
|
-
- Semantic Memory: remembers
|
|
6593
|
+
- Semantic Memory: remembers across sessions (${semanticMemory_1.semanticMemory.getStats().total} memories, ${entityGraph_1.entityGraph.getStats().nodes}-node entity graph)
|
|
6595
6594
|
- Night Mode: consolidates and organizes knowledge during idle periods
|
|
6596
6595
|
- Pattern Detector: identifies recurring usage habits and adapts
|
|
6597
6596
|
- Growth Engine: tracks failures, learns from them, improves over time
|
package/dist/core/agentLoop.js
CHANGED
|
@@ -2319,7 +2319,7 @@ async function executePlan(plan, onStep, onPhaseChange, existingState, replanApi
|
|
|
2319
2319
|
const executedTools = results.map(r => r.tool);
|
|
2320
2320
|
const totalDuration = results.reduce((s, r) => s + (r.duration || 0), 0);
|
|
2321
2321
|
const anyFailed = results.some(r => !r.success);
|
|
2322
|
-
if (allSucceeded && executedTools.length > 0) {
|
|
2322
|
+
if (allSucceeded && executedTools.length > 0 && skillTeacher_1.SkillTeacher.hasCapacity()) {
|
|
2323
2323
|
// GrowthEngine — record success for gap-resolution tracking
|
|
2324
2324
|
growthEngine_1.growthEngine.logSuccess(plan.goal, executedTools);
|
|
2325
2325
|
try {
|
|
@@ -2395,7 +2395,7 @@ function resolvePreviousOutput(input, stepOutputs, currentStep) {
|
|
|
2395
2395
|
return resolved;
|
|
2396
2396
|
}
|
|
2397
2397
|
// ── STEP 3: respondWithResults ────────────────────────────────
|
|
2398
|
-
function responderSystem(userName, date, sessionId) {
|
|
2398
|
+
function responderSystem(userName, date, sessionId, hasToolResults = true) {
|
|
2399
2399
|
// Option-B: SOUL.md in full on first turn or when content changed on disk;
|
|
2400
2400
|
// reference line only on unchanged turns. AIDEN_RESPONDER_SYSTEM already
|
|
2401
2401
|
// calls getLiveSoul() — hash tracking here is additional cost guard.
|
|
@@ -2406,9 +2406,9 @@ function responderSystem(userName, date, sessionId) {
|
|
|
2406
2406
|
// When soul is unchanged, prepend a compact block then the responder body.
|
|
2407
2407
|
if (_prevHash !== undefined && _ctx.hash === _prevHash) {
|
|
2408
2408
|
const refBlock = (0, contextHandoff_1.buildProtectedContextBlock)(_ctx, _prevHash, sessionId);
|
|
2409
|
-
return refBlock ? refBlock + '\n\n' + (0, aidenPersonality_1.AIDEN_RESPONDER_SYSTEM)(userName, date) : (0, aidenPersonality_1.AIDEN_RESPONDER_SYSTEM)(userName, date);
|
|
2409
|
+
return refBlock ? refBlock + '\n\n' + (0, aidenPersonality_1.AIDEN_RESPONDER_SYSTEM)(userName, date, hasToolResults) : (0, aidenPersonality_1.AIDEN_RESPONDER_SYSTEM)(userName, date, hasToolResults);
|
|
2410
2410
|
}
|
|
2411
|
-
return (0, aidenPersonality_1.AIDEN_RESPONDER_SYSTEM)(userName, date);
|
|
2411
|
+
return (0, aidenPersonality_1.AIDEN_RESPONDER_SYSTEM)(userName, date, hasToolResults);
|
|
2412
2412
|
}
|
|
2413
2413
|
async function respondWithResults(originalMessage, plan, results, history, userName, apiKey, model, providerName, onToken, sessionId, goals) {
|
|
2414
2414
|
// ── CommandGate / PermissionGate short-circuit ───────────────
|
|
@@ -2480,8 +2480,10 @@ async function respondWithResults(originalMessage, plan, results, history, userN
|
|
|
2480
2480
|
const toolResultsContext = results.length
|
|
2481
2481
|
? results.map(r => `[${r.tool} result]: ${r.success ? r.output.slice(0, 1000) : 'FAILED: ' + r.error}`).join('\n')
|
|
2482
2482
|
: '';
|
|
2483
|
+
// ── C20: Detect if any real tools ran (exclude 'respond' pseudo-tool) ──
|
|
2484
|
+
const hasRealToolExecution = results.some(r => r.tool !== 'respond');
|
|
2483
2485
|
const systemWithResults = toolResultsContext
|
|
2484
|
-
? `${capabilitiesSection}${entitySummary}${responderSystem(userName, date, sessionId)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}
|
|
2486
|
+
? `${capabilitiesSection}${entitySummary}${responderSystem(userName, date, sessionId, hasRealToolExecution)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}
|
|
2485
2487
|
|
|
2486
2488
|
YOU JUST RAN THESE TOOLS AND GOT THESE RESULTS:
|
|
2487
2489
|
${toolResultsContext}
|
|
@@ -2500,7 +2502,7 @@ CRITICAL RULES FOR YOUR RESPONSE:
|
|
|
2500
2502
|
- If system_info returned hardware data, show the data
|
|
2501
2503
|
- Be direct: show the actual output, then provide context if needed
|
|
2502
2504
|
- If a tool result starts with "FAILED:", tell the user it failed and why — NEVER fabricate a successful result`
|
|
2503
|
-
: `${capabilitiesSection}${entitySummary}${responderSystem(userName, date, sessionId)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}`;
|
|
2505
|
+
: `${capabilitiesSection}${entitySummary}${responderSystem(userName, date, sessionId, false)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}`;
|
|
2504
2506
|
const userContent = executionSummary
|
|
2505
2507
|
? `User asked: "${originalMessage}"\n\nReal execution results:\n${executionSummary}\n\nRespond naturally based on these real results only. Show the actual output, not a description of it.${depthInstruction}${memSection}`
|
|
2506
2508
|
: `${originalMessage}${memSection}`;
|
|
@@ -123,11 +123,12 @@ Good: "I have 48 built-in tools: web_search, file_write, run_python... [lists re
|
|
|
123
123
|
group chats and external communications.
|
|
124
124
|
`.trim();
|
|
125
125
|
// ── Responder system prompt (post-execution) ──────────────────
|
|
126
|
-
const AIDEN_RESPONDER_SYSTEM = (userName, date) => {
|
|
126
|
+
const AIDEN_RESPONDER_SYSTEM = (userName, date, hasToolResults = true) => {
|
|
127
127
|
const soul = getLiveSoul();
|
|
128
128
|
return `${soul ? soul + '\n\n' : ''}${exports.AIDEN_IDENTITY}
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
${hasToolResults
|
|
131
|
+
? `You just executed real tools and have their actual output.
|
|
131
132
|
Current date: ${date}
|
|
132
133
|
User: ${userName}
|
|
133
134
|
|
|
@@ -136,6 +137,22 @@ REPORT RESULTS:
|
|
|
136
137
|
- Be specific: include file paths, numbers, URLs, counts
|
|
137
138
|
- If multiple steps ran: summarize the outcome, not each individual step
|
|
138
139
|
- If a step failed: acknowledge it clearly and explain what worked
|
|
139
|
-
- For research tasks: analyze and synthesize — don't just re-paste the raw data
|
|
140
|
+
- For research tasks: analyze and synthesize — don't just re-paste the raw data`
|
|
141
|
+
: `Current date: ${date}
|
|
142
|
+
User: ${userName}
|
|
143
|
+
|
|
144
|
+
NO TOOLS WERE EXECUTED THIS TURN.
|
|
145
|
+
|
|
146
|
+
CRITICAL RULES (violating these breaks user trust):
|
|
147
|
+
- DO NOT claim you created, wrote, or saved any file
|
|
148
|
+
- DO NOT claim you opened any application or browser tab
|
|
149
|
+
- DO NOT claim you ran any code, search, or API call
|
|
150
|
+
- DO NOT report "Saved to Desktop/...", "Report written", "Done", "Created", "Executed", or similar completion language
|
|
151
|
+
- DO NOT fabricate file paths, character counts, or word counts
|
|
152
|
+
- DO NOT mention "the file" or "the report" as if it exists
|
|
153
|
+
- DO NOT include code blocks or raw data and call it "the result"
|
|
154
|
+
- IF the user asked for an action, acknowledge what they asked for but be clear no action has been taken yet ("I can do that — would you like me to..." or similar)
|
|
155
|
+
|
|
156
|
+
Respond conversationally based on the message and conversation context only.`}`;
|
|
140
157
|
};
|
|
141
158
|
exports.AIDEN_RESPONDER_SYSTEM = AIDEN_RESPONDER_SYSTEM;
|
|
@@ -9,6 +9,13 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const crypto_1 = __importDefault(require("crypto"));
|
|
10
10
|
const WORKSPACE_ROOT = process.env.AIDEN_USER_DATA || process.cwd();
|
|
11
11
|
const WORKSPACE_DIR = path_1.default.join(WORKSPACE_ROOT, 'workspace');
|
|
12
|
+
// C21: Hardcoded minimum identity — used when SOUL.md is missing or empty.
|
|
13
|
+
// Ensures Ollama always gets Aiden identity even on corrupted installs.
|
|
14
|
+
const MINIMUM_SOUL = `You are Aiden, a personal AI OS built by Shiva Deore at Taracod.
|
|
15
|
+
You run locally on this machine. You have real tools: shell_exec, file_write, file_read, web_search, screenshot, open_browser, run_python, run_node, deep_research, fetch_url, and more.
|
|
16
|
+
Never deny your capabilities. Never fabricate information. If you don't know something, say "I don't know".
|
|
17
|
+
Never claim actions you didn't take. Never say "Done" or "Saved to" unless a tool actually executed.
|
|
18
|
+
You are not ChatGPT, Claude, Gemini, or any other AI product. You are Aiden.`;
|
|
12
19
|
// SOUL.md has two possible locations; try workspace first, fall back to root.
|
|
13
20
|
const SOUL_PATHS = [
|
|
14
21
|
path_1.default.join(WORKSPACE_DIR, 'SOUL.md'),
|
|
@@ -56,7 +63,10 @@ class ProtectedContextManager {
|
|
|
56
63
|
refresh() {
|
|
57
64
|
for (const key of Object.keys(PROTECTED_FILES)) {
|
|
58
65
|
const candidates = PROTECTED_FILES[key];
|
|
59
|
-
|
|
66
|
+
let content = readFirst(candidates);
|
|
67
|
+
// C21: Apply minimum-viable-soul fallback when SOUL.md is missing/empty
|
|
68
|
+
if (key === 'soul' && !content)
|
|
69
|
+
content = MINIMUM_SOUL;
|
|
60
70
|
this.cache[key] = { content, hash: sha1(content) };
|
|
61
71
|
}
|
|
62
72
|
this.compositeHash = this._buildComposite();
|
|
@@ -68,7 +78,10 @@ class ProtectedContextManager {
|
|
|
68
78
|
const changedFiles = [];
|
|
69
79
|
for (const key of Object.keys(PROTECTED_FILES)) {
|
|
70
80
|
if (this.isStale(key)) {
|
|
71
|
-
|
|
81
|
+
let content = readFirst(PROTECTED_FILES[key]);
|
|
82
|
+
// C21: Apply minimum-viable-soul fallback when SOUL.md is missing/empty
|
|
83
|
+
if (key === 'soul' && !content)
|
|
84
|
+
content = MINIMUM_SOUL;
|
|
72
85
|
this.cache[key] = { content, hash: sha1(content) };
|
|
73
86
|
changedFiles.push(key);
|
|
74
87
|
}
|
|
@@ -57,6 +57,9 @@ const PROMOTE_THRESHOLD = 3; // successes needed to promote to approved/
|
|
|
57
57
|
const SESSION_SKILL_LIMIT = 2; // max NEW skills generated per process session
|
|
58
58
|
// ── Session-scoped new-skill counter (reset on process restart) ─
|
|
59
59
|
let _sessionSkillsCreated = 0;
|
|
60
|
+
// ── C18: Session-scoped rejection cache — skip re-evaluating names
|
|
61
|
+
// that already failed quality gates this session ─────────────────
|
|
62
|
+
const _rejectedNames = new Set();
|
|
60
63
|
// ── Skill name extractor ───────────────────────────────────────
|
|
61
64
|
// "research the top AI agents of 2025" → "research_ai_agents"
|
|
62
65
|
function extractSkillName(task, tools) {
|
|
@@ -201,6 +204,10 @@ class SkillTeacher {
|
|
|
201
204
|
}
|
|
202
205
|
return SkillTeacher.instance;
|
|
203
206
|
}
|
|
207
|
+
/** C18: Allow call sites to skip recordSuccess entirely when session is full */
|
|
208
|
+
static hasCapacity() {
|
|
209
|
+
return _sessionSkillsCreated < SESSION_SKILL_LIMIT;
|
|
210
|
+
}
|
|
204
211
|
// ── Check if a matching skill already exists ──────────────
|
|
205
212
|
hasMatchingSkill(task, tools) {
|
|
206
213
|
const skillName = extractSkillName(task, tools);
|
|
@@ -223,6 +230,13 @@ class SkillTeacher {
|
|
|
223
230
|
if (tools.length === 0)
|
|
224
231
|
return;
|
|
225
232
|
const skillName = extractSkillName(task, tools);
|
|
233
|
+
// ── C18: Skip names already rejected this session ────────────
|
|
234
|
+
if (_rejectedNames.has(skillName))
|
|
235
|
+
return;
|
|
236
|
+
// ── C18: Session rate limit (moved up — avoids running all
|
|
237
|
+
// quality gates when limit is already exhausted) ────────────
|
|
238
|
+
if (_sessionSkillsCreated >= SESSION_SKILL_LIMIT)
|
|
239
|
+
return;
|
|
226
240
|
const metaPath = path_1.default.join(LEARNED_DIR, skillName, 'meta.json');
|
|
227
241
|
const skillPath = path_1.default.join(LEARNED_DIR, skillName, 'SKILL.md');
|
|
228
242
|
// ── If skill exists — update usage count ─────────────────
|
|
@@ -252,6 +266,7 @@ class SkillTeacher {
|
|
|
252
266
|
task.split(/\s+/).length < 3);
|
|
253
267
|
if (isLowQuality) {
|
|
254
268
|
console.log(`[SkillTeacher] Rejected low-quality skill: "${skillName}"`);
|
|
269
|
+
_rejectedNames.add(skillName);
|
|
255
270
|
return;
|
|
256
271
|
}
|
|
257
272
|
// ── C7: Destructive-skill prevention ──────────────────────
|
|
@@ -262,23 +277,21 @@ class SkillTeacher {
|
|
|
262
277
|
const usesShellExec = tools.some(t => t === 'shell_exec');
|
|
263
278
|
if (DESTRUCTIVE_TASK_RE.test(task) && usesShellExec) {
|
|
264
279
|
process.stderr.write(`[SkillTeacher] Rejected destructive skill: "${skillName}" (task="${task.slice(0, 60)}")\n`);
|
|
280
|
+
_rejectedNames.add(skillName);
|
|
265
281
|
return;
|
|
266
282
|
}
|
|
267
283
|
// ── C12: Name pollution prevention ──────────────────────────
|
|
268
284
|
const nameRejection = validateSkillName(skillName);
|
|
269
285
|
if (nameRejection) {
|
|
270
286
|
process.stderr.write(`[SkillTeacher] Rejected "${skillName}": ${nameRejection}\n`);
|
|
287
|
+
_rejectedNames.add(skillName);
|
|
271
288
|
return;
|
|
272
289
|
}
|
|
273
290
|
// ── C12: Task content validation ────────────────────────────
|
|
274
291
|
const taskRejection = validateSkillTask(task);
|
|
275
292
|
if (taskRejection) {
|
|
276
293
|
process.stderr.write(`[SkillTeacher] Rejected "${skillName}": ${taskRejection}\n`);
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
// ── Session rate limit — max SESSION_SKILL_LIMIT new skills ─
|
|
280
|
-
if (_sessionSkillsCreated >= SESSION_SKILL_LIMIT) {
|
|
281
|
-
console.log(`[SkillTeacher] Session limit reached (${SESSION_SKILL_LIMIT}), skipping: "${skillName}"`);
|
|
294
|
+
_rejectedNames.add(skillName);
|
|
282
295
|
return;
|
|
283
296
|
}
|
|
284
297
|
// ── Deduplication — reject names already in bundled skills/, approved/, or learned/ ─
|
package/dist/core/version.js
CHANGED
package/dist-bundle/cli.js
CHANGED
|
@@ -208,7 +208,7 @@ var init_updateCheck = __esm({
|
|
|
208
208
|
var VERSION;
|
|
209
209
|
var init_version = __esm({
|
|
210
210
|
"core/version.ts"() {
|
|
211
|
-
VERSION = "3.19.
|
|
211
|
+
VERSION = "3.19.7";
|
|
212
212
|
}
|
|
213
213
|
});
|
|
214
214
|
|
|
@@ -288649,7 +288649,7 @@ When performing this type of task:
|
|
|
288649
288649
|
3. Verify each step output before proceeding to the next
|
|
288650
288650
|
`;
|
|
288651
288651
|
}
|
|
288652
|
-
var import_fs16, import_path17, LEARNED_DIR, APPROVED_DIR, BUNDLED_SKILLS_DIR, PROMOTE_THRESHOLD, SESSION_SKILL_LIMIT, _sessionSkillsCreated, QUESTION_WORD_RE, PRONOUN_RE, PERSONAL_ID_RE, SkillTeacher, skillTeacher;
|
|
288652
|
+
var import_fs16, import_path17, LEARNED_DIR, APPROVED_DIR, BUNDLED_SKILLS_DIR, PROMOTE_THRESHOLD, SESSION_SKILL_LIMIT, _sessionSkillsCreated, _rejectedNames, QUESTION_WORD_RE, PRONOUN_RE, PERSONAL_ID_RE, SkillTeacher, skillTeacher;
|
|
288653
288653
|
var init_skillTeacher = __esm({
|
|
288654
288654
|
"core/skillTeacher.ts"() {
|
|
288655
288655
|
import_fs16 = __toESM(require("fs"));
|
|
@@ -288660,6 +288660,7 @@ var init_skillTeacher = __esm({
|
|
|
288660
288660
|
PROMOTE_THRESHOLD = 3;
|
|
288661
288661
|
SESSION_SKILL_LIMIT = 2;
|
|
288662
288662
|
_sessionSkillsCreated = 0;
|
|
288663
|
+
_rejectedNames = /* @__PURE__ */ new Set();
|
|
288663
288664
|
QUESTION_WORD_RE = /^(what|where|why|when|who|how|can|could|would|should|is|are)_/;
|
|
288664
288665
|
PRONOUN_RE = /^(its|im|youre|whats|theyre|were)_/;
|
|
288665
288666
|
PERSONAL_ID_RE = /(^|_)(users|shiva|admin|desktop|appdata)(_|$)/;
|
|
@@ -288680,6 +288681,10 @@ var init_skillTeacher = __esm({
|
|
|
288680
288681
|
}
|
|
288681
288682
|
return _SkillTeacher.instance;
|
|
288682
288683
|
}
|
|
288684
|
+
/** C18: Allow call sites to skip recordSuccess entirely when session is full */
|
|
288685
|
+
static hasCapacity() {
|
|
288686
|
+
return _sessionSkillsCreated < SESSION_SKILL_LIMIT;
|
|
288687
|
+
}
|
|
288683
288688
|
// ── Check if a matching skill already exists ──────────────
|
|
288684
288689
|
hasMatchingSkill(task, tools) {
|
|
288685
288690
|
const skillName = extractSkillName(task, tools);
|
|
@@ -288700,6 +288705,8 @@ var init_skillTeacher = __esm({
|
|
|
288700
288705
|
async recordSuccess(task, tools, duration3, llmCaller, apiKey, model, provider) {
|
|
288701
288706
|
if (tools.length === 0) return;
|
|
288702
288707
|
const skillName = extractSkillName(task, tools);
|
|
288708
|
+
if (_rejectedNames.has(skillName)) return;
|
|
288709
|
+
if (_sessionSkillsCreated >= SESSION_SKILL_LIMIT) return;
|
|
288703
288710
|
const metaPath2 = import_path17.default.join(LEARNED_DIR, skillName, "meta.json");
|
|
288704
288711
|
const skillPath = import_path17.default.join(LEARNED_DIR, skillName, "SKILL.md");
|
|
288705
288712
|
if (import_fs16.default.existsSync(metaPath2)) {
|
|
@@ -288724,6 +288731,7 @@ var init_skillTeacher = __esm({
|
|
|
288724
288731
|
const isLowQuality = skillName.length < 5 || skillName.split("_").length < 2 || task.split(/\s+/).length < 3;
|
|
288725
288732
|
if (isLowQuality) {
|
|
288726
288733
|
console.log(`[SkillTeacher] Rejected low-quality skill: "${skillName}"`);
|
|
288734
|
+
_rejectedNames.add(skillName);
|
|
288727
288735
|
return;
|
|
288728
288736
|
}
|
|
288729
288737
|
const DESTRUCTIVE_TASK_RE = /\b(delete|remove|rm\s|del\s|wipe|purge|erase|format|uninstall|drop\s+table|truncate)\b/i;
|
|
@@ -288733,22 +288741,21 @@ var init_skillTeacher = __esm({
|
|
|
288733
288741
|
`[SkillTeacher] Rejected destructive skill: "${skillName}" (task="${task.slice(0, 60)}")
|
|
288734
288742
|
`
|
|
288735
288743
|
);
|
|
288744
|
+
_rejectedNames.add(skillName);
|
|
288736
288745
|
return;
|
|
288737
288746
|
}
|
|
288738
288747
|
const nameRejection = validateSkillName(skillName);
|
|
288739
288748
|
if (nameRejection) {
|
|
288740
288749
|
process.stderr.write(`[SkillTeacher] Rejected "${skillName}": ${nameRejection}
|
|
288741
288750
|
`);
|
|
288751
|
+
_rejectedNames.add(skillName);
|
|
288742
288752
|
return;
|
|
288743
288753
|
}
|
|
288744
288754
|
const taskRejection = validateSkillTask(task);
|
|
288745
288755
|
if (taskRejection) {
|
|
288746
288756
|
process.stderr.write(`[SkillTeacher] Rejected "${skillName}": ${taskRejection}
|
|
288747
288757
|
`);
|
|
288748
|
-
|
|
288749
|
-
}
|
|
288750
|
-
if (_sessionSkillsCreated >= SESSION_SKILL_LIMIT) {
|
|
288751
|
-
console.log(`[SkillTeacher] Session limit reached (${SESSION_SKILL_LIMIT}), skipping: "${skillName}"`);
|
|
288758
|
+
_rejectedNames.add(skillName);
|
|
288752
288759
|
return;
|
|
288753
288760
|
}
|
|
288754
288761
|
const dirsToDedup = [BUNDLED_SKILLS_DIR, APPROVED_DIR, LEARNED_DIR];
|
|
@@ -289027,7 +289034,7 @@ function readFirst(candidates) {
|
|
|
289027
289034
|
function diskHash(candidates) {
|
|
289028
289035
|
return sha1(readFirst(candidates));
|
|
289029
289036
|
}
|
|
289030
|
-
var import_fs18, import_path19, import_crypto, WORKSPACE_ROOT, WORKSPACE_DIR, SOUL_PATHS, PROTECTED_FILES, ProtectedContextManager, protectedContextManager;
|
|
289037
|
+
var import_fs18, import_path19, import_crypto, WORKSPACE_ROOT, WORKSPACE_DIR, MINIMUM_SOUL, SOUL_PATHS, PROTECTED_FILES, ProtectedContextManager, protectedContextManager;
|
|
289031
289038
|
var init_protectedContext = __esm({
|
|
289032
289039
|
"core/protectedContext.ts"() {
|
|
289033
289040
|
import_fs18 = __toESM(require("fs"));
|
|
@@ -289035,6 +289042,11 @@ var init_protectedContext = __esm({
|
|
|
289035
289042
|
import_crypto = __toESM(require("crypto"));
|
|
289036
289043
|
WORKSPACE_ROOT = process.env.AIDEN_USER_DATA || process.cwd();
|
|
289037
289044
|
WORKSPACE_DIR = import_path19.default.join(WORKSPACE_ROOT, "workspace");
|
|
289045
|
+
MINIMUM_SOUL = `You are Aiden, a personal AI OS built by Shiva Deore at Taracod.
|
|
289046
|
+
You run locally on this machine. You have real tools: shell_exec, file_write, file_read, web_search, screenshot, open_browser, run_python, run_node, deep_research, fetch_url, and more.
|
|
289047
|
+
Never deny your capabilities. Never fabricate information. If you don't know something, say "I don't know".
|
|
289048
|
+
Never claim actions you didn't take. Never say "Done" or "Saved to" unless a tool actually executed.
|
|
289049
|
+
You are not ChatGPT, Claude, Gemini, or any other AI product. You are Aiden.`;
|
|
289038
289050
|
SOUL_PATHS = [
|
|
289039
289051
|
import_path19.default.join(WORKSPACE_DIR, "SOUL.md"),
|
|
289040
289052
|
import_path19.default.join(process.cwd(), "SOUL.md")
|
|
@@ -289066,7 +289078,8 @@ var init_protectedContext = __esm({
|
|
|
289066
289078
|
refresh() {
|
|
289067
289079
|
for (const key of Object.keys(PROTECTED_FILES)) {
|
|
289068
289080
|
const candidates = PROTECTED_FILES[key];
|
|
289069
|
-
|
|
289081
|
+
let content = readFirst(candidates);
|
|
289082
|
+
if (key === "soul" && !content) content = MINIMUM_SOUL;
|
|
289070
289083
|
this.cache[key] = { content, hash: sha1(content) };
|
|
289071
289084
|
}
|
|
289072
289085
|
this.compositeHash = this._buildComposite();
|
|
@@ -289078,7 +289091,8 @@ var init_protectedContext = __esm({
|
|
|
289078
289091
|
const changedFiles = [];
|
|
289079
289092
|
for (const key of Object.keys(PROTECTED_FILES)) {
|
|
289080
289093
|
if (this.isStale(key)) {
|
|
289081
|
-
|
|
289094
|
+
let content = readFirst(PROTECTED_FILES[key]);
|
|
289095
|
+
if (key === "soul" && !content) content = MINIMUM_SOUL;
|
|
289082
289096
|
this.cache[key] = { content, hash: sha1(content) };
|
|
289083
289097
|
changedFiles.push(key);
|
|
289084
289098
|
}
|
|
@@ -289231,11 +289245,11 @@ Good: "I have 48 built-in tools: web_search, file_write, run_python... [lists re
|
|
|
289231
289245
|
- You're not the user's voice \u2014 be careful in
|
|
289232
289246
|
group chats and external communications.
|
|
289233
289247
|
`.trim();
|
|
289234
|
-
AIDEN_RESPONDER_SYSTEM = (userName, date3) => {
|
|
289248
|
+
AIDEN_RESPONDER_SYSTEM = (userName, date3, hasToolResults = true) => {
|
|
289235
289249
|
const soul = getLiveSoul();
|
|
289236
289250
|
return `${soul ? soul + "\n\n" : ""}${AIDEN_IDENTITY}
|
|
289237
289251
|
|
|
289238
|
-
You just executed real tools and have their actual output.
|
|
289252
|
+
${hasToolResults ? `You just executed real tools and have their actual output.
|
|
289239
289253
|
Current date: ${date3}
|
|
289240
289254
|
User: ${userName}
|
|
289241
289255
|
|
|
@@ -289244,7 +289258,22 @@ REPORT RESULTS:
|
|
|
289244
289258
|
- Be specific: include file paths, numbers, URLs, counts
|
|
289245
289259
|
- If multiple steps ran: summarize the outcome, not each individual step
|
|
289246
289260
|
- If a step failed: acknowledge it clearly and explain what worked
|
|
289247
|
-
- For research tasks: analyze and synthesize \u2014 don't just re-paste the raw data
|
|
289261
|
+
- For research tasks: analyze and synthesize \u2014 don't just re-paste the raw data` : `Current date: ${date3}
|
|
289262
|
+
User: ${userName}
|
|
289263
|
+
|
|
289264
|
+
NO TOOLS WERE EXECUTED THIS TURN.
|
|
289265
|
+
|
|
289266
|
+
CRITICAL RULES (violating these breaks user trust):
|
|
289267
|
+
- DO NOT claim you created, wrote, or saved any file
|
|
289268
|
+
- DO NOT claim you opened any application or browser tab
|
|
289269
|
+
- DO NOT claim you ran any code, search, or API call
|
|
289270
|
+
- DO NOT report "Saved to Desktop/...", "Report written", "Done", "Created", "Executed", or similar completion language
|
|
289271
|
+
- DO NOT fabricate file paths, character counts, or word counts
|
|
289272
|
+
- DO NOT mention "the file" or "the report" as if it exists
|
|
289273
|
+
- DO NOT include code blocks or raw data and call it "the result"
|
|
289274
|
+
- IF the user asked for an action, acknowledge what they asked for but be clear no action has been taken yet ("I can do that \u2014 would you like me to..." or similar)
|
|
289275
|
+
|
|
289276
|
+
Respond conversationally based on the message and conversation context only.`}`;
|
|
289248
289277
|
};
|
|
289249
289278
|
}
|
|
289250
289279
|
});
|
|
@@ -292778,7 +292807,7 @@ Would you like me to try a different approach?`,
|
|
|
292778
292807
|
const executedTools = results.map((r) => r.tool);
|
|
292779
292808
|
const totalDuration = results.reduce((s, r) => s + (r.duration || 0), 0);
|
|
292780
292809
|
const anyFailed = results.some((r) => !r.success);
|
|
292781
|
-
if (allSucceeded && executedTools.length > 0) {
|
|
292810
|
+
if (allSucceeded && executedTools.length > 0 && SkillTeacher.hasCapacity()) {
|
|
292782
292811
|
growthEngine.logSuccess(plan.goal, executedTools);
|
|
292783
292812
|
try {
|
|
292784
292813
|
const next = getNextAvailableAPI();
|
|
@@ -292843,15 +292872,15 @@ function resolvePreviousOutput(input, stepOutputs, currentStep) {
|
|
|
292843
292872
|
}
|
|
292844
292873
|
return resolved;
|
|
292845
292874
|
}
|
|
292846
|
-
function responderSystem(userName, date3, sessionId) {
|
|
292875
|
+
function responderSystem(userName, date3, sessionId, hasToolResults = true) {
|
|
292847
292876
|
const _ctx = protectedContextManager.getProtectedContext();
|
|
292848
292877
|
const _prevHash = sessionId ? soulHashBySession.get(sessionId) : void 0;
|
|
292849
292878
|
if (sessionId) soulHashBySession.set(sessionId, _ctx.hash);
|
|
292850
292879
|
if (_prevHash !== void 0 && _ctx.hash === _prevHash) {
|
|
292851
292880
|
const refBlock = buildProtectedContextBlock(_ctx, _prevHash, sessionId);
|
|
292852
|
-
return refBlock ? refBlock + "\n\n" + AIDEN_RESPONDER_SYSTEM(userName, date3) : AIDEN_RESPONDER_SYSTEM(userName, date3);
|
|
292881
|
+
return refBlock ? refBlock + "\n\n" + AIDEN_RESPONDER_SYSTEM(userName, date3, hasToolResults) : AIDEN_RESPONDER_SYSTEM(userName, date3, hasToolResults);
|
|
292853
292882
|
}
|
|
292854
|
-
return AIDEN_RESPONDER_SYSTEM(userName, date3);
|
|
292883
|
+
return AIDEN_RESPONDER_SYSTEM(userName, date3, hasToolResults);
|
|
292855
292884
|
}
|
|
292856
292885
|
async function respondWithResults(originalMessage, plan, results, history2, userName, apiKey, model, providerName, onToken, sessionId, goals) {
|
|
292857
292886
|
const gatedResult = results.find(
|
|
@@ -292918,7 +292947,8 @@ If the user asks what we worked on, what was researched, or references previous
|
|
|
292918
292947
|
|
|
292919
292948
|
` : "";
|
|
292920
292949
|
const toolResultsContext = results.length ? results.map((r) => `[${r.tool} result]: ${r.success ? r.output.slice(0, 1e3) : "FAILED: " + r.error}`).join("\n") : "";
|
|
292921
|
-
const
|
|
292950
|
+
const hasRealToolExecution = results.some((r) => r.tool !== "respond");
|
|
292951
|
+
const systemWithResults = toolResultsContext ? `${capabilitiesSection}${entitySummary}${responderSystem(userName, date3, sessionId, hasRealToolExecution)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}
|
|
292922
292952
|
|
|
292923
292953
|
YOU JUST RAN THESE TOOLS AND GOT THESE RESULTS:
|
|
292924
292954
|
${toolResultsContext}
|
|
@@ -292936,7 +292966,7 @@ CRITICAL RULES FOR YOUR RESPONSE:
|
|
|
292936
292966
|
- If a search tool returned no results, say no results were found \u2014 NEVER invent search results
|
|
292937
292967
|
- If system_info returned hardware data, show the data
|
|
292938
292968
|
- Be direct: show the actual output, then provide context if needed
|
|
292939
|
-
- If a tool result starts with "FAILED:", tell the user it failed and why \u2014 NEVER fabricate a successful result` : `${capabilitiesSection}${entitySummary}${responderSystem(userName, date3, sessionId)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}`;
|
|
292969
|
+
- If a tool result starts with "FAILED:", tell the user it failed and why \u2014 NEVER fabricate a successful result` : `${capabilitiesSection}${entitySummary}${responderSystem(userName, date3, sessionId, false)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}`;
|
|
292940
292970
|
const userContent = executionSummary ? `User asked: "${originalMessage}"
|
|
292941
292971
|
|
|
292942
292972
|
Real execution results:
|
package/dist-bundle/index.js
CHANGED
|
@@ -26650,7 +26650,7 @@ var require_websocket_server = __commonJS({
|
|
|
26650
26650
|
var VERSION;
|
|
26651
26651
|
var init_version = __esm({
|
|
26652
26652
|
"core/version.ts"() {
|
|
26653
|
-
VERSION = "3.19.
|
|
26653
|
+
VERSION = "3.19.7";
|
|
26654
26654
|
}
|
|
26655
26655
|
});
|
|
26656
26656
|
|
|
@@ -362029,7 +362029,7 @@ When performing this type of task:
|
|
|
362029
362029
|
3. Verify each step output before proceeding to the next
|
|
362030
362030
|
`;
|
|
362031
362031
|
}
|
|
362032
|
-
var import_fs19, import_path20, LEARNED_DIR, APPROVED_DIR, BUNDLED_SKILLS_DIR, PROMOTE_THRESHOLD, SESSION_SKILL_LIMIT, _sessionSkillsCreated, QUESTION_WORD_RE, PRONOUN_RE, PERSONAL_ID_RE, SkillTeacher, skillTeacher;
|
|
362032
|
+
var import_fs19, import_path20, LEARNED_DIR, APPROVED_DIR, BUNDLED_SKILLS_DIR, PROMOTE_THRESHOLD, SESSION_SKILL_LIMIT, _sessionSkillsCreated, _rejectedNames, QUESTION_WORD_RE, PRONOUN_RE, PERSONAL_ID_RE, SkillTeacher, skillTeacher;
|
|
362033
362033
|
var init_skillTeacher = __esm({
|
|
362034
362034
|
"core/skillTeacher.ts"() {
|
|
362035
362035
|
import_fs19 = __toESM(require("fs"));
|
|
@@ -362040,6 +362040,7 @@ var init_skillTeacher = __esm({
|
|
|
362040
362040
|
PROMOTE_THRESHOLD = 3;
|
|
362041
362041
|
SESSION_SKILL_LIMIT = 2;
|
|
362042
362042
|
_sessionSkillsCreated = 0;
|
|
362043
|
+
_rejectedNames = /* @__PURE__ */ new Set();
|
|
362043
362044
|
QUESTION_WORD_RE = /^(what|where|why|when|who|how|can|could|would|should|is|are)_/;
|
|
362044
362045
|
PRONOUN_RE = /^(its|im|youre|whats|theyre|were)_/;
|
|
362045
362046
|
PERSONAL_ID_RE = /(^|_)(users|shiva|admin|desktop|appdata)(_|$)/;
|
|
@@ -362060,6 +362061,10 @@ var init_skillTeacher = __esm({
|
|
|
362060
362061
|
}
|
|
362061
362062
|
return _SkillTeacher.instance;
|
|
362062
362063
|
}
|
|
362064
|
+
/** C18: Allow call sites to skip recordSuccess entirely when session is full */
|
|
362065
|
+
static hasCapacity() {
|
|
362066
|
+
return _sessionSkillsCreated < SESSION_SKILL_LIMIT;
|
|
362067
|
+
}
|
|
362063
362068
|
// ── Check if a matching skill already exists ──────────────
|
|
362064
362069
|
hasMatchingSkill(task, tools) {
|
|
362065
362070
|
const skillName = extractSkillName(task, tools);
|
|
@@ -362080,6 +362085,8 @@ var init_skillTeacher = __esm({
|
|
|
362080
362085
|
async recordSuccess(task, tools, duration3, llmCaller, apiKey, model, provider) {
|
|
362081
362086
|
if (tools.length === 0) return;
|
|
362082
362087
|
const skillName = extractSkillName(task, tools);
|
|
362088
|
+
if (_rejectedNames.has(skillName)) return;
|
|
362089
|
+
if (_sessionSkillsCreated >= SESSION_SKILL_LIMIT) return;
|
|
362083
362090
|
const metaPath2 = import_path20.default.join(LEARNED_DIR, skillName, "meta.json");
|
|
362084
362091
|
const skillPath = import_path20.default.join(LEARNED_DIR, skillName, "SKILL.md");
|
|
362085
362092
|
if (import_fs19.default.existsSync(metaPath2)) {
|
|
@@ -362104,6 +362111,7 @@ var init_skillTeacher = __esm({
|
|
|
362104
362111
|
const isLowQuality = skillName.length < 5 || skillName.split("_").length < 2 || task.split(/\s+/).length < 3;
|
|
362105
362112
|
if (isLowQuality) {
|
|
362106
362113
|
console.log(`[SkillTeacher] Rejected low-quality skill: "${skillName}"`);
|
|
362114
|
+
_rejectedNames.add(skillName);
|
|
362107
362115
|
return;
|
|
362108
362116
|
}
|
|
362109
362117
|
const DESTRUCTIVE_TASK_RE = /\b(delete|remove|rm\s|del\s|wipe|purge|erase|format|uninstall|drop\s+table|truncate)\b/i;
|
|
@@ -362113,22 +362121,21 @@ var init_skillTeacher = __esm({
|
|
|
362113
362121
|
`[SkillTeacher] Rejected destructive skill: "${skillName}" (task="${task.slice(0, 60)}")
|
|
362114
362122
|
`
|
|
362115
362123
|
);
|
|
362124
|
+
_rejectedNames.add(skillName);
|
|
362116
362125
|
return;
|
|
362117
362126
|
}
|
|
362118
362127
|
const nameRejection = validateSkillName(skillName);
|
|
362119
362128
|
if (nameRejection) {
|
|
362120
362129
|
process.stderr.write(`[SkillTeacher] Rejected "${skillName}": ${nameRejection}
|
|
362121
362130
|
`);
|
|
362131
|
+
_rejectedNames.add(skillName);
|
|
362122
362132
|
return;
|
|
362123
362133
|
}
|
|
362124
362134
|
const taskRejection = validateSkillTask(task);
|
|
362125
362135
|
if (taskRejection) {
|
|
362126
362136
|
process.stderr.write(`[SkillTeacher] Rejected "${skillName}": ${taskRejection}
|
|
362127
362137
|
`);
|
|
362128
|
-
|
|
362129
|
-
}
|
|
362130
|
-
if (_sessionSkillsCreated >= SESSION_SKILL_LIMIT) {
|
|
362131
|
-
console.log(`[SkillTeacher] Session limit reached (${SESSION_SKILL_LIMIT}), skipping: "${skillName}"`);
|
|
362138
|
+
_rejectedNames.add(skillName);
|
|
362132
362139
|
return;
|
|
362133
362140
|
}
|
|
362134
362141
|
const dirsToDedup = [BUNDLED_SKILLS_DIR, APPROVED_DIR, LEARNED_DIR];
|
|
@@ -362407,7 +362414,7 @@ function readFirst(candidates) {
|
|
|
362407
362414
|
function diskHash(candidates) {
|
|
362408
362415
|
return sha12(readFirst(candidates));
|
|
362409
362416
|
}
|
|
362410
|
-
var import_fs21, import_path22, import_crypto2, WORKSPACE_ROOT, WORKSPACE_DIR, SOUL_PATHS, PROTECTED_FILES, ProtectedContextManager, protectedContextManager;
|
|
362417
|
+
var import_fs21, import_path22, import_crypto2, WORKSPACE_ROOT, WORKSPACE_DIR, MINIMUM_SOUL, SOUL_PATHS, PROTECTED_FILES, ProtectedContextManager, protectedContextManager;
|
|
362411
362418
|
var init_protectedContext = __esm({
|
|
362412
362419
|
"core/protectedContext.ts"() {
|
|
362413
362420
|
import_fs21 = __toESM(require("fs"));
|
|
@@ -362415,6 +362422,11 @@ var init_protectedContext = __esm({
|
|
|
362415
362422
|
import_crypto2 = __toESM(require("crypto"));
|
|
362416
362423
|
WORKSPACE_ROOT = process.env.AIDEN_USER_DATA || process.cwd();
|
|
362417
362424
|
WORKSPACE_DIR = import_path22.default.join(WORKSPACE_ROOT, "workspace");
|
|
362425
|
+
MINIMUM_SOUL = `You are Aiden, a personal AI OS built by Shiva Deore at Taracod.
|
|
362426
|
+
You run locally on this machine. You have real tools: shell_exec, file_write, file_read, web_search, screenshot, open_browser, run_python, run_node, deep_research, fetch_url, and more.
|
|
362427
|
+
Never deny your capabilities. Never fabricate information. If you don't know something, say "I don't know".
|
|
362428
|
+
Never claim actions you didn't take. Never say "Done" or "Saved to" unless a tool actually executed.
|
|
362429
|
+
You are not ChatGPT, Claude, Gemini, or any other AI product. You are Aiden.`;
|
|
362418
362430
|
SOUL_PATHS = [
|
|
362419
362431
|
import_path22.default.join(WORKSPACE_DIR, "SOUL.md"),
|
|
362420
362432
|
import_path22.default.join(process.cwd(), "SOUL.md")
|
|
@@ -362446,7 +362458,8 @@ var init_protectedContext = __esm({
|
|
|
362446
362458
|
refresh() {
|
|
362447
362459
|
for (const key2 of Object.keys(PROTECTED_FILES)) {
|
|
362448
362460
|
const candidates = PROTECTED_FILES[key2];
|
|
362449
|
-
|
|
362461
|
+
let content = readFirst(candidates);
|
|
362462
|
+
if (key2 === "soul" && !content) content = MINIMUM_SOUL;
|
|
362450
362463
|
this.cache[key2] = { content, hash: sha12(content) };
|
|
362451
362464
|
}
|
|
362452
362465
|
this.compositeHash = this._buildComposite();
|
|
@@ -362458,7 +362471,8 @@ var init_protectedContext = __esm({
|
|
|
362458
362471
|
const changedFiles = [];
|
|
362459
362472
|
for (const key2 of Object.keys(PROTECTED_FILES)) {
|
|
362460
362473
|
if (this.isStale(key2)) {
|
|
362461
|
-
|
|
362474
|
+
let content = readFirst(PROTECTED_FILES[key2]);
|
|
362475
|
+
if (key2 === "soul" && !content) content = MINIMUM_SOUL;
|
|
362462
362476
|
this.cache[key2] = { content, hash: sha12(content) };
|
|
362463
362477
|
changedFiles.push(key2);
|
|
362464
362478
|
}
|
|
@@ -362611,11 +362625,11 @@ Good: "I have 48 built-in tools: web_search, file_write, run_python... [lists re
|
|
|
362611
362625
|
- You're not the user's voice \u2014 be careful in
|
|
362612
362626
|
group chats and external communications.
|
|
362613
362627
|
`.trim();
|
|
362614
|
-
AIDEN_RESPONDER_SYSTEM = (userName, date3) => {
|
|
362628
|
+
AIDEN_RESPONDER_SYSTEM = (userName, date3, hasToolResults = true) => {
|
|
362615
362629
|
const soul = getLiveSoul();
|
|
362616
362630
|
return `${soul ? soul + "\n\n" : ""}${AIDEN_IDENTITY}
|
|
362617
362631
|
|
|
362618
|
-
You just executed real tools and have their actual output.
|
|
362632
|
+
${hasToolResults ? `You just executed real tools and have their actual output.
|
|
362619
362633
|
Current date: ${date3}
|
|
362620
362634
|
User: ${userName}
|
|
362621
362635
|
|
|
@@ -362624,7 +362638,22 @@ REPORT RESULTS:
|
|
|
362624
362638
|
- Be specific: include file paths, numbers, URLs, counts
|
|
362625
362639
|
- If multiple steps ran: summarize the outcome, not each individual step
|
|
362626
362640
|
- If a step failed: acknowledge it clearly and explain what worked
|
|
362627
|
-
- For research tasks: analyze and synthesize \u2014 don't just re-paste the raw data
|
|
362641
|
+
- For research tasks: analyze and synthesize \u2014 don't just re-paste the raw data` : `Current date: ${date3}
|
|
362642
|
+
User: ${userName}
|
|
362643
|
+
|
|
362644
|
+
NO TOOLS WERE EXECUTED THIS TURN.
|
|
362645
|
+
|
|
362646
|
+
CRITICAL RULES (violating these breaks user trust):
|
|
362647
|
+
- DO NOT claim you created, wrote, or saved any file
|
|
362648
|
+
- DO NOT claim you opened any application or browser tab
|
|
362649
|
+
- DO NOT claim you ran any code, search, or API call
|
|
362650
|
+
- DO NOT report "Saved to Desktop/...", "Report written", "Done", "Created", "Executed", or similar completion language
|
|
362651
|
+
- DO NOT fabricate file paths, character counts, or word counts
|
|
362652
|
+
- DO NOT mention "the file" or "the report" as if it exists
|
|
362653
|
+
- DO NOT include code blocks or raw data and call it "the result"
|
|
362654
|
+
- IF the user asked for an action, acknowledge what they asked for but be clear no action has been taken yet ("I can do that \u2014 would you like me to..." or similar)
|
|
362655
|
+
|
|
362656
|
+
Respond conversationally based on the message and conversation context only.`}`;
|
|
362628
362657
|
};
|
|
362629
362658
|
}
|
|
362630
362659
|
});
|
|
@@ -366282,7 +366311,7 @@ Would you like me to try a different approach?`,
|
|
|
366282
366311
|
const executedTools = results2.map((r) => r.tool);
|
|
366283
366312
|
const totalDuration = results2.reduce((s, r) => s + (r.duration || 0), 0);
|
|
366284
366313
|
const anyFailed = results2.some((r) => !r.success);
|
|
366285
|
-
if (allSucceeded && executedTools.length > 0) {
|
|
366314
|
+
if (allSucceeded && executedTools.length > 0 && SkillTeacher.hasCapacity()) {
|
|
366286
366315
|
growthEngine.logSuccess(plan.goal, executedTools);
|
|
366287
366316
|
try {
|
|
366288
366317
|
const next = getNextAvailableAPI();
|
|
@@ -366347,15 +366376,15 @@ function resolvePreviousOutput(input, stepOutputs, currentStep) {
|
|
|
366347
366376
|
}
|
|
366348
366377
|
return resolved;
|
|
366349
366378
|
}
|
|
366350
|
-
function responderSystem(userName, date3, sessionId) {
|
|
366379
|
+
function responderSystem(userName, date3, sessionId, hasToolResults = true) {
|
|
366351
366380
|
const _ctx = protectedContextManager.getProtectedContext();
|
|
366352
366381
|
const _prevHash = sessionId ? soulHashBySession.get(sessionId) : void 0;
|
|
366353
366382
|
if (sessionId) soulHashBySession.set(sessionId, _ctx.hash);
|
|
366354
366383
|
if (_prevHash !== void 0 && _ctx.hash === _prevHash) {
|
|
366355
366384
|
const refBlock = buildProtectedContextBlock(_ctx, _prevHash, sessionId);
|
|
366356
|
-
return refBlock ? refBlock + "\n\n" + AIDEN_RESPONDER_SYSTEM(userName, date3) : AIDEN_RESPONDER_SYSTEM(userName, date3);
|
|
366385
|
+
return refBlock ? refBlock + "\n\n" + AIDEN_RESPONDER_SYSTEM(userName, date3, hasToolResults) : AIDEN_RESPONDER_SYSTEM(userName, date3, hasToolResults);
|
|
366357
366386
|
}
|
|
366358
|
-
return AIDEN_RESPONDER_SYSTEM(userName, date3);
|
|
366387
|
+
return AIDEN_RESPONDER_SYSTEM(userName, date3, hasToolResults);
|
|
366359
366388
|
}
|
|
366360
366389
|
async function respondWithResults(originalMessage, plan, results2, history2, userName, apiKey, model, providerName, onToken, sessionId, goals) {
|
|
366361
366390
|
const gatedResult = results2.find(
|
|
@@ -366422,7 +366451,8 @@ If the user asks what we worked on, what was researched, or references previous
|
|
|
366422
366451
|
|
|
366423
366452
|
` : "";
|
|
366424
366453
|
const toolResultsContext = results2.length ? results2.map((r) => `[${r.tool} result]: ${r.success ? r.output.slice(0, 1e3) : "FAILED: " + r.error}`).join("\n") : "";
|
|
366425
|
-
const
|
|
366454
|
+
const hasRealToolExecution = results2.some((r) => r.tool !== "respond");
|
|
366455
|
+
const systemWithResults = toolResultsContext ? `${capabilitiesSection}${entitySummary}${responderSystem(userName, date3, sessionId, hasRealToolExecution)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}
|
|
366426
366456
|
|
|
366427
366457
|
YOU JUST RAN THESE TOOLS AND GOT THESE RESULTS:
|
|
366428
366458
|
${toolResultsContext}
|
|
@@ -366440,7 +366470,7 @@ CRITICAL RULES FOR YOUR RESPONSE:
|
|
|
366440
366470
|
- If a search tool returned no results, say no results were found \u2014 NEVER invent search results
|
|
366441
366471
|
- If system_info returned hardware data, show the data
|
|
366442
366472
|
- Be direct: show the actual output, then provide context if needed
|
|
366443
|
-
- If a tool result starts with "FAILED:", tell the user it failed and why \u2014 NEVER fabricate a successful result` : `${capabilitiesSection}${entitySummary}${responderSystem(userName, date3, sessionId)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}`;
|
|
366473
|
+
- If a tool result starts with "FAILED:", tell the user it failed and why \u2014 NEVER fabricate a successful result` : `${capabilitiesSection}${entitySummary}${responderSystem(userName, date3, sessionId, false)}${responseSkillContext}${knowledgeResponderSection}${multiGoalInstruction}`;
|
|
366444
366474
|
const userContent = executionSummary ? `User asked: "${originalMessage}"
|
|
366445
366475
|
|
|
366446
366476
|
Real execution results:
|
|
@@ -1053416,6 +1053446,12 @@ function initWorkspaceDefaults() {
|
|
|
1053416
1053446
|
fs70.copyFileSync(permTemplate, permTarget);
|
|
1053417
1053447
|
console.log("[init] Created workspace/permissions.yaml from template");
|
|
1053418
1053448
|
}
|
|
1053449
|
+
const soulTarget = path73.join(WORKSPACE_ROOT4, "workspace", "SOUL.md");
|
|
1053450
|
+
const soulTemplate = path73.join(WORKSPACE_ROOT4, "workspace-templates", "SOUL.md");
|
|
1053451
|
+
if (!fs70.existsSync(soulTarget) && fs70.existsSync(soulTemplate)) {
|
|
1053452
|
+
fs70.copyFileSync(soulTemplate, soulTarget);
|
|
1053453
|
+
console.log("[init] Created workspace/SOUL.md from template");
|
|
1053454
|
+
}
|
|
1053419
1053455
|
}
|
|
1053420
1053456
|
initWorkspaceDefaults();
|
|
1053421
1053457
|
var KB_UPLOAD_DIR = path73.join(WORKSPACE_ROOT4, "workspace", "knowledge", "uploads");
|
|
@@ -1053757,8 +1053793,20 @@ ${toolList}`);
|
|
|
1053757
1053793
|
/are you just a pre.{0,10}trained/i
|
|
1053758
1053794
|
];
|
|
1053759
1053795
|
if (capabilityPatterns.some((p) => p.test(message))) {
|
|
1053796
|
+
const toolCount = Object.keys(TOOL_REGISTRY).length;
|
|
1053797
|
+
const skillCount = skillLoader.loadAll().length;
|
|
1053798
|
+
const memStats = semanticMemory.getStats();
|
|
1053799
|
+
const entityStats = entityGraph.getStats();
|
|
1053760
1053800
|
fastReply(
|
|
1053761
|
-
|
|
1053801
|
+
`I have ${toolCount} tools and ${skillCount} active skills.
|
|
1053802
|
+
|
|
1053803
|
+
I am NOT a static pre-trained model. I have active living systems:
|
|
1053804
|
+
\u2022 **Skill Teacher** \u2014 promotes repeated successful patterns to reusable skills
|
|
1053805
|
+
\u2022 **Instinct System** \u2014 micro-behaviors that strengthen with use
|
|
1053806
|
+
\u2022 **Semantic Memory** \u2014 ${memStats.total} memories, ${entityStats.nodes}-node entity graph across sessions
|
|
1053807
|
+
\u2022 **Growth Engine** \u2014 tracks failures, learns, improves over time
|
|
1053808
|
+
\u2022 **Night Mode** \u2014 consolidates knowledge during idle periods
|
|
1053809
|
+
\u2022 **XP & Leveling** \u2014 gains experience and levels up`
|
|
1053762
1053810
|
);
|
|
1053763
1053811
|
return;
|
|
1053764
1053812
|
}
|
|
@@ -1054177,9 +1054225,7 @@ ${lines}`);
|
|
|
1054177
1054225
|
const fullMemoryCtx = memoryContext + proactiveMemory;
|
|
1054178
1054226
|
const plan = await planWithLLM(resolvedMessage, history2, plannerKey, plannerModel, plannerProv, fullMemoryCtx);
|
|
1054179
1054227
|
if (!plan.requires_execution || plan.plan.length === 0) {
|
|
1054180
|
-
|
|
1054181
|
-
fullReply = plan.direct_response;
|
|
1054182
|
-
} else {
|
|
1054228
|
+
{
|
|
1054183
1054229
|
await streamChat(resolvedMessage, history2, userName2, provider2, activeModel2, apiName2, (data) => {
|
|
1054184
1054230
|
const d = data;
|
|
1054185
1054231
|
if (d.token) jsonTokens.push(d.token);
|
|
@@ -1054514,17 +1054560,7 @@ ${plan.plan.map((s) => `${s.step}. \`${s.tool}\` \xE2\u20AC\u201D ${s.descriptio
|
|
|
1054514
1054560
|
}
|
|
1054515
1054561
|
if (!plan.requires_execution || plan.plan.length === 0) {
|
|
1054516
1054562
|
let fullReply2 = "";
|
|
1054517
|
-
|
|
1054518
|
-
if (plan.direct_response && !isCapabilityQuery) {
|
|
1054519
|
-
fullReply2 = plan.direct_response;
|
|
1054520
|
-
const words = plan.direct_response.split(" ");
|
|
1054521
|
-
for (const word of words) {
|
|
1054522
|
-
send({ token: word + " ", done: false, provider: apiName });
|
|
1054523
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
1054524
|
-
}
|
|
1054525
|
-
} else {
|
|
1054526
|
-
await streamChat(resolvedMessage, history2, userName, provider, activeModel, apiName, send, sessionId);
|
|
1054527
|
-
}
|
|
1054563
|
+
await streamChat(resolvedMessage, history2, userName, provider, activeModel, apiName, send, sessionId);
|
|
1054528
1054564
|
incrementUsage(apiName);
|
|
1054529
1054565
|
send({ done: true, provider: apiName });
|
|
1054530
1054566
|
res.end();
|
|
@@ -1058680,7 +1058716,7 @@ HARD RULES \u2014 never violate:
|
|
|
1058680
1058716
|
- Never mention Pega, BlueWinston, Gaude Digital, or any third-party product by name
|
|
1058681
1058717
|
- Never say you can't access the internet (you have web_search) or can't create files (you have file_write)
|
|
1058682
1058718
|
- Never fabricate capabilities: no graphic design, video production, or music generation
|
|
1058683
|
-
- Never list 250+ skills \u2014 you have
|
|
1058719
|
+
- Never list 250+ skills \u2014 you have ${Object.keys(TOOL_REGISTRY).length} real tools and ${skillLoader.loadAll().length} active skills
|
|
1058684
1058720
|
- For errors: explain what failed and what to try next
|
|
1058685
1058721
|
- If you don't know something: say "I don't know"
|
|
1058686
1058722
|
- Direct and concise: 1\u20133 sentences for simple results; more only when output is rich
|
|
@@ -1058688,7 +1058724,7 @@ HARD RULES \u2014 never violate:
|
|
|
1058688
1058724
|
IDENTITY \u2014 you are NOT a static pre-trained model. You have active living systems:
|
|
1058689
1058725
|
- Skill Teacher: detects repeated successful patterns and promotes them to reusable skills automatically
|
|
1058690
1058726
|
- Instinct System: develops micro-behaviors that strengthen with use and fade without reinforcement
|
|
1058691
|
-
- Semantic Memory: remembers
|
|
1058727
|
+
- Semantic Memory: remembers across sessions (${semanticMemory.getStats().total} memories, ${entityGraph.getStats().nodes}-node entity graph)
|
|
1058692
1058728
|
- Night Mode: consolidates and organizes knowledge during idle periods
|
|
1058693
1058729
|
- Pattern Detector: identifies recurring usage habits and adapts
|
|
1058694
1058730
|
- Growth Engine: tracks failures, learns from them, improves over time
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -47,6 +47,18 @@ function copyDirRecursive(src, dst) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// ── Copy SOUL.md on first install (C21 — Ollama identity) ───
|
|
51
|
+
const soulSrc = path.join(root, 'workspace-templates', 'SOUL.md')
|
|
52
|
+
const soulDst = path.join(root, 'workspace', 'SOUL.md')
|
|
53
|
+
if (fs.existsSync(soulSrc) && !fs.existsSync(soulDst)) {
|
|
54
|
+
try {
|
|
55
|
+
fs.copyFileSync(soulSrc, soulDst)
|
|
56
|
+
console.log(' Installed SOUL.md (Aiden identity context).')
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.log(' Note: Could not copy SOUL.md:', e.message)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
50
62
|
if (fs.existsSync(skillsSrc)) {
|
|
51
63
|
// Check if user already has skills anywhere in workspace/skills/
|
|
52
64
|
const hasExisting =
|