@lakitu/sdk 0.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.
Files changed (111) hide show
  1. package/README.md +166 -0
  2. package/convex/_generated/api.d.ts +45 -0
  3. package/convex/_generated/api.js +23 -0
  4. package/convex/_generated/dataModel.d.ts +58 -0
  5. package/convex/_generated/server.d.ts +143 -0
  6. package/convex/_generated/server.js +93 -0
  7. package/convex/cloud/CLAUDE.md +238 -0
  8. package/convex/cloud/_generated/api.ts +84 -0
  9. package/convex/cloud/_generated/component.ts +861 -0
  10. package/convex/cloud/_generated/dataModel.ts +60 -0
  11. package/convex/cloud/_generated/server.ts +156 -0
  12. package/convex/cloud/convex.config.ts +16 -0
  13. package/convex/cloud/index.ts +29 -0
  14. package/convex/cloud/intentSchema/generate.ts +447 -0
  15. package/convex/cloud/intentSchema/index.ts +16 -0
  16. package/convex/cloud/intentSchema/types.ts +418 -0
  17. package/convex/cloud/ksaPolicy.ts +554 -0
  18. package/convex/cloud/mail.ts +92 -0
  19. package/convex/cloud/schema.ts +322 -0
  20. package/convex/cloud/utils/kanbanContext.ts +229 -0
  21. package/convex/cloud/workflows/agentBoard.ts +451 -0
  22. package/convex/cloud/workflows/agentPrompt.ts +272 -0
  23. package/convex/cloud/workflows/agentThread.ts +374 -0
  24. package/convex/cloud/workflows/compileSandbox.ts +146 -0
  25. package/convex/cloud/workflows/crudBoard.ts +217 -0
  26. package/convex/cloud/workflows/crudKSAs.ts +262 -0
  27. package/convex/cloud/workflows/crudLorobeads.ts +371 -0
  28. package/convex/cloud/workflows/crudSkills.ts +205 -0
  29. package/convex/cloud/workflows/crudThreads.ts +708 -0
  30. package/convex/cloud/workflows/lifecycleSandbox.ts +1396 -0
  31. package/convex/cloud/workflows/sandboxConvex.ts +1046 -0
  32. package/convex/sandbox/README.md +90 -0
  33. package/convex/sandbox/_generated/api.d.ts +2934 -0
  34. package/convex/sandbox/_generated/api.js +23 -0
  35. package/convex/sandbox/_generated/dataModel.d.ts +60 -0
  36. package/convex/sandbox/_generated/server.d.ts +143 -0
  37. package/convex/sandbox/_generated/server.js +93 -0
  38. package/convex/sandbox/actions/bash.ts +130 -0
  39. package/convex/sandbox/actions/browser.ts +282 -0
  40. package/convex/sandbox/actions/file.ts +336 -0
  41. package/convex/sandbox/actions/lsp.ts +325 -0
  42. package/convex/sandbox/actions/pdf.ts +119 -0
  43. package/convex/sandbox/agent/codeExecLoop.ts +535 -0
  44. package/convex/sandbox/agent/decisions.ts +284 -0
  45. package/convex/sandbox/agent/index.ts +515 -0
  46. package/convex/sandbox/agent/subagents.ts +651 -0
  47. package/convex/sandbox/brandResearch/index.ts +417 -0
  48. package/convex/sandbox/context/index.ts +7 -0
  49. package/convex/sandbox/context/session.ts +402 -0
  50. package/convex/sandbox/convex.config.ts +17 -0
  51. package/convex/sandbox/index.ts +51 -0
  52. package/convex/sandbox/nodeActions/codeExec.ts +130 -0
  53. package/convex/sandbox/planning/beads.ts +187 -0
  54. package/convex/sandbox/planning/index.ts +8 -0
  55. package/convex/sandbox/planning/sync.ts +194 -0
  56. package/convex/sandbox/prompts/codeExec.ts +852 -0
  57. package/convex/sandbox/prompts/modes.ts +231 -0
  58. package/convex/sandbox/prompts/system.ts +142 -0
  59. package/convex/sandbox/schema.ts +510 -0
  60. package/convex/sandbox/state/artifacts.ts +99 -0
  61. package/convex/sandbox/state/checkpoints.ts +341 -0
  62. package/convex/sandbox/state/files.ts +383 -0
  63. package/convex/sandbox/state/index.ts +10 -0
  64. package/convex/sandbox/state/verification.actions.ts +268 -0
  65. package/convex/sandbox/state/verification.ts +101 -0
  66. package/convex/sandbox/tsconfig.json +25 -0
  67. package/convex/sandbox/utils/codeExecHelpers.ts +52 -0
  68. package/dist/cli/commands/build.d.ts +19 -0
  69. package/dist/cli/commands/build.d.ts.map +1 -0
  70. package/dist/cli/commands/build.js +223 -0
  71. package/dist/cli/commands/init.d.ts +16 -0
  72. package/dist/cli/commands/init.d.ts.map +1 -0
  73. package/dist/cli/commands/init.js +148 -0
  74. package/dist/cli/commands/publish.d.ts +12 -0
  75. package/dist/cli/commands/publish.d.ts.map +1 -0
  76. package/dist/cli/commands/publish.js +33 -0
  77. package/dist/cli/index.d.ts +14 -0
  78. package/dist/cli/index.d.ts.map +1 -0
  79. package/dist/cli/index.js +40 -0
  80. package/dist/sdk/builders.d.ts +104 -0
  81. package/dist/sdk/builders.d.ts.map +1 -0
  82. package/dist/sdk/builders.js +214 -0
  83. package/dist/sdk/index.d.ts +29 -0
  84. package/dist/sdk/index.d.ts.map +1 -0
  85. package/dist/sdk/index.js +38 -0
  86. package/dist/sdk/types.d.ts +107 -0
  87. package/dist/sdk/types.d.ts.map +1 -0
  88. package/dist/sdk/types.js +6 -0
  89. package/ksa/README.md +263 -0
  90. package/ksa/_generated/REFERENCE.md +2954 -0
  91. package/ksa/_generated/registry.ts +257 -0
  92. package/ksa/_shared/configReader.ts +302 -0
  93. package/ksa/_shared/configSchemas.ts +649 -0
  94. package/ksa/_shared/gateway.ts +175 -0
  95. package/ksa/_shared/ksaBehaviors.ts +411 -0
  96. package/ksa/_shared/ksaProxy.ts +248 -0
  97. package/ksa/_shared/localDb.ts +302 -0
  98. package/ksa/index.ts +134 -0
  99. package/package.json +93 -0
  100. package/runtime/browser/agent-browser.ts +330 -0
  101. package/runtime/entrypoint.ts +194 -0
  102. package/runtime/lsp/manager.ts +366 -0
  103. package/runtime/pdf/pdf-generator.ts +50 -0
  104. package/runtime/pdf/renderer.ts +357 -0
  105. package/runtime/pdf/schema.ts +97 -0
  106. package/runtime/services/file-watcher.ts +191 -0
  107. package/template/build.ts +307 -0
  108. package/template/e2b/Dockerfile +69 -0
  109. package/template/e2b/e2b.toml +13 -0
  110. package/template/e2b/prebuild.sh +68 -0
  111. package/template/e2b/start.sh +14 -0
