genesis-ai-cli 7.4.5
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/.env.example +78 -0
- package/README.md +282 -0
- package/dist/src/active-inference/actions.d.ts +75 -0
- package/dist/src/active-inference/actions.js +250 -0
- package/dist/src/active-inference/autonomous-loop.d.ts +103 -0
- package/dist/src/active-inference/autonomous-loop.js +289 -0
- package/dist/src/active-inference/core.d.ts +85 -0
- package/dist/src/active-inference/core.js +555 -0
- package/dist/src/active-inference/demo-autonomous-loop.d.ts +8 -0
- package/dist/src/active-inference/demo-autonomous-loop.js +338 -0
- package/dist/src/active-inference/demo-value-integration.d.ts +8 -0
- package/dist/src/active-inference/demo-value-integration.js +174 -0
- package/dist/src/active-inference/index.d.ts +32 -0
- package/dist/src/active-inference/index.js +88 -0
- package/dist/src/active-inference/integration.d.ts +114 -0
- package/dist/src/active-inference/integration.js +698 -0
- package/dist/src/active-inference/memory-integration.d.ts +51 -0
- package/dist/src/active-inference/memory-integration.js +232 -0
- package/dist/src/active-inference/observations.d.ts +67 -0
- package/dist/src/active-inference/observations.js +147 -0
- package/dist/src/active-inference/test-active-inference.d.ts +8 -0
- package/dist/src/active-inference/test-active-inference.js +320 -0
- package/dist/src/active-inference/test-value-integration.d.ts +6 -0
- package/dist/src/active-inference/test-value-integration.js +168 -0
- package/dist/src/active-inference/types.d.ts +150 -0
- package/dist/src/active-inference/types.js +59 -0
- package/dist/src/active-inference/value-integration.d.ts +164 -0
- package/dist/src/active-inference/value-integration.js +459 -0
- package/dist/src/agents/base-agent.d.ts +53 -0
- package/dist/src/agents/base-agent.js +178 -0
- package/dist/src/agents/builder.d.ts +67 -0
- package/dist/src/agents/builder.js +537 -0
- package/dist/src/agents/critic.d.ts +35 -0
- package/dist/src/agents/critic.js +322 -0
- package/dist/src/agents/ethicist.d.ts +54 -0
- package/dist/src/agents/ethicist.js +393 -0
- package/dist/src/agents/explorer.d.ts +26 -0
- package/dist/src/agents/explorer.js +216 -0
- package/dist/src/agents/feeling.d.ts +41 -0
- package/dist/src/agents/feeling.js +320 -0
- package/dist/src/agents/index.d.ts +111 -0
- package/dist/src/agents/index.js +222 -0
- package/dist/src/agents/memory.d.ts +69 -0
- package/dist/src/agents/memory.js +404 -0
- package/dist/src/agents/message-bus.d.ts +88 -0
- package/dist/src/agents/message-bus.js +267 -0
- package/dist/src/agents/narrator.d.ts +90 -0
- package/dist/src/agents/narrator.js +473 -0
- package/dist/src/agents/planner.d.ts +38 -0
- package/dist/src/agents/planner.js +341 -0
- package/dist/src/agents/predictor.d.ts +73 -0
- package/dist/src/agents/predictor.js +506 -0
- package/dist/src/agents/sensor.d.ts +88 -0
- package/dist/src/agents/sensor.js +377 -0
- package/dist/src/agents/test-agents.d.ts +6 -0
- package/dist/src/agents/test-agents.js +73 -0
- package/dist/src/agents/types.d.ts +194 -0
- package/dist/src/agents/types.js +7 -0
- package/dist/src/brain/index.d.ts +185 -0
- package/dist/src/brain/index.js +843 -0
- package/dist/src/brain/trace.d.ts +91 -0
- package/dist/src/brain/trace.js +327 -0
- package/dist/src/brain/types.d.ts +165 -0
- package/dist/src/brain/types.js +51 -0
- package/dist/src/cli/chat.d.ts +237 -0
- package/dist/src/cli/chat.js +1959 -0
- package/dist/src/cli/dispatcher.d.ts +182 -0
- package/dist/src/cli/dispatcher.js +718 -0
- package/dist/src/cli/human-loop.d.ts +170 -0
- package/dist/src/cli/human-loop.js +543 -0
- package/dist/src/cli/index.d.ts +12 -0
- package/dist/src/cli/index.js +28 -0
- package/dist/src/cli/interactive.d.ts +141 -0
- package/dist/src/cli/interactive.js +757 -0
- package/dist/src/cli/ui.d.ts +205 -0
- package/dist/src/cli/ui.js +632 -0
- package/dist/src/consciousness/attention-schema.d.ts +154 -0
- package/dist/src/consciousness/attention-schema.js +432 -0
- package/dist/src/consciousness/global-workspace.d.ts +149 -0
- package/dist/src/consciousness/global-workspace.js +422 -0
- package/dist/src/consciousness/index.d.ts +186 -0
- package/dist/src/consciousness/index.js +476 -0
- package/dist/src/consciousness/phi-calculator.d.ts +119 -0
- package/dist/src/consciousness/phi-calculator.js +445 -0
- package/dist/src/consciousness/phi-decisions.d.ts +169 -0
- package/dist/src/consciousness/phi-decisions.js +383 -0
- package/dist/src/consciousness/phi-monitor.d.ts +153 -0
- package/dist/src/consciousness/phi-monitor.js +465 -0
- package/dist/src/consciousness/types.d.ts +260 -0
- package/dist/src/consciousness/types.js +44 -0
- package/dist/src/daemon/dream-mode.d.ts +115 -0
- package/dist/src/daemon/dream-mode.js +470 -0
- package/dist/src/daemon/index.d.ts +162 -0
- package/dist/src/daemon/index.js +542 -0
- package/dist/src/daemon/maintenance.d.ts +139 -0
- package/dist/src/daemon/maintenance.js +549 -0
- package/dist/src/daemon/process.d.ts +82 -0
- package/dist/src/daemon/process.js +442 -0
- package/dist/src/daemon/scheduler.d.ts +90 -0
- package/dist/src/daemon/scheduler.js +494 -0
- package/dist/src/daemon/types.d.ts +213 -0
- package/dist/src/daemon/types.js +50 -0
- package/dist/src/epistemic/index.d.ts +74 -0
- package/dist/src/epistemic/index.js +225 -0
- package/dist/src/grounding/epistemic-stack.d.ts +100 -0
- package/dist/src/grounding/epistemic-stack.js +408 -0
- package/dist/src/grounding/feedback.d.ts +98 -0
- package/dist/src/grounding/feedback.js +276 -0
- package/dist/src/grounding/index.d.ts +123 -0
- package/dist/src/grounding/index.js +224 -0
- package/dist/src/grounding/verifier.d.ts +149 -0
- package/dist/src/grounding/verifier.js +484 -0
- package/dist/src/healing/detector.d.ts +110 -0
- package/dist/src/healing/detector.js +436 -0
- package/dist/src/healing/fixer.d.ts +138 -0
- package/dist/src/healing/fixer.js +572 -0
- package/dist/src/healing/index.d.ts +23 -0
- package/dist/src/healing/index.js +43 -0
- package/dist/src/hooks/index.d.ts +135 -0
- package/dist/src/hooks/index.js +317 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.js +1266 -0
- package/dist/src/kernel/index.d.ts +155 -0
- package/dist/src/kernel/index.js +795 -0
- package/dist/src/kernel/invariants.d.ts +153 -0
- package/dist/src/kernel/invariants.js +355 -0
- package/dist/src/kernel/test-kernel.d.ts +6 -0
- package/dist/src/kernel/test-kernel.js +108 -0
- package/dist/src/kernel/test-real-mcp.d.ts +10 -0
- package/dist/src/kernel/test-real-mcp.js +295 -0
- package/dist/src/llm/index.d.ts +146 -0
- package/dist/src/llm/index.js +428 -0
- package/dist/src/llm/router.d.ts +136 -0
- package/dist/src/llm/router.js +510 -0
- package/dist/src/mcp/index.d.ts +85 -0
- package/dist/src/mcp/index.js +657 -0
- package/dist/src/mcp/resilient.d.ts +139 -0
- package/dist/src/mcp/resilient.js +417 -0
- package/dist/src/memory/cache.d.ts +118 -0
- package/dist/src/memory/cache.js +356 -0
- package/dist/src/memory/cognitive-workspace.d.ts +231 -0
- package/dist/src/memory/cognitive-workspace.js +521 -0
- package/dist/src/memory/consolidation.d.ts +99 -0
- package/dist/src/memory/consolidation.js +443 -0
- package/dist/src/memory/episodic.d.ts +114 -0
- package/dist/src/memory/episodic.js +394 -0
- package/dist/src/memory/forgetting.d.ts +134 -0
- package/dist/src/memory/forgetting.js +324 -0
- package/dist/src/memory/index.d.ts +211 -0
- package/dist/src/memory/index.js +367 -0
- package/dist/src/memory/indexer.d.ts +123 -0
- package/dist/src/memory/indexer.js +479 -0
- package/dist/src/memory/procedural.d.ts +136 -0
- package/dist/src/memory/procedural.js +479 -0
- package/dist/src/memory/semantic.d.ts +132 -0
- package/dist/src/memory/semantic.js +497 -0
- package/dist/src/memory/types.d.ts +193 -0
- package/dist/src/memory/types.js +15 -0
- package/dist/src/orchestrator.d.ts +65 -0
- package/dist/src/orchestrator.js +317 -0
- package/dist/src/persistence/index.d.ts +257 -0
- package/dist/src/persistence/index.js +763 -0
- package/dist/src/pipeline/executor.d.ts +51 -0
- package/dist/src/pipeline/executor.js +695 -0
- package/dist/src/pipeline/index.d.ts +7 -0
- package/dist/src/pipeline/index.js +11 -0
- package/dist/src/self-production.d.ts +67 -0
- package/dist/src/self-production.js +205 -0
- package/dist/src/subagents/executor.d.ts +58 -0
- package/dist/src/subagents/executor.js +283 -0
- package/dist/src/subagents/index.d.ts +37 -0
- package/dist/src/subagents/index.js +53 -0
- package/dist/src/subagents/registry.d.ts +23 -0
- package/dist/src/subagents/registry.js +167 -0
- package/dist/src/subagents/types.d.ts +79 -0
- package/dist/src/subagents/types.js +14 -0
- package/dist/src/tools/bash.d.ts +139 -0
- package/dist/src/tools/bash.js +583 -0
- package/dist/src/tools/edit.d.ts +125 -0
- package/dist/src/tools/edit.js +424 -0
- package/dist/src/tools/git.d.ts +179 -0
- package/dist/src/tools/git.js +504 -0
- package/dist/src/tools/index.d.ts +21 -0
- package/dist/src/tools/index.js +163 -0
- package/dist/src/types.d.ts +145 -0
- package/dist/src/types.js +7 -0
- package/dist/src/world-model/decoder.d.ts +163 -0
- package/dist/src/world-model/decoder.js +517 -0
- package/dist/src/world-model/digital-twin.d.ts +219 -0
- package/dist/src/world-model/digital-twin.js +695 -0
- package/dist/src/world-model/encoder.d.ts +141 -0
- package/dist/src/world-model/encoder.js +564 -0
- package/dist/src/world-model/index.d.ts +221 -0
- package/dist/src/world-model/index.js +772 -0
- package/dist/src/world-model/predictor.d.ts +161 -0
- package/dist/src/world-model/predictor.js +681 -0
- package/dist/src/world-model/test-value-jepa.d.ts +8 -0
- package/dist/src/world-model/test-value-jepa.js +430 -0
- package/dist/src/world-model/types.d.ts +341 -0
- package/dist/src/world-model/types.js +69 -0
- package/dist/src/world-model/value-jepa.d.ts +247 -0
- package/dist/src/world-model/value-jepa.js +622 -0
- package/dist/test/brain.test.d.ts +11 -0
- package/dist/test/brain.test.js +358 -0
- package/dist/test/cli/dispatcher.test.d.ts +4 -0
- package/dist/test/cli/dispatcher.test.js +332 -0
- package/dist/test/cli/human-loop.test.d.ts +4 -0
- package/dist/test/cli/human-loop.test.js +270 -0
- package/dist/test/grounding/feedback.test.d.ts +4 -0
- package/dist/test/grounding/feedback.test.js +462 -0
- package/dist/test/grounding/verifier.test.d.ts +4 -0
- package/dist/test/grounding/verifier.test.js +442 -0
- package/dist/test/grounding.test.d.ts +6 -0
- package/dist/test/grounding.test.js +246 -0
- package/dist/test/healing/detector.test.d.ts +4 -0
- package/dist/test/healing/detector.test.js +266 -0
- package/dist/test/healing/fixer.test.d.ts +4 -0
- package/dist/test/healing/fixer.test.js +369 -0
- package/dist/test/integration.test.d.ts +5 -0
- package/dist/test/integration.test.js +290 -0
- package/dist/test/tools/bash.test.d.ts +4 -0
- package/dist/test/tools/bash.test.js +348 -0
- package/dist/test/tools/edit.test.d.ts +4 -0
- package/dist/test/tools/edit.test.js +350 -0
- package/dist/test/tools/git.test.d.ts +4 -0
- package/dist/test/tools/git.test.js +350 -0
- package/package.json +60 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis 6.0 - Task Scheduler
|
|
4
|
+
*
|
|
5
|
+
* Background task scheduling with priorities, retries, and monitoring.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Priority-based execution queue
|
|
9
|
+
* - Interval and cron scheduling
|
|
10
|
+
* - Automatic retries with backoff
|
|
11
|
+
* - Task timeout handling
|
|
12
|
+
* - Concurrent execution limits
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { createScheduler } from './daemon/scheduler.js';
|
|
17
|
+
*
|
|
18
|
+
* const scheduler = createScheduler({ maxConcurrentTasks: 5 });
|
|
19
|
+
*
|
|
20
|
+
* // Schedule a recurring task
|
|
21
|
+
* scheduler.schedule({
|
|
22
|
+
* name: 'health-check',
|
|
23
|
+
* schedule: { type: 'interval', intervalMs: 60000 },
|
|
24
|
+
* handler: async (ctx) => {
|
|
25
|
+
* ctx.logger.info('Running health check');
|
|
26
|
+
* return { success: true, duration: 50 };
|
|
27
|
+
* },
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Start the scheduler
|
|
31
|
+
* scheduler.start();
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.Scheduler = exports.DEFAULT_SCHEDULER_CONFIG = void 0;
|
|
36
|
+
exports.createScheduler = createScheduler;
|
|
37
|
+
const crypto_1 = require("crypto");
|
|
38
|
+
exports.DEFAULT_SCHEDULER_CONFIG = {
|
|
39
|
+
maxConcurrentTasks: 5,
|
|
40
|
+
defaultTimeout: 60000, // 1 minute
|
|
41
|
+
defaultRetries: 3,
|
|
42
|
+
defaultRetryDelay: 1000, // 1 second
|
|
43
|
+
tickIntervalMs: 1000, // Check every second
|
|
44
|
+
};
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Priority Queue
|
|
47
|
+
// ============================================================================
|
|
48
|
+
const PRIORITY_ORDER = {
|
|
49
|
+
critical: 0,
|
|
50
|
+
high: 1,
|
|
51
|
+
normal: 2,
|
|
52
|
+
low: 3,
|
|
53
|
+
idle: 4,
|
|
54
|
+
};
|
|
55
|
+
function compareTasks(a, b) {
|
|
56
|
+
// First by priority
|
|
57
|
+
const priorityDiff = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority];
|
|
58
|
+
if (priorityDiff !== 0)
|
|
59
|
+
return priorityDiff;
|
|
60
|
+
// Then by next run time
|
|
61
|
+
if (a.nextRun && b.nextRun) {
|
|
62
|
+
return a.nextRun.getTime() - b.nextRun.getTime();
|
|
63
|
+
}
|
|
64
|
+
if (a.nextRun)
|
|
65
|
+
return -1;
|
|
66
|
+
if (b.nextRun)
|
|
67
|
+
return 1;
|
|
68
|
+
// Finally by creation time
|
|
69
|
+
return a.createdAt.getTime() - b.createdAt.getTime();
|
|
70
|
+
}
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// Task Logger Implementation
|
|
73
|
+
// ============================================================================
|
|
74
|
+
function createTaskLogger(taskId, taskName) {
|
|
75
|
+
const prefix = `[Task:${taskName}]`;
|
|
76
|
+
return {
|
|
77
|
+
debug(message, data) {
|
|
78
|
+
if (process.env.LOG_LEVEL === 'debug') {
|
|
79
|
+
console.log(`${prefix} DEBUG: ${message}`, data || '');
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
info(message, data) {
|
|
83
|
+
console.log(`${prefix} INFO: ${message}`, data || '');
|
|
84
|
+
},
|
|
85
|
+
warn(message, data) {
|
|
86
|
+
console.warn(`${prefix} WARN: ${message}`, data || '');
|
|
87
|
+
},
|
|
88
|
+
error(message, error) {
|
|
89
|
+
console.error(`${prefix} ERROR: ${message}`, error?.message || '');
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// Cron Parser (Simplified)
|
|
95
|
+
// ============================================================================
|
|
96
|
+
/**
|
|
97
|
+
* Parse a simplified cron expression
|
|
98
|
+
* Format: minute hour day-of-month month day-of-week
|
|
99
|
+
* Supports: *, numbers, ranges (1-5), steps (* /5)
|
|
100
|
+
*/
|
|
101
|
+
function parseCron(expression) {
|
|
102
|
+
const parts = expression.trim().split(/\s+/);
|
|
103
|
+
if (parts.length !== 5) {
|
|
104
|
+
throw new Error(`Invalid cron expression: ${expression}`);
|
|
105
|
+
}
|
|
106
|
+
const parse = (part, min, max) => {
|
|
107
|
+
if (part === '*') {
|
|
108
|
+
return Array.from({ length: max - min + 1 }, (_, i) => min + i);
|
|
109
|
+
}
|
|
110
|
+
// Handle step (*/5)
|
|
111
|
+
if (part.startsWith('*/')) {
|
|
112
|
+
const step = parseInt(part.slice(2), 10);
|
|
113
|
+
const result = [];
|
|
114
|
+
for (let i = min; i <= max; i += step) {
|
|
115
|
+
result.push(i);
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
// Handle range (1-5)
|
|
120
|
+
if (part.includes('-')) {
|
|
121
|
+
const [start, end] = part.split('-').map((n) => parseInt(n, 10));
|
|
122
|
+
const result = [];
|
|
123
|
+
for (let i = start; i <= end; i++) {
|
|
124
|
+
result.push(i);
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
// Handle list (1,3,5)
|
|
129
|
+
if (part.includes(',')) {
|
|
130
|
+
return part.split(',').map((n) => parseInt(n, 10));
|
|
131
|
+
}
|
|
132
|
+
// Single value
|
|
133
|
+
return [parseInt(part, 10)];
|
|
134
|
+
};
|
|
135
|
+
return {
|
|
136
|
+
minutes: parse(parts[0], 0, 59),
|
|
137
|
+
hours: parse(parts[1], 0, 23),
|
|
138
|
+
days: parse(parts[2], 1, 31),
|
|
139
|
+
months: parse(parts[3], 1, 12),
|
|
140
|
+
weekdays: parse(parts[4], 0, 6),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function getNextCronTime(expression, after = new Date()) {
|
|
144
|
+
const cron = parseCron(expression);
|
|
145
|
+
const next = new Date(after);
|
|
146
|
+
next.setSeconds(0, 0);
|
|
147
|
+
next.setMinutes(next.getMinutes() + 1);
|
|
148
|
+
// Search up to 1 year ahead
|
|
149
|
+
const maxIterations = 366 * 24 * 60;
|
|
150
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
151
|
+
const month = next.getMonth() + 1;
|
|
152
|
+
const day = next.getDate();
|
|
153
|
+
const weekday = next.getDay();
|
|
154
|
+
const hour = next.getHours();
|
|
155
|
+
const minute = next.getMinutes();
|
|
156
|
+
if (cron.months.includes(month) &&
|
|
157
|
+
cron.days.includes(day) &&
|
|
158
|
+
cron.weekdays.includes(weekday) &&
|
|
159
|
+
cron.hours.includes(hour) &&
|
|
160
|
+
cron.minutes.includes(minute)) {
|
|
161
|
+
return next;
|
|
162
|
+
}
|
|
163
|
+
next.setMinutes(next.getMinutes() + 1);
|
|
164
|
+
}
|
|
165
|
+
throw new Error(`Could not find next cron time for: ${expression}`);
|
|
166
|
+
}
|
|
167
|
+
class Scheduler {
|
|
168
|
+
tasks = new Map();
|
|
169
|
+
running = new Set();
|
|
170
|
+
tickTimer = null;
|
|
171
|
+
config;
|
|
172
|
+
started = false;
|
|
173
|
+
eventHandlers = new Set();
|
|
174
|
+
constructor(config = {}) {
|
|
175
|
+
this.config = { ...exports.DEFAULT_SCHEDULER_CONFIG, ...config };
|
|
176
|
+
}
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// Lifecycle
|
|
179
|
+
// ============================================================================
|
|
180
|
+
start() {
|
|
181
|
+
if (this.started)
|
|
182
|
+
return;
|
|
183
|
+
this.started = true;
|
|
184
|
+
this.tickTimer = setInterval(() => this.tick(), this.config.tickIntervalMs);
|
|
185
|
+
this.emit({ type: 'started' });
|
|
186
|
+
// Run immediate tasks
|
|
187
|
+
this.tick();
|
|
188
|
+
}
|
|
189
|
+
stop() {
|
|
190
|
+
if (!this.started)
|
|
191
|
+
return;
|
|
192
|
+
this.started = false;
|
|
193
|
+
if (this.tickTimer) {
|
|
194
|
+
clearInterval(this.tickTimer);
|
|
195
|
+
this.tickTimer = null;
|
|
196
|
+
}
|
|
197
|
+
this.emit({ type: 'stopped' });
|
|
198
|
+
}
|
|
199
|
+
isRunning() {
|
|
200
|
+
return this.started;
|
|
201
|
+
}
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// Task Management
|
|
204
|
+
// ============================================================================
|
|
205
|
+
schedule(options) {
|
|
206
|
+
const id = (0, crypto_1.randomUUID)();
|
|
207
|
+
const now = new Date();
|
|
208
|
+
const task = {
|
|
209
|
+
id,
|
|
210
|
+
name: options.name,
|
|
211
|
+
description: options.description,
|
|
212
|
+
state: 'pending',
|
|
213
|
+
priority: options.priority || 'normal',
|
|
214
|
+
schedule: options.schedule,
|
|
215
|
+
nextRun: this.calculateNextRun(options.schedule, now),
|
|
216
|
+
lastRun: null,
|
|
217
|
+
handler: options.handler,
|
|
218
|
+
timeout: options.timeout || this.config.defaultTimeout,
|
|
219
|
+
retries: options.retries ?? this.config.defaultRetries,
|
|
220
|
+
retryDelay: options.retryDelay || this.config.defaultRetryDelay,
|
|
221
|
+
runCount: 0,
|
|
222
|
+
successCount: 0,
|
|
223
|
+
failureCount: 0,
|
|
224
|
+
avgDuration: 0,
|
|
225
|
+
createdAt: now,
|
|
226
|
+
tags: options.tags || [],
|
|
227
|
+
};
|
|
228
|
+
if (task.nextRun) {
|
|
229
|
+
task.state = 'scheduled';
|
|
230
|
+
}
|
|
231
|
+
this.tasks.set(id, task);
|
|
232
|
+
this.emit({ type: 'task_scheduled', task });
|
|
233
|
+
return task;
|
|
234
|
+
}
|
|
235
|
+
cancel(taskId) {
|
|
236
|
+
const task = this.tasks.get(taskId);
|
|
237
|
+
if (!task)
|
|
238
|
+
return false;
|
|
239
|
+
if (task.state === 'running') {
|
|
240
|
+
// Can't cancel running tasks directly (they have abort signals)
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
task.state = 'cancelled';
|
|
244
|
+
this.emit({ type: 'task_cancelled', task });
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
remove(taskId) {
|
|
248
|
+
const task = this.tasks.get(taskId);
|
|
249
|
+
if (!task)
|
|
250
|
+
return false;
|
|
251
|
+
if (task.state === 'running') {
|
|
252
|
+
return false; // Can't remove running tasks
|
|
253
|
+
}
|
|
254
|
+
return this.tasks.delete(taskId);
|
|
255
|
+
}
|
|
256
|
+
pause(taskId) {
|
|
257
|
+
const task = this.tasks.get(taskId);
|
|
258
|
+
if (!task)
|
|
259
|
+
return false;
|
|
260
|
+
if (task.state === 'scheduled' || task.state === 'pending') {
|
|
261
|
+
task.state = 'paused';
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
resume(taskId) {
|
|
267
|
+
const task = this.tasks.get(taskId);
|
|
268
|
+
if (!task)
|
|
269
|
+
return false;
|
|
270
|
+
if (task.state === 'paused') {
|
|
271
|
+
task.state = task.nextRun ? 'scheduled' : 'pending';
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
trigger(taskId) {
|
|
277
|
+
const task = this.tasks.get(taskId);
|
|
278
|
+
if (!task)
|
|
279
|
+
return false;
|
|
280
|
+
if (task.state !== 'running') {
|
|
281
|
+
task.nextRun = new Date();
|
|
282
|
+
task.state = 'scheduled';
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
// ============================================================================
|
|
288
|
+
// Query
|
|
289
|
+
// ============================================================================
|
|
290
|
+
get(taskId) {
|
|
291
|
+
return this.tasks.get(taskId);
|
|
292
|
+
}
|
|
293
|
+
getByName(name) {
|
|
294
|
+
for (const task of this.tasks.values()) {
|
|
295
|
+
if (task.name === name)
|
|
296
|
+
return task;
|
|
297
|
+
}
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
getAll() {
|
|
301
|
+
return Array.from(this.tasks.values());
|
|
302
|
+
}
|
|
303
|
+
getPending() {
|
|
304
|
+
return this.getAll().filter((t) => ['pending', 'scheduled'].includes(t.state));
|
|
305
|
+
}
|
|
306
|
+
getRunning() {
|
|
307
|
+
return this.getAll().filter((t) => t.state === 'running');
|
|
308
|
+
}
|
|
309
|
+
getByTag(tag) {
|
|
310
|
+
return this.getAll().filter((t) => t.tags.includes(tag));
|
|
311
|
+
}
|
|
312
|
+
// ============================================================================
|
|
313
|
+
// Stats
|
|
314
|
+
// ============================================================================
|
|
315
|
+
stats() {
|
|
316
|
+
const tasks = this.getAll();
|
|
317
|
+
return {
|
|
318
|
+
total: tasks.length,
|
|
319
|
+
pending: tasks.filter((t) => t.state === 'pending').length,
|
|
320
|
+
scheduled: tasks.filter((t) => t.state === 'scheduled').length,
|
|
321
|
+
running: tasks.filter((t) => t.state === 'running').length,
|
|
322
|
+
completed: tasks.filter((t) => t.state === 'completed').length,
|
|
323
|
+
failed: tasks.filter((t) => t.state === 'failed').length,
|
|
324
|
+
cancelled: tasks.filter((t) => t.state === 'cancelled').length,
|
|
325
|
+
paused: tasks.filter((t) => t.state === 'paused').length,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
// ============================================================================
|
|
329
|
+
// Events
|
|
330
|
+
// ============================================================================
|
|
331
|
+
on(handler) {
|
|
332
|
+
this.eventHandlers.add(handler);
|
|
333
|
+
return () => this.eventHandlers.delete(handler);
|
|
334
|
+
}
|
|
335
|
+
emit(event) {
|
|
336
|
+
for (const handler of this.eventHandlers) {
|
|
337
|
+
try {
|
|
338
|
+
handler(event);
|
|
339
|
+
}
|
|
340
|
+
catch (err) {
|
|
341
|
+
console.error('Scheduler event handler error:', err);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// ============================================================================
|
|
346
|
+
// Internal
|
|
347
|
+
// ============================================================================
|
|
348
|
+
async tick() {
|
|
349
|
+
if (!this.started)
|
|
350
|
+
return;
|
|
351
|
+
const now = new Date();
|
|
352
|
+
const dueTasks = this.getDueTasks(now);
|
|
353
|
+
// Sort by priority
|
|
354
|
+
dueTasks.sort(compareTasks);
|
|
355
|
+
// Execute up to max concurrent
|
|
356
|
+
const available = this.config.maxConcurrentTasks - this.running.size;
|
|
357
|
+
const toRun = dueTasks.slice(0, available);
|
|
358
|
+
for (const task of toRun) {
|
|
359
|
+
this.executeTask(task);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
getDueTasks(now) {
|
|
363
|
+
const due = [];
|
|
364
|
+
for (const task of this.tasks.values()) {
|
|
365
|
+
if (task.state === 'scheduled' && task.nextRun && task.nextRun <= now) {
|
|
366
|
+
due.push(task);
|
|
367
|
+
}
|
|
368
|
+
if (task.state === 'pending' && task.schedule.type === 'immediate') {
|
|
369
|
+
due.push(task);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return due;
|
|
373
|
+
}
|
|
374
|
+
async executeTask(task) {
|
|
375
|
+
task.state = 'running';
|
|
376
|
+
this.running.add(task.id);
|
|
377
|
+
this.emit({ type: 'task_started', task });
|
|
378
|
+
const startTime = Date.now();
|
|
379
|
+
let attempt = 0;
|
|
380
|
+
let lastError;
|
|
381
|
+
while (attempt <= task.retries) {
|
|
382
|
+
attempt++;
|
|
383
|
+
try {
|
|
384
|
+
const result = await this.runWithTimeout(task, attempt);
|
|
385
|
+
if (result.success) {
|
|
386
|
+
// Success
|
|
387
|
+
task.successCount++;
|
|
388
|
+
task.runCount++;
|
|
389
|
+
task.lastRun = new Date();
|
|
390
|
+
// Update average duration
|
|
391
|
+
const newAvg = (task.avgDuration * (task.runCount - 1) + result.duration) / task.runCount;
|
|
392
|
+
task.avgDuration = newAvg;
|
|
393
|
+
// Reschedule if recurring
|
|
394
|
+
const nextRun = this.calculateNextRun(task.schedule, task.lastRun);
|
|
395
|
+
if (nextRun) {
|
|
396
|
+
task.nextRun = nextRun;
|
|
397
|
+
task.state = 'scheduled';
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
task.state = 'completed';
|
|
401
|
+
}
|
|
402
|
+
this.emit({ type: 'task_completed', task });
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
lastError = result.error;
|
|
407
|
+
if (attempt <= task.retries) {
|
|
408
|
+
await this.sleep(task.retryDelay * attempt); // Exponential backoff
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
catch (err) {
|
|
413
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
414
|
+
if (attempt <= task.retries) {
|
|
415
|
+
await this.sleep(task.retryDelay * attempt);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
// If we exhausted all retries
|
|
420
|
+
if (task.state === 'running') {
|
|
421
|
+
task.failureCount++;
|
|
422
|
+
task.runCount++;
|
|
423
|
+
task.lastRun = new Date();
|
|
424
|
+
// Still reschedule if recurring
|
|
425
|
+
const nextRun = this.calculateNextRun(task.schedule, task.lastRun);
|
|
426
|
+
if (nextRun) {
|
|
427
|
+
task.nextRun = nextRun;
|
|
428
|
+
task.state = 'scheduled';
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
task.state = 'failed';
|
|
432
|
+
}
|
|
433
|
+
this.emit({ type: 'task_failed', task, error: lastError });
|
|
434
|
+
}
|
|
435
|
+
this.running.delete(task.id);
|
|
436
|
+
}
|
|
437
|
+
async runWithTimeout(task, attempt) {
|
|
438
|
+
const controller = new AbortController();
|
|
439
|
+
const timeout = setTimeout(() => controller.abort(), task.timeout);
|
|
440
|
+
const context = {
|
|
441
|
+
taskId: task.id,
|
|
442
|
+
attempt,
|
|
443
|
+
maxAttempts: task.retries + 1,
|
|
444
|
+
startedAt: new Date(),
|
|
445
|
+
timeout: task.timeout,
|
|
446
|
+
signal: controller.signal,
|
|
447
|
+
logger: createTaskLogger(task.id, task.name),
|
|
448
|
+
};
|
|
449
|
+
try {
|
|
450
|
+
const startTime = Date.now();
|
|
451
|
+
const result = await task.handler(context);
|
|
452
|
+
clearTimeout(timeout);
|
|
453
|
+
return {
|
|
454
|
+
...result,
|
|
455
|
+
duration: result.duration || (Date.now() - startTime),
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
catch (err) {
|
|
459
|
+
clearTimeout(timeout);
|
|
460
|
+
return {
|
|
461
|
+
success: false,
|
|
462
|
+
duration: Date.now() - context.startedAt.getTime(),
|
|
463
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
calculateNextRun(schedule, after) {
|
|
468
|
+
switch (schedule.type) {
|
|
469
|
+
case 'once':
|
|
470
|
+
// Already passed
|
|
471
|
+
return schedule.at > after ? schedule.at : null;
|
|
472
|
+
case 'immediate':
|
|
473
|
+
return null; // Only run once
|
|
474
|
+
case 'manual':
|
|
475
|
+
return null; // Triggered manually
|
|
476
|
+
case 'interval':
|
|
477
|
+
return new Date(after.getTime() + schedule.intervalMs);
|
|
478
|
+
case 'cron':
|
|
479
|
+
return getNextCronTime(schedule.expression, after);
|
|
480
|
+
default:
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
sleep(ms) {
|
|
485
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
exports.Scheduler = Scheduler;
|
|
489
|
+
// ============================================================================
|
|
490
|
+
// Factory
|
|
491
|
+
// ============================================================================
|
|
492
|
+
function createScheduler(config) {
|
|
493
|
+
return new Scheduler(config);
|
|
494
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis 6.0 - Daemon Module Types
|
|
3
|
+
*
|
|
4
|
+
* Types for background task scheduling, maintenance, and dream mode.
|
|
5
|
+
*
|
|
6
|
+
* Based on:
|
|
7
|
+
* - Node.js daemon patterns
|
|
8
|
+
* - Self-healing systems (Kubernetes liveness/readiness)
|
|
9
|
+
* - Sleep consolidation research (Walker, 2017)
|
|
10
|
+
*/
|
|
11
|
+
export type DaemonState = 'stopped' | 'starting' | 'running' | 'dreaming' | 'maintaining' | 'stopping' | 'error';
|
|
12
|
+
export interface DaemonStatus {
|
|
13
|
+
state: DaemonState;
|
|
14
|
+
uptime: number;
|
|
15
|
+
startedAt: Date | null;
|
|
16
|
+
lastHeartbeat: Date;
|
|
17
|
+
activeTasks: number;
|
|
18
|
+
completedTasks: number;
|
|
19
|
+
failedTasks: number;
|
|
20
|
+
dreamCycles: number;
|
|
21
|
+
maintenanceCycles: number;
|
|
22
|
+
errors: DaemonError[];
|
|
23
|
+
}
|
|
24
|
+
export interface DaemonError {
|
|
25
|
+
timestamp: Date;
|
|
26
|
+
code: string;
|
|
27
|
+
message: string;
|
|
28
|
+
source: 'scheduler' | 'maintenance' | 'dream' | 'task';
|
|
29
|
+
recovered: boolean;
|
|
30
|
+
}
|
|
31
|
+
export type TaskPriority = 'critical' | 'high' | 'normal' | 'low' | 'idle';
|
|
32
|
+
export type TaskState = 'pending' | 'scheduled' | 'running' | 'completed' | 'failed' | 'cancelled' | 'paused';
|
|
33
|
+
export interface ScheduledTask {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
state: TaskState;
|
|
38
|
+
priority: TaskPriority;
|
|
39
|
+
schedule: TaskSchedule;
|
|
40
|
+
nextRun: Date | null;
|
|
41
|
+
lastRun: Date | null;
|
|
42
|
+
handler: TaskHandler;
|
|
43
|
+
timeout: number;
|
|
44
|
+
retries: number;
|
|
45
|
+
retryDelay: number;
|
|
46
|
+
runCount: number;
|
|
47
|
+
successCount: number;
|
|
48
|
+
failureCount: number;
|
|
49
|
+
avgDuration: number;
|
|
50
|
+
createdAt: Date;
|
|
51
|
+
tags: string[];
|
|
52
|
+
}
|
|
53
|
+
export type TaskSchedule = {
|
|
54
|
+
type: 'once';
|
|
55
|
+
at: Date;
|
|
56
|
+
} | {
|
|
57
|
+
type: 'interval';
|
|
58
|
+
intervalMs: number;
|
|
59
|
+
} | {
|
|
60
|
+
type: 'cron';
|
|
61
|
+
expression: string;
|
|
62
|
+
} | {
|
|
63
|
+
type: 'immediate';
|
|
64
|
+
} | {
|
|
65
|
+
type: 'manual';
|
|
66
|
+
};
|
|
67
|
+
export type TaskHandler = (context: TaskContext) => Promise<TaskResult>;
|
|
68
|
+
export interface TaskContext {
|
|
69
|
+
taskId: string;
|
|
70
|
+
attempt: number;
|
|
71
|
+
maxAttempts: number;
|
|
72
|
+
startedAt: Date;
|
|
73
|
+
timeout: number;
|
|
74
|
+
signal: AbortSignal;
|
|
75
|
+
logger: TaskLogger;
|
|
76
|
+
}
|
|
77
|
+
export interface TaskLogger {
|
|
78
|
+
debug(message: string, data?: unknown): void;
|
|
79
|
+
info(message: string, data?: unknown): void;
|
|
80
|
+
warn(message: string, data?: unknown): void;
|
|
81
|
+
error(message: string, error?: Error): void;
|
|
82
|
+
}
|
|
83
|
+
export interface TaskResult {
|
|
84
|
+
success: boolean;
|
|
85
|
+
duration: number;
|
|
86
|
+
output?: unknown;
|
|
87
|
+
error?: Error;
|
|
88
|
+
metrics?: Record<string, number>;
|
|
89
|
+
}
|
|
90
|
+
export interface CreateTaskOptions {
|
|
91
|
+
name: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
handler: TaskHandler;
|
|
94
|
+
schedule: TaskSchedule;
|
|
95
|
+
priority?: TaskPriority;
|
|
96
|
+
timeout?: number;
|
|
97
|
+
retries?: number;
|
|
98
|
+
retryDelay?: number;
|
|
99
|
+
tags?: string[];
|
|
100
|
+
}
|
|
101
|
+
export type MaintenanceAction = 'agent_restart' | 'memory_cleanup' | 'cache_clear' | 'health_check' | 'invariant_repair' | 'state_reset' | 'log_rotation' | 'resource_reclaim';
|
|
102
|
+
export interface MaintenanceTask {
|
|
103
|
+
id: string;
|
|
104
|
+
action: MaintenanceAction;
|
|
105
|
+
target?: string;
|
|
106
|
+
priority: TaskPriority;
|
|
107
|
+
state: TaskState;
|
|
108
|
+
reason: string;
|
|
109
|
+
startedAt?: Date;
|
|
110
|
+
completedAt?: Date;
|
|
111
|
+
success?: boolean;
|
|
112
|
+
details?: string;
|
|
113
|
+
}
|
|
114
|
+
export interface MaintenanceConfig {
|
|
115
|
+
enabled: boolean;
|
|
116
|
+
intervalMs: number;
|
|
117
|
+
healthCheckIntervalMs: number;
|
|
118
|
+
memoryCleanupIntervalMs: number;
|
|
119
|
+
autoRepair: boolean;
|
|
120
|
+
maxConcurrentTasks: number;
|
|
121
|
+
unhealthyAgentThreshold: number;
|
|
122
|
+
memoryRetentionThreshold: number;
|
|
123
|
+
resourceUsageThreshold: number;
|
|
124
|
+
}
|
|
125
|
+
export interface MaintenanceReport {
|
|
126
|
+
timestamp: Date;
|
|
127
|
+
duration: number;
|
|
128
|
+
tasksRun: number;
|
|
129
|
+
tasksSucceeded: number;
|
|
130
|
+
tasksFailed: number;
|
|
131
|
+
issues: MaintenanceIssue[];
|
|
132
|
+
actions: MaintenanceTask[];
|
|
133
|
+
}
|
|
134
|
+
export interface MaintenanceIssue {
|
|
135
|
+
type: string;
|
|
136
|
+
severity: 'critical' | 'warning' | 'info';
|
|
137
|
+
description: string;
|
|
138
|
+
detected: Date;
|
|
139
|
+
resolved: boolean;
|
|
140
|
+
resolution?: string;
|
|
141
|
+
}
|
|
142
|
+
export type DreamPhase = 'light' | 'deep' | 'rem' | 'wake';
|
|
143
|
+
export interface DreamConfig {
|
|
144
|
+
enabled: boolean;
|
|
145
|
+
autoTrigger: boolean;
|
|
146
|
+
inactivityThresholdMs: number;
|
|
147
|
+
minDreamDurationMs: number;
|
|
148
|
+
maxDreamDurationMs: number;
|
|
149
|
+
lightSleepRatio: number;
|
|
150
|
+
deepSleepRatio: number;
|
|
151
|
+
remSleepRatio: number;
|
|
152
|
+
episodicConsolidationThreshold: number;
|
|
153
|
+
patternExtractionThreshold: number;
|
|
154
|
+
creativityTemperature: number;
|
|
155
|
+
}
|
|
156
|
+
export interface DreamSession {
|
|
157
|
+
id: string;
|
|
158
|
+
startedAt: Date;
|
|
159
|
+
endedAt?: Date;
|
|
160
|
+
phase: DreamPhase;
|
|
161
|
+
phaseHistory: Array<{
|
|
162
|
+
phase: DreamPhase;
|
|
163
|
+
enteredAt: Date;
|
|
164
|
+
exitedAt?: Date;
|
|
165
|
+
}>;
|
|
166
|
+
results?: DreamResults;
|
|
167
|
+
interrupted: boolean;
|
|
168
|
+
interruptReason?: string;
|
|
169
|
+
}
|
|
170
|
+
export interface DreamResults {
|
|
171
|
+
episodesProcessed: number;
|
|
172
|
+
memoriesConsolidated: number;
|
|
173
|
+
patternsExtracted: number;
|
|
174
|
+
skillsReinforced: number;
|
|
175
|
+
memoriesForgotten: number;
|
|
176
|
+
newAssociations: number;
|
|
177
|
+
novelIdeas: string[];
|
|
178
|
+
stateRepairs: number;
|
|
179
|
+
invariantsChecked: number;
|
|
180
|
+
}
|
|
181
|
+
export interface DreamMetrics {
|
|
182
|
+
totalDreamTime: number;
|
|
183
|
+
dreamCycles: number;
|
|
184
|
+
avgCycleDuration: number;
|
|
185
|
+
consolidationRate: number;
|
|
186
|
+
patternExtractionRate: number;
|
|
187
|
+
lastDreamAt: Date | null;
|
|
188
|
+
nextScheduledDream: Date | null;
|
|
189
|
+
}
|
|
190
|
+
export interface DaemonConfig {
|
|
191
|
+
enabled: boolean;
|
|
192
|
+
heartbeatIntervalMs: number;
|
|
193
|
+
maxErrors: number;
|
|
194
|
+
scheduler: {
|
|
195
|
+
enabled: boolean;
|
|
196
|
+
maxConcurrentTasks: number;
|
|
197
|
+
defaultTimeout: number;
|
|
198
|
+
defaultRetries: number;
|
|
199
|
+
};
|
|
200
|
+
maintenance: MaintenanceConfig;
|
|
201
|
+
dream: DreamConfig;
|
|
202
|
+
logLevel: 'debug' | 'info' | 'warn' | 'error';
|
|
203
|
+
logToFile: boolean;
|
|
204
|
+
logFilePath?: string;
|
|
205
|
+
}
|
|
206
|
+
export declare const DEFAULT_DAEMON_CONFIG: DaemonConfig;
|
|
207
|
+
export type DaemonEventType = 'daemon_started' | 'daemon_stopped' | 'daemon_error' | 'task_scheduled' | 'task_started' | 'task_completed' | 'task_failed' | 'task_cancelled' | 'maintenance_started' | 'maintenance_completed' | 'maintenance_issue' | 'dream_started' | 'dream_phase_changed' | 'dream_completed' | 'dream_interrupted';
|
|
208
|
+
export interface DaemonEvent {
|
|
209
|
+
type: DaemonEventType;
|
|
210
|
+
timestamp: Date;
|
|
211
|
+
data: unknown;
|
|
212
|
+
}
|
|
213
|
+
export type DaemonEventHandler = (event: DaemonEvent) => void;
|