@soulcraft/sdk 1.6.2 → 2.0.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.
- package/dist/client/create-client-sdk.d.ts +16 -2
- package/dist/client/create-client-sdk.d.ts.map +1 -1
- package/dist/client/create-client-sdk.js +2 -7
- package/dist/client/create-client-sdk.js.map +1 -1
- package/dist/client/index.d.ts +48 -37
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +61 -42
- package/dist/client/index.js.map +1 -1
- package/dist/client/namespace-proxy.d.ts +108 -0
- package/dist/client/namespace-proxy.d.ts.map +1 -0
- package/dist/client/namespace-proxy.js +151 -0
- package/dist/client/namespace-proxy.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/app-context/index.d.ts +214 -0
- package/dist/modules/app-context/index.d.ts.map +1 -0
- package/dist/modules/app-context/index.js +569 -0
- package/dist/modules/app-context/index.js.map +1 -0
- package/dist/modules/auth/products.d.ts +208 -0
- package/dist/modules/auth/products.d.ts.map +1 -0
- package/dist/modules/auth/products.js +165 -0
- package/dist/modules/auth/products.js.map +1 -0
- package/dist/namespaces.d.ts +2942 -0
- package/dist/namespaces.d.ts.map +1 -0
- package/dist/namespaces.js +37 -0
- package/dist/namespaces.js.map +1 -0
- package/dist/rpc.d.ts +156 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +26 -0
- package/dist/rpc.js.map +1 -0
- package/dist/server/create-sdk.d.ts.map +1 -1
- package/dist/server/create-sdk.js +3 -13
- package/dist/server/create-sdk.js.map +1 -1
- package/dist/server/handlers/annotations.d.ts +52 -0
- package/dist/server/handlers/annotations.d.ts.map +1 -0
- package/dist/server/handlers/annotations.js +204 -0
- package/dist/server/handlers/annotations.js.map +1 -0
- package/dist/server/handlers/auth.d.ts +53 -0
- package/dist/server/handlers/auth.d.ts.map +1 -0
- package/dist/server/handlers/auth.js +66 -0
- package/dist/server/handlers/auth.js.map +1 -0
- package/dist/server/handlers/certification.d.ts +32 -0
- package/dist/server/handlers/certification.d.ts.map +1 -0
- package/dist/server/handlers/certification.js +253 -0
- package/dist/server/handlers/certification.js.map +1 -0
- package/dist/server/handlers/chat/conversations.d.ts +91 -0
- package/dist/server/handlers/chat/conversations.d.ts.map +1 -0
- package/dist/server/handlers/chat/conversations.js +314 -0
- package/dist/server/handlers/chat/conversations.js.map +1 -0
- package/dist/server/handlers/chat/delegator.d.ts +144 -0
- package/dist/server/handlers/chat/delegator.d.ts.map +1 -0
- package/dist/server/handlers/chat/delegator.js +431 -0
- package/dist/server/handlers/chat/delegator.js.map +1 -0
- package/dist/server/handlers/chat/engine.d.ts +81 -0
- package/dist/server/handlers/chat/engine.d.ts.map +1 -0
- package/dist/server/handlers/chat/engine.js +442 -0
- package/dist/server/handlers/chat/engine.js.map +1 -0
- package/dist/server/handlers/chat/executor.d.ts +65 -0
- package/dist/server/handlers/chat/executor.d.ts.map +1 -0
- package/dist/server/handlers/chat/executor.js +375 -0
- package/dist/server/handlers/chat/executor.js.map +1 -0
- package/dist/server/handlers/chat/index.d.ts +62 -0
- package/dist/server/handlers/chat/index.d.ts.map +1 -0
- package/dist/server/handlers/chat/index.js +182 -0
- package/dist/server/handlers/chat/index.js.map +1 -0
- package/dist/server/handlers/chat/memory.d.ts +91 -0
- package/dist/server/handlers/chat/memory.d.ts.map +1 -0
- package/dist/server/handlers/chat/memory.js +293 -0
- package/dist/server/handlers/chat/memory.js.map +1 -0
- package/dist/server/handlers/chat/models.d.ts +180 -0
- package/dist/server/handlers/chat/models.d.ts.map +1 -0
- package/dist/server/handlers/chat/models.js +304 -0
- package/dist/server/handlers/chat/models.js.map +1 -0
- package/dist/server/handlers/chat/planner.d.ts +116 -0
- package/dist/server/handlers/chat/planner.d.ts.map +1 -0
- package/dist/server/handlers/chat/planner.js +344 -0
- package/dist/server/handlers/chat/planner.js.map +1 -0
- package/dist/server/handlers/chat/types.d.ts +500 -0
- package/dist/server/handlers/chat/types.d.ts.map +1 -0
- package/dist/server/handlers/chat/types.js +11 -0
- package/dist/server/handlers/chat/types.js.map +1 -0
- package/dist/server/handlers/collections.d.ts +67 -0
- package/dist/server/handlers/collections.d.ts.map +1 -0
- package/dist/server/handlers/collections.js +484 -0
- package/dist/server/handlers/collections.js.map +1 -0
- package/dist/server/handlers/commerce.d.ts +106 -0
- package/dist/server/handlers/commerce.d.ts.map +1 -0
- package/dist/server/handlers/commerce.js +62 -0
- package/dist/server/handlers/commerce.js.map +1 -0
- package/dist/server/handlers/config.d.ts +112 -0
- package/dist/server/handlers/config.d.ts.map +1 -0
- package/dist/server/handlers/config.js +122 -0
- package/dist/server/handlers/config.js.map +1 -0
- package/dist/server/handlers/export.d.ts +72 -0
- package/dist/server/handlers/export.d.ts.map +1 -0
- package/dist/server/handlers/export.js +175 -0
- package/dist/server/handlers/export.js.map +1 -0
- package/dist/server/handlers/formats.d.ts +77 -0
- package/dist/server/handlers/formats.d.ts.map +1 -0
- package/dist/server/handlers/formats.js +65 -0
- package/dist/server/handlers/formats.js.map +1 -0
- package/dist/server/handlers/graph.d.ts +31 -0
- package/dist/server/handlers/graph.d.ts.map +1 -0
- package/dist/server/handlers/graph.js +490 -0
- package/dist/server/handlers/graph.js.map +1 -0
- package/dist/server/handlers/import.d.ts +96 -0
- package/dist/server/handlers/import.d.ts.map +1 -0
- package/dist/server/handlers/import.js +108 -0
- package/dist/server/handlers/import.js.map +1 -0
- package/dist/server/handlers/index.d.ts +68 -0
- package/dist/server/handlers/index.d.ts.map +1 -0
- package/dist/server/handlers/index.js +71 -0
- package/dist/server/handlers/index.js.map +1 -0
- package/dist/server/handlers/media.d.ts +76 -0
- package/dist/server/handlers/media.d.ts.map +1 -0
- package/dist/server/handlers/media.js +53 -0
- package/dist/server/handlers/media.js.map +1 -0
- package/dist/server/handlers/project.d.ts +45 -0
- package/dist/server/handlers/project.d.ts.map +1 -0
- package/dist/server/handlers/project.js +181 -0
- package/dist/server/handlers/project.js.map +1 -0
- package/dist/server/handlers/publish.d.ts +102 -0
- package/dist/server/handlers/publish.d.ts.map +1 -0
- package/dist/server/handlers/publish.js +130 -0
- package/dist/server/handlers/publish.js.map +1 -0
- package/dist/server/handlers/pulse.d.ts +39 -0
- package/dist/server/handlers/pulse.d.ts.map +1 -0
- package/dist/server/handlers/pulse.js +78 -0
- package/dist/server/handlers/pulse.js.map +1 -0
- package/dist/server/handlers/realtime.d.ts +55 -0
- package/dist/server/handlers/realtime.d.ts.map +1 -0
- package/dist/server/handlers/realtime.js +49 -0
- package/dist/server/handlers/realtime.js.map +1 -0
- package/dist/server/handlers/search.d.ts +21 -0
- package/dist/server/handlers/search.d.ts.map +1 -0
- package/dist/server/handlers/search.js +237 -0
- package/dist/server/handlers/search.js.map +1 -0
- package/dist/server/handlers/session.d.ts +47 -0
- package/dist/server/handlers/session.d.ts.map +1 -0
- package/dist/server/handlers/session.js +286 -0
- package/dist/server/handlers/session.js.map +1 -0
- package/dist/server/handlers/settings.d.ts +97 -0
- package/dist/server/handlers/settings.d.ts.map +1 -0
- package/dist/server/handlers/settings.js +131 -0
- package/dist/server/handlers/settings.js.map +1 -0
- package/dist/server/handlers/workspace.d.ts +78 -0
- package/dist/server/handlers/workspace.d.ts.map +1 -0
- package/dist/server/handlers/workspace.js +270 -0
- package/dist/server/handlers/workspace.js.map +1 -0
- package/dist/server/hono-router.d.ts +66 -0
- package/dist/server/hono-router.d.ts.map +1 -0
- package/dist/server/hono-router.js +203 -0
- package/dist/server/hono-router.js.map +1 -0
- package/dist/server/index.d.ts +29 -19
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +33 -19
- package/dist/server/index.js.map +1 -1
- package/dist/server/namespace-router.d.ts +204 -0
- package/dist/server/namespace-router.d.ts.map +1 -0
- package/dist/server/namespace-router.js +262 -0
- package/dist/server/namespace-router.js.map +1 -0
- package/dist/transports/http-namespace.d.ts +210 -0
- package/dist/transports/http-namespace.d.ts.map +1 -0
- package/dist/transports/http-namespace.js +514 -0
- package/dist/transports/http-namespace.js.map +1 -0
- package/dist/transports/workshop.d.ts +173 -0
- package/dist/transports/workshop.d.ts.map +1 -0
- package/dist/transports/workshop.js +307 -0
- package/dist/transports/workshop.js.map +1 -0
- package/dist/types.d.ts +65 -67
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -3
- package/dist/types.js.map +1 -1
- package/docs/ADR-004-product-registry.md +108 -0
- package/package.json +1 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/search
|
|
3
|
+
* @description Search namespace handler — semantic vector search, unified search with
|
|
4
|
+
* rich results, and file content highlighting.
|
|
5
|
+
*
|
|
6
|
+
* Absorbs Workshop `routes/search.ts`. Uses Brainy's `brain.find()` for semantic
|
|
7
|
+
* vector search and `brain.highlight()` for in-file content matching.
|
|
8
|
+
*
|
|
9
|
+
* Methods:
|
|
10
|
+
* - `query` — Simple semantic search returning entity matches
|
|
11
|
+
* - `unified` — Rich search with type grouping, scope filtering, and context
|
|
12
|
+
* - `highlight` — Find text + semantic matches within a specific file
|
|
13
|
+
*/
|
|
14
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
// Constants
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
/** Icon mapping for entity types in unified search results. */
|
|
18
|
+
const TYPE_ICONS = {
|
|
19
|
+
file: '\u{1F4C4}', folder: '\u{1F4C1}', concept: '\u{1F4A1}',
|
|
20
|
+
person: '\u{1F464}', organization: '\u{1F3E2}', location: '\u{1F4CD}',
|
|
21
|
+
event: '\u{1F4C5}', project: '\u{1F3AF}', task: '\u2705',
|
|
22
|
+
document: '\u{1F4D1}', idea: '\u{1F4AD}', note: '\u{1F4DD}',
|
|
23
|
+
topic: '\u{1F3F7}\uFE0F', technology: '\u2699\uFE0F', skill: '\u{1F3AF}',
|
|
24
|
+
tool: '\u{1F527}', product: '\u{1F4E6}', conversation: '\u{1F4AC}',
|
|
25
|
+
default: '\u25C6',
|
|
26
|
+
};
|
|
27
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
|
+
// Handler factory
|
|
29
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
30
|
+
/**
|
|
31
|
+
* Creates the `search` namespace handler.
|
|
32
|
+
*
|
|
33
|
+
* @returns A {@link NamespaceProvider} implementing {@link SearchNamespace}.
|
|
34
|
+
*/
|
|
35
|
+
export function createSearchHandler() {
|
|
36
|
+
return {
|
|
37
|
+
/**
|
|
38
|
+
* Simple semantic search.
|
|
39
|
+
*
|
|
40
|
+
* @param query - Search query string.
|
|
41
|
+
* @param options - Search options.
|
|
42
|
+
* @param ctx - Handler context.
|
|
43
|
+
* @returns Array of search results with scores.
|
|
44
|
+
*/
|
|
45
|
+
async query(query, options, ctx) {
|
|
46
|
+
const { brain } = ctx;
|
|
47
|
+
const limit = options?.limit ?? 50;
|
|
48
|
+
const results = await brain.find({ query, limit });
|
|
49
|
+
const mapped = results.map((r) => ({
|
|
50
|
+
id: r.id,
|
|
51
|
+
name: r.data || r.metadata?.name || r.metadata?.label || r.id,
|
|
52
|
+
type: r.type || r.metadata?.noun || 'concept',
|
|
53
|
+
score: r.score ?? 0,
|
|
54
|
+
}));
|
|
55
|
+
return { query, results: mapped, total: mapped.length };
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* Unified rich search for Command Palette and advanced search UIs.
|
|
59
|
+
*
|
|
60
|
+
* Combines semantic search with post-filters for scope, collection membership,
|
|
61
|
+
* type, date range, and graph connectivity.
|
|
62
|
+
*
|
|
63
|
+
* @param query - Search query string.
|
|
64
|
+
* @param options - Unified search options.
|
|
65
|
+
* @param ctx - Handler context.
|
|
66
|
+
* @returns Rich results grouped by type with context and preview.
|
|
67
|
+
*/
|
|
68
|
+
async unified(query, options, ctx) {
|
|
69
|
+
const { brain } = ctx;
|
|
70
|
+
const limit = options?.limit ?? 50;
|
|
71
|
+
const scope = options?.scope ?? 'all';
|
|
72
|
+
const collectionId = options?.collectionId;
|
|
73
|
+
const typeFilters = options?.types ?? [];
|
|
74
|
+
const dateFrom = options?.dateFrom;
|
|
75
|
+
const dateTo = options?.dateTo;
|
|
76
|
+
const connectedTo = options?.connectedTo;
|
|
77
|
+
let results = [];
|
|
78
|
+
const queryTrimmed = query.trim();
|
|
79
|
+
if (queryTrimmed.length >= 1) {
|
|
80
|
+
// Determine if we have post-filters requiring over-fetch
|
|
81
|
+
const hasPostFilters = (scope === 'collection' && collectionId) ||
|
|
82
|
+
connectedTo || dateFrom || dateTo || typeFilters.length > 0;
|
|
83
|
+
const findOptions = {
|
|
84
|
+
query: queryTrimmed,
|
|
85
|
+
limit: hasPostFilters ? limit * 3 : limit,
|
|
86
|
+
};
|
|
87
|
+
if (scope === 'collection')
|
|
88
|
+
findOptions.excludeVFS = true;
|
|
89
|
+
// Pre-fetch collection member IDs
|
|
90
|
+
let collectionMemberIds = null;
|
|
91
|
+
if (scope === 'collection' && collectionId) {
|
|
92
|
+
try {
|
|
93
|
+
const relations = await brain.getRelations({ from: collectionId, type: 'contains' });
|
|
94
|
+
collectionMemberIds = new Set(relations.map((r) => r.to));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
collectionMemberIds = new Set();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Pre-fetch connected entity IDs
|
|
101
|
+
let connectedToIds = null;
|
|
102
|
+
if (connectedTo) {
|
|
103
|
+
try {
|
|
104
|
+
const outgoing = await brain.getRelations({ from: connectedTo });
|
|
105
|
+
const incoming = await brain.getRelations({ to: connectedTo });
|
|
106
|
+
connectedToIds = new Set([
|
|
107
|
+
...outgoing.map((r) => r.to),
|
|
108
|
+
...incoming.map((r) => r.from),
|
|
109
|
+
]);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
connectedToIds = new Set();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const semanticResults = await brain.find(findOptions);
|
|
116
|
+
// Post-filter
|
|
117
|
+
for (const result of semanticResults) {
|
|
118
|
+
const metadata = result.metadata || {};
|
|
119
|
+
const entityType = (result.type || metadata.noun || '').toLowerCase();
|
|
120
|
+
const vfsType = (metadata.vfsType || '').toLowerCase();
|
|
121
|
+
const isVFS = metadata.isVFS || metadata.isVFSEntity || !!vfsType;
|
|
122
|
+
if (scope === 'files' && !isVFS)
|
|
123
|
+
continue;
|
|
124
|
+
if (scope === 'collection' && collectionMemberIds && !collectionMemberIds.has(result.id))
|
|
125
|
+
continue;
|
|
126
|
+
if (typeFilters.length > 0 && !typeFilters.includes(entityType))
|
|
127
|
+
continue;
|
|
128
|
+
if (connectedToIds && !connectedToIds.has(result.id))
|
|
129
|
+
continue;
|
|
130
|
+
if (dateFrom || dateTo) {
|
|
131
|
+
const createdAt = metadata.createdAt || result.createdAt;
|
|
132
|
+
if (createdAt) {
|
|
133
|
+
const ts = new Date(createdAt).getTime();
|
|
134
|
+
if (dateFrom && ts < new Date(dateFrom).getTime())
|
|
135
|
+
continue;
|
|
136
|
+
if (dateTo && ts > new Date(dateTo).getTime())
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
results.push({ ...result, score: result.score || 0.5 });
|
|
141
|
+
}
|
|
142
|
+
results.sort((a, b) => b.score - a.score);
|
|
143
|
+
results = results.slice(0, limit);
|
|
144
|
+
}
|
|
145
|
+
// Normalize scores relative to the top result
|
|
146
|
+
const topScore = results.length > 0 ? Math.max(...results.map((r) => r.score || 0)) : 1;
|
|
147
|
+
const scoreScale = topScore > 0 ? 1 / topScore : 1;
|
|
148
|
+
// Transform to rich format
|
|
149
|
+
const richResults = results.map((result) => {
|
|
150
|
+
const metadata = result.metadata || {};
|
|
151
|
+
const entityType = (result.type || '').toLowerCase();
|
|
152
|
+
const vfsType = (metadata.vfsType || '').toLowerCase();
|
|
153
|
+
const isVFS = metadata.isVFS || metadata.isVFSEntity || !!vfsType;
|
|
154
|
+
const isFile = vfsType === 'file' || (isVFS && entityType === 'document') || entityType === 'file';
|
|
155
|
+
const isFolder = vfsType === 'directory' || vfsType === 'folder' || entityType === 'folder';
|
|
156
|
+
let name = metadata.name || metadata.label || metadata.title || result.id;
|
|
157
|
+
if (typeof name === 'object')
|
|
158
|
+
name = name.name || name.label || result.id;
|
|
159
|
+
if (name === result.id && result.data && typeof result.data === 'string')
|
|
160
|
+
name = result.data;
|
|
161
|
+
let displayType = entityType || 'concept';
|
|
162
|
+
if (isFile)
|
|
163
|
+
displayType = 'file';
|
|
164
|
+
if (isFolder)
|
|
165
|
+
displayType = 'folder';
|
|
166
|
+
if (metadata._aiDataType)
|
|
167
|
+
displayType = metadata._aiDataType;
|
|
168
|
+
return {
|
|
169
|
+
id: result.id,
|
|
170
|
+
name: String(name),
|
|
171
|
+
type: displayType,
|
|
172
|
+
icon: TYPE_ICONS[displayType] || TYPE_ICONS.default,
|
|
173
|
+
score: result.score,
|
|
174
|
+
scorePercent: Math.round((result.score || 0) * scoreScale * 100),
|
|
175
|
+
context: {
|
|
176
|
+
path: metadata.path || undefined,
|
|
177
|
+
connectionCount: (!isFile && !isFolder) ? metadata.connections : undefined,
|
|
178
|
+
subtitle: metadata.subtitle || metadata.description?.slice(0, 100),
|
|
179
|
+
},
|
|
180
|
+
preview: isFile && (metadata.content || metadata.description || result.data)
|
|
181
|
+
? String(metadata.content || metadata.description || result.data).slice(0, 200).replace(/\n/g, ' ').trim()
|
|
182
|
+
: undefined,
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
// Group by type
|
|
186
|
+
const groups = {
|
|
187
|
+
files: richResults.filter(r => r.type === 'file'),
|
|
188
|
+
folders: richResults.filter(r => r.type === 'folder'),
|
|
189
|
+
concepts: richResults.filter(r => ['concept', 'idea', 'topic', 'note'].includes(r.type)),
|
|
190
|
+
people: richResults.filter(r => r.type === 'person'),
|
|
191
|
+
organizations: richResults.filter(r => r.type === 'organization'),
|
|
192
|
+
locations: richResults.filter(r => r.type === 'location'),
|
|
193
|
+
other: richResults.filter(r => !['file', 'folder', 'concept', 'idea', 'topic', 'note', 'person', 'organization', 'location'].includes(r.type)),
|
|
194
|
+
};
|
|
195
|
+
return { query, scope, results: richResults, groups, total: richResults.length };
|
|
196
|
+
},
|
|
197
|
+
/**
|
|
198
|
+
* Highlight search matches within a specific file's content.
|
|
199
|
+
*
|
|
200
|
+
* @param query - Search query.
|
|
201
|
+
* @param filePath - VFS path to the file.
|
|
202
|
+
* @param options - Highlight options.
|
|
203
|
+
* @param ctx - Handler context.
|
|
204
|
+
* @returns Array of highlight positions with scores.
|
|
205
|
+
*/
|
|
206
|
+
async highlight(query, filePath, options, ctx) {
|
|
207
|
+
const { brain } = ctx;
|
|
208
|
+
const granularity = options?.granularity ?? 'word';
|
|
209
|
+
if (!query.trim() || !filePath.trim()) {
|
|
210
|
+
return { query, path: filePath, highlights: [], total: 0 };
|
|
211
|
+
}
|
|
212
|
+
// Read file content from VFS
|
|
213
|
+
let fileContent;
|
|
214
|
+
try {
|
|
215
|
+
fileContent = await brain.vfs.readFile(filePath);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return { query, path: filePath, highlights: [], total: 0 };
|
|
219
|
+
}
|
|
220
|
+
const highlightParams = { query: query.trim(), text: fileContent, granularity };
|
|
221
|
+
const highlights = await brain.highlight(highlightParams);
|
|
222
|
+
return {
|
|
223
|
+
query,
|
|
224
|
+
path: filePath,
|
|
225
|
+
highlights: highlights.map((h) => ({
|
|
226
|
+
text: h.text,
|
|
227
|
+
score: h.score,
|
|
228
|
+
position: h.position,
|
|
229
|
+
matchType: h.matchType,
|
|
230
|
+
contentCategory: h.contentCategory || undefined,
|
|
231
|
+
})),
|
|
232
|
+
total: highlights.length,
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/server/handlers/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/session
|
|
3
|
+
* @description Session namespace handler — collaborative session lifecycle for
|
|
4
|
+
* Living Links (join, leave, state, history).
|
|
5
|
+
*
|
|
6
|
+
* Absorbs Workshop `routes/session.ts`. Sessions are persisted as Brainy
|
|
7
|
+
* entities (NounType.Collection with sessionType metadata). Each session tracks
|
|
8
|
+
* participants, start/end times, and an inactivity timer that auto-closes
|
|
9
|
+
* after 30 minutes.
|
|
10
|
+
*
|
|
11
|
+
* Methods:
|
|
12
|
+
* - `join` — Join or create a collaborative session
|
|
13
|
+
* - `leave` — Record a participant leaving
|
|
14
|
+
* - `getState` — Get the current session state
|
|
15
|
+
* - `getHistory` — Get past sessions for a Living Link
|
|
16
|
+
*/
|
|
17
|
+
import type { NamespaceProvider } from '../namespace-router.js';
|
|
18
|
+
/**
|
|
19
|
+
* Event emitter interface for broadcasting session state changes.
|
|
20
|
+
*
|
|
21
|
+
* Products inject their own emitter — Workshop uses `dataChangeEmitter`,
|
|
22
|
+
* Venue might use a WebSocket broadcast.
|
|
23
|
+
*/
|
|
24
|
+
export interface SessionEventEmitter {
|
|
25
|
+
/** Emit a session lifecycle event. */
|
|
26
|
+
emit(event: string, data: Record<string, unknown>): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Options for {@link createSessionHandler}.
|
|
30
|
+
*/
|
|
31
|
+
export interface SessionHandlerOptions {
|
|
32
|
+
/** Event emitter for broadcasting session changes. */
|
|
33
|
+
events?: SessionEventEmitter;
|
|
34
|
+
/**
|
|
35
|
+
* Inactivity timeout in milliseconds before a session is auto-closed.
|
|
36
|
+
* Default: 30 minutes (1,800,000 ms).
|
|
37
|
+
*/
|
|
38
|
+
inactivityMs?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates the `session` namespace handler.
|
|
42
|
+
*
|
|
43
|
+
* @param options - Optional session handler configuration.
|
|
44
|
+
* @returns A {@link NamespaceProvider} implementing {@link SessionNamespace}.
|
|
45
|
+
*/
|
|
46
|
+
export declare function createSessionHandler(options?: SessionHandlerOptions): NamespaceProvider;
|
|
47
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,wBAAwB,CAAA;AAyB/E;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CACzD;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,MAAM,CAAC,EAAE,mBAAmB,CAAA;IAE5B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAkID;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,iBAAiB,CAiMvF"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/session
|
|
3
|
+
* @description Session namespace handler — collaborative session lifecycle for
|
|
4
|
+
* Living Links (join, leave, state, history).
|
|
5
|
+
*
|
|
6
|
+
* Absorbs Workshop `routes/session.ts`. Sessions are persisted as Brainy
|
|
7
|
+
* entities (NounType.Collection with sessionType metadata). Each session tracks
|
|
8
|
+
* participants, start/end times, and an inactivity timer that auto-closes
|
|
9
|
+
* after 30 minutes.
|
|
10
|
+
*
|
|
11
|
+
* Methods:
|
|
12
|
+
* - `join` — Join or create a collaborative session
|
|
13
|
+
* - `leave` — Record a participant leaving
|
|
14
|
+
* - `getState` — Get the current session state
|
|
15
|
+
* - `getHistory` — Get past sessions for a Living Link
|
|
16
|
+
*/
|
|
17
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
// Inactivity timer management
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
/** Per-session inactivity timers. Key: sessionId. */
|
|
21
|
+
const inactivityTimers = new Map();
|
|
22
|
+
/**
|
|
23
|
+
* Reset or start the inactivity timer for a session.
|
|
24
|
+
*
|
|
25
|
+
* @param sessionId - The session entity ID.
|
|
26
|
+
* @param brain - Brainy instance for closing the session on timeout.
|
|
27
|
+
* @param timeoutMs - Inactivity timeout in milliseconds.
|
|
28
|
+
* @param events - Optional event emitter for broadcasting closure.
|
|
29
|
+
*/
|
|
30
|
+
function resetInactivityTimer(sessionId, brain, timeoutMs, events) {
|
|
31
|
+
const existing = inactivityTimers.get(sessionId);
|
|
32
|
+
if (existing)
|
|
33
|
+
clearTimeout(existing);
|
|
34
|
+
const timer = setTimeout(async () => {
|
|
35
|
+
inactivityTimers.delete(sessionId);
|
|
36
|
+
try {
|
|
37
|
+
await brain.update(sessionId, {
|
|
38
|
+
metadata: {
|
|
39
|
+
endedAt: new Date().toISOString(),
|
|
40
|
+
sessionStatus: 'closed',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
events?.emit('session_closed', { sessionId, reason: 'inactivity' });
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
console.error('[session] Failed to auto-close session:', err);
|
|
47
|
+
}
|
|
48
|
+
}, timeoutMs);
|
|
49
|
+
inactivityTimers.set(sessionId, timer);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Cancel any pending inactivity timer.
|
|
53
|
+
*
|
|
54
|
+
* @param sessionId - The session entity ID.
|
|
55
|
+
*/
|
|
56
|
+
function cancelInactivityTimer(sessionId) {
|
|
57
|
+
const existing = inactivityTimers.get(sessionId);
|
|
58
|
+
if (existing) {
|
|
59
|
+
clearTimeout(existing);
|
|
60
|
+
inactivityTimers.delete(sessionId);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
64
|
+
// Helpers
|
|
65
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
66
|
+
/**
|
|
67
|
+
* Find the currently active session for a given scope (e.g., Living Link slug).
|
|
68
|
+
*
|
|
69
|
+
* Sessions are Collection entities with `sessionType: 'collaborative-session'`
|
|
70
|
+
* and `sessionStatus: 'active'`.
|
|
71
|
+
*
|
|
72
|
+
* @param brain - Brainy instance.
|
|
73
|
+
* @param scope - The scope identifier (Living Link slug or session group).
|
|
74
|
+
* @returns The active session entity, or `null` if none found.
|
|
75
|
+
*/
|
|
76
|
+
async function findActiveSession(brain, scope) {
|
|
77
|
+
try {
|
|
78
|
+
const results = await brain.find({
|
|
79
|
+
where: { type: 'Collection' },
|
|
80
|
+
limit: 100,
|
|
81
|
+
});
|
|
82
|
+
for (const entity of results) {
|
|
83
|
+
const meta = entity.metadata || {};
|
|
84
|
+
if (meta.sessionType === 'collaborative-session' &&
|
|
85
|
+
meta.sessionStatus === 'active' &&
|
|
86
|
+
(meta.livingLinkSlug === scope || entity.id === scope)) {
|
|
87
|
+
return entity;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// No sessions found
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Find all collaborative sessions for a scope (both active and closed).
|
|
98
|
+
*
|
|
99
|
+
* @param brain - Brainy instance.
|
|
100
|
+
* @param scope - The scope identifier.
|
|
101
|
+
* @returns Array of session entities, newest first.
|
|
102
|
+
*/
|
|
103
|
+
async function findAllSessions(brain, scope) {
|
|
104
|
+
try {
|
|
105
|
+
const results = await brain.find({
|
|
106
|
+
where: { type: 'Collection' },
|
|
107
|
+
limit: 500,
|
|
108
|
+
});
|
|
109
|
+
return results
|
|
110
|
+
.filter((entity) => {
|
|
111
|
+
const meta = entity.metadata || {};
|
|
112
|
+
return (meta.sessionType === 'collaborative-session' &&
|
|
113
|
+
(meta.livingLinkSlug === scope || entity.id === scope));
|
|
114
|
+
})
|
|
115
|
+
.sort((a, b) => {
|
|
116
|
+
const aTime = new Date(a.metadata?.startedAt || 0).getTime();
|
|
117
|
+
const bTime = new Date(b.metadata?.startedAt || 0).getTime();
|
|
118
|
+
return bTime - aTime; // newest first
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
126
|
+
// Handler factory
|
|
127
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
128
|
+
/**
|
|
129
|
+
* Creates the `session` namespace handler.
|
|
130
|
+
*
|
|
131
|
+
* @param options - Optional session handler configuration.
|
|
132
|
+
* @returns A {@link NamespaceProvider} implementing {@link SessionNamespace}.
|
|
133
|
+
*/
|
|
134
|
+
export function createSessionHandler(options) {
|
|
135
|
+
const events = options?.events;
|
|
136
|
+
const inactivityMs = options?.inactivityMs ?? 30 * 60 * 1000;
|
|
137
|
+
return {
|
|
138
|
+
/**
|
|
139
|
+
* Join a collaborative session.
|
|
140
|
+
*
|
|
141
|
+
* Creates a new session if none is currently active for the given scope.
|
|
142
|
+
* Otherwise, adds the current user as a participant. Resets the inactivity
|
|
143
|
+
* timer on every join.
|
|
144
|
+
*
|
|
145
|
+
* @param sessionId - Session scope (Living Link slug or session group ID).
|
|
146
|
+
* @param joinOptions - Join options.
|
|
147
|
+
* @param ctx - Handler context.
|
|
148
|
+
* @returns The current session state.
|
|
149
|
+
*/
|
|
150
|
+
async join(sessionId, joinOptions, ctx) {
|
|
151
|
+
const { brain } = ctx;
|
|
152
|
+
const displayName = joinOptions?.displayName || ctx.user.name || 'Anonymous';
|
|
153
|
+
const peerId = ctx.user.id;
|
|
154
|
+
const participant = {
|
|
155
|
+
peerId,
|
|
156
|
+
displayName,
|
|
157
|
+
joinedAt: new Date().toISOString(),
|
|
158
|
+
};
|
|
159
|
+
let activeSession = await findActiveSession(brain, sessionId);
|
|
160
|
+
if (!activeSession) {
|
|
161
|
+
// Create a new session entity
|
|
162
|
+
const newId = await brain.add({
|
|
163
|
+
type: 'collection',
|
|
164
|
+
data: `Session — ${sessionId} — ${new Date().toLocaleDateString()}`,
|
|
165
|
+
metadata: {
|
|
166
|
+
name: `Session — ${sessionId}`,
|
|
167
|
+
sessionType: 'collaborative-session',
|
|
168
|
+
livingLinkSlug: sessionId,
|
|
169
|
+
startedAt: new Date().toISOString(),
|
|
170
|
+
endedAt: null,
|
|
171
|
+
sessionStatus: 'active',
|
|
172
|
+
participants: [participant],
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
activeSession = await brain.get(newId);
|
|
176
|
+
events?.emit('session_created', {
|
|
177
|
+
sessionId: newId,
|
|
178
|
+
scope: sessionId,
|
|
179
|
+
userId: ctx.user.id,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// Add participant if not already present
|
|
184
|
+
const meta = activeSession.metadata || {};
|
|
185
|
+
const participants = meta.participants ?? [];
|
|
186
|
+
const alreadyPresent = participants.some((p) => p.peerId === peerId && !p.leftAt);
|
|
187
|
+
if (!alreadyPresent) {
|
|
188
|
+
participants.push(participant);
|
|
189
|
+
await brain.update({ id: activeSession.id, metadata: { participants } });
|
|
190
|
+
}
|
|
191
|
+
events?.emit('session_participant_joined', {
|
|
192
|
+
sessionId: activeSession.id,
|
|
193
|
+
participant: { displayName, peerId },
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
// Reset inactivity timer
|
|
197
|
+
resetInactivityTimer(activeSession.id, brain, inactivityMs, events);
|
|
198
|
+
// Build response
|
|
199
|
+
const meta = activeSession.metadata || {};
|
|
200
|
+
const participants = meta.participants ?? [];
|
|
201
|
+
const activeParticipants = participants.filter((p) => !p.leftAt);
|
|
202
|
+
return {
|
|
203
|
+
sessionId: activeSession.id,
|
|
204
|
+
participants: activeParticipants.map((p) => ({
|
|
205
|
+
userId: p.peerId,
|
|
206
|
+
name: p.displayName,
|
|
207
|
+
joinedAt: p.joinedAt,
|
|
208
|
+
})),
|
|
209
|
+
createdAt: meta.startedAt || new Date().toISOString(),
|
|
210
|
+
};
|
|
211
|
+
},
|
|
212
|
+
/**
|
|
213
|
+
* Leave a collaborative session.
|
|
214
|
+
*
|
|
215
|
+
* Records `leftAt` on the participant entry and resets the inactivity timer.
|
|
216
|
+
*
|
|
217
|
+
* @param sessionId - Session scope (Living Link slug or session group ID).
|
|
218
|
+
* @param ctx - Handler context.
|
|
219
|
+
*/
|
|
220
|
+
async leave(sessionId, ctx) {
|
|
221
|
+
const { brain } = ctx;
|
|
222
|
+
const peerId = ctx.user.id;
|
|
223
|
+
const now = new Date().toISOString();
|
|
224
|
+
const activeSession = await findActiveSession(brain, sessionId);
|
|
225
|
+
if (!activeSession)
|
|
226
|
+
return;
|
|
227
|
+
const meta = activeSession.metadata || {};
|
|
228
|
+
const participants = meta.participants ?? [];
|
|
229
|
+
// Mark this peer as left
|
|
230
|
+
const updated = participants.map((p) => p.peerId === peerId && !p.leftAt ? { ...p, leftAt: now } : p);
|
|
231
|
+
await brain.update({ id: activeSession.id, metadata: { participants: updated } });
|
|
232
|
+
events?.emit('session_participant_left', {
|
|
233
|
+
sessionId: activeSession.id,
|
|
234
|
+
peerId,
|
|
235
|
+
});
|
|
236
|
+
// Reset inactivity timer (departures count as activity)
|
|
237
|
+
resetInactivityTimer(activeSession.id, brain, inactivityMs, events);
|
|
238
|
+
},
|
|
239
|
+
/**
|
|
240
|
+
* Get the current state of a session.
|
|
241
|
+
*
|
|
242
|
+
* @param sessionId - Session scope (Living Link slug or session ID).
|
|
243
|
+
* @param ctx - Handler context.
|
|
244
|
+
* @returns Session state, or `null` if no active session exists.
|
|
245
|
+
*/
|
|
246
|
+
async getState(sessionId, ctx) {
|
|
247
|
+
const activeSession = await findActiveSession(ctx.brain, sessionId);
|
|
248
|
+
if (!activeSession)
|
|
249
|
+
return null;
|
|
250
|
+
const meta = activeSession.metadata || {};
|
|
251
|
+
const participants = meta.participants ?? [];
|
|
252
|
+
const activeParticipants = participants.filter((p) => !p.leftAt);
|
|
253
|
+
return {
|
|
254
|
+
sessionId: activeSession.id,
|
|
255
|
+
participants: activeParticipants.map((p) => ({
|
|
256
|
+
userId: p.peerId,
|
|
257
|
+
name: p.displayName,
|
|
258
|
+
joinedAt: p.joinedAt,
|
|
259
|
+
})),
|
|
260
|
+
createdAt: meta.startedAt || '',
|
|
261
|
+
};
|
|
262
|
+
},
|
|
263
|
+
/**
|
|
264
|
+
* Get the history of past sessions.
|
|
265
|
+
*
|
|
266
|
+
* @param historyOptions - Pagination options.
|
|
267
|
+
* @param ctx - Handler context.
|
|
268
|
+
* @returns Array of past session summaries.
|
|
269
|
+
*/
|
|
270
|
+
async getHistory(historyOptions, ctx) {
|
|
271
|
+
const limit = historyOptions?.limit ?? 20;
|
|
272
|
+
const sessions = await findAllSessions(ctx.brain, ctx.workspaceId);
|
|
273
|
+
return sessions.slice(0, limit).map((session) => {
|
|
274
|
+
const meta = session.metadata || {};
|
|
275
|
+
const participants = meta.participants ?? [];
|
|
276
|
+
return {
|
|
277
|
+
sessionId: session.id,
|
|
278
|
+
startedAt: meta.startedAt || '',
|
|
279
|
+
endedAt: meta.endedAt || '',
|
|
280
|
+
participantCount: participants.length,
|
|
281
|
+
};
|
|
282
|
+
});
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/server/handlers/session.ts"],"names":[],"mappings":"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"}
|