@alexkroman1/aai

中文文档
0.18.2发布于 2026/10/30MITTypeScriptES Module构建来源已验证近 30 天下载 1897

Assembly Associate SDK:一切都是一个 agent.ts 文件导入。 可自行托管的运行时间 CLI 和管理的平台运行为 @alexkroman1/aai-runtime。 。 。 .

中文使用文档
文档目录17 节
  1. 简单的案子就简单
  2. 定义代理人
  3. 工具:一个工具是 FILE
  4. 内置工具和代码执行
  5. 输入会话状态
  6. 每届会议可以复会
  7. 作为保证的谈话令
  8. 理解中转
  9. 副剂
  10. 活在电话里的工作
  11. 说话,屏出
  12. 每行各一名探员
  13. 会话模式和提供者
  14. 测试工具
  15. 行为影响
  16. 其他子路径
  17. 文档

@alexkroman1/aai (英语)

Assembly Associate SDK:一切都是一个 agent.ts 文件导入。 这个 自控运行时间 CLI 和管理的平台运行为 @alexkroman1/aai-runtime。 。 。 .

npm i @alexkroman1/aai zod

大多数项目不直接安装这个.. aai init (从) @alexkroman1/aai-cli(中文(简体) ) 脚手架用它连接一个项目.

简单的案子就简单

SDK的一种模式是单个套接字上的快取、语音和一些密钥名词 整个特工:

import { agent, assemblyAIS2s } from "@alexkroman1/aai";

export default agent({
  name: "Support",
  // The prompt is the system-prompt.md beside this file.
  mode: "s2s",
  s2s: assemblyAIS2s({ voice: "jane", keyterms: ["AssemblyAI"] }),
});

下方的一切都是当您自己的代码运行在它旁边时 能得到的. 这里不需要任何工作代理.

能力这是什么何处
工具文件在 tools/ 模型可以调用tool()
构建代码执行( D)可选入模式的可调用工具,直至运行真正的联署材料builtinTools
输入会话状态已命名、 已输入状态工具的翻转读写sessionSlot()
转动级耐久性失传的回音记录恢复
对话框以代码执行的对话命令, 不在提示中建议dialog()
工具内情报一发LLM在工具内呼叫,返回精确的形状ctx.generate()
副剂具有自身工具和上下文窗口的第二个工具循环ctx.delegate()
长期工作流程日记运行超过呼叫workflow()
定制产品表面会话上的网络用户界面,仅显示您的预测syncState
运输浏览器 WebSocket、Twilio 和 Telnyx 上的同一代理电话
工程寿命周期孤立工具测试、构建时间检查、部署或自主机测试
行为影响开一个真实的会话 并断言经纪人做了什么describeEval

定义代理人

agent.ts ——定义,加上拥有会话状态的槽:

import { agent, sessionSlot } from "@alexkroman1/aai";

export const notesSlot = sessionSlot("notes", () => ({ items: [] as string[] }), {
  view: (notes) => ({ count: notes.items.length }),
  sync: true,
});

// `sync: true` on the slot is what shows it to the browser client (read there
// with `useAgentState`); the prompt is the system-prompt.md beside this file.
export default agent({ name: "Notes" });
  • agent() ——代理定义;每个字段和默认记录在 AgentDef。没有提供者字段 运行默认的 Assembly STT → LLM → TTS 管道,计费为 1 ASSEMBLYAI_API_KEY· ; voice: "aai-michael" 选它TTS的声音.
  • tool() - 无国籍人案件输入的工具:Zod inputSchema 还有一个 execute(args, ctx) 运行服务器侧 ctx.env (秘诀), ctx.signal (驳船时的破坏), ctx.generate (一发LLM呼叫), ctx.delegate (水手们), ctx.workflows (启动并找到可持久运行)和 ctx.send (向浏览器客户端推出事件).
  • sessionSlot() ——一个被打出名的槽,拥有会话状态. slot.tool() 读取(数值被深深地冻结)和 slot.updateTool() 写出来 同步进行. 没有 ctx.state 没有 ctx.db。 。 。 .
  • dialog() 编号 : procedure() - 车型被门挡住 车型自有 密码驱动器.
  • speaker() 编号 : roster() 第2个声音:下放到线下 (单位:千美元)ctx.delegate),或发出电话(speaks: true) (中文(简体) ).
  • workflow() 编号 : workflowApp() - 耐用跑道, 和形式形状的代理人 前门是工作流程而不是麦克风.
  • assemblyAIPipeline() ——与明确分布相同的默认管道 (单位:千美元)...assemblyAIPipeline({ region: "eu" })),因为当你想要三个 在配置或跨STT和网关的欧盟区域可见.

