botnote 0.1.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.
Files changed (79) hide show
  1. package/README.md +277 -0
  2. package/dist/bin.d.ts +2 -0
  3. package/dist/bin.js +320 -0
  4. package/dist/bin.js.map +1 -0
  5. package/dist/cli.d.ts +1 -0
  6. package/dist/cli.js +61 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/db/client.d.ts +10 -0
  9. package/dist/db/client.js +16 -0
  10. package/dist/db/client.js.map +1 -0
  11. package/dist/db/migrate.d.ts +1 -0
  12. package/dist/db/migrate.js +57 -0
  13. package/dist/db/migrate.js.map +1 -0
  14. package/dist/db/migrations/0001_init.sql +89 -0
  15. package/dist/db/migrations/0002_tasks_due_at.sql +16 -0
  16. package/dist/db/migrations/0003_task_priority_and_sequence.sql +45 -0
  17. package/dist/db/migrations/0004_pinned.sql +8 -0
  18. package/dist/db/migrations/0005_nullable_title_and_parent.sql +5 -0
  19. package/dist/db/migrations/0006_project_color_icon.sql +3 -0
  20. package/dist/db/migrations/0007_tokens.sql +14 -0
  21. package/dist/db/migrations/0008_simplify_kinds_drop_actors.sql +21 -0
  22. package/dist/db/migrations/0009_sessions.sql +14 -0
  23. package/dist/db/migrations/0010_completed_at.sql +17 -0
  24. package/dist/db/migrations/0011_completed_at_backfill_fix.sql +14 -0
  25. package/dist/db/migrations/0012_completed_at_backfill_due.sql +16 -0
  26. package/dist/db/migrations/0013_due_at_noon_utc.sql +13 -0
  27. package/dist/db/schema.d.ts +811 -0
  28. package/dist/db/schema.js +112 -0
  29. package/dist/db/schema.js.map +1 -0
  30. package/dist/mcp/http-client.d.ts +154 -0
  31. package/dist/mcp/http-client.js +113 -0
  32. package/dist/mcp/http-client.js.map +1 -0
  33. package/dist/mcp/server.d.ts +7 -0
  34. package/dist/mcp/server.js +492 -0
  35. package/dist/mcp/server.js.map +1 -0
  36. package/dist/rest/routes.d.ts +3 -0
  37. package/dist/rest/routes.js +320 -0
  38. package/dist/rest/routes.js.map +1 -0
  39. package/dist/rest/server.d.ts +12 -0
  40. package/dist/rest/server.js +282 -0
  41. package/dist/rest/server.js.map +1 -0
  42. package/dist/service/embedding.d.ts +25 -0
  43. package/dist/service/embedding.js +112 -0
  44. package/dist/service/embedding.js.map +1 -0
  45. package/dist/service/entities.d.ts +22 -0
  46. package/dist/service/entities.js +174 -0
  47. package/dist/service/entities.js.map +1 -0
  48. package/dist/service/index.d.ts +8 -0
  49. package/dist/service/index.js +8 -0
  50. package/dist/service/index.js.map +1 -0
  51. package/dist/service/opening_brief.d.ts +14 -0
  52. package/dist/service/opening_brief.js +104 -0
  53. package/dist/service/opening_brief.js.map +1 -0
  54. package/dist/service/projects.d.ts +8 -0
  55. package/dist/service/projects.js +36 -0
  56. package/dist/service/projects.js.map +1 -0
  57. package/dist/service/search.d.ts +15 -0
  58. package/dist/service/search.js +101 -0
  59. package/dist/service/search.js.map +1 -0
  60. package/dist/service/sessions.d.ts +25 -0
  61. package/dist/service/sessions.js +89 -0
  62. package/dist/service/sessions.js.map +1 -0
  63. package/dist/service/tasks.d.ts +23 -0
  64. package/dist/service/tasks.js +130 -0
  65. package/dist/service/tasks.js.map +1 -0
  66. package/dist/service/tokens.d.ts +18 -0
  67. package/dist/service/tokens.js +41 -0
  68. package/dist/service/tokens.js.map +1 -0
  69. package/dist/service/types.d.ts +294 -0
  70. package/dist/service/types.js +132 -0
  71. package/dist/service/types.js.map +1 -0
  72. package/dist/version.d.ts +1 -0
  73. package/dist/version.js +13 -0
  74. package/dist/version.js.map +1 -0
  75. package/package.json +73 -0
  76. package/web/dist/assets/index-Bddg7h_x.css +1 -0
  77. package/web/dist/assets/index-DYW6stVx.js +542 -0
  78. package/web/dist/favicon.svg +13 -0
  79. package/web/dist/index.html +17 -0
