Skip to content

Commit

Permalink
Merge branch 'develop' into fix/twitter-profile-cache-1638
Browse files Browse the repository at this point in the history
  • Loading branch information
augchan42 authored Jan 4, 2025
2 parents 6df4ea6 + 5e17ccd commit 89b9a80
Show file tree
Hide file tree
Showing 48 changed files with 3,052 additions and 574 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ POST_INTERVAL_MAX= # Default: 180
POST_IMMEDIATELY=

# Twitter action processing configuration
ACTION_INTERVAL=300000 # Interval in milliseconds between action processing runs (default: 5 minutes)
ACTION_INTERVAL= # Interval in minutes between action processing runs (default: 5 minutes)
ENABLE_ACTION_PROCESSING=false # Set to true to enable the action processing loop

# Feature Flags
Expand Down
39 changes: 28 additions & 11 deletions .github/workflows/jsdoc-automation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,32 @@ name: JSDoc Automation
on:
workflow_dispatch:
inputs:
jsdoc:
description: 'Generate JSDoc comments (T/F)'
required: true
default: 'T'
type: string
readme:
description: 'Generate README documentation (T/F)'
required: true
default: 'T'
type: string
pull_number:
description: 'Pull Request Number (if not provided, scans root_directory) - PR must be merged to develop branch'
description: 'Pull Request Number (if not provided, scans root_directory) - PR must be merged to develop branch. DONT provide if `README documentation` is T from above'
required: false
type: string
root_directory:
description: 'Only scans files in this directory (relative to repository root, e.g., packages/core/src)'
required: true
default: 'packages/core/src/test_resources'
default: 'packages/plugin-near/'
type: string
excluded_directories:
description: 'Directories to exclude from scanning (comma-separated, relative to root_directory)'
required: true
default: 'node_modules,dist,test'
type: string
reviewers:
description: 'Pull Request Reviewers (comma-separated GitHub usernames)'
description: 'Pull Request Reviewers (Must be collaborator on the repository) comma-separated GitHub usernames'
required: true
default: ''
type: string
Expand All @@ -27,6 +37,11 @@ on:
required: false
default: 'develop'
type: string
language:
description: 'Documentation language (e.g., English, Spanish, French)'
required: true
default: 'English'
type: string

jobs:
generate-docs:
Expand All @@ -45,7 +60,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '23'
node-version: '20'

- name: Install pnpm
uses: pnpm/action-setup@v2
Expand All @@ -71,17 +86,19 @@ jobs:
working-directory: scripts/jsdoc-automation
run: pnpm install --no-frozen-lockfile

- name: Build TypeScript
working-directory: scripts/jsdoc-automation
run: pnpm build

- name: Run documentation generator
working-directory: scripts/jsdoc-automation
run: |
echo "Node version: $(node --version)"
echo "NPM version: $(npm --version)"
echo "Directory contents:"
ls -la
NODE_OPTIONS='--experimental-vm-modules --no-warnings' pnpm start
run: pnpm start
env:
INPUT_ROOT_DIRECTORY: ${{ inputs.root_directory }}
INPUT_PULL_NUMBER: ${{ inputs.pull_number }}
INPUT_EXCLUDED_DIRECTORIES: ${{ inputs.excluded_directories }}
INPUT_REVIEWERS: ${{ inputs.reviewers }}
INPUT_BRANCH: ${{ inputs.branch }}
INPUT_BRANCH: ${{ inputs.branch }}
INPUT_LANGUAGE: ${{ inputs.language }}
INPUT_JSDOC: ${{ inputs.jsdoc }}
INPUT_README: ${{ inputs.readme }}
58 changes: 58 additions & 0 deletions Dockerfile.docs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# syntax=docker/dockerfile:1

## Modified version of https://docusaurus.community/knowledge/deployment/docker/

# Stage 1: Base image.
## Start with a base image containing NodeJS so we can build Docusaurus.
FROM node:23.3.0-slim AS base
## Disable colour output from yarn to make logs easier to read.

## https://pnpm.io/docker
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"

