agent-common 1.0.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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/dashboard.d.ts +29 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +71 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/domain/cleanup.d.ts +30 -0
- package/dist/domain/cleanup.d.ts.map +1 -0
- package/dist/domain/cleanup.js +54 -0
- package/dist/domain/cleanup.js.map +1 -0
- package/dist/domain/events.d.ts +13 -0
- package/dist/domain/events.d.ts.map +1 -0
- package/dist/domain/events.js +61 -0
- package/dist/domain/events.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/package-meta.d.ts +22 -0
- package/dist/package-meta.d.ts.map +1 -0
- package/dist/package-meta.js +48 -0
- package/dist/package-meta.js.map +1 -0
- package/dist/storage/database.d.ts +27 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +73 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/fts.d.ts +27 -0
- package/dist/storage/fts.d.ts.map +1 -0
- package/dist/storage/fts.js +57 -0
- package/dist/storage/fts.js.map +1 -0
- package/dist/transport/mcp.d.ts +16 -0
- package/dist/transport/mcp.d.ts.map +1 -0
- package/dist/transport/mcp.js +111 -0
- package/dist/transport/mcp.js.map +1 -0
- package/dist/transport/rest.d.ts +18 -0
- package/dist/transport/rest.d.ts.map +1 -0
- package/dist/transport/rest.js +185 -0
- package/dist/transport/rest.js.map +1 -0
- package/dist/transport/ws.d.ts +28 -0
- package/dist/transport/ws.d.ts.map +1 -0
- package/dist/transport/ws.js +143 -0
- package/dist/transport/ws.js.map +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +26 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.0.0] - 2026-04-07
|
|
4
|
+
|
|
5
|
+
Initial release of `agent-common`. Extracted shared scaffolding from `agent-comm`, `agent-tasks`, `agent-knowledge`, and `agent-discover`:
|
|
6
|
+
|
|
7
|
+
- `createDb` + migration runner (`storage/database.ts`)
|
|
8
|
+
- FTS5 helpers (`storage/fts.ts`)
|
|
9
|
+
- REST router builder (`transport/rest.ts`)
|
|
10
|
+
- WebSocket server with fingerprint-based delta polling (`transport/ws.ts`)
|
|
11
|
+
- MCP JSON-RPC dispatcher (`transport/mcp.ts`)
|
|
12
|
+
- `EventBus` (`domain/events.ts`)
|
|
13
|
+
- `CleanupService` base class (`domain/cleanup.ts`)
|
|
14
|
+
- `startDashboard` with port leader-election (`dashboard.ts`)
|
|
15
|
+
- `readPackageMeta` (`package-meta.ts`)
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MuK IT GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# agent-common
|
|
2
|
+
|
|
3
|
+
Shared foundation for `agent-*` MCP servers (`agent-comm`, `agent-tasks`, `agent-knowledge`, `agent-discover`).
|
|
4
|
+
|
|
5
|
+
## What it provides
|
|
6
|
+
|
|
7
|
+
- **storage** — better-sqlite3 wrapper with WAL pragmas, transaction helper, migration runner
|
|
8
|
+
- **transport/rest** — node:http router with `:param` matching, JSON helper, CORS preflight, body reader, static file serving
|
|
9
|
+
- **transport/ws** — WebSocket server with full-state-on-connect, DB-fingerprint polling for cross-process delta updates, ping/pong heartbeat, max-connection cap
|
|
10
|
+
- **transport/mcp** — JSON-RPC over stdio, tool dispatcher, `ToolDefinition` type
|
|
11
|
+
- **domain/events** — typed in-process EventBus with wildcard subscribers
|
|
12
|
+
- **domain/cleanup** — base `CleanupService` with retention timer, startup reset hook
|
|
13
|
+
- **dashboard** — auto-start with port leader-election (graceful skip if port in use)
|
|
14
|
+
- **package-meta** — runtime read of `name` + `version` from a consumer's `package.json`
|
|
15
|
+
- **fts** — FTS5 virtual table + trigger boilerplate, search helper with LIKE fallback
|
|
16
|
+
|
|
17
|
+
## Who uses it
|
|
18
|
+
|
|
19
|
+
Internal: the four `agent-*` MCP servers. The package is host-agnostic — no `~/.claude` paths or Claude-specific config baked in.
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
|
|
23
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Server } from 'http';
|
|
2
|
+
import type { IncomingMessage, ServerResponse } from 'http';
|
|
3
|
+
export interface DashboardServer {
|
|
4
|
+
httpServer: Server;
|
|
5
|
+
port: number;
|
|
6
|
+
close(): void;
|
|
7
|
+
}
|
|
8
|
+
export interface DashboardOptions {
|
|
9
|
+
port: number;
|
|
10
|
+
handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;
|
|
11
|
+
/** Optional callback after the HTTP server is listening, to attach a WebSocket. */
|
|
12
|
+
onListen?: (httpServer: Server) => {
|
|
13
|
+
close(): void;
|
|
14
|
+
} | void;
|
|
15
|
+
/** Banner string written to stderr on successful start. Defaults to dashboard URL. */
|
|
16
|
+
banner?: (port: number) => string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Start a dashboard HTTP server. Resolves to a `DashboardServer` on success.
|
|
20
|
+
* Rejects with an error whose `code === 'EADDRINUSE'` when the port is taken.
|
|
21
|
+
*/
|
|
22
|
+
export declare function startDashboard(opts: DashboardOptions): Promise<DashboardServer>;
|
|
23
|
+
/**
|
|
24
|
+
* Try to start a dashboard, but resolve to `null` (rather than rejecting) if the
|
|
25
|
+
* port is already taken. Use this from MCP entrypoints where multiple processes
|
|
26
|
+
* may race to bind the same port.
|
|
27
|
+
*/
|
|
28
|
+
export declare function tryStartDashboard(opts: DashboardOptions): Promise<DashboardServer | null>;
|
|
29
|
+
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AASA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,mFAAmF;IACnF,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK;QAAE,KAAK,IAAI,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5D,sFAAsF;IACtF,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CA4C/E;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAY/F"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// agent-kit — Dashboard auto-start
|
|
3
|
+
//
|
|
4
|
+
// Starts an HTTP+WebSocket server on a fixed port using leader-election:
|
|
5
|
+
// the first process to bind wins; subsequent processes get EADDRINUSE and
|
|
6
|
+
// gracefully skip (the existing dashboard is already serving). This lets
|
|
7
|
+
// every MCP client process call `startDashboard()` without coordination.
|
|
8
|
+
// =============================================================================
|
|
9
|
+
import { createServer } from 'http';
|
|
10
|
+
/**
|
|
11
|
+
* Start a dashboard HTTP server. Resolves to a `DashboardServer` on success.
|
|
12
|
+
* Rejects with an error whose `code === 'EADDRINUSE'` when the port is taken.
|
|
13
|
+
*/
|
|
14
|
+
export function startDashboard(opts) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const httpServer = createServer((req, res) => {
|
|
17
|
+
Promise.resolve(opts.handler(req, res)).catch((err) => {
|
|
18
|
+
process.stderr.write('[agent-kit] Dashboard handler error: ' +
|
|
19
|
+
(err instanceof Error ? err.message : String(err)) +
|
|
20
|
+
'\n');
|
|
21
|
+
if (!res.headersSent) {
|
|
22
|
+
res.writeHead(500);
|
|
23
|
+
res.end('Internal server error');
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
let attached;
|
|
28
|
+
httpServer.on('error', (err) => {
|
|
29
|
+
reject(err);
|
|
30
|
+
});
|
|
31
|
+
httpServer.listen(opts.port, () => {
|
|
32
|
+
try {
|
|
33
|
+
attached = opts.onListen?.(httpServer);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
process.stderr.write('[agent-kit] Dashboard onListen error: ' +
|
|
37
|
+
(err instanceof Error ? err.message : String(err)) +
|
|
38
|
+
'\n');
|
|
39
|
+
}
|
|
40
|
+
const banner = opts.banner ? opts.banner(opts.port) : `dashboard: http://localhost:${opts.port}`;
|
|
41
|
+
process.stderr.write(banner + '\n');
|
|
42
|
+
resolve({
|
|
43
|
+
httpServer,
|
|
44
|
+
port: opts.port,
|
|
45
|
+
close() {
|
|
46
|
+
if (attached)
|
|
47
|
+
attached.close();
|
|
48
|
+
httpServer.close();
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Try to start a dashboard, but resolve to `null` (rather than rejecting) if the
|
|
56
|
+
* port is already taken. Use this from MCP entrypoints where multiple processes
|
|
57
|
+
* may race to bind the same port.
|
|
58
|
+
*/
|
|
59
|
+
export async function tryStartDashboard(opts) {
|
|
60
|
+
try {
|
|
61
|
+
return await startDashboard(opts);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (err.code === 'EADDRINUSE') {
|
|
65
|
+
process.stderr.write(`[agent-kit] Dashboard port ${opts.port} in use — another instance is serving.\n`);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,mCAAmC;AACnC,EAAE;AACF,yEAAyE;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,yEAAyE;AACzE,gFAAgF;AAEhF,OAAO,EAAE,YAAY,EAAe,MAAM,MAAM,CAAC;AAkBjD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAsB;IACnD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC3C,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uCAAuC;oBACrC,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAClD,IAAI,CACP,CAAC;gBACF,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;oBACnB,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,QAAkC,CAAC;QAEvC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YACpD,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;YAChC,IAAI,CAAC;gBACH,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wCAAwC;oBACtC,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAClD,IAAI,CACP,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,+BAA+B,IAAI,CAAC,IAAI,EAAE,CAAC;YACjG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;YACpC,OAAO,CAAC;gBACN,UAAU;gBACV,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK;oBACH,IAAI,QAAQ;wBAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;oBAC/B,UAAU,CAAC,KAAK,EAAE,CAAC;gBACrB,CAAC;aACF,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAsB;IAC5D,IAAI,CAAC;QACH,OAAO,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,8BAA8B,IAAI,CAAC,IAAI,0CAA0C,CAClF,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Db } from '../storage/database.js';
|
|
2
|
+
export interface CleanupOptions {
|
|
3
|
+
/** Retention period in days for the consumer's main rows. Default: 7. */
|
|
4
|
+
retentionDays?: number;
|
|
5
|
+
/** Interval at which `run()` is invoked. Default: 1 hour. */
|
|
6
|
+
intervalMs?: number;
|
|
7
|
+
/** If true, calls `resetOnStartup()` and `run()` immediately on construction. */
|
|
8
|
+
autoStart?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare abstract class CleanupService<S extends Record<string, number> = Record<string, number>> {
|
|
11
|
+
protected readonly db: Db;
|
|
12
|
+
protected readonly retentionDays: number;
|
|
13
|
+
protected readonly intervalMs: number;
|
|
14
|
+
private timer;
|
|
15
|
+
constructor(db: Db, options?: CleanupOptions);
|
|
16
|
+
/**
|
|
17
|
+
* Override to delete stale rows. Called on startup, on the timer, and
|
|
18
|
+
* via the public `purgeAll()` entry point.
|
|
19
|
+
*/
|
|
20
|
+
abstract run(): S;
|
|
21
|
+
/**
|
|
22
|
+
* Override to fix up state on server start (e.g. mark agents offline).
|
|
23
|
+
* Default no-op.
|
|
24
|
+
*/
|
|
25
|
+
resetOnStartup(): void;
|
|
26
|
+
purgeAll(): S;
|
|
27
|
+
startTimer(): void;
|
|
28
|
+
stopTimer(): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/domain/cleanup.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,8BAAsB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAM1F,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE;IAL3B,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IACtC,OAAO,CAAC,KAAK,CAA+C;gBAGvC,EAAE,EAAE,EAAE,EACzB,OAAO,GAAE,cAAmB;IAW9B;;;OAGG;IACH,QAAQ,CAAC,GAAG,IAAI,CAAC;IAEjB;;;OAGG;IACH,cAAc,IAAI,IAAI;IAItB,QAAQ,IAAI,CAAC;IAIb,UAAU,IAAI,IAAI;IAiBlB,SAAS,IAAI,IAAI;CAMlB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// agent-kit — Cleanup service base
|
|
3
|
+
//
|
|
4
|
+
// Provides timer scheduling and a startup-reset hook. Consumers extend
|
|
5
|
+
// `CleanupService` and override `run()` to delete their own stale rows.
|
|
6
|
+
// =============================================================================
|
|
7
|
+
export class CleanupService {
|
|
8
|
+
db;
|
|
9
|
+
retentionDays;
|
|
10
|
+
intervalMs;
|
|
11
|
+
timer = null;
|
|
12
|
+
constructor(db, options = {}) {
|
|
13
|
+
this.db = db;
|
|
14
|
+
this.retentionDays = options.retentionDays ?? 7;
|
|
15
|
+
this.intervalMs = options.intervalMs ?? 60 * 60 * 1000;
|
|
16
|
+
if (options.autoStart !== false) {
|
|
17
|
+
this.resetOnStartup();
|
|
18
|
+
this.startTimer();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Override to fix up state on server start (e.g. mark agents offline).
|
|
23
|
+
* Default no-op.
|
|
24
|
+
*/
|
|
25
|
+
resetOnStartup() {
|
|
26
|
+
/* override in consumer */
|
|
27
|
+
}
|
|
28
|
+
purgeAll() {
|
|
29
|
+
return this.run();
|
|
30
|
+
}
|
|
31
|
+
startTimer() {
|
|
32
|
+
if (this.timer)
|
|
33
|
+
return;
|
|
34
|
+
this.run();
|
|
35
|
+
this.timer = setInterval(() => {
|
|
36
|
+
try {
|
|
37
|
+
this.run();
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
process.stderr.write('[agent-kit] Cleanup timer error: ' +
|
|
41
|
+
(err instanceof Error ? err.message : String(err)) +
|
|
42
|
+
'\n');
|
|
43
|
+
}
|
|
44
|
+
}, this.intervalMs);
|
|
45
|
+
this.timer.unref();
|
|
46
|
+
}
|
|
47
|
+
stopTimer() {
|
|
48
|
+
if (this.timer) {
|
|
49
|
+
clearInterval(this.timer);
|
|
50
|
+
this.timer = null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/domain/cleanup.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,mCAAmC;AACnC,EAAE;AACF,uEAAuE;AACvE,wEAAwE;AACxE,gFAAgF;AAahF,MAAM,OAAgB,cAAc;IAMb;IALF,aAAa,CAAS;IACtB,UAAU,CAAS;IAC9B,KAAK,GAA0C,IAAI,CAAC;IAE5D,YACqB,EAAM,EACzB,UAA0B,EAAE;QADT,OAAE,GAAF,EAAE,CAAI;QAGzB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAEvD,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;YAChC,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAQD;;;OAGG;IACH,cAAc;QACZ,0BAA0B;IAC5B,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO;QACvB,IAAI,CAAC,GAAG,EAAE,CAAC;QACX,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC;gBACH,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mCAAmC;oBACjC,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAClD,IAAI,CACP,CAAC;YACJ,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,SAAS;QACP,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface BusEvent<T extends string = string> {
|
|
2
|
+
type: T;
|
|
3
|
+
timestamp: string;
|
|
4
|
+
data: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export type EventHandler<T extends string = string> = (event: BusEvent<T>) => void;
|
|
7
|
+
export declare class EventBus<T extends string = string> {
|
|
8
|
+
private readonly listeners;
|
|
9
|
+
emit(type: T, data?: Record<string, unknown>): void;
|
|
10
|
+
on(type: T | '*', handler: EventHandler<T>): () => void;
|
|
11
|
+
removeAll(): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/domain/events.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACjD,IAAI,EAAE,CAAC,CAAC;IACR,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAEnF,qBAAa,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IAEtE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IA0CvD,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAYvD,SAAS,IAAI,IAAI;CAGlB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// agent-kit — Event bus
|
|
3
|
+
//
|
|
4
|
+
// In-process pub/sub with wildcard subscribers. Consumer-defined event types
|
|
5
|
+
// are passed as a generic parameter for type safety.
|
|
6
|
+
// =============================================================================
|
|
7
|
+
export class EventBus {
|
|
8
|
+
listeners = new Map();
|
|
9
|
+
emit(type, data = {}) {
|
|
10
|
+
const event = {
|
|
11
|
+
type,
|
|
12
|
+
timestamp: new Date().toISOString(),
|
|
13
|
+
data,
|
|
14
|
+
};
|
|
15
|
+
const specific = this.listeners.get(type);
|
|
16
|
+
if (specific) {
|
|
17
|
+
for (const handler of specific) {
|
|
18
|
+
try {
|
|
19
|
+
handler(event);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
process.stderr.write('[agent-kit] Event listener error (' +
|
|
23
|
+
type +
|
|
24
|
+
'): ' +
|
|
25
|
+
(err instanceof Error ? err.message : String(err)) +
|
|
26
|
+
'\n');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const wildcards = this.listeners.get('*');
|
|
31
|
+
if (wildcards) {
|
|
32
|
+
for (const handler of wildcards) {
|
|
33
|
+
try {
|
|
34
|
+
handler(event);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
process.stderr.write('[agent-kit] Wildcard listener error (' +
|
|
38
|
+
type +
|
|
39
|
+
'): ' +
|
|
40
|
+
(err instanceof Error ? err.message : String(err)) +
|
|
41
|
+
'\n');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
on(type, handler) {
|
|
47
|
+
let set = this.listeners.get(type);
|
|
48
|
+
if (!set) {
|
|
49
|
+
set = new Set();
|
|
50
|
+
this.listeners.set(type, set);
|
|
51
|
+
}
|
|
52
|
+
set.add(handler);
|
|
53
|
+
return () => {
|
|
54
|
+
set.delete(handler);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
removeAll() {
|
|
58
|
+
this.listeners.clear();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/domain/events.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,wBAAwB;AACxB,EAAE;AACF,6EAA6E;AAC7E,qDAAqD;AACrD,gFAAgF;AAUhF,MAAM,OAAO,QAAQ;IACF,SAAS,GAAG,IAAI,GAAG,EAAiC,CAAC;IAEtE,IAAI,CAAC,IAAO,EAAE,OAAgC,EAAE;QAC9C,MAAM,KAAK,GAAgB;YACzB,IAAI;YACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI;SACL,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,IAAI,CAAC;oBACH,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oCAAoC;wBAClC,IAAI;wBACJ,KAAK;wBACL,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;wBAClD,IAAI,CACP,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACH,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uCAAuC;wBACrC,IAAI;wBACJ,KAAK;wBACL,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;wBAClD,IAAI,CACP,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,EAAE,CAAC,IAAa,EAAE,OAAwB;QACxC,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjB,OAAO,GAAG,EAAE;YACV,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC,CAAC;IACJ,CAAC;IAED,SAAS;QACP,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './storage/database.js';
|
|
3
|
+
export * from './storage/fts.js';
|
|
4
|
+
export * from './transport/rest.js';
|
|
5
|
+
export * from './transport/ws.js';
|
|
6
|
+
export * from './transport/mcp.js';
|
|
7
|
+
export * from './domain/events.js';
|
|
8
|
+
export * from './domain/cleanup.js';
|
|
9
|
+
export * from './dashboard.js';
|
|
10
|
+
export * from './package-meta.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// agent-kit — Public API
|
|
3
|
+
// =============================================================================
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
export * from './storage/database.js';
|
|
6
|
+
export * from './storage/fts.js';
|
|
7
|
+
export * from './transport/rest.js';
|
|
8
|
+
export * from './transport/ws.js';
|
|
9
|
+
export * from './transport/mcp.js';
|
|
10
|
+
export * from './domain/events.js';
|
|
11
|
+
export * from './domain/cleanup.js';
|
|
12
|
+
export * from './dashboard.js';
|
|
13
|
+
export * from './package-meta.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,yBAAyB;AACzB,gFAAgF;AAEhF,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface PackageMeta {
|
|
2
|
+
name: string;
|
|
3
|
+
version: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ReadPackageMetaOptions {
|
|
6
|
+
/** import.meta.url of the calling file. Required when running as ESM. */
|
|
7
|
+
importMetaUrl?: string;
|
|
8
|
+
/** Override absolute path to a package.json. Wins over importMetaUrl. */
|
|
9
|
+
packageJsonPath?: string;
|
|
10
|
+
/** Fallback name if package.json is missing or unreadable. */
|
|
11
|
+
fallbackName?: string;
|
|
12
|
+
/** Fallback version if package.json is missing or unreadable. */
|
|
13
|
+
fallbackVersion?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Read `name` + `version` from a package.json. Resolution order:
|
|
17
|
+
* 1. options.packageJsonPath (absolute)
|
|
18
|
+
* 2. options.importMetaUrl → ../package.json (relative to caller)
|
|
19
|
+
* 3. fallback values
|
|
20
|
+
*/
|
|
21
|
+
export declare function readPackageMeta(options?: ReadPackageMetaOptions): PackageMeta;
|
|
22
|
+
//# sourceMappingURL=package-meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-meta.d.ts","sourceRoot":"","sources":["../src/package-meta.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,WAAW,CA8BjF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// agent-kit — Read package.json metadata at runtime
|
|
3
|
+
//
|
|
4
|
+
// Consumers call this from a known location (typically `dist/<file>.js`) so
|
|
5
|
+
// that the relative `..` path resolves to their package.json. The result is
|
|
6
|
+
// cached per-path so repeated calls are cheap.
|
|
7
|
+
// =============================================================================
|
|
8
|
+
import { readFileSync } from 'fs';
|
|
9
|
+
import { dirname, join, resolve } from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
const cache = new Map();
|
|
12
|
+
/**
|
|
13
|
+
* Read `name` + `version` from a package.json. Resolution order:
|
|
14
|
+
* 1. options.packageJsonPath (absolute)
|
|
15
|
+
* 2. options.importMetaUrl → ../package.json (relative to caller)
|
|
16
|
+
* 3. fallback values
|
|
17
|
+
*/
|
|
18
|
+
export function readPackageMeta(options = {}) {
|
|
19
|
+
const fallback = {
|
|
20
|
+
name: options.fallbackName ?? 'unknown',
|
|
21
|
+
version: options.fallbackVersion ?? '0.0.0',
|
|
22
|
+
};
|
|
23
|
+
let path = options.packageJsonPath;
|
|
24
|
+
if (!path && options.importMetaUrl) {
|
|
25
|
+
const callerDir = dirname(fileURLToPath(options.importMetaUrl));
|
|
26
|
+
path = resolve(join(callerDir, '..', 'package.json'));
|
|
27
|
+
}
|
|
28
|
+
if (!path)
|
|
29
|
+
return fallback;
|
|
30
|
+
const cached = cache.get(path);
|
|
31
|
+
if (cached)
|
|
32
|
+
return cached;
|
|
33
|
+
try {
|
|
34
|
+
const raw = readFileSync(path, 'utf8');
|
|
35
|
+
const pkg = JSON.parse(raw);
|
|
36
|
+
const meta = {
|
|
37
|
+
name: typeof pkg.name === 'string' ? pkg.name : fallback.name,
|
|
38
|
+
version: typeof pkg.version === 'string' ? pkg.version : fallback.version,
|
|
39
|
+
};
|
|
40
|
+
cache.set(path, meta);
|
|
41
|
+
return meta;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
cache.set(path, fallback);
|
|
45
|
+
return fallback;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=package-meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-meta.js","sourceRoot":"","sources":["../src/package-meta.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,oDAAoD;AACpD,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,+CAA+C;AAC/C,gFAAgF;AAEhF,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAOpC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;AAa7C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,UAAkC,EAAE;IAClE,MAAM,QAAQ,GAAgB;QAC5B,IAAI,EAAE,OAAO,CAAC,YAAY,IAAI,SAAS;QACvC,OAAO,EAAE,OAAO,CAAC,eAAe,IAAI,OAAO;KAC5C,CAAC;IAEF,IAAI,IAAI,GAAuB,OAAO,CAAC,eAAe,CAAC;IACvD,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;QAChE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAC;IAE3B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwC,CAAC;QACnE,MAAM,IAAI,GAAgB;YACxB,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI;YAC7D,OAAO,EAAE,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO;SAC1E,CAAC;QACF,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1B,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
export interface Db {
|
|
3
|
+
readonly raw: Database.Database;
|
|
4
|
+
run(sql: string, params?: unknown[]): Database.RunResult;
|
|
5
|
+
queryAll<T>(sql: string, params?: unknown[]): T[];
|
|
6
|
+
queryOne<T>(sql: string, params?: unknown[]): T | null;
|
|
7
|
+
transaction<T>(fn: () => T): T;
|
|
8
|
+
close(): void;
|
|
9
|
+
}
|
|
10
|
+
export interface Migration {
|
|
11
|
+
/** 1-based version number; migrations run in ascending order. */
|
|
12
|
+
version: number;
|
|
13
|
+
/** Idempotent SQL or programmatic step. */
|
|
14
|
+
up: (raw: Database.Database) => void;
|
|
15
|
+
}
|
|
16
|
+
export interface DbOptions {
|
|
17
|
+
/** Use ':memory:' for tests, or an absolute file path. */
|
|
18
|
+
path: string;
|
|
19
|
+
/** Migrations to apply on open. */
|
|
20
|
+
migrations?: Migration[];
|
|
21
|
+
/** Enable verbose logging to stderr. */
|
|
22
|
+
verbose?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare function createDb(options: DbOptions): Db;
|
|
25
|
+
export declare function runMigrations(raw: Database.Database, migrations: Migration[]): void;
|
|
26
|
+
export declare function getSchemaVersion(raw: Database.Database): number;
|
|
27
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/storage/database.ts"],"names":[],"mappings":"AAQA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,MAAM,WAAW,EAAE;IACjB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC;IAChC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC;IACzD,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;IAClD,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACvD,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/B,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,EAAE,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,SAAS;IACxB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,wCAAwC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,EAAE,CAwC/C;AAMD,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,CAyBnF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAK/D"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// agent-kit — Storage layer
|
|
3
|
+
//
|
|
4
|
+
// Generic better-sqlite3 wrapper with WAL pragmas, transactions, and a
|
|
5
|
+
// version-based migration runner. Consumers supply their own migrations and
|
|
6
|
+
// resolve their own DB path.
|
|
7
|
+
// =============================================================================
|
|
8
|
+
import Database from 'better-sqlite3';
|
|
9
|
+
export function createDb(options) {
|
|
10
|
+
const raw = new Database(options.path, {
|
|
11
|
+
verbose: options.verbose ? (msg) => process.stderr.write(`[sql] ${msg}\n`) : undefined,
|
|
12
|
+
});
|
|
13
|
+
raw.pragma('journal_mode = WAL');
|
|
14
|
+
raw.pragma('busy_timeout = 5000');
|
|
15
|
+
raw.pragma('synchronous = NORMAL');
|
|
16
|
+
raw.pragma('foreign_keys = ON');
|
|
17
|
+
if (options.migrations && options.migrations.length > 0) {
|
|
18
|
+
runMigrations(raw, options.migrations);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
raw,
|
|
22
|
+
run(sql, params) {
|
|
23
|
+
const stmt = raw.prepare(sql);
|
|
24
|
+
return params?.length ? stmt.run(...params) : stmt.run();
|
|
25
|
+
},
|
|
26
|
+
queryAll(sql, params) {
|
|
27
|
+
const stmt = raw.prepare(sql);
|
|
28
|
+
return (params?.length ? stmt.all(...params) : stmt.all());
|
|
29
|
+
},
|
|
30
|
+
queryOne(sql, params) {
|
|
31
|
+
const stmt = raw.prepare(sql);
|
|
32
|
+
const row = params?.length ? stmt.get(...params) : stmt.get();
|
|
33
|
+
return row ?? null;
|
|
34
|
+
},
|
|
35
|
+
transaction(fn) {
|
|
36
|
+
return raw.transaction(fn)();
|
|
37
|
+
},
|
|
38
|
+
close() {
|
|
39
|
+
try {
|
|
40
|
+
raw.close();
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
/* ignore */
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Migration runner
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
export function runMigrations(raw, migrations) {
|
|
52
|
+
raw.exec(`
|
|
53
|
+
CREATE TABLE IF NOT EXISTS _meta (
|
|
54
|
+
key TEXT PRIMARY KEY,
|
|
55
|
+
value TEXT NOT NULL
|
|
56
|
+
)
|
|
57
|
+
`);
|
|
58
|
+
const row = raw.prepare(`SELECT value FROM _meta WHERE key = 'schema_version'`).get();
|
|
59
|
+
const currentVersion = row ? parseInt(row.value, 10) : 0;
|
|
60
|
+
const sorted = [...migrations].sort((a, b) => a.version - b.version);
|
|
61
|
+
const target = sorted.length > 0 ? sorted[sorted.length - 1].version : 0;
|
|
62
|
+
for (const m of sorted) {
|
|
63
|
+
if (m.version > currentVersion) {
|
|
64
|
+
m.up(raw);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
raw.prepare(`INSERT OR REPLACE INTO _meta (key, value) VALUES ('schema_version', ?)`).run(String(target));
|
|
68
|
+
}
|
|
69
|
+
export function getSchemaVersion(raw) {
|
|
70
|
+
const row = raw.prepare(`SELECT value FROM _meta WHERE key = 'schema_version'`).get();
|
|
71
|
+
return row ? parseInt(row.value, 10) : 0;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/storage/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Db } from './database.js';
|
|
2
|
+
export interface FtsOptions {
|
|
3
|
+
/** Name of the FTS5 virtual table to create (e.g. "messages_fts"). */
|
|
4
|
+
ftsTable: string;
|
|
5
|
+
/** Name of the content table the FTS index mirrors (e.g. "messages"). */
|
|
6
|
+
contentTable: string;
|
|
7
|
+
/** Column name in the content table to index (e.g. "content"). */
|
|
8
|
+
column: string;
|
|
9
|
+
}
|
|
10
|
+
/** Create an FTS5 virtual table + insert/update/delete triggers idempotently. */
|
|
11
|
+
export declare function createFtsTable(db: Db, opts: FtsOptions): void;
|
|
12
|
+
export interface FtsSearchOptions {
|
|
13
|
+
ftsTable: string;
|
|
14
|
+
contentTable: string;
|
|
15
|
+
column: string;
|
|
16
|
+
query: string;
|
|
17
|
+
limit?: number;
|
|
18
|
+
/** Optional extra WHERE clause appended after the FTS join. */
|
|
19
|
+
extraWhere?: string;
|
|
20
|
+
extraParams?: unknown[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* FTS5 MATCH search with LIKE fallback. Returns matching content rows.
|
|
24
|
+
* If the FTS query parses incorrectly, falls back to a LIKE wildcard scan.
|
|
25
|
+
*/
|
|
26
|
+
export declare function ftsSearch<T>(db: Db, opts: FtsSearchOptions): T[];
|
|
27
|
+
//# sourceMappingURL=fts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fts.d.ts","sourceRoot":"","sources":["../../src/storage/fts.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAsB7D;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,GAAG,CAAC,EAAE,CA0BhE"}
|