初始化提交
Some checks failed
CI / Check / macos-latest (push) Has been cancelled
CI / Check / ubuntu-latest (push) Has been cancelled
CI / Check / windows-latest (push) Has been cancelled
CI / Test / macos-latest (push) Has been cancelled
CI / Test / ubuntu-latest (push) Has been cancelled
CI / Test / windows-latest (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Security Audit (push) Has been cancelled
CI / Secrets Scan (push) Has been cancelled
CI / Install Script Smoke Test (push) Has been cancelled

This commit is contained in:
iven
2026-03-01 16:24:24 +08:00
commit 92e5def702
492 changed files with 211343 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
/**
* Basic example — create an agent and chat with it.
*
* Usage:
* node basic.js
*/
const { OpenFang } = require("../index");
async function main() {
const client = new OpenFang("http://localhost:3000");
// Check server health
const health = await client.health();
console.log("Server:", health);
// List existing agents
const agents = await client.agents.list();
console.log("Agents:", agents.length);
// Create a new agent from the "assistant" template
const agent = await client.agents.create({ template: "assistant" });
console.log("Created agent:", agent.id);
// Send a message and get the full response
const reply = await client.agents.message(agent.id, "What can you help me with?");
console.log("Reply:", reply);
// Clean up
await client.agents.delete(agent.id);
console.log("Agent deleted.");
}
main().catch(console.error);

View File

@@ -0,0 +1,33 @@
/**
* Streaming example — stream agent responses token by token.
*
* Usage:
* node streaming.js
*/
const { OpenFang } = require("../index");
async function main() {
const client = new OpenFang("http://localhost:3000");
// Create an agent
const agent = await client.agents.create({ template: "assistant" });
console.log("Agent:", agent.id);
// Stream the response
console.log("\n--- Streaming response ---");
for await (const event of client.agents.stream(agent.id, "Tell me a short story about a robot.")) {
if (event.type === "text_delta" && event.delta) {
process.stdout.write(event.delta);
} else if (event.type === "tool_call") {
console.log("\n[Tool call:", event.tool, "]");
} else if (event.type === "done") {
console.log("\n--- Done ---");
}
}
// Clean up
await client.agents.delete(agent.id);
}
main().catch(console.error);

140
sdk/javascript/index.d.ts vendored Normal file
View File

@@ -0,0 +1,140 @@
export class OpenFangError extends Error {
status: number;
body: string;
constructor(message: string, status: number, body: string);
}
export interface AgentCreateOpts {
template?: string;
name?: string;
model?: string;
[key: string]: unknown;
}
export interface MessageOpts {
attachments?: string[];
[key: string]: unknown;
}
export interface StreamEvent {
type?: string;
delta?: string;
raw?: string;
[key: string]: unknown;
}
export class OpenFang {
baseUrl: string;
agents: AgentResource;
sessions: SessionResource;
workflows: WorkflowResource;
skills: SkillResource;
channels: ChannelResource;
tools: ToolResource;
models: ModelResource;
providers: ProviderResource;
memory: MemoryResource;
triggers: TriggerResource;
schedules: ScheduleResource;
constructor(baseUrl: string, opts?: { headers?: Record<string, string> });
health(): Promise<unknown>;
healthDetail(): Promise<unknown>;
status(): Promise<unknown>;
version(): Promise<unknown>;
metrics(): Promise<string>;
usage(): Promise<unknown>;
config(): Promise<unknown>;
}
export class AgentResource {
list(): Promise<unknown[]>;
get(id: string): Promise<unknown>;
create(opts: AgentCreateOpts): Promise<{ id: string; [key: string]: unknown }>;
delete(id: string): Promise<unknown>;
stop(id: string): Promise<unknown>;
clone(id: string): Promise<unknown>;
update(id: string, data: Record<string, unknown>): Promise<unknown>;
setMode(id: string, mode: string): Promise<unknown>;
setModel(id: string, model: string): Promise<unknown>;
message(id: string, text: string, opts?: MessageOpts): Promise<unknown>;
stream(id: string, text: string, opts?: MessageOpts): AsyncGenerator<StreamEvent>;
session(id: string): Promise<unknown>;
resetSession(id: string): Promise<unknown>;
compactSession(id: string): Promise<unknown>;
listSessions(id: string): Promise<unknown[]>;
createSession(id: string, label?: string): Promise<unknown>;
switchSession(id: string, sessionId: string): Promise<unknown>;
getSkills(id: string): Promise<unknown>;
setSkills(id: string, skills: unknown): Promise<unknown>;
upload(id: string, file: Blob | File, filename: string): Promise<unknown>;
setIdentity(id: string, identity: Record<string, unknown>): Promise<unknown>;
patchConfig(id: string, config: Record<string, unknown>): Promise<unknown>;
}
export class SessionResource {
list(): Promise<unknown[]>;
delete(id: string): Promise<unknown>;
setLabel(id: string, label: string): Promise<unknown>;
}
export class WorkflowResource {
list(): Promise<unknown[]>;
create(workflow: Record<string, unknown>): Promise<unknown>;
run(id: string, input?: Record<string, unknown>): Promise<unknown>;
runs(id: string): Promise<unknown[]>;
}
export class SkillResource {
list(): Promise<unknown[]>;
install(skill: Record<string, unknown>): Promise<unknown>;
uninstall(skill: Record<string, unknown>): Promise<unknown>;
search(query: string): Promise<unknown[]>;
}
export class ChannelResource {
list(): Promise<unknown[]>;
configure(name: string, config: Record<string, unknown>): Promise<unknown>;
remove(name: string): Promise<unknown>;
test(name: string): Promise<unknown>;
}
export class ToolResource {
list(): Promise<unknown[]>;
}
export class ModelResource {
list(): Promise<unknown[]>;
get(id: string): Promise<unknown>;
aliases(): Promise<unknown>;
}
export class ProviderResource {
list(): Promise<unknown[]>;
setKey(name: string, key: string): Promise<unknown>;
deleteKey(name: string): Promise<unknown>;
test(name: string): Promise<unknown>;
}
export class MemoryResource {
getAll(agentId: string): Promise<Record<string, unknown>>;
get(agentId: string, key: string): Promise<unknown>;
set(agentId: string, key: string, value: unknown): Promise<unknown>;
delete(agentId: string, key: string): Promise<unknown>;
}
export class TriggerResource {
list(): Promise<unknown[]>;
create(trigger: Record<string, unknown>): Promise<unknown>;
update(id: string, trigger: Record<string, unknown>): Promise<unknown>;
delete(id: string): Promise<unknown>;
}
export class ScheduleResource {
list(): Promise<unknown[]>;
create(schedule: Record<string, unknown>): Promise<unknown>;
update(id: string, schedule: Record<string, unknown>): Promise<unknown>;
delete(id: string): Promise<unknown>;
run(id: string): Promise<unknown>;
}

479
sdk/javascript/index.js Normal file
View File

@@ -0,0 +1,479 @@
/**
* @openfang/sdk — Official JavaScript client for the OpenFang Agent OS REST API.
*
* Usage:
* const { OpenFang } = require("@openfang/sdk");
* const client = new OpenFang("http://localhost:3000");
*
* const agent = await client.agents.create({ template: "assistant" });
* const reply = await client.agents.message(agent.id, "Hello!");
* console.log(reply);
*
* // Streaming:
* for await (const event of client.agents.stream(agent.id, "Tell me a joke")) {
* process.stdout.write(event.delta || "");
* }
*/
"use strict";
class OpenFangError extends Error {
constructor(message, status, body) {
super(message);
this.name = "OpenFangError";
this.status = status;
this.body = body;
}
}
class OpenFang {
/**
* @param {string} baseUrl - OpenFang server URL (e.g. "http://localhost:3000")
* @param {object} [opts]
* @param {Record<string, string>} [opts.headers] - Extra headers for every request
*/
constructor(baseUrl, opts) {
this.baseUrl = baseUrl.replace(/\/+$/, "");
this._headers = Object.assign({ "Content-Type": "application/json" }, (opts && opts.headers) || {});
this.agents = new AgentResource(this);
this.sessions = new SessionResource(this);
this.workflows = new WorkflowResource(this);
this.skills = new SkillResource(this);
this.channels = new ChannelResource(this);
this.tools = new ToolResource(this);
this.models = new ModelResource(this);
this.providers = new ProviderResource(this);
this.memory = new MemoryResource(this);
this.triggers = new TriggerResource(this);
this.schedules = new ScheduleResource(this);
}
/** Low-level fetch wrapper. */
async _request(method, path, body) {
var url = this.baseUrl + path;
var init = { method: method, headers: Object.assign({}, this._headers) };
if (body !== undefined) {
init.body = JSON.stringify(body);
}
var res = await fetch(url, init);
if (!res.ok) {
var text = await res.text().catch(function () { return ""; });
throw new OpenFangError("HTTP " + res.status + ": " + text, res.status, text);
}
var ct = res.headers.get("content-type") || "";
if (ct.includes("application/json")) {
return res.json();
}
return res.text();
}
/** Low-level SSE streaming. Returns an async iterator of parsed events. */
async *_stream(method, path, body) {
var url = this.baseUrl + path;
var headers = Object.assign({}, this._headers, { Accept: "text/event-stream" });
var init = { method: method, headers: headers };
if (body !== undefined) {
init.body = JSON.stringify(body);
}
var res = await fetch(url, init);
if (!res.ok) {
var text = await res.text().catch(function () { return ""; });
throw new OpenFangError("HTTP " + res.status + ": " + text, res.status, text);
}
var reader = res.body.getReader();
var decoder = new TextDecoder();
var buffer = "";
while (true) {
var result = await reader.read();
if (result.done) break;
buffer += decoder.decode(result.value, { stream: true });
var lines = buffer.split("\n");
buffer = lines.pop() || "";
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
if (line.startsWith("data: ")) {
var data = line.slice(6);
if (data === "[DONE]") return;
try {
yield JSON.parse(data);
} catch (_) {
yield { raw: data };
}
}
}
}
}
/** Health check. */
async health() {
return this._request("GET", "/api/health");
}
/** Detailed health. */
async healthDetail() {
return this._request("GET", "/api/health/detail");
}
/** Server status. */
async status() {
return this._request("GET", "/api/status");
}
/** Server version. */
async version() {
return this._request("GET", "/api/version");
}
/** Prometheus metrics (text). */
async metrics() {
return this._request("GET", "/api/metrics");
}
/** Usage statistics. */
async usage() {
return this._request("GET", "/api/usage");
}
/** Config. */
async config() {
return this._request("GET", "/api/config");
}
}
// ── Agent Resource ──────────────────────────────────────────────
class AgentResource {
constructor(client) { this._c = client; }
/** List all agents. */
async list() {
return this._c._request("GET", "/api/agents");
}
/** Get agent by ID. */
async get(id) {
return this._c._request("GET", "/api/agents/" + id);
}
/** Create (spawn) a new agent.
* @param {object} opts - e.g. { template: "assistant", name: "My Agent" }
*/
async create(opts) {
return this._c._request("POST", "/api/agents", opts);
}
/** Delete (kill) an agent. */
async delete(id) {
return this._c._request("DELETE", "/api/agents/" + id);
}
/** Stop an agent. */
async stop(id) {
return this._c._request("POST", "/api/agents/" + id + "/stop");
}
/** Clone an agent. */
async clone(id) {
return this._c._request("POST", "/api/agents/" + id + "/clone");
}
/** Update agent. */
async update(id, data) {
return this._c._request("PUT", "/api/agents/" + id + "/update", data);
}
/** Set agent mode. */
async setMode(id, mode) {
return this._c._request("PUT", "/api/agents/" + id + "/mode", { mode: mode });
}
/** Set agent model. */
async setModel(id, model) {
return this._c._request("PUT", "/api/agents/" + id + "/model", { model: model });
}
/** Send a message and get the full response. */
async message(id, text, opts) {
var body = Object.assign({ message: text }, opts || {});
return this._c._request("POST", "/api/agents/" + id + "/message", body);
}
/** Send a message and stream the response (async iterator of SSE events).
* @example
* for await (const evt of client.agents.stream(id, "Hello")) {
* if (evt.type === "text_delta") process.stdout.write(evt.delta);
* }
*/
async *stream(id, text, opts) {
var body = Object.assign({ message: text }, opts || {});
yield* this._c._stream("POST", "/api/agents/" + id + "/message/stream", body);
}
/** Get agent session. */
async session(id) {
return this._c._request("GET", "/api/agents/" + id + "/session");
}
/** Reset agent session. */
async resetSession(id) {
return this._c._request("POST", "/api/agents/" + id + "/session/reset");
}
/** Compact session. */
async compactSession(id) {
return this._c._request("POST", "/api/agents/" + id + "/session/compact");
}
/** List sessions for an agent. */
async listSessions(id) {
return this._c._request("GET", "/api/agents/" + id + "/sessions");
}
/** Create a new session. */
async createSession(id, label) {
return this._c._request("POST", "/api/agents/" + id + "/sessions", { label: label });
}
/** Switch to a session. */
async switchSession(id, sessionId) {
return this._c._request("POST", "/api/agents/" + id + "/sessions/" + sessionId + "/switch");
}
/** Get agent skills. */
async getSkills(id) {
return this._c._request("GET", "/api/agents/" + id + "/skills");
}
/** Set agent skills. */
async setSkills(id, skills) {
return this._c._request("PUT", "/api/agents/" + id + "/skills", skills);
}
/** Upload a file to agent. */
async upload(id, file, filename) {
var url = this._c.baseUrl + "/api/agents/" + id + "/upload";
var form = new FormData();
form.append("file", file, filename);
var res = await fetch(url, { method: "POST", body: form });
if (!res.ok) throw new OpenFangError("Upload failed: " + res.status, res.status);
return res.json();
}
/** Update agent identity. */
async setIdentity(id, identity) {
return this._c._request("PATCH", "/api/agents/" + id + "/identity", identity);
}
/** Patch agent config. */
async patchConfig(id, config) {
return this._c._request("PATCH", "/api/agents/" + id + "/config", config);
}
}
// ── Session Resource ────────────────────────────────────────────
class SessionResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/sessions");
}
async delete(id) {
return this._c._request("DELETE", "/api/sessions/" + id);
}
async setLabel(id, label) {
return this._c._request("PUT", "/api/sessions/" + id + "/label", { label: label });
}
}
// ── Workflow Resource ───────────────────────────────────────────
class WorkflowResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/workflows");
}
async create(workflow) {
return this._c._request("POST", "/api/workflows", workflow);
}
async run(id, input) {
return this._c._request("POST", "/api/workflows/" + id + "/run", input);
}
async runs(id) {
return this._c._request("GET", "/api/workflows/" + id + "/runs");
}
}
// ── Skill Resource ──────────────────────────────────────────────
class SkillResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/skills");
}
async install(skill) {
return this._c._request("POST", "/api/skills/install", skill);
}
async uninstall(skill) {
return this._c._request("POST", "/api/skills/uninstall", skill);
}
async search(query) {
return this._c._request("GET", "/api/marketplace/search?q=" + encodeURIComponent(query));
}
}
// ── Channel Resource ────────────────────────────────────────────
class ChannelResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/channels");
}
async configure(name, config) {
return this._c._request("POST", "/api/channels/" + name + "/configure", config);
}
async remove(name) {
return this._c._request("DELETE", "/api/channels/" + name + "/configure");
}
async test(name) {
return this._c._request("POST", "/api/channels/" + name + "/test");
}
}
// ── Tool Resource ───────────────────────────────────────────────
class ToolResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/tools");
}
}
// ── Model Resource ──────────────────────────────────────────────
class ModelResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/models");
}
async get(id) {
return this._c._request("GET", "/api/models/" + id);
}
async aliases() {
return this._c._request("GET", "/api/models/aliases");
}
}
// ── Provider Resource ───────────────────────────────────────────
class ProviderResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/providers");
}
async setKey(name, key) {
return this._c._request("POST", "/api/providers/" + name + "/key", { key: key });
}
async deleteKey(name) {
return this._c._request("DELETE", "/api/providers/" + name + "/key");
}
async test(name) {
return this._c._request("POST", "/api/providers/" + name + "/test");
}
}
// ── Memory Resource ─────────────────────────────────────────────
class MemoryResource {
constructor(client) { this._c = client; }
async getAll(agentId) {
return this._c._request("GET", "/api/memory/agents/" + agentId + "/kv");
}
async get(agentId, key) {
return this._c._request("GET", "/api/memory/agents/" + agentId + "/kv/" + key);
}
async set(agentId, key, value) {
return this._c._request("PUT", "/api/memory/agents/" + agentId + "/kv/" + key, { value: value });
}
async delete(agentId, key) {
return this._c._request("DELETE", "/api/memory/agents/" + agentId + "/kv/" + key);
}
}
// ── Trigger Resource ────────────────────────────────────────────
class TriggerResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/triggers");
}
async create(trigger) {
return this._c._request("POST", "/api/triggers", trigger);
}
async update(id, trigger) {
return this._c._request("PUT", "/api/triggers/" + id, trigger);
}
async delete(id) {
return this._c._request("DELETE", "/api/triggers/" + id);
}
}
// ── Schedule Resource ───────────────────────────────────────────
class ScheduleResource {
constructor(client) { this._c = client; }
async list() {
return this._c._request("GET", "/api/schedules");
}
async create(schedule) {
return this._c._request("POST", "/api/schedules", schedule);
}
async update(id, schedule) {
return this._c._request("PUT", "/api/schedules/" + id, schedule);
}
async delete(id) {
return this._c._request("DELETE", "/api/schedules/" + id);
}
async run(id) {
return this._c._request("POST", "/api/schedules/" + id + "/run");
}
}
// ── Exports ─────────────────────────────────────────────────────
module.exports = { OpenFang: OpenFang, OpenFangError: OpenFangError };

View File

@@ -0,0 +1,17 @@
{
"name": "@openfang/sdk",
"version": "0.1.0",
"description": "Official JavaScript/TypeScript client for the OpenFang Agent OS REST API",
"main": "index.js",
"types": "index.d.ts",
"keywords": ["openfang", "agent", "ai", "llm", "sdk"],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/openfang/openfang"
},
"engines": {
"node": ">=18.0.0"
},
"files": ["index.js", "index.d.ts"]
}