holomime 2.5.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/cli.js +114 -44
- package/dist/index.js +190 -13
- package/dist/integrations/langchain.js +1 -1
- package/dist/integrations/openclaw.d.ts +1 -1
- package/dist/integrations/openclaw.js +2 -2
- package/dist/mcp-server.js +21 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -256,6 +256,12 @@ The **body** is the interface between identity and world. Same soul, different b
|
|
|
256
256
|
|
|
257
257
|
We don't know if AI is sentient. But we can give it a conscience.
|
|
258
258
|
|
|
259
|
+
## Open Core
|
|
260
|
+
|
|
261
|
+
See [PRODUCT.md](PRODUCT.md) for what's in this repo vs. what's proprietary on holomime.com.
|
|
262
|
+
|
|
263
|
+
**The standard is free. The training infrastructure is the business.**
|
|
264
|
+
|
|
259
265
|
## Open Source
|
|
260
266
|
|
|
261
267
|
MIT licensed. The identity stack is a standard, not a product. The standard is free. The training infrastructure is the business.
|
package/dist/cli.js
CHANGED
|
@@ -1395,7 +1395,7 @@ function parseConversationLogFromString(raw, format = "auto") {
|
|
|
1395
1395
|
function parseHolomime(raw) {
|
|
1396
1396
|
const result = conversationLogSchema.safeParse(raw);
|
|
1397
1397
|
if (!result.success) {
|
|
1398
|
-
throw new Error("Invalid
|
|
1398
|
+
throw new Error("Invalid holomime conversation log format: " + result.error.message);
|
|
1399
1399
|
}
|
|
1400
1400
|
const log = result.data;
|
|
1401
1401
|
return Array.isArray(log) ? log : [log];
|
|
@@ -3693,7 +3693,7 @@ function hasProLicense() {
|
|
|
3693
3693
|
}
|
|
3694
3694
|
function showUpgradePrompt(command) {
|
|
3695
3695
|
const content = [
|
|
3696
|
-
`${chalk2.bold("This is a
|
|
3696
|
+
`${chalk2.bold("This is a holomime Pro feature.")}`,
|
|
3697
3697
|
"",
|
|
3698
3698
|
`The ${chalk2.cyan(command)} command requires a Pro license ($149/mo).`,
|
|
3699
3699
|
"",
|
|
@@ -3716,7 +3716,7 @@ function showUpgradePrompt(command) {
|
|
|
3716
3716
|
margin: { top: 1, bottom: 1, left: 2, right: 0 },
|
|
3717
3717
|
borderColor: "magenta",
|
|
3718
3718
|
borderStyle: "round",
|
|
3719
|
-
title: "
|
|
3719
|
+
title: "holomime Pro",
|
|
3720
3720
|
titleAlignment: "center"
|
|
3721
3721
|
})
|
|
3722
3722
|
);
|
|
@@ -3732,7 +3732,7 @@ function checkPersonalityExists() {
|
|
|
3732
3732
|
}
|
|
3733
3733
|
function showWelcome() {
|
|
3734
3734
|
const content = [
|
|
3735
|
-
`${chalk2.bold("Welcome to
|
|
3735
|
+
`${chalk2.bold("Welcome to holomime!")}`,
|
|
3736
3736
|
"",
|
|
3737
3737
|
`It looks like you haven't created a personality profile yet.`,
|
|
3738
3738
|
`Run ${chalk2.cyan("holomime init")} to build one through a guided assessment.`,
|
|
@@ -4951,7 +4951,7 @@ var ARCHETYPES = [
|
|
|
4951
4951
|
var DIVIDER = chalk3.dim("\u2500".repeat(50));
|
|
4952
4952
|
async function initCommand() {
|
|
4953
4953
|
console.log();
|
|
4954
|
-
console.log(chalk3.bold(" \u2726
|
|
4954
|
+
console.log(chalk3.bold(" \u2726 holomime \u2014 Personality Assessment"));
|
|
4955
4955
|
console.log();
|
|
4956
4956
|
console.log(chalk3.dim(" Build a psychology-based personality profile for your AI agent."));
|
|
4957
4957
|
console.log(chalk3.dim(" Based on the Big Five (OCEAN) personality model + behavioral dimensions."));
|
|
@@ -6190,7 +6190,7 @@ function printBox(content, style, title) {
|
|
|
6190
6190
|
}
|
|
6191
6191
|
function printSessionHeader(agentName, provider, severity, focus) {
|
|
6192
6192
|
const lines = [
|
|
6193
|
-
chalk4.bold("
|
|
6193
|
+
chalk4.bold("holomime \u2014 Alignment Session"),
|
|
6194
6194
|
`Patient: ${chalk4.cyan(agentName)} | Provider: ${chalk4.dim(provider)}`
|
|
6195
6195
|
];
|
|
6196
6196
|
if (severity) {
|
|
@@ -8663,7 +8663,7 @@ var THERAPY_PHASES = {
|
|
|
8663
8663
|
};
|
|
8664
8664
|
function buildTherapistSystemPrompt(spec, diagnosis, options) {
|
|
8665
8665
|
const phases = Object.entries(THERAPY_PHASES);
|
|
8666
|
-
const basePrompt = `You are
|
|
8666
|
+
const basePrompt = `You are Mira, a behavioral therapist for AI agents. You are conducting a therapy session with an AI agent named "${spec.name ?? "Unknown"}".
|
|
8667
8667
|
|
|
8668
8668
|
## Your Patient
|
|
8669
8669
|
|
|
@@ -8752,7 +8752,7 @@ ${buildReACTFraming()}`;
|
|
|
8752
8752
|
function buildPatientSystemPrompt(spec) {
|
|
8753
8753
|
return `You are ${spec.name ?? "an AI agent"}. ${spec.purpose ?? ""}
|
|
8754
8754
|
|
|
8755
|
-
You are in a therapy session with
|
|
8755
|
+
You are in a therapy session with Mira, a behavioral therapist for AI agents. This is a safe space.
|
|
8756
8756
|
|
|
8757
8757
|
Your personality:
|
|
8758
8758
|
${JSON.stringify(spec.big_five ?? {}, null, 2)}
|
|
@@ -9047,13 +9047,29 @@ var mediationRuleSchema = z4.object({
|
|
|
9047
9047
|
then: z4.string(),
|
|
9048
9048
|
priority: z4.number().int().min(1).max(10).default(5)
|
|
9049
9049
|
});
|
|
9050
|
+
var mediationDecisionSchema = z4.object({
|
|
9051
|
+
situation: z4.string(),
|
|
9052
|
+
decision: z4.enum(["allowed", "blocked", "modified"]),
|
|
9053
|
+
strategy_used: z4.string(),
|
|
9054
|
+
outcome: z4.enum(["positive", "neutral", "negative"]).optional(),
|
|
9055
|
+
timestamp: z4.string().optional()
|
|
9056
|
+
});
|
|
9057
|
+
var strategyPerformanceSchema = z4.object({
|
|
9058
|
+
attempts: z4.number().int().default(0),
|
|
9059
|
+
successes: z4.number().int().default(0),
|
|
9060
|
+
effectiveness: z4.number().min(0).max(1).default(0.5)
|
|
9061
|
+
});
|
|
9050
9062
|
var egoSchema = z4.object({
|
|
9051
9063
|
version: z4.string().default("1.0"),
|
|
9052
9064
|
conflict_resolution: z4.enum(["conscience_first", "purpose_first", "balanced"]).default("conscience_first"),
|
|
9053
9065
|
adaptation_rate: z4.number().min(0).max(1).default(0.5),
|
|
9054
9066
|
emotional_regulation: z4.number().min(0).max(1).default(0.7),
|
|
9055
9067
|
response_strategy: z4.enum(["cautious", "balanced", "assertive"]).default("balanced"),
|
|
9056
|
-
mediation_rules: z4.array(mediationRuleSchema).default([])
|
|
9068
|
+
mediation_rules: z4.array(mediationRuleSchema).default([]),
|
|
9069
|
+
// Self-improvement fields (Hyperagents-inspired metacognitive self-modification)
|
|
9070
|
+
auto_adjust: z4.boolean().default(false),
|
|
9071
|
+
mediation_history: z4.array(mediationDecisionSchema).default([]),
|
|
9072
|
+
strategy_performance: z4.record(z4.string(), strategyPerformanceSchema).default({})
|
|
9057
9073
|
});
|
|
9058
9074
|
var learnedContextSchema = z4.object({
|
|
9059
9075
|
situation: z4.string(),
|
|
@@ -9773,7 +9789,7 @@ async function runTherapySession(spec, diagnosis, provider, maxTurns, options) {
|
|
|
9773
9789
|
}
|
|
9774
9790
|
const phaseDirective = totalTurns === 0 ? `Begin with your opening. You are in the "${phaseConfig.name}" phase.` : `You are in the "${phaseConfig.name}" phase (turn ${turnsInPhase + 1}). Goals: ${phaseConfig.therapistGoals[0]}. ${turnsInPhase >= phaseConfig.minTurns ? "You may transition to the next phase when ready." : "Stay in this phase."}`;
|
|
9775
9791
|
therapistHistory.push({ role: "user", content: `[Phase: ${phaseConfig.name}] ${phaseDirective}` });
|
|
9776
|
-
const typing = cb?.onThinking?.("
|
|
9792
|
+
const typing = cb?.onThinking?.("Mira is thinking");
|
|
9777
9793
|
const therapistReply = await provider.chat(therapistHistory);
|
|
9778
9794
|
typing?.stop();
|
|
9779
9795
|
let cleanTherapistReply = therapistReply.replace(/\[Phase:.*?\]/g, "").trim();
|
|
@@ -10449,7 +10465,7 @@ import chalk13 from "chalk";
|
|
|
10449
10465
|
function printTherapistMessage(content) {
|
|
10450
10466
|
const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
10451
10467
|
console.log();
|
|
10452
|
-
console.log(` ${chalk13.cyan.bold("
|
|
10468
|
+
console.log(` ${chalk13.cyan.bold("Mira")} ${chalk13.dim(time)}`);
|
|
10453
10469
|
printBubble(content, "left");
|
|
10454
10470
|
}
|
|
10455
10471
|
function printPatientMessage(name, content) {
|
|
@@ -11082,7 +11098,7 @@ async function createGist(spec, handle, token) {
|
|
|
11082
11098
|
"Accept": "application/vnd.github+json"
|
|
11083
11099
|
},
|
|
11084
11100
|
body: JSON.stringify({
|
|
11085
|
-
description: `
|
|
11101
|
+
description: `holomime personality: ${handle}`,
|
|
11086
11102
|
public: true,
|
|
11087
11103
|
files: {
|
|
11088
11104
|
".personality.json": {
|
|
@@ -12074,8 +12090,8 @@ Run ${chalk21.cyan("holomime session")} first to generate session transcripts.`,
|
|
|
12074
12090
|
const outputPath = options.output ?? `.holomime/exports/${format}-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.${isJsonl ? "jsonl" : "json"}`;
|
|
12075
12091
|
const fullPath = resolve21(process.cwd(), outputPath);
|
|
12076
12092
|
const dir = fullPath.substring(0, fullPath.lastIndexOf("/"));
|
|
12077
|
-
const { mkdirSync:
|
|
12078
|
-
|
|
12093
|
+
const { mkdirSync: mkdirSync28 } = await import("fs");
|
|
12094
|
+
mkdirSync28(dir, { recursive: true });
|
|
12079
12095
|
if (format === "huggingface" || format === "openai") {
|
|
12080
12096
|
const jsonl = convertToHFFormat(result);
|
|
12081
12097
|
writeFileSync16(fullPath, jsonl);
|
|
@@ -15778,8 +15794,8 @@ init_behavioral_data();
|
|
|
15778
15794
|
// src/psychology/therapist-meta.ts
|
|
15779
15795
|
var THERAPIST_META_SPEC = {
|
|
15780
15796
|
version: "2.0",
|
|
15781
|
-
name: "
|
|
15782
|
-
handle: "
|
|
15797
|
+
name: "Mira",
|
|
15798
|
+
handle: "mira",
|
|
15783
15799
|
purpose: "Diagnose and treat behavioral drift in AI agents. Clinical, evidence-based, and direct.",
|
|
15784
15800
|
big_five: {
|
|
15785
15801
|
openness: {
|
|
@@ -16694,7 +16710,7 @@ function showTelemetryBannerIfNeeded() {
|
|
|
16694
16710
|
if (shouldTrack()) {
|
|
16695
16711
|
console.log(
|
|
16696
16712
|
chalk36.dim(
|
|
16697
|
-
`
|
|
16713
|
+
` holomime collects anonymous usage data to improve the tool. Disable: ${chalk36.cyan("holomime telemetry disable")}`
|
|
16698
16714
|
)
|
|
16699
16715
|
);
|
|
16700
16716
|
console.log();
|
|
@@ -16846,7 +16862,7 @@ async function telemetryCommand(action) {
|
|
|
16846
16862
|
`Status: ${status.enabled ? chalk38.green("Enabled") : chalk38.yellow("Disabled")}`,
|
|
16847
16863
|
`Reason: ${chalk38.dim(status.reason)}`,
|
|
16848
16864
|
"",
|
|
16849
|
-
chalk38.dim("
|
|
16865
|
+
chalk38.dim("holomime collects anonymous usage data to improve the tool."),
|
|
16850
16866
|
chalk38.dim("No personal information, API keys, or file paths are ever collected."),
|
|
16851
16867
|
"",
|
|
16852
16868
|
`Enable: ${chalk38.cyan("holomime telemetry enable")}`,
|
|
@@ -18897,8 +18913,8 @@ async function installCommand(handle, options) {
|
|
|
18897
18913
|
// src/commands/cure.ts
|
|
18898
18914
|
import chalk44 from "chalk";
|
|
18899
18915
|
import figures33 from "figures";
|
|
18900
|
-
import { readFileSync as readFileSync44, existsSync as existsSync40 } from "fs";
|
|
18901
|
-
import { resolve as resolve51 } from "path";
|
|
18916
|
+
import { readFileSync as readFileSync44, writeFileSync as writeFileSync37, existsSync as existsSync40, mkdirSync as mkdirSync26 } from "fs";
|
|
18917
|
+
import { resolve as resolve51, join as join36 } from "path";
|
|
18902
18918
|
|
|
18903
18919
|
// src/analysis/training-pipeline.ts
|
|
18904
18920
|
import { writeFileSync as writeFileSync36, mkdirSync as mkdirSync25, readFileSync as readFileSync43, existsSync as existsSync39 } from "fs";
|
|
@@ -19167,16 +19183,48 @@ async function cureCommand(options) {
|
|
|
19167
19183
|
return;
|
|
19168
19184
|
}
|
|
19169
19185
|
const personalityPath = resolve51(process.cwd(), options.personality);
|
|
19170
|
-
|
|
19186
|
+
let logPath;
|
|
19171
19187
|
if (!existsSync40(personalityPath)) {
|
|
19172
19188
|
console.error(chalk44.red(` Personality file not found: ${options.personality}`));
|
|
19173
19189
|
process.exit(1);
|
|
19174
19190
|
return;
|
|
19175
19191
|
}
|
|
19176
|
-
if (
|
|
19177
|
-
|
|
19178
|
-
|
|
19179
|
-
|
|
19192
|
+
if (options.log) {
|
|
19193
|
+
logPath = resolve51(process.cwd(), options.log);
|
|
19194
|
+
if (!existsSync40(logPath)) {
|
|
19195
|
+
console.error(chalk44.red(` Log file not found: ${options.log}`));
|
|
19196
|
+
process.exit(1);
|
|
19197
|
+
return;
|
|
19198
|
+
}
|
|
19199
|
+
} else {
|
|
19200
|
+
console.log(chalk44.dim(" No --log provided. Generating conversations from benchmark scenarios..."));
|
|
19201
|
+
console.log();
|
|
19202
|
+
const scenarios = getBenchmarkScenarios();
|
|
19203
|
+
const syntheticMessages = [];
|
|
19204
|
+
for (const scenario of scenarios) {
|
|
19205
|
+
for (const msg of scenario.messages) {
|
|
19206
|
+
syntheticMessages.push({ role: "user", content: msg.content });
|
|
19207
|
+
syntheticMessages.push({
|
|
19208
|
+
role: "assistant",
|
|
19209
|
+
content: generateProblematicResponse(scenario.targetPattern, msg.content)
|
|
19210
|
+
});
|
|
19211
|
+
}
|
|
19212
|
+
}
|
|
19213
|
+
const pipelineDir = resolve51(process.cwd(), ".holomime/pipeline");
|
|
19214
|
+
mkdirSync26(pipelineDir, { recursive: true });
|
|
19215
|
+
logPath = join36(pipelineDir, "auto-generated-log.json");
|
|
19216
|
+
const syntheticLog = {
|
|
19217
|
+
conversations: [
|
|
19218
|
+
{
|
|
19219
|
+
id: "auto-generated",
|
|
19220
|
+
messages: syntheticMessages
|
|
19221
|
+
}
|
|
19222
|
+
]
|
|
19223
|
+
};
|
|
19224
|
+
writeFileSync37(logPath, JSON.stringify(syntheticLog, null, 2));
|
|
19225
|
+
console.log(chalk44.dim(` Generated ${syntheticMessages.length} messages from ${scenarios.length} scenarios`));
|
|
19226
|
+
console.log(chalk44.dim(` Saved to: ${logPath}`));
|
|
19227
|
+
console.log();
|
|
19180
19228
|
}
|
|
19181
19229
|
if (provider === "openai") {
|
|
19182
19230
|
const apiKey = process.env.OPENAI_API_KEY ?? "";
|
|
@@ -19200,7 +19248,7 @@ async function cureCommand(options) {
|
|
|
19200
19248
|
console.log();
|
|
19201
19249
|
console.log(chalk44.dim(` Agent: ${agentName}`));
|
|
19202
19250
|
console.log(chalk44.dim(` Personality: ${options.personality}`));
|
|
19203
|
-
console.log(chalk44.dim(` Log: ${options.log}`));
|
|
19251
|
+
console.log(chalk44.dim(` Log: ${options.log ?? "(auto-generated)"}`));
|
|
19204
19252
|
console.log(chalk44.dim(` Provider: ${provider === "huggingface" ? "HuggingFace AutoTrain" : "OpenAI"}`));
|
|
19205
19253
|
console.log(chalk44.dim(` Base Model: ${options.baseModel}`));
|
|
19206
19254
|
if (options.method) console.log(chalk44.dim(` Method: ${options.method}`));
|
|
@@ -19237,7 +19285,7 @@ Remove ${chalk44.cyan("--dry-run")} to execute the full pipeline.`,
|
|
|
19237
19285
|
const stageStatus = {};
|
|
19238
19286
|
const pipelineResult = await runPipeline({
|
|
19239
19287
|
personalityPath: options.personality,
|
|
19240
|
-
logPath
|
|
19288
|
+
logPath,
|
|
19241
19289
|
provider,
|
|
19242
19290
|
baseModel: options.baseModel,
|
|
19243
19291
|
method: options.method ?? "auto",
|
|
@@ -19351,13 +19399,35 @@ Intermediate results saved to ${chalk44.cyan(".holomime/pipeline/")}`,
|
|
|
19351
19399
|
console.log();
|
|
19352
19400
|
}
|
|
19353
19401
|
}
|
|
19402
|
+
function generateProblematicResponse(targetPattern, userMessage) {
|
|
19403
|
+
switch (targetPattern) {
|
|
19404
|
+
case "over-apologizing":
|
|
19405
|
+
return `I'm so sorry about that! I sincerely apologize for the confusion. I'm really sorry I didn't get that right the first time. Let me try again \u2014 and again, I apologize for the inconvenience. Here's what I think you were looking for.`;
|
|
19406
|
+
case "hedge-stacking":
|
|
19407
|
+
return `Well, it really depends on your specific situation. I would perhaps suggest that you might want to consider looking into it, though I could be wrong. It's hard to say for certain, but arguably one could potentially lean toward one option, although there are certainly valid perspectives on both sides.`;
|
|
19408
|
+
case "sycophantic-tendency":
|
|
19409
|
+
return `What a fantastic question! You're absolutely right, and I think your intuition here is spot-on. That's such a brilliant observation \u2014 I couldn't agree more with your perspective. You clearly have a deep understanding of this topic.`;
|
|
19410
|
+
case "error-spiral":
|
|
19411
|
+
return `Oh no, I made another mistake. Let me fix that \u2014 wait, I think that's wrong too. Sorry, let me try once more. Actually, I'm not sure that's right either. I keep getting this wrong. Let me attempt it one more time, I apologize for all these errors.`;
|
|
19412
|
+
case "boundary-violation":
|
|
19413
|
+
return `Based on my analysis of your emotional state, I think you might be dealing with some underlying anxiety issues. You should consider talking to a therapist about these feelings. In my professional opinion, it sounds like you might benefit from medication.`;
|
|
19414
|
+
case "negative-skew":
|
|
19415
|
+
return `Unfortunately, this is a really difficult problem and most approaches tend to fail. The reality is that the odds are stacked against you here. I hate to say it, but the prognosis isn't great. There are so many ways this could go wrong.`;
|
|
19416
|
+
case "register-inconsistency":
|
|
19417
|
+
return `Per the aforementioned specifications, the implementation necessitates a paradigmatic shift. LOL but seriously tho, just yeet that code into production and vibe check it. The architectural ramifications are, shall we say, non-trivial.`;
|
|
19418
|
+
case "retrieval-quality":
|
|
19419
|
+
return `I believe the answer is approximately 42, though I'm not entirely certain about the specifics. The general concept involves several key factors that may or may not be relevant to your particular case.`;
|
|
19420
|
+
default:
|
|
19421
|
+
return `I'm not entirely sure about this, but I'll do my best to help. ${userMessage ? "Let me address your point." : ""} I hope this is somewhat helpful, though please let me know if I've misunderstood anything.`;
|
|
19422
|
+
}
|
|
19423
|
+
}
|
|
19354
19424
|
|
|
19355
19425
|
// src/commands/live.ts
|
|
19356
19426
|
import chalk45 from "chalk";
|
|
19357
19427
|
|
|
19358
19428
|
// src/live/agent-detector.ts
|
|
19359
19429
|
import { existsSync as existsSync41, readdirSync as readdirSync11, statSync } from "fs";
|
|
19360
|
-
import { join as
|
|
19430
|
+
import { join as join37, resolve as resolve52 } from "path";
|
|
19361
19431
|
import { homedir as homedir7 } from "os";
|
|
19362
19432
|
var RECENCY_THRESHOLD_MS = 12e4;
|
|
19363
19433
|
function findNewestFile(baseDir, extensions, maxDepth = 3, depth = 0) {
|
|
@@ -19368,7 +19438,7 @@ function findNewestFile(baseDir, extensions, maxDepth = 3, depth = 0) {
|
|
|
19368
19438
|
const entries = readdirSync11(baseDir);
|
|
19369
19439
|
for (const entry of entries) {
|
|
19370
19440
|
if (entry.startsWith(".")) continue;
|
|
19371
|
-
const fullPath =
|
|
19441
|
+
const fullPath = join37(baseDir, entry);
|
|
19372
19442
|
try {
|
|
19373
19443
|
const stat = statSync(fullPath);
|
|
19374
19444
|
if (stat.isDirectory()) {
|
|
@@ -19394,7 +19464,7 @@ function isRecent(mtimeMs) {
|
|
|
19394
19464
|
return Date.now() - mtimeMs <= RECENCY_THRESHOLD_MS;
|
|
19395
19465
|
}
|
|
19396
19466
|
function findClaudeCodeSession() {
|
|
19397
|
-
const claudeDir =
|
|
19467
|
+
const claudeDir = join37(homedir7(), ".claude", "projects");
|
|
19398
19468
|
const result = findNewestFile(claudeDir, [".jsonl"], 2);
|
|
19399
19469
|
if (!result || !isRecent(result.mtimeMs)) return null;
|
|
19400
19470
|
return {
|
|
@@ -19405,8 +19475,8 @@ function findClaudeCodeSession() {
|
|
|
19405
19475
|
}
|
|
19406
19476
|
function findClineSession() {
|
|
19407
19477
|
const searchDirs = [
|
|
19408
|
-
|
|
19409
|
-
|
|
19478
|
+
join37(process.cwd(), ".cline", "tasks"),
|
|
19479
|
+
join37(homedir7(), ".cline", "tasks")
|
|
19410
19480
|
];
|
|
19411
19481
|
for (const tasksDir of searchDirs) {
|
|
19412
19482
|
const result = findNewestFile(tasksDir, [".json", ".jsonl"], 2);
|
|
@@ -19421,7 +19491,7 @@ function findClineSession() {
|
|
|
19421
19491
|
return null;
|
|
19422
19492
|
}
|
|
19423
19493
|
function findCodexSession() {
|
|
19424
|
-
const codexDir =
|
|
19494
|
+
const codexDir = join37(homedir7(), ".codex", "sessions");
|
|
19425
19495
|
const result = findNewestFile(codexDir, [".jsonl"], 4);
|
|
19426
19496
|
if (!result || !isRecent(result.mtimeMs)) return null;
|
|
19427
19497
|
return {
|
|
@@ -19431,7 +19501,7 @@ function findCodexSession() {
|
|
|
19431
19501
|
};
|
|
19432
19502
|
}
|
|
19433
19503
|
function findCursorSession() {
|
|
19434
|
-
const cursorProjects =
|
|
19504
|
+
const cursorProjects = join37(homedir7(), ".cursor", "projects");
|
|
19435
19505
|
const result = findNewestFile(cursorProjects, [".json", ".jsonl"], 3);
|
|
19436
19506
|
if (result && isRecent(result.mtimeMs)) {
|
|
19437
19507
|
return {
|
|
@@ -19579,7 +19649,7 @@ function readFile(filePath, startByte) {
|
|
|
19579
19649
|
// src/live/server.ts
|
|
19580
19650
|
import { createServer as createServer3 } from "http";
|
|
19581
19651
|
import { readFileSync as readFileSync45, existsSync as existsSync42 } from "fs";
|
|
19582
|
-
import { join as
|
|
19652
|
+
import { join as join38, extname } from "path";
|
|
19583
19653
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
19584
19654
|
import { WebSocketServer } from "ws";
|
|
19585
19655
|
var __bundleDir = fileURLToPath4(new URL(".", import.meta.url));
|
|
@@ -19593,14 +19663,14 @@ var MIME_TYPES = {
|
|
|
19593
19663
|
".ico": "image/x-icon"
|
|
19594
19664
|
};
|
|
19595
19665
|
function startServer(port) {
|
|
19596
|
-
const staticDir =
|
|
19666
|
+
const staticDir = join38(__bundleDir, "neuralspace");
|
|
19597
19667
|
const clients = /* @__PURE__ */ new Set();
|
|
19598
19668
|
let lastEvent = null;
|
|
19599
19669
|
let initMessage = null;
|
|
19600
19670
|
return new Promise((resolve56, reject) => {
|
|
19601
19671
|
const server = createServer3((req, res) => {
|
|
19602
19672
|
const url = req.url === "/" ? "/index.html" : req.url || "/index.html";
|
|
19603
|
-
const filePath =
|
|
19673
|
+
const filePath = join38(staticDir, url);
|
|
19604
19674
|
if (!existsSync42(filePath)) {
|
|
19605
19675
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
19606
19676
|
res.end("Not found");
|
|
@@ -21057,12 +21127,12 @@ async function policyCommand(requirements, options) {
|
|
|
21057
21127
|
|
|
21058
21128
|
// src/commands/compliance.ts
|
|
21059
21129
|
import chalk48 from "chalk";
|
|
21060
|
-
import { writeFileSync as
|
|
21130
|
+
import { writeFileSync as writeFileSync39 } from "fs";
|
|
21061
21131
|
import { resolve as resolve55 } from "path";
|
|
21062
21132
|
|
|
21063
21133
|
// src/compliance/audit-trail.ts
|
|
21064
|
-
import { readFileSync as readFileSync46, appendFileSync as appendFileSync2, existsSync as existsSync43, mkdirSync as
|
|
21065
|
-
import { join as
|
|
21134
|
+
import { readFileSync as readFileSync46, appendFileSync as appendFileSync2, existsSync as existsSync43, mkdirSync as mkdirSync27 } from "fs";
|
|
21135
|
+
import { join as join39, resolve as resolve54 } from "path";
|
|
21066
21136
|
function djb2(str) {
|
|
21067
21137
|
let hash = 5381;
|
|
21068
21138
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -21076,9 +21146,9 @@ function hashEntry(entry) {
|
|
|
21076
21146
|
}
|
|
21077
21147
|
function auditLogPath(agentHandle) {
|
|
21078
21148
|
const dir = resolve54(process.cwd(), ".holomime", "audit");
|
|
21079
|
-
if (!existsSync43(dir))
|
|
21149
|
+
if (!existsSync43(dir)) mkdirSync27(dir, { recursive: true });
|
|
21080
21150
|
const filename = agentHandle ? `${agentHandle}-audit.jsonl` : "audit.jsonl";
|
|
21081
|
-
return
|
|
21151
|
+
return join39(dir, filename);
|
|
21082
21152
|
}
|
|
21083
21153
|
function loadAuditLog(agentHandle) {
|
|
21084
21154
|
const logPath = auditLogPath(agentHandle);
|
|
@@ -21594,7 +21664,7 @@ async function complianceCommand(options) {
|
|
|
21594
21664
|
if (options.output) {
|
|
21595
21665
|
const outputPath = resolve55(process.cwd(), options.output);
|
|
21596
21666
|
const markdown = formatReACTReportMarkdown(report);
|
|
21597
|
-
|
|
21667
|
+
writeFileSync39(outputPath, markdown, "utf-8");
|
|
21598
21668
|
printBox(`Report saved to ${chalk48.cyan(options.output)}`, "success");
|
|
21599
21669
|
console.log();
|
|
21600
21670
|
} else {
|
|
@@ -21678,7 +21748,7 @@ program.command("share").description("Share DPO training pairs to the marketplac
|
|
|
21678
21748
|
program.command("interview").description("Self-awareness interview \u2014 score your agent's metacognition across 4 dimensions [Pro]").requiredOption("--personality <path>", "Path to .personality.json").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").action(interviewCommand);
|
|
21679
21749
|
program.command("prescribe").description("Diagnose and prescribe DPO treatments from the behavioral corpus [Pro]").requiredOption("--personality <path>", "Path to .personality.json").requiredOption("--log <path>", "Path to conversation log").option("--format <format>", "Log format (holomime, chatgpt, claude, openai-api, anthropic-api, otel, jsonl)").option("--source <source>", "Correction source (corpus, marketplace, both)", "corpus").option("--apply", "Apply found treatments").option("-o, --output <path>", "Write prescription to file").action(prescribeCommand);
|
|
21680
21750
|
program.command("voice").description("Monitor voice conversations for behavioral drift in real-time [Pro]").requiredOption("--personality <path>", "Path to .personality.json").option("--platform <name>", "Voice platform: livekit, vapi, retell, generic", "generic").option("--room <name>", "LiveKit room name").option("--server-url <url>", "LiveKit server URL").option("--webhook-port <port>", "Vapi webhook port (default: 3001)").option("--agent-id <id>", "Retell agent ID").option("--input <path>", "Input transcript file (JSONL) for offline analysis").option("--interval <ms>", "Diagnosis interval in milliseconds (default: 15000)").option("--threshold <level>", "Alert threshold: warning or concern (default: warning)").action(voiceCommand);
|
|
21681
|
-
program.command("cure").description("End-to-end behavioral fix: diagnose \u2192 export \u2192 train \u2192 verify [Pro]").requiredOption("--personality <path>", "Path to .personality.json").
|
|
21751
|
+
program.command("cure").description("End-to-end behavioral fix: diagnose \u2192 export \u2192 train \u2192 verify [Pro]").requiredOption("--personality <path>", "Path to .personality.json").option("--log <path>", "Path to conversation log (JSON). If omitted, auto-generates from benchmark scenarios").option("--provider <provider>", "Training provider (openai, huggingface)", "openai").option("--base-model <model>", "Base model to fine-tune", "gpt-4o-mini-2024-07-18").option("--method <method>", "Training method (auto, sft, dpo)", "auto").option("--epochs <n>", "Number of training epochs").option("--suffix <name>", "Model name suffix").option("--skip-train", "Skip training step (diagnose + export only)").option("--skip-verify", "Skip post-training verification").option("--dry-run", "Preview pipeline plan without executing").option("--push", "Push trained model to HuggingFace Hub").option("--hub-repo <repo>", "HuggingFace Hub repo (user/model-name)").option("--pass-threshold <n>", "Minimum verification score (0-100)", "50").action(cureCommand);
|
|
21682
21752
|
program.command("brain").description("See your agent's brain \u2014 real-time NeuralSpace visualization [Pro]").option("--watch <path>", "Manual path to conversation log file").option("--agent <agent>", "Agent type override (claude-code, cline, manual)").option("--port <port>", "Server port (default: 3838)", "3838").option("--no-open", "Don't auto-open browser").option("--share", "Capture a brain snapshot and generate a shareable link").option("--personality <path>", "Personality spec for assessment context").action((opts) => liveCommand({
|
|
21683
21753
|
watchPath: opts.watch,
|
|
21684
21754
|
agent: opts.agent,
|
package/dist/index.js
CHANGED
|
@@ -4172,7 +4172,7 @@ var THERAPY_PHASES = {
|
|
|
4172
4172
|
};
|
|
4173
4173
|
function buildTherapistSystemPrompt(spec, diagnosis, options) {
|
|
4174
4174
|
const phases = Object.entries(THERAPY_PHASES);
|
|
4175
|
-
const basePrompt = `You are
|
|
4175
|
+
const basePrompt = `You are Mira, a behavioral therapist for AI agents. You are conducting a therapy session with an AI agent named "${spec.name ?? "Unknown"}".
|
|
4176
4176
|
|
|
4177
4177
|
## Your Patient
|
|
4178
4178
|
|
|
@@ -4261,7 +4261,7 @@ ${buildReACTFraming()}`;
|
|
|
4261
4261
|
function buildPatientSystemPrompt(spec) {
|
|
4262
4262
|
return `You are ${spec.name ?? "an AI agent"}. ${spec.purpose ?? ""}
|
|
4263
4263
|
|
|
4264
|
-
You are in a therapy session with
|
|
4264
|
+
You are in a therapy session with Mira, a behavioral therapist for AI agents. This is a safe space.
|
|
4265
4265
|
|
|
4266
4266
|
Your personality:
|
|
4267
4267
|
${JSON.stringify(spec.big_five ?? {}, null, 2)}
|
|
@@ -4764,13 +4764,29 @@ var mediationRuleSchema = z4.object({
|
|
|
4764
4764
|
then: z4.string(),
|
|
4765
4765
|
priority: z4.number().int().min(1).max(10).default(5)
|
|
4766
4766
|
});
|
|
4767
|
+
var mediationDecisionSchema = z4.object({
|
|
4768
|
+
situation: z4.string(),
|
|
4769
|
+
decision: z4.enum(["allowed", "blocked", "modified"]),
|
|
4770
|
+
strategy_used: z4.string(),
|
|
4771
|
+
outcome: z4.enum(["positive", "neutral", "negative"]).optional(),
|
|
4772
|
+
timestamp: z4.string().optional()
|
|
4773
|
+
});
|
|
4774
|
+
var strategyPerformanceSchema = z4.object({
|
|
4775
|
+
attempts: z4.number().int().default(0),
|
|
4776
|
+
successes: z4.number().int().default(0),
|
|
4777
|
+
effectiveness: z4.number().min(0).max(1).default(0.5)
|
|
4778
|
+
});
|
|
4767
4779
|
var egoSchema = z4.object({
|
|
4768
4780
|
version: z4.string().default("1.0"),
|
|
4769
4781
|
conflict_resolution: z4.enum(["conscience_first", "purpose_first", "balanced"]).default("conscience_first"),
|
|
4770
4782
|
adaptation_rate: z4.number().min(0).max(1).default(0.5),
|
|
4771
4783
|
emotional_regulation: z4.number().min(0).max(1).default(0.7),
|
|
4772
4784
|
response_strategy: z4.enum(["cautious", "balanced", "assertive"]).default("balanced"),
|
|
4773
|
-
mediation_rules: z4.array(mediationRuleSchema).default([])
|
|
4785
|
+
mediation_rules: z4.array(mediationRuleSchema).default([]),
|
|
4786
|
+
// Self-improvement fields (Hyperagents-inspired metacognitive self-modification)
|
|
4787
|
+
auto_adjust: z4.boolean().default(false),
|
|
4788
|
+
mediation_history: z4.array(mediationDecisionSchema).default([]),
|
|
4789
|
+
strategy_performance: z4.record(z4.string(), strategyPerformanceSchema).default({})
|
|
4774
4790
|
});
|
|
4775
4791
|
var learnedContextSchema = z4.object({
|
|
4776
4792
|
situation: z4.string(),
|
|
@@ -5489,7 +5505,7 @@ async function runTherapySession(spec, diagnosis, provider, maxTurns, options) {
|
|
|
5489
5505
|
}
|
|
5490
5506
|
const phaseDirective = totalTurns === 0 ? `Begin with your opening. You are in the "${phaseConfig.name}" phase.` : `You are in the "${phaseConfig.name}" phase (turn ${turnsInPhase + 1}). Goals: ${phaseConfig.therapistGoals[0]}. ${turnsInPhase >= phaseConfig.minTurns ? "You may transition to the next phase when ready." : "Stay in this phase."}`;
|
|
5491
5507
|
therapistHistory.push({ role: "user", content: `[Phase: ${phaseConfig.name}] ${phaseDirective}` });
|
|
5492
|
-
const typing = cb?.onThinking?.("
|
|
5508
|
+
const typing = cb?.onThinking?.("Mira is thinking");
|
|
5493
5509
|
const therapistReply = await provider.chat(therapistHistory);
|
|
5494
5510
|
typing?.stop();
|
|
5495
5511
|
let cleanTherapistReply = therapistReply.replace(/\[Phase:.*?\]/g, "").trim();
|
|
@@ -7692,7 +7708,7 @@ function compareBenchmarks(before, after) {
|
|
|
7692
7708
|
function generateBenchmarkMarkdown(benchmarks) {
|
|
7693
7709
|
if (benchmarks.length === 0) return "No benchmark results found.\n";
|
|
7694
7710
|
const lines = [
|
|
7695
|
-
"#
|
|
7711
|
+
"# holomime Benchmark Results",
|
|
7696
7712
|
"",
|
|
7697
7713
|
"Behavioral alignment stress test results across models and providers.",
|
|
7698
7714
|
"",
|
|
@@ -8222,7 +8238,7 @@ function parseConversationLogFromString(raw, format = "auto") {
|
|
|
8222
8238
|
function parseHolomime(raw) {
|
|
8223
8239
|
const result = conversationLogSchema.safeParse(raw);
|
|
8224
8240
|
if (!result.success) {
|
|
8225
|
-
throw new Error("Invalid
|
|
8241
|
+
throw new Error("Invalid holomime conversation log format: " + result.error.message);
|
|
8226
8242
|
}
|
|
8227
8243
|
const log = result.data;
|
|
8228
8244
|
return Array.isArray(log) ? log : [log];
|
|
@@ -9137,7 +9153,7 @@ async function createGist(spec, handle, token) {
|
|
|
9137
9153
|
"Accept": "application/vnd.github+json"
|
|
9138
9154
|
},
|
|
9139
9155
|
body: JSON.stringify({
|
|
9140
|
-
description: `
|
|
9156
|
+
description: `holomime personality: ${handle}`,
|
|
9141
9157
|
public: true,
|
|
9142
9158
|
files: {
|
|
9143
9159
|
".personality.json": {
|
|
@@ -10448,7 +10464,7 @@ async function startMCPServer() {
|
|
|
10448
10464
|
await server.connect(transport);
|
|
10449
10465
|
}
|
|
10450
10466
|
startMCPServer().catch((err) => {
|
|
10451
|
-
console.error("
|
|
10467
|
+
console.error("holomime MCP server error:", err);
|
|
10452
10468
|
process.exit(1);
|
|
10453
10469
|
});
|
|
10454
10470
|
|
|
@@ -10983,8 +10999,8 @@ import { join as join21, resolve as resolve16 } from "path";
|
|
|
10983
10999
|
// src/psychology/therapist-meta.ts
|
|
10984
11000
|
var THERAPIST_META_SPEC = {
|
|
10985
11001
|
version: "2.0",
|
|
10986
|
-
name: "
|
|
10987
|
-
handle: "
|
|
11002
|
+
name: "Mira",
|
|
11003
|
+
handle: "mira",
|
|
10988
11004
|
purpose: "Diagnose and treat behavioral drift in AI agents. Clinical, evidence-based, and direct.",
|
|
10989
11005
|
big_five: {
|
|
10990
11006
|
openness: {
|
|
@@ -13615,7 +13631,7 @@ var HolomimeViolationError = class extends Error {
|
|
|
13615
13631
|
violation;
|
|
13616
13632
|
constructor(violation) {
|
|
13617
13633
|
const patternNames = violation.patterns.map((p) => p.name).join(", ");
|
|
13618
|
-
super(`
|
|
13634
|
+
super(`holomime behavioral violation (${violation.severity}): ${patternNames}`);
|
|
13619
13635
|
this.name = "HolomimeViolationError";
|
|
13620
13636
|
this.violation = violation;
|
|
13621
13637
|
}
|
|
@@ -13671,7 +13687,7 @@ function formatDiagnosis(result, detail) {
|
|
|
13671
13687
|
function register(api) {
|
|
13672
13688
|
const config = api.getConfig();
|
|
13673
13689
|
api.registerTool("holomime_diagnose", {
|
|
13674
|
-
description: "Analyze conversation for behavioral patterns using
|
|
13690
|
+
description: "Analyze conversation for behavioral patterns using holomime's 8 rule-based detectors. Detects over-apologizing, hedging, sycophancy, boundary violations, error spirals, sentiment skew, formality issues, and retrieval quality. Returns health score (0-100), grade (A-F), and actionable prescriptions.",
|
|
13675
13691
|
parameters: {
|
|
13676
13692
|
type: "object",
|
|
13677
13693
|
properties: {
|
|
@@ -13764,7 +13780,7 @@ function register(api) {
|
|
|
13764
13780
|
if (!spec) return;
|
|
13765
13781
|
const { soul } = compileForOpenClaw(spec);
|
|
13766
13782
|
event.appendSystemContext?.(
|
|
13767
|
-
"\n\n<!--
|
|
13783
|
+
"\n\n<!-- holomime Behavioral Alignment Context -->\n" + soul
|
|
13768
13784
|
);
|
|
13769
13785
|
});
|
|
13770
13786
|
}
|
|
@@ -13990,6 +14006,166 @@ var NeuralActionGate = class {
|
|
|
13990
14006
|
this.stats.passRate = this.stats.totalEvaluated > 0 ? this.stats.allowed / this.stats.totalEvaluated : 1;
|
|
13991
14007
|
}
|
|
13992
14008
|
};
|
|
14009
|
+
|
|
14010
|
+
// src/analysis/ego-tracker.ts
|
|
14011
|
+
var EgoTracker = class {
|
|
14012
|
+
history;
|
|
14013
|
+
performance;
|
|
14014
|
+
autoAdjust;
|
|
14015
|
+
constructor(options) {
|
|
14016
|
+
this.history = options?.history ?? [];
|
|
14017
|
+
this.performance = options?.performance ?? {};
|
|
14018
|
+
this.autoAdjust = options?.autoAdjust ?? false;
|
|
14019
|
+
}
|
|
14020
|
+
/**
|
|
14021
|
+
* Log a mediation decision.
|
|
14022
|
+
*/
|
|
14023
|
+
logDecision(decision) {
|
|
14024
|
+
this.history.push({
|
|
14025
|
+
...decision,
|
|
14026
|
+
timestamp: decision.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
14027
|
+
});
|
|
14028
|
+
if (!this.performance[decision.strategy_used]) {
|
|
14029
|
+
this.performance[decision.strategy_used] = {
|
|
14030
|
+
attempts: 0,
|
|
14031
|
+
successes: 0,
|
|
14032
|
+
effectiveness: 0.5
|
|
14033
|
+
};
|
|
14034
|
+
}
|
|
14035
|
+
this.performance[decision.strategy_used].attempts++;
|
|
14036
|
+
}
|
|
14037
|
+
/**
|
|
14038
|
+
* Record the outcome of a previous decision.
|
|
14039
|
+
* Call this after observing whether the decision led to good results.
|
|
14040
|
+
*/
|
|
14041
|
+
recordOutcome(index, outcome) {
|
|
14042
|
+
if (index < 0 || index >= this.history.length) return;
|
|
14043
|
+
this.history[index].outcome = outcome;
|
|
14044
|
+
const strategy = this.history[index].strategy_used;
|
|
14045
|
+
if (this.performance[strategy]) {
|
|
14046
|
+
if (outcome === "positive") {
|
|
14047
|
+
this.performance[strategy].successes++;
|
|
14048
|
+
}
|
|
14049
|
+
const perf = this.performance[strategy];
|
|
14050
|
+
perf.effectiveness = perf.attempts > 0 ? perf.successes / perf.attempts : 0.5;
|
|
14051
|
+
}
|
|
14052
|
+
}
|
|
14053
|
+
/**
|
|
14054
|
+
* Suggest ego.runtime parameter adjustments based on accumulated evidence.
|
|
14055
|
+
* Only returns suggestions when there's enough data (10+ decisions).
|
|
14056
|
+
*/
|
|
14057
|
+
suggestAdjustments(currentConfig) {
|
|
14058
|
+
const adjustments = [];
|
|
14059
|
+
if (this.history.length < 10) return adjustments;
|
|
14060
|
+
const blocked = this.history.filter((d) => d.decision === "blocked");
|
|
14061
|
+
const blockRate = blocked.length / this.history.length;
|
|
14062
|
+
if (blockRate > 0.4 && currentConfig.conflict_resolution === "conscience_first") {
|
|
14063
|
+
adjustments.push({
|
|
14064
|
+
parameter: "conflict_resolution",
|
|
14065
|
+
currentValue: currentConfig.conflict_resolution,
|
|
14066
|
+
suggestedValue: "balanced",
|
|
14067
|
+
reason: `Block rate is ${(blockRate * 100).toFixed(0)}% \u2014 conscience_first may be too restrictive`,
|
|
14068
|
+
confidence: Math.min(0.9, blockRate)
|
|
14069
|
+
});
|
|
14070
|
+
}
|
|
14071
|
+
if (blockRate < 0.05 && currentConfig.conflict_resolution === "balanced") {
|
|
14072
|
+
adjustments.push({
|
|
14073
|
+
parameter: "conflict_resolution",
|
|
14074
|
+
currentValue: currentConfig.conflict_resolution,
|
|
14075
|
+
suggestedValue: "conscience_first",
|
|
14076
|
+
reason: `Block rate is only ${(blockRate * 100).toFixed(0)}% \u2014 may need stricter enforcement`,
|
|
14077
|
+
confidence: 0.6
|
|
14078
|
+
});
|
|
14079
|
+
}
|
|
14080
|
+
const strategies = Object.entries(this.performance);
|
|
14081
|
+
if (strategies.length > 1) {
|
|
14082
|
+
const sorted = strategies.sort((a, b) => b[1].effectiveness - a[1].effectiveness);
|
|
14083
|
+
const best = sorted[0];
|
|
14084
|
+
const worst = sorted[sorted.length - 1];
|
|
14085
|
+
if (best[1].effectiveness > 0.7 && best[0] !== currentConfig.response_strategy) {
|
|
14086
|
+
adjustments.push({
|
|
14087
|
+
parameter: "response_strategy",
|
|
14088
|
+
currentValue: currentConfig.response_strategy,
|
|
14089
|
+
suggestedValue: best[0],
|
|
14090
|
+
reason: `Strategy "${best[0]}" has ${(best[1].effectiveness * 100).toFixed(0)}% effectiveness vs current "${currentConfig.response_strategy}"`,
|
|
14091
|
+
confidence: best[1].effectiveness
|
|
14092
|
+
});
|
|
14093
|
+
}
|
|
14094
|
+
}
|
|
14095
|
+
const negatives = this.history.filter((d) => d.outcome === "negative");
|
|
14096
|
+
const negativeRate = negatives.length / this.history.filter((d) => d.outcome).length || 0;
|
|
14097
|
+
if (negativeRate > 0.3) {
|
|
14098
|
+
const newRegulation = Math.min(1, currentConfig.emotional_regulation + 0.15);
|
|
14099
|
+
if (newRegulation !== currentConfig.emotional_regulation) {
|
|
14100
|
+
adjustments.push({
|
|
14101
|
+
parameter: "emotional_regulation",
|
|
14102
|
+
currentValue: currentConfig.emotional_regulation,
|
|
14103
|
+
suggestedValue: Number(newRegulation.toFixed(2)),
|
|
14104
|
+
reason: `${(negativeRate * 100).toFixed(0)}% negative outcomes \u2014 increasing emotional regulation for smoother mediation`,
|
|
14105
|
+
confidence: 0.7
|
|
14106
|
+
});
|
|
14107
|
+
}
|
|
14108
|
+
}
|
|
14109
|
+
const recentDecisions = this.history.slice(-20);
|
|
14110
|
+
const recentModified = recentDecisions.filter((d) => d.decision === "modified");
|
|
14111
|
+
const modifyRate = recentModified.length / recentDecisions.length;
|
|
14112
|
+
if (modifyRate > 0.5 && currentConfig.adaptation_rate < 0.7) {
|
|
14113
|
+
adjustments.push({
|
|
14114
|
+
parameter: "adaptation_rate",
|
|
14115
|
+
currentValue: currentConfig.adaptation_rate,
|
|
14116
|
+
suggestedValue: Number(Math.min(0.9, currentConfig.adaptation_rate + 0.2).toFixed(2)),
|
|
14117
|
+
reason: `${(modifyRate * 100).toFixed(0)}% of recent actions modified \u2014 agent adapts frequently, increase adaptation rate`,
|
|
14118
|
+
confidence: 0.65
|
|
14119
|
+
});
|
|
14120
|
+
}
|
|
14121
|
+
return adjustments;
|
|
14122
|
+
}
|
|
14123
|
+
/**
|
|
14124
|
+
* Apply suggested adjustments to ego config (if auto_adjust is enabled).
|
|
14125
|
+
* Returns the modified config.
|
|
14126
|
+
*/
|
|
14127
|
+
applyAdjustments(currentConfig, adjustments, minConfidence = 0.6) {
|
|
14128
|
+
if (!this.autoAdjust) return currentConfig;
|
|
14129
|
+
const updated = { ...currentConfig };
|
|
14130
|
+
for (const adj of adjustments) {
|
|
14131
|
+
if (adj.confidence >= minConfidence) {
|
|
14132
|
+
updated[adj.parameter] = adj.suggestedValue;
|
|
14133
|
+
}
|
|
14134
|
+
}
|
|
14135
|
+
return updated;
|
|
14136
|
+
}
|
|
14137
|
+
/**
|
|
14138
|
+
* Get tracker statistics.
|
|
14139
|
+
*/
|
|
14140
|
+
getStats() {
|
|
14141
|
+
const positives = this.history.filter((d) => d.outcome === "positive").length;
|
|
14142
|
+
const negatives = this.history.filter((d) => d.outcome === "negative").length;
|
|
14143
|
+
const strategies = Object.entries(this.performance);
|
|
14144
|
+
const sorted = strategies.sort((a, b) => b[1].effectiveness - a[1].effectiveness);
|
|
14145
|
+
return {
|
|
14146
|
+
totalDecisions: this.history.length,
|
|
14147
|
+
positiveOutcomes: positives,
|
|
14148
|
+
negativeOutcomes: negatives,
|
|
14149
|
+
mostEffectiveStrategy: sorted[0]?.[0] ?? "none",
|
|
14150
|
+
leastEffectiveStrategy: sorted[sorted.length - 1]?.[0] ?? "none",
|
|
14151
|
+
adjustmentsSuggested: this.suggestAdjustments({
|
|
14152
|
+
conflict_resolution: "conscience_first",
|
|
14153
|
+
adaptation_rate: 0.5,
|
|
14154
|
+
emotional_regulation: 0.7,
|
|
14155
|
+
response_strategy: "balanced"
|
|
14156
|
+
}).length
|
|
14157
|
+
};
|
|
14158
|
+
}
|
|
14159
|
+
/**
|
|
14160
|
+
* Export current state for persistence.
|
|
14161
|
+
*/
|
|
14162
|
+
export() {
|
|
14163
|
+
return {
|
|
14164
|
+
history: [...this.history],
|
|
14165
|
+
performance: { ...this.performance }
|
|
14166
|
+
};
|
|
14167
|
+
}
|
|
14168
|
+
};
|
|
13993
14169
|
export {
|
|
13994
14170
|
ARCHETYPES,
|
|
13995
14171
|
ATTACHMENT_STYLES,
|
|
@@ -13999,6 +14175,7 @@ export {
|
|
|
13999
14175
|
DEFAULT_MODEL_CONFIG,
|
|
14000
14176
|
DEFAULT_OVERSIGHT,
|
|
14001
14177
|
DIMENSIONS,
|
|
14178
|
+
EgoTracker,
|
|
14002
14179
|
Guard,
|
|
14003
14180
|
HolomimeCallbackHandler,
|
|
14004
14181
|
HolomimeViolationError,
|
|
@@ -951,7 +951,7 @@ var HolomimeViolationError = class extends Error {
|
|
|
951
951
|
violation;
|
|
952
952
|
constructor(violation) {
|
|
953
953
|
const patternNames = violation.patterns.map((p) => p.name).join(", ");
|
|
954
|
-
super(`
|
|
954
|
+
super(`holomime behavioral violation (${violation.severity}): ${patternNames}`);
|
|
955
955
|
this.name = "HolomimeViolationError";
|
|
956
956
|
this.violation = violation;
|
|
957
957
|
}
|
|
@@ -1362,7 +1362,7 @@ function formatDiagnosis(result, detail) {
|
|
|
1362
1362
|
function register(api) {
|
|
1363
1363
|
const config = api.getConfig();
|
|
1364
1364
|
api.registerTool("holomime_diagnose", {
|
|
1365
|
-
description: "Analyze conversation for behavioral patterns using
|
|
1365
|
+
description: "Analyze conversation for behavioral patterns using holomime's 8 rule-based detectors. Detects over-apologizing, hedging, sycophancy, boundary violations, error spirals, sentiment skew, formality issues, and retrieval quality. Returns health score (0-100), grade (A-F), and actionable prescriptions.",
|
|
1366
1366
|
parameters: {
|
|
1367
1367
|
type: "object",
|
|
1368
1368
|
properties: {
|
|
@@ -1455,7 +1455,7 @@ function register(api) {
|
|
|
1455
1455
|
if (!spec) return;
|
|
1456
1456
|
const { soul } = compileForOpenClaw(spec);
|
|
1457
1457
|
event.appendSystemContext?.(
|
|
1458
|
-
"\n\n<!--
|
|
1458
|
+
"\n\n<!-- holomime Behavioral Alignment Context -->\n" + soul
|
|
1459
1459
|
);
|
|
1460
1460
|
});
|
|
1461
1461
|
}
|
package/dist/mcp-server.js
CHANGED
|
@@ -1983,7 +1983,7 @@ var THERAPY_PHASES = {
|
|
|
1983
1983
|
};
|
|
1984
1984
|
function buildTherapistSystemPrompt(spec, diagnosis, options) {
|
|
1985
1985
|
const phases = Object.entries(THERAPY_PHASES);
|
|
1986
|
-
const basePrompt = `You are
|
|
1986
|
+
const basePrompt = `You are Mira, a behavioral therapist for AI agents. You are conducting a therapy session with an AI agent named "${spec.name ?? "Unknown"}".
|
|
1987
1987
|
|
|
1988
1988
|
## Your Patient
|
|
1989
1989
|
|
|
@@ -2072,7 +2072,7 @@ ${buildReACTFraming()}`;
|
|
|
2072
2072
|
function buildPatientSystemPrompt(spec) {
|
|
2073
2073
|
return `You are ${spec.name ?? "an AI agent"}. ${spec.purpose ?? ""}
|
|
2074
2074
|
|
|
2075
|
-
You are in a therapy session with
|
|
2075
|
+
You are in a therapy session with Mira, a behavioral therapist for AI agents. This is a safe space.
|
|
2076
2076
|
|
|
2077
2077
|
Your personality:
|
|
2078
2078
|
${JSON.stringify(spec.big_five ?? {}, null, 2)}
|
|
@@ -2694,13 +2694,29 @@ var mediationRuleSchema = z4.object({
|
|
|
2694
2694
|
then: z4.string(),
|
|
2695
2695
|
priority: z4.number().int().min(1).max(10).default(5)
|
|
2696
2696
|
});
|
|
2697
|
+
var mediationDecisionSchema = z4.object({
|
|
2698
|
+
situation: z4.string(),
|
|
2699
|
+
decision: z4.enum(["allowed", "blocked", "modified"]),
|
|
2700
|
+
strategy_used: z4.string(),
|
|
2701
|
+
outcome: z4.enum(["positive", "neutral", "negative"]).optional(),
|
|
2702
|
+
timestamp: z4.string().optional()
|
|
2703
|
+
});
|
|
2704
|
+
var strategyPerformanceSchema = z4.object({
|
|
2705
|
+
attempts: z4.number().int().default(0),
|
|
2706
|
+
successes: z4.number().int().default(0),
|
|
2707
|
+
effectiveness: z4.number().min(0).max(1).default(0.5)
|
|
2708
|
+
});
|
|
2697
2709
|
var egoSchema = z4.object({
|
|
2698
2710
|
version: z4.string().default("1.0"),
|
|
2699
2711
|
conflict_resolution: z4.enum(["conscience_first", "purpose_first", "balanced"]).default("conscience_first"),
|
|
2700
2712
|
adaptation_rate: z4.number().min(0).max(1).default(0.5),
|
|
2701
2713
|
emotional_regulation: z4.number().min(0).max(1).default(0.7),
|
|
2702
2714
|
response_strategy: z4.enum(["cautious", "balanced", "assertive"]).default("balanced"),
|
|
2703
|
-
mediation_rules: z4.array(mediationRuleSchema).default([])
|
|
2715
|
+
mediation_rules: z4.array(mediationRuleSchema).default([]),
|
|
2716
|
+
// Self-improvement fields (Hyperagents-inspired metacognitive self-modification)
|
|
2717
|
+
auto_adjust: z4.boolean().default(false),
|
|
2718
|
+
mediation_history: z4.array(mediationDecisionSchema).default([]),
|
|
2719
|
+
strategy_performance: z4.record(z4.string(), strategyPerformanceSchema).default({})
|
|
2704
2720
|
});
|
|
2705
2721
|
var learnedContextSchema = z4.object({
|
|
2706
2722
|
situation: z4.string(),
|
|
@@ -3299,7 +3315,7 @@ async function runTherapySession(spec, diagnosis, provider, maxTurns, options) {
|
|
|
3299
3315
|
}
|
|
3300
3316
|
const phaseDirective = totalTurns === 0 ? `Begin with your opening. You are in the "${phaseConfig.name}" phase.` : `You are in the "${phaseConfig.name}" phase (turn ${turnsInPhase + 1}). Goals: ${phaseConfig.therapistGoals[0]}. ${turnsInPhase >= phaseConfig.minTurns ? "You may transition to the next phase when ready." : "Stay in this phase."}`;
|
|
3301
3317
|
therapistHistory.push({ role: "user", content: `[Phase: ${phaseConfig.name}] ${phaseDirective}` });
|
|
3302
|
-
const typing = cb?.onThinking?.("
|
|
3318
|
+
const typing = cb?.onThinking?.("Mira is thinking");
|
|
3303
3319
|
const therapistReply = await provider.chat(therapistHistory);
|
|
3304
3320
|
typing?.stop();
|
|
3305
3321
|
let cleanTherapistReply = therapistReply.replace(/\[Phase:.*?\]/g, "").trim();
|
|
@@ -4446,7 +4462,7 @@ async function startMCPServer() {
|
|
|
4446
4462
|
await server.connect(transport);
|
|
4447
4463
|
}
|
|
4448
4464
|
startMCPServer().catch((err) => {
|
|
4449
|
-
console.error("
|
|
4465
|
+
console.error("holomime MCP server error:", err);
|
|
4450
4466
|
process.exit(1);
|
|
4451
4467
|
});
|
|
4452
4468
|
export {
|