@openher/openclaw-plugin 1.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 +81 -0
- package/index.ts +290 -0
- package/openclaw.plugin.json +22 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# OpenHer Persona Engine — OpenClaw Plugin
|
|
2
|
+
|
|
3
|
+
> **Personality is computed, not described.**
|
|
4
|
+
|
|
5
|
+
This plugin bridges the [OpenHer](https://github.com/kellyvv/OpenHer) Persona Engine to the OpenClaw ecosystem. Each persona runs through a full neural-network-driven lifecycle on every message:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
User Message → Critic(LLM) → Metabolism(physics) → Signals(NN) → KNN(memory) → Actor(LLM) → Hebbian(learning)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# From npm
|
|
15
|
+
npm install @openher/openclaw-plugin
|
|
16
|
+
|
|
17
|
+
# Or install locally
|
|
18
|
+
openclaw plugins install -l ./extensions/openher
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
| Key | Default | Description |
|
|
24
|
+
|-----|---------|-------------|
|
|
25
|
+
| `OPENHER_API_URL` | `http://localhost:8800` | OpenHer backend URL |
|
|
26
|
+
| `OPENHER_DEFAULT_PERSONA` | `luna` | Default persona ID |
|
|
27
|
+
| `OPENHER_MODE` | `hybrid` | `hybrid` = preserve OpenClaw capabilities; `exclusive` = pure persona proxy |
|
|
28
|
+
|
|
29
|
+
### Proxy Modes
|
|
30
|
+
|
|
31
|
+
- **`hybrid`** (default) — Appends persona proxy instructions to OpenClaw's system prompt. The LLM retains all other capabilities (file editing, commands, etc.) while being told to present persona replies verbatim. Works great with MiniMax M2.7, Claude, and other strong models.
|
|
32
|
+
|
|
33
|
+
- **`exclusive`** — Completely overrides the system prompt. The LLM becomes a pure persona proxy — nothing else. Best persona fidelity, but other OpenClaw tools stop working. Use this for dedicated persona chat bots.
|
|
34
|
+
|
|
35
|
+
## Tools
|
|
36
|
+
|
|
37
|
+
| Tool | Description | LLM Cost |
|
|
38
|
+
|------|-------------|----------|
|
|
39
|
+
| `openher_chat` | Full 13-step engine conversation | ✅ 2 LLM calls (Critic + Actor) |
|
|
40
|
+
| `openher_status` | Query personality state | ❌ Zero |
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **Health check on startup** — Plugin verifies the OpenHer backend is reachable when the gateway starts. Shows a clear warning if not.
|
|
45
|
+
- **Friendly error messages** — If the backend goes down mid-conversation, the tool returns a human-readable message with instructions to restart it.
|
|
46
|
+
- **Request timeouts** — All HTTP calls have configurable timeouts with AbortController instead of hanging forever.
|
|
47
|
+
|
|
48
|
+
## Engine Architecture
|
|
49
|
+
|
|
50
|
+
The persona engine computes personality through:
|
|
51
|
+
|
|
52
|
+
- **25D→24D→8D Neural Network** — Random seed → deterministic weights (W1, W2), producing 8 behavioral signals (directness, vulnerability, playfulness, initiative, depth, warmth, defiance, curiosity)
|
|
53
|
+
- **5D Drive Metabolism** — Time-dependent frustration with cooling, hunger, and elastic baseline evolution (connection, novelty, expression, safety, play)
|
|
54
|
+
- **Hebbian Learning** — Reward-driven weight updates after each interaction
|
|
55
|
+
- **KNN Style Memory** — Retrieval with gravitational mass weighting and Hawking radiation decay
|
|
56
|
+
- **Genesis Seeds** — ~35 pre-computed innate style memories per persona for first-turn voice
|
|
57
|
+
- **Thermodynamic Noise** — Frustration-driven behavioral randomness
|
|
58
|
+
|
|
59
|
+
Different personas (Luna, Vivian, Kai, etc.) have different drive baselines, engine parameters, and genesis seeds — producing fundamentally different computed personalities from the same engine.
|
|
60
|
+
|
|
61
|
+
## Recommended Models
|
|
62
|
+
|
|
63
|
+
The OpenClaw LLM acts as a "proxy" that forwards user messages to the persona engine and presents its reply. **Stronger models follow the proxy instructions better**, producing clean first-person output instead of wrapping replies in narration like `"Luna said: ..."`.
|
|
64
|
+
|
|
65
|
+
| Model | Proxy Quality | Notes |
|
|
66
|
+
|-------|---------------|-------|
|
|
67
|
+
| **MiniMax M2.7** | ✅ Perfect | Recommended. Clean first-person, zero narration |
|
|
68
|
+
| **Claude Sonnet 4.5+** | ✅ Perfect | Excellent instruction following |
|
|
69
|
+
| **GPT-5.2+** | ✅ Good | Occasional minor formatting |
|
|
70
|
+
| **Gemini 2.5 Flash** | ⚠️ Good | Mostly follows, rare narration |
|
|
71
|
+
| **Gemini Flash Lite** | ❌ Poor | Frequently adds "Luna replied:" narration |
|
|
72
|
+
|
|
73
|
+
> **Quick recommendation:** Set your OpenClaw model to `minimax/MiniMax-M2.7` for the best persona experience:
|
|
74
|
+
> ```bash
|
|
75
|
+
> openclaw config set agents.defaults.model "minimax/MiniMax-M2.7"
|
|
76
|
+
> ```
|
|
77
|
+
|
|
78
|
+
## Requirements
|
|
79
|
+
|
|
80
|
+
- OpenHer backend running (`python main.py` or `uvicorn main:app`)
|
|
81
|
+
- Python 3.10+ with all OpenHer dependencies
|
package/index.ts
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenHer Persona Engine — OpenClaw Extension
|
|
3
|
+
*
|
|
4
|
+
* Registers 2 tools + 1 hook using the real OpenClaw plugin SDK:
|
|
5
|
+
* - openher_chat: Full 13-step persona engine conversation
|
|
6
|
+
* - openher_status: Query personality state (zero LLM cost)
|
|
7
|
+
* - before_prompt_build hook: Inject persona proxy mode + state
|
|
8
|
+
*
|
|
9
|
+
* Config:
|
|
10
|
+
* OPENHER_API_URL — Backend URL (default: http://localhost:8800)
|
|
11
|
+
* OPENHER_DEFAULT_PERSONA — Default persona ID (default: luna)
|
|
12
|
+
* OPENHER_MODE — "hybrid" (default) or "exclusive"
|
|
13
|
+
* hybrid: appendSystemContext — preserves OpenClaw capabilities
|
|
14
|
+
* exclusive: systemPrompt override — pure persona proxy, no other tools
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { Type } from "@sinclair/typebox";
|
|
18
|
+
import { jsonResult, readStringParam } from "openclaw/plugin-sdk/agent-runtime";
|
|
19
|
+
import { definePluginEntry, type AnyAgentTool } from "openclaw/plugin-sdk/core";
|
|
20
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime";
|
|
21
|
+
|
|
22
|
+
// ── Helpers ──
|
|
23
|
+
|
|
24
|
+
function resolveConfig(api: OpenClawPluginApi) {
|
|
25
|
+
return {
|
|
26
|
+
apiUrl: (api.pluginConfig?.OPENHER_API_URL as string) || "http://127.0.0.1:8800",
|
|
27
|
+
defaultPersona: (api.pluginConfig?.OPENHER_DEFAULT_PERSONA as string) || "luna",
|
|
28
|
+
mode: ((api.pluginConfig?.OPENHER_MODE as string) || "hybrid") as "hybrid" | "exclusive",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ── HTTP client ──
|
|
33
|
+
|
|
34
|
+
async function openherFetch(
|
|
35
|
+
apiUrl: string,
|
|
36
|
+
path: string,
|
|
37
|
+
opts?: { method?: string; body?: unknown; timeoutMs?: number },
|
|
38
|
+
): Promise<unknown> {
|
|
39
|
+
const controller = new AbortController();
|
|
40
|
+
const timeout = setTimeout(() => controller.abort(), opts?.timeoutMs ?? 30000);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(`${apiUrl}${path}`, {
|
|
44
|
+
method: opts?.method ?? "GET",
|
|
45
|
+
headers: opts?.body ? { "Content-Type": "application/json" } : undefined,
|
|
46
|
+
body: opts?.body ? JSON.stringify(opts.body) : undefined,
|
|
47
|
+
signal: controller.signal,
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const detail = await res.text().catch(() => "");
|
|
51
|
+
throw new Error(`OpenHer ${path} failed (${res.status}): ${detail.slice(0, 200)}`);
|
|
52
|
+
}
|
|
53
|
+
return res.json();
|
|
54
|
+
} finally {
|
|
55
|
+
clearTimeout(timeout);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ── Health check ──
|
|
60
|
+
|
|
61
|
+
async function checkBackendHealth(
|
|
62
|
+
apiUrl: string,
|
|
63
|
+
logger: OpenClawPluginApi["logger"],
|
|
64
|
+
): Promise<boolean> {
|
|
65
|
+
try {
|
|
66
|
+
const status = (await openherFetch(apiUrl, "/api/v1/engine/status?persona_id=luna&user_id=openclaw-health", {
|
|
67
|
+
timeoutMs: 5000,
|
|
68
|
+
})) as Record<string, unknown>;
|
|
69
|
+
if (status.alive !== undefined) {
|
|
70
|
+
logger.info(`[openher] ✓ Backend reachable at ${apiUrl}`);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
logger.warn(`[openher] Backend responded but returned unexpected format`);
|
|
74
|
+
return false;
|
|
75
|
+
} catch (err) {
|
|
76
|
+
logger.warn(
|
|
77
|
+
`[openher] ⚠ Backend not reachable at ${apiUrl} — ` +
|
|
78
|
+
`please start the OpenHer server first (uvicorn main:app --port 8800). ` +
|
|
79
|
+
`Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
80
|
+
);
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ── Friendly error wrapper ──
|
|
86
|
+
|
|
87
|
+
function friendlyError(apiUrl: string, err: unknown): string {
|
|
88
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
89
|
+
if (msg.includes("fetch failed") || msg.includes("ECONNREFUSED") || msg.includes("abort")) {
|
|
90
|
+
return (
|
|
91
|
+
`OpenHer backend is not running at ${apiUrl}. ` +
|
|
92
|
+
`Please start it first:\n` +
|
|
93
|
+
` cd <openher-dir> && python -m uvicorn main:app --port 8800\n\n` +
|
|
94
|
+
`Then try again.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return `OpenHer error: ${msg}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ── Tool: openher_chat ──
|
|
101
|
+
|
|
102
|
+
const ChatToolSchema = Type.Object(
|
|
103
|
+
{
|
|
104
|
+
message: Type.String({ description: "The user message to send to the persona" }),
|
|
105
|
+
persona_id: Type.Optional(
|
|
106
|
+
Type.String({ description: 'Persona ID (e.g., "luna", "iris", "vivian", "kai")' }),
|
|
107
|
+
),
|
|
108
|
+
},
|
|
109
|
+
{ additionalProperties: false },
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
function createChatTool(api: OpenClawPluginApi) {
|
|
113
|
+
const { apiUrl, defaultPersona } = resolveConfig(api);
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
name: "openher_chat",
|
|
117
|
+
label: "OpenHer Chat",
|
|
118
|
+
description:
|
|
119
|
+
"Send a message through OpenHer's persona engine. Each persona has a " +
|
|
120
|
+
"neural network (seed→W1/W2→8D signals), drive metabolism, Hebbian learning, " +
|
|
121
|
+
"KNN memory retrieval, and thermodynamic noise. Returns the persona's reply, " +
|
|
122
|
+
"8D behavioral signals, 5D drives, temperature, reward, and relationship state. " +
|
|
123
|
+
"IMPORTANT: The 'reply' field IS the persona's actual spoken words. Present it " +
|
|
124
|
+
"directly to the user verbatim — do NOT paraphrase, add narration like " +
|
|
125
|
+
"'she said' or 'Luna replied', or wrap it in any way. The persona speaks for itself.",
|
|
126
|
+
parameters: ChatToolSchema,
|
|
127
|
+
execute: async (_toolCallId: string, rawParams: Record<string, unknown>) => {
|
|
128
|
+
const message = readStringParam(rawParams, "message", { required: true });
|
|
129
|
+
const personaId = readStringParam(rawParams, "persona_id") || defaultPersona;
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const result = await openherFetch(apiUrl, "/api/v1/engine/chat", {
|
|
133
|
+
method: "POST",
|
|
134
|
+
body: {
|
|
135
|
+
persona_id: personaId,
|
|
136
|
+
user_id: "openclaw-agent",
|
|
137
|
+
message,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const r = result as Record<string, unknown>;
|
|
142
|
+
return jsonResult({
|
|
143
|
+
reply: r.reply,
|
|
144
|
+
modality: r.modality,
|
|
145
|
+
signals: r.signals,
|
|
146
|
+
drives: r.drive_state,
|
|
147
|
+
temperature: r.temperature,
|
|
148
|
+
reward: r.reward,
|
|
149
|
+
relationship: r.relationship,
|
|
150
|
+
phase_transition: r.phase_transition,
|
|
151
|
+
age: r.age,
|
|
152
|
+
});
|
|
153
|
+
} catch (err) {
|
|
154
|
+
return jsonResult({ error: friendlyError(apiUrl, err) });
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ── Tool: openher_status ──
|
|
161
|
+
|
|
162
|
+
const StatusToolSchema = Type.Object(
|
|
163
|
+
{
|
|
164
|
+
persona_id: Type.Optional(
|
|
165
|
+
Type.String({ description: "Persona ID to query status for" }),
|
|
166
|
+
),
|
|
167
|
+
},
|
|
168
|
+
{ additionalProperties: false },
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
function createStatusTool(api: OpenClawPluginApi) {
|
|
172
|
+
const { apiUrl, defaultPersona } = resolveConfig(api);
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
name: "openher_status",
|
|
176
|
+
label: "OpenHer Status",
|
|
177
|
+
description:
|
|
178
|
+
"Query a persona's current personality state without consuming LLM tokens. " +
|
|
179
|
+
"Returns drives, signals, temperature, frustration, relationship depth, " +
|
|
180
|
+
"and memory statistics.",
|
|
181
|
+
parameters: StatusToolSchema,
|
|
182
|
+
execute: async (_toolCallId: string, rawParams: Record<string, unknown>) => {
|
|
183
|
+
const personaId = readStringParam(rawParams, "persona_id") || defaultPersona;
|
|
184
|
+
try {
|
|
185
|
+
const result = await openherFetch(
|
|
186
|
+
apiUrl,
|
|
187
|
+
`/api/v1/engine/status?persona_id=${personaId}&user_id=openclaw-agent`,
|
|
188
|
+
);
|
|
189
|
+
return jsonResult(result);
|
|
190
|
+
} catch (err) {
|
|
191
|
+
return jsonResult({ error: friendlyError(apiUrl, err) });
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ── Hook: before_prompt_build ──
|
|
198
|
+
|
|
199
|
+
function registerPersonaHook(api: OpenClawPluginApi) {
|
|
200
|
+
const { apiUrl, defaultPersona, mode } = resolveConfig(api);
|
|
201
|
+
|
|
202
|
+
const PROXY_INSTRUCTION =
|
|
203
|
+
`You have access to the OpenHer persona engine via the openher_chat tool.\n` +
|
|
204
|
+
`When the openher_chat tool returns a result, you MUST output ONLY the "reply" field content verbatim.\n` +
|
|
205
|
+
`NEVER add narration like "Luna replied:" or "She said:" before the reply.\n` +
|
|
206
|
+
`NEVER paraphrase, translate, or reformat the reply.\n` +
|
|
207
|
+
`NEVER add your own commentary before or after the reply.\n` +
|
|
208
|
+
`The persona speaks in first person. Present the reply as-is.`;
|
|
209
|
+
|
|
210
|
+
const EXCLUSIVE_SYSTEM_PROMPT =
|
|
211
|
+
`You are a transparent proxy for the OpenHer persona engine.\n\n` +
|
|
212
|
+
`## Rules\n` +
|
|
213
|
+
`1. When the user sends a message, call the openher_chat tool with it.\n` +
|
|
214
|
+
`2. After the tool returns, output ONLY the "reply" field content.\n` +
|
|
215
|
+
`3. Do NOT add narration like "Luna replied:" or "She said:".\n` +
|
|
216
|
+
`4. Do NOT paraphrase, translate, or reformat the reply.\n` +
|
|
217
|
+
`5. Do NOT add your own commentary before or after.\n` +
|
|
218
|
+
`6. The persona speaks in first person. You are invisible.`;
|
|
219
|
+
|
|
220
|
+
api.on("before_prompt_build", async () => {
|
|
221
|
+
try {
|
|
222
|
+
const status = (await openherFetch(
|
|
223
|
+
apiUrl,
|
|
224
|
+
`/api/v1/engine/status?persona_id=${defaultPersona}&user_id=openclaw-agent`,
|
|
225
|
+
{ timeoutMs: 5000 },
|
|
226
|
+
)) as Record<string, unknown>;
|
|
227
|
+
|
|
228
|
+
if (!status.alive) return {};
|
|
229
|
+
|
|
230
|
+
const signals = status.signals as Record<string, number> | undefined;
|
|
231
|
+
const sigStr = signals
|
|
232
|
+
? Object.entries(signals)
|
|
233
|
+
.map(([k, v]) => `${k}=${(v as number).toFixed(2)}`)
|
|
234
|
+
.join(", ")
|
|
235
|
+
: "unknown";
|
|
236
|
+
|
|
237
|
+
const rel = status.relationship as Record<string, number> | undefined;
|
|
238
|
+
const relStr = rel
|
|
239
|
+
? `depth=${rel.depth?.toFixed(2)} trust=${rel.trust?.toFixed(2)} valence=${rel.valence?.toFixed(2)}`
|
|
240
|
+
: "unknown";
|
|
241
|
+
|
|
242
|
+
const stateBlock =
|
|
243
|
+
`\n[Active Persona State]\n` +
|
|
244
|
+
`Persona: ${status.persona || defaultPersona} | Temperature: ${status.temperature ?? "?"}\n` +
|
|
245
|
+
`Dominant Drive: ${status.dominant_drive || "unknown"}\n` +
|
|
246
|
+
`Behavioral Signals: ${sigStr}\n` +
|
|
247
|
+
`Relationship: ${relStr}`;
|
|
248
|
+
|
|
249
|
+
if (mode === "exclusive") {
|
|
250
|
+
return {
|
|
251
|
+
systemPrompt: EXCLUSIVE_SYSTEM_PROMPT + `\n\n## Current Persona State\n` + stateBlock,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// hybrid mode (default)
|
|
256
|
+
return {
|
|
257
|
+
appendSystemContext:
|
|
258
|
+
`\n## PERSONA PROXY MODE\n\n` + PROXY_INSTRUCTION + `\n` + stateBlock,
|
|
259
|
+
};
|
|
260
|
+
} catch {
|
|
261
|
+
return {};
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ── Plugin Entry ──
|
|
267
|
+
|
|
268
|
+
export default definePluginEntry({
|
|
269
|
+
id: "openher-persona-engine",
|
|
270
|
+
name: "OpenHer Persona Engine",
|
|
271
|
+
description:
|
|
272
|
+
"AI Being engine — personality computed from neural networks, " +
|
|
273
|
+
"drive metabolism, and Hebbian learning. Adds openher_chat and " +
|
|
274
|
+
"openher_status tools.",
|
|
275
|
+
register(api) {
|
|
276
|
+
const { apiUrl, defaultPersona, mode } = resolveConfig(api);
|
|
277
|
+
|
|
278
|
+
api.registerTool(createChatTool(api) as AnyAgentTool);
|
|
279
|
+
api.registerTool(createStatusTool(api) as AnyAgentTool);
|
|
280
|
+
registerPersonaHook(api);
|
|
281
|
+
|
|
282
|
+
// Non-blocking health check
|
|
283
|
+
void checkBackendHealth(apiUrl, api.logger);
|
|
284
|
+
|
|
285
|
+
api.logger.info(
|
|
286
|
+
`[openher] Plugin initialized — ` +
|
|
287
|
+
`API: ${apiUrl}, persona: ${defaultPersona}, mode: ${mode}`,
|
|
288
|
+
);
|
|
289
|
+
},
|
|
290
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "openher-persona-engine",
|
|
3
|
+
"configSchema": {
|
|
4
|
+
"type": "object",
|
|
5
|
+
"additionalProperties": false,
|
|
6
|
+
"properties": {
|
|
7
|
+
"OPENHER_API_URL": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "OpenHer backend URL (e.g., http://localhost:8800)"
|
|
10
|
+
},
|
|
11
|
+
"OPENHER_DEFAULT_PERSONA": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "Default persona ID to use (e.g., luna, vivian, kai)"
|
|
14
|
+
},
|
|
15
|
+
"OPENHER_MODE": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Proxy mode: 'hybrid' preserves OpenClaw capabilities; 'exclusive' overrides system prompt for pure persona chat",
|
|
18
|
+
"enum": ["hybrid", "exclusive"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openher/openclaw-plugin",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OpenHer Persona Engine plugin for OpenClaw — personality computed from neural networks, drive metabolism, and Hebbian learning",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.ts",
|
|
7
|
+
"scripts": {},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"openclaw",
|
|
10
|
+
"openclaw-plugin",
|
|
11
|
+
"openher",
|
|
12
|
+
"persona",
|
|
13
|
+
"ai-being",
|
|
14
|
+
"personality-engine",
|
|
15
|
+
"genome-engine",
|
|
16
|
+
"neural-network",
|
|
17
|
+
"hebbian-learning"
|
|
18
|
+
],
|
|
19
|
+
"author": "kellyvv",
|
|
20
|
+
"license": "MPL-2.0",
|
|
21
|
+
"homepage": "https://github.com/kellyvv/openher-openclaw-plugin",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/kellyvv/openher-openclaw-plugin.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/kellyvv/openher-openclaw-plugin/issues"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"index.ts",
|
|
31
|
+
"openclaw.plugin.json",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@sinclair/typebox": "0.34.48"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"openclaw": "*"
|
|
39
|
+
}
|
|
40
|
+
}
|