Skip to content
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
2 changes: 1 addition & 1 deletion apps/example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ It demonstrates:
- one local skill (`/example-local`)
- one plugin-bundled skill (`/example-bundle-help`)
- one bundle-only plugin (`app/plugins/example-bundle/plugin.yaml`) with no credential broker config
- installed plugin packages (`@sentry/junior-agent-browser`, `@sentry/junior-datadog`, `@sentry/junior-github`, `@sentry/junior-hex`, `@sentry/junior-linear`, `@sentry/junior-memory`, `@sentry/junior-notion`, `@sentry/junior-sentry`, `@sentry/junior-vercel`)
- installed plugin packages (`@sentry/junior-agent-browser`, `@sentry/junior-datadog`, `@sentry/junior-github`, `@sentry/junior-hex`, `@sentry/junior-linear`, `@sentry/junior-notion`, `@sentry/junior-sentry`, `@sentry/junior-vercel`)

## Run

Expand Down
2 changes: 2 additions & 0 deletions apps/example/app/skills/example-local/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ description: Provide a compact local example response. Use when users invoke /ex

1. Confirm the request in one sentence.
2. Return three bullets:

- what this app demonstrates
- what plugin-bundled skills add
- one practical next action

3. Keep the reply under 120 words.
5 changes: 2 additions & 3 deletions apps/example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"private": true,
"type": "module",
"scripts": {
"predev": "pnpm --filter @sentry/junior build && pnpm --filter @sentry/junior-dashboard build && pnpm --filter @sentry/junior-memory build",
"predev": "pnpm --filter @sentry/junior build && pnpm --filter @sentry/junior-dashboard build",
"dev": "cross-env NODE_OPTIONS=--import=./instrument.mjs nitro dev",
"prebuild": "pnpm --filter @sentry/junior build && pnpm --filter @sentry/junior-dashboard build && pnpm --filter @sentry/junior-memory build",
"prebuild": "pnpm --filter @sentry/junior build && pnpm --filter @sentry/junior-dashboard build",
"build": "junior snapshot create && nitro build",
"postbuild": "node scripts/check-vercel-output.mjs",
"preview": "cross-env NODE_OPTIONS=--import=./instrument.mjs nitro preview",
Expand All @@ -22,7 +22,6 @@
"@sentry/junior-github": "workspace:*",
"@sentry/junior-hex": "workspace:*",
"@sentry/junior-linear": "workspace:*",
"@sentry/junior-memory": "workspace:*",
"@sentry/junior-notion": "workspace:*",
"@sentry/junior-sentry": "workspace:*",
"@sentry/junior-vercel": "workspace:*",
Expand Down
2 changes: 0 additions & 2 deletions apps/example/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { defineJuniorPlugins } from "@sentry/junior";
import { githubPlugin } from "@sentry/junior-github";
import { linearPlugin } from "@sentry/junior-linear";
import { memoryPlugin } from "@sentry/junior-memory";
import { sentryPlugin } from "@sentry/junior-sentry";
import { vercelPlugin } from "@sentry/junior-vercel";

Expand All @@ -19,7 +18,6 @@ export const plugins = defineJuniorPlugins([
}),
"@sentry/junior-hex",
linearPlugin(),
memoryPlugin(),
"@sentry/junior-notion",
sentryPlugin(),
vercelPlugin(),
Expand Down
8 changes: 4 additions & 4 deletions ast-grep/rules/no-memory-semantic-regex.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ language: TypeScript
severity: error
message: Memory semantic decisions must stay agentic. Do not use regex classifiers in memory tools, policy, extraction, or agent modules.
files:
- packages/junior-memory/src/tools.ts
- packages/junior-memory/src/agent.ts
- packages/junior-memory/src/**/*policy*.ts
- packages/junior-memory/src/**/*extraction*.ts
- packages/junior/src/chat/memory/tools.ts
- packages/junior/src/chat/memory/agent.ts
- packages/junior/src/chat/memory/**/*policy*.ts
- packages/junior/src/chat/memory/**/*extraction*.ts
rule:
any:
- pattern: /$R/
Expand Down
6 changes: 3 additions & 3 deletions packages/docs/src/content/docs/cli/init.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ The command requires exactly one argument: the target directory.

The scaffold includes:

- `package.json` with `@sentry/junior`, `@sentry/junior-maintenance`, `@sentry/junior-memory`, `hono`, `nitro`, `typescript`, `jiti`, and `@types/node`
- `package.json` with `@sentry/junior`, `@sentry/junior-maintenance`, `hono`, `nitro`, `typescript`, `jiti`, and `@types/node`
- `pnpm-workspace.yaml` with a 24-hour dependency release delay and an immediate exception for the `@sentry/*` package scope
- `plugins.ts` with `@sentry/junior-maintenance` and `memoryPlugin()` enabled
- `plugins.ts` with `@sentry/junior-maintenance` enabled
- `server.ts`
- `nitro.config.ts` pointing at `./plugins`
- `tsconfig.json` extending Nitro's TypeScript config
Expand All @@ -43,7 +43,7 @@ The scaffold includes:

`SOUL.md` sets Junior's default voice, `WORLD.md` holds operational context, and `DESCRIPTION.md` powers the user-facing app description. Add other `app/*.md` files only when you want optional reference material available to the agent at runtime.

The generated `plugins.ts` enables `@sentry/junior-maintenance` and `memoryPlugin()` by default. Maintenance provides the `self-update` skill for keeping Junior packages current, and memory provides long-term recall once you configure Postgres with pgvector. `plugins.ts` is also the place to add other packaged plugins later.
The generated app includes core Memory by default. The generated `plugins.ts` enables `@sentry/junior-maintenance`, which provides the `self-update` skill. Add other packaged plugins in this file.

This gives you the supported app shape needed to run Junior locally, keep the app updated, and continue with plugin or skill setup.

Expand Down
48 changes: 13 additions & 35 deletions packages/docs/src/content/docs/extend/memory-plugin.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Memory Plugin
description: Configure the memory plugin for persistent long-term memory storage and recall.
title: Memory
description: Configure core Memory for persistent long-term memory storage and recall.
type: tutorial
summary: Set up pgvector-backed memory storage so Junior can recall preferences and context across conversations.
prerequisites:
Expand All @@ -10,50 +10,29 @@ related:
- /start-here/quickstart/
---

The memory plugin uses a Postgres database with the pgvector extension to store and retrieve long-term memories across conversations. Before each user turn, Junior combines semantic and full-text matches and includes only memories that directly help with the current request. The plugin also exposes explicit memory tools (remember, list, search, remove) and passively extracts memories from completed public-channel and local sessions.
Memory uses a Postgres database with the pgvector extension to store and retrieve long-term memories across conversations. Before each user turn, Junior combines semantic and full-text matches and includes only memories that directly help with the current request. Memory also exposes explicit memory tools (remember, list, search, remove) and passively extracts memories from completed public-channel and local sessions.

New apps created with `junior init` include `memoryPlugin()` in `plugins.ts` by default.
Memory is part of `@sentry/junior`. New apps created with `junior init` do not install or register a separate Memory package.

## Prerequisites

Provision a Postgres database with pgvector support before running migrations. The memory plugin migrations create the `vector` and `btree_gin` extensions, store 1536-dimensional embeddings, maintain a scope-aware full-text search index, and create an HNSW cosine index on embeddings for hybrid recall. Most managed Postgres providers — Neon, Supabase, Railway, and AWS RDS/Aurora PostgreSQL with pgvector enabled — support this out of the box.

## Install

Install the plugin package alongside `@sentry/junior`:

```bash
pnpm add @sentry/junior @sentry/junior-memory
```

## Runtime setup

The memory plugin requires a factory function call to register its tools and session hooks. Add `memoryPlugin()` to the plugin set exported from `plugins.ts`:

```ts title="plugins.ts"
import { defineJuniorPlugins } from "@sentry/junior";
import { memoryPlugin } from "@sentry/junior-memory";

export const plugins = defineJuniorPlugins([memoryPlugin()]);
```

Do not register `@sentry/junior-memory` as a bare package-name string. The memory plugin uses `defineJuniorPlugin` with runtime hooks for tool registration and session processing; a bare string skips those hooks and the plugin will not activate its runtime behavior.
Provision a Postgres database with pgvector support before running migrations. Core migrations create the `vector` and `btree_gin` extensions, store 1536-dimensional embeddings, maintain a scope-aware full-text search index, and create an HNSW cosine index on embeddings for hybrid recall. Most managed Postgres providers — Neon, Supabase, Railway, and AWS RDS/Aurora PostgreSQL with pgvector enabled — support this out of the box.

## Config

Pass plugin options to `memoryPlugin({ ... })` in `plugins.ts`. Set deployment variables in the Junior environment, then redeploy.
Pass Memory options to `createApp({ memory: { ... } })`. Set deployment variables in the Junior environment, then redeploy.

### Plugin options
### Memory options

<details class="plugin-config">
<summary><code>modelId</code></summary>

Model used for memory classification, consolidation, and automatic recall relevance.

- **Define:** `memoryPlugin({ modelId: "anthropic/claude-sonnet-4-5" })` in `plugins.ts`
- **Define:** `createApp({ memory: { modelId: "anthropic/claude-sonnet-4-5" } })`
- **Default:** The app's structured model
- **Required:** No
- **Environment override:** `AI_MEMORY_MODEL`; the plugin option takes precedence
- **Environment override:** `AI_MEMORY_MODEL`; the app option takes precedence

</details>

Expand All @@ -62,7 +41,7 @@ Model used for memory classification, consolidation, and automatic recall releva

Disables automatic prompt recall while keeping explicit memory tools available.

- **Define:** `memoryPlugin({ disableRecall: true })` in `plugins.ts`
- **Define:** `createApp({ memory: { disableRecall: true } })`
- **Default:** `false`
- **Required:** No
- **Environment override:** None
Expand All @@ -74,7 +53,7 @@ Disables automatic prompt recall while keeping explicit memory tools available.

Disables passive memory extraction from completed sessions while keeping explicit memory tools available.

- **Define:** `memoryPlugin({ disableExtraction: true })` in `plugins.ts`
- **Define:** `createApp({ memory: { disableExtraction: true } })`
- **Default:** `false`
- **Required:** No
- **Environment override:** None
Expand Down Expand Up @@ -147,7 +126,7 @@ explains whether Junior learned it automatically or saved it because the user
asked. Overview groups the viewer's active memories by type and how they were
added. Forgetting archives the memory so Junior no longer recalls it.

The plugin also exposes authenticated REST resources:
Memory also exposes authenticated REST resources:

| Method | Path | Purpose |
| -------- | ---------------------------------- | --------------------------------------------- |
Expand All @@ -161,7 +140,7 @@ authenticated dashboard browser session.

## Run migrations

After setting `DATABASE_URL`, run the upgrade command to apply the memory plugin schema:
After setting `DATABASE_URL`, run the upgrade command to apply the Memory schema:

```bash
pnpm junior upgrade
Expand Down Expand Up @@ -195,7 +174,6 @@ Public Slack channel memories are workspace-visible. A durable fact remembered i

## Failure modes

- **Plugin not active after registration**: `@sentry/junior-memory` was registered as a bare string instead of `memoryPlugin()`. Switch to the factory call and redeploy.
- **Migration error — extension "vector" does not exist**: the Postgres database does not have pgvector available. Use a provider that supports pgvector or install it manually with `CREATE EXTENSION vector`.
- **Migration error — extension "btree_gin" does not exist**: the Postgres database does not include the standard `btree_gin` extension. Enable it with your provider or install it manually with `CREATE EXTENSION btree_gin`.
- **`DATABASE_URL` is required**: no database URL is configured. Set it in the deployment environment.
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/content/docs/reference/config-and-env.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ Each profile value may be a model id string or an object with `modelId` and opti

Set `profiles` and `defaultProfile` together. Pass auxiliary model ids on the same `createApp()` options object. App config replaces profiles from env settings and overrides auxiliary model env settings. If app config omits both profile options, the deprecated env settings create `standard` and `handoff` profiles with default task-fit descriptions. `AI_MODEL_PROFILES` can add or replace those profiles and may use the same string or object shape.

The memory model belongs to the memory plugin. Set it with `memoryPlugin({ modelId })` in the plugin set.
Set the Memory model with `createApp({ memory: { modelId } })`. `AI_MEMORY_MODEL` remains the environment fallback.

## Install-wide config defaults

Expand Down
46 changes: 22 additions & 24 deletions packages/docs/src/content/docs/start-here/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Use the same baseline that the scaffolded CI workflow uses:

- Node.js 24
- pnpm
- A Postgres database for Junior SQL records and the default memory plugin
- A Postgres database for Junior SQL records and the core Memory
- A Redis URL for runtime state, locks, and durable automation records

Slack credentials are needed before the bot can reply in Slack. You can scaffold and verify the local health route first, then finish [Slack App Setup](/start-here/slack-app-setup/).
Expand Down Expand Up @@ -65,27 +65,27 @@ node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'

Set these values before running real turns:

| Variable | Required | Purpose |
| ------------------------- | ---------------------- | ------------------------------------------------------------- |
| `SLACK_SIGNING_SECRET` | Yes, for Slack traffic | Verifies Slack requests. |
| `SLACK_BOT_TOKEN` | Yes, for Slack replies | Posts thread replies and calls Slack APIs. |
| `DATABASE_URL` | Yes | Postgres connection string for Junior SQL records and memory. |
| `JUNIOR_DATABASE_DRIVER` | No | SQL client driver: `neon` or `postgres`. |
| `REDIS_URL` | Yes | Runtime state, locks, and durable background automation records. |
| `JUNIOR_SECRET` | Yes | Signs internal resume callbacks and sandbox actor context. |
| `JUNIOR_BOT_NAME` | No | Bot display/config name. |
| `JUNIOR_SLASH_COMMAND` | No | Slack slash command name. Defaults to `/jr`. |
| `AI_MODEL` | No | Deprecated default model setting. |
| `AI_FAST_MODEL` | No | Lightweight routing/classification model override. |
| `AI_HANDOFF_MODEL` | No | Deprecated handoff model setting. |
| `AI_MODEL_PROFILES` | No | Deprecated JSON map of named profiles. |
| `AI_EMBEDDING_MODEL` | No | Embedding model override for plugin vector retrieval. |
| `AI_VISION_MODEL` | No | Enables image understanding when set. |
| `AI_WEB_SEARCH_MODEL` | No | Search model override. |
| `JUNIOR_STATE_KEY_PREFIX` | No | Redis key namespace for this local app/environment. |
| Variable | Required | Purpose |
| ------------------------- | ---------------------- | ---------------------------------------------------------------- |
| `SLACK_SIGNING_SECRET` | Yes, for Slack traffic | Verifies Slack requests. |
| `SLACK_BOT_TOKEN` | Yes, for Slack replies | Posts thread replies and calls Slack APIs. |
| `DATABASE_URL` | Yes | Postgres connection string for Junior SQL records and memory. |
| `JUNIOR_DATABASE_DRIVER` | No | SQL client driver: `neon` or `postgres`. |
| `REDIS_URL` | Yes | Runtime state, locks, and durable background automation records. |
| `JUNIOR_SECRET` | Yes | Signs internal resume callbacks and sandbox actor context. |
| `JUNIOR_BOT_NAME` | No | Bot display/config name. |
| `JUNIOR_SLASH_COMMAND` | No | Slack slash command name. Defaults to `/jr`. |
| `AI_MODEL` | No | Deprecated default model setting. |
| `AI_FAST_MODEL` | No | Lightweight routing/classification model override. |
| `AI_HANDOFF_MODEL` | No | Deprecated handoff model setting. |
| `AI_MODEL_PROFILES` | No | Deprecated JSON map of named profiles. |
| `AI_EMBEDDING_MODEL` | No | Embedding model override for plugin vector retrieval. |
| `AI_VISION_MODEL` | No | Enables image understanding when set. |
| `AI_WEB_SEARCH_MODEL` | No | Search model override. |
| `JUNIOR_STATE_KEY_PREFIX` | No | Redis key namespace for this local app/environment. |

See [Config & Environment](/reference/config-and-env/) for the full reference.
If you keep the default memory plugin enabled, use a Postgres database with
If you keep the core Memory enabled, use a Postgres database with
pgvector support before running migrations. Local Postgres URLs automatically
use the `postgres` driver; set `JUNIOR_DATABASE_DRIVER=postgres` for other
non-Neon Postgres providers.
Expand Down Expand Up @@ -119,24 +119,22 @@ New apps created with `junior init` already have a `plugins.ts` file with mainte
For an existing app created without a `plugins.ts`, create one as shown below.

Install only the plugins you plan to enable. If you are creating `plugins.ts`
for an existing app, include the default maintenance and memory packages too:
for an existing app, include the default maintenance package too:

```bash
pnpm add @sentry/junior-maintenance @sentry/junior-memory @sentry/junior-agent-browser @sentry/junior-amplitude @sentry/junior-cloudflare @sentry/junior-datadog @sentry/junior-github @sentry/junior-hex @sentry/junior-linear @sentry/junior-notion @sentry/junior-sentry @sentry/junior-vercel
pnpm add @sentry/junior-maintenance @sentry/junior-agent-browser @sentry/junior-amplitude @sentry/junior-cloudflare @sentry/junior-datadog @sentry/junior-github @sentry/junior-hex @sentry/junior-linear @sentry/junior-notion @sentry/junior-sentry @sentry/junior-vercel
```

Add them to the plugin set in `plugins.ts`:

```ts title="plugins.ts"
import { defineJuniorPlugins } from "@sentry/junior";
import { memoryPlugin } from "@sentry/junior-memory";
import { githubPlugin } from "@sentry/junior-github";
import { linearPlugin } from "@sentry/junior-linear";
import { sentryPlugin } from "@sentry/junior-sentry";
import { vercelPlugin } from "@sentry/junior-vercel";

export const plugins = defineJuniorPlugins([
memoryPlugin(),
"@sentry/junior-maintenance",
"@sentry/junior-agent-browser",
"@sentry/junior-amplitude",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ describe("dashboard plugin routes", () => {
plugins: defineJuniorPlugins([
defineJuniorPlugin({
manifest: {
name: "memory",
displayName: "Memory",
description: "Memory plugin",
name: "demo",
displayName: "Demo",
description: "Demo plugin",
},
hooks: {
apiRoutes() {
Expand All @@ -110,7 +110,7 @@ describe("dashboard plugin routes", () => {
});

const response = await app.fetch(
new Request("http://localhost/api/plugins/memory/memories"),
new Request("http://localhost/api/plugins/demo/memories"),
);
expect(response.status).toBe(200);
await expect(response.json()).resolves.toEqual({
Expand Down
Loading
Loading