@vibesdotdev/runtime-client 0.0.1

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.
Files changed (63) hide show
  1. package/README.md +97 -0
  2. package/SPEC.md +44 -0
  3. package/dist/base.d.ts +49 -0
  4. package/dist/base.d.ts.map +1 -0
  5. package/dist/base.js +86 -0
  6. package/dist/base.js.map +1 -0
  7. package/dist/contract.d.ts +23 -0
  8. package/dist/contract.d.ts.map +1 -0
  9. package/dist/contract.js +2 -0
  10. package/dist/contract.js.map +1 -0
  11. package/dist/docs/runtime-client.api.docs.descriptor.d.ts +8 -0
  12. package/dist/docs/runtime-client.api.docs.descriptor.d.ts.map +1 -0
  13. package/dist/docs/runtime-client.api.docs.descriptor.js +344 -0
  14. package/dist/docs/runtime-client.api.docs.descriptor.js.map +1 -0
  15. package/dist/docs/runtime-client.helpers.docs.descriptor.d.ts +8 -0
  16. package/dist/docs/runtime-client.helpers.docs.descriptor.d.ts.map +1 -0
  17. package/dist/docs/runtime-client.helpers.docs.descriptor.js +352 -0
  18. package/dist/docs/runtime-client.helpers.docs.descriptor.js.map +1 -0
  19. package/dist/docs/runtime-client.surface.docs.descriptor.d.ts +8 -0
  20. package/dist/docs/runtime-client.surface.docs.descriptor.d.ts.map +1 -0
  21. package/dist/docs/runtime-client.surface.docs.descriptor.js +464 -0
  22. package/dist/docs/runtime-client.surface.docs.descriptor.js.map +1 -0
  23. package/dist/docs/types.d.ts +19 -0
  24. package/dist/docs/types.d.ts.map +1 -0
  25. package/dist/docs/types.js +2 -0
  26. package/dist/docs/types.js.map +1 -0
  27. package/dist/helper.d.ts +14 -0
  28. package/dist/helper.d.ts.map +1 -0
  29. package/dist/helper.js +27 -0
  30. package/dist/helper.js.map +1 -0
  31. package/dist/index.d.ts +8 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +8 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/kind.d.ts +10 -0
  36. package/dist/kind.d.ts.map +1 -0
  37. package/dist/kind.js +12 -0
  38. package/dist/kind.js.map +1 -0
  39. package/dist/plugin.d.ts +10 -0
  40. package/dist/plugin.d.ts.map +1 -0
  41. package/dist/plugin.js +17 -0
  42. package/dist/plugin.js.map +1 -0
  43. package/dist/runtime-client.plugin.d.ts +13 -0
  44. package/dist/runtime-client.plugin.d.ts.map +1 -0
  45. package/dist/runtime-client.plugin.js +27 -0
  46. package/dist/runtime-client.plugin.js.map +1 -0
  47. package/dist/schema.d.ts +32 -0
  48. package/dist/schema.d.ts.map +1 -0
  49. package/dist/schema.js +8 -0
  50. package/dist/schema.js.map +1 -0
  51. package/package.json +61 -0
  52. package/src/base.ts +100 -0
  53. package/src/contract.ts +23 -0
  54. package/src/docs/runtime-client.api.docs.descriptor.ts +346 -0
  55. package/src/docs/runtime-client.helpers.docs.descriptor.ts +354 -0
  56. package/src/docs/runtime-client.surface.docs.descriptor.ts +466 -0
  57. package/src/docs/types.ts +18 -0
  58. package/src/helper.ts +32 -0
  59. package/src/index.ts +11 -0
  60. package/src/kind.ts +14 -0
  61. package/src/plugin.ts +19 -0
  62. package/src/runtime-client.plugin.ts +32 -0
  63. package/src/schema.ts +27 -0
