Skip to content
Merged
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
66 changes: 63 additions & 3 deletions .github/workflows/explorer-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,44 +22,104 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: sensibledb-explorer/src/frontend/pnpm-lock.yaml

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-apple-darwin

- name: Install frontend dependencies
run: |
cd sensibledb-explorer/src/frontend
pnpm install

- name: Install Tauri CLI
run: cargo install tauri-cli --version "^2"

- name: Build .app and .dmg
run: |
cd sensibledb-explorer
cargo tauri build --bundles app,dmg --target aarch64-apple-darwin
- name: Re-sign app bundle

- name: Import Apple Certificate (if secrets available)
if: env.APPLE_CERTIFICATE != ''
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
# Create temporary keychain
security create-keychain -p "" build.keychain
security set-keychain-settings build.keychain

# Decode and import certificate
echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12
security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12

# Fix keychain partition list
security set-key-partition-list -S apple-tool:,apple: -k "" build.keychain

- name: Sign and Notarize App (if secrets available)
if: env.APPLE_ID != ''
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
APP_DIR="target/aarch64-apple-darwin/release/bundle/macos/SensibleDB Explorer.app"

# Sign with hardened runtime and entitlements
codesign --deep --force --verify \
--sign "$APPLE_SIGNING_IDENTITY" \
--options runtime \
--entitlements sensibledb-explorer/entitlements.plist \
"$APP_DIR"

# Create DMG
hdiutil create -volname "SensibleDB Explorer" \
-srcfolder "$APP_DIR" \
-ov -format UDZO \
"target/aarch64-apple-darwin/release/bundle/dmg/SensibleDB-Explorer.dmg"

# Notarize (requires Apple Developer account)
xcrun notarytool submit "target/aarch64-apple-darwin/release/bundle/dmg/SensibleDB-Explorer.dmg" \
--apple-id "$APPLE_ID" \
--password "$APPLE_PASSWORD" \
--team-id "$APPLE_TEAM_ID" \
--wait

# Staple the notarization ticket
xcrun stapler staple "target/aarch64-apple-darwin/release/bundle/dmg/SensibleDB-Explorer.dmg"

- name: Re-sign app bundle (fallback without signing)
if: env.APPLE_SIGNING_IDENTITY == ''
run: |
APP_DIR="target/aarch64-apple-darwin/release/bundle/macos/SensibleDB Explorer.app"
codesign --force --deep --sign - --preserve-metadata=entitlements,identifier,flags "$APP_DIR"

- name: Zip .app bundle
run: |
APP_DIR="target/aarch64-apple-darwin/release/bundle/macos/SensibleDB Explorer.app"
zip -r -y "target/aarch64-apple-darwin/release/bundle/macos/SensibleDB-Explorer-aarch64.app.zip" "$APP_DIR"

- name: Release
uses: softprops/action-gh-release@v2
with:
files: |
target/aarch64-apple-darwin/release/bundle/macos/SensibleDB-Explorer-aarch64.app.zip
target/aarch64-apple-darwin/release/bundle/dmg/SensibleDB Explorer_*.dmg
target/aarch64-apple-darwin/release/bundle/dmg/SensibleDB-Explorer.dmg
draft: false
prerelease: false
generate_release_notes: true
generate_release_notes: true
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ If you're looking for a personal app to help you organize and search through you

### Quick Start (Explorer UI)

