Skip to content

Feat/agentkit-typescript-implementation #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions hyperbolic_agentkit_TS/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
dist/
coverage/
28 changes: 28 additions & 0 deletions hyperbolic_agentkit_TS/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"env": {
"node": true,
"es2020": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"project": "./tsconfig.test.json"
},
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/explicit-function-return-type": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-unsafe-member-access": "error",
"@typescript-eslint/no-unsafe-call": "error",
"@typescript-eslint/no-unsafe-return": "error",
"no-console": ["error", { "allow": ["warn", "error"] }]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Tool } from "@langchain/core/tools";
import { HyperbolicTool } from "../tools/hyperbolic-tool";
import { HyperbolicAgentkitWrapper } from "../utils/hyperbolic-agentkit-wrapper";
import { HYPERBOLIC_ACTIONS, HyperbolicAction } from "../../src/actions";

/**
* Hyperbolic Platform Toolkit.
*
* Security Note: This toolkit contains tools that can read and modify
* the state of a service; e.g., by creating, deleting, or updating,
* reading underlying data.
*
* For example, this toolkit can be used to rent compute, check GPU status,
* and manage compute resources on Hyperbolic supported infrastructure.
*/
export class HyperbolicToolkit {
private readonly tools: Tool[];

constructor(private readonly hyperbolicAgentkitWrapper: HyperbolicAgentkitWrapper) {
this.tools = this.loadTools();
}

/**
* Get the tools in the toolkit.
* @returns Array of tools
*/
getTools(): Tool[] {
return this.tools;
}

/**
* Create a toolkit from a HyperbolicAgentkitWrapper instance.
* @param hyperbolicAgentkitWrapper The wrapper instance
* @returns HyperbolicToolkit instance
*/
static fromHyperbolicAgentkitWrapper(
hyperbolicAgentkitWrapper: HyperbolicAgentkitWrapper
): HyperbolicToolkit {
return new HyperbolicToolkit(hyperbolicAgentkitWrapper);
}

/**
* Load all available Hyperbolic tools.
* @returns Array of Tool instances
*/
private loadTools(): Tool[] {
return Object.entries(HYPERBOLIC_ACTIONS).map(([name, action]: [string, HyperbolicAction]) => {
return new HyperbolicTool(
this.hyperbolicAgentkitWrapper,
name,
action.description || "",
action.execute.bind(action),
action.schema
);
});
}
}
3 changes: 3 additions & 0 deletions hyperbolic_agentkit_TS/langchain/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { HyperbolicTool } from "./tools/hyperbolic-tool";
export { HyperbolicToolkit } from "./agent-toolkits/hyperbolic-toolkit";
export { HyperbolicAgentkitWrapper } from "./utils/hyperbolic-agentkit-wrapper";
111 changes: 111 additions & 0 deletions hyperbolic_agentkit_TS/langchain/tools/hyperbolic-tool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { Tool, ToolParams } from "@langchain/core/tools";
import { z } from "zod";
import { CallbackManagerForToolRun } from "@langchain/core/callbacks/manager";
import { RunnableConfig } from "@langchain/core/runnables";
import { HyperbolicAgentkitWrapper } from "../utils/hyperbolic-agentkit-wrapper";

/**
* Exception raised when a command execution times out.
*/
class CommandTimeout extends Error {
constructor(message: string) {
super(message);
this.name = "CommandTimeout";
}
}

type ToolInputSchema = z.ZodEffects<
z.ZodObject<
{ input: z.ZodOptional<z.ZodString> },
"strip",
z.ZodTypeAny,
{ input?: string },
{ input?: string }
>,
string | undefined,
{ input?: string }
>;

const DEFAULT_SCHEMA: ToolInputSchema = z
.object({
input: z.string().optional().describe("The input to the tool"),
})
.strip()
.transform((obj) => obj.input);

const createToolSchema = (schema: z.ZodObject<any>): ToolInputSchema => {
return schema.strip().transform((obj) => obj.input) as ToolInputSchema;
};

