agent-remnote 0.0.1 → 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.
Files changed (102) hide show
  1. package/cli.js +2 -0
  2. package/dist/apps/cli/src/adapters/mcp.js +1 -0
  3. package/dist/apps/cli/src/commands/_enqueue.js +138 -0
  4. package/dist/apps/cli/src/commands/_shared.js +57 -0
  5. package/dist/apps/cli/src/commands/_tool.js +28 -0
  6. package/dist/apps/cli/src/commands/apply.js +81 -0
  7. package/dist/apps/cli/src/commands/config/index.js +3 -0
  8. package/dist/apps/cli/src/commands/config/print.js +28 -0
  9. package/dist/apps/cli/src/commands/daily/index.js +4 -0
  10. package/dist/apps/cli/src/commands/daily/summary.js +25 -0
  11. package/dist/apps/cli/src/commands/daily/write.js +145 -0
  12. package/dist/apps/cli/src/commands/db/backups.js +23 -0
  13. package/dist/apps/cli/src/commands/db/index.js +4 -0
  14. package/dist/apps/cli/src/commands/db/recent.js +178 -0
  15. package/dist/apps/cli/src/commands/doctor.js +124 -0
  16. package/dist/apps/cli/src/commands/index.js +73 -0
  17. package/dist/apps/cli/src/commands/ops/index.js +4 -0
  18. package/dist/apps/cli/src/commands/ops/list.js +12 -0
  19. package/dist/apps/cli/src/commands/ops/schema.js +77 -0
  20. package/dist/apps/cli/src/commands/queue/enqueue.js +73 -0
  21. package/dist/apps/cli/src/commands/queue/index.js +5 -0
  22. package/dist/apps/cli/src/commands/queue/inspect.js +26 -0
  23. package/dist/apps/cli/src/commands/queue/stats.js +14 -0
  24. package/dist/apps/cli/src/commands/read/by-reference.js +35 -0
  25. package/dist/apps/cli/src/commands/read/connections.js +15 -0
  26. package/dist/apps/cli/src/commands/read/index.js +21 -0
  27. package/dist/apps/cli/src/commands/read/inspect.js +34 -0
  28. package/dist/apps/cli/src/commands/read/outline.js +59 -0
  29. package/dist/apps/cli/src/commands/read/query.js +95 -0
  30. package/dist/apps/cli/src/commands/read/references.js +41 -0
  31. package/dist/apps/cli/src/commands/read/resolve-ref.js +32 -0
  32. package/dist/apps/cli/src/commands/read/search.js +40 -0
  33. package/dist/apps/cli/src/commands/read/table.js +32 -0
  34. package/dist/apps/cli/src/commands/todos/index.js +3 -0
  35. package/dist/apps/cli/src/commands/todos/list.js +33 -0
  36. package/dist/apps/cli/src/commands/topic/index.js +3 -0
  37. package/dist/apps/cli/src/commands/topic/summary.js +44 -0
  38. package/dist/apps/cli/src/commands/wechat/index.js +3 -0
  39. package/dist/apps/cli/src/commands/wechat/outline.js +430 -0
  40. package/dist/apps/cli/src/commands/write/bullet.js +76 -0
  41. package/dist/apps/cli/src/commands/write/index.js +4 -0
  42. package/dist/apps/cli/src/commands/write/md.js +91 -0
  43. package/dist/apps/cli/src/commands/ws/_shared.js +129 -0
  44. package/dist/apps/cli/src/commands/ws/ensure.js +22 -0
  45. package/dist/apps/cli/src/commands/ws/health.js +15 -0
  46. package/dist/apps/cli/src/commands/ws/index.js +21 -0
  47. package/dist/apps/cli/src/commands/ws/logs.js +95 -0
  48. package/dist/apps/cli/src/commands/ws/restart.js +73 -0
  49. package/dist/apps/cli/src/commands/ws/serve.js +52 -0
  50. package/dist/apps/cli/src/commands/ws/start.js +70 -0
  51. package/dist/apps/cli/src/commands/ws/status.js +60 -0
  52. package/dist/apps/cli/src/commands/ws/stop.js +59 -0
  53. package/dist/apps/cli/src/commands/ws/trigger.js +20 -0
  54. package/dist/apps/cli/src/main.js +79 -0
  55. package/dist/apps/cli/src/services/AppConfig.js +3 -0
  56. package/dist/apps/cli/src/services/Config.js +91 -0
  57. package/dist/apps/cli/src/services/DaemonFiles.js +91 -0
  58. package/dist/apps/cli/src/services/Errors.js +49 -0
  59. package/dist/apps/cli/src/services/Output.js +16 -0
  60. package/dist/apps/cli/src/services/Payload.js +90 -0
  61. package/dist/apps/cli/src/services/Process.js +94 -0
  62. package/dist/apps/cli/src/services/Queue.js +120 -0
  63. package/dist/apps/cli/src/services/RefResolver.js +111 -0
  64. package/dist/apps/cli/src/services/RemDb.js +35 -0
  65. package/dist/apps/cli/src/services/WsClient.js +170 -0
  66. package/dist/apps/cli/tests/apply.contract.test.js +31 -0
  67. package/dist/apps/cli/tests/db-recent.contract.test.js +22 -0
  68. package/dist/apps/cli/tests/help.contract.test.js +30 -0
  69. package/dist/apps/cli/tests/helpers/runCli.js +45 -0
  70. package/dist/apps/cli/tests/ids-output.contract.test.js +30 -0
  71. package/dist/apps/cli/tests/payload-stdin.contract.test.js +15 -0
  72. package/dist/apps/cli/tests/read-search.contract.test.js +22 -0
  73. package/dist/apps/cli/tests/ws-health.contract.test.js +36 -0
  74. package/dist/apps/cli/vitest.config.js +7 -0
  75. package/dist/main.js +100985 -0
  76. package/dist/packages/mcp/src/public.js +18 -0
  77. package/dist/packages/mcp/src/queue/dao.js +165 -0
  78. package/dist/packages/mcp/src/queue/db.js +26 -0
  79. package/dist/packages/mcp/src/tools/executeSearchQuery.js +914 -0
  80. package/dist/packages/mcp/src/tools/findRemsByReference.js +447 -0
  81. package/dist/packages/mcp/src/tools/getRemConnections.js +566 -0
  82. package/dist/packages/mcp/src/tools/inspectRemDoc.js +60 -0
  83. package/dist/packages/mcp/src/tools/listRemBackups.js +35 -0
  84. package/dist/packages/mcp/src/tools/listRemReferences.js +421 -0
  85. package/dist/packages/mcp/src/tools/listSupportedOps.js +41 -0
  86. package/dist/packages/mcp/src/tools/listTodos.js +815 -0
  87. package/dist/packages/mcp/src/tools/outlineRemSubtree.js +203 -0
  88. package/dist/packages/mcp/src/tools/readRemTable.js +252 -0
  89. package/dist/packages/mcp/src/tools/resolveRemReference.js +174 -0
  90. package/dist/packages/mcp/src/tools/searchQueryTypes.js +127 -0
  91. package/dist/packages/mcp/src/tools/searchRemOverview.js +422 -0
  92. package/dist/packages/mcp/src/tools/searchUtils.js +32 -0
  93. package/dist/packages/mcp/src/tools/shared.js +393 -0
  94. package/dist/packages/mcp/src/tools/summarizeDailyNotes.js +221 -0
  95. package/dist/packages/mcp/src/tools/summarizeTopicActivity.js +605 -0
  96. package/dist/packages/mcp/src/tools/timeFilters.js +130 -0
  97. package/dist/packages/mcp/src/ws/bridge.js +377 -0
  98. package/package.json +40 -8
  99. package/README.md +0 -3
  100. package/dist/index.d.ts +0 -2
  101. package/dist/index.d.ts.map +0 -1
  102. package/dist/index.js +0 -5
