Skip to content

Commit

Permalink
Typescript support (entry level only) (#49)
Browse files Browse the repository at this point in the history
Attempt to fix issue #41 [Enhance Public AgenticJS API TypeScript](#41)

- Added types for relevant entry API
- Missing type for unknown context (WIP)
- Added "test:types" script for testing typescript validation
- Added package type: module
  • Loading branch information
darielnoel authored Aug 30, 2024
2 parents 95dc250 + 2ee8981 commit ed141b2
Show file tree
Hide file tree
Showing 19 changed files with 4,126 additions and 859 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ out/
build
dist


# Debug
npm-debug.log*
yarn-debug.log*
Expand Down
28 changes: 14 additions & 14 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module.exports = {
transform: {
"^.+\\.[t|j]sx?$": "babel-jest"
},
moduleNameMapper: {
'^agenticjs$': '<rootDir>/dist/bundle.cjs.js'
},
testTimeout: 300000, // Sets global timeout to 10 seconds for all tests
testEnvironment: 'node', // Use Node.js environment for executing tests,
verbose: true, // Make Jest more verbose
silent: false, // Ensure Jest is not silent (though this is not directly related to console.log output)
// testMatch: [
// "**/tests/e2e/exampl/**/*.js"
// ], // Run tests only in the specific directory
};
transform: {
"^.+\\.[t|j]sx?$": "babel-jest"
},
moduleNameMapper: {
'^agenticjs$': '<rootDir>/dist/bundle.cjs'
},
testTimeout: 300000, // Sets global timeout to 10 seconds for all tests
testEnvironment: 'node', // Use Node.js environment for executing tests,
verbose: true, // Make Jest more verbose
silent: false, // Ensure Jest is not silent (though this is not directly related to console.log output)
// testMatch: [
// "**/tests/e2e/exampl/**/*.js"
// ], // Run tests only in the specific directory
};
2,896 changes: 2,138 additions & 758 deletions package-lock.json

Large diffs are not rendered by default.