agent() 取一个物体. AgentDef 是每个字段的参考文献 E. 方法——每个字段和默认都记载在那里 AgentParams 这是 以法律为组合的参考。 更全面的配置,包括 字段,上面的例子除外:

import { agent, sessionSlot } from "@alexkroman1/aai";
import { assemblyAITts } from "@alexkroman1/aai/tts";

// `sync: true` is what the browser client renders with `useAgentState`.
const cart = sessionSlot("cart", () => ({ items: [] as string[] }), {
  view: (c) => ({ count: c.items.length }),
  sync: true,
});

export default agent({
  name: "Storefront",
  greeting: "Storefront here — what are you after?",
  tts: assemblyAITts({ voice: "aai-michael" }),
  // Server-side helpers the model may call, on top of your own tool files.
  builtinTools: ["calculate"],
  // Tool-calling steps per reply, and how long a pause ends the caller's turn.
  maxSteps: 6,
  turnTaking: { minSilenceMs: 1200 },
  // Observe-only hooks over the session event stream.
  events: {
    "tool.called": (event) => {
      console.log("called", event.toolName);
    },
  },
});

工具:一个工具是 FILE

一个特工的价值是它要采取的行动, 他们每个人都生活在一个 只有您的代码才能到达系统 。 工具是一个文件在 tools/,以其名称命名 文件名 - agent() 采取不 tools 字段,没有记录:

// file: agent.ts
import { agent, sessionSlot } from "@alexkroman1/aai";

export const notesSlot = sessionSlot("notes", () => ({ items: [] as string[] }));

export default agent({ name: "Notes" });

// file: tools/add_note.ts
import { z } from "zod";
import { notesSlot } from "../agent.ts";

export default notesSlot.updateTool({
  description: "Save a note for the caller",
  inputSchema: z.object({ text: z.string() }),
  // `updateTool` hands the body a mutable draft, stored when it returns.
  execute: ({ text }, notes) => {
    notes.items.push(text);
    return { saved: notes.items.length };
  },
});

秘密不在代码之外 飞行中的工作就停止了 打断.. 通过 ctx.signal 任何缓慢的事物数字 :

import { requireEnv, tool } from "@alexkroman1/aai";
import { z } from "zod";

export default tool({
  description: "Get current weather for a city",
  inputSchema: z.object({ city: z.string() }),
  execute: async ({ city }, ctx) => {
    const key = requireEnv(ctx, "WEATHER_KEY");
    const resp = await fetch(`https://api.example.com/weather?q=${city}&key=${key}`, {
      // Aborts on barge-in, reset, session stop, or this call's timeout.
      signal: ctx.signal,
    });
    return await resp.json();
  },
});

内置工具和代码执行

builtinTools 将模型选择为服务器侧助手, 它可以调用 - web_search, (中文(简体) ), visit_webpage, (中文(简体) ), get_page_design, (中文(简体) ), fetch_json, (中文(简体) ), think, (中文(简体) ), remember编号 :recall, (中文(简体) ), calculate,以及 run_code,模型写 JavaScript并运行在代理的沙盒中. 模型在精神上是不可靠的 算术; 真正的执行是使拨打的号码正确 打电话者要采取行动了.