ENV FORCE_COLOR=0
## Enable corepack.
RUN corepack enable
## Set the working directory to `/opt/docusaurus`.
WORKDIR /opt/docusaurus

## Required by docusaurus: [ERROR] Loading of version failed for version current
RUN apt-get update && apt-get install -y git

FROM base AS dev
## Set the working directory to `/opt/docusaurus`.
WORKDIR /opt/docusaurus
## Expose the port that Docusaurus will run on.
EXPOSE 3000
## Run the development server.
CMD [ -d "node_modules" ] && npm run start -- --host 0.0.0.0 --poll 1000 || pnpm install && pnpm run start -- --host 0.0.0.0 --poll 1000

# Stage 2b: Production build mode.
FROM base AS prod
## Set the working directory to `/opt/docusaurus`.
WORKDIR /opt/docusaurus

COPY docs/package.json /opt/docusaurus/package.json
COPY docs/package-lock.json /opt/docusaurus/package-lock.json

## Install dependencies with `--immutable` to ensure reproducibility.
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install

## Copy over the source code.
COPY docs/ /opt/docusaurus/
COPY packages/ /opt/packages/

## Required buy docusaurus [ERROR] Loading of version failed for version current
COPY .git/ /opt/.git/

# Build from sources
RUN pnpm run build

# Stage 3a: Serve with `docusaurus serve`.
FROM prod AS serve
## Expose the port that Docusaurus will run on.
EXPOSE 3000
## Run the production server.
CMD ["npm", "run", "serve", "--", "--host", "0.0.0.0", "--no-open"]

16 changes: 2 additions & 14 deletions client/src/Agents.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
import { useQuery } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { useNavigate } from "react-router-dom";
import { useGetAgentsQuery } from "@/api";
import "./App.css";

type Agent = {
id: string;
name: string;
};