31 changes: 25 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@
"name": "agenticjs",
"version": "0.1.0",
"description": "AI Multi-Agent library for Javascript Developers.",
"main": "dist/bundle.cjs.js",
"module": "dist/bundle.esm.js",
"unpkg": "dist/bundle.umd.js",
"types": "types/index.d.ts",
"main": "./dist/bundle.cjs",
"types": "./dist/bundle.d.ts",
"module": "./dist/bundle.mjs",
"unpkg": "./dist/bundle.js",
"exports": {
".": {
"import": {
"types": "./dist/bundle.d.ts",
"default": "./dist/bundle.mjs"
},
"require": {
"types": "./dist/bundle.d.ts",
"default": "./dist/bundle.cjs"
}
}
},
"scripts": {
"build": "npx rollup -c",
"build:test": "NODE_ENV=development TEST_ENV=mocked-llm-apis npx rollup -c",
Expand All @@ -18,6 +30,7 @@
"test:e2e": "TEST_ENV=real-llm-apis jest --testPathPattern='tests/e2e'",
"test:unit": "jest --testPathPattern='tests/unit' --watch",
"test:unit:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --verbose --testPathPattern='tests/unit'",
"test:types": "npx tsc",
"play:react": "cd playground/react && npm run dev",
"play:sb": "cd playground/react && npm run storybook",
"play:node": "cd playground/nodejs && node index.js",
Expand Down Expand Up @@ -70,14 +83,20 @@
"@rollup/plugin-commonjs": "26.0.1",
"@rollup/plugin-node-resolve": "15.2.3",
"@rollup/plugin-replace": "5.0.7",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"@types/init-package-json": "^1.10.3",
"babel-jest": "^29.7.0",
"dotenv": "16.4.5",
"eslint": "7.32.0",
"init-package-json": "^6.0.3",
"jest": "29.7.0",
"prettier": "2.3.2",
"rollup": "4.21.1",
"rollup-plugin-peer-deps-external": "2.2.4",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2"
"rollup-plugin-dts": "6.1.1",
"tslib": "^2.7.0",
"typescript": "^5.5.4"
},
"engines": {
"node": ">=12.0.0"
Expand Down
55 changes: 55 additions & 0 deletions playground/nodejs-ts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# AgenticJS - NodeJS Typescript Example

### Getting started

To begin using agenticjs using typescript support.

1. Install the agenticjs library like normal.

`npm install agenticjs`

2. Install typescript as a dev depedency.

`npm install typescript --save-dev`

(Optional) You may create a custom tsconfig.json file if needed.
A basic configuration would look something like this:-

```json
{
"compilerOptions": {
"noEmit": true,
"strict": true,
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"skipLibCheck": true
},
"exclude": ["node_modules"]
}
```

3. And now you can start using agenticjs with full typescript support.
Main classes are typed and can be called directly from the library - `Agent`, `Task` and `Type`.

`import { Agent, Task, Team } from "agenticjs";`

For any specific types, can call them like below:-

`import type { IAgentParams, ITaskParams } from "agenticjs";`

You can check the index.ts as a good reference to get started.

### Development

> NOTE: Make sure your local typed package is built. (Use `npm run build` in the root folder to build the package if haven't already)
For testing the playground example, setup as follows:-

1. Install all dependencies

`npm i`

2. Run the example!

`npm run start`
136 changes: 136 additions & 0 deletions playground/nodejs-ts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Assuming agenticjs is a local module or a placeholder for demonstration purposes
// This file is now a typescript file and all the types are included in the module
import { Agent, Task, Team } from "agenticjs";
import type { IAgentParams, ITaskParams } from "agenticjs";
import * as dotenv from "dotenv";

dotenv.config({ path: "./.env.local" });

const main = async () => {
// ╔══════════════════════════════════════════════════════╗
// ║ How to Use AgenticJS: ║
// ║ 1. Define your Agents with specific roles and goals ║
// ║ 2. Define the Tasks each Agent will perform ║
// ║ 3. Create the Team and assign Agents and their Tasks ║
// ║ 4. Start the Team to execute the defined tasks ║
// ╚══════════════════════════════════════════════════════╝

// ──── Agents ────────────────────────────────────────────
// ─ Agents are autonomous entities designed to perform
// ─ specific roles and achieve goals based on the
// ─ tasks assigned to them.
// ────────────────────────────────────────────────────────

// We create an list of different agents based on our needs.
const AgentParams: Record<string, IAgentParams> = {
profileAnalyst: {
name: "Ivy",
role: "Profile Analyst",
goal: "Extract structured information from conversational user input.",
background: "Data Processor",
tools: [], // Tools are omitted for now
},
formatter: {
name: "Formy",
role: "Formatter",
goal: "Format structured information into a professional resume.",
background: "Document Formatter",
tools: [],
},
reviewer: {
name: "Revy",
role: "Reviewer",
goal: "Review and polish the final resume.",
background: "Quality Assurance Specialist",
tools: [],
},
};

// Now we can create a new agent class instance using each of the agent params
const profileAnalyst: Agent = new Agent(AgentParams.profileAnalyst);
const formatter: Agent = new Agent(AgentParams.formatter);
const reviewer: Agent = new Agent(AgentParams.reviewer);

// ──── Tasks ─────────────────────────────────────────────
// ─ Tasks define the specific actions each agent must
// ─ take, their expected outputs, and mark critical
// ─ outputs as deliverables if they are the final
// ─ products.
// ────────────────────────────────────────────────────────

// We create a list of different tasks that we would like to perform
const taskParams: Record<string, ITaskParams> = {
processing: {
title: "Process User Input",
description: `Extract relevant details such as name, experience, skills, and job history from the user's 'aboutMe' input.
aboutMe: {aboutMe}`,
expectedOutput: "Structured data ready for formatting.",
agent: profileAnalyst,
},
formatting: {
title: "Format Resume",
description: `Use the extracted information to create a clean, professional resume layout tailored for a JavaScript Developer.`,
expectedOutput: "A well-formatted resume in PDF format.",
agent: formatter,
},
review: {
title: "Review Resume",
description: `Ensure the resume is error-free, engaging, and meets professional standards.`,
expectedOutput:
"A polished, final resume ready for job applications. Please do not give any feedback on the resume. Just the final resume.",
agent: reviewer,
},
};

// Now we can create a new task class instance using each of the task params
const processingTask: Task = new Task(taskParams.processing);
const formattingTask: Task = new Task(taskParams.formatting);
const reviewTask: Task = new Task(taskParams.review);

// ──── Team ────────────────────────────────────────────
// ─ The Team coordinates the agents and their tasks.
// ─ It starts with an initial input and manages the
// ─ flow of information between tasks.
// ──────────────────────────────────────────────────────

const team: Team = new Team({
name: "Resume Creation Team",
agents: [profileAnalyst, formatter, reviewer],
tasks: [processingTask, formattingTask, reviewTask],
inputs: {
aboutMe:
"My name is Will, I have been a Javascript Developer for 3 years. I know React, NextJS, and REDUX. My latest job was as a Junior Developer at Disney creating UIs for the main landing page.",
}, // Initial input for the first task
env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY },
});

// ──── Listening to Changes────────────────────────────────────────────
//
// Listening to changes in the team's state is crucial for dynamic updates.
// Yup...AgenticJS utilizes a store similar to Redux for state management.
//
// You can subscribe to specific fields or any field on the store.
//──────────────────────────────────────────────────────────────────────

const unsubscribe = team.subscribeToChanges(
(updatedFields) => {
console.log("Workflow Status Updated:", updatedFields);
},
["teamWorkflowStatus"]
);

// ──── Start Team Workflow ───────────────────────────────────────
//
// Begins the predefined team process, producing the final result.
// We unsubscribe from the store after we have completed the process.
//─────────────────────────────────────────────────────────────────
const result = await team.start();
console.log("Final Output:", result);
unsubscribe();
};

console.log("Starting AgenticJS Workflow...");

main();

console.log("AgenticJS Workflow Completed.");
Loading

0 comments on commit ed141b2

Please sign in to comment.