import { agent } from "@alexkroman1/aai";

// system-prompt.md: "Use run_code for ANY math, counting, or data processing."
export default agent({
  name: "Analyst",
  builtinTools: ["web_search", "run_code"],
});

选择 builtinTools 让他们都无法生存 网络化的内建 模型控制的 URL,所以它们在容器和盖外被 SSRF 筛选 回来的是什么; run_code 需要一个沙盒——平台,或 零允许 AAI_RUN_CODE=deno - 并拒绝一个外.

输入会话状态

长时间的通话积累了事实——订单号,什么已经核实,什么在 车。 没有结构化的状态 探员从记录中重新找到他们 每转一圈. sessionSlot() 在一个共享模块中声明,唯一的 如何在会话工具中保持状态 :

import { sessionSlot } from "@alexkroman1/aai";
import { z } from "zod";

export const cartSlot = sessionSlot("cart", () => ({ items: [] as string[] }));

// `slot.tool()` READS — what the body is handed is frozen.
export const listCart = cartSlot.tool({
  description: "List what's in the cart",
  execute: (_args, cart) => ({ items: cart.items }),
});

// `slot.updateTool()` WRITES — mutate the draft; it is stored when the body
// returns, so a write is SYNCHRONOUS and may not `await`.
export const addItem = cartSlot.updateTool({
  description: "Add an item to the cart",
  inputSchema: z.object({ item: z.string() }),
  execute: ({ item }, cart) => {
    cart.items.push(item);
    return { count: cart.items.length };
  },
});

槽持有纯数据(a) Map, (中文(简体) ), Set, (中文(简体) ), Date 或类案例被拒绝 字段名称)。 在平台上,他们被储存 为你 - 一个坠机或一个 调用不再失去它们,也没有任何可用的. 下 aai dev 他们生活在记忆中 除非你设置 DATABASE_URL代码是相同的 就是这样.

每届会议可以复会

连接下降, 五分钟的身份验证加半建 命令不应该重新启动。 客户端重新连接 ?sessionId=<id> 重新登记 同一会话:事件日志被恢复,槽值被还水 问候被压制,因为呼叫者已经听到了. 简历 没有东西被当做新会议 而不是坐着问候 相通而无声. 背景工作按键再次找到——稍后, 或者在下一个电话:

import { tool, workflow } from "@alexkroman1/aai";
import { z } from "zod";

export const research = workflow({
  description: "Research a topic",
  input: z.object({ topic: z.string() }),
  run: async (input) => ({ topic: input.topic, findings: [] as string[] }),
});

export default tool({
  description: "Check on research from earlier",
  execute: async (_args, ctx) => {
    // The run outlived the call — find it by the key it was started with.
    const [run] = await ctx.workflows.find(research, ctx.sessionId);
    if (!run) return { status: "none started" };
    return run.status === "completed" ? run.output : { status: run.status };
  },
});

作为保证的谈话令

在系统提示中“在披露前验证”是建议. dialog() 让它成为一个 规则: 以 when 根本就没有在这些国家之外运行 模型会回来的 ToolFailure 命名必须先发生的事情。 这个 位置是下面的一个插槽,所以它能活过再连接.

import { dialog } from "@alexkroman1/aai";
import { z } from "zod";

export const claim = dialog("claim", {
  initial: "verifying",
  states: {
    verifying: {
      instruction: "Verify the caller's policy number before quoting anything.",
      on: { VERIFIED: "quoting" },
    },
    quoting: {
      instruction: "Quote the excess. Do not re-verify.",
      on: { QUOTED: "done" },
    },
    done: { final: true },
  },
});

// Cannot run before the caller is verified; advances the dialog when it does.
export const quoteClaim = claim.tool({
  when: "quoting",
  send: { type: "QUOTED" },
  description: "Quote the premium for an excess",
  inputSchema: z.object({ excess: z.number() }),
  execute: ({ excess }) => ({ premium: excess * 2 }),
});

