kavoru 0.9.3 → 0.9.4

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.4",
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,10 @@ 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_URL=http://llama:11434");
778
+ lines.push("LLAMA_MODEL=llama3.2");
779
+ }
746
780
  return `${lines.join("\n")}\n`;
747
781
  }
748
782
 
@@ -760,6 +794,10 @@ function buildAppDependsOn(selection: FeatureSelection): string {
760
794
  deps.push(` redis:
761
795
  condition: service_healthy`);
762
796
  }
797
+ if (selection.llama) {
798
+ deps.push(` llama:
799
+ condition: service_started`);
800
+ }
763
801
  if (deps.length === 0) return "";
764
802
  return ` depends_on:
765
803
  ${deps.join("\n")}
@@ -863,6 +901,24 @@ function generateDockerCompose(selection: FeatureSelection): string {
863
901
  `
864
902
  : "";
865
903
 
904
+ const llamaService = selection.llama
905
+ ? `
906
+ llama:
907
+ build:
908
+ context: docker/llama
909
+ hostname: llama
910
+ ports:
911
+ - "\${LLAMA_PORT:-11434}:11434"
912
+ env_file:
913
+ - docker/llama/.env
914
+ volumes:
915
+ - llama_data:/root/.ollama
916
+ networks:
917
+ - app_network
918
+ restart: unless-stopped
919
+ `
920
+ : "";
921
+
866
922
  return `services:
867
923
  app:
868
924
  build:
@@ -893,11 +949,19 @@ ${appDependsOn} healthcheck:
893
949
  timeout: 300s
894
950
  retries: 1
895
951
  start_period: 90s
896
- ${postgresService}${kafkaService}${redisService}${otelService}${spotlightService}
952
+ ${postgresService}${kafkaService}${redisService}${otelService}${spotlightService}${llamaService}
897
953
  networks:
898
954
  app_network:
899
955
  driver: bridge
900
- ${selection.postgres ? "\nvolumes:\n postgres_data:\n" : ""}`;
956
+ ${buildComposeVolumes(selection)}`;
957
+ }
958
+
959
+ function buildComposeVolumes(selection: FeatureSelection): string {
960
+ const volumes: string[] = [];
961
+ if (selection.postgres) volumes.push(" postgres_data:");
962
+ if (selection.llama) volumes.push(" llama_data:");
963
+ if (volumes.length === 0) return "";
964
+ return `\nvolumes:\n${volumes.join("\n")}\n`;
901
965
  }
902
966
 
903
967
  async function patchDockerCompose(
@@ -923,6 +987,9 @@ async function patchDockerCompose(
923
987
  if (!selection.sentry) {
924
988
  await removePaths(projectDir, ["docker/spotlight"]);
925
989
  }
990
+ if (!selection.llama) {
991
+ await removePaths(projectDir, ["docker/llama"]);
992
+ }
926
993
 
927
994
  await writeText(
928
995
  projectDir,
@@ -952,6 +1019,9 @@ async function patchDockerCompose(
952
1019
  if (selection.sentry) {
953
1020
  await writeText(projectDir, "docker/spotlight/.env", DOCKER_SPOTLIGHT_ENV);
954
1021
  }
1022
+ if (selection.llama) {
1023
+ await writeText(projectDir, "docker/llama/.env", DOCKER_LLAMA_ENV);
1024
+ }
955
1025
  await writeText(
956
1026
  projectDir,
957
1027
  "docker-compose.yaml",