shraga 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -1
- package/defaults/agents/trace-extractor.md +1 -1
- package/defaults/extensions/stripe-webhook.ext.ts +29 -21
- package/defaults/scripts/agent-once.ts +1 -1
- package/defaults/skills/communications.md +1 -1
- package/defaults/skills/mcps-sync.md +2 -2
- package/defaults/skills/self-aware.md +1 -1
- package/dist/client/assets/{index-BoHttkMt.js → index-BnArwb7g.js} +43 -43
- package/dist/client/index.html +1 -1
- package/package.json +8 -5
- package/src/cli.ts +3 -1
- package/src/client/components/ArtifactPanel.tsx +16 -3
- package/src/index.ts +172 -0
- package/src/server/artifacts/artifacts.routes.ts +2 -19
- package/src/server/boot.ts +1779 -0
- package/src/server/engine/claude-code.ts +2 -2
- package/src/server/events/bus.ts +21 -5
- package/src/server/events/types.ts +26 -3
- package/src/server/events/webhook.ts +64 -0
- package/src/server/extensions.ts +34 -0
- package/src/server/hooks.ts +2 -2
- package/src/server/index.ts +8 -1712
- package/src/server/slack/bot.ts +1 -1
- package/src/server/slack/feature.ts +1 -1
- package/src/server/turn-context.ts +7 -0
- package/src/server/artifacts/artifacts.export.ts +0 -85
package/README.md
CHANGED
|
@@ -24,7 +24,8 @@ Give it its own machine, its own keys, its own identity. Onboard it once, then d
|
|
|
24
24
|
- ⭐ **Multi-user by design.** One Shraga serves a whole team, each with their own sessions,
|
|
25
25
|
tools, and permissions.
|
|
26
26
|
- ⭐ **A shared brain that compounds.** It onboards, learns your codebase and conventions, and
|
|
27
|
-
carries that knowledge forward
|
|
27
|
+
carries that knowledge forward via skills and sessions. The full org-wide capture is the
|
|
28
|
+
north star ([the shared brain](./docs/shared-brain.md)) — it opens in stages.
|
|
28
29
|
- **Chat with an agent** that has your workspace, shell, and tools.
|
|
29
30
|
- **Sessions** you can fork, resume, and revisit.
|
|
30
31
|
- **Skills**: reusable procedures you teach it once (files in `data/skills/`).
|
|
@@ -32,10 +33,71 @@ Give it its own machine, its own keys, its own identity. Onboard it once, then d
|
|
|
32
33
|
- **Schedules**: run agent jobs on a cron or in response to events.
|
|
33
34
|
- **Programmatic API + MCP endpoint**: drive the agent from scripts or from claude.ai.
|
|
34
35
|
|
|
36
|
+
## What's in the box
|
|
37
|
+
|
|
38
|
+
Shraga ships as a small core (this repo, the `shraga` npm package — "CE") plus two ways to grow it.
|
|
39
|
+
Capabilities fall into three tiers:
|
|
40
|
+
|
|
41
|
+
- **Built-in** — ships and runs in CE. Nothing to install; some need credentials configured.
|
|
42
|
+
- **Optional overlay** — an external add-on module loaded at startup via `SHRAGA_OVERLAY`. Not in
|
|
43
|
+
this repo; you bring or build it.
|
|
44
|
+
- **Bring-your-own** — you extend the core yourself through its seams (MCP, engine, skills, features).
|
|
45
|
+
|
|
46
|
+
### Built-in (ships in CE)
|
|
47
|
+
|
|
48
|
+
| Capability | What you get | Setup |
|
|
49
|
+
|-----------|--------------|-------|
|
|
50
|
+
| **Agent chat & sessions** | Chat with an agent that has your workspace, shell, and tools; fork, resume, and revisit sessions. | none |
|
|
51
|
+
| **Slack** | The agent is **active on Slack** — it replies in threads, manages reactions, handles uploaded files, resolves `@mentions`, and runs polls. Via the public [`mcp-slack-use`](https://github.com/Livshitz/mcp-slack-use) package. | Slack app + tokens |
|
|
52
|
+
| **Scheduler** | Cron schedules and event-triggered tasks that run agent jobs unattended. | none |
|
|
53
|
+
| **Events** | Generic event-bus ingress (`POST /api/events/:source`) that fires matching schedules. | none |
|
|
54
|
+
| **Push notifications** | Web and native push. | none |
|
|
55
|
+
| **Artifacts** | Render HTML artifacts from a session. (PNG export is overlay-only — see below.) | none |
|
|
56
|
+
| **MCP — both directions** | *Consume* external MCP servers to give the agent tools, **and** *expose* Shraga itself as an MCP endpoint (`POST /mcp`) so claude.ai and other clients can drive it. | per-server config |
|
|
57
|
+
| **Engine seam** | Pluggable agent runtime. Claude Code is the built-in engine. | none |
|
|
58
|
+
| **Auth** | Local username/password by default; Firebase optional (`AUTH_PROVIDER=firebase`). | none / Firebase config |
|
|
59
|
+
| **CLI** | `shraga` server bin plus `shraga user add <email> <password>` to seed a local user. | none |
|
|
60
|
+
|
|
61
|
+
### Optional overlay (add-on module, not in CE)
|
|
62
|
+
|
|
63
|
+
Loaded only when you point `SHRAGA_OVERLAY` at an external module. **None of these ship in this
|
|
64
|
+
repo** — a bare self-host does not get them out of the box:
|
|
65
|
+
|
|
66
|
+
| Capability | Notes |
|
|
67
|
+
|-----------|-------|
|
|
68
|
+
| **Email / Gmail** | Inbound email → agent sessions. **Not built-in** — overlay only. |
|
|
69
|
+
| **GitHub bot** | Issues/PRs → agent sessions with GH-native trust tiers. |
|
|
70
|
+
| **Voice** | Voice input/output. |
|
|
71
|
+
| **Fleet / multi-instance** | Blue-green and multi-instance orchestration. |
|
|
72
|
+
| **PNG artifact export** | Puppeteer-rendered PNGs of artifacts. |
|
|
73
|
+
|
|
74
|
+
### Bring-your-own (extend it yourself)
|
|
75
|
+
|
|
76
|
+
The core is deliberately small and grows through documented seams (see
|
|
77
|
+
[`AGENTS.md`](./AGENTS.md#the-extension-seams)):
|
|
78
|
+
|
|
79
|
+
| Seam | Use it for |
|
|
80
|
+
|------|-----------|
|
|
81
|
+
| **MCP servers** | Give the agent new tools, per-user or globally. |
|
|
82
|
+
| **Skills** (`data/skills/`) | Reusable procedures you teach the agent once. |
|
|
83
|
+
| **Engines** (`src/server/engine/`) | Swap or add agent runtimes behind the engine seam. |
|
|
84
|
+
| **Server features** (`src/server/features.ts`) | Mount new server-side surfaces via `registerFeature`. |
|
|
85
|
+
| **Client slots** (`src/client/lib/slots.tsx`) | Inject UI into typed render slots without touching core. |
|
|
86
|
+
| **Route extensions** (`data/extensions/*.ext.ts`) | Drop-in public routes (webhooks, OAuth callbacks) per deployment. |
|
|
87
|
+
| **`SHRAGA_OVERLAY`** | Load a whole external add-on module at startup (the overlay tier above). |
|
|
88
|
+
|
|
35
89
|
## Quickstart
|
|
36
90
|
|
|
37
91
|
Requires [Bun](https://bun.sh) ≥ 1.0.
|
|
38
92
|
|
|
93
|
+
**Fastest — run from npm:**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
bunx shraga # serve on http://localhost:3032, state in ./data/
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**From source (to develop or customize):**
|
|
100
|
+
|
|
39
101
|
```bash
|
|
40
102
|
# 1. Install & configure
|
|
41
103
|
bun install
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
// Example: a vendor webhook → event-trigger bridge.
|
|
1
|
+
// Example: a vendor webhook → event-trigger bridge, via the generic helper.
|
|
2
2
|
//
|
|
3
3
|
// A vendor (Stripe here) can't send shraga auth, so its webhook can't hit the
|
|
4
|
-
// generic POST /api/events/:source endpoint. Instead this extension
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// generic POST /api/events/:source endpoint. Instead this extension declares a
|
|
5
|
+
// webhook as DATA: ctx.registerWebhook({ source, verify }) mounts a PUBLIC route
|
|
6
|
+
// that verifies the vendor's OWN signature and, on success, emits the event —
|
|
7
|
+
// firing any enabled schedule with trigger { kind:'event', source:'stripe' }.
|
|
8
|
+
//
|
|
9
|
+
// The ONLY per-vendor code is `verify`. Dispatch, dedup (by event id), the route,
|
|
10
|
+
// and typing are all generic (src/server/events/webhook.ts).
|
|
7
11
|
//
|
|
8
12
|
// Pair it with a schedule (see the scheduler skill):
|
|
9
13
|
// { "trigger": { "kind":"event", "source":"stripe", "match":{ "type":"invoice.paid" } },
|
|
@@ -11,15 +15,24 @@
|
|
|
11
15
|
//
|
|
12
16
|
// DORMANT until STRIPE_WEBHOOK_SECRET is set — no route is registered without it,
|
|
13
17
|
// so this ships harmlessly enabled. Swap the verifier for any vendor's scheme.
|
|
14
|
-
import type { Express, Request
|
|
18
|
+
import type { Express, Request } from 'express';
|
|
15
19
|
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
16
20
|
|
|
21
|
+
// Minimal local shape of the loader's ctx (see src/server/extensions.ts).
|
|
22
|
+
interface WebhookOptions {
|
|
23
|
+
source: string;
|
|
24
|
+
verify: (req: Request, raw: string) => boolean | unknown;
|
|
25
|
+
normalize?: (req: Request) => unknown;
|
|
26
|
+
eventId?: (payload: unknown, req: Request) => string | undefined;
|
|
27
|
+
path?: string;
|
|
28
|
+
}
|
|
17
29
|
interface ExtensionContext {
|
|
18
30
|
dataPath: (p: string) => string;
|
|
19
31
|
requireAuth: any;
|
|
20
32
|
log: (...a: unknown[]) => void;
|
|
21
33
|
app: Express;
|
|
22
34
|
emitEvent: (source: string, payload: unknown, opts?: { id?: string }) => void;
|
|
35
|
+
registerWebhook: (opts: WebhookOptions) => string;
|
|
23
36
|
}
|
|
24
37
|
|
|
25
38
|
/** Minimal Stripe `Stripe-Signature` verification (t=…,v1=…) over the raw body. */
|
|
@@ -31,28 +44,23 @@ function verifyStripeSig(raw: string, header: string, secret: string): boolean {
|
|
|
31
44
|
try { return timingSafeEqual(Buffer.from(expected), Buffer.from(v1)); } catch { return false; }
|
|
32
45
|
}
|
|
33
46
|
|
|
34
|
-
export default function register(
|
|
47
|
+
export default function register(_app: Express, ctx: ExtensionContext) {
|
|
35
48
|
const secret = process.env.STRIPE_WEBHOOK_SECRET;
|
|
36
49
|
if (!secret) {
|
|
37
50
|
ctx.log('stripe-webhook extension dormant (set STRIPE_WEBHOOK_SECRET to enable)');
|
|
38
51
|
return;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// evt.id dedupes Stripe's retries; evt.type is what schedules `match` on.
|
|
52
|
-
const evt = req.body; // already parsed by the global JSON body parser
|
|
53
|
-
ctx.emitEvent('stripe', evt, { id: evt?.id });
|
|
54
|
-
res.json({ received: true });
|
|
54
|
+
// Stripe authenticates via its own signature, not shraga auth. The raw request
|
|
55
|
+
// bytes are read from req.rawBody (stashed by the global express.json in index.ts);
|
|
56
|
+
// `verify` returns true iff the signature matches. Payload = the parsed body, and
|
|
57
|
+
// its `id` dedupes Stripe's retries — both handled generically by registerWebhook.
|
|
58
|
+
const path = ctx.registerWebhook({
|
|
59
|
+
source: 'stripe',
|
|
60
|
+
// Keep the original public path (Stripe's dashboard points at /webhooks/stripe).
|
|
61
|
+
path: '/webhooks/stripe',
|
|
62
|
+
verify: (req, raw) => verifyStripeSig(raw, String(req.headers['stripe-signature'] ?? ''), secret),
|
|
55
63
|
});
|
|
56
64
|
|
|
57
|
-
ctx.log(
|
|
65
|
+
ctx.log(`stripe-webhook extension ready — POST ${path} → emitEvent("stripe")`);
|
|
58
66
|
}
|
|
@@ -19,7 +19,7 @@ if (argv[0] === '--uid') {
|
|
|
19
19
|
}
|
|
20
20
|
const prompt =
|
|
21
21
|
argv.join(' ').trim() ||
|
|
22
|
-
'Call mcp-slack tool get_slack_channels with limit=2 only. Output the JSON ok field and first channel name, nothing else.';
|
|
22
|
+
'Call mcp-slack-use tool get_slack_channels with limit=2 only. Output the JSON ok field and first channel name, nothing else.';
|
|
23
23
|
|
|
24
24
|
if (!process.env.ANTHROPIC_API_KEY?.trim()) {
|
|
25
25
|
console.error('Missing ANTHROPIC_API_KEY — cannot run Claude Agent SDK.');
|
|
@@ -12,7 +12,7 @@ Dedup applies only when **you** decide to reach out (not when fulfilling a user
|
|
|
12
12
|
|
|
13
13
|
1. **Read the comms log** — `Read data/comms-log.jsonl` (tail last 50-100 lines if large). If the file exceeds 500 lines, only read the last 100.
|
|
14
14
|
2. **Check for recent similar outreach** — same recipient + similar topic within the last 24h = skip or significantly alter the message
|
|
15
|
-
3. **For Slack** — the mcp-slack skill already requires reading channel history before posting (rule #6). That check + this log together cover both same-session and cross-session duplicates.
|
|
15
|
+
3. **For Slack** — the mcp-slack-use skill already requires reading channel history before posting (rule #6). That check + this log together cover both same-session and cross-session duplicates.
|
|
16
16
|
|
|
17
17
|
### What counts as a duplicate (proactive only)
|
|
18
18
|
|
|
@@ -83,7 +83,7 @@ Print a summary table:
|
|
|
83
83
|
|
|
84
84
|
```
|
|
85
85
|
MCP Sync Results:
|
|
86
|
-
mcp-slack up to date
|
|
86
|
+
mcp-slack-use up to date
|
|
87
87
|
mcp-firebase pulled 3 commits
|
|
88
88
|
mcp-pdf cloned (NEW)
|
|
89
89
|
mcp-cursor pushed 1, pulled 2
|
|
@@ -92,7 +92,7 @@ Missing env vars (add to .env):
|
|
|
92
92
|
mcp-stripe STRIPE_SECRET_KEY
|
|
93
93
|
mcp-gmail GOOGLE_SERVICE_ACCOUNT, GMAIL_USER_EMAIL
|
|
94
94
|
|
|
95
|
-
All configured: mcp-slack, mcp-firebase, mcp-google-drive
|
|
95
|
+
All configured: mcp-slack-use, mcp-firebase, mcp-google-drive
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
## Rules
|
|
@@ -85,7 +85,7 @@ List checkpoints with `git -C "$APP_DIR" log --oneline`; reset to any of them.
|
|
|
85
85
|
- `src/server/mcp.ts` — MCP server injection and config
|
|
86
86
|
- `src/server/skills.ts` — skill loading and injection
|
|
87
87
|
- `defaults/` — canonical source for runtime-seeded dirs (see Architecture skill § "Defaults → Runtime Seeding Pattern")
|
|
88
|
-
- `vendor/` — vendored MCP servers (mcp-firebase, mcp-github, mcp-slack, etc.)
|
|
88
|
+
- `vendor/` — vendored MCP servers (mcp-firebase, mcp-github, mcp-slack-use, etc.)
|
|
89
89
|
- `data/` — runtime data, git-tracked behavioral config via data-sync (skills, mcps, workspace, schedules, contacts, agent-config, whitelist)
|
|
90
90
|
|
|
91
91
|
## Where one-off / custom code goes (NOT main `src/`)
|