synomem 0.9.6 → 0.10.0

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 (118) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +5 -3
  3. package/dist/actor-directory.d.ts +34 -0
  4. package/dist/actor-directory.d.ts.map +1 -0
  5. package/dist/actor-directory.js +52 -0
  6. package/dist/actor-directory.js.map +1 -0
  7. package/dist/backend.d.ts +3 -0
  8. package/dist/backend.d.ts.map +1 -1
  9. package/dist/backend.js +26 -3
  10. package/dist/backend.js.map +1 -1
  11. package/dist/bookmarks.d.ts +30 -0
  12. package/dist/bookmarks.d.ts.map +1 -0
  13. package/dist/bookmarks.js +87 -0
  14. package/dist/bookmarks.js.map +1 -0
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +291 -61
  17. package/dist/cli.js.map +1 -1
  18. package/dist/client.d.ts +115 -4
  19. package/dist/client.d.ts.map +1 -1
  20. package/dist/client.js +854 -138
  21. package/dist/client.js.map +1 -1
  22. package/dist/cursors.d.ts +30 -0
  23. package/dist/cursors.d.ts.map +1 -0
  24. package/dist/cursors.js +101 -0
  25. package/dist/cursors.js.map +1 -0
  26. package/dist/errors.d.ts +1 -1
  27. package/dist/errors.d.ts.map +1 -1
  28. package/dist/errors.js +2 -0
  29. package/dist/errors.js.map +1 -1
  30. package/dist/import.d.ts +605 -39
  31. package/dist/import.d.ts.map +1 -1
  32. package/dist/index.d.ts +19 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +11 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/mcp/index.d.ts +1 -1
  37. package/dist/mcp/index.d.ts.map +1 -1
  38. package/dist/mcp/index.js +329 -22
  39. package/dist/mcp/index.js.map +1 -1
  40. package/dist/mutation-receipts.d.ts +8 -0
  41. package/dist/mutation-receipts.d.ts.map +1 -0
  42. package/dist/mutation-receipts.js +2 -0
  43. package/dist/mutation-receipts.js.map +1 -0
  44. package/dist/notifications.d.ts +73 -0
  45. package/dist/notifications.d.ts.map +1 -0
  46. package/dist/notifications.js +309 -0
  47. package/dist/notifications.js.map +1 -0
  48. package/dist/participation-repository.d.ts +46 -0
  49. package/dist/participation-repository.d.ts.map +1 -0
  50. package/dist/participation-repository.js +296 -0
  51. package/dist/participation-repository.js.map +1 -0
  52. package/dist/participation.d.ts +97 -0
  53. package/dist/participation.d.ts.map +1 -0
  54. package/dist/participation.js +10 -0
  55. package/dist/participation.js.map +1 -0
  56. package/dist/policy.d.ts +31 -0
  57. package/dist/policy.d.ts.map +1 -0
  58. package/dist/policy.js +71 -0
  59. package/dist/policy.js.map +1 -0
  60. package/dist/ports/repository.d.ts +23 -0
  61. package/dist/ports/repository.d.ts.map +1 -1
  62. package/dist/profiles.d.ts +12 -0
  63. package/dist/profiles.d.ts.map +1 -1
  64. package/dist/profiles.js +2 -1
  65. package/dist/profiles.js.map +1 -1
  66. package/dist/projections.d.ts.map +1 -1
  67. package/dist/projections.js +29 -11
  68. package/dist/projections.js.map +1 -1
  69. package/dist/remote.d.ts +79 -0
  70. package/dist/remote.d.ts.map +1 -1
  71. package/dist/remote.js +65 -6
  72. package/dist/remote.js.map +1 -1
  73. package/dist/schemas.d.ts +746 -58
  74. package/dist/schemas.d.ts.map +1 -1
  75. package/dist/schemas.js +114 -16
  76. package/dist/schemas.js.map +1 -1
  77. package/dist/search.d.ts +25 -0
  78. package/dist/search.d.ts.map +1 -0
  79. package/dist/search.js +2 -0
  80. package/dist/search.js.map +1 -0
  81. package/dist/service.d.ts +89 -0
  82. package/dist/service.d.ts.map +1 -1
  83. package/dist/storage.d.ts +38 -3
  84. package/dist/storage.d.ts.map +1 -1
  85. package/dist/storage.js +494 -365
  86. package/dist/storage.js.map +1 -1
  87. package/dist/types.d.ts +65 -34
  88. package/dist/types.d.ts.map +1 -1
  89. package/docs/cli.md +6 -0
  90. package/docs/human-participation.md +20 -0
  91. package/docs/mcp.md +2 -0
  92. package/docs/storage-format.md +4 -15
  93. package/openapi/synomem-v1.yaml +187 -10
  94. package/package.json +2 -1
  95. package/skills/synomem/SKILL.md +2 -0
  96. package/src/actor-directory.ts +87 -0
  97. package/src/backend.ts +29 -3
  98. package/src/bookmarks.ts +127 -0
  99. package/src/cli.ts +941 -546
  100. package/src/client.ts +1143 -279
  101. package/src/cursors.ts +132 -0
  102. package/src/errors.ts +2 -0
  103. package/src/index.ts +50 -0
  104. package/src/mcp/index.ts +412 -96
  105. package/src/mutation-receipts.ts +7 -0
  106. package/src/notifications.ts +483 -0
  107. package/src/participation-repository.ts +406 -0
  108. package/src/participation.ts +103 -0
  109. package/src/policy.ts +109 -0
  110. package/src/ports/repository.ts +33 -0
  111. package/src/profiles.ts +2 -1
  112. package/src/projections.ts +49 -48
  113. package/src/remote.ts +227 -37
  114. package/src/schemas.ts +116 -16
  115. package/src/search.ts +24 -0
  116. package/src/service.ts +122 -8
  117. package/src/storage.ts +1039 -697
  118. package/src/types.ts +67 -32
