@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,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-llm
|
|
3
|
+
* Global LLM access helper with tier-based model selection.
|
|
4
|
+
*
|
|
5
|
+
* Provides clean access to LLM with adaptive tier routing.
|
|
6
|
+
* Plugins specify tiers (small/medium/large), platform resolves to actual models.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { useLLM } from '@kb-labs/shared-command-kit';
|
|
11
|
+
*
|
|
12
|
+
* async handler(ctx, argv, flags) {
|
|
13
|
+
* // Simple usage (uses configured default tier)
|
|
14
|
+
* const llm = useLLM();
|
|
15
|
+
*
|
|
16
|
+
* // Request specific tier (platform adapts if needed)
|
|
17
|
+
* const llm = useLLM({ tier: 'small' }); // Simple tasks
|
|
18
|
+
* const llm = useLLM({ tier: 'large' }); // Complex tasks
|
|
19
|
+
*
|
|
20
|
+
* // Request capabilities
|
|
21
|
+
* const llm = useLLM({ tier: 'medium', capabilities: ['coding'] });
|
|
22
|
+
*
|
|
23
|
+
* if (llm) {
|
|
24
|
+
* const result = await llm.complete('Explain this code');
|
|
25
|
+
* console.log(result.content);
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { usePlatform } from './use-platform.js';
|
|
32
|
+
import type {
|
|
33
|
+
ILLM,
|
|
34
|
+
LLMTier,
|
|
35
|
+
LLMOptions,
|
|
36
|
+
LLMResponse,
|
|
37
|
+
LLMMessage,
|
|
38
|
+
LLMToolCallOptions,
|
|
39
|
+
LLMToolCallResponse,
|
|
40
|
+
UseLLMOptions,
|
|
41
|
+
ILLMRouter,
|
|
42
|
+
LLMAdapterBinding,
|
|
43
|
+
LLMExecutionPolicy,
|
|
44
|
+
LLMProtocolCapabilities,
|
|
45
|
+
LLMCacheDecisionTrace,
|
|
46
|
+
} from '@kb-labs/core-platform';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Access global LLM adapter with tier-based selection.
|
|
50
|
+
*
|
|
51
|
+
* Platform automatically adapts to available models:
|
|
52
|
+
* - If plugin requests 'small' but 'medium' configured → uses 'medium' (escalation)
|
|
53
|
+
* - If plugin requests 'large' but 'medium' configured → uses 'medium' with warning (degradation)
|
|
54
|
+
*
|
|
55
|
+
* **Tiers are user-defined slots:**
|
|
56
|
+
* - `small` - Plugin says: "This task is simple"
|
|
57
|
+
* - `medium` - Plugin says: "Standard task"
|
|
58
|
+
* - `large` - Plugin says: "Complex task, need maximum quality"
|
|
59
|
+
*
|
|
60
|
+
* User decides what model maps to each tier in their config.
|
|
61
|
+
*
|
|
62
|
+
* @param options - Optional tier and capability requirements
|
|
63
|
+
* @returns LLM adapter or undefined if not configured
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* // Simple usage (uses configured default)
|
|
68
|
+
* const llm = useLLM();
|
|
69
|
+
*
|
|
70
|
+
* // Request specific tier
|
|
71
|
+
* const llm = useLLM({ tier: 'small' }); // Simple tasks
|
|
72
|
+
* const llm = useLLM({ tier: 'large' }); // Complex tasks
|
|
73
|
+
*
|
|
74
|
+
* // Request capabilities
|
|
75
|
+
* const llm = useLLM({ tier: 'medium', capabilities: ['coding'] });
|
|
76
|
+
* const llm = useLLM({ capabilities: ['vision'] });
|
|
77
|
+
*
|
|
78
|
+
* if (llm) {
|
|
79
|
+
* const result = await llm.complete('Generate commit message');
|
|
80
|
+
* console.log(result.content);
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function useLLM(options?: UseLLMOptions): ILLM | undefined {
|
|
85
|
+
const platform = usePlatform();
|
|
86
|
+
const llm = platform.llm;
|
|
87
|
+
|
|
88
|
+
if (!llm) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// If router and options given → return immutable LazyBoundLLM (no state mutation)
|
|
93
|
+
if (options && isLLMRouter(llm)) {
|
|
94
|
+
return new LazyBoundLLM(llm, options);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return llm;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Lazy adapter binding that resolves tier on first use.
|
|
102
|
+
* Immutable — does NOT mutate the global LLMRouter state.
|
|
103
|
+
* This fixes the race condition where useLLM({ tier: 'large' }) was immediately
|
|
104
|
+
* overwritten by useLLM({ tier: 'small' }) from SmartSummarizer.
|
|
105
|
+
*/
|
|
106
|
+
class LazyBoundLLM implements ILLM {
|
|
107
|
+
private _resolved: Promise<LLMAdapterBinding> | null = null;
|
|
108
|
+
|
|
109
|
+
constructor(
|
|
110
|
+
private readonly router: ILLM & ILLMRouter,
|
|
111
|
+
private readonly options: UseLLMOptions,
|
|
112
|
+
) {}
|
|
113
|
+
|
|
114
|
+
private resolve(): Promise<LLMAdapterBinding> {
|
|
115
|
+
if (!this._resolved) {
|
|
116
|
+
this._resolved = this.router.resolveAdapter(this.options);
|
|
117
|
+
}
|
|
118
|
+
return this._resolved;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private mergeExecutionPolicy(callOptions?: LLMOptions): LLMExecutionPolicy | undefined {
|
|
122
|
+
const globalPolicy = this.options.execution;
|
|
123
|
+
const localPolicy = callOptions?.execution;
|
|
124
|
+
if (!globalPolicy && !localPolicy) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
...globalPolicy,
|
|
129
|
+
...localPolicy,
|
|
130
|
+
cache: { ...globalPolicy?.cache, ...localPolicy?.cache },
|
|
131
|
+
stream: { ...globalPolicy?.stream, ...localPolicy?.stream },
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private async resolveProtocolCapabilities(adapter: ILLM): Promise<LLMProtocolCapabilities> {
|
|
136
|
+
if (!adapter.getProtocolCapabilities) {
|
|
137
|
+
return {
|
|
138
|
+
cache: { supported: false },
|
|
139
|
+
stream: { supported: true },
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return adapter.getProtocolCapabilities();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private enforceCachePolicy(caps: LLMProtocolCapabilities, execution?: LLMExecutionPolicy): void {
|
|
146
|
+
if (execution?.cache?.mode === 'require' && !caps.cache.supported) {
|
|
147
|
+
throw new Error('CACHE_NOT_SUPPORTED: adapter does not support required cache policy');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private buildDecisionTrace(
|
|
152
|
+
caps: LLMProtocolCapabilities,
|
|
153
|
+
execution: LLMExecutionPolicy | undefined,
|
|
154
|
+
streamAppliedMode: 'prefer' | 'require' | 'off',
|
|
155
|
+
streamFallback?: 'complete',
|
|
156
|
+
reason?: string,
|
|
157
|
+
): LLMCacheDecisionTrace {
|
|
158
|
+
const requestedCacheMode = execution?.cache?.mode ?? 'prefer';
|
|
159
|
+
const requestedStreamMode = execution?.stream?.mode ?? 'prefer';
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
cacheRequestedMode: requestedCacheMode,
|
|
163
|
+
cacheSupported: caps.cache.supported,
|
|
164
|
+
cacheAppliedMode:
|
|
165
|
+
requestedCacheMode === 'require' || requestedCacheMode === 'bypass'
|
|
166
|
+
? requestedCacheMode
|
|
167
|
+
: caps.cache.supported
|
|
168
|
+
? 'prefer'
|
|
169
|
+
: 'bypass',
|
|
170
|
+
streamRequestedMode: requestedStreamMode,
|
|
171
|
+
streamSupported: caps.stream.supported,
|
|
172
|
+
streamAppliedMode,
|
|
173
|
+
streamFallback,
|
|
174
|
+
reason,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private withDecisionMetadata(
|
|
179
|
+
options: LLMOptions | undefined,
|
|
180
|
+
trace: LLMCacheDecisionTrace,
|
|
181
|
+
): LLMOptions | undefined {
|
|
182
|
+
if (!options) {
|
|
183
|
+
return { metadata: { cacheDecisionTrace: trace } };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
...options,
|
|
188
|
+
metadata: {
|
|
189
|
+
...options.metadata,
|
|
190
|
+
cacheDecisionTrace: trace,
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async complete(prompt: string, options?: LLMOptions): Promise<LLMResponse> {
|
|
196
|
+
const { adapter, model } = await this.resolve();
|
|
197
|
+
const execution = this.mergeExecutionPolicy(options);
|
|
198
|
+
const caps = await this.resolveProtocolCapabilities(adapter);
|
|
199
|
+
this.enforceCachePolicy(caps, execution);
|
|
200
|
+
const trace = this.buildDecisionTrace(caps, execution, 'off');
|
|
201
|
+
const optionsWithTrace = this.withDecisionMetadata(options, trace);
|
|
202
|
+
return adapter.complete(prompt, { ...optionsWithTrace, model, execution });
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async *stream(prompt: string, options?: LLMOptions): AsyncIterable<string> {
|
|
206
|
+
const { adapter, model } = await this.resolve();
|
|
207
|
+
const execution = this.mergeExecutionPolicy(options);
|
|
208
|
+
const caps = await this.resolveProtocolCapabilities(adapter);
|
|
209
|
+
this.enforceCachePolicy(caps, execution);
|
|
210
|
+
|
|
211
|
+
const streamMode = execution?.stream?.mode ?? 'prefer';
|
|
212
|
+
const canStream = caps.stream.supported;
|
|
213
|
+
const allowFallback = execution?.stream?.fallbackToComplete ?? true;
|
|
214
|
+
|
|
215
|
+
if (streamMode === 'off' || (!canStream && streamMode === 'prefer' && allowFallback)) {
|
|
216
|
+
const fallbackReason =
|
|
217
|
+
streamMode === 'off'
|
|
218
|
+
? 'STREAM_OFF'
|
|
219
|
+
: 'STREAM_UNSUPPORTED_FALLBACK_TO_COMPLETE';
|
|
220
|
+
const trace = this.buildDecisionTrace(caps, execution, 'off', 'complete', fallbackReason);
|
|
221
|
+
const optionsWithTrace = this.withDecisionMetadata(options, trace);
|
|
222
|
+
const response = await adapter.complete(prompt, { ...optionsWithTrace, model, execution });
|
|
223
|
+
if (response.content) {
|
|
224
|
+
yield response.content;
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (!canStream && streamMode === 'require') {
|
|
230
|
+
throw new Error('STREAM_NOT_SUPPORTED: adapter does not support required streaming');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const trace = this.buildDecisionTrace(caps, execution, streamMode);
|
|
234
|
+
const optionsWithTrace = this.withDecisionMetadata(options, trace);
|
|
235
|
+
yield* adapter.stream(prompt, { ...optionsWithTrace, model, execution });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async chatWithTools(
|
|
239
|
+
messages: LLMMessage[],
|
|
240
|
+
options: LLMToolCallOptions,
|
|
241
|
+
): Promise<LLMToolCallResponse> {
|
|
242
|
+
const { adapter, model, tier } = await this.resolve();
|
|
243
|
+
const execution = this.mergeExecutionPolicy(options);
|
|
244
|
+
const caps = await this.resolveProtocolCapabilities(adapter);
|
|
245
|
+
this.enforceCachePolicy(caps, execution);
|
|
246
|
+
if (!adapter.chatWithTools) {
|
|
247
|
+
throw new Error('Current adapter does not support chatWithTools');
|
|
248
|
+
}
|
|
249
|
+
const trace = this.buildDecisionTrace(caps, execution, 'off');
|
|
250
|
+
const optionsWithTrace = this.withDecisionMetadata(options, trace) as LLMToolCallOptions;
|
|
251
|
+
return adapter.chatWithTools(messages, {
|
|
252
|
+
...optionsWithTrace,
|
|
253
|
+
model,
|
|
254
|
+
execution,
|
|
255
|
+
metadata: { ...optionsWithTrace.metadata, tier },
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Check if LLM is available.
|
|
262
|
+
*
|
|
263
|
+
* Useful for conditional logic (LLM-powered vs deterministic fallback).
|
|
264
|
+
*
|
|
265
|
+
* @returns true if LLM is configured and ready
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```typescript
|
|
269
|
+
* if (isLLMAvailable()) {
|
|
270
|
+
* const summary = await generateWithLLM(data);
|
|
271
|
+
* } else {
|
|
272
|
+
* const summary = generateDeterministic(data);
|
|
273
|
+
* }
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
export function isLLMAvailable(): boolean {
|
|
277
|
+
const llm = useLLM();
|
|
278
|
+
return !!llm;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Get configured LLM tier.
|
|
283
|
+
*
|
|
284
|
+
* Useful for diagnostics and logging.
|
|
285
|
+
*
|
|
286
|
+
* @returns Configured tier or undefined if LLM not available/not a router
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```typescript
|
|
290
|
+
* const tier = getLLMTier();
|
|
291
|
+
* console.log(`Using LLM tier: ${tier ?? 'default'}`);
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
export function getLLMTier(): LLMTier | undefined {
|
|
295
|
+
const platform = usePlatform();
|
|
296
|
+
const llm = platform.llm;
|
|
297
|
+
|
|
298
|
+
if (llm && isLLMRouter(llm)) {
|
|
299
|
+
return llm.getConfiguredTier();
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Type guard for ILLMRouter.
|
|
307
|
+
*/
|
|
308
|
+
function isLLMRouter(llm: ILLM): llm is ILLM & ILLMRouter {
|
|
309
|
+
return (
|
|
310
|
+
typeof (llm as unknown as ILLMRouter).getConfiguredTier === 'function' &&
|
|
311
|
+
typeof (llm as unknown as ILLMRouter).resolve === 'function'
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Re-export types for convenience
|
|
316
|
+
export type { LLMTier, UseLLMOptions } from '@kb-labs/core-platform';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-logger
|
|
3
|
+
* Global logger access helper
|
|
4
|
+
*
|
|
5
|
+
* Provides clean access to structured logging without context drilling.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { useLogger } from '@kb-labs/shared-command-kit';
|
|
10
|
+
*
|
|
11
|
+
* async handler(ctx, argv, flags) {
|
|
12
|
+
* const logger = useLogger();
|
|
13
|
+
*
|
|
14
|
+
* await logger.info('Processing started');
|
|
15
|
+
* await logger.debug('Details', { userId: 123 });
|
|
16
|
+
* await logger.error('Failed', { error: err });
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { usePlatform } from './use-platform';
|
|
22
|
+
import type { ILogger } from '@kb-labs/core-platform';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Access global logger
|
|
26
|
+
*
|
|
27
|
+
* Returns the platform logger with structured logging capabilities.
|
|
28
|
+
* Supports child loggers with additional context.
|
|
29
|
+
*
|
|
30
|
+
* **Methods:**
|
|
31
|
+
* - `logger.trace(message, meta?)` - Trace-level logs (most verbose)
|
|
32
|
+
* - `logger.debug(message, meta?)` - Debug-level logs
|
|
33
|
+
* - `logger.info(message, meta?)` - Info-level logs
|
|
34
|
+
* - `logger.warn(message, meta?)` - Warning-level logs
|
|
35
|
+
* - `logger.error(message, meta?)` - Error-level logs
|
|
36
|
+
* - `logger.child(meta)` - Create child logger with additional context
|
|
37
|
+
*
|
|
38
|
+
* @returns Platform logger instance
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const logger = useLogger();
|
|
43
|
+
*
|
|
44
|
+
* await logger.info('Task started', { taskId: '123' });
|
|
45
|
+
* await logger.error('Task failed', { taskId: '123', error: err.message });
|
|
46
|
+
*
|
|
47
|
+
* // Child logger with persistent context
|
|
48
|
+
* const taskLogger = logger.child({ taskId: '123', userId: 'user-1' });
|
|
49
|
+
* await taskLogger.info('Step 1 completed');
|
|
50
|
+
* await taskLogger.info('Step 2 completed');
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function useLogger(): ILogger {
|
|
54
|
+
const platform = usePlatform();
|
|
55
|
+
return platform.logger;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Create child logger with additional context
|
|
60
|
+
*
|
|
61
|
+
* Useful for scoped logging within a specific operation.
|
|
62
|
+
*
|
|
63
|
+
* @param context - Additional context to attach to all log entries
|
|
64
|
+
* @returns Child logger with persistent context
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const logger = useLoggerWithContext({ operation: 'release', version: '1.0.0' });
|
|
69
|
+
*
|
|
70
|
+
* await logger.info('Started'); // Automatically includes operation + version
|
|
71
|
+
* await logger.info('Completed');
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export function useLoggerWithContext(context: Record<string, unknown>): ILogger {
|
|
75
|
+
const logger = useLogger();
|
|
76
|
+
return logger.child(context);
|
|
77
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-platform
|
|
3
|
+
* Global platform singleton access helper
|
|
4
|
+
*
|
|
5
|
+
* Provides clean access to platform services without context drilling.
|
|
6
|
+
* Similar to React hooks pattern, but for KB Labs platform.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { usePlatform } from '@kb-labs/shared-command-kit';
|
|
11
|
+
*
|
|
12
|
+
* // In any command handler
|
|
13
|
+
* async handler(ctx, argv, flags) {
|
|
14
|
+
* const platform = usePlatform();
|
|
15
|
+
*
|
|
16
|
+
* if (platform.llm) {
|
|
17
|
+
* const result = await platform.llm.complete('prompt');
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* await platform.logger.info('Task completed');
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { platform as globalPlatform } from '@kb-labs/core-runtime';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Access global platform singleton
|
|
29
|
+
*
|
|
30
|
+
* Returns the initialized platform object with all registered adapters.
|
|
31
|
+
* This is the single source of truth for platform services.
|
|
32
|
+
*
|
|
33
|
+
* **What's available:**
|
|
34
|
+
* - `platform.llm` - LLM adapter (OpenAI, Anthropic, etc.)
|
|
35
|
+
* - `platform.embeddings` - Embeddings adapter
|
|
36
|
+
* - `platform.vectorStore` - Vector storage (Qdrant, local, etc.)
|
|
37
|
+
* - `platform.storage` - File/blob storage
|
|
38
|
+
* - `platform.cache` - Caching layer
|
|
39
|
+
* - `platform.analytics` - Analytics/telemetry
|
|
40
|
+
* - `platform.logger` - Structured logging
|
|
41
|
+
* - `platform.eventBus` - Event system
|
|
42
|
+
* - `platform.workflows` - Workflow engine
|
|
43
|
+
* - `platform.jobs` - Background jobs
|
|
44
|
+
* - `platform.cron` - Scheduled tasks
|
|
45
|
+
* - `platform.resources` - Resource management
|
|
46
|
+
* - `platform.invoke` - Plugin invocation
|
|
47
|
+
* - `platform.artifacts` - Build artifacts
|
|
48
|
+
*
|
|
49
|
+
* **Graceful degradation:**
|
|
50
|
+
* Always check if adapter is available before using:
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const platform = usePlatform();
|
|
53
|
+
* if (platform.llm) {
|
|
54
|
+
* // Use LLM
|
|
55
|
+
* } else {
|
|
56
|
+
* // Fallback logic
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* **Multi-tenancy:**
|
|
61
|
+
* Currently returns global singleton (single-tenant).
|
|
62
|
+
* Future: Will support tenant-scoped platform via AsyncLocalStorage.
|
|
63
|
+
*
|
|
64
|
+
* @returns Global platform singleton
|
|
65
|
+
*/
|
|
66
|
+
export function usePlatform(): typeof globalPlatform {
|
|
67
|
+
return globalPlatform;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if specific platform adapter is configured
|
|
72
|
+
*
|
|
73
|
+
* Useful for conditional logic based on available services.
|
|
74
|
+
*
|
|
75
|
+
* @param adapterName - Name of the adapter to check
|
|
76
|
+
* @returns true if adapter is configured and available
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* if (isPlatformConfigured('llm')) {
|
|
81
|
+
* // Use LLM-powered feature
|
|
82
|
+
* } else {
|
|
83
|
+
* // Use deterministic fallback
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export function isPlatformConfigured(adapterName: keyof typeof globalPlatform): boolean {
|
|
88
|
+
const platform = usePlatform();
|
|
89
|
+
|
|
90
|
+
// Check if adapter exists and is not a noop/fallback
|
|
91
|
+
const adapter = platform[adapterName];
|
|
92
|
+
|
|
93
|
+
if (!adapter) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// For adapters with hasAdapter method (like platform itself)
|
|
98
|
+
if ('hasAdapter' in platform && typeof platform.hasAdapter === 'function') {
|
|
99
|
+
return platform.hasAdapter(adapterName as any);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Fallback: check if adapter is not noop
|
|
103
|
+
// Noop adapters usually have a specific constructor name or are simple objects
|
|
104
|
+
if (typeof adapter === 'object' && adapter.constructor) {
|
|
105
|
+
const constructorName = adapter.constructor.name;
|
|
106
|
+
return !constructorName.toLowerCase().includes('noop') &&
|
|
107
|
+
!constructorName.toLowerCase().includes('fallback');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-resource-broker
|
|
3
|
+
* Global ResourceBroker access helper
|
|
4
|
+
*
|
|
5
|
+
* Provides clean access to ResourceBroker for queue and rate limiting.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { useResourceBroker } from '@kb-labs/shared-command-kit';
|
|
10
|
+
*
|
|
11
|
+
* async handler(ctx, argv, flags) {
|
|
12
|
+
* const broker = useResourceBroker();
|
|
13
|
+
*
|
|
14
|
+
* // Get statistics
|
|
15
|
+
* const stats = broker.getStats();
|
|
16
|
+
* console.log(`Queue size: ${stats.queueSize}`);
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { usePlatform } from './use-platform.js';
|
|
22
|
+
import type { IResourceBroker } from '@kb-labs/core-resource-broker';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Access global ResourceBroker
|
|
26
|
+
*
|
|
27
|
+
* Returns the platform ResourceBroker for queue management, rate limiting,
|
|
28
|
+
* and retry logic for heavy operations (LLM, embeddings, vector store).
|
|
29
|
+
*
|
|
30
|
+
* **Features:**
|
|
31
|
+
* - Priority queue (high/normal/low)
|
|
32
|
+
* - Rate limiting with configurable backend
|
|
33
|
+
* - Automatic retry with exponential backoff
|
|
34
|
+
* - Per-resource statistics
|
|
35
|
+
*
|
|
36
|
+
* **Note:** Most plugins don't need this directly.
|
|
37
|
+
* Use `useLLM()`, `useEmbeddings()`, etc. which automatically
|
|
38
|
+
* route through the ResourceBroker.
|
|
39
|
+
*
|
|
40
|
+
* @returns ResourceBroker instance
|
|
41
|
+
* @throws Error if ResourceBroker not initialized
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const broker = useResourceBroker();
|
|
46
|
+
*
|
|
47
|
+
* // Get queue statistics
|
|
48
|
+
* const stats = broker.getStats();
|
|
49
|
+
* console.log(`Total requests: ${stats.totalRequests}`);
|
|
50
|
+
* console.log(`Queue size: ${stats.queueSize}`);
|
|
51
|
+
*
|
|
52
|
+
* // Check if resource is registered
|
|
53
|
+
* if (broker.hasResource('llm')) {
|
|
54
|
+
* console.log('LLM is available for queueing');
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function useResourceBroker(): IResourceBroker {
|
|
59
|
+
const platform = usePlatform();
|
|
60
|
+
return platform.resourceBroker;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Check if ResourceBroker is available
|
|
65
|
+
*
|
|
66
|
+
* Useful for conditional logic when ResourceBroker may not be initialized.
|
|
67
|
+
*
|
|
68
|
+
* @returns true if ResourceBroker is initialized and ready
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* if (isResourceBrokerAvailable()) {
|
|
73
|
+
* const broker = useResourceBroker();
|
|
74
|
+
* const stats = broker.getStats();
|
|
75
|
+
* } else {
|
|
76
|
+
* console.log('ResourceBroker not initialized');
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function isResourceBrokerAvailable(): boolean {
|
|
81
|
+
const platform = usePlatform();
|
|
82
|
+
return platform.hasResourceBroker;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get ResourceBroker statistics
|
|
87
|
+
*
|
|
88
|
+
* Convenience helper to get statistics without handling the broker directly.
|
|
89
|
+
*
|
|
90
|
+
* @returns ResourceBroker statistics or undefined if not available
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const stats = getResourceBrokerStats();
|
|
95
|
+
* if (stats) {
|
|
96
|
+
* console.log(`LLM requests: ${stats.resources.llm?.totalRequests ?? 0}`);
|
|
97
|
+
* console.log(`Queue size: ${stats.queueSize}`);
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export function getResourceBrokerStats() {
|
|
102
|
+
if (!isResourceBrokerAvailable()) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
return useResourceBroker().getStats();
|
|
106
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-storage
|
|
3
|
+
* Global storage access helper
|
|
4
|
+
*
|
|
5
|
+
* Provides clean access to file/blob storage adapter.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { useStorage } from '@kb-labs/shared-command-kit';
|
|
10
|
+
*
|
|
11
|
+
* async handler(ctx, argv, flags) {
|
|
12
|
+
* const storage = useStorage();
|
|
13
|
+
*
|
|
14
|
+
* if (storage) {
|
|
15
|
+
* await storage.write('path/to/file.txt', 'content');
|
|
16
|
+
* const content = await storage.read('path/to/file.txt');
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { usePlatform } from './use-platform';
|
|
23
|
+
import type { IStorage } from '@kb-labs/core-platform';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Access global storage adapter
|
|
27
|
+
*
|
|
28
|
+
* Returns the platform storage adapter for file/blob operations.
|
|
29
|
+
* Returns undefined if storage is not configured (graceful degradation).
|
|
30
|
+
*
|
|
31
|
+
* **Methods:**
|
|
32
|
+
* - `storage.read(path)` - Read file content
|
|
33
|
+
* - `storage.write(path, content)` - Write file content
|
|
34
|
+
* - `storage.exists(path)` - Check if file exists
|
|
35
|
+
* - `storage.delete(path)` - Delete file
|
|
36
|
+
* - `storage.list(prefix?)` - List files
|
|
37
|
+
*
|
|
38
|
+
* **Always check availability:**
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const storage = useStorage();
|
|
41
|
+
* if (storage) {
|
|
42
|
+
* await storage.write('file.txt', 'content');
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @returns Storage adapter or undefined if not configured
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const storage = useStorage();
|
|
51
|
+
*
|
|
52
|
+
* if (storage) {
|
|
53
|
+
* // Write file
|
|
54
|
+
* await storage.write('releases/v1.0.0.json', JSON.stringify(data));
|
|
55
|
+
*
|
|
56
|
+
* // Read file
|
|
57
|
+
* const content = await storage.read('releases/v1.0.0.json');
|
|
58
|
+
* const data = JSON.parse(content);
|
|
59
|
+
*
|
|
60
|
+
* // Check existence
|
|
61
|
+
* const exists = await storage.exists('releases/v1.0.0.json');
|
|
62
|
+
*
|
|
63
|
+
* // List files
|
|
64
|
+
* const files = await storage.list('releases/');
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function useStorage(): IStorage | undefined {
|
|
69
|
+
const platform = usePlatform();
|
|
70
|
+
return platform.storage;
|
|
71
|
+
}
|