function Agents() {
const navigate = useNavigate();
const { data: agents, isLoading } = useQuery({
queryKey: ["agents"],
queryFn: async () => {
const res = await fetch("/api/agents");
const data = await res.json();
return data.agents as Agent[];
},
});
const { data: agents, isLoading } = useGetAgentsQuery()

return (
<div className="min-h-screen flex flex-col items-center justify-center p-4">
Expand Down
51 changes: 12 additions & 39 deletions client/src/Chat.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { useMutation } from "@tanstack/react-query";
import type { TextResponse } from "@/api";
import { useSendMessageMutation } from "@/api";
import { ImageIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import "./App.css";

type TextResponse = {
text: string;
user: string;
attachments?: { url: string; contentType: string; title: string }[];
};

export default function Chat() {
const { agentId } = useParams();
const [input, setInput] = useState("");
const [messages, setMessages] = useState<TextResponse[]>([]);
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const messagesEndRef = useRef<HTMLDivElement>(null);
const { mutate: sendMessage, isPending } = useSendMessageMutation({ setMessages, setSelectedFile });

const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
Expand All @@ -28,32 +24,9 @@ export default function Chat() {
scrollToBottom();
}, [messages]);

const mutation = useMutation({
mutationFn: async (text: string) => {
const formData = new FormData();
formData.append("text", text);
formData.append("userId", "user");
formData.append("roomId", `default-room-${agentId}`);

if (selectedFile) {
formData.append("file", selectedFile);
}

const res = await fetch(`/api/${agentId}/message`, {
method: "POST",
body: formData,
});
return res.json() as Promise<TextResponse[]>;
},
onSuccess: (data) => {
setMessages((prev) => [...prev, ...data]);
setSelectedFile(null);
},
});

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!input.trim() && !selectedFile) return;
if ((!input.trim() && !selectedFile) || !agentId) return;

// Add user message immediately to state
const userMessage: TextResponse = {
Expand All @@ -63,7 +36,7 @@ export default function Chat() {
};
setMessages((prev) => [...prev, userMessage]);

mutation.mutate(input);
sendMessage({ text: input, agentId, selectedFile });
setInput("");
};

Expand Down Expand Up @@ -92,8 +65,8 @@ export default function Chat() {
: "justify-start"
}`}
>
<div
className={`max-w-[80%] rounded-lg px-4 py-2 ${
<pre
className={`max-w-[80%] rounded-lg px-4 py-2 whitespace-pre-wrap ${
message.user === "user"
? "bg-primary text-primary-foreground"
: "bg-muted"
Expand All @@ -115,7 +88,7 @@ export default function Chat() {
/>
)
))}
</div>
</pre>
</div>
))
) : (
Expand All @@ -142,19 +115,19 @@ export default function Chat() {
onChange={(e) => setInput(e.target.value)}
placeholder="Type a message..."
className="flex-1"
disabled={mutation.isPending}
disabled={isPending}
/>
<Button
type="button"
variant="outline"
size="icon"
onClick={handleFileSelect}
disabled={mutation.isPending}
disabled={isPending}
>
<ImageIcon className="h-4 w-4" />
</Button>
<Button type="submit" disabled={mutation.isPending}>
{mutation.isPending ? "..." : "Send"}
<Button type="submit" disabled={isPending}>
{isPending ? "..." : "Send"}
</Button>
</form>
{selectedFile && (
Expand Down
2 changes: 2 additions & 0 deletions client/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./mutations";
export * from "./queries";
1 change: 1 addition & 0 deletions client/src/api/mutations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./sendMessageMutation";
60 changes: 60 additions & 0 deletions client/src/api/mutations/sendMessageMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { CustomMutationResult } from "../types";

import { useMutation } from "@tanstack/react-query";
import { ROUTES } from "../routes";
import { SetStateAction } from "react";

export type TextResponse = {
text: string;
user: string;
attachments?: { url: string; contentType: string; title: string }[];
};

type SendMessageMutationProps = {
text: string;
agentId: string;
selectedFile: File | null;
};

type Props = Required<{
setMessages: (value: SetStateAction<TextResponse[]>) => void;
setSelectedFile: (value: SetStateAction<File | null>) => void;
}>;

export const useSendMessageMutation = ({
setMessages,
setSelectedFile,
}: Props): CustomMutationResult<TextResponse[], SendMessageMutationProps> => {
const mutation = useMutation({
mutationFn: async ({
text,
agentId,
selectedFile,
}: SendMessageMutationProps) => {
const formData = new FormData();
formData.append("text", text);
formData.append("userId", "user");
formData.append("roomId", `default-room-${agentId}`);

if (selectedFile) {
formData.append("file", selectedFile);
}

const res = await fetch(ROUTES.sendMessage(agentId), {
method: "POST",
body: formData,
});

return res.json() as Promise<TextResponse[]>;
},
onSuccess: (data) => {
setMessages((prev) => [...prev, ...data]);
setSelectedFile(null);
},
onError: (error) => {
console.error("[useSendMessageMutation]:", error);
},
});

return mutation;
};
1 change: 1 addition & 0 deletions client/src/api/queries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./useGetAgentsQuery";
3 changes: 3 additions & 0 deletions client/src/api/queries/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum Queries {
AGENTS = "agents",
}
23 changes: 23 additions & 0 deletions client/src/api/queries/useGetAgentsQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useQuery } from "@tanstack/react-query";
import type { CustomQueryResult } from "../types";
import { Queries } from "./queries";
import { ROUTES } from "../routes";

export type Agent = {
id: string;
name: string;
};

export const useGetAgentsQuery = (): CustomQueryResult<Agent[] | undefined> => {
return useQuery({
queryKey: [Queries.AGENTS],
queryFn: async () => {
const res = await fetch(ROUTES.getAgents());
const data = await res.json();
return data.agents as Agent[];
},
retry: (failureCount) => failureCount < 3,
staleTime: 5 * 60 * 1000, // 5 minutes
refetchOnWindowFocus: false,
});
};
4 changes: 4 additions & 0 deletions client/src/api/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const ROUTES = {
sendMessage: (agentId: string): string => `/api/${agentId}/message`,
getAgents: (): string => `/api/agents`,
};
Loading

0 comments on commit 89b9a80

Please sign in to comment.