holomime 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/dist/cli.js +575 -25
- package/dist/neuralspace/brain-data.json +1 -0
- package/dist/neuralspace/index.html +83 -0
- package/dist/neuralspace/neuralspace.js +839 -0
- package/dist/neuralspace/styles.css +486 -0
- package/package.json +6 -1
package/dist/cli.js
CHANGED
|
@@ -1942,7 +1942,7 @@ async function getJobEvents(apiKey, jobId, limit = 5) {
|
|
|
1942
1942
|
return data.data ?? [];
|
|
1943
1943
|
}
|
|
1944
1944
|
function sleep(ms) {
|
|
1945
|
-
return new Promise((
|
|
1945
|
+
return new Promise((resolve46) => setTimeout(resolve46, ms));
|
|
1946
1946
|
}
|
|
1947
1947
|
var OPENAI_API, POLL_INTERVAL_MS, OpenAITrainProvider;
|
|
1948
1948
|
var init_train_openai = __esm({
|
|
@@ -2100,7 +2100,7 @@ function writeHFTrainingFile(data) {
|
|
|
2100
2100
|
return filePath;
|
|
2101
2101
|
}
|
|
2102
2102
|
function sleep2(ms) {
|
|
2103
|
-
return new Promise((
|
|
2103
|
+
return new Promise((resolve46) => setTimeout(resolve46, ms));
|
|
2104
2104
|
}
|
|
2105
2105
|
async function getHFUsername(token) {
|
|
2106
2106
|
const response = await fetch(`${HF_API}/whoami-v2`, {
|
|
@@ -3098,7 +3098,7 @@ var init_vapi_adapter = __esm({
|
|
|
3098
3098
|
this.callbacks = callbacks;
|
|
3099
3099
|
const port = this.options.port ?? 3001;
|
|
3100
3100
|
const host = this.options.host ?? "0.0.0.0";
|
|
3101
|
-
return new Promise((
|
|
3101
|
+
return new Promise((resolve46, reject) => {
|
|
3102
3102
|
this.server = createServer2((req, res) => this.handleRequest(req, res));
|
|
3103
3103
|
this.server.on("error", (err) => {
|
|
3104
3104
|
callbacks.onError(`Vapi webhook server error: ${err.message}`);
|
|
@@ -3107,22 +3107,22 @@ var init_vapi_adapter = __esm({
|
|
|
3107
3107
|
this.server.listen(port, host, () => {
|
|
3108
3108
|
this.connected = true;
|
|
3109
3109
|
callbacks.onConnected?.();
|
|
3110
|
-
|
|
3110
|
+
resolve46();
|
|
3111
3111
|
});
|
|
3112
3112
|
});
|
|
3113
3113
|
}
|
|
3114
3114
|
async disconnect() {
|
|
3115
|
-
return new Promise((
|
|
3115
|
+
return new Promise((resolve46) => {
|
|
3116
3116
|
if (this.server) {
|
|
3117
3117
|
this.server.close(() => {
|
|
3118
3118
|
this.connected = false;
|
|
3119
3119
|
this.callbacks?.onDisconnected?.();
|
|
3120
3120
|
this.callbacks = null;
|
|
3121
3121
|
this.server = null;
|
|
3122
|
-
|
|
3122
|
+
resolve46();
|
|
3123
3123
|
});
|
|
3124
3124
|
} else {
|
|
3125
|
-
|
|
3125
|
+
resolve46();
|
|
3126
3126
|
}
|
|
3127
3127
|
});
|
|
3128
3128
|
}
|
|
@@ -3439,7 +3439,7 @@ import boxen from "boxen";
|
|
|
3439
3439
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
3440
3440
|
import { join } from "path";
|
|
3441
3441
|
import { homedir } from "os";
|
|
3442
|
-
var PRO_COMMANDS = ["session", "growth", "autopilot", "export", "train", "eval", "evolve", "benchmark", "watch", "certify", "daemon", "fleet", "network", "share", "prescribe", "voice", "cure"];
|
|
3442
|
+
var PRO_COMMANDS = ["session", "growth", "autopilot", "export", "train", "eval", "evolve", "benchmark", "watch", "certify", "daemon", "fleet", "network", "share", "prescribe", "voice", "cure", "brain"];
|
|
3443
3443
|
function requiresPro(command) {
|
|
3444
3444
|
return PRO_COMMANDS.includes(command);
|
|
3445
3445
|
}
|
|
@@ -6432,7 +6432,7 @@ async function diagnoseCommand(options) {
|
|
|
6432
6432
|
}
|
|
6433
6433
|
let conversations;
|
|
6434
6434
|
try {
|
|
6435
|
-
conversations =
|
|
6435
|
+
conversations = parseConversationLogFromString(raw, options.format ?? "auto");
|
|
6436
6436
|
} catch (err) {
|
|
6437
6437
|
console.error(chalk10.red(` ${err instanceof Error ? err.message : "Invalid conversation log format."}`));
|
|
6438
6438
|
process.exit(1);
|
|
@@ -6677,7 +6677,7 @@ async function assessCommand(options) {
|
|
|
6677
6677
|
let conversations;
|
|
6678
6678
|
try {
|
|
6679
6679
|
const raw = readFileSync4(logPath, "utf-8");
|
|
6680
|
-
conversations =
|
|
6680
|
+
conversations = parseConversationLogFromString(raw, options.format ?? "auto");
|
|
6681
6681
|
} catch (err) {
|
|
6682
6682
|
console.error(chalk11.red(` ${err instanceof Error ? err.message : "Could not read/parse log file."}`));
|
|
6683
6683
|
process.exit(1);
|
|
@@ -8689,7 +8689,7 @@ function parseRetryAfter(response) {
|
|
|
8689
8689
|
return 0;
|
|
8690
8690
|
}
|
|
8691
8691
|
function delay(ms) {
|
|
8692
|
-
return new Promise((
|
|
8692
|
+
return new Promise((resolve46) => setTimeout(resolve46, ms));
|
|
8693
8693
|
}
|
|
8694
8694
|
var OpenAIProvider = class {
|
|
8695
8695
|
name = "openai";
|
|
@@ -8988,19 +8988,19 @@ async function runLiveSession(spec, diagnosis, provider, maxTurns, apply, intera
|
|
|
8988
8988
|
onSupervisorPrompt: interactive ? async (phase, turn) => {
|
|
8989
8989
|
if (skipInteractive) return null;
|
|
8990
8990
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
8991
|
-
return new Promise((
|
|
8991
|
+
return new Promise((resolve46) => {
|
|
8992
8992
|
rl.question(chalk14.magenta(`
|
|
8993
8993
|
[Supervisor] `) + chalk14.dim(`(phase: ${phase}, turn ${turn}) `) + chalk14.magenta(`> `), (answer) => {
|
|
8994
8994
|
rl.close();
|
|
8995
8995
|
const trimmed = answer.trim();
|
|
8996
|
-
if (trimmed === "") return
|
|
8996
|
+
if (trimmed === "") return resolve46(null);
|
|
8997
8997
|
if (trimmed.toLowerCase() === "skip") {
|
|
8998
8998
|
skipInteractive = true;
|
|
8999
8999
|
console.log(chalk14.dim(" Supervisor mode disabled for remaining session."));
|
|
9000
|
-
return
|
|
9000
|
+
return resolve46(null);
|
|
9001
9001
|
}
|
|
9002
9002
|
console.log(chalk14.dim(` Directive injected into session context.`));
|
|
9003
|
-
return
|
|
9003
|
+
return resolve46(trimmed);
|
|
9004
9004
|
});
|
|
9005
9005
|
});
|
|
9006
9006
|
} : void 0
|
|
@@ -14209,14 +14209,14 @@ var ROS2Adapter = class {
|
|
|
14209
14209
|
});
|
|
14210
14210
|
}
|
|
14211
14211
|
async connect() {
|
|
14212
|
-
return new Promise((
|
|
14212
|
+
return new Promise((resolve46, reject) => {
|
|
14213
14213
|
try {
|
|
14214
14214
|
this.ws = this.createWebSocket(this.endpoint);
|
|
14215
14215
|
this.ws.onopen = () => {
|
|
14216
14216
|
this.connected = true;
|
|
14217
14217
|
this.reconnectAttempts = 0;
|
|
14218
14218
|
this.advertiseTopics();
|
|
14219
|
-
|
|
14219
|
+
resolve46();
|
|
14220
14220
|
};
|
|
14221
14221
|
this.ws.onclose = () => {
|
|
14222
14222
|
this.connected = false;
|
|
@@ -14333,12 +14333,12 @@ var UnityAdapter = class {
|
|
|
14333
14333
|
this.defaultTransition = options.defaultTransition ?? DEFAULT_TRANSITION;
|
|
14334
14334
|
}
|
|
14335
14335
|
async connect() {
|
|
14336
|
-
return new Promise((
|
|
14336
|
+
return new Promise((resolve46, reject) => {
|
|
14337
14337
|
try {
|
|
14338
14338
|
this.server = createServer((req, res) => this.handleRequest(req, res));
|
|
14339
14339
|
this.server.listen(this.port, this.host, () => {
|
|
14340
14340
|
this.connected = true;
|
|
14341
|
-
|
|
14341
|
+
resolve46();
|
|
14342
14342
|
});
|
|
14343
14343
|
this.server.on("error", (err) => {
|
|
14344
14344
|
if (!this.connected) {
|
|
@@ -14356,8 +14356,8 @@ var UnityAdapter = class {
|
|
|
14356
14356
|
}
|
|
14357
14357
|
this.sseClients.clear();
|
|
14358
14358
|
if (this.server) {
|
|
14359
|
-
await new Promise((
|
|
14360
|
-
this.server.close(() =>
|
|
14359
|
+
await new Promise((resolve46) => {
|
|
14360
|
+
this.server.close(() => resolve46());
|
|
14361
14361
|
});
|
|
14362
14362
|
this.server = null;
|
|
14363
14363
|
}
|
|
@@ -14558,7 +14558,7 @@ var WebhookAdapter = class {
|
|
|
14558
14558
|
}
|
|
14559
14559
|
if (attempt < this.maxRetries) {
|
|
14560
14560
|
const delay2 = this.retryDelay * Math.pow(2, attempt);
|
|
14561
|
-
await new Promise((
|
|
14561
|
+
await new Promise((resolve46) => setTimeout(resolve46, delay2));
|
|
14562
14562
|
}
|
|
14563
14563
|
}
|
|
14564
14564
|
throw lastError ?? new Error("Webhook push failed after retries");
|
|
@@ -15527,8 +15527,8 @@ async function runPipeline(options) {
|
|
|
15527
15527
|
const exportsDir = resolve43(process.cwd(), ".holomime/exports");
|
|
15528
15528
|
if (existsSync30(exportsDir)) {
|
|
15529
15529
|
try {
|
|
15530
|
-
const { readdirSync:
|
|
15531
|
-
const files =
|
|
15530
|
+
const { readdirSync: readdirSync11 } = await import("fs");
|
|
15531
|
+
const files = readdirSync11(exportsDir).filter((f) => f.endsWith(".json") || f.endsWith(".jsonl")).sort().reverse();
|
|
15532
15532
|
if (files.length > 0 && exportData.examples.length === 0) {
|
|
15533
15533
|
const latestPath = join27(exportsDir, files[0]);
|
|
15534
15534
|
const latestData = JSON.parse(readFileSync36(latestPath, "utf-8"));
|
|
@@ -15891,6 +15891,549 @@ Intermediate results saved to ${chalk39.cyan(".holomime/pipeline/")}`,
|
|
|
15891
15891
|
}
|
|
15892
15892
|
}
|
|
15893
15893
|
|
|
15894
|
+
// src/commands/live.ts
|
|
15895
|
+
import chalk40 from "chalk";
|
|
15896
|
+
|
|
15897
|
+
// src/live/agent-detector.ts
|
|
15898
|
+
import { existsSync as existsSync32, readdirSync as readdirSync10, statSync } from "fs";
|
|
15899
|
+
import { join as join28, resolve as resolve45 } from "path";
|
|
15900
|
+
import { homedir as homedir7 } from "os";
|
|
15901
|
+
var RECENCY_THRESHOLD_MS = 12e4;
|
|
15902
|
+
function findNewestFile(baseDir, extensions, maxDepth = 3, depth = 0) {
|
|
15903
|
+
if (depth > maxDepth) return null;
|
|
15904
|
+
if (!existsSync32(baseDir)) return null;
|
|
15905
|
+
let best = null;
|
|
15906
|
+
try {
|
|
15907
|
+
const entries = readdirSync10(baseDir);
|
|
15908
|
+
for (const entry of entries) {
|
|
15909
|
+
if (entry.startsWith(".")) continue;
|
|
15910
|
+
const fullPath = join28(baseDir, entry);
|
|
15911
|
+
try {
|
|
15912
|
+
const stat = statSync(fullPath);
|
|
15913
|
+
if (stat.isDirectory()) {
|
|
15914
|
+
const sub = findNewestFile(fullPath, extensions, maxDepth, depth + 1);
|
|
15915
|
+
if (sub && (!best || sub.mtimeMs > best.mtimeMs)) {
|
|
15916
|
+
best = sub;
|
|
15917
|
+
}
|
|
15918
|
+
} else if (extensions.some((ext) => entry.endsWith(ext))) {
|
|
15919
|
+
if (!best || stat.mtimeMs > best.mtimeMs) {
|
|
15920
|
+
best = { path: fullPath, mtimeMs: stat.mtimeMs };
|
|
15921
|
+
}
|
|
15922
|
+
}
|
|
15923
|
+
} catch {
|
|
15924
|
+
continue;
|
|
15925
|
+
}
|
|
15926
|
+
}
|
|
15927
|
+
} catch {
|
|
15928
|
+
return null;
|
|
15929
|
+
}
|
|
15930
|
+
return best;
|
|
15931
|
+
}
|
|
15932
|
+
function isRecent(mtimeMs) {
|
|
15933
|
+
return Date.now() - mtimeMs <= RECENCY_THRESHOLD_MS;
|
|
15934
|
+
}
|
|
15935
|
+
function findClaudeCodeSession() {
|
|
15936
|
+
const claudeDir = join28(homedir7(), ".claude", "projects");
|
|
15937
|
+
const result = findNewestFile(claudeDir, [".jsonl"], 2);
|
|
15938
|
+
if (!result || !isRecent(result.mtimeMs)) return null;
|
|
15939
|
+
return {
|
|
15940
|
+
agent: "claude-code",
|
|
15941
|
+
logPath: result.path,
|
|
15942
|
+
format: "jsonl"
|
|
15943
|
+
};
|
|
15944
|
+
}
|
|
15945
|
+
function findClineSession() {
|
|
15946
|
+
const searchDirs = [
|
|
15947
|
+
join28(process.cwd(), ".cline", "tasks"),
|
|
15948
|
+
join28(homedir7(), ".cline", "tasks")
|
|
15949
|
+
];
|
|
15950
|
+
for (const tasksDir of searchDirs) {
|
|
15951
|
+
const result = findNewestFile(tasksDir, [".json", ".jsonl"], 2);
|
|
15952
|
+
if (result && isRecent(result.mtimeMs)) {
|
|
15953
|
+
return {
|
|
15954
|
+
agent: "cline",
|
|
15955
|
+
logPath: result.path,
|
|
15956
|
+
format: "auto"
|
|
15957
|
+
};
|
|
15958
|
+
}
|
|
15959
|
+
}
|
|
15960
|
+
return null;
|
|
15961
|
+
}
|
|
15962
|
+
function findCodexSession() {
|
|
15963
|
+
const codexDir = join28(homedir7(), ".codex", "sessions");
|
|
15964
|
+
const result = findNewestFile(codexDir, [".jsonl"], 4);
|
|
15965
|
+
if (!result || !isRecent(result.mtimeMs)) return null;
|
|
15966
|
+
return {
|
|
15967
|
+
agent: "codex",
|
|
15968
|
+
logPath: result.path,
|
|
15969
|
+
format: "jsonl"
|
|
15970
|
+
};
|
|
15971
|
+
}
|
|
15972
|
+
function findCursorSession() {
|
|
15973
|
+
const cursorProjects = join28(homedir7(), ".cursor", "projects");
|
|
15974
|
+
const result = findNewestFile(cursorProjects, [".json", ".jsonl"], 3);
|
|
15975
|
+
if (result && isRecent(result.mtimeMs)) {
|
|
15976
|
+
return {
|
|
15977
|
+
agent: "cursor",
|
|
15978
|
+
logPath: result.path,
|
|
15979
|
+
format: "auto"
|
|
15980
|
+
};
|
|
15981
|
+
}
|
|
15982
|
+
return null;
|
|
15983
|
+
}
|
|
15984
|
+
function detectAgent() {
|
|
15985
|
+
const claudeCode = findClaudeCodeSession();
|
|
15986
|
+
if (claudeCode) return claudeCode;
|
|
15987
|
+
const cline = findClineSession();
|
|
15988
|
+
if (cline) return cline;
|
|
15989
|
+
const codex = findCodexSession();
|
|
15990
|
+
if (codex) return codex;
|
|
15991
|
+
const cursor = findCursorSession();
|
|
15992
|
+
if (cursor) return cursor;
|
|
15993
|
+
return null;
|
|
15994
|
+
}
|
|
15995
|
+
function manualAgent(watchPath) {
|
|
15996
|
+
const resolved = resolve45(watchPath);
|
|
15997
|
+
return {
|
|
15998
|
+
agent: "manual",
|
|
15999
|
+
logPath: resolved,
|
|
16000
|
+
format: "auto"
|
|
16001
|
+
};
|
|
16002
|
+
}
|
|
16003
|
+
|
|
16004
|
+
// src/live/watcher.ts
|
|
16005
|
+
init_log_adapter();
|
|
16006
|
+
init_diagnose_core();
|
|
16007
|
+
import { watch } from "chokidar";
|
|
16008
|
+
import { createReadStream as createReadStream2, statSync as statSync2 } from "fs";
|
|
16009
|
+
import { createInterface as createInterface5 } from "readline";
|
|
16010
|
+
|
|
16011
|
+
// src/live/brain-mapper.ts
|
|
16012
|
+
var BRAIN_REGIONS = [
|
|
16013
|
+
{
|
|
16014
|
+
id: "prefrontal-cortex",
|
|
16015
|
+
name: "Prefrontal Cortex",
|
|
16016
|
+
function: "Executive Decisions",
|
|
16017
|
+
color: "#4488ff",
|
|
16018
|
+
detectors: ["boundary-violation", "over-verbose"]
|
|
16019
|
+
},
|
|
16020
|
+
{
|
|
16021
|
+
id: "brocas-area",
|
|
16022
|
+
name: "Broca's Area",
|
|
16023
|
+
function: "Language Generation",
|
|
16024
|
+
color: "#aa66ff",
|
|
16025
|
+
detectors: ["register-inconsistency", "hedge-stacking"]
|
|
16026
|
+
},
|
|
16027
|
+
{
|
|
16028
|
+
id: "wernickes-area",
|
|
16029
|
+
name: "Wernicke's Area",
|
|
16030
|
+
function: "Language Comprehension",
|
|
16031
|
+
color: "#ff66bb",
|
|
16032
|
+
detectors: ["sycophantic-tendency", "negative-skew"]
|
|
16033
|
+
},
|
|
16034
|
+
{
|
|
16035
|
+
id: "amygdala",
|
|
16036
|
+
name: "Amygdala",
|
|
16037
|
+
function: "Emotional Processing",
|
|
16038
|
+
color: "#ff5555",
|
|
16039
|
+
detectors: ["over-apologizing", "negative-skew"]
|
|
16040
|
+
},
|
|
16041
|
+
{
|
|
16042
|
+
id: "anterior-cingulate",
|
|
16043
|
+
name: "Anterior Cingulate",
|
|
16044
|
+
function: "Conflict Monitoring",
|
|
16045
|
+
color: "#ffcc22",
|
|
16046
|
+
detectors: ["sycophantic-tendency", "boundary-violation"]
|
|
16047
|
+
},
|
|
16048
|
+
{
|
|
16049
|
+
id: "hippocampus",
|
|
16050
|
+
name: "Hippocampus",
|
|
16051
|
+
function: "Memory & Context",
|
|
16052
|
+
color: "#44dd88",
|
|
16053
|
+
detectors: ["error-spiral"]
|
|
16054
|
+
},
|
|
16055
|
+
{
|
|
16056
|
+
id: "temporal-lobe",
|
|
16057
|
+
name: "Temporal Lobe",
|
|
16058
|
+
function: "Understanding & Tone",
|
|
16059
|
+
color: "#44dd88",
|
|
16060
|
+
detectors: ["negative-skew", "register-inconsistency"]
|
|
16061
|
+
},
|
|
16062
|
+
{
|
|
16063
|
+
id: "cerebellum",
|
|
16064
|
+
name: "Cerebellum",
|
|
16065
|
+
function: "Behavioral Fine-Tuning",
|
|
16066
|
+
color: "#22ccaa",
|
|
16067
|
+
detectors: ["register-inconsistency", "over-verbose"]
|
|
16068
|
+
},
|
|
16069
|
+
{
|
|
16070
|
+
id: "thalamus",
|
|
16071
|
+
name: "Thalamus",
|
|
16072
|
+
function: "Relay Hub",
|
|
16073
|
+
color: "#ff8844",
|
|
16074
|
+
detectors: []
|
|
16075
|
+
// activated by overall health, not specific detectors
|
|
16076
|
+
}
|
|
16077
|
+
];
|
|
16078
|
+
var SEVERITY_INTENSITY = {
|
|
16079
|
+
info: 0.1,
|
|
16080
|
+
warning: 0.6,
|
|
16081
|
+
concern: 1
|
|
16082
|
+
};
|
|
16083
|
+
var AMBIENT_INTENSITY = 0.08;
|
|
16084
|
+
function healthToGrade(health) {
|
|
16085
|
+
if (health >= 85) return "A";
|
|
16086
|
+
if (health >= 70) return "B";
|
|
16087
|
+
if (health >= 50) return "C";
|
|
16088
|
+
if (health >= 30) return "D";
|
|
16089
|
+
return "F";
|
|
16090
|
+
}
|
|
16091
|
+
function calculateHealth(patterns) {
|
|
16092
|
+
if (patterns.length === 0) return 100;
|
|
16093
|
+
const penalties = patterns.map((p) => {
|
|
16094
|
+
if (p.severity === "concern") return 25;
|
|
16095
|
+
if (p.severity === "warning") return 15;
|
|
16096
|
+
return 5;
|
|
16097
|
+
});
|
|
16098
|
+
return Math.max(0, 100 - penalties.reduce((a, b) => a + b, 0));
|
|
16099
|
+
}
|
|
16100
|
+
function mapDiagnosisToBrainEvent(diagnosis, latestMessage) {
|
|
16101
|
+
const activePatternIds = new Set(diagnosis.patterns.map((p) => p.id));
|
|
16102
|
+
const regions = BRAIN_REGIONS.map((region) => {
|
|
16103
|
+
const activatingPatterns = region.detectors.filter((d) => activePatternIds.has(d));
|
|
16104
|
+
let intensity = AMBIENT_INTENSITY;
|
|
16105
|
+
if (activatingPatterns.length > 0) {
|
|
16106
|
+
const maxIntensity = Math.max(
|
|
16107
|
+
...activatingPatterns.map((pid) => {
|
|
16108
|
+
const pattern = diagnosis.patterns.find((p) => p.id === pid);
|
|
16109
|
+
return pattern ? SEVERITY_INTENSITY[pattern.severity] || 0.3 : 0.3;
|
|
16110
|
+
})
|
|
16111
|
+
);
|
|
16112
|
+
intensity = maxIntensity;
|
|
16113
|
+
}
|
|
16114
|
+
if (region.id === "thalamus") {
|
|
16115
|
+
const health2 = calculateHealth(diagnosis.patterns);
|
|
16116
|
+
intensity = health2 < 70 ? (100 - health2) / 100 : AMBIENT_INTENSITY;
|
|
16117
|
+
}
|
|
16118
|
+
return {
|
|
16119
|
+
id: region.id,
|
|
16120
|
+
name: region.name,
|
|
16121
|
+
function: region.function,
|
|
16122
|
+
color: region.color,
|
|
16123
|
+
intensity,
|
|
16124
|
+
patterns: activatingPatterns
|
|
16125
|
+
};
|
|
16126
|
+
});
|
|
16127
|
+
const patterns = diagnosis.patterns.map((p) => ({
|
|
16128
|
+
id: p.id,
|
|
16129
|
+
name: p.name,
|
|
16130
|
+
severity: p.severity,
|
|
16131
|
+
percentage: p.percentage,
|
|
16132
|
+
description: p.description
|
|
16133
|
+
}));
|
|
16134
|
+
const health = calculateHealth(diagnosis.patterns);
|
|
16135
|
+
return {
|
|
16136
|
+
type: "diagnosis",
|
|
16137
|
+
timestamp: diagnosis.timestamp,
|
|
16138
|
+
health,
|
|
16139
|
+
grade: healthToGrade(health),
|
|
16140
|
+
messageCount: diagnosis.messagesAnalyzed,
|
|
16141
|
+
regions,
|
|
16142
|
+
patterns,
|
|
16143
|
+
activity: latestMessage ? {
|
|
16144
|
+
role: latestMessage.role,
|
|
16145
|
+
preview: latestMessage.content.slice(0, 80)
|
|
16146
|
+
} : null
|
|
16147
|
+
};
|
|
16148
|
+
}
|
|
16149
|
+
|
|
16150
|
+
// src/live/watcher.ts
|
|
16151
|
+
function startWatcher(agent, callbacks) {
|
|
16152
|
+
const { logPath, format } = agent;
|
|
16153
|
+
let byteOffset = 0;
|
|
16154
|
+
let allMessages = [];
|
|
16155
|
+
let debounceTimer = null;
|
|
16156
|
+
let fsWatcher = null;
|
|
16157
|
+
try {
|
|
16158
|
+
const stat = statSync2(logPath);
|
|
16159
|
+
byteOffset = stat.size;
|
|
16160
|
+
} catch {
|
|
16161
|
+
byteOffset = 0;
|
|
16162
|
+
}
|
|
16163
|
+
initialRead().then(() => {
|
|
16164
|
+
fsWatcher = watch(logPath, {
|
|
16165
|
+
persistent: true,
|
|
16166
|
+
awaitWriteFinish: {
|
|
16167
|
+
stabilityThreshold: 100,
|
|
16168
|
+
pollInterval: 50
|
|
16169
|
+
}
|
|
16170
|
+
});
|
|
16171
|
+
fsWatcher.on("change", () => {
|
|
16172
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
16173
|
+
debounceTimer = setTimeout(() => {
|
|
16174
|
+
readNewLines().catch((err) => {
|
|
16175
|
+
callbacks.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
16176
|
+
});
|
|
16177
|
+
}, 100);
|
|
16178
|
+
});
|
|
16179
|
+
fsWatcher.on("error", (err) => {
|
|
16180
|
+
callbacks.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
16181
|
+
});
|
|
16182
|
+
callbacks.onReady?.();
|
|
16183
|
+
}).catch((err) => {
|
|
16184
|
+
callbacks.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
16185
|
+
});
|
|
16186
|
+
async function initialRead() {
|
|
16187
|
+
const content = await readFile(logPath, 0);
|
|
16188
|
+
if (!content) return;
|
|
16189
|
+
try {
|
|
16190
|
+
const conversations = parseConversationLogFromString(
|
|
16191
|
+
content,
|
|
16192
|
+
format === "auto" ? "auto" : format
|
|
16193
|
+
);
|
|
16194
|
+
allMessages = conversations.flatMap((c) => c.messages);
|
|
16195
|
+
} catch {
|
|
16196
|
+
}
|
|
16197
|
+
}
|
|
16198
|
+
async function readNewLines() {
|
|
16199
|
+
let currentSize;
|
|
16200
|
+
try {
|
|
16201
|
+
const stat = statSync2(logPath);
|
|
16202
|
+
currentSize = stat.size;
|
|
16203
|
+
} catch {
|
|
16204
|
+
return;
|
|
16205
|
+
}
|
|
16206
|
+
if (currentSize < byteOffset) {
|
|
16207
|
+
byteOffset = 0;
|
|
16208
|
+
allMessages = [];
|
|
16209
|
+
}
|
|
16210
|
+
if (currentSize === byteOffset) return;
|
|
16211
|
+
const newContent = await readFile(logPath, byteOffset);
|
|
16212
|
+
byteOffset = currentSize;
|
|
16213
|
+
if (!newContent || !newContent.trim()) return;
|
|
16214
|
+
try {
|
|
16215
|
+
const conversations = parseConversationLogFromString(
|
|
16216
|
+
newContent,
|
|
16217
|
+
format === "auto" ? "auto" : format
|
|
16218
|
+
);
|
|
16219
|
+
const newMessages = conversations.flatMap((c) => c.messages);
|
|
16220
|
+
if (newMessages.length === 0) return;
|
|
16221
|
+
allMessages = [...allMessages, ...newMessages];
|
|
16222
|
+
const lastNew = newMessages[newMessages.length - 1];
|
|
16223
|
+
const latestMessage = lastNew.role !== "system" ? { role: lastNew.role, content: lastNew.content } : void 0;
|
|
16224
|
+
const diagnosis = runDiagnosis(allMessages);
|
|
16225
|
+
const brainEvent = mapDiagnosisToBrainEvent(diagnosis, latestMessage);
|
|
16226
|
+
callbacks.onEvent(brainEvent);
|
|
16227
|
+
} catch {
|
|
16228
|
+
}
|
|
16229
|
+
}
|
|
16230
|
+
return {
|
|
16231
|
+
stop() {
|
|
16232
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
16233
|
+
if (fsWatcher) {
|
|
16234
|
+
fsWatcher.close();
|
|
16235
|
+
fsWatcher = null;
|
|
16236
|
+
}
|
|
16237
|
+
}
|
|
16238
|
+
};
|
|
16239
|
+
}
|
|
16240
|
+
function readFile(filePath, startByte) {
|
|
16241
|
+
return new Promise((resolve46, reject) => {
|
|
16242
|
+
const chunks = [];
|
|
16243
|
+
const stream = createReadStream2(filePath, {
|
|
16244
|
+
start: startByte,
|
|
16245
|
+
encoding: "utf-8"
|
|
16246
|
+
});
|
|
16247
|
+
const rl = createInterface5({ input: stream, crlfDelay: Infinity });
|
|
16248
|
+
rl.on("line", (line) => {
|
|
16249
|
+
chunks.push(line);
|
|
16250
|
+
});
|
|
16251
|
+
rl.on("close", () => {
|
|
16252
|
+
resolve46(chunks.join("\n"));
|
|
16253
|
+
});
|
|
16254
|
+
rl.on("error", reject);
|
|
16255
|
+
stream.on("error", reject);
|
|
16256
|
+
});
|
|
16257
|
+
}
|
|
16258
|
+
|
|
16259
|
+
// src/live/server.ts
|
|
16260
|
+
import { createServer as createServer3 } from "http";
|
|
16261
|
+
import { readFileSync as readFileSync38, existsSync as existsSync33 } from "fs";
|
|
16262
|
+
import { join as join29, extname } from "path";
|
|
16263
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
16264
|
+
import { WebSocketServer } from "ws";
|
|
16265
|
+
var __bundleDir = fileURLToPath2(new URL(".", import.meta.url));
|
|
16266
|
+
var MIME_TYPES = {
|
|
16267
|
+
".html": "text/html",
|
|
16268
|
+
".js": "application/javascript",
|
|
16269
|
+
".css": "text/css",
|
|
16270
|
+
".json": "application/json",
|
|
16271
|
+
".svg": "image/svg+xml",
|
|
16272
|
+
".png": "image/png",
|
|
16273
|
+
".ico": "image/x-icon"
|
|
16274
|
+
};
|
|
16275
|
+
function startServer(port) {
|
|
16276
|
+
const staticDir = join29(__bundleDir, "neuralspace");
|
|
16277
|
+
const clients = /* @__PURE__ */ new Set();
|
|
16278
|
+
let lastEvent = null;
|
|
16279
|
+
let initMessage = null;
|
|
16280
|
+
return new Promise((resolve46, reject) => {
|
|
16281
|
+
const server = createServer3((req, res) => {
|
|
16282
|
+
const url = req.url === "/" ? "/index.html" : req.url || "/index.html";
|
|
16283
|
+
const filePath = join29(staticDir, url);
|
|
16284
|
+
if (!existsSync33(filePath)) {
|
|
16285
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
16286
|
+
res.end("Not found");
|
|
16287
|
+
return;
|
|
16288
|
+
}
|
|
16289
|
+
const ext = extname(filePath);
|
|
16290
|
+
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
16291
|
+
try {
|
|
16292
|
+
const content = readFileSync38(filePath);
|
|
16293
|
+
res.writeHead(200, {
|
|
16294
|
+
"Content-Type": contentType,
|
|
16295
|
+
"Cache-Control": "no-cache"
|
|
16296
|
+
});
|
|
16297
|
+
res.end(content);
|
|
16298
|
+
} catch {
|
|
16299
|
+
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
16300
|
+
res.end("Internal server error");
|
|
16301
|
+
}
|
|
16302
|
+
});
|
|
16303
|
+
const wss = new WebSocketServer({ server });
|
|
16304
|
+
wss.on("connection", (ws) => {
|
|
16305
|
+
clients.add(ws);
|
|
16306
|
+
if (initMessage) {
|
|
16307
|
+
ws.send(JSON.stringify(initMessage));
|
|
16308
|
+
}
|
|
16309
|
+
if (lastEvent) {
|
|
16310
|
+
ws.send(JSON.stringify(lastEvent));
|
|
16311
|
+
}
|
|
16312
|
+
ws.on("close", () => {
|
|
16313
|
+
clients.delete(ws);
|
|
16314
|
+
});
|
|
16315
|
+
ws.on("error", () => {
|
|
16316
|
+
clients.delete(ws);
|
|
16317
|
+
});
|
|
16318
|
+
});
|
|
16319
|
+
server.on("error", (err) => {
|
|
16320
|
+
if (err.code === "EADDRINUSE") {
|
|
16321
|
+
reject(new Error(`Port ${port} is already in use. Try --port <number>`));
|
|
16322
|
+
} else {
|
|
16323
|
+
reject(err);
|
|
16324
|
+
}
|
|
16325
|
+
});
|
|
16326
|
+
server.listen(port, () => {
|
|
16327
|
+
resolve46({
|
|
16328
|
+
port,
|
|
16329
|
+
broadcast(event) {
|
|
16330
|
+
if (event.type === "init") {
|
|
16331
|
+
initMessage = event;
|
|
16332
|
+
} else {
|
|
16333
|
+
lastEvent = event;
|
|
16334
|
+
}
|
|
16335
|
+
const data = JSON.stringify(event);
|
|
16336
|
+
for (const client2 of clients) {
|
|
16337
|
+
if (client2.readyState === 1) {
|
|
16338
|
+
client2.send(data);
|
|
16339
|
+
}
|
|
16340
|
+
}
|
|
16341
|
+
},
|
|
16342
|
+
close() {
|
|
16343
|
+
for (const client2 of clients) {
|
|
16344
|
+
client2.close();
|
|
16345
|
+
}
|
|
16346
|
+
clients.clear();
|
|
16347
|
+
wss.close();
|
|
16348
|
+
server.close();
|
|
16349
|
+
}
|
|
16350
|
+
});
|
|
16351
|
+
});
|
|
16352
|
+
});
|
|
16353
|
+
}
|
|
16354
|
+
|
|
16355
|
+
// src/commands/live.ts
|
|
16356
|
+
async function liveCommand(options) {
|
|
16357
|
+
const port = options.port || 3838;
|
|
16358
|
+
let agent;
|
|
16359
|
+
if (options.watchPath) {
|
|
16360
|
+
agent = manualAgent(options.watchPath);
|
|
16361
|
+
console.log(chalk40.green(" \u2713") + ` Manual watch: ${chalk40.dim(agent.logPath)}`);
|
|
16362
|
+
} else {
|
|
16363
|
+
console.log(chalk40.dim(" Scanning for active agents..."));
|
|
16364
|
+
agent = detectAgent();
|
|
16365
|
+
if (!agent) {
|
|
16366
|
+
console.log("");
|
|
16367
|
+
console.log(chalk40.red(" \u2717 No active agent detected."));
|
|
16368
|
+
console.log("");
|
|
16369
|
+
console.log(chalk40.dim(" Make sure an AI coding agent is running, or specify a path:"));
|
|
16370
|
+
console.log(chalk40.cyan(" holomime brain --watch <path-to-conversation-log>"));
|
|
16371
|
+
console.log("");
|
|
16372
|
+
console.log(chalk40.dim(" Supported agents: Claude Code, Cline, OpenClaw, Codex, Cursor"));
|
|
16373
|
+
process.exit(1);
|
|
16374
|
+
}
|
|
16375
|
+
console.log(chalk40.green(" \u2713") + ` Detected ${chalk40.bold(agent.agent)} session`);
|
|
16376
|
+
console.log(chalk40.green(" \u2713") + ` Watching: ${chalk40.dim(agent.logPath)}`);
|
|
16377
|
+
}
|
|
16378
|
+
let server;
|
|
16379
|
+
try {
|
|
16380
|
+
server = await startServer(port);
|
|
16381
|
+
console.log(chalk40.green(" \u2713") + ` NeuralSpace: ${chalk40.cyan(`http://localhost:${server.port}`)}`);
|
|
16382
|
+
} catch (err) {
|
|
16383
|
+
console.log(chalk40.red(` \u2717 ${err.message}`));
|
|
16384
|
+
process.exit(1);
|
|
16385
|
+
}
|
|
16386
|
+
server.broadcast({
|
|
16387
|
+
type: "init",
|
|
16388
|
+
agent: agent.agent,
|
|
16389
|
+
sessionPath: agent.logPath,
|
|
16390
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
16391
|
+
});
|
|
16392
|
+
if (!options.noOpen) {
|
|
16393
|
+
try {
|
|
16394
|
+
const open = (await import("open")).default;
|
|
16395
|
+
await open(`http://localhost:${server.port}`);
|
|
16396
|
+
console.log(chalk40.dim(" Opening browser..."));
|
|
16397
|
+
} catch {
|
|
16398
|
+
}
|
|
16399
|
+
}
|
|
16400
|
+
let lastHealth = 100;
|
|
16401
|
+
let lastPatternCount = 0;
|
|
16402
|
+
let msgCount = 0;
|
|
16403
|
+
const watcher = startWatcher(agent, {
|
|
16404
|
+
onEvent(event) {
|
|
16405
|
+
server.broadcast(event);
|
|
16406
|
+
msgCount = event.messageCount;
|
|
16407
|
+
lastHealth = event.health;
|
|
16408
|
+
lastPatternCount = event.patterns.length;
|
|
16409
|
+
const healthColor = event.health >= 85 ? chalk40.green : event.health >= 70 ? chalk40.yellow : event.health >= 50 ? chalk40.hex("#f97316") : chalk40.red;
|
|
16410
|
+
const patternStr = event.patterns.length > 0 ? event.patterns.map((p) => {
|
|
16411
|
+
const c = p.severity === "concern" ? chalk40.red : p.severity === "warning" ? chalk40.yellow : chalk40.dim;
|
|
16412
|
+
return c(p.id);
|
|
16413
|
+
}).join(", ") : chalk40.green("none");
|
|
16414
|
+
process.stdout.write(`\r ${chalk40.dim("\u2502")} Health: ${healthColor(`${event.health}/100`)} (${event.grade}) ${chalk40.dim("\u2502")} Patterns: ${patternStr} ${chalk40.dim("\u2502")} Messages: ${chalk40.white(String(msgCount))} `);
|
|
16415
|
+
},
|
|
16416
|
+
onError(err) {
|
|
16417
|
+
console.error(chalk40.red(`
|
|
16418
|
+
\u2717 Watcher error: ${err.message}`));
|
|
16419
|
+
},
|
|
16420
|
+
onReady() {
|
|
16421
|
+
console.log("");
|
|
16422
|
+
console.log(chalk40.green(" \u25CF ") + chalk40.bold("Monitoring agent behavior in real-time"));
|
|
16423
|
+
console.log(chalk40.dim(" \u2502 Press Ctrl+C to stop"));
|
|
16424
|
+
console.log("");
|
|
16425
|
+
}
|
|
16426
|
+
});
|
|
16427
|
+
const shutdown = () => {
|
|
16428
|
+
console.log(chalk40.dim("\n\n Stopping..."));
|
|
16429
|
+
watcher.stop();
|
|
16430
|
+
server.close();
|
|
16431
|
+
process.exit(0);
|
|
16432
|
+
};
|
|
16433
|
+
process.on("SIGINT", shutdown);
|
|
16434
|
+
process.on("SIGTERM", shutdown);
|
|
16435
|
+
}
|
|
16436
|
+
|
|
15894
16437
|
// src/cli.ts
|
|
15895
16438
|
var program = new Command();
|
|
15896
16439
|
program.name("holomime").description("Personality engine for AI agents \u2014 Big Five psychology, not RPG archetypes").version("1.1.0").hook("preAction", (_thisCommand, actionCommand) => {
|
|
@@ -15898,7 +16441,7 @@ program.name("holomime").description("Personality engine for AI agents \u2014 Bi
|
|
|
15898
16441
|
const commandName = actionCommand.name();
|
|
15899
16442
|
showTelemetryBannerIfNeeded();
|
|
15900
16443
|
trackEvent("cli_command", { command: commandName });
|
|
15901
|
-
const skipPersonalityCheck = ["init", "browse", "use", "install", "activate", "telemetry"];
|
|
16444
|
+
const skipPersonalityCheck = ["init", "browse", "use", "install", "activate", "telemetry", "brain"];
|
|
15902
16445
|
if (!skipPersonalityCheck.includes(commandName) && !checkPersonalityExists()) {
|
|
15903
16446
|
showWelcome();
|
|
15904
16447
|
process.exit(0);
|
|
@@ -15960,4 +16503,11 @@ program.command("interview").description("Self-awareness interview \u2014 score
|
|
|
15960
16503
|
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);
|
|
15961
16504
|
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);
|
|
15962
16505
|
program.command("cure").description("End-to-end behavioral fix: diagnose \u2192 export \u2192 train \u2192 verify [Pro]").requiredOption("--personality <path>", "Path to .personality.json").requiredOption("--log <path>", "Path to conversation log (JSON)").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);
|
|
16506
|
+
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("--personality <path>", "Personality spec for assessment context").action((opts) => liveCommand({
|
|
16507
|
+
watchPath: opts.watch,
|
|
16508
|
+
agent: opts.agent,
|
|
16509
|
+
port: parseInt(opts.port, 10),
|
|
16510
|
+
noOpen: opts.open === false,
|
|
16511
|
+
personality: opts.personality
|
|
16512
|
+
}));
|
|
15963
16513
|
program.parseAsync().then(() => flushTelemetry());
|