1. Download SensibleDB Explorer for macOS
1. [Download SensibleDB Explorer for macOS](https://github.com/Sensible-Analytics/SensibleDB/releases)
2. Launch the app
3. Click "Add Folder" and select your documents folder
4. Start chatting with your documents
Expand Down
181 changes: 181 additions & 0 deletions docs/getting-started/agent-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# AI Agent Integration Guide

SensibleDB can serve as a knowledge base and memory store for AI agents. This guide shows how to connect agents to your local SensibleDB instance.

## Why Use SensibleDB for AI Agents?

- **Local-First**: No data leaves your machine
- **Graph + Vectors**: Combine relationship reasoning with semantic search
- **Type-Safe Queries**: Catch errors at compile time
- **No External APIs**: Works completely offline

## Architecture Overview

```
┌─────────────────────────────────────────────────────┐
│ Your AI Agent │
│ (Claude, GPT, etc.) │
└────────────────────────┬────────────────────────────┘
│ HTTP
┌─────────────────────────────────────────────────────┐
│ SensibleDB (localhost:6969) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Graph │ │ Vector │ │ Query │ │
│ │ Storage │ │ Storage │ │ Engine │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────┘
```

## Setup

### 1. Start SensibleDB

```bash
nexus push dev
```

The API is now available at `http://localhost:6969`

### 2. Define Your Schema

In `db/schema.hx`:

```sensibleql
N::Memory {
INDEX id: String,
content: String,
created_at: Date
}

N::Context {
INDEX id: String,
summary: String
}

E::RELATED_TO {
From: Memory,
To: Memory
}

E::PART_OF {
From: Memory,
To: Context
}
```

### 3. Write Query Functions

In `db/queries.hx`:

```sensibleql
QUERY storeMemory(memory_id: String, content: String) =>
mem <- AddN<Memory>({id: memory_id, content: content, created_at: NOW()})
RETURN mem

QUERY storeContext(context_id: String, summary: String) =>
ctx <- AddN<Context>({id: context_id, summary: summary})
RETURN ctx

QUERY linkMemories(from_id: String, to_id: String) =>
edge <- AddE<RELATED_TO>({})::From(from_id)::To(to_id)
RETURN edge

QUERY findRelatedMemories(memory_id: String) =>
memory <- N<Memory>({id: memory_id})
related <- TRAVERSE memory -[RELATED_TO]-> m
RETURN related

QUERY semanticSearch(query: String, limit: U32) =>
results <- SearchV<Memory>({vector: Embed(query), limit: limit})
RETURN results
```

## Integration Examples

### Python Agent

```python
import requests

class SensibleDBAgent:
def __init__(self, base_url="http://localhost:6969"):
self.base_url = base_url

def store_context(self, memory_id: str, content: str):
response = requests.post(
f"{self.base_url}/storeMemory",
json={"memory_id": memory_id, "content": content}
)
return response.json()

def retrieve_context(self, query: str, limit: int = 5):
response = requests.post(
f"{self.base_url}/semanticSearch",
json={"query": query, "limit": limit}
)
return response.json()

def find_related(self, memory_id: str):
response = requests.post(
f"{self.base_url}/findRelatedMemories",
json={"memory_id": memory_id}
)
return response.json()

# Usage
agent = SensibleDBAgent()
agent.store_context("session-001", "User prefers dark mode UI")
results = agent.retrieve_context("user preferences")
```

### TypeScript Agent

```typescript
class SensibleDBAgent {
private baseUrl: string;

constructor(baseUrl = "http://localhost:6969") {
this.baseUrl = baseUrl;
}

async storeMemory(memoryId: string, content: string) {
const response = await fetch(`${this.baseUrl}/storeMemory`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ memory_id: memoryId, content })
});
return response.json();
}

async search(query: string, limit = 5) {
const response = await fetch(`${this.baseUrl}/semanticSearch`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, limit })
});
return response.json();
}
}

// Usage
const agent = new SensibleDBAgent();
await agent.storeMemory("conversation-001", "User asked about pricing");
const results = await agent.search("pricing information");
```

## MCP Integration *(Coming Soon)*

The MCP (Model Context Protocol) server integration is coming soon. This will allow direct agent-to-database communication through the MCP protocol.

## Best Practices

1. **Batch writes** — Store multiple memories in one request
2. **Use indexes** — Index frequently queried fields
3. **Link related items** — Use edges for relationship tracking
4. **Semantic search** — Combine vector search with graph traversal

---

**Need Help?**
[Open an issue](https://github.com/Sensible-Analytics/SensibleDB/issues)
Loading
Loading