@@ -0,0 +1,18 @@
1
+ export { startWebSocketBridge } from './ws/bridge.js';
2
+ export { openQueueDb } from './queue/db.js';
3
+ export { enqueueTxn, getTxnIdByOpId, queueStats } from './queue/dao.js';
4
+ export { discoverBackups, formatDateWithPattern, getDateFormatting, withResolvedDatabase } from './tools/shared.js';
5
+ export { TYPES } from './tools/listSupportedOps.js';
6
+ export { executeListRemBackups } from './tools/listRemBackups.js';
7
+ export { executeSummarizeTopicActivity } from './tools/summarizeTopicActivity.js';
8
+ export { executeListRemReferences } from './tools/listRemReferences.js';
9
+ export { executeSummarizeDailyNotes } from './tools/summarizeDailyNotes.js';
10
+ export { executeSearchRemOverview } from './tools/searchRemOverview.js';
11
+ export { executeInspectRemDoc } from './tools/inspectRemDoc.js';
12
+ export { executeOutlineRemSubtree } from './tools/outlineRemSubtree.js';
13
+ export { executeReadRemTable } from './tools/readRemTable.js';
14
+ export { executeFindRemsByReference } from './tools/findRemsByReference.js';
15
+ export { executeGetRemConnections } from './tools/getRemConnections.js';
16
+ export { executeListTodos } from './tools/listTodos.js';
17
+ export { executeResolveRemReference } from './tools/resolveRemReference.js';
18
+ export { executeSearchQuery } from './tools/executeSearchQuery.js';
@@ -0,0 +1,165 @@
1
+ import { randomUUID, createHash } from "node:crypto";
2
+ export function nowMs() {
3
+ return Date.now();
4
+ }
5
+ export function stableHash(obj) {
6
+ const json = JSON.stringify(obj, Object.keys(obj).sort());
7
+ return createHash("sha256").update(json).digest("hex").slice(0, 32);
8
+ }
9
+ export function createTxn(db, params) {
10
+ const txn_id = randomUUID();
11
+ const t = nowMs();
12
+ const meta_json = JSON.stringify(params?.meta ?? {});
13
+ const stmt = db.prepare(`INSERT INTO txns (txn_id, status, priority, idempotency_key, client_id, meta_json, op_count, next_seq, created_at, updated_at)
14
+ VALUES (@txn_id, 'pending', @priority, @idempotency_key, @client_id, @meta_json, 0, 0, @t, @t)`);
15
+ stmt.run({ txn_id, priority: params?.priority ?? 0, idempotency_key: params?.idempotencyKey ?? null, client_id: params?.clientId ?? null, meta_json, t });
16
+ return txn_id;
17
+ }
18
+ export function addOps(db, txn_id, ops) {
19
+ const getSeq = db.prepare(`SELECT next_seq FROM txns WHERE txn_id = ?`);
20
+ const updSeq = db.prepare(`UPDATE txns SET next_seq = next_seq + 1, op_count = op_count + 1, updated_at = ? WHERE txn_id = ?`);
21
+ const ins = db.prepare(`INSERT INTO ops (op_id, txn_id, op_seq, type, payload_json, status, idempotency_key, op_hash, attempt_count, max_attempts, deliver_after, next_attempt_at, created_at, updated_at)
22
+ VALUES (@op_id, @txn_id, @op_seq, @type, @payload_json, 'pending', @idempotency_key, @op_hash, 0, @max_attempts, @deliver_after, @next_attempt_at, @t, @t)`);
23
+ const t = nowMs();
24
+ const trx = db.transaction(() => {
25
+ let seq = getSeq.get(txn_id)?.next_seq;
26
+ if (typeof seq !== "number")
27
+ throw new Error(`txn not found: ${txn_id}`);
28
+ for (const op of ops) {
29
+ seq += 1;
30
+ const payload_json = JSON.stringify(op.payload ?? {});
31
+ const op_hash = stableHash({ type: op.type, payload: op.payload });
32
+ const op_id = randomUUID();
33
+ const deliver_after = nowMs() + (op.deliverAfterMs ?? 0);
34
+ const next_attempt_at = deliver_after;
35
+ ins.run({
36
+ op_id,
37
+ txn_id,
38
+ op_seq: seq,
39
+ type: op.type,
40
+ payload_json,
41
+ idempotency_key: op.idempotencyKey ?? null,
42
+ op_hash,
43
+ max_attempts: op.maxAttempts ?? 10,
44
+ deliver_after,
45
+ next_attempt_at,
46
+ t,
47
+ });
48
+ updSeq.run(t, txn_id);
49
+ }
50
+ });
51
+ trx();
52
+ }
53
+ export function commitTxn(db, txn_id) {
54
+ const t = nowMs();
55
+ const upd = db.prepare(`UPDATE txns SET status = 'ready', committed_at = @t, updated_at = @t WHERE txn_id = @txn_id`);
56
+ upd.run({ t, txn_id });
57
+ }
58
+ export function enqueueTxn(db, ops, options) {
59
+ const txn_id = createTxn(db, options);
60
+ addOps(db, txn_id, ops);
61
+ commitTxn(db, txn_id);
62
+ return txn_id;
63
+ }
64
+ export function claimNextOp(db, consumer_id, leaseMs = 30_000) {
65
+ const t = nowMs();
66
+ // select a pending op whose txn is ready and earlier ops in the txn are all succeeded
67
+ const row = db
68
+ .prepare(`SELECT o.* FROM ops o
69
+ JOIN txns x ON x.txn_id = o.txn_id
70
+ WHERE o.status = 'pending' AND o.next_attempt_at <= @t AND x.status IN ('ready','in_progress')
71
+ AND NOT EXISTS (
72
+ SELECT 1 FROM ops o2 WHERE o2.txn_id = o.txn_id AND o2.op_seq < o.op_seq AND o2.status != 'succeeded'
73
+ )
74
+ ORDER BY x.priority ASC, o.created_at ASC
75
+ LIMIT 1`)
76
+ .get({ t });
77
+ if (!row)
78
+ return null;
79
+ const lease_expires_at = t + leaseMs;
80
+ const upd = db.prepare(`UPDATE ops SET status='in_flight', locked_by=@consumer_id, locked_at=@t, lease_expires_at=@lease_expires_at, updated_at=@t WHERE op_id=@op_id AND status='pending'`);
81
+ const res = upd.run({ consumer_id, t, lease_expires_at, op_id: row.op_id });
82
+ if (res.changes === 0)
83
+ return null;
84
+ // mark txn in progress
85
+ db.prepare(`UPDATE txns SET status='in_progress', updated_at=@t WHERE txn_id=@txn_id AND status!='in_progress'`).run({ t, txn_id: row.txn_id });
86
+ return { ...row, status: "in_flight", locked_by: consumer_id, locked_at: t, lease_expires_at };
87
+ }
88
+ export function ackSuccess(db, op_id, result) {
89
+ const t = nowMs();
90
+ const trx = db.transaction(() => {
91
+ db.prepare(`UPDATE ops SET status='succeeded', updated_at=@t WHERE op_id=@op_id`).run({ t, op_id });
92
+ db.prepare(`INSERT OR REPLACE INTO op_results(op_id, result_json, finished_at) VALUES(@op_id, @result_json, @t)`).run({ op_id, result_json: JSON.stringify(result ?? {}), t });
93
+ const row = db.prepare(`SELECT txn_id FROM ops WHERE op_id=?`).get(op_id);
94
+ if (row) {
95
+ const txn_id = row.txn_id;
96
+ const remain = db.prepare(`SELECT 1 FROM ops WHERE txn_id=? AND status!='succeeded' LIMIT 1`).get(txn_id);
97
+ if (!remain) {
98
+ db.prepare(`UPDATE txns SET status='succeeded', finished_at=@t, updated_at=@t WHERE txn_id=@txn_id`).run({ t, txn_id });
99
+ }
100
+ }
101
+ });
102
+ trx();
103
+ }
104
+ export function ackRetry(db, op_id, err) {
105
+ const t = nowMs();
106
+ const row = db.prepare(`SELECT attempt_count, max_attempts FROM ops WHERE op_id=?`).get(op_id);
107
+ if (!row)
108
+ return;
109
+ const attempt = row.attempt_count + 1;
110
+ const base = Math.min(60_000, Math.pow(2, attempt) * 1000);
111
+ const jitter = Math.round(base * (0.1 + Math.random() * 0.2));
112
+ const delay = err.retryAfterMs ?? base + jitter;
113
+ const next = t + delay;
114
+ const upd = db.prepare(`UPDATE ops SET status='pending', attempt_count=@attempt, next_attempt_at=@next, updated_at=@t WHERE op_id=@op_id`);
115
+ upd.run({ attempt, next, t, op_id });
116
+ db.prepare(`INSERT OR REPLACE INTO op_results(op_id, error_code, error_message, finished_at) VALUES(@op_id, @code, @message, @t)`).run({ op_id, code: err.code ?? null, message: err.message ?? null, t });
117
+ }
118
+ export function ackDead(db, op_id, err) {
119
+ const t = nowMs();
120
+ const trx = db.transaction(() => {
121
+ db.prepare(`UPDATE ops SET status='dead', dead_reason=@reason, updated_at=@t WHERE op_id=@op_id`).run({ reason: err.message ?? err.code ?? "dead", t, op_id });
122
+ db.prepare(`INSERT OR REPLACE INTO op_results(op_id, error_code, error_message, finished_at) VALUES(@op_id, @code, @message, @t)`).run({ op_id, code: err.code ?? null, message: err.message ?? null, t });
123
+ const row = db.prepare(`SELECT txn_id FROM ops WHERE op_id=?`).get(op_id);
124
+ if (row) {
125
+ db.prepare(`UPDATE txns SET status='failed', finished_at=@t, updated_at=@t WHERE txn_id=@txn_id`).run({ t, txn_id: row.txn_id });
126
+ }
127
+ });
128
+ trx();
129
+ }
130
+ export function upsertIdMap(db, entries) {
131
+ const t = nowMs();
132
+ const stmt = db.prepare(`INSERT INTO id_map(client_temp_id, remote_id, remote_type, source_txn, updated_at)
133
+ VALUES(@client_temp_id, @remote_id, @remote_type, @source_txn, @t)
134
+ ON CONFLICT(client_temp_id) DO UPDATE SET remote_id=excluded.remote_id, remote_type=excluded.remote_type, source_txn=excluded.source_txn, updated_at=excluded.updated_at`);
135
+ const trx = db.transaction(() => {
136
+ for (const e of entries)
137
+ stmt.run({ ...e, t });
138
+ });
139
+ trx();
140
+ }
141
+ export function queueStats(db) {
142
+ const q = (sql) => db.prepare(sql).get();
143
+ const pending = q(`SELECT COUNT(1) as c FROM ops WHERE status='pending' AND next_attempt_at<=${nowMs()}`)?.c ?? 0;
144
+ const in_flight = q(`SELECT COUNT(1) as c FROM ops WHERE status='in_flight'`)?.c ?? 0;
145
+ const dead = q(`SELECT COUNT(1) as c FROM ops WHERE status='dead'`)?.c ?? 0;
146
+ const ready_txns = q(`SELECT COUNT(1) as c FROM txns WHERE status IN ('ready','in_progress')`)?.c ?? 0;
147
+ return { pending, in_flight, dead, ready_txns };
148
+ }
149
+ export function getTxnIdByOpId(db, op_id) {
150
+ const row = db.prepare(`SELECT txn_id FROM ops WHERE op_id=?`).get(op_id);
151
+ return row?.txn_id;
152
+ }
153
+ export function recoverExpiredLeases(db) {
154
+ const t = nowMs();
155
+ const rows = db.prepare(`SELECT op_id FROM ops WHERE status='in_flight' AND lease_expires_at IS NOT NULL AND lease_expires_at <= ?`).all(t);
156
+ if (!rows || rows.length === 0)
157
+ return 0;
158
+ const upd = db.prepare(`UPDATE ops SET status='pending', locked_by=NULL, locked_at=NULL, lease_expires_at=NULL, next_attempt_at=@t, updated_at=@t WHERE op_id=@op_id`);
159
+ const trx = db.transaction(() => {
160
+ for (const r of rows)
161
+ upd.run({ t, op_id: r.op_id });
162
+ });
163
+ trx();
164
+ return rows.length;
165
+ }
@@ -0,0 +1,26 @@
1
+ import Database from "better-sqlite3";
2
+ import { mkdirSync, readFileSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ export function defaultQueuePath() {
5
+ const env = process.env.REMNOTE_QUEUE_DB || process.env.QUEUE_DB;
6
+ if (env)
7
+ return env;
8
+ const home = process.env.HOME || process.env.USERPROFILE || ".";
9
+ return `${home}/.remnote-mcp/queue.sqlite`;
10
+ }
11
+ export function ensureDir(path) {
12
+ const dir = dirname(path);
13
+ mkdirSync(dir, { recursive: true });
14
+ }
15
+ export function openQueueDb(dbPath = defaultQueuePath()) {
16
+ ensureDir(dbPath);
17
+ const db = new Database(dbPath);
18
+ db.pragma("foreign_keys = ON");
19
+ migrate(db);
20
+ return db;
21
+ }
22
+ function migrate(db) {
23
+ // Simple single-shot schema loader; versioning could use PRAGMA user_version later
24
+ const sql = readFileSync(new URL("./schema.sql", import.meta.url), "utf8");
25
+ db.exec(sql);
26
+ }