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

@echo-agent/core

v0.2.0

Published

The Echo agent runtime and SDK: a persistent agent — state machine, commands, events — and its pure loop. Zero runtime dependencies; the Agent owns the mechanism while you supply the ports and the policy.

Readme

@echo-agent/core

一个持续存在的 agent 的最小可执行内核:状态机 + 循环 + 会话持久化,零运行时依赖。

不是框架。它不替你选模型、不规定工具怎么写、不带 CLI——你给它一个 Model 和一组端口, 它负责「跑完一轮任务」以及「进程重启之后还记得自己是谁」。

import { createEcho, type Provider } from "@echo-agent/core";

declare const myProvider: Provider;

const echo = await createEcho({ provider: myProvider });
await echo.start();                     // 取单写锁 → 恢复会话
const result = await echo.send("把 README 翻成英文"); // = agent.prompt() + 观测三元组,第三方走这条
await echo.stop();                      // 先卸扩展 → 等落盘 settle → 释放锁

createEcho() 是唯一的装配现场:它装好 Agent,再把内建能力(Task / Skill / Memory / Schedule) 与 <cwd>/extensions/ 里你自己写的扩展,用同一套机制装上去。装了什么在 echo.extensions 里看得见。

三条正门

都在 @echo-agent/core 这一条入口上:

| 要做什么 | 从哪进 | |---|---| | 起一个能跑的 agent | createEcho()——只给 provider,端口、内建能力与扩展装配都已备好;它是唯一的装配现场 | | 给它加工具 / prompt 段 / 压缩阶段 / hook | 写一条 extension(@echo-agent/core/extension):声明注入什么、提供什么,生命周期归 host,卸载不留残骸 | | 换一个壳(Web、别的终端) | 同样是一条 extension,注入 AgentRuntime 这个 service 并把它渲染出来 |

Agent 类将收进内部(2026-09-07 拍板、尚未实现,记录在仓库 docs/decisions/proposed/2026-09-07-agent-class-internal.md;今天它还在公共面上,api-snapshot 里能看到):它有相当一部分是为承载 host 专用接线(写入闸、所有权账本、观测 writer)而存在的,把它当公共面等于承诺那些。第三方要的深度在 extension ABI 上——那条路带 hostAbiVersion 校验、Fiber/Effect 所有权与整代回滚,比裸类安全。别在新代码里 new Agent()。

另有 @echo-agent/core/testing(FakeProvider 与脚本化流、in-memory 观测 collector)、 @echo-agent/core/extension(写扩展的 ABI)、@echo-agent/core/task/fs、@echo-agent/core/mcp。

几条硬约定

  • 零运行时依赖。 运行时依赖三字段(dependencies / optionalDependencies / peerDependencies)恒空,有门守着。
  • fail-loud,绝不静默降级。 缺凭据、拿不到锁、盘上有坏档——一律抛,不回退到「假装成功」。
  • single-writer。 一个状态根同时只允许一个写者。锁被占着就拒绝启动,core 不猜对面是不是死了, 也不抢占没有自称可让位(preemptible)的持有者——可让位的实例被请走时自己交还并退出(2026-09-07:人优先,后台让位); 崩溃后需人工清锁(inspectStateLock() 告诉你是谁占着)。
  • write() resolve 即持久。 存储端口上没有 flush;stop() 等的是未 settle 的写。
  • 持久化失败会封存该会话。 一次写失败之后拒绝继续写——继续写只会产出 parent 指向 不存在 entry 的坏档。需人工确认盘上状态,再重新 createOrResume。

状态放在哪

状态根 = 一段 session 的目录(2026-09-03 起):stateDir > <sessionsRoot>/<sessionId> > $ECHO_HOME/sessions/<sessionId> > ~/.echo/sessions/<sessionId>。

一段 session 就是一个独立在跑的 agent,所以按状态根一份的东西——lease、会话账本、inbox、任务清单、 闹钟、观测库——都变成按 session 一份。同一台机器上两段 echo-coding 因此各拿各的锁、能同时起来; 在旧布局(agents/<agentId>/)下第二段直接 fail-loud。

跨 session 共享的记忆与技能不在状态根下,在 $ECHO_HOME(缺省 ~/.echo)下面:

| 放什么 | 在哪 | | --- | --- | | 这一段的账本、inbox、tasks、schedule、lease、观测库 | <ECHO_HOME>/sessions/<id>/ | | 记忆 · user 层(这个用户的所有 session) | <ECHO_HOME>/memory/ | | 记忆 · project 层(在同一个目录下工作的 session) | <ECHO_HOME>/projects/<workspace 哈希>/memory/ | | 记忆 · role 层(跑同一个角色定义的 session;没有角色名就没有这层) | <ECHO_HOME>/agents/<角色名>/memory/ | | 技能 | <ECHO_HOME>/skills/ | | 凭据、设置、扩展 | <ECHO_HOME>/ |

记忆作用域由产品声明,core 不认识具体层名;上面三层是 core 的缺省表(DEFAULT_MEMORY_SCOPES,packages/core/src/create-agent.ts), 产品给 memoryScopes 就整份替换。

工作目录是 session 的字段(SessionInfo.workspace),不是状态根的一部分——换个目录起就是新的一段, user 层记忆与技能仍是同一份,project 层按 workspace 哈希换一套。要整体隔离(评测、单测)就设 ECHO_HOME:只给 stateDir 只挪走 session 那一半。

公共面

由 test/api-snapshot.test.ts 锁着——增删任何导出符号都必须重录快照并人审 diff。 清点脚本是 scripts/api-inventory.ts,判据源与人读报告是同一份。

开发

bun test                 # 单测
bun run typecheck        # tsc --noEmit
bun run build            # 出 dist/(.js + .d.ts),发布前 prepack 自动跑

许可

MIT,见同目录 LICENSE(与仓库根那份字节一致,files 收它、npm pack 带它)。