@@ -0,0 +1,127 @@
1
+ import type { ActorIdentity, ItemSummary } from './types.js';
2
+ import type { ActorRef } from './policy.js';
3
+ import type { NotificationSql } from './notifications.js';
4
+ import { cursorFilter } from './cursors.js';
5
+ export interface BookmarkInput {
6
+ after?: string;
7
+ limit?: number;
8
+ }
9
+ export interface BookmarkPage {
10
+ items: Array<{ root: Pick<ItemSummary, 'id' | 'kind' | 'title'>; savedAt: string }>;
11
+ hasMore: boolean;
12
+ nextCursor?: string;
13
+ watermark: string;
14
+ }
15
+ export interface BookmarkRepository {
16
+ set(rootId: string, actor: ActorRef, present: boolean): Promise<void>;
17
+ has(rootId: string, actor: ActorRef): Promise<boolean>;
18
+ list(input: BookmarkInput, actor: ActorIdentity): Promise<BookmarkPage>;
19
+ }
20
+ export const bookmarkTables = `
21
+ CREATE TABLE bookmark_sequences(workspace_id TEXT PRIMARY KEY,last_sequence BIGINT NOT NULL);
22
+ CREATE TABLE bookmarks(workspace_id TEXT NOT NULL,actor_kind TEXT NOT NULL,actor_id TEXT NOT NULL,root_id TEXT NOT NULL,saved_at TEXT NOT NULL,saved_sequence BIGINT NOT NULL,PRIMARY KEY(workspace_id,actor_kind,actor_id,root_id));
23
+ CREATE INDEX bookmarks_actor_sequence ON bookmarks(workspace_id,actor_kind,actor_id,saved_sequence);
24
+ `;
25
+ export class SqlBookmarkRepository implements BookmarkRepository {
26
+ constructor(private readonly sql: NotificationSql) {}
27
+ async has(rootId: string, actor: ActorRef): Promise<boolean> {
28
+ return (
29
+ (
30
+ await this.sql.query(
31
+ 'SELECT 1 FROM bookmarks WHERE workspace_id=? AND actor_kind=? AND actor_id=? AND root_id=?',
32
+ [this.sql.workspaceId, actor.kind, actor.id, rootId],
33
+ )
34
+ ).length > 0
35
+ );
36
+ }
37
+ async set(rootId: string, actor: ActorRef, present: boolean): Promise<void> {
38
+ if (!present) {
39
+ await this.sql.execute(
40
+ 'DELETE FROM bookmarks WHERE workspace_id=? AND actor_kind=? AND actor_id=? AND root_id=?',
41
+ [this.sql.workspaceId, actor.kind, actor.id, rootId],
42
+ );
43
+ return;
44
+ }
45
+ if (await this.has(rootId, actor)) return;
46
+ const counter = (
47
+ await this.sql.query(
48
+ 'INSERT INTO bookmark_sequences(workspace_id,last_sequence) VALUES(?,1) ON CONFLICT(workspace_id) DO UPDATE SET last_sequence=bookmark_sequences.last_sequence+1 RETURNING last_sequence',
49
+ [this.sql.workspaceId],
50
+ )
51
+ )[0]!;
52
+ await this.sql.execute(
53
+ 'INSERT INTO bookmarks(workspace_id,actor_kind,actor_id,root_id,saved_at,saved_sequence) VALUES(?,?,?,?,?,?) ON CONFLICT(workspace_id,actor_kind,actor_id,root_id) DO NOTHING',
54
+ [
55
+ this.sql.workspaceId,
56
+ actor.kind,
57
+ actor.id,
58
+ rootId,
59
+ new Date().toISOString(),
60
+ String(counter.last_sequence),
61
+ ],
62
+ );
63
+ }
64
+ async list(input: BookmarkInput, actor: ActorIdentity): Promise<BookmarkPage> {
65
+ const maximum = String(
66
+ (
67
+ await this.sql.query(
68
+ 'SELECT COALESCE((SELECT last_sequence FROM bookmark_sequences WHERE workspace_id=?),0) AS max',
69
+ [this.sql.workspaceId],
70
+ )
71
+ )[0]!.max,
72
+ );
73
+ const binding = {
74
+ purpose: 'bookmarks',
75
+ workspaceId: this.sql.workspaceId,
76
+ actor,
77
+ filter: cursorFilter({}),
78
+ };
79
+ const codec = this.sql.codec();
80
+ const position = input.after ? codec.decode(input.after, binding, maximum) : undefined;
81
+ const high = position?.watermark ?? maximum;
82
+ const policy = this.sql.visibility(actor);
83
+ const limit = input.limit ?? 20;
84
+ const rows = await this.sql.query(
85
+ `SELECT b.saved_sequence,b.saved_at,i.item_id,i.kind,i.title FROM bookmarks b JOIN items_current i ON i.workspace_id=b.workspace_id AND i.item_id=b.root_id WHERE b.workspace_id=? AND b.actor_kind=? AND b.actor_id=? AND b.saved_sequence>? AND b.saved_sequence<=? AND (${policy.sql}) ORDER BY b.saved_sequence LIMIT ?`,
86
+ [
87
+ this.sql.workspaceId,
88
+ actor.kind,
89
+ actor.id,
90
+ position?.sequence ?? '0',
91
+ high,
92
+ ...policy.values,
93
+ limit + 1,
94
+ ],
95
+ );
96
+ const items: BookmarkPage['items'] = [];
97
+ let bytes = 2048;
98
+ for (const row of rows.slice(0, limit)) {
99
+ const entry = {
100
+ root: {
101
+ id: String(row.item_id),
102
+ kind: String(row.kind) as ItemSummary['kind'],
103
+ title: String(row.title),
104
+ },
105
+ savedAt: String(row.saved_at),
106
+ };
107
+ const size = Buffer.byteLength(JSON.stringify(entry));
108
+ if (items.length && bytes + size > 24576) break;
109
+ items.push(entry);
110
+ bytes += size;
111
+ }
112
+ const hasMore = rows.length > items.length;
113
+ return {
114
+ items,
115
+ hasMore,
116
+ ...(hasMore
117
+ ? {
118
+ nextCursor: codec.encode(binding, {
119
+ sequence: String(rows[items.length - 1]!.saved_sequence),
120
+ watermark: high,
121
+ }),
122
+ }
123
+ : {}),
124
+ watermark: codec.encode(binding, { sequence: high, watermark: high }),
125
+ };
126
+ }
127
+ }