kavoru 0.9.3 → 0.9.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kavoru",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "Scaffold a new Kavoru (Elysia + Bun) backend from the official template",
5
5
  "type": "module",
6
6
  "bin": {
package/src/args.ts CHANGED
@@ -37,7 +37,7 @@ Options:
37
37
  --no-features <list> Comma-separated features to exclude
38
38
 
39
39
  Features:
40
- auth, postgres, otel, sentry, kafka, redis, websocket, resend, cron, cli
40
+ auth, postgres, otel, sentry, kafka, redis, llama, websocket, resend, cron, cli
41
41
  (prisma is accepted as an alias for postgres; kavoru-cli for cli)
42
42
  Docker Compose is always included — not a toggle.
43
43
 
package/src/features.ts CHANGED
@@ -9,6 +9,7 @@ export type FeatureId =
9
9
  | "sentry"
10
10
  | "kafka"
11
11
  | "redis"
12
+ | "llama"
12
13
  | "websocket"
13
14
  | "resend"
14
15
  | "cron"
@@ -61,6 +62,11 @@ export const FEATURES: FeatureDef[] = [
61
62
  label: "Redis",
62
63
  description: "Cache client and CRUD HTTP endpoints",
63
64
  },
65
+ {
66
+ id: "llama",
67
+ label: "Llama (Ollama)",
68
+ description: "Local LLM via Ollama Docker service and chat endpoint",
69
+ },
64
70
  {
65
71
  id: "websocket",
66
72
  label: "WebSockets",
@@ -121,6 +127,12 @@ const FEATURE_PATHS: Record<FeatureId, string[]> = {
121
127
  "src/models/schemas/redis.ts",
122
128
  "__tests__/redis.test.ts",
123
129
  ],
130
+ llama: [
131
+ "src/modules/llama",
132
+ "src/infra/llama",
133
+ "src/models/schemas/llama.ts",
134
+ "__tests__/llama.test.ts",
135
+ ],
124
136
  websocket: [
125
137
  "src/modules/realtime",
126
138
  "src/models/schemas/realtime.ts",
@@ -618,6 +630,18 @@ export function buildEnvExample(
618
630
  );
619
631
  }
620
632
 
633
+ if (selection.llama) {
634
+ lines.push(
635
+ "# Llama via Ollama (enabled by default in development; disabled in test)",
636
+ "# Start server: docker compose up -d llama",
637
+ "# Model is pulled automatically on first llama container start",
638
+ "# LLAMA_ENABLED=false",
639
+ "LLAMA_URL=http://localhost:11434",
640
+ "LLAMA_MODEL=llama3.2",
641
+ "",
642
+ );
643
+ }
644
+
621
645
  if (selection.resend) {
622
646
  lines.push(
623
647
  "# Resend (disabled when RESEND_API_KEY is unset; always disabled in test)",
@@ -709,6 +733,12 @@ const DOCKER_OTEL_ENV =
709
733
  const DOCKER_SPOTLIGHT_ENV =
710
734
  "# Official Spotlight image; add overrides here if needed.\n";
711
735
 
736
+ const DOCKER_LLAMA_ENV = `# Ollama serves Llama models on port 11434
737
+ # Pulled automatically on first container start (see docker-entrypoint.sh)
738
+ OLLAMA_HOST=0.0.0.0
739
+ OLLAMA_MODEL=llama3.2
740
+ `;
741
+
712
742
  function buildDockerPostgresEnv(packageName: string): string {
713
743
  const name = toPostgresName(packageName);
714
744
  return `POSTGRES_USER=${name}
@@ -743,6 +773,11 @@ function buildDockerAppEnv(
743
773
  if (selection.sentry) {
744
774
  lines.push("SENTRY_SPOTLIGHT=http://spotlight:8969/stream");
745
775
  }
776
+ if (selection.llama) {
777
+ lines.push("LLAMA_ENABLED=true");
778
+ lines.push("LLAMA_URL=http://llama:11434");
779
+ lines.push("LLAMA_MODEL=llama3.2");
780
+ }
746
781
  return `${lines.join("\n")}\n`;
747
782
  }
748
783
 
@@ -760,6 +795,10 @@ function buildAppDependsOn(selection: FeatureSelection): string {
760
795
  deps.push(` redis:
761
796
  condition: service_healthy`);
762
797
  }
798
+ if (selection.llama) {
799
+ deps.push(` llama:
800
+ condition: service_started`);
801
+ }
763
802
  if (deps.length === 0) return "";
764
803
  return ` depends_on:
765
804
  ${deps.join("\n")}
@@ -863,6 +902,24 @@ function generateDockerCompose(selection: FeatureSelection): string {
863
902
  `
864
903
  : "";
865
904
 
905
+ const llamaService = selection.llama
906
+ ? `
907
+ llama:
908
+ build:
909
+ context: docker/llama
910
+ hostname: llama
911
+ ports:
912
+ - "\${LLAMA_PORT:-11434}:11434"
913
+ env_file:
914
+ - docker/llama/.env
915
+ volumes:
916
+ - llama_data:/root/.ollama
917
+ networks:
918
+ - app_network
919
+ restart: unless-stopped
920
+ `
921
+ : "";
922
+
866
923
  return `services:
867
924
  app:
868
925
  build:
@@ -893,11 +950,19 @@ ${appDependsOn} healthcheck:
893
950
  timeout: 300s
894
951
  retries: 1
895
952
  start_period: 90s
896
- ${postgresService}${kafkaService}${redisService}${otelService}${spotlightService}
953
+ ${postgresService}${kafkaService}${redisService}${otelService}${spotlightService}${llamaService}
897
954
  networks:
898
955
  app_network:
899
956
  driver: bridge
900
- ${selection.postgres ? "\nvolumes:\n postgres_data:\n" : ""}`;
957
+ ${buildComposeVolumes(selection)}`;
958
+ }
959
+
960
+ function buildComposeVolumes(selection: FeatureSelection): string {
961
+ const volumes: string[] = [];
962
+ if (selection.postgres) volumes.push(" postgres_data:");
963
+ if (selection.llama) volumes.push(" llama_data:");
964
+ if (volumes.length === 0) return "";
965
+ return `\nvolumes:\n${volumes.join("\n")}\n`;
901
966
  }
902
967
 
903
968
  async function patchDockerCompose(
@@ -923,6 +988,9 @@ async function patchDockerCompose(
923
988
  if (!selection.sentry) {
924
989
  await removePaths(projectDir, ["docker/spotlight"]);
925
990
  }
991
+ if (!selection.llama) {
992
+ await removePaths(projectDir, ["docker/llama"]);
993
+ }
926
994
 
927
995
  await writeText(
928
996
  projectDir,
@@ -952,6 +1020,9 @@ async function patchDockerCompose(
952
1020
  if (selection.sentry) {
953
1021
  await writeText(projectDir, "docker/spotlight/.env", DOCKER_SPOTLIGHT_ENV);
954
1022
  }
1023
+ if (selection.llama) {
1024
+ await writeText(projectDir, "docker/llama/.env", DOCKER_LLAMA_ENV);
1025
+ }
955
1026
  await writeText(
956
1027
  projectDir,
957
1028
  "docker-compose.yaml",