跳转到内容

构建你的第一个 Clip

Clip 是使用 @pinixai/core 构建的 TypeScript 包。它定义命令,供 Agent(以及人类)通过 Hub 调用。

  1. 创建项目

    Terminal window
    mkdir my-clip && cd my-clip
    bun init -y
    bun add @pinixai/core
  2. 创建 clip.json

    {
    "name": "@yourscope/my-clip",
    "version": "0.1.0",
    "description": "My first Clip",
    "main": "src/index.ts"
    }
  3. 编写 Clip

    创建 src/index.ts

    import { Clip, command } from "@pinixai/core";
    const clip = new Clip({
    name: "@yourscope/my-clip",
    description: "My first Clip",
    });
    clip.command("hello", {
    description: "Say hello",
    input: {
    name: { type: "string", description: "Name to greet", required: true },
    },
    handler: async ({ input }) => {
    return { message: `Hello, ${input.name}!` };
    },
    });
    clip.run();
  4. 本地测试

    Terminal window
    # Install as a local Clip
    pinix hub add local/my-clip --path .
    # Invoke it
    pinix invoke my-clip hello --name "World"
    # → { "message": "Hello, World!" }
  5. 迭代

    编辑 src/index.ts,Runtime 会自动重启 Clip 进程。再次调用即可测试改动。

一个最小 Clip 项目:

my-clip/
├── clip.json # Package manifest
├── src/
│ └── index.ts # Entry point
├── package.json # Dependencies
└── web/ # Optional: Web UI
└── index.html
字段必填描述
name包标识符:@scope/name
versionSemver 版本
description这个 Clip 做什么
main相对于包根目录的入口点
dependenciesClip 到 Clip 的依赖(slots)
clip.command("list", {
description: "List all items",
handler: async () => {
const items = await db.getAll();
return { items, total: items.length };
},
});
clip.command("add", {
description: "Add a new item",
input: {
title: { type: "string", required: true },
priority: { type: "string", enum: ["low", "medium", "high"] },
},
handler: async ({ input }) => {
const item = await db.create(input);
return item;
},
});

你的 Clip 可以通过 Hub 调用其他 Clip:

import { invoke } from "@pinixai/core";
clip.command("research", {
description: "Research a topic using search and browser",
input: {
topic: { type: "string", required: true },
},
handler: async ({ input }) => {
// Call another Clip
const results = await invoke("google", "search", {
query: input.topic,
});
return { results };
},
});

invoke() 函数会把请求发送到 Hub,由 Hub 路由到目标 Clip。你的 Clip 不需要知道目标 Clip 在哪里运行。

如果你的 Clip 依赖其他 Clip(在 clip.jsondependencies 中声明),需要用 bind 命令将依赖指向具体的 Clip instance:

Terminal window
# 查看当前绑定
pinix hub bindings my-clip
# 绑定依赖:将 "browser" slot 绑定到 "browser" alias
pinix hub bind my-clip browser browser
# 解除绑定
pinix hub unbind my-clip browser
# 列出满足某个 slot 依赖的已安装 Clip
pinix hub bind my-clip browser --list

绑定信息存储在 Clip 侧(bindings.json),不在 Hub 中。

在你的 Clip 项目中创建一个包含 index.htmlweb/ 目录:

<!DOCTYPE html>
<html>
<head>
<title>My Clip</title>
<script type="module">
import { createClient } from "@pinixai/core/web";
const client = createClient();
// Use client.invoke() to call your Clip's commands
</script>
</head>
<body>
<!-- Your UI -->
</body>
</html>

Web UI 由 Hub 提供服务,可在 Console 中通过 /clips/<alias>/web 访问。