diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index e9a0126..38d65f4 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,94 +1,15 @@ FROM ubuntu:24.04 LABEL org.opencontainers.image.title="GoodMem Dev Environment" \ - org.opencontainers.image.description="Minimal setup for developing with GoodMem APIs (Python + JS + .NET)" \ - org.opencontainers.image.version="1.1.0" + org.opencontainers.image.description="Minimal setup for developing with GoodMem API through GoodMem CLI" \ + org.opencontainers.image.version="1.2.0" SHELL ["/bin/bash", "-c"] -# Base deps +# Base dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ curl wget git unzip gnupg ca-certificates software-properties-common \ - build-essential apt-transport-https sudo \ - python3 python3-venv python3-pip python3-dev \ - libffi-dev libssl-dev libpq-dev cargo - -# Node.js 20 -RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ - apt-get install -y nodejs - -# .NET SDK 9.0 -RUN add-apt-repository ppa:dotnet/backports && \ - apt-get update && \ - apt-get install -y dotnet-sdk-9.0 - -#Go -ARG GO_VERSION=1.24.6 -RUN curl -fsSL https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz -o /tmp/go.tgz \ - && rm -rf /usr/local/go \ - && tar -C /usr/local -xzf /tmp/go.tgz \ - && rm /tmp/go.tgz -ENV GOROOT=/usr/local/go -ENV GOPATH=/home/vscode/go -ENV PATH=$GOROOT/bin:$GOPATH/bin:$PATH -# quick sanity -RUN go version - -# ---- Java (OpenJDK 21) ---- -RUN apt-get install -y --no-install-recommends \ - openjdk-21-jdk \ - && rm -rf /var/lib/apt/lists/* -ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 -ENV PATH="$JAVA_HOME/bin:${PATH}" - -# quick sanity -RUN java -version && javac -version - -# ---- Gradle (official binary) ---- -RUN curl -fsSL https://services.gradle.org/distributions/gradle-8.9-bin.zip -o /tmp/gradle.zip \ - && unzip -q /tmp/gradle.zip -d /opt \ - && ln -s /opt/gradle-8.9 /opt/gradle \ - && rm -f /tmp/gradle.zip -ENV PATH="/opt/gradle/bin:${PATH}" - - -# quick sanity -RUN gradle -v - -# Python defaults -RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1 -ENV PIP_DISABLE_PIP_VERSION_CHECK=1 PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 - -# Global Python deps -RUN pip install --no-cache-dir --break-system-packages \ - goodmem_client openai requests python-dotenv \ - jupyter lab - -# Dotnet Interactive (for Jupyter) -RUN dotnet tool install --global Microsoft.dotnet-interactive -ENV PATH="/root/.dotnet/tools:${PATH}" -RUN dotnet interactive jupyter install - -# IJavascript (Node.js kernel for Jupyter) -RUN npm config set prefix $HOME -RUN npm install -g ijavascript -ENV PATH="/root/bin:${PATH}" -RUN ijsinstall - -# JJava (Java kernel for Jupyter) -RUN curl -fsSL https://github.com/dflib/jjava/releases/download/1.0-a5/jjava-1.0-a5-kernelspec.zip -o /tmp/jjava.zip && \ - unzip -q /tmp/jjava.zip -d /tmp/jjava-1.0-a5-kernelspec && \ - cd /tmp && \ - jupyter kernelspec install jjava-1.0-a5-kernelspec --user --name=java - -# GONB (Go kernel for Jupyter) -RUN go install github.com/janpfeifer/gonb@latest && \ - go install golang.org/x/tools/cmd/goimports@latest && \ - go install golang.org/x/tools/gopls@latest -RUN gonb --install - -# APT clean up -RUN rm -rf /var/lib/apt/lists/* + apt-transport-https sudo # Dev user # EDIT: DISABLED for now to avoid permission issues with mounted volumes @@ -98,12 +19,10 @@ RUN rm -rf /var/lib/apt/lists/* # mkdir -p /home/vscode/.goodmem/data/database && \ # chown -R vscode:vscode /home/vscode/.goodmem -# USER vscode +# APT clean up +RUN rm -rf /var/lib/apt/lists/* -# Use Codespaces default; the repo will be mounted at /workspaces/ -WORKDIR /workspaces +# USER vscode -# Create Python virtual environment and activate it by default -RUN python3 -m venv /opt/venv -ENV PATH="/opt/venv/bin:$PATH" -ENV VIRTUAL_ENV="/opt/venv" +# # Use Codespaces default; the repo will be mounted at /workspaces/ +# WORKDIR /workspaces diff --git a/.devcontainer/configure-goodmem.sh b/.devcontainer/configure-goodmem.sh new file mode 100755 index 0000000..e57ac98 --- /dev/null +++ b/.devcontainer/configure-goodmem.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Install GoodMem and initialize (create root user and generate API key while saving it to config.toml) +echo "Installing GoodMem..." +curl -s "https://get.goodmem.ai" | bash -s -- --handsfree --db-password "my-secure-password" + +# Extract API key and add to ~/.bashrc +echo "Configuring GoodMem API key..." +if [ -f ~/.goodmem/config.toml ]; then + API_KEY=$(grep "^api_key" ~/.goodmem/config.toml | cut -d"'" -f2) + if [ -n "$API_KEY" ]; then + if ! grep -q "GOODMEM_API_KEY" ~/.bashrc; then + echo "export GOODMEM_API_KEY=\"$API_KEY\"" >> ~/.bashrc + echo "Added GOODMEM_API_KEY to ~/.bashrc" + else + echo "GOODMEM_API_KEY already exists in ~/.bashrc" + fi + echo "***REMEMBER GOODMEM_API_KEY=\"$API_KEY\"***" + else + echo "Warning: Could not extract api_key from config.toml" + fi +else + echo "Warning: ~/.goodmem/config.toml not found" +fi + +echo "GoodMem installation and configuration complete!" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c5d0a48..c8c19f2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,19 @@ { "name": "GoodMem Dev Container", - // "build": { "dockerfile": "Dockerfile" }, - "image": "ghcr.io/pair-systems-inc/devcontainer-codespace:latest", + // build docker image from local Dockerfile + "build": { "dockerfile": "Dockerfile" }, - // "postCreateCommand": "bash .devcontainer/setup.sh", # Skip example code setup - "postCreateCommand": "bash .devcontainer/post-setup.sh", + // build docker image from latest build on github container registry + // "image": "ghcr.io/pair-systems-inc/devcontainer-codespace:latest", + "postCreateCommand": "bash .devcontainer/configure-goodmem.sh", "features": { "ghcr.io/devcontainers/features/docker-in-docker:2": {} }, "customizations": { "vscode": { "extensions": [ - "ms-python.python", - "ms-vscode.vscode-docker", - "ms-toolsai.jupyter" + "ms-vscode.vscode-docker" ] } } diff --git a/.devcontainer/optional-feature-installer.sh b/.devcontainer/optional-feature-installer.sh new file mode 100755 index 0000000..cc3236a --- /dev/null +++ b/.devcontainer/optional-feature-installer.sh @@ -0,0 +1,279 @@ +#!/bin/bash + +# This script provides an interactive menu for users to choose which GoodMem SDK or tool they want install in the dev container. + +# Logic for printing menu +options=( + "Jupyter Notebook" + "Python SDK" + ".NET SDK" + "Node.js SDK" + "Java SDK" + "Go SDK" +) + +selected=0 +total=${#options[@]} + +print_menu() { + for i in "${!options[@]}"; do + if [ "$i" -eq "$selected" ]; then + echo " > ${options[$i]}" + else + echo " ${options[$i]}" + fi + done +} + +# Print header once +echo "" +echo "======================================" +echo " Welcome to GoodMem Dev Container" +echo "======================================" +echo "" +echo "Use UP/DOWN arrows to select, then press ENTER:" +echo "" + +# Print menu for the first time +print_menu + +while true; do + IFS= read -rsn1 key + if [[ $key == $'\x1b' ]]; then + read -rsn2 -t 0.1 key + case $key in + '[A') (( selected = (selected - 1 + total) % total )) ;; # Up + '[B') (( selected = (selected + 1) % total )) ;; # Down + *) continue ;; + esac + # Move cursor up $total lines and redraw only the menu + printf '\033[%dA' "$total" + print_menu + elif [[ $key == '' ]]; then + break # Enter + fi +done + +echo "" +echo "Selected: ${options[$selected]}" +echo "" + +case $selected in + 0) + echo "Installing Jupyter VS Code extension..." + code --install-extension ms-toolsai.jupyter 2>/dev/null || true + echo "Starting Jupyter Lab..." + + # clone the goodmem-samples repository + GOODMEM_REPO_DIR="goodmem-samples" + if [ ! -d "$GOODMEM_REPO_DIR" ]; then + git clone https://github.com/PAIR-Systems-Inc/goodmem-samples.git "$GOODMEM_REPO_DIR" + echo "GoodMem repository cloned to $GOODMEM_REPO_DIR" + else + echo "GoodMem repository already exists at $GOODMEM_REPO_DIR" + fi + + jupyter lab --ip=0.0.0.0 --no-browser --allow-root + ;; + ############################################################### + ##################### installing Python ####################### + ############################################################### + 1) + echo "Installing Python VS Code extension..." + code --install-extension ms-python.python 2>/dev/null || true + + echo "Installing Python dependencies..." + sudo apt-get install -y --no-install-recommends \ + build-essential python3-pip python3-dev \ + libffi-dev libssl-dev + sudo rm -rf /var/lib/apt/lists/* + sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 + + echo "Installing Python SDK packages..." + pip install --no-cache-dir --break-system-packages goodmem_client openai requests python-dotenv + # jupyter lab + + echo "Python environment ready" + ;; + ############################################################### + ###################### installing .NET ######################## + ############################################################### + 2) + echo "Installing .NET SDK 8.0..." + sudo apt-get update && sudo apt-get install -y dotnet-sdk-8.0 + sudo rm -rf /var/lib/apt/lists/* + echo "Creating .NET sample app with GoodMem client..." + + DOTNET_APP_DIR="src/GoodMemDotnetApp" + if [ ! -d "$DOTNET_APP_DIR" ]; then + dotnet new console -o "$DOTNET_APP_DIR" -n GoodMemDotnetApp + ( cd "$DOTNET_APP_DIR" && dotnet add package Pairsystems.Goodmem.Client ) + fi + ( cd "$DOTNET_APP_DIR" && dotnet restore && dotnet build ) + + echo ".NET environment ready" + echo " - Sample app: $DOTNET_APP_DIR" + ;; + ############################################################### + ################### installing Node.js ######################## + ############################################################### + 3) + echo "Installing Node.js 20..." + curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash - + sudo apt-get install -y nodejs + sudo rm -rf /var/lib/apt/lists/* + + npm install -g pnpm + + node --version + pnpm --version + + echo "Creating Node.js sample app with GoodMem client..." + NODE_APP_DIR="src/GoodMemNodeApp" + + if [ ! -d "$NODE_APP_DIR" ]; then + mkdir -p "$NODE_APP_DIR" + cd "$NODE_APP_DIR" + + cat > package.json <<'NODEPKG' +{ + "name": "goodmem-js-example", + "version": "1.0.0", + "description": "Automated dev environment for the GoodMem JS SDK", + "main": "index.js", + "type": "module", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "dotenv": "^16.4.5", + "goodmem": "0.1.0" + } +} +NODEPKG + + pnpm install + cd - >/dev/null + fi + + echo "Node.js environment ready" + echo " - Sample app: $NODE_APP_DIR" + ;; + ############################################################### + ###################### installing Java ######################## + ############################################################### + 4) + echo "Installing Java (OpenJDK 21) and Gradle 8.9..." + sudo apt-get update && sudo apt-get install -y --no-install-recommends openjdk-21-jdk + sudo rm -rf /var/lib/apt/lists/* + + export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 + export PATH="$JAVA_HOME/bin:$PATH" + + curl -fsSL https://services.gradle.org/distributions/gradle-8.9-bin.zip -o /tmp/gradle.zip + sudo unzip -q /tmp/gradle.zip -d /opt + sudo ln -sf /opt/gradle-8.9 /opt/gradle + rm -f /tmp/gradle.zip + export PATH="/opt/gradle/bin:$PATH" + + if ! grep -q 'JAVA_HOME' ~/.bashrc; then + echo 'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64' >> ~/.bashrc + echo 'export PATH="$JAVA_HOME/bin:/opt/gradle/bin:$PATH"' >> ~/.bashrc + fi + + java -version + gradle -v + + echo "Creating Java sample app with GoodMem client..." + + JAVA_APP_DIR="src/GoodMemJavaApp" + + if [ ! -d "$JAVA_APP_DIR" ]; then + mkdir -p "$JAVA_APP_DIR" + cd "$JAVA_APP_DIR" + + printf "1\n" | gradle -q init \ + --type java-application \ + --dsl kotlin \ + --test-framework junit \ + --project-name GoodMemJavaApp \ + --package com.pairsystems.goodmem.sample \ + --java-version 21 + + if [ -f "build.gradle.kts" ]; then + awk '1;/dependencies *\{/ && !x{print " implementation(\"com.pairsystems:goodmem-client:1.0.0\")"; x=1}' \ + build.gradle.kts > build.gradle.kts.tmp && mv build.gradle.kts.tmp build.gradle.kts + fi + else + cd "$JAVA_APP_DIR" + fi + + ./gradlew --no-daemon build || echo "WARN: build failed (artifact may not be published yet)" + cd - >/dev/null + + echo "Java environment ready" + echo " - Sample app: $JAVA_APP_DIR" + ;; + ############################################################### + ######################## installing Go ######################## + ############################################################### + 5) + echo "Installing Go 1.24.6..." + GO_VERSION=1.24.6 + curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o /tmp/go.tgz + sudo rm -rf /usr/local/go + sudo tar -C /usr/local -xzf /tmp/go.tgz + rm /tmp/go.tgz + + export GOROOT=/usr/local/go + export GOPATH="$HOME/go" + export PATH="$GOROOT/bin:$GOPATH/bin:$PATH" + + if ! grep -q 'GOROOT' ~/.bashrc; then + echo 'export GOROOT=/usr/local/go' >> ~/.bashrc + echo 'export GOPATH="$HOME/go"' >> ~/.bashrc + echo 'export PATH="$GOROOT/bin:$GOPATH/bin:$PATH"' >> ~/.bashrc + fi + + go version + + echo "Creating Go sample app with GoodMem client..." + + GO_APP_DIR="src/GoodMemGoApp" + GO_SDK_MOD="github.com/PAIR-Systems-Inc/goodmem/clients/go@v1.0.10" + + if [ ! -d "$GO_APP_DIR" ]; then + mkdir -p "$GO_APP_DIR" + fi + + cd "$GO_APP_DIR" + + if [ ! -f go.mod ]; then + go mod init goodmem-app + fi + + go get "$GO_SDK_MOD" + + if [ ! -f main.go ]; then + cat > main.go <<'EOF' +package main + +import ( + "fmt" + _ "github.com/PAIR-Systems-Inc/goodmem/clients/go" +) + +func main() { + fmt.Println("Go SDK wired; import ok") +} +EOF + fi + + go mod tidy + go build ./... + + cd - >/dev/null + echo "Go environment ready" + echo " - Sample app: $GO_APP_DIR" + ;; +esac diff --git a/.devcontainer/post-setup.sh b/.devcontainer/post-setup.sh deleted file mode 100755 index 3536c1e..0000000 --- a/.devcontainer/post-setup.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -set -e - -echo "=== Post-setup script started ===" - -# 0. Clone the goodmem-samples repository -GOODMEM_REPO_DIR="goodmem-samples" -if [ ! -d "$GOODMEM_REPO_DIR" ]; then - git clone https://github.com/PAIR-Systems-Inc/goodmem-samples.git "$GOODMEM_REPO_DIR" - echo "GoodMem repository cloned to $GOODMEM_REPO_DIR" -else - echo "GoodMem repository already exists at $GOODMEM_REPO_DIR" -fi - -# 1. Install GoodMem -echo "Installing GoodMem..." -curl -s https://get.goodmem.ai | bash -s -- --handsfree --db-password "hjsaFGDGHS1726HSBD" - -# 2. Extract API key and add to ~/.bashrc -echo "Configuring GoodMem API key..." -if [ -f ~/.goodmem/config.json ]; then - API_KEY=$(grep -o '"api_key"[[:space:]]*:[[:space:]]*"[^"]*"' ~/.goodmem/config.json | cut -d'"' -f4) - if [ -n "$API_KEY" ]; then - if ! grep -q "GOODMEM_API_KEY" ~/.bashrc; then - echo "export GOODMEM_API_KEY=\"$API_KEY\"" >> ~/.bashrc - echo "Added GOODMEM_API_KEY to ~/.bashrc" - else - echo "GOODMEM_API_KEY already exists in ~/.bashrc" - fi - echo "***REMEMBER GOODMEM_API_KEY=\"$API_KEY\"***" - else - echo "Warning: Could not extract api_key from config.json" - fi -else - echo "Warning: ~/.goodmem/config.json not found" -fi - - -echo "=== Post-setup script completed ===" diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh deleted file mode 100644 index 91d6fb0..0000000 --- a/.devcontainer/setup.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -echo "[setup.sh] start PWD=$(pwd) USER=$(whoami)" - -BASE_DIR="src" -mkdir -p "$BASE_DIR" - -########## .NET sample (GoodMemDotnetApp) ########## -DOTNET_APP_DIR="$BASE_DIR/GoodMemDotnetApp" -if [[ ! -d "$DOTNET_APP_DIR" ]]; then - echo "[setup.sh] creating $DOTNET_APP_DIR" - dotnet new console -o "$DOTNET_APP_DIR" -n GoodMemDotnetApp - ( cd "$DOTNET_APP_DIR" && dotnet add package Pairsystems.Goodmem.Client ) -else - echo "[setup.sh] $DOTNET_APP_DIR exists; skipping scaffold" -fi - -echo "[setup.sh] restoring/building GoodMemDotnetApp" -( cd "$DOTNET_APP_DIR" && dotnet restore && dotnet build ) - -########## Go sample (GoodMemGoApp) ########## -if command -v go >/dev/null 2>&1; then - GO_APP_DIR="$BASE_DIR/GoodMemGoApp" - GO_SDK_MOD="github.com/PAIR-Systems-Inc/goodmem/clients/go@v1.0.10" - - if [[ ! -d "$GO_APP_DIR" ]]; then - echo "[setup.sh] creating $GO_APP_DIR" - mkdir -p "$GO_APP_DIR" - fi - - pushd "$GO_APP_DIR" >/dev/null - - if [[ ! -f go.mod ]]; then - echo "[setup.sh] go mod init goodmem-app" - go mod init goodmem-app - fi - - echo "[setup.sh] ensuring Go SDK: $GO_SDK_MOD" - go get "$GO_SDK_MOD" - - if [[ ! -f main.go ]]; then - echo "[setup.sh] writing main.go" - cat > main.go <<'EOF' -package main - -import ( - "fmt" - _ "github.com/PAIR-Systems-Inc/goodmem/clients/go" -) - -func main() { - fmt.Println("Go SDK wired; import ok") -} -EOF - fi - - echo "[setup.sh] go mod tidy && go build" - go mod tidy - go build ./... - - popd >/dev/null -else - echo "[setup.sh] Go not installed; skipping GoodMemGoApp" -fi - -########## Java sample (GoodMemJavaApp via Gradle) ########## -if command -v javac >/dev/null 2>&1; then - JAVA_APP_DIR="$BASE_DIR/GoodMemJavaApp" - - if [[ ! -d "$JAVA_APP_DIR" ]]; then - echo "[setup.sh] creating $JAVA_APP_DIR" - mkdir -p "$JAVA_APP_DIR" - cd "$JAVA_APP_DIR" - - printf "1\n" | gradle -q init \ - --type java-application \ - --dsl kotlin \ - --test-framework junit \ - --project-name GoodMemJavaApp \ - --package com.pairsystems.goodmem.sample \ - --java-version 21 - - if [[ -f "build.gradle.kts" ]]; then - awk '1;/dependencies *\{/ && !x{print " implementation(\"com.pairsystems:goodmem-client:1.0.0\")"; x=1}' \ - build.gradle.kts > build.gradle.kts.tmp && mv build.gradle.kts.tmp build.gradle.kts - fi - else - cd "$JAVA_APP_DIR" - fi - - echo "[setup.sh] ./gradlew build" - ./gradlew --no-daemon build || echo "[setup.sh] WARN: build failed (artifact may not be published yet)" - cd - >/dev/null -else - echo "[setup.sh] Java not installed; skipping GoodMemJavaApp" -fi - -echo "[setup.sh] done" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..313a4ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +# OS +.DS_Store +Thumbs.db + +# Editor +.vscode/settings.json +.idea/ +*.swp +*.swo + +# LLM / AI tools +.cursor/ +.copilot/ +.aider* +.claude/ +.continue/ +*.cursorrules +.github/copilot-instructions.md +claude.json +CLAUDE.md +AGENTS.md +GEMINI.md +COPILOT.md + +# Env files +.env +.env.local +.env*.local + +# Jupyter +.ipynb_checkpoints/ + +# Python +__pycache__/ +*.py[cod] +*.pyo +*.pyd +.env +.venv/ +venv/ +*.egg-info/ +dist/ +build/ + +# Node.js +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# Java / Gradle +.gradle/ +build/ +*.class +*.jar +*.war + +# .NET +bin/ +obj/ +*.user +*.suo +.vs/ + +# Go +vendor/ \ No newline at end of file diff --git a/README.md b/README.md index 4549ccf..f5baeac 100644 --- a/README.md +++ b/README.md @@ -1,156 +1,236 @@ -# GoodMem DevContainer +# GitHub Codespace Quick Start + -### Language Support -- **Python 3.10** — includes the GoodMem SDK and OpenAI integration -- **Java 17** -- **.NET 9** -- **Go 1.22** -- **Node.js 20** with `pnpm` +This GitHub Codespace is a pre-configured development environment to help you start building with GoodMem immediately through the command line tool. -### Preinstalled Tooling -- **Visual Studio Code Extensions** — language servers, formatters, linters, and productivity tools for all supported languages - ---- - -# Next Steps - -By now you should have installed GoodMem through the devcontainer. Below is a tutorial on how to use the Goodmem CLI. - -1. In the logs, locate output similar to the following: - - ```text - Connecting to gRPC API at https://localhost:9090 - Using TLS with certificate verification disabled (insecure mode) - System initialized successfully - Root API key: gm_xxxxxxxxxxxxxxxxxxxxxxxx - User ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - ``` - -2. **Save Your Root API Key** - - The Root API Key `(gm_xxxxxxxxxxxxxxxxxxxxxxxx)` is shown only once. It’s best to copy and store it now. - You may also locate the `api_key` under `~/.goodmem/config.json` - -4. **Obtain your OpenAI API Key** from the [OpenAI dashboard](https://platform.openai.com/api-keys) and keep it ready for the next step. - -5. **Create an embedder** (must be created before a space): - - ```bash - goodmem embedder create \ - --display-name "OpenAI Small Embedder" \ - --provider-type OPENAI \ - --endpoint-url "https://api.openai.com/v1" \ - --model-identifier "text-embedding-3-small" \ - --dimensionality 1536 \ - --credentials "YOUR_OPENAI_API_KEY_FROM_STEP_3" - ``` - The command should output: - - > Embedder created successfully!\ - >\ - > ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Display Name: OpenAI Small Embedder\ - > Owner: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Provider Type: OPENAI\ - > Distribution: DENSE\ - > Endpoint URL: https://api.openai.com/v1\ - > API Path: /embeddings\ - > Model: text-embedding-3-small - - **SAVE THE ID** - -6. **Create a space** linked to that embedder: - - ```bash - goodmem space create \ - --name "My OpenAI Small Space" \ - --embedder-id - ``` - - The command should output: - - > Space created successfully!\ - >\ - > ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Name: My OpenAI Small Space\ - > Owner: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Created by: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Created at: 2025-08-20T21:08:20Z\ - > Public: false\ - > Embedder: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (weight: 1.0) - - **SAVE THE ID** +**Please make sure to read the requirements section.** -7. **Create an LLM**: +> If you would prefer to interact with GoodMem through a Jupyter Notebook or an SDK, please navigate to the [optional features section](#optional-features) + +To get started with GoodMem navigate to the [quick start instructions section](#quick-start-instructions). + +## Requirements + +- An OpenAI API key (access at https://platform.openai.com/) +- A running GoodMem server (already setup) +- A GoodMem API key (already setup, access with `grep key ~/.goodmem/config.toml`) + +> If you do not want to use an OpenAI API key, please use an embedding provider we support +(Cohere, Jina, Voyage AI, vLLM, TEI, OpenAI) + +# Quick Start Instructions + +Below is a tutorial on how to use the Goodmem CLI (command line interface). + +You can use `control + c`, `control + shift + c`, `control + v`, and `control + shift + v` to copy paste commands and data for the tutorial below. + +**Please follow the instructions in order** + +1. **Setup The Terminal** + +The terminal is usually located on the bottom half of the screen and should display the text `devcontainer-codespace`. + +If the terminal displays "Running postCreateCommand" please wait a few seconds for GoodMem to complete installation. + +You can also adjust the size of the terminal by dragging the top edge of the terminal screen. + +If the terminal is not already open, you can launch the terminal in a few ways: + +- use the keyboard shortcut `control + j` +- use the keyboard shortcut ```control + ` ``` +- click the bottom left warning icon -> Terminal +- click the three horizontal bars at the top left of the screen -> Terminal -> New Terminal +- click the three horizontal bars at the top left of the screen -> View -> Terminal - ```bash - goodmem llm create \ - --display-name "My GPT-4" \ - --provider-type OPENAI \ - --endpoint-url "https://api.openai.com/v1" \ - --model-identifier "gpt-4o" - ``` +If the terminal is open but it does not display the text `devcontainer-codespace` try these options to open a new terminal: - The command should output: +- use the keyboard shortcut ```control + shift + ` ``` +- click the '+' sign at the top right of the terminal +- click the three bars (sandwich icon) at the top left of the screen -> Terminal -> New Terminal - > LLM created successfully!\ - > ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Name: My GPT-4\ - > Provider: LLM_PROVIDER_TYPE_OPENAI\ - > Model: gpt-4o +2. **Save Your GoodMem API Key** - **SAVE THE ID** +Copy paste the command below into the terminal using `control + shift + v`. -### Testing the Queries +`grep key ~/.goodmem/config.toml` -The next major step is to upload content into memory so it can be queried. To do this, we will first upload a PDF and store it in memory. After that, we will run some queries. Follow the directions below: +Copy and store the value, this is your GoodMem API key. -1. **Begin by creating a memory.** In this case, I will be using this PDF, which I recommend you use as well for testing: +3. **Obtain your OpenAI API Key** from the [OpenAI dashboard](https://platform.openai.com/api-keys) and copy and store it. - [An Excellent Study of Social Media and Its Positive and Negative Effects on Human Being’s Mental Health](https://dr.lib.iastate.edu/server/api/core/bitstreams/8d3ccb03-cbc4-4b8a-b452-0ebccf0dde55/content) +4. **Create an embedder** (must be created before a space): +```bash +goodmem embedder create \ + --display-name "OpenAI Small Embedder" \ + --provider-type OPENAI \ + --endpoint-url "https://api.openai.com/v1" \ + --model-identifier "text-embedding-3-small" \ + --dimensionality 1536 \ + --cred-api-key YOUR_OPENAI_API_KEY_FROM_STEP_3 +``` +The command should output: - Then run this command: +``` +Embedder created successfully! - ```bash - goodmem memory create \ - --space-id \ - --file "path to where you downloaded the pdf" \ - --content-type "application/pdf" - ``` +ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Display Name: OpenAI Small Embedder +Owner: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Provider Type: OPENAI +Distribution: DENSE +Endpoint URL: https://api.openai.com/v1 +API Path: /embeddings +Model: text-embedding-3-small +Dimensionality: 1536 +Created by: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Created at: 2026-03-17T22:51:57Z +``` - It should output: +**SAVE THE ID** - > Memory created successfully!\ - >\ - > ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Space ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Content Type: application/pdf\ - > Status: PENDING\ - > Created by: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Created at: 2025-08-20T21:20:00Z +5. **Create a space** linked to that embedder: - **SAVE THE ID** (not the space ID since you already have that) +```bash +goodmem space create \ + --name "My OpenAI Small Space" \ + --embedder-id YOUR_EMBEDDER_ID_FROM_STEP_4 +``` + +The command should output: + +``` +Space created successfully! + +ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Name: My OpenAI Small Space +Owner: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Created by: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Created at: 2026-03-17T23:04:06Z +Public: false +Embedder: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (weight: 1) +``` + +**SAVE THE ID** + +7. **Create an LLM**: + +```bash +goodmem llm create \ + --display-name "My GPT-4" \ + --provider-type OPENAI \ + --endpoint-url "https://api.openai.com/v1" \ + --model-identifier "gpt-4o" +``` + +The command should output: + +``` +LLM created successfully! + +ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Display Name: My GPT-4 +Owner: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Provider Type: OPENAI +Endpoint URL: https://api.openai.com/v1 +API Path: /chat/completions +Model: gpt-4o +Modalities: TEXT +Capabilities: Chat, Completion, Functions, System Messages, Streaming, Sampling Parameters +Created by: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Created at: 2026-03-17T23:06:04Z + +Capability Inference: + ✓ Chat Support: true (detected from model family 'gpt-4o') + ✓ Completion Support: true (detected from model family 'gpt-4o') + ✓ Function Calling: true (detected from model family 'gpt-4o') + ✓ System Messages: true (detected from model family 'gpt-4o') + ✓ Streaming: true (detected from model family 'gpt-4o') + ✓ Sampling Parameters: true (detected from model family 'gpt-4o') +``` + +**SAVE THE ID** + +## Testing the Queries + +The next major step is to upload content into memory so it can be queried. +To do this, we will first upload a PDF and store it in memory. After that, we will run some queries. + +1. **Begin by creating a memory.** We will be using this pre-downloaded PDF: + +[An Excellent Study of Social Media and Its Positive and Negative Effects on Human Being’s Mental Health](https://dr.lib.iastate.edu/server/api/core/bitstreams/8d3ccb03-cbc4-4b8a-b452-0ebccf0dde55/content) + +Then run this command: + +```bash +goodmem memory create \ + --file "social_media_study.pdf" \ + --content-type "application/pdf" \ + --space-id YOUR_SPACE_ID_FROM_STEP_5 +``` + +It should output: + +``` +Memory created successfully! + +ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Space ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Content Type: application/pdf +Page images: enabled +Status: PENDING +Created by: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +Created at: 2026-03-17T23:18:33Z +Metadata: + filename: social_media_study.pdf +``` + +**SAVE THE ID** (not the space ID since you already have that) 2. To run a query, you have two options: non-interactive mode and interactive mode. - **Non-interactive mode:** - ```bash - goodmem memory retrieve \ - "what are the top three negative affects of social media?" \ - --space-id - ``` +**Non-interactive mode:** +```bash +goodmem memory retrieve \ + "what are the top three negative affects of social media?" \ + --space-id YOUR_SPACE_ID_FROM_STEP_5 +``` + +**Interactive mode (easier to retrieve results):** + +```bash +goodmem memory retrieve \ + --post-processor-interactive "what are the top three negative affects of social media?" \ + --space-id YOUR_SPACE_ID_FROM_STEP_5 +``` - **Interactive mode (easier to retrieve results):** +# Optional Features - ```bash - goodmem memory retrieve \ - --space-id \ - --post-processor-interactive "what are the top three negative affects of social media?" - ``` +To enable optional features, follow the instructions below. + +1. copy and paste this command in the terminal + +`source .devcontainer/optional-feature-installer.sh` + +2. hit enter + +3. follow the installer instructions + +### optional features Language Support +- **Python 3.10** - includes the GoodMem SDK and OpenAI integration +- **Java 17** +- **.NET 9** +- **Go 1.22** +- **Node.js 20** with `pnpm` + +### Preinstalled Tooling +- **Visual Studio Code Extensions** — language servers, formatters, linters, and productivity tools for all supported languages diff --git a/next.md b/next.md deleted file mode 100644 index 892ceb9..0000000 --- a/next.md +++ /dev/null @@ -1,165 +0,0 @@ -# Next Steps - -By now you should have installed GoodMem, either manually or through the devcontainer. If you have not completed this step, please proceed with the installation. - -### Devcontainer Setup (Skip if you installed GoodMem manually) - -1. Click below to open a Codespace using the GoodMem template repository: - - [Open Codespace](https://github.com/codespaces/new?repo=PAIR-Systems-Inc/devcontainer-codespace) - - -2. After your Codespace launches, check the **bottom-left corner** of VS Code. Click on the `Codespaces: [name]` badge and choose **View Creation Logs**. - -### Configuration Steps - -1. In the logs, locate output similar to the following: - - ```text - Connecting to gRPC API at https://localhost:9090 - Using TLS with certificate verification disabled (insecure mode) - System initialized successfully - Root API key: gm_xxxxxxxxxxxxxxxxxxxxxxxx - User ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - ``` - -2. **Save Your Root API Key**\ - - The Root API Key `(gm_xxxxxxxxxxxxxxxxxxxxxxxx)` is shown only once. It’s best to copy and store it now. - -4. **Obtain your OpenAI API Key** from the [OpenAI dashboard](https://platform.openai.com/api-keys) and keep it ready for the next step. - -5. **Create an embedder** (must be created before a space): - - ```bash - goodmem embedder create \ - --display-name "OpenAI Small Embedder" \ - --provider-type OPENAI \ - --endpoint-url "https://api.openai.com/v1" \ - --model-identifier "text-embedding-3-small" \ - --dimensionality 1536 \ - --credentials "YOUR_OPENAI_API_KEY_FROM_STEP_3" - ``` - The command should output: - - > Embedder created successfully!\ - >\ - > ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Display Name: OpenAI Small Embedder\ - > Owner: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Provider Type: OPENAI\ - > Distribution: DENSE\ - > Endpoint URL: https://api.openai.com/v1\ - > API Path: /embeddings\ - > Model: text-embedding-3-small - - **SAVE THE ID** - -6. **Create a space** linked to that embedder: - - ```bash - goodmem space create \ - --name "My OpenAI Small Space" \ - --embedder-id - ``` - - The command should output: - - > Space created successfully!\ - >\ - > ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Name: My OpenAI Small Space\ - > Owner: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Created by: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Created at: 2025-08-20T21:08:20Z\ - > Public: false\ - > Embedder: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (weight: 1.0) - - **SAVE THE ID** - -7. **Create an LLM**: - - ```bash - goodmem llm create \ - --display-name "My GPT-4" \ - --provider-type OPENAI \ - --endpoint-url "https://api.openai.com/v1" \ - --model-identifier "gpt-4o" - ``` - - The command should output: - - > LLM created successfully!\ - > ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Name: My GPT-4\ - > Provider: LLM_PROVIDER_TYPE_OPENAI\ - > Model: gpt-4o - - **SAVE THE ID** - -### Testing the Queries - -The next major step is to upload content into memory so it can be queried. To do this, we will first upload a PDF and store it in memory. After that, we will run some queries. Follow the directions below: - -1. **Begin by creating a memory.** In this case, I will be using this PDF, which I recommend you use as well for testing: - - [An Excellent Study of Social Media and Its Positive and Negative Effects on Human Being’s Mental Health](https://dr.lib.iastate.edu/server/api/core/bitstreams/8d3ccb03-cbc4-4b8a-b452-0ebccf0dde55/content) - - - Then run this command: - - ```bash - goodmem memory create \ - --space-id \ - --file "path to where you downloaded the pdf" \ - --content-type "application/pdf" - ``` - - It should output: - - > Memory created successfully!\ - >\ - > ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Space ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Content Type: application/pdf\ - > Status: PENDING\ - > Created by: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ - > Created at: 2025-08-20T21:20:00Z - - **SAVE THE ID** (not the space ID since you already have that) - -2. To run a query, you have two options: non-interactive mode and interactive mode. - - **Non-interactive mode:** - ```bash - goodmem memory retrieve \ - "what are the top three negative affects of social media?" \ - --space-id - ``` - - **Interactive mode (easier to retrieve results):** - - ```bash - goodmem memory retrieve \ - --space-id \ - --post-processor-interactive "what are the top three negative affects of social media?" - ``` - - -### Next Step: Test Your SDK (for devcontainer) - -**Setup your environment**: - -1. Obtain your **OpenAI API Key** from the OpenAI dashboard and paste it into the `.env` file that was automatically generated in your workspace. Also paste the Root API key from step 4. - - Example `.env` file: - - ```env - OPENAI_API_KEY=sk-... - ADD_API_KEY=gm_xxxxxxxxxxxxxxxxxxxxxxxx - ``` - -**Verify your setup**: -- Navigate to the `src/test/` directory -- Choose a test in your preferred language (Python, Java, Go, etc.) -- Run it and confirm that it connects successfully to the local GoodMem server and returns the expected output diff --git a/package.json b/package.json deleted file mode 100644 index 00bff91..0000000 --- a/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "goodmem-js-example", - "version": "1.0.0", - "description": "Automated dev environment for the GoodMem JS SDK", - "main": "index.js", - "type": "module", - "scripts": { - "start": "node index.js" - }, - "dependencies": { - "dotenv": "^16.4.5", - "goodmem": "0.1.0" - } -} diff --git a/social_media_study.pdf b/social_media_study.pdf new file mode 100644 index 0000000..0928e2e Binary files /dev/null and b/social_media_study.pdf differ diff --git a/src/test.js b/src/tests/test.js similarity index 100% rename from src/test.js rename to src/tests/test.js diff --git a/src/test.py b/src/tests/test.py similarity index 100% rename from src/test.py rename to src/tests/test.py