@signetai/signet-memory-openclaw 0.211.16 → 0.211.20

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.
Files changed (2) hide show
  1. package/dist/index.js +669 -27
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15992,6 +15992,319 @@ function up137(db) {
15992
15992
  if (!cols.has(name))
15993
15993
  db.exec(`ALTER TABLE dreaming_passes ADD COLUMN ${name} ${type}`);
15994
15994
  }
15995
+ function hasColumn25(db, table, column) {
15996
+ const rows = db.prepare(`PRAGMA table_info(${table})`).all();
15997
+ return rows.some((row) => row.name === column);
15998
+ }
15999
+ function addColumnIfMissing27(db, table, column, definition) {
16000
+ if (!hasColumn25(db, table, column))
16001
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
16002
+ }
16003
+ function up138(db) {
16004
+ addColumnIfMissing27(db, "memories", "manual_override", "INTEGER DEFAULT 0");
16005
+ db.exec(`
16006
+ CREATE TABLE IF NOT EXISTS transcript_capture_status (
16007
+ agent_id TEXT PRIMARY KEY,
16008
+ pending INTEGER NOT NULL DEFAULT 0,
16009
+ processing INTEGER NOT NULL DEFAULT 0,
16010
+ completed INTEGER NOT NULL DEFAULT 0,
16011
+ failed INTEGER NOT NULL DEFAULT 0,
16012
+ dead INTEGER NOT NULL DEFAULT 0,
16013
+ oldest_pending_at TEXT,
16014
+ last_error TEXT,
16015
+ last_error_at TEXT
16016
+ );
16017
+
16018
+ CREATE INDEX IF NOT EXISTS idx_transcript_capture_jobs_agent_status_created_at
16019
+ ON transcript_capture_jobs(agent_id, status, created_at);
16020
+
16021
+ CREATE INDEX IF NOT EXISTS idx_transcript_capture_jobs_error_updated_at
16022
+ ON transcript_capture_jobs(agent_id, updated_at DESC)
16023
+ WHERE error IS NOT NULL;
16024
+
16025
+ CREATE TABLE IF NOT EXISTS memories_duplicate_hash_counts (
16026
+ content_hash TEXT PRIMARY KEY,
16027
+ dup_count INTEGER NOT NULL
16028
+ );
16029
+
16030
+ CREATE INDEX IF NOT EXISTS idx_memories_dup_counts_active
16031
+ ON memories_duplicate_hash_counts(dup_count)
16032
+ WHERE dup_count > 1;
16033
+
16034
+ CREATE TABLE IF NOT EXISTS memories_diagnostics_state (
16035
+ id INTEGER PRIMARY KEY CHECK (id = 1),
16036
+ total_active INTEGER NOT NULL DEFAULT 0,
16037
+ exact_duplicates INTEGER NOT NULL DEFAULT 0,
16038
+ exact_clusters INTEGER NOT NULL DEFAULT 0
16039
+ );
16040
+
16041
+ CREATE INDEX IF NOT EXISTS idx_memories_active_hash_diagnostics
16042
+ ON memories(content_hash)
16043
+ WHERE is_deleted = 0
16044
+ AND content_hash IS NOT NULL
16045
+ AND pinned = 0
16046
+ AND manual_override = 0;
16047
+ `);
16048
+ db.exec(`
16049
+ CREATE TRIGGER IF NOT EXISTS transcript_capture_status_ai
16050
+ AFTER INSERT ON transcript_capture_jobs
16051
+ BEGIN
16052
+ INSERT INTO transcript_capture_status (agent_id)
16053
+ VALUES (NEW.agent_id)
16054
+ ON CONFLICT(agent_id) DO NOTHING;
16055
+
16056
+ UPDATE transcript_capture_status
16057
+ SET pending = pending + (NEW.status = 'pending'),
16058
+ processing = processing + (NEW.status = 'processing'),
16059
+ completed = completed + (NEW.status = 'completed'),
16060
+ failed = failed + (NEW.status = 'failed'),
16061
+ dead = dead + (NEW.status = 'dead')
16062
+ WHERE agent_id = NEW.agent_id;
16063
+
16064
+ UPDATE transcript_capture_status
16065
+ SET oldest_pending_at = (
16066
+ SELECT MIN(created_at) FROM transcript_capture_jobs
16067
+ WHERE agent_id = NEW.agent_id AND status = 'pending'
16068
+ )
16069
+ WHERE agent_id = NEW.agent_id;
16070
+
16071
+ UPDATE transcript_capture_status
16072
+ SET last_error = (
16073
+ SELECT error FROM transcript_capture_jobs
16074
+ WHERE agent_id = NEW.agent_id AND error IS NOT NULL
16075
+ ORDER BY updated_at DESC LIMIT 1
16076
+ ),
16077
+ last_error_at = (
16078
+ SELECT updated_at FROM transcript_capture_jobs
16079
+ WHERE agent_id = NEW.agent_id AND error IS NOT NULL
16080
+ ORDER BY updated_at DESC LIMIT 1
16081
+ )
16082
+ WHERE agent_id = NEW.agent_id
16083
+ AND NEW.error IS NOT NULL;
16084
+ END;
16085
+
16086
+ CREATE TRIGGER IF NOT EXISTS transcript_capture_status_au
16087
+ AFTER UPDATE OF status, error, updated_at, created_at ON transcript_capture_jobs
16088
+ BEGIN
16089
+ UPDATE transcript_capture_status
16090
+ SET pending = pending + (NEW.status = 'pending') - (OLD.status = 'pending'),
16091
+ processing = processing + (NEW.status = 'processing') - (OLD.status = 'processing'),
16092
+ completed = completed + (NEW.status = 'completed') - (OLD.status = 'completed'),
16093
+ failed = failed + (NEW.status = 'failed') - (OLD.status = 'failed'),
16094
+ dead = dead + (NEW.status = 'dead') - (OLD.status = 'dead')
16095
+ WHERE agent_id = NEW.agent_id;
16096
+
16097
+ UPDATE transcript_capture_status
16098
+ SET oldest_pending_at = (
16099
+ SELECT MIN(created_at) FROM transcript_capture_jobs
16100
+ WHERE agent_id = NEW.agent_id AND status = 'pending'
16101
+ )
16102
+ WHERE agent_id = NEW.agent_id;
16103
+
16104
+ UPDATE transcript_capture_status
16105
+ SET last_error = (
16106
+ SELECT error FROM transcript_capture_jobs
16107
+ WHERE agent_id = NEW.agent_id AND error IS NOT NULL
16108
+ ORDER BY updated_at DESC LIMIT 1
16109
+ ),
16110
+ last_error_at = (
16111
+ SELECT updated_at FROM transcript_capture_jobs
16112
+ WHERE agent_id = NEW.agent_id AND error IS NOT NULL
16113
+ ORDER BY updated_at DESC LIMIT 1
16114
+ )
16115
+ WHERE agent_id = NEW.agent_id
16116
+ AND (NEW.error IS NOT NULL OR OLD.error IS NOT NULL);
16117
+ END;
16118
+
16119
+ CREATE TRIGGER IF NOT EXISTS transcript_capture_status_ad
16120
+ AFTER DELETE ON transcript_capture_jobs
16121
+ BEGIN
16122
+ UPDATE transcript_capture_status
16123
+ SET pending = pending - (OLD.status = 'pending'),
16124
+ processing = processing - (OLD.status = 'processing'),
16125
+ completed = completed - (OLD.status = 'completed'),
16126
+ failed = failed - (OLD.status = 'failed'),
16127
+ dead = dead - (OLD.status = 'dead')
16128
+ WHERE agent_id = OLD.agent_id;
16129
+
16130
+ UPDATE transcript_capture_status
16131
+ SET oldest_pending_at = (
16132
+ SELECT MIN(created_at) FROM transcript_capture_jobs
16133
+ WHERE agent_id = OLD.agent_id AND status = 'pending'
16134
+ )
16135
+ WHERE agent_id = OLD.agent_id;
16136
+
16137
+ UPDATE transcript_capture_status
16138
+ SET last_error = (
16139
+ SELECT error FROM transcript_capture_jobs
16140
+ WHERE agent_id = OLD.agent_id AND error IS NOT NULL
16141
+ ORDER BY updated_at DESC LIMIT 1
16142
+ ),
16143
+ last_error_at = (
16144
+ SELECT updated_at FROM transcript_capture_jobs
16145
+ WHERE agent_id = OLD.agent_id AND error IS NOT NULL
16146
+ ORDER BY updated_at DESC LIMIT 1
16147
+ )
16148
+ WHERE agent_id = OLD.agent_id
16149
+ AND OLD.error IS NOT NULL;
16150
+ END;
16151
+ `);
16152
+ db.exec(`
16153
+ CREATE TRIGGER IF NOT EXISTS memories_dup_projection_ai
16154
+ AFTER INSERT ON memories
16155
+ BEGIN
16156
+ UPDATE memories_diagnostics_state
16157
+ SET total_active = total_active + CASE WHEN NEW.is_deleted = 0 THEN 1 ELSE 0 END,
16158
+ exact_duplicates = exact_duplicates + CASE
16159
+ WHEN NEW.is_deleted = 0 AND NEW.content_hash IS NOT NULL
16160
+ AND NEW.pinned = 0 AND NEW.manual_override = 0
16161
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = NEW.content_hash), 0) >= 1
16162
+ THEN 1 ELSE 0 END,
16163
+ exact_clusters = exact_clusters + CASE
16164
+ WHEN NEW.is_deleted = 0 AND NEW.content_hash IS NOT NULL
16165
+ AND NEW.pinned = 0 AND NEW.manual_override = 0
16166
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = NEW.content_hash), 0) = 1
16167
+ THEN 1 ELSE 0 END
16168
+ WHERE id = 1;
16169
+
16170
+ INSERT INTO memories_duplicate_hash_counts (content_hash, dup_count)
16171
+ SELECT NEW.content_hash, 1
16172
+ WHERE NEW.is_deleted = 0
16173
+ AND NEW.content_hash IS NOT NULL
16174
+ AND NEW.pinned = 0
16175
+ AND NEW.manual_override = 0
16176
+ ON CONFLICT(content_hash) DO UPDATE SET dup_count = dup_count + 1;
16177
+ END;
16178
+
16179
+ CREATE TRIGGER IF NOT EXISTS memories_dup_projection_au
16180
+ AFTER UPDATE OF is_deleted, content_hash, pinned, manual_override ON memories
16181
+ BEGIN
16182
+ UPDATE memories_diagnostics_state
16183
+ SET total_active = total_active
16184
+ + CASE WHEN NEW.is_deleted = 0 THEN 1 ELSE 0 END
16185
+ - CASE WHEN OLD.is_deleted = 0 THEN 1 ELSE 0 END,
16186
+ exact_duplicates = exact_duplicates - CASE
16187
+ WHEN OLD.is_deleted = 0 AND OLD.content_hash IS NOT NULL
16188
+ AND OLD.pinned = 0 AND OLD.manual_override = 0
16189
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = OLD.content_hash), 0) > 1
16190
+ THEN 1 ELSE 0 END,
16191
+ exact_clusters = exact_clusters - CASE
16192
+ WHEN OLD.is_deleted = 0 AND OLD.content_hash IS NOT NULL
16193
+ AND OLD.pinned = 0 AND OLD.manual_override = 0
16194
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = OLD.content_hash), 0) = 2
16195
+ THEN 1 ELSE 0 END
16196
+ WHERE id = 1;
16197
+
16198
+ UPDATE memories_duplicate_hash_counts
16199
+ SET dup_count = dup_count - 1
16200
+ WHERE OLD.is_deleted = 0
16201
+ AND OLD.content_hash IS NOT NULL
16202
+ AND OLD.pinned = 0
16203
+ AND OLD.manual_override = 0
16204
+ AND content_hash = OLD.content_hash;
16205
+
16206
+ DELETE FROM memories_duplicate_hash_counts
16207
+ WHERE content_hash = OLD.content_hash
16208
+ AND dup_count <= 0;
16209
+
16210
+ UPDATE memories_diagnostics_state
16211
+ SET exact_duplicates = exact_duplicates + CASE
16212
+ WHEN NEW.is_deleted = 0 AND NEW.content_hash IS NOT NULL
16213
+ AND NEW.pinned = 0 AND NEW.manual_override = 0
16214
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = NEW.content_hash), 0) >= 1
16215
+ THEN 1 ELSE 0 END,
16216
+ exact_clusters = exact_clusters + CASE
16217
+ WHEN NEW.is_deleted = 0 AND NEW.content_hash IS NOT NULL
16218
+ AND NEW.pinned = 0 AND NEW.manual_override = 0
16219
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = NEW.content_hash), 0) = 1
16220
+ THEN 1 ELSE 0 END
16221
+ WHERE id = 1;
16222
+
16223
+ INSERT INTO memories_duplicate_hash_counts (content_hash, dup_count)
16224
+ SELECT NEW.content_hash, 1
16225
+ WHERE NEW.is_deleted = 0
16226
+ AND NEW.content_hash IS NOT NULL
16227
+ AND NEW.pinned = 0
16228
+ AND NEW.manual_override = 0
16229
+ ON CONFLICT(content_hash) DO UPDATE SET dup_count = dup_count + 1;
16230
+ END;
16231
+
16232
+ CREATE TRIGGER IF NOT EXISTS memories_dup_projection_ad
16233
+ AFTER DELETE ON memories
16234
+ BEGIN
16235
+ UPDATE memories_diagnostics_state
16236
+ SET total_active = total_active - CASE WHEN OLD.is_deleted = 0 THEN 1 ELSE 0 END,
16237
+ exact_duplicates = exact_duplicates - CASE
16238
+ WHEN OLD.is_deleted = 0 AND OLD.content_hash IS NOT NULL
16239
+ AND OLD.pinned = 0 AND OLD.manual_override = 0
16240
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = OLD.content_hash), 0) > 1
16241
+ THEN 1 ELSE 0 END,
16242
+ exact_clusters = exact_clusters - CASE
16243
+ WHEN OLD.is_deleted = 0 AND OLD.content_hash IS NOT NULL
16244
+ AND OLD.pinned = 0 AND OLD.manual_override = 0
16245
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = OLD.content_hash), 0) = 2
16246
+ THEN 1 ELSE 0 END
16247
+ WHERE id = 1;
16248
+
16249
+ UPDATE memories_duplicate_hash_counts
16250
+ SET dup_count = dup_count - 1
16251
+ WHERE OLD.is_deleted = 0
16252
+ AND OLD.content_hash IS NOT NULL
16253
+ AND OLD.pinned = 0
16254
+ AND OLD.manual_override = 0
16255
+ AND content_hash = OLD.content_hash;
16256
+
16257
+ DELETE FROM memories_duplicate_hash_counts
16258
+ WHERE content_hash = OLD.content_hash
16259
+ AND dup_count <= 0;
16260
+ END;
16261
+ `);
16262
+ db.exec(`
16263
+ DELETE FROM transcript_capture_status;
16264
+ DELETE FROM memories_duplicate_hash_counts;
16265
+ INSERT INTO memories_duplicate_hash_counts (content_hash, dup_count)
16266
+ SELECT content_hash, COUNT(*)
16267
+ FROM memories
16268
+ WHERE is_deleted = 0
16269
+ AND content_hash IS NOT NULL
16270
+ AND pinned = 0
16271
+ AND manual_override = 0
16272
+ GROUP BY content_hash;
16273
+
16274
+ INSERT INTO memories_diagnostics_state (id, total_active, exact_duplicates, exact_clusters)
16275
+ VALUES (
16276
+ 1,
16277
+ (SELECT COUNT(*) FROM memories WHERE is_deleted = 0),
16278
+ COALESCE((SELECT SUM(dup_count - 1) FROM memories_duplicate_hash_counts WHERE dup_count > 1), 0),
16279
+ (SELECT COUNT(*) FROM memories_duplicate_hash_counts WHERE dup_count > 1)
16280
+ )
16281
+ ON CONFLICT(id) DO UPDATE SET
16282
+ total_active = excluded.total_active,
16283
+ exact_duplicates = excluded.exact_duplicates,
16284
+ exact_clusters = excluded.exact_clusters;
16285
+
16286
+ INSERT INTO transcript_capture_status (
16287
+ agent_id, pending, processing, completed, failed, dead,
16288
+ oldest_pending_at, last_error, last_error_at
16289
+ )
16290
+ SELECT
16291
+ j.agent_id,
16292
+ SUM(j.status = 'pending'),
16293
+ SUM(j.status = 'processing'),
16294
+ SUM(j.status = 'completed'),
16295
+ SUM(j.status = 'failed'),
16296
+ SUM(j.status = 'dead'),
16297
+ MIN(CASE WHEN j.status = 'pending' THEN j.created_at END),
16298
+ (SELECT e2.error FROM transcript_capture_jobs e2
16299
+ WHERE e2.agent_id = j.agent_id AND e2.error IS NOT NULL
16300
+ ORDER BY e2.updated_at DESC LIMIT 1),
16301
+ (SELECT e3.updated_at FROM transcript_capture_jobs e3
16302
+ WHERE e3.agent_id = j.agent_id AND e3.error IS NOT NULL
16303
+ ORDER BY e3.updated_at DESC LIMIT 1)
16304
+ FROM transcript_capture_jobs j
16305
+ GROUP BY j.agent_id;
16306
+ `);
16307
+ }
15995
16308
  var MIGRATIONS = [
15996
16309
  {
15997
16310
  version: 1,
@@ -17081,6 +17394,14 @@ var MIGRATIONS = [
17081
17394
  { table: "dreaming_passes", column: "head_hash" }
17082
17395
  ]
17083
17396
  }
17397
+ },
17398
+ {
17399
+ version: 138,
17400
+ name: "bounded-status-projections",
17401
+ up: up138,
17402
+ artifacts: {
17403
+ tables: ["transcript_capture_status", "memories_duplicate_hash_counts", "memories_diagnostics_state"]
17404
+ }
17084
17405
  }
