@ cteno/ sdk
从Node.js调出Cteno探员 创建一个会话,发送一个即时,流出答案—— 或用自己的系统即时创建自己的代理和运行在Cteno上的工具 你的流程.
npm install @cteno/sdk 还为您的平台安装 Cteno 守护进程
(单位:千美元)@cteno/sdk-<os>-<arch>,可选择的依赖性). CtenoSession.open() 开始于
本地模式在第一次使用时:没有桌面应用程序、没有账户、没有自己的模式密钥。 要求数
节点20.
安装
npm install @cteno/sdk
一次注册一个模型( BYOK; 存储在 SDK 守护进程自己的数据目录中 ):
import { CtenoSession } from '@cteno/sdk/core';
const cteno = await CtenoSession.open();
await cteno.configureModel({ baseUrl: 'https://api.openai.com/v1', model: 'gpt-4.1-mini', apiKey: process.env.OPENAI_API_KEY! });
baseUrl 按给定使用:包括API版本(https://api.openai.com/v1, (中文(简体) ),
https://api.deepseek.com/anthropic/v1, (中文(简体) ), https://generativelanguage.googleapis.com/v1beta(三);
sDK 附件只包含资源路径。 缺少或重复版本的基数
部件制作 configureModel() 以它会要求的完整 URL 投掷 .
见 仓库读取器 用于平台、权限、守护进程 生命周期和故障排除.
一发查询
import { query } from '@cteno/sdk/core';
for await (const message of query({ prompt: 'Summarize the files in this folder', cwd: './src' })) {
if (message.type === 'assistant' && (message.kind === undefined || message.kind === 'message')) {
console.log(message.text); // answer text only; structured frames carry `kind`
}
}
query() 财务报告和审定财务报表 send() 成立受歧视的工会:
type | 含义 |
|---|---|
user | 您的即时反应, 一旦守护进程持久接受它 |
assistant | 一个模型框. text 总是指印; data 为结构化框架(工具呼叫、任务生命周期)保存解析后的信封 |
status | 会话经过思考/忽视——进步UI,可以忽略 |
result | 转向完成。 总是最后. ok: false 转弯失败时(型号404/401/429,配额,超时); error 是原始错误文本, errorKind 其类 |
突破回路 提前中止本地等待并释放连接;
守护进程可能还在工作,就像 ctrl-C 在一个CLI。 也没有超时
也无法证明守护进程已停止 .
多回合会议
import { CtenoSession } from '@cteno/sdk/core';
const session = await CtenoSession.open();
const id = await session.create({ cwd: './src', title: 'refactor', permissionMode: 'bypassPermissions' });
for await (const message of session.send({ sessionId: id, prompt: 'Start with the parser' })) {
if (message.type === 'assistant') console.log(message.text);
}
const { ok, text } = await session.run({ sessionId: id, prompt: 'Now write tests' });
const history = await session.history(id);
const trace = await session.trace(id);
const profiles = await session.listProfiles(); // model profiles the daemon can run
await session.close(id);
session.dispose();
// ok is false when the model call failed; error then holds the provider's original text
不只读的工具需要批准. 没有一个人 SDK立刻否认他们
(模型被告知原因),所以没有什么挂起。 每个电话决定 canUseTool
打开 send() 编号 : run() 编号 : query()数字 :
await session.run({ sessionId: id, prompt: 'Run the tests',
canUseTool: req => req.toolName === 'Bash' ? { allow: true } : { allow: false, reason: 'no' } });
或设置 permissionMode 打开 create()数字 : acceptEdits (允许文件编辑),
plan (没有突变), bypassPermissions (一切运行——只有当你控制
快速和工作目录.
您自己的代理: 迅速、 客户端工具、 结构化输出
2.10.10(能力) sdk-session-spec-v1) (中文(简体) ).
const id = await session.create({
model: 'my-profile',
spec: {
systemPrompt: 'You are a city guide. Answer with one recommendation.',
tools: { allow: [] }, // no built-in Cteno tools
clientTools: [{
name: 'search_places',
description: 'Search places by keyword',
inputSchema: { type: 'object', properties: { keyword: { type: 'string' } }, required: ['keyword'] },
handler: async ({ keyword }) => mySearch(String(keyword)), // runs in YOUR process
}],
outputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] },
limits: { maxIterations: 10, maxToolCalls: 8, turnTimeoutMs: 60_000 },
},
});
const result = await session.run({ sessionId: id, prompt: 'Somewhere quiet for coffee?' });
console.log(result.output); // parsed structured result
留着 CtenoSession 在会话运行时打开:它为客户端工具服务.
重新连接后, 处理器与 serveClientTools(id, tools)。 。 。 .
| 光谱字段 | 页:1 |
|---|---|
systemPrompt | 字符串=替换(保持一个短的安全地板); { mode: 'append', text } 保持 Cteno 的提示 |
context | datetime (违约), language, (中文(简体) ), modelIdentity, (中文(简体) ), skills, (中文(简体) ), workspace, (中文(简体) ), extra: string[] |
tools.allow 编号 : deny | 内置和MCP工具; prefix* 模式 |
clientTools | • 64;名称 [A-Za-z0-9_-]; 扔出处理器成为工具错误, 模型可以重试 |
terminalTools, (中文(简体) ), requireTerminalTool | 第一个成功的终端呼叫结束 |
outputSchema | 添加 final_result· ; run() 返回其解析后输入为 output |
limits | 只能收紧守护进程默认值 |
history | ≤ 200 user编号 :assistant 从您自己的商店发送的消息, 只包含上下文 |
tenant | { tenantId, userId } ——隔离每个终端用户的工作目录,内存和配额 |
租户会话的对象是不信任的最终用户:他们的内置工具被封顶了,
写作仅限于每个用户的目录,每个租户的录取受到控制
与 tenantPolicy() 编号 : tenantStatus()。 。 。 .
钩子
const unsubscribe = await session.hooks.on('PreToolUse', 'shell', call => {
if (JSON.stringify(call.payload.tool_input ?? {}).includes('rm -rf')) return { decision: 'deny', reason: 'not here' };
});
原始方法调用和稳定性
没有包裹的任何东西都可以被守护进程自己的方法名所达到(机器代号) 为您添加范围 :
await session.call('get-session-trace', { sessionId: id });
方法 STABLE_METHODS (单位:千美元)@cteno/sdk/method-tiers跟着铸币局 其他人则
守护进程内部 : call() 仍然工作,但警告一次;通过 { quiet: true } 当
依赖是故意的.
守护进程和连接
CtenoSession.open() 附加到 SDK 自己的守护进程( 每个用户和实例一个)
root, 默认 ~/Library/Application Support/cteno-sdk, (中文(简体) ), ~/.local/share/cteno-sdk, (中文(简体) ),
%LOCALAPPDATA%\cteno-sdk; 覆盖到 CTENO_SDK_HOME 或者说 open({ daemon: { home } })(中文(简体) )
如果需要,则开始。 它和同一台机上的 Cteno 桌面应用程序是分开的
绝不连结,除非你们成功 socketPath。守护进程继续运行
您的流程退出; stopDaemon() 从 @cteno/sdk/daemon 别闹了.
连接是守护进程的所有者套接字——一种模式 0600 Unix 套接字, 或一个
在Windows上,每个根被命名为管. 您的OS 用户是证书; 没有符号 .
入境点
| 导入 | 什麽 |
|---|---|
@cteno/sdk/core | query, (中文(简体) ), CtenoSession键 |
@cteno/sdk | Transport 接口, SdkError最小 CtenoClient |
@cteno/sdk/node | 原始 Unix- socket / 命名管传输( 明确路径) |
@cteno/sdk/daemon | ensureDaemon, (中文(简体) ), stopDaemon, (中文(简体) ), instanceLayout: 捆绑的守护进程 |
@cteno/sdk/discover | 找到 Cteno app 的守护进程套接字( 从未被 open()(中文(简体) ) |
@cteno/sdk/socketio | 用于被注入、已经认证的套接字的适配器。 IO 客户端 |
@cteno/sdk/method-tiers | 稳定/内部方法分类 |
许可证
麻省理工学院. 守护进程二进制 @cteno/sdk-<platform> 非麻省理工学院;见
LICENSE.daemon 内文件.