@auxiora/behaviors 1.0.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +18 -6
- package/dist/executor.js.map +1 -1
- package/package.json +11 -5
- package/src/behavior-manager.ts +0 -305
- package/src/executor.ts +0 -132
- package/src/index.ts +0 -16
- package/src/monitor.ts +0 -45
- package/src/scheduler.ts +0 -55
- package/src/store.ts +0 -83
- package/src/types.ts +0 -59
- package/tests/behavior-manager.test.ts +0 -162
- package/tests/executor.test.ts +0 -128
- package/tests/integration.test.ts +0 -148
- package/tests/monitor.test.ts +0 -60
- package/tests/scheduler.test.ts +0 -58
- package/tests/store.test.ts +0 -108
- package/tsconfig.json +0 -14
- package/tsconfig.tsbuildinfo +0 -1
package/dist/executor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAI9D,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;YACvF,OAAO,EAAE,MAAM,CAAC;YAChB,KAAK,EAAE;gBAAE,WAAW,EAAE,MAAM,CAAC;gBAAC,YAAY,EAAE,MAAM,CAAA;aAAE,CAAC;YACrD,KAAK,EAAE,MAAM,CAAC;YACd,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC,CAAC;KACJ,CAAC;IACF,aAAa,EAAE,CACb,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KACzB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,CACjB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,EAClD,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CACzF;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAe;gBAEf,IAAI,EAAE,YAAY;IAIxB,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAI9D,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;YACvF,OAAO,EAAE,MAAM,CAAC;YAChB,KAAK,EAAE;gBAAE,WAAW,EAAE,MAAM,CAAC;gBAAC,YAAY,EAAE,MAAM,CAAA;aAAE,CAAC;YACrD,KAAK,EAAE,MAAM,CAAC;YACd,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC,CAAC;KACJ,CAAC;IACF,aAAa,EAAE,CACb,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KACzB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,CACjB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,EAClD,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CACzF;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAe;gBAEf,IAAI,EAAE,YAAY;IAIxB,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA6E7D,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,QAAQ;CAYjB"}
|
package/dist/executor.js
CHANGED
|
@@ -12,12 +12,24 @@ export class BehaviorExecutor {
|
|
|
12
12
|
const provider = this.deps.getProvider();
|
|
13
13
|
const messages = this.buildMessages(behavior);
|
|
14
14
|
const systemPrompt = this.buildSystemPrompt(behavior);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
let content;
|
|
16
|
+
if (this.deps.executeWithTools) {
|
|
17
|
+
logger.debug('Executing behavior with tools', { id: behavior.id });
|
|
18
|
+
const toolResult = await this.deps.executeWithTools(messages, systemPrompt);
|
|
19
|
+
content = toolResult.content;
|
|
20
|
+
logger.debug('Behavior AI response received (with tools)', {
|
|
21
|
+
id: behavior.id,
|
|
22
|
+
tokens: toolResult.usage,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const result = await provider.complete(messages, { systemPrompt });
|
|
27
|
+
content = result.content;
|
|
28
|
+
logger.debug('Behavior AI response received', {
|
|
29
|
+
id: behavior.id,
|
|
30
|
+
tokens: result.usage,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
21
33
|
// Deliver to channel
|
|
22
34
|
const label = this.getLabel(behavior);
|
|
23
35
|
const formattedContent = label + '\n' + content;
|
package/dist/executor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,MAAM,MAAM,GAAG,SAAS,CAAC,oBAAoB,CAAC,CAAC;AAwB/C,MAAM,OAAO,gBAAgB;IACnB,IAAI,CAAe;IAE3B,YAAY,IAAkB;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAkB;QAC9B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAErG,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAEtD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auxiora/behaviors",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Proactive behaviors: scheduled tasks, monitors, and one-shot reminders",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"node-cron": "^3.0.3",
|
|
16
16
|
"nanoid": "^5.1.2",
|
|
17
|
-
"@auxiora/
|
|
18
|
-
"@auxiora/
|
|
19
|
-
"@auxiora/
|
|
20
|
-
"@auxiora/
|
|
17
|
+
"@auxiora/errors": "1.3.0",
|
|
18
|
+
"@auxiora/core": "1.3.0",
|
|
19
|
+
"@auxiora/logger": "1.3.0",
|
|
20
|
+
"@auxiora/audit": "1.3.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node-cron": "^3.0.11"
|
|
@@ -25,6 +25,12 @@
|
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=22.0.0"
|
|
27
27
|
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist/"
|
|
33
|
+
],
|
|
28
34
|
"scripts": {
|
|
29
35
|
"build": "tsc",
|
|
30
36
|
"clean": "rm -rf dist",
|
package/src/behavior-manager.ts
DELETED
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
import { nanoid } from 'nanoid';
|
|
2
|
-
import { getLogger } from '@auxiora/logger';
|
|
3
|
-
import type {
|
|
4
|
-
Behavior,
|
|
5
|
-
BehaviorType,
|
|
6
|
-
BehaviorStatus,
|
|
7
|
-
BehaviorSchedule,
|
|
8
|
-
BehaviorPolling,
|
|
9
|
-
BehaviorDelay,
|
|
10
|
-
BehaviorChannel,
|
|
11
|
-
} from './types.js';
|
|
12
|
-
import { BEHAVIOR_DEFAULTS } from './types.js';
|
|
13
|
-
import { BehaviorStore } from './store.js';
|
|
14
|
-
import { Scheduler } from './scheduler.js';
|
|
15
|
-
import { MonitorEngine } from './monitor.js';
|
|
16
|
-
import { BehaviorExecutor, type ExecutorDeps } from './executor.js';
|
|
17
|
-
|
|
18
|
-
const logger = getLogger('behaviors:manager');
|
|
19
|
-
|
|
20
|
-
export interface CreateBehaviorInput {
|
|
21
|
-
type: BehaviorType;
|
|
22
|
-
action: string;
|
|
23
|
-
schedule?: BehaviorSchedule;
|
|
24
|
-
polling?: BehaviorPolling;
|
|
25
|
-
delay?: BehaviorDelay;
|
|
26
|
-
channel: BehaviorChannel;
|
|
27
|
-
createdBy: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface BehaviorManagerOptions {
|
|
31
|
-
storePath: string;
|
|
32
|
-
executorDeps: ExecutorDeps;
|
|
33
|
-
auditFn: (event: string, details: Record<string, unknown>) => Promise<void> | void;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class BehaviorManager {
|
|
37
|
-
private store: BehaviorStore;
|
|
38
|
-
private scheduler: Scheduler;
|
|
39
|
-
private monitor: MonitorEngine;
|
|
40
|
-
private executor: BehaviorExecutor;
|
|
41
|
-
private auditFn: (event: string, details: Record<string, unknown>) => Promise<void> | void;
|
|
42
|
-
private executionQueue: Promise<void> = Promise.resolve();
|
|
43
|
-
private oneshotTimers = new Map<string, ReturnType<typeof setTimeout>>();
|
|
44
|
-
|
|
45
|
-
constructor(options: BehaviorManagerOptions) {
|
|
46
|
-
this.store = new BehaviorStore(options.storePath);
|
|
47
|
-
this.scheduler = new Scheduler();
|
|
48
|
-
this.monitor = new MonitorEngine();
|
|
49
|
-
this.executor = new BehaviorExecutor(options.executorDeps);
|
|
50
|
-
this.auditFn = options.auditFn;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async start(): Promise<void> {
|
|
54
|
-
const behaviors = await this.store.listActive();
|
|
55
|
-
logger.info('Starting behavior manager', { activeBehaviors: behaviors.length });
|
|
56
|
-
|
|
57
|
-
for (const behavior of behaviors) {
|
|
58
|
-
this.activate(behavior);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async stop(): Promise<void> {
|
|
63
|
-
this.scheduler.stopAll();
|
|
64
|
-
this.monitor.stopAll();
|
|
65
|
-
for (const [, timer] of this.oneshotTimers) {
|
|
66
|
-
clearTimeout(timer);
|
|
67
|
-
}
|
|
68
|
-
this.oneshotTimers.clear();
|
|
69
|
-
logger.info('Behavior manager stopped');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async create(input: CreateBehaviorInput): Promise<Behavior> {
|
|
73
|
-
this.validate(input);
|
|
74
|
-
|
|
75
|
-
const behavior: Behavior = {
|
|
76
|
-
id: `bh_${nanoid(8)}`,
|
|
77
|
-
type: input.type,
|
|
78
|
-
status: 'active',
|
|
79
|
-
action: input.action,
|
|
80
|
-
schedule: input.schedule,
|
|
81
|
-
polling: input.polling,
|
|
82
|
-
delay: input.delay,
|
|
83
|
-
channel: input.channel,
|
|
84
|
-
createdBy: input.createdBy,
|
|
85
|
-
createdAt: new Date().toISOString(),
|
|
86
|
-
runCount: 0,
|
|
87
|
-
failCount: 0,
|
|
88
|
-
maxFailures: BEHAVIOR_DEFAULTS.maxFailures,
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
await this.store.save(behavior);
|
|
92
|
-
this.activate(behavior);
|
|
93
|
-
|
|
94
|
-
this.auditFn('behavior.created', {
|
|
95
|
-
behaviorId: behavior.id,
|
|
96
|
-
type: behavior.type,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
logger.info('Created behavior', { id: behavior.id, type: behavior.type, action: behavior.action });
|
|
100
|
-
return behavior;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async list(filter?: { type?: BehaviorType; status?: BehaviorStatus }): Promise<Behavior[]> {
|
|
104
|
-
const all = await this.store.getAll();
|
|
105
|
-
return all.filter((b) => {
|
|
106
|
-
if (filter?.type && b.type !== filter.type) return false;
|
|
107
|
-
if (filter?.status && b.status !== filter.status) return false;
|
|
108
|
-
return true;
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async get(id: string): Promise<Behavior | undefined> {
|
|
113
|
-
return this.store.get(id);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async update(id: string, updates: Partial<Behavior>): Promise<Behavior | undefined> {
|
|
117
|
-
const current = await this.store.get(id);
|
|
118
|
-
if (!current) return undefined;
|
|
119
|
-
|
|
120
|
-
const wasActive = current.status === 'active';
|
|
121
|
-
const updated = await this.store.update(id, updates);
|
|
122
|
-
if (!updated) return undefined;
|
|
123
|
-
|
|
124
|
-
const isActive = updated.status === 'active';
|
|
125
|
-
|
|
126
|
-
// Handle status transitions
|
|
127
|
-
if (wasActive && !isActive) {
|
|
128
|
-
this.deactivate(id);
|
|
129
|
-
} else if (!wasActive && isActive) {
|
|
130
|
-
this.activate(updated);
|
|
131
|
-
} else if (wasActive && isActive) {
|
|
132
|
-
// Re-activate with new settings
|
|
133
|
-
this.deactivate(id);
|
|
134
|
-
this.activate(updated);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
logger.info('Updated behavior', { id, updates: Object.keys(updates) });
|
|
138
|
-
return updated;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async executeNow(id: string): Promise<{ success: boolean; error?: string }> {
|
|
142
|
-
const behavior = await this.store.get(id);
|
|
143
|
-
if (!behavior) {
|
|
144
|
-
throw new Error(`Behavior ${id} not found`);
|
|
145
|
-
}
|
|
146
|
-
const result = await this.executor.execute(behavior);
|
|
147
|
-
return { success: result.success, error: result.error };
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async remove(id: string): Promise<boolean> {
|
|
151
|
-
this.deactivate(id);
|
|
152
|
-
const removed = await this.store.remove(id);
|
|
153
|
-
|
|
154
|
-
if (removed) {
|
|
155
|
-
this.auditFn('behavior.deleted', {
|
|
156
|
-
behaviorId: id,
|
|
157
|
-
});
|
|
158
|
-
logger.info('Removed behavior', { id });
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return removed;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private validate(input: CreateBehaviorInput): void {
|
|
165
|
-
if (input.type === 'scheduled') {
|
|
166
|
-
if (!input.schedule?.cron) {
|
|
167
|
-
throw new Error('Scheduled behaviors require a cron expression');
|
|
168
|
-
}
|
|
169
|
-
if (!Scheduler.isValidCron(input.schedule.cron)) {
|
|
170
|
-
throw new Error(`Invalid cron expression: ${input.schedule.cron}`);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (input.type === 'monitor') {
|
|
175
|
-
if (!input.polling?.intervalMs || !input.polling?.condition) {
|
|
176
|
-
throw new Error('Monitor behaviors require polling interval and condition');
|
|
177
|
-
}
|
|
178
|
-
if (input.polling.intervalMs < BEHAVIOR_DEFAULTS.minPollingIntervalMs) {
|
|
179
|
-
throw new Error(
|
|
180
|
-
`Polling interval must be at least ${BEHAVIOR_DEFAULTS.minPollingIntervalMs}ms (${BEHAVIOR_DEFAULTS.minPollingIntervalMs / 1000}s)`
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (input.type === 'one-shot') {
|
|
186
|
-
if (!input.delay?.fireAt) {
|
|
187
|
-
throw new Error('One-shot behaviors require a fireAt timestamp');
|
|
188
|
-
}
|
|
189
|
-
const fireAt = new Date(input.delay.fireAt);
|
|
190
|
-
if (fireAt.getTime() <= Date.now()) {
|
|
191
|
-
throw new Error('One-shot fireAt must be in the future');
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
private activate(behavior: Behavior): void {
|
|
197
|
-
switch (behavior.type) {
|
|
198
|
-
case 'scheduled':
|
|
199
|
-
if (behavior.schedule) {
|
|
200
|
-
this.scheduler.schedule(
|
|
201
|
-
behavior.id,
|
|
202
|
-
behavior.schedule.cron,
|
|
203
|
-
() => this.enqueueExecution(behavior.id),
|
|
204
|
-
behavior.schedule.timezone
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
break;
|
|
208
|
-
|
|
209
|
-
case 'monitor':
|
|
210
|
-
if (behavior.polling) {
|
|
211
|
-
this.monitor.start(
|
|
212
|
-
behavior.id,
|
|
213
|
-
behavior.polling.intervalMs,
|
|
214
|
-
() => this.enqueueExecution(behavior.id)
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
break;
|
|
218
|
-
|
|
219
|
-
case 'one-shot':
|
|
220
|
-
if (behavior.delay) {
|
|
221
|
-
const delayMs = new Date(behavior.delay.fireAt).getTime() - Date.now();
|
|
222
|
-
if (delayMs > 0) {
|
|
223
|
-
const timer = setTimeout(() => {
|
|
224
|
-
this.oneshotTimers.delete(behavior.id);
|
|
225
|
-
this.enqueueExecution(behavior.id);
|
|
226
|
-
}, delayMs);
|
|
227
|
-
this.oneshotTimers.set(behavior.id, timer);
|
|
228
|
-
} else {
|
|
229
|
-
// Missed one-shot
|
|
230
|
-
this.store.update(behavior.id, { status: 'missed' });
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
private deactivate(id: string): void {
|
|
238
|
-
this.scheduler.stop(id);
|
|
239
|
-
this.monitor.stop(id);
|
|
240
|
-
const timer = this.oneshotTimers.get(id);
|
|
241
|
-
if (timer) {
|
|
242
|
-
clearTimeout(timer);
|
|
243
|
-
this.oneshotTimers.delete(id);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
private enqueueExecution(behaviorId: string): void {
|
|
248
|
-
this.executionQueue = this.executionQueue.then(async () => {
|
|
249
|
-
await this.executeWithRetry(behaviorId);
|
|
250
|
-
}).catch((error) => {
|
|
251
|
-
logger.error('Execution queue error', { behaviorId, error: error instanceof Error ? error : new Error(String(error)) });
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
private async executeWithRetry(behaviorId: string): Promise<void> {
|
|
256
|
-
const behavior = await this.store.get(behaviorId);
|
|
257
|
-
if (!behavior || behavior.status !== 'active') return;
|
|
258
|
-
|
|
259
|
-
let result = await this.executor.execute(behavior);
|
|
260
|
-
|
|
261
|
-
// Retry once on transient failure
|
|
262
|
-
if (!result.success) {
|
|
263
|
-
logger.info('Retrying behavior execution', { id: behaviorId });
|
|
264
|
-
await new Promise((resolve) => setTimeout(resolve, BEHAVIOR_DEFAULTS.retryDelayMs));
|
|
265
|
-
result = await this.executor.execute(behavior);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Update behavior state
|
|
269
|
-
const updates: Partial<Behavior> = {
|
|
270
|
-
lastRun: new Date().toISOString(),
|
|
271
|
-
lastResult: result.success ? result.result?.slice(0, 500) : result.error,
|
|
272
|
-
runCount: behavior.runCount + 1,
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
if (result.success) {
|
|
276
|
-
updates.failCount = 0;
|
|
277
|
-
|
|
278
|
-
// Auto-remove completed one-shots
|
|
279
|
-
if (behavior.type === 'one-shot') {
|
|
280
|
-
updates.status = 'deleted';
|
|
281
|
-
this.deactivate(behaviorId);
|
|
282
|
-
}
|
|
283
|
-
} else {
|
|
284
|
-
updates.failCount = behavior.failCount + 1;
|
|
285
|
-
|
|
286
|
-
// Auto-pause on repeated failures
|
|
287
|
-
if (updates.failCount >= behavior.maxFailures) {
|
|
288
|
-
updates.status = 'paused';
|
|
289
|
-
this.deactivate(behaviorId);
|
|
290
|
-
logger.warn('Auto-paused behavior due to repeated failures', {
|
|
291
|
-
id: behaviorId,
|
|
292
|
-
failCount: updates.failCount,
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
await this.store.update(behaviorId, updates);
|
|
298
|
-
|
|
299
|
-
this.auditFn('behavior.executed', {
|
|
300
|
-
behaviorId,
|
|
301
|
-
success: result.success,
|
|
302
|
-
error: result.error,
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
}
|
package/src/executor.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { getLogger } from '@auxiora/logger';
|
|
2
|
-
import type { Behavior, BehaviorExecution } from './types.js';
|
|
3
|
-
|
|
4
|
-
const logger = getLogger('behaviors:executor');
|
|
5
|
-
|
|
6
|
-
export interface ExecutorDeps {
|
|
7
|
-
getProvider: () => {
|
|
8
|
-
name: string;
|
|
9
|
-
complete: (messages: Array<{ role: string; content: string }>, options?: any) => Promise<{
|
|
10
|
-
content: string;
|
|
11
|
-
usage: { inputTokens: number; outputTokens: number };
|
|
12
|
-
model: string;
|
|
13
|
-
finishReason: string;
|
|
14
|
-
}>;
|
|
15
|
-
};
|
|
16
|
-
sendToChannel: (
|
|
17
|
-
channelType: string,
|
|
18
|
-
channelId: string,
|
|
19
|
-
message: { content: string }
|
|
20
|
-
) => Promise<{ success: boolean; error?: string }>;
|
|
21
|
-
getSystemPrompt: () => string;
|
|
22
|
-
executeWithTools?: (
|
|
23
|
-
messages: Array<{ role: string; content: string }>,
|
|
24
|
-
systemPrompt: string,
|
|
25
|
-
) => Promise<{ content: string; usage: { inputTokens: number; outputTokens: number } }>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export class BehaviorExecutor {
|
|
29
|
-
private deps: ExecutorDeps;
|
|
30
|
-
|
|
31
|
-
constructor(deps: ExecutorDeps) {
|
|
32
|
-
this.deps = deps;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async execute(behavior: Behavior): Promise<BehaviorExecution> {
|
|
36
|
-
const startedAt = new Date().toISOString();
|
|
37
|
-
logger.info('Executing behavior', { id: behavior.id, type: behavior.type, action: behavior.action });
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
const provider = this.deps.getProvider();
|
|
41
|
-
const messages = this.buildMessages(behavior);
|
|
42
|
-
const systemPrompt = this.buildSystemPrompt(behavior);
|
|
43
|
-
|
|
44
|
-
const result = await provider.complete(messages, { systemPrompt });
|
|
45
|
-
const content = result.content;
|
|
46
|
-
|
|
47
|
-
logger.debug('Behavior AI response received', {
|
|
48
|
-
id: behavior.id,
|
|
49
|
-
tokens: result.usage,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// Deliver to channel
|
|
53
|
-
const label = this.getLabel(behavior);
|
|
54
|
-
const formattedContent = label + '\n' + content;
|
|
55
|
-
|
|
56
|
-
const sendResult = await this.deps.sendToChannel(
|
|
57
|
-
behavior.channel.type,
|
|
58
|
-
behavior.channel.id,
|
|
59
|
-
{ content: formattedContent }
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
if (!sendResult.success) {
|
|
63
|
-
logger.warn('Failed to deliver behavior result', {
|
|
64
|
-
id: behavior.id,
|
|
65
|
-
channelType: behavior.channel.type,
|
|
66
|
-
error: sendResult.error ? new Error(sendResult.error) : undefined,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
behaviorId: behavior.id,
|
|
71
|
-
startedAt,
|
|
72
|
-
completedAt: new Date().toISOString(),
|
|
73
|
-
success: false,
|
|
74
|
-
error: 'Delivery failed: ' + sendResult.error,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
logger.info('Behavior executed successfully', { id: behavior.id });
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
behaviorId: behavior.id,
|
|
82
|
-
startedAt,
|
|
83
|
-
completedAt: new Date().toISOString(),
|
|
84
|
-
success: true,
|
|
85
|
-
result: content,
|
|
86
|
-
};
|
|
87
|
-
} catch (error) {
|
|
88
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
89
|
-
logger.error('Behavior execution failed', { id: behavior.id, error: new Error(errorMessage) });
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
behaviorId: behavior.id,
|
|
93
|
-
startedAt,
|
|
94
|
-
completedAt: new Date().toISOString(),
|
|
95
|
-
success: false,
|
|
96
|
-
error: errorMessage,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
private buildMessages(behavior: Behavior): Array<{ role: string; content: string }> {
|
|
102
|
-
if (behavior.type === 'monitor' && behavior.polling?.condition) {
|
|
103
|
-
return [
|
|
104
|
-
{
|
|
105
|
-
role: 'user',
|
|
106
|
-
content: behavior.action + '\n\nIMPORTANT: Only provide a result if this condition is met: ' + behavior.polling.condition + '\nIf the condition is NOT met, respond with exactly: [CONDITION_NOT_MET]',
|
|
107
|
-
},
|
|
108
|
-
];
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return [{ role: 'user', content: behavior.action }];
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private buildSystemPrompt(behavior: Behavior): string {
|
|
115
|
-
const base = this.deps.getSystemPrompt();
|
|
116
|
-
const context = '\n\n---\nThis is an automated proactive behavior execution. Behavior ID: ' + behavior.id + '. Be concise and direct in your response.';
|
|
117
|
-
return base + context;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private getLabel(behavior: Behavior): string {
|
|
121
|
-
switch (behavior.type) {
|
|
122
|
-
case 'scheduled':
|
|
123
|
-
return '**[Scheduled]** _' + behavior.action.slice(0, 50) + '_';
|
|
124
|
-
case 'monitor':
|
|
125
|
-
return '**[Monitor Alert]** _' + (behavior.polling?.condition || behavior.action.slice(0, 50)) + '_';
|
|
126
|
-
case 'one-shot':
|
|
127
|
-
return '**[Reminder]**';
|
|
128
|
-
default:
|
|
129
|
-
return '**[Behavior]**';
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
Behavior,
|
|
3
|
-
BehaviorType,
|
|
4
|
-
BehaviorStatus,
|
|
5
|
-
BehaviorSchedule,
|
|
6
|
-
BehaviorPolling,
|
|
7
|
-
BehaviorDelay,
|
|
8
|
-
BehaviorChannel,
|
|
9
|
-
BehaviorExecution,
|
|
10
|
-
} from './types.js';
|
|
11
|
-
export { BEHAVIOR_DEFAULTS } from './types.js';
|
|
12
|
-
export { BehaviorStore } from './store.js';
|
|
13
|
-
export { Scheduler } from './scheduler.js';
|
|
14
|
-
export { MonitorEngine } from './monitor.js';
|
|
15
|
-
export { BehaviorExecutor, type ExecutorDeps } from './executor.js';
|
|
16
|
-
export { BehaviorManager, type CreateBehaviorInput, type BehaviorManagerOptions } from './behavior-manager.js';
|
package/src/monitor.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { getLogger } from '@auxiora/logger';
|
|
2
|
-
|
|
3
|
-
const logger = getLogger('behaviors:monitor');
|
|
4
|
-
|
|
5
|
-
export class MonitorEngine {
|
|
6
|
-
private timers = new Map<string, ReturnType<typeof setInterval>>();
|
|
7
|
-
|
|
8
|
-
start(id: string, intervalMs: number, callback: () => void): void {
|
|
9
|
-
// Stop existing monitor with same ID
|
|
10
|
-
this.stop(id);
|
|
11
|
-
|
|
12
|
-
const timer = setInterval(() => {
|
|
13
|
-
logger.debug('Monitor poll fired', { id, intervalMs });
|
|
14
|
-
callback();
|
|
15
|
-
}, intervalMs);
|
|
16
|
-
|
|
17
|
-
this.timers.set(id, timer);
|
|
18
|
-
logger.info('Started monitor', { id, intervalMs });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
stop(id: string): void {
|
|
22
|
-
const timer = this.timers.get(id);
|
|
23
|
-
if (timer) {
|
|
24
|
-
clearInterval(timer);
|
|
25
|
-
this.timers.delete(id);
|
|
26
|
-
logger.debug('Stopped monitor', { id });
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
stopAll(): void {
|
|
31
|
-
for (const [id, timer] of this.timers) {
|
|
32
|
-
clearInterval(timer);
|
|
33
|
-
logger.debug('Stopped monitor', { id });
|
|
34
|
-
}
|
|
35
|
-
this.timers.clear();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
isRunning(id: string): boolean {
|
|
39
|
-
return this.timers.has(id);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
listRunning(): string[] {
|
|
43
|
-
return Array.from(this.timers.keys());
|
|
44
|
-
}
|
|
45
|
-
}
|
package/src/scheduler.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import cron from 'node-cron';
|
|
2
|
-
import { getLogger } from '@auxiora/logger';
|
|
3
|
-
|
|
4
|
-
const logger = getLogger('behaviors:scheduler');
|
|
5
|
-
|
|
6
|
-
export class Scheduler {
|
|
7
|
-
private jobs = new Map<string, cron.ScheduledTask>();
|
|
8
|
-
|
|
9
|
-
schedule(id: string, cronExpression: string, callback: () => void, timezone?: string): void {
|
|
10
|
-
// Stop existing job with same ID
|
|
11
|
-
this.stop(id);
|
|
12
|
-
|
|
13
|
-
const options: cron.ScheduleOptions = {
|
|
14
|
-
scheduled: true,
|
|
15
|
-
timezone: timezone || undefined,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const task = cron.schedule(cronExpression, () => {
|
|
19
|
-
logger.debug('Cron job fired', { id, cron: cronExpression });
|
|
20
|
-
callback();
|
|
21
|
-
}, options);
|
|
22
|
-
|
|
23
|
-
this.jobs.set(id, task);
|
|
24
|
-
logger.info('Scheduled cron job', { id, cron: cronExpression, timezone });
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
stop(id: string): void {
|
|
28
|
-
const task = this.jobs.get(id);
|
|
29
|
-
if (task) {
|
|
30
|
-
task.stop();
|
|
31
|
-
this.jobs.delete(id);
|
|
32
|
-
logger.debug('Stopped cron job', { id });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
stopAll(): void {
|
|
37
|
-
for (const [id, task] of this.jobs) {
|
|
38
|
-
task.stop();
|
|
39
|
-
logger.debug('Stopped cron job', { id });
|
|
40
|
-
}
|
|
41
|
-
this.jobs.clear();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
isScheduled(id: string): boolean {
|
|
45
|
-
return this.jobs.has(id);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
listScheduled(): string[] {
|
|
49
|
-
return Array.from(this.jobs.keys());
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
static isValidCron(expression: string): boolean {
|
|
53
|
-
return cron.validate(expression);
|
|
54
|
-
}
|
|
55
|
-
}
|