@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,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/platform
|
|
3
|
+
* Platform service access helpers with graceful error handling.
|
|
4
|
+
*
|
|
5
|
+
* These helpers provide convenient access to platform services with automatic
|
|
6
|
+
* configuration checks and helpful error messages.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { PluginContextV3 as PluginContext } from '@kb-labs/plugin-runtime';
|
|
10
|
+
import type {
|
|
11
|
+
ILLM,
|
|
12
|
+
IEmbeddings,
|
|
13
|
+
IVectorStore,
|
|
14
|
+
ICache,
|
|
15
|
+
IStorage,
|
|
16
|
+
ILogger,
|
|
17
|
+
IAnalytics,
|
|
18
|
+
IEventBus,
|
|
19
|
+
LLMOptions,
|
|
20
|
+
LLMResponse,
|
|
21
|
+
VectorSearchResult,
|
|
22
|
+
} from '@kb-labs/core-platform';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Error thrown when required platform service is not configured.
|
|
26
|
+
*/
|
|
27
|
+
export class ServiceNotConfiguredError extends Error {
|
|
28
|
+
constructor(
|
|
29
|
+
public readonly service: string,
|
|
30
|
+
public readonly requiredAdapter?: string
|
|
31
|
+
) {
|
|
32
|
+
super(
|
|
33
|
+
requiredAdapter
|
|
34
|
+
? `Service '${service}' is not configured. Add "${requiredAdapter}" to kb.config.json adapters.`
|
|
35
|
+
: `Service '${service}' is not configured. Configure it in kb.config.json.`
|
|
36
|
+
);
|
|
37
|
+
this.name = 'ServiceNotConfiguredError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
42
|
+
// ADAPTERS (Replaceable Services)
|
|
43
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get LLM service with configuration check.
|
|
47
|
+
* Throws if LLM is not configured (using NoOp/Mock).
|
|
48
|
+
*
|
|
49
|
+
* @param ctx - Plugin context
|
|
50
|
+
* @returns LLM service
|
|
51
|
+
* @throws {ServiceNotConfiguredError} If LLM not configured
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const llm = useLLM(ctx);
|
|
56
|
+
* const response = await llm.complete('Hello, world!');
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function useLLM(ctx: PluginContext): ILLM {
|
|
60
|
+
if (!ctx.platform.llm) {
|
|
61
|
+
throw new ServiceNotConfiguredError('llm', '@kb-labs/shared-openai');
|
|
62
|
+
}
|
|
63
|
+
return ctx.platform.llm;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get embeddings service with configuration check.
|
|
68
|
+
* Throws if embeddings are not configured.
|
|
69
|
+
*
|
|
70
|
+
* @param ctx - Plugin context
|
|
71
|
+
* @returns Embeddings service
|
|
72
|
+
* @throws {ServiceNotConfiguredError} If embeddings not configured
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const embeddings = useEmbeddings(ctx);
|
|
77
|
+
* const vector = await embeddings.embed('text to embed');
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function useEmbeddings(ctx: PluginContext): IEmbeddings {
|
|
81
|
+
if (!ctx.platform.embeddings) {
|
|
82
|
+
throw new ServiceNotConfiguredError('embeddings', '@kb-labs/shared-openai');
|
|
83
|
+
}
|
|
84
|
+
return ctx.platform.embeddings;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get vector store with configuration check.
|
|
89
|
+
* Throws if vector store is not configured (using in-memory fallback).
|
|
90
|
+
*
|
|
91
|
+
* @param ctx - Plugin context
|
|
92
|
+
* @returns Vector store service
|
|
93
|
+
* @throws {ServiceNotConfiguredError} If vectorStore not configured
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const vectorStore = useVectorStore(ctx);
|
|
98
|
+
* const results = await vectorStore.search(queryVector, 10);
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export function useVectorStore(ctx: PluginContext): IVectorStore {
|
|
102
|
+
if (!ctx.platform.vectorStore) {
|
|
103
|
+
throw new ServiceNotConfiguredError('vectorStore', '@kb-labs/mind-qdrant');
|
|
104
|
+
}
|
|
105
|
+
return ctx.platform.vectorStore;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get cache service.
|
|
110
|
+
* Safe to use even without configuration (falls back to in-memory).
|
|
111
|
+
*
|
|
112
|
+
* @param ctx - Plugin context
|
|
113
|
+
* @returns Cache service (always available)
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const cache = useCache(ctx);
|
|
118
|
+
* await cache.set('key', value, 3600000); // TTL 1 hour
|
|
119
|
+
* const cached = await cache.get('key');
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
export function useCache(ctx: PluginContext): ICache {
|
|
123
|
+
return ctx.platform.cache!;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get storage service.
|
|
128
|
+
* Safe to use even without configuration (falls back to in-memory).
|
|
129
|
+
*
|
|
130
|
+
* @param ctx - Plugin context
|
|
131
|
+
* @returns Storage service (always available)
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const storage = useStorage(ctx);
|
|
136
|
+
* await storage.write('path/to/file.txt', Buffer.from('content'));
|
|
137
|
+
* const content = await storage.read('path/to/file.txt');
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export function useStorage(ctx: PluginContext): IStorage {
|
|
141
|
+
return ctx.platform.storage!;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Get logger service.
|
|
146
|
+
* Always available (falls back to console logger).
|
|
147
|
+
*
|
|
148
|
+
* @param ctx - Plugin context
|
|
149
|
+
* @returns Logger service (always available)
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const logger = useLogger(ctx);
|
|
154
|
+
* logger.info('Processing started', { itemCount: 10 });
|
|
155
|
+
* logger.error('Failed to process', error);
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export function useLogger(ctx: PluginContext): ILogger {
|
|
159
|
+
return ctx.platform.logger!;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get analytics service.
|
|
164
|
+
* Safe to use even without configuration (falls back to NoOp).
|
|
165
|
+
*
|
|
166
|
+
* @param ctx - Plugin context
|
|
167
|
+
* @returns Analytics service (always available)
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const analytics = useAnalytics(ctx);
|
|
172
|
+
* await analytics.track('feature.used', { feature: 'search' });
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
export function useAnalytics(ctx: PluginContext): IAnalytics {
|
|
176
|
+
return ctx.platform.analytics!;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get event bus service.
|
|
181
|
+
* Safe to use even without configuration (falls back to in-memory).
|
|
182
|
+
*
|
|
183
|
+
* @param ctx - Plugin context
|
|
184
|
+
* @returns Event bus service (always available)
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* const events = useEventBus(ctx);
|
|
189
|
+
* await events.publish('user.created', { userId: '123' });
|
|
190
|
+
* const unsubscribe = events.subscribe('user.created', async (event) => {
|
|
191
|
+
* console.log('User created:', event);
|
|
192
|
+
* });
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
export function useEventBus(ctx: PluginContext): IEventBus {
|
|
196
|
+
return ctx.platform.eventBus;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
200
|
+
// SHORTCUT FUNCTIONS (High-level operations)
|
|
201
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Generate embedding for text.
|
|
205
|
+
* Shortcut for embeddings.embed().
|
|
206
|
+
*
|
|
207
|
+
* @param ctx - Plugin context
|
|
208
|
+
* @param text - Text to embed
|
|
209
|
+
* @returns Embedding vector
|
|
210
|
+
* @throws {ServiceNotConfiguredError} If embeddings not configured
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```typescript
|
|
214
|
+
* const vector = await embedText(ctx, 'Hello, world!');
|
|
215
|
+
* console.log(vector.length); // e.g., 1536 for OpenAI ada-002
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
export async function embedText(ctx: PluginContext, text: string): Promise<number[]> {
|
|
219
|
+
const embeddings = useEmbeddings(ctx);
|
|
220
|
+
return embeddings.embed(text);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Generate embeddings for multiple texts.
|
|
225
|
+
* Shortcut for embeddings.embedBatch().
|
|
226
|
+
*
|
|
227
|
+
* @param ctx - Plugin context
|
|
228
|
+
* @param texts - Array of texts to embed
|
|
229
|
+
* @returns Array of embedding vectors
|
|
230
|
+
* @throws {ServiceNotConfiguredError} If embeddings not configured
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* const vectors = await embedBatch(ctx, ['text 1', 'text 2', 'text 3']);
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
export async function embedBatch(ctx: PluginContext, texts: string[]): Promise<number[][]> {
|
|
238
|
+
const embeddings = useEmbeddings(ctx);
|
|
239
|
+
return embeddings.embedBatch(texts);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Perform vector search.
|
|
244
|
+
* Shortcut for vectorStore.search().
|
|
245
|
+
*
|
|
246
|
+
* @param ctx - Plugin context
|
|
247
|
+
* @param query - Query vector
|
|
248
|
+
* @param limit - Maximum results (default: 10)
|
|
249
|
+
* @returns Search results
|
|
250
|
+
* @throws {ServiceNotConfiguredError} If vectorStore not configured
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```typescript
|
|
254
|
+
* const queryVector = await embedText(ctx, 'search query');
|
|
255
|
+
* const results = await searchVectors(ctx, queryVector, 5);
|
|
256
|
+
*
|
|
257
|
+
* for (const result of results) {
|
|
258
|
+
* console.log(`Score: ${result.score}, ID: ${result.id}`);
|
|
259
|
+
* }
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export async function searchVectors(
|
|
263
|
+
ctx: PluginContext,
|
|
264
|
+
query: number[],
|
|
265
|
+
limit = 10
|
|
266
|
+
): Promise<VectorSearchResult[]> {
|
|
267
|
+
const vectorStore = useVectorStore(ctx);
|
|
268
|
+
return vectorStore.search(query, limit);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Call LLM with text prompt.
|
|
273
|
+
* Shortcut for llm.complete().
|
|
274
|
+
*
|
|
275
|
+
* @param ctx - Plugin context
|
|
276
|
+
* @param prompt - Prompt text
|
|
277
|
+
* @param options - LLM options
|
|
278
|
+
* @returns LLM response
|
|
279
|
+
* @throws {ServiceNotConfiguredError} If LLM not configured
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```typescript
|
|
283
|
+
* const response = await completeLLM(ctx, 'Explain quantum computing', {
|
|
284
|
+
* temperature: 0.7,
|
|
285
|
+
* maxTokens: 500,
|
|
286
|
+
* });
|
|
287
|
+
* console.log(response.content);
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
export async function completeLLM(
|
|
291
|
+
ctx: PluginContext,
|
|
292
|
+
prompt: string,
|
|
293
|
+
options?: LLMOptions
|
|
294
|
+
): Promise<LLMResponse> {
|
|
295
|
+
const llm = useLLM(ctx);
|
|
296
|
+
return llm.complete(prompt, options);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Stream LLM response.
|
|
301
|
+
* Shortcut for llm.stream().
|
|
302
|
+
*
|
|
303
|
+
* @param ctx - Plugin context
|
|
304
|
+
* @param prompt - Prompt text
|
|
305
|
+
* @param options - LLM options
|
|
306
|
+
* @returns Async iterable of response chunks
|
|
307
|
+
* @throws {ServiceNotConfiguredError} If LLM not configured
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```typescript
|
|
311
|
+
* for await (const chunk of streamLLM(ctx, 'Write a story')) {
|
|
312
|
+
* ctx.ui.message(chunk);
|
|
313
|
+
* }
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
export function streamLLM(
|
|
317
|
+
ctx: PluginContext,
|
|
318
|
+
prompt: string,
|
|
319
|
+
options?: LLMOptions
|
|
320
|
+
): AsyncIterable<string> {
|
|
321
|
+
const llm = useLLM(ctx);
|
|
322
|
+
return llm.stream(prompt, options);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Check if a service is configured.
|
|
327
|
+
* Non-throwing alternative to use* functions.
|
|
328
|
+
*
|
|
329
|
+
* @param ctx - Plugin context
|
|
330
|
+
* @param service - Service name to check ('llm' | 'embeddings' | 'vectorStore' | 'cache' | 'storage' | 'analytics' | 'eventBus')
|
|
331
|
+
* @returns true if service is configured, false otherwise
|
|
332
|
+
*/
|
|
333
|
+
export function isServiceConfigured(ctx: PluginContext, service: keyof typeof ctx.platform): boolean {
|
|
334
|
+
return !!ctx.platform[service];
|
|
335
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-analytics
|
|
3
|
+
* Global analytics access helper
|
|
4
|
+
*
|
|
5
|
+
* Provides clean access to analytics/telemetry without context drilling.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { useAnalytics } from '@kb-labs/shared-command-kit';
|
|
10
|
+
*
|
|
11
|
+
* async handler(ctx, argv, flags) {
|
|
12
|
+
* const analytics = useAnalytics();
|
|
13
|
+
*
|
|
14
|
+
* if (analytics) {
|
|
15
|
+
* await analytics.track('release_started', { version: '1.0.0' });
|
|
16
|
+
* analytics.metric('release_duration_ms', 1234);
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { usePlatform } from './use-platform';
|
|
23
|
+
import type { IAnalytics } from '@kb-labs/core-platform';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Access global analytics adapter
|
|
27
|
+
*
|
|
28
|
+
* Returns the platform analytics adapter for tracking events and metrics.
|
|
29
|
+
* Returns undefined if analytics is not configured (graceful degradation).
|
|
30
|
+
*
|
|
31
|
+
* **Methods:**
|
|
32
|
+
* - `analytics.track(event, properties?)` - Track events
|
|
33
|
+
* - `analytics.metric(name, value, tags?)` - Record metrics
|
|
34
|
+
*
|
|
35
|
+
* **Always check availability:**
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const analytics = useAnalytics();
|
|
38
|
+
* if (analytics) {
|
|
39
|
+
* await analytics.track('event');
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @returns Analytics adapter or undefined if not configured
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const analytics = useAnalytics();
|
|
48
|
+
*
|
|
49
|
+
* if (analytics) {
|
|
50
|
+
* await analytics.track('command_executed', {
|
|
51
|
+
* command: 'release:run',
|
|
52
|
+
* duration_ms: 1234,
|
|
53
|
+
* success: true,
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* analytics.metric('release_packages_count', 5, {
|
|
57
|
+
* project: 'kb-labs',
|
|
58
|
+
* });
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function useAnalytics(): IAnalytics | undefined {
|
|
63
|
+
const platform = usePlatform();
|
|
64
|
+
return platform.analytics;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Track event with analytics (safe, global singleton)
|
|
69
|
+
*
|
|
70
|
+
* Convenience wrapper that uses global platform analytics.
|
|
71
|
+
* Does nothing if analytics is not configured.
|
|
72
|
+
*
|
|
73
|
+
* NOTE: For context-based analytics, use trackEvent() from '../analytics/with-analytics'.
|
|
74
|
+
* This helper uses global singleton, not request-scoped context.
|
|
75
|
+
*
|
|
76
|
+
* @param event - Event name
|
|
77
|
+
* @param properties - Event properties
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* import { trackAnalyticsEvent } from '@kb-labs/shared-command-kit/helpers';
|
|
82
|
+
*
|
|
83
|
+
* // No need to check if analytics exists
|
|
84
|
+
* await trackAnalyticsEvent('release_completed', { version: '1.0.0', packages: 5 });
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export async function trackAnalyticsEvent(
|
|
88
|
+
event: string,
|
|
89
|
+
properties?: Record<string, unknown>
|
|
90
|
+
): Promise<void> {
|
|
91
|
+
const analytics = useAnalytics();
|
|
92
|
+
if (analytics) {
|
|
93
|
+
await analytics.track(event, properties);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-cache
|
|
3
|
+
* Global Cache access helper
|
|
4
|
+
*
|
|
5
|
+
* Provides clean access to platform cache (Redis, InMemory, or custom adapter).
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { useCache } from '@kb-labs/shared-command-kit';
|
|
10
|
+
*
|
|
11
|
+
* async handler(ctx, argv, flags) {
|
|
12
|
+
* const cache = useCache();
|
|
13
|
+
*
|
|
14
|
+
* if (cache) {
|
|
15
|
+
* await cache.set('key', { data: 'value' }, 60000); // TTL: 60s
|
|
16
|
+
* const value = await cache.get('key');
|
|
17
|
+
* console.log(value);
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { usePlatform } from './use-platform.js';
|
|
24
|
+
import type { ICache } from '@kb-labs/core-platform';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Access global cache adapter
|
|
28
|
+
*
|
|
29
|
+
* Returns the platform cache adapter (Redis, InMemory, or custom).
|
|
30
|
+
* Returns undefined if cache is not configured (graceful degradation).
|
|
31
|
+
*
|
|
32
|
+
* **Methods:**
|
|
33
|
+
* - `cache.set(key, value, ttlMs?)` - Store value with optional TTL
|
|
34
|
+
* - `cache.get<T>(key)` - Retrieve value by key
|
|
35
|
+
* - `cache.delete(key)` - Remove value
|
|
36
|
+
* - `cache.clear()` - Clear all cached values
|
|
37
|
+
*
|
|
38
|
+
* **Always check availability:**
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const cache = useCache();
|
|
41
|
+
* if (cache) {
|
|
42
|
+
* await cache.set('query-123', result, 60000);
|
|
43
|
+
* } else {
|
|
44
|
+
* // No caching, compute every time
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @returns Cache adapter or undefined if not configured
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const cache = useCache();
|
|
53
|
+
*
|
|
54
|
+
* if (cache) {
|
|
55
|
+
* // Check cache first
|
|
56
|
+
* const cached = await cache.get<QueryResult>('query-123');
|
|
57
|
+
* if (cached) {
|
|
58
|
+
* return cached;
|
|
59
|
+
* }
|
|
60
|
+
*
|
|
61
|
+
* // Compute result
|
|
62
|
+
* const result = await expensiveQuery();
|
|
63
|
+
*
|
|
64
|
+
* // Cache for 5 minutes
|
|
65
|
+
* await cache.set('query-123', result, 5 * 60 * 1000);
|
|
66
|
+
*
|
|
67
|
+
* return result;
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export function useCache(): ICache | undefined {
|
|
72
|
+
const platform = usePlatform();
|
|
73
|
+
return platform.cache;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if cache is available
|
|
78
|
+
*
|
|
79
|
+
* Useful for conditional logic (cached vs non-cached execution).
|
|
80
|
+
*
|
|
81
|
+
* @returns true if cache is configured and ready
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* if (isCacheAvailable()) {
|
|
86
|
+
* // Use cached results
|
|
87
|
+
* const result = await getCachedOrCompute(key);
|
|
88
|
+
* } else {
|
|
89
|
+
* // Compute every time
|
|
90
|
+
* const result = await compute();
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export function isCacheAvailable(): boolean {
|
|
95
|
+
const cache = useCache();
|
|
96
|
+
return !!cache;
|
|
97
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-config
|
|
3
|
+
* Global config access helper
|
|
4
|
+
*
|
|
5
|
+
* Provides clean access to product-specific configuration without context drilling.
|
|
6
|
+
* Similar to React hooks pattern, but for KB Labs config.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { useConfig } from '@kb-labs/shared-command-kit';
|
|
11
|
+
*
|
|
12
|
+
* // In any command handler
|
|
13
|
+
* async handler(ctx, argv, flags) {
|
|
14
|
+
* const config = await useConfig('mind');
|
|
15
|
+
*
|
|
16
|
+
* if (config) {
|
|
17
|
+
* const scopes = config.scopes;
|
|
18
|
+
* // Use config...
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Access product-specific configuration from kb.config.json
|
|
26
|
+
*
|
|
27
|
+
* Returns ONLY the config for the specified product and profile.
|
|
28
|
+
* Uses platform.config adapter (works across parent/child processes via IPC).
|
|
29
|
+
* Supports both Profiles v2 and legacy config structures.
|
|
30
|
+
*
|
|
31
|
+
* **Security:** This function returns ONLY the product-specific config,
|
|
32
|
+
* not the entire kb.config.json. This prevents cross-product config access.
|
|
33
|
+
*
|
|
34
|
+
* **Auto-detection:** If productId is not provided, it's automatically inferred
|
|
35
|
+
* from the plugin's manifest.configSection field (passed via execution context).
|
|
36
|
+
*
|
|
37
|
+
* **Profiles v2 structure:**
|
|
38
|
+
* ```json
|
|
39
|
+
* {
|
|
40
|
+
* "profiles": [
|
|
41
|
+
* {
|
|
42
|
+
* "id": "default",
|
|
43
|
+
* "products": {
|
|
44
|
+
* "mind": { "scopes": [...] },
|
|
45
|
+
* "workflow": { "maxConcurrency": 10 }
|
|
46
|
+
* }
|
|
47
|
+
* }
|
|
48
|
+
* ]
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* **Legacy structure:**
|
|
53
|
+
* ```json
|
|
54
|
+
* {
|
|
55
|
+
* "knowledge": { "scopes": [...] }, // for "mind" product
|
|
56
|
+
* "workflow": { "maxConcurrency": 10 }
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @param productId - Product identifier (e.g., 'mind', 'workflow', 'plugins'). Optional - auto-detected from context.
|
|
61
|
+
* @param profileId - Profile identifier (defaults to 'default' or KB_PROFILE env var)
|
|
62
|
+
* @returns Promise resolving to product-specific config or undefined
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // Auto-detect from context (recommended)
|
|
67
|
+
* const config = await useConfig();
|
|
68
|
+
*
|
|
69
|
+
* // Explicit product ID
|
|
70
|
+
* const mindConfig = await useConfig('mind');
|
|
71
|
+
* if (mindConfig?.scopes) {
|
|
72
|
+
* // Use scopes
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* // With explicit profile
|
|
76
|
+
* const workflowConfig = await useConfig('workflow', 'production');
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export async function useConfig<T = any>(productId?: string, profileId?: string): Promise<T | undefined> {
|
|
80
|
+
// Auto-detect productId from manifest.configSection if not provided
|
|
81
|
+
let effectiveProductId = productId;
|
|
82
|
+
if (!effectiveProductId) {
|
|
83
|
+
effectiveProductId = (globalThis as any).__KB_CONFIG_SECTION__;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!effectiveProductId) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const { usePlatform } = await import('./use-platform.js');
|
|
91
|
+
const platform = usePlatform();
|
|
92
|
+
|
|
93
|
+
if (!platform) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Returns ONLY the product-specific config, not the entire kb.config.json
|
|
98
|
+
return await platform.config.getConfig(effectiveProductId, profileId) as T | undefined;
|
|
99
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/helpers/use-embeddings
|
|
3
|
+
* Global Embeddings access helper
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { usePlatform } from './use-platform';
|
|
7
|
+
import type { IEmbeddings } from '@kb-labs/core-platform';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Access global Embeddings adapter
|
|
11
|
+
*
|
|
12
|
+
* Returns the platform embeddings adapter (OpenAI, etc.).
|
|
13
|
+
* Returns undefined if embeddings is not configured (graceful degradation).
|
|
14
|
+
*
|
|
15
|
+
* @returns Embeddings adapter or undefined if not configured
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const embeddings = useEmbeddings();
|
|
20
|
+
*
|
|
21
|
+
* if (embeddings) {
|
|
22
|
+
* const vector = await embeddings.embed('Hello, world!');
|
|
23
|
+
* console.log(vector.length); // e.g., 1536 for OpenAI
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function useEmbeddings(): IEmbeddings | undefined {
|
|
28
|
+
const platform = usePlatform();
|
|
29
|
+
return platform.embeddings;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Check if Embeddings is available
|
|
34
|
+
*
|
|
35
|
+
* @returns true if embeddings is configured and ready
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* if (isEmbeddingsAvailable()) {
|
|
40
|
+
* const vector = await embeddings.embed(text);
|
|
41
|
+
* } else {
|
|
42
|
+
* // Use deterministic fallback
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function isEmbeddingsAvailable(): boolean {
|
|
47
|
+
const embeddings = useEmbeddings();
|
|
48
|
+
return !!embeddings;
|
|
49
|
+
}
|