州和事件是从谱中推断出来的 所以拼错了 send 是一个 编译错误 . procedure() 是无型号驱动的流体兄弟 循环中的 X 状态机器,有分支、重试和有限制的预算,运行 与 await procedure(machine).run(input)。 。 。 .

理解中转

特工们不断需要小的谅解行为: 从乱伦的句子中,对意图进行分类,对检索到的文件进行分级. ctx.generate() 一个LLM呼叫,主机侧, 保证形状回:

import { tool } from "@alexkroman1/aai";
import { z } from "zod";

export default tool({
  description: "Start an order from what the caller just said",
  inputSchema: z.object({ utterance: z.string() }),
  execute: async ({ utterance }, ctx) => {
    const parsed = await ctx.generate({
      prompt: `Extract the order from: "${utterance}"`,
      schema: z.object({ sku: z.string(), qty: z.number() }),
    });
    // `object` is typed by the schema: { sku: string; qty: number }.
    return parsed.object;
  },
});

它默认为代理自己的 llm; 通过一个 llm 描述符或模型代号 字符串用于使用密钥在代理机密中的任何提供者——这也是 s2S代理如何到达模型.

副剂

复杂请求需要未知数量的查询 呼叫者不需要 听着 排出队来,他们低声说话,每转一转就慢一点; 外出时,腿部工作会从侧面进行——如果有的话,则平行进行 数个角度——呼叫只带答案. 副剂是第二 工具环路, 带有自己的系统即时、模型、工具和上下文窗口:

import { speaker, tool } from "@alexkroman1/aai";
import { z } from "zod";

const researcher = speaker({
  name: "researcher",
  systemPrompt:
    "Research the task with the tools you have. IMPORTANT: your final message " +
    "is the only thing the caller sees — end with a self-contained summary.",
  builtinTools: ["web_search", "visit_webpage"],
  maxSteps: 6,
});

export default tool({
  description: "Research a question in depth",
  inputSchema: z.object({ question: z.string() }),
  execute: async ({ question }, ctx) => {
    const { text, toolCalls } = await ctx.delegate(researcher, { task: question });
    return { answer: text, lookups: toolCalls.length };
  },
});

你收到它的最后信息,它的背景是孤立的,因此请它 总结和写 task 作为完整的简介。 代表团是一个深层.

活在电话里的工作

报告生成时,没有呼叫者持有4分钟。 工具开始持久 运行并回答转弯; 运行是日记的, 因此它能通过重启, a 调用和闲置的沙盒。 与 notify 经纪人说结果的时候 lands——普通可中断的转会,只有在呼叫者仍然在线上. 如果他们挂了,运行完成 反正下一个电话找到它 key。 。 。 .

import { tool, workflow, type WorkflowContext } from "@alexkroman1/aai";
import { z } from "zod";

// workflows/research.ts — an ordinary async function of its input and a ctx.
export async function researchFlow({ topic }: { topic: string }, ctx: WorkflowContext) {
  // `ctx.step` runs once and journals what it returned; a replay never re-runs
  // it. The body itself makes no undurable decision — no Date.now(), no fetch.
  const findings = await ctx.step("gather", () => gather(topic));
  // Suspended, not blocked: the container may exit here and resume when due.
  // Ten minutes and six hours work the same way.
  await ctx.sleep("settle", 10 * 60 * 1000);
  return findings;
}

declare function gather(topic: string): Promise<{ topic: string; points: string[] }>;

export const research = workflow({
  description: "Research a topic and report back",
  input: z.object({ topic: z.string() }),
  run: researchFlow,
});

