@qwickapps/server 1.5.1 → 1.5.2
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/CHANGELOG.md +21 -0
- package/dist/core/control-panel.d.ts.map +1 -1
- package/dist/core/control-panel.js +41 -0
- package/dist/core/control-panel.js.map +1 -1
- package/dist/core/guards.d.ts.map +1 -1
- package/dist/core/guards.js +77 -0
- package/dist/core/guards.js.map +1 -1
- package/dist/core/health-manager.d.ts +4 -0
- package/dist/core/health-manager.d.ts.map +1 -1
- package/dist/core/health-manager.js +6 -1
- package/dist/core/health-manager.js.map +1 -1
- package/dist/core/plugin-registry.d.ts +55 -5
- package/dist/core/plugin-registry.d.ts.map +1 -1
- package/dist/core/plugin-registry.js +57 -19
- package/dist/core/plugin-registry.js.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/auth/auth-plugin.d.ts.map +1 -1
- package/dist/plugins/auth/auth-plugin.js +16 -0
- package/dist/plugins/auth/auth-plugin.js.map +1 -1
- package/dist/plugins/auth/auth-plugin.test.js +133 -0
- package/dist/plugins/auth/auth-plugin.test.js.map +1 -1
- package/dist/plugins/auth/env-config.d.ts.map +1 -1
- package/dist/plugins/auth/env-config.js +4 -0
- package/dist/plugins/auth/env-config.js.map +1 -1
- package/dist/plugins/auth/types.d.ts +10 -0
- package/dist/plugins/auth/types.d.ts.map +1 -1
- package/dist/plugins/auth/types.js.map +1 -1
- package/dist/plugins/devices/__tests__/token-utils.test.js +4 -2
- package/dist/plugins/devices/__tests__/token-utils.test.js.map +1 -1
- package/dist/plugins/frontend-app-plugin.d.ts.map +1 -1
- package/dist/plugins/frontend-app-plugin.js +18 -4
- package/dist/plugins/frontend-app-plugin.js.map +1 -1
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +2 -0
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/qwickbrain/index.d.ts +25 -0
- package/dist/plugins/qwickbrain/index.d.ts.map +1 -0
- package/dist/plugins/qwickbrain/index.js +24 -0
- package/dist/plugins/qwickbrain/index.js.map +1 -0
- package/dist/plugins/qwickbrain/qwickbrain-plugin.d.ts +23 -0
- package/dist/plugins/qwickbrain/qwickbrain-plugin.d.ts.map +1 -0
- package/dist/plugins/qwickbrain/qwickbrain-plugin.js +528 -0
- package/dist/plugins/qwickbrain/qwickbrain-plugin.js.map +1 -0
- package/dist/plugins/qwickbrain/types.d.ts +131 -0
- package/dist/plugins/qwickbrain/types.d.ts.map +1 -0
- package/dist/plugins/qwickbrain/types.js +9 -0
- package/dist/plugins/qwickbrain/types.js.map +1 -0
- package/dist-ui/assets/{index-CynOqPkb.js → index-BfC7mG5L.js} +2 -2
- package/dist-ui/assets/{index-CynOqPkb.js.map → index-BfC7mG5L.js.map} +1 -1
- package/dist-ui/index.html +1 -1
- package/dist-ui-lib/api/controlPanelApi.d.ts +6 -0
- package/dist-ui-lib/index.js +277 -266
- package/dist-ui-lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/control-panel.ts +47 -0
- package/src/core/guards.ts +89 -0
- package/src/core/health-manager.ts +6 -1
- package/src/core/plugin-registry.ts +123 -25
- package/src/core/types.ts +2 -0
- package/src/index.ts +11 -0
- package/src/plugins/auth/auth-plugin.test.ts +167 -0
- package/src/plugins/auth/auth-plugin.ts +16 -0
- package/src/plugins/auth/env-config.ts +4 -0
- package/src/plugins/auth/types.ts +10 -0
- package/src/plugins/devices/__tests__/token-utils.test.ts +4 -2
- package/src/plugins/frontend-app-plugin.ts +19 -4
- package/src/plugins/index.ts +15 -0
- package/src/plugins/qwickbrain/index.ts +33 -0
- package/src/plugins/qwickbrain/qwickbrain-plugin.ts +642 -0
- package/src/plugins/qwickbrain/types.ts +146 -0
- package/ui/src/api/controlPanelApi.ts +49 -37
|
@@ -403,6 +403,7 @@ export function createAuthPluginFromEnv(options?: AuthEnvPluginOptions): Plugin
|
|
|
403
403
|
authRequired,
|
|
404
404
|
debug,
|
|
405
405
|
onUnauthorized: options?.onUnauthorized,
|
|
406
|
+
onAuthenticated: options?.onAuthenticated,
|
|
406
407
|
};
|
|
407
408
|
|
|
408
409
|
// Update status
|
|
@@ -418,6 +419,7 @@ export function createAuthPluginFromEnv(options?: AuthEnvPluginOptions): Plugin
|
|
|
418
419
|
// Wrap to add config status routes
|
|
419
420
|
return {
|
|
420
421
|
...basePlugin,
|
|
422
|
+
type: 'system' as const, // Explicit system type (auth can handle any path)
|
|
421
423
|
async onStart(pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
|
|
422
424
|
// Call base plugin onStart
|
|
423
425
|
await basePlugin.onStart?.(pluginConfig, registry);
|
|
@@ -825,6 +827,7 @@ function createDisabledPlugin(): Plugin {
|
|
|
825
827
|
id: 'auth',
|
|
826
828
|
name: 'Auth Plugin (Disabled)',
|
|
827
829
|
version: '1.0.0',
|
|
830
|
+
type: 'system' as const,
|
|
828
831
|
|
|
829
832
|
async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
|
|
830
833
|
const logger = registry.getLogger('auth');
|
|
@@ -848,6 +851,7 @@ function createErrorPlugin(error: string): Plugin {
|
|
|
848
851
|
id: 'auth',
|
|
849
852
|
name: 'Auth Plugin (Error)',
|
|
850
853
|
version: '1.0.0',
|
|
854
|
+
type: 'system' as const,
|
|
851
855
|
|
|
852
856
|
async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
|
|
853
857
|
const logger = registry.getLogger('auth');
|
|
@@ -182,6 +182,11 @@ export interface AuthPluginConfig {
|
|
|
182
182
|
authRequired?: boolean;
|
|
183
183
|
/** Custom unauthorized handler */
|
|
184
184
|
onUnauthorized?: (req: Request, res: Response) => void;
|
|
185
|
+
/**
|
|
186
|
+
* Callback invoked after successful authentication.
|
|
187
|
+
* Use this to sync users to a local database on first login.
|
|
188
|
+
*/
|
|
189
|
+
onAuthenticated?: (user: AuthenticatedUser) => Promise<void>;
|
|
185
190
|
/** Enable debug logging */
|
|
186
191
|
debug?: boolean;
|
|
187
192
|
}
|
|
@@ -226,6 +231,11 @@ export interface AuthEnvPluginOptions {
|
|
|
226
231
|
debug?: boolean;
|
|
227
232
|
/** Custom unauthorized handler */
|
|
228
233
|
onUnauthorized?: (req: Request, res: Response) => void;
|
|
234
|
+
/**
|
|
235
|
+
* Callback invoked after successful authentication.
|
|
236
|
+
* Use this to sync users to a local database on first login.
|
|
237
|
+
*/
|
|
238
|
+
onAuthenticated?: (user: AuthenticatedUser) => Promise<void>;
|
|
229
239
|
}
|
|
230
240
|
|
|
231
241
|
/**
|
|
@@ -24,13 +24,15 @@ describe('Token Utilities', () => {
|
|
|
24
24
|
|
|
25
25
|
it('should generate a 43-character secret after prefix', async () => {
|
|
26
26
|
const result = await generateDeviceToken('mob');
|
|
27
|
-
|
|
27
|
+
// Use slice to get everything after 'mob_' since base64url can contain '_'
|
|
28
|
+
const secret = result.token.slice(4); // 'mob_'.length = 4
|
|
28
29
|
expect(secret.length).toBe(43);
|
|
29
30
|
});
|
|
30
31
|
|
|
31
32
|
it('should generate base64url-safe characters', async () => {
|
|
32
33
|
const result = await generateDeviceToken('test');
|
|
33
|
-
|
|
34
|
+
// Use slice to get everything after 'test_' since base64url can contain '_'
|
|
35
|
+
const secret = result.token.slice(5); // 'test_'.length = 5
|
|
34
36
|
expect(secret).toMatch(/^[A-Za-z0-9_-]+$/);
|
|
35
37
|
});
|
|
36
38
|
|
|
@@ -50,6 +50,7 @@ export function createFrontendAppPlugin(config: FrontendAppPluginConfig): Plugin
|
|
|
50
50
|
id: 'frontend-app',
|
|
51
51
|
name: 'Frontend App Plugin',
|
|
52
52
|
version: '1.0.0',
|
|
53
|
+
type: 'system' as const,
|
|
53
54
|
|
|
54
55
|
async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
|
|
55
56
|
const logger = registry.getLogger('frontend-app');
|
|
@@ -80,11 +81,25 @@ export function createFrontendAppPlugin(config: FrontendAppPluginConfig): Plugin
|
|
|
80
81
|
// Priority 2: Serve static files
|
|
81
82
|
if (config.staticPath && existsSync(config.staticPath)) {
|
|
82
83
|
logger.info(`Frontend app: Serving static files from ${config.staticPath}`);
|
|
83
|
-
app.use('/', express.static(config.staticPath));
|
|
84
84
|
|
|
85
|
-
//
|
|
86
|
-
app.
|
|
87
|
-
|
|
85
|
+
// Serve static assets first
|
|
86
|
+
app.use(express.static(config.staticPath, { index: false }));
|
|
87
|
+
|
|
88
|
+
// SPA fallback for all non-API routes
|
|
89
|
+
// This must be registered after static files but handles routes that don't match files
|
|
90
|
+
app.get('*', (req, res, next) => {
|
|
91
|
+
// Skip API routes and control panel
|
|
92
|
+
if (req.path.startsWith('/api') || req.path.startsWith(config.mountPath || '/cpanel')) {
|
|
93
|
+
return next();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Serve index.html for all other routes (SPA routing)
|
|
97
|
+
const indexPath = resolve(config.staticPath!, 'index.html');
|
|
98
|
+
if (existsSync(indexPath)) {
|
|
99
|
+
res.sendFile(indexPath);
|
|
100
|
+
} else {
|
|
101
|
+
next();
|
|
102
|
+
}
|
|
88
103
|
});
|
|
89
104
|
return;
|
|
90
105
|
}
|
package/src/plugins/index.ts
CHANGED
|
@@ -423,3 +423,18 @@ export type {
|
|
|
423
423
|
ConnectionHealth,
|
|
424
424
|
NotificationsManagerInterface,
|
|
425
425
|
} from './notifications/index.js';
|
|
426
|
+
|
|
427
|
+
// QwickBrain MCP plugin
|
|
428
|
+
export {
|
|
429
|
+
createQwickBrainPlugin,
|
|
430
|
+
getConnectionStatus,
|
|
431
|
+
isConnected,
|
|
432
|
+
} from './qwickbrain/index.js';
|
|
433
|
+
export type {
|
|
434
|
+
QwickBrainPluginConfig,
|
|
435
|
+
MCPToolDefinition,
|
|
436
|
+
MCPToolCallRequest,
|
|
437
|
+
MCPToolCallResponse,
|
|
438
|
+
QwickBrainConnectionStatus,
|
|
439
|
+
MCPRateLimitConfig,
|
|
440
|
+
} from './qwickbrain/index.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QwickBrain Plugin
|
|
3
|
+
*
|
|
4
|
+
* MCP proxy plugin for exposing QwickBrain tools to external AI clients.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { createControlPanel } from '@qwickapps/server';
|
|
9
|
+
* import { createQwickBrainPlugin } from '@qwickapps/server/plugins';
|
|
10
|
+
*
|
|
11
|
+
* const panel = await createControlPanel({
|
|
12
|
+
* plugins: [
|
|
13
|
+
* createQwickBrainPlugin({
|
|
14
|
+
* qwickbrainUrl: 'http://macmini.tailnet-xxx.ts.net:8080',
|
|
15
|
+
* exposedTools: '*', // or ['search_codebase', 'get_document', ...]
|
|
16
|
+
* }),
|
|
17
|
+
* ],
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export { createQwickBrainPlugin, getConnectionStatus, isConnected } from './qwickbrain-plugin.js';
|
|
25
|
+
|
|
26
|
+
export type {
|
|
27
|
+
QwickBrainPluginConfig,
|
|
28
|
+
MCPToolDefinition,
|
|
29
|
+
MCPToolCallRequest,
|
|
30
|
+
MCPToolCallResponse,
|
|
31
|
+
QwickBrainConnectionStatus,
|
|
32
|
+
MCPRateLimitConfig,
|
|
33
|
+
} from './types.js';
|