@signetai/connector-openclaw 0.185.4 → 0.185.6

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 +527 -25
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ import { dirname as dirname5, isAbsolute, join as join3, relative, sep } from "n
10
10
  import { createRequire } from "node:module";
11
11
  import { dirname, join } from "node:path";
12
12
  import { fileURLToPath } from "node:url";
13
+ import { createHash } from "node:crypto";
13
14
  import { createRequire as createRequire2 } from "node:module";
14
15
  import { homedir as homedir4 } from "node:os";
15
16
  import { dirname as dirname3, join as join6, resolve as resolve2 } from "node:path";
@@ -10541,6 +10542,240 @@ function up116(db) {
10541
10542
  ON cross_agent_messages(delivery_path, delivery_state, delivery_lease_expires_at, delivery_updated_at);
10542
10543
  `);
10543
10544
  }
10545
+ function hasTable4(db, table) {
10546
+ return db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
10547
+ }
10548
+ function addColumnIfMissing25(db, table, column, definition) {
10549
+ const columns = db.prepare(`PRAGMA table_info(${table})`).all();
10550
+ if (columns.some((row) => row.name === column))
10551
+ return;
10552
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
10553
+ }
10554
+ function tableColumns(db, table) {
10555
+ const rows = db.prepare(`PRAGMA table_info(${table})`).all();
10556
+ return new Set(rows.map((row) => typeof row.name === "string" ? row.name : ""));
10557
+ }
10558
+ function hashTranscript(content) {
10559
+ return createHash("sha256").update(content, "utf8").digest("hex");
10560
+ }
10561
+ function backfillTranscriptHashes(db) {
10562
+ const columns = tableColumns(db, "session_transcripts");
10563
+ if (!columns.has("content_hash") || !columns.has("content"))
10564
+ return;
10565
+ const rows = db.prepare("SELECT session_key, agent_id, content FROM session_transcripts WHERE content_hash IS NULL").all();
10566
+ const update = db.prepare("UPDATE session_transcripts SET content_hash = ? WHERE agent_id = ? AND session_key = ? AND content_hash IS NULL");
10567
+ for (const row of rows) {
10568
+ if (typeof row.content !== "string" || typeof row.session_key !== "string")
10569
+ continue;
10570
+ update.run(hashTranscript(row.content), typeof row.agent_id === "string" ? row.agent_id : "default", row.session_key);
10571
+ }
10572
+ }
10573
+ var COMPLETION_BOUNDARY_REASONS = new Set(["session_closed", "session_clear", "stale_session", "ttl_expired"]);
10574
+ function summaryJobTimestamp(job) {
10575
+ return job.completed_at ?? job.ended_at ?? job.captured_at ?? job.created_at ?? new Date(0).toISOString();
10576
+ }
10577
+ function laterTimestamp(current, candidate) {
10578
+ if (current === null)
10579
+ return candidate;
10580
+ if (candidate === null)
10581
+ return current;
10582
+ const currentMillis = Date.parse(current);
10583
+ const candidateMillis = Date.parse(candidate);
10584
+ if (Number.isFinite(currentMillis) && Number.isFinite(candidateMillis)) {
10585
+ return candidateMillis > currentMillis ? candidate : current;
10586
+ }
10587
+ return candidate > current ? candidate : current;
10588
+ }
10589
+ function isCompletionBoundary(job, columns) {
10590
+ return columns.has("trigger") && job.trigger === "session_end" || columns.has("boundary_reason") && COMPLETION_BOUNDARY_REASONS.has(job.boundary_reason ?? "");
10591
+ }
10592
+ function mergeTranscriptContent(current, next) {
10593
+ if (current.length === 0)
10594
+ return next;
10595
+ if (next.length === 0 || current === next || current.includes(next))
10596
+ return current;
10597
+ if (next.includes(current))
10598
+ return next;
10599
+ return `${current}
10600
+ ${next}`;
10601
+ }
10602
+ function backfillTranscriptsFromSummaryJobs(db) {
10603
+ if (!hasTable4(db, "summary_jobs"))
10604
+ return;
10605
+ const summaryColumns = tableColumns(db, "summary_jobs");
10606
+ if (!summaryColumns.has("transcript"))
10607
+ return;
10608
+ const select = (name) => summaryColumns.has(name) ? `"${name}" AS "${name}"` : `NULL AS "${name}"`;
10609
+ const jobs = db.prepare(`SELECT ${[
10610
+ "id",
10611
+ "session_key",
10612
+ "transcript",
10613
+ "harness",
10614
+ "project",
10615
+ "agent_id",
10616
+ "trigger",
10617
+ "boundary_reason",
10618
+ "captured_at",
10619
+ "ended_at",
10620
+ "completed_at",
10621
+ "created_at"
10622
+ ].map(select).join(", ")} FROM summary_jobs`).all();
10623
+ const candidates = new Map;
10624
+ for (const job of jobs) {
10625
+ if (typeof job.transcript !== "string" || job.transcript.trim().length === 0)
10626
+ continue;
10627
+ const agentId = typeof job.agent_id === "string" && job.agent_id.length > 0 ? job.agent_id : "default";
10628
+ const sessionKey = typeof job.session_key === "string" && job.session_key.trim().length > 0 ? job.session_key : `legacy-summary-job:${job.id ?? hashTranscript(`${summaryJobTimestamp(job)}\x00${job.transcript}`)}`;
10629
+ const key = `${agentId}\x00${sessionKey}`;
10630
+ const current = candidates.get(key);
10631
+ const timestamp = summaryJobTimestamp(job);
10632
+ const boundary = isCompletionBoundary(job, summaryColumns);
10633
+ const createdAt = job.captured_at ?? job.created_at ?? job.ended_at ?? timestamp;
10634
+ if (!current) {
10635
+ candidates.set(key, {
10636
+ sessionKey,
10637
+ job: { ...job, agent_id: agentId },
10638
+ content: job.transcript,
10639
+ createdAt,
10640
+ completedAt: boundary ? timestamp : null
10641
+ });
10642
+ continue;
10643
+ }
10644
+ const currentTimestamp = summaryJobTimestamp(current.job);
10645
+ const preferred = timestamp > currentTimestamp || timestamp === currentTimestamp && job.transcript.length > current.content.length ? { ...job, agent_id: agentId } : current.job;
10646
+ candidates.set(key, {
10647
+ sessionKey,
10648
+ job: preferred,
10649
+ content: mergeTranscriptContent(current.content, job.transcript),
10650
+ createdAt: current.createdAt < createdAt ? current.createdAt : createdAt,
10651
+ completedAt: laterTimestamp(current.completedAt, boundary ? timestamp : null)
10652
+ });
10653
+ }
10654
+ const transcriptColumns = tableColumns(db, "session_transcripts");
10655
+ const hasUpdated = transcriptColumns.has("updated_at");
10656
+ const hasCompleted = transcriptColumns.has("completed_at");
10657
+ const hasHash = transcriptColumns.has("content_hash");
10658
+ const insertColumns = ["session_key", "content", "harness", "project", "agent_id", "created_at"];
10659
+ if (hasUpdated)
10660
+ insertColumns.push("updated_at");
10661
+ if (hasCompleted)
10662
+ insertColumns.push("completed_at");
10663
+ if (hasHash)
10664
+ insertColumns.push("content_hash");
10665
+ const insert = db.prepare(`INSERT OR IGNORE INTO session_transcripts (${insertColumns.join(", ")}) VALUES (${insertColumns.map(() => "?").join(", ")})`);
10666
+ const existing = db.prepare("SELECT content, completed_at FROM session_transcripts WHERE agent_id = ? AND session_key = ?");
10667
+ for (const candidate of candidates.values()) {
10668
+ const job = candidate.job;
10669
+ const agentId = job.agent_id ?? "default";
10670
+ const existingRow = existing.get(agentId, candidate.sessionKey);
10671
+ if (existingRow != null) {
10672
+ const previousContent = typeof existingRow.content === "string" ? existingRow.content : "";
10673
+ const mergedContent = mergeTranscriptContent(previousContent, candidate.content);
10674
+ const completedAt = typeof existingRow.completed_at === "string" && existingRow.completed_at.length > 0 ? existingRow.completed_at : candidate.completedAt;
10675
+ const assignments = ["content = ?"];
10676
+ const values2 = [mergedContent];
10677
+ if (hasUpdated && mergedContent !== previousContent) {
10678
+ assignments.push("updated_at = ?");
10679
+ values2.push(candidate.createdAt);
10680
+ }
10681
+ if (hasCompleted && completedAt && !existingRow.completed_at) {
10682
+ assignments.push("completed_at = ?");
10683
+ values2.push(completedAt);
10684
+ }
10685
+ if (hasHash) {
10686
+ assignments.push("content_hash = ?");
10687
+ values2.push(hashTranscript(mergedContent));
10688
+ }
10689
+ values2.push(agentId, candidate.sessionKey);
10690
+ db.prepare(`UPDATE session_transcripts SET ${assignments.join(", ")} WHERE agent_id = ? AND session_key = ?`).run(...values2);
10691
+ continue;
10692
+ }
10693
+ const values = [
10694
+ candidate.sessionKey,
10695
+ candidate.content,
10696
+ job.harness ?? null,
10697
+ job.project ?? null,
10698
+ agentId,
10699
+ candidate.createdAt
10700
+ ];
10701
+ if (hasUpdated)
10702
+ values.push(candidate.createdAt);
10703
+ if (hasCompleted)
10704
+ values.push(candidate.completedAt);
10705
+ if (hasHash)
10706
+ values.push(hashTranscript(candidate.content));
10707
+ insert.run(...values);
10708
+ }
10709
+ }
10710
+ function up117(db) {
10711
+ if (!hasTable4(db, "session_transcripts"))
10712
+ return;
10713
+ addColumnIfMissing25(db, "session_transcripts", "completed_at", "TEXT");
10714
+ addColumnIfMissing25(db, "session_transcripts", "content_hash", "TEXT");
10715
+ backfillTranscriptHashes(db);
10716
+ if (hasTable4(db, "transcript_capture_jobs")) {
10717
+ const captureColumns = db.prepare("PRAGMA table_info(transcript_capture_jobs)").all();
10718
+ if (captureColumns.some((row) => row.name === "summary_status")) {
10719
+ db.exec("UPDATE transcript_capture_jobs SET summary_status = 'not_requested' WHERE summary_status IN ('pending', 'failed', 'skipped')");
10720
+ }
10721
+ }
10722
+ if (hasTable4(db, "summary_jobs")) {
10723
+ backfillTranscriptsFromSummaryJobs(db);
10724
+ backfillTranscriptHashes(db);
10725
+ const summaryColumns = tableColumns(db, "summary_jobs");
10726
+ const timestampParts = ["completed_at", "ended_at", "captured_at", "created_at"].filter((column) => summaryColumns.has(column)).map((column) => `sj.${column}`);
10727
+ const timestampValue = timestampParts.length === 1 ? timestampParts[0] : `COALESCE(${timestampParts.join(", ")})`;
10728
+ const completionTimestamp = timestampValue ? `MAX(${timestampValue})` : "NULL";
10729
+ const boundaryParts = [
10730
+ summaryColumns.has("trigger") ? "sj.trigger = 'session_end'" : null,
10731
+ summaryColumns.has("boundary_reason") ? "sj.boundary_reason IN ('session_closed', 'session_clear', 'stale_session', 'ttl_expired')" : null
10732
+ ].filter((part) => part !== null);
10733
+ const boundaryPredicate = boundaryParts.length > 0 ? `(${boundaryParts.join(" OR ")})` : "1=1";
10734
+ const agentPredicate = summaryColumns.has("agent_id") ? "sj.agent_id = session_transcripts.agent_id" : "session_transcripts.agent_id = 'default'";
10735
+ if (completionTimestamp !== "NULL") {
10736
+ db.exec(`
10737
+ UPDATE session_transcripts
10738
+ SET completed_at = COALESCE(
10739
+ completed_at,
10740
+ (
10741
+ SELECT ${completionTimestamp}
10742
+ FROM summary_jobs AS sj
10743
+ WHERE ${agentPredicate}
10744
+ AND sj.session_key = session_transcripts.session_key
10745
+ AND ${boundaryPredicate}
10746
+ )
10747
+ )
10748
+ WHERE completed_at IS NULL;
10749
+ `);
10750
+ }
10751
+ db.exec("DELETE FROM summary_jobs");
10752
+ }
10753
+ const completionIndexColumns = ["agent_id", "completed_at"];
10754
+ if (tableColumns(db, "session_transcripts").has("updated_at"))
10755
+ completionIndexColumns.push("updated_at");
10756
+ db.exec(`
10757
+ CREATE INDEX IF NOT EXISTS idx_st_agent_completed
10758
+ ON session_transcripts(${completionIndexColumns.join(", ")});
10759
+ CREATE INDEX IF NOT EXISTS idx_st_agent_hash
10760
+ ON session_transcripts(agent_id, content_hash);
10761
+ `);
10762
+ }
10763
+ function up118(db) {
10764
+ db.exec(`
10765
+ CREATE INDEX IF NOT EXISTS idx_memory_jobs_pressure_status
10766
+ ON memory_jobs(status)
10767
+ WHERE status IN ('pending', 'leased') AND job_type <> 'extract';
10768
+ CREATE INDEX IF NOT EXISTS idx_memory_jobs_pressure_created_at
10769
+ ON memory_jobs(created_at)
10770
+ WHERE status IN ('pending', 'leased') AND job_type <> 'extract';
10771
+ CREATE INDEX IF NOT EXISTS idx_summary_jobs_pressure_status
10772
+ ON summary_jobs(status)
10773
+ WHERE status IN ('pending', 'leased');
10774
+ CREATE INDEX IF NOT EXISTS idx_summary_jobs_pressure_created_at
10775
+ ON summary_jobs(created_at)
10776
+ WHERE status IN ('pending', 'leased');
10777
+ `);
10778
+ }
10544
10779
  var MIGRATIONS = [
10545
10780
  {
10546
10781
  version: 1,
@@ -11480,6 +11715,22 @@ var MIGRATIONS = [
11480
11715
  { table: "cross_agent_messages", column: "acp_target_agent_name" }
11481
11716
  ]
11482
11717
  }
11718
+ },
11719
+ {
11720
+ version: 117,
11721
+ name: "retire-summary-worker",
11722
+ up: up117,
11723
+ artifacts: {
11724
+ columns: [
11725
+ { table: "session_transcripts", column: "completed_at" },
11726
+ { table: "session_transcripts", column: "content_hash" }
11727
+ ]
11728
+ }
11729
+ },
11730
+ {
11731
+ version: 118,
11732
+ name: "queue-pressure-indices",
11733
+ up: up118
11483
11734
  }
11484
11735
  ];
11485
11736
  var LATEST_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
@@ -13791,6 +14042,7 @@ function parseLenientJsonObject(raw, options) {
13791
14042
  import { createRequire as createRequire3 } from "node:module";
13792
14043
  import { dirname as dirname2, join as join2 } from "node:path";
13793
14044
  import { fileURLToPath as fileURLToPath2 } from "node:url";
14045
+ import { createHash as createHash2 } from "node:crypto";
13794
14046
  import { homedir as homedir2 } from "os";
13795
14047
  import { join as join22 } from "path";
13796
14048
  import { createRequire as createRequire22 } from "node:module";
@@ -20746,7 +20998,7 @@ function memoriesFtsNeedsTokenizerRepair2(sql) {
20746
20998
  return true;
20747
20999
  return !normalized.includes(`tokenize='${MEMORIES_FTS_TOKENIZER2}'`);
20748
21000
  }
20749
- function up117(db) {
21001
+ function up119(db) {
20750
21002
  db.exec(`
20751
21003
  CREATE TABLE IF NOT EXISTS schema_migrations (
20752
21004
  version INTEGER PRIMARY KEY,
@@ -20839,27 +21091,27 @@ function hasColumn22(db, table, column) {
20839
21091
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
20840
21092
  return rows.some((r) => r.name === column);
20841
21093
  }
20842
- function addColumnIfMissing25(db, table, column, definition) {
21094
+ function addColumnIfMissing26(db, table, column, definition) {
20843
21095
  if (!hasColumn22(db, table, column)) {
20844
21096
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
20845
21097
  }
20846
21098
  }
20847
21099
  function up210(db) {
20848
- addColumnIfMissing25(db, "memories", "content_hash", "TEXT");
20849
- addColumnIfMissing25(db, "memories", "normalized_content", "TEXT");
20850
- addColumnIfMissing25(db, "memories", "is_deleted", "INTEGER DEFAULT 0");
20851
- addColumnIfMissing25(db, "memories", "deleted_at", "TEXT");
20852
- addColumnIfMissing25(db, "memories", "extraction_status", "TEXT DEFAULT 'none'");
20853
- addColumnIfMissing25(db, "memories", "embedding_model", "TEXT");
20854
- addColumnIfMissing25(db, "memories", "extraction_model", "TEXT");
20855
- addColumnIfMissing25(db, "memories", "update_count", "INTEGER DEFAULT 0");
20856
- addColumnIfMissing25(db, "memories", "who", "TEXT");
20857
- addColumnIfMissing25(db, "memories", "why", "TEXT");
20858
- addColumnIfMissing25(db, "memories", "project", "TEXT");
20859
- addColumnIfMissing25(db, "memories", "pinned", "INTEGER DEFAULT 0");
20860
- addColumnIfMissing25(db, "memories", "importance", "REAL DEFAULT 0.5");
20861
- addColumnIfMissing25(db, "memories", "last_accessed", "TEXT");
20862
- addColumnIfMissing25(db, "memories", "access_count", "INTEGER DEFAULT 0");
21100
+ addColumnIfMissing26(db, "memories", "content_hash", "TEXT");
21101
+ addColumnIfMissing26(db, "memories", "normalized_content", "TEXT");
21102
+ addColumnIfMissing26(db, "memories", "is_deleted", "INTEGER DEFAULT 0");
21103
+ addColumnIfMissing26(db, "memories", "deleted_at", "TEXT");
21104
+ addColumnIfMissing26(db, "memories", "extraction_status", "TEXT DEFAULT 'none'");
21105
+ addColumnIfMissing26(db, "memories", "embedding_model", "TEXT");
21106
+ addColumnIfMissing26(db, "memories", "extraction_model", "TEXT");
21107
+ addColumnIfMissing26(db, "memories", "update_count", "INTEGER DEFAULT 0");
21108
+ addColumnIfMissing26(db, "memories", "who", "TEXT");
21109
+ addColumnIfMissing26(db, "memories", "why", "TEXT");
21110
+ addColumnIfMissing26(db, "memories", "project", "TEXT");
21111
+ addColumnIfMissing26(db, "memories", "pinned", "INTEGER DEFAULT 0");
21112
+ addColumnIfMissing26(db, "memories", "importance", "REAL DEFAULT 0.5");
21113
+ addColumnIfMissing26(db, "memories", "last_accessed", "TEXT");
21114
+ addColumnIfMissing26(db, "memories", "access_count", "INTEGER DEFAULT 0");
20863
21115
  db.exec(`
20864
21116
  CREATE TABLE IF NOT EXISTS memory_history (
20865
21117
  id TEXT PRIMARY KEY,
@@ -20955,7 +21207,7 @@ function up210(db) {
20955
21207
  ON memory_entity_mentions(entity_id);
20956
21208
  `);
20957
21209
  }
20958
- function addColumnIfMissing26(db, table, column, definition) {
21210
+ function addColumnIfMissing27(db, table, column, definition) {
20959
21211
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
20960
21212
  if (rows.some((r) => r.name === column))
20961
21213
  return false;
@@ -20963,8 +21215,8 @@ function addColumnIfMissing26(db, table, column, definition) {
20963
21215
  return true;
20964
21216
  }
20965
21217
  function up310(db) {
20966
- addColumnIfMissing26(db, "memories", "why", "TEXT");
20967
- addColumnIfMissing26(db, "memories", "project", "TEXT");
21218
+ addColumnIfMissing27(db, "memories", "why", "TEXT");
21219
+ addColumnIfMissing27(db, "memories", "project", "TEXT");
20968
21220
  db.exec(`DROP INDEX IF EXISTS idx_memories_content_hash`);
20969
21221
  db.exec(`
20970
21222
  UPDATE memories
@@ -21169,7 +21421,7 @@ function up1010(db) {
21169
21421
  )
21170
21422
  `);
21171
21423
  }
21172
- function up118(db) {
21424
+ function up1110(db) {
21173
21425
  db.exec(`
21174
21426
  CREATE TABLE IF NOT EXISTS session_scores (
21175
21427
  id TEXT PRIMARY KEY,
@@ -22390,7 +22642,7 @@ function up492(db) {
22390
22642
  );
22391
22643
  `);
22392
22644
  }
22393
- function hasTable4(db, name) {
22645
+ function hasTable5(db, name) {
22394
22646
  return db.prepare(`SELECT name
22395
22647
  FROM sqlite_master
22396
22648
  WHERE type = 'table' AND name = ?
@@ -22420,7 +22672,7 @@ function up502(db) {
22420
22672
  CREATE INDEX IF NOT EXISTS idx_entity_dependency_history_created
22421
22673
  ON entity_dependency_history(created_at DESC);
22422
22674
  `);
22423
- if (!hasTable4(db, "entity_dependencies"))
22675
+ if (!hasTable5(db, "entity_dependencies"))
22424
22676
  return;
22425
22677
  db.exec("DROP TRIGGER IF EXISTS trg_entity_dependencies_related_to_reason_insert");
22426
22678
  db.exec("DROP TRIGGER IF EXISTS trg_entity_dependencies_related_to_reason_update");
@@ -24322,11 +24574,245 @@ function up1162(db) {
24322
24574
  ON cross_agent_messages(delivery_path, delivery_state, delivery_lease_expires_at, delivery_updated_at);
24323
24575
  `);
24324
24576
  }
24577
+ function hasTable42(db, table) {
24578
+ return db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
24579
+ }
24580
+ function addColumnIfMissing252(db, table, column, definition) {
24581
+ const columns = db.prepare(`PRAGMA table_info(${table})`).all();
24582
+ if (columns.some((row) => row.name === column))
24583
+ return;
24584
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
24585
+ }
24586
+ function tableColumns2(db, table) {
24587
+ const rows = db.prepare(`PRAGMA table_info(${table})`).all();
24588
+ return new Set(rows.map((row) => typeof row.name === "string" ? row.name : ""));
24589
+ }
24590
+ function hashTranscript2(content) {
24591
+ return createHash2("sha256").update(content, "utf8").digest("hex");
24592
+ }
24593
+ function backfillTranscriptHashes2(db) {
24594
+ const columns = tableColumns2(db, "session_transcripts");
24595
+ if (!columns.has("content_hash") || !columns.has("content"))
24596
+ return;
24597
+ const rows = db.prepare("SELECT session_key, agent_id, content FROM session_transcripts WHERE content_hash IS NULL").all();
24598
+ const update = db.prepare("UPDATE session_transcripts SET content_hash = ? WHERE agent_id = ? AND session_key = ? AND content_hash IS NULL");
24599
+ for (const row of rows) {
24600
+ if (typeof row.content !== "string" || typeof row.session_key !== "string")
24601
+ continue;
24602
+ update.run(hashTranscript2(row.content), typeof row.agent_id === "string" ? row.agent_id : "default", row.session_key);
24603
+ }
24604
+ }
24605
+ var COMPLETION_BOUNDARY_REASONS2 = new Set(["session_closed", "session_clear", "stale_session", "ttl_expired"]);
24606
+ function summaryJobTimestamp2(job) {
24607
+ return job.completed_at ?? job.ended_at ?? job.captured_at ?? job.created_at ?? new Date(0).toISOString();
24608
+ }
24609
+ function laterTimestamp2(current, candidate) {
24610
+ if (current === null)
24611
+ return candidate;
24612
+ if (candidate === null)
24613
+ return current;
24614
+ const currentMillis = Date.parse(current);
24615
+ const candidateMillis = Date.parse(candidate);
24616
+ if (Number.isFinite(currentMillis) && Number.isFinite(candidateMillis)) {
24617
+ return candidateMillis > currentMillis ? candidate : current;
24618
+ }
24619
+ return candidate > current ? candidate : current;
24620
+ }
24621
+ function isCompletionBoundary2(job, columns) {
24622
+ return columns.has("trigger") && job.trigger === "session_end" || columns.has("boundary_reason") && COMPLETION_BOUNDARY_REASONS2.has(job.boundary_reason ?? "");
24623
+ }
24624
+ function mergeTranscriptContent2(current, next) {
24625
+ if (current.length === 0)
24626
+ return next;
24627
+ if (next.length === 0 || current === next || current.includes(next))
24628
+ return current;
24629
+ if (next.includes(current))
24630
+ return next;
24631
+ return `${current}
24632
+ ${next}`;
24633
+ }
24634
+ function backfillTranscriptsFromSummaryJobs2(db) {
24635
+ if (!hasTable42(db, "summary_jobs"))
24636
+ return;
24637
+ const summaryColumns = tableColumns2(db, "summary_jobs");
24638
+ if (!summaryColumns.has("transcript"))
24639
+ return;
24640
+ const select = (name) => summaryColumns.has(name) ? `"${name}" AS "${name}"` : `NULL AS "${name}"`;
24641
+ const jobs = db.prepare(`SELECT ${[
24642
+ "id",
24643
+ "session_key",
24644
+ "transcript",
24645
+ "harness",
24646
+ "project",
24647
+ "agent_id",
24648
+ "trigger",
24649
+ "boundary_reason",
24650
+ "captured_at",
24651
+ "ended_at",
24652
+ "completed_at",
24653
+ "created_at"
24654
+ ].map(select).join(", ")} FROM summary_jobs`).all();
24655
+ const candidates = new Map;
24656
+ for (const job of jobs) {
24657
+ if (typeof job.transcript !== "string" || job.transcript.trim().length === 0)
24658
+ continue;
24659
+ const agentId = typeof job.agent_id === "string" && job.agent_id.length > 0 ? job.agent_id : "default";
24660
+ const sessionKey = typeof job.session_key === "string" && job.session_key.trim().length > 0 ? job.session_key : `legacy-summary-job:${job.id ?? hashTranscript2(`${summaryJobTimestamp2(job)}\x00${job.transcript}`)}`;
24661
+ const key = `${agentId}\x00${sessionKey}`;
24662
+ const current = candidates.get(key);
24663
+ const timestamp = summaryJobTimestamp2(job);
24664
+ const boundary = isCompletionBoundary2(job, summaryColumns);
24665
+ const createdAt = job.captured_at ?? job.created_at ?? job.ended_at ?? timestamp;
24666
+ if (!current) {
24667
+ candidates.set(key, {
24668
+ sessionKey,
24669
+ job: { ...job, agent_id: agentId },
24670
+ content: job.transcript,
24671
+ createdAt,
24672
+ completedAt: boundary ? timestamp : null
24673
+ });
24674
+ continue;
24675
+ }
24676
+ const currentTimestamp = summaryJobTimestamp2(current.job);
24677
+ const preferred = timestamp > currentTimestamp || timestamp === currentTimestamp && job.transcript.length > current.content.length ? { ...job, agent_id: agentId } : current.job;
24678
+ candidates.set(key, {
24679
+ sessionKey,
24680
+ job: preferred,
24681
+ content: mergeTranscriptContent2(current.content, job.transcript),
24682
+ createdAt: current.createdAt < createdAt ? current.createdAt : createdAt,
24683
+ completedAt: laterTimestamp2(current.completedAt, boundary ? timestamp : null)
24684
+ });
24685
+ }
24686
+ const transcriptColumns = tableColumns2(db, "session_transcripts");
24687
+ const hasUpdated = transcriptColumns.has("updated_at");
24688
+ const hasCompleted = transcriptColumns.has("completed_at");
24689
+ const hasHash = transcriptColumns.has("content_hash");
24690
+ const insertColumns = ["session_key", "content", "harness", "project", "agent_id", "created_at"];
24691
+ if (hasUpdated)
24692
+ insertColumns.push("updated_at");
24693
+ if (hasCompleted)
24694
+ insertColumns.push("completed_at");
24695
+ if (hasHash)
24696
+ insertColumns.push("content_hash");
24697
+ const insert = db.prepare(`INSERT OR IGNORE INTO session_transcripts (${insertColumns.join(", ")}) VALUES (${insertColumns.map(() => "?").join(", ")})`);
24698
+ const existing = db.prepare("SELECT content, completed_at FROM session_transcripts WHERE agent_id = ? AND session_key = ?");
24699
+ for (const candidate of candidates.values()) {
24700
+ const job = candidate.job;
24701
+ const agentId = job.agent_id ?? "default";
24702
+ const existingRow = existing.get(agentId, candidate.sessionKey);
24703
+ if (existingRow != null) {
24704
+ const previousContent = typeof existingRow.content === "string" ? existingRow.content : "";
24705
+ const mergedContent = mergeTranscriptContent2(previousContent, candidate.content);
24706
+ const completedAt = typeof existingRow.completed_at === "string" && existingRow.completed_at.length > 0 ? existingRow.completed_at : candidate.completedAt;
24707
+ const assignments = ["content = ?"];
24708
+ const values2 = [mergedContent];
24709
+ if (hasUpdated && mergedContent !== previousContent) {
24710
+ assignments.push("updated_at = ?");
24711
+ values2.push(candidate.createdAt);
24712
+ }
24713
+ if (hasCompleted && completedAt && !existingRow.completed_at) {
24714
+ assignments.push("completed_at = ?");
24715
+ values2.push(completedAt);
24716
+ }
24717
+ if (hasHash) {
24718
+ assignments.push("content_hash = ?");
24719
+ values2.push(hashTranscript2(mergedContent));
24720
+ }
24721
+ values2.push(agentId, candidate.sessionKey);
24722
+ db.prepare(`UPDATE session_transcripts SET ${assignments.join(", ")} WHERE agent_id = ? AND session_key = ?`).run(...values2);
24723
+ continue;
24724
+ }
24725
+ const values = [
24726
+ candidate.sessionKey,
24727
+ candidate.content,
24728
+ job.harness ?? null,
24729
+ job.project ?? null,
24730
+ agentId,
24731
+ candidate.createdAt
24732
+ ];
24733
+ if (hasUpdated)
24734
+ values.push(candidate.createdAt);
24735
+ if (hasCompleted)
24736
+ values.push(candidate.completedAt);
24737
+ if (hasHash)
24738
+ values.push(hashTranscript2(candidate.content));
24739
+ insert.run(...values);
24740
+ }
24741
+ }
24742
+ function up1172(db) {
24743
+ if (!hasTable42(db, "session_transcripts"))
24744
+ return;
24745
+ addColumnIfMissing252(db, "session_transcripts", "completed_at", "TEXT");
24746
+ addColumnIfMissing252(db, "session_transcripts", "content_hash", "TEXT");
24747
+ backfillTranscriptHashes2(db);
24748
+ if (hasTable42(db, "transcript_capture_jobs")) {
24749
+ const captureColumns = db.prepare("PRAGMA table_info(transcript_capture_jobs)").all();
24750
+ if (captureColumns.some((row) => row.name === "summary_status")) {
24751
+ db.exec("UPDATE transcript_capture_jobs SET summary_status = 'not_requested' WHERE summary_status IN ('pending', 'failed', 'skipped')");
24752
+ }
24753
+ }
24754
+ if (hasTable42(db, "summary_jobs")) {
24755
+ backfillTranscriptsFromSummaryJobs2(db);
24756
+ backfillTranscriptHashes2(db);
24757
+ const summaryColumns = tableColumns2(db, "summary_jobs");
24758
+ const timestampParts = ["completed_at", "ended_at", "captured_at", "created_at"].filter((column) => summaryColumns.has(column)).map((column) => `sj.${column}`);
24759
+ const timestampValue = timestampParts.length === 1 ? timestampParts[0] : `COALESCE(${timestampParts.join(", ")})`;
24760
+ const completionTimestamp = timestampValue ? `MAX(${timestampValue})` : "NULL";
24761
+ const boundaryParts = [
24762
+ summaryColumns.has("trigger") ? "sj.trigger = 'session_end'" : null,
24763
+ summaryColumns.has("boundary_reason") ? "sj.boundary_reason IN ('session_closed', 'session_clear', 'stale_session', 'ttl_expired')" : null
24764
+ ].filter((part) => part !== null);
24765
+ const boundaryPredicate = boundaryParts.length > 0 ? `(${boundaryParts.join(" OR ")})` : "1=1";
24766
+ const agentPredicate = summaryColumns.has("agent_id") ? "sj.agent_id = session_transcripts.agent_id" : "session_transcripts.agent_id = 'default'";
24767
+ if (completionTimestamp !== "NULL") {
24768
+ db.exec(`
24769
+ UPDATE session_transcripts
24770
+ SET completed_at = COALESCE(
24771
+ completed_at,
24772
+ (
24773
+ SELECT ${completionTimestamp}
24774
+ FROM summary_jobs AS sj
24775
+ WHERE ${agentPredicate}
24776
+ AND sj.session_key = session_transcripts.session_key
24777
+ AND ${boundaryPredicate}
24778
+ )
24779
+ )
24780
+ WHERE completed_at IS NULL;
24781
+ `);
24782
+ }
24783
+ db.exec("DELETE FROM summary_jobs");
24784
+ }
24785
+ const completionIndexColumns = ["agent_id", "completed_at"];
24786
+ if (tableColumns2(db, "session_transcripts").has("updated_at"))
24787
+ completionIndexColumns.push("updated_at");
24788
+ db.exec(`
24789
+ CREATE INDEX IF NOT EXISTS idx_st_agent_completed
24790
+ ON session_transcripts(${completionIndexColumns.join(", ")});
24791
+ CREATE INDEX IF NOT EXISTS idx_st_agent_hash
24792
+ ON session_transcripts(agent_id, content_hash);
24793
+ `);
24794
+ }
24795
+ function up1182(db) {
24796
+ db.exec(`
24797
+ CREATE INDEX IF NOT EXISTS idx_memory_jobs_pressure_status
24798
+ ON memory_jobs(status)
24799
+ WHERE status IN ('pending', 'leased') AND job_type <> 'extract';
24800
+ CREATE INDEX IF NOT EXISTS idx_memory_jobs_pressure_created_at
24801
+ ON memory_jobs(created_at)
24802
+ WHERE status IN ('pending', 'leased') AND job_type <> 'extract';
24803
+ CREATE INDEX IF NOT EXISTS idx_summary_jobs_pressure_status
24804
+ ON summary_jobs(status)
24805
+ WHERE status IN ('pending', 'leased');
24806
+ CREATE INDEX IF NOT EXISTS idx_summary_jobs_pressure_created_at
24807
+ ON summary_jobs(created_at)
24808
+ WHERE status IN ('pending', 'leased');
24809
+ `);
24810
+ }
24325
24811
  var MIGRATIONS2 = [
24326
24812
  {
24327
24813
  version: 1,
24328
24814
  name: "baseline",
24329
- up: up117,
24815
+ up: up119,
24330
24816
  artifacts: { tables: ["memories", "conversations", "embeddings"] }
24331
24817
  },
24332
24818
  {
@@ -24392,7 +24878,7 @@ var MIGRATIONS2 = [
24392
24878
  {
24393
24879
  version: 11,
24394
24880
  name: "session-scores",
24395
- up: up118,
24881
+ up: up1110,
24396
24882
  artifacts: { tables: ["session_scores"] }
24397
24883
  },
24398
24884
  {
@@ -25261,6 +25747,22 @@ var MIGRATIONS2 = [
25261
25747
  { table: "cross_agent_messages", column: "acp_target_agent_name" }
25262
25748
  ]
25263
25749
  }
25750
+ },
25751
+ {
25752
+ version: 117,
25753
+ name: "retire-summary-worker",
25754
+ up: up1172,
25755
+ artifacts: {
25756
+ columns: [
25757
+ { table: "session_transcripts", column: "completed_at" },
25758
+ { table: "session_transcripts", column: "content_hash" }
25759
+ ]
25760
+ }
25761
+ },
25762
+ {
25763
+ version: 118,
25764
+ name: "queue-pressure-indices",
25765
+ up: up1182
25264
25766
  }
25265
25767
  ];
25266
25768
  var LATEST_SCHEMA_VERSION2 = MIGRATIONS2[MIGRATIONS2.length - 1]?.version ?? 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signetai/connector-openclaw",
3
- "version": "0.185.4",
3
+ "version": "0.185.6",
4
4
  "description": "Signet connector for OpenClaw - configures workspace and memory hooks",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,8 +25,8 @@
25
25
  "test": "bun test"
26
26
  },
27
27
  "dependencies": {
28
- "@signetai/connector-base": "0.185.4",
29
- "@signetai/core": "0.185.4"
28
+ "@signetai/connector-base": "0.185.6",
29
+ "@signetai/core": "0.185.6"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.0.0",