swarm-mail 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -16964,6 +16964,90 @@ var init_migrations = __esm(() => {
16964
16964
  CREATE INDEX IF NOT EXISTS idx_swarm_contexts_epic ON swarm_contexts(epic_id);
16965
16965
  CREATE INDEX IF NOT EXISTS idx_swarm_contexts_bead ON swarm_contexts(bead_id);
16966
16966
  `
16967
+ },
16968
+ {
16969
+ version: 6,
16970
+ description: "Add core event store tables (events, agents, messages, reservations)",
16971
+ up: `
16972
+ -- Events table: append-only event log
16973
+ CREATE TABLE IF NOT EXISTS events (
16974
+ id SERIAL PRIMARY KEY,
16975
+ sequence SERIAL,
16976
+ type TEXT NOT NULL,
16977
+ project_key TEXT NOT NULL,
16978
+ timestamp BIGINT NOT NULL,
16979
+ data JSONB NOT NULL DEFAULT '{}'
16980
+ );
16981
+ CREATE INDEX IF NOT EXISTS idx_events_project ON events(project_key);
16982
+ CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
16983
+ CREATE INDEX IF NOT EXISTS idx_events_sequence ON events(sequence);
16984
+ CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
16985
+
16986
+ -- Agents table: materialized view of registered agents
16987
+ CREATE TABLE IF NOT EXISTS agents (
16988
+ id SERIAL PRIMARY KEY,
16989
+ project_key TEXT NOT NULL,
16990
+ name TEXT NOT NULL,
16991
+ program TEXT,
16992
+ model TEXT,
16993
+ task_description TEXT,
16994
+ registered_at BIGINT NOT NULL,
16995
+ last_active_at BIGINT NOT NULL,
16996
+ UNIQUE(project_key, name)
16997
+ );
16998
+ CREATE INDEX IF NOT EXISTS idx_agents_project ON agents(project_key);
16999
+
17000
+ -- Messages table: materialized view of sent messages
17001
+ CREATE TABLE IF NOT EXISTS messages (
17002
+ id SERIAL PRIMARY KEY,
17003
+ project_key TEXT NOT NULL,
17004
+ from_agent TEXT NOT NULL,
17005
+ subject TEXT NOT NULL,
17006
+ body TEXT,
17007
+ thread_id TEXT,
17008
+ importance TEXT NOT NULL DEFAULT 'normal',
17009
+ ack_required BOOLEAN NOT NULL DEFAULT FALSE,
17010
+ created_at BIGINT NOT NULL
17011
+ );
17012
+ CREATE INDEX IF NOT EXISTS idx_messages_project ON messages(project_key);
17013
+ CREATE INDEX IF NOT EXISTS idx_messages_thread ON messages(thread_id);
17014
+ CREATE INDEX IF NOT EXISTS idx_messages_from ON messages(from_agent);
17015
+
17016
+ -- Message recipients: join table for message routing
17017
+ CREATE TABLE IF NOT EXISTS message_recipients (
17018
+ id SERIAL PRIMARY KEY,
17019
+ message_id INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
17020
+ agent_name TEXT NOT NULL,
17021
+ read_at BIGINT,
17022
+ acked_at BIGINT,
17023
+ UNIQUE(message_id, agent_name)
17024
+ );
17025
+ CREATE INDEX IF NOT EXISTS idx_message_recipients_agent ON message_recipients(agent_name);
17026
+ CREATE INDEX IF NOT EXISTS idx_message_recipients_message ON message_recipients(message_id);
17027
+
17028
+ -- Reservations table: materialized view of file locks
17029
+ CREATE TABLE IF NOT EXISTS reservations (
17030
+ id SERIAL PRIMARY KEY,
17031
+ project_key TEXT NOT NULL,
17032
+ agent_name TEXT NOT NULL,
17033
+ path_pattern TEXT NOT NULL,
17034
+ exclusive BOOLEAN NOT NULL DEFAULT TRUE,
17035
+ reason TEXT,
17036
+ created_at BIGINT NOT NULL,
17037
+ expires_at BIGINT NOT NULL,
17038
+ released_at BIGINT
17039
+ );
17040
+ CREATE INDEX IF NOT EXISTS idx_reservations_project ON reservations(project_key);
17041
+ CREATE INDEX IF NOT EXISTS idx_reservations_agent ON reservations(agent_name);
17042
+ CREATE INDEX IF NOT EXISTS idx_reservations_expires ON reservations(expires_at);
17043
+ `,
17044
+ down: `
17045
+ DROP TABLE IF EXISTS message_recipients;
17046
+ DROP TABLE IF EXISTS messages;
17047
+ DROP TABLE IF EXISTS reservations;
17048
+ DROP TABLE IF EXISTS agents;
17049
+ DROP TABLE IF EXISTS events;
17050
+ `
16967
17051
  }
16968
17052
  ];
16969
17053
  });
@@ -19863,25 +19947,26 @@ async function importSingleBead(adapter, projectKey, beadExport, options, result
19863
19947
  }
19864
19948
  if (!existing) {
19865
19949
  const db = await adapter.getDatabase();
19950
+ const status = beadExport.status === "tombstone" ? "closed" : beadExport.status;
19951
+ const isClosed = status === "closed";
19952
+ const closedAt = isClosed ? beadExport.closed_at ? new Date(beadExport.closed_at).getTime() : new Date(beadExport.updated_at).getTime() : null;
19866
19953
  await db.query(`INSERT INTO beads (
19867
19954
  id, project_key, type, status, title, description, priority,
19868
- parent_id, assignee, created_at, updated_at
19869
- ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, [
19955
+ parent_id, assignee, created_at, updated_at, closed_at
19956
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, [
19870
19957
  beadExport.id,
19871
19958
  projectKey,
19872
19959
  beadExport.issue_type,
19873
- beadExport.status === "tombstone" ? "closed" : beadExport.status,
19960
+ status,
19874
19961
  beadExport.title,
19875
19962
  beadExport.description || null,
19876
19963
  beadExport.priority,
19877
19964
  beadExport.parent_id || null,
19878
19965
  beadExport.assignee || null,
19879
19966
  new Date(beadExport.created_at).getTime(),
19880
- new Date(beadExport.updated_at).getTime()
19967
+ new Date(beadExport.updated_at).getTime(),
19968
+ closedAt
19881
19969
  ]);
19882
- if (beadExport.status === "closed" && beadExport.closed_at) {
19883
- await db.query("UPDATE beads SET closed_at = $1 WHERE id = $2", [new Date(beadExport.closed_at).getTime(), beadExport.id]);
19884
- }
19885
19970
  if (beadExport.status === "tombstone") {
19886
19971
  await db.query("UPDATE beads SET deleted_at = $1 WHERE id = $2", [Date.now(), beadExport.id]);
19887
19972
  }
@@ -19944,6 +20029,9 @@ async function computeBeadHash(adapter, projectKey, beadId) {
19944
20029
  return computeContentHash(beadExport);
19945
20030
  }
19946
20031
  async function importDependencies(adapter, projectKey, beadExport) {
20032
+ if (!beadExport.dependencies || beadExport.dependencies.length === 0) {
20033
+ return;
20034
+ }
19947
20035
  const db = await adapter.getDatabase();
19948
20036
  await db.query("DELETE FROM bead_dependencies WHERE bead_id = $1", [
19949
20037
  beadExport.id
@@ -19953,6 +20041,9 @@ async function importDependencies(adapter, projectKey, beadExport) {
19953
20041
  }
19954
20042
  }
19955
20043
  async function importLabels(adapter, projectKey, beadExport) {
20044
+ if (!beadExport.labels || beadExport.labels.length === 0) {
20045
+ return;
20046
+ }
19956
20047
  const db = await adapter.getDatabase();
19957
20048
  await db.query("DELETE FROM bead_labels WHERE bead_id = $1", [
19958
20049
  beadExport.id
@@ -19962,6 +20053,9 @@ async function importLabels(adapter, projectKey, beadExport) {
19962
20053
  }
19963
20054
  }
19964
20055
  async function importComments(adapter, projectKey, beadExport) {
20056
+ if (!beadExport.comments || beadExport.comments.length === 0) {
20057
+ return;
20058
+ }
19965
20059
  const db = await adapter.getDatabase();
19966
20060
  await db.query("DELETE FROM bead_comments WHERE bead_id = $1", [
19967
20061
  beadExport.id
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/streams/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAMnD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAMD,eAAO,MAAM,UAAU,EAAE,SAAS,EAgPjC,CAAC;AAmBF;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUnE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,aAAa,EAAE,CAAC,CAgB1B;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACvD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAmDD;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IACT,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CA4CD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CASlB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAK3E"}
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/streams/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAMnD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAMD,eAAO,MAAM,UAAU,EAAE,SAAS,EAoUjC,CAAC;AAmBF;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUnE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,aAAa,EAAE,CAAC,CAgB1B;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACvD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAmDD;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IACT,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CA4CD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CASlB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAK3E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swarm-mail",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Event sourcing primitives for multi-agent coordination. Local-first, no external servers.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",