17085
17406
  ];
17086
17407
  var LATEST_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
@@ -29059,7 +29380,7 @@ function memoriesFtsNeedsTokenizerRepair2(sql) {
29059
29380
  return true;
29060
29381
  return !normalized.includes(`tokenize='${MEMORIES_FTS_TOKENIZER2}'`);
29061
29382
  }
29062
- function up138(db) {
29383
+ function up139(db) {
29063
29384
  db.exec(`
29064
29385
  CREATE TABLE IF NOT EXISTS schema_migrations (
29065
29386
  version INTEGER PRIMARY KEY,
@@ -29148,31 +29469,31 @@ function up138(db) {
29148
29469
  } catch {}
29149
29470
  createMemoriesFts2(db);
29150
29471
  }
29151
- function hasColumn25(db, table, column) {
29472
+ function hasColumn26(db, table, column) {
29152
29473
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
29153
29474
  return rows.some((r22) => r22.name === column);
29154
29475
  }
29155
- function addColumnIfMissing27(db, table, column, definition) {
29156
- if (!hasColumn25(db, table, column)) {
29476
+ function addColumnIfMissing28(db, table, column, definition) {
29477
+ if (!hasColumn26(db, table, column)) {
29157
29478
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
29158
29479
  }
29159
29480
  }
29160
29481
  function up210(db) {
29161
- addColumnIfMissing27(db, "memories", "content_hash", "TEXT");
29162
- addColumnIfMissing27(db, "memories", "normalized_content", "TEXT");
29163
- addColumnIfMissing27(db, "memories", "is_deleted", "INTEGER DEFAULT 0");
29164
- addColumnIfMissing27(db, "memories", "deleted_at", "TEXT");
29165
- addColumnIfMissing27(db, "memories", "extraction_status", "TEXT DEFAULT 'none'");
29166
- addColumnIfMissing27(db, "memories", "embedding_model", "TEXT");
29167
- addColumnIfMissing27(db, "memories", "extraction_model", "TEXT");
29168
- addColumnIfMissing27(db, "memories", "update_count", "INTEGER DEFAULT 0");
29169
- addColumnIfMissing27(db, "memories", "who", "TEXT");
29170
- addColumnIfMissing27(db, "memories", "why", "TEXT");
29171
- addColumnIfMissing27(db, "memories", "project", "TEXT");
29172
- addColumnIfMissing27(db, "memories", "pinned", "INTEGER DEFAULT 0");
29173
- addColumnIfMissing27(db, "memories", "importance", "REAL DEFAULT 0.5");
29174
- addColumnIfMissing27(db, "memories", "last_accessed", "TEXT");
29175
- addColumnIfMissing27(db, "memories", "access_count", "INTEGER DEFAULT 0");
29482
+ addColumnIfMissing28(db, "memories", "content_hash", "TEXT");
29483
+ addColumnIfMissing28(db, "memories", "normalized_content", "TEXT");
29484
+ addColumnIfMissing28(db, "memories", "is_deleted", "INTEGER DEFAULT 0");
29485
+ addColumnIfMissing28(db, "memories", "deleted_at", "TEXT");
29486
+ addColumnIfMissing28(db, "memories", "extraction_status", "TEXT DEFAULT 'none'");
29487
+ addColumnIfMissing28(db, "memories", "embedding_model", "TEXT");
29488
+ addColumnIfMissing28(db, "memories", "extraction_model", "TEXT");
29489
+ addColumnIfMissing28(db, "memories", "update_count", "INTEGER DEFAULT 0");
29490
+ addColumnIfMissing28(db, "memories", "who", "TEXT");
29491
+ addColumnIfMissing28(db, "memories", "why", "TEXT");
29492
+ addColumnIfMissing28(db, "memories", "project", "TEXT");
29493
+ addColumnIfMissing28(db, "memories", "pinned", "INTEGER DEFAULT 0");
29494
+ addColumnIfMissing28(db, "memories", "importance", "REAL DEFAULT 0.5");
29495
+ addColumnIfMissing28(db, "memories", "last_accessed", "TEXT");
29496
+ addColumnIfMissing28(db, "memories", "access_count", "INTEGER DEFAULT 0");
29176
29497
  db.exec(`
29177
29498
  CREATE TABLE IF NOT EXISTS memory_history (
29178
29499
  id TEXT PRIMARY KEY,
@@ -29268,7 +29589,7 @@ function up210(db) {
29268
29589
  ON memory_entity_mentions(entity_id);
29269
29590
  `);
29270
29591
  }
29271
- function addColumnIfMissing28(db, table, column, definition) {
29592
+ function addColumnIfMissing29(db, table, column, definition) {
29272
29593
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
29273
29594
  if (rows.some((r22) => r22.name === column))
29274
29595
  return false;
@@ -29276,8 +29597,8 @@ function addColumnIfMissing28(db, table, column, definition) {
29276
29597
  return true;
29277
29598
  }
29278
29599
  function up310(db) {
29279
- addColumnIfMissing28(db, "memories", "why", "TEXT");
29280
- addColumnIfMissing28(db, "memories", "project", "TEXT");
29600
+ addColumnIfMissing29(db, "memories", "why", "TEXT");
29601
+ addColumnIfMissing29(db, "memories", "project", "TEXT");
29281
29602
  db.exec(`DROP INDEX IF EXISTS idx_memories_content_hash`);
29282
29603
  db.exec(`
29283
29604
  UPDATE memories
@@ -29303,12 +29624,12 @@ function up310(db) {
29303
29624
  WHERE content_hash IS NOT NULL AND is_deleted = 0
29304
29625
  `);
29305
29626
  }
29306
- function hasColumn26(db, table, column) {
29627
+ function hasColumn27(db, table, column) {
29307
29628
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
29308
29629
  return rows.some((r22) => r22.name === column);
29309
29630
  }
29310
29631
  function addColumnIfMissing32(db, table, column, definition) {
29311
- if (!hasColumn26(db, table, column)) {
29632
+ if (!hasColumn27(db, table, column)) {
29312
29633
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
29313
29634
  }
29314
29635
  }
@@ -29543,7 +29864,7 @@ function addColumnIfMissing52(db, table, column, definition) {
29543
29864
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
29544
29865
  }
29545
29866
  }
29546
- function up139(db) {
29867
+ function up1310(db) {
29547
29868
  db.exec(`
29548
29869
  CREATE TABLE IF NOT EXISTS ingestion_jobs (
29549
29870
  id TEXT PRIMARY KEY,
@@ -33412,11 +33733,324 @@ function up1372(db) {
33412
33733
  if (!cols.has(name))
33413
33734
  db.exec(`ALTER TABLE dreaming_passes ADD COLUMN ${name} ${type}`);
33414
33735
  }
33736
+ function hasColumn252(db, table, column) {
33737
+ const rows = db.prepare(`PRAGMA table_info(${table})`).all();
33738
+ return rows.some((row) => row.name === column);
33739
+ }
33740
+ function addColumnIfMissing272(db, table, column, definition) {
33741
+ if (!hasColumn252(db, table, column))
33742
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
33743
+ }
33744
+ function up1382(db) {
33745
+ addColumnIfMissing272(db, "memories", "manual_override", "INTEGER DEFAULT 0");
33746
+ db.exec(`
33747
+ CREATE TABLE IF NOT EXISTS transcript_capture_status (
33748
+ agent_id TEXT PRIMARY KEY,
33749
+ pending INTEGER NOT NULL DEFAULT 0,
33750
+ processing INTEGER NOT NULL DEFAULT 0,
33751
+ completed INTEGER NOT NULL DEFAULT 0,
33752
+ failed INTEGER NOT NULL DEFAULT 0,
33753
+ dead INTEGER NOT NULL DEFAULT 0,
33754
+ oldest_pending_at TEXT,
33755
+ last_error TEXT,
33756
+ last_error_at TEXT
33757
+ );
33758
+
33759
+ CREATE INDEX IF NOT EXISTS idx_transcript_capture_jobs_agent_status_created_at
33760
+ ON transcript_capture_jobs(agent_id, status, created_at);
33761
+
33762
+ CREATE INDEX IF NOT EXISTS idx_transcript_capture_jobs_error_updated_at
33763
+ ON transcript_capture_jobs(agent_id, updated_at DESC)
33764
+ WHERE error IS NOT NULL;
33765
+
33766
+ CREATE TABLE IF NOT EXISTS memories_duplicate_hash_counts (
33767
+ content_hash TEXT PRIMARY KEY,
33768
+ dup_count INTEGER NOT NULL
33769
+ );
33770
+
33771
+ CREATE INDEX IF NOT EXISTS idx_memories_dup_counts_active
33772
+ ON memories_duplicate_hash_counts(dup_count)
33773
+ WHERE dup_count > 1;
33774
+
33775
+ CREATE TABLE IF NOT EXISTS memories_diagnostics_state (
33776
+ id INTEGER PRIMARY KEY CHECK (id = 1),
33777
+ total_active INTEGER NOT NULL DEFAULT 0,
33778
+ exact_duplicates INTEGER NOT NULL DEFAULT 0,
33779
+ exact_clusters INTEGER NOT NULL DEFAULT 0
33780
+ );
33781
+
33782
+ CREATE INDEX IF NOT EXISTS idx_memories_active_hash_diagnostics
33783
+ ON memories(content_hash)
33784
+ WHERE is_deleted = 0
33785
+ AND content_hash IS NOT NULL
33786
+ AND pinned = 0
33787
+ AND manual_override = 0;
33788
+ `);
33789
+ db.exec(`
33790
+ CREATE TRIGGER IF NOT EXISTS transcript_capture_status_ai
33791
+ AFTER INSERT ON transcript_capture_jobs
33792
+ BEGIN
33793
+ INSERT INTO transcript_capture_status (agent_id)
33794
+ VALUES (NEW.agent_id)
33795
+ ON CONFLICT(agent_id) DO NOTHING;
33796
+
33797
+ UPDATE transcript_capture_status
33798
+ SET pending = pending + (NEW.status = 'pending'),
33799
+ processing = processing + (NEW.status = 'processing'),
33800
+ completed = completed + (NEW.status = 'completed'),
33801
+ failed = failed + (NEW.status = 'failed'),
33802
+ dead = dead + (NEW.status = 'dead')
33803
+ WHERE agent_id = NEW.agent_id;
33804
+
33805
+ UPDATE transcript_capture_status
33806
+ SET oldest_pending_at = (
33807
+ SELECT MIN(created_at) FROM transcript_capture_jobs
33808
+ WHERE agent_id = NEW.agent_id AND status = 'pending'
33809
+ )
33810
+ WHERE agent_id = NEW.agent_id;
33811
+
33812
+ UPDATE transcript_capture_status
33813
+ SET last_error = (
33814
+ SELECT error FROM transcript_capture_jobs
33815
+ WHERE agent_id = NEW.agent_id AND error IS NOT NULL
33816
+ ORDER BY updated_at DESC LIMIT 1
33817
+ ),
33818
+ last_error_at = (
33819
+ SELECT updated_at FROM transcript_capture_jobs
33820
+ WHERE agent_id = NEW.agent_id AND error IS NOT NULL
33821
+ ORDER BY updated_at DESC LIMIT 1
33822
+ )
33823
+ WHERE agent_id = NEW.agent_id
33824
+ AND NEW.error IS NOT NULL;
33825
+ END;
33826
+
33827
+ CREATE TRIGGER IF NOT EXISTS transcript_capture_status_au
33828
+ AFTER UPDATE OF status, error, updated_at, created_at ON transcript_capture_jobs
33829
+ BEGIN
33830
+ UPDATE transcript_capture_status
33831
+ SET pending = pending + (NEW.status = 'pending') - (OLD.status = 'pending'),
33832
+ processing = processing + (NEW.status = 'processing') - (OLD.status = 'processing'),
33833
+ completed = completed + (NEW.status = 'completed') - (OLD.status = 'completed'),
33834
+ failed = failed + (NEW.status = 'failed') - (OLD.status = 'failed'),
33835
+ dead = dead + (NEW.status = 'dead') - (OLD.status = 'dead')
33836
+ WHERE agent_id = NEW.agent_id;
33837
+
33838
+ UPDATE transcript_capture_status
33839
+ SET oldest_pending_at = (
33840
+ SELECT MIN(created_at) FROM transcript_capture_jobs
33841
+ WHERE agent_id = NEW.agent_id AND status = 'pending'
33842
+ )
33843
+ WHERE agent_id = NEW.agent_id;
33844
+
33845
+ UPDATE transcript_capture_status
33846
+ SET last_error = (
33847
+ SELECT error FROM transcript_capture_jobs
33848
+ WHERE agent_id = NEW.agent_id AND error IS NOT NULL
33849
+ ORDER BY updated_at DESC LIMIT 1
33850
+ ),
33851
+ last_error_at = (
33852
+ SELECT updated_at FROM transcript_capture_jobs
33853
+ WHERE agent_id = NEW.agent_id AND error IS NOT NULL
33854
+ ORDER BY updated_at DESC LIMIT 1
33855
+ )
33856
+ WHERE agent_id = NEW.agent_id
33857
+ AND (NEW.error IS NOT NULL OR OLD.error IS NOT NULL);
33858
+ END;
33859
+
33860
+ CREATE TRIGGER IF NOT EXISTS transcript_capture_status_ad
33861
+ AFTER DELETE ON transcript_capture_jobs
33862
+ BEGIN
33863
+ UPDATE transcript_capture_status
33864
+ SET pending = pending - (OLD.status = 'pending'),
33865
+ processing = processing - (OLD.status = 'processing'),
33866
+ completed = completed - (OLD.status = 'completed'),
33867
+ failed = failed - (OLD.status = 'failed'),
33868
+ dead = dead - (OLD.status = 'dead')
33869
+ WHERE agent_id = OLD.agent_id;
33870
+
33871
+ UPDATE transcript_capture_status
33872
+ SET oldest_pending_at = (
33873
+ SELECT MIN(created_at) FROM transcript_capture_jobs
33874
+ WHERE agent_id = OLD.agent_id AND status = 'pending'
33875
+ )
33876
+ WHERE agent_id = OLD.agent_id;
33877
+
33878
+ UPDATE transcript_capture_status
33879
+ SET last_error = (
33880
+ SELECT error FROM transcript_capture_jobs
33881
+ WHERE agent_id = OLD.agent_id AND error IS NOT NULL
33882
+ ORDER BY updated_at DESC LIMIT 1
33883
+ ),
33884
+ last_error_at = (
33885
+ SELECT updated_at FROM transcript_capture_jobs
33886
+ WHERE agent_id = OLD.agent_id AND error IS NOT NULL
33887
+ ORDER BY updated_at DESC LIMIT 1
33888
+ )
33889
+ WHERE agent_id = OLD.agent_id
33890
+ AND OLD.error IS NOT NULL;
33891
+ END;
33892
+ `);
33893
+ db.exec(`
33894
+ CREATE TRIGGER IF NOT EXISTS memories_dup_projection_ai
33895
+ AFTER INSERT ON memories
33896
+ BEGIN
33897
+ UPDATE memories_diagnostics_state
33898
+ SET total_active = total_active + CASE WHEN NEW.is_deleted = 0 THEN 1 ELSE 0 END,
33899
+ exact_duplicates = exact_duplicates + CASE
33900
+ WHEN NEW.is_deleted = 0 AND NEW.content_hash IS NOT NULL
33901
+ AND NEW.pinned = 0 AND NEW.manual_override = 0
33902
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = NEW.content_hash), 0) >= 1
33903
+ THEN 1 ELSE 0 END,
33904
+ exact_clusters = exact_clusters + CASE
33905
+ WHEN NEW.is_deleted = 0 AND NEW.content_hash IS NOT NULL
33906
+ AND NEW.pinned = 0 AND NEW.manual_override = 0
33907
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = NEW.content_hash), 0) = 1
33908
+ THEN 1 ELSE 0 END
33909
+ WHERE id = 1;
33910
+
33911
+ INSERT INTO memories_duplicate_hash_counts (content_hash, dup_count)
33912
+ SELECT NEW.content_hash, 1
33913
+ WHERE NEW.is_deleted = 0
33914
+ AND NEW.content_hash IS NOT NULL
33915
+ AND NEW.pinned = 0
33916
+ AND NEW.manual_override = 0
33917
+ ON CONFLICT(content_hash) DO UPDATE SET dup_count = dup_count + 1;
33918
+ END;
33919
+
33920
+ CREATE TRIGGER IF NOT EXISTS memories_dup_projection_au
33921
+ AFTER UPDATE OF is_deleted, content_hash, pinned, manual_override ON memories
33922
+ BEGIN
33923
+ UPDATE memories_diagnostics_state
33924
+ SET total_active = total_active
33925
+ + CASE WHEN NEW.is_deleted = 0 THEN 1 ELSE 0 END
33926
+ - CASE WHEN OLD.is_deleted = 0 THEN 1 ELSE 0 END,
33927
+ exact_duplicates = exact_duplicates - CASE
33928
+ WHEN OLD.is_deleted = 0 AND OLD.content_hash IS NOT NULL
33929
+ AND OLD.pinned = 0 AND OLD.manual_override = 0
33930
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = OLD.content_hash), 0) > 1
33931
+ THEN 1 ELSE 0 END,
33932
+ exact_clusters = exact_clusters - CASE
33933
+ WHEN OLD.is_deleted = 0 AND OLD.content_hash IS NOT NULL
33934
+ AND OLD.pinned = 0 AND OLD.manual_override = 0
33935
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = OLD.content_hash), 0) = 2
33936
+ THEN 1 ELSE 0 END
33937
+ WHERE id = 1;
33938
+
33939
+ UPDATE memories_duplicate_hash_counts
33940
+ SET dup_count = dup_count - 1
33941
+ WHERE OLD.is_deleted = 0
33942
+ AND OLD.content_hash IS NOT NULL
33943
+ AND OLD.pinned = 0
33944
+ AND OLD.manual_override = 0
33945
+ AND content_hash = OLD.content_hash;
33946
+
33947
+ DELETE FROM memories_duplicate_hash_counts
33948
+ WHERE content_hash = OLD.content_hash
33949
+ AND dup_count <= 0;
33950
+
33951
+ UPDATE memories_diagnostics_state
33952
+ SET exact_duplicates = exact_duplicates + CASE
33953
+ WHEN NEW.is_deleted = 0 AND NEW.content_hash IS NOT NULL
33954
+ AND NEW.pinned = 0 AND NEW.manual_override = 0
33955
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = NEW.content_hash), 0) >= 1
33956
+ THEN 1 ELSE 0 END,
33957
+ exact_clusters = exact_clusters + CASE
33958
+ WHEN NEW.is_deleted = 0 AND NEW.content_hash IS NOT NULL
33959
+ AND NEW.pinned = 0 AND NEW.manual_override = 0
33960
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = NEW.content_hash), 0) = 1
33961
+ THEN 1 ELSE 0 END
33962
+ WHERE id = 1;
33963
+
33964
+ INSERT INTO memories_duplicate_hash_counts (content_hash, dup_count)
33965
+ SELECT NEW.content_hash, 1
33966
+ WHERE NEW.is_deleted = 0
33967
+ AND NEW.content_hash IS NOT NULL
33968
+ AND NEW.pinned = 0
33969
+ AND NEW.manual_override = 0
33970
+ ON CONFLICT(content_hash) DO UPDATE SET dup_count = dup_count + 1;
33971
+ END;
33972
+
33973
+ CREATE TRIGGER IF NOT EXISTS memories_dup_projection_ad
33974
+ AFTER DELETE ON memories
33975
+ BEGIN
33976
+ UPDATE memories_diagnostics_state
33977
+ SET total_active = total_active - CASE WHEN OLD.is_deleted = 0 THEN 1 ELSE 0 END,
33978
+ exact_duplicates = exact_duplicates - CASE
33979
+ WHEN OLD.is_deleted = 0 AND OLD.content_hash IS NOT NULL
33980
+ AND OLD.pinned = 0 AND OLD.manual_override = 0
33981
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = OLD.content_hash), 0) > 1
33982
+ THEN 1 ELSE 0 END,
33983
+ exact_clusters = exact_clusters - CASE
33984
+ WHEN OLD.is_deleted = 0 AND OLD.content_hash IS NOT NULL
33985
+ AND OLD.pinned = 0 AND OLD.manual_override = 0
33986
+ AND COALESCE((SELECT dup_count FROM memories_duplicate_hash_counts WHERE content_hash = OLD.content_hash), 0) = 2
33987
+ THEN 1 ELSE 0 END
33988
+ WHERE id = 1;
33989
+
33990
+ UPDATE memories_duplicate_hash_counts
33991
+ SET dup_count = dup_count - 1
33992
+ WHERE OLD.is_deleted = 0
33993
+ AND OLD.content_hash IS NOT NULL
33994
+ AND OLD.pinned = 0
33995
+ AND OLD.manual_override = 0
33996
+ AND content_hash = OLD.content_hash;
33997
+
33998
+ DELETE FROM memories_duplicate_hash_counts
33999
+ WHERE content_hash = OLD.content_hash
34000
+ AND dup_count <= 0;
34001
+ END;
34002
+ `);
34003
+ db.exec(`
34004
+ DELETE FROM transcript_capture_status;
34005
+ DELETE FROM memories_duplicate_hash_counts;
34006
+ INSERT INTO memories_duplicate_hash_counts (content_hash, dup_count)
34007
+ SELECT content_hash, COUNT(*)
34008
+ FROM memories
34009
+ WHERE is_deleted = 0
34010
+ AND content_hash IS NOT NULL
34011
+ AND pinned = 0
34012
+ AND manual_override = 0
34013
+ GROUP BY content_hash;
34014
+
34015
+ INSERT INTO memories_diagnostics_state (id, total_active, exact_duplicates, exact_clusters)
34016
+ VALUES (
34017
+ 1,
34018
+ (SELECT COUNT(*) FROM memories WHERE is_deleted = 0),
34019
+ COALESCE((SELECT SUM(dup_count - 1) FROM memories_duplicate_hash_counts WHERE dup_count > 1), 0),
34020
+ (SELECT COUNT(*) FROM memories_duplicate_hash_counts WHERE dup_count > 1)
34021
+ )
34022
+ ON CONFLICT(id) DO UPDATE SET
34023
+ total_active = excluded.total_active,
34024
+ exact_duplicates = excluded.exact_duplicates,
34025
+ exact_clusters = excluded.exact_clusters;
34026
+
34027
+ INSERT INTO transcript_capture_status (
34028
+ agent_id, pending, processing, completed, failed, dead,
34029
+ oldest_pending_at, last_error, last_error_at
34030
+ )
34031
+ SELECT
34032
+ j.agent_id,
34033
+ SUM(j.status = 'pending'),
34034
+ SUM(j.status = 'processing'),
34035
+ SUM(j.status = 'completed'),
34036
+ SUM(j.status = 'failed'),
34037
+ SUM(j.status = 'dead'),
34038
+ MIN(CASE WHEN j.status = 'pending' THEN j.created_at END),
34039
+ (SELECT e2.error FROM transcript_capture_jobs e2
34040
+ WHERE e2.agent_id = j.agent_id AND e2.error IS NOT NULL
34041
+ ORDER BY e2.updated_at DESC LIMIT 1),
34042
+ (SELECT e3.updated_at FROM transcript_capture_jobs e3
34043
+ WHERE e3.agent_id = j.agent_id AND e3.error IS NOT NULL
34044
+ ORDER BY e3.updated_at DESC LIMIT 1)
34045
+ FROM transcript_capture_jobs j
34046
+ GROUP BY j.agent_id;
34047
+ `);
34048
+ }
33415
34049
  var MIGRATIONS2 = [
33416
34050
  {
33417
34051
  version: 1,
33418
34052
  name: "baseline",
33419
- up: up138,
34053
+ up: up139,
33420
34054
  artifacts: { tables: ["memories", "conversations", "embeddings"] }
33421
34055
  },
33422
34056
  {
@@ -33494,7 +34128,7 @@ var MIGRATIONS2 = [
33494
34128
  {
33495
34129
  version: 13,
33496
34130
  name: "ingestion-tracking",
33497
- up: up139,
34131
+ up: up1310,
33498
34132
  artifacts: {
33499
34133
  columns: [
33500
34134
  { table: "memories", column: "source_path" },
@@ -34501,6 +35135,14 @@ var MIGRATIONS2 = [
34501
35135
  { table: "dreaming_passes", column: "head_hash" }
34502
35136
  ]
34503
35137
  }
35138
+ },
35139
+ {
35140
+ version: 138,
35141
+ name: "bounded-status-projections",
35142
+ up: up1382,
35143
+ artifacts: {
35144
+ tables: ["transcript_capture_status", "memories_duplicate_hash_counts", "memories_diagnostics_state"]
35145
+ }
34504
35146
  }
34505
35147
  ];
34506
35148
  var LATEST_SCHEMA_VERSION2 = MIGRATIONS2[MIGRATIONS2.length - 1]?.version ?? 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signetai/signet-memory-openclaw",
3
- "version": "0.211.16",
3
+ "version": "0.211.20",
4
4
  "description": "Signet adapter for OpenClaw — runtime plugin for AI agent memory",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",