@sage-protocol/openclaw-sage 0.1.8 → 0.1.10
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 +71 -3
- package/dist/index.d.ts +79 -0
- package/dist/index.js +1031 -0
- package/dist/mcp-bridge.d.ts +42 -0
- package/dist/mcp-bridge.js +170 -0
- package/dist/runtime.d.ts +41 -0
- package/dist/runtime.js +317 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +2 -0
- package/openclaw.plugin.json +16 -1
- package/package.json +17 -4
- package/.github/workflows/ci.yml +0 -30
- package/.github/workflows/release-please.yml +0 -19
- package/.release-please-manifest.json +0 -3
- package/CHANGELOG.md +0 -80
- package/SOUL.md +0 -172
- package/release-please-config.json +0 -13
- package/src/index.ts +0 -1179
- package/src/mcp-bridge.test.ts +0 -469
- package/src/mcp-bridge.ts +0 -230
- package/src/openclaw-hook.integration.test.ts +0 -258
- package/src/rlm-capture.e2e.test.ts +0 -279
- package/tsconfig.json +0 -18
package/README.md
CHANGED
|
@@ -5,19 +5,56 @@ MCP bridge plugin that exposes Sage Protocol tools inside OpenClaw via Code Mode
|
|
|
5
5
|
## What It Does
|
|
6
6
|
|
|
7
7
|
- **Code Mode Gateway** - Spawns `sage mcp start` and routes plugin calls through `sage_search`/`sage_execute`/`sage_status`
|
|
8
|
-
- **
|
|
8
|
+
- **Agent Profile (Identity Context)** - Injects wallet, active libraries, and skill counts into every turn so the agent knows who it's working for
|
|
9
|
+
- **Auto-Context Injection** - Injects Sage tool context and skill suggestions via `before_prompt_build` with stable context cached separately from per-turn dynamic context
|
|
9
10
|
- **Injection Guard** - Optional prompt-injection scanning on outgoing `sage_execute` mutations
|
|
10
11
|
- **Crash Recovery** - Automatically restarts the MCP subprocess on unexpected exits
|
|
11
12
|
- **External Servers** - Sage internal tools are available immediately; only external MCP tools require starting servers first via the Sage app, CLI, or raw MCP `hub_*` tools
|
|
12
13
|
|
|
14
|
+
## Agent Profile (Identity Context)
|
|
15
|
+
|
|
16
|
+
Every OpenClaw session automatically gets Sage Protocol identity context injected via the `before_prompt_build` hook. Stable context (protocol description, identity, tool docs) goes in `prependSystemContext` so providers can cache it across turns. Dynamic content (skill suggestions, security guard) goes in `prependContext` and refreshes each turn.
|
|
17
|
+
|
|
18
|
+
Example of what gets injected:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
## Sage Protocol Context
|
|
22
|
+
Sage Protocol is a decentralized network for collaborative prompt, skill, and knowledge
|
|
23
|
+
curation on Base (L2). Skills and prompts live in libraries governed by DAOs. Creators
|
|
24
|
+
and curators earn when their work is used. SXXX is the governance token: hold it to
|
|
25
|
+
vote, create DAOs, and shape the protocol. Burns from activity create deflationary
|
|
26
|
+
pressure — early participants gain governance influence and economic upside as the
|
|
27
|
+
network grows. The more skills published, the more valuable discovery becomes for every
|
|
28
|
+
user and agent.
|
|
29
|
+
|
|
30
|
+
### Active Identity
|
|
31
|
+
- Wallet: 0x9794...507ca (privy, Base Sepolia)
|
|
32
|
+
- Active libraries (6): sage-entrypoints, impeccable-ui-review, sage-review-foundations, ...
|
|
33
|
+
- Libraries: 10 installed (48 skills, 12 prompts)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The context is fetched from the sage CLI (`wallet current`, `library active`, `library list`) and cached for 60 seconds. If the CLI is unavailable or any query fails, the identity block is silently omitted.
|
|
37
|
+
|
|
13
38
|
## Install
|
|
14
39
|
|
|
40
|
+
```bash
|
|
41
|
+
sage init --openclaw
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This is the recommended product path: it installs the bundled OpenClaw plugin, the companion Sage
|
|
45
|
+
skills, and only the scan-only internal hooks.
|
|
46
|
+
|
|
47
|
+
If you only want the raw plugin package flow, you can still run:
|
|
48
|
+
|
|
15
49
|
```bash
|
|
16
50
|
openclaw plugins install @sage-protocol/openclaw-sage
|
|
17
51
|
```
|
|
18
52
|
|
|
19
53
|
After install, **restart the Gateway** for the plugin to take effect.
|
|
20
54
|
|
|
55
|
+
CI validates the packed tarball against the latest published `openclaw` CLI by running
|
|
56
|
+
`npx openclaw@latest plugins install` in an isolated `OPENCLAW_HOME`.
|
|
57
|
+
|
|
21
58
|
### Verify
|
|
22
59
|
|
|
23
60
|
```bash
|
|
@@ -33,6 +70,35 @@ openclaw plugins update openclaw-sage
|
|
|
33
70
|
openclaw plugins update --all
|
|
34
71
|
```
|
|
35
72
|
|
|
73
|
+
### Auto-Enable
|
|
74
|
+
|
|
75
|
+
The plugin sets `enabledByDefault: true` in its manifest, so it auto-enables when referenced in `openclaw.json` config without needing a manual `plugins.allow` entry.
|
|
76
|
+
|
|
77
|
+
### Hook Priority
|
|
78
|
+
|
|
79
|
+
The `before_prompt_build` hook runs at priority 90 (higher = earlier). This ensures Sage's stable system context (protocol description, wallet identity, tool docs) is the base layer that other plugins build on. Dynamic per-turn content (skill suggestions, security guards) goes in `prependContext`.
|
|
80
|
+
|
|
81
|
+
### Secrets Management
|
|
82
|
+
|
|
83
|
+
Sage credentials support OpenClaw's SecretRef system instead of raw environment variables:
|
|
84
|
+
|
|
85
|
+
```json5
|
|
86
|
+
{
|
|
87
|
+
"secrets": {
|
|
88
|
+
"providers": {
|
|
89
|
+
"default": { "source": "env", "allowlist": ["SAGE_*", "KEYSTORE_*"] }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The plugin declares three SecretRef-compatible credentials:
|
|
96
|
+
- `SAGE_IPFS_UPLOAD_TOKEN` — Bearer token for Worker API auth
|
|
97
|
+
- `KEYSTORE_PASSWORD` — Wallet keystore password (non-interactive)
|
|
98
|
+
- `SAGE_DELEGATE_KEYSTORE_PASSWORD` — Delegate keystore password (daemon/operator)
|
|
99
|
+
|
|
100
|
+
These are resolved through OpenClaw's secret provider chain (env, file, or exec) rather than passed as raw env vars.
|
|
101
|
+
|
|
36
102
|
### Login With Code (Privy Device-Code)
|
|
37
103
|
|
|
38
104
|
If browser OAuth is unreliable, use:
|
|
@@ -96,7 +162,7 @@ sage bounties create --mode direct --assignee 0x... --title "Task" --description
|
|
|
96
162
|
|
|
97
163
|
### Auto-Inject / Auto-Suggest
|
|
98
164
|
|
|
99
|
-
This plugin uses OpenClaw's plugin hook API to inject context at the start of each
|
|
165
|
+
This plugin uses OpenClaw's plugin hook API to inject context at the start of each prompt build via `before_prompt_build`.
|
|
100
166
|
|
|
101
167
|
Available config fields:
|
|
102
168
|
|
|
@@ -151,7 +217,9 @@ Notes:
|
|
|
151
217
|
|
|
152
218
|
If you also enabled Sage's OpenClaw _internal hook_ (installed by `sage init`), both the hook and this plugin can inject Sage context.
|
|
153
219
|
|
|
154
|
-
-
|
|
220
|
+
- `sage init --openclaw` now defaults to plugin-first setup and only installs scan-only hooks, so duplicate injection should not happen by default.
|
|
221
|
+
- Only `sage init --openclaw --mode hooks` installs the legacy `agent:bootstrap` injection hook.
|
|
222
|
+
- If you deliberately re-enable bootstrap injection alongside the plugin, disable it with `SAGE_OPENCLAW_INJECT_CONTEXT=0`.
|
|
155
223
|
|
|
156
224
|
The internal hook now also scans `command:new` and `command:stop` through `sage security scan-hook` and prepends warnings when suspicious content is detected.
|
|
157
225
|
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type TSchema } from "@sinclair/typebox";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal type stubs for OpenClaw plugin API.
|
|
4
|
+
*
|
|
5
|
+
* OpenClaw's jiti runtime resolves "openclaw/plugin-sdk" at load time.
|
|
6
|
+
* These stubs keep the code compilable standalone.
|
|
7
|
+
*/
|
|
8
|
+
type PluginLogger = {
|
|
9
|
+
info: (msg: string) => void;
|
|
10
|
+
warn: (msg: string) => void;
|
|
11
|
+
error: (msg: string) => void;
|
|
12
|
+
};
|
|
13
|
+
type PluginServiceContext = {
|
|
14
|
+
config: unknown;
|
|
15
|
+
workspaceDir?: string;
|
|
16
|
+
stateDir: string;
|
|
17
|
+
logger: PluginLogger;
|
|
18
|
+
};
|
|
19
|
+
type PluginApi = {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
logger: PluginLogger;
|
|
23
|
+
pluginConfig?: Record<string, unknown>;
|
|
24
|
+
registerTool: (tool: unknown, opts?: {
|
|
25
|
+
name?: string;
|
|
26
|
+
optional?: boolean;
|
|
27
|
+
}) => void;
|
|
28
|
+
registerService: (service: {
|
|
29
|
+
id: string;
|
|
30
|
+
start: (ctx: PluginServiceContext) => void | Promise<void>;
|
|
31
|
+
stop?: (ctx: PluginServiceContext) => void | Promise<void>;
|
|
32
|
+
}) => void;
|
|
33
|
+
on: (hook: string, handler: (...args: unknown[]) => unknown | Promise<unknown>, opts?: {
|
|
34
|
+
priority?: number;
|
|
35
|
+
}) => void;
|
|
36
|
+
};
|
|
37
|
+
declare function normalizePrompt(prompt: string, opts?: {
|
|
38
|
+
maxBytes?: number;
|
|
39
|
+
}): string;
|
|
40
|
+
declare function extractJsonFromMcpResult(result: unknown): unknown;
|
|
41
|
+
type SkillSearchResult = {
|
|
42
|
+
key?: string;
|
|
43
|
+
name?: string;
|
|
44
|
+
description?: string;
|
|
45
|
+
source?: string;
|
|
46
|
+
library?: string;
|
|
47
|
+
mcpServers?: string[];
|
|
48
|
+
};
|
|
49
|
+
declare function formatSkillSuggestions(results: SkillSearchResult[], limit: number): string;
|
|
50
|
+
/**
|
|
51
|
+
* Convert a single MCP JSON Schema property into a TypeBox type.
|
|
52
|
+
* Handles nested objects, typed arrays, and enums.
|
|
53
|
+
*/
|
|
54
|
+
declare function jsonSchemaToTypebox(prop: Record<string, unknown>): TSchema;
|
|
55
|
+
/**
|
|
56
|
+
* Convert an MCP JSON Schema inputSchema into a TypeBox object schema
|
|
57
|
+
* that OpenClaw's tool system accepts.
|
|
58
|
+
*/
|
|
59
|
+
declare function mcpSchemaToTypebox(inputSchema?: Record<string, unknown>): import("@sinclair/typebox").TObject<{}>;
|
|
60
|
+
declare const plugin: {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
version: string;
|
|
64
|
+
description: string;
|
|
65
|
+
register(api: PluginApi): void;
|
|
66
|
+
};
|
|
67
|
+
/** Map common error patterns to actionable hints */
|
|
68
|
+
declare function enrichErrorMessage(err: Error, toolName: string): string;
|
|
69
|
+
export default plugin;
|
|
70
|
+
export declare const __test: {
|
|
71
|
+
PKG_VERSION: string;
|
|
72
|
+
SAGE_CONTEXT: string;
|
|
73
|
+
normalizePrompt: typeof normalizePrompt;
|
|
74
|
+
extractJsonFromMcpResult: typeof extractJsonFromMcpResult;
|
|
75
|
+
formatSkillSuggestions: typeof formatSkillSuggestions;
|
|
76
|
+
mcpSchemaToTypebox: typeof mcpSchemaToTypebox;
|
|
77
|
+
jsonSchemaToTypebox: typeof jsonSchemaToTypebox;
|
|
78
|
+
enrichErrorMessage: typeof enrichErrorMessage;
|
|
79
|
+
};
|