@soulcraft/sdk 1.0.0 → 1.2.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/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/auth/service-token.d.ts +62 -0
- package/dist/modules/auth/service-token.d.ts.map +1 -0
- package/dist/modules/auth/service-token.js +99 -0
- package/dist/modules/auth/service-token.js.map +1 -0
- package/dist/modules/billing/firestore-provider.d.ts +60 -0
- package/dist/modules/billing/firestore-provider.d.ts.map +1 -0
- package/dist/modules/billing/firestore-provider.js +314 -0
- package/dist/modules/billing/firestore-provider.js.map +1 -0
- package/dist/modules/billing/index.d.ts +58 -0
- package/dist/modules/billing/index.d.ts.map +1 -0
- package/dist/modules/billing/index.js +164 -0
- package/dist/modules/billing/index.js.map +1 -0
- package/dist/modules/billing/local-provider.d.ts +38 -0
- package/dist/modules/billing/local-provider.d.ts.map +1 -0
- package/dist/modules/billing/local-provider.js +242 -0
- package/dist/modules/billing/local-provider.js.map +1 -0
- package/dist/modules/billing/portal-provider.d.ts +70 -0
- package/dist/modules/billing/portal-provider.d.ts.map +1 -0
- package/dist/modules/billing/portal-provider.js +204 -0
- package/dist/modules/billing/portal-provider.js.map +1 -0
- package/dist/modules/billing/types.d.ts +323 -3
- package/dist/modules/billing/types.d.ts.map +1 -1
- package/dist/modules/billing/types.js +22 -2
- package/dist/modules/billing/types.js.map +1 -1
- package/dist/modules/billing/usage-buffer.d.ts +72 -0
- package/dist/modules/billing/usage-buffer.d.ts.map +1 -0
- package/dist/modules/billing/usage-buffer.js +141 -0
- package/dist/modules/billing/usage-buffer.js.map +1 -0
- package/dist/modules/formats/types.d.ts +65 -3
- package/dist/modules/formats/types.d.ts.map +1 -1
- package/dist/modules/formats/types.js +40 -3
- package/dist/modules/formats/types.js.map +1 -1
- package/dist/modules/formats/wdoc.d.ts +263 -0
- package/dist/modules/formats/wdoc.d.ts.map +1 -0
- package/dist/modules/formats/wdoc.js +21 -0
- package/dist/modules/formats/wdoc.js.map +1 -0
- package/dist/modules/formats/wquiz.d.ts +122 -0
- package/dist/modules/formats/wquiz.d.ts.map +1 -0
- package/dist/modules/formats/wquiz.js +23 -0
- package/dist/modules/formats/wquiz.js.map +1 -0
- package/dist/modules/formats/wslide.d.ts +130 -0
- package/dist/modules/formats/wslide.d.ts.map +1 -0
- package/dist/modules/formats/wslide.js +23 -0
- package/dist/modules/formats/wslide.js.map +1 -0
- package/dist/modules/formats/wviz.d.ts +114 -0
- package/dist/modules/formats/wviz.d.ts.map +1 -0
- package/dist/modules/formats/wviz.js +21 -0
- package/dist/modules/formats/wviz.js.map +1 -0
- package/dist/modules/hall/browser.d.ts +88 -0
- package/dist/modules/hall/browser.d.ts.map +1 -0
- package/dist/modules/hall/browser.js +265 -0
- package/dist/modules/hall/browser.js.map +1 -0
- package/dist/modules/hall/protocol.d.ts +39 -0
- package/dist/modules/hall/protocol.d.ts.map +1 -0
- package/dist/modules/hall/protocol.js +52 -0
- package/dist/modules/hall/protocol.js.map +1 -0
- package/dist/modules/hall/server.d.ts +172 -0
- package/dist/modules/hall/server.d.ts.map +1 -0
- package/dist/modules/hall/server.js +457 -0
- package/dist/modules/hall/server.js.map +1 -0
- package/dist/modules/hall/types.d.ts +502 -31
- package/dist/modules/hall/types.d.ts.map +1 -1
- package/dist/modules/hall/types.js +13 -8
- package/dist/modules/hall/types.js.map +1 -1
- package/dist/modules/kits/index.d.ts +41 -0
- package/dist/modules/kits/index.d.ts.map +1 -0
- package/dist/modules/kits/index.js +85 -0
- package/dist/modules/kits/index.js.map +1 -0
- package/dist/modules/kits/types.d.ts +107 -3
- package/dist/modules/kits/types.d.ts.map +1 -1
- package/dist/modules/kits/types.js +15 -2
- package/dist/modules/kits/types.js.map +1 -1
- package/dist/modules/license/index.d.ts +53 -0
- package/dist/modules/license/index.d.ts.map +1 -0
- package/dist/modules/license/index.js +233 -0
- package/dist/modules/license/index.js.map +1 -0
- package/dist/modules/license/types.d.ts +222 -3
- package/dist/modules/license/types.d.ts.map +1 -1
- package/dist/modules/license/types.js +21 -2
- package/dist/modules/license/types.js.map +1 -1
- package/dist/modules/notifications/index.d.ts +40 -0
- package/dist/modules/notifications/index.d.ts.map +1 -0
- package/dist/modules/notifications/index.js +280 -0
- package/dist/modules/notifications/index.js.map +1 -0
- package/dist/modules/notifications/types.d.ts +152 -3
- package/dist/modules/notifications/types.d.ts.map +1 -1
- package/dist/modules/notifications/types.js +21 -2
- package/dist/modules/notifications/types.js.map +1 -1
- package/dist/server/create-sdk.d.ts +4 -0
- package/dist/server/create-sdk.d.ts.map +1 -1
- package/dist/server/create-sdk.js +19 -26
- package/dist/server/create-sdk.js.map +1 -1
- package/dist/server/hall-handlers.d.ts +90 -151
- package/dist/server/hall-handlers.d.ts.map +1 -1
- package/dist/server/hall-handlers.js +84 -204
- package/dist/server/hall-handlers.js.map +1 -1
- package/dist/server/index.d.ts +10 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +9 -2
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +35 -25
- package/dist/types.d.ts.map +1 -1
- package/docs/USAGE.md +224 -1
- package/package.json +13 -5
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kits
|
|
3
|
+
* @description Factory for sdk.kits.* — the Soulcraft kit registry module.
|
|
4
|
+
*
|
|
5
|
+
* Provides read-only access to kit configurations from the `@soulcraft/kits`
|
|
6
|
+
* package. The package is an optional peer dependency loaded lazily via
|
|
7
|
+
* `createRequire` so that the SDK compiles and runs without it installed;
|
|
8
|
+
* calls gracefully return `null` / empty array when it is absent.
|
|
9
|
+
*
|
|
10
|
+
* The factory accepts an optional `bundledRegistry` override (used in tests)
|
|
11
|
+
* to inject a mock registry without needing the real package.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { createKitsModule } from '@soulcraft/sdk/server'
|
|
16
|
+
*
|
|
17
|
+
* const kits = createKitsModule()
|
|
18
|
+
* const kit = await kits.load('wicks-and-whiskers')
|
|
19
|
+
* console.log(kit?.name) // "Wicks & Whiskers"
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { createRequire } from 'node:module';
|
|
23
|
+
// createRequire enables CJS-style require() inside an ESM module — the only
|
|
24
|
+
// reliable way to conditionally load optional peer dependencies in Node/Bun ESM.
|
|
25
|
+
const _require = createRequire(import.meta.url);
|
|
26
|
+
// Module-level cache — loaded once per process, not per SDK instance.
|
|
27
|
+
let _registryCache = undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Load the kit registry from the installed `@soulcraft/kits` package.
|
|
30
|
+
* Returns `null` when the package is not installed, allowing callers to
|
|
31
|
+
* degrade gracefully rather than throwing.
|
|
32
|
+
*/
|
|
33
|
+
function _getBundledRegistry() {
|
|
34
|
+
if (_registryCache !== undefined)
|
|
35
|
+
return _registryCache;
|
|
36
|
+
try {
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
const kits = _require('@soulcraft/kits');
|
|
39
|
+
_registryCache = kits.kitRegistry ?? null;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
_registryCache = null;
|
|
43
|
+
}
|
|
44
|
+
return _registryCache;
|
|
45
|
+
}
|
|
46
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
47
|
+
// Factory
|
|
48
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* Create the `sdk.kits.*` module.
|
|
51
|
+
*
|
|
52
|
+
* @param options - Optional overrides, primarily for testing.
|
|
53
|
+
* @returns A `KitsModule` backed by the `@soulcraft/kits` registry.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* // In production:
|
|
58
|
+
* const kits = createKitsModule()
|
|
59
|
+
*
|
|
60
|
+
* // In tests — inject a mock registry to avoid the peer dep:
|
|
61
|
+
* const kits = createKitsModule({
|
|
62
|
+
* bundledRegistry: { 'test-kit': { id: 'test-kit', name: 'Test Kit', ... } }
|
|
63
|
+
* })
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function createKitsModule(options = {}) {
|
|
67
|
+
const getRegistry = options.bundledRegistry !== undefined
|
|
68
|
+
? () => options.bundledRegistry ?? null
|
|
69
|
+
: _getBundledRegistry;
|
|
70
|
+
return {
|
|
71
|
+
async load(kitId) {
|
|
72
|
+
const registry = getRegistry();
|
|
73
|
+
if (!registry)
|
|
74
|
+
return null;
|
|
75
|
+
return registry[kitId] ?? null;
|
|
76
|
+
},
|
|
77
|
+
async list() {
|
|
78
|
+
const registry = getRegistry();
|
|
79
|
+
if (!registry)
|
|
80
|
+
return [];
|
|
81
|
+
return Object.values(registry);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/kits/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAG3C,4EAA4E;AAC5E,iFAAiF;AACjF,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAE/C,sEAAsE;AACtE,IAAI,cAAc,GAA0D,SAAS,CAAA;AAErF;;;;GAIG;AACH,SAAS,mBAAmB;IAC1B,IAAI,cAAc,KAAK,SAAS;QAAE,OAAO,cAAc,CAAA;IACvD,IAAI,CAAC;QACH,8DAA8D;QAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,iBAAiB,CAAQ,CAAA;QAC/C,cAAc,GAAI,IAAI,CAAC,WAAkD,IAAI,IAAI,CAAA;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,cAAc,GAAG,IAAI,CAAA;IACvB,CAAC;IACD,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,gFAAgF;AAChF,UAAU;AACV,gFAAgF;AAEhF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAmC,EAAE;IACpE,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,KAAK,SAAS;QACvD,CAAC,CAAC,GAA8C,EAAE,CAAC,OAAO,CAAC,eAAe,IAAI,IAAI;QAClF,CAAC,CAAC,mBAAmB,CAAA;IAEvB,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,KAAa;YACtB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;YAC9B,IAAI,CAAC,QAAQ;gBAAE,OAAO,IAAI,CAAA;YAC1B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAA;QAChC,CAAC;QAED,KAAK,CAAC,IAAI;YACR,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;YAC9B,IAAI,CAAC,QAAQ;gBAAE,OAAO,EAAE,CAAA;YACxB,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAChC,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -1,7 +1,111 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module kits/types
|
|
3
|
-
* @description Type definitions for sdk.kits.*
|
|
4
|
-
*
|
|
3
|
+
* @description Type definitions for sdk.kits.* — the kit loader and registry module.
|
|
4
|
+
*
|
|
5
|
+
* Kits (`@soulcraft/kits`) are pure configuration packages: `kit.json` manifests
|
|
6
|
+
* and `SKILL.md` prompt files that describe a domain, persona, glossary, and
|
|
7
|
+
* workflow. They contain no TypeScript logic, no server code, and no SDK imports.
|
|
8
|
+
*
|
|
9
|
+
* The `KitsModule` provides read-only access to the kit registry: loading a single
|
|
10
|
+
* kit by ID, listing all available kits, and accessing the raw skill registry.
|
|
11
|
+
*
|
|
12
|
+
* Kit initialization (populating a workspace's Brainy and VFS from a kit's
|
|
13
|
+
* `starterFiles`) is a product-level concern and lives in each product's
|
|
14
|
+
* bootstrap code, not in the SDK.
|
|
15
|
+
*
|
|
16
|
+
* @see `@soulcraft/kit-schema` for the full kit manifest schema with product-specific fields.
|
|
17
|
+
* @see `sdk.skills.*` for loading SKILL.md prompt files.
|
|
5
18
|
*/
|
|
6
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Base fields shared by every Soulcraft kit manifest.
|
|
21
|
+
*
|
|
22
|
+
* This is a structural subset of `BaseKitManifest` from `@soulcraft/kit-schema`.
|
|
23
|
+
* The SDK uses this minimal type to avoid a hard dependency on the schema package.
|
|
24
|
+
* Product-specific fields (venue config, workshop config, etc.) are accessible
|
|
25
|
+
* via type assertion against the full `@soulcraft/kit-schema` types if needed.
|
|
26
|
+
*/
|
|
27
|
+
export interface SoulcraftKitConfig {
|
|
28
|
+
/** Unique kit identifier, used as the registry key (e.g. `'wicks-and-whiskers'`). */
|
|
29
|
+
id: string;
|
|
30
|
+
/** Display name of the kit. */
|
|
31
|
+
name: string;
|
|
32
|
+
/** One-sentence description of what this kit is for. */
|
|
33
|
+
description: string;
|
|
34
|
+
/** Semantic version string (e.g. `'1.0.0'`). */
|
|
35
|
+
version: string;
|
|
36
|
+
/** Kit type discriminant. */
|
|
37
|
+
type: 'venue' | 'content' | 'app' | 'academy' | 'soulcraft';
|
|
38
|
+
/** Shared cross-product configuration. */
|
|
39
|
+
shared?: {
|
|
40
|
+
/** AI persona system prompt. */
|
|
41
|
+
aiPersona?: string;
|
|
42
|
+
/** Suggestion chips for AI chat interfaces. */
|
|
43
|
+
suggestions?: Array<{
|
|
44
|
+
label: string;
|
|
45
|
+
prompt: string;
|
|
46
|
+
}>;
|
|
47
|
+
};
|
|
48
|
+
/** Additional product-specific fields are permitted. */
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Options passed to `createKitsModule()` to override the bundled registry.
|
|
53
|
+
* Primarily useful in tests.
|
|
54
|
+
*/
|
|
55
|
+
export interface CreateKitsModuleOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Override the kit registry loaded from `@soulcraft/kits`.
|
|
58
|
+
* When provided, the module uses this registry directly instead of requiring
|
|
59
|
+
* the package. Set to `null` to simulate the package being absent.
|
|
60
|
+
*/
|
|
61
|
+
bundledRegistry?: Record<string, SoulcraftKitConfig> | null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The `sdk.kits.*` namespace — read-only access to the Soulcraft kit registry.
|
|
65
|
+
*
|
|
66
|
+
* Backed by the `@soulcraft/kits` package (a peer dependency). If the package
|
|
67
|
+
* is not installed, `load()` returns `null` and `list()` returns an empty array.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const kit = await sdk.kits.load('wicks-and-whiskers')
|
|
72
|
+
* if (kit) {
|
|
73
|
+
* const response = await sdk.ai.complete({
|
|
74
|
+
* messages: [{ role: 'user', content: 'What candles are low in stock?' }],
|
|
75
|
+
* systemPrompt: kit.shared?.aiPersona,
|
|
76
|
+
* })
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export interface KitsModule {
|
|
81
|
+
/**
|
|
82
|
+
* Load a single kit configuration by ID.
|
|
83
|
+
*
|
|
84
|
+
* Returns `null` if the kit is not found or `@soulcraft/kits` is not installed.
|
|
85
|
+
*
|
|
86
|
+
* @param kitId - The kit identifier (e.g. `'wicks-and-whiskers'`).
|
|
87
|
+
* @returns The kit configuration, or `null` if not found.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const kit = await sdk.kits.load('wicks-and-whiskers')
|
|
92
|
+
* console.log(kit?.name) // → "Wicks & Whiskers"
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
load(kitId: string): Promise<SoulcraftKitConfig | null>;
|
|
96
|
+
/**
|
|
97
|
+
* List all available kits from the registry.
|
|
98
|
+
*
|
|
99
|
+
* Returns an empty array if `@soulcraft/kits` is not installed.
|
|
100
|
+
*
|
|
101
|
+
* @returns All kit configurations as an array.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const kits = await sdk.kits.list()
|
|
106
|
+
* console.log(kits.map(k => k.name))
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
list(): Promise<SoulcraftKitConfig[]>;
|
|
110
|
+
}
|
|
7
111
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/modules/kits/types.ts"],"names":[],"mappings":"AAAA;;;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/modules/kits/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,qFAAqF;IACrF,EAAE,EAAE,MAAM,CAAA;IACV,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAA;IACnB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAA;IACf,6BAA6B;IAC7B,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,CAAA;IAC3D,0CAA0C;IAC1C,MAAM,CAAC,EAAE;QACP,gCAAgC;QAChC,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,+CAA+C;QAC/C,WAAW,CAAC,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KACvD,CAAA;IACD,wDAAwD;IACxD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAMD;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAAA;CAC5D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAA;IAEvD;;;;;;;;;;;;OAYG;IACH,IAAI,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAA;CACtC"}
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module kits/types
|
|
3
|
-
* @description Type definitions for sdk.kits.*
|
|
4
|
-
*
|
|
3
|
+
* @description Type definitions for sdk.kits.* — the kit loader and registry module.
|
|
4
|
+
*
|
|
5
|
+
* Kits (`@soulcraft/kits`) are pure configuration packages: `kit.json` manifests
|
|
6
|
+
* and `SKILL.md` prompt files that describe a domain, persona, glossary, and
|
|
7
|
+
* workflow. They contain no TypeScript logic, no server code, and no SDK imports.
|
|
8
|
+
*
|
|
9
|
+
* The `KitsModule` provides read-only access to the kit registry: loading a single
|
|
10
|
+
* kit by ID, listing all available kits, and accessing the raw skill registry.
|
|
11
|
+
*
|
|
12
|
+
* Kit initialization (populating a workspace's Brainy and VFS from a kit's
|
|
13
|
+
* `starterFiles`) is a product-level concern and lives in each product's
|
|
14
|
+
* bootstrap code, not in the SDK.
|
|
15
|
+
*
|
|
16
|
+
* @see `@soulcraft/kit-schema` for the full kit manifest schema with product-specific fields.
|
|
17
|
+
* @see `sdk.skills.*` for loading SKILL.md prompt files.
|
|
5
18
|
*/
|
|
6
19
|
export {};
|
|
7
20
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/modules/kits/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/modules/kits/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module license
|
|
3
|
+
* @description Factory for sdk.license.* — license validation, AI credit management,
|
|
4
|
+
* and BYOK API key support.
|
|
5
|
+
*
|
|
6
|
+
* Validates the product license against the Portal license server. Initialization
|
|
7
|
+
* is lazy: the first call to `validate()` performs an online check against
|
|
8
|
+
* `portal.soulcraft.com` and starts the background heartbeat.
|
|
9
|
+
*
|
|
10
|
+
* License state is read from the `SOULCRAFT_LICENSE_KEY` environment variable
|
|
11
|
+
* or a `.soulcraft.json` file in the working directory. On free-tier deployments
|
|
12
|
+
* (no key configured), `validate()` returns `{ valid: false, tier: 'free' }` and
|
|
13
|
+
* all AI credit limits apply.
|
|
14
|
+
*
|
|
15
|
+
* **AI credit metering** delegates to the `sdk.billing.*` module for storage and
|
|
16
|
+
* period management. The license module provides the gate check and credit recording
|
|
17
|
+
* interface; billing handles persistence.
|
|
18
|
+
*
|
|
19
|
+
* **BYOK users** always bypass credit metering — they provide their own Anthropic key
|
|
20
|
+
* and are not subject to monthly limits.
|
|
21
|
+
*
|
|
22
|
+
* @example Server startup
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Force immediate license check and start heartbeat:
|
|
25
|
+
* sdk.license.startHeartbeat()
|
|
26
|
+
* const result = await sdk.license.validate(true)
|
|
27
|
+
* if (!result.valid) console.warn('[SDK] No active license — running in free tier')
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import type { LicenseModule } from './types.js';
|
|
31
|
+
import type { BillingModule } from '../billing/types.js';
|
|
32
|
+
/** Options for `createLicenseModule()`. */
|
|
33
|
+
export interface CreateLicenseModuleOptions {
|
|
34
|
+
/**
|
|
35
|
+
* The billing module instance, used for AI credit metering.
|
|
36
|
+
* When not provided, credit checks assume unlimited (no billing gate).
|
|
37
|
+
*/
|
|
38
|
+
billing?: BillingModule;
|
|
39
|
+
/**
|
|
40
|
+
* Register a user's BYOK Anthropic API key.
|
|
41
|
+
* The license module uses this to short-circuit credit checks for BYOK users.
|
|
42
|
+
*/
|
|
43
|
+
byokKeys?: Map<string, string>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create the `sdk.license.*` module.
|
|
47
|
+
*
|
|
48
|
+
* @param options - Optional billing module and BYOK key overrides.
|
|
49
|
+
* @returns A fully configured `LicenseModule`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function createLicenseModule(options?: CreateLicenseModuleOptions): LicenseModule;
|
|
52
|
+
export type { LicenseResult, LicensePlanTier, LicenseFeatures, AICreditCheckResult, AIUsageRecord, AIProviderConfig, LicenseModule, } from './types.js';
|
|
53
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/license/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EACV,aAAa,EAMd,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAqDxD,2CAA2C;AAC3C,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,0BAA+B,GAAG,aAAa,CAqK3F;AAGD,YAAY,EACV,aAAa,EACb,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module license
|
|
3
|
+
* @description Factory for sdk.license.* — license validation, AI credit management,
|
|
4
|
+
* and BYOK API key support.
|
|
5
|
+
*
|
|
6
|
+
* Validates the product license against the Portal license server. Initialization
|
|
7
|
+
* is lazy: the first call to `validate()` performs an online check against
|
|
8
|
+
* `portal.soulcraft.com` and starts the background heartbeat.
|
|
9
|
+
*
|
|
10
|
+
* License state is read from the `SOULCRAFT_LICENSE_KEY` environment variable
|
|
11
|
+
* or a `.soulcraft.json` file in the working directory. On free-tier deployments
|
|
12
|
+
* (no key configured), `validate()` returns `{ valid: false, tier: 'free' }` and
|
|
13
|
+
* all AI credit limits apply.
|
|
14
|
+
*
|
|
15
|
+
* **AI credit metering** delegates to the `sdk.billing.*` module for storage and
|
|
16
|
+
* period management. The license module provides the gate check and credit recording
|
|
17
|
+
* interface; billing handles persistence.
|
|
18
|
+
*
|
|
19
|
+
* **BYOK users** always bypass credit metering — they provide their own Anthropic key
|
|
20
|
+
* and are not subject to monthly limits.
|
|
21
|
+
*
|
|
22
|
+
* @example Server startup
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Force immediate license check and start heartbeat:
|
|
25
|
+
* sdk.license.startHeartbeat()
|
|
26
|
+
* const result = await sdk.license.validate(true)
|
|
27
|
+
* if (!result.valid) console.warn('[SDK] No active license — running in free tier')
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
31
|
+
// Portal license API
|
|
32
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
33
|
+
/** Default heartbeat interval: 4 hours. */
|
|
34
|
+
const DEFAULT_CHECK_INTERVAL_MS = 4 * 60 * 60 * 1000;
|
|
35
|
+
/** Portal license validation endpoint. */
|
|
36
|
+
const PORTAL_LICENSE_URL = 'https://portal.soulcraft.com/api/license/validate';
|
|
37
|
+
/**
|
|
38
|
+
* Validate the license key against Portal.
|
|
39
|
+
* Reads `SOULCRAFT_LICENSE_KEY` from the environment.
|
|
40
|
+
* Returns a free-tier result when no key is configured.
|
|
41
|
+
*/
|
|
42
|
+
async function _validateWithPortal() {
|
|
43
|
+
const key = process.env['SOULCRAFT_LICENSE_KEY'];
|
|
44
|
+
if (!key) {
|
|
45
|
+
return { valid: false, tier: 'free', reason: 'No license key configured (SOULCRAFT_LICENSE_KEY)' };
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch(PORTAL_LICENSE_URL, {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: { 'Content-Type': 'application/json' },
|
|
51
|
+
body: JSON.stringify({ key }),
|
|
52
|
+
signal: AbortSignal.timeout(10_000),
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
return { valid: false, tier: 'free', reason: `Portal responded ${response.status}` };
|
|
56
|
+
}
|
|
57
|
+
return (await response.json());
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Network failure — degrade gracefully. The cached result (if any) remains valid.
|
|
61
|
+
return { valid: false, tier: 'free', reason: 'License check failed (network error)' };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
65
|
+
// BYOK key storage (in-process, keyed by userId)
|
|
66
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
67
|
+
// BYOK keys are stored in memory only — they are never written to disk by the
|
|
68
|
+
// SDK. Products are responsible for persisting them (e.g. encrypted in Firestore
|
|
69
|
+
// or a user settings document). The license module reads them via getAIProvider()
|
|
70
|
+
// which is overridable per-user via the byokStore.
|
|
71
|
+
const _byokStore = new Map();
|
|
72
|
+
/**
|
|
73
|
+
* Create the `sdk.license.*` module.
|
|
74
|
+
*
|
|
75
|
+
* @param options - Optional billing module and BYOK key overrides.
|
|
76
|
+
* @returns A fully configured `LicenseModule`.
|
|
77
|
+
*/
|
|
78
|
+
export function createLicenseModule(options = {}) {
|
|
79
|
+
const billing = options.billing;
|
|
80
|
+
const byokStore = options.byokKeys ?? _byokStore;
|
|
81
|
+
// Cached validation result — refreshed by heartbeat or explicit forceRefresh.
|
|
82
|
+
let _cachedResult;
|
|
83
|
+
// Whether the heartbeat interval is running.
|
|
84
|
+
let _heartbeatTimer;
|
|
85
|
+
// Pending init promise — deduplicates concurrent first-call races.
|
|
86
|
+
let _initPromise;
|
|
87
|
+
// ── Internal helpers ──────────────────────────────────────────────────────
|
|
88
|
+
async function _init() {
|
|
89
|
+
if (_initPromise)
|
|
90
|
+
return _initPromise;
|
|
91
|
+
_initPromise = (async () => {
|
|
92
|
+
const result = await _validateWithPortal();
|
|
93
|
+
_cachedResult = result;
|
|
94
|
+
// Start background heartbeat after first successful init.
|
|
95
|
+
if (!_heartbeatTimer) {
|
|
96
|
+
_startHeartbeat(DEFAULT_CHECK_INTERVAL_MS);
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
})();
|
|
100
|
+
return _initPromise;
|
|
101
|
+
}
|
|
102
|
+
async function _refreshHeartbeat() {
|
|
103
|
+
try {
|
|
104
|
+
const result = await _validateWithPortal();
|
|
105
|
+
_cachedResult = result;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Heartbeat failures are non-fatal — the cached result remains valid.
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function _startHeartbeat(intervalMs) {
|
|
112
|
+
if (_heartbeatTimer)
|
|
113
|
+
clearInterval(_heartbeatTimer);
|
|
114
|
+
_heartbeatTimer = setInterval(() => {
|
|
115
|
+
void _refreshHeartbeat();
|
|
116
|
+
}, intervalMs);
|
|
117
|
+
// Allow the process to exit normally even if the heartbeat is running.
|
|
118
|
+
if (_heartbeatTimer.unref)
|
|
119
|
+
_heartbeatTimer.unref();
|
|
120
|
+
}
|
|
121
|
+
function _tierToFeatures(tier) {
|
|
122
|
+
switch (tier) {
|
|
123
|
+
case 'enterprise':
|
|
124
|
+
case 'internal':
|
|
125
|
+
return { cortex: true, ai: { monthlyCredits: null } };
|
|
126
|
+
case 'pro':
|
|
127
|
+
return { cortex: true, ai: { monthlyCredits: 1000 } };
|
|
128
|
+
case 'free':
|
|
129
|
+
default:
|
|
130
|
+
return { cortex: false, ai: { monthlyCredits: 100 } };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// ── Public API ────────────────────────────────────────────────────────────
|
|
134
|
+
return {
|
|
135
|
+
async validate(forceRefresh = false) {
|
|
136
|
+
if (forceRefresh || !_cachedResult) {
|
|
137
|
+
_initPromise = undefined; // Allow re-init on force refresh.
|
|
138
|
+
return _init();
|
|
139
|
+
}
|
|
140
|
+
return _cachedResult;
|
|
141
|
+
},
|
|
142
|
+
async isActive() {
|
|
143
|
+
const result = await _init();
|
|
144
|
+
return result.valid;
|
|
145
|
+
},
|
|
146
|
+
async plan() {
|
|
147
|
+
const result = await _init();
|
|
148
|
+
if (!result.valid)
|
|
149
|
+
return 'free';
|
|
150
|
+
return result.tier;
|
|
151
|
+
},
|
|
152
|
+
async features() {
|
|
153
|
+
const tier = await this.plan();
|
|
154
|
+
return _tierToFeatures(tier);
|
|
155
|
+
},
|
|
156
|
+
async checkAICredits(userId) {
|
|
157
|
+
// BYOK users bypass all credit metering.
|
|
158
|
+
if (byokStore.has(userId)) {
|
|
159
|
+
return { ok: true, remaining: null, isByok: true };
|
|
160
|
+
}
|
|
161
|
+
// If no billing module, assume unlimited (dev/free tier).
|
|
162
|
+
if (!billing) {
|
|
163
|
+
const active = await this.isActive();
|
|
164
|
+
if (!active) {
|
|
165
|
+
return { ok: false, remaining: null, isByok: false, reason: 'license_inactive' };
|
|
166
|
+
}
|
|
167
|
+
return { ok: true, remaining: null, isByok: false };
|
|
168
|
+
}
|
|
169
|
+
const check = await billing.checkLimit(userId, false);
|
|
170
|
+
if (!check.ok) {
|
|
171
|
+
return { ok: false, remaining: check.remaining, isByok: false, reason: 'limit_reached' };
|
|
172
|
+
}
|
|
173
|
+
return { ok: true, remaining: check.remaining, isByok: false };
|
|
174
|
+
},
|
|
175
|
+
consumeAICredit(userId, usage) {
|
|
176
|
+
// BYOK users are not metered.
|
|
177
|
+
if (byokStore.has(userId))
|
|
178
|
+
return;
|
|
179
|
+
if (!billing)
|
|
180
|
+
return;
|
|
181
|
+
// Fire-and-forget — billing buffers and flushes asynchronously.
|
|
182
|
+
void billing.recordUsage(userId, usage.inputTokens, usage.outputTokens, usage.model);
|
|
183
|
+
},
|
|
184
|
+
async validateBYOK(apiKey) {
|
|
185
|
+
// Validate by attempting a minimal Anthropic API call (count_tokens endpoint
|
|
186
|
+
// is cheaper than a full completion).
|
|
187
|
+
try {
|
|
188
|
+
const response = await fetch('https://api.anthropic.com/v1/messages/count_tokens', {
|
|
189
|
+
method: 'POST',
|
|
190
|
+
headers: {
|
|
191
|
+
'x-api-key': apiKey,
|
|
192
|
+
'anthropic-version': '2023-06-01',
|
|
193
|
+
'content-type': 'application/json',
|
|
194
|
+
},
|
|
195
|
+
body: JSON.stringify({
|
|
196
|
+
model: 'claude-haiku-4-5-20251001',
|
|
197
|
+
messages: [{ role: 'user', content: 'hi' }],
|
|
198
|
+
}),
|
|
199
|
+
});
|
|
200
|
+
// 200 = valid key, 401 = invalid key, other = network/service error
|
|
201
|
+
return response.status === 200;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
async getAIProvider(userId) {
|
|
208
|
+
const byokKey = byokStore.get(userId);
|
|
209
|
+
if (byokKey) {
|
|
210
|
+
return { apiKey: byokKey, source: 'byok' };
|
|
211
|
+
}
|
|
212
|
+
const platformKey = process.env['ANTHROPIC_API_KEY'];
|
|
213
|
+
if (!platformKey) {
|
|
214
|
+
throw new Error('No Anthropic API key available. Set ANTHROPIC_API_KEY in the environment ' +
|
|
215
|
+
'or provide a BYOK key for this user via sdk.license.');
|
|
216
|
+
}
|
|
217
|
+
return { apiKey: platformKey, source: 'platform' };
|
|
218
|
+
},
|
|
219
|
+
startHeartbeat(intervalMs) {
|
|
220
|
+
const interval = intervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
|
|
221
|
+
_startHeartbeat(interval);
|
|
222
|
+
// Force an immediate online check on explicit startHeartbeat() call.
|
|
223
|
+
void _refreshHeartbeat();
|
|
224
|
+
},
|
|
225
|
+
stopHeartbeat() {
|
|
226
|
+
if (_heartbeatTimer) {
|
|
227
|
+
clearInterval(_heartbeatTimer);
|
|
228
|
+
_heartbeatTimer = undefined;
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/license/index.ts"],"names":[],"mappings":"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"}
|