@arki-moe/agent-ts 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,11 +1,13 @@
1
- # agent.ts
1
+ # agent-ts
2
+
3
+ [![npm](https://img.shields.io/npm/v/@arki-moe/agent-ts.svg)](https://www.npmjs.com/package/@arki-moe/agent-ts) [![npm](https://img.shields.io/npm/dm/@arki-moe/agent-ts.svg)](https://www.npmjs.com/package/@arki-moe/agent-ts)
2
4
 
3
5
  Minimal Agent library, zero dependencies
4
6
 
5
7
  ## Usage Example
6
8
 
7
9
  ```ts
8
- import { Agent, Role, type Tool } from "agent-ts";
10
+ import { Agent, Role, type Tool } from "@arki-moe/agent-ts";
9
11
 
10
12
  const getTimeTool: Tool = {
11
13
  name: "get_time",
@@ -33,6 +35,22 @@ console.log(msgs2);
33
35
  console.log(agent.context);
34
36
  ```
35
37
 
38
+ ## OpenRouter
39
+
40
+ ```ts
41
+ import { Agent, Role } from "@arki-moe/agent-ts";
42
+
43
+ const agent = new Agent("openrouter", {
44
+ apiKey: "or-...",
45
+ model: "gpt-5-nano",
46
+ httpReferer: "https://your-site.example", // optional
47
+ title: "Your App", // optional
48
+ });
49
+
50
+ const msgs = await agent.step({ role: Role.User, content: "Hello" });
51
+ console.log(msgs);
52
+ ```
53
+
36
54
  ## API
37
55
 
38
56
  - `Agent(adapterName, config)` - Create Agent, config contains `apiKey`, `model`, `system` (optional), etc.
@@ -40,3 +58,11 @@ console.log(agent.context);
40
58
  - `agent.registerTool(tool)` - Register tool
41
59
  - `agent.step(message)` - Call model once, returns new `Message[]`
42
60
  - `agent.run(message)` - Execute tool chain automatically, returns all new `Message[]`
61
+
62
+ ## Scripts
63
+
64
+ | Command | Description |
65
+ |---------|--------------|
66
+ | `pnpm run build` | Compile TypeScript to `dist/` |
67
+ | `pnpm run check` | Type check (no emit) |
68
+ | `pnpm test` | Run tests (API key read from env var for real API tests) |
@@ -0,0 +1,2 @@
1
+ import { type Message, type Tool } from "../types";
2
+ export declare function openrouterAdapter(config: Record<string, unknown>, context: Message[], tools: Tool[]): Promise<Message[]>;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.openrouterAdapter = openrouterAdapter;
4
+ const types_1 = require("../types");
5
+ const ROLE_TO_OPENROUTER = {
6
+ [types_1.Role.System]: "system",
7
+ [types_1.Role.User]: "user",
8
+ [types_1.Role.Ai]: "assistant",
9
+ };
10
+ function toOpenRouterMessages(context) {
11
+ return context.reduce((out, m) => {
12
+ if (m.role === types_1.Role.System || m.role === types_1.Role.User || m.role === types_1.Role.Ai)
13
+ return [...out, { role: ROLE_TO_OPENROUTER[m.role], content: m.content }];
14
+ if (m.role === types_1.Role.ToolResult)
15
+ return [...out, { role: "tool", content: m.content, tool_call_id: m.callId }];
16
+ if (m.role === types_1.Role.ToolCall) {
17
+ const tc = { id: m.callId, type: "function", function: { name: m.toolName, arguments: m.argsText ?? "{}" } };
18
+ const last = out[out.length - 1];
19
+ if (last?.tool_calls) {
20
+ last.tool_calls.push(tc);
21
+ return out;
22
+ }
23
+ return [...out, { role: "assistant", tool_calls: [tc] }];
24
+ }
25
+ return out;
26
+ }, []);
27
+ }
28
+ async function openrouterAdapter(config, context, tools) {
29
+ const baseUrl = config.baseUrl ?? "https://openrouter.ai/api/v1";
30
+ const apiKey = config.apiKey ?? "";
31
+ const model = config.model ?? "gpt-5-nano";
32
+ const httpReferer = config.httpReferer;
33
+ const title = config.title;
34
+ if (!apiKey)
35
+ throw new Error("OpenRouter adapter requires apiKey in config");
36
+ const contextMessages = toOpenRouterMessages(context);
37
+ const systemContent = config.system;
38
+ const messages = systemContent
39
+ ? [{ role: "system", content: systemContent }, ...contextMessages]
40
+ : contextMessages;
41
+ const body = {
42
+ model,
43
+ messages,
44
+ tools: tools.length ? tools.map((t) => ({ type: "function", function: { name: t.name, description: t.description, parameters: t.parameters ?? {} } })) : undefined,
45
+ tool_choice: tools.length ? "auto" : undefined,
46
+ };
47
+ const headers = {
48
+ "Content-Type": "application/json",
49
+ Authorization: `Bearer ${apiKey}`,
50
+ };
51
+ if (httpReferer)
52
+ headers["HTTP-Referer"] = httpReferer;
53
+ if (title)
54
+ headers["X-Title"] = title;
55
+ const res = await fetch(`${baseUrl.replace(/\/$/, "")}/chat/completions`, {
56
+ method: "POST",
57
+ headers,
58
+ body: JSON.stringify(body),
59
+ });
60
+ const text = await res.text();
61
+ if (!res.ok) {
62
+ let errMsg = `OpenRouter API HTTP ${res.status}`;
63
+ try {
64
+ const parsed = JSON.parse(text);
65
+ if (parsed?.error?.message)
66
+ errMsg = parsed.error.message;
67
+ }
68
+ catch {
69
+ if (text)
70
+ errMsg += `: ${text.slice(0, 200)}`;
71
+ }
72
+ throw new Error(errMsg);
73
+ }
74
+ let data;
75
+ try {
76
+ data = JSON.parse(text);
77
+ }
78
+ catch {
79
+ throw new Error(`OpenRouter API returned invalid JSON: ${text.slice(0, 200)}`);
80
+ }
81
+ if (data.error)
82
+ throw new Error(`OpenRouter API error: ${data.error.message}`);
83
+ const msg = data.choices?.[0]?.message;
84
+ if (!msg)
85
+ throw new Error("OpenRouter API returned empty response");
86
+ if (msg.tool_calls?.length) {
87
+ return msg.tool_calls.map((tc) => ({
88
+ role: types_1.Role.ToolCall,
89
+ toolName: tc.function.name,
90
+ callId: tc.id,
91
+ argsText: tc.function.arguments ?? "{}",
92
+ }));
93
+ }
94
+ return [{ role: types_1.Role.Ai, content: msg.content ?? "" }];
95
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Context, Message, Tool } from "./types";
2
2
  export { openaiAdapter } from "./adapter/openai";
3
+ export { openrouterAdapter } from "./adapter/openrouter";
3
4
  export type { Adapter, Context, Message, Tool } from "./types";
4
5
  export { Role } from "./types";
5
6
  export declare class Agent {
package/dist/index.js CHANGED
@@ -1,14 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Agent = exports.Role = exports.openaiAdapter = void 0;
3
+ exports.Agent = exports.Role = exports.openrouterAdapter = exports.openaiAdapter = void 0;
4
4
  const openai_1 = require("./adapter/openai");
5
+ const openrouter_1 = require("./adapter/openrouter");
5
6
  const types_1 = require("./types");
6
7
  var openai_2 = require("./adapter/openai");
7
8
  Object.defineProperty(exports, "openaiAdapter", { enumerable: true, get: function () { return openai_2.openaiAdapter; } });
9
+ var openrouter_2 = require("./adapter/openrouter");
10
+ Object.defineProperty(exports, "openrouterAdapter", { enumerable: true, get: function () { return openrouter_2.openrouterAdapter; } });
8
11
  var types_2 = require("./types");
9
12
  Object.defineProperty(exports, "Role", { enumerable: true, get: function () { return types_2.Role; } });
10
13
  const adapters = {
11
14
  openai: openai_1.openaiAdapter,
15
+ openrouter: openrouter_1.openrouterAdapter,
12
16
  };
13
17
  class Agent {
14
18
  constructor(adapterName, config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arki-moe/agent-ts",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Minimal Agent library, zero dependencies",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",