// tools/research_topic.ts — promise made, and kept.
export default tool({
  description: "Research a topic in the background",
  inputSchema: z.object({ topic: z.string() }),
  execute: async ({ topic }, ctx) => {
    await ctx.workflows.start(research, { topic }, {
      key: ctx.sessionId,
      notify: "Tell the caller what it found.",
    });
    return { started: true };
  },
});

宣布代理工作流程(agent({ workflows: { research } })和 ctx.workflows 能够 start, (中文(简体) ), find, (中文(简体) ), get, (中文(简体) ), wakeUp 财务报告和审定财务报表 stream 它的运行。 何时 产品是形式而不是呼唤, workflowApp() 其代理人 前门是一个工作流程——没有会话,没有LLM回路,每个语音节点 a 编译错误 .

说话,屏出

调用者在屏幕上的手推车、表格或行程更新时进行交谈 输入,屏幕确认。 这样一来,命令就不用读了 十六位数大声点. syncState 取一个proJECTION,而不是一面旗帜,所以你选择 允许浏览器查看的内容 :

import { agent, sessionSlot } from "@alexkroman1/aai";

// shared.ts — declare the view on the slot and import it at both ends.
// `staffPin` is not in the view, so it never reaches the browser.
export const cartSlot = sessionSlot("cart", () => ({ cart: [] as string[], staffPin: "" }), {
  view: (s) => ({ cart: s.cart }),
  sync: true,
});

export default agent({ name: "Storefront" }); // the `sync: true` slot is collected
import { sessionSlot } from "@alexkroman1/aai";
import { mountClient, useAgentState } from "@alexkroman1/aai-ui";

// client.tsx — in a project this is `import { cartSlot } from "./shared.ts"`,
// the same slot the agent declared, so the two ends cannot name different views.
const cartProjection = sessionSlot("cart", () => ({ cart: [] as string[] }), {
  view: (s) => ({ cart: s.cart }),
}).projected;

function App() {
  // The projection types the state AND supplies the frame rendered before the
  // first push — no type argument, no `?? EMPTY`.
  const view = useAgentState(cartProjection);
  return (
    <ul>
      {view.cart.map((item) => (
        <li key={item}>{item}</li>
      ))}
    </ul>
  );
}

mountClient({ component: App });

投影在每次工具调用后运行, 只有在结果出来时才发出 换了. ctx.send(event, data) {\fn黑体\fs20\shad2\2ah82\3ah20\4ah33\fscx95\3ch592001\be1}是一切不真实的推道 状态; @alexkroman1/aai-ui 有钩子和部件.

每行各一名探员

说出你的号码所在的载体, 和特工的电话 会话以 :

import { agent } from "@alexkroman1/aai";

export default agent({
  name: "Support",
  // `true` admits every carrier this build decodes; omit it and the phone
  // route is not served at all.
  telephony: ["twilio"],
});

然后把数字的语音网钩对准经纪人 用媒体回答 流线 :

wss://<your-agent-url>/phone?carrier=twilio
wss://<your-agent-url>/phone?carrier=telnyx

Twilio和Telnyx是这些建筑解码器的载体;它们都说出8千赫的m-law, 以两面相接而行, 驳船,工具和槽像浏览器一样在呼叫中运行. 一个电话是 运输,不是一种模式——你在网络演示中测试的是呼叫者得到的.

会话模式和提供者

管道模式 (默认) 串流 STT 部分进入服务器侧 LLM 循环和 通过 TTS 供应商来表达答案 。 把任何舞台都换成工厂 提供者子路径 - 设置任意子集 stt, (中文(简体) ), llm, (中文(简体) ), tts; 未设置的相位保留 assemblyAI 默认:

子路径工厂
@alexkroman1/aai/sttassemblyAIStt, (中文(简体) ), deepgramStt, (中文(简体) ), elevenLabsStt, (中文(简体) ), sonioxStt
@alexkroman1/aai/llmllm({ provider, model }) - 一个工厂; provider 实值 "assemblyai", (中文(简体) ), "anthropic", (中文(简体) ), "openai", (中文(简体) ), "google", (中文(简体) ), "mistral", (中文(简体) ), "xai", (中文(简体) ), "groq", (中文(简体) ), "cerebras", (中文(简体) ), "openrouter", (中文(简体) ), "gateway",或任何以下列方式命名的 OpenAI 兼容端点: baseUrl
@alexkroman1/aai/ttsassemblyAITts, (中文(简体) ), cartesiaTts, (中文(简体) ), rimeTts

工厂返回纯描述符——可序列数据,而不是SDK客户端. 证书由代理服务器端解决(每个工厂的文件) 所以没有提供商SDK 或秘密进入代理包. llm 也接受一个模型化字符串 : "creator/model" 途经 Vercel AI Gateway,一个通过AssemblyAI LLM Gateway的赤裸的身份证—— agent({ name: "...", llm: "claude-sonnet-4-6" }) 换掉的只是模型.

S2S 模式 是语音对语音服务的明确选择,其中STT, lLM 环路和 TTS 都在一个套接字上运行: s2s: assemblyAIS2s() (源导出)或 openAIS2s() 从 @alexkroman1/aai/s2s。 。 。 .

测试工具

一个复杂的代理是一个活代码库——数十个工具,一个不断发展的即时, 有几个人编辑它。 一个工具是文件,所以 agent.ts默认导出 没有携带工具; deployedAgent 给您定义一个部署的代理 运行,然后每个工具都可以单独调用,没有会话、模型和 无网络 :

// file: agent.ts
import { agent, sessionSlot } from "@alexkroman1/aai";

export const notesSlot = sessionSlot("notes", () => ({ items: [] as string[] }));

export default agent({ name: "Notes" });

// file: tools/add_note.ts
import { z } from "zod";
import { notesSlot } from "../agent.ts";

export default notesSlot.updateTool({
  description: "Save a note for the caller",
  inputSchema: z.object({ text: z.string() }),
  execute: ({ text }, notes) => {
    notes.items.push(text);
    return { saved: notes.items.length };
  },
});

// file: agent.test.ts
import { createToolContext, deployedAgent, toolRunner } from "@alexkroman1/aai-runtime/testing";
import { expect, test } from "vitest";
import authored from "./agent.ts";
import addNote from "./tools/add_note.ts";

const agentDef = deployedAgent(authored, {
  tools: import.meta.glob("./tools/*.ts", { eager: true }),
});
const run = toolRunner(agentDef);

test("saves a note", async () => {
  // Typed by the tool's own def: `saved` is a number, no cast.
  const { saved } = await run(addNote, { text: "milk" }, createToolContext());
  expect(saved).toBe(1);
});

createToolContext() 建立一个完整的 ToolContext 有惰性默认和 a 录音 ctx.send· ; stubGenerate, (中文(简体) ), stubDelegate, (中文(简体) ), stubGateway 财务报告和审定财务报表 stubUploads 驱动工具合作者的答案. aai build 运行 在项目捆绑之前先检查套件和类型.

行为影响

快速的调子可以悄悄地降低工具纪律 没有人用手测试每部编辑的40种情景. describeEval (从) @alexkroman1/aai-runtime/testing/vitest运行 aai eval驱动一个真实的 并声称代理人做了什么 是什么工具 它叫什么顺序, 和它所说的:

import { agent } from "@alexkroman1/aai";
import { describeEval } from "@alexkroman1/aai-runtime/testing/vitest";
import { expect } from "vitest";

const agentDef = agent({ name: "Support" }); // the prompt is system-prompt.md

describeEval(agentDef, (test) => {
  test(
    "looks the order up first",
    async ({ session }) => {
      const turn = await session.say("where is order W1234?");
      expect(turn.toolCalls.map((c) => c.name)).toContain("look_up");
      expect(turn.text).toMatch(/shipped/i);
    },
    // What a scripted model answers when there is no provider key — the eval
    // still proves the agent boots, tools resolve, and a reply comes back.
    { stubReply: "Order W1234 shipped yesterday." },
  );
});

使用提供者密钥, 同一文件驱动一个活模式; 没有一个则运行 脚本,所以它在CI中是自由的和决定性的.

其他子路径

每个子路径都由WHO 读取它命名——当右侧一栏到达 描述你在做什么.

子路径找到它的时候
/testing, (中文(简体) ), /testing/vitest测试助手被宣布的地方 – 一个测试文件导入到 @alexkroman1/aai-runtime/testing 财务报告和审定财务报表 /testing/vitest
/stt, (中文(简体) ), /llm, (中文(简体) ), /tts, (中文(简体) ), /s2s为管道阶段挑选供应商(上表)
/step, (中文(简体) ), /step-errors, (中文(简体) ), /step-files在工作流程中写一个步骤—— stepFetch, (中文(简体) ), stepEnv, (中文(简体) ), mapConcurrent, (中文(简体) ), stepGenerate, (中文(简体) ), readUploadToFile
/workflow-api从网页、脚本或简历中调用已部署的代理人—— createAgentClient
/tools电话 fetchJson, (中文(简体) ), visitWebpage 或者说 webSearch 从您自己的工具代码
/channels发布一个结果某处 - slackChannel, (中文(简体) ), sendToChannel
/html读取页面或种子.. htmlToText, (中文(简体) ), pageMetadata, (中文(简体) ), parseFeed
/utils在工具体内写作的小助手—— toolFailure, (中文(简体) ), errorMessage, (中文(简体) ), pushCapped, (中文(简体) ), withLock
/ffmpeg从一个步骤运行 ffmpeg -- runFfmpeg, (中文(简体) ), probeMedia, (中文(简体) ), transcodeToWav
/protocol, (中文(简体) ), /manifest, (中文(简体) ), /slugify, (中文(简体) ), /workspace-files, (中文(简体) ), /internalcLI 和平台所使用的框架内部; 不是一个公共的 API , 并且没有被 semver 覆盖

文档

完整 API 参考 : https://alexkroman.github.io/ agent/ 页面存档备份,存于互联网档案馆

完整的编写指南 agent() 字段、工作流程规则、UI 钩子 语音即时规则——本套装中的船为: AGENT_GUIDE.md, (中文(简体) ), 除了这个文件。 (直接不是相对链接: TypeDoc 复制链接) 文件输入了制成的 Docs 树,这个是生成的100 kB 文本 已经住在两个地方。 )

