agent-working-memory 0.6.0 → 0.6.1
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 +15 -9
- package/dist/adapters/claude-code.d.ts +4 -0
- package/dist/adapters/claude-code.d.ts.map +1 -0
- package/dist/adapters/claude-code.js +218 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +4 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +226 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/common.d.ts +34 -0
- package/dist/adapters/common.d.ts.map +1 -0
- package/dist/adapters/common.js +145 -0
- package/dist/adapters/common.js.map +1 -0
- package/dist/adapters/cursor.d.ts +4 -0
- package/dist/adapters/cursor.d.ts.map +1 -0
- package/dist/adapters/cursor.js +138 -0
- package/dist/adapters/cursor.js.map +1 -0
- package/dist/adapters/http.d.ts +4 -0
- package/dist/adapters/http.d.ts.map +1 -0
- package/dist/adapters/http.js +88 -0
- package/dist/adapters/http.js.map +1 -0
- package/dist/adapters/index.d.ts +7 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +21 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/types.d.ts +65 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +4 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/cli.js +104 -230
- package/dist/cli.js.map +1 -1
- package/dist/coordination/events.d.ts +59 -0
- package/dist/coordination/events.d.ts.map +1 -0
- package/dist/coordination/events.js +28 -0
- package/dist/coordination/events.js.map +1 -0
- package/dist/coordination/index.d.ts +10 -1
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +87 -3
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/peer-decisions.d.ts +40 -0
- package/dist/coordination/peer-decisions.d.ts.map +1 -0
- package/dist/coordination/peer-decisions.js +82 -0
- package/dist/coordination/peer-decisions.js.map +1 -0
- package/dist/coordination/plugin-loader.d.ts +18 -0
- package/dist/coordination/plugin-loader.d.ts.map +1 -0
- package/dist/coordination/plugin-loader.js +55 -0
- package/dist/coordination/plugin-loader.js.map +1 -0
- package/dist/coordination/plugin.d.ts +40 -0
- package/dist/coordination/plugin.d.ts.map +1 -0
- package/dist/coordination/plugin.js +22 -0
- package/dist/coordination/plugin.js.map +1 -0
- package/dist/coordination/routes.d.ts +2 -1
- package/dist/coordination/routes.d.ts.map +1 -1
- package/dist/coordination/routes.js +899 -76
- package/dist/coordination/routes.js.map +1 -1
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +72 -14
- package/dist/coordination/schema.js.map +1 -1
- package/dist/coordination/schemas.d.ts +84 -3
- package/dist/coordination/schemas.d.ts.map +1 -1
- package/dist/coordination/schemas.js +71 -1
- package/dist/coordination/schemas.js.map +1 -1
- package/dist/coordination/stale.d.ts.map +1 -1
- package/dist/coordination/stale.js +2 -1
- package/dist/coordination/stale.js.map +1 -1
- package/dist/coordination/types.d.ts +252 -0
- package/dist/coordination/types.d.ts.map +1 -0
- package/dist/coordination/types.js +8 -0
- package/dist/coordination/types.js.map +1 -0
- package/dist/coordination/write-mutex.d.ts +26 -0
- package/dist/coordination/write-mutex.d.ts.map +1 -0
- package/dist/coordination/write-mutex.js +63 -0
- package/dist/coordination/write-mutex.js.map +1 -0
- package/dist/core/embeddings.d.ts +2 -0
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +4 -0
- package/dist/core/embeddings.js.map +1 -1
- package/dist/engine/activation.d.ts.map +1 -1
- package/dist/engine/activation.js +16 -3
- package/dist/engine/activation.js.map +1 -1
- package/dist/engine/consolidation.d.ts.map +1 -1
- package/dist/engine/consolidation.js +15 -6
- package/dist/engine/consolidation.js.map +1 -1
- package/dist/engine/retraction.d.ts +3 -1
- package/dist/engine/retraction.d.ts.map +1 -1
- package/dist/engine/retraction.js +19 -6
- package/dist/engine/retraction.js.map +1 -1
- package/dist/index.js +6 -18
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +52 -3
- package/dist/mcp.js.map +1 -1
- package/dist/storage/sqlite.d.ts +6 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +39 -3
- package/dist/storage/sqlite.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/claude-code.ts +234 -0
- package/src/adapters/codex.ts +262 -0
- package/src/adapters/common.ts +172 -0
- package/src/adapters/cursor.ts +150 -0
- package/src/adapters/http.ts +100 -0
- package/src/adapters/index.ts +31 -0
- package/src/adapters/types.ts +75 -0
- package/src/cli.ts +107 -238
- package/src/coordination/events.ts +90 -0
- package/src/coordination/index.ts +102 -3
- package/src/coordination/peer-decisions.ts +105 -0
- package/src/coordination/plugin-loader.ts +60 -0
- package/src/coordination/plugin.ts +44 -0
- package/src/coordination/routes.ts +1176 -105
- package/src/coordination/schema.ts +67 -14
- package/src/coordination/schemas.ts +85 -1
- package/src/coordination/stale.ts +3 -2
- package/src/coordination/types.ts +311 -0
- package/src/coordination/write-mutex.ts +69 -0
- package/src/core/embeddings.ts +5 -0
- package/src/engine/activation.ts +13 -3
- package/src/engine/consolidation.ts +15 -6
- package/src/engine/retraction.ts +22 -6
- package/src/index.ts +6 -15
- package/src/mcp.ts +73 -9
- package/src/storage/sqlite.ts +39 -3
|
@@ -7,20 +7,61 @@
|
|
|
7
7
|
import { ZodError } from 'zod';
|
|
8
8
|
import { initCoordinationTables } from './schema.js';
|
|
9
9
|
import { registerCoordinationRoutes } from './routes.js';
|
|
10
|
-
import { cleanSlate } from './stale.js';
|
|
10
|
+
import { cleanSlate, pruneOldHeartbeats, purgeDeadAgents } from './stale.js';
|
|
11
|
+
import { createWriteMutex, needsWriteLock } from './write-mutex.js';
|
|
12
|
+
import { createEventBus } from './events.js';
|
|
13
|
+
import { loadPlugins, teardownPlugins } from './plugin-loader.js';
|
|
14
|
+
/** Active cleanup intervals — cleared on shutdown. */
|
|
15
|
+
const cleanupIntervals = [];
|
|
16
|
+
/** Singleton event bus for this coordination module instance. */
|
|
17
|
+
let coordinationEventBus = null;
|
|
18
|
+
/** Get the coordination event bus (available after initCoordination). */
|
|
19
|
+
export function getEventBus() {
|
|
20
|
+
return coordinationEventBus;
|
|
21
|
+
}
|
|
11
22
|
/** Check if coordination is enabled via environment variable. */
|
|
12
23
|
export function isCoordinationEnabled() {
|
|
13
24
|
const val = process.env.AWM_COORDINATION;
|
|
14
25
|
return val === 'true' || val === '1';
|
|
15
26
|
}
|
|
16
27
|
/** Initialize the coordination module: create tables, clean slate, mount routes, error handler. */
|
|
17
|
-
export function initCoordination(app, db) {
|
|
28
|
+
export function initCoordination(app, db, store) {
|
|
18
29
|
// Create coordination tables (idempotent)
|
|
19
30
|
initCoordinationTables(db);
|
|
20
31
|
// Clean slate: mark stale agents as dead from previous sessions
|
|
21
32
|
cleanSlate(db);
|
|
33
|
+
// CORS — allow localhost origins only (coordination is local-only)
|
|
34
|
+
app.addHook('onRequest', async (request, reply) => {
|
|
35
|
+
const origin = request.headers.origin ?? '';
|
|
36
|
+
if (/^https?:\/\/localhost(:\d+)?$/.test(origin) || /^https?:\/\/127\.0\.0\.1(:\d+)?$/.test(origin)) {
|
|
37
|
+
reply.header('Access-Control-Allow-Origin', origin);
|
|
38
|
+
reply.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, DELETE, OPTIONS');
|
|
39
|
+
reply.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
40
|
+
}
|
|
41
|
+
if (request.method === 'OPTIONS') {
|
|
42
|
+
return reply.code(204).send();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
// Body size limit — 256KB max for coordination requests (tasks with context can be large)
|
|
46
|
+
app.addHook('onRoute', (routeOptions) => {
|
|
47
|
+
if (!routeOptions.bodyLimit) {
|
|
48
|
+
routeOptions.bodyLimit = 256_000;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// Write serialization: serialize POST/PATCH/PUT/DELETE through a mutex
|
|
52
|
+
// to prevent SQLITE_BUSY under 5+ concurrent worker burst
|
|
53
|
+
const writeMutex = createWriteMutex();
|
|
54
|
+
app.addHook('preHandler', async (request, reply) => {
|
|
55
|
+
if (needsWriteLock(request.method, request.url)) {
|
|
56
|
+
const release = await writeMutex.acquire();
|
|
57
|
+
// Release after response is sent (onResponse fires after reply)
|
|
58
|
+
reply.raw.on('finish', release);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// Create event bus for decoupled side-effects
|
|
62
|
+
coordinationEventBus = createEventBus();
|
|
22
63
|
// Mount all coordination HTTP routes
|
|
23
|
-
registerCoordinationRoutes(app, db);
|
|
64
|
+
registerCoordinationRoutes(app, db, store, coordinationEventBus);
|
|
24
65
|
// ZodError handler — coordination routes use .parse() which throws on invalid params
|
|
25
66
|
app.setErrorHandler((error, _request, reply) => {
|
|
26
67
|
if (error instanceof ZodError) {
|
|
@@ -34,6 +75,49 @@ export function initCoordination(app, db) {
|
|
|
34
75
|
error: { code: 'INTERNAL_ERROR', message: error.message },
|
|
35
76
|
});
|
|
36
77
|
});
|
|
78
|
+
// Periodic cleanup: prune heartbeat events every 30 min, purge dead agents every hour
|
|
79
|
+
cleanupIntervals.push(setInterval(() => {
|
|
80
|
+
try {
|
|
81
|
+
pruneOldHeartbeats(db);
|
|
82
|
+
}
|
|
83
|
+
catch { /* db may be closed */ }
|
|
84
|
+
}, 30 * 60 * 1000), setInterval(() => {
|
|
85
|
+
try {
|
|
86
|
+
purgeDeadAgents(db, 24);
|
|
87
|
+
}
|
|
88
|
+
catch { /* db may be closed */ }
|
|
89
|
+
}, 60 * 60 * 1000));
|
|
90
|
+
// Periodic channel liveness probe every 60s — mark unreachable sessions as disconnected
|
|
91
|
+
cleanupIntervals.push(setInterval(async () => {
|
|
92
|
+
try {
|
|
93
|
+
const sessions = db.prepare(`SELECT agent_id, channel_id FROM coord_channel_sessions WHERE status = 'connected'`).all();
|
|
94
|
+
for (const session of sessions) {
|
|
95
|
+
try {
|
|
96
|
+
const res = await fetch(`${session.channel_id}/health`, {
|
|
97
|
+
signal: AbortSignal.timeout(3000),
|
|
98
|
+
});
|
|
99
|
+
if (!res.ok) {
|
|
100
|
+
db.prepare(`UPDATE coord_channel_sessions SET status = 'disconnected' WHERE agent_id = ?`).run(session.agent_id);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
db.prepare(`UPDATE coord_channel_sessions SET status = 'disconnected' WHERE agent_id = ?`).run(session.agent_id);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch { /* db may be closed */ }
|
|
109
|
+
}, 60_000));
|
|
110
|
+
// Load plugins (async — fire and forget, errors logged per-plugin)
|
|
111
|
+
loadPlugins({ events: coordinationEventBus, db, fastify: app }).catch((err) => {
|
|
112
|
+
console.error(' [plugin] Plugin loader error:', err.message);
|
|
113
|
+
});
|
|
37
114
|
console.log(' Coordination module enabled');
|
|
38
115
|
}
|
|
116
|
+
/** Stop periodic cleanup intervals and teardown plugins. Call on server shutdown. */
|
|
117
|
+
export async function stopCoordinationCleanup() {
|
|
118
|
+
for (const id of cleanupIntervals)
|
|
119
|
+
clearInterval(id);
|
|
120
|
+
cleanupIntervals.length = 0;
|
|
121
|
+
await teardownPlugins();
|
|
122
|
+
}
|
|
39
123
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/coordination/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/coordination/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Peer-decision injection for memory_recall.
|
|
3
|
+
*
|
|
4
|
+
* When coordination is enabled, memory_recall appends recent decisions
|
|
5
|
+
* made by OTHER agents that are relevant to the current recall query.
|
|
6
|
+
* This enables passive cross-agent knowledge sharing without explicit
|
|
7
|
+
* communication.
|
|
8
|
+
*/
|
|
9
|
+
import type Database from 'better-sqlite3';
|
|
10
|
+
export interface PeerDecision {
|
|
11
|
+
id: number;
|
|
12
|
+
author_name: string;
|
|
13
|
+
assignment_id: string | null;
|
|
14
|
+
tags: string | null;
|
|
15
|
+
summary: string;
|
|
16
|
+
created_at: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Extract significant keywords from a recall query for relevance matching.
|
|
20
|
+
* Returns up to maxKeywords words of length >= 4 that are not stop words.
|
|
21
|
+
*/
|
|
22
|
+
export declare function extractKeywords(query: string, maxKeywords?: number): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Query coord_decisions for recent decisions by agents OTHER than the current one
|
|
25
|
+
* that are relevant to the given query string.
|
|
26
|
+
*
|
|
27
|
+
* @param db The shared coordination database handle.
|
|
28
|
+
* @param selfName The current agent's name (AWM_AGENT_ID / WORKER_NAME). Excluded from results.
|
|
29
|
+
* @param query The recall query text used for keyword relevance matching.
|
|
30
|
+
* @param windowHours How far back to look (default 1 hour).
|
|
31
|
+
* @param limit Maximum number of decisions to return (default 5).
|
|
32
|
+
* @returns Array of peer decisions, ordered newest-first. Empty array on any error.
|
|
33
|
+
*/
|
|
34
|
+
export declare function queryPeerDecisions(db: Database.Database, selfName: string, query: string, windowHours?: number, limit?: number): PeerDecision[];
|
|
35
|
+
/**
|
|
36
|
+
* Format peer decisions as a text section to append to memory_recall output.
|
|
37
|
+
* Returns an empty string when there are no peer decisions.
|
|
38
|
+
*/
|
|
39
|
+
export declare function formatPeerDecisions(decisions: PeerDecision[], windowHours?: number): string;
|
|
40
|
+
//# sourceMappingURL=peer-decisions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-decisions.d.ts","sourceRoot":"","sources":["../../src/coordination/peer-decisions.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAWD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,SAAI,GAAG,MAAM,EAAE,CAOxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,WAAW,SAAI,EACf,KAAK,SAAI,GACR,YAAY,EAAE,CAgChB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,YAAY,EAAE,EAAE,WAAW,SAAI,GAAG,MAAM,CAKtF"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Peer-decision injection for memory_recall.
|
|
5
|
+
*
|
|
6
|
+
* When coordination is enabled, memory_recall appends recent decisions
|
|
7
|
+
* made by OTHER agents that are relevant to the current recall query.
|
|
8
|
+
* This enables passive cross-agent knowledge sharing without explicit
|
|
9
|
+
* communication.
|
|
10
|
+
*/
|
|
11
|
+
/** Stop words filtered out before keyword matching. */
|
|
12
|
+
const STOP_WORDS = new Set([
|
|
13
|
+
'that', 'this', 'with', 'from', 'have', 'been', 'will', 'when', 'what',
|
|
14
|
+
'which', 'then', 'than', 'into', 'over', 'after', 'some', 'more', 'also',
|
|
15
|
+
'most', 'other', 'each', 'such', 'only', 'just', 'about', 'there', 'their',
|
|
16
|
+
'where', 'would', 'could', 'should', 'these', 'those', 'make', 'made',
|
|
17
|
+
'using', 'used', 'call', 'calls', 'does', 'done', 'were', 'they',
|
|
18
|
+
]);
|
|
19
|
+
/**
|
|
20
|
+
* Extract significant keywords from a recall query for relevance matching.
|
|
21
|
+
* Returns up to maxKeywords words of length >= 4 that are not stop words.
|
|
22
|
+
*/
|
|
23
|
+
export function extractKeywords(query, maxKeywords = 8) {
|
|
24
|
+
return query
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
27
|
+
.split(/\s+/)
|
|
28
|
+
.filter(w => w.length >= 4 && !STOP_WORDS.has(w))
|
|
29
|
+
.slice(0, maxKeywords);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Query coord_decisions for recent decisions by agents OTHER than the current one
|
|
33
|
+
* that are relevant to the given query string.
|
|
34
|
+
*
|
|
35
|
+
* @param db The shared coordination database handle.
|
|
36
|
+
* @param selfName The current agent's name (AWM_AGENT_ID / WORKER_NAME). Excluded from results.
|
|
37
|
+
* @param query The recall query text used for keyword relevance matching.
|
|
38
|
+
* @param windowHours How far back to look (default 1 hour).
|
|
39
|
+
* @param limit Maximum number of decisions to return (default 5).
|
|
40
|
+
* @returns Array of peer decisions, ordered newest-first. Empty array on any error.
|
|
41
|
+
*/
|
|
42
|
+
export function queryPeerDecisions(db, selfName, query, windowHours = 1, limit = 5) {
|
|
43
|
+
try {
|
|
44
|
+
const safeHours = Math.max(0.1, Math.min(windowHours, 168)); // 6min – 1 week
|
|
45
|
+
const safeLimit = Math.max(1, Math.min(limit, 50));
|
|
46
|
+
const keywords = extractKeywords(query);
|
|
47
|
+
const baseWhere = `
|
|
48
|
+
d.created_at >= datetime('now', '-${safeHours} hours')
|
|
49
|
+
AND a.name != ?
|
|
50
|
+
`;
|
|
51
|
+
const select = `
|
|
52
|
+
SELECT d.id, a.name AS author_name, d.assignment_id, d.tags, d.summary, d.created_at
|
|
53
|
+
FROM coord_decisions d
|
|
54
|
+
JOIN coord_agents a ON d.author_id = a.id
|
|
55
|
+
`;
|
|
56
|
+
if (keywords.length === 0) {
|
|
57
|
+
// No useful keywords — return the N most recent decisions from other agents
|
|
58
|
+
const sql = `${select} WHERE ${baseWhere} ORDER BY d.created_at DESC LIMIT ?`;
|
|
59
|
+
return db.prepare(sql).all(selfName, safeLimit);
|
|
60
|
+
}
|
|
61
|
+
// Build keyword filter: match any keyword in summary or tags
|
|
62
|
+
const kwClauses = keywords.map(() => `(d.summary LIKE ? OR d.tags LIKE ?)`).join(' OR ');
|
|
63
|
+
const sql = `${select} WHERE ${baseWhere} AND (${kwClauses}) ORDER BY d.created_at DESC LIMIT ?`;
|
|
64
|
+
const kwParams = keywords.flatMap(kw => [`%${kw}%`, `%${kw}%`]);
|
|
65
|
+
return db.prepare(sql).all(selfName, ...kwParams, safeLimit);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return []; // non-fatal — peer decisions are best-effort
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Format peer decisions as a text section to append to memory_recall output.
|
|
73
|
+
* Returns an empty string when there are no peer decisions.
|
|
74
|
+
*/
|
|
75
|
+
export function formatPeerDecisions(decisions, windowHours = 1) {
|
|
76
|
+
if (decisions.length === 0)
|
|
77
|
+
return '';
|
|
78
|
+
const label = windowHours === 1 ? '1h' : `${windowHours}h`;
|
|
79
|
+
const lines = decisions.map(d => `[${d.author_name}] ${d.summary}`);
|
|
80
|
+
return `\n--- Peer Decisions (last ${label}) ---\n${lines.join('\n')}`;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=peer-decisions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-decisions.js","sourceRoot":"","sources":["../../src/coordination/peer-decisions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin loader for AWM coordination.
|
|
3
|
+
*
|
|
4
|
+
* Reads AWM_PLUGINS env var (comma-separated module paths or package names),
|
|
5
|
+
* dynamically imports each, and calls register() with the plugin context.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* AWM_PLUGINS=./plugins/slack-notify.js,my-awm-plugin npm start
|
|
9
|
+
*/
|
|
10
|
+
import type { AWMPluginContext } from './plugin.js';
|
|
11
|
+
/**
|
|
12
|
+
* Load and register all plugins specified in AWM_PLUGINS env var.
|
|
13
|
+
* Errors in individual plugins are logged but don't prevent other plugins from loading.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadPlugins(ctx: AWMPluginContext): Promise<void>;
|
|
16
|
+
/** Teardown all loaded plugins (call on shutdown). */
|
|
17
|
+
export declare function teardownPlugins(): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=plugin-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../../src/coordination/plugin-loader.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAa,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK/D;;;GAGG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BtE;AAED,sDAAsD;AACtD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CASrD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Plugin loader for AWM coordination.
|
|
5
|
+
*
|
|
6
|
+
* Reads AWM_PLUGINS env var (comma-separated module paths or package names),
|
|
7
|
+
* dynamically imports each, and calls register() with the plugin context.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* AWM_PLUGINS=./plugins/slack-notify.js,my-awm-plugin npm start
|
|
11
|
+
*/
|
|
12
|
+
/** Loaded plugin instances (for teardown). */
|
|
13
|
+
const loadedPlugins = [];
|
|
14
|
+
/**
|
|
15
|
+
* Load and register all plugins specified in AWM_PLUGINS env var.
|
|
16
|
+
* Errors in individual plugins are logged but don't prevent other plugins from loading.
|
|
17
|
+
*/
|
|
18
|
+
export async function loadPlugins(ctx) {
|
|
19
|
+
const pluginList = process.env.AWM_PLUGINS;
|
|
20
|
+
if (!pluginList)
|
|
21
|
+
return;
|
|
22
|
+
const paths = pluginList
|
|
23
|
+
.split(',')
|
|
24
|
+
.map((p) => p.trim())
|
|
25
|
+
.filter(Boolean);
|
|
26
|
+
for (const modulePath of paths) {
|
|
27
|
+
try {
|
|
28
|
+
const mod = await import(modulePath);
|
|
29
|
+
const plugin = mod.default ?? mod;
|
|
30
|
+
if (!plugin.name || typeof plugin.register !== 'function') {
|
|
31
|
+
console.warn(` [plugin] Skipping ${modulePath}: missing name or register()`);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
await plugin.register(ctx);
|
|
35
|
+
loadedPlugins.push(plugin);
|
|
36
|
+
console.log(` [plugin] Loaded: ${plugin.name}`);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
console.error(` [plugin] Failed to load ${modulePath}:`, err.message);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Teardown all loaded plugins (call on shutdown). */
|
|
44
|
+
export async function teardownPlugins() {
|
|
45
|
+
for (const plugin of loadedPlugins) {
|
|
46
|
+
try {
|
|
47
|
+
await plugin.teardown?.();
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
console.error(` [plugin] Teardown error (${plugin.name}):`, err.message);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
loadedPlugins.length = 0;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=plugin-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/coordination/plugin-loader.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;GAQG;AAIH,8CAA8C;AAC9C,MAAM,aAAa,GAAgB,EAAE,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAqB;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAC3C,IAAI,CAAC,UAAU;QAAE,OAAO;IAExB,MAAM,KAAK,GAAG,UAAU;SACrB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnB,KAAK,MAAM,UAAU,IAAI,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,MAAM,GAAc,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC;YAE7C,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;gBAC1D,OAAO,CAAC,IAAI,CAAC,uBAAuB,UAAU,8BAA8B,CAAC,CAAC;gBAC9E,SAAS;YACX,CAAC;YAED,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC3B,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,6BAA6B,UAAU,GAAG,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;AACH,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,8BAA8B,MAAM,CAAC,IAAI,IAAI,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IACD,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWM Plugin contract.
|
|
3
|
+
*
|
|
4
|
+
* Plugins extend coordination with custom behavior by subscribing to
|
|
5
|
+
* events, adding routes, or querying the DB. They are loaded at startup
|
|
6
|
+
* via AWM_PLUGINS env var (comma-separated module paths).
|
|
7
|
+
*
|
|
8
|
+
* Example plugin:
|
|
9
|
+
* import type { AWMPlugin } from 'agent-working-memory';
|
|
10
|
+
* export default {
|
|
11
|
+
* name: 'my-plugin',
|
|
12
|
+
* register(ctx) {
|
|
13
|
+
* ctx.events.on('assignment.completed', (evt) => {
|
|
14
|
+
* console.log(`Task done: ${evt.assignmentId}`);
|
|
15
|
+
* });
|
|
16
|
+
* },
|
|
17
|
+
* } satisfies AWMPlugin;
|
|
18
|
+
*/
|
|
19
|
+
import type { FastifyInstance } from 'fastify';
|
|
20
|
+
import type Database from 'better-sqlite3';
|
|
21
|
+
import type { CoordinationEventBus } from './events.js';
|
|
22
|
+
/** Context passed to plugin register(). */
|
|
23
|
+
export interface AWMPluginContext {
|
|
24
|
+
/** Typed event bus — subscribe to coordination events. */
|
|
25
|
+
events: CoordinationEventBus;
|
|
26
|
+
/** Raw better-sqlite3 database handle (coordination tables). */
|
|
27
|
+
db: Database.Database;
|
|
28
|
+
/** Fastify instance — add custom routes if needed. */
|
|
29
|
+
fastify: FastifyInstance;
|
|
30
|
+
}
|
|
31
|
+
/** Plugin contract. Every AWM plugin must export this shape. */
|
|
32
|
+
export interface AWMPlugin {
|
|
33
|
+
/** Unique plugin name (for logging and dedup). */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Called once at startup with the plugin context. */
|
|
36
|
+
register(ctx: AWMPluginContext): void | Promise<void>;
|
|
37
|
+
/** Optional cleanup on shutdown. */
|
|
38
|
+
teardown?(): void | Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/coordination/plugin.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,MAAM,EAAE,oBAAoB,CAAC;IAC7B,gEAAgE;IAChE,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACtB,sDAAsD;IACtD,OAAO,EAAE,eAAe,CAAC;CAC1B;AAED,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,QAAQ,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,oCAAoC;IACpC,QAAQ,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* AWM Plugin contract.
|
|
5
|
+
*
|
|
6
|
+
* Plugins extend coordination with custom behavior by subscribing to
|
|
7
|
+
* events, adding routes, or querying the DB. They are loaded at startup
|
|
8
|
+
* via AWM_PLUGINS env var (comma-separated module paths).
|
|
9
|
+
*
|
|
10
|
+
* Example plugin:
|
|
11
|
+
* import type { AWMPlugin } from 'agent-working-memory';
|
|
12
|
+
* export default {
|
|
13
|
+
* name: 'my-plugin',
|
|
14
|
+
* register(ctx) {
|
|
15
|
+
* ctx.events.on('assignment.completed', (evt) => {
|
|
16
|
+
* console.log(`Task done: ${evt.assignmentId}`);
|
|
17
|
+
* });
|
|
18
|
+
* },
|
|
19
|
+
* } satisfies AWMPlugin;
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/coordination/plugin.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -5,5 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { FastifyInstance } from 'fastify';
|
|
7
7
|
import type Database from 'better-sqlite3';
|
|
8
|
-
|
|
8
|
+
import type { EngramStore } from '../storage/sqlite.js';
|
|
9
|
+
export declare function registerCoordinationRoutes(app: FastifyInstance, db: Database.Database, store?: EngramStore, eventBus?: import('./events.js').CoordinationEventBus): void;
|
|
9
10
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/coordination/routes.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/coordination/routes.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAsCxD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,eAAe,EAAE,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,OAAO,aAAa,EAAE,oBAAoB,GAAG,IAAI,CA40DxK"}
|