From 501b844f0f2d4fe7d47a5b8a22eb6bd9bd0a59b1 Mon Sep 17 00:00:00 2001
From: Alex Yang <himself65@outlook.com>
Date: Sun, 21 Apr 2024 20:31:16 -0500
Subject: [PATCH] refactor: use official ollama sdk (#744)

---
 examples/ollama.ts                            |   2 +-
 packages/core/e2e/fixtures/llm/anthropic.ts   |   2 +-
 .../fixtures/llm/{open_ai.ts => openai.ts}    |   0
 packages/core/package.json                    |   3 +-
 packages/core/src/ChatHistory.ts              |   2 +-
 packages/core/src/QuestionGenerator.ts        |   2 +-
 packages/core/src/ServiceContext.ts           |   2 +-
 packages/core/src/Settings.ts                 |   2 +-
 packages/core/src/agent/openai.ts             |   2 +-
 .../core/src/embeddings/OpenAIEmbedding.ts    |   4 +-
 packages/core/src/index.ts                    |   2 +
 packages/core/src/llm/fireworks.ts            |   2 +-
 packages/core/src/llm/groq.ts                 |   2 +-
 packages/core/src/llm/index.ts                |   3 +-
 packages/core/src/llm/ollama.ts               | 287 +++++----
 .../core/src/llm/{open_ai.ts => openai.ts}    |   0
 packages/core/src/llm/together.ts             |   2 +-
 packages/core/tests/CallbackManager.test.ts   |   2 +-
 .../core/tests/MetadataExtractors.test.ts     |   2 +-
 packages/core/tests/utility/mockOpenAI.ts     |   2 +-
 packages/edge/package.json                    |   1 +
 pnpm-lock.yaml                                | 556 +++++-------------
 22 files changed, 351 insertions(+), 531 deletions(-)
 rename packages/core/e2e/fixtures/llm/{open_ai.ts => openai.ts} (100%)
 rename packages/core/src/llm/{open_ai.ts => openai.ts} (100%)

diff --git a/examples/ollama.ts b/examples/ollama.ts
index d5cd145e6..745855a8c 100644
--- a/examples/ollama.ts
+++ b/examples/ollama.ts
@@ -1,7 +1,7 @@
 import { Ollama } from "llamaindex/llm/ollama";
 
 (async () => {
-  const llm = new Ollama({ model: "llama2", temperature: 0.75 });
+  const llm = new Ollama({ model: "llama3" });
   {
     const response = await llm.chat({
       messages: [{ content: "Tell me a joke.", role: "user" }],
diff --git a/packages/core/e2e/fixtures/llm/anthropic.ts b/packages/core/e2e/fixtures/llm/anthropic.ts
index 8d5d01e58..e5490befe 100644
--- a/packages/core/e2e/fixtures/llm/anthropic.ts
+++ b/packages/core/e2e/fixtures/llm/anthropic.ts
@@ -1,3 +1,3 @@
-import { OpenAI } from "./open_ai.js";
+import { OpenAI } from "./openai.js";
 
 export class Anthropic extends OpenAI {}
diff --git a/packages/core/e2e/fixtures/llm/open_ai.ts b/packages/core/e2e/fixtures/llm/openai.ts
similarity index 100%
rename from packages/core/e2e/fixtures/llm/open_ai.ts
rename to packages/core/e2e/fixtures/llm/openai.ts
diff --git a/packages/core/package.json b/packages/core/package.json
index f3328348b..18409fbab 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -32,6 +32,7 @@
     "md-utils-ts": "^2.0.0",
     "mongodb": "^6.5.0",
     "notion-md-crawler": "^0.0.2",
+    "ollama": "^0.5.0",
     "openai": "^4.38.0",
     "papaparse": "^5.4.1",
     "pathe": "^1.1.2",
@@ -49,7 +50,7 @@
     "@swc/core": "^1.4.16",
     "concurrently": "^8.2.2",
     "glob": "^10.3.12",
-    "madge": "^6.1.0",
+    "madge": "^7.0.0",
     "typescript": "^5.4.5"
   },
   "engines": {
diff --git a/packages/core/src/ChatHistory.ts b/packages/core/src/ChatHistory.ts
index 470ad6507..1da4e612b 100644
--- a/packages/core/src/ChatHistory.ts
+++ b/packages/core/src/ChatHistory.ts
@@ -1,7 +1,7 @@
 import { globalsHelper } from "./GlobalsHelper.js";
 import type { SummaryPrompt } from "./Prompt.js";
 import { defaultSummaryPrompt, messagesToHistoryStr } from "./Prompt.js";
-import { OpenAI } from "./llm/open_ai.js";
+import { OpenAI } from "./llm/openai.js";
 import type { ChatMessage, LLM, MessageType } from "./llm/types.js";
 import { extractText } from "./llm/utils.js";
 
diff --git a/packages/core/src/QuestionGenerator.ts b/packages/core/src/QuestionGenerator.ts
index 0e7785a9e..74c350564 100644
--- a/packages/core/src/QuestionGenerator.ts
+++ b/packages/core/src/QuestionGenerator.ts
@@ -5,7 +5,7 @@ import type {
   BaseQuestionGenerator,
   SubQuestion,
 } from "./engines/query/types.js";
-import { OpenAI } from "./llm/open_ai.js";
+import { OpenAI } from "./llm/openai.js";
 import type { LLM } from "./llm/types.js";
 import { PromptMixin } from "./prompts/index.js";
 import type {
diff --git a/packages/core/src/ServiceContext.ts b/packages/core/src/ServiceContext.ts
index 48a318f02..0686d2a0b 100644
--- a/packages/core/src/ServiceContext.ts
+++ b/packages/core/src/ServiceContext.ts
@@ -1,7 +1,7 @@
 import { PromptHelper } from "./PromptHelper.js";
 import { OpenAIEmbedding } from "./embeddings/OpenAIEmbedding.js";
 import type { BaseEmbedding } from "./embeddings/types.js";
-import { OpenAI } from "./llm/open_ai.js";
+import { OpenAI } from "./llm/openai.js";
 import type { LLM } from "./llm/types.js";
 import { SimpleNodeParser } from "./nodeParsers/SimpleNodeParser.js";
 import type { NodeParser } from "./nodeParsers/types.js";
diff --git a/packages/core/src/Settings.ts b/packages/core/src/Settings.ts
index bf30f3f4d..7e9f8eb90 100644
--- a/packages/core/src/Settings.ts
+++ b/packages/core/src/Settings.ts
@@ -1,6 +1,6 @@
 import { CallbackManager } from "./callbacks/CallbackManager.js";
 import { OpenAIEmbedding } from "./embeddings/OpenAIEmbedding.js";
-import { OpenAI } from "./llm/open_ai.js";
+import { OpenAI } from "./llm/openai.js";
 
 import { PromptHelper } from "./PromptHelper.js";
 import { SimpleNodeParser } from "./nodeParsers/SimpleNodeParser.js";
diff --git a/packages/core/src/agent/openai.ts b/packages/core/src/agent/openai.ts
index 47c25325b..89a707724 100644
--- a/packages/core/src/agent/openai.ts
+++ b/packages/core/src/agent/openai.ts
@@ -6,7 +6,7 @@ import type {
   ToolCall,
   ToolCallLLMMessageOptions,
 } from "../llm/index.js";
-import { OpenAI } from "../llm/open_ai.js";
+import { OpenAI } from "../llm/openai.js";
 import { ObjectRetriever } from "../objects/index.js";
 import type { BaseToolWithCall } from "../types.js";
 import {
diff --git a/packages/core/src/embeddings/OpenAIEmbedding.ts b/packages/core/src/embeddings/OpenAIEmbedding.ts
index e46de7c80..42037692c 100644
--- a/packages/core/src/embeddings/OpenAIEmbedding.ts
+++ b/packages/core/src/embeddings/OpenAIEmbedding.ts
@@ -6,8 +6,8 @@ import {
   getAzureModel,
   shouldUseAzure,
 } from "../llm/azure.js";
-import type { OpenAISession } from "../llm/open_ai.js";
-import { getOpenAISession } from "../llm/open_ai.js";
+import type { OpenAISession } from "../llm/openai.js";
+import { getOpenAISession } from "../llm/openai.js";
 import { BaseEmbedding } from "./types.js";
 
 export const ALL_OPENAI_EMBEDDING_MODELS = {
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 99167ee4b..a3bc326f9 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -1,3 +1,5 @@
 export * from "./index.edge.js";
 export * from "./readers/index.js";
 export * from "./storage/index.js";
+// Ollama is only compatible with the Node.js runtime
+export { Ollama, type OllamaParams } from "./llm/ollama.js";
diff --git a/packages/core/src/llm/fireworks.ts b/packages/core/src/llm/fireworks.ts
index f7814559b..0385b62f2 100644
--- a/packages/core/src/llm/fireworks.ts
+++ b/packages/core/src/llm/fireworks.ts
@@ -1,5 +1,5 @@
 import { getEnv } from "@llamaindex/env";
-import { OpenAI } from "./open_ai.js";
+import { OpenAI } from "./openai.js";
 
 export class FireworksLLM extends OpenAI {
   constructor(init?: Partial<OpenAI>) {
diff --git a/packages/core/src/llm/groq.ts b/packages/core/src/llm/groq.ts
index 083e305cb..6683f3cdc 100644
--- a/packages/core/src/llm/groq.ts
+++ b/packages/core/src/llm/groq.ts
@@ -1,5 +1,5 @@
 import { getEnv } from "@llamaindex/env";
-import { OpenAI } from "./open_ai.js";
+import { OpenAI } from "./openai.js";
 
 export class Groq extends OpenAI {
   constructor(init?: Partial<OpenAI>) {
diff --git a/packages/core/src/llm/index.ts b/packages/core/src/llm/index.ts
index 836cd4be7..46d8b6892 100644
--- a/packages/core/src/llm/index.ts
+++ b/packages/core/src/llm/index.ts
@@ -6,8 +6,7 @@ export {
   MistralAI,
   MistralAISession,
 } from "./mistral.js";
-export { Ollama } from "./ollama.js";
-export * from "./open_ai.js";
+export * from "./openai.js";
 export { Portkey } from "./portkey.js";
 export * from "./replicate_ai.js";
 // Note: The type aliases for replicate are to simplify usage for Llama 2 (we're using replicate for Llama 2 support)
diff --git a/packages/core/src/llm/ollama.ts b/packages/core/src/llm/ollama.ts
index c7b132bc8..195b5ef05 100644
--- a/packages/core/src/llm/ollama.ts
+++ b/packages/core/src/llm/ollama.ts
@@ -1,4 +1,11 @@
-import { ok } from "@llamaindex/env";
+import ollama, {
+  type CreateRequest,
+  type ChatResponse as OllamaChatResponse,
+  type GenerateResponse as OllamaGenerateResponse,
+  type Options,
+  type ProgressResponse,
+  type ShowRequest,
+} from "ollama/browser";
 import { BaseEmbedding } from "../embeddings/types.js";
 import type {
   ChatResponse,
@@ -11,55 +18,62 @@ import type {
   LLMCompletionParamsStreaming,
   LLMMetadata,
 } from "./types.js";
+import { extractText, streamConverter } from "./utils.js";
 
-const messageAccessor = (data: any): ChatResponseChunk => {
+const messageAccessor = (part: OllamaChatResponse): ChatResponseChunk => {
   return {
-    raw: data,
-    delta: data.message.content,
+    raw: part,
+    delta: part.message.content,
   };
 };
 
-const completionAccessor = (data: any): CompletionResponse => {
-  return { text: data.response, raw: null };
+const completionAccessor = (
+  part: OllamaGenerateResponse,
+): CompletionResponse => {
+  return { text: part.response, raw: part };
 };
 
-// https://github.com/jmorganca/ollama
+export type OllamaParams = {
+  model: string;
+  options?: Partial<Options>;
+};
+
+/**
+ * This class both implements the LLM and Embedding interfaces.
+ */
 export class Ollama extends BaseEmbedding implements LLM {
   readonly hasStreaming = true;
 
   // https://ollama.ai/library
   model: string;
-  baseURL: string = "http://127.0.0.1:11434";
-  temperature: number = 0.7;
-  topP: number = 0.9;
-  contextWindow: number = 4096;
-  requestTimeout: number = 60 * 1000; // Default is 60 seconds
-  additionalChatOptions?: Record<string, unknown>;
-
-  protected modelMetadata: Partial<LLMMetadata>;
-
-  constructor(
-    init: Partial<Ollama> & {
-      // model is required
-      model: string;
-      modelMetadata?: Partial<LLMMetadata>;
-    },
-  ) {
+
+  options: Partial<Omit<Options, "num_ctx" | "top_p" | "temperature">> &
+    Pick<Options, "num_ctx" | "top_p" | "temperature"> = {
+    num_ctx: 4096,
+    top_p: 0.9,
+    temperature: 0.7,
+  };
+
+  constructor(params: OllamaParams) {
     super();
-    this.model = init.model;
-    this.modelMetadata = init.modelMetadata ?? {};
-    Object.assign(this, init);
+    this.model = params.model;
+    if (params.options) {
+      this.options = {
+        ...this.options,
+        ...params.options,
+      };
+    }
   }
 
   get metadata(): LLMMetadata {
+    const { temperature, top_p, num_ctx } = this.options;
     return {
       model: this.model,
-      temperature: this.temperature,
-      topP: this.topP,
+      temperature: temperature,
+      topP: top_p,
       maxTokens: undefined,
-      contextWindow: this.contextWindow,
+      contextWindow: num_ctx,
       tokenizer: undefined,
-      ...this.modelMetadata,
     };
   }
 
@@ -75,66 +89,32 @@ export class Ollama extends BaseEmbedding implements LLM {
       model: this.model,
       messages: messages.map((message) => ({
         role: message.role,
-        content: message.content,
+        content: extractText(message.content),
       })),
       stream: !!stream,
       options: {
-        temperature: this.temperature,
-        num_ctx: this.contextWindow,
-        top_p: this.topP,
-        ...this.additionalChatOptions,
+        ...this.options,
       },
     };
-    const response = await fetch(`${this.baseURL}/api/chat`, {
-      body: JSON.stringify(payload),
-      method: "POST",
-      signal: AbortSignal.timeout(this.requestTimeout),
-      headers: {
-        "Content-Type": "application/json",
-      },
-    });
     if (!stream) {
-      const raw = await response.json();
-      const { message } = raw;
+      const chatResponse = await ollama.chat({
+        ...payload,
+        stream: false,
+      });
+
       return {
         message: {
           role: "assistant",
-          content: message.content,
+          content: chatResponse.message.content,
         },
-        raw,
+        raw: chatResponse,
       };
     } else {
-      const stream = response.body;
-      ok(stream, "stream is null");
-      ok(stream instanceof ReadableStream, "stream is not readable");
-      return this.streamChat(stream, messageAccessor);
-    }
-  }
-
-  private async *streamChat<T>(
-    stream: ReadableStream<Uint8Array>,
-    accessor: (data: any) => T,
-  ): AsyncIterable<T> {
-    const reader = stream.getReader();
-    while (true) {
-      const { done, value } = await reader.read();
-      if (done) {
-        return;
-      }
-      const lines = Buffer.from(value)
-        .toString("utf-8")
-        .split("\n")
-        .map((line) => line.trim());
-      for (const line of lines) {
-        if (line === "") {
-          continue;
-        }
-        const json = JSON.parse(line);
-        if (json.error) {
-          throw new Error(json.error);
-        }
-        yield accessor(json);
-      }
+      const stream = await ollama.chat({
+        ...payload,
+        stream: true,
+      });
+      return streamConverter(stream, messageAccessor);
     }
   }
 
@@ -150,34 +130,27 @@ export class Ollama extends BaseEmbedding implements LLM {
     const { prompt, stream } = params;
     const payload = {
       model: this.model,
-      prompt: prompt,
+      prompt: extractText(prompt),
       stream: !!stream,
       options: {
-        temperature: this.temperature,
-        num_ctx: this.contextWindow,
-        top_p: this.topP,
-        ...this.additionalChatOptions,
+        ...this.options,
       },
     };
-    const response = await fetch(`${this.baseURL}/api/generate`, {
-      body: JSON.stringify(payload),
-      method: "POST",
-      signal: AbortSignal.timeout(this.requestTimeout),
-      headers: {
-        "Content-Type": "application/json",
-      },
-    });
     if (!stream) {
-      const raw = await response.json();
+      const response = await ollama.generate({
+        ...payload,
+        stream: false,
+      });
       return {
-        text: raw.response,
-        raw,
+        text: response.response,
+        raw: response,
       };
     } else {
-      const stream = response.body;
-      ok(stream, "stream is null");
-      ok(stream instanceof ReadableStream, "stream is not readable");
-      return this.streamChat(stream, completionAccessor);
+      const stream = await ollama.generate({
+        ...payload,
+        stream: true,
+      });
+      return streamConverter(stream, completionAccessor);
     }
   }
 
@@ -186,22 +159,13 @@ export class Ollama extends BaseEmbedding implements LLM {
       model: this.model,
       prompt,
       options: {
-        temperature: this.temperature,
-        num_ctx: this.contextWindow,
-        top_p: this.topP,
-        ...this.additionalChatOptions,
+        ...this.options,
       },
     };
-    const response = await fetch(`${this.baseURL}/api/embeddings`, {
-      body: JSON.stringify(payload),
-      method: "POST",
-      signal: AbortSignal.timeout(this.requestTimeout),
-      headers: {
-        "Content-Type": "application/json",
-      },
+    const response = await ollama.embeddings({
+      ...payload,
     });
-    const { embedding } = await response.json();
-    return embedding;
+    return response.embedding;
   }
 
   async getTextEmbedding(text: string): Promise<number[]> {
@@ -211,4 +175,105 @@ export class Ollama extends BaseEmbedding implements LLM {
   async getQueryEmbedding(query: string): Promise<number[]> {
     return this.getEmbedding(query);
   }
+
+  // ollama specific methods, inherited from the ollama library
+  static async list() {
+    const { models } = await ollama.list();
+    return models;
+  }
+
+  static async detail(modelName: string, options?: Omit<ShowRequest, "model">) {
+    return ollama.show({
+      model: modelName,
+      ...options,
+    });
+  }
+
+  static async create(
+    modelName: string,
+    options?: Omit<CreateRequest, "model"> & {
+      stream: false;
+    },
+  ): Promise<ProgressResponse>;
+  static async create(
+    modelName: string,
+    options: Omit<CreateRequest, "model"> & {
+      stream: true;
+    },
+  ): Promise<AsyncGenerator<ProgressResponse>>;
+  static async create(
+    modelName: string,
+    options?: Omit<CreateRequest, "model"> & {
+      stream: boolean;
+    },
+  ) {
+    return ollama.create({
+      model: modelName,
+      ...options,
+      stream: (options ? !!options.stream : false) as never,
+    }) as Promise<ProgressResponse> | Promise<AsyncGenerator<ProgressResponse>>;
+  }
+
+  static async delete(modelName: string) {
+    return ollama.delete({
+      model: modelName,
+    });
+  }
+
+  static async copy(source: string, destination: string) {
+    return ollama.copy({
+      source,
+      destination,
+    });
+  }
+
+  static async pull(
+    modelName: string,
+    options?: Omit<CreateRequest, "model"> & {
+      stream: false;
+    },
+  ): Promise<ProgressResponse>;
+  static async pull(
+    modelName: string,
+    options: Omit<CreateRequest, "model"> & {
+      stream: true;
+    },
+  ): Promise<AsyncGenerator<ProgressResponse>>;
+  static async pull(
+    modelName: string,
+    options?: Omit<CreateRequest, "model"> & {
+      stream: boolean;
+    },
+  ) {
+    return ollama.pull({
+      model: modelName,
+      ...options,
+      stream: (options ? !!options.stream : false) as never,
+    }) as Promise<ProgressResponse> | Promise<AsyncGenerator<ProgressResponse>>;
+  }
+
+  static async push(
+    modelName: string,
+    options?: Omit<CreateRequest, "model"> & {
+      stream: false;
+    },
+  ): Promise<ProgressResponse>;
+  static async push(
+    modelName: string,
+    options: Omit<CreateRequest, "model"> & {
+      stream: true;
+    },
+  ): Promise<AsyncGenerator<ProgressResponse>>;
+  static async push(
+    modelName: string,
+    options?: Omit<CreateRequest, "model"> & {
+      stream: boolean;
+    },
+  ) {
+    return ollama.push({
+      model: modelName,
+      ...options,
+      stream: (options ? !!options.stream : false) as never,
+    }) as Promise<ProgressResponse> | Promise<AsyncGenerator<ProgressResponse>>;
+  }
 }
diff --git a/packages/core/src/llm/open_ai.ts b/packages/core/src/llm/openai.ts
similarity index 100%
rename from packages/core/src/llm/open_ai.ts
rename to packages/core/src/llm/openai.ts
diff --git a/packages/core/src/llm/together.ts b/packages/core/src/llm/together.ts
index 0ab3fc443..3772b2be2 100644
--- a/packages/core/src/llm/together.ts
+++ b/packages/core/src/llm/together.ts
@@ -1,5 +1,5 @@
 import { getEnv } from "@llamaindex/env";
-import { OpenAI } from "./open_ai.js";
+import { OpenAI } from "./openai.js";
 
 export class TogetherLLM extends OpenAI {
   constructor(init?: Partial<OpenAI>) {
diff --git a/packages/core/tests/CallbackManager.test.ts b/packages/core/tests/CallbackManager.test.ts
index 6788c9047..784784806 100644
--- a/packages/core/tests/CallbackManager.test.ts
+++ b/packages/core/tests/CallbackManager.test.ts
@@ -20,7 +20,7 @@ import { CallbackManager } from "llamaindex/callbacks/CallbackManager";
 import { OpenAIEmbedding } from "llamaindex/embeddings/index";
 import { SummaryIndex } from "llamaindex/indices/summary/index";
 import { VectorStoreIndex } from "llamaindex/indices/vectorStore/index";
-import { OpenAI } from "llamaindex/llm/open_ai";
+import { OpenAI } from "llamaindex/llm/openai";
 import {
   ResponseSynthesizer,
   SimpleResponseBuilder,
diff --git a/packages/core/tests/MetadataExtractors.test.ts b/packages/core/tests/MetadataExtractors.test.ts
index e71dd9674..e70ae9701 100644
--- a/packages/core/tests/MetadataExtractors.test.ts
+++ b/packages/core/tests/MetadataExtractors.test.ts
@@ -9,7 +9,7 @@ import {
   SummaryExtractor,
   TitleExtractor,
 } from "llamaindex/extractors/index";
-import { OpenAI } from "llamaindex/llm/open_ai";
+import { OpenAI } from "llamaindex/llm/openai";
 import { SimpleNodeParser } from "llamaindex/nodeParsers/index";
 import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
 import {
diff --git a/packages/core/tests/utility/mockOpenAI.ts b/packages/core/tests/utility/mockOpenAI.ts
index d3dd73758..626f7c901 100644
--- a/packages/core/tests/utility/mockOpenAI.ts
+++ b/packages/core/tests/utility/mockOpenAI.ts
@@ -1,7 +1,7 @@
 import { Settings } from "llamaindex";
 import type { CallbackManager } from "llamaindex/callbacks/CallbackManager";
 import type { OpenAIEmbedding } from "llamaindex/embeddings/index";
-import { OpenAI } from "llamaindex/llm/open_ai";
+import { OpenAI } from "llamaindex/llm/openai";
 import type { LLMChatParamsBase } from "llamaindex/llm/types";
 import { vi } from "vitest";
 
diff --git a/packages/edge/package.json b/packages/edge/package.json
index 0acfe49a2..274dc56e8 100644
--- a/packages/edge/package.json
+++ b/packages/edge/package.json
@@ -31,6 +31,7 @@
     "md-utils-ts": "^2.0.0",
     "mongodb": "^6.5.0",
     "notion-md-crawler": "^0.0.2",
+    "ollama": "^0.5.0",
     "openai": "^4.38.0",
     "papaparse": "^5.4.1",
     "pathe": "^1.1.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bd3cede6b..699e084a6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -268,6 +268,9 @@ importers:
       notion-md-crawler:
         specifier: ^0.0.2
         version: 0.0.2(encoding@0.1.13)
+      ollama:
+        specifier: ^0.5.0
+        version: 0.5.0
       openai:
         specifier: ^4.38.0
         version: 4.38.0(encoding@0.1.13)
@@ -315,8 +318,8 @@ importers:
         specifier: ^10.3.12
         version: 10.3.12
       madge:
-        specifier: ^6.1.0
-        version: 6.1.0(typescript@5.4.5)
+        specifier: ^7.0.0
+        version: 7.0.0(typescript@5.4.5)
       typescript:
         specifier: ^5.4.5
         version: 5.4.5
@@ -428,6 +431,9 @@ importers:
       notion-md-crawler:
         specifier: ^0.0.2
         version: 0.0.2(encoding@0.1.13)
+      ollama:
+        specifier: ^0.5.0
+        version: 0.5.0
       openai:
         specifier: ^4.38.0
         version: 4.38.0(encoding@0.1.13)
@@ -1414,9 +1420,9 @@ packages:
     resolution: {integrity: sha512-TSfP/Lv0ghPc01lVqiXGdunM+2CsBt8tG/9cqTs8K3LaM5vRJJj760Q2+udif834rrbXM4xN8LZQeWPfVPy6BA==}
     engines: {node: '>=14.0.0'}
 
-  '@dependents/detective-less@3.0.2':
-    resolution: {integrity: sha512-1YUvQ+e0eeTWAHoN8Uz2x2U37jZs6IGutiIE5LXId7cxfUGhtZjzxE06FdUiuiRrW+UE0vNCdSNPH2lY4dQCOQ==}
-    engines: {node: '>=12'}
+  '@dependents/detective-less@4.1.0':
+    resolution: {integrity: sha512-KrkT6qO5NxqNfy68sBl6CTSoJ4SNDIS5iQArkibhlbGU4LaDukZ3q2HIkh8aUKDio6o4itU4xDR7t82Y2eP1Bg==}
+    engines: {node: '>=14'}
 
   '@discoveryjs/json-ext@0.5.7':
     resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==}
@@ -2694,10 +2700,6 @@ packages:
       typescript:
         optional: true
 
-  '@typescript-eslint/types@4.33.0':
-    resolution: {integrity: sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==}
-    engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
-
   '@typescript-eslint/types@5.62.0':
     resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -2714,15 +2716,6 @@ packages:
     resolution: {integrity: sha512-G01YPZ1Bd2hn+KPpIbrAhEWOn5lQBrjxkzHkWvP6NucMXFtfXoevK82hzQdpfuQYuhkvFDeQYbzXCjR1z9Z03w==}
     engines: {node: ^18.18.0 || >=20.0.0}
 
-  '@typescript-eslint/typescript-estree@4.33.0':
-    resolution: {integrity: sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==}
-    engines: {node: ^10.12.0 || >=12.0.0}
-    peerDependencies:
-      typescript: '*'
-    peerDependenciesMeta:
-      typescript:
-        optional: true
-
   '@typescript-eslint/typescript-estree@5.62.0':
     resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -2765,10 +2758,6 @@ packages:
     peerDependencies:
       eslint: ^8.56.0
 
-  '@typescript-eslint/visitor-keys@4.33.0':
-    resolution: {integrity: sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==}
-    engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
-
   '@typescript-eslint/visitor-keys@5.62.0':
     resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3065,16 +3054,9 @@ packages:
   assertion-error@1.1.0:
     resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
 
-  ast-module-types@2.7.1:
-    resolution: {integrity: sha512-Rnnx/4Dus6fn7fTqdeLEAn5vUll5w7/vts0RN608yFa6si/rDOUonlIIiwugHBFWjylHjxm9owoSZn71KwG4gw==}
-
-  ast-module-types@3.0.0:
-    resolution: {integrity: sha512-CMxMCOCS+4D+DkOQfuZf+vLrSEmY/7xtORwdxs4wtcC1wVgvk2MqFFTwQCFhvWsI4KPU9lcWXPI8DgRiz+xetQ==}
-    engines: {node: '>=6.0'}
-
-  ast-module-types@4.0.0:
-    resolution: {integrity: sha512-Kd0o8r6CDazJGCRzs8Ivpn0xj19oNKrULhoJFzhGjRsLpekF2zyZs9Ukz+JvZhWD6smszfepakTFhAaYpsI12g==}
-    engines: {node: '>=12.0'}
+  ast-module-types@5.0.0:
+    resolution: {integrity: sha512-JvqziE0Wc0rXQfma0HZC/aY7URXHFuZV84fJRtP8u+lhp0JYCNd5wJzVXP45t0PH0Mej3ynlzvdyITYIu0G4LQ==}
+    engines: {node: '>=14'}
 
   ast-types-flow@0.0.8:
     resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
@@ -3552,10 +3534,6 @@ packages:
     resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
     engines: {node: '>= 12'}
 
-  commander@9.5.0:
-    resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
-    engines: {node: ^12.20.0 || >=14}
-
   common-path-prefix@3.0.0:
     resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==}
 
@@ -3899,9 +3877,9 @@ packages:
     resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
     engines: {node: '>= 0.8'}
 
-  dependency-tree@9.0.0:
-    resolution: {integrity: sha512-osYHZJ1fBSon3lNLw70amAXsQ+RGzXsPvk9HbBgTLbp/bQBmpH5mOmsUvqXU+YEWVU0ZLewsmzOET/8jWswjDQ==}
-    engines: {node: ^10.13 || ^12 || >=14}
+  dependency-tree@10.0.9:
+    resolution: {integrity: sha512-dwc59FRIsht+HfnTVM0BCjJaEWxdq2YAvEDy4/Hn6CwS3CBWMtFnL3aZGAkQn3XCYxk/YcTDE4jX2Q7bFTwCjA==}
+    engines: {node: '>=14'}
     hasBin: true
 
   dequal@2.0.3:
@@ -3932,78 +3910,38 @@ packages:
     resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==}
     hasBin: true
 
-  detective-amd@3.1.2:
-    resolution: {integrity: sha512-jffU26dyqJ37JHR/o44La6CxtrDf3Rt9tvd2IbImJYxWKTMdBjctp37qoZ6ZcY80RHg+kzWz4bXn39e4P7cctQ==}
-    engines: {node: '>=6.0'}
-    hasBin: true
-
-  detective-amd@4.2.0:
-    resolution: {integrity: sha512-RbuEJHz78A8nW7CklkqTzd8lDCN42En53dgEIsya0DilpkwslamSZDasLg8dJyxbw46OxhSQeY+C2btdSkCvQQ==}
-    engines: {node: '>=12'}
+  detective-amd@5.0.2:
+    resolution: {integrity: sha512-XFd/VEQ76HSpym80zxM68ieB77unNuoMwopU2TFT/ErUk5n4KvUTwW4beafAVUugrjV48l4BmmR0rh2MglBaiA==}
+    engines: {node: '>=14'}
     hasBin: true
 
-  detective-cjs@3.1.3:
-    resolution: {integrity: sha512-ljs7P0Yj9MK64B7G0eNl0ThWSYjhAaSYy+fQcpzaKalYl/UoQBOzOeLCSFEY1qEBhziZ3w7l46KG/nH+s+L7BQ==}
-    engines: {node: '>=6.0'}
-
-  detective-cjs@4.1.0:
-    resolution: {integrity: sha512-QxzMwt5MfPLwS7mG30zvnmOvHLx5vyVvjsAV6gQOyuMoBR5G1DhS1eJZ4P10AlH+HSnk93mTcrg3l39+24XCtg==}
-    engines: {node: '>=12'}
-
-  detective-es6@2.2.2:
-    resolution: {integrity: sha512-eZUKCUsbHm8xoeoCM0z6JFwvDfJ5Ww5HANo+jPR7AzkFpW9Mun3t/TqIF2jjeWa2TFbAiGaWESykf2OQp3oeMw==}
-    engines: {node: '>=6.0'}
-
-  detective-es6@3.0.1:
-    resolution: {integrity: sha512-evPeYIEdK1jK3Oji5p0hX4sPV/1vK+o4ihcWZkMQE6voypSW/cIBiynOLxQk5KOOQbdP8oOAsYqouMTYO5l1sw==}
-    engines: {node: '>=12'}
-
-  detective-less@1.0.2:
-    resolution: {integrity: sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==}
-    engines: {node: '>= 6.0'}
+  detective-cjs@5.0.1:
+    resolution: {integrity: sha512-6nTvAZtpomyz/2pmEmGX1sXNjaqgMplhQkskq2MLrar0ZAIkHMrDhLXkRiK2mvbu9wSWr0V5/IfiTrZqAQMrmQ==}
+    engines: {node: '>=14'}
 
-  detective-postcss@4.0.0:
-    resolution: {integrity: sha512-Fwc/g9VcrowODIAeKRWZfVA/EufxYL7XfuqJQFroBKGikKX83d2G7NFw6kDlSYGG3LNQIyVa+eWv1mqre+v4+A==}
-    engines: {node: ^10 || ^12 || >=14}
+  detective-es6@4.0.1:
+    resolution: {integrity: sha512-k3Z5tB4LQ8UVHkuMrFOlvb3GgFWdJ9NqAa2YLUU/jTaWJIm+JJnEh4PsMc+6dfT223Y8ACKOaC0qcj7diIhBKw==}
+    engines: {node: '>=14'}
 
   detective-postcss@6.1.3:
     resolution: {integrity: sha512-7BRVvE5pPEvk2ukUWNQ+H2XOq43xENWbH0LcdCE14mwgTBEAMoAx+Fc1rdp76SmyZ4Sp48HlV7VedUnP6GA1Tw==}
     engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
 
-  detective-sass@3.0.2:
-    resolution: {integrity: sha512-DNVYbaSlmti/eztFGSfBw4nZvwsTaVXEQ4NsT/uFckxhJrNRFUh24d76KzoCC3aarvpZP9m8sC2L1XbLej4F7g==}
-    engines: {node: '>=6.0'}
-
-  detective-sass@4.1.3:
-    resolution: {integrity: sha512-xGRbwGaGte57gvEqM8B9GDiURY3El/H49vA6g9wFkxq9zalmTlTAuqWu+BsH0iwonGPruLt55tZZDEZqPc6lag==}
-    engines: {node: '>=12'}
-
-  detective-scss@2.0.2:
-    resolution: {integrity: sha512-hDWnWh/l0tht/7JQltumpVea/inmkBaanJUcXRB9kEEXVwVUMuZd6z7eusQ6GcBFrfifu3pX/XPyD7StjbAiBg==}
-    engines: {node: '>=6.0'}
-
-  detective-scss@3.1.1:
-    resolution: {integrity: sha512-FWkfru1jZBhUeuBsOeGKXKAVDrzYFSQFK2o2tuG/nCCFQ0U/EcXC157MNAcR5mmj+mCeneZzlkBOFJTesDjrww==}
-    engines: {node: '>=12'}
-
-  detective-stylus@1.0.3:
-    resolution: {integrity: sha512-4/bfIU5kqjwugymoxLXXLltzQNeQfxGoLm2eIaqtnkWxqbhap9puDVpJPVDx96hnptdERzS5Cy6p9N8/08A69Q==}
-
-  detective-stylus@2.0.1:
-    resolution: {integrity: sha512-/Tvs1pWLg8eYwwV6kZQY5IslGaYqc/GACxjcaGudiNtN5nKCH6o2WnJK3j0gA3huCnoQcbv8X7oz/c1lnvE3zQ==}
-    engines: {node: '>=6.0'}
+  detective-sass@5.0.3:
+    resolution: {integrity: sha512-YsYT2WuA8YIafp2RVF5CEfGhhyIVdPzlwQgxSjK+TUm3JoHP+Tcorbk3SfG0cNZ7D7+cYWa0ZBcvOaR0O8+LlA==}
+    engines: {node: '>=14'}
 
-  detective-stylus@3.0.0:
-    resolution: {integrity: sha512-1xYTzbrduExqMYmte7Qk99IRA3Aa6oV7PYzd+3yDcQXkmENvyGF/arripri6lxRDdNYEb4fZFuHtNRAXbz3iAA==}
-    engines: {node: '>=12'}
+  detective-scss@4.0.3:
+    resolution: {integrity: sha512-VYI6cHcD0fLokwqqPFFtDQhhSnlFWvU614J42eY6G0s8c+MBhi9QAWycLwIOGxlmD8I/XvGSOUV1kIDhJ70ZPg==}
+    engines: {node: '>=14'}
 
-  detective-typescript@7.0.2:
-    resolution: {integrity: sha512-unqovnhxzvkCz3m1/W4QW4qGsvXCU06aU2BAm8tkza+xLnp9SOFnob2QsTxUv5PdnQKfDvWcv9YeOeFckWejwA==}
-    engines: {node: ^10.13 || >=12.0.0}
+  detective-stylus@4.0.0:
+    resolution: {integrity: sha512-TfPotjhszKLgFBzBhTOxNHDsutIxx9GTWjrL5Wh7Qx/ydxKhwUrlSFeLIn+ZaHPF+h0siVBkAQSuy6CADyTxgQ==}
+    engines: {node: '>=14'}
 
-  detective-typescript@9.1.1:
-    resolution: {integrity: sha512-Uc1yVutTF0RRm1YJ3g//i1Cn2vx1kwHj15cnzQP6ff5koNzQ0idc1zAC73ryaWEulA0ElRXFTq6wOqe8vUQ3MA==}
-    engines: {node: ^12.20.0 || ^14.14.0 || >=16.0.0}
+  detective-typescript@11.2.0:
+    resolution: {integrity: sha512-ARFxjzizOhPqs1fYC/2NMC3N4jrQ6HvVflnXBTRqNEqJuXwyKLRr9CrJwkRcV/SnZt1sNXgsF6FPm0x57Tq0rw==}
+    engines: {node: ^14.14.0 || >=16.0.0}
 
   devlop@1.1.0:
     resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
@@ -4317,10 +4255,6 @@ packages:
     resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
 
-  eslint-visitor-keys@2.1.0:
-    resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==}
-    engines: {node: '>=10'}
-
   eslint-visitor-keys@3.4.3:
     resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -4527,9 +4461,9 @@ packages:
     resolution: {integrity: sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==}
     engines: {node: '>= 0.4.0'}
 
-  filing-cabinet@3.3.1:
-    resolution: {integrity: sha512-renEK4Hh6DUl9Vl22Y3cxBq1yh8oNvbAdXnhih0wVpmea+uyKjC9K4QeRjUaybIiIewdzfum+Fg15ZqJ/GyCaA==}
-    engines: {node: '>=10.13.0'}
+  filing-cabinet@4.2.0:
+    resolution: {integrity: sha512-YZ21ryzRcyqxpyKggdYSoXx//d3sCJzM3lsYoaeg/FyXdADGJrUl+BW1KIglaVLJN5BBcMtWylkygY8zBp2MrQ==}
+    engines: {node: '>=14'}
     hasBin: true
 
   fill-range@7.0.1:
@@ -4581,10 +4515,6 @@ packages:
   flatted@3.3.1:
     resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
 
-  flatten@1.0.3:
-    resolution: {integrity: sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==}
-    deprecated: flatten is deprecated in favor of utility frameworks such as lodash.
-
   fn.name@1.1.0:
     resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
 
@@ -4703,13 +4633,9 @@ packages:
     resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
     engines: {node: '>=6.9.0'}
 
-  get-amd-module-type@3.0.2:
-    resolution: {integrity: sha512-PcuKwB8ouJnKuAPn6Hk3UtdfKoUV3zXRqVEvj8XGIXqjWfgd1j7QGdXy5Z9OdQfzVt1Sk29HVe/P+X74ccOuqw==}
-    engines: {node: '>=6.0'}
-
-  get-amd-module-type@4.1.0:
-    resolution: {integrity: sha512-0e/eK6vTGCnSfQ6eYs3wtH05KotJYIP7ZIZEueP/KlA+0dIAEs8bYFvOd/U56w1vfjhJqBagUxVMyy9Tr/cViQ==}
-    engines: {node: '>=12'}
+  get-amd-module-type@5.0.1:
+    resolution: {integrity: sha512-jb65zDeHyDjFR1loOVk0HQGM5WNwoGB8aLWy3LKCieMKol0/ProHkhO2X1JxojuN10vbz1qNn09MJ7tNp7qMzw==}
+    engines: {node: '>=14'}
 
   get-caller-file@2.0.5:
     resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
@@ -5083,9 +5009,6 @@ packages:
     resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
     engines: {node: '>=8'}
 
-  indexes-of@1.0.1:
-    resolution: {integrity: sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==}
-
   infima@0.2.0-alpha.43:
     resolution: {integrity: sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ==}
     engines: {node: '>=12'}
@@ -5697,8 +5620,8 @@ packages:
   lunr@2.3.9:
     resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==}
 
-  madge@6.1.0:
-    resolution: {integrity: sha512-irWhT5RpFOc6lkzGHKLihonCVgM0YtfNUh4IrFeW3EqHpnt/JHUG3z26j8PeJEktCGB4tmGOOOJi1Rl/ACWucQ==}
+  madge@7.0.0:
+    resolution: {integrity: sha512-x9eHkBWoCJ2B8yGesWf8LRucarkbH5P3lazqgvmxe4xn5U2Meyfu906iG9mBB1RnY/f4D+gtELWdiz1k6+jAZA==}
     engines: {node: '>=14'}
     hasBin: true
     peerDependencies:
@@ -6044,19 +5967,14 @@ packages:
   mlly@1.6.0:
     resolution: {integrity: sha512-YOvg9hfYQmnaB56Yb+KrJE2u0Yzz5zR+sLejEvF4fzwzV1Al6hkf2vyHTwqCRyv0hCi9rVCqVoXpyYevQIRwLQ==}
 
-  module-definition@3.4.0:
-    resolution: {integrity: sha512-XxJ88R1v458pifaSkPNLUTdSPNVGMP2SXVncVmApGO+gAfrLANiYe6JofymCzVceGOMwQE2xogxBSc8uB7XegA==}
-    engines: {node: '>=6.0'}
-    hasBin: true
-
-  module-definition@4.1.0:
-    resolution: {integrity: sha512-rHXi/DpMcD2qcKbPCTklDbX9lBKJrUSl971TW5l6nMpqKCIlzJqmQ8cfEF5M923h2OOLHPDVlh5pJxNyV+AJlw==}
-    engines: {node: '>=12'}
+  module-definition@5.0.1:
+    resolution: {integrity: sha512-kvw3B4G19IXk+BOXnYq/D/VeO9qfHaapMeuS7w7sNUqmGaA6hywdFHMi+VWeR9wUScXM7XjoryTffCZ5B0/8IA==}
+    engines: {node: '>=14'}
     hasBin: true
 
-  module-lookup-amd@7.0.1:
-    resolution: {integrity: sha512-w9mCNlj0S8qviuHzpakaLVc+/7q50jl9a/kmJ/n8bmXQZgDPkQHnPBb8MUOYh3WpAYkXuNc2c+khsozhIp/amQ==}
-    engines: {node: '>=10.13.0'}
+  module-lookup-amd@8.0.5:
+    resolution: {integrity: sha512-vc3rYLjDo5Frjox8NZpiyLXsNWJ5BWshztc/5KSOMzpg9k5cHH652YsJ7VKKmtM4SvaxuE9RkrYGhiSjH3Ehow==}
+    engines: {node: '>=14'}
     hasBin: true
 
   mongodb-connection-string-url@3.0.0:
@@ -6187,13 +6105,9 @@ packages:
   node-releases@2.0.14:
     resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
 
-  node-source-walk@4.3.0:
-    resolution: {integrity: sha512-8Q1hXew6ETzqKRAs3jjLioSxNfT1cx74ooiF8RlAONwVMcfq+UdzLC2eB5qcPldUxaE5w3ytLkrmV1TGddhZTA==}
-    engines: {node: '>=6.0'}
-
-  node-source-walk@5.0.2:
-    resolution: {integrity: sha512-Y4jr/8SRS5hzEdZ7SGuvZGwfORvNsSsNRwDXx5WisiqzsVfeftDvRgfeqWNgZvWSJbgubTRVRYBzK6UO+ErqjA==}
-    engines: {node: '>=12'}
+  node-source-walk@6.0.2:
+    resolution: {integrity: sha512-jn9vOIK/nfqoFCcpK89/VCVaLg1IHE6UVfDOzvqmANaJ/rWCTEdH8RZ1V278nv2jr36BJdyQXIAavBLXpzdlag==}
+    engines: {node: '>=14'}
 
   normalize-package-data@2.5.0:
     resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
@@ -6281,6 +6195,9 @@ packages:
   obuf@1.1.2:
     resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
 
+  ollama@0.5.0:
+    resolution: {integrity: sha512-CRtRzsho210EGdK52GrUMohA2pU+7NbgEaBG3DcYeRmvQthDO7E2LHOkLlUUeaYUlNmEd8icbjC02ug9meSYnw==}
+
   on-finished@2.4.1:
     resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
     engines: {node: '>= 0.8'}
@@ -6857,10 +6774,6 @@ packages:
   postcss-value-parser@4.2.0:
     resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
 
-  postcss-values-parser@2.0.1:
-    resolution: {integrity: sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==}
-    engines: {node: '>=6.14.4'}
-
   postcss-values-parser@6.0.2:
     resolution: {integrity: sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==}
     engines: {node: '>=10'}
@@ -6921,14 +6834,9 @@ packages:
     engines: {node: '>=10'}
     hasBin: true
 
-  precinct@8.3.1:
-    resolution: {integrity: sha512-pVppfMWLp2wF68rwHqBIpPBYY8Kd12lDhk8LVQzOwqllifVR15qNFyod43YLyFpurKRZQKnE7E4pofAagDOm2Q==}
-    engines: {node: ^10.13 || ^12 || >=14}
-    hasBin: true
-
-  precinct@9.2.1:
-    resolution: {integrity: sha512-uzKHaTyiVejWW7VJtHInb9KBUq9yl9ojxXGujhjhDmPon2wgZPBKQIKR+6csGqSlUeGXAA4MEFnU6DesxZib+A==}
-    engines: {node: ^12.20.0 || ^14.14.0 || >=16.0.0}
+  precinct@11.0.5:
+    resolution: {integrity: sha512-oHSWLC8cL/0znFhvln26D14KfCQFFn4KOLSw6hmLhd+LQ2SKt9Ljm89but76Pc7flM9Ty1TnXyrA2u16MfRV3w==}
+    engines: {node: ^14.14.0 || >=16.0.0}
     hasBin: true
 
   preferred-pm@3.1.3:
@@ -7339,9 +7247,9 @@ packages:
   resolve-alpn@1.2.1:
     resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
 
-  resolve-dependency-path@2.0.0:
-    resolution: {integrity: sha512-DIgu+0Dv+6v2XwRaNWnumKu7GPufBBOr5I1gRPJHkvghrfCGOooJODFvgFimX/KRxk9j0whD2MnKHzM1jYvk9w==}
-    engines: {node: '>=6.0.0'}
+  resolve-dependency-path@3.0.2:
+    resolution: {integrity: sha512-Tz7zfjhLfsvR39ADOSk9us4421J/1ztVBo4rWUkF38hgHK5m0OCZ3NxFVpqHRkjctnwVa15igEUHFJp8MCS7vA==}
+    engines: {node: '>=14'}
 
   resolve-from@4.0.0:
     resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
@@ -7435,9 +7343,9 @@ packages:
   safer-buffer@2.1.2:
     resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
 
-  sass-lookup@3.0.0:
-    resolution: {integrity: sha512-TTsus8CfFRn1N44bvdEai1no6PqdmDiQUiqW5DlpmtT+tYnIt1tXtDIph5KA1efC+LmioJXSnCtUVpcK9gaKIg==}
-    engines: {node: '>=6.0.0'}
+  sass-lookup@5.0.1:
+    resolution: {integrity: sha512-t0X5PaizPc2H4+rCwszAqHZRtr4bugo4pgiCvrBFvIX0XFxnr29g77LJcpyj9A0DcKf7gXMLcgvRjsonYI6x4g==}
+    engines: {node: '>=14'}
     hasBin: true
 
   sax@1.3.0:
@@ -7878,9 +7786,9 @@ packages:
     peerDependencies:
       postcss: ^8.2.15
 
-  stylus-lookup@3.0.2:
-    resolution: {integrity: sha512-oEQGHSjg/AMaWlKe7gqsnYzan8DLcGIHe0dUaFkucZZ14z4zjENRlQMCHT4FNsiWnJf17YN9OvrCfCoi7VvOyg==}
-    engines: {node: '>=6.0.0'}
+  stylus-lookup@5.0.1:
+    resolution: {integrity: sha512-tLtJEd5AGvnVy4f9UHQMw4bkJJtaAcmo54N+ovQBjDY3DuWyK9Eltxzr5+KG0q4ew6v2EHyuWWNnHeiw/Eo7rQ==}
+    engines: {node: '>=14'}
     hasBin: true
 
   supports-color@5.5.0:
@@ -8076,6 +7984,10 @@ packages:
   tsconfig-paths@3.15.0:
     resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
 
+  tsconfig-paths@4.2.0:
+    resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
+    engines: {node: '>=6'}
+
   tslib@1.14.1:
     resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
 
@@ -8209,16 +8121,6 @@ packages:
     peerDependencies:
       typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x
 
-  typescript@3.9.10:
-    resolution: {integrity: sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==}
-    engines: {node: '>=4.2.0'}
-    hasBin: true
-
-  typescript@4.9.5:
-    resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
-    engines: {node: '>=4.2.0'}
-    hasBin: true
-
   typescript@5.4.2:
     resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==}
     engines: {node: '>=14.17'}
@@ -8286,9 +8188,6 @@ packages:
   unified@11.0.4:
     resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==}
 
-  uniq@1.0.1:
-    resolution: {integrity: sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==}
-
   unique-string@3.0.0:
     resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==}
     engines: {node: '>=12'}
@@ -9885,10 +9784,10 @@ snapshots:
       typed-emitter: 2.1.0
       uuidv7: 0.6.3
 
-  '@dependents/detective-less@3.0.2':
+  '@dependents/detective-less@4.1.0':
     dependencies:
       gonzales-pe: 4.3.0
-      node-source-walk: 5.0.2
+      node-source-walk: 6.0.2
 
   '@discoveryjs/json-ext@0.5.7': {}
 
@@ -11651,8 +11550,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/types@4.33.0': {}
-
   '@typescript-eslint/types@5.62.0': {}
 
   '@typescript-eslint/types@6.21.0': {}
@@ -11661,21 +11558,7 @@ snapshots:
 
   '@typescript-eslint/types@7.7.0': {}
 
-  '@typescript-eslint/typescript-estree@4.33.0(typescript@3.9.10)':
-    dependencies:
-      '@typescript-eslint/types': 4.33.0
-      '@typescript-eslint/visitor-keys': 4.33.0
-      debug: 4.3.4
-      globby: 11.1.0
-      is-glob: 4.0.3
-      semver: 7.6.0
-      tsutils: 3.21.0(typescript@3.9.10)
-    optionalDependencies:
-      typescript: 3.9.10
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/typescript-estree@5.62.0(typescript@4.9.5)':
+  '@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.5)':
     dependencies:
       '@typescript-eslint/types': 5.62.0
       '@typescript-eslint/visitor-keys': 5.62.0
@@ -11683,9 +11566,9 @@ snapshots:
       globby: 11.1.0
       is-glob: 4.0.3
       semver: 7.6.0
-      tsutils: 3.21.0(typescript@4.9.5)
+      tsutils: 3.21.0(typescript@5.4.5)
     optionalDependencies:
-      typescript: 4.9.5
+      typescript: 5.4.5
     transitivePeerDependencies:
       - supports-color
 
@@ -11748,11 +11631,6 @@ snapshots:
       - supports-color
       - typescript
 
-  '@typescript-eslint/visitor-keys@4.33.0':
-    dependencies:
-      '@typescript-eslint/types': 4.33.0
-      eslint-visitor-keys: 2.1.0
-
   '@typescript-eslint/visitor-keys@5.62.0':
     dependencies:
       '@typescript-eslint/types': 5.62.0
@@ -12135,11 +12013,7 @@ snapshots:
 
   assertion-error@1.1.0: {}
 
-  ast-module-types@2.7.1: {}
-
-  ast-module-types@3.0.0: {}
-
-  ast-module-types@4.0.0: {}
+  ast-module-types@5.0.0: {}
 
   ast-types-flow@0.0.8: {}
 
@@ -12665,8 +12539,6 @@ snapshots:
 
   commander@8.3.0: {}
 
-  commander@9.5.0: {}
-
   common-path-prefix@3.0.0: {}
 
   commondir@1.0.1: {}
@@ -13038,13 +12910,12 @@ snapshots:
 
   depd@2.0.0: {}
 
-  dependency-tree@9.0.0:
+  dependency-tree@10.0.9:
     dependencies:
-      commander: 2.20.3
-      debug: 4.3.4
-      filing-cabinet: 3.3.1
-      precinct: 9.2.1
-      typescript: 4.9.5
+      commander: 10.0.1
+      filing-cabinet: 4.2.0
+      precinct: 11.0.5
+      typescript: 5.4.5
     transitivePeerDependencies:
       - supports-color
 
@@ -13072,54 +12943,21 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  detective-amd@3.1.2:
-    dependencies:
-      ast-module-types: 3.0.0
-      escodegen: 2.1.0
-      get-amd-module-type: 3.0.2
-      node-source-walk: 4.3.0
-
-  detective-amd@4.2.0:
+  detective-amd@5.0.2:
     dependencies:
-      ast-module-types: 4.0.0
+      ast-module-types: 5.0.0
       escodegen: 2.1.0
-      get-amd-module-type: 4.1.0
-      node-source-walk: 5.0.2
+      get-amd-module-type: 5.0.1
+      node-source-walk: 6.0.2
 
-  detective-cjs@3.1.3:
+  detective-cjs@5.0.1:
     dependencies:
-      ast-module-types: 3.0.0
-      node-source-walk: 4.3.0
-
-  detective-cjs@4.1.0:
-    dependencies:
-      ast-module-types: 4.0.0
-      node-source-walk: 5.0.2
-
-  detective-es6@2.2.2:
-    dependencies:
-      node-source-walk: 4.3.0
-
-  detective-es6@3.0.1:
-    dependencies:
-      node-source-walk: 5.0.2
-
-  detective-less@1.0.2:
-    dependencies:
-      debug: 4.3.4
-      gonzales-pe: 4.3.0
-      node-source-walk: 4.3.0
-    transitivePeerDependencies:
-      - supports-color
+      ast-module-types: 5.0.0
+      node-source-walk: 6.0.2
 
-  detective-postcss@4.0.0:
+  detective-es6@4.0.1:
     dependencies:
-      debug: 4.3.4
-      is-url: 1.2.4
-      postcss: 8.4.38
-      postcss-values-parser: 2.0.1
-    transitivePeerDependencies:
-      - supports-color
+      node-source-walk: 6.0.2
 
   detective-postcss@6.1.3:
     dependencies:
@@ -13127,47 +12965,24 @@ snapshots:
       postcss: 8.4.38
       postcss-values-parser: 6.0.2(postcss@8.4.38)
 
-  detective-sass@3.0.2:
-    dependencies:
-      gonzales-pe: 4.3.0
-      node-source-walk: 4.3.0
-
-  detective-sass@4.1.3:
-    dependencies:
-      gonzales-pe: 4.3.0
-      node-source-walk: 5.0.2
-
-  detective-scss@2.0.2:
+  detective-sass@5.0.3:
     dependencies:
       gonzales-pe: 4.3.0
-      node-source-walk: 4.3.0
+      node-source-walk: 6.0.2
 
-  detective-scss@3.1.1:
+  detective-scss@4.0.3:
     dependencies:
       gonzales-pe: 4.3.0
-      node-source-walk: 5.0.2
-
-  detective-stylus@1.0.3: {}
+      node-source-walk: 6.0.2
 
-  detective-stylus@2.0.1: {}
+  detective-stylus@4.0.0: {}
 
-  detective-stylus@3.0.0: {}
-
-  detective-typescript@7.0.2:
-    dependencies:
-      '@typescript-eslint/typescript-estree': 4.33.0(typescript@3.9.10)
-      ast-module-types: 2.7.1
-      node-source-walk: 4.3.0
-      typescript: 3.9.10
-    transitivePeerDependencies:
-      - supports-color
-
-  detective-typescript@9.1.1:
+  detective-typescript@11.2.0:
     dependencies:
-      '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5)
-      ast-module-types: 4.0.0
-      node-source-walk: 5.0.2
-      typescript: 4.9.5
+      '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5)
+      ast-module-types: 5.0.0
+      node-source-walk: 6.0.2
+      typescript: 5.4.5
     transitivePeerDependencies:
       - supports-color
 
@@ -13635,8 +13450,6 @@ snapshots:
       esrecurse: 4.3.0
       estraverse: 5.3.0
 
-  eslint-visitor-keys@2.1.0: {}
-
   eslint-visitor-keys@3.4.3: {}
 
   eslint@8.57.0:
@@ -13937,23 +13750,20 @@ snapshots:
 
   filesize@8.0.7: {}
 
-  filing-cabinet@3.3.1:
+  filing-cabinet@4.2.0:
     dependencies:
       app-module-path: 2.2.0
-      commander: 2.20.3
-      debug: 4.3.4
+      commander: 10.0.1
       enhanced-resolve: 5.16.0
       is-relative-path: 1.0.2
-      module-definition: 3.4.0
-      module-lookup-amd: 7.0.1
+      module-definition: 5.0.1
+      module-lookup-amd: 8.0.5
       resolve: 1.22.8
-      resolve-dependency-path: 2.0.0
-      sass-lookup: 3.0.0
-      stylus-lookup: 3.0.2
-      tsconfig-paths: 3.15.0
-      typescript: 3.9.10
-    transitivePeerDependencies:
-      - supports-color
+      resolve-dependency-path: 3.0.2
+      sass-lookup: 5.0.1
+      stylus-lookup: 5.0.1
+      tsconfig-paths: 4.2.0
+      typescript: 5.4.5
 
   fill-range@7.0.1:
     dependencies:
@@ -14016,8 +13826,6 @@ snapshots:
 
   flatted@3.3.1: {}
 
-  flatten@1.0.3: {}
-
   fn.name@1.1.0: {}
 
   follow-redirects@1.15.6: {}
@@ -14135,15 +13943,10 @@ snapshots:
 
   gensync@1.0.0-beta.2: {}
 
-  get-amd-module-type@3.0.2:
+  get-amd-module-type@5.0.1:
     dependencies:
-      ast-module-types: 3.0.0
-      node-source-walk: 4.3.0
-
-  get-amd-module-type@4.1.0:
-    dependencies:
-      ast-module-types: 4.0.0
-      node-source-walk: 5.0.2
+      ast-module-types: 5.0.0
+      node-source-walk: 6.0.2
 
   get-caller-file@2.0.5: {}
 
@@ -14624,8 +14427,6 @@ snapshots:
 
   indent-string@4.0.0: {}
 
-  indexes-of@1.0.1: {}
-
   infima@0.2.0-alpha.43: {}
 
   inflight@1.0.6:
@@ -15194,25 +14995,16 @@ snapshots:
 
   lunr@2.3.9: {}
 
-  madge@6.1.0(typescript@5.4.5):
+  madge@7.0.0(typescript@5.4.5):
     dependencies:
       chalk: 4.1.2
       commander: 7.2.0
       commondir: 1.0.1
       debug: 4.3.4
-      dependency-tree: 9.0.0
-      detective-amd: 4.2.0
-      detective-cjs: 4.1.0
-      detective-es6: 3.0.1
-      detective-less: 1.0.2
-      detective-postcss: 6.1.3
-      detective-sass: 4.1.3
-      detective-scss: 3.1.1
-      detective-stylus: 2.0.1
-      detective-typescript: 9.1.1
+      dependency-tree: 10.0.9
       ora: 5.4.1
       pluralize: 8.0.0
-      precinct: 8.3.1
+      precinct: 11.0.5
       pretty-ms: 7.0.1
       rc: 1.2.8
       stream-to-array: 2.3.0
@@ -15842,25 +15634,17 @@ snapshots:
       pkg-types: 1.0.3
       ufo: 1.4.0
 
-  module-definition@3.4.0:
-    dependencies:
-      ast-module-types: 3.0.0
-      node-source-walk: 4.3.0
-
-  module-definition@4.1.0:
+  module-definition@5.0.1:
     dependencies:
-      ast-module-types: 4.0.0
-      node-source-walk: 5.0.2
+      ast-module-types: 5.0.0
+      node-source-walk: 6.0.2
 
-  module-lookup-amd@7.0.1:
+  module-lookup-amd@8.0.5:
     dependencies:
-      commander: 2.20.3
-      debug: 4.3.4
+      commander: 10.0.1
       glob: 7.2.3
       requirejs: 2.3.6
       requirejs-config-file: 4.0.0
-    transitivePeerDependencies:
-      - supports-color
 
   mongodb-connection-string-url@3.0.0:
     dependencies:
@@ -15969,11 +15753,7 @@ snapshots:
 
   node-releases@2.0.14: {}
 
-  node-source-walk@4.3.0:
-    dependencies:
-      '@babel/parser': 7.24.4
-
-  node-source-walk@5.0.2:
+  node-source-walk@6.0.2:
     dependencies:
       '@babel/parser': 7.24.4
 
@@ -16067,6 +15847,10 @@ snapshots:
 
   obuf@1.1.2: {}
 
+  ollama@0.5.0:
+    dependencies:
+      whatwg-fetch: 3.6.20
+
   on-finished@2.4.1:
     dependencies:
       ee-first: 1.1.1
@@ -16632,12 +16416,6 @@ snapshots:
 
   postcss-value-parser@4.2.0: {}
 
-  postcss-values-parser@2.0.1:
-    dependencies:
-      flatten: 1.0.3
-      indexes-of: 1.0.1
-      uniq: 1.0.1
-
   postcss-values-parser@6.0.2(postcss@8.4.38):
     dependencies:
       color-name: 1.1.4
@@ -16698,38 +16476,20 @@ snapshots:
       tar-fs: 2.1.1
       tunnel-agent: 0.6.0
 
-  precinct@8.3.1:
-    dependencies:
-      commander: 2.20.3
-      debug: 4.3.4
-      detective-amd: 3.1.2
-      detective-cjs: 3.1.3
-      detective-es6: 2.2.2
-      detective-less: 1.0.2
-      detective-postcss: 4.0.0
-      detective-sass: 3.0.2
-      detective-scss: 2.0.2
-      detective-stylus: 1.0.3
-      detective-typescript: 7.0.2
-      module-definition: 3.4.0
-      node-source-walk: 4.3.0
-    transitivePeerDependencies:
-      - supports-color
-
-  precinct@9.2.1:
+  precinct@11.0.5:
     dependencies:
-      '@dependents/detective-less': 3.0.2
-      commander: 9.5.0
-      detective-amd: 4.2.0
-      detective-cjs: 4.1.0
-      detective-es6: 3.0.1
+      '@dependents/detective-less': 4.1.0
+      commander: 10.0.1
+      detective-amd: 5.0.2
+      detective-cjs: 5.0.1
+      detective-es6: 4.0.1
       detective-postcss: 6.1.3
-      detective-sass: 4.1.3
-      detective-scss: 3.1.1
-      detective-stylus: 3.0.0
-      detective-typescript: 9.1.1
-      module-definition: 4.1.0
-      node-source-walk: 5.0.2
+      detective-sass: 5.0.3
+      detective-scss: 4.0.3
+      detective-stylus: 4.0.0
+      detective-typescript: 11.2.0
+      module-definition: 5.0.1
+      node-source-walk: 6.0.2
     transitivePeerDependencies:
       - supports-color
 
@@ -17245,7 +17005,7 @@ snapshots:
 
   resolve-alpn@1.2.1: {}
 
-  resolve-dependency-path@2.0.0: {}
+  resolve-dependency-path@3.0.2: {}
 
   resolve-from@4.0.0: {}
 
@@ -17352,9 +17112,9 @@ snapshots:
 
   safer-buffer@2.1.2: {}
 
-  sass-lookup@3.0.0:
+  sass-lookup@5.0.1:
     dependencies:
-      commander: 2.20.3
+      commander: 10.0.1
 
   sax@1.3.0: {}
 
@@ -17864,12 +17624,9 @@ snapshots:
       postcss: 8.4.38
       postcss-selector-parser: 6.0.16
 
-  stylus-lookup@3.0.2:
+  stylus-lookup@5.0.1:
     dependencies:
-      commander: 2.20.3
-      debug: 4.3.4
-    transitivePeerDependencies:
-      - supports-color
+      commander: 10.0.1
 
   supports-color@5.5.0:
     dependencies:
@@ -18077,19 +17834,20 @@ snapshots:
       minimist: 1.2.8
       strip-bom: 3.0.0
 
+  tsconfig-paths@4.2.0:
+    dependencies:
+      json5: 2.2.3
+      minimist: 1.2.8
+      strip-bom: 3.0.0
+
   tslib@1.14.1: {}
 
   tslib@2.6.2: {}
 
-  tsutils@3.21.0(typescript@3.9.10):
-    dependencies:
-      tslib: 1.14.1
-      typescript: 3.9.10
-
-  tsutils@3.21.0(typescript@4.9.5):
+  tsutils@3.21.0(typescript@5.4.5):
     dependencies:
       tslib: 1.14.1
-      typescript: 4.9.5
+      typescript: 5.4.5
 
   tsx@4.7.2:
     dependencies:
@@ -18219,10 +17977,6 @@ snapshots:
       shiki: 0.14.7
       typescript: 5.4.4
 
-  typescript@3.9.10: {}
-
-  typescript@4.9.5: {}
-
   typescript@5.4.2: {}
 
   typescript@5.4.3: {}
@@ -18276,8 +18030,6 @@ snapshots:
       trough: 2.2.0
       vfile: 6.0.1
 
-  uniq@1.0.1: {}
-
   unique-string@3.0.0:
     dependencies:
       crypto-random-string: 4.0.0
-- 
GitLab