@signetai/connector-openclaw 0.185.4 → 0.185.5

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 +485 -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,224 @@ 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
+ }
10544
10763
  var MIGRATIONS = [
10545
10764
  {
10546
10765
  version: 1,
@@ -11480,6 +11699,17 @@ var MIGRATIONS = [
11480
11699
  { table: "cross_agent_messages", column: "acp_target_agent_name" }
11481
11700
  ]
11482
11701
  }
11702
+ },
11703
+ {
11704
+ version: 117,
11705
+ name: "retire-summary-worker",
11706
+ up: up117,
11707
+ artifacts: {
11708
+ columns: [
11709
+ { table: "session_transcripts", column: "completed_at" },
11710
+ { table: "session_transcripts", column: "content_hash" }
11711
+ ]
11712
+ }
11483
11713
  }
11484
11714
  ];
11485
11715
  var LATEST_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
@@ -13791,6 +14021,7 @@ function parseLenientJsonObject(raw, options) {
13791
14021
  import { createRequire as createRequire3 } from "node:module";
13792
14022
  import { dirname as dirname2, join as join2 } from "node:path";
13793
14023
  import { fileURLToPath as fileURLToPath2 } from "node:url";
14024
+ import { createHash as createHash2 } from "node:crypto";
13794
14025
  import { homedir as homedir2 } from "os";
13795
14026
  import { join as join22 } from "path";
13796
14027
  import { createRequire as createRequire22 } from "node:module";
@@ -20746,7 +20977,7 @@ function memoriesFtsNeedsTokenizerRepair2(sql) {
20746
20977
  return true;
20747
20978
  return !normalized.includes(`tokenize='${MEMORIES_FTS_TOKENIZER2}'`);
20748
20979
  }
20749
- function up117(db) {
20980
+ function up118(db) {
20750
20981
  db.exec(`
20751
20982
  CREATE TABLE IF NOT EXISTS schema_migrations (
20752
20983
  version INTEGER PRIMARY KEY,
@@ -20839,27 +21070,27 @@ function hasColumn22(db, table, column) {
20839
21070
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
20840
21071
  return rows.some((r) => r.name === column);
20841
21072
  }
20842
- function addColumnIfMissing25(db, table, column, definition) {
21073
+ function addColumnIfMissing26(db, table, column, definition) {
20843
21074
  if (!hasColumn22(db, table, column)) {
20844
21075
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
20845
21076
  }
20846
21077
  }
20847
21078
  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");
21079
+ addColumnIfMissing26(db, "memories", "content_hash", "TEXT");
21080
+ addColumnIfMissing26(db, "memories", "normalized_content", "TEXT");
21081
+ addColumnIfMissing26(db, "memories", "is_deleted", "INTEGER DEFAULT 0");
21082
+ addColumnIfMissing26(db, "memories", "deleted_at", "TEXT");
21083
+ addColumnIfMissing26(db, "memories", "extraction_status", "TEXT DEFAULT 'none'");
21084
+ addColumnIfMissing26(db, "memories", "embedding_model", "TEXT");
21085
+ addColumnIfMissing26(db, "memories", "extraction_model", "TEXT");
21086
+ addColumnIfMissing26(db, "memories", "update_count", "INTEGER DEFAULT 0");
21087
+ addColumnIfMissing26(db, "memories", "who", "TEXT");
21088
+ addColumnIfMissing26(db, "memories", "why", "TEXT");
21089
+ addColumnIfMissing26(db, "memories", "project", "TEXT");
21090
+ addColumnIfMissing26(db, "memories", "pinned", "INTEGER DEFAULT 0");
21091
+ addColumnIfMissing26(db, "memories", "importance", "REAL DEFAULT 0.5");
21092
+ addColumnIfMissing26(db, "memories", "last_accessed", "TEXT");
21093
+ addColumnIfMissing26(db, "memories", "access_count", "INTEGER DEFAULT 0");
20863
21094
  db.exec(`
20864
21095
  CREATE TABLE IF NOT EXISTS memory_history (
20865
21096
  id TEXT PRIMARY KEY,
@@ -20955,7 +21186,7 @@ function up210(db) {
20955
21186
  ON memory_entity_mentions(entity_id);
20956
21187
  `);
20957
21188
  }
20958
- function addColumnIfMissing26(db, table, column, definition) {
21189
+ function addColumnIfMissing27(db, table, column, definition) {
20959
21190
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
20960
21191
  if (rows.some((r) => r.name === column))
20961
21192
  return false;
@@ -20963,8 +21194,8 @@ function addColumnIfMissing26(db, table, column, definition) {
20963
21194
  return true;
20964
21195
  }
20965
21196
  function up310(db) {
20966
- addColumnIfMissing26(db, "memories", "why", "TEXT");
20967
- addColumnIfMissing26(db, "memories", "project", "TEXT");
21197
+ addColumnIfMissing27(db, "memories", "why", "TEXT");
21198
+ addColumnIfMissing27(db, "memories", "project", "TEXT");
20968
21199
  db.exec(`DROP INDEX IF EXISTS idx_memories_content_hash`);
20969
21200
  db.exec(`
20970
21201
  UPDATE memories
@@ -21169,7 +21400,7 @@ function up1010(db) {
21169
21400
  )
21170
21401
  `);
21171
21402
  }
21172
- function up118(db) {
21403
+ function up119(db) {
21173
21404
  db.exec(`
21174
21405
  CREATE TABLE IF NOT EXISTS session_scores (
21175
21406
  id TEXT PRIMARY KEY,
@@ -22390,7 +22621,7 @@ function up492(db) {
22390
22621
  );
22391
22622
  `);
22392
22623
  }
22393
- function hasTable4(db, name) {
22624
+ function hasTable5(db, name) {
22394
22625
  return db.prepare(`SELECT name
22395
22626
  FROM sqlite_master
22396
22627
  WHERE type = 'table' AND name = ?
@@ -22420,7 +22651,7 @@ function up502(db) {
22420
22651
  CREATE INDEX IF NOT EXISTS idx_entity_dependency_history_created
22421
22652
  ON entity_dependency_history(created_at DESC);
22422
22653
  `);
22423
- if (!hasTable4(db, "entity_dependencies"))
22654
+ if (!hasTable5(db, "entity_dependencies"))
22424
22655
  return;
22425
22656
  db.exec("DROP TRIGGER IF EXISTS trg_entity_dependencies_related_to_reason_insert");
22426
22657
  db.exec("DROP TRIGGER IF EXISTS trg_entity_dependencies_related_to_reason_update");
@@ -24322,11 +24553,229 @@ function up1162(db) {
24322
24553
  ON cross_agent_messages(delivery_path, delivery_state, delivery_lease_expires_at, delivery_updated_at);
24323
24554
  `);
24324
24555
  }
24556
+ function hasTable42(db, table) {
24557
+ return db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
24558
+ }
24559
+ function addColumnIfMissing252(db, table, column, definition) {
24560
+ const columns = db.prepare(`PRAGMA table_info(${table})`).all();
24561
+ if (columns.some((row) => row.name === column))
24562
+ return;
24563
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
24564
+ }
24565
+ function tableColumns2(db, table) {
24566
+ const rows = db.prepare(`PRAGMA table_info(${table})`).all();
24567
+ return new Set(rows.map((row) => typeof row.name === "string" ? row.name : ""));
24568
+ }
24569
+ function hashTranscript2(content) {
24570
+ return createHash2("sha256").update(content, "utf8").digest("hex");
24571
+ }
24572
+ function backfillTranscriptHashes2(db) {
24573
+ const columns = tableColumns2(db, "session_transcripts");
24574
+ if (!columns.has("content_hash") || !columns.has("content"))
24575
+ return;
24576
+ const rows = db.prepare("SELECT session_key, agent_id, content FROM session_transcripts WHERE content_hash IS NULL").all();
24577
+ const update = db.prepare("UPDATE session_transcripts SET content_hash = ? WHERE agent_id = ? AND session_key = ? AND content_hash IS NULL");
24578
+ for (const row of rows) {
24579
+ if (typeof row.content !== "string" || typeof row.session_key !== "string")
24580
+ continue;
24581
+ update.run(hashTranscript2(row.content), typeof row.agent_id === "string" ? row.agent_id : "default", row.session_key);
24582
+ }
24583
+ }
24584
+ var COMPLETION_BOUNDARY_REASONS2 = new Set(["session_closed", "session_clear", "stale_session", "ttl_expired"]);
24585
+ function summaryJobTimestamp2(job) {
24586
+ return job.completed_at ?? job.ended_at ?? job.captured_at ?? job.created_at ?? new Date(0).toISOString();
24587
+ }
24588
+ function laterTimestamp2(current, candidate) {
24589
+ if (current === null)
24590
+ return candidate;
24591
+ if (candidate === null)
24592
+ return current;
24593
+ const currentMillis = Date.parse(current);
24594
+ const candidateMillis = Date.parse(candidate);
24595
+ if (Number.isFinite(currentMillis) && Number.isFinite(candidateMillis)) {
24596
+ return candidateMillis > currentMillis ? candidate : current;
24597
+ }
24598
+ return candidate > current ? candidate : current;
24599
+ }
24600
+ function isCompletionBoundary2(job, columns) {
24601
+ return columns.has("trigger") && job.trigger === "session_end" || columns.has("boundary_reason") && COMPLETION_BOUNDARY_REASONS2.has(job.boundary_reason ?? "");
24602
+ }
24603
+ function mergeTranscriptContent2(current, next) {
24604
+ if (current.length === 0)
24605
+ return next;
24606
+ if (next.length === 0 || current === next || current.includes(next))
24607
+ return current;
24608
+ if (next.includes(current))
24609
+ return next;
24610
+ return `${current}
24611
+ ${next}`;
24612
+ }
24613
+ function backfillTranscriptsFromSummaryJobs2(db) {
24614
+ if (!hasTable42(db, "summary_jobs"))
24615
+ return;
24616
+ const summaryColumns = tableColumns2(db, "summary_jobs");
24617
+ if (!summaryColumns.has("transcript"))
24618
+ return;
24619
+ const select = (name) => summaryColumns.has(name) ? `"${name}" AS "${name}"` : `NULL AS "${name}"`;
24620
+ const jobs = db.prepare(`SELECT ${[
24621
+ "id",
24622
+ "session_key",
24623
+ "transcript",
24624
+ "harness",
24625
+ "project",
24626
+ "agent_id",
24627
+ "trigger",
24628
+ "boundary_reason",
24629
+ "captured_at",
24630
+ "ended_at",
24631
+ "completed_at",
24632
+ "created_at"
24633
+ ].map(select).join(", ")} FROM summary_jobs`).all();
24634
+ const candidates = new Map;
24635
+ for (const job of jobs) {
24636
+ if (typeof job.transcript !== "string" || job.transcript.trim().length === 0)
24637
+ continue;
24638
+ const agentId = typeof job.agent_id === "string" && job.agent_id.length > 0 ? job.agent_id : "default";
24639
+ 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}`)}`;
24640
+ const key = `${agentId}\x00${sessionKey}`;
24641
+ const current = candidates.get(key);
24642
+ const timestamp = summaryJobTimestamp2(job);
24643
+ const boundary = isCompletionBoundary2(job, summaryColumns);
24644
+ const createdAt = job.captured_at ?? job.created_at ?? job.ended_at ?? timestamp;
24645
+ if (!current) {
24646
+ candidates.set(key, {
24647
+ sessionKey,
24648
+ job: { ...job, agent_id: agentId },
24649
+ content: job.transcript,
24650
+ createdAt,
24651
+ completedAt: boundary ? timestamp : null
24652
+ });
24653
+ continue;
24654
+ }
24655
+ const currentTimestamp = summaryJobTimestamp2(current.job);
24656
+ const preferred = timestamp > currentTimestamp || timestamp === currentTimestamp && job.transcript.length > current.content.length ? { ...job, agent_id: agentId } : current.job;
24657
+ candidates.set(key, {
24658
+ sessionKey,
24659
+ job: preferred,
24660
+ content: mergeTranscriptContent2(current.content, job.transcript),
24661
+ createdAt: current.createdAt < createdAt ? current.createdAt : createdAt,
24662
+ completedAt: laterTimestamp2(current.completedAt, boundary ? timestamp : null)
24663
+ });
24664
+ }
24665
+ const transcriptColumns = tableColumns2(db, "session_transcripts");
24666
+ const hasUpdated = transcriptColumns.has("updated_at");
24667
+ const hasCompleted = transcriptColumns.has("completed_at");
24668
+ const hasHash = transcriptColumns.has("content_hash");
24669
+ const insertColumns = ["session_key", "content", "harness", "project", "agent_id", "created_at"];
24670
+ if (hasUpdated)
24671
+ insertColumns.push("updated_at");
24672
+ if (hasCompleted)
24673
+ insertColumns.push("completed_at");
24674
+ if (hasHash)
24675
+ insertColumns.push("content_hash");
24676
+ const insert = db.prepare(`INSERT OR IGNORE INTO session_transcripts (${insertColumns.join(", ")}) VALUES (${insertColumns.map(() => "?").join(", ")})`);
24677
+ const existing = db.prepare("SELECT content, completed_at FROM session_transcripts WHERE agent_id = ? AND session_key = ?");
24678
+ for (const candidate of candidates.values()) {
24679
+ const job = candidate.job;
24680
+ const agentId = job.agent_id ?? "default";
24681
+ const existingRow = existing.get(agentId, candidate.sessionKey);
24682
+ if (existingRow != null) {
24683
+ const previousContent = typeof existingRow.content === "string" ? existingRow.content : "";
24684
+ const mergedContent = mergeTranscriptContent2(previousContent, candidate.content);
24685
+ const completedAt = typeof existingRow.completed_at === "string" && existingRow.completed_at.length > 0 ? existingRow.completed_at : candidate.completedAt;
24686
+ const assignments = ["content = ?"];
24687
+ const values2 = [mergedContent];
24688
+ if (hasUpdated && mergedContent !== previousContent) {
24689
+ assignments.push("updated_at = ?");
24690
+ values2.push(candidate.createdAt);
24691
+ }
24692
+ if (hasCompleted && completedAt && !existingRow.completed_at) {
24693
+ assignments.push("completed_at = ?");
24694
+ values2.push(completedAt);
24695
+ }
24696
+ if (hasHash) {
24697
+ assignments.push("content_hash = ?");
24698
+ values2.push(hashTranscript2(mergedContent));
24699
+ }
24700
+ values2.push(agentId, candidate.sessionKey);
24701
+ db.prepare(`UPDATE session_transcripts SET ${assignments.join(", ")} WHERE agent_id = ? AND session_key = ?`).run(...values2);
24702
+ continue;
24703
+ }
24704
+ const values = [
24705
+ candidate.sessionKey,
24706
+ candidate.content,
24707
+ job.harness ?? null,
24708
+ job.project ?? null,
24709
+ agentId,
24710
+ candidate.createdAt
24711
+ ];
24712
+ if (hasUpdated)
24713
+ values.push(candidate.createdAt);
24714
+ if (hasCompleted)
24715
+ values.push(candidate.completedAt);
24716
+ if (hasHash)
24717
+ values.push(hashTranscript2(candidate.content));
24718
+ insert.run(...values);
24719
+ }
24720
+ }
24721
+ function up1172(db) {
24722
+ if (!hasTable42(db, "session_transcripts"))
24723
+ return;
24724
+ addColumnIfMissing252(db, "session_transcripts", "completed_at", "TEXT");
24725
+ addColumnIfMissing252(db, "session_transcripts", "content_hash", "TEXT");
24726
+ backfillTranscriptHashes2(db);
24727
+ if (hasTable42(db, "transcript_capture_jobs")) {
24728
+ const captureColumns = db.prepare("PRAGMA table_info(transcript_capture_jobs)").all();
24729
+ if (captureColumns.some((row) => row.name === "summary_status")) {
24730
+ db.exec("UPDATE transcript_capture_jobs SET summary_status = 'not_requested' WHERE summary_status IN ('pending', 'failed', 'skipped')");
24731
+ }
24732
+ }
24733
+ if (hasTable42(db, "summary_jobs")) {
24734
+ backfillTranscriptsFromSummaryJobs2(db);
24735
+ backfillTranscriptHashes2(db);
24736
+ const summaryColumns = tableColumns2(db, "summary_jobs");
24737
+ const timestampParts = ["completed_at", "ended_at", "captured_at", "created_at"].filter((column) => summaryColumns.has(column)).map((column) => `sj.${column}`);
24738
+ const timestampValue = timestampParts.length === 1 ? timestampParts[0] : `COALESCE(${timestampParts.join(", ")})`;
24739
+ const completionTimestamp = timestampValue ? `MAX(${timestampValue})` : "NULL";
24740
+ const boundaryParts = [
24741
+ summaryColumns.has("trigger") ? "sj.trigger = 'session_end'" : null,
24742
+ summaryColumns.has("boundary_reason") ? "sj.boundary_reason IN ('session_closed', 'session_clear', 'stale_session', 'ttl_expired')" : null
24743
+ ].filter((part) => part !== null);
24744
+ const boundaryPredicate = boundaryParts.length > 0 ? `(${boundaryParts.join(" OR ")})` : "1=1";
24745
+ const agentPredicate = summaryColumns.has("agent_id") ? "sj.agent_id = session_transcripts.agent_id" : "session_transcripts.agent_id = 'default'";
24746
+ if (completionTimestamp !== "NULL") {
24747
+ db.exec(`
24748
+ UPDATE session_transcripts
24749
+ SET completed_at = COALESCE(
24750
+ completed_at,
24751
+ (
24752
+ SELECT ${completionTimestamp}
24753
+ FROM summary_jobs AS sj
24754
+ WHERE ${agentPredicate}
24755
+ AND sj.session_key = session_transcripts.session_key
24756
+ AND ${boundaryPredicate}
24757
+ )
24758
+ )
24759
+ WHERE completed_at IS NULL;
24760
+ `);
24761
+ }
24762
+ db.exec("DELETE FROM summary_jobs");
24763
+ }
24764
+ const completionIndexColumns = ["agent_id", "completed_at"];
24765
+ if (tableColumns2(db, "session_transcripts").has("updated_at"))
24766
+ completionIndexColumns.push("updated_at");
24767
+ db.exec(`
24768
+ CREATE INDEX IF NOT EXISTS idx_st_agent_completed
24769
+ ON session_transcripts(${completionIndexColumns.join(", ")});
24770
+ CREATE INDEX IF NOT EXISTS idx_st_agent_hash
24771
+ ON session_transcripts(agent_id, content_hash);
24772
+ `);
24773
+ }
24325
24774
  var MIGRATIONS2 = [
24326
24775
  {
24327
24776
  version: 1,
24328
24777
  name: "baseline",
24329
- up: up117,
24778
+ up: up118,
24330
24779
  artifacts: { tables: ["memories", "conversations", "embeddings"] }
24331
24780
  },
24332
24781
  {
@@ -24392,7 +24841,7 @@ var MIGRATIONS2 = [
24392
24841
  {
24393
24842
  version: 11,
24394
24843
  name: "session-scores",
24395
- up: up118,
24844
+ up: up119,
24396
24845
  artifacts: { tables: ["session_scores"] }
24397
24846
  },
24398
24847
  {
@@ -25261,6 +25710,17 @@ var MIGRATIONS2 = [
25261
25710
  { table: "cross_agent_messages", column: "acp_target_agent_name" }
25262
25711
  ]
25263
25712
  }
25713
+ },
25714
+ {
25715
+ version: 117,
25716
+ name: "retire-summary-worker",
25717
+ up: up1172,
25718
+ artifacts: {
25719
+ columns: [
25720
+ { table: "session_transcripts", column: "completed_at" },
25721
+ { table: "session_transcripts", column: "content_hash" }
25722
+ ]
25723
+ }
25264
25724
  }
25265
25725
  ];
25266
25726
  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.5",
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.5",
29
+ "@signetai/core": "0.185.5"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.0.0",