@karmaniverous/jeeves-watcher-openclaw 0.17.0 → 0.18.0-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 +12 -11
- package/dist/index.js +1118 -858
- package/dist/scripts/build-skills.d.ts +1 -1
- package/dist/skills/jeeves-watcher/SKILL.md +94 -42
- package/dist/src/auth.test.d.ts +1 -1
- package/dist/src/catalogTools.d.ts +96 -0
- package/dist/src/catalogTools.test.d.ts +5 -0
- package/dist/src/distSmoke.test.d.ts +5 -0
- package/dist/src/helpers.d.ts +3 -3
- package/dist/src/manifest.test.d.ts +1 -1
- package/dist/src/promptContext.d.ts +10 -10
- package/dist/src/skillFiles.d.ts +14 -0
- package/dist/src/test/surfaceDiff.d.ts +27 -0
- package/dist/src/test/toolRenames.d.ts +13 -0
- package/dist/src/toolGating.d.ts +6 -8
- package/dist/src/toolSurface.test.d.ts +5 -0
- package/dist/src/watcherComponent.d.ts +3 -4
- package/openclaw.plugin.json +11 -11
- package/package.json +14 -11
- package/dist/src/apiTool.d.ts +0 -45
- package/dist/src/configTools.d.ts +0 -14
- package/dist/src/configTools.test.d.ts +0 -5
- package/dist/src/http.d.ts +0 -19
- package/dist/src/http.test.d.ts +0 -5
- package/dist/src/toolTestHarness.d.ts +0 -23
- package/dist/src/vcsTools.d.ts +0 -7
- package/dist/src/vcsTools.test.d.ts +0 -1
- package/dist/src/watcherTools.d.ts +0 -21
- package/dist/src/watcherTools.test.d.ts +0 -1
- /package/dist/src/{apiTool.test.d.ts → skillFiles.test.d.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jeeves-watcher
|
|
3
3
|
description: >
|
|
4
|
-
Semantic search
|
|
4
|
+
Semantic search of the indexed archive: recall prior context, find documents, scan, enrich metadata, watcher config, reindex, indexing issues, file history.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# jeeves-watcher — Search, Discovery & Administration
|
|
@@ -12,11 +12,11 @@ The watcher is an HTTP API running as a background service (typically NSSM on Wi
|
|
|
12
12
|
|
|
13
13
|
**Default port:** 1936 (configurable via `api.port` in watcher config) **Non-default port:** If the watcher runs on a different port, the user must set `plugins.entries.jeeves-watcher-openclaw.config.apiUrl` in `openclaw.json`. The plugin cannot auto-discover a non-default port.
|
|
14
14
|
|
|
15
|
-
**API key:** If the watcher sets `api.apiKey`, every route except `GET /status` needs `Authorization: Bearer <key>`. The tools send it from `plugins.entries.jeeves-watcher-openclaw.config.apiKey` (or the `JEEVES_WATCHER_API_KEY` env var).
|
|
15
|
+
**API key:** If the watcher sets `api.apiKey`, every route except `GET /status` and `GET /openapi.json` needs `Authorization: Bearer <key>`. The tools send it from `plugins.entries.jeeves-watcher-openclaw.config.apiKey` (or the `JEEVES_WATCHER_API_KEY` env var). From `watcher_config`, `watcher_config_apply`, `watcher_search`, `watcher_scan` and `watcher_show_vcs_file`, a missing or wrong key comes back as `HTTP 401: {"error":"Unauthorized","code":"unauthorized"}` (see [Error Handling](#error-handling) for the fix). From the other tools it reads `HTTP 401 unauthorized: the watcher API requires an API key. Provide it via plugins.entries.jeeves-watcher-openclaw.config.apiKey or the JEEVES_WATCHER_API_KEY env var.` (or, when a key was sent, `... rejected the API key. Check ... against the service's api.apiKey.`). When calling the API directly, add the header yourself. Never echo the key.
|
|
16
16
|
|
|
17
|
-
**Tool errors:** Tool error text is prefixed `Error: `.
|
|
17
|
+
**Tool errors:** Tool error text is prefixed `Error: `. Every `watcher_*` tool is built from the watcher's endpoint catalog and reports a non-2xx response as `HTTP <status>: <body>`, with the server's JSON body verbatim: read its `code` (and `details` or `issues`) there, e.g. `HTTP 400: {"error":"Validation failed","code":"invalid_request",...}` or `HTTP 503: {"error":"Scan in progress","code":"scan_in_progress"}`. Branch on the code, not the message. The tools reject parameters that don't match their schema before sending anything. Each call waits up to 120 s; a timeout does not cancel a state change on the service, so check the outcome (e.g. `watcher_check_vcs_exclusion` after `watcher_exclude_vcs_path`) before retrying. An unreachable service reads `Service not reachable at <url>.` with a hint to set `apiUrl`. (`watcher_service` comes from the shared Jeeves core toolset and words its own errors.)
|
|
18
18
|
|
|
19
|
-
**Health check:** `GET /status` returns `name`, `version`, `uptime`, `status` (`healthy`/`degraded`/`unhealthy`), and a `health` object containing `collection` (`name`, `pointCount`, `dimensions`), `reindex` progress, and `
|
|
19
|
+
**Health check:** `GET /status` returns `name`, `version`, `uptime`, `status` (`healthy`/`degraded`/`unhealthy`), and a `health` object containing `collection` (`name`, `pointCount`, `dimensions`, `systemIndexes`), `reindex` progress, `initialScan` progress, `embedding` (provider health), and (when version tracking is on) `vcs` (`roots`, `pending`, `trippedRoots`, `oldestTrippedAt`). `status` is `degraded` (still HTTP 200) when embeddings are failing or a version-control root has tripped.
|
|
20
20
|
|
|
21
21
|
**Mental model:** The `watcher_*` tools are thin HTTP wrappers. Each tool call translates to an HTTP request to the watcher API. When tools are available, use them. When they're not (e.g., different session, plugin not loaded), you can hit the API directly. Replace `<PORT>` below with the configured port (default 1936; check `plugins.entries.jeeves-watcher-openclaw.config.apiUrl` in `openclaw.json` if overridden), and add `-H "Authorization: Bearer <key>"` when the service sets `api.apiKey`:
|
|
22
22
|
|
|
@@ -38,6 +38,7 @@ curl http://127.0.0.1:<PORT>/config
|
|
|
38
38
|
| Endpoint | Method | Purpose |
|
|
39
39
|
| --- | --- | --- |
|
|
40
40
|
| `/status` | GET | Health check, uptime, collection stats |
|
|
41
|
+
| `/openapi.json` | GET | OpenAPI 3.1 document of the catalog routes (no key needed) |
|
|
41
42
|
| `/search` | POST | Semantic search (main query interface) |
|
|
42
43
|
| `/config` | GET | Public resolved config (allow-listed keys plus `issues`); optional `?path=<jsonpath>` filter |
|
|
43
44
|
| `/config/validate` | POST | Validate candidate config |
|
|
@@ -55,7 +56,8 @@ curl http://127.0.0.1:<PORT>/config
|
|
|
55
56
|
| `/rules/reapply` | POST | Re-apply rules to indexed files matching `globs` |
|
|
56
57
|
| `/points/delete` | POST | Delete points matching a Qdrant filter |
|
|
57
58
|
| `/render` | POST | Render a document (file path or source reference) through its rule |
|
|
58
|
-
| `/search/facets` | GET | Get search facet values |
|
|
59
|
+
| `/search/facets` | GET | Get search facet definitions and values (`?rules=a,b` scopes them to those rules) |
|
|
60
|
+
| `/search/facets/counts` | POST | Count values of indexed fields over a filter, each document once; counts are approximate (`{ fields, filter?, rules?, limit? }`); `{ min, max }` for number/date fields; `503 not_available` while its system indexes build or past its 10 s budget |
|
|
59
61
|
| `/rebuild-metadata` | POST | Rebuild the enrichment store from Qdrant file point payloads |
|
|
60
62
|
| `/config/schema` | GET | Get config JSON schema |
|
|
61
63
|
| `/config/match` | POST | Test file paths against inference rules and watch scope |
|
|
@@ -89,7 +91,7 @@ You have access to a **semantic archive** of your human's working world. Documen
|
|
|
89
91
|
|
|
90
92
|
**STOP and ask for a human decision before:**
|
|
91
93
|
|
|
92
|
-
- **Renaming, moving, or reorganizing watched directories.** The watcher has **move detection** enabled by default (`watch.moveDetection.enabled: true`). When a file is moved,
|
|
94
|
+
- **Renaming, moving, or reorganizing watched directories.** The watcher has **move detection** enabled by default (`watch.moveDetection.enabled: true`). When a file is moved, the change source reports an unlink and an add; the `MoveCorrelator` buffers the unlink, matches it with the add via content hash, and processes it as a zero-embedding move (point ID remap, metadata re-inference, enrichment migration). Under the default parcel source, a renamed or moved directory is paired as a whole (at least 90% of its files at the same relative path and size) and each file becomes such a move. **No re-embedding cost for moves.** However, if a rename is blocked (e.g., by a file lock from the watcher or another service), **do NOT work around it by creating new directories and copying/moving files**. That creates duplicate embeddings at the new paths while the old paths still exist. Instead: stop the blocking service, perform the rename, restart.
|
|
93
95
|
- **Changing `watch.paths` to add large directory trees.** Adding a new watch root triggers initial indexing of every matching file under it.
|
|
94
96
|
- **Running `scope: "full"` reindex.** Every watched file is re-extracted (a file whose text to embed changed, or that was never indexed, is re-embedded) and every indexed source document is retrieved through its callback and always re-embedded. Use `scope: "rules"` for inference rule changes (no file re-embedding; only metadata reapplication).
|
|
95
97
|
- **Any bulk file operation** (mass copy, mass move, template-based file generation) under watched paths.
|
|
@@ -119,13 +121,13 @@ When the plugin loads and the watcher service is NOT yet set up, drive the entir
|
|
|
119
121
|
|
|
120
122
|
### Step 1: Check Node.js
|
|
121
123
|
|
|
122
|
-
Verify Node.js is installed and version ≥ 22.
|
|
124
|
+
Verify Node.js is installed and version ≥ 24.22.2:
|
|
123
125
|
|
|
124
126
|
```bash
|
|
125
127
|
node --version
|
|
126
128
|
```
|
|
127
129
|
|
|
128
|
-
If missing or too old, guide the user to install Node.js 22.
|
|
130
|
+
If missing or too old, guide the user to install Node.js 24.22.2 or later from https://nodejs.org or via their package manager.
|
|
129
131
|
|
|
130
132
|
### Step 2: Install Qdrant
|
|
131
133
|
|
|
@@ -344,7 +346,7 @@ Call `watcher_status` (or `curl http://127.0.0.1:1936/status`). Confirm:
|
|
|
344
346
|
- Qdrant collection exists with expected dimensions (3072)
|
|
345
347
|
- Point count is increasing (initial indexing in progress)
|
|
346
348
|
|
|
347
|
-
If the point count is 0 after a minute, check `
|
|
349
|
+
If the point count is 0 after a minute, check `watcher_list_issues` for processing failures.
|
|
348
350
|
|
|
349
351
|
### Step 8: Orientation
|
|
350
352
|
|
|
@@ -366,7 +368,7 @@ On sessions after bootstrap is complete:
|
|
|
366
368
|
|
|
367
369
|
## Tools
|
|
368
370
|
|
|
369
|
-
The plugin registers 18 tools: `watcher_status`, `watcher_config`, `watcher_config_apply`, `watcher_service`, `watcher_search`, `
|
|
371
|
+
The plugin registers 18 tools: `watcher_status`, `watcher_config`, `watcher_config_apply`, `watcher_service`, `watcher_search`, `watcher_set_metadata`, `watcher_validate_config`, `watcher_reindex`, `watcher_scan`, `watcher_list_issues`, `watcher_walk`, and the seven version-control tools (see [Version Tracking](#version-tracking)).
|
|
370
372
|
|
|
371
373
|
### `watcher_search`
|
|
372
374
|
|
|
@@ -379,22 +381,22 @@ Semantic search over indexed documents (`POST /search`).
|
|
|
379
381
|
|
|
380
382
|
Returns an array of `{ id, score, payload }` ordered by score (see [Search Result Shape](#search-result-shape)). A filter Qdrant rejects is `400 invalid_request`; an exhausted embedding budget is `503 embedding_unavailable`.
|
|
381
383
|
|
|
382
|
-
### `
|
|
384
|
+
### `watcher_set_metadata`
|
|
383
385
|
|
|
384
386
|
Set or update metadata on a document (`POST /metadata`).
|
|
385
387
|
|
|
386
388
|
- `path` (string, required) — file path of the document (absolute or watched path)
|
|
387
389
|
- `metadata` (object, required) — key-value metadata to merge
|
|
388
390
|
|
|
389
|
-
Returns `{ ok: true, matched_rules }`. The tool addresses files only; to enrich a source document, call `POST /metadata` directly with `{ "source": "<name>://<id>", "metadata": { ... } }` (exactly one of `path` or `source`).
|
|
391
|
+
Returns `{ ok: true, matched_rules }`. If the document is busy (being indexed) for 10 s, the tool reports `503 not_available` with `Retry-After: 10` and changes nothing; retry after 10 s. The tool addresses files only; to enrich a source document, call `POST /metadata` directly with `{ "source": "<name>://<id>", "metadata": { ... } }` (exactly one of `path` or `source`).
|
|
390
392
|
|
|
391
393
|
### `watcher_status`
|
|
392
394
|
|
|
393
|
-
Service health check (`GET /status`, never needs the API key). Returns `name`, `version`, `uptime`, `status`, and a `health` object: `collection` (`name`, `pointCount`, `dimensions`), `reindex` (`active`; while active also `scope`, `startedAt`, `filesProcessed`, `totalFiles`), and `
|
|
395
|
+
Service health check (`GET /status`, never needs the API key). Returns `name`, `version`, `uptime`, `status`, and a `health` object: `collection` (`name`, `pointCount`, `dimensions`, and `systemIndexes`: the state of each index the service creates itself, e.g. `{ "chunk_index": "ready", "file_path": "ready", "matched_rules": "building" }`; `building`, `ready`, `conflict` or `failed`), `embedding` (`state` `ok` or `failing`, `lastSuccessAt`, `lastError` `{ at, code }`, `failingSince`, `backoffUntil`; codes only, never provider text), `reindex` (`active`; while active also `scope`, `startedAt`, `filesProcessed`, `totalFiles`), `initialScan`, and `vcs` when version tracking is on: `roots`, `pending` (changes not yet committed), `trippedRoots` (roots whose commits keep failing) and `oldestTrippedAt`.
|
|
394
396
|
|
|
395
397
|
After a service restart, the `health.initialScan` field shows scan progress:
|
|
396
398
|
|
|
397
|
-
- `active: true` — filesystem walk in progress; `filesMatched` and `filesEnqueued` grow until chokidar completes
|
|
399
|
+
- `active: true` — filesystem walk in progress; `filesMatched` and `filesEnqueued` grow until the initial walk (or chokidar's scan) completes
|
|
398
400
|
- `active: false` with `completedAt`/`durationMs` — scan finished
|
|
399
401
|
|
|
400
402
|
Use this to determine if the service is still initializing after a restart.
|
|
@@ -407,7 +409,7 @@ Query the effective runtime config via JSONPath (`GET /config`). Returns the ful
|
|
|
407
409
|
|
|
408
410
|
The document holds only the allow-listed keys `description`, `watch`, `configWatch`, `search`, `schemas`, `inferenceRules`, `mapHelpers`, `templateHelpers`, `maps`, `templates`, plus `issues` (the current issues). `api`, `sources`, `embedding`, `vectorStore` (and their keys) are never included. Each rule carries `source` (`config`, or the registering source of a virtual rule) and `values` (the runtime values index). File references (`map`, `maps`, `templates`) and named schema references are always resolved. An invalid JSONPath is `400 invalid_request`.
|
|
409
411
|
|
|
410
|
-
### `
|
|
412
|
+
### `watcher_validate_config`
|
|
411
413
|
|
|
412
414
|
Validate config and optionally test file paths (`POST /config/validate`).
|
|
413
415
|
|
|
@@ -421,10 +423,11 @@ Partial configs are merged into the running config shallowly: each top-level key
|
|
|
421
423
|
Apply config changes (`POST /config/apply`, sent as `{ patch: config }`).
|
|
422
424
|
|
|
423
425
|
- `config` (object, required) — full or partial config to apply
|
|
426
|
+
- `replace` (boolean, optional) — replace the whole config with `config` instead of merging
|
|
424
427
|
|
|
425
428
|
Partial configs are deep-merged into the config file the service runs from (objects recursively, arrays replaced, `inferenceRules` by rule name), so `{}` or a single key is valid. The merged result is validated and written to disk, then the `configWatch.reindex` scope (default `issues`) runs; that reindex covers files only. With `configWatch.enabled` (default `true`) the service picks up the written file without a restart, including new/removed watch paths (the filesystem watcher is rebuilt), inference rule changes, move detection settings, and gitignore filter updates.
|
|
426
429
|
|
|
427
|
-
Returns `{ applied: true, config }`. `config` is redacted through the same allow-list as `GET /config`: `api`, `sources` and provider keys are never echoed. When the file was written but the post-write apply step failed, the body also carries `warning` (a string describing the failure). An invalid merged config is a tool error reading `HTTP 400
|
|
430
|
+
Returns `{ applied: true, config }`. `config` is redacted through the same allow-list as `GET /config`: `api`, `sources` and provider keys are never echoed. When the file was written but the post-write apply step failed, the body also carries `warning` (a string describing the failure). An invalid merged config is a tool error reading `HTTP 400: {"error":"Config validation failed","code":"invalid_request","issues":[...]}`, so run `watcher_validate_config` first. A config file the service cannot read or write is `HTTP 500` with the generic `internal_error` body, the cause in the service log.
|
|
428
431
|
|
|
429
432
|
### `watcher_reindex`
|
|
430
433
|
|
|
@@ -435,7 +438,7 @@ Trigger a reindex operation (`POST /reindex`). Non-prune scopes return a `plan`
|
|
|
435
438
|
- `scope` (string, optional) — Reindex scope. The tool sends `"rules"` when omitted (the HTTP API's own default is `"issues"`). One of:
|
|
436
439
|
- `"rules"` — Re-apply inference rules to every watched file (no re-embedding; changed values written, keys the rules no longer project removed). With `path`, only files matching those globs. Without `path`, every indexed source document is also retrieved through its callback and its stored rule re-applied: unchanged content gets a metadata-only update, and a document is re-embedded only if its rendered text changed.
|
|
437
440
|
- `"full"` — Re-extract and re-process every watched file (a file is re-embedded when the text to embed changed or it was never indexed), and retrieve and always re-embed every indexed source document. Clears the runtime values index first.
|
|
438
|
-
- `"issues"` — Re-process the documents in `
|
|
441
|
+
- `"issues"` — Re-process the documents in `watcher_list_issues`: failed files, and failed source references (with their stored rule, or the `rule` recorded on the issue when the document was never indexed).
|
|
439
442
|
- `"path"` — Re-process a specific file or all files under a directory. Requires `path`. Each target must be watched and not gitignored (`403 path_not_watched`) and must exist (`404 not_found`). Files only.
|
|
440
443
|
- `"prune"` — Delete Qdrant points for files no longer in watch scope (removed paths, gitignored files, deleted files). No re-embedding. Pure cleanup. Never selects source points (`source` set, no `file_path`).
|
|
441
444
|
- `path` (string | string[], optional) — Target file(s) or directories for `"path"` (required there), or globs narrowing `"rules"`. Ignored by other scopes.
|
|
@@ -495,7 +498,7 @@ Filter-only point query without vector search (`POST /scan`). Use for structural
|
|
|
495
498
|
|
|
496
499
|
- `filter` (object, required) — Qdrant filter object. Required to prevent accidental full-collection scans.
|
|
497
500
|
- `limit` (number, optional) — page size (integer 1 to 1000), default 100
|
|
498
|
-
- `cursor` (string, optional) — opaque cursor from previous response for pagination
|
|
501
|
+
- `cursor` (string or number, optional) — opaque cursor from previous response for pagination
|
|
499
502
|
- `fields` (string[], optional) — payload fields to return (projection)
|
|
500
503
|
- `countOnly` (boolean, optional) — if true, return `{ count }` instead of points
|
|
501
504
|
|
|
@@ -509,7 +512,7 @@ Filter-only point query without vector search (`POST /scan`). Use for structural
|
|
|
509
512
|
"payload": { "file_path": "/data/tickets/PROJ-123.json" }
|
|
510
513
|
}
|
|
511
514
|
],
|
|
512
|
-
"cursor": "opaque
|
|
515
|
+
"cursor": "opaque string, number or null"
|
|
513
516
|
}
|
|
514
517
|
```
|
|
515
518
|
|
|
@@ -545,7 +548,7 @@ Manage the watcher background service (install, uninstall, start, stop, restart,
|
|
|
545
548
|
|
|
546
549
|
Returns the service manager's response. On Windows uses NSSM, on Linux systemd, on macOS launchd. Only `install` needs `configRoot` (see [Plugin Installation](#plugin-installation)).
|
|
547
550
|
|
|
548
|
-
### `
|
|
551
|
+
### `watcher_list_issues`
|
|
549
552
|
|
|
550
553
|
Get runtime processing failures (`GET /issues`). Returns `{ count, issues: { [key]: IssueRecord[] } }`: `count` is the number of documents with issues, and each key is a file path or a source reference (`<name>://<id>`). Each `IssueRecord` has `type` (one of the [issue codes](#error-categories)), `message`, `timestamp`, and optionally `operation`, `property`, `rule`, `rules`, `types`, `details`.
|
|
551
554
|
|
|
@@ -818,10 +821,10 @@ Search gives you chunks; use `read` with `file_path` for the complete document.
|
|
|
818
821
|
|
|
819
822
|
## Path Testing
|
|
820
823
|
|
|
821
|
-
When uncertain whether a file would be indexed, test it against the rules. `
|
|
824
|
+
When uncertain whether a file would be indexed, test it against the rules. `watcher_validate_config` with `testPaths` (and no `config`) runs the current rules against each path and returns `{ path, matchedRules, metadata }` per path (`error: "File not found"` when the file cannot be read):
|
|
822
825
|
|
|
823
826
|
```
|
|
824
|
-
|
|
827
|
+
watcher_validate_config: testPaths=["/data/tickets/PROJ-123.json"]
|
|
825
828
|
```
|
|
826
829
|
|
|
827
830
|
Or call `POST /config/match` directly with `{ "paths": [...] }`. It returns `{ matches: [{ rules, watched }] }`, one entry per path, without reading the files:
|
|
@@ -846,12 +849,19 @@ Each inference rule has:
|
|
|
846
849
|
- `render` (optional) — declarative frontmatter + Markdown renderer (mutually exclusive with `template`)
|
|
847
850
|
- `renderAs` (optional) — output extension (1-10 lowercase alphanumerics); requires `template` or `render`
|
|
848
851
|
|
|
852
|
+
### Authoring Notes
|
|
853
|
+
|
|
854
|
+
- **`maps` entries are bare strings or inline maps.** A string value is a file path, loaded and parsed as a JsonMap at startup. A `{ path, description }` object is kept as-is and never loaded from the file, so it silently does nothing useful. (`mapHelpers` and `templateHelpers` are different: `{ path, description }` objects are their documented form.)
|
|
855
|
+
- **Metadata is derived with `set`, not `attributes`.** Each schema property's `set` template produces its value. There is no `attributes` key in the config schema; older configs and examples that use one need rewriting.
|
|
856
|
+
- **`render.frontmatter` accepts picomatch globs and `!` exclusions** alongside explicit keys, e.g. `["meta_id", "*", "!_*", "!chunk_*"]`. Explicit names keep their listed order; keys matched by a glob follow, sorted alphabetically; a key matching an exclusion is dropped.
|
|
857
|
+
- **Virtual rules have a startup window.** Virtual rules are registered at runtime by other services (`POST /rules/register`, e.g. jeeves-meta), so they are absent during the initial file scan after a watcher start. Files indexed in that window lack virtual-rule metadata until the registration's automatic rules reindex runs, or until `POST /rules/reapply` covers them. If metadata from a virtual rule is missing right after a restart, check whether its service has registered yet.
|
|
858
|
+
|
|
849
859
|
### Config Workflow
|
|
850
860
|
|
|
851
861
|
1. Edit config (or build partial config object)
|
|
852
|
-
2. Validate: `
|
|
862
|
+
2. Validate: `watcher_validate_config` with optional `testPaths` for dry-run preview
|
|
853
863
|
3. Apply: `watcher_config_apply` — validates, writes, triggers the `configWatch.reindex` reindex
|
|
854
|
-
4. Monitor: `
|
|
864
|
+
4. Monitor: `watcher_list_issues` for runtime processing failures
|
|
855
865
|
|
|
856
866
|
### Reindex Concurrency
|
|
857
867
|
|
|
@@ -874,7 +884,7 @@ Progress is reported via `watcher_status` (`health.reindex.filesProcessed` / `he
|
|
|
874
884
|
### Escalation Path
|
|
875
885
|
|
|
876
886
|
1. `watcher_status` — is the service healthy? Is a reindex running? Is the initial scan still active?
|
|
877
|
-
2. `
|
|
887
|
+
2. `watcher_list_issues` — which documents are failing and why?
|
|
878
888
|
3. `watcher_config` with `$.issues` — the same issue records via JSONPath
|
|
879
889
|
4. Check logs at the configured log path
|
|
880
890
|
|
|
@@ -892,11 +902,32 @@ Every issue record's `type` is one of these codes:
|
|
|
892
902
|
- `no_content` — nothing to embed
|
|
893
903
|
- `source_unavailable` — the source callback failed
|
|
894
904
|
- `unsupported_content_type` — the source callback returned a non-JSON body
|
|
905
|
+
- `too_large` — the document is over a `processing` ceiling (`maxFileBytes`, `maxChunksPerFile` or `maxTextBytes`); it is not embedded and its points are deleted. Raise the ceiling and run `reindex` with scope `issues` to restore it
|
|
895
906
|
|
|
896
907
|
Source-document issues always carry `rule` (the designated rule of the failed run).
|
|
897
908
|
|
|
898
909
|
**Issues are self-healing:** resolved on successful re-process. The issues file always represents the current set of unresolved problems: a live todo list.
|
|
899
910
|
|
|
911
|
+
### Change Source
|
|
912
|
+
|
|
913
|
+
`watcher_status` reports the change source under `health.changeSource` (`@parcel/watcher` by default, chokidar on request or when polling):
|
|
914
|
+
|
|
915
|
+
- **Service refuses to start, log names `@parcel/watcher failed to load`:** the platform binary is missing or broken. Reinstall without `--omit=optional`, or set `watch.changeSource: chokidar` (the manual switch; a reload rebuilds the watcher with one full initial scan).
|
|
916
|
+
- **Rising `reconcileEvents`:** the source is missing events and reconciliation is finding them. **Rising `resubscribes`:** subscriptions keep failing (Linux). **Rising `renewFailures`:** a Linux renewal could not unsubscribe; restart the service. **`unavailableRoots` above 0:** a watch root is missing or unreadable (an unmounted share); its files keep their points until it returns. **High `pendingStability`, or a long `lastReconcileDurationMs` / `lastRenewDurationMs`:** a large write burst or a slow disk; a long renewal pauses event handling for every root.
|
|
917
|
+
- **Linux, a file in a moved-in or renamed folder is indexed late:** changes inside folders nested in a newly created or moved-in tree, or in a directory renamed within a root, are missed until the root's subscription is renewed at the next periodic reconcile, up to `watch.reconcileIntervalMs` (15 minutes by default) late. Expected; shorten the interval if the latency matters. The files moved in with the tree are indexed at once.
|
|
918
|
+
- **Linux, events lost under a write burst with nothing in the log:** parcel cannot detect an inotify queue overflow. Check `sysctl fs.inotify.max_queued_events` (recommended 1048576) and `fs.inotify.max_user_watches` (the start log warns at 90%); the periodic reconcile finds what was lost (`reconcileEvents` rises).
|
|
919
|
+
- **Windows, files in deep folders indexed only by reconciliation:** expected. Under parcel, creating or changing a file whose path is 260 characters or more produces no change event at either `LongPathsEnabled` setting, so it is indexed at the next periodic reconcile, up to `watch.reconcileIntervalMs` late. Nothing to fix; check that `watch.reconcileIntervalMs` is not 0. (`LongPathsEnabled = 1` is still recommended for other tools; it is a host change for the owner.)
|
|
920
|
+
- **Windows, `lastRestartCause` set:** under parcel the service never unsubscribes on Windows (`@parcel/watcher` 2.6.0 crashes the process there), so a reload that rebuilds the watcher, a subscription error or a vanished watch root exits with code 75 and the service manager restarts it. `watch-config-changed`, `subscription-error` or `root-gone` says why, `lastRestartAt` when. If the service stays down after such an exit, its service manager is not restarting it on exit (NSSM: `AppExit Default Restart`).
|
|
921
|
+
|
|
922
|
+
### Index Check at Start
|
|
923
|
+
|
|
924
|
+
After the start walk the service deletes the indexed documents of files gone from disk (deleted or moved while it was down). `watcher_status` reports it under `health.indexCheck` (`state`, `at`, `durationMs`, `checked`, `removed`, `skippedRoots`, `capped`):
|
|
925
|
+
|
|
926
|
+
- **`capped` above 0:** under some watch root more than 10% of the indexed documents (once more than 20 are missing) or more than 1,000 were missing from disk or filters, so nothing was deleted there; the log names the root. Run `watcher_reindex` with scope `prune` and `dryRun: true`, check the plan, then run it.
|
|
927
|
+
- **`state: failed`:** the index could not be listed (Qdrant down), or the service stopped first; it runs again at the next start.
|
|
928
|
+
- **`skippedRoots` above 0:** a root was unavailable, unwatched, gone, or its start walk failed; its deletions wait for the next start or a `prune`.
|
|
929
|
+
- **Files that still exist but are now ignored** keep their points: that is `prune`'s job. `watch.indexCheckOnStart: false` turns the check off.
|
|
930
|
+
|
|
900
931
|
---
|
|
901
932
|
|
|
902
933
|
## Helper Management
|
|
@@ -942,7 +973,7 @@ Retrieve extracted text from neighboring files in the same directory with the sa
|
|
|
942
973
|
|
|
943
974
|
## Enrichment
|
|
944
975
|
|
|
945
|
-
Use `
|
|
976
|
+
Use `watcher_set_metadata` to tag documents after analysis (e.g., `reviewed: true`, project labels).
|
|
946
977
|
|
|
947
978
|
**Enrichments are durable.** Stored in a SQLite database (`<stateDir>/enrichments.sqlite`, default `stateDir` `.jeeves-metadata`), enrichments survive full reindexes. Enriching a file that is not indexed yet stores the enrichment, which applies once the file is indexed. When the watcher re-processes a file, enrichments are merged with inference rule output using composable semantics: scalar fields overwrite, array fields union+deduplicate.
|
|
948
979
|
|
|
@@ -968,56 +999,56 @@ Use `watcher_enrich` to tag documents after analysis (e.g., `reviewed: true`, pr
|
|
|
968
999
|
|
|
969
1000
|
## Version Tracking
|
|
970
1001
|
|
|
971
|
-
The watcher includes built-in history and undo for your watched files. When enabled, every change to a watched file is automatically versioned. You can view the history of any file or folder, see exactly what changed between versions, retrieve old versions, and undo changes — all through the
|
|
1002
|
+
The watcher includes built-in history and undo for your watched files. When enabled, every change to a watched file is automatically versioned. You can view the history of any file or folder, see exactly what changed between versions, retrieve old versions, and undo changes — all through the version-control tools below.
|
|
972
1003
|
|
|
973
1004
|
### Tools
|
|
974
1005
|
|
|
975
1006
|
| Tool | Purpose |
|
|
976
1007
|
| --- | --- |
|
|
977
|
-
| `
|
|
978
|
-
| `
|
|
979
|
-
| `
|
|
980
|
-
| `
|
|
981
|
-
| `
|
|
982
|
-
| `
|
|
983
|
-
| `
|
|
1008
|
+
| `watcher_get_vcs_status` | Check version tracking health: enabled state, tracked roots, remote sync status |
|
|
1009
|
+
| `watcher_list_vcs_history` | View change history for a file or folder, with optional date range and limit |
|
|
1010
|
+
| `watcher_show_vcs_file` | Retrieve the content of a file at a specific past version |
|
|
1011
|
+
| `watcher_diff_vcs` | Show what changed between two versions, or between a past version and now |
|
|
1012
|
+
| `watcher_revert_vcs` | Undo changes by restoring files to a specific past version |
|
|
1013
|
+
| `watcher_exclude_vcs_path` | Exclude a path from version history (it stays in search), or remove the exclusion; untracks matching files |
|
|
1014
|
+
| `watcher_check_vcs_exclusion` | Check whether git ignores a path and why (rule, file, line) |
|
|
984
1015
|
|
|
985
1016
|
### Usage Patterns
|
|
986
1017
|
|
|
987
1018
|
**View recent changes to a file:**
|
|
988
1019
|
|
|
989
1020
|
```
|
|
990
|
-
|
|
1021
|
+
watcher_list_vcs_history: glob="/data/tickets/PROJ-123.json", limit=10
|
|
991
1022
|
```
|
|
992
1023
|
|
|
993
1024
|
**See what changed between two versions:**
|
|
994
1025
|
|
|
995
1026
|
```
|
|
996
|
-
|
|
1027
|
+
watcher_diff_vcs: glob="/data/tickets/PROJ-123.json", commit="abc1234"
|
|
997
1028
|
```
|
|
998
1029
|
|
|
999
1030
|
**Restore a file to a previous version:**
|
|
1000
1031
|
|
|
1001
1032
|
```
|
|
1002
|
-
|
|
1033
|
+
watcher_revert_vcs: glob="/data/tickets/PROJ-123.json", commit="abc1234"
|
|
1003
1034
|
```
|
|
1004
1035
|
|
|
1005
1036
|
**View old content without restoring:**
|
|
1006
1037
|
|
|
1007
1038
|
```
|
|
1008
|
-
|
|
1039
|
+
watcher_show_vcs_file: path="/data/tickets/PROJ-123.json", commit="abc1234"
|
|
1009
1040
|
```
|
|
1010
1041
|
|
|
1011
1042
|
**Exclude files that don't need versioning** (e.g., Jira issues that are read-only syncs):
|
|
1012
1043
|
|
|
1013
1044
|
```
|
|
1014
|
-
|
|
1045
|
+
watcher_exclude_vcs_path: glob="/data/tickets/**/*.json"
|
|
1015
1046
|
```
|
|
1016
1047
|
|
|
1017
1048
|
**Check if a file is excluded and why:**
|
|
1018
1049
|
|
|
1019
1050
|
```
|
|
1020
|
-
|
|
1051
|
+
watcher_check_vcs_exclusion: path="/data/tickets/PROJ-123.json"
|
|
1021
1052
|
```
|
|
1022
1053
|
|
|
1023
1054
|
### Enabling Version Tracking
|
|
@@ -1028,9 +1059,17 @@ Squash retention activates by default when VCS is enabled, even without explicit
|
|
|
1028
1059
|
|
|
1029
1060
|
### Excluding Paths
|
|
1030
1061
|
|
|
1031
|
-
Not all watched files need version history. For example, if Jira issues are synced read-only, there's nothing to "undo." Use `
|
|
1062
|
+
Not all watched files need version history. For example, if Jira issues are synced read-only, there's nothing to "undo." Use `watcher_exclude_vcs_path` to stop tracking specific paths.
|
|
1063
|
+
|
|
1064
|
+
The exclusion is VCS-only: the pattern goes to the root's `.git/info/exclude`, so the files stop being versioned but stay indexed and searchable.
|
|
1032
1065
|
|
|
1033
|
-
|
|
1066
|
+
- **Destructive.** Adding a pattern untracks the tracked files it matches, in one commit: their history ends at their last committed version (the files stay on disk). `remove: true` deletes the pattern but does not restore history; the files are versioned again from their next change.
|
|
1067
|
+
- **One gitignore pattern, root-anchored.** The pattern is written as `/` plus the glob relative to the root, so `/data/tickets/*.json` (root `/data`) matches only directly under `tickets/`; use `**/` for any depth. Pass `root` to give a root-relative glob (`tickets/**/*.json`, without a leading `/`: with `root`, a glob starting with `/` is a filesystem path and must lie under the root).
|
|
1068
|
+
- **Brackets are a character class.** `Report [draft].docx` matches `Report d.docx`; escape them to name the file: `Report \[draft\].docx`.
|
|
1069
|
+
- **Refused (`400`):** a newline, a leading `!` or `#`, braces, a pattern matching the whole root (`*`, `**`, `**/*`, ...), or a glob outside the given `root`.
|
|
1070
|
+
- **More than 100 files** to untrack need `confirm: true`; without it the tool reports `409 confirm_required` with the count and changes nothing. Check the count with the user before confirming.
|
|
1071
|
+
- **Busy root.** If version control is busy on the root for 30 s the tool reports `503 not_available`; retry after 30 s.
|
|
1072
|
+
- `watcher_check_vcs_exclusion` reports `excluded: false` for a tracked file even when a human `.gitignore` matches it (git never reports tracked paths as ignored); exclude it to untrack it.
|
|
1034
1073
|
|
|
1035
1074
|
### Score Interpretation
|
|
1036
1075
|
|
|
@@ -1046,6 +1085,19 @@ If the watcher is unreachable:
|
|
|
1046
1085
|
- Fall back to direct `read` for known file paths
|
|
1047
1086
|
- Do not retry silently in a loop
|
|
1048
1087
|
|
|
1088
|
+
If a tool fails with `HTTP 401` (`unauthorized`):
|
|
1089
|
+
|
|
1090
|
+
- The watcher sets `api.apiKey` and the plugin sent no key, or a different one.
|
|
1091
|
+
- Ask the user to set `plugins.entries.jeeves-watcher-openclaw.config.apiKey` in `openclaw.json` (or the `JEEVES_WATCHER_API_KEY` environment variable of the gateway) to the service's `api.apiKey`. The tools read it on every call, so no restart is needed.
|
|
1092
|
+
- Never ask for, print or guess the key. `GET /status` and `GET /openapi.json` never need it.
|
|
1093
|
+
|
|
1094
|
+
If a tool or call fails with `HTTP 503` (`not_available`) and a `Retry-After` header:
|
|
1095
|
+
|
|
1096
|
+
- `POST /metadata` (`watcher_set_metadata`), `POST /rules/reapply` and `POST /documents/delete` wait at most 10 s for a document that is being indexed, then answer `503` with `Retry-After: 10`. A single-document request changed nothing; a multi-document request kept the documents it already changed. All three are idempotent: retry the same request after 10 s.
|
|
1097
|
+
- `watcher_exclude_vcs_path` waits 30 s for a busy version-control root.
|
|
1098
|
+
|
|
1099
|
+
If a tool fails with `HTTP 500: {"error":"Response validation failed","code":"internal_error"}`, the watcher produced a response that doesn't match its own schema: a server bug. Report it with the request you made; retrying won't help.
|
|
1100
|
+
|
|
1049
1101
|
If tools are unavailable (plugin not loaded in this session):
|
|
1050
1102
|
|
|
1051
1103
|
- The watcher API is still accessible via direct HTTP calls
|
package/dist/src/auth.test.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module plugin/auth.test
|
|
3
|
-
* Plugin-level bearer-key tests through the real entry point: every HTTP tool sends the key when configured and none when unset; the key never reaches logs or tool results.
|
|
3
|
+
* Plugin-level bearer-key tests through the real entry point: every HTTP tool (all catalog-built) sends the key when configured and none when unset; the key never reaches logs or tool results.
|
|
4
4
|
*/
|
|
5
5
|
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module plugin/catalogTools
|
|
3
|
+
* Every watcher tool, built from `WATCHER_CATALOG` by core's toolset (D38): the four standard tools (`watcher_status`, `watcher_service`, `watcher_config`, `watcher_config_apply`) and the 14 domain tools, all sending the bearer key where their entry requires it; `registerCatalogTool` registers one of them as an optional tool.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Each tool is named `watcher_` plus its entry's verb-first name in
|
|
7
|
+
* snake_case (D77, `toToolName`). Parameters come from the entry's request
|
|
8
|
+
* schemas; descriptions keep the 0.17.0 wording where it is still true
|
|
9
|
+
* (`WATCHER_TOOL_SELECTION`). `watcher_search` and `watcher_scan` are
|
|
10
|
+
* `catalogMode: 'direct-only'`, so OpenClaw Tool Search keeps them
|
|
11
|
+
* model-visible: semantic search must be a direct tool or the model reaches
|
|
12
|
+
* for grep first. Every call runs on core's 120 s default timeout
|
|
13
|
+
* (`DEFAULT_FETCH_TIMEOUT_MS`, D137), the status probe on 5 s. Errors are
|
|
14
|
+
* reported as core's `HTTP <status>: <body>`; API-key guidance lives in the
|
|
15
|
+
* skill's troubleshooting section (spec #281 D31).
|
|
16
|
+
*/
|
|
17
|
+
import { type JeevesComponentDescriptor, type PluginApi, type ToolDescriptor } from '@karmaniverous/jeeves';
|
|
18
|
+
/** `watcher_exclude_vcs_path` description (D103, D137). */
|
|
19
|
+
export declare const VCS_EXCLUDE_DESCRIPTION: string;
|
|
20
|
+
/** `watcher_check_vcs_exclusion` description (0.21.0, spec B4). */
|
|
21
|
+
export declare const VCS_CHECK_DESCRIPTION = "Check whether git ignores a path and why: the rule, the file holding it and its line";
|
|
22
|
+
/** The scope `watcher_reindex` sends when the caller omits one: 0.17.0's default (owner ruling, 2026-11-04). */
|
|
23
|
+
export declare const REINDEX_DEFAULT_SCOPE = "rules";
|
|
24
|
+
/** `watcher_reindex` description. */
|
|
25
|
+
export declare const REINDEX_DESCRIPTION = "Trigger a reindex of the watched files. Without scope, re-applies inference rules (scope \"rules\"); the HTTP API's own default is \"issues\".";
|
|
26
|
+
/**
|
|
27
|
+
* The 14 domain tools, in their 0.17.0 registration order, by catalog entry.
|
|
28
|
+
* Descriptions keep the 0.17.0 text unless it changed with the tool.
|
|
29
|
+
*/
|
|
30
|
+
export declare const WATCHER_TOOL_SELECTION: {
|
|
31
|
+
readonly search: {
|
|
32
|
+
readonly description: "Semantic search over indexed documents. Supports Qdrant filters. This is a direct tool: call it directly, never through tool_call.";
|
|
33
|
+
readonly catalogMode: "direct-only";
|
|
34
|
+
};
|
|
35
|
+
readonly setMetadata: {
|
|
36
|
+
readonly description: "Set or update metadata on a document by file path or source reference.";
|
|
37
|
+
};
|
|
38
|
+
readonly validateConfig: {
|
|
39
|
+
readonly description: "Validate a candidate config (or current config if omitted). Optionally test file paths against the config to preview rule matching and metadata output.";
|
|
40
|
+
};
|
|
41
|
+
readonly reindex: {
|
|
42
|
+
readonly description: "Trigger a reindex of the watched files. Without scope, re-applies inference rules (scope \"rules\"); the HTTP API's own default is \"issues\".";
|
|
43
|
+
};
|
|
44
|
+
readonly scan: {
|
|
45
|
+
readonly description: "Filter-only point query without vector search. Returns metadata for points matching a Qdrant filter. Use for structural queries: file enumeration, staleness checks, delta computation. Use watcher_search for semantic/similarity queries. This is a direct tool: call it directly, never through tool_call.";
|
|
46
|
+
readonly catalogMode: "direct-only";
|
|
47
|
+
};
|
|
48
|
+
readonly listIssues: {
|
|
49
|
+
readonly description: "Get runtime processing failures. Shows the documents (file path or source reference) that failed processing and why.";
|
|
50
|
+
};
|
|
51
|
+
readonly walk: {
|
|
52
|
+
readonly description: "Walk watched filesystem paths with glob intersection. Returns matching file paths from all configured watch roots, applying watch.ignored and gitignore filtering.";
|
|
53
|
+
};
|
|
54
|
+
readonly getVcsStatus: {
|
|
55
|
+
readonly description: "Get version tracking health: enabled state, tracked roots, remote status, last activity";
|
|
56
|
+
};
|
|
57
|
+
readonly listVcsHistory: {
|
|
58
|
+
readonly description: "Query change history by path or glob with optional date range";
|
|
59
|
+
};
|
|
60
|
+
readonly showVcsFile: {
|
|
61
|
+
readonly description: "Retrieve file content at a specific version";
|
|
62
|
+
};
|
|
63
|
+
readonly diffVcs: {
|
|
64
|
+
readonly description: "Show what changed between two versions, or between a version and current";
|
|
65
|
+
};
|
|
66
|
+
readonly revertVcs: {
|
|
67
|
+
readonly description: "Undo changes by restoring files to a specific version";
|
|
68
|
+
};
|
|
69
|
+
readonly excludeVcsPath: {
|
|
70
|
+
readonly description: string;
|
|
71
|
+
};
|
|
72
|
+
readonly checkVcsExclusion: {
|
|
73
|
+
readonly description: "Check whether git ignores a path and why: the rule, the file holding it and its line";
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
/** Every tool the plugin registers, in registration order (0.17.0 order). */
|
|
77
|
+
export declare const WATCHER_TOOL_NAMES: readonly string[];
|
|
78
|
+
/**
|
|
79
|
+
* Core's toolset for the watcher: the four standard tools and the 14 domain
|
|
80
|
+
* tools. The base URL and the bearer key are resolved from `api` on every
|
|
81
|
+
* call.
|
|
82
|
+
*
|
|
83
|
+
* @param api - Plugin API (config source).
|
|
84
|
+
* @param component - Plugin-side component descriptor.
|
|
85
|
+
* @returns The tools, keyed by name.
|
|
86
|
+
*/
|
|
87
|
+
export declare function createCatalogTools(api: PluginApi, component: JeevesComponentDescriptor): Map<string, ToolDescriptor>;
|
|
88
|
+
/**
|
|
89
|
+
* Register one catalog-built tool as an optional tool.
|
|
90
|
+
*
|
|
91
|
+
* @param api - Plugin API (tool registration target).
|
|
92
|
+
* @param catalogTools - Catalog-built tools, by name ({@link createCatalogTools}).
|
|
93
|
+
* @param name - Tool name.
|
|
94
|
+
* @throws When no tool of that name was built.
|
|
95
|
+
*/
|
|
96
|
+
export declare function registerCatalogTool(api: Pick<PluginApi, 'registerTool'>, catalogTools: ReadonlyMap<string, ToolDescriptor>, name: string): void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module plugin/catalogTools.test
|
|
3
|
+
* Tests for the catalog-built toolset: the tool-name rule (D77), registration order, each rebuilt domain tool's request (method, path, query, body, bearer key), the destructive annotation, the 120 s timeout (D137), the error format (D31), and that every `watcher_*` name in the prompt rules and the skill is a built tool (Design 14).
|
|
4
|
+
*/
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module plugin/distSmoke.test
|
|
3
|
+
* Smoke test of the built plugin (`dist/index.js`, as OpenClaw loads it): it registers the 18 tools in their 0.17.0 order (under their D77 names) from its bundled watcher-core and Zod, keeps `watcher_search` and `watcher_scan` `direct-only`, and a catalog-built tool sends the bearer key. Runs after `npm run build`; in CI (which builds before testing) a missing `dist` fails.
|
|
4
|
+
*/
|
|
5
|
+
export {};
|
package/dist/src/helpers.d.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @remarks
|
|
5
5
|
* Only watcher-specific resolution logic (API URL, API key, config root)
|
|
6
|
-
* lives here. Core SDK types and utilities
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* lives here. Core SDK types and utilities should be imported directly from
|
|
7
|
+
* `@karmaniverous/jeeves`; every watcher API request goes through core's
|
|
8
|
+
* catalog toolset (`catalogTools.ts`).
|
|
9
9
|
*
|
|
10
10
|
* @module plugin/helpers
|
|
11
11
|
*/
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module plugin/promptContext
|
|
3
|
-
*
|
|
3
|
+
* Injects the descriptor's always-in-context rules (`promptRules`, from watcher-core) via `before_prompt_build`.
|
|
4
4
|
*
|
|
5
5
|
* @remarks
|
|
6
6
|
* Replaces the v0.x TOOLS.md `## Watcher` section that core's
|
|
7
|
-
* `ComponentWriter` wrote on a timer.
|
|
8
|
-
*
|
|
9
|
-
* `watcher_status` and `watcher_config`, and detail lives in the skill.
|
|
7
|
+
* `ComponentWriter` wrote on a timer. Core registers nothing itself: the
|
|
8
|
+
* plugin passes the descriptor's `promptRules` to `registerPromptContext`.
|
|
10
9
|
*/
|
|
11
|
-
import { type PluginApi } from '@karmaniverous/jeeves';
|
|
12
|
-
/** Static watcher rules the agent must see on every turn. */
|
|
13
|
-
export declare const WATCHER_PROMPT_CONTEXT: string;
|
|
10
|
+
import { type JeevesComponentDescriptor, type PluginApi } from '@karmaniverous/jeeves';
|
|
14
11
|
/**
|
|
15
|
-
* Register the
|
|
12
|
+
* Register the component's prompt rules with OpenClaw's `before_prompt_build` hook.
|
|
16
13
|
*
|
|
17
|
-
* @
|
|
14
|
+
* @param api - Plugin API.
|
|
15
|
+
* @param component - Descriptor carrying `promptRules`.
|
|
16
|
+
* @returns `true` when the hook was registered; `false` when the host has no
|
|
17
|
+
* `api.on` or the descriptor has no rules.
|
|
18
18
|
*/
|
|
19
|
-
export declare function registerWatcherPromptContext(api: PluginApi): boolean;
|
|
19
|
+
export declare function registerWatcherPromptContext(api: PluginApi, component: Pick<JeevesComponentDescriptor, 'promptRules'>): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module plugin/skillFiles
|
|
3
|
+
* Writes the watcher skill (descriptor `skill`, from watcher-core) as `SKILL.md` into the plugin's dist, the folder `openclaw.plugin.json` lists under `skills`. Used by the build (`scripts/build-skills.ts`); writes files.
|
|
4
|
+
*/
|
|
5
|
+
/** Skill folder relative to the dist directory (manifest `skills[0]` minus `dist/`). */
|
|
6
|
+
export declare const SKILL_DIR = "skills/jeeves-watcher";
|
|
7
|
+
/**
|
|
8
|
+
* Write `skill` to `<distDir>/skills/jeeves-watcher/SKILL.md`.
|
|
9
|
+
*
|
|
10
|
+
* @param distDir - The plugin's dist directory.
|
|
11
|
+
* @param skill - Skill markdown (the descriptor's `skill`).
|
|
12
|
+
* @returns The path written.
|
|
13
|
+
*/
|
|
14
|
+
export declare function writeSkill(distDir: string, skill: string): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module test/surfaceDiff
|
|
3
|
+
* Renders the agent-facing differences between two plugin tool surfaces (tool name, description, parameters, catalog mode, options) as Markdown, for the reviewed delta report. Pure.
|
|
4
|
+
*/
|
|
5
|
+
/** One registered tool, as the surface fixtures record it. */
|
|
6
|
+
export interface ToolSurface {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
parameters: {
|
|
10
|
+
type?: string;
|
|
11
|
+
properties?: Record<string, unknown>;
|
|
12
|
+
required?: string[];
|
|
13
|
+
additionalProperties?: unknown;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
};
|
|
16
|
+
catalogMode?: unknown;
|
|
17
|
+
options?: unknown;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render the delta report between a baseline surface and the current one.
|
|
21
|
+
*
|
|
22
|
+
* @param before - Baseline tools, in registration order.
|
|
23
|
+
* @param after - Current tools, in registration order.
|
|
24
|
+
* @param renames - Each renamed baseline tool and its current name.
|
|
25
|
+
* @returns Markdown: one section per tool that changed, then removed and added tools.
|
|
26
|
+
*/
|
|
27
|
+
export declare function renderSurfaceDiff(before: readonly ToolSurface[], after: readonly ToolSurface[], renames: Readonly<Record<string, string>>): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module test/toolRenames
|
|
3
|
+
* The plugin tool renames of 0.18.0 (D77, Design 14): each 0.17.0 tool name and its current name, for the surface tests. Pure data.
|
|
4
|
+
*/
|
|
5
|
+
/** Each renamed 0.17.0 tool name and its current name. */
|
|
6
|
+
export declare const TOOL_RENAMES: Readonly<Record<string, string>>;
|
|
7
|
+
/**
|
|
8
|
+
* A 0.17.0 tool name under its current name.
|
|
9
|
+
*
|
|
10
|
+
* @param name - The 0.17.0 name.
|
|
11
|
+
* @returns The current name.
|
|
12
|
+
*/
|
|
13
|
+
export declare const renamedTool: (name: string) => string;
|