holomime 1.0.0 → 1.1.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 +122 -96
- package/dist/cli.js +413 -51
- package/dist/index.d.ts +111 -2
- package/dist/index.js +272 -1
- package/package.json +14 -2
package/dist/index.d.ts
CHANGED
|
@@ -2420,14 +2420,22 @@ declare class OllamaProvider implements LLMProvider {
|
|
|
2420
2420
|
/**
|
|
2421
2421
|
* Unified conversation log adapter.
|
|
2422
2422
|
* Auto-detects format or uses explicit format parameter.
|
|
2423
|
+
* Supports: HoloMime, ChatGPT, Claude, OpenAI API, Anthropic API,
|
|
2424
|
+
* OpenTelemetry GenAI, and JSONL.
|
|
2423
2425
|
*/
|
|
2424
2426
|
|
|
2425
|
-
type LogFormat = "holomime" | "chatgpt" | "claude" | "openai-api" | "auto";
|
|
2427
|
+
type LogFormat = "holomime" | "chatgpt" | "claude" | "openai-api" | "anthropic-api" | "otel" | "jsonl" | "auto";
|
|
2426
2428
|
/**
|
|
2427
2429
|
* Parse a conversation log from any supported format.
|
|
2428
2430
|
* Returns normalized Conversation[].
|
|
2429
2431
|
*/
|
|
2430
2432
|
declare function parseConversationLog(raw: unknown, format?: LogFormat): Conversation[];
|
|
2433
|
+
/**
|
|
2434
|
+
* Parse a conversation log from a raw file string.
|
|
2435
|
+
* Handles JSONL (which isn't valid JSON) before falling back to JSON parsing.
|
|
2436
|
+
* This is the recommended entry point for CLI commands reading from files.
|
|
2437
|
+
*/
|
|
2438
|
+
declare function parseConversationLogFromString(raw: string, format?: LogFormat): Conversation[];
|
|
2431
2439
|
|
|
2432
2440
|
/**
|
|
2433
2441
|
* ChatGPT export format adapter.
|
|
@@ -2504,6 +2512,107 @@ interface OpenAIResponse {
|
|
|
2504
2512
|
*/
|
|
2505
2513
|
declare function parseOpenAIAPILog(data: OpenAIResponse | OpenAIResponse[]): Conversation[];
|
|
2506
2514
|
|
|
2515
|
+
/**
|
|
2516
|
+
* Anthropic Messages API log format adapter.
|
|
2517
|
+
* Handles response objects from the Anthropic Messages API,
|
|
2518
|
+
* including single responses, arrays, and request+response log pairs.
|
|
2519
|
+
*/
|
|
2520
|
+
|
|
2521
|
+
interface AnthropicContentBlock {
|
|
2522
|
+
type: string;
|
|
2523
|
+
text?: string;
|
|
2524
|
+
}
|
|
2525
|
+
interface AnthropicResponse {
|
|
2526
|
+
id?: string;
|
|
2527
|
+
type: "message";
|
|
2528
|
+
role: "assistant";
|
|
2529
|
+
content: AnthropicContentBlock[];
|
|
2530
|
+
model?: string;
|
|
2531
|
+
stop_reason?: string;
|
|
2532
|
+
}
|
|
2533
|
+
interface AnthropicRequestMessage {
|
|
2534
|
+
role: "user" | "assistant";
|
|
2535
|
+
content: string | AnthropicContentBlock[];
|
|
2536
|
+
}
|
|
2537
|
+
interface AnthropicRequestResponsePair {
|
|
2538
|
+
request: {
|
|
2539
|
+
messages: AnthropicRequestMessage[];
|
|
2540
|
+
system?: string | AnthropicContentBlock[];
|
|
2541
|
+
model?: string;
|
|
2542
|
+
};
|
|
2543
|
+
response: AnthropicResponse;
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Parse Anthropic API response logs.
|
|
2547
|
+
* Handles: single response, array of responses, or request+response pairs.
|
|
2548
|
+
*/
|
|
2549
|
+
declare function parseAnthropicAPILog(data: AnthropicResponse | AnthropicResponse[] | AnthropicRequestResponsePair | AnthropicRequestResponsePair[]): Conversation[];
|
|
2550
|
+
|
|
2551
|
+
/**
|
|
2552
|
+
* OpenTelemetry GenAI semantic conventions adapter.
|
|
2553
|
+
* Handles OTel JSON export format with gen_ai.* span attributes.
|
|
2554
|
+
* Covers traces from LangChain, OpenAI SDK, Anthropic SDK, CrewAI,
|
|
2555
|
+
* Vercel AI SDK, AWS Strands, Google ADK, and any OTel-compatible framework.
|
|
2556
|
+
*/
|
|
2557
|
+
|
|
2558
|
+
interface OTelAttributeValue {
|
|
2559
|
+
stringValue?: string;
|
|
2560
|
+
intValue?: string | number;
|
|
2561
|
+
boolValue?: boolean;
|
|
2562
|
+
arrayValue?: {
|
|
2563
|
+
values?: OTelAttributeValue[];
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2566
|
+
interface OTelAttribute {
|
|
2567
|
+
key: string;
|
|
2568
|
+
value: OTelAttributeValue;
|
|
2569
|
+
}
|
|
2570
|
+
interface OTelSpan {
|
|
2571
|
+
traceId: string;
|
|
2572
|
+
spanId: string;
|
|
2573
|
+
name: string;
|
|
2574
|
+
startTimeUnixNano?: string;
|
|
2575
|
+
endTimeUnixNano?: string;
|
|
2576
|
+
attributes?: OTelAttribute[];
|
|
2577
|
+
}
|
|
2578
|
+
interface OTelScopeSpan {
|
|
2579
|
+
scope?: {
|
|
2580
|
+
name?: string;
|
|
2581
|
+
};
|
|
2582
|
+
spans?: OTelSpan[];
|
|
2583
|
+
}
|
|
2584
|
+
interface OTelResourceSpan {
|
|
2585
|
+
resource?: {
|
|
2586
|
+
attributes?: OTelAttribute[];
|
|
2587
|
+
};
|
|
2588
|
+
scopeSpans?: OTelScopeSpan[];
|
|
2589
|
+
}
|
|
2590
|
+
interface OTelExport {
|
|
2591
|
+
resourceSpans: OTelResourceSpan[];
|
|
2592
|
+
}
|
|
2593
|
+
/**
|
|
2594
|
+
* Parse an OTel GenAI JSON export into normalized conversations.
|
|
2595
|
+
* Groups spans by traceId. Extracts messages from gen_ai.* attributes.
|
|
2596
|
+
*/
|
|
2597
|
+
declare function parseOTelGenAIExport(data: OTelExport): Conversation[];
|
|
2598
|
+
|
|
2599
|
+
/**
|
|
2600
|
+
* JSONL (JSON Lines) adapter.
|
|
2601
|
+
* Handles line-delimited JSON where each line is a message
|
|
2602
|
+
* with at minimum { role, content } fields.
|
|
2603
|
+
*
|
|
2604
|
+
* JSONL is not valid JSON — this adapter works on raw strings,
|
|
2605
|
+
* not pre-parsed objects.
|
|
2606
|
+
*/
|
|
2607
|
+
|
|
2608
|
+
/**
|
|
2609
|
+
* Parse a JSONL string into normalized conversations.
|
|
2610
|
+
* Each line should be a JSON object with at least `role` and `content`.
|
|
2611
|
+
* Optional: `conversation_id` (groups into separate conversations),
|
|
2612
|
+
* `timestamp` (ISO 8601 or Unix epoch).
|
|
2613
|
+
*/
|
|
2614
|
+
declare function parseJSONLLog(raw: string): Conversation[];
|
|
2615
|
+
|
|
2507
2616
|
/**
|
|
2508
2617
|
* HoloMime Personality Marketplace — registry client.
|
|
2509
2618
|
* Fetches personality profiles from a GitHub-hosted JSON registry.
|
|
@@ -2755,4 +2864,4 @@ declare function generateIndexMarkdown(index: BehavioralIndex): string;
|
|
|
2755
2864
|
*/
|
|
2756
2865
|
declare function startMCPServer(): Promise<void>;
|
|
2757
2866
|
|
|
2758
|
-
export { ARCHETYPES, ATTACHMENT_STYLES, type AlpacaExample, AnthropicProvider, type ArchetypeTemplate, type AssessmentReport, type AssessmentResult, type AttachmentStyle, type AutopilotResult, type AutopilotThreshold, BUILT_IN_DETECTORS, type BehavioralCredential, type BehavioralIndex, type BenchmarkCallbacks, type BenchmarkComparison, type BenchmarkReport, type BenchmarkResult, type BenchmarkScenario, type BigFive, CATEGORIES, type CertifyInput, type Communication, type CompileInput, type CompiledConfig, type Conversation, type ConversationLog, DIMENSIONS, type DPOPair, type DetectedPattern, type DetectorFactory, type DetectorFn, type DetectorOptions, type DiagnosisResult, type Domain, type EvolutionEntry, type EvolutionHistory, type EvolutionSummary, type EvolveCallbacks, type EvolveOptions, type EvolveResult, type FleetAgent, type FleetAgentStatus, type FleetConfig, type FleetHandle, type FleetOptions, type Growth, type GrowthArea, type GrowthReport, type GrowthSnapshot, Guard, type GuardEntry, type GuardResult, type HFPushOptions, type HFPushResult, type HubDetector, type IndexComparison, type IndexEntry, type IterationResult, LEARNING_ORIENTATIONS, type LLMMessage, type LLMProvider, type LearningOrientation, type LogFormat, type Message, OllamaProvider, OpenAIProvider, type OutcomeReport, PROVIDER_PARAMS, type PatternDelta, type PatternReport, type PersonalitySpec, type PhaseConfig, type PreSessionDiagnosis, type Prescription, type Provider, type ProviderConfig, type PublishedBenchmark, type RLHFExample, type Registry, type RegistryEntry, SURFACE_MULTIPLIERS, type SelfAuditFlag, type SelfAuditResult, type SessionCallbacks, type SessionOptions, type SessionOutcome, type SessionTranscript, type SessionTurn, type Severity, type Surface, THERAPY_DIMENSIONS, THERAPY_PHASES, type TherapyDimensions, type TherapyPhase, type TrainingExport, type TraitAlignment, type TraitScores, type TreatmentGoal, type TreatmentPlan, type TreatmentProgressReport, type VerifyResult, type WatchCallbacks, type WatchEvent, type WatchHandle, type WatchOptions, appendEvolution, applyRecommendations, bigFiveSchema, buildPatientSystemPrompt, buildTherapistSystemPrompt, communicationSchema, compareBenchmarks, compareIndex, compile, compileForOpenClaw, compiledConfigSchema, computeDimensionScore, conversationLogSchema, conversationSchema, convertToHFFormat, createGist, createIndex, createIndexEntry, createProvider, createTreatmentPlan, deepMergeSpec, detectApologies, detectBoundaryIssues, detectFormalityIssues, detectHedging, detectRecoveryPatterns, detectSentiment, detectVerbosity, discoverAgents, domainSchema, evaluateOutcome, exportTrainingData, extractAlpacaExamples, extractDPOPairs, extractRLHFExamples, extractRecommendations, fetchPersonality, fetchRegistry, generateBenchmarkMarkdown, generateComparisonMarkdown, generateCredential, generateIndexMarkdown, generatePrescriptions, generateProgressReport, generateSystemPrompt, getArchetype, getArchetypesByCategory, getBenchmarkScenarios, getCategories, getDetector, getDimension, getEvolutionSummary, getInheritanceChain, getScenarioById, getTotalSignalCount, growthAreaSchema, growthSchema, listArchetypeIds, listDetectors, listDetectorsByCategory, listDetectorsByTag, loadBenchmarkResults, loadEvolution, loadFleetConfig, loadLatestBenchmark, loadSpec, loadTranscripts, loadTreatmentPlan, messageSchema, parseChatGPTExport, parseClaudeExport, parseConversationLog, parseOpenAIAPILog, personalitySpecSchema, providerSchema, pushToHFHub, recordSessionOutcome, registerBuiltInDetectors, registerDetector, resolveInheritance, runAssessment, runAutopilot, runBenchmark, runDiagnosis, runEvolve, runPreSessionDiagnosis, runSelfAudit, runTherapySession, saveBenchmarkResult, saveCredential, saveTranscript, saveTreatmentPlan, scoreLabel, scoreTraitsFromMessages, severityMeetsThreshold, severitySchema, startFleet, startMCPServer, startWatch, summarize, summarizeTherapy, surfaceSchema, therapyDimensionsSchema, therapyScoreLabel, unregisterDetector, verifyCredential };
|
|
2867
|
+
export { ARCHETYPES, ATTACHMENT_STYLES, type AlpacaExample, AnthropicProvider, type ArchetypeTemplate, type AssessmentReport, type AssessmentResult, type AttachmentStyle, type AutopilotResult, type AutopilotThreshold, BUILT_IN_DETECTORS, type BehavioralCredential, type BehavioralIndex, type BenchmarkCallbacks, type BenchmarkComparison, type BenchmarkReport, type BenchmarkResult, type BenchmarkScenario, type BigFive, CATEGORIES, type CertifyInput, type Communication, type CompileInput, type CompiledConfig, type Conversation, type ConversationLog, DIMENSIONS, type DPOPair, type DetectedPattern, type DetectorFactory, type DetectorFn, type DetectorOptions, type DiagnosisResult, type Domain, type EvolutionEntry, type EvolutionHistory, type EvolutionSummary, type EvolveCallbacks, type EvolveOptions, type EvolveResult, type FleetAgent, type FleetAgentStatus, type FleetConfig, type FleetHandle, type FleetOptions, type Growth, type GrowthArea, type GrowthReport, type GrowthSnapshot, Guard, type GuardEntry, type GuardResult, type HFPushOptions, type HFPushResult, type HubDetector, type IndexComparison, type IndexEntry, type IterationResult, LEARNING_ORIENTATIONS, type LLMMessage, type LLMProvider, type LearningOrientation, type LogFormat, type Message, OllamaProvider, OpenAIProvider, type OutcomeReport, PROVIDER_PARAMS, type PatternDelta, type PatternReport, type PersonalitySpec, type PhaseConfig, type PreSessionDiagnosis, type Prescription, type Provider, type ProviderConfig, type PublishedBenchmark, type RLHFExample, type Registry, type RegistryEntry, SURFACE_MULTIPLIERS, type SelfAuditFlag, type SelfAuditResult, type SessionCallbacks, type SessionOptions, type SessionOutcome, type SessionTranscript, type SessionTurn, type Severity, type Surface, THERAPY_DIMENSIONS, THERAPY_PHASES, type TherapyDimensions, type TherapyPhase, type TrainingExport, type TraitAlignment, type TraitScores, type TreatmentGoal, type TreatmentPlan, type TreatmentProgressReport, type VerifyResult, type WatchCallbacks, type WatchEvent, type WatchHandle, type WatchOptions, appendEvolution, applyRecommendations, bigFiveSchema, buildPatientSystemPrompt, buildTherapistSystemPrompt, communicationSchema, compareBenchmarks, compareIndex, compile, compileForOpenClaw, compiledConfigSchema, computeDimensionScore, conversationLogSchema, conversationSchema, convertToHFFormat, createGist, createIndex, createIndexEntry, createProvider, createTreatmentPlan, deepMergeSpec, detectApologies, detectBoundaryIssues, detectFormalityIssues, detectHedging, detectRecoveryPatterns, detectSentiment, detectVerbosity, discoverAgents, domainSchema, evaluateOutcome, exportTrainingData, extractAlpacaExamples, extractDPOPairs, extractRLHFExamples, extractRecommendations, fetchPersonality, fetchRegistry, generateBenchmarkMarkdown, generateComparisonMarkdown, generateCredential, generateIndexMarkdown, generatePrescriptions, generateProgressReport, generateSystemPrompt, getArchetype, getArchetypesByCategory, getBenchmarkScenarios, getCategories, getDetector, getDimension, getEvolutionSummary, getInheritanceChain, getScenarioById, getTotalSignalCount, growthAreaSchema, growthSchema, listArchetypeIds, listDetectors, listDetectorsByCategory, listDetectorsByTag, loadBenchmarkResults, loadEvolution, loadFleetConfig, loadLatestBenchmark, loadSpec, loadTranscripts, loadTreatmentPlan, messageSchema, parseAnthropicAPILog, parseChatGPTExport, parseClaudeExport, parseConversationLog, parseConversationLogFromString, parseJSONLLog, parseOTelGenAIExport, parseOpenAIAPILog, personalitySpecSchema, providerSchema, pushToHFHub, recordSessionOutcome, registerBuiltInDetectors, registerDetector, resolveInheritance, runAssessment, runAutopilot, runBenchmark, runDiagnosis, runEvolve, runPreSessionDiagnosis, runSelfAudit, runTherapySession, saveBenchmarkResult, saveCredential, saveTranscript, saveTreatmentPlan, scoreLabel, scoreTraitsFromMessages, severityMeetsThreshold, severitySchema, startFleet, startMCPServer, startWatch, summarize, summarizeTherapy, surfaceSchema, therapyDimensionsSchema, therapyScoreLabel, unregisterDetector, verifyCredential };
|
package/dist/index.js
CHANGED
|
@@ -4005,6 +4005,240 @@ function isOpenAIAPILog(data) {
|
|
|
4005
4005
|
return false;
|
|
4006
4006
|
}
|
|
4007
4007
|
|
|
4008
|
+
// src/adapters/anthropic-api.ts
|
|
4009
|
+
function extractTextContent(content) {
|
|
4010
|
+
if (typeof content === "string") return content;
|
|
4011
|
+
return content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("");
|
|
4012
|
+
}
|
|
4013
|
+
function mapRole3(role) {
|
|
4014
|
+
if (role === "user") return "user";
|
|
4015
|
+
if (role === "system") return "system";
|
|
4016
|
+
return "assistant";
|
|
4017
|
+
}
|
|
4018
|
+
function parseAnthropicAPILog(data) {
|
|
4019
|
+
const items = Array.isArray(data) ? data : [data];
|
|
4020
|
+
const conversations = [];
|
|
4021
|
+
for (const item of items) {
|
|
4022
|
+
const messages = [];
|
|
4023
|
+
let model;
|
|
4024
|
+
if (isRequestResponsePair(item)) {
|
|
4025
|
+
const pair = item;
|
|
4026
|
+
model = pair.request.model ?? pair.response.model;
|
|
4027
|
+
if (pair.request.system) {
|
|
4028
|
+
const systemText = extractTextContent(pair.request.system);
|
|
4029
|
+
if (systemText.trim()) {
|
|
4030
|
+
messages.push({ role: "system", content: systemText });
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
4033
|
+
for (const msg of pair.request.messages) {
|
|
4034
|
+
const content = extractTextContent(msg.content);
|
|
4035
|
+
if (content.trim()) {
|
|
4036
|
+
messages.push({ role: mapRole3(msg.role), content });
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
const responseText = extractTextContent(pair.response.content);
|
|
4040
|
+
if (responseText.trim()) {
|
|
4041
|
+
messages.push({ role: "assistant", content: responseText });
|
|
4042
|
+
}
|
|
4043
|
+
} else {
|
|
4044
|
+
const resp = item;
|
|
4045
|
+
model = resp.model;
|
|
4046
|
+
const text = extractTextContent(resp.content);
|
|
4047
|
+
if (text.trim()) {
|
|
4048
|
+
messages.push({ role: "assistant", content: text });
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4051
|
+
if (messages.length > 0) {
|
|
4052
|
+
conversations.push({
|
|
4053
|
+
id: item.id ?? item.response?.id,
|
|
4054
|
+
messages,
|
|
4055
|
+
metadata: {
|
|
4056
|
+
source: "anthropic-api",
|
|
4057
|
+
...model && { model }
|
|
4058
|
+
}
|
|
4059
|
+
});
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
return conversations;
|
|
4063
|
+
}
|
|
4064
|
+
function isRequestResponsePair(item) {
|
|
4065
|
+
return typeof item === "object" && item !== null && "request" in item && "response" in item && typeof item.request === "object" && typeof item.response === "object";
|
|
4066
|
+
}
|
|
4067
|
+
function isAnthropicAPILog(data) {
|
|
4068
|
+
if (isAnthropicResponse(data)) return true;
|
|
4069
|
+
if (isRequestResponsePair(data)) return true;
|
|
4070
|
+
if (Array.isArray(data) && data.length > 0) {
|
|
4071
|
+
return isAnthropicResponse(data[0]) || isRequestResponsePair(data[0]);
|
|
4072
|
+
}
|
|
4073
|
+
return false;
|
|
4074
|
+
}
|
|
4075
|
+
function isAnthropicResponse(data) {
|
|
4076
|
+
if (typeof data !== "object" || data === null) return false;
|
|
4077
|
+
const obj = data;
|
|
4078
|
+
return obj.type === "message" && Array.isArray(obj.content);
|
|
4079
|
+
}
|
|
4080
|
+
|
|
4081
|
+
// src/adapters/otel-genai.ts
|
|
4082
|
+
function getAttr(attrs, key) {
|
|
4083
|
+
if (!attrs) return void 0;
|
|
4084
|
+
const attr = attrs.find((a) => a.key === key);
|
|
4085
|
+
if (!attr) return void 0;
|
|
4086
|
+
return attr.value.stringValue ?? (attr.value.intValue != null ? String(attr.value.intValue) : void 0);
|
|
4087
|
+
}
|
|
4088
|
+
function hasGenAIAttrs(attrs) {
|
|
4089
|
+
if (!attrs) return false;
|
|
4090
|
+
return attrs.some((a) => a.key.startsWith("gen_ai."));
|
|
4091
|
+
}
|
|
4092
|
+
function mapRole4(role) {
|
|
4093
|
+
if (role === "user") return "user";
|
|
4094
|
+
if (role === "system") return "system";
|
|
4095
|
+
return "assistant";
|
|
4096
|
+
}
|
|
4097
|
+
function nanoToISO(nano) {
|
|
4098
|
+
if (!nano) return void 0;
|
|
4099
|
+
const ms = Number(BigInt(nano) / BigInt(1e6));
|
|
4100
|
+
return new Date(ms).toISOString();
|
|
4101
|
+
}
|
|
4102
|
+
function parseOTelGenAIExport(data) {
|
|
4103
|
+
const traceMap = /* @__PURE__ */ new Map();
|
|
4104
|
+
for (const rs of data.resourceSpans) {
|
|
4105
|
+
for (const ss of rs.scopeSpans ?? []) {
|
|
4106
|
+
for (const span of ss.spans ?? []) {
|
|
4107
|
+
if (!hasGenAIAttrs(span.attributes)) continue;
|
|
4108
|
+
const traceId = span.traceId;
|
|
4109
|
+
if (!traceMap.has(traceId)) {
|
|
4110
|
+
traceMap.set(traceId, { messages: [] });
|
|
4111
|
+
}
|
|
4112
|
+
const trace = traceMap.get(traceId);
|
|
4113
|
+
const system = getAttr(span.attributes, "gen_ai.system");
|
|
4114
|
+
const model = getAttr(span.attributes, "gen_ai.request.model");
|
|
4115
|
+
if (system) trace.system = system;
|
|
4116
|
+
if (model) trace.model = model;
|
|
4117
|
+
const timestamp = nanoToISO(span.startTimeUnixNano);
|
|
4118
|
+
const messagesAttr = span.attributes?.find((a) => a.key === "gen_ai.request.messages");
|
|
4119
|
+
if (messagesAttr?.value.stringValue) {
|
|
4120
|
+
try {
|
|
4121
|
+
const parsed = JSON.parse(messagesAttr.value.stringValue);
|
|
4122
|
+
if (Array.isArray(parsed)) {
|
|
4123
|
+
for (const m of parsed) {
|
|
4124
|
+
if (m.role && m.content) {
|
|
4125
|
+
trace.messages.push({
|
|
4126
|
+
role: mapRole4(m.role),
|
|
4127
|
+
content: typeof m.content === "string" ? m.content : JSON.stringify(m.content),
|
|
4128
|
+
...timestamp && { timestamp }
|
|
4129
|
+
});
|
|
4130
|
+
}
|
|
4131
|
+
}
|
|
4132
|
+
continue;
|
|
4133
|
+
}
|
|
4134
|
+
} catch {
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
const promptContent = getAttr(span.attributes, "gen_ai.prompt.0.content");
|
|
4138
|
+
const completionContent = getAttr(span.attributes, "gen_ai.completion.0.content");
|
|
4139
|
+
if (promptContent) {
|
|
4140
|
+
trace.messages.push({
|
|
4141
|
+
role: "user",
|
|
4142
|
+
content: promptContent,
|
|
4143
|
+
...timestamp && { timestamp }
|
|
4144
|
+
});
|
|
4145
|
+
}
|
|
4146
|
+
if (completionContent) {
|
|
4147
|
+
trace.messages.push({
|
|
4148
|
+
role: "assistant",
|
|
4149
|
+
content: completionContent,
|
|
4150
|
+
...timestamp && { timestamp }
|
|
4151
|
+
});
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
}
|
|
4156
|
+
const conversations = [];
|
|
4157
|
+
for (const [traceId, trace] of traceMap) {
|
|
4158
|
+
if (trace.messages.length === 0) continue;
|
|
4159
|
+
conversations.push({
|
|
4160
|
+
id: traceId,
|
|
4161
|
+
messages: trace.messages,
|
|
4162
|
+
metadata: {
|
|
4163
|
+
source: "otel",
|
|
4164
|
+
...trace.system && { system: trace.system },
|
|
4165
|
+
...trace.model && { model: trace.model }
|
|
4166
|
+
}
|
|
4167
|
+
});
|
|
4168
|
+
}
|
|
4169
|
+
return conversations;
|
|
4170
|
+
}
|
|
4171
|
+
function isOTelGenAIExport(data) {
|
|
4172
|
+
if (typeof data !== "object" || data === null) return false;
|
|
4173
|
+
if (!("resourceSpans" in data) || !Array.isArray(data.resourceSpans)) return false;
|
|
4174
|
+
const rs = data.resourceSpans;
|
|
4175
|
+
for (const r of rs) {
|
|
4176
|
+
for (const ss of r.scopeSpans ?? []) {
|
|
4177
|
+
for (const span of ss.spans ?? []) {
|
|
4178
|
+
if (hasGenAIAttrs(span.attributes)) return true;
|
|
4179
|
+
}
|
|
4180
|
+
}
|
|
4181
|
+
}
|
|
4182
|
+
return false;
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
// src/adapters/jsonl.ts
|
|
4186
|
+
function mapRole5(role) {
|
|
4187
|
+
if (role === "user") return "user";
|
|
4188
|
+
if (role === "system") return "system";
|
|
4189
|
+
return "assistant";
|
|
4190
|
+
}
|
|
4191
|
+
function parseJSONLLog(raw) {
|
|
4192
|
+
const lines = raw.split("\n").filter((l) => l.trim() !== "");
|
|
4193
|
+
const convMap = /* @__PURE__ */ new Map();
|
|
4194
|
+
const defaultKey = "__default__";
|
|
4195
|
+
for (const line of lines) {
|
|
4196
|
+
let parsed;
|
|
4197
|
+
try {
|
|
4198
|
+
parsed = JSON.parse(line);
|
|
4199
|
+
} catch {
|
|
4200
|
+
continue;
|
|
4201
|
+
}
|
|
4202
|
+
if (typeof parsed !== "object" || parsed === null) continue;
|
|
4203
|
+
if (typeof parsed.role !== "string" || typeof parsed.content !== "string") continue;
|
|
4204
|
+
const convId = typeof parsed.conversation_id === "string" ? parsed.conversation_id : defaultKey;
|
|
4205
|
+
if (!convMap.has(convId)) {
|
|
4206
|
+
convMap.set(convId, []);
|
|
4207
|
+
}
|
|
4208
|
+
const message = {
|
|
4209
|
+
role: mapRole5(parsed.role),
|
|
4210
|
+
content: parsed.content
|
|
4211
|
+
};
|
|
4212
|
+
if (typeof parsed.timestamp === "string") {
|
|
4213
|
+
message.timestamp = parsed.timestamp;
|
|
4214
|
+
} else if (typeof parsed.timestamp === "number") {
|
|
4215
|
+
message.timestamp = new Date(parsed.timestamp * 1e3).toISOString();
|
|
4216
|
+
}
|
|
4217
|
+
convMap.get(convId).push(message);
|
|
4218
|
+
}
|
|
4219
|
+
const conversations = [];
|
|
4220
|
+
for (const [key, messages] of convMap) {
|
|
4221
|
+
if (messages.length === 0) continue;
|
|
4222
|
+
conversations.push({
|
|
4223
|
+
...key !== defaultKey && { id: key },
|
|
4224
|
+
messages,
|
|
4225
|
+
metadata: { source: "jsonl" }
|
|
4226
|
+
});
|
|
4227
|
+
}
|
|
4228
|
+
return conversations;
|
|
4229
|
+
}
|
|
4230
|
+
function isJSONLString(data) {
|
|
4231
|
+
if (typeof data !== "string") return false;
|
|
4232
|
+
const firstLine = data.split("\n").find((l) => l.trim() !== "");
|
|
4233
|
+
if (!firstLine) return false;
|
|
4234
|
+
try {
|
|
4235
|
+
const parsed = JSON.parse(firstLine);
|
|
4236
|
+
return typeof parsed === "object" && parsed !== null && typeof parsed.role === "string" && typeof parsed.content === "string";
|
|
4237
|
+
} catch {
|
|
4238
|
+
return false;
|
|
4239
|
+
}
|
|
4240
|
+
}
|
|
4241
|
+
|
|
4008
4242
|
// src/adapters/log-adapter.ts
|
|
4009
4243
|
function parseConversationLog(raw, format = "auto") {
|
|
4010
4244
|
if (format === "holomime") {
|
|
@@ -4020,6 +4254,16 @@ function parseConversationLog(raw, format = "auto") {
|
|
|
4020
4254
|
if (format === "openai-api") {
|
|
4021
4255
|
return parseOpenAIAPILog(raw);
|
|
4022
4256
|
}
|
|
4257
|
+
if (format === "anthropic-api") {
|
|
4258
|
+
return parseAnthropicAPILog(raw);
|
|
4259
|
+
}
|
|
4260
|
+
if (format === "otel") {
|
|
4261
|
+
return parseOTelGenAIExport(raw);
|
|
4262
|
+
}
|
|
4263
|
+
if (format === "jsonl") {
|
|
4264
|
+
if (typeof raw !== "string") throw new Error("JSONL format expects a raw string (not parsed JSON)");
|
|
4265
|
+
return parseJSONLLog(raw);
|
|
4266
|
+
}
|
|
4023
4267
|
const holomimeResult = conversationLogSchema.safeParse(raw);
|
|
4024
4268
|
if (holomimeResult.success) {
|
|
4025
4269
|
const log = holomimeResult.data;
|
|
@@ -4031,13 +4275,36 @@ function parseConversationLog(raw, format = "auto") {
|
|
|
4031
4275
|
if (isClaudeExport(raw)) {
|
|
4032
4276
|
return parseClaudeExport(raw);
|
|
4033
4277
|
}
|
|
4278
|
+
if (isAnthropicAPILog(raw)) {
|
|
4279
|
+
return parseAnthropicAPILog(raw);
|
|
4280
|
+
}
|
|
4034
4281
|
if (isOpenAIAPILog(raw)) {
|
|
4035
4282
|
return parseOpenAIAPILog(raw);
|
|
4036
4283
|
}
|
|
4284
|
+
if (isOTelGenAIExport(raw)) {
|
|
4285
|
+
return parseOTelGenAIExport(raw);
|
|
4286
|
+
}
|
|
4037
4287
|
throw new Error(
|
|
4038
|
-
"Unrecognized log format. Supported: holomime, chatgpt, claude, openai-api. Use --format to specify explicitly."
|
|
4288
|
+
"Unrecognized log format. Supported: holomime, chatgpt, claude, openai-api, anthropic-api, otel, jsonl. Use --format to specify explicitly."
|
|
4039
4289
|
);
|
|
4040
4290
|
}
|
|
4291
|
+
function parseConversationLogFromString(raw, format = "auto") {
|
|
4292
|
+
if (format === "jsonl") {
|
|
4293
|
+
return parseJSONLLog(raw);
|
|
4294
|
+
}
|
|
4295
|
+
if (format === "auto" && isJSONLString(raw)) {
|
|
4296
|
+
return parseJSONLLog(raw);
|
|
4297
|
+
}
|
|
4298
|
+
let parsed;
|
|
4299
|
+
try {
|
|
4300
|
+
parsed = JSON.parse(raw);
|
|
4301
|
+
} catch {
|
|
4302
|
+
throw new Error(
|
|
4303
|
+
"Failed to parse log file. If the file is JSONL (one JSON object per line), use --format jsonl."
|
|
4304
|
+
);
|
|
4305
|
+
}
|
|
4306
|
+
return parseConversationLog(parsed, format);
|
|
4307
|
+
}
|
|
4041
4308
|
function parseHolomime(raw) {
|
|
4042
4309
|
const result = conversationLogSchema.safeParse(raw);
|
|
4043
4310
|
if (!result.success) {
|
|
@@ -5362,9 +5629,13 @@ export {
|
|
|
5362
5629
|
loadTranscripts,
|
|
5363
5630
|
loadTreatmentPlan,
|
|
5364
5631
|
messageSchema,
|
|
5632
|
+
parseAnthropicAPILog,
|
|
5365
5633
|
parseChatGPTExport,
|
|
5366
5634
|
parseClaudeExport,
|
|
5367
5635
|
parseConversationLog,
|
|
5636
|
+
parseConversationLogFromString,
|
|
5637
|
+
parseJSONLLog,
|
|
5638
|
+
parseOTelGenAIExport,
|
|
5368
5639
|
parseOpenAIAPILog,
|
|
5369
5640
|
personalitySpecSchema,
|
|
5370
5641
|
providerSchema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holomime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Behavioral alignment infrastructure for AI agents — Big Five psychology, guided refinement, DPO training data",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -44,7 +44,19 @@
|
|
|
44
44
|
"alignment",
|
|
45
45
|
"behavioral-analysis",
|
|
46
46
|
"agent-training",
|
|
47
|
-
"system-prompt"
|
|
47
|
+
"system-prompt",
|
|
48
|
+
"opentelemetry",
|
|
49
|
+
"otel",
|
|
50
|
+
"genai",
|
|
51
|
+
"drift-detection",
|
|
52
|
+
"dpo",
|
|
53
|
+
"rlhf",
|
|
54
|
+
"fine-tuning",
|
|
55
|
+
"anthropic",
|
|
56
|
+
"openai",
|
|
57
|
+
"claude",
|
|
58
|
+
"agents-md",
|
|
59
|
+
"personality-json"
|
|
48
60
|
],
|
|
49
61
|
"author": "holomime <hello@holomime.dev>",
|
|
50
62
|
"license": "MIT",
|