opencode-mailbox 0.0.0 → 0.0.2
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/README.md +7 -4
- package/dist/index.js +63 -44
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -4,7 +4,9 @@ A simple mailbox system for sending and receiving messages between sessions.
|
|
|
4
4
|
|
|
5
5
|
## Description
|
|
6
6
|
|
|
7
|
-
This OpenCode plugin provides a lightweight mailbox system that allows sessions to send messages to each other asynchronously. Messages are stored
|
|
7
|
+
This OpenCode plugin provides a lightweight mailbox system that allows sessions to send messages to each other asynchronously. Messages are stored in a SQLite database with proper indexing for fast lookups.
|
|
8
|
+
|
|
9
|
+
**NOTE: Mail is stored in `~/.config/opencode/mailbox.db`**
|
|
8
10
|
|
|
9
11
|
## Installation
|
|
10
12
|
|
|
@@ -58,9 +60,10 @@ Stop all mail watching for the current session.
|
|
|
58
60
|
|
|
59
61
|
## Storage
|
|
60
62
|
|
|
61
|
-
Mail data is persisted in
|
|
62
|
-
-
|
|
63
|
-
-
|
|
63
|
+
Mail data is persisted in a SQLite database at `~/.config/opencode/mailbox.db`. The database includes:
|
|
64
|
+
- Indexed `recipient` column for fast recipient lookups
|
|
65
|
+
- Indexed `read` status for efficient watch queries
|
|
66
|
+
- WAL (Write-Ahead Logging) mode for better concurrency
|
|
64
67
|
|
|
65
68
|
## Session Management
|
|
66
69
|
|
package/dist/index.js
CHANGED
|
@@ -12677,30 +12677,68 @@ var init_dist = __esm(() => {
|
|
|
12677
12677
|
});
|
|
12678
12678
|
|
|
12679
12679
|
// index.ts
|
|
12680
|
-
import * as fs from "fs";
|
|
12681
12680
|
import * as path from "path";
|
|
12682
|
-
|
|
12681
|
+
import Database from "better-sqlite3";
|
|
12682
|
+
var dbFile = null;
|
|
12683
|
+
var db = null;
|
|
12683
12684
|
var activeWatches = new Map;
|
|
12684
|
-
async function
|
|
12685
|
-
if (!
|
|
12685
|
+
async function getDbFile(client) {
|
|
12686
|
+
if (!dbFile) {
|
|
12686
12687
|
const result = await client.path.get();
|
|
12687
|
-
|
|
12688
|
-
}
|
|
12689
|
-
return
|
|
12690
|
-
}
|
|
12691
|
-
async function
|
|
12692
|
-
|
|
12693
|
-
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12697
|
-
|
|
12698
|
-
|
|
12699
|
-
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
|
|
12703
|
-
|
|
12688
|
+
dbFile = path.join(result.data.config, "mailbox.db");
|
|
12689
|
+
}
|
|
12690
|
+
return dbFile;
|
|
12691
|
+
}
|
|
12692
|
+
async function getDatabase(client) {
|
|
12693
|
+
if (!db) {
|
|
12694
|
+
const file2 = await getDbFile(client);
|
|
12695
|
+
db = new Database(file2);
|
|
12696
|
+
db.pragma("journal_mode = WAL");
|
|
12697
|
+
db.exec(`
|
|
12698
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
12699
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
12700
|
+
recipient TEXT NOT NULL,
|
|
12701
|
+
sender TEXT NOT NULL,
|
|
12702
|
+
message TEXT NOT NULL,
|
|
12703
|
+
timestamp INTEGER NOT NULL,
|
|
12704
|
+
read INTEGER NOT NULL DEFAULT 0
|
|
12705
|
+
)
|
|
12706
|
+
`);
|
|
12707
|
+
db.exec(`
|
|
12708
|
+
CREATE INDEX IF NOT EXISTS idx_messages_recipient ON messages(recipient)
|
|
12709
|
+
`);
|
|
12710
|
+
db.exec(`
|
|
12711
|
+
CREATE INDEX IF NOT EXISTS idx_messages_read ON messages(recipient, read)
|
|
12712
|
+
`);
|
|
12713
|
+
}
|
|
12714
|
+
return db;
|
|
12715
|
+
}
|
|
12716
|
+
async function addMessage(client, recipient, sender, message, timestamp) {
|
|
12717
|
+
const database = await getDatabase(client);
|
|
12718
|
+
const stmt = database.prepare(`
|
|
12719
|
+
INSERT INTO messages (recipient, sender, message, timestamp, read)
|
|
12720
|
+
VALUES (?, ?, ?, ?, 0)
|
|
12721
|
+
`);
|
|
12722
|
+
stmt.run(recipient.toLowerCase(), sender.toLowerCase(), message, timestamp);
|
|
12723
|
+
}
|
|
12724
|
+
async function getUnreadMessages(client, recipient) {
|
|
12725
|
+
const database = await getDatabase(client);
|
|
12726
|
+
const stmt = database.prepare(`
|
|
12727
|
+
SELECT sender as from, message, timestamp, read
|
|
12728
|
+
FROM messages
|
|
12729
|
+
WHERE recipient = ? AND read = 0
|
|
12730
|
+
ORDER BY timestamp ASC
|
|
12731
|
+
`);
|
|
12732
|
+
return stmt.all(recipient.toLowerCase());
|
|
12733
|
+
}
|
|
12734
|
+
async function markMessageAsRead(client, recipient, timestamp) {
|
|
12735
|
+
const database = await getDatabase(client);
|
|
12736
|
+
const stmt = database.prepare(`
|
|
12737
|
+
UPDATE messages
|
|
12738
|
+
SET read = 1
|
|
12739
|
+
WHERE recipient = ? AND timestamp = ?
|
|
12740
|
+
`);
|
|
12741
|
+
stmt.run(recipient.toLowerCase(), timestamp);
|
|
12704
12742
|
}
|
|
12705
12743
|
function startMailWatch(client, recipient, sessionId, instructions) {
|
|
12706
12744
|
if (activeWatches.has(recipient)) {
|
|
@@ -12708,25 +12746,16 @@ function startMailWatch(client, recipient, sessionId, instructions) {
|
|
|
12708
12746
|
}
|
|
12709
12747
|
const interval = setInterval(async () => {
|
|
12710
12748
|
try {
|
|
12711
|
-
const mailbox = await loadMailbox(client);
|
|
12712
12749
|
const watch = activeWatches.get(recipient);
|
|
12713
12750
|
if (!watch) {
|
|
12714
12751
|
return;
|
|
12715
12752
|
}
|
|
12716
|
-
const
|
|
12717
|
-
if (
|
|
12753
|
+
const unreadMessages = await getUnreadMessages(client, recipient);
|
|
12754
|
+
if (unreadMessages.length === 0) {
|
|
12718
12755
|
return;
|
|
12719
12756
|
}
|
|
12720
|
-
const unreadMessages = [];
|
|
12721
|
-
for (const [timestamp, message] of Object.entries(recipientMailbox)) {
|
|
12722
|
-
if (!message.read) {
|
|
12723
|
-
unreadMessages.push(message);
|
|
12724
|
-
}
|
|
12725
|
-
}
|
|
12726
|
-
unreadMessages.sort((a, b) => a.timestamp - b.timestamp);
|
|
12727
12757
|
for (const message of unreadMessages) {
|
|
12728
|
-
|
|
12729
|
-
await saveMailbox(client, mailbox);
|
|
12758
|
+
await markMessageAsRead(client, recipient, message.timestamp);
|
|
12730
12759
|
await injectMailMessage(client, sessionId, recipient, message, instructions);
|
|
12731
12760
|
}
|
|
12732
12761
|
} catch (error45) {
|
|
@@ -12793,20 +12822,10 @@ var mailboxPlugin = async (ctx) => {
|
|
|
12793
12822
|
message: z.string().describe("Message content to send")
|
|
12794
12823
|
},
|
|
12795
12824
|
async execute(args) {
|
|
12796
|
-
const mailbox = await loadMailbox(client);
|
|
12797
12825
|
const to = args.to.toLowerCase();
|
|
12798
12826
|
const from = args.from.toLowerCase();
|
|
12799
12827
|
const timestamp = Date.now();
|
|
12800
|
-
|
|
12801
|
-
mailbox[to] = {};
|
|
12802
|
-
}
|
|
12803
|
-
mailbox[to][timestamp] = {
|
|
12804
|
-
from,
|
|
12805
|
-
message: args.message,
|
|
12806
|
-
timestamp,
|
|
12807
|
-
read: false
|
|
12808
|
-
};
|
|
12809
|
-
await saveMailbox(client, mailbox);
|
|
12828
|
+
await addMessage(client, to, from, args.message, timestamp);
|
|
12810
12829
|
return `Mail sent to "${args.to}" from "${args.from}" at ${new Date(timestamp).toISOString()}`;
|
|
12811
12830
|
}
|
|
12812
12831
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-mailbox",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "A simple mailbox system for sending and receiving messages between sessions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
"README.md"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "bun build ./index.ts --outdir ./dist --target bun && bun run build:types",
|
|
19
|
+
"build": "bun build ./index.ts --outdir ./dist --target bun --external better-sqlite3 && bun run build:types",
|
|
20
20
|
"build:types": "tsc --emitDeclarationOnly",
|
|
21
21
|
"start": "bun run build",
|
|
22
22
|
"prepublishOnly": "bun run build"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
+
"@types/better-sqlite3": "^7.6.12",
|
|
25
26
|
"@types/node": "^25.0.10",
|
|
26
27
|
"electron": "^28.0.0",
|
|
27
28
|
"typescript": "^5.9.3"
|
|
@@ -30,6 +31,7 @@
|
|
|
30
31
|
"@opencode-ai/plugin": "^1.1.25"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
34
|
+
"better-sqlite3": "^12.1.0",
|
|
33
35
|
"dotenv": "^17.2.3"
|
|
34
36
|
},
|
|
35
37
|
"keywords": [
|