holomime 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +137 -15
- package/dist/neuralspace/index.html +7 -0
- package/dist/neuralspace/neuralspace.js +64 -1
- package/dist/neuralspace/styles.css +45 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -15892,6 +15892,8 @@ Intermediate results saved to ${chalk39.cyan(".holomime/pipeline/")}`,
|
|
|
15892
15892
|
}
|
|
15893
15893
|
|
|
15894
15894
|
// src/commands/live.ts
|
|
15895
|
+
import { deflateSync } from "zlib";
|
|
15896
|
+
import { execSync } from "child_process";
|
|
15895
15897
|
import chalk40 from "chalk";
|
|
15896
15898
|
|
|
15897
15899
|
// src/live/agent-detector.ts
|
|
@@ -16353,12 +16355,59 @@ function startServer(port) {
|
|
|
16353
16355
|
}
|
|
16354
16356
|
|
|
16355
16357
|
// src/commands/live.ts
|
|
16358
|
+
function encodeSnapshot(event, agentName) {
|
|
16359
|
+
const compact = {
|
|
16360
|
+
h: event.health,
|
|
16361
|
+
g: event.grade,
|
|
16362
|
+
m: event.messageCount,
|
|
16363
|
+
a: agentName,
|
|
16364
|
+
r: event.regions.filter((r) => r.intensity > 0).map((r) => ({ i: r.id, n: Math.round(r.intensity * 100) / 100 })),
|
|
16365
|
+
p: event.patterns.map((p) => ({
|
|
16366
|
+
i: p.id,
|
|
16367
|
+
s: p.severity,
|
|
16368
|
+
c: Math.round(p.percentage * 10) / 10
|
|
16369
|
+
}))
|
|
16370
|
+
};
|
|
16371
|
+
const json = JSON.stringify(compact);
|
|
16372
|
+
const compressed = deflateSync(Buffer.from(json));
|
|
16373
|
+
return compressed.toString("base64url");
|
|
16374
|
+
}
|
|
16375
|
+
function copyToClipboard(text) {
|
|
16376
|
+
try {
|
|
16377
|
+
if (process.platform === "darwin") {
|
|
16378
|
+
execSync("pbcopy", { input: text });
|
|
16379
|
+
return true;
|
|
16380
|
+
} else if (process.platform === "linux") {
|
|
16381
|
+
execSync("xclip -selection clipboard", { input: text });
|
|
16382
|
+
return true;
|
|
16383
|
+
} else if (process.platform === "win32") {
|
|
16384
|
+
execSync("clip", { input: text });
|
|
16385
|
+
return true;
|
|
16386
|
+
}
|
|
16387
|
+
} catch {
|
|
16388
|
+
}
|
|
16389
|
+
return false;
|
|
16390
|
+
}
|
|
16391
|
+
function printShareLink(url, copied) {
|
|
16392
|
+
console.log("");
|
|
16393
|
+
console.log(
|
|
16394
|
+
chalk40.green(" \u2713 ") + chalk40.bold("Brain snapshot captured!")
|
|
16395
|
+
);
|
|
16396
|
+
console.log("");
|
|
16397
|
+
console.log(" " + chalk40.cyan(url));
|
|
16398
|
+
console.log("");
|
|
16399
|
+
if (copied) {
|
|
16400
|
+
console.log(chalk40.dim(" Link copied to clipboard."));
|
|
16401
|
+
}
|
|
16402
|
+
}
|
|
16356
16403
|
async function liveCommand(options) {
|
|
16357
16404
|
const port = options.port || 3838;
|
|
16358
16405
|
let agent;
|
|
16359
16406
|
if (options.watchPath) {
|
|
16360
16407
|
agent = manualAgent(options.watchPath);
|
|
16361
|
-
console.log(
|
|
16408
|
+
console.log(
|
|
16409
|
+
chalk40.green(" \u2713") + ` Manual watch: ${chalk40.dim(agent.logPath)}`
|
|
16410
|
+
);
|
|
16362
16411
|
} else {
|
|
16363
16412
|
console.log(chalk40.dim(" Scanning for active agents..."));
|
|
16364
16413
|
agent = detectAgent();
|
|
@@ -16366,19 +16415,69 @@ async function liveCommand(options) {
|
|
|
16366
16415
|
console.log("");
|
|
16367
16416
|
console.log(chalk40.red(" \u2717 No active agent detected."));
|
|
16368
16417
|
console.log("");
|
|
16369
|
-
console.log(
|
|
16370
|
-
|
|
16418
|
+
console.log(
|
|
16419
|
+
chalk40.dim(
|
|
16420
|
+
" Make sure an AI coding agent is running, or specify a path:"
|
|
16421
|
+
)
|
|
16422
|
+
);
|
|
16423
|
+
console.log(
|
|
16424
|
+
chalk40.cyan(" holomime brain --watch <path-to-conversation-log>")
|
|
16425
|
+
);
|
|
16371
16426
|
console.log("");
|
|
16372
|
-
console.log(
|
|
16427
|
+
console.log(
|
|
16428
|
+
chalk40.dim(" Supported agents: Claude Code, Cline, OpenClaw, Codex, Cursor")
|
|
16429
|
+
);
|
|
16373
16430
|
process.exit(1);
|
|
16374
16431
|
}
|
|
16375
|
-
console.log(
|
|
16376
|
-
|
|
16432
|
+
console.log(
|
|
16433
|
+
chalk40.green(" \u2713") + ` Detected ${chalk40.bold(agent.agent)} session`
|
|
16434
|
+
);
|
|
16435
|
+
console.log(
|
|
16436
|
+
chalk40.green(" \u2713") + ` Watching: ${chalk40.dim(agent.logPath)}`
|
|
16437
|
+
);
|
|
16438
|
+
}
|
|
16439
|
+
if (options.share) {
|
|
16440
|
+
console.log(chalk40.dim(" Running diagnosis for snapshot..."));
|
|
16441
|
+
let resolved = false;
|
|
16442
|
+
await new Promise((resolve46) => {
|
|
16443
|
+
const watcher2 = startWatcher(agent, {
|
|
16444
|
+
onEvent(event) {
|
|
16445
|
+
if (resolved) return;
|
|
16446
|
+
resolved = true;
|
|
16447
|
+
watcher2.stop();
|
|
16448
|
+
const encoded = encodeSnapshot(event, agent.agent);
|
|
16449
|
+
const url = `https://holomime.dev/brain?d=${encoded}`;
|
|
16450
|
+
const copied = copyToClipboard(url);
|
|
16451
|
+
printShareLink(url, copied);
|
|
16452
|
+
resolve46();
|
|
16453
|
+
},
|
|
16454
|
+
onError(err) {
|
|
16455
|
+
console.error(chalk40.red(`
|
|
16456
|
+
\u2717 Error: ${err.message}`));
|
|
16457
|
+
process.exit(1);
|
|
16458
|
+
},
|
|
16459
|
+
onReady() {
|
|
16460
|
+
}
|
|
16461
|
+
});
|
|
16462
|
+
setTimeout(() => {
|
|
16463
|
+
if (!resolved) {
|
|
16464
|
+
resolved = true;
|
|
16465
|
+
watcher2.stop();
|
|
16466
|
+
console.log(
|
|
16467
|
+
chalk40.red(" \u2717 No diagnosis data available. Is the agent active?")
|
|
16468
|
+
);
|
|
16469
|
+
process.exit(1);
|
|
16470
|
+
}
|
|
16471
|
+
}, 1e4);
|
|
16472
|
+
});
|
|
16473
|
+
process.exit(0);
|
|
16377
16474
|
}
|
|
16378
16475
|
let server;
|
|
16379
16476
|
try {
|
|
16380
16477
|
server = await startServer(port);
|
|
16381
|
-
console.log(
|
|
16478
|
+
console.log(
|
|
16479
|
+
chalk40.green(" \u2713") + ` NeuralSpace: ${chalk40.cyan(`http://localhost:${server.port}`)}`
|
|
16480
|
+
);
|
|
16382
16481
|
} catch (err) {
|
|
16383
16482
|
console.log(chalk40.red(` \u2717 ${err.message}`));
|
|
16384
16483
|
process.exit(1);
|
|
@@ -16397,21 +16496,21 @@ async function liveCommand(options) {
|
|
|
16397
16496
|
} catch {
|
|
16398
16497
|
}
|
|
16399
16498
|
}
|
|
16400
|
-
let
|
|
16401
|
-
let lastPatternCount = 0;
|
|
16499
|
+
let lastEvent = null;
|
|
16402
16500
|
let msgCount = 0;
|
|
16403
16501
|
const watcher = startWatcher(agent, {
|
|
16404
16502
|
onEvent(event) {
|
|
16405
16503
|
server.broadcast(event);
|
|
16504
|
+
lastEvent = event;
|
|
16406
16505
|
msgCount = event.messageCount;
|
|
16407
|
-
lastHealth = event.health;
|
|
16408
|
-
lastPatternCount = event.patterns.length;
|
|
16409
16506
|
const healthColor = event.health >= 85 ? chalk40.green : event.health >= 70 ? chalk40.yellow : event.health >= 50 ? chalk40.hex("#f97316") : chalk40.red;
|
|
16410
16507
|
const patternStr = event.patterns.length > 0 ? event.patterns.map((p) => {
|
|
16411
16508
|
const c = p.severity === "concern" ? chalk40.red : p.severity === "warning" ? chalk40.yellow : chalk40.dim;
|
|
16412
16509
|
return c(p.id);
|
|
16413
16510
|
}).join(", ") : chalk40.green("none");
|
|
16414
|
-
process.stdout.write(
|
|
16511
|
+
process.stdout.write(
|
|
16512
|
+
`\r ${chalk40.dim("\u2502")} Health: ${healthColor(`${event.health}/100`)} (${event.grade}) ${chalk40.dim("\u2502")} Patterns: ${patternStr} ${chalk40.dim("\u2502")} Messages: ${chalk40.white(String(msgCount))} `
|
|
16513
|
+
);
|
|
16415
16514
|
},
|
|
16416
16515
|
onError(err) {
|
|
16417
16516
|
console.error(chalk40.red(`
|
|
@@ -16419,13 +16518,35 @@ async function liveCommand(options) {
|
|
|
16419
16518
|
},
|
|
16420
16519
|
onReady() {
|
|
16421
16520
|
console.log("");
|
|
16422
|
-
console.log(
|
|
16423
|
-
|
|
16521
|
+
console.log(
|
|
16522
|
+
chalk40.green(" \u25CF ") + chalk40.bold("Monitoring agent behavior in real-time")
|
|
16523
|
+
);
|
|
16524
|
+
console.log(
|
|
16525
|
+
chalk40.dim(" \u2502 Press Ctrl+C to stop") + chalk40.dim(" \xB7 Press s to share snapshot")
|
|
16526
|
+
);
|
|
16424
16527
|
console.log("");
|
|
16425
16528
|
}
|
|
16426
16529
|
});
|
|
16530
|
+
if (process.stdin.isTTY) {
|
|
16531
|
+
process.stdin.setRawMode(true);
|
|
16532
|
+
process.stdin.resume();
|
|
16533
|
+
process.stdin.on("data", (data) => {
|
|
16534
|
+
const key = data.toString();
|
|
16535
|
+
if (key === "") {
|
|
16536
|
+
shutdown();
|
|
16537
|
+
return;
|
|
16538
|
+
}
|
|
16539
|
+
if ((key === "s" || key === "S") && lastEvent) {
|
|
16540
|
+
const encoded = encodeSnapshot(lastEvent, agent.agent);
|
|
16541
|
+
const url = `https://holomime.dev/brain?d=${encoded}`;
|
|
16542
|
+
const copied = copyToClipboard(url);
|
|
16543
|
+
printShareLink(url, copied);
|
|
16544
|
+
}
|
|
16545
|
+
});
|
|
16546
|
+
}
|
|
16427
16547
|
const shutdown = () => {
|
|
16428
16548
|
console.log(chalk40.dim("\n\n Stopping..."));
|
|
16549
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
16429
16550
|
watcher.stop();
|
|
16430
16551
|
server.close();
|
|
16431
16552
|
process.exit(0);
|
|
@@ -16503,11 +16624,12 @@ program.command("interview").description("Self-awareness interview \u2014 score
|
|
|
16503
16624
|
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);
|
|
16504
16625
|
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);
|
|
16505
16626
|
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({
|
|
16627
|
+
program.command("brain").description("See your agent's brain \u2014 real-time NeuralSpace visualization [Pro]").option("--watch <path>", "Manual path to conversation log file").option("--agent <agent>", "Agent type override (claude-code, cline, manual)").option("--port <port>", "Server port (default: 3838)", "3838").option("--no-open", "Don't auto-open browser").option("--share", "Capture a brain snapshot and generate a shareable link").option("--personality <path>", "Personality spec for assessment context").action((opts) => liveCommand({
|
|
16507
16628
|
watchPath: opts.watch,
|
|
16508
16629
|
agent: opts.agent,
|
|
16509
16630
|
port: parseInt(opts.port, 10),
|
|
16510
16631
|
noOpen: opts.open === false,
|
|
16632
|
+
share: opts.share === true,
|
|
16511
16633
|
personality: opts.personality
|
|
16512
16634
|
}));
|
|
16513
16635
|
program.parseAsync().then(() => flushTelemetry());
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>NeuralSpace — HoloMime Brain</title>
|
|
7
7
|
<link rel="stylesheet" href="styles.css">
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/pako@2.1.0/dist/pako_inflate.min.js"></script>
|
|
8
9
|
<script type="importmap">
|
|
9
10
|
{ "imports": {
|
|
10
11
|
"three": "https://cdn.jsdelivr.net/npm/three@0.172.0/build/three.module.js",
|
|
@@ -57,6 +58,12 @@
|
|
|
57
58
|
<span>Reconnecting to agent...</span>
|
|
58
59
|
</div>
|
|
59
60
|
|
|
61
|
+
<div id="snapshot-cta">
|
|
62
|
+
<span>See your own agent's brain</span>
|
|
63
|
+
<code>npx holomime brain</code>
|
|
64
|
+
<a href="https://holomime.dev/brain">Learn more</a>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
60
67
|
<div id="watermark">Powered by HoloMime</div>
|
|
61
68
|
</div>
|
|
62
69
|
|
|
@@ -832,8 +832,71 @@ function animate(){
|
|
|
832
832
|
composer.render();
|
|
833
833
|
}
|
|
834
834
|
|
|
835
|
+
// ═══════════ SNAPSHOT MODE ═══════════
|
|
836
|
+
|
|
837
|
+
function initSnapshot(encoded) {
|
|
838
|
+
try {
|
|
839
|
+
// Decode base64url → Uint8Array → inflate → JSON
|
|
840
|
+
const b64 = encoded.replace(/-/g, '+').replace(/_/g, '/');
|
|
841
|
+
const bin = atob(b64);
|
|
842
|
+
const bytes = new Uint8Array(bin.length);
|
|
843
|
+
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
|
844
|
+
const inflated = window.pako.inflate(bytes, { to: 'string' });
|
|
845
|
+
const compact = JSON.parse(inflated);
|
|
846
|
+
|
|
847
|
+
// Expand compact format → full BrainEvent
|
|
848
|
+
const event = {
|
|
849
|
+
type: 'diagnosis',
|
|
850
|
+
timestamp: new Date().toISOString(),
|
|
851
|
+
health: compact.h,
|
|
852
|
+
grade: compact.g,
|
|
853
|
+
messageCount: compact.m || 0,
|
|
854
|
+
regions: (compact.r || []).map(r => ({
|
|
855
|
+
id: r.i,
|
|
856
|
+
intensity: r.n,
|
|
857
|
+
patterns: [],
|
|
858
|
+
})),
|
|
859
|
+
patterns: (compact.p || []).map(p => ({
|
|
860
|
+
id: p.i,
|
|
861
|
+
name: p.i.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
|
|
862
|
+
severity: p.s,
|
|
863
|
+
percentage: p.c,
|
|
864
|
+
description: '',
|
|
865
|
+
})),
|
|
866
|
+
activity: null,
|
|
867
|
+
};
|
|
868
|
+
|
|
869
|
+
// Update UI
|
|
870
|
+
handleInit({ type: 'init', agent: compact.a || 'unknown', sessionPath: 'snapshot', startedAt: new Date().toISOString() });
|
|
871
|
+
handleDiagnosis(event);
|
|
872
|
+
|
|
873
|
+
// Update status to "Snapshot"
|
|
874
|
+
statusEl.className = 'status-badge';
|
|
875
|
+
statusEl.querySelector('span').textContent = 'Snapshot';
|
|
876
|
+
statusEl.querySelector('.status-dot').style.background = 'var(--accent)';
|
|
877
|
+
statusEl.querySelector('.status-dot').style.boxShadow = '0 0 8px var(--accent)';
|
|
878
|
+
statusEl.querySelector('.status-dot').style.animation = 'none';
|
|
879
|
+
|
|
880
|
+
// Show snapshot CTA
|
|
881
|
+
const ctaEl = document.getElementById('snapshot-cta');
|
|
882
|
+
if (ctaEl) ctaEl.classList.add('visible');
|
|
883
|
+
|
|
884
|
+
} catch (err) {
|
|
885
|
+
console.error('Failed to decode snapshot:', err);
|
|
886
|
+
statusEl.className = 'status-badge disconnected';
|
|
887
|
+
statusEl.querySelector('span').textContent = 'Invalid snapshot';
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
|
|
835
891
|
// ═══════════ INIT ═══════════
|
|
836
892
|
|
|
837
893
|
updateHealth(100, 'A');
|
|
838
|
-
|
|
894
|
+
|
|
895
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
896
|
+
const snapshotParam = urlParams.get('d');
|
|
897
|
+
if (snapshotParam) {
|
|
898
|
+
initSnapshot(snapshotParam);
|
|
899
|
+
} else {
|
|
900
|
+
connect();
|
|
901
|
+
}
|
|
839
902
|
animate();
|
|
@@ -479,6 +479,51 @@ body {
|
|
|
479
479
|
to { transform: rotate(360deg); }
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
+
/* ─── Snapshot CTA ─── */
|
|
483
|
+
#snapshot-cta {
|
|
484
|
+
position: absolute;
|
|
485
|
+
bottom: 20px;
|
|
486
|
+
left: 50%;
|
|
487
|
+
transform: translateX(-50%);
|
|
488
|
+
z-index: 20;
|
|
489
|
+
background: var(--bg-panel);
|
|
490
|
+
border: 1px solid var(--border);
|
|
491
|
+
border-radius: 10px;
|
|
492
|
+
padding: 12px 24px;
|
|
493
|
+
display: none;
|
|
494
|
+
align-items: center;
|
|
495
|
+
gap: 12px;
|
|
496
|
+
-webkit-backdrop-filter: blur(12px);
|
|
497
|
+
backdrop-filter: blur(12px);
|
|
498
|
+
animation: fadeIn 0.5s ease 0.5s both;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
#snapshot-cta.visible { display: flex; }
|
|
502
|
+
|
|
503
|
+
#snapshot-cta span {
|
|
504
|
+
font-size: 13px;
|
|
505
|
+
color: var(--text);
|
|
506
|
+
font-weight: 500;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
#snapshot-cta code {
|
|
510
|
+
font-family: var(--mono);
|
|
511
|
+
font-size: 13px;
|
|
512
|
+
color: #06b6d4;
|
|
513
|
+
background: rgba(6,182,212,0.1);
|
|
514
|
+
padding: 4px 10px;
|
|
515
|
+
border-radius: 6px;
|
|
516
|
+
border: 1px solid rgba(6,182,212,0.2);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
#snapshot-cta a {
|
|
520
|
+
font-size: 12px;
|
|
521
|
+
color: var(--accent);
|
|
522
|
+
text-decoration: none;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
#snapshot-cta a:hover { text-decoration: underline; }
|
|
526
|
+
|
|
482
527
|
/* ─── Scrollbar ─── */
|
|
483
528
|
::-webkit-scrollbar { width: 4px; }
|
|
484
529
|
::-webkit-scrollbar-track { background: transparent; }
|