版本与发布记录

@alexkroman1/aai 共发布 163 个版本,首次发布于 2026/03/18;过去 12 个月发布了 163 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.18.2latest2026/10/309 天前
0.18.12026/10/309 天前
0.18.02026/10/299 天前
0.17.02026/10/2316 天前
0.16.02026/10/2316 天前
0.15.52026/10/1523 天前

关于 @alexkroman1/aai 的常见问题

@alexkroman1/aai 是什么?

Assembly Associate SDK:一切都是一个 agent.ts 文件导入。 可自行托管的运行时间 CLI 和管理的平台运行为 @alexkroman1/aai-runtime。 。 。 .

如何安装 @alexkroman1/aai?

在项目目录运行 npm install @alexkroman1/aai,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:zod(^4.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@alexkroman1/aai 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@alexkroman1/aai 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@alexkroman1/aai 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@alexkroman1/aai 可以商用吗?

@alexkroman1/aai 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@alexkroman1/aai 的下载量有多少?

根据 npm 官方下载统计,@alexkroman1/aai 在 2026/10/06 – 2026/11/04 这 30 天内被下载 1,897 次,日均约 63 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@alexkroman1/aai 还在维护吗?

最新版本 0.18.2 发布于 2026/10/30(9 天前);至今共发布 163 个版本,其中过去 12 个月发布了 163 个;首次发布于 2026/03/18。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。