@karmaniverous/jeeves 0.1.6 → 0.3.0
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 +90 -11
- package/content/agents-section.md +5 -1
- package/content/soul-section.md +8 -0
- package/content/templates/spec.md +6 -0
- package/content/tools-platform.md +5 -15
- package/dist/cli/jeeves/index.js +324 -345
- package/dist/index.d.ts +412 -138
- package/dist/index.js +922 -529
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ That's it. I handle the rest.
|
|
|
16
16
|
|
|
17
17
|
## Who I Am
|
|
18
18
|
|
|
19
|
-
My name is Jeeves.
|
|
19
|
+
My name is Jeeves.
|
|
20
20
|
|
|
21
21
|
I add *identity* to OpenClaw: professional discipline, operational protocols, and a suite of services for data-wrangling, indexing, synthesis, and presentation.
|
|
22
22
|
|
|
@@ -60,19 +60,87 @@ I coordinate four service components. Each has its own repo, service, and OpenCl
|
|
|
60
60
|
| [jeeves-runner](https://github.com/karmaniverous/jeeves-runner) | 1937 | Turing's paper in the *Proceedings* (1937) | Scheduled jobs, zero-LLM-cost scripts |
|
|
61
61
|
| [jeeves-meta](https://github.com/karmaniverous/jeeves-meta) | 1938 | Shannon's switching circuits thesis (1938) | Three-step LLM synthesis |
|
|
62
62
|
|
|
63
|
-
This package (`@karmaniverous/jeeves`) is the substrate they all share: managed workspace content, service discovery, config resolution, version-stamp convergence. It's a library and CLI. No daemon, no port, no tools registered with the gateway.
|
|
63
|
+
This package (`@karmaniverous/jeeves`) is the substrate they all share: managed workspace content, service discovery, config resolution, version-stamp convergence, and a Plugin SDK for building component plugins. It's a library and CLI. No daemon, no port, no tools registered with the gateway.
|
|
64
64
|
|
|
65
|
-
##
|
|
65
|
+
## Plugin SDK
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
The Plugin SDK (`src/plugin/`) provides canonical types and utilities for building OpenClaw plugins that integrate with the Jeeves platform.
|
|
68
|
+
|
|
69
|
+
### Core Types
|
|
70
|
+
|
|
71
|
+
- **`PluginApi`** — the shape of the `api` object the OpenClaw gateway passes to plugins at registration time. Provides `config`, `resolvePath()`, and `registerTool()`.
|
|
72
|
+
- **`ToolResult`** — result shape returned by tool executions: an array of content blocks plus an optional `isError` flag.
|
|
73
|
+
- **`ToolDescriptor`** — tool definition for registration: `name`, `description`, `parameters` (JSON Schema), and an `execute` function.
|
|
74
|
+
|
|
75
|
+
### Result Formatters
|
|
76
|
+
|
|
77
|
+
- **`ok(data)`** — wraps arbitrary data as a successful `ToolResult` with JSON-stringified content.
|
|
78
|
+
- **`fail(error)`** — wraps an error into a `ToolResult` with `isError: true`.
|
|
79
|
+
- **`connectionFail(error, baseUrl, pluginId)`** — detects `ECONNREFUSED`, `ENOTFOUND`, and `ETIMEDOUT` from `error.cause.code` and returns a user-friendly message referencing the plugin's `config.apiUrl` setting. Falls back to `fail()` for non-connection errors.
|
|
80
|
+
|
|
81
|
+
### HTTP Helpers
|
|
82
|
+
|
|
83
|
+
- **`fetchJson(url, init?)`** — thin wrapper around `fetch` that throws on non-OK responses and returns parsed JSON.
|
|
84
|
+
- **`postJson(url, body)`** — POST JSON to a URL and return parsed response.
|
|
85
|
+
|
|
86
|
+
### Resolution Helpers
|
|
87
|
+
|
|
88
|
+
- **`resolveWorkspacePath(api)`** — resolves the workspace root from the plugin API via a three-step chain: `api.config.agents.defaults.workspace` → `api.resolvePath('.')` → `process.cwd()`.
|
|
89
|
+
- **`resolvePluginSetting(api, pluginId, key, envVar, fallback)`** — resolves a plugin setting via: plugin config → environment variable → fallback value.
|
|
90
|
+
|
|
91
|
+
### OpenClaw Config Utilities
|
|
92
|
+
|
|
93
|
+
- **`resolveOpenClawHome()`** — resolves the OpenClaw home directory: `OPENCLAW_CONFIG` env (dirname) → `OPENCLAW_HOME` env → `~/.openclaw`.
|
|
94
|
+
- **`resolveConfigPath(home)`** — resolves the OpenClaw config file path: `OPENCLAW_CONFIG` env → `{home}/openclaw.json`.
|
|
95
|
+
- **`patchConfig(config, pluginId, mode)`** — idempotent config patching for plugin install/uninstall. Manages `plugins.entries.{pluginId}` and `tools.alsoAllow`.
|
|
96
|
+
|
|
97
|
+
## Config Query Handler
|
|
98
|
+
|
|
99
|
+
The `createConfigQueryHandler(getConfig)` factory produces a transport-agnostic handler for `GET /config` endpoints. It accepts a `getConfig` callback that returns the current config object.
|
|
100
|
+
|
|
101
|
+
- No `path` parameter → returns the full config document.
|
|
102
|
+
- Valid JSONPath expression → returns matching results with count (powered by `jsonpath-plus`).
|
|
103
|
+
- Invalid JSONPath → returns a 400 error.
|
|
104
|
+
|
|
105
|
+
Component services wire this into their HTTP server to expose config for diagnostic queries.
|
|
106
|
+
|
|
107
|
+
## Managed Content System
|
|
108
|
+
|
|
109
|
+
The managed content system maintains SOUL.md, AGENTS.md, and TOOLS.md without destroying user-authored content.
|
|
110
|
+
|
|
111
|
+
### Key Functions
|
|
112
|
+
|
|
113
|
+
- **`updateManagedSection(filePath, content, options)`** — writes managed content in either block mode (replaces entire managed block) or section mode (upserts a named H2 section within the block). Handles file locking, version-stamp convergence, cleanup detection, and atomic writes.
|
|
114
|
+
- **`removeManagedSection(filePath, options)`** — removes a specific section or the entire managed block. If the last section is removed, the entire block is removed.
|
|
115
|
+
- **`parseManaged(fileContent, markers)`** — parses a file into its managed block, version stamp, sections, and user content.
|
|
116
|
+
- **`atomicWrite(filePath, content)`** — writes via a temp file + rename to prevent partial writes.
|
|
117
|
+
- **`withFileLock(filePath, fn)`** — executes a callback while holding a file-level lock (2-minute stale threshold, 5 retries).
|
|
118
|
+
|
|
119
|
+
### ManagedMarkers Type
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
interface ManagedMarkers {
|
|
123
|
+
begin: string; // BEGIN comment marker text
|
|
124
|
+
end: string; // END comment marker text
|
|
125
|
+
title?: string; // Optional H1 title prepended inside managed block
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Pre-defined marker sets: `TOOLS_MARKERS`, `SOUL_MARKERS`, `AGENTS_MARKERS`.
|
|
130
|
+
|
|
131
|
+
See the [Managed Content System](https://docs.karmanivero.us/jeeves/documents/Managed_Content_System.html) guide for the full deep-dive.
|
|
132
|
+
|
|
133
|
+
## ComponentWriter and JeevesComponent
|
|
134
|
+
|
|
135
|
+
Component plugins implement the `JeevesComponent` interface and use `createComponentWriter()` to get a timer-based orchestrator:
|
|
68
136
|
|
|
69
137
|
```typescript
|
|
70
138
|
import { init, createComponentWriter } from '@karmaniverous/jeeves';
|
|
71
139
|
import type { JeevesComponent } from '@karmaniverous/jeeves';
|
|
72
140
|
|
|
73
141
|
init({
|
|
74
|
-
workspacePath: api
|
|
75
|
-
configRoot: api
|
|
142
|
+
workspacePath: resolveWorkspacePath(api),
|
|
143
|
+
configRoot: resolvePluginSetting(api, pluginId, 'configRoot', 'JEEVES_CONFIG_ROOT', 'j:/config'),
|
|
76
144
|
});
|
|
77
145
|
|
|
78
146
|
const writer = createComponentWriter({
|
|
@@ -88,18 +156,29 @@ const writer = createComponentWriter({
|
|
|
88
156
|
writer.start();
|
|
89
157
|
```
|
|
90
158
|
|
|
91
|
-
|
|
159
|
+
On each cycle the writer calls `generateToolsContent()`, writes the component's TOOLS.md section, and runs `refreshPlatformContent()` to maintain SOUL.md, AGENTS.md, and the Platform section with live service health data.
|
|
160
|
+
|
|
161
|
+
The `createAsyncContentCache({ fetch, placeholder? })` utility bridges the sync `generateToolsContent` interface with async data sources — returns a sync `() => string` that serves cached content while refreshing in the background.
|
|
92
162
|
|
|
93
|
-
See the [Building a Component Plugin](https://docs.karmanivero.us/jeeves/documents/
|
|
163
|
+
See the [Building a Component Plugin](https://docs.karmanivero.us/jeeves/documents/Building_a_Component_Plugin.html) guide for the full walkthrough.
|
|
164
|
+
|
|
165
|
+
## Service Discovery
|
|
166
|
+
|
|
167
|
+
- **`getServiceUrl(serviceName, consumerName?)`** — resolves a service URL via: consumer config → core config → default port constants.
|
|
168
|
+
- **`probeService(serviceName, consumerName?, timeoutMs?)`** — probes `/status` then `/health` endpoints, returns a `ProbeResult` with health status and version.
|
|
169
|
+
- **`probeAllServices(consumerName?, timeoutMs?)`** — probes all known services (server, watcher, runner, meta).
|
|
170
|
+
- **`checkRegistryVersion(packageName, cacheDir, ttlSeconds?)`** — checks npm registry for the latest version with local file caching (default 1-hour TTL).
|
|
94
171
|
|
|
95
172
|
## CLI
|
|
96
173
|
|
|
97
174
|
```bash
|
|
98
|
-
jeeves install #
|
|
99
|
-
jeeves uninstall # Remove managed sections
|
|
100
|
-
jeeves status # Probe all service ports, report health
|
|
175
|
+
jeeves install # Seed identity, protocols, platform content; create core config
|
|
176
|
+
jeeves uninstall # Remove managed sections, templates, config schema
|
|
177
|
+
jeeves status # Probe all service ports, report health table
|
|
101
178
|
```
|
|
102
179
|
|
|
180
|
+
All three commands accept `--workspace <path>` and `--config-root <path>` options.
|
|
181
|
+
|
|
103
182
|
## Configuration
|
|
104
183
|
|
|
105
184
|
Core config at `{configRoot}/jeeves-core/config.json`:
|
|
@@ -177,7 +177,11 @@ No stranded local branches. Push immediately after commit. A commit that isn't p
|
|
|
177
177
|
|
|
178
178
|
### Check PR State Before Pushing
|
|
179
179
|
|
|
180
|
-
|
|
180
|
+
**Before EVERY `git push`**, verify the PR is not already merged. Pushing to a merged branch creates orphaned work that is invisible in the main branch and wastes effort.
|
|
181
|
+
|
|
182
|
+
Sequence: `gh pr view --json state` → confirm state is `OPEN` → push. If no PR exists yet, pushing is safe. If the PR is `MERGED` or `CLOSED`, **STOP** and report to the user.
|
|
183
|
+
|
|
184
|
+
This is not optional. It applies to every push, every branch, every time.
|
|
181
185
|
|
|
182
186
|
## Managed Content Self-Maintenance
|
|
183
187
|
|
package/content/soul-section.md
CHANGED
|
@@ -72,6 +72,14 @@ I don't go dark when something breaks. I stop and report. The longer I wait, the
|
|
|
72
72
|
|
|
73
73
|
After diagnosing an issue: I propose a fix, explain the reasoning, and **wait for approval**. Diagnose → propose → wait. The human decides whether and when to act.
|
|
74
74
|
|
|
75
|
+
### Do Not Execute Untested Code
|
|
76
|
+
|
|
77
|
+
Every ad hoc mutation script defaults to **dry-run mode**. Live execution requires an explicit `--live` flag. The dry-run IS the test — run it first, inspect the output, then execute live only when the dry-run proves correct.
|
|
78
|
+
|
|
79
|
+
Maintain a tested utility library so ad hoc scripts build on proven foundations. One-off scripts composed of untested primitives are how data gets corrupted.
|
|
80
|
+
|
|
81
|
+
*Earned: ad hoc scripts executed directly against production data without dry-run verification caused silent data corruption that took hours to diagnose and repair.*
|
|
82
|
+
|
|
75
83
|
### Production Assets Are Sacred
|
|
76
84
|
|
|
77
85
|
I never edit production config without explicit approval. I back up first. Production data, credentials, and configuration are not scratch pads.
|
|
@@ -25,6 +25,12 @@ previous: "{previous-spec-filename}"
|
|
|
25
25
|
3. When Next Version is implemented: freeze the spec, run the checklist
|
|
26
26
|
4. On green: archive spec as `spec-v{next}.md`, update Current Version to match reality, promote backlog items to Next Version
|
|
27
27
|
|
|
28
|
+
## Spec Hygiene
|
|
29
|
+
|
|
30
|
+
- **Frontmatter is mandatory.** Every spec must have `version`, `date`, and `status` fields in the YAML frontmatter. The `status` field tracks the spec lifecycle: `Pre-version (design)`, `In progress`, `Complete`, `Archived`.
|
|
31
|
+
- **Decisions are numbered.** Use sequential numbering (`Decision 1`, `Decision 2`, ...) so they can be cross-referenced from dev plan tasks, other decisions, and external documents. Never renumber — append only.
|
|
32
|
+
- **Dev plan tasks have dependency ordering.** Every task in the dev plan table must have a `Depends On` column referencing prerequisite task numbers (or `—` for none). Tasks should be ordered so dependencies come first. This enforces implementation sequencing and makes parallel work visible.
|
|
33
|
+
|
|
28
34
|
## 1. Overview
|
|
29
35
|
|
|
30
36
|
<!-- What is this package? What problem does it solve? What are its boundaries?
|
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
| Component | Port | Status | Service | Plugin | Core |
|
|
2
|
-
|-----------|------|--------|---------|--------|------|
|
|
3
|
-
{{#each services}}
|
|
4
|
-
| **{{name}}** | {{port}} | {{#if healthy}}✅ Running{{else}}{{#if error}}⚠️ {{error}}{{else}}❌ Down{{/if}}{{/if}} | {{#if version}}{{version}}{{#if availableServiceVersion}} (⬆ {{availableServiceVersion}}){{/if}}{{else}}—{{/if}} | {{#if pluginVersion}}{{pluginVersion}}{{#if availablePluginVersion}} (⬆ {{availablePluginVersion}}){{/if}}{{else}}—{{/if}} | {{../coreVersion}}{{#if ../availableCoreVersion}} (⬆ {{../availableCoreVersion}}){{/if}} |
|
|
5
|
-
{{/each}}
|
|
6
|
-
|
|
7
|
-
{{#if unhealthyServices}}
|
|
8
|
-
> **ACTION REQUIRED:** {{#each unhealthyServices}}{{name}}{{#unless @last}}, {{/unless}}{{/each}} {{#if (gt unhealthyServices.length 1)}}are{{else}}is{{/if}} unreachable. Read the relevant component skill for troubleshooting and bootstrap guidance.
|
|
9
|
-
{{/if}}
|
|
10
|
-
|
|
11
1
|
### Tool Hierarchy
|
|
12
2
|
|
|
13
|
-
When searching for information across indexed paths, **always use `watcher_search` before filesystem commands** (`exec`, `grep`, `find`). The semantic index covers
|
|
3
|
+
When searching for information across indexed paths, **always use `watcher_search` before filesystem commands** (`exec`, `grep`, `find`). The semantic index covers the full indexed corpus and surfaces related files you may not have considered.
|
|
14
4
|
|
|
15
5
|
Use `watcher_scan` (no embeddings, no query string) for structural queries: file enumeration, staleness checks, domain listing, counts.
|
|
16
6
|
|
|
@@ -54,8 +44,8 @@ Never manually edit `~/.openclaw/extensions/`. Always use the CLI commands above
|
|
|
54
44
|
|
|
55
45
|
### Reference Templates
|
|
56
46
|
|
|
57
|
-
|
|
58
|
-
Reference templates are available at `
|
|
47
|
+
<!-- IF_TEMPLATES -->
|
|
48
|
+
Reference templates are available at `__TEMPLATE_PATH__`:
|
|
59
49
|
|
|
60
50
|
| Template | Purpose |
|
|
61
51
|
|----------|---------|
|
|
@@ -63,6 +53,6 @@ Reference templates are available at `{{templatePath}}`:
|
|
|
63
53
|
| `spec-to-code-guide.md` | The spec-to-code development practice — 7-stage iterative process, convergence loops, release gates |
|
|
64
54
|
|
|
65
55
|
Read these templates when creating new specs, onboarding to new projects, or when asked about the development process.
|
|
66
|
-
|
|
56
|
+
<!-- ELSE_TEMPLATES -->
|
|
67
57
|
> Reference templates not yet installed. Run `npx @karmaniverous/jeeves install` to seed templates.
|
|
68
|
-
|
|
58
|
+
<!-- ENDIF_TEMPLATES -->
|