npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

trek-ai-core

v0.1.35

Published

AI Agent core runtime: LLM clients, semantic retrieval, event bus, agent journal, lessons, env manager

Readme

trek-ai-core

TypeScript runtime: LLM clients, semantic retrieval primitives, agent journal, on-disk lesson store, retry / circuit-breaker, and path management. Host-agnostic; consumed by trek-ai-cli but also importable directly.

Node ≥ 22 · MIT · Pure ESM

Install

pnpm add trek-ai-core

Subpath exports

| Subpath | 内容 | 什么时候用 | |---|---|---| | trek-ai-core | barrel: 路径管理 + LLM + 嵌入 + agent-loop + lessons + retry | 一次性拿全部 | | trek-ai-core/llm | LLMClient、createLLMClient + 消息 / 响应 / 选项类型 | 只想用 LLM | | trek-ai-core/retriever | 混合检索器(cosine + keyword 排序) | 检索业务知识 | | trek-ai-core/event-bus | 进程内 pub/sub bus | 监听 agent 内部事件 | | trek-ai-core/agent-loop | Plan / Observe / Reflect 状态机 | 自己做 agent 调度 | | trek-ai-core/lessons | 磁盘 lesson 存储(JSON + 互斥锁) | 经验沉淀 / RAG | | trek-ai-core/env-manager | .env 加载 + 平台探测 | 检测 Python / 写盘 / bin 路径 | | trek-ai-core/paths | 路径注入 + 全局 getXxxPath() | 配置宿主项目布局 | | trek-ai-core/utils | ensureDir / readJson / writeJson / fileExists | 通用 IO 工具 | | trek-ai-core/retry | CircuitBreaker / retryWithBackoff / retryFetch | 任何需要重试 / 熔断的地方 |


路径注入(必读)

trek-ai-core 不硬编码任何宿主项目路径。所有下游消费者(knowledge base、embeddings、lessons、LLM 缓存)都通过全局 path store 读路径。 宿主项目启动时调一次 setPaths():

import { setPaths } from 'trek-ai-core'

setPaths({
  projectRoot: '/abs/path/to/your/repo',
  dataDir: '/abs/path/to/your/repo/.ai-workflow',
  knowledgePath: '/abs/path/to/your/repo/.ai-workflow/knowledge.json',
  embeddingsPath: '/abs/path/to/your/repo/.ai-workflow/embeddings.json',
  lessonsPath: '/abs/path/to/your/repo/.ai-workflow/lessons.json',
  modelsDir: '/abs/path/to/your/repo/.ai-workflow/models',
  componentRoot: '/abs/path/to/your/repo/packages/components',
  docsRoot: '/abs/path/to/your/repo/docs/en-US/component',
  examplesRoot: '/abs/path/to/your/repo/docs/examples',
  componentsIndex: '/abs/path/to/your/repo/packages/my-lib/component.ts',
  sidebarConfig: '/abs/path/to/your/repo/docs/.vitepress/i18n/pages/component.json',
  // 可选
  aiConfigPath: '/abs/path/to/your/repo/ai.config.ts',
})

之后任何模块都可以读:

import { getKnowledgePath, getLessonsPath, getDataDir } from 'trek-ai-core'

const kPath = getKnowledgePath()      // '/abs/.../knowledge.json'
const lPath = getLessonsPath()        // '/abs/.../lessons.json'
const dDir  = getDataDir()            // '/abs/.../.ai-workflow'

LLMClient

import { LLMClient } from 'trek-ai-core/llm'

const llm = new LLMClient({ model: 'gpt-4o-mini' })

const res = await llm.generateText(
  [
    { role: 'system', content: 'You are a friendly assistant.' },
    { role: 'user', content: 'Hi!' },
  ],
  {
    temperature: 0.4,
    maxNewTokens: 200,
    // 透传给 OpenAI / DeepSeek 兼容 API 的额外字段
    extraBody: { response_format: { type: 'json_object' } },
  }
)