@@ -0,0 +1,112 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { boolean, customType, index, integer, jsonb, pgTable, primaryKey, text, timestamp, uniqueIndex, uuid } from "drizzle-orm/pg-core";
3
+ export const VECTOR_DIMENSIONS = 384;
4
+ const vector = customType({
5
+ dataType() {
6
+ return `vector(${VECTOR_DIMENSIONS})`;
7
+ },
8
+ toDriver(value) {
9
+ return `[${value.join(",")}]`;
10
+ },
11
+ fromDriver(value) {
12
+ const trimmed = value.replace(/^\[/, "").replace(/\]$/, "");
13
+ if (!trimmed)
14
+ return [];
15
+ return trimmed.split(",").map((s) => Number(s));
16
+ }
17
+ });
18
+ const tsvector = customType({
19
+ dataType() {
20
+ return "tsvector";
21
+ }
22
+ });
23
+ export const ENTITY_KINDS = ["task", "note"];
24
+ export const ACTOR_KINDS = ["human", "agent", "system"];
25
+ export const EDGE_KINDS = ["blocks", "references", "parent_of"];
26
+ export const projects = pgTable("projects", {
27
+ id: uuid("id").primaryKey().defaultRandom(),
28
+ key: text("key").notNull(),
29
+ name: text("name").notNull(),
30
+ color: text("color").notNull().default("#5e6ad2"),
31
+ icon: text("icon").notNull().default("circle"),
32
+ agentsMd: text("agents_md").notNull().default(""),
33
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
34
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
35
+ }, (t) => ({
36
+ keyIdx: uniqueIndex("projects_key_idx").on(t.key)
37
+ }));
38
+ export const entities = pgTable("entities", {
39
+ id: uuid("id").primaryKey().defaultRandom(),
40
+ projectId: uuid("project_id").references(() => projects.id, { onDelete: "set null" }),
41
+ kind: text("kind").notNull(),
42
+ title: text("title"),
43
+ body: text("body").notNull().default(""),
44
+ tags: text("tags")
45
+ .array()
46
+ .notNull()
47
+ .default(sql `'{}'::text[]`),
48
+ status: text("status").notNull().default("open"),
49
+ actorKind: text("actor_kind").notNull().default("human"),
50
+ idempotencyKey: text("idempotency_key"),
51
+ parentId: uuid("parent_id"),
52
+ bodyTsv: tsvector("body_tsv"),
53
+ bodyVec: vector("body_vec"),
54
+ metadata: jsonb("metadata").notNull().default({}),
55
+ dueAt: timestamp("due_at", { withTimezone: true }),
56
+ priority: text("priority").notNull().default("none"),
57
+ sequenceId: integer("sequence_id"),
58
+ pinned: boolean("pinned").notNull().default(false),
59
+ // Set automatically on a status transition into 'done', cleared on exit.
60
+ // Drives the calendar's display-date logic: done tasks render on
61
+ // completedAt rather than dueAt so the timeline reflects what actually
62
+ // happened.
63
+ completedAt: timestamp("completed_at", { withTimezone: true }),
64
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
65
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
66
+ }, (t) => ({
67
+ projectCreatedIdx: index("entities_project_created_idx").on(t.projectId, t.createdAt),
68
+ projectKindCreatedIdx: index("entities_project_kind_created_idx").on(t.projectId, t.kind, t.createdAt),
69
+ parentIdx: index("entities_parent_idx").on(t.parentId),
70
+ completedAtIdx: index("entities_completed_at_idx").on(t.completedAt),
71
+ idempotencyIdx: uniqueIndex("entities_idempotency_idx").on(t.idempotencyKey)
72
+ }));
73
+ export const edges = pgTable("edges", {
74
+ fromId: uuid("from_id")
75
+ .notNull()
76
+ .references(() => entities.id, { onDelete: "cascade" }),
77
+ toId: uuid("to_id")
78
+ .notNull()
79
+ .references(() => entities.id, { onDelete: "cascade" }),
80
+ kind: text("kind").notNull(),
81
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
82
+ }, (t) => ({
83
+ pk: primaryKey({ columns: [t.fromId, t.toId, t.kind] }),
84
+ toIdx: index("edges_to_idx").on(t.toId, t.kind),
85
+ fromIdx: index("edges_from_idx").on(t.fromId, t.kind)
86
+ }));
87
+ export const tokens = pgTable("tokens", {
88
+ id: uuid("id").primaryKey().defaultRandom(),
89
+ name: text("name").notNull(),
90
+ tokenHash: text("token_hash").notNull(),
91
+ prefix: text("prefix").notNull(),
92
+ lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
93
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
94
+ }, (t) => ({
95
+ tokenHashIdx: uniqueIndex("tokens_token_hash_idx").on(t.tokenHash),
96
+ createdIdx: index("tokens_created_idx").on(t.createdAt)
97
+ }));
98
+ // Browser-facing session cookies. The plaintext is stored in an httpOnly
99
+ // cookie; the row stores sha256(plaintext). On login the user posts the master
100
+ // password (env BOTNOTE_PASSWORD) and we mint a row + set the cookie.
101
+ export const sessions = pgTable("sessions", {
102
+ id: uuid("id").primaryKey().defaultRandom(),
103
+ tokenHash: text("token_hash").notNull(),
104
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
105
+ userAgent: text("user_agent"),
106
+ lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
107
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
108
+ }, (t) => ({
109
+ tokenHashIdx: uniqueIndex("sessions_token_hash_idx").on(t.tokenHash),
110
+ expiresIdx: index("sessions_expires_at_idx").on(t.expiresAt)
111
+ }));
112
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EACL,OAAO,EACP,UAAU,EACV,KAAK,EACL,OAAO,EACP,KAAK,EACL,OAAO,EACP,UAAU,EACV,IAAI,EACJ,SAAS,EACT,WAAW,EACX,IAAI,EACL,MAAM,qBAAqB,CAAC;AAE7B,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC,MAAM,MAAM,GAAG,UAAU,CAAyC;IAChE,QAAQ;QACN,OAAO,UAAU,iBAAiB,GAAG,CAAC;IACxC,CAAC;IACD,QAAQ,CAAC,KAAe;QACtB,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,CAAC;IACD,UAAU,CAAC,KAAa;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,UAAU,CAAmB;IAC5C,QAAQ;QACN,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAU,CAAC;AAGtD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAC;AAGjE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,CAAU,CAAC;AAGzE,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAC7B,UAAU,EACV;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE;IAC3C,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE;IAC1B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IACjD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC9C,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACjD,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;IACjF,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;CAClF,EACD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACN,MAAM,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;CAClD,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAC7B,UAAU,EACV;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE;IAC3C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IACrF,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;IACpB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACxC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;SACf,KAAK,EAAE;SACP,OAAO,EAAE;SACT,OAAO,CAAC,GAAG,CAAA,cAAc,CAAC;IAC7B,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IACxD,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC;IACvC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACjD,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAClD,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IACpD,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAClD,yEAAyE;IACzE,iEAAiE;IACjE,uEAAuE;IACvE,YAAY;IACZ,WAAW,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAC9D,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;IACjF,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;CAClF,EACD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACN,iBAAiB,EAAE,KAAK,CAAC,8BAA8B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC;IACrF,qBAAqB,EAAE,KAAK,CAAC,mCAAmC,CAAC,CAAC,EAAE,CAClE,CAAC,CAAC,SAAS,EACX,CAAC,CAAC,IAAI,EACN,CAAC,CAAC,SAAS,CACZ;IACD,SAAS,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtD,cAAc,EAAE,KAAK,CAAC,2BAA2B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IACpE,cAAc,EAAE,WAAW,CAAC,0BAA0B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC;CAC7E,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAC1B,OAAO,EACP;IACE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;SACpB,OAAO,EAAE;SACT,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACzD,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC;SAChB,OAAO,EAAE;SACT,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACzD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;CAClF,EACD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACN,EAAE,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;IACvD,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IAC/C,OAAO,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC;CACtD,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,CAC3B,QAAQ,EACR;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE;IAC3C,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE;IAChC,UAAU,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAC7D,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;CAClF,EACD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACN,YAAY,EAAE,WAAW,CAAC,uBAAuB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAClE,UAAU,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;CACxD,CAAC,CACH,CAAC;AAEF,yEAAyE;AACzE,+EAA+E;AAC/E,sEAAsE;AACtE,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAC7B,UAAU,EACV;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE;IAC3C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACpE,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC;IAC7B,UAAU,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAC7D,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;CAClF,EACD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACN,YAAY,EAAE,WAAW,CAAC,yBAAyB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACpE,UAAU,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;CAC7D,CAAC,CACH,CAAC"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * HTTP client used by the stdio MCP server to talk to the botnote daemon.
3
+ *
4
+ * The MCP server used to import drizzle and hit the DB directly. That coupled
5
+ * the MCP process to the daemon's machine and required DATABASE_URL. The
6
+ * plugin model needs the MCP to be runnable on any machine — laptop, tailnet,
7
+ * public — pointing at whichever botnote daemon the user is reachable to.
8
+ *
9
+ * Auth model mirrors the daemon's:
10
+ * - direct tailnet/localhost: no token required (daemon trusts the network)
11
+ * - through Cloudflare Tunnel: bearer + optional CF Access service token
12
+ */
13
+ export interface HttpClientOptions {
14
+ baseUrl: string;
15
+ token?: string;
16
+ cfAccessClientId?: string;
17
+ cfAccessClientSecret?: string;
18
+ version?: string;
19
+ }
20
+ export declare class BotnoteHttpError extends Error {
21
+ status: number;
22
+ statusText: string;
23
+ body: string;
24
+ constructor(status: number, statusText: string, body: string);
25
+ }
26
+ export declare class BotnoteHttpClient {
27
+ private opts;
28
+ constructor(opts: HttpClientOptions);
29
+ private request;
30
+ listProjects(): Promise<ProjectDTO[]>;
31
+ getProject(id: string): Promise<ProjectDTO>;
32
+ getProjectByKey(key: string): Promise<ProjectDTO>;
33
+ createProject(body: CreateProjectBody): Promise<ProjectDTO>;
34
+ updateProject(id: string, body: UpdateProjectBody): Promise<ProjectDTO>;
35
+ openingBrief(body: {
36
+ projectId?: string | null;
37
+ recentLimit?: number;
38
+ }): Promise<OpeningBriefDTO>;
39
+ getEntity(id: string): Promise<EntityDTO>;
40
+ getEntityByKey(projectKey: string, seq: number): Promise<EntityDTO>;
41
+ listRelated(id: string): Promise<EntityDTO[]>;
42
+ recent(body: RecentBody): Promise<EntityDTO[]>;
43
+ search(body: SearchBody): Promise<{
44
+ hits: SearchHitDTO[];
45
+ embeddingUsed: boolean;
46
+ }>;
47
+ createTask(body: CreateTaskBody): Promise<EntityDTO>;
48
+ remember(body: CreateNoteBody): Promise<EntityDTO>;
49
+ updateEntity(id: string, body: UpdateEntityBody): Promise<EntityDTO>;
50
+ link(fromId: string, body: {
51
+ toId: string;
52
+ kind: LinkKind;
53
+ }): Promise<{
54
+ created: boolean;
55
+ }>;
56
+ }
57
+ export interface ProjectDTO {
58
+ id: string;
59
+ key: string;
60
+ name: string;
61
+ color: string;
62
+ icon: string;
63
+ agentsMd: string;
64
+ createdAt: string;
65
+ updatedAt: string;
66
+ }
67
+ export interface EntityDTO {
68
+ id: string;
69
+ projectId: string | null;
70
+ kind: "task" | "note";
71
+ title: string | null;
72
+ body: string;
73
+ tags: string[];
74
+ status: string;
75
+ parentId: string | null;
76
+ actorKind: string;
77
+ metadata: Record<string, unknown>;
78
+ dueAt: string | null;
79
+ priority: string;
80
+ pinned: boolean;
81
+ sequenceId: number | null;
82
+ createdAt: string;
83
+ updatedAt: string;
84
+ }
85
+ export interface SearchHitDTO {
86
+ entity: EntityDTO;
87
+ score: number;
88
+ }
89
+ export interface OpeningBriefDTO {
90
+ project: ProjectDTO | null;
91
+ pinnedNotes: EntityDTO[];
92
+ openTasks: EntityDTO[];
93
+ recentActivity: EntityDTO[];
94
+ agentsMd: string;
95
+ markdown: string;
96
+ }
97
+ export type LinkKind = "blocks" | "references" | "parent_of";
98
+ export interface CreateProjectBody {
99
+ key: string;
100
+ name: string;
101
+ color?: string;
102
+ icon?: string;
103
+ agentsMd?: string;
104
+ }
105
+ export interface UpdateProjectBody {
106
+ name?: string;
107
+ color?: string;
108
+ icon?: string;
109
+ agentsMd?: string;
110
+ }
111
+ export interface CreateTaskBody {
112
+ projectId?: string | null;
113
+ title: string;
114
+ body?: string;
115
+ tags?: string[];
116
+ status?: string;
117
+ parentId?: string | null;
118
+ actorKind?: string;
119
+ dueAt?: string | null;
120
+ priority?: string;
121
+ idempotencyKey?: string;
122
+ }
123
+ export interface CreateNoteBody {
124
+ projectId?: string | null;
125
+ title?: string | null;
126
+ body?: string;
127
+ tags?: string[];
128
+ parentId?: string | null;
129
+ actorKind?: string;
130
+ pinned?: boolean;
131
+ idempotencyKey?: string;
132
+ }
133
+ export interface UpdateEntityBody {
134
+ title?: string | null;
135
+ body?: string;
136
+ tags?: string[];
137
+ status?: string;
138
+ parentId?: string | null;
139
+ dueAt?: string | null;
140
+ priority?: string;
141
+ pinned?: boolean;
142
+ }
143
+ export interface RecentBody {
144
+ projectId?: string | null;
145
+ since?: string | null;
146
+ kinds?: string[];
147
+ limit?: number;
148
+ }
149
+ export interface SearchBody {
150
+ query: string;
151
+ projectId?: string | null;
152
+ kind?: string;
153
+ limit?: number;
154
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * HTTP client used by the stdio MCP server to talk to the botnote daemon.
3
+ *
4
+ * The MCP server used to import drizzle and hit the DB directly. That coupled
5
+ * the MCP process to the daemon's machine and required DATABASE_URL. The
6
+ * plugin model needs the MCP to be runnable on any machine — laptop, tailnet,
7
+ * public — pointing at whichever botnote daemon the user is reachable to.
8
+ *
9
+ * Auth model mirrors the daemon's:
10
+ * - direct tailnet/localhost: no token required (daemon trusts the network)
11
+ * - through Cloudflare Tunnel: bearer + optional CF Access service token
12
+ */
13
+ const VERSION_HEADER = "x-botnote-mcp-version";
14
+ export class BotnoteHttpError extends Error {
15
+ status;
16
+ statusText;
17
+ body;
18
+ constructor(status, statusText, body) {
19
+ super(`HTTP ${status} ${statusText}: ${body}`);
20
+ this.status = status;
21
+ this.statusText = statusText;
22
+ this.body = body;
23
+ }
24
+ }
25
+ export class BotnoteHttpClient {
26
+ opts;
27
+ constructor(opts) {
28
+ this.opts = opts;
29
+ }
30
+ async request(method, path, body) {
31
+ const url = new URL(path, this.opts.baseUrl);
32
+ const headers = {
33
+ accept: "application/json"
34
+ };
35
+ if (body !== undefined)
36
+ headers["content-type"] = "application/json";
37
+ if (this.opts.token)
38
+ headers.authorization = `Bearer ${this.opts.token}`;
39
+ if (this.opts.cfAccessClientId) {
40
+ headers["cf-access-client-id"] = this.opts.cfAccessClientId;
41
+ }
42
+ if (this.opts.cfAccessClientSecret) {
43
+ headers["cf-access-client-secret"] = this.opts.cfAccessClientSecret;
44
+ }
45
+ if (this.opts.version)
46
+ headers[VERSION_HEADER] = this.opts.version;
47
+ const res = await fetch(url.toString(), {
48
+ method,
49
+ headers,
50
+ body: body === undefined ? undefined : JSON.stringify(body)
51
+ });
52
+ if (!res.ok) {
53
+ const text = await res.text().catch(() => "");
54
+ throw new BotnoteHttpError(res.status, res.statusText, text);
55
+ }
56
+ if (res.status === 204)
57
+ return undefined;
58
+ const ct = res.headers.get("content-type") ?? "";
59
+ if (!ct.includes("application/json"))
60
+ return (await res.text());
61
+ return (await res.json());
62
+ }
63
+ // ----- projects -----
64
+ listProjects() {
65
+ return this.request("GET", "/v1/projects");
66
+ }
67
+ getProject(id) {
68
+ return this.request("GET", `/v1/projects/${id}`);
69
+ }
70
+ getProjectByKey(key) {
71
+ return this.request("GET", `/v1/projects/by-key/${key}`);
72
+ }
73
+ createProject(body) {
74
+ return this.request("POST", "/v1/projects", body);
75
+ }
76
+ updateProject(id, body) {
77
+ return this.request("PATCH", `/v1/projects/${id}`, body);
78
+ }
79
+ // ----- opening brief -----
80
+ openingBrief(body) {
81
+ return this.request("POST", "/v1/opening-brief", body);
82
+ }
83
+ // ----- entities (read) -----
84
+ getEntity(id) {
85
+ return this.request("GET", `/v1/entities/${id}`);
86
+ }
87
+ getEntityByKey(projectKey, seq) {
88
+ return this.request("GET", `/v1/projects/by-key/${projectKey}/entities/by-seq/${seq}`);
89
+ }
90
+ listRelated(id) {
91
+ return this.request("GET", `/v1/entities/${id}/related`);
92
+ }
93
+ recent(body) {
94
+ return this.request("POST", "/v1/recent", body);
95
+ }
96
+ search(body) {
97
+ return this.request("POST", "/v1/search", body);
98
+ }
99
+ // ----- entities (write) -----
100
+ createTask(body) {
101
+ return this.request("POST", "/v1/tasks", body);
102
+ }
103
+ remember(body) {
104
+ return this.request("POST", "/v1/notes", body);
105
+ }
106
+ updateEntity(id, body) {
107
+ return this.request("PATCH", `/v1/entities/${id}`, body);
108
+ }
109
+ link(fromId, body) {
110
+ return this.request("POST", `/v1/entities/${fromId}/links`, body);
111
+ }
112
+ }
113
+ //# sourceMappingURL=http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../src/mcp/http-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BotnoteHttpClient } from "./http-client.js";
3
+ export interface McpServerContext {
4
+ client: BotnoteHttpClient;
5
+ version?: string;
6
+ }
7
+ export declare function buildMcpServer(ctx: McpServerContext): McpServer;