@hasna/mementos 0.14.74 → 0.14.75
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/cli/commands/agent.d.ts.map +1 -1
- package/dist/cli/index.js +117 -14
- package/dist/db/agents.d.ts +6 -0
- package/dist/db/agents.d.ts.map +1 -1
- package/dist/db/audit.d.ts +14 -0
- package/dist/db/audit.d.ts.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/pg-migrations.d.ts.map +1 -1
- package/dist/index.js +81 -10
- package/dist/mcp/index.js +110 -10
- package/dist/server/index.js +94 -11
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4N5D"}
|
package/dist/cli/index.js
CHANGED
|
@@ -4130,6 +4130,39 @@ INSERT OR IGNORE INTO _migrations (id) VALUES (35);
|
|
|
4130
4130
|
`
|
|
4131
4131
|
${MEMORY_VERSION_SNAPSHOT_TRIGGER}
|
|
4132
4132
|
INSERT OR IGNORE INTO _migrations (id) VALUES (36);
|
|
4133
|
+
`,
|
|
4134
|
+
`
|
|
4135
|
+
DROP TRIGGER IF EXISTS audit_memory_insert;
|
|
4136
|
+
CREATE TRIGGER audit_memory_insert AFTER INSERT ON memories BEGIN
|
|
4137
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, created_at)
|
|
4138
|
+
VALUES (hex(randomblob(4)), new.id, new.key, 'create', new.agent_id, datetime('now'));
|
|
4139
|
+
END;
|
|
4140
|
+
|
|
4141
|
+
DROP TRIGGER IF EXISTS audit_memory_update;
|
|
4142
|
+
CREATE TRIGGER audit_memory_update AFTER UPDATE ON memories BEGIN
|
|
4143
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, changes, created_at)
|
|
4144
|
+
VALUES (hex(randomblob(4)), new.id, new.key, 'update', new.agent_id,
|
|
4145
|
+
json_object('version_from', old.version, 'version_to', new.version, 'importance_from', old.importance, 'importance_to', new.importance),
|
|
4146
|
+
datetime('now'));
|
|
4147
|
+
END;
|
|
4148
|
+
|
|
4149
|
+
DROP TRIGGER IF EXISTS audit_memory_delete;
|
|
4150
|
+
CREATE TRIGGER audit_memory_delete AFTER DELETE ON memories BEGIN
|
|
4151
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, created_at)
|
|
4152
|
+
VALUES (hex(randomblob(4)), old.id, old.key, 'delete', old.agent_id, datetime('now'));
|
|
4153
|
+
END;
|
|
4154
|
+
|
|
4155
|
+
UPDATE memory_audit_log SET old_value_hash = NULL
|
|
4156
|
+
WHERE old_value_hash IS NOT NULL
|
|
4157
|
+
AND length(old_value_hash) = 32
|
|
4158
|
+
AND old_value_hash NOT GLOB '*[^0-9A-F]*';
|
|
4159
|
+
|
|
4160
|
+
UPDATE memory_audit_log SET new_value_hash = NULL
|
|
4161
|
+
WHERE new_value_hash IS NOT NULL
|
|
4162
|
+
AND length(new_value_hash) = 32
|
|
4163
|
+
AND new_value_hash NOT GLOB '*[^0-9A-F]*';
|
|
4164
|
+
|
|
4165
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (37);
|
|
4133
4166
|
`
|
|
4134
4167
|
];
|
|
4135
4168
|
});
|
|
@@ -6708,13 +6741,46 @@ function getAgent(idOrName, db) {
|
|
|
6708
6741
|
return parseAgentRow(rows[0]);
|
|
6709
6742
|
return null;
|
|
6710
6743
|
}
|
|
6711
|
-
function
|
|
6712
|
-
|
|
6713
|
-
|
|
6744
|
+
function normalizedAgentListFilter(filter) {
|
|
6745
|
+
const limit = Number.isFinite(filter.limit) ? Math.max(0, Math.floor(filter.limit)) : undefined;
|
|
6746
|
+
const offset = Number.isFinite(filter.offset) ? Math.max(0, Math.floor(filter.offset)) : undefined;
|
|
6747
|
+
return { limit, offset };
|
|
6748
|
+
}
|
|
6749
|
+
function isDatabaseAdapter(value) {
|
|
6750
|
+
return typeof value === "object" && value !== null && "query" in value && typeof value.query === "function";
|
|
6751
|
+
}
|
|
6752
|
+
function paginatedAgentQuery(baseSql, baseParams, filter) {
|
|
6753
|
+
const { limit, offset } = normalizedAgentListFilter(filter);
|
|
6754
|
+
let sql = `${baseSql} ORDER BY created_at ASC, id ASC`;
|
|
6755
|
+
const params = [...baseParams];
|
|
6756
|
+
if (limit !== undefined) {
|
|
6757
|
+
sql += " LIMIT ?";
|
|
6758
|
+
params.push(limit);
|
|
6759
|
+
} else if ((offset ?? 0) > 0) {
|
|
6760
|
+
sql += " LIMIT ?";
|
|
6761
|
+
params.push(UNBOUNDED_AGENT_LIST_LIMIT);
|
|
6762
|
+
}
|
|
6763
|
+
if ((offset ?? 0) > 0) {
|
|
6764
|
+
sql += " OFFSET ?";
|
|
6765
|
+
params.push(offset);
|
|
6766
|
+
}
|
|
6767
|
+
return { sql, params };
|
|
6768
|
+
}
|
|
6769
|
+
function listAgents(filterOrDb = {}, db) {
|
|
6770
|
+
const explicitDb = isDatabaseAdapter(filterOrDb) ? filterOrDb : db;
|
|
6771
|
+
const filter = isDatabaseAdapter(filterOrDb) ? {} : filterOrDb;
|
|
6772
|
+
const normalized = normalizedAgentListFilter(filter);
|
|
6773
|
+
if (!explicitDb && isApiMode()) {
|
|
6774
|
+
const q = toQuery({
|
|
6775
|
+
limit: normalized.limit,
|
|
6776
|
+
offset: normalized.offset
|
|
6777
|
+
});
|
|
6778
|
+
const { data } = apiJson("GET", `/agents${q}`);
|
|
6714
6779
|
return data?.agents ?? [];
|
|
6715
6780
|
}
|
|
6716
|
-
const d =
|
|
6717
|
-
const
|
|
6781
|
+
const d = explicitDb || getDatabase();
|
|
6782
|
+
const { sql, params } = paginatedAgentQuery("SELECT * FROM agents", [], normalized);
|
|
6783
|
+
const rows = d.query(sql).all(...params);
|
|
6718
6784
|
return rows.map(parseAgentRow);
|
|
6719
6785
|
}
|
|
6720
6786
|
function touchAgent(idOrName, db) {
|
|
@@ -6731,15 +6797,19 @@ function touchAgent(idOrName, db) {
|
|
|
6731
6797
|
return;
|
|
6732
6798
|
d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [now(), agent.id]);
|
|
6733
6799
|
}
|
|
6734
|
-
function listAgentsByProject(projectId, db) {
|
|
6735
|
-
|
|
6736
|
-
|
|
6800
|
+
function listAgentsByProject(projectId, filterOrDb = {}, db) {
|
|
6801
|
+
const explicitDb = isDatabaseAdapter(filterOrDb) ? filterOrDb : db;
|
|
6802
|
+
const filter = isDatabaseAdapter(filterOrDb) ? {} : filterOrDb;
|
|
6803
|
+
const normalized = normalizedAgentListFilter(filter);
|
|
6804
|
+
if (!explicitDb && isApiMode()) {
|
|
6805
|
+
const q = toQuery({ project_id: projectId, ...normalized });
|
|
6737
6806
|
const { data } = apiJson("GET", `/agents${q}`);
|
|
6738
6807
|
return data?.agents ?? [];
|
|
6739
6808
|
}
|
|
6740
|
-
const d =
|
|
6809
|
+
const d = explicitDb || getDatabase();
|
|
6741
6810
|
const resolvedId = resolvePartialId(d, "projects", projectId) || projectId;
|
|
6742
|
-
const
|
|
6811
|
+
const { sql, params } = paginatedAgentQuery("SELECT * FROM agents WHERE active_project_id = ?", [resolvedId], normalized);
|
|
6812
|
+
const rows = d.query(sql).all(...params);
|
|
6743
6813
|
return rows.map(parseAgentRow);
|
|
6744
6814
|
}
|
|
6745
6815
|
function updateAgent(id, updates, db) {
|
|
@@ -6787,12 +6857,13 @@ function updateAgent(id, updates, db) {
|
|
|
6787
6857
|
d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [timestamp, agent.id]);
|
|
6788
6858
|
return getAgent(agent.id, d);
|
|
6789
6859
|
}
|
|
6790
|
-
var CONFLICT_WINDOW_MS;
|
|
6860
|
+
var CONFLICT_WINDOW_MS, UNBOUNDED_AGENT_LIST_LIMIT;
|
|
6791
6861
|
var init_agents = __esm(() => {
|
|
6792
6862
|
init_types();
|
|
6793
6863
|
init_database();
|
|
6794
6864
|
init_api_mode();
|
|
6795
6865
|
CONFLICT_WINDOW_MS = 30 * 60 * 1000;
|
|
6866
|
+
UNBOUNDED_AGENT_LIST_LIMIT = Number.MAX_SAFE_INTEGER;
|
|
6796
6867
|
});
|
|
6797
6868
|
|
|
6798
6869
|
// src/lib/poll.ts
|
|
@@ -12222,6 +12293,35 @@ var init_pg_migrations = __esm(() => {
|
|
|
12222
12293
|
EXECUTE FUNCTION snapshot_memory_version();
|
|
12223
12294
|
|
|
12224
12295
|
INSERT INTO _migrations (id) VALUES (36) ON CONFLICT DO NOTHING;
|
|
12296
|
+
`,
|
|
12297
|
+
`
|
|
12298
|
+
CREATE OR REPLACE FUNCTION audit_memory_insert() RETURNS trigger AS $$
|
|
12299
|
+
BEGIN
|
|
12300
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, new_value_hash, created_at)
|
|
12301
|
+
VALUES (gen_random_uuid()::text, NEW.id, NEW.key, 'create', NEW.agent_id, md5(COALESCE(NEW.value, '')), NOW());
|
|
12302
|
+
RETURN NEW;
|
|
12303
|
+
END;
|
|
12304
|
+
$$ LANGUAGE plpgsql;
|
|
12305
|
+
|
|
12306
|
+
CREATE OR REPLACE FUNCTION audit_memory_update() RETURNS trigger AS $$
|
|
12307
|
+
BEGIN
|
|
12308
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, old_value_hash, new_value_hash, changes, created_at)
|
|
12309
|
+
VALUES (gen_random_uuid()::text, NEW.id, NEW.key, 'update', NEW.agent_id, md5(COALESCE(OLD.value, '')), md5(COALESCE(NEW.value, '')),
|
|
12310
|
+
json_build_object('version_from', OLD.version, 'version_to', NEW.version, 'importance_from', OLD.importance, 'importance_to', NEW.importance)::text,
|
|
12311
|
+
NOW());
|
|
12312
|
+
RETURN NEW;
|
|
12313
|
+
END;
|
|
12314
|
+
$$ LANGUAGE plpgsql;
|
|
12315
|
+
|
|
12316
|
+
CREATE OR REPLACE FUNCTION audit_memory_delete() RETURNS trigger AS $$
|
|
12317
|
+
BEGIN
|
|
12318
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, old_value_hash, created_at)
|
|
12319
|
+
VALUES (gen_random_uuid()::text, OLD.id, OLD.key, 'delete', OLD.agent_id, md5(COALESCE(OLD.value, '')), NOW());
|
|
12320
|
+
RETURN OLD;
|
|
12321
|
+
END;
|
|
12322
|
+
$$ LANGUAGE plpgsql;
|
|
12323
|
+
|
|
12324
|
+
INSERT INTO _migrations (id) VALUES (37) ON CONFLICT DO NOTHING;
|
|
12225
12325
|
`
|
|
12226
12326
|
];
|
|
12227
12327
|
});
|
|
@@ -62050,14 +62150,17 @@ function registerAgentCommands(program2) {
|
|
|
62050
62150
|
program2.command("agents").description("List all registered agents").option("--limit <n>", "Max results (compact default: 20)", parseInt).option("--cursor <n>", "Cursor offset for the next page", parseInt).option("--offset <n>", "Offset for pagination", parseInt).action((opts) => {
|
|
62051
62151
|
try {
|
|
62052
62152
|
const globalOpts = program2.opts();
|
|
62053
|
-
const allAgents = listAgents();
|
|
62054
62153
|
const limit = positiveIntOrDefault(opts.limit, DEFAULT_COMPACT_LIMIT);
|
|
62055
62154
|
const offset = cursorOrOffset(opts.cursor, opts.offset) ?? 0;
|
|
62056
|
-
const
|
|
62155
|
+
const explicitPagination = opts.limit !== undefined || opts.cursor !== undefined || opts.offset !== undefined;
|
|
62156
|
+
const agents = listAgents({
|
|
62157
|
+
limit: globalOpts.json ? explicitPagination ? limit : undefined : limit + 1,
|
|
62158
|
+
offset
|
|
62159
|
+
});
|
|
62057
62160
|
const hasMore = !globalOpts.json && agents.length > limit;
|
|
62058
62161
|
const displayAgents = hasMore ? agents.slice(0, limit) : agents;
|
|
62059
62162
|
if (globalOpts.json) {
|
|
62060
|
-
outputJson(
|
|
62163
|
+
outputJson(agents);
|
|
62061
62164
|
return;
|
|
62062
62165
|
}
|
|
62063
62166
|
if (displayAgents.length === 0) {
|
package/dist/db/agents.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { SqliteAdapter as Database } from "../storage.js";
|
|
2
2
|
import type { Agent } from "../types/index.js";
|
|
3
|
+
export interface AgentListFilter {
|
|
4
|
+
limit?: number;
|
|
5
|
+
offset?: number;
|
|
6
|
+
}
|
|
3
7
|
export declare function registerAgent(name: string, sessionId?: string, description?: string, role?: string, projectId?: string, db?: Database): Agent;
|
|
4
8
|
export declare function getAgent(idOrName: string, db?: Database): Agent | null;
|
|
5
9
|
export declare function listAgents(db?: Database): Agent[];
|
|
10
|
+
export declare function listAgents(filter: AgentListFilter, db?: Database): Agent[];
|
|
6
11
|
export declare function touchAgent(idOrName: string, db?: Database): void;
|
|
7
12
|
export declare function listAgentsByProject(projectId: string, db?: Database): Agent[];
|
|
13
|
+
export declare function listAgentsByProject(projectId: string, filter: AgentListFilter, db?: Database): Agent[];
|
|
8
14
|
export declare function updateAgent(id: string, updates: {
|
|
9
15
|
name?: string;
|
|
10
16
|
description?: string;
|
package/dist/db/agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/db/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/db/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAQ/C,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgBD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,CA0EP;AAED,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,GAAG,IAAI,CA6Bd;AA+CD,wBAAgB,UAAU,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,EAAE,CAAC;AACnD,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,EAAE,CAAC;AAsB5E,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAahE;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,EAAE,CAAC;AAC/E,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,eAAe,EACvB,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,EAAE,CAAC;AA0BX,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACtI,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,GAAG,IAAI,CAsDd"}
|
package/dist/db/audit.d.ts
CHANGED
|
@@ -9,7 +9,21 @@ export interface AuditEntry {
|
|
|
9
9
|
memory_key: string | null;
|
|
10
10
|
operation: "create" | "update" | "delete" | "archive" | "restore" | "read";
|
|
11
11
|
agent_id: string | null;
|
|
12
|
+
/**
|
|
13
|
+
* md5 hex digest of the value the row held BEFORE the operation, or `null`.
|
|
14
|
+
*
|
|
15
|
+
* `null` means the digest is UNAVAILABLE, never that the value was empty. It is
|
|
16
|
+
* the honest answer on SQLite, which has no `md5()` and whose driver
|
|
17
|
+
* (`bun:sqlite`) exposes no user-defined-function API, so a trigger cannot
|
|
18
|
+
* compute one. Postgres computes `md5(COALESCE(...))` natively and populates it.
|
|
19
|
+
*
|
|
20
|
+
* So: compare `md5(candidate)` against a NON-NULL value to prove what a row
|
|
21
|
+
* held. A `null` is a statement about the BACKEND and must never be read as
|
|
22
|
+
* evidence about the content — treating it as a failed match is the confident
|
|
23
|
+
* wrong answer migration 37 exists to prevent.
|
|
24
|
+
*/
|
|
12
25
|
old_value_hash: string | null;
|
|
26
|
+
/** md5 hex digest of the value AFTER the operation, or `null`. See `old_value_hash`. */
|
|
13
27
|
new_value_hash: string | null;
|
|
14
28
|
changes: Record<string, unknown>;
|
|
15
29
|
created_at: string;
|
package/dist/db/audit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/db/audit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAgBD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAW,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,UAAU,EAAE,CAMd;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,GAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACX,EACN,EAAE,CAAC,EAAE,QAAQ,GACZ,UAAU,EAAE,CA6Bd;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB,CAkBA"}
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/db/audit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;;;;;;;;OAYG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,wFAAwF;IACxF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAgBD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAW,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,UAAU,EAAE,CAMd;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,GAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACX,EACN,EAAE,CAAC,EAAE,QAAQ,GACZ,UAAU,EAAE,CA6Bd;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB,CAkBA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,+BAA+B,wqBAiB3C,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,+BAA+B,wqBAiB3C,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,MAAM,EAkhC9B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-migrations.d.ts","sourceRoot":"","sources":["../../src/db/pg-migrations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"pg-migrations.d.ts","sourceRoot":"","sources":["../../src/db/pg-migrations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,EAy0BjC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2098,6 +2098,39 @@ INSERT OR IGNORE INTO _migrations (id) VALUES (35);
|
|
|
2098
2098
|
`
|
|
2099
2099
|
${MEMORY_VERSION_SNAPSHOT_TRIGGER}
|
|
2100
2100
|
INSERT OR IGNORE INTO _migrations (id) VALUES (36);
|
|
2101
|
+
`,
|
|
2102
|
+
`
|
|
2103
|
+
DROP TRIGGER IF EXISTS audit_memory_insert;
|
|
2104
|
+
CREATE TRIGGER audit_memory_insert AFTER INSERT ON memories BEGIN
|
|
2105
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, created_at)
|
|
2106
|
+
VALUES (hex(randomblob(4)), new.id, new.key, 'create', new.agent_id, datetime('now'));
|
|
2107
|
+
END;
|
|
2108
|
+
|
|
2109
|
+
DROP TRIGGER IF EXISTS audit_memory_update;
|
|
2110
|
+
CREATE TRIGGER audit_memory_update AFTER UPDATE ON memories BEGIN
|
|
2111
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, changes, created_at)
|
|
2112
|
+
VALUES (hex(randomblob(4)), new.id, new.key, 'update', new.agent_id,
|
|
2113
|
+
json_object('version_from', old.version, 'version_to', new.version, 'importance_from', old.importance, 'importance_to', new.importance),
|
|
2114
|
+
datetime('now'));
|
|
2115
|
+
END;
|
|
2116
|
+
|
|
2117
|
+
DROP TRIGGER IF EXISTS audit_memory_delete;
|
|
2118
|
+
CREATE TRIGGER audit_memory_delete AFTER DELETE ON memories BEGIN
|
|
2119
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, created_at)
|
|
2120
|
+
VALUES (hex(randomblob(4)), old.id, old.key, 'delete', old.agent_id, datetime('now'));
|
|
2121
|
+
END;
|
|
2122
|
+
|
|
2123
|
+
UPDATE memory_audit_log SET old_value_hash = NULL
|
|
2124
|
+
WHERE old_value_hash IS NOT NULL
|
|
2125
|
+
AND length(old_value_hash) = 32
|
|
2126
|
+
AND old_value_hash NOT GLOB '*[^0-9A-F]*';
|
|
2127
|
+
|
|
2128
|
+
UPDATE memory_audit_log SET new_value_hash = NULL
|
|
2129
|
+
WHERE new_value_hash IS NOT NULL
|
|
2130
|
+
AND length(new_value_hash) = 32
|
|
2131
|
+
AND new_value_hash NOT GLOB '*[^0-9A-F]*';
|
|
2132
|
+
|
|
2133
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (37);
|
|
2101
2134
|
`
|
|
2102
2135
|
];
|
|
2103
2136
|
});
|
|
@@ -49995,6 +50028,7 @@ function getMemoryVersions(memoryId, db) {
|
|
|
49995
50028
|
init_database();
|
|
49996
50029
|
init_api_mode();
|
|
49997
50030
|
var CONFLICT_WINDOW_MS = 30 * 60 * 1000;
|
|
50031
|
+
var UNBOUNDED_AGENT_LIST_LIMIT = Number.MAX_SAFE_INTEGER;
|
|
49998
50032
|
function parseAgentRow(row) {
|
|
49999
50033
|
return {
|
|
50000
50034
|
id: row["id"],
|
|
@@ -50086,13 +50120,46 @@ function getAgent(idOrName, db) {
|
|
|
50086
50120
|
return parseAgentRow(rows[0]);
|
|
50087
50121
|
return null;
|
|
50088
50122
|
}
|
|
50089
|
-
function
|
|
50090
|
-
|
|
50091
|
-
|
|
50123
|
+
function normalizedAgentListFilter(filter) {
|
|
50124
|
+
const limit = Number.isFinite(filter.limit) ? Math.max(0, Math.floor(filter.limit)) : undefined;
|
|
50125
|
+
const offset = Number.isFinite(filter.offset) ? Math.max(0, Math.floor(filter.offset)) : undefined;
|
|
50126
|
+
return { limit, offset };
|
|
50127
|
+
}
|
|
50128
|
+
function isDatabaseAdapter(value) {
|
|
50129
|
+
return typeof value === "object" && value !== null && "query" in value && typeof value.query === "function";
|
|
50130
|
+
}
|
|
50131
|
+
function paginatedAgentQuery(baseSql, baseParams, filter) {
|
|
50132
|
+
const { limit, offset } = normalizedAgentListFilter(filter);
|
|
50133
|
+
let sql = `${baseSql} ORDER BY created_at ASC, id ASC`;
|
|
50134
|
+
const params = [...baseParams];
|
|
50135
|
+
if (limit !== undefined) {
|
|
50136
|
+
sql += " LIMIT ?";
|
|
50137
|
+
params.push(limit);
|
|
50138
|
+
} else if ((offset ?? 0) > 0) {
|
|
50139
|
+
sql += " LIMIT ?";
|
|
50140
|
+
params.push(UNBOUNDED_AGENT_LIST_LIMIT);
|
|
50141
|
+
}
|
|
50142
|
+
if ((offset ?? 0) > 0) {
|
|
50143
|
+
sql += " OFFSET ?";
|
|
50144
|
+
params.push(offset);
|
|
50145
|
+
}
|
|
50146
|
+
return { sql, params };
|
|
50147
|
+
}
|
|
50148
|
+
function listAgents(filterOrDb = {}, db) {
|
|
50149
|
+
const explicitDb = isDatabaseAdapter(filterOrDb) ? filterOrDb : db;
|
|
50150
|
+
const filter = isDatabaseAdapter(filterOrDb) ? {} : filterOrDb;
|
|
50151
|
+
const normalized = normalizedAgentListFilter(filter);
|
|
50152
|
+
if (!explicitDb && isApiMode()) {
|
|
50153
|
+
const q = toQuery({
|
|
50154
|
+
limit: normalized.limit,
|
|
50155
|
+
offset: normalized.offset
|
|
50156
|
+
});
|
|
50157
|
+
const { data } = apiJson("GET", `/agents${q}`);
|
|
50092
50158
|
return data?.agents ?? [];
|
|
50093
50159
|
}
|
|
50094
|
-
const d =
|
|
50095
|
-
const
|
|
50160
|
+
const d = explicitDb || getDatabase();
|
|
50161
|
+
const { sql, params } = paginatedAgentQuery("SELECT * FROM agents", [], normalized);
|
|
50162
|
+
const rows = d.query(sql).all(...params);
|
|
50096
50163
|
return rows.map(parseAgentRow);
|
|
50097
50164
|
}
|
|
50098
50165
|
function touchAgent(idOrName, db) {
|
|
@@ -50109,15 +50176,19 @@ function touchAgent(idOrName, db) {
|
|
|
50109
50176
|
return;
|
|
50110
50177
|
d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [now(), agent.id]);
|
|
50111
50178
|
}
|
|
50112
|
-
function listAgentsByProject(projectId, db) {
|
|
50113
|
-
|
|
50114
|
-
|
|
50179
|
+
function listAgentsByProject(projectId, filterOrDb = {}, db) {
|
|
50180
|
+
const explicitDb = isDatabaseAdapter(filterOrDb) ? filterOrDb : db;
|
|
50181
|
+
const filter = isDatabaseAdapter(filterOrDb) ? {} : filterOrDb;
|
|
50182
|
+
const normalized = normalizedAgentListFilter(filter);
|
|
50183
|
+
if (!explicitDb && isApiMode()) {
|
|
50184
|
+
const q = toQuery({ project_id: projectId, ...normalized });
|
|
50115
50185
|
const { data } = apiJson("GET", `/agents${q}`);
|
|
50116
50186
|
return data?.agents ?? [];
|
|
50117
50187
|
}
|
|
50118
|
-
const d =
|
|
50188
|
+
const d = explicitDb || getDatabase();
|
|
50119
50189
|
const resolvedId = resolvePartialId(d, "projects", projectId) || projectId;
|
|
50120
|
-
const
|
|
50190
|
+
const { sql, params } = paginatedAgentQuery("SELECT * FROM agents WHERE active_project_id = ?", [resolvedId], normalized);
|
|
50191
|
+
const rows = d.query(sql).all(...params);
|
|
50121
50192
|
return rows.map(parseAgentRow);
|
|
50122
50193
|
}
|
|
50123
50194
|
function updateAgent(id, updates, db) {
|
package/dist/mcp/index.js
CHANGED
|
@@ -2161,6 +2161,39 @@ INSERT OR IGNORE INTO _migrations (id) VALUES (35);
|
|
|
2161
2161
|
`
|
|
2162
2162
|
${MEMORY_VERSION_SNAPSHOT_TRIGGER}
|
|
2163
2163
|
INSERT OR IGNORE INTO _migrations (id) VALUES (36);
|
|
2164
|
+
`,
|
|
2165
|
+
`
|
|
2166
|
+
DROP TRIGGER IF EXISTS audit_memory_insert;
|
|
2167
|
+
CREATE TRIGGER audit_memory_insert AFTER INSERT ON memories BEGIN
|
|
2168
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, created_at)
|
|
2169
|
+
VALUES (hex(randomblob(4)), new.id, new.key, 'create', new.agent_id, datetime('now'));
|
|
2170
|
+
END;
|
|
2171
|
+
|
|
2172
|
+
DROP TRIGGER IF EXISTS audit_memory_update;
|
|
2173
|
+
CREATE TRIGGER audit_memory_update AFTER UPDATE ON memories BEGIN
|
|
2174
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, changes, created_at)
|
|
2175
|
+
VALUES (hex(randomblob(4)), new.id, new.key, 'update', new.agent_id,
|
|
2176
|
+
json_object('version_from', old.version, 'version_to', new.version, 'importance_from', old.importance, 'importance_to', new.importance),
|
|
2177
|
+
datetime('now'));
|
|
2178
|
+
END;
|
|
2179
|
+
|
|
2180
|
+
DROP TRIGGER IF EXISTS audit_memory_delete;
|
|
2181
|
+
CREATE TRIGGER audit_memory_delete AFTER DELETE ON memories BEGIN
|
|
2182
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, created_at)
|
|
2183
|
+
VALUES (hex(randomblob(4)), old.id, old.key, 'delete', old.agent_id, datetime('now'));
|
|
2184
|
+
END;
|
|
2185
|
+
|
|
2186
|
+
UPDATE memory_audit_log SET old_value_hash = NULL
|
|
2187
|
+
WHERE old_value_hash IS NOT NULL
|
|
2188
|
+
AND length(old_value_hash) = 32
|
|
2189
|
+
AND old_value_hash NOT GLOB '*[^0-9A-F]*';
|
|
2190
|
+
|
|
2191
|
+
UPDATE memory_audit_log SET new_value_hash = NULL
|
|
2192
|
+
WHERE new_value_hash IS NOT NULL
|
|
2193
|
+
AND length(new_value_hash) = 32
|
|
2194
|
+
AND new_value_hash NOT GLOB '*[^0-9A-F]*';
|
|
2195
|
+
|
|
2196
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (37);
|
|
2164
2197
|
`
|
|
2165
2198
|
];
|
|
2166
2199
|
});
|
|
@@ -13016,6 +13049,35 @@ var init_pg_migrations = __esm(() => {
|
|
|
13016
13049
|
EXECUTE FUNCTION snapshot_memory_version();
|
|
13017
13050
|
|
|
13018
13051
|
INSERT INTO _migrations (id) VALUES (36) ON CONFLICT DO NOTHING;
|
|
13052
|
+
`,
|
|
13053
|
+
`
|
|
13054
|
+
CREATE OR REPLACE FUNCTION audit_memory_insert() RETURNS trigger AS $$
|
|
13055
|
+
BEGIN
|
|
13056
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, new_value_hash, created_at)
|
|
13057
|
+
VALUES (gen_random_uuid()::text, NEW.id, NEW.key, 'create', NEW.agent_id, md5(COALESCE(NEW.value, '')), NOW());
|
|
13058
|
+
RETURN NEW;
|
|
13059
|
+
END;
|
|
13060
|
+
$$ LANGUAGE plpgsql;
|
|
13061
|
+
|
|
13062
|
+
CREATE OR REPLACE FUNCTION audit_memory_update() RETURNS trigger AS $$
|
|
13063
|
+
BEGIN
|
|
13064
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, old_value_hash, new_value_hash, changes, created_at)
|
|
13065
|
+
VALUES (gen_random_uuid()::text, NEW.id, NEW.key, 'update', NEW.agent_id, md5(COALESCE(OLD.value, '')), md5(COALESCE(NEW.value, '')),
|
|
13066
|
+
json_build_object('version_from', OLD.version, 'version_to', NEW.version, 'importance_from', OLD.importance, 'importance_to', NEW.importance)::text,
|
|
13067
|
+
NOW());
|
|
13068
|
+
RETURN NEW;
|
|
13069
|
+
END;
|
|
13070
|
+
$$ LANGUAGE plpgsql;
|
|
13071
|
+
|
|
13072
|
+
CREATE OR REPLACE FUNCTION audit_memory_delete() RETURNS trigger AS $$
|
|
13073
|
+
BEGIN
|
|
13074
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, old_value_hash, created_at)
|
|
13075
|
+
VALUES (gen_random_uuid()::text, OLD.id, OLD.key, 'delete', OLD.agent_id, md5(COALESCE(OLD.value, '')), NOW());
|
|
13076
|
+
RETURN OLD;
|
|
13077
|
+
END;
|
|
13078
|
+
$$ LANGUAGE plpgsql;
|
|
13079
|
+
|
|
13080
|
+
INSERT INTO _migrations (id) VALUES (37) ON CONFLICT DO NOTHING;
|
|
13019
13081
|
`
|
|
13020
13082
|
];
|
|
13021
13083
|
});
|
|
@@ -55743,6 +55805,7 @@ init_types();
|
|
|
55743
55805
|
init_database();
|
|
55744
55806
|
init_api_mode();
|
|
55745
55807
|
var CONFLICT_WINDOW_MS = 30 * 60 * 1000;
|
|
55808
|
+
var UNBOUNDED_AGENT_LIST_LIMIT = Number.MAX_SAFE_INTEGER;
|
|
55746
55809
|
function parseAgentRow(row) {
|
|
55747
55810
|
return {
|
|
55748
55811
|
id: row["id"],
|
|
@@ -55834,13 +55897,46 @@ function getAgent(idOrName, db) {
|
|
|
55834
55897
|
return parseAgentRow(rows[0]);
|
|
55835
55898
|
return null;
|
|
55836
55899
|
}
|
|
55837
|
-
function
|
|
55838
|
-
|
|
55839
|
-
|
|
55900
|
+
function normalizedAgentListFilter(filter) {
|
|
55901
|
+
const limit = Number.isFinite(filter.limit) ? Math.max(0, Math.floor(filter.limit)) : undefined;
|
|
55902
|
+
const offset = Number.isFinite(filter.offset) ? Math.max(0, Math.floor(filter.offset)) : undefined;
|
|
55903
|
+
return { limit, offset };
|
|
55904
|
+
}
|
|
55905
|
+
function isDatabaseAdapter(value) {
|
|
55906
|
+
return typeof value === "object" && value !== null && "query" in value && typeof value.query === "function";
|
|
55907
|
+
}
|
|
55908
|
+
function paginatedAgentQuery(baseSql, baseParams, filter) {
|
|
55909
|
+
const { limit, offset } = normalizedAgentListFilter(filter);
|
|
55910
|
+
let sql = `${baseSql} ORDER BY created_at ASC, id ASC`;
|
|
55911
|
+
const params = [...baseParams];
|
|
55912
|
+
if (limit !== undefined) {
|
|
55913
|
+
sql += " LIMIT ?";
|
|
55914
|
+
params.push(limit);
|
|
55915
|
+
} else if ((offset ?? 0) > 0) {
|
|
55916
|
+
sql += " LIMIT ?";
|
|
55917
|
+
params.push(UNBOUNDED_AGENT_LIST_LIMIT);
|
|
55918
|
+
}
|
|
55919
|
+
if ((offset ?? 0) > 0) {
|
|
55920
|
+
sql += " OFFSET ?";
|
|
55921
|
+
params.push(offset);
|
|
55922
|
+
}
|
|
55923
|
+
return { sql, params };
|
|
55924
|
+
}
|
|
55925
|
+
function listAgents(filterOrDb = {}, db) {
|
|
55926
|
+
const explicitDb = isDatabaseAdapter(filterOrDb) ? filterOrDb : db;
|
|
55927
|
+
const filter = isDatabaseAdapter(filterOrDb) ? {} : filterOrDb;
|
|
55928
|
+
const normalized = normalizedAgentListFilter(filter);
|
|
55929
|
+
if (!explicitDb && isApiMode()) {
|
|
55930
|
+
const q = toQuery({
|
|
55931
|
+
limit: normalized.limit,
|
|
55932
|
+
offset: normalized.offset
|
|
55933
|
+
});
|
|
55934
|
+
const { data } = apiJson("GET", `/agents${q}`);
|
|
55840
55935
|
return data?.agents ?? [];
|
|
55841
55936
|
}
|
|
55842
|
-
const d =
|
|
55843
|
-
const
|
|
55937
|
+
const d = explicitDb || getDatabase();
|
|
55938
|
+
const { sql, params } = paginatedAgentQuery("SELECT * FROM agents", [], normalized);
|
|
55939
|
+
const rows = d.query(sql).all(...params);
|
|
55844
55940
|
return rows.map(parseAgentRow);
|
|
55845
55941
|
}
|
|
55846
55942
|
function touchAgent(idOrName, db) {
|
|
@@ -55857,15 +55953,19 @@ function touchAgent(idOrName, db) {
|
|
|
55857
55953
|
return;
|
|
55858
55954
|
d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [now(), agent.id]);
|
|
55859
55955
|
}
|
|
55860
|
-
function listAgentsByProject(projectId, db) {
|
|
55861
|
-
|
|
55862
|
-
|
|
55956
|
+
function listAgentsByProject(projectId, filterOrDb = {}, db) {
|
|
55957
|
+
const explicitDb = isDatabaseAdapter(filterOrDb) ? filterOrDb : db;
|
|
55958
|
+
const filter = isDatabaseAdapter(filterOrDb) ? {} : filterOrDb;
|
|
55959
|
+
const normalized = normalizedAgentListFilter(filter);
|
|
55960
|
+
if (!explicitDb && isApiMode()) {
|
|
55961
|
+
const q = toQuery({ project_id: projectId, ...normalized });
|
|
55863
55962
|
const { data } = apiJson("GET", `/agents${q}`);
|
|
55864
55963
|
return data?.agents ?? [];
|
|
55865
55964
|
}
|
|
55866
|
-
const d =
|
|
55965
|
+
const d = explicitDb || getDatabase();
|
|
55867
55966
|
const resolvedId = resolvePartialId(d, "projects", projectId) || projectId;
|
|
55868
|
-
const
|
|
55967
|
+
const { sql, params } = paginatedAgentQuery("SELECT * FROM agents WHERE active_project_id = ?", [resolvedId], normalized);
|
|
55968
|
+
const rows = d.query(sql).all(...params);
|
|
55869
55969
|
return rows.map(parseAgentRow);
|
|
55870
55970
|
}
|
|
55871
55971
|
function updateAgent(id, updates, db) {
|
package/dist/server/index.js
CHANGED
|
@@ -1722,6 +1722,39 @@ INSERT OR IGNORE INTO _migrations (id) VALUES (35);
|
|
|
1722
1722
|
`
|
|
1723
1723
|
${MEMORY_VERSION_SNAPSHOT_TRIGGER}
|
|
1724
1724
|
INSERT OR IGNORE INTO _migrations (id) VALUES (36);
|
|
1725
|
+
`,
|
|
1726
|
+
`
|
|
1727
|
+
DROP TRIGGER IF EXISTS audit_memory_insert;
|
|
1728
|
+
CREATE TRIGGER audit_memory_insert AFTER INSERT ON memories BEGIN
|
|
1729
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, created_at)
|
|
1730
|
+
VALUES (hex(randomblob(4)), new.id, new.key, 'create', new.agent_id, datetime('now'));
|
|
1731
|
+
END;
|
|
1732
|
+
|
|
1733
|
+
DROP TRIGGER IF EXISTS audit_memory_update;
|
|
1734
|
+
CREATE TRIGGER audit_memory_update AFTER UPDATE ON memories BEGIN
|
|
1735
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, changes, created_at)
|
|
1736
|
+
VALUES (hex(randomblob(4)), new.id, new.key, 'update', new.agent_id,
|
|
1737
|
+
json_object('version_from', old.version, 'version_to', new.version, 'importance_from', old.importance, 'importance_to', new.importance),
|
|
1738
|
+
datetime('now'));
|
|
1739
|
+
END;
|
|
1740
|
+
|
|
1741
|
+
DROP TRIGGER IF EXISTS audit_memory_delete;
|
|
1742
|
+
CREATE TRIGGER audit_memory_delete AFTER DELETE ON memories BEGIN
|
|
1743
|
+
INSERT INTO memory_audit_log (id, memory_id, memory_key, operation, agent_id, created_at)
|
|
1744
|
+
VALUES (hex(randomblob(4)), old.id, old.key, 'delete', old.agent_id, datetime('now'));
|
|
1745
|
+
END;
|
|
1746
|
+
|
|
1747
|
+
UPDATE memory_audit_log SET old_value_hash = NULL
|
|
1748
|
+
WHERE old_value_hash IS NOT NULL
|
|
1749
|
+
AND length(old_value_hash) = 32
|
|
1750
|
+
AND old_value_hash NOT GLOB '*[^0-9A-F]*';
|
|
1751
|
+
|
|
1752
|
+
UPDATE memory_audit_log SET new_value_hash = NULL
|
|
1753
|
+
WHERE new_value_hash IS NOT NULL
|
|
1754
|
+
AND length(new_value_hash) = 32
|
|
1755
|
+
AND new_value_hash NOT GLOB '*[^0-9A-F]*';
|
|
1756
|
+
|
|
1757
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (37);
|
|
1725
1758
|
`
|
|
1726
1759
|
];
|
|
1727
1760
|
});
|
|
@@ -56147,6 +56180,7 @@ init_types();
|
|
|
56147
56180
|
init_database();
|
|
56148
56181
|
init_api_mode();
|
|
56149
56182
|
var CONFLICT_WINDOW_MS = 30 * 60 * 1000;
|
|
56183
|
+
var UNBOUNDED_AGENT_LIST_LIMIT = Number.MAX_SAFE_INTEGER;
|
|
56150
56184
|
function parseAgentRow(row) {
|
|
56151
56185
|
return {
|
|
56152
56186
|
id: row["id"],
|
|
@@ -56238,24 +56272,61 @@ function getAgent(idOrName, db) {
|
|
|
56238
56272
|
return parseAgentRow(rows[0]);
|
|
56239
56273
|
return null;
|
|
56240
56274
|
}
|
|
56241
|
-
function
|
|
56242
|
-
|
|
56243
|
-
|
|
56275
|
+
function normalizedAgentListFilter(filter) {
|
|
56276
|
+
const limit = Number.isFinite(filter.limit) ? Math.max(0, Math.floor(filter.limit)) : undefined;
|
|
56277
|
+
const offset = Number.isFinite(filter.offset) ? Math.max(0, Math.floor(filter.offset)) : undefined;
|
|
56278
|
+
return { limit, offset };
|
|
56279
|
+
}
|
|
56280
|
+
function isDatabaseAdapter(value) {
|
|
56281
|
+
return typeof value === "object" && value !== null && "query" in value && typeof value.query === "function";
|
|
56282
|
+
}
|
|
56283
|
+
function paginatedAgentQuery(baseSql, baseParams, filter) {
|
|
56284
|
+
const { limit, offset } = normalizedAgentListFilter(filter);
|
|
56285
|
+
let sql = `${baseSql} ORDER BY created_at ASC, id ASC`;
|
|
56286
|
+
const params = [...baseParams];
|
|
56287
|
+
if (limit !== undefined) {
|
|
56288
|
+
sql += " LIMIT ?";
|
|
56289
|
+
params.push(limit);
|
|
56290
|
+
} else if ((offset ?? 0) > 0) {
|
|
56291
|
+
sql += " LIMIT ?";
|
|
56292
|
+
params.push(UNBOUNDED_AGENT_LIST_LIMIT);
|
|
56293
|
+
}
|
|
56294
|
+
if ((offset ?? 0) > 0) {
|
|
56295
|
+
sql += " OFFSET ?";
|
|
56296
|
+
params.push(offset);
|
|
56297
|
+
}
|
|
56298
|
+
return { sql, params };
|
|
56299
|
+
}
|
|
56300
|
+
function listAgents(filterOrDb = {}, db) {
|
|
56301
|
+
const explicitDb = isDatabaseAdapter(filterOrDb) ? filterOrDb : db;
|
|
56302
|
+
const filter = isDatabaseAdapter(filterOrDb) ? {} : filterOrDb;
|
|
56303
|
+
const normalized = normalizedAgentListFilter(filter);
|
|
56304
|
+
if (!explicitDb && isApiMode()) {
|
|
56305
|
+
const q = toQuery({
|
|
56306
|
+
limit: normalized.limit,
|
|
56307
|
+
offset: normalized.offset
|
|
56308
|
+
});
|
|
56309
|
+
const { data } = apiJson("GET", `/agents${q}`);
|
|
56244
56310
|
return data?.agents ?? [];
|
|
56245
56311
|
}
|
|
56246
|
-
const d =
|
|
56247
|
-
const
|
|
56312
|
+
const d = explicitDb || getDatabase();
|
|
56313
|
+
const { sql, params } = paginatedAgentQuery("SELECT * FROM agents", [], normalized);
|
|
56314
|
+
const rows = d.query(sql).all(...params);
|
|
56248
56315
|
return rows.map(parseAgentRow);
|
|
56249
56316
|
}
|
|
56250
|
-
function listAgentsByProject(projectId, db) {
|
|
56251
|
-
|
|
56252
|
-
|
|
56317
|
+
function listAgentsByProject(projectId, filterOrDb = {}, db) {
|
|
56318
|
+
const explicitDb = isDatabaseAdapter(filterOrDb) ? filterOrDb : db;
|
|
56319
|
+
const filter = isDatabaseAdapter(filterOrDb) ? {} : filterOrDb;
|
|
56320
|
+
const normalized = normalizedAgentListFilter(filter);
|
|
56321
|
+
if (!explicitDb && isApiMode()) {
|
|
56322
|
+
const q = toQuery({ project_id: projectId, ...normalized });
|
|
56253
56323
|
const { data } = apiJson("GET", `/agents${q}`);
|
|
56254
56324
|
return data?.agents ?? [];
|
|
56255
56325
|
}
|
|
56256
|
-
const d =
|
|
56326
|
+
const d = explicitDb || getDatabase();
|
|
56257
56327
|
const resolvedId = resolvePartialId(d, "projects", projectId) || projectId;
|
|
56258
|
-
const
|
|
56328
|
+
const { sql, params } = paginatedAgentQuery("SELECT * FROM agents WHERE active_project_id = ?", [resolvedId], normalized);
|
|
56329
|
+
const rows = d.query(sql).all(...params);
|
|
56259
56330
|
return rows.map(parseAgentRow);
|
|
56260
56331
|
}
|
|
56261
56332
|
function updateAgent(id, updates, db) {
|
|
@@ -56418,9 +56489,21 @@ function cleanExpiredLocks(db) {
|
|
|
56418
56489
|
|
|
56419
56490
|
// src/server/routes/agents.ts
|
|
56420
56491
|
init_router();
|
|
56492
|
+
function paginationInt(value) {
|
|
56493
|
+
if (value === undefined)
|
|
56494
|
+
return;
|
|
56495
|
+
const parsed = Number(value);
|
|
56496
|
+
if (!Number.isFinite(parsed) || parsed < 0)
|
|
56497
|
+
return;
|
|
56498
|
+
return Math.floor(parsed);
|
|
56499
|
+
}
|
|
56421
56500
|
addRoute("GET", "/api/agents", (_req, url) => {
|
|
56422
56501
|
const q = getSearchParams(url);
|
|
56423
|
-
const
|
|
56502
|
+
const pagination = {
|
|
56503
|
+
limit: paginationInt(q["limit"]),
|
|
56504
|
+
offset: paginationInt(q["cursor"] ?? q["offset"])
|
|
56505
|
+
};
|
|
56506
|
+
const agents = q["project_id"] ? listAgentsByProject(q["project_id"], pagination) : listAgents(pagination);
|
|
56424
56507
|
if (q["fields"]) {
|
|
56425
56508
|
const fields = q["fields"].split(",").map((f) => f.trim());
|
|
56426
56509
|
const filtered = agents.map((a) => Object.fromEntries(fields.map((f) => [f, a[f]]).filter(([, v]) => v !== undefined)));
|