console.log(res.content)
// res: { content: string, model: string, usage?: { promptTokens, completionTokens, totalTokens } }

支持 provider(自动从环境变量推断):

  • OPENAI_API_KEY → OpenAI(gpt-4o*、o1-*)
  • DEEPSEEK_API_KEY → DeepSeek(deepseek-chat、deepseek-reasoner)
  • OLLAMA_HOST → Ollama(本地)

强制离线:LLM_DISABLED=1 时,isConfiguredSafe() 永远返回 false, 所有 generateText() 抛 LLMDisabledError。

工厂方法(读环境变量自动选 provider):

import { createLLMClient } from 'trek-ai-core/llm'

const llm = createLLMClient({ model: 'gpt-4o-mini' })

配置项:

  • LLM_PROVIDER — openai / deepseek / ollama / custom
  • LLM_MODEL — 默认模型
  • LLM_TEMPERATURE — 默认 temperature
  • LLM_MAX_TOKENS — 默认 max tokens
  • LLM_BASE_URL — 自定义 endpoint(OpenAI 兼容)

嵌入 & 语义搜索

import { embedText, cosineSimilarity, normalizeEmbedding } from 'trek-ai-core'

// 把一段文本转成向量(本地 ONNX 模型,无需 API key)
const v1 = await embedText('how do I add a v-model?')
const v2 = await embedText('use UPDATE_MODEL_EVENT from @my-scope/constants')

// 余弦相似度,[-1, 1]
const score = cosineSimilarity(v1, v2)

// 如果你要做关键词 + 向量混合排序,normalize 一下
const n1 = normalizeEmbedding(v1)

需要本地 ONNX 模型(默认 Xenova/all-MiniLM-L6-v2),首次运行会下载到 modelsDir(见 setPaths())。想自己预下载,调:

npx ai-agent download-model

Agent loop(Plan → Observe → Reflect)

import {
  setPlan,
  agentObserve,
  agentReflect,
  getAgentState,
  resetAgentState,
} from 'trek-ai-core/agent-loop'

// 1. 设定目标
setPlan({
  goal: 'Add the FancyButton component',
  steps: ['scaffold', 'implement', 'test', 'document'],
})

// 2. 每跑一步,记一条观察
agentObserve({ step: 'implement', result: 'compiled', note: 'first try' })

// 3. 跑完一步后反思
const reflection = agentReflect()
// → { continue: true, nextStep: 'test', lesson: '...', ... }

// 4. 拿当前 state
const state = getAgentState()
// → { goal, steps, observations: [...], reflections: [...], status: 'in-progress' }

// 测试时重置
resetAgentState()

journal 写到 <dataDir>/agent-journal.jsonl,每条记录一行 JSON。


Lessons(经验库,带 RAG 检索)

import {
  findRelevantLessons,
  recordLesson,
  loadLessons,
  getTopLessons,
} from 'trek-ai-core/lessons'

// 1. 记一条经验(写入时带文件锁,支持并发)
recordLesson({
  componentName: 'fancy-button',
  issuePattern: 'missing-use-namespace',
  issueDescription: 'SFC 忘了 useNamespace',
  fix: "import { useNamespace } from '@my-scope/hooks'",
  fixDescription: '在 <script setup> 顶部 import useNamespace,然后 ns = useNamespace("button")',
})

// 2. 遇到类似问题,语义检索
const lessons = await findRelevantLessons('useNamespace missing', {
  topK: 5,
  componentName: 'fancy-button',
  // 过滤:只返回最近 90 天 / 使用次数 ≥ 2 的
  since: Date.now() - 90 * 24 * 3600 * 1000,
  minUsage: 2,
})
// → Lesson[]

// 3. 看最常用的
const top = getTopLessons(10)

// 4. 全部载入(直接读 JSON)
const all = loadLessons()

存储在 <lessonsPath>(默认 .ai-workflow/lessons.json),每条 lesson 含 id / componentName / issuePattern / fix / usageCount / lastUsed / timestamp。


