@kb-labs/shared 1.1.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/.cursorrules +32 -0
- package/.github/workflows/ci.yml +13 -0
- package/.github/workflows/deploy.yml +28 -0
- package/.github/workflows/docker-build.yml +25 -0
- package/.github/workflows/drift-check.yml +10 -0
- package/.github/workflows/profiles-validate.yml +16 -0
- package/.github/workflows/release.yml +8 -0
- package/.kb/devkit/agents/devkit-maintainer/context.globs +15 -0
- package/.kb/devkit/agents/devkit-maintainer/permissions.yml +17 -0
- package/.kb/devkit/agents/devkit-maintainer/prompt.md +28 -0
- package/.kb/devkit/agents/devkit-maintainer/runbook.md +31 -0
- package/.kb/devkit/agents/docs-crafter/prompt.md +24 -0
- package/.kb/devkit/agents/docs-crafter/runbook.md +18 -0
- package/.kb/devkit/agents/release-manager/context.globs +7 -0
- package/.kb/devkit/agents/release-manager/prompt.md +27 -0
- package/.kb/devkit/agents/release-manager/runbook.md +17 -0
- package/.kb/devkit/agents/test-generator/context.globs +7 -0
- package/.kb/devkit/agents/test-generator/prompt.md +27 -0
- package/.kb/devkit/agents/test-generator/runbook.md +18 -0
- package/.vscode/settings.json +23 -0
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +117 -0
- package/LICENSE +21 -0
- package/README.md +306 -0
- package/docs/DECLARATIVE-FLAGS-AND-ENV.md +622 -0
- package/docs/DOCUMENTATION.md +70 -0
- package/docs/adr/0000-template.md +52 -0
- package/docs/adr/0001-architecture-and-repository-layout.md +31 -0
- package/docs/adr/0002-plugins-and-extensibility.md +44 -0
- package/docs/adr/0003-package-and-module-boundaries.md +35 -0
- package/docs/adr/0004-versioning-and-release-policy.md +36 -0
- package/docs/adr/0005-reactive-loader-pattern.md +179 -0
- package/docs/adr/0006-declarative-flags-and-env-systems.md +376 -0
- package/eslint.config.js +27 -0
- package/kb-labs.config.json +5 -0
- package/package.json +88 -0
- package/package.json.bin +25 -0
- package/package.json.lib +30 -0
- package/packages/shared-cli-ui/CHANGELOG.md +20 -0
- package/packages/shared-cli-ui/README.md +342 -0
- package/packages/shared-cli-ui/docs/ARCHITECTURE.md +105 -0
- package/packages/shared-cli-ui/eslint.config.js +27 -0
- package/packages/shared-cli-ui/package.json +72 -0
- package/packages/shared-cli-ui/src/__tests__/artifacts-display.spec.ts +89 -0
- package/packages/shared-cli-ui/src/__tests__/format.spec.ts +44 -0
- package/packages/shared-cli-ui/src/__tests__/loader-json-mode.test.ts +119 -0
- package/packages/shared-cli-ui/src/artifacts-display.ts +266 -0
- package/packages/shared-cli-ui/src/cli-auto-discovery.ts +120 -0
- package/packages/shared-cli-ui/src/colors.ts +142 -0
- package/packages/shared-cli-ui/src/command-discovery.ts +72 -0
- package/packages/shared-cli-ui/src/command-output.ts +153 -0
- package/packages/shared-cli-ui/src/command-result.ts +267 -0
- package/packages/shared-cli-ui/src/command-runner.ts +310 -0
- package/packages/shared-cli-ui/src/command-suggestions.ts +204 -0
- package/packages/shared-cli-ui/src/debug/components/output.ts +141 -0
- package/packages/shared-cli-ui/src/debug/components/trace.ts +101 -0
- package/packages/shared-cli-ui/src/debug/components/tree.ts +88 -0
- package/packages/shared-cli-ui/src/debug/formatters/ai.ts +17 -0
- package/packages/shared-cli-ui/src/debug/formatters/human.ts +98 -0
- package/packages/shared-cli-ui/src/debug/formatters/timeline.ts +94 -0
- package/packages/shared-cli-ui/src/debug/index.ts +56 -0
- package/packages/shared-cli-ui/src/debug/types.ts +57 -0
- package/packages/shared-cli-ui/src/debug/utilities.ts +203 -0
- package/packages/shared-cli-ui/src/dynamic-command-discovery.ts +131 -0
- package/packages/shared-cli-ui/src/format.ts +412 -0
- package/packages/shared-cli-ui/src/index.ts +34 -0
- package/packages/shared-cli-ui/src/loader.ts +196 -0
- package/packages/shared-cli-ui/src/manifest-parser.ts +151 -0
- package/packages/shared-cli-ui/src/modern-format.ts +271 -0
- package/packages/shared-cli-ui/src/multi-cli-suggestions.ts +159 -0
- package/packages/shared-cli-ui/src/table.ts +134 -0
- package/packages/shared-cli-ui/src/timing-tracker.ts +68 -0
- package/packages/shared-cli-ui/src/utils/context.ts +12 -0
- package/packages/shared-cli-ui/src/utils/env.ts +164 -0
- package/packages/shared-cli-ui/src/utils/flags.ts +269 -0
- package/packages/shared-cli-ui/src/utils/path.ts +8 -0
- package/packages/shared-cli-ui/tsconfig.build.json +15 -0
- package/packages/shared-cli-ui/tsconfig.json +9 -0
- package/packages/shared-cli-ui/tsup.config.ts +11 -0
- package/packages/shared-cli-ui/vitest.config.ts +15 -0
- package/packages/shared-command-kit/CHANGELOG.md +20 -0
- package/packages/shared-command-kit/LICENSE +22 -0
- package/packages/shared-command-kit/README.md +1030 -0
- package/packages/shared-command-kit/docs/HIGH-LEVEL-API.md +89 -0
- package/packages/shared-command-kit/docs/LOW-LEVEL-API.md +105 -0
- package/packages/shared-command-kit/docs/MIGRATION-GUIDE.md +135 -0
- package/packages/shared-command-kit/eslint.config.js +27 -0
- package/packages/shared-command-kit/eslint.config.ts +14 -0
- package/packages/shared-command-kit/package.json +76 -0
- package/packages/shared-command-kit/prettierrc.json +5 -0
- package/packages/shared-command-kit/src/__tests__/define-command.spec.ts +294 -0
- package/packages/shared-command-kit/src/__tests__/define-route.test.ts +285 -0
- package/packages/shared-command-kit/src/__tests__/define-system-command.spec.ts +508 -0
- package/packages/shared-command-kit/src/__tests__/define-webhook.test.ts +156 -0
- package/packages/shared-command-kit/src/__tests__/define-websocket.test.ts +316 -0
- package/packages/shared-command-kit/src/__tests__/errors.spec.ts +45 -0
- package/packages/shared-command-kit/src/__tests__/flags.spec.ts +353 -0
- package/packages/shared-command-kit/src/__tests__/platform-api.test.ts +135 -0
- package/packages/shared-command-kit/src/__tests__/plugin-context-v3.snapshot.spec.ts +240 -0
- package/packages/shared-command-kit/src/__tests__/ws-types.test.ts +359 -0
- package/packages/shared-command-kit/src/analytics/index.ts +6 -0
- package/packages/shared-command-kit/src/analytics/with-analytics.ts +195 -0
- package/packages/shared-command-kit/src/define-action.ts +100 -0
- package/packages/shared-command-kit/src/define-command.ts +113 -0
- package/packages/shared-command-kit/src/define-route.ts +113 -0
- package/packages/shared-command-kit/src/define-system-command.ts +362 -0
- package/packages/shared-command-kit/src/define-webhook.ts +115 -0
- package/packages/shared-command-kit/src/define-websocket.ts +308 -0
- package/packages/shared-command-kit/src/errors/factory.ts +282 -0
- package/packages/shared-command-kit/src/errors/format-validation.ts +144 -0
- package/packages/shared-command-kit/src/errors/format.ts +92 -0
- package/packages/shared-command-kit/src/errors/index.ts +9 -0
- package/packages/shared-command-kit/src/errors/types.ts +32 -0
- package/packages/shared-command-kit/src/flags/define.ts +92 -0
- package/packages/shared-command-kit/src/flags/index.ts +9 -0
- package/packages/shared-command-kit/src/flags/types.ts +153 -0
- package/packages/shared-command-kit/src/flags/validate.ts +358 -0
- package/packages/shared-command-kit/src/helpers/context.ts +8 -0
- package/packages/shared-command-kit/src/helpers/flags.ts +84 -0
- package/packages/shared-command-kit/src/helpers/index.ts +42 -0
- package/packages/shared-command-kit/src/helpers/patterns.ts +464 -0
- package/packages/shared-command-kit/src/helpers/platform.ts +335 -0
- package/packages/shared-command-kit/src/helpers/use-analytics.ts +95 -0
- package/packages/shared-command-kit/src/helpers/use-cache.ts +97 -0
- package/packages/shared-command-kit/src/helpers/use-config.ts +99 -0
- package/packages/shared-command-kit/src/helpers/use-embeddings.ts +49 -0
- package/packages/shared-command-kit/src/helpers/use-llm.ts +316 -0
- package/packages/shared-command-kit/src/helpers/use-logger.ts +77 -0
- package/packages/shared-command-kit/src/helpers/use-platform.ts +111 -0
- package/packages/shared-command-kit/src/helpers/use-resource-broker.ts +106 -0
- package/packages/shared-command-kit/src/helpers/use-storage.ts +71 -0
- package/packages/shared-command-kit/src/helpers/use-vector-store.ts +49 -0
- package/packages/shared-command-kit/src/helpers/validation.ts +398 -0
- package/packages/shared-command-kit/src/index.ts +410 -0
- package/packages/shared-command-kit/src/jobs.ts +132 -0
- package/packages/shared-command-kit/src/lifecycle/define-handlers.ts +366 -0
- package/packages/shared-command-kit/src/lifecycle/index.ts +6 -0
- package/packages/shared-command-kit/src/manifest.ts +127 -0
- package/packages/shared-command-kit/src/rest/define-handler.ts +187 -0
- package/packages/shared-command-kit/src/rest/index.ts +11 -0
- package/packages/shared-command-kit/src/studio/index.ts +12 -0
- package/packages/shared-command-kit/src/validation/index.ts +6 -0
- package/packages/shared-command-kit/src/validation/schema-builders.ts +409 -0
- package/packages/shared-command-kit/src/ws-types.ts +106 -0
- package/packages/shared-command-kit/tsconfig.build.json +15 -0
- package/packages/shared-command-kit/tsconfig.json +9 -0
- package/packages/shared-command-kit/tsup.config.ts +30 -0
- package/packages/shared-command-kit/vitest.config.ts +4 -0
- package/packages/shared-http/package.json +67 -0
- package/packages/shared-http/src/__tests__/log-correlation.test.ts +81 -0
- package/packages/shared-http/src/__tests__/operation-metrics-tracker.test.ts +55 -0
- package/packages/shared-http/src/http-observability-collector.ts +363 -0
- package/packages/shared-http/src/index.ts +36 -0
- package/packages/shared-http/src/log-correlation.ts +89 -0
- package/packages/shared-http/src/operation-metrics-tracker.ts +107 -0
- package/packages/shared-http/src/register-openapi.ts +108 -0
- package/packages/shared-http/src/resolve-schema-ref.ts +75 -0
- package/packages/shared-http/src/schemas.ts +29 -0
- package/packages/shared-http/src/service-observability.ts +63 -0
- package/packages/shared-http/tsconfig.build.json +15 -0
- package/packages/shared-http/tsconfig.json +9 -0
- package/packages/shared-http/tsup.config.ts +23 -0
- package/packages/shared-http/vitest.config.ts +13 -0
- package/packages/shared-perm-presets/CHANGELOG.md +20 -0
- package/packages/shared-perm-presets/README.md +78 -0
- package/packages/shared-perm-presets/eslint.config.js +27 -0
- package/packages/shared-perm-presets/package.json +45 -0
- package/packages/shared-perm-presets/src/__tests__/combine.test.ts +403 -0
- package/packages/shared-perm-presets/src/__tests__/presets.test.ts +205 -0
- package/packages/shared-perm-presets/src/combine.ts +278 -0
- package/packages/shared-perm-presets/src/index.ts +18 -0
- package/packages/shared-perm-presets/src/presets/ci-environment.ts +34 -0
- package/packages/shared-perm-presets/src/presets/full-env.ts +16 -0
- package/packages/shared-perm-presets/src/presets/git-workflow.ts +40 -0
- package/packages/shared-perm-presets/src/presets/index.ts +8 -0
- package/packages/shared-perm-presets/src/presets/kb-platform.ts +30 -0
- package/packages/shared-perm-presets/src/presets/llm-access.ts +29 -0
- package/packages/shared-perm-presets/src/presets/minimal.ts +21 -0
- package/packages/shared-perm-presets/src/presets/npm-publish.ts +48 -0
- package/packages/shared-perm-presets/src/presets/vector-store.ts +40 -0
- package/packages/shared-perm-presets/src/types.ts +192 -0
- package/packages/shared-perm-presets/tsconfig.build.json +15 -0
- package/packages/shared-perm-presets/tsconfig.json +9 -0
- package/packages/shared-perm-presets/tsup.config.ts +8 -0
- package/packages/shared-perm-presets/vitest.config.ts +9 -0
- package/packages/shared-testing/CHANGELOG.md +20 -0
- package/packages/shared-testing/README.md +430 -0
- package/packages/shared-testing/package.json +51 -0
- package/packages/shared-testing/src/__tests__/create-test-context.test.ts +199 -0
- package/packages/shared-testing/src/__tests__/mock-cache.test.ts +174 -0
- package/packages/shared-testing/src/__tests__/mock-llm.test.ts +212 -0
- package/packages/shared-testing/src/__tests__/setup-platform.test.ts +90 -0
- package/packages/shared-testing/src/__tests__/test-command.test.ts +557 -0
- package/packages/shared-testing/src/create-test-context.ts +550 -0
- package/packages/shared-testing/src/index.ts +77 -0
- package/packages/shared-testing/src/mock-cache.ts +179 -0
- package/packages/shared-testing/src/mock-llm.ts +319 -0
- package/packages/shared-testing/src/mock-logger.ts +97 -0
- package/packages/shared-testing/src/mock-storage.ts +108 -0
- package/packages/shared-testing/src/setup-platform.ts +101 -0
- package/packages/shared-testing/src/test-command.ts +288 -0
- package/packages/shared-testing/tsconfig.build.json +15 -0
- package/packages/shared-testing/tsconfig.json +9 -0
- package/packages/shared-testing/tsup.config.ts +20 -0
- package/packages/shared-testing/vitest.config.ts +3 -0
- package/packages/shared-tool-kit/CHANGELOG.md +20 -0
- package/packages/shared-tool-kit/package.json +47 -0
- package/packages/shared-tool-kit/src/__tests__/factory.test.ts +103 -0
- package/packages/shared-tool-kit/src/__tests__/mock-tool.test.ts +95 -0
- package/packages/shared-tool-kit/src/factory.ts +126 -0
- package/packages/shared-tool-kit/src/index.ts +32 -0
- package/packages/shared-tool-kit/src/testing/index.ts +84 -0
- package/packages/shared-tool-kit/tsconfig.build.json +15 -0
- package/packages/shared-tool-kit/tsconfig.json +9 -0
- package/packages/shared-tool-kit/tsup.config.ts +21 -0
- package/pnpm-workspace.yaml +11070 -0
- package/prettierrc.json +1 -0
- package/scripts/devkit-sync.mjs +37 -0
- package/scripts/hooks/post-push +9 -0
- package/scripts/hooks/pre-commit +9 -0
- package/scripts/hooks/pre-push +9 -0
- package/tsconfig.base.json +9 -0
- package/tsconfig.build.json +15 -0
- package/tsconfig.json +9 -0
- package/tsconfig.paths.json +50 -0
- package/tsconfig.tools.json +18 -0
- package/tsup.config.bin.ts +34 -0
- package/tsup.config.cli.ts +41 -0
- package/tsup.config.dual.ts +46 -0
- package/tsup.config.ts +36 -0
- package/tsup.external.json +104 -0
- package/vitest.config.ts +48 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle Hook Helpers
|
|
3
|
+
*
|
|
4
|
+
* Optional helpers for plugin lifecycle hooks (setup, destroy, upgrade).
|
|
5
|
+
* You can always use plain functions - this is just convenience.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { defineSetupHandler } from '@kb-labs/shared-command-kit';
|
|
10
|
+
*
|
|
11
|
+
* export const setup = defineSetupHandler({
|
|
12
|
+
* name: 'mind:setup',
|
|
13
|
+
* workspace: {
|
|
14
|
+
* directories: ['.kb/mind/index', '.kb/mind/cache'],
|
|
15
|
+
* },
|
|
16
|
+
* config: {
|
|
17
|
+
* 'kb.config.json': {
|
|
18
|
+
* mind: { enabled: true, scopes: ['default'] },
|
|
19
|
+
* },
|
|
20
|
+
* },
|
|
21
|
+
* async handler(ctx) {
|
|
22
|
+
* ctx.log('Mind workspace initialized');
|
|
23
|
+
* return { ok: true };
|
|
24
|
+
* },
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import * as fs from 'node:fs/promises';
|
|
30
|
+
import * as path from 'node:path';
|
|
31
|
+
import { existsSync } from 'node:fs';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Lifecycle handler context
|
|
35
|
+
*/
|
|
36
|
+
export interface LifecycleContext {
|
|
37
|
+
/** Output directory (plugin workspace root) */
|
|
38
|
+
outdir: string;
|
|
39
|
+
/** Plugin ID */
|
|
40
|
+
pluginId: string;
|
|
41
|
+
/** Request ID for tracing */
|
|
42
|
+
requestId?: string;
|
|
43
|
+
/** Logger */
|
|
44
|
+
log?: (level: 'debug' | 'info' | 'warn' | 'error', msg: string, meta?: Record<string, unknown>) => void;
|
|
45
|
+
/** Environment getter */
|
|
46
|
+
env?: (key: string) => string | undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Workspace setup configuration
|
|
51
|
+
*/
|
|
52
|
+
export interface WorkspaceConfig {
|
|
53
|
+
/** Directories to create (relative to outdir or absolute) */
|
|
54
|
+
directories?: string[];
|
|
55
|
+
/** Files to create with content */
|
|
56
|
+
files?: Record<string, string>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Config file updates
|
|
61
|
+
*/
|
|
62
|
+
export type ConfigUpdates = Record<string, Record<string, unknown>>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Setup handler definition
|
|
66
|
+
*/
|
|
67
|
+
export interface SetupHandlerDefinition {
|
|
68
|
+
/** Handler name (for logging) */
|
|
69
|
+
name: string;
|
|
70
|
+
/** Workspace configuration (directories/files to create) */
|
|
71
|
+
workspace?: WorkspaceConfig;
|
|
72
|
+
/** Config file updates (will be merged with existing config) */
|
|
73
|
+
config?: ConfigUpdates;
|
|
74
|
+
/** Custom setup logic (optional) */
|
|
75
|
+
handler?: (ctx: LifecycleContext) => Promise<{ ok: boolean; message?: string }>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Destroy handler definition
|
|
80
|
+
*/
|
|
81
|
+
export interface DestroyHandlerDefinition {
|
|
82
|
+
/** Handler name (for logging) */
|
|
83
|
+
name: string;
|
|
84
|
+
/** Workspace cleanup (directories/files to remove) */
|
|
85
|
+
workspace?: {
|
|
86
|
+
/** Directories to remove */
|
|
87
|
+
directories?: string[];
|
|
88
|
+
/** Files to remove */
|
|
89
|
+
files?: string[];
|
|
90
|
+
};
|
|
91
|
+
/** Config cleanup (keys to remove from config files) */
|
|
92
|
+
config?: Record<string, string[]>; // file -> keys to remove
|
|
93
|
+
/** Custom destroy logic (optional) */
|
|
94
|
+
handler?: (ctx: LifecycleContext) => Promise<{ ok: boolean; message?: string }>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Setup handler result
|
|
99
|
+
*/
|
|
100
|
+
export interface SetupResult {
|
|
101
|
+
ok: boolean;
|
|
102
|
+
message?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Define a setup handler with declarative workspace and config setup
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* export const setup = defineSetupHandler({
|
|
111
|
+
* name: 'mind:setup',
|
|
112
|
+
* workspace: {
|
|
113
|
+
* directories: [
|
|
114
|
+
* '.kb/mind/index',
|
|
115
|
+
* '.kb/mind/cache',
|
|
116
|
+
* '.kb/mind/pack',
|
|
117
|
+
* ],
|
|
118
|
+
* files: {
|
|
119
|
+
* '.kb/mind/.gitignore': 'cache/\npack/\n',
|
|
120
|
+
* },
|
|
121
|
+
* },
|
|
122
|
+
* config: {
|
|
123
|
+
* 'kb.config.json': {
|
|
124
|
+
* mind: {
|
|
125
|
+
* enabled: true,
|
|
126
|
+
* scopes: ['default'],
|
|
127
|
+
* },
|
|
128
|
+
* },
|
|
129
|
+
* },
|
|
130
|
+
* async handler(ctx) {
|
|
131
|
+
* ctx.log?.('info', 'Custom setup logic', {});
|
|
132
|
+
* return { ok: true };
|
|
133
|
+
* },
|
|
134
|
+
* });
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
export function defineSetupHandler(
|
|
138
|
+
definition: SetupHandlerDefinition
|
|
139
|
+
): (ctx: LifecycleContext) => Promise<SetupResult> {
|
|
140
|
+
return async (ctx: LifecycleContext) => {
|
|
141
|
+
const log = ctx.log || ((level: string, msg: string, meta?: Record<string, unknown>) => {
|
|
142
|
+
console.log(`[${level}] ${msg}`, meta || '');
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
log('info', 'Setup started', { handler: definition.name, outdir: ctx.outdir });
|
|
147
|
+
|
|
148
|
+
// 1. Create workspace directories and files
|
|
149
|
+
if (definition.workspace) {
|
|
150
|
+
await setupWorkspace(ctx.outdir, definition.workspace, log);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 2. Update config files
|
|
154
|
+
if (definition.config) {
|
|
155
|
+
await updateConfigFiles(ctx.outdir, definition.config, log);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 3. Run custom handler logic
|
|
159
|
+
if (definition.handler) {
|
|
160
|
+
const result = await definition.handler(ctx);
|
|
161
|
+
if (!result.ok) {
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
log('info', 'Setup completed', { handler: definition.name });
|
|
167
|
+
return { ok: true, message: `${definition.name} setup completed` };
|
|
168
|
+
} catch (error: any) {
|
|
169
|
+
log('error', 'Setup failed', {
|
|
170
|
+
handler: definition.name,
|
|
171
|
+
error: error.message,
|
|
172
|
+
stack: error.stack,
|
|
173
|
+
});
|
|
174
|
+
return { ok: false, message: `Setup failed: ${error.message}` };
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Define a destroy handler with declarative cleanup
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* export const destroy = defineDestroyHandler({
|
|
185
|
+
* name: 'mind:destroy',
|
|
186
|
+
* workspace: {
|
|
187
|
+
* directories: ['.kb/mind'],
|
|
188
|
+
* },
|
|
189
|
+
* config: {
|
|
190
|
+
* 'kb.config.json': ['mind'], // Remove 'mind' key
|
|
191
|
+
* },
|
|
192
|
+
* });
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
export function defineDestroyHandler(
|
|
196
|
+
definition: DestroyHandlerDefinition
|
|
197
|
+
): (ctx: LifecycleContext) => Promise<SetupResult> {
|
|
198
|
+
return async (ctx: LifecycleContext) => {
|
|
199
|
+
const log = ctx.log || ((level: string, msg: string, meta?: Record<string, unknown>) => {
|
|
200
|
+
console.log(`[${level}] ${msg}`, meta || '');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
log('info', 'Destroy started', { handler: definition.name, outdir: ctx.outdir });
|
|
205
|
+
|
|
206
|
+
// 1. Clean up config files
|
|
207
|
+
if (definition.config) {
|
|
208
|
+
await cleanupConfigFiles(ctx.outdir, definition.config, log);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 2. Remove workspace directories and files
|
|
212
|
+
if (definition.workspace) {
|
|
213
|
+
await cleanupWorkspace(ctx.outdir, definition.workspace, log);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 3. Run custom handler logic
|
|
217
|
+
if (definition.handler) {
|
|
218
|
+
const result = await definition.handler(ctx);
|
|
219
|
+
if (!result.ok) {
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
log('info', 'Destroy completed', { handler: definition.name });
|
|
225
|
+
return { ok: true, message: `${definition.name} destroy completed` };
|
|
226
|
+
} catch (error: any) {
|
|
227
|
+
log('error', 'Destroy failed', {
|
|
228
|
+
handler: definition.name,
|
|
229
|
+
error: error.message,
|
|
230
|
+
stack: error.stack,
|
|
231
|
+
});
|
|
232
|
+
return { ok: false, message: `Destroy failed: ${error.message}` };
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Setup workspace directories and files
|
|
239
|
+
*/
|
|
240
|
+
async function setupWorkspace(
|
|
241
|
+
outdir: string,
|
|
242
|
+
config: WorkspaceConfig,
|
|
243
|
+
log: (level: 'error' | 'info' | 'debug' | 'warn', msg: string, meta?: Record<string, unknown>) => void
|
|
244
|
+
): Promise<void> {
|
|
245
|
+
// Create directories
|
|
246
|
+
if (config.directories) {
|
|
247
|
+
for (const dir of config.directories) {
|
|
248
|
+
const dirPath = path.resolve(outdir, dir);
|
|
249
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
250
|
+
log('debug', 'Created directory', { path: dirPath });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Create files
|
|
255
|
+
if (config.files) {
|
|
256
|
+
for (const [filePath, content] of Object.entries(config.files)) {
|
|
257
|
+
const fullPath = path.resolve(outdir, filePath);
|
|
258
|
+
const dirPath = path.dirname(fullPath);
|
|
259
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
260
|
+
await fs.writeFile(fullPath, content, 'utf-8');
|
|
261
|
+
log('debug', 'Created file', { path: fullPath });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Update config files (merge with existing config)
|
|
268
|
+
*/
|
|
269
|
+
async function updateConfigFiles(
|
|
270
|
+
outdir: string,
|
|
271
|
+
updates: ConfigUpdates,
|
|
272
|
+
log: (level: 'error' | 'info' | 'debug' | 'warn', msg: string, meta?: Record<string, unknown>) => void
|
|
273
|
+
): Promise<void> {
|
|
274
|
+
for (const [configFile, configUpdates] of Object.entries(updates)) {
|
|
275
|
+
const configPath = path.resolve(outdir, configFile);
|
|
276
|
+
|
|
277
|
+
// Read existing config or create empty
|
|
278
|
+
let config: Record<string, unknown> = {};
|
|
279
|
+
if (existsSync(configPath)) {
|
|
280
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
281
|
+
try {
|
|
282
|
+
config = JSON.parse(content);
|
|
283
|
+
} catch (error) {
|
|
284
|
+
log('warn', 'Failed to parse existing config, starting fresh', { path: configPath });
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Merge updates
|
|
289
|
+
config = { ...config, ...configUpdates };
|
|
290
|
+
|
|
291
|
+
// Write updated config
|
|
292
|
+
const dirPath = path.dirname(configPath);
|
|
293
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
294
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
295
|
+
log('debug', 'Updated config file', { path: configPath });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Cleanup workspace directories and files
|
|
301
|
+
*/
|
|
302
|
+
async function cleanupWorkspace(
|
|
303
|
+
outdir: string,
|
|
304
|
+
config: DestroyHandlerDefinition['workspace'],
|
|
305
|
+
log: (level: 'error' | 'info' | 'debug' | 'warn', msg: string, meta?: Record<string, unknown>) => void
|
|
306
|
+
): Promise<void> {
|
|
307
|
+
if (!config) {return;}
|
|
308
|
+
|
|
309
|
+
// Remove files first
|
|
310
|
+
if (config.files) {
|
|
311
|
+
for (const file of config.files) {
|
|
312
|
+
const filePath = path.resolve(outdir, file);
|
|
313
|
+
if (existsSync(filePath)) {
|
|
314
|
+
await fs.unlink(filePath);
|
|
315
|
+
log('debug', 'Removed file', { path: filePath });
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Remove directories
|
|
321
|
+
if (config.directories) {
|
|
322
|
+
for (const dir of config.directories) {
|
|
323
|
+
const dirPath = path.resolve(outdir, dir);
|
|
324
|
+
if (existsSync(dirPath)) {
|
|
325
|
+
await fs.rm(dirPath, { recursive: true, force: true });
|
|
326
|
+
log('debug', 'Removed directory', { path: dirPath });
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Cleanup config files (remove keys)
|
|
334
|
+
*/
|
|
335
|
+
async function cleanupConfigFiles(
|
|
336
|
+
outdir: string,
|
|
337
|
+
cleanups: Record<string, string[]>,
|
|
338
|
+
log: (level: 'error' | 'info' | 'debug' | 'warn', msg: string, meta?: Record<string, unknown>) => void
|
|
339
|
+
): Promise<void> {
|
|
340
|
+
for (const [configFile, keysToRemove] of Object.entries(cleanups)) {
|
|
341
|
+
const configPath = path.resolve(outdir, configFile);
|
|
342
|
+
|
|
343
|
+
if (!existsSync(configPath)) {
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Read config
|
|
348
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
349
|
+
let config: Record<string, unknown>;
|
|
350
|
+
try {
|
|
351
|
+
config = JSON.parse(content);
|
|
352
|
+
} catch (error) {
|
|
353
|
+
log('warn', 'Failed to parse config for cleanup', { path: configPath });
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Remove keys
|
|
358
|
+
for (const key of keysToRemove) {
|
|
359
|
+
delete config[key];
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Write updated config
|
|
363
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
364
|
+
log('debug', 'Cleaned up config file', { path: configPath, removed: keysToRemove });
|
|
365
|
+
}
|
|
366
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest definition helpers
|
|
3
|
+
* @module @kb-labs/shared-command-kit/manifest
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ManifestV3 } from '@kb-labs/plugin-contracts';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Define a ManifestV3 with type safety
|
|
10
|
+
*
|
|
11
|
+
* This is a type-safe wrapper for creating ManifestV3 objects.
|
|
12
|
+
* It provides compile-time validation via TypeScript and optional
|
|
13
|
+
* runtime validation via Zod (if enabled).
|
|
14
|
+
*
|
|
15
|
+
* For built plugins (dist/), this function is compiled away and only
|
|
16
|
+
* the plain object remains, avoiding runtime dependencies.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Basic usage
|
|
21
|
+
* export const manifest = defineManifest({
|
|
22
|
+
* schema: 'kb.plugin/2',
|
|
23
|
+
* id: '@kb-labs/my-plugin',
|
|
24
|
+
* version: '1.0.0',
|
|
25
|
+
* cli: {
|
|
26
|
+
* commands: [...]
|
|
27
|
+
* }
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // With contracts typing (Level 2)
|
|
31
|
+
* import type { PluginContracts } from '@kb-labs/my-plugin-contracts';
|
|
32
|
+
*
|
|
33
|
+
* export const manifest = defineManifest<typeof pluginContractsManifest>({
|
|
34
|
+
* schema: 'kb.plugin/2',
|
|
35
|
+
* id: '@kb-labs/my-plugin',
|
|
36
|
+
* artifacts: [
|
|
37
|
+
* { id: 'my.artifact.id' } // ✅ Type-checked against contracts
|
|
38
|
+
* ],
|
|
39
|
+
* cli: {
|
|
40
|
+
* commands: [{
|
|
41
|
+
* id: 'my:command', // ✅ Type-checked against contracts
|
|
42
|
+
* // ...
|
|
43
|
+
* }]
|
|
44
|
+
* }
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @param manifest - Manifest configuration
|
|
49
|
+
* @returns ManifestV3 object
|
|
50
|
+
*/
|
|
51
|
+
export function defineManifest<TContracts = unknown>(
|
|
52
|
+
manifest: ManifestV3
|
|
53
|
+
): ManifestV3 {
|
|
54
|
+
// In development, you could add runtime validation here if needed:
|
|
55
|
+
// if (process.env.NODE_ENV === 'development') {
|
|
56
|
+
// validateManifestV3(manifest);
|
|
57
|
+
// }
|
|
58
|
+
|
|
59
|
+
// For production builds, this is just an identity function
|
|
60
|
+
// that provides type safety at compile time
|
|
61
|
+
return manifest;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Flag schema definition (compatible with defineFlags)
|
|
66
|
+
*/
|
|
67
|
+
type FlagSchemaDefinition = Record<
|
|
68
|
+
string,
|
|
69
|
+
{
|
|
70
|
+
type: 'string' | 'boolean' | 'number' | 'array';
|
|
71
|
+
alias?: string;
|
|
72
|
+
default?: unknown;
|
|
73
|
+
description?: string;
|
|
74
|
+
choices?: string[];
|
|
75
|
+
required?: boolean;
|
|
76
|
+
}
|
|
77
|
+
>;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Convert flag schema definition to CliFlagDecl[] for manifest
|
|
81
|
+
*
|
|
82
|
+
* This helper converts the flag schema format used in defineCommand
|
|
83
|
+
* to the array format expected in ManifestV3.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const helloFlags = {
|
|
88
|
+
* name: { type: 'string', description: 'Name to greet', alias: 'n' },
|
|
89
|
+
* json: { type: 'boolean', description: 'Emit JSON', default: false }
|
|
90
|
+
* };
|
|
91
|
+
*
|
|
92
|
+
* const manifestFlags = defineCommandFlags(helloFlags);
|
|
93
|
+
* // Use in manifest: flags: manifestFlags
|
|
94
|
+
*
|
|
95
|
+
* // In manifest.v2.ts:
|
|
96
|
+
* export const manifest = defineManifest({
|
|
97
|
+
* cli: {
|
|
98
|
+
* commands: [{
|
|
99
|
+
* id: 'hello',
|
|
100
|
+
* flags: defineCommandFlags(helloFlags),
|
|
101
|
+
* // ...
|
|
102
|
+
* }]
|
|
103
|
+
* }
|
|
104
|
+
* });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export function defineCommandFlags<TFlags extends FlagSchemaDefinition>(
|
|
108
|
+
flags: TFlags
|
|
109
|
+
): Array<{
|
|
110
|
+
name: string;
|
|
111
|
+
type: 'string' | 'boolean' | 'number' | 'array';
|
|
112
|
+
alias?: string;
|
|
113
|
+
default?: unknown;
|
|
114
|
+
description?: string;
|
|
115
|
+
choices?: string[];
|
|
116
|
+
required?: boolean;
|
|
117
|
+
}> {
|
|
118
|
+
return Object.entries(flags).map(([name, flag]) => ({
|
|
119
|
+
name,
|
|
120
|
+
type: flag.type,
|
|
121
|
+
...(flag.alias !== undefined && { alias: flag.alias }),
|
|
122
|
+
...(flag.default !== undefined && { default: flag.default }),
|
|
123
|
+
...(flag.description !== undefined && { description: flag.description }),
|
|
124
|
+
...(flag.choices !== undefined && { choices: flag.choices }),
|
|
125
|
+
...(flag.required !== undefined && { required: flag.required }),
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REST Handler Definition (V3)
|
|
3
|
+
*
|
|
4
|
+
* Define REST handlers compatible with plugin-runtime's runInProcess().
|
|
5
|
+
* Returns { execute } object with (ctx, input) signature.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { defineHandler } from '@kb-labs/shared-command-kit';
|
|
10
|
+
*
|
|
11
|
+
* export default defineHandler({
|
|
12
|
+
* async execute(ctx, input: { scope?: string }) {
|
|
13
|
+
* const plan = await loadPlan(ctx.cwd);
|
|
14
|
+
* return plan;
|
|
15
|
+
* }
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { PluginContextV3 } from '@kb-labs/plugin-contracts';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* REST input structure from route-mounter.
|
|
24
|
+
* Query params, body, and route params are separated to avoid conflicts.
|
|
25
|
+
*/
|
|
26
|
+
export interface RestInput<TQuery = unknown, TBody = unknown, TParams = unknown> {
|
|
27
|
+
query?: TQuery;
|
|
28
|
+
body?: TBody;
|
|
29
|
+
params?: TParams;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Handler interface expected by runInProcess().
|
|
34
|
+
*/
|
|
35
|
+
export interface Handler<TConfig = unknown, TInput = unknown, TOutput = unknown> {
|
|
36
|
+
/**
|
|
37
|
+
* Execute the handler
|
|
38
|
+
*/
|
|
39
|
+
execute(
|
|
40
|
+
ctx: PluginContextV3<TConfig>,
|
|
41
|
+
input: TInput
|
|
42
|
+
): Promise<TOutput>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Handler definition options.
|
|
47
|
+
* Extensible for future features (inputSchema, middleware, etc.)
|
|
48
|
+
*/
|
|
49
|
+
export interface HandlerDefinition<TConfig = unknown, TInput = unknown, TOutput = unknown> {
|
|
50
|
+
/**
|
|
51
|
+
* Execute the handler.
|
|
52
|
+
* Returns data directly - no need for exitCode/CommandResult wrapper.
|
|
53
|
+
*
|
|
54
|
+
* @param ctx - Plugin context with runtime APIs (fs, fetch, env, ui, etc.)
|
|
55
|
+
* @param input - Request input (body for POST, query for GET, etc.)
|
|
56
|
+
* @returns Response data (will be serialized as JSON)
|
|
57
|
+
* @throws Error on failure (will be converted to HTTP 500)
|
|
58
|
+
*/
|
|
59
|
+
execute(
|
|
60
|
+
ctx: PluginContextV3<TConfig>,
|
|
61
|
+
input: TInput
|
|
62
|
+
): Promise<TOutput>;
|
|
63
|
+
|
|
64
|
+
// Future options (non-breaking additions):
|
|
65
|
+
// inputSchema?: ZodType<TInput>;
|
|
66
|
+
// outputSchema?: ZodType<TOutput>;
|
|
67
|
+
// middleware?: Middleware[];
|
|
68
|
+
// timeout?: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Define a REST handler
|
|
73
|
+
*
|
|
74
|
+
* Creates a handler object compatible with runInProcess() from plugin-runtime.
|
|
75
|
+
* The handler receives full PluginContextV3 with runtime APIs.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* // Simple handler
|
|
80
|
+
* export default defineHandler({
|
|
81
|
+
* async execute(ctx, input: { scope?: string }) {
|
|
82
|
+
* const plan = await loadPlan(ctx.cwd);
|
|
83
|
+
* return plan;
|
|
84
|
+
* }
|
|
85
|
+
* });
|
|
86
|
+
*
|
|
87
|
+
* // With typed query parameters using RestInput
|
|
88
|
+
* import { defineHandler, type RestInput } from '@kb-labs/sdk';
|
|
89
|
+
*
|
|
90
|
+
* export default defineHandler({
|
|
91
|
+
* async execute(ctx, input: RestInput<{ workspace?: string }>) {
|
|
92
|
+
* const workspace = input.query?.workspace || 'root';
|
|
93
|
+
* return { workspace };
|
|
94
|
+
* }
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* // With typed query and body
|
|
98
|
+
* interface QueryParams {
|
|
99
|
+
* workspace?: string;
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* interface BodyParams {
|
|
103
|
+
* name: string;
|
|
104
|
+
* description?: string;
|
|
105
|
+
* }
|
|
106
|
+
*
|
|
107
|
+
* export default defineHandler({
|
|
108
|
+
* async execute(ctx, input: RestInput<QueryParams, BodyParams>) {
|
|
109
|
+
* const workspace = input.query?.workspace || 'root';
|
|
110
|
+
* const name = input.body?.name;
|
|
111
|
+
* return { workspace, name };
|
|
112
|
+
* }
|
|
113
|
+
* });
|
|
114
|
+
*
|
|
115
|
+
* // With typed generics
|
|
116
|
+
* interface GetPlanInput {
|
|
117
|
+
* scope?: string;
|
|
118
|
+
* includeHistory?: boolean;
|
|
119
|
+
* }
|
|
120
|
+
*
|
|
121
|
+
* interface ReleasePlan {
|
|
122
|
+
* version: string;
|
|
123
|
+
* packages: string[];
|
|
124
|
+
* }
|
|
125
|
+
*
|
|
126
|
+
* export default defineHandler<unknown, GetPlanInput, ReleasePlan>({
|
|
127
|
+
* async execute(ctx, input) {
|
|
128
|
+
* // ctx: PluginContextV3 with runtime.fs, ui, etc.
|
|
129
|
+
* // input: GetPlanInput (typed)
|
|
130
|
+
* // return: ReleasePlan (typed)
|
|
131
|
+
* return await loadPlan(ctx.cwd, input.scope);
|
|
132
|
+
* }
|
|
133
|
+
* });
|
|
134
|
+
*
|
|
135
|
+
* // Using runtime APIs
|
|
136
|
+
* export default defineHandler({
|
|
137
|
+
* async execute(ctx, input: { path: string }) {
|
|
138
|
+
* // File system access
|
|
139
|
+
* const content = await ctx.runtime.fs.readFile(input.path, 'utf-8');
|
|
140
|
+
*
|
|
141
|
+
* // Environment variables
|
|
142
|
+
* const apiKey = ctx.runtime.env('API_KEY');
|
|
143
|
+
*
|
|
144
|
+
* // Logging
|
|
145
|
+
* ctx.runtime.log('info', 'Processing file', { path: input.path });
|
|
146
|
+
*
|
|
147
|
+
* return { content, hasApiKey: !!apiKey };
|
|
148
|
+
* }
|
|
149
|
+
* });
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export function defineHandler<TConfig = unknown, TInput = unknown, TOutput = unknown>(
|
|
153
|
+
definition: HandlerDefinition<TConfig, TInput, TOutput>
|
|
154
|
+
): Handler<TConfig, TInput, TOutput> {
|
|
155
|
+
// Return handler object compatible with runInProcess()
|
|
156
|
+
// Currently passes through, but this wrapper enables:
|
|
157
|
+
// - Future input validation via inputSchema
|
|
158
|
+
// - Future output validation via outputSchema
|
|
159
|
+
// - Middleware execution
|
|
160
|
+
// - Logging/tracing hooks
|
|
161
|
+
// - Error normalization
|
|
162
|
+
return {
|
|
163
|
+
execute: async (ctx, input) => {
|
|
164
|
+
// Future: validate input against schema
|
|
165
|
+
// if (definition.inputSchema) {
|
|
166
|
+
// input = definition.inputSchema.parse(input);
|
|
167
|
+
// }
|
|
168
|
+
|
|
169
|
+
// Future: run pre-middleware
|
|
170
|
+
// for (const mw of definition.middleware ?? []) {
|
|
171
|
+
// await mw.before?.(ctx, input);
|
|
172
|
+
// }
|
|
173
|
+
|
|
174
|
+
// Future: validate output against schema
|
|
175
|
+
// if (definition.outputSchema) {
|
|
176
|
+
// definition.outputSchema.parse(result);
|
|
177
|
+
// }
|
|
178
|
+
|
|
179
|
+
// Future: run post-middleware
|
|
180
|
+
// for (const mw of definition.middleware ?? []) {
|
|
181
|
+
// await mw.after?.(ctx, input, result);
|
|
182
|
+
// }
|
|
183
|
+
|
|
184
|
+
return definition.execute(ctx, input);
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/studio
|
|
3
|
+
*
|
|
4
|
+
* Studio V2 types re-exported for convenience.
|
|
5
|
+
* Plugin authors use `@kb-labs/sdk/studio` instead.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type {
|
|
9
|
+
StudioConfig,
|
|
10
|
+
StudioPageEntry,
|
|
11
|
+
StudioMenuEntry,
|
|
12
|
+
} from '@kb-labs/plugin-contracts';
|