interface HyperbolicToolParams extends ToolParams {
schema?: z.ZodObject<any>;
}

/**
* Tool for interacting with the Hyperbolic SDK.
*/
export class HyperbolicTool extends Tool {
public name: string;
public description: string;
private readonly hyperbolicAgentkitWrapper: HyperbolicAgentkitWrapper;
private readonly func: (...args: any[]) => Promise<string>;
private readonly timeoutSeconds = 10;
private readonly customSchema?: z.ZodObject<any>;

constructor(
hyperbolicAgentkitWrapper: HyperbolicAgentkitWrapper,
toolName: string,
toolDescription: string,
func: (...args: any[]) => Promise<string>,
schema?: z.ZodObject<any>
) {
const params: HyperbolicToolParams = {
verbose: true
};
super(params);

this.name = toolName;
this.description = toolDescription;
this.hyperbolicAgentkitWrapper = hyperbolicAgentkitWrapper;
this.func = func;
this.customSchema = schema;

this.schema = schema ? createToolSchema(schema) : DEFAULT_SCHEMA;
}

/** @ignore */
protected async _call(
args: Record<string, any>,
runManager?: CallbackManagerForToolRun,
config?: RunnableConfig
): Promise<string> {
let parsedInputArgs: Record<string, any>;
if (this.customSchema) {
parsedInputArgs = this.customSchema.parse(args);
} else {
const input = args.input || "";
parsedInputArgs = { instructions: input };
}

return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
reject(
new CommandTimeout(
`Command timed out after ${this.timeoutSeconds} seconds`
)
);
}, this.timeoutSeconds * 1000);

this.hyperbolicAgentkitWrapper
.runAction(this.func, parsedInputArgs)
.then((result) => {
clearTimeout(timeoutId);
resolve(result);
})
.catch((error) => {
clearTimeout(timeoutId);
reject(error);
});
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { getEnvironmentVariable } from "@langchain/core/utils/env";

/**
* Wrapper for Hyperbolic Agentkit Core.
*/
export class HyperbolicAgentkitWrapper {
hyperbolicApiKey: string;

constructor(fields?: { hyperbolicApiKey?: string }) {
const apiKey = fields?.hyperbolicApiKey ??
getEnvironmentVariable("HYPERBOLIC_API_KEY");

if (!apiKey) {
throw new Error(
"Hyperbolic API Key not found. Please set HYPERBOLIC_API_KEY environment variable or pass it in the constructor."
);
}

this.hyperbolicApiKey = apiKey;
}

/**
* Run a Hyperbolic Action.
* @param func The function to run
* @param args The arguments to pass to the function
* @returns The result of the function call
*/
async runAction(
func: (...args: any[]) => Promise<string>,
args: Record<string, any>
): Promise<string> {
return await func(args);
}
}
40 changes: 40 additions & 0 deletions hyperbolic_agentkit_TS/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@elizaos/hyperbolic-agentkit-ts",
"version": "1.0.0",
"description": "TypeScript version of Hyperbolic Agent Kit",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"private": true,
"scripts": {
"build": "tsc",
"lint": "eslint 'src/**/*.{js,ts}'",
"lint:fix": "eslint 'src/**/*.{js,ts}' --fix",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"prepare": "npm run build"
},
"dependencies": {
"axios": "^1.6.5",
"ssh2": "^1.15.0",
"zod": "^3.22.4",
"@coinbase/coinbase-sdk": "^0.13.0",
"viem": "^2.0.0",
"decimal.js": "^10.4.3",
"@langchain/core": "^0.1.15",
"langchain": "^0.1.9"
},
"devDependencies": {
"@types/node": "^20.11.5",
"@types/ssh2": "^1.11.18",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"@vitest/coverage-v8": "^1.2.1",
"eslint": "^8.56.0",
"typescript": "^5.3.3",
"vitest": "^1.2.1"
},
"engines": {
"node": ">=18.0.0"
}
}
Loading