@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,622 @@
|
|
|
1
|
+
# Declarative Flags and Environment Variables
|
|
2
|
+
|
|
3
|
+
**For Plugin Developers**: Type-safe CLI flags and environment variables with automatic validation.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
KB Labs provides declarative systems for defining CLI flags and environment variables with:
|
|
8
|
+
|
|
9
|
+
✅ **Type Safety** — Automatic type inference from schema
|
|
10
|
+
✅ **Validation** — Built-in type checking + custom validators
|
|
11
|
+
✅ **DX** — 1 line of code instead of 5+
|
|
12
|
+
✅ **Self-Documenting** — Schema serves as documentation
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
### CLI Flags
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
// In your-plugin-contracts/src/flags.ts
|
|
20
|
+
import { defineFlags } from '@kb-labs/sdk';
|
|
21
|
+
|
|
22
|
+
export const myFlags = defineFlags({
|
|
23
|
+
scope: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
description: 'Limit to package or path',
|
|
26
|
+
examples: ['@kb-labs/core', 'packages/**'],
|
|
27
|
+
},
|
|
28
|
+
'dry-run': {
|
|
29
|
+
type: 'boolean',
|
|
30
|
+
description: 'Preview without applying',
|
|
31
|
+
default: false,
|
|
32
|
+
},
|
|
33
|
+
timeout: {
|
|
34
|
+
type: 'number',
|
|
35
|
+
description: 'Timeout in milliseconds',
|
|
36
|
+
default: 5000,
|
|
37
|
+
validate: (v) => {
|
|
38
|
+
if (v < 0) throw new Error('Timeout must be positive');
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export type MyFlags = typeof myFlags.type;
|
|
44
|
+
// Result: { scope?: string; 'dry-run': boolean; timeout: number }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// In your command
|
|
49
|
+
import { defineCommand } from '@kb-labs/sdk';
|
|
50
|
+
import { type MyFlags } from './contracts';
|
|
51
|
+
|
|
52
|
+
export default defineCommand({
|
|
53
|
+
handler: {
|
|
54
|
+
async execute(ctx, input: MyFlags) {
|
|
55
|
+
const { scope, 'dry-run': dryRun, timeout } = input;
|
|
56
|
+
// ✅ Fully typed, no manual parsing needed
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Environment Variables
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// In your-plugin-contracts/src/env.ts
|
|
66
|
+
import { defineEnv } from '@kb-labs/sdk';
|
|
67
|
+
|
|
68
|
+
export const myEnv = defineEnv({
|
|
69
|
+
MY_API_KEY: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: 'API key for service',
|
|
72
|
+
},
|
|
73
|
+
MY_ENABLED: {
|
|
74
|
+
type: 'boolean',
|
|
75
|
+
default: true,
|
|
76
|
+
description: 'Enable feature',
|
|
77
|
+
},
|
|
78
|
+
MY_TIMEOUT: {
|
|
79
|
+
type: 'number',
|
|
80
|
+
default: 5000,
|
|
81
|
+
description: 'Timeout in ms',
|
|
82
|
+
validate: (v) => {
|
|
83
|
+
if (v < 0) throw new Error('Timeout must be positive');
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export type MyEnv = typeof myEnv.type;
|
|
89
|
+
// Result: { MY_API_KEY?: string; MY_ENABLED: boolean; MY_TIMEOUT: number }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// In your command
|
|
94
|
+
const env = myEnv.parse(ctx.runtime);
|
|
95
|
+
// ✅ One line! Fully typed and validated
|
|
96
|
+
// env.MY_API_KEY → string | undefined
|
|
97
|
+
// env.MY_ENABLED → boolean
|
|
98
|
+
// env.MY_TIMEOUT → number
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Flag Types
|
|
102
|
+
|
|
103
|
+
### String Flags
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
export const flags = defineFlags({
|
|
107
|
+
name: {
|
|
108
|
+
type: 'string',
|
|
109
|
+
description: 'User name',
|
|
110
|
+
examples: ['john', 'jane'],
|
|
111
|
+
},
|
|
112
|
+
email: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
default: 'noreply@example.com',
|
|
115
|
+
validate: (v) => {
|
|
116
|
+
if (!v.includes('@')) throw new Error('Invalid email');
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
type Result = typeof flags.type;
|
|
122
|
+
// { name?: string; email: string }
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Key points**:
|
|
126
|
+
- Without `default`: optional (`string | undefined`)
|
|
127
|
+
- With `default`: required (`string`)
|
|
128
|
+
- Custom validation via `validate` function
|
|
129
|
+
|
|
130
|
+
### Boolean Flags
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
export const flags = defineFlags({
|
|
134
|
+
verbose: {
|
|
135
|
+
type: 'boolean',
|
|
136
|
+
description: 'Enable verbose logging',
|
|
137
|
+
default: false,
|
|
138
|
+
},
|
|
139
|
+
force: {
|
|
140
|
+
type: 'boolean',
|
|
141
|
+
description: 'Force operation',
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
type Result = typeof flags.type;
|
|
146
|
+
// { verbose: boolean; force?: boolean }
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Parsing**:
|
|
150
|
+
- `true`, `'true'`, `'1'`, `'yes'` → `true`
|
|
151
|
+
- `false`, `'false'`, `'0'`, `'no'` → `false`
|
|
152
|
+
|
|
153
|
+
### Number Flags
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
export const flags = defineFlags({
|
|
157
|
+
port: {
|
|
158
|
+
type: 'number',
|
|
159
|
+
default: 3000,
|
|
160
|
+
description: 'Server port',
|
|
161
|
+
validate: (v) => {
|
|
162
|
+
if (v < 1024 || v > 65535) {
|
|
163
|
+
throw new Error('Port must be 1024-65535');
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
retries: {
|
|
168
|
+
type: 'number',
|
|
169
|
+
description: 'Number of retries',
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
type Result = typeof flags.type;
|
|
174
|
+
// { port: number; retries?: number }
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Parsing**:
|
|
178
|
+
- Numbers: `3000` → `3000`
|
|
179
|
+
- Strings: `'3000'` → `3000`
|
|
180
|
+
- Invalid: `'abc'` → throws error
|
|
181
|
+
|
|
182
|
+
## Type Inference
|
|
183
|
+
|
|
184
|
+
The type system automatically infers correct types:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
export const flags = defineFlags({
|
|
188
|
+
// Without default → optional
|
|
189
|
+
scope: { type: 'string' },
|
|
190
|
+
|
|
191
|
+
// With default → required
|
|
192
|
+
verbose: { type: 'boolean', default: false },
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
type Inferred = typeof flags.type;
|
|
196
|
+
// { scope?: string; verbose: boolean }
|
|
197
|
+
// ^^^^^ optional ^^^^^^^ required
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Why This Matters
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
function doSomething(input: MyFlags) {
|
|
204
|
+
// ✅ TypeScript knows this might be undefined
|
|
205
|
+
if (input.scope) {
|
|
206
|
+
console.log(input.scope.toUpperCase());
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ✅ TypeScript knows this is always boolean
|
|
210
|
+
if (input.verbose) {
|
|
211
|
+
console.log('Verbose mode enabled');
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Validation
|
|
217
|
+
|
|
218
|
+
### Built-in Type Validation
|
|
219
|
+
|
|
220
|
+
Automatic for all types:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
// ❌ Runtime error: "Flag 'port' must be number, got string"
|
|
224
|
+
const flags = { port: 'invalid' };
|
|
225
|
+
myFlags.parse(flags);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Custom Validation
|
|
229
|
+
|
|
230
|
+
Add business logic validation:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
export const flags = defineFlags({
|
|
234
|
+
temperature: {
|
|
235
|
+
type: 'number',
|
|
236
|
+
default: 0.3,
|
|
237
|
+
validate: (v) => {
|
|
238
|
+
if (v < 0 || v > 1) {
|
|
239
|
+
throw new Error('Temperature must be 0-1');
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
email: {
|
|
244
|
+
type: 'string',
|
|
245
|
+
validate: (v) => {
|
|
246
|
+
if (!v.includes('@')) {
|
|
247
|
+
throw new Error('Invalid email format');
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Validation happens**:
|
|
255
|
+
- After type coercion
|
|
256
|
+
- Before returning to command
|
|
257
|
+
- Only if value is present (not for `undefined`)
|
|
258
|
+
|
|
259
|
+
## Environment Variables
|
|
260
|
+
|
|
261
|
+
### Basic Usage
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
// In contracts
|
|
265
|
+
export const myEnv = defineEnv({
|
|
266
|
+
MY_VAR: { type: 'boolean', default: true },
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// In command
|
|
270
|
+
const env = myEnv.parse(ctx.runtime);
|
|
271
|
+
console.log(env.MY_VAR); // boolean
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### With Validation
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
export const myEnv = defineEnv({
|
|
278
|
+
MY_TEMPERATURE: {
|
|
279
|
+
type: 'number',
|
|
280
|
+
default: 0.3,
|
|
281
|
+
validate: (v) => {
|
|
282
|
+
if (v < 0 || v > 1) {
|
|
283
|
+
throw new Error('MY_TEMPERATURE must be 0-1');
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Usage
|
|
290
|
+
MY_TEMPERATURE=1.5 pnpm kb my-command
|
|
291
|
+
// ❌ Error: MY_TEMPERATURE must be 0-1
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Real-World Example
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
// commit-contracts/src/env.ts
|
|
298
|
+
export const commitEnv = defineEnv({
|
|
299
|
+
KB_COMMIT_LLM_ENABLED: {
|
|
300
|
+
type: 'boolean',
|
|
301
|
+
default: true,
|
|
302
|
+
description: 'Enable LLM-powered commit analysis',
|
|
303
|
+
},
|
|
304
|
+
KB_COMMIT_LLM_TEMPERATURE: {
|
|
305
|
+
type: 'number',
|
|
306
|
+
default: 0.3,
|
|
307
|
+
description: 'LLM temperature (0-1)',
|
|
308
|
+
validate: (v) => {
|
|
309
|
+
if (v < 0 || v > 1) {
|
|
310
|
+
throw new Error('Temperature must be 0-1');
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
KB_COMMIT_LLM_MAX_TOKENS: {
|
|
315
|
+
type: 'number',
|
|
316
|
+
default: 2000,
|
|
317
|
+
description: 'Maximum tokens for LLM',
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// In command
|
|
322
|
+
const env = commitEnv.parse(ctx.runtime);
|
|
323
|
+
// env.KB_COMMIT_LLM_ENABLED → boolean
|
|
324
|
+
// env.KB_COMMIT_LLM_TEMPERATURE → number (validated 0-1)
|
|
325
|
+
// env.KB_COMMIT_LLM_MAX_TOKENS → number
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Migration Guide
|
|
329
|
+
|
|
330
|
+
### Before (Manual)
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
// ❌ OLD: Lots of boilerplate, no type safety
|
|
334
|
+
type MyInput = {
|
|
335
|
+
scope?: string;
|
|
336
|
+
'dry-run'?: boolean;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const env = {
|
|
340
|
+
MY_ENABLED: ctx.runtime.env('MY_ENABLED'),
|
|
341
|
+
MY_TEMPERATURE: ctx.runtime.env('MY_TEMPERATURE'),
|
|
342
|
+
MY_MAX_TOKENS: ctx.runtime.env('MY_MAX_TOKENS'),
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
// Manual parsing
|
|
346
|
+
let enabled = true;
|
|
347
|
+
if (env.MY_ENABLED !== undefined) {
|
|
348
|
+
enabled = env.MY_ENABLED === 'true';
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
let temperature = 0.3;
|
|
352
|
+
if (env.MY_TEMPERATURE !== undefined) {
|
|
353
|
+
const temp = parseFloat(env.MY_TEMPERATURE);
|
|
354
|
+
if (!isNaN(temp) && temp >= 0 && temp <= 1) {
|
|
355
|
+
temperature = temp;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Use values
|
|
360
|
+
const dryRun = input['dry-run'] ?? false;
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### After (Declarative)
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
// ✅ NEW: Clean, type-safe, validated
|
|
367
|
+
export const myFlags = defineFlags({
|
|
368
|
+
scope: { type: 'string' },
|
|
369
|
+
'dry-run': { type: 'boolean', default: false },
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
export const myEnv = defineEnv({
|
|
373
|
+
MY_ENABLED: { type: 'boolean', default: true },
|
|
374
|
+
MY_TEMPERATURE: {
|
|
375
|
+
type: 'number',
|
|
376
|
+
default: 0.3,
|
|
377
|
+
validate: (v) => {
|
|
378
|
+
if (v < 0 || v > 1) throw new Error('Must be 0-1');
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// In command
|
|
384
|
+
const env = myEnv.parse(ctx.runtime);
|
|
385
|
+
const { scope, 'dry-run': dryRun } = input;
|
|
386
|
+
|
|
387
|
+
// ✅ 2 lines instead of 20+, fully typed
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Best Practices
|
|
391
|
+
|
|
392
|
+
### 1. Always Add Descriptions
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// ✅ GOOD: Self-documenting
|
|
396
|
+
export const flags = defineFlags({
|
|
397
|
+
scope: {
|
|
398
|
+
type: 'string',
|
|
399
|
+
description: 'Limit operation to specific scope',
|
|
400
|
+
examples: ['@kb-labs/core', 'packages/**'],
|
|
401
|
+
},
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// ❌ BAD: No documentation
|
|
405
|
+
export const flags = defineFlags({
|
|
406
|
+
scope: { type: 'string' },
|
|
407
|
+
});
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### 2. Use Defaults for Required Values
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
// ✅ GOOD: Required boolean with default
|
|
414
|
+
export const flags = defineFlags({
|
|
415
|
+
verbose: {
|
|
416
|
+
type: 'boolean',
|
|
417
|
+
default: false, // Always boolean, never undefined
|
|
418
|
+
},
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// ⚠️ CAUTION: Optional boolean
|
|
422
|
+
export const flags = defineFlags({
|
|
423
|
+
verbose: { type: 'boolean' }, // boolean | undefined
|
|
424
|
+
});
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### 3. Validate Business Logic
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
// ✅ GOOD: Domain validation
|
|
431
|
+
export const flags = defineFlags({
|
|
432
|
+
port: {
|
|
433
|
+
type: 'number',
|
|
434
|
+
validate: (v) => {
|
|
435
|
+
if (v < 1024 || v > 65535) {
|
|
436
|
+
throw new Error('Port must be 1024-65535');
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// ❌ BAD: No validation, runtime errors possible
|
|
443
|
+
export const flags = defineFlags({
|
|
444
|
+
port: { type: 'number' },
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### 4. Group Related Flags
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
// ✅ GOOD: Organized by feature
|
|
452
|
+
export const llmFlags = defineFlags({
|
|
453
|
+
'llm-temperature': { type: 'number', default: 0.3 },
|
|
454
|
+
'llm-max-tokens': { type: 'number', default: 2000 },
|
|
455
|
+
'llm-enabled': { type: 'boolean', default: true },
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
export const gitFlags = defineFlags({
|
|
459
|
+
'git-auto-stage': { type: 'boolean', default: false },
|
|
460
|
+
'git-push': { type: 'boolean', default: false },
|
|
461
|
+
});
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
## Error Handling
|
|
465
|
+
|
|
466
|
+
### Type Errors
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
const flags = defineFlags({
|
|
470
|
+
port: { type: 'number' },
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// ❌ Error: Flag "port" must be number, got string
|
|
474
|
+
flags.parse({ port: 'invalid' });
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Validation Errors
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
const flags = defineFlags({
|
|
481
|
+
temperature: {
|
|
482
|
+
type: 'number',
|
|
483
|
+
validate: (v) => {
|
|
484
|
+
if (v < 0 || v > 1) {
|
|
485
|
+
throw new Error('Temperature must be 0-1');
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// ❌ Error: Temperature must be 0-1
|
|
492
|
+
flags.parse({ temperature: 1.5 });
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### Graceful Handling
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
try {
|
|
499
|
+
const env = myEnv.parse(ctx.runtime);
|
|
500
|
+
// Use env
|
|
501
|
+
} catch (error) {
|
|
502
|
+
ctx.ui?.error?.(`Invalid environment: ${error.message}`);
|
|
503
|
+
return { exitCode: 1 };
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Advanced Patterns
|
|
508
|
+
|
|
509
|
+
### Combining Flags and Env
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
// Flags for CLI args
|
|
513
|
+
export const myFlags = defineFlags({
|
|
514
|
+
scope: { type: 'string' },
|
|
515
|
+
verbose: { type: 'boolean', default: false },
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
// Env for configuration
|
|
519
|
+
export const myEnv = defineEnv({
|
|
520
|
+
MY_API_KEY: { type: 'string' },
|
|
521
|
+
MY_ENABLED: { type: 'boolean', default: true },
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
// In command
|
|
525
|
+
const env = myEnv.parse(ctx.runtime);
|
|
526
|
+
const { scope, verbose } = input;
|
|
527
|
+
|
|
528
|
+
// Merge: flags override env
|
|
529
|
+
const enabled = input.enabled ?? env.MY_ENABLED;
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Conditional Validation
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
export const flags = defineFlags({
|
|
536
|
+
mode: { type: 'string', default: 'auto' },
|
|
537
|
+
temperature: {
|
|
538
|
+
type: 'number',
|
|
539
|
+
default: 0.3,
|
|
540
|
+
validate: (v) => {
|
|
541
|
+
// Only validate if mode is 'thinking'
|
|
542
|
+
// (actual check done in command)
|
|
543
|
+
if (v < 0 || v > 1) {
|
|
544
|
+
throw new Error('Temperature must be 0-1');
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
},
|
|
548
|
+
});
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Dynamic Defaults
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
export const flags = defineFlags({
|
|
555
|
+
output: {
|
|
556
|
+
type: 'string',
|
|
557
|
+
// No default here - set dynamically in command
|
|
558
|
+
},
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
// In command
|
|
562
|
+
const output = input.output ?? `.kb/output-${Date.now()}.json`;
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
## Reference
|
|
566
|
+
|
|
567
|
+
### Flag Spec
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
interface StringFlagSpec {
|
|
571
|
+
type: 'string';
|
|
572
|
+
description?: string;
|
|
573
|
+
examples?: string[];
|
|
574
|
+
deprecated?: boolean | string;
|
|
575
|
+
default?: string;
|
|
576
|
+
validate?: (value: string) => void | Promise<void>;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
interface BooleanFlagSpec {
|
|
580
|
+
type: 'boolean';
|
|
581
|
+
description?: string;
|
|
582
|
+
deprecated?: boolean | string;
|
|
583
|
+
default?: boolean;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
interface NumberFlagSpec {
|
|
587
|
+
type: 'number';
|
|
588
|
+
description?: string;
|
|
589
|
+
deprecated?: boolean | string;
|
|
590
|
+
default?: number;
|
|
591
|
+
validate?: (value: number) => void | Promise<void>;
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### API
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
// Define flags
|
|
599
|
+
const flags = defineFlags({ ... });
|
|
600
|
+
// → FlagsDefinition<T>
|
|
601
|
+
|
|
602
|
+
// Get inferred type
|
|
603
|
+
type MyFlags = typeof flags.type;
|
|
604
|
+
// → InferFlagsType<T>
|
|
605
|
+
|
|
606
|
+
// Parse flags
|
|
607
|
+
const parsed = flags.parse(input);
|
|
608
|
+
// → InferFlagsType<T>
|
|
609
|
+
|
|
610
|
+
// Define env
|
|
611
|
+
const env = defineEnv({ ... });
|
|
612
|
+
// → EnvDefinition<T>
|
|
613
|
+
|
|
614
|
+
// Parse env
|
|
615
|
+
const parsed = env.parse(runtime);
|
|
616
|
+
// → InferFlagsType<T>
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
## See Also
|
|
620
|
+
|
|
621
|
+
- [ADR-0006: Declarative Flags and Env Systems](./adr/0006-declarative-flags-and-env-systems.md)
|
|
622
|
+
- [V3 Plugin System Spec](../../docs/V3-IMPLEMENTATION-SPEC.md)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# KB Labs Shared Documentation Standard
|
|
2
|
+
|
|
3
|
+
> **This document is a project-specific copy of the KB Labs Documentation Standard.**
|
|
4
|
+
> See [Main Documentation Standard](https://github.com/KirillBaranov/kb-labs/blob/main/docs/DOCUMENTATION.md) for the complete ecosystem standard.
|
|
5
|
+
|
|
6
|
+
This document defines the documentation standards for **KB Labs Shared**. This project follows the [KB Labs Documentation Standard](https://github.com/KirillBaranov/kb-labs/blob/main/docs/DOCUMENTATION.md) with the following project-specific customizations:
|
|
7
|
+
|
|
8
|
+
## Project-Specific Customizations
|
|
9
|
+
|
|
10
|
+
KB Labs Shared provides building blocks for all KB Labs plugins. Documentation should focus on:
|
|
11
|
+
|
|
12
|
+
- Platform composables and command definitions (`shared-command-kit`)
|
|
13
|
+
- CLI UI formatting utilities (`shared-cli-ui`)
|
|
14
|
+
- Permission presets for plugin manifests (`perm-presets`)
|
|
15
|
+
- Mock builders and test helpers (`shared-testing`)
|
|
16
|
+
- Tool factory for agent tools (`shared-tool-kit`)
|
|
17
|
+
|
|
18
|
+
## Project Documentation Structure
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
docs/
|
|
22
|
+
├── DOCUMENTATION.md # This standard (REQUIRED)
|
|
23
|
+
└── adr/ # Architecture Decision Records
|
|
24
|
+
├── 0000-template.md # ADR template
|
|
25
|
+
└── *.md # ADR files
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Required Documentation
|
|
29
|
+
|
|
30
|
+
This project requires:
|
|
31
|
+
|
|
32
|
+
- [x] `README.md` in root with all required sections
|
|
33
|
+
- [x] `CONTRIBUTING.md` in root with development guidelines
|
|
34
|
+
- [x] `docs/DOCUMENTATION.md` (this file)
|
|
35
|
+
- [ ] `docs/adr/0000-template.md` (ADR template - should be created from main standard)
|
|
36
|
+
- [x] `LICENSE` in root
|
|
37
|
+
|
|
38
|
+
## ADR Requirements
|
|
39
|
+
|
|
40
|
+
All ADRs must follow the format defined in the [main standard](https://github.com/KirillBaranov/kb-labs/blob/main/docs/DOCUMENTATION.md#architecture-decision-records-adr) with:
|
|
41
|
+
|
|
42
|
+
- Required metadata: Date, Status, Deciders, Last Reviewed, Tags
|
|
43
|
+
- Minimum 1 tag, maximum 5 tags
|
|
44
|
+
- Tags from approved list
|
|
45
|
+
- See main standard `docs/templates/ADR.template.md` for template
|
|
46
|
+
|
|
47
|
+
## Cross-Linking
|
|
48
|
+
|
|
49
|
+
This project links to:
|
|
50
|
+
|
|
51
|
+
**Dependencies:**
|
|
52
|
+
- None (shared utilities only)
|
|
53
|
+
|
|
54
|
+
**Used By:**
|
|
55
|
+
- [@kb-labs/core](https://github.com/KirillBaranov/kb-labs-core) - Core utilities
|
|
56
|
+
- [@kb-labs/cli](https://github.com/KirillBaranov/kb-labs-cli) - CLI wrapper
|
|
57
|
+
- [@kb-labs/ai-review](https://github.com/KirillBaranov/kb-labs-ai-review) - AI Review
|
|
58
|
+
- All other KB Labs products
|
|
59
|
+
|
|
60
|
+
**Ecosystem:**
|
|
61
|
+
- [KB Labs](https://github.com/KirillBaranov/kb-labs) - Main ecosystem repository
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
**Last Updated:** 2026-02-24
|
|
66
|
+
**Standard Version:** 1.0 (following KB Labs ecosystem standard)
|
|
67
|
+
**See Main Standard:** [KB Labs Documentation Standard](https://github.com/KirillBaranov/kb-labs/blob/main/docs/DOCUMENTATION.md)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|