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-coreSubpath 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/customLLM_MODEL— 默认模型LLM_TEMPERATURE— 默认 temperatureLLM_MAX_TOKENS— 默认 max tokensLLM_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-modelAgent 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_ESMLicense
MIT.
