@possumtech/rummy 0.2.1
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/.env.example +55 -0
- package/LICENSE +21 -0
- package/PLUGINS.md +302 -0
- package/README.md +41 -0
- package/SPEC.md +524 -0
- package/lang/en.json +34 -0
- package/migrations/001_initial_schema.sql +226 -0
- package/package.json +54 -0
- package/service.js +143 -0
- package/src/agent/AgentLoop.js +553 -0
- package/src/agent/ContextAssembler.js +29 -0
- package/src/agent/KnownStore.js +254 -0
- package/src/agent/ProjectAgent.js +101 -0
- package/src/agent/ResponseHealer.js +134 -0
- package/src/agent/TurnExecutor.js +457 -0
- package/src/agent/XmlParser.js +247 -0
- package/src/agent/known_checks.sql +42 -0
- package/src/agent/known_queries.sql +80 -0
- package/src/agent/known_store.sql +161 -0
- package/src/agent/messages.js +17 -0
- package/src/agent/prompt_queue.sql +39 -0
- package/src/agent/runs.sql +114 -0
- package/src/agent/schemes.sql +3 -0
- package/src/agent/sessions.sql +51 -0
- package/src/agent/tokens.js +28 -0
- package/src/agent/turns.sql +36 -0
- package/src/hooks/HookRegistry.js +72 -0
- package/src/hooks/Hooks.js +115 -0
- package/src/hooks/PluginContext.js +116 -0
- package/src/hooks/RummyContext.js +181 -0
- package/src/hooks/ToolRegistry.js +83 -0
- package/src/llm/LlmProvider.js +107 -0
- package/src/llm/OllamaClient.js +88 -0
- package/src/llm/OpenAiClient.js +80 -0
- package/src/llm/OpenRouterClient.js +78 -0
- package/src/llm/XaiClient.js +113 -0
- package/src/plugins/ask_user/README.md +18 -0
- package/src/plugins/ask_user/ask_user.js +48 -0
- package/src/plugins/ask_user/docs.md +2 -0
- package/src/plugins/cp/README.md +18 -0
- package/src/plugins/cp/cp.js +55 -0
- package/src/plugins/cp/docs.md +2 -0
- package/src/plugins/current/README.md +14 -0
- package/src/plugins/current/current.js +48 -0
- package/src/plugins/engine/README.md +12 -0
- package/src/plugins/engine/engine.sql +18 -0
- package/src/plugins/engine/turn_context.sql +51 -0
- package/src/plugins/env/README.md +14 -0
- package/src/plugins/env/docs.md +2 -0
- package/src/plugins/env/env.js +32 -0
- package/src/plugins/file/README.md +25 -0
- package/src/plugins/file/file.js +85 -0
- package/src/plugins/get/README.md +19 -0
- package/src/plugins/get/docs.md +6 -0
- package/src/plugins/get/get.js +53 -0
- package/src/plugins/hedberg/README.md +72 -0
- package/src/plugins/hedberg/docs.md +9 -0
- package/src/plugins/hedberg/edits.js +65 -0
- package/src/plugins/hedberg/hedberg.js +89 -0
- package/src/plugins/hedberg/matcher.js +181 -0
- package/src/plugins/hedberg/normalize.js +41 -0
- package/src/plugins/hedberg/patterns.js +452 -0
- package/src/plugins/hedberg/sed.js +48 -0
- package/src/plugins/helpers.js +22 -0
- package/src/plugins/index.js +180 -0
- package/src/plugins/instructions/README.md +11 -0
- package/src/plugins/instructions/instructions.js +37 -0
- package/src/plugins/instructions/preamble.md +12 -0
- package/src/plugins/known/README.md +18 -0
- package/src/plugins/known/docs.md +3 -0
- package/src/plugins/known/known.js +57 -0
- package/src/plugins/mv/README.md +18 -0
- package/src/plugins/mv/docs.md +2 -0
- package/src/plugins/mv/mv.js +56 -0
- package/src/plugins/previous/README.md +15 -0
- package/src/plugins/previous/previous.js +50 -0
- package/src/plugins/progress/README.md +17 -0
- package/src/plugins/progress/progress.js +44 -0
- package/src/plugins/prompt/README.md +16 -0
- package/src/plugins/prompt/prompt.js +45 -0
- package/src/plugins/rm/README.md +18 -0
- package/src/plugins/rm/docs.md +4 -0
- package/src/plugins/rm/rm.js +51 -0
- package/src/plugins/rpc/README.md +45 -0
- package/src/plugins/rpc/rpc.js +587 -0
- package/src/plugins/set/README.md +32 -0
- package/src/plugins/set/docs.md +4 -0
- package/src/plugins/set/set.js +268 -0
- package/src/plugins/sh/README.md +18 -0
- package/src/plugins/sh/docs.md +2 -0
- package/src/plugins/sh/sh.js +32 -0
- package/src/plugins/skills/README.md +25 -0
- package/src/plugins/skills/skills.js +175 -0
- package/src/plugins/store/README.md +20 -0
- package/src/plugins/store/docs.md +5 -0
- package/src/plugins/store/store.js +52 -0
- package/src/plugins/summarize/README.md +18 -0
- package/src/plugins/summarize/docs.md +4 -0
- package/src/plugins/summarize/summarize.js +24 -0
- package/src/plugins/telemetry/README.md +19 -0
- package/src/plugins/telemetry/rpc_log.sql +28 -0
- package/src/plugins/telemetry/telemetry.js +186 -0
- package/src/plugins/unknown/README.md +23 -0
- package/src/plugins/unknown/docs.md +5 -0
- package/src/plugins/unknown/unknown.js +31 -0
- package/src/plugins/update/README.md +18 -0
- package/src/plugins/update/docs.md +4 -0
- package/src/plugins/update/update.js +24 -0
- package/src/server/ClientConnection.js +228 -0
- package/src/server/RpcRegistry.js +52 -0
- package/src/server/SocketServer.js +43 -0
- package/src/sql/file_constraints.sql +15 -0
- package/src/sql/functions/countTokens.js +7 -0
- package/src/sql/functions/hedmatch.js +8 -0
- package/src/sql/functions/hedreplace.js +8 -0
- package/src/sql/functions/hedsearch.js +8 -0
- package/src/sql/functions/schemeOf.js +7 -0
- package/src/sql/functions/slugify.js +6 -0
- package/src/sql/v_model_context.sql +101 -0
- package/src/sql/v_run_log.sql +23 -0
package/.env.example
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Service Configuration
|
|
2
|
+
PORT=3044
|
|
3
|
+
|
|
4
|
+
# Absolute path, no ~
|
|
5
|
+
# RUMMY_HOME=/home/ubuntu/.rummy
|
|
6
|
+
|
|
7
|
+
RUMMY_DB_PATH=./rummy.db
|
|
8
|
+
# SQLite mmap size in MB
|
|
9
|
+
RUMMY_MMAP_MB=256
|
|
10
|
+
|
|
11
|
+
# Agent Loop Limits
|
|
12
|
+
RUMMY_MAX_TURNS=99
|
|
13
|
+
RUMMY_MAX_UNKNOWN_WARNINGS=3
|
|
14
|
+
RUMMY_MAX_REPETITIONS=3
|
|
15
|
+
|
|
16
|
+
# Hygiene
|
|
17
|
+
# Days to keep completed/aborted runs before purging
|
|
18
|
+
RUMMY_RETENTION_DAYS=31
|
|
19
|
+
|
|
20
|
+
# Timeouts (ms)
|
|
21
|
+
RUMMY_RPC_TIMEOUT=30000
|
|
22
|
+
RUMMY_FETCH_TIMEOUT=120000
|
|
23
|
+
|
|
24
|
+
# Model Behavior
|
|
25
|
+
# LLM temperature (0 = deterministic, 0.7 = creative). Client can override per-request.
|
|
26
|
+
RUMMY_TEMPERATURE=0.5
|
|
27
|
+
|
|
28
|
+
# Provider Configuration
|
|
29
|
+
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
|
|
30
|
+
# OPENROUTER_API_KEY=
|
|
31
|
+
RUMMY_HTTP_REFERER=https://github.com/possumtech/rummy
|
|
32
|
+
# RUMMY_X_TITLE shows your app name in OpenRouter dashboards/rankings
|
|
33
|
+
RUMMY_X_TITLE=RUMMY
|
|
34
|
+
|
|
35
|
+
OLLAMA_BASE_URL="http://127.0.0.1:11434"
|
|
36
|
+
|
|
37
|
+
# OPENAI_BASE_URL="http://127.0.0.1:11434"
|
|
38
|
+
# OPENAI_API_KEY=
|
|
39
|
+
|
|
40
|
+
XAI_BASE_URL="https://api.x.ai/v1/responses"
|
|
41
|
+
# XAI_API_KEY=""
|
|
42
|
+
|
|
43
|
+
# Model Aliases (Optional)
|
|
44
|
+
RUMMY_MODEL_g420="x.ai/grok-4.20-reasoning-latest"
|
|
45
|
+
RUMMY_MODEL_grok="x.ai/grok-4-1-fast-reasoning-latest"
|
|
46
|
+
|
|
47
|
+
# Necessary for automated testing
|
|
48
|
+
# RUMMY_TEST_MODEL=grok
|
|
49
|
+
|
|
50
|
+
# Web Search
|
|
51
|
+
# RUMMY_SEARXNG_URL="http://127.0.0.1:8888"
|
|
52
|
+
|
|
53
|
+
# External plugins (npm packages with register() export)
|
|
54
|
+
# RUMMY_PLUGIN_WEB="@possumtech/rummy.web"
|
|
55
|
+
# RUMMY_PLUGIN_REPO="@possumtech/rummy.repo"
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PossumTech Laboratories
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PLUGINS.md
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# PLUGINS.md — Plugin Development Guide
|
|
2
|
+
|
|
3
|
+
## Plugin Contract
|
|
4
|
+
|
|
5
|
+
A plugin is a directory under `src/plugins/` containing a `.js` file that
|
|
6
|
+
exports a default class. The class name matches the file name. The
|
|
7
|
+
constructor receives `core` (a PluginContext) — the plugin's complete
|
|
8
|
+
interface with the system.
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
export default class MyTool {
|
|
12
|
+
#core;
|
|
13
|
+
|
|
14
|
+
constructor(core) {
|
|
15
|
+
this.#core = core;
|
|
16
|
+
core.on("handler", this.handler.bind(this));
|
|
17
|
+
core.on("full", this.full.bind(this));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async handler(entry, rummy) {
|
|
21
|
+
// What the tool does (rummy is per-turn RummyContext)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
full(entry) {
|
|
25
|
+
// What the model sees at full fidelity
|
|
26
|
+
return `# mytool ${entry.path}\n${entry.body}`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
File naming: `src/plugins/mytool/mytool.js`. Class name = file name.
|
|
32
|
+
|
|
33
|
+
External plugins install via npm and load via `RUMMY_PLUGIN_*` env vars:
|
|
34
|
+
|
|
35
|
+
```env
|
|
36
|
+
RUMMY_PLUGIN_WEB=@possumtech/rummy.web
|
|
37
|
+
RUMMY_PLUGIN_REPO=@possumtech/rummy.repo
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Unified API
|
|
41
|
+
|
|
42
|
+
The model, the client, and plugins all use the same interface. Each tier
|
|
43
|
+
is a superset of the one below. `name` (model) = `method` (client) =
|
|
44
|
+
method name (plugin). The params shape is the same at every tier.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Model: <rm path="file.txt"/> → { name: "rm", path: "file.txt" }
|
|
48
|
+
Client: { method: "rm", params: { path: "file.txt" } }
|
|
49
|
+
Plugin: rummy.rm({ path: "file.txt" })
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Registration
|
|
53
|
+
|
|
54
|
+
All registration happens in the constructor via `core.on()` and
|
|
55
|
+
`core.filter()`. No static methods. No direct hook manipulation.
|
|
56
|
+
|
|
57
|
+
### core.on(event, callback, priority?)
|
|
58
|
+
|
|
59
|
+
| Event | Purpose |
|
|
60
|
+
|-------|---------|
|
|
61
|
+
| `"handler"` | Tool handler — called when model/client invokes this tool |
|
|
62
|
+
| `"full"` | Full projection — what the model sees at full fidelity |
|
|
63
|
+
| `"summary"` | Summary projection — condensed view under token pressure |
|
|
64
|
+
| `"docs"` | Tool documentation — included in model prompt |
|
|
65
|
+
| `"turn"` | Turn processor — runs before context materialization |
|
|
66
|
+
| `"entry.created"` | Entry created during dispatch |
|
|
67
|
+
| `"entry.changed"` | File entries changed on disk |
|
|
68
|
+
| Any `"dotted.name"` | Resolves to the matching hook in the hook tree |
|
|
69
|
+
|
|
70
|
+
### core.filter(name, callback, priority?)
|
|
71
|
+
|
|
72
|
+
| Filter | Purpose |
|
|
73
|
+
|--------|---------|
|
|
74
|
+
| `"assembly.system"` | Contribute to system message |
|
|
75
|
+
| `"assembly.user"` | Contribute to user message |
|
|
76
|
+
| `"llm.messages"` | Transform final messages before LLM call |
|
|
77
|
+
| `"llm.response"` | Transform LLM response |
|
|
78
|
+
| Any `"dotted.name"` | Resolves to the matching filter in the hook tree |
|
|
79
|
+
|
|
80
|
+
### handler(entry, rummy)
|
|
81
|
+
|
|
82
|
+
The handler receives the parsed command entry and a per-turn RummyContext:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
entry = {
|
|
86
|
+
scheme, // Tool name ("set", "get", "rm", etc.)
|
|
87
|
+
path, // Entry path ("set://src/app.js")
|
|
88
|
+
body, // Tag body text
|
|
89
|
+
attributes, // Parsed tag attributes
|
|
90
|
+
state, // Current state
|
|
91
|
+
resultPath, // Where to write the result
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Multiple handlers per scheme. Lower priority runs first. Return `false`
|
|
96
|
+
to stop the chain.
|
|
97
|
+
|
|
98
|
+
### full(entry) / summary(entry)
|
|
99
|
+
|
|
100
|
+
Returns the string the model sees for this tool's entries at the given
|
|
101
|
+
fidelity. Called during materialization. Every tool MUST register `full`.
|
|
102
|
+
`summary` is optional — if unregistered, the entry is invisible at summary
|
|
103
|
+
fidelity (no fallback).
|
|
104
|
+
|
|
105
|
+
## Two Objects
|
|
106
|
+
|
|
107
|
+
Plugins interact with two objects at different scopes:
|
|
108
|
+
|
|
109
|
+
**PluginContext** (`this.#core`) — startup-scoped. Created once per plugin.
|
|
110
|
+
Used for registration (`on()`, `filter()`), database access, store queries.
|
|
111
|
+
Lives for the lifetime of the service. This is `rummy.core` — the
|
|
112
|
+
plugin-only tier that clients cannot reach.
|
|
113
|
+
|
|
114
|
+
**RummyContext** (`rummy` argument) — turn-scoped. Passed to handlers
|
|
115
|
+
per-invocation. Has tool verbs, per-turn state (runId, turn, mode).
|
|
116
|
+
|
|
117
|
+
### Tool Verbs (available on both objects)
|
|
118
|
+
|
|
119
|
+
| Method | Effect |
|
|
120
|
+
|--------|--------|
|
|
121
|
+
| `rummy.set({ path, body, state, attributes })` | Create/update entry |
|
|
122
|
+
| `rummy.get({ path })` | Promote to full state |
|
|
123
|
+
| `rummy.store({ path })` | Demote to stored state |
|
|
124
|
+
| `rummy.rm({ path })` | Delete permanently |
|
|
125
|
+
| `rummy.mv({ path, to })` | Move entry |
|
|
126
|
+
| `rummy.cp({ path, to })` | Copy entry |
|
|
127
|
+
|
|
128
|
+
### Query Methods
|
|
129
|
+
|
|
130
|
+
| Method | Returns |
|
|
131
|
+
|--------|---------|
|
|
132
|
+
| `rummy.getEntry(path)` | Full entry object |
|
|
133
|
+
| `rummy.getBody(path)` | Body text or null |
|
|
134
|
+
| `rummy.getState(path)` | State string or null |
|
|
135
|
+
| `rummy.getAttributes(path)` | Parsed attributes `{}` |
|
|
136
|
+
| `rummy.getEntries(pattern, body?)` | Array of matching entries |
|
|
137
|
+
|
|
138
|
+
### Properties
|
|
139
|
+
|
|
140
|
+
| Property | Type |
|
|
141
|
+
|----------|------|
|
|
142
|
+
| `rummy.name` | Plugin name (PluginContext only) |
|
|
143
|
+
| `rummy.entries` | KnownStore instance |
|
|
144
|
+
| `rummy.db` | Database |
|
|
145
|
+
| `rummy.runId` | Current run ID (RummyContext only) |
|
|
146
|
+
| `rummy.projectId` | Current project ID |
|
|
147
|
+
| `rummy.sequence` | Current turn number (RummyContext only) |
|
|
148
|
+
|
|
149
|
+
## Events & Filters
|
|
150
|
+
|
|
151
|
+
**Events** are fire-and-forget. All handlers run. Return values ignored.
|
|
152
|
+
|
|
153
|
+
```js
|
|
154
|
+
hooks.entry.changed.on(async ({ rummy, runId, turn, paths }) => {
|
|
155
|
+
// React to file changes
|
|
156
|
+
}, priority);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Filters** transform data through a chain. Each handler receives the value
|
|
160
|
+
and context, returns the (possibly modified) value.
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
hooks.llm.messages.addFilter(async (messages, context) => {
|
|
164
|
+
return [{ role: "system", content: "Extra" }, ...messages];
|
|
165
|
+
}, priority);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Lower priority runs first. All hooks are async.
|
|
169
|
+
|
|
170
|
+
### Project Lifecycle
|
|
171
|
+
|
|
172
|
+
| Hook | Type | Payload | When |
|
|
173
|
+
|------|------|---------|------|
|
|
174
|
+
| `project.init.started` | event | `{ projectName, projectRoot }` | Before project DB upsert |
|
|
175
|
+
| `project.init.completed` | event | `{ projectId, projectRoot, db }` | After project created |
|
|
176
|
+
|
|
177
|
+
### RPC Pipeline
|
|
178
|
+
|
|
179
|
+
| Hook | Type | Payload | When |
|
|
180
|
+
|------|------|---------|------|
|
|
181
|
+
| `socket.message.raw` | filter | Raw buffer | Before JSON parse |
|
|
182
|
+
| `rpc.request` | filter | `{ method, params, id }` | Before handler lookup |
|
|
183
|
+
| `rpc.started` | event | `{ method, params, id, projectId }` | Before handler execution |
|
|
184
|
+
| `rpc.response.result` | filter | `result, { method, id }` | Before sending response |
|
|
185
|
+
| `rpc.completed` | event | `{ method, id, result }` | After response sent |
|
|
186
|
+
| `rpc.error` | event | `{ id, error }` | On handler error |
|
|
187
|
+
|
|
188
|
+
### Run Lifecycle
|
|
189
|
+
|
|
190
|
+
| Hook | Type | Payload | When |
|
|
191
|
+
|------|------|---------|------|
|
|
192
|
+
| `ask.started` | event | `{ projectId, model, prompt, run }` | Run requested in ask mode |
|
|
193
|
+
| `act.started` | event | `{ projectId, model, prompt, run }` | Run requested in act mode |
|
|
194
|
+
| `run.config` | filter | Config object, `{ projectId }` | Before run config applied |
|
|
195
|
+
| `run.progress` | event | `{ run, turn, status }` | Status change (thinking, processing) |
|
|
196
|
+
| `run.state` | event | `{ run, turn, status, summary, history, unknowns, proposed, telemetry }` | After each turn — full state snapshot |
|
|
197
|
+
| `run.step.completed` | event | `{ run, turn, flags }` | Turn resolved, no proposals pending |
|
|
198
|
+
| `ask.completed` | event | `{ projectId, run, status, turn }` | Ask run finished |
|
|
199
|
+
| `act.completed` | event | `{ projectId, run, status, turn }` | Act run finished |
|
|
200
|
+
|
|
201
|
+
### Turn Pipeline
|
|
202
|
+
|
|
203
|
+
Hooks fire in this order every turn:
|
|
204
|
+
|
|
205
|
+
| Hook | Type | Payload | When |
|
|
206
|
+
|------|------|---------|------|
|
|
207
|
+
| `entry.changed` | event | `{ rummy, runId, turn, paths }` | Files changed on disk since last turn |
|
|
208
|
+
| `onTurn` | processor | `(rummy)` | Plugin turn setup, before context assembly |
|
|
209
|
+
| `assembly.system` | filter | `(content, { rows, loopStartTurn, type, tools })` | Build system message — plugins append sections |
|
|
210
|
+
| `assembly.user` | filter | `(content, { rows, loopStartTurn, type, tools })` | Build user message — plugins append sections |
|
|
211
|
+
| `llm.messages` | filter | `messages[], { model, projectId, runId }` | Before LLM call — modify final messages |
|
|
212
|
+
| `llm.request.started` | event | `{ model, turn }` | LLM call about to fire |
|
|
213
|
+
| `llm.response` | filter | `response, { model, projectId, runId }` | Raw LLM response — normalize, transform |
|
|
214
|
+
| `llm.request.completed` | event | `{ model, turn, usage }` | LLM call finished |
|
|
215
|
+
| `tools.dispatch` | handler | `(entry, rummy)` | Per command — handler chain executes |
|
|
216
|
+
| `entry.created` | event | `{ scheme, path, body, attributes, state, resultPath }` | After each command dispatched |
|
|
217
|
+
| `turn.proposing` | event | `{ rummy, recorded }` | All dispatches done — materialize proposals |
|
|
218
|
+
|
|
219
|
+
### Client Notifications
|
|
220
|
+
|
|
221
|
+
| Hook | Type | Payload | When |
|
|
222
|
+
|------|------|---------|------|
|
|
223
|
+
| `ui.render` | event | `{ text, append }` | Text for client display |
|
|
224
|
+
| `ui.notify` | event | `{ text, level }` | Status notification |
|
|
225
|
+
|
|
226
|
+
## RPC Registration
|
|
227
|
+
|
|
228
|
+
```js
|
|
229
|
+
hooks.rpc.registry.register("myMethod", {
|
|
230
|
+
handler: async (params, ctx) => {
|
|
231
|
+
// ctx.projectAgent, ctx.db, ctx.projectId, ctx.projectRoot
|
|
232
|
+
return { result: "value" };
|
|
233
|
+
},
|
|
234
|
+
description: "What this method does",
|
|
235
|
+
params: { arg1: "description" },
|
|
236
|
+
requiresInit: true,
|
|
237
|
+
longRunning: true, // for methods that call the model
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Hedberg Pattern Library
|
|
242
|
+
|
|
243
|
+
Available in JS and SQL. Five pattern types, auto-detected:
|
|
244
|
+
|
|
245
|
+
| Syntax | Type | Example |
|
|
246
|
+
|--------|------|---------|
|
|
247
|
+
| `s/old/new/flags` | Sed replace | `s/3000/8080/g` |
|
|
248
|
+
| `/pattern/flags` | Regex | `/\d+/g` |
|
|
249
|
+
| `$.path` | JSONPath | `$.config.port` |
|
|
250
|
+
| `//element` | XPath | `//div[@class]` |
|
|
251
|
+
| `*glob*` | Glob | `src/**/*.js` |
|
|
252
|
+
| Everything else | Literal | `port = 3000` |
|
|
253
|
+
|
|
254
|
+
JS API:
|
|
255
|
+
|
|
256
|
+
```js
|
|
257
|
+
import { hedmatch, hedsearch, hedreplace } from "./sql/functions/hedberg.js";
|
|
258
|
+
|
|
259
|
+
hedmatch(pattern, string) // → boolean (full string match)
|
|
260
|
+
hedsearch(pattern, string) // → { found, match, index }
|
|
261
|
+
hedreplace(pattern, replacement, string) // → new string or null
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
SQL functions: `hedmatch()`, `hedsearch()`, `hedreplace()`.
|
|
265
|
+
|
|
266
|
+
## Bundled Plugins
|
|
267
|
+
|
|
268
|
+
Each plugin has its own README at `src/plugins/{name}/README.md`.
|
|
269
|
+
|
|
270
|
+
| Plugin | Type | Description |
|
|
271
|
+
|--------|------|-------------|
|
|
272
|
+
| [`get`](src/plugins/get/) | Core tool | Load file/entry into context |
|
|
273
|
+
| [`set`](src/plugins/set/) | Core tool | Edit file/entry |
|
|
274
|
+
| [`known`](src/plugins/known/) | Core tool | Save knowledge, render `<known>` |
|
|
275
|
+
| [`store`](src/plugins/store/) | Core tool | Remove from context |
|
|
276
|
+
| [`rm`](src/plugins/rm/) | Core tool | Delete permanently |
|
|
277
|
+
| [`mv`](src/plugins/mv/) | Core tool | Move entry |
|
|
278
|
+
| [`cp`](src/plugins/cp/) | Core tool | Copy entry |
|
|
279
|
+
| [`sh`](src/plugins/sh/) | Core tool | Shell command |
|
|
280
|
+
| [`env`](src/plugins/env/) | Core tool | Exploratory command |
|
|
281
|
+
| [`ask_user`](src/plugins/ask_user/) | Core tool | Ask the user |
|
|
282
|
+
| [`summarize`](src/plugins/summarize/) | Structural | Signal completion |
|
|
283
|
+
| [`update`](src/plugins/update/) | Structural | Signal continued work |
|
|
284
|
+
| [`unknown`](src/plugins/unknown/) | Structural | Register unknowns, render `<unknowns>` |
|
|
285
|
+
| [`previous`](src/plugins/previous/) | Assembly | Render `<previous>` loop history |
|
|
286
|
+
| [`current`](src/plugins/current/) | Assembly | Render `<current>` active loop work |
|
|
287
|
+
| [`progress`](src/plugins/progress/) | Assembly | Render `<progress>` bridge text |
|
|
288
|
+
| [`prompt`](src/plugins/prompt/) | Assembly | Render `<ask>`/`<act>` prompt tag |
|
|
289
|
+
| [`instructions`](src/plugins/instructions/) | Internal | System prompt assembly |
|
|
290
|
+
| [`file`](src/plugins/file/) | Internal | File projections, constraints, scanning |
|
|
291
|
+
| [`rpc`](src/plugins/rpc/) | Internal | RPC method registration |
|
|
292
|
+
| [`skills`](src/plugins/skills/) | Internal | Skill/persona management |
|
|
293
|
+
| [`telemetry`](src/plugins/telemetry/) | Internal | Debug logging |
|
|
294
|
+
|
|
295
|
+
## External Plugins
|
|
296
|
+
|
|
297
|
+
| Plugin | Package | Description |
|
|
298
|
+
|--------|---------|-------------|
|
|
299
|
+
| Web | `@possumtech/rummy.web` | Search and URL fetching |
|
|
300
|
+
| Repo | `@possumtech/rummy.repo` | Symbol extraction |
|
|
301
|
+
|
|
302
|
+
Loaded via `RUMMY_PLUGIN_*` env vars. Graceful failure if not installed.
|
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# RUMMY: Relational Unknowns Memory Management Yoke
|
|
2
|
+
|
|
3
|
+
Rummy is the only LLM agent service inspired by and dedicated to the memory of former Secretary of State Donald "Rummy" Rumsfeld. Our unique fusion of apophatic and hedbergian engineering strategies yields more accurate and efficient results than any other agent. Our client/server and plugin architecture integrates it into more workflows than any other agent. It's also more flexible and lean than any other agent. Our dynamic cache management, model hot-swapping, and flexible router interface make it more affordable than any other agent.
|
|
4
|
+
|
|
5
|
+
## Key Features
|
|
6
|
+
|
|
7
|
+
- **The Rumsfeld Loop:** Forcing models to catalog what they don't know is a powerful weapon against hallucination and laziness. Every turn, the model calls `<known>`, `<unknown>`, and `<update>` — externalizing its reasoning into a persistent K/V store that survives across turns without message history.
|
|
8
|
+
|
|
9
|
+
- **One K/V Store:** Files, knowledge, tool results, unknowns, user prompts — everything is a keyed entry in one SQLite table. No message history. No separate file listings. The model's entire context is assembled from the store each turn.
|
|
10
|
+
|
|
11
|
+
- **Hedberg:** The interpretation boundary between stochastic model output and deterministic system operations. Models speak in whatever syntax they were trained on — sed regex, SEARCH/REPLACE blocks, escaped characters. Hedberg normalizes all of it. Available to all plugins via `core.hooks.hedberg`.
|
|
12
|
+
|
|
13
|
+
- **Plugin Architecture:** Every `<tag>` the model sees is a plugin. Every scheme is registered by its owner. The prompt itself is assembled from plugins. Drop a directory into `~/.rummy/plugins/` or install via npm. See [PLUGINS.md](PLUGINS.md) for the complete plugin API.
|
|
14
|
+
|
|
15
|
+
- **Symbols Done Right:** Designed with universal language support in mind. Powered by [@possumtech/antlrmap](https://github.com/possumtech/antlrmap).
|
|
16
|
+
|
|
17
|
+
- **SQLite Done Right:** Async, compiled WAL-mode SQL engine in worker threads. Powered by [@possumtech/sqlrite](https://github.com/possumtech/sqlrite).
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @possumtech/rummy
|
|
23
|
+
cp .env.example .env
|
|
24
|
+
vim .env
|
|
25
|
+
npm start
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
Rummy is just the service. You'll need to get (or vibe) yourself a client interface. We're partial the our Neovim plugin: [@possumtech/rummy.nvim](https://github.com/possumtech/rummy.nvim)
|
|
31
|
+
|
|
32
|
+
## Documentation
|
|
33
|
+
|
|
34
|
+
| Document | Contents |
|
|
35
|
+
|----------|----------|
|
|
36
|
+
| [SPEC.md](SPEC.md) | System design: K/V store, dispatch, packet structure, RPC |
|
|
37
|
+
| [PLUGINS.md](PLUGINS.md) | Plugin development: registration, events, filters, hedberg |
|
|
38
|
+
| [AGENTS.md](AGENTS.md) | Planning and progress |
|
|
39
|
+
|
|
40
|
+
Each plugin has its own README at `src/plugins/{name}/README.md`.
|
|
41
|
+
The `discover` RPC method returns the live protocol reference at runtime.
|