@@ -0,0 +1,354 @@
1
+ import type { DocsTopicDescriptor } from './types.ts';
2
+
3
+ /**
4
+ * Descriptor for runtime-client.helpers
5
+ * getVibesClient() helper functions, surface detection
6
+ */
7
+ const descriptor: DocsTopicDescriptor = {
8
+ kind: 'docs/topic',
9
+ id: 'runtime-client.helpers',
10
+ title: 'Runtime Client Helpers',
11
+ summary: 'getVibesClient() helper functions for resolving module clients by id',
12
+ body: {
13
+ type: 'markdown',
14
+ sourceType: 'raw',
15
+ source: `---
16
+ title: Runtime Client Helpers
17
+ summary: getVibesClient() helper functions for resolving module clients by id
18
+ tags: [runtime-client, helpers, getVibesClient, resolution, singleton]
19
+ parent: runtime-client
20
+ order: 2
21
+ surfaces: [cli, web, in-app]
22
+ hardware: [consumer, cloud]
23
+ ---
24
+
25
+ # Runtime Client Helpers
26
+
27
+ The \`@vibesdotdev/runtime-client\` package exports helper functions for resolving module-level clients without manual \`runtime.query()\` chains. These helpers abstract runtime acquisition, kind registration, and error handling.
28
+
29
+ ## getVibesClient<T>()
30
+
31
+ Primary helper for resolving a client by id:
32
+
33
+ \`\`\`ts
34
+ import { getVibesClient } from '@vibesdotdev/runtime-client';
35
+ import type { AIClient } from '@vibesdotdev/ai/client';
36
+
37
+ const ai = await getVibesClient<AIClient>('ai');
38
+ const response = await ai.generate({ prompt: 'Hello' });
39
+ \`\`\`
40
+
41
+ ### How it works
42
+
43
+ \`\`\`ts
44
+ // Simplified implementation
45
+ export async function getVibesClient<T extends RuntimeClient>(
46
+ id: string
47
+ ): Promise<T> {
48
+ const runtime = getVibesRuntime();
49
+
50
+ // Auto-register runtime/client kind if not present
51
+ if (!runtime.hasKind('runtime/client')) {
52
+ await runtime.registerPlugin(runtimeClientPlugin);
53
+ }
54
+
55
+ // Resolve via runtime.query()
56
+ const client = await runtime
57
+ .query('runtime/client')
58
+ .withId(id)
59
+ .resolve();
60
+
61
+ if (!client) {
62
+ throw new Error(
63
+ \`No runtime client registered with id "\${id}". \${
64
+ 'Compose the owning module\\'s plugin (e.g. aiPlugin for id="ai") ' +
65
+ 'before use, and ensure runtimeClientPlugin is registered.'
66
+ }\`
67
+ );
68
+ }
69
+
70
+ return client as T;
71
+ }
72
+ \`\`\`
73
+
74
+ ### Auto-registration semantics
75
+
76
+ \`getVibesClient()\` automatically registers the \`runtime/client\` kind if it hasn't been registered yet. This means:
77
+
78
+ 1. **No manual bootstrap required** — Call \`getVibesClient()\` directly
79
+ 2. **Kind registration is idempotent** — Safe to call multiple times
80
+ 3. **Module plugins still needed** — The module owning the client (e.g., \`aiPlugin\`) must still be registered to provide the implementation
81
+
82
+ \`\`\`ts
83
+ // ✅ Works — runtime/client kind auto-registered
84
+ import { getVibesClient } from '@vibesdotdev/runtime-client';
85
+ import { aiPlugin } from '@vibesdotdev/ai';
86
+
87
+ const runtime = getVibesRuntime();
88
+ await runtime.registerPlugin(aiPlugin); // Provides AIClient implementation
89
+
90
+ const ai = await getVibesClient('ai'); // ✅ Resolves AIClient
91
+ \`\`\`
92
+
93
+ ### Type safety
94
+
95
+ Use TypeScript generics for type-safe client access:
96
+
97
+ \`\`\`ts
98
+ import { getVibesClient } from '@vibesdotdev/runtime-client';
99
+ import type { ToolsClient } from '@vibesdotdev/tools/client';
100
+ import type { KnowledgeClient } from '@vibesdotdev/knowledge/client';
101
+
102
+ // Type-safe resolution
103
+ const tools = await getVibesClient<ToolsClient>('tools');
104
+ const knowledge = await getVibesClient<KnowledgeClient>('knowledge');
105
+
106
+ // IntelliSense works:
107
+ await tools.listTools(); // ✅ Typed
108
+ await knowledge.search('...'); // ✅ Typed
109
+ \`\`\`
110
+
111
+ ### Error handling
112
+
113
+ \`getVibesClient()\` throws if the client is not registered:
114
+
115
+ \`\`\`ts
116
+ try {
117
+ const ai = await getVibesClient('ai');
118
+ } catch (error) {
119
+ // Error: No runtime client registered with id "ai".
120
+ // Compose the owning module's plugin (e.g. aiPlugin for id="ai")
121
+ // before use, and ensure runtimeClientPlugin is registered.
122
+ }
123
+ \`\`\`
124
+
125
+ **Common causes:**
126
+ 1. Module plugin not registered (e.g., \`aiPlugin\`)
127
+ 2. Wrong client id (use \`'ai'\`, not \`'ai-client'\`)
128
+ 3. Runtime not bootstrapped (call \`getVibesRuntime()\` first)
129
+
130
+ ## Module-Specific Helper Wrappers
131
+
132
+ Many packages export their own typed helper that wraps \`getVibesClient()\`:
133
+
134
+ ### Example: Tools
135
+
136
+ \`\`\`ts
137
+ // packages/tools/src/client/helper.ts
138
+ import { getVibesClient } from '@vibesdotdev/runtime-client';
139
+ import type { ToolsClient } from './runtime-client';
140
+
141
+ export function getVibesToolsClient(): Promise<ToolsClient> {
142
+ return getVibesClient<ToolsClient>('tools');
143
+ }
144
+
145
+ // Usage
146
+ import { getVibesToolsClient } from '@vibesdotdev/tools/client';
147
+
148
+ const tools = await getVibesToolsClient();
149
+ const toolList = await tools.listTools();
150
+ \`\`\`
151
+
152
+ ### Example: AI
153
+
154
+ \`\`\`ts
155
+ // packages/ai/src/client/helper.ts
156
+ import { getVibesClient } from '@vibesdotdev/runtime-client';
157
+ import type { AIClient } from './ai-client';
158
+
159
+ export function getVibesAIClient(): Promise<AIClient> {
160
+ return getVibesClient<AIClient>('ai');
161
+ }
162
+
163
+ // Usage
164
+ import { getVibesAIClient } from '@vibesdotdev/ai/client';
165
+
166
+ const ai = await getVibesAIClient();
167
+ const response = await ai.generate({ prompt: 'Hello' });
168
+ \`\`\`
169
+
170
+ **Benefits of wrappers:**
171
+ - Type inference without generics
172
+ - Centralized error handling
173
+ - Easier refactoring if client ids change
174
+ - Better IDE autocomplete
175
+
176
+ ## Comparison: getVibesClient() vs runtime.query()
177
+
178
+ | Aspect | \`getVibesClient()\` | \`runtime.query()\` |
179
+ |--------|---------------------|---------------------|
180
+ | **Verbosity** | Concise | Verbose |
181
+ | **Type safety** | Generic \`<T>\` | Manual casting |
182
+ | **Auto-registration** | Yes | No |
183
+ | **Error messages** | Helpful | Generic |
184
+ | **Use case** | Client resolution | General kind resolution |
185
+
186
+ \`\`\`ts
187
+ // Verbose: runtime.query()
188
+ const client = await runtime
189
+ .query('runtime/client')
190
+ .withId('ai')
191
+ .resolve() as AIClient;
192
+
193
+ // Concise: getVibesClient()
194
+ const client = await getVibesClient<AIClient>('ai');
195
+ \`\`\`
196
+
197
+ **Rule of thumb:** Use \`getVibesClient()\` for client resolution, \`runtime.query()\` for other kinds (tools, providers, models, etc.).
198
+
199
+ ## Surface Detection
200
+
201
+ The helpers themselves are **surface-neutral** — they work in CLI, SSR, browser, and worker contexts. Surface detection happens at the runtime level:
202
+
203
+ \`\`\`ts
204
+ // All surfaces use the same helper
205
+ import { getVibesClient } from '@vibesdotdev/runtime-client';
206
+
207
+ const tools = await getVibesClient('tools');
208
+
209
+ // Surface is determined by runtime scope:
210
+ // - CLI: { surface: 'cli', hardware: 'consumer' }
211
+ // - SSR: { surface: 'ssr', hardware: 'consumer' }
212
+ // - Browser: { surface: 'browser', hardware: 'consumer' }
213
+ // - Worker: { surface: 'worker', hardware: 'cloud' }
214
+ \`\`\`
215
+
216
+ The runtime's scope affects **which implementation** is resolved, not **how** it's resolved:
217
+
218
+ \`\`\`ts
219
+ // In CLI surface
220
+ const runtime = getVibesRuntime();
221
+ runtime.scope; // { surface: 'cli', hardware: 'consumer' }
222
+
223
+ // In SSR surface (SvelteKit +page.server.ts)
224
+ const runtime = getVibesRuntime();
225
+ runtime.scope; // { surface: 'ssr', hardware: 'consumer' }
226
+
227
+ // Same helper, different underlying implementations
228
+ const tools = await getVibesClient('tools');
229
+ \`\`\`
230
+
231
+ See [\`runtime-client.surface\`](runtime-client.surface) for surface-specific initialization patterns.
232
+
233
+ ## WRONG patterns
234
+
235
+ :::card{title="Anti-patterns"}
236
+ - ❌ **Manual runtime.query() chains** — Use \`getVibesClient()\` for client resolution
237
+ - ❌ **Ignoring type parameters** — Always specify \`getVibesClient<T>()\` for type safety
238
+ - ❌ **Catching and swallowing errors** — Let registration errors surface; they indicate misconfiguration
239
+ - ❌ **Assuming client is cached** — Helper resolves fresh each call; client implementations cache internally
240
+ - ❌ **Using in module scope** — Call at function/call site, not top-level module scope
241
+ :::
242
+
243
+ ## Example: Service layer
244
+
245
+ \`\`\`ts
246
+ // packages/my-app/src/services/content-generator.ts
247
+ import { getVibesClient } from '@vibesdotdev/runtime-client';
248
+ import type { AIClient } from '@vibesdotdev/ai/client';
249
+ import type { ToolsClient } from '@vibesdotdev/tools/client';
250
+
251
+ export class ContentGenerator {
252
+ private aiClient?: AIClient;
253
+ private toolsClient?: ToolsClient;
254
+
255
+ async initialize(): Promise<void> {
256
+ // Lazy initialization with error handling
257
+ try {
258
+ this.aiClient = await getVibesClient<AIClient>('ai');
259
+ this.toolsClient = await getVibesClient<ToolsClient>('tools');
260
+ } catch (error) {
261
+ throw new Error(\`Failed to initialize content generator: \${error}\`);
262
+ }
263
+ }
264
+
265
+ async generateContent(topic: string): Promise<string> {
266
+ if (!this.aiClient || !this.toolsClient) {
267
+ await this.initialize();
268
+ }
269
+
270
+ // Use tools to gather context
271
+ const context = await this.toolsClient!.runTool('web-search', {
272
+ query: topic
273
+ });
274
+
275
+ // Generate content with AI
276
+ const response = await this.aiClient!.generate({
277
+ prompt: \`Write about \${topic}. Context: \${context}\`,
278
+ maxTokens: 2000
279
+ });
280
+
281
+ return response;
282
+ }
283
+ }
284
+ \`\`\`
285
+
286
+ ## Example: Testing
287
+
288
+ \`\`\`ts
289
+ // packages/my-app/src/__tests__/content-generator.test.ts
290
+ import { describe, it, expect, beforeEach } from 'bun:test';
291
+ import { getVibesRuntime, resetVibesRuntime } from '@vibesdotdev/runtime';
292
+ import { getVibesClient } from '@vibesdotdev/runtime-client';
293
+ import { aiPlugin } from '@vibesdotdev/ai';
294
+ import { toolsPlugin } from '@vibesdotdev/tools';
295
+
296
+ describe('ContentGenerator', () => {
297
+ beforeEach(async () => {
298
+ resetVibesRuntime();
299
+ const runtime = getVibesRuntime();
300
+ await runtime.registerPlugin(aiPlugin);
301
+ await runtime.registerPlugin(toolsPlugin);
302
+ });
303
+
304
+ it('generates content', async () => {
305
+ const ai = await getVibesClient('ai');
306
+ const tools = await getVibesClient('tools');
307
+
308
+ // Test with real clients
309
+ const response = await ai.generate({ prompt: 'Test' });
310
+ expect(response).toBeDefined();
311
+ });
312
+ });
313
+ \`\`\`
314
+
315
+ ## Code paths
316
+
317
+ - Helper implementation: [\`packages/runtime-client/src/helper.ts\`](https://github.com/vibesdotdev/monorepo/tree/main/packages/runtime-client/src/helper.ts)
318
+ - Plugin registration: [\`packages/runtime-client/src/plugin.ts\`](https://github.com/vibesdotdev/monorepo/tree/main/packages/runtime-client/src/plugin.ts)
319
+ - Kind definition: [\`packages/runtime-client/src/kind.ts\`](https://github.com/vibesdotdev/monorepo/tree/main/packages/runtime-client/src/kind.ts)
320
+
321
+ :::card{title="See also"}
322
+ - [\`runtime-client.api\`](runtime-client.api) — BaseRuntimeClient and extension patterns
323
+ - [\`runtime-client.surface\`](runtime-client.surface) — Surface initialization patterns
324
+ - [\`runtime.query\`](runtime.query) — Runtime query API
325
+ - [\`runtime.plugins\`](runtime.plugins) — Plugin registration and lifecycle
326
+ :::
327
+ `
328
+ },
329
+ parent: 'runtime-client',
330
+ order: 2,
331
+ tags: ['runtime-client', 'helpers', 'getVibesClient', 'resolution', 'singleton'],
332
+ surfaces: ['cli', 'web', 'in-app'],
333
+ hardware: ['consumer', 'cloud'],
334
+ enabled: true,
335
+ man: {
336
+ name: 'runtime-client.helpers — getVibesClient() helper functions',
337
+ section: 1,
338
+ synopsis: 'vibes man runtime-client.helpers',
339
+ options: [],
340
+ examples: [
341
+ {
342
+ description: 'Resolve client by id',
343
+ command: 'const ai = await getVibesClient<AIClient>("ai")'
344
+ },
345
+ {
346
+ description: 'Use typed wrapper',
347
+ command: 'const tools = await getVibesToolsClient()'
348
+ }
349
+ ],
350
+ seeAlso: ['runtime-client.api', 'runtime-client.surface', 'runtime.query']
351
+ }
352
+ };
353
+
354
+ export default descriptor;