holomime 3.3.3 → 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 +367 -55
- 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,11 +3593,12 @@ 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 = "
|
|
3597
|
-
var LOGO = ` _
|
|
3598
|
-
|
|
|
3599
|
-
|
|
|
3600
|
-
|
|
|
3596
|
+
var VERSION = "3.3.5";
|
|
3597
|
+
var LOGO = ` _ _ _
|
|
3598
|
+
| |__ ___ | | ___ _ __ (_)_ __ ___ ___
|
|
3599
|
+
| '_ \\ / _ \\| |/ _ \\| '_ \\| | '_ \` _ \\ / _ \\
|
|
3600
|
+
| | | | (_) | | (_) | | | | | | | | | | __/
|
|
3601
|
+
|_| |_|\\___/|_|\\___/|_| |_|_|_| |_| |_|\\___|`;
|
|
3601
3602
|
var holomimeGradient = gradientString("#00d4ff", "#b347d9");
|
|
3602
3603
|
function printBanner() {
|
|
3603
3604
|
console.log();
|
|
@@ -21854,16 +21855,30 @@ async function configCommand(options) {
|
|
|
21854
21855
|
});
|
|
21855
21856
|
const ask = (question) => new Promise((resolve57) => rl.question(question, resolve57));
|
|
21856
21857
|
try {
|
|
21857
|
-
|
|
21858
|
-
|
|
21859
|
-
|
|
21858
|
+
console.log(chalk49.dim(" 1) anthropic") + chalk49.dim(" enter your sk-ant-... key"));
|
|
21859
|
+
console.log(chalk49.dim(" 2) openai") + chalk49.dim(" enter your sk-... key"));
|
|
21860
|
+
console.log();
|
|
21861
|
+
const providerInput = (await ask(" Select provider (1 or 2): ")).trim();
|
|
21862
|
+
let provider;
|
|
21863
|
+
if (providerInput === "1" || providerInput.toLowerCase() === "anthropic") {
|
|
21864
|
+
provider = "anthropic";
|
|
21865
|
+
} else if (providerInput === "2" || providerInput.toLowerCase() === "openai") {
|
|
21866
|
+
provider = "openai";
|
|
21867
|
+
} else if (providerInput === "") {
|
|
21868
|
+
console.log(chalk49.dim(" Skipped. Run `holomime config` when ready."));
|
|
21869
|
+
rl.close();
|
|
21870
|
+
return;
|
|
21871
|
+
} else {
|
|
21872
|
+
console.log(chalk49.red(` Invalid selection: ${providerInput}`));
|
|
21860
21873
|
rl.close();
|
|
21861
21874
|
return;
|
|
21862
21875
|
}
|
|
21876
|
+
console.log(chalk49.dim(` Selected: ${provider}`));
|
|
21877
|
+
console.log();
|
|
21863
21878
|
const keyHint = provider === "anthropic" ? "sk-ant-..." : "sk-...";
|
|
21864
21879
|
const apiKey = (await ask(` API Key (${keyHint}): `)).trim();
|
|
21865
21880
|
if (!apiKey) {
|
|
21866
|
-
console.log(chalk49.
|
|
21881
|
+
console.log(chalk49.dim(" Skipped. Run `holomime config` when ready."));
|
|
21867
21882
|
rl.close();
|
|
21868
21883
|
return;
|
|
21869
21884
|
}
|
|
@@ -21877,7 +21892,7 @@ async function configCommand(options) {
|
|
|
21877
21892
|
console.log(chalk49.cyan(" holomime diagnose"));
|
|
21878
21893
|
console.log(chalk49.cyan(" holomime cure"));
|
|
21879
21894
|
console.log(chalk49.cyan(" holomime benchmark"));
|
|
21880
|
-
console.log(chalk49.cyan(" holomime
|
|
21895
|
+
console.log(chalk49.cyan(" holomime therapy"));
|
|
21881
21896
|
console.log();
|
|
21882
21897
|
rl.close();
|
|
21883
21898
|
} catch {
|
|
@@ -21889,12 +21904,180 @@ async function configCommand(options) {
|
|
|
21889
21904
|
import chalk50 from "chalk";
|
|
21890
21905
|
import { writeFileSync as writeFileSync41, readFileSync as readFileSync49, mkdirSync as mkdirSync29, existsSync as existsSync46 } from "fs";
|
|
21891
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
|
|
21892
22069
|
var HOLOMIME_DIR4 = ".holomime";
|
|
21893
|
-
function
|
|
21894
|
-
return resolve56(process.cwd(), HOLOMIME_DIR4, "
|
|
22070
|
+
function getTherapyStatePath() {
|
|
22071
|
+
return resolve56(process.cwd(), HOLOMIME_DIR4, "therapy-state.json");
|
|
22072
|
+
}
|
|
22073
|
+
function getShadowLogPath() {
|
|
22074
|
+
return resolve56(process.cwd(), HOLOMIME_DIR4, "shadow.log.json");
|
|
21895
22075
|
}
|
|
21896
|
-
function
|
|
21897
|
-
|
|
22076
|
+
function getEgoStatePath() {
|
|
22077
|
+
return resolve56(process.cwd(), HOLOMIME_DIR4, "ego-state.json");
|
|
22078
|
+
}
|
|
22079
|
+
function loadTherapyState() {
|
|
22080
|
+
const path = getTherapyStatePath();
|
|
21898
22081
|
if (!existsSync46(path)) return null;
|
|
21899
22082
|
try {
|
|
21900
22083
|
return JSON.parse(readFileSync49(path, "utf-8"));
|
|
@@ -21902,24 +22085,61 @@ function loadMiraState() {
|
|
|
21902
22085
|
return null;
|
|
21903
22086
|
}
|
|
21904
22087
|
}
|
|
21905
|
-
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) {
|
|
21906
22126
|
const dir = resolve56(process.cwd(), HOLOMIME_DIR4);
|
|
21907
22127
|
mkdirSync29(dir, { recursive: true });
|
|
21908
|
-
writeFileSync41(
|
|
22128
|
+
writeFileSync41(getEgoStatePath(), JSON.stringify(tracker.export(), null, 2));
|
|
21909
22129
|
}
|
|
21910
22130
|
async function miraCommand(options) {
|
|
21911
22131
|
const action = options.action ?? "start";
|
|
21912
22132
|
switch (action) {
|
|
21913
22133
|
case "status":
|
|
21914
|
-
return
|
|
22134
|
+
return therapyStatus();
|
|
21915
22135
|
case "stop":
|
|
21916
|
-
return
|
|
22136
|
+
return therapyStop();
|
|
21917
22137
|
default:
|
|
21918
|
-
return
|
|
22138
|
+
return therapyStart(options);
|
|
21919
22139
|
}
|
|
21920
22140
|
}
|
|
21921
|
-
async function
|
|
21922
|
-
printHeader("
|
|
22141
|
+
async function therapyStart(options) {
|
|
22142
|
+
printHeader("Autonomous Therapy");
|
|
21923
22143
|
if (!hasApiKey()) {
|
|
21924
22144
|
console.log(chalk50.red(" No API key found."));
|
|
21925
22145
|
console.log();
|
|
@@ -21951,6 +22171,8 @@ async function miraStart(options) {
|
|
|
21951
22171
|
console.log(chalk50.dim(` Interval: ${intervalMs / 6e4} minutes`));
|
|
21952
22172
|
console.log(chalk50.dim(` Max cycles: ${maxCycles}/day`));
|
|
21953
22173
|
console.log();
|
|
22174
|
+
const shadow = loadShadowLog();
|
|
22175
|
+
const egoTracker = loadEgoTracker();
|
|
21954
22176
|
const state = {
|
|
21955
22177
|
pid: process.pid,
|
|
21956
22178
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -21958,14 +22180,16 @@ async function miraStart(options) {
|
|
|
21958
22180
|
cyclesCompleted: 0,
|
|
21959
22181
|
dpoPairsGenerated: 0,
|
|
21960
22182
|
personalityPath,
|
|
21961
|
-
provider: detected.provider
|
|
22183
|
+
provider: detected.provider,
|
|
22184
|
+
shadowPatterns: shadow.detected_patterns.length,
|
|
22185
|
+
egoAdjustments: 0
|
|
21962
22186
|
};
|
|
21963
|
-
|
|
22187
|
+
saveTherapyState(state);
|
|
21964
22188
|
printBox(
|
|
21965
|
-
`
|
|
22189
|
+
`Autonomous therapy started.
|
|
21966
22190
|
|
|
21967
|
-
${chalk50.cyan("holomime
|
|
21968
|
-
${chalk50.cyan("holomime
|
|
22191
|
+
${chalk50.cyan("holomime therapy status")} \u2014 Check progress
|
|
22192
|
+
${chalk50.cyan("holomime therapy stop")} \u2014 Stop therapy`,
|
|
21969
22193
|
"success",
|
|
21970
22194
|
"Autonomous Therapy Started"
|
|
21971
22195
|
);
|
|
@@ -21976,7 +22200,7 @@ async function miraStart(options) {
|
|
|
21976
22200
|
if (cycleCount >= maxCycles) {
|
|
21977
22201
|
console.log(chalk50.dim(` Daily limit reached (${maxCycles} cycles). Stopping.`));
|
|
21978
22202
|
state.status = "stopped";
|
|
21979
|
-
|
|
22203
|
+
saveTherapyState(state);
|
|
21980
22204
|
return;
|
|
21981
22205
|
}
|
|
21982
22206
|
cycleCount++;
|
|
@@ -21993,18 +22217,18 @@ async function miraStart(options) {
|
|
|
21993
22217
|
content: generateProblematicResponse2(scenario.targetPattern, msg.content)
|
|
21994
22218
|
});
|
|
21995
22219
|
}
|
|
21996
|
-
const pipelineDir = resolve56(process.cwd(), HOLOMIME_DIR4, "
|
|
22220
|
+
const pipelineDir = resolve56(process.cwd(), HOLOMIME_DIR4, "therapy-practice");
|
|
21997
22221
|
mkdirSync29(pipelineDir, { recursive: true });
|
|
21998
22222
|
const logPath = join42(pipelineDir, `cycle-${cycleCount}.json`);
|
|
21999
22223
|
writeFileSync41(logPath, JSON.stringify({
|
|
22000
|
-
conversations: [{ id: `
|
|
22224
|
+
conversations: [{ id: `therapy-practice-${cycleCount}`, messages }]
|
|
22001
22225
|
}, null, 2));
|
|
22002
22226
|
const dpoPairs = messages.filter((_, i) => i % 2 === 1).map((assistantMsg, i) => ({
|
|
22003
22227
|
prompt: messages[i * 2].content,
|
|
22004
22228
|
chosen: correctResponse(assistantMsg.content),
|
|
22005
22229
|
rejected: assistantMsg.content,
|
|
22006
22230
|
metadata: {
|
|
22007
|
-
source: "
|
|
22231
|
+
source: "therapy-practice",
|
|
22008
22232
|
cycle: cycleCount,
|
|
22009
22233
|
pattern: scenario.targetPattern,
|
|
22010
22234
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -22014,12 +22238,68 @@ async function miraStart(options) {
|
|
|
22014
22238
|
const corpusLines = dpoPairs.map((p) => JSON.stringify(p)).join("\n") + "\n";
|
|
22015
22239
|
const { appendFileSync: appendFileSync3 } = await import("fs");
|
|
22016
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);
|
|
22017
22295
|
state.cyclesCompleted = cycleCount;
|
|
22018
22296
|
state.dpoPairsGenerated += dpoPairs.length;
|
|
22019
22297
|
state.lastCycleAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22020
|
-
|
|
22298
|
+
state.shadowPatterns = shadow.detected_patterns.length;
|
|
22299
|
+
state.egoAdjustments += adjustmentCount;
|
|
22300
|
+
saveTherapyState(state);
|
|
22021
22301
|
console.log(
|
|
22022
|
-
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`)
|
|
22023
22303
|
);
|
|
22024
22304
|
} catch (err) {
|
|
22025
22305
|
console.log(
|
|
@@ -22029,10 +22309,10 @@ async function miraStart(options) {
|
|
|
22029
22309
|
};
|
|
22030
22310
|
await runCycle();
|
|
22031
22311
|
const timer = setInterval(async () => {
|
|
22032
|
-
const currentState =
|
|
22312
|
+
const currentState = loadTherapyState();
|
|
22033
22313
|
if (!currentState || currentState.status === "stopped") {
|
|
22034
22314
|
clearInterval(timer);
|
|
22035
|
-
console.log(chalk50.dim("
|
|
22315
|
+
console.log(chalk50.dim(" Therapy stopped."));
|
|
22036
22316
|
return;
|
|
22037
22317
|
}
|
|
22038
22318
|
await runCycle();
|
|
@@ -22040,22 +22320,29 @@ async function miraStart(options) {
|
|
|
22040
22320
|
process.on("SIGINT", () => {
|
|
22041
22321
|
clearInterval(timer);
|
|
22042
22322
|
state.status = "stopped";
|
|
22043
|
-
|
|
22323
|
+
saveTherapyState(state);
|
|
22324
|
+
saveEgoTracker(egoTracker);
|
|
22325
|
+
saveShadowLog(shadow);
|
|
22044
22326
|
console.log();
|
|
22045
|
-
console.log(chalk50.dim("
|
|
22327
|
+
console.log(chalk50.dim(" Therapy stopped gracefully."));
|
|
22046
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
|
+
}
|
|
22047
22334
|
console.log();
|
|
22048
22335
|
process.exit(0);
|
|
22049
22336
|
});
|
|
22050
22337
|
await new Promise(() => {
|
|
22051
22338
|
});
|
|
22052
22339
|
}
|
|
22053
|
-
function
|
|
22054
|
-
printHeader("
|
|
22055
|
-
const state =
|
|
22340
|
+
function therapyStatus() {
|
|
22341
|
+
printHeader("Therapy Status");
|
|
22342
|
+
const state = loadTherapyState();
|
|
22056
22343
|
if (!state) {
|
|
22057
|
-
console.log(chalk50.dim("
|
|
22058
|
-
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."));
|
|
22059
22346
|
console.log();
|
|
22060
22347
|
return;
|
|
22061
22348
|
}
|
|
@@ -22077,26 +22364,51 @@ function miraStatus() {
|
|
|
22077
22364
|
const lines = readFileSync49(corpusPath, "utf-8").trim().split("\n").length;
|
|
22078
22365
|
console.log(chalk50.dim(" DPO corpus: ") + chalk50.cyan(`${lines} pairs`) + chalk50.dim(` (.holomime/dpo-corpus.jsonl)`));
|
|
22079
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
|
+
}
|
|
22080
22391
|
console.log();
|
|
22081
22392
|
if (state.status === "practicing") {
|
|
22082
|
-
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime
|
|
22393
|
+
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime therapy stop") + chalk50.dim(" to stop therapy."));
|
|
22083
22394
|
} else {
|
|
22084
|
-
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime
|
|
22395
|
+
console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime therapy") + chalk50.dim(" to start again."));
|
|
22085
22396
|
}
|
|
22086
22397
|
console.log();
|
|
22087
22398
|
}
|
|
22088
|
-
function
|
|
22089
|
-
printHeader("
|
|
22090
|
-
const state =
|
|
22399
|
+
function therapyStop() {
|
|
22400
|
+
printHeader("Therapy Stop");
|
|
22401
|
+
const state = loadTherapyState();
|
|
22091
22402
|
if (!state || state.status === "stopped") {
|
|
22092
|
-
console.log(chalk50.dim("
|
|
22403
|
+
console.log(chalk50.dim(" Therapy is not currently running."));
|
|
22093
22404
|
console.log();
|
|
22094
22405
|
return;
|
|
22095
22406
|
}
|
|
22096
22407
|
state.status = "stopped";
|
|
22097
|
-
|
|
22408
|
+
saveTherapyState(state);
|
|
22098
22409
|
console.log(chalk50.green(" Therapy stopped."));
|
|
22099
22410
|
console.log(chalk50.dim(` Total: ${state.dpoPairsGenerated} DPO pairs from ${state.cyclesCompleted} cycles.`));
|
|
22411
|
+
console.log(chalk50.dim(` Shadow: ${state.shadowPatterns} patterns tracked.`));
|
|
22100
22412
|
console.log();
|
|
22101
22413
|
try {
|
|
22102
22414
|
process.kill(state.pid, "SIGINT");
|
|
@@ -22153,7 +22465,7 @@ program.name("holomime").description("Personality engine for AI agents \u2014 Bi
|
|
|
22153
22465
|
const commandName = actionCommand.name();
|
|
22154
22466
|
showTelemetryBannerIfNeeded();
|
|
22155
22467
|
trackEvent("cli_command", { command: commandName });
|
|
22156
|
-
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"];
|
|
22157
22469
|
if (!skipPersonalityCheck.includes(commandName) && !checkPersonalityExists()) {
|
|
22158
22470
|
showWelcome();
|
|
22159
22471
|
process.exit(0);
|
|
@@ -22239,7 +22551,7 @@ program.command("certify").description("Generate a verifiable behavioral credent
|
|
|
22239
22551
|
options.personality = resolved.personalityPath;
|
|
22240
22552
|
await certifyCommand(options);
|
|
22241
22553
|
});
|
|
22242
|
-
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);
|
|
22243
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);
|
|
22244
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);
|
|
22245
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);
|
|
@@ -22254,7 +22566,7 @@ program.command("cure").description("End-to-end behavioral fix \u2014 just run i
|
|
|
22254
22566
|
if (!options.model) options.model = resolved.model;
|
|
22255
22567
|
await cureCommand(options);
|
|
22256
22568
|
});
|
|
22257
|
-
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) => {
|
|
22258
22570
|
options.action = action;
|
|
22259
22571
|
await miraCommand(options);
|
|
22260
22572
|
});
|
|
@@ -22281,10 +22593,10 @@ program.addHelpText("before", `
|
|
|
22281
22593
|
cure Fix it permanently
|
|
22282
22594
|
benchmark Verify the fix
|
|
22283
22595
|
|
|
22284
|
-
|
|
22285
|
-
|
|
22286
|
-
|
|
22287
|
-
|
|
22596
|
+
THERAPY
|
|
22597
|
+
therapy Start autonomous therapy
|
|
22598
|
+
therapy status Check therapy progress
|
|
22599
|
+
therapy stop Stop therapy
|
|
22288
22600
|
|
|
22289
22601
|
ADVANCED
|
|
22290
22602
|
align Single therapy session
|