@soulcraft/sdk 1.7.0 → 2.0.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.
- 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 +44 -37
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +59 -44
- 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 +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/modules/app-context/index.d.ts +15 -15
- package/dist/modules/app-context/index.d.ts.map +1 -1
- package/dist/modules/app-context/index.js +17 -17
- package/dist/modules/app-context/index.js.map +1 -1
- 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 +446 -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 +515 -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 +27 -19
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +30 -18
- 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/types.d.ts +59 -65
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -3
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/auth
|
|
3
|
+
* @description Auth namespace handler — session introspection and WebSocket
|
|
4
|
+
* token generation.
|
|
5
|
+
*
|
|
6
|
+
* The auth handler is deliberately thin. Heavy auth logic (login, logout, OAuth
|
|
7
|
+
* flows, session creation) lives in middleware (`modules/auth/middleware.ts`).
|
|
8
|
+
* This handler only exposes the two methods that clients need at runtime:
|
|
9
|
+
* checking who they are (`getSession`) and getting a short-lived WS token.
|
|
10
|
+
*
|
|
11
|
+
* Methods:
|
|
12
|
+
* - `getSession` — Return the authenticated user and status
|
|
13
|
+
* - `getWsToken` — Generate a capability token for WebSocket connections
|
|
14
|
+
*/
|
|
15
|
+
import type { NamespaceProvider } from '../namespace-router.js';
|
|
16
|
+
/**
|
|
17
|
+
* Capability token generator for WebSocket authentication.
|
|
18
|
+
*
|
|
19
|
+
* Products inject their own token factory — Workshop uses HMAC-signed tokens
|
|
20
|
+
* from `@soulcraft/sdk/server`.
|
|
21
|
+
*/
|
|
22
|
+
export interface CapabilityTokenFactory {
|
|
23
|
+
/**
|
|
24
|
+
* Create a short-lived capability token.
|
|
25
|
+
*
|
|
26
|
+
* @param email - User's email hash for scoping.
|
|
27
|
+
* @param scope - Workspace or resource scope.
|
|
28
|
+
* @returns Signed token string.
|
|
29
|
+
*/
|
|
30
|
+
create(email: string, scope: string): Promise<string>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Options for {@link createAuthHandler}.
|
|
34
|
+
*/
|
|
35
|
+
export interface AuthHandlerOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Capability token factory for WS token generation.
|
|
38
|
+
* If not provided, `getWsToken` throws an error.
|
|
39
|
+
*/
|
|
40
|
+
tokenFactory?: CapabilityTokenFactory;
|
|
41
|
+
/**
|
|
42
|
+
* Token TTL in seconds. Default: 300 (5 minutes).
|
|
43
|
+
*/
|
|
44
|
+
tokenTtlSeconds?: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates the `auth` namespace handler.
|
|
48
|
+
*
|
|
49
|
+
* @param options - Optional auth handler dependencies.
|
|
50
|
+
* @returns A {@link NamespaceProvider} implementing {@link AuthNamespace}.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createAuthHandler(options?: AuthHandlerOptions): NamespaceProvider;
|
|
53
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,wBAAwB,CAAA;AAM/E;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,YAAY,CAAC,EAAE,sBAAsB,CAAA;IAErC;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAMD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAoDjF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/auth
|
|
3
|
+
* @description Auth namespace handler — session introspection and WebSocket
|
|
4
|
+
* token generation.
|
|
5
|
+
*
|
|
6
|
+
* The auth handler is deliberately thin. Heavy auth logic (login, logout, OAuth
|
|
7
|
+
* flows, session creation) lives in middleware (`modules/auth/middleware.ts`).
|
|
8
|
+
* This handler only exposes the two methods that clients need at runtime:
|
|
9
|
+
* checking who they are (`getSession`) and getting a short-lived WS token.
|
|
10
|
+
*
|
|
11
|
+
* Methods:
|
|
12
|
+
* - `getSession` — Return the authenticated user and status
|
|
13
|
+
* - `getWsToken` — Generate a capability token for WebSocket connections
|
|
14
|
+
*/
|
|
15
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
16
|
+
// Handler factory
|
|
17
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Creates the `auth` namespace handler.
|
|
20
|
+
*
|
|
21
|
+
* @param options - Optional auth handler dependencies.
|
|
22
|
+
* @returns A {@link NamespaceProvider} implementing {@link AuthNamespace}.
|
|
23
|
+
*/
|
|
24
|
+
export function createAuthHandler(options) {
|
|
25
|
+
const tokenFactory = options?.tokenFactory;
|
|
26
|
+
const tokenTtlSeconds = options?.tokenTtlSeconds ?? 300;
|
|
27
|
+
return {
|
|
28
|
+
/**
|
|
29
|
+
* Get the current session user and authentication status.
|
|
30
|
+
*
|
|
31
|
+
* The user is already resolved by the namespace router's `authenticate`
|
|
32
|
+
* callback and passed in the handler context. This method simply returns it.
|
|
33
|
+
*
|
|
34
|
+
* @param ctx - Handler context with authenticated user.
|
|
35
|
+
* @returns User info and authentication flag.
|
|
36
|
+
*/
|
|
37
|
+
async getSession(ctx) {
|
|
38
|
+
return {
|
|
39
|
+
user: {
|
|
40
|
+
id: ctx.user.id,
|
|
41
|
+
email: ctx.user.email,
|
|
42
|
+
name: ctx.user.name,
|
|
43
|
+
...(ctx.user.role != null ? { role: ctx.user.role } : {}),
|
|
44
|
+
},
|
|
45
|
+
authenticated: true,
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* Get a short-lived WebSocket capability token.
|
|
50
|
+
*
|
|
51
|
+
* @param tokenOptions - Token scope options.
|
|
52
|
+
* @param ctx - Handler context.
|
|
53
|
+
* @returns Token string and expiration timestamp.
|
|
54
|
+
*/
|
|
55
|
+
async getWsToken(tokenOptions, ctx) {
|
|
56
|
+
if (!tokenFactory) {
|
|
57
|
+
throw new Error('WebSocket tokens are not configured — provide a tokenFactory in handler options');
|
|
58
|
+
}
|
|
59
|
+
const scope = tokenOptions?.scope || ctx.workspaceId;
|
|
60
|
+
const token = await tokenFactory.create(ctx.user.emailHash, scope);
|
|
61
|
+
const expiresAt = new Date(Date.now() + tokenTtlSeconds * 1000).toISOString();
|
|
62
|
+
return { token, expiresAt };
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/server/handlers/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAyCH,gFAAgF;AAChF,kBAAkB;AAClB,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA4B;IAC5D,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,CAAA;IAC1C,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,GAAG,CAAA;IAEvD,OAAO;QACL;;;;;;;;WAQG;QACH,KAAK,CAAC,UAAU,CAAC,GAAmB;YAIlC,OAAO;gBACL,IAAI,EAAE;oBACJ,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE;oBACf,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;oBACrB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;oBACnB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC1D;gBACD,aAAa,EAAE,IAAI;aACpB,CAAA;QACH,CAAC;QAED;;;;;;WAMG;QACH,KAAK,CAAC,UAAU,CACd,YAA4C,EAC5C,GAAmB;YAEnB,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAA;YACpG,CAAC;YAED,MAAM,KAAK,GAAG,YAAY,EAAE,KAAK,IAAI,GAAG,CAAC,WAAW,CAAA;YACpD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;YAElE,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA;YAE7E,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;QAC7B,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/certification
|
|
3
|
+
* @description Certification namespace handler — issue, verify, and trace
|
|
4
|
+
* credential lineage using Brainy's graph model.
|
|
5
|
+
*
|
|
6
|
+
* Certifications are `Contract` entities linked by `endorses` (certifier → cert),
|
|
7
|
+
* `attributedTo` (cert → learner), and `dependsOn` (cert → upstream cert)
|
|
8
|
+
* relationships. This creates a verifiable lineage chain — the medieval guild
|
|
9
|
+
* model where every credential traces back to the authority that granted it.
|
|
10
|
+
*
|
|
11
|
+
* Originally built for Academy (course completion credentials). Now a platform
|
|
12
|
+
* primitive usable by Workshop, Venue, and kit apps.
|
|
13
|
+
*
|
|
14
|
+
* Methods:
|
|
15
|
+
* - `issue` — Issue a new certification
|
|
16
|
+
* - `verify` — Verify a certification's validity
|
|
17
|
+
* - `getWithLineage` — Get a certification with its ancestor chain
|
|
18
|
+
* - `assess` — Compute assessment score against required competencies
|
|
19
|
+
* - `list` — List certifications by issuer or recipient
|
|
20
|
+
*/
|
|
21
|
+
import type { NamespaceProvider } from '../namespace-router.js';
|
|
22
|
+
/**
|
|
23
|
+
* Creates the `certification` namespace handler.
|
|
24
|
+
*
|
|
25
|
+
* All methods operate directly on Brainy entities and relationships.
|
|
26
|
+
* No external dependencies required — the knowledge graph IS the
|
|
27
|
+
* certification store.
|
|
28
|
+
*
|
|
29
|
+
* @returns A {@link NamespaceProvider} implementing {@link CertificationNamespace}.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createCertificationHandler(): NamespaceProvider;
|
|
32
|
+
//# sourceMappingURL=certification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certification.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/certification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,wBAAwB,CAAA;AAM/E;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,IAAI,iBAAiB,CAqQ9D"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/certification
|
|
3
|
+
* @description Certification namespace handler — issue, verify, and trace
|
|
4
|
+
* credential lineage using Brainy's graph model.
|
|
5
|
+
*
|
|
6
|
+
* Certifications are `Contract` entities linked by `endorses` (certifier → cert),
|
|
7
|
+
* `attributedTo` (cert → learner), and `dependsOn` (cert → upstream cert)
|
|
8
|
+
* relationships. This creates a verifiable lineage chain — the medieval guild
|
|
9
|
+
* model where every credential traces back to the authority that granted it.
|
|
10
|
+
*
|
|
11
|
+
* Originally built for Academy (course completion credentials). Now a platform
|
|
12
|
+
* primitive usable by Workshop, Venue, and kit apps.
|
|
13
|
+
*
|
|
14
|
+
* Methods:
|
|
15
|
+
* - `issue` — Issue a new certification
|
|
16
|
+
* - `verify` — Verify a certification's validity
|
|
17
|
+
* - `getWithLineage` — Get a certification with its ancestor chain
|
|
18
|
+
* - `assess` — Compute assessment score against required competencies
|
|
19
|
+
* - `list` — List certifications by issuer or recipient
|
|
20
|
+
*/
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
// Handler factory
|
|
23
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
/**
|
|
25
|
+
* Creates the `certification` namespace handler.
|
|
26
|
+
*
|
|
27
|
+
* All methods operate directly on Brainy entities and relationships.
|
|
28
|
+
* No external dependencies required — the knowledge graph IS the
|
|
29
|
+
* certification store.
|
|
30
|
+
*
|
|
31
|
+
* @returns A {@link NamespaceProvider} implementing {@link CertificationNamespace}.
|
|
32
|
+
*/
|
|
33
|
+
export function createCertificationHandler() {
|
|
34
|
+
return {
|
|
35
|
+
/**
|
|
36
|
+
* Issue a new certification.
|
|
37
|
+
*
|
|
38
|
+
* Creates a Contract entity with endorses/attributedTo/dependsOn edges.
|
|
39
|
+
*
|
|
40
|
+
* @param issueOptions - Certification details.
|
|
41
|
+
* @param ctx - Handler context with Brainy instance.
|
|
42
|
+
* @returns The created certification.
|
|
43
|
+
*/
|
|
44
|
+
async issue(issueOptions, ctx) {
|
|
45
|
+
const { brain } = ctx;
|
|
46
|
+
const now = new Date().toISOString();
|
|
47
|
+
// Create the certification entity
|
|
48
|
+
const certId = await brain.add({
|
|
49
|
+
type: 'contract',
|
|
50
|
+
data: issueOptions.name,
|
|
51
|
+
metadata: {
|
|
52
|
+
name: issueOptions.name,
|
|
53
|
+
certType: 'certification',
|
|
54
|
+
score: issueOptions.score,
|
|
55
|
+
aiIssued: issueOptions.aiIssued ?? false,
|
|
56
|
+
issuedAt: now,
|
|
57
|
+
issuedBy: ctx.user.id,
|
|
58
|
+
issuedTo: issueOptions.learnerId,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
// Create endorses relationship (certifier → cert)
|
|
62
|
+
await brain.relate({
|
|
63
|
+
from: ctx.user.id,
|
|
64
|
+
to: certId,
|
|
65
|
+
type: 'endorses',
|
|
66
|
+
}).catch(() => {
|
|
67
|
+
// User entity may not exist — non-fatal
|
|
68
|
+
});
|
|
69
|
+
// Create attributedTo relationship (cert → learner)
|
|
70
|
+
await brain.relate({
|
|
71
|
+
from: certId,
|
|
72
|
+
to: issueOptions.learnerId,
|
|
73
|
+
type: 'attributedTo',
|
|
74
|
+
}).catch(() => {
|
|
75
|
+
// Learner entity may not exist — non-fatal
|
|
76
|
+
});
|
|
77
|
+
// Create dependsOn relationship for lineage
|
|
78
|
+
if (issueOptions.upstreamCertificationId) {
|
|
79
|
+
await brain.relate({
|
|
80
|
+
from: certId,
|
|
81
|
+
to: issueOptions.upstreamCertificationId,
|
|
82
|
+
type: 'dependsOn',
|
|
83
|
+
}).catch(() => {
|
|
84
|
+
// Upstream cert may not exist — non-fatal
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
id: certId,
|
|
89
|
+
name: issueOptions.name,
|
|
90
|
+
score: issueOptions.score,
|
|
91
|
+
issuedAt: now,
|
|
92
|
+
certifierId: ctx.user.id,
|
|
93
|
+
learnerId: issueOptions.learnerId,
|
|
94
|
+
lineageDepth: issueOptions.upstreamCertificationId ? 1 : 0,
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
/**
|
|
98
|
+
* Verify a certification's validity.
|
|
99
|
+
*
|
|
100
|
+
* @param certificationId - The certification entity ID.
|
|
101
|
+
* @param ctx - Handler context.
|
|
102
|
+
* @returns Verification result.
|
|
103
|
+
*/
|
|
104
|
+
async verify(certificationId, ctx) {
|
|
105
|
+
const { brain } = ctx;
|
|
106
|
+
try {
|
|
107
|
+
const entity = await brain.get(certificationId);
|
|
108
|
+
if (!entity)
|
|
109
|
+
return { valid: false, certification: null };
|
|
110
|
+
const meta = entity.metadata || {};
|
|
111
|
+
if (meta.certType !== 'certification') {
|
|
112
|
+
return { valid: false, certification: null };
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
valid: true,
|
|
116
|
+
certification: {
|
|
117
|
+
id: entity.id,
|
|
118
|
+
name: meta.name || entity.data,
|
|
119
|
+
score: meta.score ?? 0,
|
|
120
|
+
issuedAt: meta.issuedAt || '',
|
|
121
|
+
certifierId: meta.issuedBy || '',
|
|
122
|
+
learnerId: meta.issuedTo || '',
|
|
123
|
+
lineageDepth: 0, // Computed in getWithLineage
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return { valid: false, certification: null };
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
/**
|
|
132
|
+
* Get a certification with its full lineage chain.
|
|
133
|
+
*
|
|
134
|
+
* @param certificationId - The certification entity ID.
|
|
135
|
+
* @param ctx - Handler context.
|
|
136
|
+
* @returns Certification and ancestor chain.
|
|
137
|
+
*/
|
|
138
|
+
async getWithLineage(certificationId, ctx) {
|
|
139
|
+
const { brain } = ctx;
|
|
140
|
+
const entity = await brain.get(certificationId);
|
|
141
|
+
if (!entity)
|
|
142
|
+
return { certification: null, lineage: [] };
|
|
143
|
+
const meta = entity.metadata || {};
|
|
144
|
+
const cert = {
|
|
145
|
+
id: entity.id,
|
|
146
|
+
name: meta.name || entity.data,
|
|
147
|
+
score: meta.score ?? 0,
|
|
148
|
+
issuedAt: meta.issuedAt || '',
|
|
149
|
+
certifierId: meta.issuedBy || '',
|
|
150
|
+
learnerId: meta.issuedTo || '',
|
|
151
|
+
lineageDepth: 0,
|
|
152
|
+
};
|
|
153
|
+
// Traverse dependsOn chain
|
|
154
|
+
const lineage = [];
|
|
155
|
+
let currentId = certificationId;
|
|
156
|
+
const visited = new Set();
|
|
157
|
+
const maxDepth = 20; // Prevent infinite loops
|
|
158
|
+
while (lineage.length < maxDepth) {
|
|
159
|
+
visited.add(currentId);
|
|
160
|
+
const outgoing = await brain.getRelations({ from: currentId }) || [];
|
|
161
|
+
const dependsOn = outgoing.find((r) => r.type.toLowerCase() === 'dependson' || r.type === 'DependsOn');
|
|
162
|
+
if (!dependsOn || visited.has(dependsOn.to))
|
|
163
|
+
break;
|
|
164
|
+
const upstream = await brain.get(dependsOn.to);
|
|
165
|
+
if (!upstream)
|
|
166
|
+
break;
|
|
167
|
+
const upMeta = upstream.metadata || {};
|
|
168
|
+
lineage.push({
|
|
169
|
+
id: upstream.id,
|
|
170
|
+
name: upMeta.name || upstream.data,
|
|
171
|
+
score: upMeta.score ?? 0,
|
|
172
|
+
issuedAt: upMeta.issuedAt || '',
|
|
173
|
+
certifierId: upMeta.issuedBy || '',
|
|
174
|
+
learnerId: upMeta.issuedTo || '',
|
|
175
|
+
lineageDepth: lineage.length + 1,
|
|
176
|
+
});
|
|
177
|
+
currentId = dependsOn.to;
|
|
178
|
+
}
|
|
179
|
+
cert.lineageDepth = lineage.length;
|
|
180
|
+
return { certification: cert, lineage };
|
|
181
|
+
},
|
|
182
|
+
/**
|
|
183
|
+
* Compute assessment score for a learner against required competencies.
|
|
184
|
+
*
|
|
185
|
+
* Score = demonstrated / total required. A competency is "demonstrated"
|
|
186
|
+
* if there's a `learns` edge from the learner to the competency entity.
|
|
187
|
+
*
|
|
188
|
+
* @param assessOptions - Assessment parameters.
|
|
189
|
+
* @param ctx - Handler context.
|
|
190
|
+
* @returns Assessment result with score, pass/fail, and gaps.
|
|
191
|
+
*/
|
|
192
|
+
async assess(assessOptions, ctx) {
|
|
193
|
+
const { brain } = ctx;
|
|
194
|
+
const threshold = assessOptions.threshold ?? 0.8;
|
|
195
|
+
// Get all "learns" edges from the learner
|
|
196
|
+
const outgoing = await brain.getRelations({ from: assessOptions.learnerId }) || [];
|
|
197
|
+
const demonstrated = new Set(outgoing
|
|
198
|
+
.filter((r) => r.type.toLowerCase() === 'learns')
|
|
199
|
+
.map((r) => r.to));
|
|
200
|
+
const total = assessOptions.competencyIds.length;
|
|
201
|
+
const met = assessOptions.competencyIds.filter(id => demonstrated.has(id));
|
|
202
|
+
const gaps = assessOptions.competencyIds.filter(id => !demonstrated.has(id));
|
|
203
|
+
const score = total > 0 ? met.length / total : 0;
|
|
204
|
+
return {
|
|
205
|
+
score,
|
|
206
|
+
passed: score >= threshold,
|
|
207
|
+
totalCompetencies: total,
|
|
208
|
+
demonstratedCount: met.length,
|
|
209
|
+
gaps,
|
|
210
|
+
};
|
|
211
|
+
},
|
|
212
|
+
/**
|
|
213
|
+
* List certifications issued by or to a user.
|
|
214
|
+
*
|
|
215
|
+
* @param listOptions - Filter options.
|
|
216
|
+
* @param ctx - Handler context.
|
|
217
|
+
* @returns Array of certifications.
|
|
218
|
+
*/
|
|
219
|
+
async list(listOptions, ctx) {
|
|
220
|
+
const { brain } = ctx;
|
|
221
|
+
const limit = listOptions?.limit ?? 50;
|
|
222
|
+
const results = await brain.find({
|
|
223
|
+
where: { type: 'contract' },
|
|
224
|
+
limit: limit * 2, // Over-fetch for filtering
|
|
225
|
+
});
|
|
226
|
+
return results
|
|
227
|
+
.filter((entity) => {
|
|
228
|
+
const meta = entity.metadata || {};
|
|
229
|
+
if (meta.certType !== 'certification')
|
|
230
|
+
return false;
|
|
231
|
+
if (listOptions?.issuedBy && meta.issuedBy !== listOptions.issuedBy)
|
|
232
|
+
return false;
|
|
233
|
+
if (listOptions?.issuedTo && meta.issuedTo !== listOptions.issuedTo)
|
|
234
|
+
return false;
|
|
235
|
+
return true;
|
|
236
|
+
})
|
|
237
|
+
.slice(0, limit)
|
|
238
|
+
.map((entity) => {
|
|
239
|
+
const meta = entity.metadata || {};
|
|
240
|
+
return {
|
|
241
|
+
id: entity.id,
|
|
242
|
+
name: meta.name || entity.data,
|
|
243
|
+
score: meta.score ?? 0,
|
|
244
|
+
issuedAt: meta.issuedAt || '',
|
|
245
|
+
certifierId: meta.issuedBy || '',
|
|
246
|
+
learnerId: meta.issuedTo || '',
|
|
247
|
+
lineageDepth: 0,
|
|
248
|
+
};
|
|
249
|
+
});
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=certification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certification.js","sourceRoot":"","sources":["../../../src/server/handlers/certification.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/chat/conversations
|
|
3
|
+
* @description Conversation and message CRUD operations using Brainy entities.
|
|
4
|
+
*
|
|
5
|
+
* Conversations are stored as `collection` entities with `_aiDataType: 'conversation'`.
|
|
6
|
+
* Messages are `message` entities linked to conversations via `contains` edges.
|
|
7
|
+
* Temporal ordering uses `precedes` edges between consecutive messages.
|
|
8
|
+
*
|
|
9
|
+
* All operations are universal — Workshop, Venue, Academy, and Pulse share
|
|
10
|
+
* the same conversation storage model.
|
|
11
|
+
*/
|
|
12
|
+
import type { Brainy } from '@soulcraft/brainy';
|
|
13
|
+
import type { ChatConversation, ChatConversationDetail } from '../../../namespaces.js';
|
|
14
|
+
import type { ChatEventEmitter } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Create a new conversation entity.
|
|
17
|
+
*
|
|
18
|
+
* @param brain - Brainy instance.
|
|
19
|
+
* @param userId - User who owns the conversation.
|
|
20
|
+
* @param title - Optional initial title.
|
|
21
|
+
* @returns The conversation ID.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createConversation(brain: Brainy, userId: string, title?: string): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* List all conversations for a user.
|
|
26
|
+
*
|
|
27
|
+
* @param brain - Brainy instance.
|
|
28
|
+
* @param userId - User to list conversations for.
|
|
29
|
+
* @returns Array of conversation summaries sorted by most recent first.
|
|
30
|
+
*/
|
|
31
|
+
export declare function listConversations(brain: Brainy, userId: string): Promise<ChatConversation[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Get a conversation with its full message history.
|
|
34
|
+
*
|
|
35
|
+
* @param brain - Brainy instance.
|
|
36
|
+
* @param conversationId - Conversation to retrieve.
|
|
37
|
+
* @returns Full conversation with messages, or null if not found.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getConversation(brain: Brainy, conversationId: string): Promise<ChatConversationDetail | null>;
|
|
40
|
+
/**
|
|
41
|
+
* Delete a conversation and all its messages (soft delete).
|
|
42
|
+
*
|
|
43
|
+
* @param brain - Brainy instance.
|
|
44
|
+
* @param conversationId - Conversation to delete.
|
|
45
|
+
*/
|
|
46
|
+
export declare function deleteConversation(brain: Brainy, conversationId: string): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Rename a conversation.
|
|
49
|
+
*
|
|
50
|
+
* @param brain - Brainy instance.
|
|
51
|
+
* @param conversationId - Conversation to rename.
|
|
52
|
+
* @param title - New title.
|
|
53
|
+
*/
|
|
54
|
+
export declare function renameConversation(brain: Brainy, conversationId: string, title: string): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Store a message in a conversation.
|
|
57
|
+
*
|
|
58
|
+
* Creates the message entity, links it to the conversation via `contains`,
|
|
59
|
+
* and establishes temporal ordering via `precedes`.
|
|
60
|
+
*
|
|
61
|
+
* @param brain - Brainy instance.
|
|
62
|
+
* @param conversationId - Conversation to add the message to.
|
|
63
|
+
* @param role - Message role ('user' or 'assistant').
|
|
64
|
+
* @param content - Message text content.
|
|
65
|
+
* @param events - Optional event emitter for real-time updates.
|
|
66
|
+
* @returns The message entity ID.
|
|
67
|
+
*/
|
|
68
|
+
export declare function storeMessage(brain: Brainy, conversationId: string, role: 'user' | 'assistant', content: string, events?: ChatEventEmitter): Promise<string>;
|
|
69
|
+
/**
|
|
70
|
+
* Load conversation history — recent messages in chronological order.
|
|
71
|
+
*
|
|
72
|
+
* @param brain - Brainy instance.
|
|
73
|
+
* @param conversationId - Conversation to load.
|
|
74
|
+
* @param limit - Maximum messages to return (most recent).
|
|
75
|
+
* @returns Array of role/content pairs.
|
|
76
|
+
*/
|
|
77
|
+
export declare function loadConversationHistory(brain: Brainy, conversationId: string, limit?: number): Promise<Array<{
|
|
78
|
+
role: string;
|
|
79
|
+
content: string;
|
|
80
|
+
}>>;
|
|
81
|
+
/**
|
|
82
|
+
* Auto-title a conversation from the first user message.
|
|
83
|
+
*
|
|
84
|
+
* Fire-and-forget — errors are logged but don't propagate.
|
|
85
|
+
*
|
|
86
|
+
* @param brain - Brainy instance.
|
|
87
|
+
* @param conversationId - Conversation to title.
|
|
88
|
+
* @param message - The first user message.
|
|
89
|
+
*/
|
|
90
|
+
export declare function autoTitleConversation(brain: Brainy, conversationId: string, message: string): Promise<void>;
|
|
91
|
+
//# sourceMappingURL=conversations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../../../src/server/handlers/chat/conversations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAe,MAAM,wBAAwB,CAAA;AACnG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAalD;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAiD7B;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CA2CxC;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CASf;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,GAAG,WAAW,EAC1B,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CAkFjB;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,EACtB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAyBnD;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAef"}
|