@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.
Files changed (120) hide show
  1. package/.env.example +55 -0
  2. package/LICENSE +21 -0
  3. package/PLUGINS.md +302 -0
  4. package/README.md +41 -0
  5. package/SPEC.md +524 -0
  6. package/lang/en.json +34 -0
  7. package/migrations/001_initial_schema.sql +226 -0
  8. package/package.json +54 -0
  9. package/service.js +143 -0
  10. package/src/agent/AgentLoop.js +553 -0
  11. package/src/agent/ContextAssembler.js +29 -0
  12. package/src/agent/KnownStore.js +254 -0
  13. package/src/agent/ProjectAgent.js +101 -0
  14. package/src/agent/ResponseHealer.js +134 -0
  15. package/src/agent/TurnExecutor.js +457 -0
  16. package/src/agent/XmlParser.js +247 -0
  17. package/src/agent/known_checks.sql +42 -0
  18. package/src/agent/known_queries.sql +80 -0
  19. package/src/agent/known_store.sql +161 -0
  20. package/src/agent/messages.js +17 -0
  21. package/src/agent/prompt_queue.sql +39 -0
  22. package/src/agent/runs.sql +114 -0
  23. package/src/agent/schemes.sql +3 -0
  24. package/src/agent/sessions.sql +51 -0
  25. package/src/agent/tokens.js +28 -0
  26. package/src/agent/turns.sql +36 -0
  27. package/src/hooks/HookRegistry.js +72 -0
  28. package/src/hooks/Hooks.js +115 -0
  29. package/src/hooks/PluginContext.js +116 -0
  30. package/src/hooks/RummyContext.js +181 -0
  31. package/src/hooks/ToolRegistry.js +83 -0
  32. package/src/llm/LlmProvider.js +107 -0
  33. package/src/llm/OllamaClient.js +88 -0
  34. package/src/llm/OpenAiClient.js +80 -0
  35. package/src/llm/OpenRouterClient.js +78 -0
  36. package/src/llm/XaiClient.js +113 -0
  37. package/src/plugins/ask_user/README.md +18 -0
  38. package/src/plugins/ask_user/ask_user.js +48 -0
  39. package/src/plugins/ask_user/docs.md +2 -0
  40. package/src/plugins/cp/README.md +18 -0
  41. package/src/plugins/cp/cp.js +55 -0
  42. package/src/plugins/cp/docs.md +2 -0
  43. package/src/plugins/current/README.md +14 -0
  44. package/src/plugins/current/current.js +48 -0
  45. package/src/plugins/engine/README.md +12 -0
  46. package/src/plugins/engine/engine.sql +18 -0
  47. package/src/plugins/engine/turn_context.sql +51 -0
  48. package/src/plugins/env/README.md +14 -0
  49. package/src/plugins/env/docs.md +2 -0
  50. package/src/plugins/env/env.js +32 -0
  51. package/src/plugins/file/README.md +25 -0
  52. package/src/plugins/file/file.js +85 -0
  53. package/src/plugins/get/README.md +19 -0
  54. package/src/plugins/get/docs.md +6 -0
  55. package/src/plugins/get/get.js +53 -0
  56. package/src/plugins/hedberg/README.md +72 -0
  57. package/src/plugins/hedberg/docs.md +9 -0
  58. package/src/plugins/hedberg/edits.js +65 -0
  59. package/src/plugins/hedberg/hedberg.js +89 -0
  60. package/src/plugins/hedberg/matcher.js +181 -0
  61. package/src/plugins/hedberg/normalize.js +41 -0
  62. package/src/plugins/hedberg/patterns.js +452 -0
  63. package/src/plugins/hedberg/sed.js +48 -0
  64. package/src/plugins/helpers.js +22 -0
  65. package/src/plugins/index.js +180 -0
  66. package/src/plugins/instructions/README.md +11 -0
  67. package/src/plugins/instructions/instructions.js +37 -0
  68. package/src/plugins/instructions/preamble.md +12 -0
  69. package/src/plugins/known/README.md +18 -0
  70. package/src/plugins/known/docs.md +3 -0
  71. package/src/plugins/known/known.js +57 -0
  72. package/src/plugins/mv/README.md +18 -0
  73. package/src/plugins/mv/docs.md +2 -0
  74. package/src/plugins/mv/mv.js +56 -0
  75. package/src/plugins/previous/README.md +15 -0
  76. package/src/plugins/previous/previous.js +50 -0
  77. package/src/plugins/progress/README.md +17 -0
  78. package/src/plugins/progress/progress.js +44 -0
  79. package/src/plugins/prompt/README.md +16 -0
  80. package/src/plugins/prompt/prompt.js +45 -0
  81. package/src/plugins/rm/README.md +18 -0
  82. package/src/plugins/rm/docs.md +4 -0
  83. package/src/plugins/rm/rm.js +51 -0
  84. package/src/plugins/rpc/README.md +45 -0
  85. package/src/plugins/rpc/rpc.js +587 -0
  86. package/src/plugins/set/README.md +32 -0
  87. package/src/plugins/set/docs.md +4 -0
  88. package/src/plugins/set/set.js +268 -0
  89. package/src/plugins/sh/README.md +18 -0
  90. package/src/plugins/sh/docs.md +2 -0
  91. package/src/plugins/sh/sh.js +32 -0
  92. package/src/plugins/skills/README.md +25 -0
  93. package/src/plugins/skills/skills.js +175 -0
  94. package/src/plugins/store/README.md +20 -0
  95. package/src/plugins/store/docs.md +5 -0
  96. package/src/plugins/store/store.js +52 -0
  97. package/src/plugins/summarize/README.md +18 -0
  98. package/src/plugins/summarize/docs.md +4 -0
  99. package/src/plugins/summarize/summarize.js +24 -0
  100. package/src/plugins/telemetry/README.md +19 -0
  101. package/src/plugins/telemetry/rpc_log.sql +28 -0
  102. package/src/plugins/telemetry/telemetry.js +186 -0
  103. package/src/plugins/unknown/README.md +23 -0
  104. package/src/plugins/unknown/docs.md +5 -0
  105. package/src/plugins/unknown/unknown.js +31 -0
  106. package/src/plugins/update/README.md +18 -0
  107. package/src/plugins/update/docs.md +4 -0
  108. package/src/plugins/update/update.js +24 -0
  109. package/src/server/ClientConnection.js +228 -0
  110. package/src/server/RpcRegistry.js +52 -0
  111. package/src/server/SocketServer.js +43 -0
  112. package/src/sql/file_constraints.sql +15 -0
  113. package/src/sql/functions/countTokens.js +7 -0
  114. package/src/sql/functions/hedmatch.js +8 -0
  115. package/src/sql/functions/hedreplace.js +8 -0
  116. package/src/sql/functions/hedsearch.js +8 -0
  117. package/src/sql/functions/schemeOf.js +7 -0
  118. package/src/sql/functions/slugify.js +6 -0
  119. package/src/sql/v_model_context.sql +101 -0
  120. 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.