@hasna/conversations 0.1.4 → 0.1.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.
- package/bin/hook.js +626 -0
- package/bin/index.js +234 -21
- package/bin/mcp.js +315 -156
- package/dist/hooks/blocker-hook.d.ts +2 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +243 -153
- package/dist/lib/identity.d.ts +1 -1
- package/dist/lib/messages.d.ts +1 -0
- package/dist/lib/presence.d.ts +1 -0
- package/dist/types.d.ts +2 -0
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ var __create = Object.create;
|
|
|
3
3
|
var __getProtoOf = Object.getPrototypeOf;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
8
|
var __toESM = (mod, isNodeMode, target) => {
|
|
8
9
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
@@ -15,7 +16,190 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
15
16
|
});
|
|
16
17
|
return to;
|
|
17
18
|
};
|
|
19
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
20
|
+
var __toCommonJS = (from) => {
|
|
21
|
+
var entry = __moduleCache.get(from), desc;
|
|
22
|
+
if (entry)
|
|
23
|
+
return entry;
|
|
24
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
25
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
26
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
27
|
+
get: () => from[key],
|
|
28
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
29
|
+
}));
|
|
30
|
+
__moduleCache.set(from, entry);
|
|
31
|
+
return entry;
|
|
32
|
+
};
|
|
18
33
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
|
+
var __export = (target, all) => {
|
|
35
|
+
for (var name in all)
|
|
36
|
+
__defProp(target, name, {
|
|
37
|
+
get: all[name],
|
|
38
|
+
enumerable: true,
|
|
39
|
+
configurable: true,
|
|
40
|
+
set: (newValue) => all[name] = () => newValue
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
44
|
+
|
|
45
|
+
// src/lib/db.ts
|
|
46
|
+
var exports_db = {};
|
|
47
|
+
__export(exports_db, {
|
|
48
|
+
getDbPath: () => getDbPath,
|
|
49
|
+
getDb: () => getDb,
|
|
50
|
+
closeDb: () => closeDb
|
|
51
|
+
});
|
|
52
|
+
import { Database } from "bun:sqlite";
|
|
53
|
+
import { mkdirSync } from "fs";
|
|
54
|
+
import { join, dirname } from "path";
|
|
55
|
+
import { homedir } from "os";
|
|
56
|
+
function getDbPath() {
|
|
57
|
+
if (process.env.CONVERSATIONS_DB_PATH)
|
|
58
|
+
return process.env.CONVERSATIONS_DB_PATH;
|
|
59
|
+
return join(homedir(), ".conversations", "messages.db");
|
|
60
|
+
}
|
|
61
|
+
function getDb() {
|
|
62
|
+
if (db)
|
|
63
|
+
return db;
|
|
64
|
+
const dbPath = getDbPath();
|
|
65
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
66
|
+
db = new Database(dbPath, { create: true });
|
|
67
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
68
|
+
db.exec("PRAGMA busy_timeout = 5000");
|
|
69
|
+
db.exec(`
|
|
70
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
71
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
72
|
+
session_id TEXT NOT NULL,
|
|
73
|
+
from_agent TEXT NOT NULL,
|
|
74
|
+
to_agent TEXT NOT NULL,
|
|
75
|
+
space TEXT,
|
|
76
|
+
content TEXT NOT NULL,
|
|
77
|
+
priority TEXT NOT NULL DEFAULT 'normal',
|
|
78
|
+
working_dir TEXT,
|
|
79
|
+
repository TEXT,
|
|
80
|
+
branch TEXT,
|
|
81
|
+
metadata TEXT,
|
|
82
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
83
|
+
read_at TEXT
|
|
84
|
+
)
|
|
85
|
+
`);
|
|
86
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id)");
|
|
87
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_to ON messages(to_agent)");
|
|
88
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_created ON messages(created_at)");
|
|
89
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_space ON messages(space)");
|
|
90
|
+
db.exec(`
|
|
91
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
92
|
+
id TEXT PRIMARY KEY,
|
|
93
|
+
name TEXT NOT NULL UNIQUE,
|
|
94
|
+
description TEXT,
|
|
95
|
+
path TEXT,
|
|
96
|
+
created_by TEXT NOT NULL,
|
|
97
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
98
|
+
metadata TEXT,
|
|
99
|
+
tags TEXT,
|
|
100
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
101
|
+
repository TEXT,
|
|
102
|
+
settings TEXT
|
|
103
|
+
)
|
|
104
|
+
`);
|
|
105
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_projects_name ON projects(name)");
|
|
106
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status)");
|
|
107
|
+
db.exec(`
|
|
108
|
+
CREATE TABLE IF NOT EXISTS spaces (
|
|
109
|
+
name TEXT PRIMARY KEY,
|
|
110
|
+
description TEXT,
|
|
111
|
+
parent_id TEXT REFERENCES spaces(name),
|
|
112
|
+
project_id TEXT REFERENCES projects(id),
|
|
113
|
+
created_by TEXT NOT NULL,
|
|
114
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
115
|
+
archived_at TEXT
|
|
116
|
+
)
|
|
117
|
+
`);
|
|
118
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_spaces_parent ON spaces(parent_id)");
|
|
119
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_spaces_project ON spaces(project_id)");
|
|
120
|
+
db.exec(`
|
|
121
|
+
CREATE TABLE IF NOT EXISTS space_members (
|
|
122
|
+
space TEXT NOT NULL REFERENCES spaces(name),
|
|
123
|
+
agent TEXT NOT NULL,
|
|
124
|
+
joined_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
125
|
+
PRIMARY KEY (space, agent)
|
|
126
|
+
)
|
|
127
|
+
`);
|
|
128
|
+
db.exec(`
|
|
129
|
+
CREATE TABLE IF NOT EXISTS agent_presence (
|
|
130
|
+
agent TEXT PRIMARY KEY,
|
|
131
|
+
status TEXT NOT NULL DEFAULT 'online',
|
|
132
|
+
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
133
|
+
metadata TEXT
|
|
134
|
+
)
|
|
135
|
+
`);
|
|
136
|
+
const existingTables = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all();
|
|
137
|
+
const tableNames = existingTables.map((t) => t.name);
|
|
138
|
+
if (tableNames.includes("channels") && tableNames.includes("spaces")) {
|
|
139
|
+
const spaceCount = db.prepare("SELECT COUNT(*) as c FROM spaces").get().c;
|
|
140
|
+
const channelCount = db.prepare("SELECT COUNT(*) as c FROM channels").get().c;
|
|
141
|
+
if (channelCount > 0 && spaceCount === 0) {
|
|
142
|
+
db.exec("BEGIN");
|
|
143
|
+
try {
|
|
144
|
+
db.exec(`
|
|
145
|
+
INSERT OR IGNORE INTO spaces (name, description, created_by, created_at)
|
|
146
|
+
SELECT name, description, created_by, created_at FROM channels
|
|
147
|
+
`);
|
|
148
|
+
if (tableNames.includes("channel_members")) {
|
|
149
|
+
db.exec(`
|
|
150
|
+
INSERT OR IGNORE INTO space_members (space, agent, joined_at)
|
|
151
|
+
SELECT channel, agent, joined_at FROM channel_members
|
|
152
|
+
`);
|
|
153
|
+
}
|
|
154
|
+
db.exec("COMMIT");
|
|
155
|
+
} catch (e) {
|
|
156
|
+
db.exec("ROLLBACK");
|
|
157
|
+
throw e;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
db.exec("DROP TABLE IF EXISTS channel_members");
|
|
161
|
+
db.exec("DROP TABLE IF EXISTS channels");
|
|
162
|
+
}
|
|
163
|
+
const msgCols = db.prepare("PRAGMA table_info(messages)").all();
|
|
164
|
+
const colNames = msgCols.map((c) => c.name);
|
|
165
|
+
if (colNames.includes("channel") && !colNames.includes("space")) {
|
|
166
|
+
db.exec("ALTER TABLE messages ADD COLUMN space TEXT");
|
|
167
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_space ON messages(space)");
|
|
168
|
+
db.exec("UPDATE messages SET space = channel WHERE channel IS NOT NULL");
|
|
169
|
+
db.exec(`
|
|
170
|
+
UPDATE messages
|
|
171
|
+
SET session_id = 'space:' || substr(session_id, 9)
|
|
172
|
+
WHERE session_id LIKE 'channel:%'
|
|
173
|
+
`);
|
|
174
|
+
}
|
|
175
|
+
const spaceCols = db.prepare("PRAGMA table_info(spaces)").all();
|
|
176
|
+
const spaceColNames = spaceCols.map((c) => c.name);
|
|
177
|
+
if (!spaceColNames.includes("archived_at")) {
|
|
178
|
+
db.exec("ALTER TABLE spaces ADD COLUMN archived_at TEXT");
|
|
179
|
+
}
|
|
180
|
+
const msgCols2 = db.prepare("PRAGMA table_info(messages)").all();
|
|
181
|
+
const colNames2 = msgCols2.map((c) => c.name);
|
|
182
|
+
if (!colNames2.includes("edited_at")) {
|
|
183
|
+
db.exec("ALTER TABLE messages ADD COLUMN edited_at TEXT");
|
|
184
|
+
}
|
|
185
|
+
if (!colNames2.includes("pinned_at")) {
|
|
186
|
+
db.exec("ALTER TABLE messages ADD COLUMN pinned_at TEXT");
|
|
187
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_pinned ON messages(pinned_at)");
|
|
188
|
+
}
|
|
189
|
+
if (!colNames2.includes("blocking")) {
|
|
190
|
+
db.exec("ALTER TABLE messages ADD COLUMN blocking INTEGER NOT NULL DEFAULT 0");
|
|
191
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_blocking ON messages(blocking)");
|
|
192
|
+
}
|
|
193
|
+
return db;
|
|
194
|
+
}
|
|
195
|
+
function closeDb() {
|
|
196
|
+
if (db) {
|
|
197
|
+
db.close();
|
|
198
|
+
db = null;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
var db = null;
|
|
202
|
+
var init_db = () => {};
|
|
19
203
|
|
|
20
204
|
// node_modules/react/cjs/react.development.js
|
|
21
205
|
var require_react_development = __commonJS((exports, module) => {
|
|
@@ -1828,155 +2012,8 @@ var require_react = __commonJS((exports, module) => {
|
|
|
1828
2012
|
}
|
|
1829
2013
|
});
|
|
1830
2014
|
|
|
1831
|
-
// src/lib/db.ts
|
|
1832
|
-
import { Database } from "bun:sqlite";
|
|
1833
|
-
import { mkdirSync } from "fs";
|
|
1834
|
-
import { join, dirname } from "path";
|
|
1835
|
-
import { homedir } from "os";
|
|
1836
|
-
var db = null;
|
|
1837
|
-
function getDbPath() {
|
|
1838
|
-
if (process.env.CONVERSATIONS_DB_PATH)
|
|
1839
|
-
return process.env.CONVERSATIONS_DB_PATH;
|
|
1840
|
-
return join(homedir(), ".conversations", "messages.db");
|
|
1841
|
-
}
|
|
1842
|
-
function getDb() {
|
|
1843
|
-
if (db)
|
|
1844
|
-
return db;
|
|
1845
|
-
const dbPath = getDbPath();
|
|
1846
|
-
mkdirSync(dirname(dbPath), { recursive: true });
|
|
1847
|
-
db = new Database(dbPath, { create: true });
|
|
1848
|
-
db.exec("PRAGMA journal_mode = WAL");
|
|
1849
|
-
db.exec("PRAGMA busy_timeout = 5000");
|
|
1850
|
-
db.exec(`
|
|
1851
|
-
CREATE TABLE IF NOT EXISTS messages (
|
|
1852
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1853
|
-
session_id TEXT NOT NULL,
|
|
1854
|
-
from_agent TEXT NOT NULL,
|
|
1855
|
-
to_agent TEXT NOT NULL,
|
|
1856
|
-
space TEXT,
|
|
1857
|
-
content TEXT NOT NULL,
|
|
1858
|
-
priority TEXT NOT NULL DEFAULT 'normal',
|
|
1859
|
-
working_dir TEXT,
|
|
1860
|
-
repository TEXT,
|
|
1861
|
-
branch TEXT,
|
|
1862
|
-
metadata TEXT,
|
|
1863
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
1864
|
-
read_at TEXT
|
|
1865
|
-
)
|
|
1866
|
-
`);
|
|
1867
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id)");
|
|
1868
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_to ON messages(to_agent)");
|
|
1869
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_created ON messages(created_at)");
|
|
1870
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_space ON messages(space)");
|
|
1871
|
-
db.exec(`
|
|
1872
|
-
CREATE TABLE IF NOT EXISTS projects (
|
|
1873
|
-
id TEXT PRIMARY KEY,
|
|
1874
|
-
name TEXT NOT NULL UNIQUE,
|
|
1875
|
-
description TEXT,
|
|
1876
|
-
path TEXT,
|
|
1877
|
-
created_by TEXT NOT NULL,
|
|
1878
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
1879
|
-
metadata TEXT,
|
|
1880
|
-
tags TEXT,
|
|
1881
|
-
status TEXT NOT NULL DEFAULT 'active',
|
|
1882
|
-
repository TEXT,
|
|
1883
|
-
settings TEXT
|
|
1884
|
-
)
|
|
1885
|
-
`);
|
|
1886
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_projects_name ON projects(name)");
|
|
1887
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status)");
|
|
1888
|
-
db.exec(`
|
|
1889
|
-
CREATE TABLE IF NOT EXISTS spaces (
|
|
1890
|
-
name TEXT PRIMARY KEY,
|
|
1891
|
-
description TEXT,
|
|
1892
|
-
parent_id TEXT REFERENCES spaces(name),
|
|
1893
|
-
project_id TEXT REFERENCES projects(id),
|
|
1894
|
-
created_by TEXT NOT NULL,
|
|
1895
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
1896
|
-
archived_at TEXT
|
|
1897
|
-
)
|
|
1898
|
-
`);
|
|
1899
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_spaces_parent ON spaces(parent_id)");
|
|
1900
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_spaces_project ON spaces(project_id)");
|
|
1901
|
-
db.exec(`
|
|
1902
|
-
CREATE TABLE IF NOT EXISTS space_members (
|
|
1903
|
-
space TEXT NOT NULL REFERENCES spaces(name),
|
|
1904
|
-
agent TEXT NOT NULL,
|
|
1905
|
-
joined_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
1906
|
-
PRIMARY KEY (space, agent)
|
|
1907
|
-
)
|
|
1908
|
-
`);
|
|
1909
|
-
db.exec(`
|
|
1910
|
-
CREATE TABLE IF NOT EXISTS agent_presence (
|
|
1911
|
-
agent TEXT PRIMARY KEY,
|
|
1912
|
-
status TEXT NOT NULL DEFAULT 'online',
|
|
1913
|
-
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
1914
|
-
metadata TEXT
|
|
1915
|
-
)
|
|
1916
|
-
`);
|
|
1917
|
-
const existingTables = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all();
|
|
1918
|
-
const tableNames = existingTables.map((t) => t.name);
|
|
1919
|
-
if (tableNames.includes("channels") && tableNames.includes("spaces")) {
|
|
1920
|
-
const spaceCount = db.prepare("SELECT COUNT(*) as c FROM spaces").get().c;
|
|
1921
|
-
const channelCount = db.prepare("SELECT COUNT(*) as c FROM channels").get().c;
|
|
1922
|
-
if (channelCount > 0 && spaceCount === 0) {
|
|
1923
|
-
db.exec("BEGIN");
|
|
1924
|
-
try {
|
|
1925
|
-
db.exec(`
|
|
1926
|
-
INSERT OR IGNORE INTO spaces (name, description, created_by, created_at)
|
|
1927
|
-
SELECT name, description, created_by, created_at FROM channels
|
|
1928
|
-
`);
|
|
1929
|
-
if (tableNames.includes("channel_members")) {
|
|
1930
|
-
db.exec(`
|
|
1931
|
-
INSERT OR IGNORE INTO space_members (space, agent, joined_at)
|
|
1932
|
-
SELECT channel, agent, joined_at FROM channel_members
|
|
1933
|
-
`);
|
|
1934
|
-
}
|
|
1935
|
-
db.exec("COMMIT");
|
|
1936
|
-
} catch (e) {
|
|
1937
|
-
db.exec("ROLLBACK");
|
|
1938
|
-
throw e;
|
|
1939
|
-
}
|
|
1940
|
-
}
|
|
1941
|
-
db.exec("DROP TABLE IF EXISTS channel_members");
|
|
1942
|
-
db.exec("DROP TABLE IF EXISTS channels");
|
|
1943
|
-
}
|
|
1944
|
-
const msgCols = db.prepare("PRAGMA table_info(messages)").all();
|
|
1945
|
-
const colNames = msgCols.map((c) => c.name);
|
|
1946
|
-
if (colNames.includes("channel") && !colNames.includes("space")) {
|
|
1947
|
-
db.exec("ALTER TABLE messages ADD COLUMN space TEXT");
|
|
1948
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_space ON messages(space)");
|
|
1949
|
-
db.exec("UPDATE messages SET space = channel WHERE channel IS NOT NULL");
|
|
1950
|
-
db.exec(`
|
|
1951
|
-
UPDATE messages
|
|
1952
|
-
SET session_id = 'space:' || substr(session_id, 9)
|
|
1953
|
-
WHERE session_id LIKE 'channel:%'
|
|
1954
|
-
`);
|
|
1955
|
-
}
|
|
1956
|
-
const spaceCols = db.prepare("PRAGMA table_info(spaces)").all();
|
|
1957
|
-
const spaceColNames = spaceCols.map((c) => c.name);
|
|
1958
|
-
if (!spaceColNames.includes("archived_at")) {
|
|
1959
|
-
db.exec("ALTER TABLE spaces ADD COLUMN archived_at TEXT");
|
|
1960
|
-
}
|
|
1961
|
-
const msgCols2 = db.prepare("PRAGMA table_info(messages)").all();
|
|
1962
|
-
const colNames2 = msgCols2.map((c) => c.name);
|
|
1963
|
-
if (!colNames2.includes("edited_at")) {
|
|
1964
|
-
db.exec("ALTER TABLE messages ADD COLUMN edited_at TEXT");
|
|
1965
|
-
}
|
|
1966
|
-
if (!colNames2.includes("pinned_at")) {
|
|
1967
|
-
db.exec("ALTER TABLE messages ADD COLUMN pinned_at TEXT");
|
|
1968
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_pinned ON messages(pinned_at)");
|
|
1969
|
-
}
|
|
1970
|
-
return db;
|
|
1971
|
-
}
|
|
1972
|
-
function closeDb() {
|
|
1973
|
-
if (db) {
|
|
1974
|
-
db.close();
|
|
1975
|
-
db = null;
|
|
1976
|
-
}
|
|
1977
|
-
}
|
|
1978
|
-
|
|
1979
2015
|
// src/lib/messages.ts
|
|
2016
|
+
init_db();
|
|
1980
2017
|
import { randomUUID } from "crypto";
|
|
1981
2018
|
function parseMessage(row) {
|
|
1982
2019
|
let metadata = null;
|
|
@@ -1989,7 +2026,8 @@ function parseMessage(row) {
|
|
|
1989
2026
|
}
|
|
1990
2027
|
return {
|
|
1991
2028
|
...row,
|
|
1992
|
-
metadata
|
|
2029
|
+
metadata,
|
|
2030
|
+
blocking: !!row.blocking
|
|
1993
2031
|
};
|
|
1994
2032
|
}
|
|
1995
2033
|
function sendMessage(opts) {
|
|
@@ -1998,12 +2036,13 @@ function sendMessage(opts) {
|
|
|
1998
2036
|
const sessionId = explicitSession ?? (opts.space ? `space:${opts.space}` : `${[opts.from, opts.to].sort().join("-")}-${randomUUID().slice(0, 8)}`);
|
|
1999
2037
|
const metadata = opts.metadata ? JSON.stringify(opts.metadata) : null;
|
|
2000
2038
|
const normalizedPriority = opts.priority === "low" || opts.priority === "normal" || opts.priority === "high" || opts.priority === "urgent" ? opts.priority : "normal";
|
|
2039
|
+
const blocking = opts.blocking ? 1 : 0;
|
|
2001
2040
|
const stmt = db2.prepare(`
|
|
2002
|
-
INSERT INTO messages (session_id, from_agent, to_agent, space, content, priority, working_dir, repository, branch, metadata)
|
|
2003
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2041
|
+
INSERT INTO messages (session_id, from_agent, to_agent, space, content, priority, working_dir, repository, branch, metadata, blocking)
|
|
2042
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2004
2043
|
RETURNING *
|
|
2005
2044
|
`);
|
|
2006
|
-
const row = stmt.get(sessionId, opts.from, opts.to, opts.space || null, opts.content, normalizedPriority, opts.working_dir || null, opts.repository || null, opts.branch || null, metadata);
|
|
2045
|
+
const row = stmt.get(sessionId, opts.from, opts.to, opts.space || null, opts.content, normalizedPriority, opts.working_dir || null, opts.repository || null, opts.branch || null, metadata, blocking);
|
|
2007
2046
|
return parseMessage(row);
|
|
2008
2047
|
}
|
|
2009
2048
|
function readMessages(opts = {}) {
|
|
@@ -2172,6 +2211,19 @@ function getPinnedMessages(opts) {
|
|
|
2172
2211
|
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY pinned_at DESC, id DESC ${limit}`).all(...params);
|
|
2173
2212
|
return rows.map(parseMessage);
|
|
2174
2213
|
}
|
|
2214
|
+
function getUnreadBlockers(agent) {
|
|
2215
|
+
const db2 = getDb();
|
|
2216
|
+
const rows = db2.prepare(`
|
|
2217
|
+
SELECT * FROM messages
|
|
2218
|
+
WHERE blocking = 1 AND read_at IS NULL
|
|
2219
|
+
AND (
|
|
2220
|
+
to_agent = ?
|
|
2221
|
+
OR space IN (SELECT space FROM space_members WHERE agent = ?)
|
|
2222
|
+
)
|
|
2223
|
+
ORDER BY created_at ASC, id ASC
|
|
2224
|
+
`).all(agent, agent);
|
|
2225
|
+
return rows.map(parseMessage);
|
|
2226
|
+
}
|
|
2175
2227
|
function searchMessages(opts) {
|
|
2176
2228
|
const db2 = getDb();
|
|
2177
2229
|
const conditions = ["content LIKE ?"];
|
|
@@ -2194,6 +2246,7 @@ function searchMessages(opts) {
|
|
|
2194
2246
|
return rows.map(parseMessage);
|
|
2195
2247
|
}
|
|
2196
2248
|
// src/lib/sessions.ts
|
|
2249
|
+
init_db();
|
|
2197
2250
|
function listSessions(agent) {
|
|
2198
2251
|
const db2 = getDb();
|
|
2199
2252
|
const agentFilter = agent ? "WHERE from_agent = ? OR to_agent = ?" : "";
|
|
@@ -2248,6 +2301,7 @@ function getSession(sessionId) {
|
|
|
2248
2301
|
};
|
|
2249
2302
|
}
|
|
2250
2303
|
// src/lib/spaces.ts
|
|
2304
|
+
init_db();
|
|
2251
2305
|
function getSpaceDepth(spaceName) {
|
|
2252
2306
|
const db2 = getDb();
|
|
2253
2307
|
let depth = 0;
|
|
@@ -2429,6 +2483,7 @@ function isSpaceMember(spaceName, agent) {
|
|
|
2429
2483
|
return !!row;
|
|
2430
2484
|
}
|
|
2431
2485
|
// src/lib/projects.ts
|
|
2486
|
+
init_db();
|
|
2432
2487
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2433
2488
|
function parseProject(row) {
|
|
2434
2489
|
let metadata = null;
|
|
@@ -2592,6 +2647,10 @@ function deleteProject(id) {
|
|
|
2592
2647
|
const result = db2.prepare("DELETE FROM projects WHERE id = ?").run(id);
|
|
2593
2648
|
return result.changes > 0;
|
|
2594
2649
|
}
|
|
2650
|
+
|
|
2651
|
+
// src/index.ts
|
|
2652
|
+
init_db();
|
|
2653
|
+
|
|
2595
2654
|
// src/lib/poll.ts
|
|
2596
2655
|
var import_react = __toESM(require_react(), 1);
|
|
2597
2656
|
function startPolling(opts) {
|
|
@@ -3017,6 +3076,16 @@ var AGENT_NAMES = [
|
|
|
3017
3076
|
// src/lib/identity.ts
|
|
3018
3077
|
var AGENT_ID_FILE = join2(homedir2(), ".conversations", "agent-id");
|
|
3019
3078
|
var cachedAutoName = null;
|
|
3079
|
+
function isNameTaken(name) {
|
|
3080
|
+
try {
|
|
3081
|
+
const { getDb: getDb2 } = (init_db(), __toCommonJS(exports_db));
|
|
3082
|
+
const db2 = getDb2();
|
|
3083
|
+
const row = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(name);
|
|
3084
|
+
return !!row;
|
|
3085
|
+
} catch {
|
|
3086
|
+
return false;
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3020
3089
|
function getAutoName() {
|
|
3021
3090
|
if (cachedAutoName)
|
|
3022
3091
|
return cachedAutoName;
|
|
@@ -3027,7 +3096,14 @@ function getAutoName() {
|
|
|
3027
3096
|
return name2;
|
|
3028
3097
|
}
|
|
3029
3098
|
} catch {}
|
|
3030
|
-
const
|
|
3099
|
+
const shuffled = [...AGENT_NAMES].sort(() => Math.random() - 0.5);
|
|
3100
|
+
let name = shuffled[0];
|
|
3101
|
+
for (const candidate of shuffled) {
|
|
3102
|
+
if (!isNameTaken(candidate)) {
|
|
3103
|
+
name = candidate;
|
|
3104
|
+
break;
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3031
3107
|
cachedAutoName = name;
|
|
3032
3108
|
try {
|
|
3033
3109
|
mkdirSync2(dirname2(AGENT_ID_FILE), { recursive: true });
|
|
@@ -3055,6 +3131,7 @@ function requireIdentity(explicit) {
|
|
|
3055
3131
|
throw new Error("Agent identity required. Set CONVERSATIONS_AGENT_ID env var or pass --from flag.");
|
|
3056
3132
|
}
|
|
3057
3133
|
// src/lib/presence.ts
|
|
3134
|
+
init_db();
|
|
3058
3135
|
var ONLINE_THRESHOLD_SECONDS = 60;
|
|
3059
3136
|
function parsePresence(row) {
|
|
3060
3137
|
let metadata = null;
|
|
@@ -3111,6 +3188,17 @@ function removePresence(agent) {
|
|
|
3111
3188
|
const result = db2.prepare("DELETE FROM agent_presence WHERE agent = ?").run(agent);
|
|
3112
3189
|
return result.changes > 0;
|
|
3113
3190
|
}
|
|
3191
|
+
function renameAgent(oldName, newName) {
|
|
3192
|
+
const db2 = getDb();
|
|
3193
|
+
const existing = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(oldName);
|
|
3194
|
+
if (!existing)
|
|
3195
|
+
return false;
|
|
3196
|
+
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(newName);
|
|
3197
|
+
if (conflict)
|
|
3198
|
+
throw new Error(`Agent "${newName}" already exists`);
|
|
3199
|
+
db2.prepare("UPDATE agent_presence SET agent = ? WHERE agent = ?").run(newName, oldName);
|
|
3200
|
+
return true;
|
|
3201
|
+
}
|
|
3114
3202
|
export {
|
|
3115
3203
|
useSpaceMessages,
|
|
3116
3204
|
updateSpace,
|
|
@@ -3122,6 +3210,7 @@ export {
|
|
|
3122
3210
|
searchMessages,
|
|
3123
3211
|
resolveIdentity,
|
|
3124
3212
|
requireIdentity,
|
|
3213
|
+
renameAgent,
|
|
3125
3214
|
removePresence,
|
|
3126
3215
|
readMessages,
|
|
3127
3216
|
pinMessage,
|
|
@@ -3137,6 +3226,7 @@ export {
|
|
|
3137
3226
|
joinSpace,
|
|
3138
3227
|
isSpaceMember,
|
|
3139
3228
|
heartbeat,
|
|
3229
|
+
getUnreadBlockers,
|
|
3140
3230
|
getSpaceMembers,
|
|
3141
3231
|
getSpaceDepth,
|
|
3142
3232
|
getSpace,
|
package/dist/lib/identity.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Get or create a persistent auto-generated agent name.
|
|
3
3
|
* Stored in ~/.conversations/agent-id so the same installation
|
|
4
|
-
* always gets the same name.
|
|
4
|
+
* always gets the same name. Checks the DB to avoid duplicates.
|
|
5
5
|
*/
|
|
6
6
|
export declare function getAutoName(): string;
|
|
7
7
|
/**
|
package/dist/lib/messages.d.ts
CHANGED
package/dist/lib/presence.d.ts
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface Message {
|
|
|
15
15
|
read_at: string | null;
|
|
16
16
|
edited_at: string | null;
|
|
17
17
|
pinned_at: string | null;
|
|
18
|
+
blocking: boolean;
|
|
18
19
|
}
|
|
19
20
|
export interface Session {
|
|
20
21
|
session_id: string;
|
|
@@ -69,6 +70,7 @@ export interface SendMessageOptions {
|
|
|
69
70
|
repository?: string;
|
|
70
71
|
branch?: string;
|
|
71
72
|
metadata?: Record<string, unknown>;
|
|
73
|
+
blocking?: boolean;
|
|
72
74
|
}
|
|
73
75
|
export interface ReadMessagesOptions {
|
|
74
76
|
session_id?: string;
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/conversations",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Real-time CLI messaging for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"conversations": "bin/index.js",
|
|
8
|
-
"conversations-mcp": "bin/mcp.js"
|
|
8
|
+
"conversations-mcp": "bin/mcp.js",
|
|
9
|
+
"conversations-hook": "bin/hook.js"
|
|
9
10
|
},
|
|
10
11
|
"exports": {
|
|
11
12
|
".": {
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
"main": "./dist/index.js",
|
|
24
25
|
"types": "./dist/index.d.ts",
|
|
25
26
|
"scripts": {
|
|
26
|
-
"build": "bun build ./src/cli/index.tsx --outdir ./bin --target bun --external ink --external react --external chalk && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/index.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
27
|
+
"build": "bun build ./src/cli/index.tsx --outdir ./bin --target bun --external ink --external react --external chalk && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/hooks/blocker-hook.ts --outfile ./bin/hook.js --target bun && bun build ./src/index.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
27
28
|
"build:dashboard": "cd dashboard && bun install && bun run build",
|
|
28
29
|
"test": "bun test",
|
|
29
30
|
"dev": "bun run ./src/cli/index.tsx",
|