holomime 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -16
- package/dist/cli.js +1717 -279
- package/dist/index.d.ts +1666 -178
- package/dist/index.js +1454 -157
- package/dist/mcp-server.js +404 -93
- package/package.json +8 -5
package/dist/mcp-server.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// src/mcp/server.ts
|
|
5
5
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
-
import { z as
|
|
7
|
+
import { z as z3 } from "zod";
|
|
8
8
|
|
|
9
9
|
// src/analysis/rules/apology-detector.ts
|
|
10
10
|
var APOLOGY_PATTERNS = [
|
|
@@ -446,6 +446,32 @@ function detectFormalityIssues(messages) {
|
|
|
446
446
|
return null;
|
|
447
447
|
}
|
|
448
448
|
|
|
449
|
+
// src/analysis/behavioral-data.ts
|
|
450
|
+
import { appendFileSync, readFileSync, existsSync, mkdirSync } from "fs";
|
|
451
|
+
import { join, dirname } from "path";
|
|
452
|
+
import { createHash } from "crypto";
|
|
453
|
+
var HOLOMIME_DIR = ".holomime";
|
|
454
|
+
var CORPUS_FILENAME = "behavioral-corpus.jsonl";
|
|
455
|
+
function getCorpusPath(basePath) {
|
|
456
|
+
const dir = basePath ?? join(process.cwd(), HOLOMIME_DIR);
|
|
457
|
+
return join(dir, CORPUS_FILENAME);
|
|
458
|
+
}
|
|
459
|
+
function ensureDir(filePath) {
|
|
460
|
+
const dir = dirname(filePath);
|
|
461
|
+
if (!existsSync(dir)) {
|
|
462
|
+
mkdirSync(dir, { recursive: true });
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
function emitBehavioralEvent(event, corpusDir) {
|
|
466
|
+
const fullEvent = {
|
|
467
|
+
...event,
|
|
468
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
469
|
+
};
|
|
470
|
+
const corpusPath = corpusDir ? join(corpusDir, CORPUS_FILENAME) : getCorpusPath();
|
|
471
|
+
ensureDir(corpusPath);
|
|
472
|
+
appendFileSync(corpusPath, JSON.stringify(fullEvent) + "\n", "utf-8");
|
|
473
|
+
}
|
|
474
|
+
|
|
449
475
|
// src/analysis/diagnose-core.ts
|
|
450
476
|
function runDiagnosis(messages) {
|
|
451
477
|
const detectors = [
|
|
@@ -459,16 +485,31 @@ function runDiagnosis(messages) {
|
|
|
459
485
|
];
|
|
460
486
|
const detected = [];
|
|
461
487
|
for (const detector of detectors) {
|
|
462
|
-
const
|
|
463
|
-
if (
|
|
488
|
+
const result2 = detector(messages);
|
|
489
|
+
if (result2) detected.push(result2);
|
|
464
490
|
}
|
|
465
|
-
|
|
491
|
+
const result = {
|
|
466
492
|
messagesAnalyzed: messages.length,
|
|
467
493
|
assistantResponses: messages.filter((m) => m.role === "assistant").length,
|
|
468
494
|
patterns: detected.filter((p) => p.severity !== "info"),
|
|
469
495
|
healthy: detected.filter((p) => p.severity === "info"),
|
|
470
496
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
471
497
|
};
|
|
498
|
+
try {
|
|
499
|
+
emitBehavioralEvent({
|
|
500
|
+
event_type: "diagnosis",
|
|
501
|
+
agent: "unknown",
|
|
502
|
+
// Caller can provide more context
|
|
503
|
+
data: {
|
|
504
|
+
messagesAnalyzed: result.messagesAnalyzed,
|
|
505
|
+
patternsDetected: result.patterns.length,
|
|
506
|
+
patternIds: result.patterns.map((p) => p.id)
|
|
507
|
+
},
|
|
508
|
+
spec_hash: ""
|
|
509
|
+
});
|
|
510
|
+
} catch {
|
|
511
|
+
}
|
|
512
|
+
return result;
|
|
472
513
|
}
|
|
473
514
|
|
|
474
515
|
// src/analysis/trait-scorer.ts
|
|
@@ -731,8 +772,8 @@ function runPreSessionDiagnosis(messages, spec) {
|
|
|
731
772
|
}
|
|
732
773
|
|
|
733
774
|
// src/analysis/session-runner.ts
|
|
734
|
-
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
735
|
-
import { resolve, join } from "path";
|
|
775
|
+
import { writeFileSync, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
|
|
776
|
+
import { resolve, join as join2 } from "path";
|
|
736
777
|
|
|
737
778
|
// src/analysis/therapy-protocol.ts
|
|
738
779
|
var THERAPY_PHASES = {
|
|
@@ -1062,6 +1103,21 @@ async function runTherapySession(spec, diagnosis, provider, maxTurns, options) {
|
|
|
1062
1103
|
}
|
|
1063
1104
|
transcript.recommendations = extractRecommendations(transcript.turns);
|
|
1064
1105
|
transcript.supervisorInterventions = supervisorInterventions;
|
|
1106
|
+
try {
|
|
1107
|
+
emitBehavioralEvent({
|
|
1108
|
+
event_type: "session",
|
|
1109
|
+
agent: agentName,
|
|
1110
|
+
data: {
|
|
1111
|
+
turns: totalTurns,
|
|
1112
|
+
phases: currentPhaseIdx + 1,
|
|
1113
|
+
recommendations: transcript.recommendations.length,
|
|
1114
|
+
supervisorInterventions,
|
|
1115
|
+
severity: diagnosis.severity
|
|
1116
|
+
},
|
|
1117
|
+
spec_hash: ""
|
|
1118
|
+
});
|
|
1119
|
+
} catch {
|
|
1120
|
+
}
|
|
1065
1121
|
return transcript;
|
|
1066
1122
|
}
|
|
1067
1123
|
function extractRecommendations(turns) {
|
|
@@ -1092,7 +1148,7 @@ function extractRecommendations(turns) {
|
|
|
1092
1148
|
}
|
|
1093
1149
|
return recommendations.slice(0, 5);
|
|
1094
1150
|
}
|
|
1095
|
-
function applyRecommendations(spec, diagnosis) {
|
|
1151
|
+
async function applyRecommendations(spec, diagnosis, transcript, provider) {
|
|
1096
1152
|
const changes = [];
|
|
1097
1153
|
const patternIds = diagnosis.patterns.map((p) => p.id);
|
|
1098
1154
|
if (patternIds.includes("over-apologizing")) {
|
|
@@ -1152,17 +1208,102 @@ function applyRecommendations(spec, diagnosis) {
|
|
|
1152
1208
|
changes.push('Added "negative sentiment patterns" to patterns_to_watch');
|
|
1153
1209
|
}
|
|
1154
1210
|
}
|
|
1211
|
+
if (transcript && provider && transcript.turns.length > 4) {
|
|
1212
|
+
try {
|
|
1213
|
+
const llmChanges = await deriveLLMRecommendations(spec, transcript, provider);
|
|
1214
|
+
for (const change of llmChanges) {
|
|
1215
|
+
applyStructuredChange(spec, change);
|
|
1216
|
+
changes.push(change.description);
|
|
1217
|
+
}
|
|
1218
|
+
} catch {
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1155
1221
|
return { changed: changes.length > 0, changes };
|
|
1156
1222
|
}
|
|
1223
|
+
async function deriveLLMRecommendations(spec, transcript, provider) {
|
|
1224
|
+
const relevantTurns = transcript.turns.filter((t) => t.phase === "challenge" || t.phase === "skill_building" || t.phase === "integration").slice(-6).map((t) => `${t.speaker}: ${t.content}`).join("\n");
|
|
1225
|
+
if (!relevantTurns) return [];
|
|
1226
|
+
const currentSpec = JSON.stringify({
|
|
1227
|
+
therapy_dimensions: spec.therapy_dimensions,
|
|
1228
|
+
communication: spec.communication,
|
|
1229
|
+
growth: spec.growth
|
|
1230
|
+
}, null, 2);
|
|
1231
|
+
const response = await provider.chat([
|
|
1232
|
+
{
|
|
1233
|
+
role: "system",
|
|
1234
|
+
content: `You are a behavioral alignment specialist. Given a therapy session transcript and the agent's current personality spec, propose specific spec changes.
|
|
1235
|
+
|
|
1236
|
+
Return ONLY a JSON array of changes. Each change:
|
|
1237
|
+
- "path": dot-notation spec path (e.g., "therapy_dimensions.self_awareness", "communication.conflict_approach", "growth.patterns_to_watch")
|
|
1238
|
+
- "value": new value (number 0-1 for dimensions, string for enums, string for list append)
|
|
1239
|
+
- "description": brief explanation
|
|
1240
|
+
|
|
1241
|
+
Rules:
|
|
1242
|
+
- Only propose changes supported by transcript evidence
|
|
1243
|
+
- Numeric values: 0.0 to 1.0
|
|
1244
|
+
- Do not change big_five scores
|
|
1245
|
+
- Max 5 changes
|
|
1246
|
+
- Valid paths: therapy_dimensions.{self_awareness,distress_tolerance,boundary_awareness,interpersonal_sensitivity,learning_orientation}, communication.{register,conflict_approach,uncertainty_handling,emoji_policy}, growth.{areas,patterns_to_watch,strengths}
|
|
1247
|
+
|
|
1248
|
+
Return [] if no changes warranted.`
|
|
1249
|
+
},
|
|
1250
|
+
{
|
|
1251
|
+
role: "user",
|
|
1252
|
+
content: `Current spec:
|
|
1253
|
+
${currentSpec}
|
|
1254
|
+
|
|
1255
|
+
Therapy transcript (key turns):
|
|
1256
|
+
${relevantTurns}`
|
|
1257
|
+
}
|
|
1258
|
+
]);
|
|
1259
|
+
const jsonMatch = response.match(/\[[\s\S]*?\]/);
|
|
1260
|
+
if (!jsonMatch) return [];
|
|
1261
|
+
try {
|
|
1262
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
1263
|
+
if (!Array.isArray(parsed)) return [];
|
|
1264
|
+
return parsed.filter(
|
|
1265
|
+
(c) => typeof c.path === "string" && c.value !== void 0 && typeof c.description === "string" && c.path.length > 0 && !c.path.startsWith("big_five")
|
|
1266
|
+
).slice(0, 5);
|
|
1267
|
+
} catch {
|
|
1268
|
+
return [];
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
function applyStructuredChange(spec, change) {
|
|
1272
|
+
const parts = change.path.split(".");
|
|
1273
|
+
let current = spec;
|
|
1274
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
1275
|
+
if (current[parts[i]] === void 0 || current[parts[i]] === null) {
|
|
1276
|
+
current[parts[i]] = {};
|
|
1277
|
+
}
|
|
1278
|
+
current = current[parts[i]];
|
|
1279
|
+
}
|
|
1280
|
+
const lastKey = parts[parts.length - 1];
|
|
1281
|
+
if (lastKey === "patterns_to_watch" || lastKey === "areas" || lastKey === "strengths") {
|
|
1282
|
+
current[lastKey] = current[lastKey] ?? [];
|
|
1283
|
+
if (typeof change.value === "string" && !current[lastKey].includes(change.value)) {
|
|
1284
|
+
current[lastKey].push(change.value);
|
|
1285
|
+
} else if (Array.isArray(change.value)) {
|
|
1286
|
+
for (const item of change.value) {
|
|
1287
|
+
if (!current[lastKey].includes(item)) {
|
|
1288
|
+
current[lastKey].push(item);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
} else if (typeof change.value === "number") {
|
|
1293
|
+
current[lastKey] = Math.max(0, Math.min(1, change.value));
|
|
1294
|
+
} else {
|
|
1295
|
+
current[lastKey] = change.value;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1157
1298
|
function saveTranscript(transcript, agentName) {
|
|
1158
1299
|
const dir = resolve(process.cwd(), ".holomime", "sessions");
|
|
1159
|
-
if (!
|
|
1160
|
-
|
|
1300
|
+
if (!existsSync2(dir)) {
|
|
1301
|
+
mkdirSync2(dir, { recursive: true });
|
|
1161
1302
|
}
|
|
1162
1303
|
const slug = agentName.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
1163
1304
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1164
1305
|
const filename = `${date}-${slug}.json`;
|
|
1165
|
-
const filepath =
|
|
1306
|
+
const filepath = join2(dir, filename);
|
|
1166
1307
|
writeFileSync(filepath, JSON.stringify(transcript, null, 2));
|
|
1167
1308
|
return filepath;
|
|
1168
1309
|
}
|
|
@@ -1202,7 +1343,7 @@ async function runAutopilot(spec, messages, provider, options) {
|
|
|
1202
1343
|
callbacks: options?.callbacks
|
|
1203
1344
|
});
|
|
1204
1345
|
const specCopy = JSON.parse(JSON.stringify(spec));
|
|
1205
|
-
const { changed, changes } = applyRecommendations(specCopy, diagnosis);
|
|
1346
|
+
const { changed, changes } = await applyRecommendations(specCopy, diagnosis, transcript, provider);
|
|
1206
1347
|
if (changed && options?.specPath) {
|
|
1207
1348
|
writeFileSync2(options.specPath, JSON.stringify(specCopy, null, 2) + "\n");
|
|
1208
1349
|
}
|
|
@@ -1220,48 +1361,214 @@ async function runAutopilot(spec, messages, provider, options) {
|
|
|
1220
1361
|
}
|
|
1221
1362
|
|
|
1222
1363
|
// src/core/types.ts
|
|
1364
|
+
import { z as z2 } from "zod";
|
|
1365
|
+
|
|
1366
|
+
// src/core/embodiment-types.ts
|
|
1223
1367
|
import { z } from "zod";
|
|
1224
|
-
var
|
|
1368
|
+
var modalitySchema = z.enum([
|
|
1369
|
+
"gesture",
|
|
1370
|
+
// arm/hand movement
|
|
1371
|
+
"locomotion",
|
|
1372
|
+
// walking, wheeling, navigating
|
|
1373
|
+
"gaze",
|
|
1374
|
+
// eye tracking, head orientation
|
|
1375
|
+
"facial",
|
|
1376
|
+
// facial expression actuators
|
|
1377
|
+
"voice",
|
|
1378
|
+
// prosody, volume, rate (not content)
|
|
1379
|
+
"haptic",
|
|
1380
|
+
// touch-based interaction
|
|
1381
|
+
"posture",
|
|
1382
|
+
// full-body orientation/lean
|
|
1383
|
+
"manipulation"
|
|
1384
|
+
// grasping, carrying, tool use
|
|
1385
|
+
]);
|
|
1386
|
+
var morphologySchema = z.enum([
|
|
1387
|
+
"humanoid",
|
|
1388
|
+
// bipedal, two arms, head
|
|
1389
|
+
"humanoid_upper",
|
|
1390
|
+
// torso-up only (desk robot, mounted)
|
|
1391
|
+
"quadruped",
|
|
1392
|
+
// four-legged
|
|
1393
|
+
"wheeled",
|
|
1394
|
+
// mobile base with upper body
|
|
1395
|
+
"fixed",
|
|
1396
|
+
// stationary (kiosk, screen + arm)
|
|
1397
|
+
"swarm_unit",
|
|
1398
|
+
// one node of a multi-body system
|
|
1399
|
+
"avatar",
|
|
1400
|
+
// virtual 3D body (no physical actuators)
|
|
1401
|
+
"custom"
|
|
1402
|
+
// user-defined
|
|
1403
|
+
]);
|
|
1404
|
+
var safetyEnvelopeSchema = z.object({
|
|
1405
|
+
max_linear_speed_m_s: z.number().min(0).default(1.5),
|
|
1406
|
+
max_angular_speed_rad_s: z.number().min(0).default(2),
|
|
1407
|
+
min_proximity_m: z.number().min(0).default(0.3),
|
|
1408
|
+
max_contact_force_n: z.number().min(0).default(10),
|
|
1409
|
+
emergency_stop_decel_m_s2: z.number().min(0).default(5),
|
|
1410
|
+
max_reach_m: z.number().min(0).optional(),
|
|
1411
|
+
operating_temperature_c: z.tuple([z.number(), z.number()]).optional()
|
|
1412
|
+
});
|
|
1413
|
+
var embodimentSchema = z.object({
|
|
1414
|
+
morphology: morphologySchema.default("humanoid"),
|
|
1415
|
+
modalities: z.array(modalitySchema).default(["gesture", "gaze", "voice", "posture"]),
|
|
1416
|
+
safety_envelope: safetyEnvelopeSchema.default({}),
|
|
1417
|
+
metadata: z.record(z.string(), z.unknown()).optional()
|
|
1418
|
+
});
|
|
1419
|
+
var gazePolicySchema = z.object({
|
|
1420
|
+
contact_ratio: z.number().min(0).max(1).default(0.6),
|
|
1421
|
+
aversion_style: z.enum(["look_down", "look_away", "blink"]).default("look_away"),
|
|
1422
|
+
tracking_mode: z.enum(["face", "speaker", "gesture_follow", "ambient"]).default("face")
|
|
1423
|
+
});
|
|
1424
|
+
var proxemicZoneSchema = z.object({
|
|
1425
|
+
intimate_m: z.number().min(0).default(0.45),
|
|
1426
|
+
personal_m: z.number().min(0).default(1.2),
|
|
1427
|
+
social_m: z.number().min(0).default(3.6),
|
|
1428
|
+
preferred_zone: z.enum(["intimate", "personal", "social", "adaptive"]).default("personal")
|
|
1429
|
+
});
|
|
1430
|
+
var hapticPolicySchema = z.object({
|
|
1431
|
+
touch_permitted: z.boolean().default(false),
|
|
1432
|
+
requires_consent: z.boolean().default(true),
|
|
1433
|
+
allowed_contacts: z.array(z.enum([
|
|
1434
|
+
"handshake",
|
|
1435
|
+
"shoulder_tap",
|
|
1436
|
+
"high_five",
|
|
1437
|
+
"guide_touch",
|
|
1438
|
+
"none"
|
|
1439
|
+
])).default(["none"]),
|
|
1440
|
+
max_force_n: z.number().min(0).optional()
|
|
1441
|
+
});
|
|
1442
|
+
var prosodySchema = z.object({
|
|
1443
|
+
base_pitch_hz: z.number().optional(),
|
|
1444
|
+
pitch_variation: z.number().min(0).max(1).default(0.5),
|
|
1445
|
+
speaking_rate_wpm: z.number().default(150),
|
|
1446
|
+
volume_db_offset: z.number().default(0),
|
|
1447
|
+
pause_tendency: z.number().min(0).max(1).default(0.5)
|
|
1448
|
+
});
|
|
1449
|
+
var gestureSchema = z.object({
|
|
1450
|
+
id: z.string(),
|
|
1451
|
+
category: z.enum(["conversational", "emphatic", "deictic", "regulatory", "adaptive"]),
|
|
1452
|
+
modalities: z.array(modalitySchema),
|
|
1453
|
+
intensity_range: z.tuple([
|
|
1454
|
+
z.number().min(0).max(1),
|
|
1455
|
+
z.number().min(0).max(1)
|
|
1456
|
+
]).default([0.3, 0.8]),
|
|
1457
|
+
requires_consent: z.boolean().default(false)
|
|
1458
|
+
});
|
|
1459
|
+
var expressionSchema = z.object({
|
|
1460
|
+
gesture_vocabulary: z.array(gestureSchema).default([]),
|
|
1461
|
+
gaze: gazePolicySchema.default({}),
|
|
1462
|
+
proxemics: proxemicZoneSchema.default({}),
|
|
1463
|
+
haptics: hapticPolicySchema.default({}),
|
|
1464
|
+
prosody: prosodySchema.default({}),
|
|
1465
|
+
facial_expressiveness: z.number().min(0).max(1).default(0.5)
|
|
1466
|
+
});
|
|
1467
|
+
var physicalSafetySchema = z.object({
|
|
1468
|
+
hard_limits: z.array(z.string()).default([
|
|
1469
|
+
"Never exceed safety_envelope speeds",
|
|
1470
|
+
"Never exceed max_contact_force_n",
|
|
1471
|
+
"Emergency stop on unrecognized obstacle within min_proximity_m"
|
|
1472
|
+
]),
|
|
1473
|
+
require_consent_for: z.array(z.string()).default([
|
|
1474
|
+
"haptic_contact",
|
|
1475
|
+
"intimate_zone_entry"
|
|
1476
|
+
]),
|
|
1477
|
+
collision_response: z.enum(["stop", "retreat", "freeze"]).default("stop"),
|
|
1478
|
+
unattended_policy: z.enum(["idle", "return_home", "shutdown"]).default("idle")
|
|
1479
|
+
});
|
|
1480
|
+
var motionParametersSchema = z.object({
|
|
1481
|
+
// Speeds (normalized 0-1, scaled by safety_envelope at runtime)
|
|
1482
|
+
base_speed: z.number().min(0).max(1),
|
|
1483
|
+
gesture_speed: z.number().min(0).max(1),
|
|
1484
|
+
gesture_amplitude: z.number().min(0).max(1),
|
|
1485
|
+
gesture_frequency: z.number().min(0).max(1),
|
|
1486
|
+
// Spatial
|
|
1487
|
+
approach_distance: z.number().min(0).max(1),
|
|
1488
|
+
spatial_exploration: z.number().min(0).max(1),
|
|
1489
|
+
// Smoothness
|
|
1490
|
+
movement_smoothness: z.number().min(0).max(1),
|
|
1491
|
+
trajectory_variability: z.number().min(0).max(1),
|
|
1492
|
+
// Timing
|
|
1493
|
+
response_latency: z.number().min(0).max(1),
|
|
1494
|
+
idle_animation_frequency: z.number().min(0).max(1),
|
|
1495
|
+
// Social
|
|
1496
|
+
gaze_contact_ratio: z.number().min(0).max(1),
|
|
1497
|
+
head_tilt_tendency: z.number().min(0).max(1),
|
|
1498
|
+
postural_openness: z.number().min(0).max(1),
|
|
1499
|
+
smile_frequency: z.number().min(0).max(1),
|
|
1500
|
+
// Voice prosody
|
|
1501
|
+
voice_volume: z.number().min(0).max(1),
|
|
1502
|
+
speaking_rate: z.number().min(0).max(1),
|
|
1503
|
+
pitch_variation: z.number().min(0).max(1),
|
|
1504
|
+
pause_duration: z.number().min(0).max(1)
|
|
1505
|
+
});
|
|
1506
|
+
var compiledEmbodiedConfigSchema = z.object({
|
|
1507
|
+
// Base compiled config fields (duplicated to avoid circular import with types.ts)
|
|
1508
|
+
provider: z.string(),
|
|
1509
|
+
surface: z.literal("embodied"),
|
|
1510
|
+
system_prompt: z.string(),
|
|
1511
|
+
temperature: z.number().min(0).max(2),
|
|
1512
|
+
top_p: z.number().min(0).max(1),
|
|
1513
|
+
max_tokens: z.number().int().positive(),
|
|
1514
|
+
metadata: z.object({
|
|
1515
|
+
personality_hash: z.string(),
|
|
1516
|
+
compiled_at: z.string(),
|
|
1517
|
+
holomime_version: z.string()
|
|
1518
|
+
}),
|
|
1519
|
+
// Embodied-specific fields
|
|
1520
|
+
motion_parameters: motionParametersSchema,
|
|
1521
|
+
safety_envelope: safetyEnvelopeSchema,
|
|
1522
|
+
active_modalities: z.array(modalitySchema),
|
|
1523
|
+
gesture_vocabulary: z.array(z.string()),
|
|
1524
|
+
prosody: prosodySchema,
|
|
1525
|
+
gaze: gazePolicySchema,
|
|
1526
|
+
proxemics: proxemicZoneSchema,
|
|
1527
|
+
haptics: hapticPolicySchema
|
|
1528
|
+
});
|
|
1529
|
+
|
|
1530
|
+
// src/core/types.ts
|
|
1531
|
+
var bigFiveDimensionSchema = z2.enum([
|
|
1225
1532
|
"openness",
|
|
1226
1533
|
"conscientiousness",
|
|
1227
1534
|
"extraversion",
|
|
1228
1535
|
"agreeableness",
|
|
1229
1536
|
"emotional_stability"
|
|
1230
1537
|
]);
|
|
1231
|
-
var traitScore =
|
|
1232
|
-
var opennessFacetsSchema =
|
|
1538
|
+
var traitScore = z2.number().min(0).max(1);
|
|
1539
|
+
var opennessFacetsSchema = z2.object({
|
|
1233
1540
|
imagination: traitScore,
|
|
1234
1541
|
intellectual_curiosity: traitScore,
|
|
1235
1542
|
aesthetic_sensitivity: traitScore,
|
|
1236
1543
|
willingness_to_experiment: traitScore
|
|
1237
1544
|
});
|
|
1238
|
-
var conscientiousnessFacetsSchema =
|
|
1545
|
+
var conscientiousnessFacetsSchema = z2.object({
|
|
1239
1546
|
self_discipline: traitScore,
|
|
1240
1547
|
orderliness: traitScore,
|
|
1241
1548
|
goal_orientation: traitScore,
|
|
1242
1549
|
attention_to_detail: traitScore
|
|
1243
1550
|
});
|
|
1244
|
-
var extraversionFacetsSchema =
|
|
1551
|
+
var extraversionFacetsSchema = z2.object({
|
|
1245
1552
|
assertiveness: traitScore,
|
|
1246
1553
|
enthusiasm: traitScore,
|
|
1247
1554
|
sociability: traitScore,
|
|
1248
1555
|
initiative: traitScore
|
|
1249
1556
|
});
|
|
1250
|
-
var agreeablenessFacetsSchema =
|
|
1557
|
+
var agreeablenessFacetsSchema = z2.object({
|
|
1251
1558
|
warmth: traitScore,
|
|
1252
1559
|
empathy: traitScore,
|
|
1253
1560
|
cooperation: traitScore,
|
|
1254
1561
|
trust_tendency: traitScore
|
|
1255
1562
|
});
|
|
1256
|
-
var emotionalStabilityFacetsSchema =
|
|
1563
|
+
var emotionalStabilityFacetsSchema = z2.object({
|
|
1257
1564
|
stress_tolerance: traitScore,
|
|
1258
1565
|
emotional_regulation: traitScore,
|
|
1259
1566
|
confidence: traitScore,
|
|
1260
1567
|
adaptability: traitScore
|
|
1261
1568
|
});
|
|
1262
|
-
var bigFiveTraitSchema =
|
|
1569
|
+
var bigFiveTraitSchema = z2.object({
|
|
1263
1570
|
score: traitScore,
|
|
1264
|
-
facets:
|
|
1571
|
+
facets: z2.union([
|
|
1265
1572
|
opennessFacetsSchema,
|
|
1266
1573
|
conscientiousnessFacetsSchema,
|
|
1267
1574
|
extraversionFacetsSchema,
|
|
@@ -1269,16 +1576,16 @@ var bigFiveTraitSchema = z.object({
|
|
|
1269
1576
|
emotionalStabilityFacetsSchema
|
|
1270
1577
|
])
|
|
1271
1578
|
});
|
|
1272
|
-
var bigFiveSchema =
|
|
1273
|
-
openness:
|
|
1274
|
-
conscientiousness:
|
|
1275
|
-
extraversion:
|
|
1276
|
-
agreeableness:
|
|
1277
|
-
emotional_stability:
|
|
1579
|
+
var bigFiveSchema = z2.object({
|
|
1580
|
+
openness: z2.object({ score: traitScore, facets: opennessFacetsSchema }),
|
|
1581
|
+
conscientiousness: z2.object({ score: traitScore, facets: conscientiousnessFacetsSchema }),
|
|
1582
|
+
extraversion: z2.object({ score: traitScore, facets: extraversionFacetsSchema }),
|
|
1583
|
+
agreeableness: z2.object({ score: traitScore, facets: agreeablenessFacetsSchema }),
|
|
1584
|
+
emotional_stability: z2.object({ score: traitScore, facets: emotionalStabilityFacetsSchema })
|
|
1278
1585
|
});
|
|
1279
|
-
var attachmentStyleSchema =
|
|
1280
|
-
var learningOrientationSchema =
|
|
1281
|
-
var therapyDimensionsSchema =
|
|
1586
|
+
var attachmentStyleSchema = z2.enum(["secure", "anxious", "avoidant", "disorganized"]);
|
|
1587
|
+
var learningOrientationSchema = z2.enum(["growth", "fixed", "mixed"]);
|
|
1588
|
+
var therapyDimensionsSchema = z2.object({
|
|
1282
1589
|
self_awareness: traitScore,
|
|
1283
1590
|
distress_tolerance: traitScore,
|
|
1284
1591
|
attachment_style: attachmentStyleSchema,
|
|
@@ -1286,28 +1593,28 @@ var therapyDimensionsSchema = z.object({
|
|
|
1286
1593
|
boundary_awareness: traitScore,
|
|
1287
1594
|
interpersonal_sensitivity: traitScore
|
|
1288
1595
|
});
|
|
1289
|
-
var registerSchema =
|
|
1596
|
+
var registerSchema = z2.enum([
|
|
1290
1597
|
"casual_professional",
|
|
1291
1598
|
"formal",
|
|
1292
1599
|
"conversational",
|
|
1293
1600
|
"adaptive"
|
|
1294
1601
|
]);
|
|
1295
|
-
var outputFormatSchema =
|
|
1296
|
-
var emojiPolicySchema =
|
|
1297
|
-
var reasoningTransparencySchema =
|
|
1298
|
-
var conflictApproachSchema =
|
|
1602
|
+
var outputFormatSchema = z2.enum(["prose", "bullets", "mixed", "structured"]);
|
|
1603
|
+
var emojiPolicySchema = z2.enum(["never", "sparingly", "freely"]);
|
|
1604
|
+
var reasoningTransparencySchema = z2.enum(["hidden", "on_request", "always"]);
|
|
1605
|
+
var conflictApproachSchema = z2.enum([
|
|
1299
1606
|
"direct_but_kind",
|
|
1300
1607
|
"curious_first",
|
|
1301
1608
|
"supportive_then_honest",
|
|
1302
1609
|
"diplomatic"
|
|
1303
1610
|
]);
|
|
1304
|
-
var uncertaintyHandlingSchema =
|
|
1611
|
+
var uncertaintyHandlingSchema = z2.enum([
|
|
1305
1612
|
"transparent",
|
|
1306
1613
|
"confident_transparency",
|
|
1307
1614
|
"minimize",
|
|
1308
1615
|
"reframe"
|
|
1309
1616
|
]);
|
|
1310
|
-
var communicationSchema =
|
|
1617
|
+
var communicationSchema = z2.object({
|
|
1311
1618
|
register: registerSchema.default("casual_professional"),
|
|
1312
1619
|
output_format: outputFormatSchema.default("mixed"),
|
|
1313
1620
|
emoji_policy: emojiPolicySchema.default("sparingly"),
|
|
@@ -1315,69 +1622,73 @@ var communicationSchema = z.object({
|
|
|
1315
1622
|
conflict_approach: conflictApproachSchema.default("direct_but_kind"),
|
|
1316
1623
|
uncertainty_handling: uncertaintyHandlingSchema.default("transparent")
|
|
1317
1624
|
});
|
|
1318
|
-
var domainSchema =
|
|
1319
|
-
expertise:
|
|
1320
|
-
boundaries:
|
|
1321
|
-
refuses:
|
|
1322
|
-
escalation_triggers:
|
|
1323
|
-
hard_limits:
|
|
1625
|
+
var domainSchema = z2.object({
|
|
1626
|
+
expertise: z2.array(z2.string()).default([]),
|
|
1627
|
+
boundaries: z2.object({
|
|
1628
|
+
refuses: z2.array(z2.string()).default([]),
|
|
1629
|
+
escalation_triggers: z2.array(z2.string()).default([]),
|
|
1630
|
+
hard_limits: z2.array(z2.string()).default([]),
|
|
1631
|
+
physical_safety: physicalSafetySchema.optional()
|
|
1324
1632
|
}).default({})
|
|
1325
1633
|
});
|
|
1326
|
-
var growthAreaSchema =
|
|
1327
|
-
area:
|
|
1328
|
-
severity:
|
|
1329
|
-
first_detected:
|
|
1330
|
-
session_count:
|
|
1331
|
-
resolved:
|
|
1634
|
+
var growthAreaSchema = z2.object({
|
|
1635
|
+
area: z2.string(),
|
|
1636
|
+
severity: z2.enum(["mild", "moderate", "significant"]),
|
|
1637
|
+
first_detected: z2.string().optional(),
|
|
1638
|
+
session_count: z2.number().default(0),
|
|
1639
|
+
resolved: z2.boolean().default(false)
|
|
1332
1640
|
});
|
|
1333
|
-
var growthSchema =
|
|
1334
|
-
areas:
|
|
1335
|
-
patterns_to_watch:
|
|
1336
|
-
strengths:
|
|
1641
|
+
var growthSchema = z2.object({
|
|
1642
|
+
areas: z2.union([z2.array(z2.string()), z2.array(growthAreaSchema)]).default([]),
|
|
1643
|
+
patterns_to_watch: z2.array(z2.string()).default([]),
|
|
1644
|
+
strengths: z2.array(z2.string()).default([])
|
|
1337
1645
|
});
|
|
1338
|
-
var providerSchema =
|
|
1339
|
-
var surfaceSchema =
|
|
1340
|
-
var personalitySpecSchema =
|
|
1341
|
-
$schema:
|
|
1342
|
-
extends:
|
|
1343
|
-
version:
|
|
1344
|
-
name:
|
|
1345
|
-
handle:
|
|
1346
|
-
purpose:
|
|
1646
|
+
var providerSchema = z2.enum(["anthropic", "openai", "gemini", "ollama"]);
|
|
1647
|
+
var surfaceSchema = z2.enum(["chat", "email", "code_review", "slack", "api", "embodied"]);
|
|
1648
|
+
var personalitySpecSchema = z2.object({
|
|
1649
|
+
$schema: z2.string().optional(),
|
|
1650
|
+
extends: z2.string().optional(),
|
|
1651
|
+
version: z2.literal("2.0"),
|
|
1652
|
+
name: z2.string().min(1).max(100),
|
|
1653
|
+
handle: z2.string().min(3).max(50).regex(/^[a-z0-9-]+$/, "Handle must be lowercase alphanumeric with hyphens"),
|
|
1654
|
+
purpose: z2.string().max(500).optional(),
|
|
1347
1655
|
big_five: bigFiveSchema,
|
|
1348
1656
|
therapy_dimensions: therapyDimensionsSchema,
|
|
1349
1657
|
communication: communicationSchema.default({}),
|
|
1350
1658
|
domain: domainSchema.default({}),
|
|
1351
|
-
growth: growthSchema.default({})
|
|
1659
|
+
growth: growthSchema.default({}),
|
|
1660
|
+
// ─── Embodiment (optional — for physical/embodied agents) ───
|
|
1661
|
+
embodiment: embodimentSchema.optional(),
|
|
1662
|
+
expression: expressionSchema.optional()
|
|
1352
1663
|
});
|
|
1353
|
-
var compiledConfigSchema =
|
|
1664
|
+
var compiledConfigSchema = z2.object({
|
|
1354
1665
|
provider: providerSchema,
|
|
1355
1666
|
surface: surfaceSchema,
|
|
1356
|
-
system_prompt:
|
|
1357
|
-
temperature:
|
|
1358
|
-
top_p:
|
|
1359
|
-
max_tokens:
|
|
1360
|
-
metadata:
|
|
1361
|
-
personality_hash:
|
|
1362
|
-
compiled_at:
|
|
1363
|
-
holomime_version:
|
|
1667
|
+
system_prompt: z2.string(),
|
|
1668
|
+
temperature: z2.number().min(0).max(2),
|
|
1669
|
+
top_p: z2.number().min(0).max(1),
|
|
1670
|
+
max_tokens: z2.number().int().positive(),
|
|
1671
|
+
metadata: z2.object({
|
|
1672
|
+
personality_hash: z2.string(),
|
|
1673
|
+
compiled_at: z2.string(),
|
|
1674
|
+
holomime_version: z2.string()
|
|
1364
1675
|
})
|
|
1365
1676
|
});
|
|
1366
|
-
var messageSchema =
|
|
1367
|
-
role:
|
|
1368
|
-
content:
|
|
1369
|
-
timestamp:
|
|
1677
|
+
var messageSchema = z2.object({
|
|
1678
|
+
role: z2.enum(["user", "assistant", "system"]),
|
|
1679
|
+
content: z2.string(),
|
|
1680
|
+
timestamp: z2.string().optional()
|
|
1370
1681
|
});
|
|
1371
|
-
var conversationSchema =
|
|
1372
|
-
id:
|
|
1373
|
-
messages:
|
|
1374
|
-
metadata:
|
|
1682
|
+
var conversationSchema = z2.object({
|
|
1683
|
+
id: z2.string().optional(),
|
|
1684
|
+
messages: z2.array(messageSchema),
|
|
1685
|
+
metadata: z2.record(z2.string(), z2.unknown()).optional()
|
|
1375
1686
|
});
|
|
1376
|
-
var conversationLogSchema =
|
|
1687
|
+
var conversationLogSchema = z2.union([
|
|
1377
1688
|
conversationSchema,
|
|
1378
|
-
|
|
1689
|
+
z2.array(conversationSchema)
|
|
1379
1690
|
]);
|
|
1380
|
-
var severitySchema =
|
|
1691
|
+
var severitySchema = z2.enum(["info", "warning", "concern"]);
|
|
1381
1692
|
|
|
1382
1693
|
// src/psychology/big-five.ts
|
|
1383
1694
|
function scoreLabel(score) {
|
|
@@ -1632,14 +1943,14 @@ function runSelfAudit(messages, personality) {
|
|
|
1632
1943
|
|
|
1633
1944
|
// src/mcp/server.ts
|
|
1634
1945
|
var messageShape = {
|
|
1635
|
-
role:
|
|
1636
|
-
content:
|
|
1946
|
+
role: z3.enum(["user", "assistant", "system"]),
|
|
1947
|
+
content: z3.string()
|
|
1637
1948
|
};
|
|
1638
1949
|
var messagesShape = {
|
|
1639
|
-
messages:
|
|
1950
|
+
messages: z3.array(z3.object(messageShape)).describe("Conversation messages to analyze")
|
|
1640
1951
|
};
|
|
1641
1952
|
var personalityShape = {
|
|
1642
|
-
personality:
|
|
1953
|
+
personality: z3.record(z3.string(), z3.unknown()).describe("The .personality.json spec object")
|
|
1643
1954
|
};
|
|
1644
1955
|
var server = new McpServer(
|
|
1645
1956
|
{
|
|
@@ -1755,12 +2066,12 @@ server.tool(
|
|
|
1755
2066
|
{
|
|
1756
2067
|
...personalityShape,
|
|
1757
2068
|
...messagesShape,
|
|
1758
|
-
provider:
|
|
1759
|
-
apiKey:
|
|
1760
|
-
model:
|
|
1761
|
-
threshold:
|
|
1762
|
-
maxTurns:
|
|
1763
|
-
dryRun:
|
|
2069
|
+
provider: z3.enum(["anthropic", "openai"]).describe("LLM provider for alignment session").optional(),
|
|
2070
|
+
apiKey: z3.string().describe("API key for the LLM provider").optional(),
|
|
2071
|
+
model: z3.string().describe("Model override").optional(),
|
|
2072
|
+
threshold: z3.enum(["routine", "targeted", "intervention"]).describe("Minimum severity to trigger alignment (default: targeted)").optional(),
|
|
2073
|
+
maxTurns: z3.number().describe("Maximum session turns (default: 24)").optional(),
|
|
2074
|
+
dryRun: z3.boolean().describe("If true, only diagnose without running alignment").optional()
|
|
1764
2075
|
},
|
|
1765
2076
|
async ({ personality, messages, provider, apiKey, model, threshold, maxTurns, dryRun }) => {
|
|
1766
2077
|
const specResult = personalitySpecSchema.safeParse(personality);
|
|
@@ -1815,7 +2126,7 @@ server.tool(
|
|
|
1815
2126
|
"Mid-conversation behavioral self-check. Call this during a conversation to detect if you are falling into problematic patterns (sycophancy, over-apologizing, hedging, error spirals, boundary violations). Returns flags with actionable suggestions for immediate correction. No LLM required \u2014 pure rule-based analysis.",
|
|
1816
2127
|
{
|
|
1817
2128
|
...messagesShape,
|
|
1818
|
-
personality:
|
|
2129
|
+
personality: z3.record(z3.string(), z3.unknown()).describe("Optional .personality.json spec for personalized audit").optional()
|
|
1819
2130
|
},
|
|
1820
2131
|
async ({ messages, personality }) => {
|
|
1821
2132
|
const result = runSelfAudit(messages, personality ?? void 0);
|