Retry / Circuit Breaker

import { retryWithBackoff, CircuitBreaker, retryFetch } from 'trek-ai-core/retry'

// 1. 退避重试
const data = await retryWithBackoff(
  () => fetch('https://api.example.com/data').then(r => r.json()),
  {
    maxAttempts: 5,
    initialDelayMs: 200,
    maxDelayMs: 5000,
    jitter: 'full',  // 'none' | 'full' | 'equal'
    onFailedAttempt: (info) => {
      console.warn(`retry ${info.attempt}, waiting ${info.delayMs}ms`)
    },
  }
)

// 2. 熔断器
const breaker = new CircuitBreaker({
  failureThreshold: 5,    // 5 次失败就打开
  resetTimeoutMs: 30_000, // 30s 后半开
})

const result = await breaker.execute(() => callFlakyService())

// 3. fetch 重试
const res = await retryFetch('https://api.example.com/data', { method: 'GET' })

Event bus

import { EventBus, bus } from 'trek-ai-core/event-bus'

// 1. 自己 new 一个
const myBus = new EventBus<{ tick: number; done: void }>()
myBus.on('tick', (n) => console.log(n))
myBus.emit('tick', 1)

// 2. 用全局共享 bus(agent loop 在用)
bus.on('agent:plan', (plan) => console.log('new plan', plan))
bus.emit('agent:plan', { goal: '...' })

完整 API 速查

| 导出 | 类型 | 说明 | |---|---|---| | setPaths | (paths: ProjectPaths) => void | 注入宿主路径(启动时必调) | | getProjectRoot / getDataDir / getKnowledgePath / getLessonsPath / ... | () => string | 读全局 path store | | LLMClient | class | OpenAI/DeepSeek/Ollama 聊天客户端 | | createLLMClient | (opts?) => LLMClient | 工厂,从 env 自动选 provider | | LLMMessage / LLMResponse / LLMGenerationOptions | type | LLM 客户端相关类型 | | llmConfig / getProviderConfig / getModelConfig / getApiKey | object / () => ... | LLM 配置访问器 | | embedText | (text: string) => Promise<number[]> | 文本 → 向量(本地 ONNX) | | cosineSimilarity | (a: number[], b: number[]) => number | 余弦相似度 | | normalizeEmbedding | (v: number[]) => number[] | L2 归一化 | | setPlan / agentObserve / agentReflect / getAgentState / resetAgentState / summarize | functions | agent loop | | findRelevantLessons / recordLesson / loadLessons / saveLessons / updateLessonUsage / getTopLessons / extractPatternFromError | functions | lesson 库 | | Lesson / FindLessonsOptions | type | lesson 类型 | | CircuitBreaker | class | 熔断器 | | retryWithBackoff / retryFetch / retrySpawn / retrySpawnSync / computeDelay | functions | 重试 | | EventBus / bus | class / instance | 进程内 pub/sub | | core.EventBus / core.WorkerPool / core.Tracer / core.MetricsCollector / core.CheckpointStore / core.FileHashStore | (under core namespace) | 内部基础设施 | | detectPlatform / isWindows / resolvePythonCommand / checkEnvAll / installAgentReach / installGraphify | functions | env-manager | | ensureDir / readJson / writeJson / fileExists | functions | utils |


TypeScript 注意事项

  • trek-ai-core 是 ESM-only,不能 require()
  • import { core } from 'trek-ai-core' 拿到一个 namespace(core.EventBus 等)
  • import { EventBus } from 'trek-ai-core/event-bus' 拿到具体类(tree-shakable)
// ✅ 推荐(显式 subpath)
import { LLMClient } from 'trek-ai-core/llm'
import { retryWithBackoff } from 'trek-ai-core/retry'

// ✅ 也行(barrel)
import { LLMClient, retryWithBackoff, setPaths } from 'trek-ai-core'

// ❌ 不行(CJS)
const { LLMClient } = require('trek-ai-core')  // ERR_REQUIRE_ESM

License

MIT.