@@ -0,0 +1,649 @@
1
+ /**
2
+ * KSA Configuration Schemas
3
+ *
4
+ * Defines the configurable options for each KSA.
5
+ * These schemas drive the UI config panel and validation.
6
+ */
7
+
8
+ // =============================================================================
9
+ // Types
10
+ // =============================================================================
11
+
12
+ export type ConfigFieldType =
13
+ | "select"
14
+ | "multiselect"
15
+ | "boolean"
16
+ | "number"
17
+ | "string"
18
+ | "textarea"
19
+ | "array";
20
+
21
+ export interface ConfigFieldOption {
22
+ value: string | number | boolean;
23
+ label: string;
24
+ }
25
+
26
+ export interface ConfigField {
27
+ type: ConfigFieldType;
28
+ label: string;
29
+ description?: string;
30
+ placeholder?: string;
31
+ options?: ConfigFieldOption[];
32
+ min?: number;
33
+ max?: number;
34
+ default: unknown;
35
+ }
36
+
37
+ export interface PresetDefinition {
38
+ name: string;
39
+ displayName: string;
40
+ description: string;
41
+ icon?: string;
42
+ baseKSA: string;
43
+ lockedConfig: Record<string, unknown>;
44
+ }
45
+
46
+ // =============================================================================
47
+ // Universal Fields (present on all KSAs)
48
+ // =============================================================================
49
+
50
+ export const INSTRUCTIONS_FIELD: ConfigField = {
51
+ type: "textarea",
52
+ label: "Custom Instructions",
53
+ description:
54
+ "Instructions for the agent when using this skill (embedded in system prompt)",
55
+ placeholder:
56
+ 'e.g., "Focus on enterprise clients" or "Prioritize recent sources"',
57
+ default: "",
58
+ };
59
+
60
+ // =============================================================================
61
+ // Framework Config (Local DB Integration)
62
+ // =============================================================================
63
+
64
+ /**
65
+ * Framework-level config fields that control automatic local DB behaviors.
66
+ * These are applied to ALL KSAs via the proxy layer.
67
+ */
68
+ export const FRAMEWORK_CONFIG_SCHEMA: Record<string, ConfigField> = {
69
+ // Caching
70
+ cacheResults: {
71
+ type: "boolean",
72
+ label: "Cache Results",
73
+ description: "Cache function results in local DB to avoid redundant calls",
74
+ default: true,
75
+ },
76
+ cacheTTLMs: {
77
+ type: "number",
78
+ label: "Cache TTL (ms)",
79
+ description: "How long cached results are valid (milliseconds)",
80
+ min: 0,
81
+ max: 3600000, // 1 hour max
82
+ default: 300000, // 5 minutes
83
+ },
84
+
85
+ // State Tracking
86
+ trackCalls: {
87
+ type: "boolean",
88
+ label: "Track Calls",
89
+ description: "Log all KSA function calls to local DB for debugging",
90
+ default: true,
91
+ },
92
+ trackFileState: {
93
+ type: "boolean",
94
+ label: "Track File State",
95
+ description: "Track file reads/writes/edits in local DB (file KSA only)",
96
+ default: true,
97
+ },
98
+
99
+ // Session Persistence
100
+ persistToSession: {
101
+ type: "boolean",
102
+ label: "Persist to Session",
103
+ description: "Store results in session memory for cross-run access",
104
+ default: false,
105
+ },
106
+ };
107
+
108
+ export const FRAMEWORK_DEFAULTS: Record<string, unknown> = {
109
+ cacheResults: true,
110
+ cacheTTLMs: 300000,
111
+ trackCalls: true,
112
+ trackFileState: true,
113
+ persistToSession: false,
114
+ };
115
+
116
+ /**
117
+ * Framework config type for TypeScript consumers.
118
+ */
119
+ export interface FrameworkConfig {
120
+ cacheResults: boolean;
121
+ cacheTTLMs: number;
122
+ trackCalls: boolean;
123
+ trackFileState: boolean;
124
+ persistToSession: boolean;
125
+ }
126
+
127
+ /**
128
+ * Get framework config merged with defaults.
129
+ */
130
+ export function getFrameworkConfig(
131
+ userConfig: Partial<FrameworkConfig> = {}
132
+ ): FrameworkConfig {
133
+ return { ...FRAMEWORK_DEFAULTS, ...userConfig } as FrameworkConfig;
134
+ }
135
+
136
+ // =============================================================================
137
+ // Web KSA Config
138
+ // =============================================================================
139
+
140
+ export const WEB_CONFIG_SCHEMA: Record<string, ConfigField> = {
141
+ depth: {
142
+ type: "select",
143
+ label: "Research Depth",
144
+ description: "Number of results to fetch",
145
+ options: [
146
+ { value: "quick", label: "Quick (8 results)" },
147
+ { value: "thorough", label: "Thorough (15+ results)" },
148
+ ],
149
+ default: "quick",
150
+ },
151
+ searchType: {
152
+ type: "select",
153
+ label: "Search Type",
154
+ description: "Type of content to search",
155
+ options: [
156
+ { value: "all", label: "All Sources" },
157
+ { value: "web", label: "Web Only" },
158
+ { value: "news", label: "News Only" },
159
+ ],
160
+ default: "all",
161
+ },
162
+ fastMode: {
163
+ type: "boolean",
164
+ label: "Fast Mode",
165
+ description: "Prioritize speed over depth",
166
+ default: true,
167
+ },
168
+ includeSources: {
169
+ type: "array",
170
+ label: "Include Sources",
171
+ description: "Only search these domains (leave empty for all)",
172
+ placeholder: "e.g., techcrunch.com, reuters.com",
173
+ default: [],
174
+ },
175
+ excludeSources: {
176
+ type: "array",
177
+ label: "Exclude Sources",
178
+ description: "Never search these domains",
179
+ placeholder: "e.g., pinterest.com, reddit.com",
180
+ default: [],
181
+ },
182
+ instructions: INSTRUCTIONS_FIELD,
183
+ };
184
+
185
+ export const WEB_DEFAULTS = {
186
+ depth: "quick",
187
+ searchType: "all",
188
+ fastMode: true,
189
+ includeSources: [],
190
+ excludeSources: [],
191
+ instructions: "",
192
+ };
193
+
194
+ // =============================================================================
195
+ // Social KSA Config
196
+ // =============================================================================
197
+
198
+ export const SOCIAL_CONFIG_SCHEMA: Record<string, ConfigField> = {
199
+ platforms: {
200
+ type: "multiselect",
201
+ label: "Platforms",
202
+ description: "Social platforms to search",
203
+ options: [
204
+ { value: "instagram", label: "Instagram" },
205
+ { value: "tiktok", label: "TikTok" },
206
+ { value: "youtube", label: "YouTube" },
207
+ { value: "twitter", label: "Twitter/X" },
208
+ { value: "linkedin", label: "LinkedIn" },
209
+ ],
210
+ default: ["instagram", "tiktok"],
211
+ },
212
+ contentTypes: {
213
+ type: "multiselect",
214
+ label: "Content Types",
215
+ description: "Types of content to fetch",
216
+ options: [
217
+ { value: "profiles", label: "Profiles" },
218
+ { value: "posts", label: "Posts" },
219
+ { value: "comments", label: "Comments" },
220
+ ],
221
+ default: ["profiles", "posts"],
222
+ },
223
+ postsLimit: {
224
+ type: "number",
225
+ label: "Posts Limit",
226
+ description: "Maximum posts per profile",
227
+ min: 1,
228
+ max: 50,
229
+ default: 10,
230
+ },
231
+ instructions: INSTRUCTIONS_FIELD,
232
+ };
233
+
234
+ export const SOCIAL_DEFAULTS = {
235
+ platforms: ["instagram", "tiktok"],
236
+ contentTypes: ["profiles", "posts"],
237
+ postsLimit: 10,
238
+ instructions: "",
239
+ };
240
+
241
+ // =============================================================================
242
+ // Companies KSA Config
243
+ // =============================================================================
244
+
245
+ export const COMPANIES_CONFIG_SCHEMA: Record<string, ConfigField> = {
246
+ enrichmentLevel: {
247
+ type: "select",
248
+ label: "Enrichment Level",
249
+ description: "Depth of company data",
250
+ options: [
251
+ { value: "basic", label: "Basic (name, domain, logo)" },
252
+ { value: "detailed", label: "Detailed (+ description, industry)" },
253
+ { value: "full", label: "Full (+ employees, funding, tech)" },
254
+ ],
255
+ default: "basic",
256
+ },
257
+ includeTechStack: {
258
+ type: "boolean",
259
+ label: "Include Tech Stack",
260
+ description: "Fetch technology stack information",
261
+ default: false,
262
+ },
263
+ sources: {
264
+ type: "multiselect",
265
+ label: "Data Sources",
266
+ description: "Sources to query",
267
+ options: [
268
+ { value: "domain", label: "Domain Lookup" },
269
+ { value: "linkedin", label: "LinkedIn" },
270
+ { value: "crunchbase", label: "Crunchbase" },
271
+ ],
272
+ default: ["domain"],
273
+ },
274
+ instructions: INSTRUCTIONS_FIELD,
275
+ };
276
+
277
+ export const COMPANIES_DEFAULTS = {
278
+ enrichmentLevel: "basic",
279
+ includeTechStack: false,
280
+ sources: ["domain"],
281
+ instructions: "",
282
+ };
283
+
284
+ // =============================================================================
285
+ // Artifacts KSA Config
286
+ // =============================================================================
287
+
288
+ export const ARTIFACTS_CONFIG_SCHEMA: Record<string, ConfigField> = {
289
+ validationRequired: {
290
+ type: "boolean",
291
+ label: "Require Artifact",
292
+ description: "Stage must produce at least one artifact",
293
+ default: false,
294
+ },
295
+ validationMinLength: {
296
+ type: "number",
297
+ label: "Minimum Length",
298
+ description: "Minimum content length (0 = no limit)",
299
+ min: 0,
300
+ max: 10000,
301
+ default: 0,
302
+ },
303
+ validationFormat: {
304
+ type: "select",
305
+ label: "Required Format",
306
+ description: "Artifact format requirement",
307
+ options: [
308
+ { value: "any", label: "Any Format" },
309
+ { value: "markdown", label: "Markdown" },
310
+ { value: "json", label: "JSON" },
311
+ { value: "html", label: "HTML" },
312
+ ],
313
+ default: "any",
314
+ },
315
+ autoSave: {
316
+ type: "boolean",
317
+ label: "Auto-Save",
318
+ description: "Automatically save artifacts on completion",
319
+ default: true,
320
+ },
321
+ instructions: INSTRUCTIONS_FIELD,
322
+ };
323
+
324
+ export const ARTIFACTS_DEFAULTS = {
325
+ validationRequired: false,
326
+ validationMinLength: 0,
327
+ validationFormat: "any",
328
+ autoSave: true,
329
+ instructions: "",
330
+ };
331
+
332
+ // =============================================================================
333
+ // PDF KSA Config
334
+ // =============================================================================
335
+
336
+ export const PDF_CONFIG_SCHEMA: Record<string, ConfigField> = {
337
+ template: {
338
+ type: "select",
339
+ label: "Template",
340
+ description: "PDF template style",
341
+ options: [
342
+ { value: "report", label: "Report" },
343
+ { value: "presentation", label: "Presentation" },
344
+ { value: "minimal", label: "Minimal" },
345
+ ],
346
+ default: "report",
347
+ },
348
+ pageSize: {
349
+ type: "select",
350
+ label: "Page Size",
351
+ description: "Document page size",
352
+ options: [
353
+ { value: "letter", label: "Letter (8.5 x 11)" },
354
+ { value: "a4", label: "A4" },
355
+ ],
356
+ default: "letter",
357
+ },
358
+ includeTableOfContents: {
359
+ type: "boolean",
360
+ label: "Table of Contents",
361
+ description: "Include table of contents",
362
+ default: true,
363
+ },
364
+ instructions: INSTRUCTIONS_FIELD,
365
+ };
366
+
367
+ export const PDF_DEFAULTS = {
368
+ template: "report",
369
+ pageSize: "letter",
370
+ includeTableOfContents: true,
371
+ instructions: "",
372
+ };
373
+
374
+ // =============================================================================
375
+ // Email KSA Config
376
+ // =============================================================================
377
+
378
+ export const EMAIL_CONFIG_SCHEMA: Record<string, ConfigField> = {
379
+ fromName: {
380
+ type: "string",
381
+ label: "From Name",
382
+ description: "Sender display name",
383
+ placeholder: "e.g., Marketing Team",
384
+ default: "Agent",
385
+ },
386
+ replyTo: {
387
+ type: "string",
388
+ label: "Reply-To",
389
+ description: "Reply-to email address",
390
+ placeholder: "e.g., replies@company.com",
391
+ default: "",
392
+ },
393
+ sandboxMode: {
394
+ type: "boolean",
395
+ label: "Sandbox Mode",
396
+ description: "Test mode - emails are logged but not sent",
397
+ default: true,
398
+ },
399
+ defaultTemplateId: {
400
+ type: "string",
401
+ label: "Default Template ID",
402
+ description: "SendGrid template ID",
403
+ placeholder: "e.g., d-abc123...",
404
+ default: "",
405
+ },
406
+ instructions: INSTRUCTIONS_FIELD,
407
+ };
408
+
409
+ export const EMAIL_DEFAULTS = {
410
+ fromName: "Agent",
411
+ replyTo: "",
412
+ sandboxMode: true,
413
+ defaultTemplateId: "",
414
+ instructions: "",
415
+ };
416
+
417
+ // =============================================================================
418
+ // News KSA Config
419
+ // =============================================================================
420
+
421
+ export const NEWS_CONFIG_SCHEMA: Record<string, ConfigField> = {
422
+ sources: {
423
+ type: "multiselect",
424
+ label: "News Sources",
425
+ description: "Preferred news sources",
426
+ options: [
427
+ { value: "general", label: "General News" },
428
+ { value: "tech", label: "Tech News" },
429
+ { value: "business", label: "Business News" },
430
+ { value: "finance", label: "Finance News" },
431
+ ],
432
+ default: ["general"],
433
+ },
434
+ recency: {
435
+ type: "select",
436
+ label: "Recency",
437
+ description: "How recent should articles be",
438
+ options: [
439
+ { value: "day", label: "Last 24 hours" },
440
+ { value: "week", label: "Last week" },
441
+ { value: "month", label: "Last month" },
442
+ { value: "any", label: "Any time" },
443
+ ],
444
+ default: "week",
445
+ },
446
+ instructions: INSTRUCTIONS_FIELD,
447
+ };
448
+
449
+ export const NEWS_DEFAULTS = {
450
+ sources: ["general"],
451
+ recency: "week",
452
+ instructions: "",
453
+ };
454
+
455
+ // =============================================================================
456
+ // Browser KSA Config
457
+ // =============================================================================
458
+
459
+ export const BROWSER_CONFIG_SCHEMA: Record<string, ConfigField> = {
460
+ headless: {
461
+ type: "boolean",
462
+ label: "Headless Mode",
463
+ description: "Run browser without UI",
464
+ default: true,
465
+ },
466
+ timeout: {
467
+ type: "number",
468
+ label: "Page Timeout",
469
+ description: "Max seconds to wait for page load",
470
+ min: 5,
471
+ max: 120,
472
+ default: 30,
473
+ },
474
+ instructions: INSTRUCTIONS_FIELD,
475
+ };
476
+
477
+ export const BROWSER_DEFAULTS = {
478
+ headless: true,
479
+ timeout: 30,
480
+ instructions: "",
481
+ };
482
+
483
+ // =============================================================================
484
+ // Platform-Specific Presets
485
+ // =============================================================================
486
+
487
+ export const KSA_PRESETS: PresetDefinition[] = [
488
+ // Social presets
489
+ {
490
+ name: "instagram-research",
491
+ displayName: "Instagram Research",
492
+ description: "Social research focused on Instagram",
493
+ icon: "mdi:instagram",
494
+ baseKSA: "social",
495
+ lockedConfig: { platforms: ["instagram"] },
496
+ },
497
+ {
498
+ name: "tiktok-research",
499
+ displayName: "TikTok Research",
500
+ description: "Social research focused on TikTok trends",
501
+ icon: "mdi:music-note",
502
+ baseKSA: "social",
503
+ lockedConfig: { platforms: ["tiktok"] },
504
+ },
505
+ {
506
+ name: "linkedin-research",
507
+ displayName: "LinkedIn Research",
508
+ description: "B2B professional network research",
509
+ icon: "mdi:linkedin",
510
+ baseKSA: "social",
511
+ lockedConfig: { platforms: ["linkedin"] },
512
+ },
513
+ {
514
+ name: "youtube-research",
515
+ displayName: "YouTube Research",
516
+ description: "Video content and channel analysis",
517
+ icon: "mdi:youtube",
518
+ baseKSA: "social",
519
+ lockedConfig: { platforms: ["youtube"] },
520
+ },
521
+
522
+ // Web presets
523
+ {
524
+ name: "news-monitoring",
525
+ displayName: "News Monitoring",
526
+ description: "News-focused web research",
527
+ icon: "mdi:newspaper",
528
+ baseKSA: "web",
529
+ lockedConfig: { searchType: "news" },
530
+ },
531
+ {
532
+ name: "deep-research",
533
+ displayName: "Deep Research",
534
+ description: "Thorough web research with more results",
535
+ icon: "mdi:magnify-plus",
536
+ baseKSA: "web",
537
+ lockedConfig: { depth: "thorough", fastMode: false },
538
+ },
539
+
540
+ // Companies presets
541
+ {
542
+ name: "company-enrichment",
543
+ displayName: "Company Enrichment",
544
+ description: "Full company data enrichment",
545
+ icon: "mdi:office-building",
546
+ baseKSA: "companies",
547
+ lockedConfig: { enrichmentLevel: "full", includeTechStack: true },
548
+ },
549
+ {
550
+ name: "tech-stack-lookup",
551
+ displayName: "Tech Stack Lookup",
552
+ description: "Focus on technology stack discovery",
553
+ icon: "mdi:code-braces",
554
+ baseKSA: "companies",
555
+ lockedConfig: { includeTechStack: true },
556
+ },
557
+ ];
558
+
559
+ // =============================================================================
560
+ // Registry Export
561
+ // =============================================================================
562
+
563
+ export const CONFIG_SCHEMAS: Record<string, Record<string, ConfigField>> = {
564
+ _framework: FRAMEWORK_CONFIG_SCHEMA,
565
+ web: WEB_CONFIG_SCHEMA,
566
+ social: SOCIAL_CONFIG_SCHEMA,
567
+ companies: COMPANIES_CONFIG_SCHEMA,
568
+ artifacts: ARTIFACTS_CONFIG_SCHEMA,
569
+ pdf: PDF_CONFIG_SCHEMA,
570
+ email: EMAIL_CONFIG_SCHEMA,
571
+ news: NEWS_CONFIG_SCHEMA,
572
+ browser: BROWSER_CONFIG_SCHEMA,
573
+ };
574
+
575
+ export const CONFIG_DEFAULTS: Record<string, Record<string, unknown>> = {
576
+ _framework: FRAMEWORK_DEFAULTS,
577
+ web: WEB_DEFAULTS,
578
+ social: SOCIAL_DEFAULTS,
579
+ companies: COMPANIES_DEFAULTS,
580
+ artifacts: ARTIFACTS_DEFAULTS,
581
+ pdf: PDF_DEFAULTS,
582
+ email: EMAIL_DEFAULTS,
583
+ news: NEWS_DEFAULTS,
584
+ browser: BROWSER_DEFAULTS,
585
+ };
586
+
587
+ /**
588
+ * Get config schema for a KSA
589
+ */
590
+ export function getConfigSchema(
591
+ ksaName: string
592
+ ): Record<string, ConfigField> | undefined {
593
+ return CONFIG_SCHEMAS[ksaName];
594
+ }
595
+
596
+ /**
597
+ * Get default config for a KSA
598
+ */
599
+ export function getConfigDefaults(
600
+ ksaName: string
601
+ ): Record<string, unknown> | undefined {
602
+ return CONFIG_DEFAULTS[ksaName];
603
+ }
604
+
605
+ /**
606
+ * Get a preset by name
607
+ */
608
+ export function getPreset(name: string): PresetDefinition | undefined {
609
+ return KSA_PRESETS.find((p) => p.name === name);
610
+ }
611
+
612
+ /**
613
+ * Get all presets for a base KSA
614
+ */
615
+ export function getPresetsForKSA(ksaName: string): PresetDefinition[] {
616
+ return KSA_PRESETS.filter((p) => p.baseKSA === ksaName);
617
+ }
618
+
619
+ /**
620
+ * Merge user config with defaults
621
+ */
622
+ export function mergeWithDefaults(
623
+ ksaName: string,
624
+ userConfig: Record<string, unknown>
625
+ ): Record<string, unknown> {
626
+ const defaults = CONFIG_DEFAULTS[ksaName] || {};
627
+ return { ...defaults, ...userConfig };
628
+ }
629
+
630
+ /**
631
+ * Resolve a preset to its base KSA + merged config
632
+ */
633
+ export function resolvePreset(presetName: string): {
634
+ baseKSA: string;
635
+ config: Record<string, unknown>;
636
+ lockedFields: string[];
637
+ } | null {
638
+ const preset = getPreset(presetName);
639
+ if (!preset) return null;
640
+
641
+ const defaults = CONFIG_DEFAULTS[preset.baseKSA] || {};
642
+ const config = { ...defaults, ...preset.lockedConfig };
643
+
644
+ return {
645
+ baseKSA: preset.baseKSA,
646
+ config,
647
+ lockedFields: Object.keys(preset.lockedConfig),
648
+ };
649
+ }