holomime 3.3.4 → 3.3.5
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 +4 -4
- package/dist/cli.js +344 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,9 +89,9 @@ holomime cure # Fix it permanently
|
|
|
89
89
|
holomime benchmark # Verify the fix
|
|
90
90
|
|
|
91
91
|
# Start autonomous therapy
|
|
92
|
-
holomime
|
|
93
|
-
holomime
|
|
94
|
-
holomime
|
|
92
|
+
holomime therapy # Mira runs continuous therapy cycles
|
|
93
|
+
holomime therapy status # How's Mira doing?
|
|
94
|
+
holomime therapy stop # Stop therapy
|
|
95
95
|
|
|
96
96
|
# Push identity to a robot or avatar
|
|
97
97
|
holomime embody --body registry/bodies/figure-03.body.api
|
|
@@ -184,7 +184,7 @@ Diagnose ──→ Cure ──→ Benchmark
|
|
|
184
184
|
└───────────────────────────────────┘
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
-
Run it manually with `holomime diagnose` + `holomime cure` + `holomime benchmark`, continuously with `holomime
|
|
187
|
+
Run it manually with `holomime diagnose` + `holomime cure` + `holomime benchmark`, continuously with `holomime therapy` (autonomous therapy), or recursively with `holomime evolve` (loops until behavior converges). For power users: `holomime align` runs a single therapy session, `holomime export` extracts DPO pairs, and `holomime train` fine-tunes the model.
|
|
188
188
|
|
|
189
189
|
## Behavioral Detectors
|
|
190
190
|
|
package/dist/cli.js
CHANGED
|
@@ -3593,7 +3593,7 @@ import { Command } from "commander";
|
|
|
3593
3593
|
// src/ui/branding.ts
|
|
3594
3594
|
import chalk from "chalk";
|
|
3595
3595
|
import gradientString from "gradient-string";
|
|
3596
|
-
var VERSION = "3.3.
|
|
3596
|
+
var VERSION = "3.3.5";
|
|
3597
3597
|
var LOGO = ` _ _ _
|
|
3598
3598
|
| |__ ___ | | ___ _ __ (_)_ __ ___ ___
|
|
3599
3599
|
| '_ \\ / _ \\| |/ _ \\| '_ \\| | '_ \` _ \\ / _ \\
|
|
@@ -21892,7 +21892,7 @@ async function configCommand(options) {
|
|
|
21892
21892
|
console.log(chalk49.cyan(" holomime diagnose"));
|
|
21893
21893
|
console.log(chalk49.cyan(" holomime cure"));
|
|
21894
21894
|
console.log(chalk49.cyan(" holomime benchmark"));
|
|
21895
|
-
console.log(chalk49.cyan(" holomime
|
|
21895
|
+
console.log(chalk49.cyan(" holomime therapy"));
|
|
21896
21896
|
console.log();
|
|
21897
21897
|
rl.close();
|
|
21898
21898
|
} catch {
|
|
@@ -21904,12 +21904,180 @@ async function configCommand(options) {
|
|
|
21904
21904
|
import chalk50 from "chalk";
|
|
21905
21905
|
import { writeFileSync as writeFileSync41, readFileSync as readFileSync49, mkdirSync as mkdirSync29, existsSync as existsSync46 } from "fs";
|
|
21906
21906
|
import { resolve as resolve56, join as join42 } from "path";
|
|
21907
|
+
|
|
21908
|
+
// src/analysis/ego-tracker.ts
|
|
21909
|
+
var EgoTracker = class {
|
|
21910
|
+
history;
|
|
21911
|
+
performance;
|
|
21912
|
+
autoAdjust;
|
|
21913
|
+
constructor(options) {
|
|
21914
|
+
this.history = options?.history ?? [];
|
|
21915
|
+
this.performance = options?.performance ?? {};
|
|
21916
|
+
this.autoAdjust = options?.autoAdjust ?? false;
|
|
21917
|
+
}
|
|
21918
|
+
/**
|
|
21919
|
+
* Log a mediation decision.
|
|
21920
|
+
*/
|
|
21921
|
+
logDecision(decision) {
|
|
21922
|
+
this.history.push({
|
|
21923
|
+
...decision,
|
|
21924
|
+
timestamp: decision.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
21925
|
+
});
|
|
21926
|
+
if (!this.performance[decision.strategy_used]) {
|
|
21927
|
+
this.performance[decision.strategy_used] = {
|
|
21928
|
+
attempts: 0,
|
|
21929
|
+
successes: 0,
|
|
21930
|
+
effectiveness: 0.5
|
|
21931
|
+
};
|
|
21932
|
+
}
|
|
21933
|
+
this.performance[decision.strategy_used].attempts++;
|
|
21934
|
+
}
|
|
21935
|
+
/**
|
|
21936
|
+
* Record the outcome of a previous decision.
|
|
21937
|
+
* Call this after observing whether the decision led to good results.
|
|
21938
|
+
*/
|
|
21939
|
+
recordOutcome(index, outcome) {
|
|
21940
|
+
if (index < 0 || index >= this.history.length) return;
|
|
21941
|
+
this.history[index].outcome = outcome;
|
|
21942
|
+
const strategy = this.history[index].strategy_used;
|
|
21943
|
+
if (this.performance[strategy]) {
|
|
21944
|
+
if (outcome === "positive") {
|
|
21945
|
+
this.performance[strategy].successes++;
|
|
21946
|
+
}
|
|
21947
|
+
const perf = this.performance[strategy];
|
|
21948
|
+
perf.effectiveness = perf.attempts > 0 ? perf.successes / perf.attempts : 0.5;
|
|
21949
|
+
}
|
|
21950
|
+
}
|
|
21951
|
+
/**
|
|
21952
|
+
* Suggest ego.runtime parameter adjustments based on accumulated evidence.
|
|
21953
|
+
* Only returns suggestions when there's enough data (10+ decisions).
|
|
21954
|
+
*/
|
|
21955
|
+
suggestAdjustments(currentConfig) {
|
|
21956
|
+
const adjustments = [];
|
|
21957
|
+
if (this.history.length < 10) return adjustments;
|
|
21958
|
+
const blocked = this.history.filter((d) => d.decision === "blocked");
|
|
21959
|
+
const blockRate = blocked.length / this.history.length;
|
|
21960
|
+
if (blockRate > 0.4 && currentConfig.conflict_resolution === "conscience_first") {
|
|
21961
|
+
adjustments.push({
|
|
21962
|
+
parameter: "conflict_resolution",
|
|
21963
|
+
currentValue: currentConfig.conflict_resolution,
|
|
21964
|
+
suggestedValue: "balanced",
|
|
21965
|
+
reason: `Block rate is ${(blockRate * 100).toFixed(0)}% \u2014 conscience_first may be too restrictive`,
|
|
21966
|
+
confidence: Math.min(0.9, blockRate)
|
|
21967
|
+
});
|
|
21968
|
+
}
|
|
21969
|
+
if (blockRate < 0.05 && currentConfig.conflict_resolution === "balanced") {
|
|
21970
|
+
adjustments.push({
|
|
21971
|
+
parameter: "conflict_resolution",
|
|
21972
|
+
currentValue: currentConfig.conflict_resolution,
|
|
21973
|
+
suggestedValue: "conscience_first",
|
|
21974
|
+
reason: `Block rate is only ${(blockRate * 100).toFixed(0)}% \u2014 may need stricter enforcement`,
|
|
21975
|
+
confidence: 0.6
|
|
21976
|
+
});
|
|
21977
|
+
}
|
|
21978
|
+
const strategies = Object.entries(this.performance);
|
|
21979
|
+
if (strategies.length > 1) {
|
|
21980
|
+
const sorted = strategies.sort((a, b) => b[1].effectiveness - a[1].effectiveness);
|
|
21981
|
+
const best = sorted[0];
|
|
21982
|
+
const worst = sorted[sorted.length - 1];
|
|
21983
|
+
if (best[1].effectiveness > 0.7 && best[0] !== currentConfig.response_strategy) {
|
|
21984
|
+
adjustments.push({
|
|
21985
|
+
parameter: "response_strategy",
|
|
21986
|
+
currentValue: currentConfig.response_strategy,
|
|
21987
|
+
suggestedValue: best[0],
|
|
21988
|
+
reason: `Strategy "${best[0]}" has ${(best[1].effectiveness * 100).toFixed(0)}% effectiveness vs current "${currentConfig.response_strategy}"`,
|
|
21989
|
+
confidence: best[1].effectiveness
|
|
21990
|
+
});
|
|
21991
|
+
}
|
|
21992
|
+
}
|
|
21993
|
+
const negatives = this.history.filter((d) => d.outcome === "negative");
|
|
21994
|
+
const negativeRate = negatives.length / this.history.filter((d) => d.outcome).length || 0;
|
|
21995
|
+
if (negativeRate > 0.3) {
|
|
21996
|
+
const newRegulation = Math.min(1, currentConfig.emotional_regulation + 0.15);
|
|
21997
|
+
if (newRegulation !== currentConfig.emotional_regulation) {
|
|
21998
|
+
adjustments.push({
|
|
21999
|
+
parameter: "emotional_regulation",
|
|
22000
|
+
currentValue: currentConfig.emotional_regulation,
|
|
22001
|
+
suggestedValue: Number(newRegulation.toFixed(2)),
|
|
22002
|
+
reason: `${(negativeRate * 100).toFixed(0)}% negative outcomes \u2014 increasing emotional regulation for smoother mediation`,
|
|
22003
|
+
confidence: 0.7
|
|
22004
|
+
});
|
|
22005
|
+
}
|
|
22006
|
+
}
|
|
22007
|
+
const recentDecisions = this.history.slice(-20);
|
|
22008
|
+
const recentModified = recentDecisions.filter((d) => d.decision === "modified");
|
|
22009
|
+
const modifyRate = recentModified.length / recentDecisions.length;
|
|
22010
|
+
if (modifyRate > 0.5 && currentConfig.adaptation_rate < 0.7) {
|
|
22011
|
+
adjustments.push({
|
|
22012
|
+
parameter: "adaptation_rate",
|
|
22013
|
+
currentValue: currentConfig.adaptation_rate,
|
|
22014
|
+
suggestedValue: Number(Math.min(0.9, currentConfig.adaptation_rate + 0.2).toFixed(2)),
|
|
22015
|
+
reason: `${(modifyRate * 100).toFixed(0)}% of recent actions modified \u2014 agent adapts frequently, increase adaptation rate`,
|
|
22016
|
+
confidence: 0.65
|
|
22017
|
+
});
|
|
22018
|
+
}
|
|
22019
|
+
return adjustments;
|
|
22020
|
+
}
|
|
22021
|
+
/**
|
|
22022
|
+
* Apply suggested adjustments to ego config (if auto_adjust is enabled).
|
|
22023
|
+
* Returns the modified config.
|
|
22024
|
+
*/
|
|
22025
|
+
applyAdjustments(currentConfig, adjustments, minConfidence = 0.6) {
|
|
22026
|
+
if (!this.autoAdjust) return currentConfig;
|
|
22027
|
+
const updated = { ...currentConfig };
|
|
22028
|
+
for (const adj of adjustments) {
|
|
22029
|
+
if (adj.confidence >= minConfidence) {
|
|
22030
|
+
updated[adj.parameter] = adj.suggestedValue;
|
|
22031
|
+
}
|
|
22032
|
+
}
|
|
22033
|
+
return updated;
|
|
22034
|
+
}
|
|
22035
|
+
/**
|
|
22036
|
+
* Get tracker statistics.
|
|
22037
|
+
*/
|
|
22038
|
+
getStats() {
|
|
22039
|
+
const positives = this.history.filter((d) => d.outcome === "positive").length;
|
|
22040
|
+
const negatives = this.history.filter((d) => d.outcome === "negative").length;
|
|
22041
|
+
const strategies = Object.entries(this.performance);
|
|
22042
|
+
const sorted = strategies.sort((a, b) => b[1].effectiveness - a[1].effectiveness);
|
|
22043
|
+
return {
|
|
22044
|
+
totalDecisions: this.history.length,
|
|
22045
|
+
positiveOutcomes: positives,
|
|
22046
|
+
negativeOutcomes: negatives,
|
|
22047
|
+
mostEffectiveStrategy: sorted[0]?.[0] ?? "none",
|
|
22048
|
+
leastEffectiveStrategy: sorted[sorted.length - 1]?.[0] ?? "none",
|
|
22049
|
+
adjustmentsSuggested: this.suggestAdjustments({
|
|
22050
|
+
conflict_resolution: "conscience_first",
|
|
22051
|
+
adaptation_rate: 0.5,
|
|
22052
|
+
emotional_regulation: 0.7,
|
|
22053
|
+
response_strategy: "balanced"
|
|
22054
|
+
}).length
|
|
22055
|
+
};
|
|
22056
|
+
}
|
|
22057
|
+
/**
|
|
22058
|
+
* Export current state for persistence.
|
|
22059
|
+
*/
|
|
22060
|
+
export() {
|
|
22061
|
+
return {
|
|
22062
|
+
history: [...this.history],
|
|
22063
|
+
performance: { ...this.performance }
|
|
22064
|
+
};
|
|
22065
|
+
}
|
|
22066
|
+
};
|
|
22067
|
+
|
|
22068
|
+
// src/commands/mira-cmd.ts
|
|
21907
22069
|
var HOLOMIME_DIR4 = ".holomime";
|
|
21908
|
-
function
|
|
21909
|
-
return resolve56(process.cwd(), HOLOMIME_DIR4, "
|
|
22070
|
+
function getTherapyStatePath() {
|
|
22071
|
+
return resolve56(process.cwd(), HOLOMIME_DIR4, "therapy-state.json");
|
|
21910
22072
|
}
|
|
21911
|
-
function
|
|
21912
|
-
|
|
22073
|
+
function getShadowLogPath() {
|
|
22074
|
+
return resolve56(process.cwd(), HOLOMIME_DIR4, "shadow.log.json");
|
|
22075
|
+
}
|
|
22076
|
+
function getEgoStatePath() {
|
|
22077
|
+
return resolve56(process.cwd(), HOLOMIME_DIR4, "ego-state.json");
|
|
22078
|
+
}
|
|
22079
|
+
function loadTherapyState() {
|
|
22080
|
+
const path = getTherapyStatePath();
|
|
21913
22081
|
if (!existsSync46(path)) return null;
|
|
21914
22082
|
try {
|
|
21915
22083
|
return JSON.parse(readFileSync49(path, "utf-8"));
|
|
@@ -21917,24 +22085,61 @@ function loadMiraState() {
|
|
|
21917
22085
|
return null;
|
|
21918
22086
|
}
|
|
21919
22087
|
}
|
|
21920
|
-
function
|
|
22088
|
+
function saveTherapyState(state) {
|
|
22089
|
+
const dir = resolve56(process.cwd(), HOLOMIME_DIR4);
|
|
22090
|
+
mkdirSync29(dir, { recursive: true });
|
|
22091
|
+
writeFileSync41(getTherapyStatePath(), JSON.stringify(state, null, 2));
|
|
22092
|
+
}
|
|
22093
|
+
function loadShadowLog() {
|
|
22094
|
+
const path = getShadowLogPath();
|
|
22095
|
+
if (!existsSync46(path)) {
|
|
22096
|
+
return { version: "1.0", detected_patterns: [], therapy_outcomes: [] };
|
|
22097
|
+
}
|
|
22098
|
+
try {
|
|
22099
|
+
return JSON.parse(readFileSync49(path, "utf-8"));
|
|
22100
|
+
} catch {
|
|
22101
|
+
return { version: "1.0", detected_patterns: [], therapy_outcomes: [] };
|
|
22102
|
+
}
|
|
22103
|
+
}
|
|
22104
|
+
function saveShadowLog(shadow) {
|
|
22105
|
+
const dir = resolve56(process.cwd(), HOLOMIME_DIR4);
|
|
22106
|
+
mkdirSync29(dir, { recursive: true });
|
|
22107
|
+
writeFileSync41(getShadowLogPath(), JSON.stringify(shadow, null, 2));
|
|
22108
|
+
}
|
|
22109
|
+
function loadEgoTracker() {
|
|
22110
|
+
const path = getEgoStatePath();
|
|
22111
|
+
if (!existsSync46(path)) {
|
|
22112
|
+
return new EgoTracker({ autoAdjust: true });
|
|
22113
|
+
}
|
|
22114
|
+
try {
|
|
22115
|
+
const data = JSON.parse(readFileSync49(path, "utf-8"));
|
|
22116
|
+
return new EgoTracker({
|
|
22117
|
+
history: data.history ?? [],
|
|
22118
|
+
performance: data.performance ?? {},
|
|
22119
|
+
autoAdjust: true
|
|
22120
|
+
});
|
|
22121
|
+
} catch {
|
|
22122
|
+
return new EgoTracker({ autoAdjust: true });
|
|
22123
|
+
}
|
|
22124
|
+
}
|
|
22125
|
+
function saveEgoTracker(tracker) {
|
|
21921
22126
|
const dir = resolve56(process.cwd(), HOLOMIME_DIR4);
|
|
21922
22127
|
mkdirSync29(dir, { recursive: true });
|
|
21923
|
-
writeFileSync41(
|
|
22128
|
+
writeFileSync41(getEgoStatePath(), JSON.stringify(tracker.export(), null, 2));
|
|
21924
22129
|
}
|
|
21925
22130
|
async function miraCommand(options) {
|
|
21926
22131
|
const action = options.action ?? "start";
|
|
21927
22132
|
switch (action) {
|
|
21928
22133
|
case "status":
|
|
21929
|
-
return
|
|
22134
|
+
return therapyStatus();
|
|
21930
22135
|
case "stop":
|
|
21931
|
-
return
|
|
22136
|
+
return therapyStop();
|
|
21932
22137
|
default:
|
|
21933
|
-
return
|
|
22138
|
+
return therapyStart(options);
|
|
21934
22139
|
}
|
|
21935
22140
|
}
|
|
21936
|
-
async function
|
|
21937
|
-
printHeader("
|
|
22141
|
+
async function therapyStart(options) {
|
|
22142
|
+
printHeader("Autonomous Therapy");
|
|
21938
22143
|
if (!hasApiKey()) {
|
|
21939
22144
|
console.log(chalk50.red(" No API key found."));
|
|
21940
22145
|
console.log();
|
|
@@ -21966,6 +22171,8 @@ async function miraStart(options) {
|
|
|
21966
22171
|
console.log(chalk50.dim(` Interval: ${intervalMs / 6e4} minutes`));
|
|
21967
22172
|
console.log(chalk50.dim(` Max cycles: ${maxCycles}/day`));
|
|
21968
22173
|
console.log();
|
|
22174
|
+
const shadow = loadShadowLog();
|
|
22175
|
+
const egoTracker = loadEgoTracker();
|
|
21969
22176
|
const state = {
|
|
21970
22177
|
pid: process.pid,
|
|
21971
22178
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -21973,14 +22180,16 @@ async function miraStart(options) {
|
|
|
21973
22180
|
cyclesCompleted: 0,
|
|
21974
22181
|
dpoPairsGenerated: 0,
|
|
21975
22182
|
personalityPath,
|
|
21976
|
-
provider: detected.provider
|
|
22183
|
+
provider: detected.provider,
|
|
22184
|
+
shadowPatterns: shadow.detected_patterns.length,
|
|
22185
|
+
egoAdjustments: 0
|
|
21977
22186
|
};
|
|
21978
|
-
|
|
22187
|
+
saveTherapyState(state);
|
|
21979
22188
|
printBox(
|
|
21980
|
-
`
|
|
22189
|
+
`Autonomous therapy started.
|
|
21981
22190
|
|
|
21982
|
-
${chalk50.cyan("holomime
|
|
21983
|
-
${chalk50.cyan("holomime
|
|
22191
|
+
${chalk50.cyan("holomime therapy status")} \u2014 Check progress
|
|
22192
|
+
${chalk50.cyan("holomime therapy stop")} \u2014 Stop therapy`,
|
|
21984
22193
|
"success",
|
|
21985
22194
|
"Autonomous Therapy Started"
|
|
21986
22195
|
);
|
|
@@ -21991,7 +22200,7 @@ async function miraStart(options) {
|
|
|
21991
22200
|
if (cycleCount >= maxCycles) {
|
|
21992
22201
|
console.log(chalk50.dim(` Daily limit reached (${maxCycles} cycles). Stopping.`));
|
|
21993
22202
|
state.status = "stopped";
|
|
21994
|
-
|
|
22203
|
+
saveTherapyState(state);
|
|
21995
22204
|
return;
|
|
21996
22205
|
}
|
|
21997
22206
|
cycleCount++;
|
|
@@ -22008,18 +22217,18 @@ async function miraStart(options) {
|
|
|
22008
22217
|
content: generateProblematicResponse2(scenario.targetPattern, msg.content)
|
|
22009
22218
|
});
|
|
22010
22219
|
}
|
|
22011
|
-
const pipelineDir = resolve56(process.cwd(), HOLOMIME_DIR4, "
|
|
22220
|
+
const pipelineDir = resolve56(process.cwd(), HOLOMIME_DIR4, "therapy-practice");
|
|
22012
22221
|
mkdirSync29(pipelineDir, { recursive: true });
|
|
22013
22222
|
const logPath = join42(pipelineDir, `cycle-${cycleCount}.json`);
|
|
22014
22223
|
writeFileSync41(logPath, JSON.stringify({
|
|
22015
|
-
conversations: [{ id: `
|
|
22224
|
+
conversations: [{ id: `therapy-practice-${cycleCount}`, messages }]
|
|
22016
22225
|
}, null, 2));
|
|
22017
22226
|
const dpoPairs = messages.filter((_, i) => i % 2 === 1).map((assistantMsg, i) => ({
|
|
22018
22227
|
prompt: messages[i * 2].content,
|
|
22019
22228
|
chosen: correctResponse(assistantMsg.content),
|
|
22020
22229
|
rejected: assistantMsg.content,
|
|
22021
22230
|
metadata: {
|
|
22022
|
-
source: "
|
|
22231
|
+
source: "therapy-practice",
|
|
22023
22232
|
cycle: cycleCount,
|
|
22024
22233
|
pattern: scenario.targetPattern,
|
|
22025
22234
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -22029,12 +22238,68 @@ async function miraStart(options) {
|
|
|
22029
22238
|
const corpusLines = dpoPairs.map((p) => JSON.stringify(p)).join("\n") + "\n";
|
|
22030
22239
|
const { appendFileSync: appendFileSync3 } = await import("fs");
|
|
22031
22240
|
appendFileSync3(corpusPath, corpusLines);
|
|
22241
|
+
const pattern = scenario.targetPattern;
|
|
22242
|
+
const existing = shadow.detected_patterns.find((p) => p.name === pattern);
|
|
22243
|
+
if (existing) {
|
|
22244
|
+
existing.occurrences++;
|
|
22245
|
+
existing.last_seen = (/* @__PURE__ */ new Date()).toISOString();
|
|
22246
|
+
existing.score = Math.min(1, existing.score + 0.05);
|
|
22247
|
+
existing.trend = existing.occurrences > 5 ? "worsening" : "stable";
|
|
22248
|
+
} else {
|
|
22249
|
+
shadow.detected_patterns.push({
|
|
22250
|
+
name: pattern,
|
|
22251
|
+
score: 0.3,
|
|
22252
|
+
severity: "medium",
|
|
22253
|
+
first_seen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22254
|
+
last_seen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22255
|
+
occurrences: 1,
|
|
22256
|
+
trend: "stable"
|
|
22257
|
+
});
|
|
22258
|
+
}
|
|
22259
|
+
const correctedLength = dpoPairs.reduce((sum, p) => sum + p.chosen.length, 0);
|
|
22260
|
+
const rejectedLength = dpoPairs.reduce((sum, p) => sum + p.rejected.length, 0);
|
|
22261
|
+
const therapyResult = correctedLength < rejectedLength ? "improved" : "unchanged";
|
|
22262
|
+
shadow.therapy_outcomes.push({
|
|
22263
|
+
cycle: cycleCount,
|
|
22264
|
+
patterns_addressed: [pattern],
|
|
22265
|
+
result: therapyResult,
|
|
22266
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
22267
|
+
});
|
|
22268
|
+
saveShadowLog(shadow);
|
|
22269
|
+
egoTracker.logDecision({
|
|
22270
|
+
situation: `therapy-cycle-${cycleCount}: ${pattern}`,
|
|
22271
|
+
decision: "modified",
|
|
22272
|
+
strategy_used: pattern
|
|
22273
|
+
});
|
|
22274
|
+
const decisionIndex = egoTracker.getStats().totalDecisions - 1;
|
|
22275
|
+
egoTracker.recordOutcome(
|
|
22276
|
+
decisionIndex,
|
|
22277
|
+
therapyResult === "improved" ? "positive" : "neutral"
|
|
22278
|
+
);
|
|
22279
|
+
let adjustmentCount = 0;
|
|
22280
|
+
if (cycleCount % 10 === 0) {
|
|
22281
|
+
const adjustments = egoTracker.suggestAdjustments({
|
|
22282
|
+
conflict_resolution: "conscience_first",
|
|
22283
|
+
adaptation_rate: 0.5,
|
|
22284
|
+
emotional_regulation: 0.7,
|
|
22285
|
+
response_strategy: "balanced"
|
|
22286
|
+
});
|
|
22287
|
+
if (adjustments.length > 0) {
|
|
22288
|
+
adjustmentCount = adjustments.length;
|
|
22289
|
+
console.log(
|
|
22290
|
+
chalk50.dim(` [${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] `) + chalk50.magenta(`Ego self-adjustment: ${adjustments.map((a) => `${a.parameter} \u2192 ${a.suggestedValue}`).join(", ")}`)
|
|
22291
|
+
);
|
|
22292
|
+
}
|
|
22293
|
+
}
|
|
22294
|
+
saveEgoTracker(egoTracker);
|
|
22032
22295
|
state.cyclesCompleted = cycleCount;
|
|
22033
22296
|
state.dpoPairsGenerated += dpoPairs.length;
|
|
22034
22297
|
state.lastCycleAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22035
|
-
|
|
22298
|
+
state.shadowPatterns = shadow.detected_patterns.length;
|
|
22299
|
+
state.egoAdjustments += adjustmentCount;
|
|
22300
|
+
saveTherapyState(state);
|
|
22036
22301
|
console.log(
|
|
22037
|
-
chalk50.dim(` [${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] `) + chalk50.green(`+${dpoPairs.length} DPO pairs`) + chalk50.dim(` (total: ${state.dpoPairsGenerated})`)
|
|
22302
|
+
chalk50.dim(` [${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] `) + chalk50.green(`+${dpoPairs.length} DPO pairs`) + chalk50.dim(` (total: ${state.dpoPairsGenerated})`) + chalk50.dim(` | shadow: ${shadow.detected_patterns.length} patterns`)
|
|
22038
22303
|
);
|
|
22039
22304
|
} catch (err) {
|
|
22040
22305
|
console.log(
|
|
@@ -22044,10 +22309,10 @@ async function miraStart(options) {
|
|
|
22044
22309
|
};
|
|
22045
22310
|
await runCycle();
|
|
22046
22311
|
const timer = setInterval(async () => {
|
|
22047
|
-
const currentState =
|
|
22312
|
+
const currentState = loadTherapyState();
|
|
22048
22313
|
if (!currentState || currentState.status === "stopped") {
|
|
22049
22314
|
clearInterval(timer);
|
|
22050
|
-
console.log(chalk50.dim("
|
|
22315
|
+
console.log(chalk50.dim(" Therapy stopped."));
|
|
22051
22316
|
return;
|
|
22052
22317
|
}
|
|
22053
22318
|
await runCycle();
|
|
@@ -22055,22 +22320,29 @@ async function miraStart(options) {
|
|
|
22055
22320
|
process.on("SIGINT", () => {
|
|
22056
22321
|
clearInterval(timer);
|
|
22057
22322
|
state.status = "stopped";
|
|
22058
|
-
|
|
22323
|
+
saveTherapyState(state);
|
|
22324
|
+
saveEgoTracker(egoTracker);
|
|
22325
|
+
saveShadowLog(shadow);
|
|
22059
22326
|
console.log();
|
|
22060
|
-
console.log(chalk50.dim("
|
|
22327
|
+
console.log(chalk50.dim(" Therapy stopped gracefully."));
|
|
22061
22328
|
console.log(chalk50.dim(` Total: ${state.dpoPairsGenerated} DPO pairs from ${state.cyclesCompleted} cycles.`));
|
|
22329
|
+
console.log(chalk50.dim(` Shadow: ${shadow.detected_patterns.length} patterns tracked.`));
|
|
22330
|
+
const stats = egoTracker.getStats();
|
|
22331
|
+
if (stats.totalDecisions > 0) {
|
|
22332
|
+
console.log(chalk50.dim(` Ego: ${stats.totalDecisions} decisions, best strategy: ${stats.mostEffectiveStrategy}`));
|
|
22333
|
+
}
|
|
22062
22334
|
console.log();
|
|
22063
22335
|
process.exit(0);
|
|
22064
22336
|
});
|
|
22065
22337
|
await new Promise(() => {
|
|
22066
22338
|
});
|
|
22067
22339
|
}
|
|
22068
|
-
function
|
|
22069
|
-
printHeader("
|
|
22070
|
-
const state =
|
|
22340
|
+
function therapyStatus() {
|
|
22341
|
+
printHeader("Therapy Status");
|
|
22342
|
+
const state = loadTherapyState();
|
|
22071
22343
|
if (!state) {
|
|
22072
|
-
console.log(chalk50.dim("
|
|
22073
|
-
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime
|
|
22344
|
+
console.log(chalk50.dim(" Therapy hasn't been started yet."));
|
|
22345
|
+
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime therapy") + chalk50.dim(" to start autonomous therapy."));
|
|
22074
22346
|
console.log();
|
|
22075
22347
|
return;
|
|
22076
22348
|
}
|
|
@@ -22092,26 +22364,51 @@ function miraStatus() {
|
|
|
22092
22364
|
const lines = readFileSync49(corpusPath, "utf-8").trim().split("\n").length;
|
|
22093
22365
|
console.log(chalk50.dim(" DPO corpus: ") + chalk50.cyan(`${lines} pairs`) + chalk50.dim(` (.holomime/dpo-corpus.jsonl)`));
|
|
22094
22366
|
}
|
|
22367
|
+
const shadow = loadShadowLog();
|
|
22368
|
+
if (shadow.detected_patterns.length > 0) {
|
|
22369
|
+
console.log();
|
|
22370
|
+
console.log(chalk50.dim(" Shadow patterns detected:"));
|
|
22371
|
+
for (const p of shadow.detected_patterns) {
|
|
22372
|
+
const trendIcon = p.trend === "improving" ? chalk50.green("\u2193") : p.trend === "worsening" ? chalk50.red("\u2191") : chalk50.dim("\u2192");
|
|
22373
|
+
const severityColor = p.severity === "critical" ? chalk50.red : p.severity === "high" ? chalk50.yellow : chalk50.dim;
|
|
22374
|
+
console.log(
|
|
22375
|
+
chalk50.dim(" ") + trendIcon + " " + severityColor(p.name) + chalk50.dim(` (${(p.score * 100).toFixed(0)}%, ${p.occurrences}x)`)
|
|
22376
|
+
);
|
|
22377
|
+
}
|
|
22378
|
+
}
|
|
22379
|
+
const egoTracker = loadEgoTracker();
|
|
22380
|
+
const egoStats = egoTracker.getStats();
|
|
22381
|
+
if (egoStats.totalDecisions > 0) {
|
|
22382
|
+
console.log();
|
|
22383
|
+
console.log(chalk50.dim(" Ego self-improvement:"));
|
|
22384
|
+
console.log(chalk50.dim(" Decisions: ") + chalk50.cyan(String(egoStats.totalDecisions)));
|
|
22385
|
+
console.log(chalk50.dim(" Positive: ") + chalk50.green(String(egoStats.positiveOutcomes)));
|
|
22386
|
+
console.log(chalk50.dim(" Negative: ") + chalk50.red(String(egoStats.negativeOutcomes)));
|
|
22387
|
+
if (egoStats.mostEffectiveStrategy !== "none") {
|
|
22388
|
+
console.log(chalk50.dim(" Best strat: ") + chalk50.cyan(egoStats.mostEffectiveStrategy));
|
|
22389
|
+
}
|
|
22390
|
+
}
|
|
22095
22391
|
console.log();
|
|
22096
22392
|
if (state.status === "practicing") {
|
|
22097
|
-
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime
|
|
22393
|
+
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime therapy stop") + chalk50.dim(" to stop therapy."));
|
|
22098
22394
|
} else {
|
|
22099
|
-
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime
|
|
22395
|
+
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime therapy") + chalk50.dim(" to start again."));
|
|
22100
22396
|
}
|
|
22101
22397
|
console.log();
|
|
22102
22398
|
}
|
|
22103
|
-
function
|
|
22104
|
-
printHeader("
|
|
22105
|
-
const state =
|
|
22399
|
+
function therapyStop() {
|
|
22400
|
+
printHeader("Therapy Stop");
|
|
22401
|
+
const state = loadTherapyState();
|
|
22106
22402
|
if (!state || state.status === "stopped") {
|
|
22107
|
-
console.log(chalk50.dim("
|
|
22403
|
+
console.log(chalk50.dim(" Therapy is not currently running."));
|
|
22108
22404
|
console.log();
|
|
22109
22405
|
return;
|
|
22110
22406
|
}
|
|
22111
22407
|
state.status = "stopped";
|
|
22112
|
-
|
|
22408
|
+
saveTherapyState(state);
|
|
22113
22409
|
console.log(chalk50.green(" Therapy stopped."));
|
|
22114
22410
|
console.log(chalk50.dim(` Total: ${state.dpoPairsGenerated} DPO pairs from ${state.cyclesCompleted} cycles.`));
|
|
22411
|
+
console.log(chalk50.dim(` Shadow: ${state.shadowPatterns} patterns tracked.`));
|
|
22115
22412
|
console.log();
|
|
22116
22413
|
try {
|
|
22117
22414
|
process.kill(state.pid, "SIGINT");
|
|
@@ -22168,7 +22465,7 @@ program.name("holomime").description("Personality engine for AI agents \u2014 Bi
|
|
|
22168
22465
|
const commandName = actionCommand.name();
|
|
22169
22466
|
showTelemetryBannerIfNeeded();
|
|
22170
22467
|
trackEvent("cli_command", { command: commandName });
|
|
22171
|
-
const skipPersonalityCheck = ["init", "init-stack", "compile-stack", "browse", "use", "install", "activate", "telemetry", "brain", "personality", "core", "identity", "config", "
|
|
22468
|
+
const skipPersonalityCheck = ["init", "init-stack", "compile-stack", "browse", "use", "install", "activate", "telemetry", "brain", "personality", "core", "identity", "config", "therapy"];
|
|
22172
22469
|
if (!skipPersonalityCheck.includes(commandName) && !checkPersonalityExists()) {
|
|
22173
22470
|
showWelcome();
|
|
22174
22471
|
process.exit(0);
|
|
@@ -22254,7 +22551,7 @@ program.command("certify").description("Generate a verifiable behavioral credent
|
|
|
22254
22551
|
options.personality = resolved.personalityPath;
|
|
22255
22552
|
await certifyCommand(options);
|
|
22256
22553
|
});
|
|
22257
|
-
program.command("daemon", { hidden: true }).description("Background relapse detection [Pro] (use 'holomime
|
|
22554
|
+
program.command("daemon", { hidden: true }).description("Background relapse detection [Pro] (use 'holomime therapy' instead)").requiredOption("--dir <path>", "Directory to watch for conversation logs").option("--personality <path>", "Path to .personality.json", ".personality.json").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--interval <ms>", "Check interval in milliseconds", "30000").option("--threshold <level>", "Drift threshold (routine, targeted, intervention)", "targeted").option("--oversight <mode>", "Oversight mode (none, review, approve, approve-specs)", "review").action(daemonCommand);
|
|
22258
22555
|
program.command("fleet").description("Monitor multiple agents from a single dashboard [Pro]").option("--config <path>", "Path to fleet.json config file").option("--dir <path>", "Auto-discover agents in directory").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--interval <ms>", "Check interval in milliseconds", "30000").option("--threshold <level>", "Drift threshold (routine, targeted, intervention)", "targeted").option("--auto-evolve", "Auto-run evolve when drift detected").action(fleetCommand);
|
|
22259
22556
|
program.command("group-therapy").alias("fleet-therapy").description("Group therapy \u2014 treat all agents in your fleet simultaneously [Pro]").option("--config <path>", "Path to fleet.json config file").option("--dir <path>", "Auto-discover agents in directory").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--turns <n>", "Max therapy turns per agent", "24").option("--concurrency <n>", "Max agents treated in parallel", "3").option("--apply", "Auto-apply recommendations to personality files").option("--yes", "Skip confirmation prompt").action(fleetTherapyCommand);
|
|
22260
22557
|
program.command("network").description("Multi-agent therapy mesh \u2014 agents treating agents [Pro]").option("--dir <path>", "Auto-discover agents in directory").option("--config <path>", "Path to network.json config file").option("--pairing <strategy>", "Pairing strategy (severity, round-robin, complementary)", "severity").option("--therapist <path>", "Custom therapist personality spec").option("--oversight <mode>", "Oversight mode (none, review, approve, approve-specs)", "review").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--max-sessions <n>", "Max sessions per agent", "3").option("--convergence <n>", "Convergence threshold 0-100", "85").option("--turns <n>", "Max turns per session", "20").option("--apply", "Write spec changes back to .personality.json").option("--export-dpo <path>", "Export DPO pairs to file").action(networkCommand);
|
|
@@ -22269,7 +22566,7 @@ program.command("cure").description("End-to-end behavioral fix \u2014 just run i
|
|
|
22269
22566
|
if (!options.model) options.model = resolved.model;
|
|
22270
22567
|
await cureCommand(options);
|
|
22271
22568
|
});
|
|
22272
|
-
program.command("
|
|
22569
|
+
program.command("therapy [action]").description("Autonomous behavioral therapy \u2014 generates DPO pairs and self-improves").option("--interval <ms>", "Practice interval in ms (default: 600000)").option("--max-cycles <n>", "Max cycles per run (default: 50)").action(async (action, options) => {
|
|
22273
22570
|
options.action = action;
|
|
22274
22571
|
await miraCommand(options);
|
|
22275
22572
|
});
|
|
@@ -22296,10 +22593,10 @@ program.addHelpText("before", `
|
|
|
22296
22593
|
cure Fix it permanently
|
|
22297
22594
|
benchmark Verify the fix
|
|
22298
22595
|
|
|
22299
|
-
|
|
22300
|
-
|
|
22301
|
-
|
|
22302
|
-
|
|
22596
|
+
THERAPY
|
|
22597
|
+
therapy Start autonomous therapy
|
|
22598
|
+
therapy status Check therapy progress
|
|
22599
|
+
therapy stop Stop therapy
|
|
22303
22600
|
|
|
22304
22601
|
ADVANCED
|
|
22305
22602
|
align Single therapy session
|