mia-code 0.2.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/.claude/settings.local.json +9 -0
- package/.coaia/pde/d77620fc-1cd9-47e2-ba00-c03e114e42e9.jsonl +16 -0
- package/.coaia/pde/de44d838-b58b-4e91-b791-dd3b0f940ed1.jsonl +60 -0
- package/.gemini/settings.json +8 -0
- package/.hch/issue_.env +4 -0
- package/.hch/issue_add__2601211715.json +77 -0
- package/.hch/issue_add__2601211715.md +4 -0
- package/.hch/issue_add__2602242020.json +78 -0
- package/.hch/issue_add__2602242020.md +7 -0
- package/.hch/issues.json +2312 -0
- package/.hch/issues.md +30 -0
- package/260123084839.coaia-narrative.autoRevisionOfInitial_NewStructuralTensionChart-to-initiate-HierarchicalThinking.txt +5 -0
- package/2602010101.issue.txt +31 -0
- package/BUGS.md +242 -0
- package/CLAUDE.md +2 -0
- package/ENHANCEMENTS.md +129 -0
- package/FEATURES_ENDING_SESSIONS.md +21 -0
- package/FIXES.md +114 -0
- package/GUILLAUME.md +77 -0
- package/KINSHIP.md +50 -0
- package/LAUNCH__session_id__MiaCodeNextWorkReviewAndCommits_2601312020.sh +7 -0
- package/PHASE_2.md +153 -0
- package/PHASE_2_IMPLEMENTATION.md +134 -0
- package/README.md +203 -0
- package/RESUME__issueMaker__540244c2-b096-40d8-8c3f-398408d3e0eb.2602041757.sh +1 -0
- package/RUN_COPILOT_with_related_folders__260130.sh +2 -0
- package/WS__mia-code__260214__IAIP_PDE.code-workspace +29 -0
- package/WS__mia-code__src332__260122.code-workspace +23 -0
- package/_env.sh +12 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +679 -0
- package/dist/commands.d.ts +43 -0
- package/dist/commands.js +108 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +57 -0
- package/dist/formatting.d.ts +12 -0
- package/dist/formatting.js +133 -0
- package/dist/geminiHeadless.d.ts +25 -0
- package/dist/geminiHeadless.js +246 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +186 -0
- package/dist/mcp/config-generator.d.ts +23 -0
- package/dist/mcp/config-generator.js +116 -0
- package/dist/mcp/index.d.ts +18 -0
- package/dist/mcp/index.js +43 -0
- package/dist/mcp/miaco-server.d.ts +15 -0
- package/dist/mcp/miaco-server.js +161 -0
- package/dist/mcp/miatel-server.d.ts +15 -0
- package/dist/mcp/miatel-server.js +123 -0
- package/dist/mcp/miawa-server.d.ts +15 -0
- package/dist/mcp/miawa-server.js +125 -0
- package/dist/mcp/utils.d.ts +51 -0
- package/dist/mcp/utils.js +76 -0
- package/dist/multiline-input.d.ts +98 -0
- package/dist/multiline-input.js +630 -0
- package/dist/narrative/index.d.ts +9 -0
- package/dist/narrative/index.js +11 -0
- package/dist/narrative/router.d.ts +89 -0
- package/dist/narrative/router.js +186 -0
- package/dist/narrative/tracer.d.ts +75 -0
- package/dist/narrative/tracer.js +180 -0
- package/dist/sessionStore.d.ts +10 -0
- package/dist/sessionStore.js +93 -0
- package/dist/types.d.ts +44 -0
- package/dist/types.js +1 -0
- package/dist/unifier.d.ts +6 -0
- package/dist/unifier.js +147 -0
- package/issue-358--architecture/ARCHITECTURE_OVERVIEW.md +60 -0
- package/issue-358--architecture/CLI_INTEGRATION.md +61 -0
- package/issue-358--architecture/COVER_ART_BRIEF.md +68 -0
- package/issue-358--architecture/MEMORY_SYSTEM.md +89 -0
- package/issue-358--architecture/PERSONA_REGISTRY.md +97 -0
- package/issue-358--architecture/PODCAST_PRODUCTION_PLAN.md +61 -0
- package/issue-358--architecture/PODCAST_SCRIPT_FINAL.md +109 -0
- package/issue-358--architecture/PROTOTYPE_CHARACTER_SPEC.md +59 -0
- package/issue-358--architecture/RESOURCES.md +41 -0
- package/issue-358--architecture/TEAM_LISTENING_GUIDE.md +53 -0
- package/llms-gemini-cli.txt +145 -0
- package/package.json +39 -0
- package/samples/copilot/session-state/be76abaa-a27f-4725-b2a9-22fb45f7e0f7/checkpoints/index.md +6 -0
- package/samples/copilot/session-state/be76abaa-a27f-4725-b2a9-22fb45f7e0f7/events.jsonl +213 -0
- package/samples/copilot/session-state/be76abaa-a27f-4725-b2a9-22fb45f7e0f7/plan.md +243 -0
- package/samples/copilot/session-state/be76abaa-a27f-4725-b2a9-22fb45f7e0f7/workspace.yaml +5 -0
- package/src/cli.ts +742 -0
- package/src/commands.ts +127 -0
- package/src/config.ts +67 -0
- package/src/formatting.ts +157 -0
- package/src/geminiHeadless.ts +300 -0
- package/src/index.ts +194 -0
- package/src/mcp/config-generator.ts +141 -0
- package/src/mcp/index.ts +55 -0
- package/src/mcp/miaco-server.ts +199 -0
- package/src/mcp/miatel-server.ts +138 -0
- package/src/mcp/miawa-server.ts +158 -0
- package/src/mcp/utils.ts +121 -0
- package/src/multiline-input.ts +739 -0
- package/src/narrative/index.ts +33 -0
- package/src/narrative/router.ts +260 -0
- package/src/narrative/tracer.ts +249 -0
- package/src/sessionStore.ts +111 -0
- package/src/types.ts +49 -0
- package/src/unifier.ts +171 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrative Intelligence Integration for mia-code
|
|
3
|
+
*
|
|
4
|
+
* Exports the core narrative intelligence components:
|
|
5
|
+
* - NarrativeRouter: Routes events to miaco/miatel/miawa based on three-universe analysis
|
|
6
|
+
* - MiaCodeTracer: Observability for mia-code operations
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Router exports
|
|
10
|
+
export {
|
|
11
|
+
NarrativeRouter,
|
|
12
|
+
getNarrativeRouter,
|
|
13
|
+
MiaCodeEvent,
|
|
14
|
+
RoutingResult,
|
|
15
|
+
UNIVERSE_TO_CLI,
|
|
16
|
+
CLI_TO_UNIVERSE,
|
|
17
|
+
Universe,
|
|
18
|
+
ThreeUniverseAnalysis,
|
|
19
|
+
StoryBeat,
|
|
20
|
+
NarrativeFunction,
|
|
21
|
+
EmotionalTone,
|
|
22
|
+
CoherenceResult,
|
|
23
|
+
} from "./router.js";
|
|
24
|
+
|
|
25
|
+
// Tracer exports
|
|
26
|
+
export {
|
|
27
|
+
MiaCodeTracer,
|
|
28
|
+
getTracer,
|
|
29
|
+
removeTracer,
|
|
30
|
+
MiaCodeOperation,
|
|
31
|
+
NarrativeEventType,
|
|
32
|
+
NarrativeMetrics,
|
|
33
|
+
} from "./tracer.js";
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrative Intelligence Integration for mia-code
|
|
3
|
+
*
|
|
4
|
+
* Bridges the three-universe model from @langchain/langgraph-narrative-intelligence (that I publish as : ava-langchain-narrative-tracing and not @langchain/langgraph-narrative-intelligence)
|
|
5
|
+
* to mia-code's miaco/miatel/miawa architecture.
|
|
6
|
+
*
|
|
7
|
+
* Universe Mapping:
|
|
8
|
+
* - ENGINEER (Mia) → miaco (charts, technical precision)
|
|
9
|
+
* - CEREMONY (Ava8) → miawa (ceremonies, relational protocols)
|
|
10
|
+
* - STORY_ENGINE (Miette) → miatel (beats, narrative patterns)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
ThreeUniverseProcessor,
|
|
15
|
+
NarrativeCoherenceEngine,
|
|
16
|
+
Universe,
|
|
17
|
+
ThreeUniverseAnalysis,
|
|
18
|
+
StoryBeat,
|
|
19
|
+
createStoryBeat,
|
|
20
|
+
NarrativeFunction,
|
|
21
|
+
CoherenceResult,
|
|
22
|
+
EmotionalTone,
|
|
23
|
+
classifyEmotionalTone,
|
|
24
|
+
} from "ava-langgraph-narrative-intelligence";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Maps universe to mia-code CLI
|
|
28
|
+
*/
|
|
29
|
+
export const UNIVERSE_TO_CLI: Record<Universe, string> = {
|
|
30
|
+
[Universe.ENGINEER]: "miaco",
|
|
31
|
+
[Universe.CEREMONY]: "miawa",
|
|
32
|
+
[Universe.STORY_ENGINE]: "miatel",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Maps CLI to universe
|
|
37
|
+
*/
|
|
38
|
+
export const CLI_TO_UNIVERSE: Record<string, Universe> = {
|
|
39
|
+
miaco: Universe.ENGINEER,
|
|
40
|
+
miawa: Universe.CEREMONY,
|
|
41
|
+
miatel: Universe.STORY_ENGINE,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Mia-code event that can be analyzed through three universes
|
|
46
|
+
*/
|
|
47
|
+
export interface MiaCodeEvent {
|
|
48
|
+
id: string;
|
|
49
|
+
type: "user_input" | "agent_action" | "chart_update" | "beat_created" | "ceremony_action";
|
|
50
|
+
content: string;
|
|
51
|
+
source?: "miaco" | "miatel" | "miawa";
|
|
52
|
+
metadata?: Record<string, unknown>;
|
|
53
|
+
timestamp?: Date;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Result of routing decision
|
|
58
|
+
*/
|
|
59
|
+
export interface RoutingResult {
|
|
60
|
+
leadCli: "miaco" | "miatel" | "miawa";
|
|
61
|
+
leadUniverse: Universe;
|
|
62
|
+
analysis: ThreeUniverseAnalysis;
|
|
63
|
+
suggestedAction: string;
|
|
64
|
+
coherence: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* NarrativeRouter - Routes events to the appropriate mia-code CLI
|
|
69
|
+
* based on three-universe analysis
|
|
70
|
+
*/
|
|
71
|
+
export class NarrativeRouter {
|
|
72
|
+
private processor: ThreeUniverseProcessor;
|
|
73
|
+
private coherenceEngine: NarrativeCoherenceEngine;
|
|
74
|
+
private beatHistory: StoryBeat[] = [];
|
|
75
|
+
private beatSequence: number = 0;
|
|
76
|
+
|
|
77
|
+
constructor() {
|
|
78
|
+
this.processor = new ThreeUniverseProcessor();
|
|
79
|
+
this.coherenceEngine = new NarrativeCoherenceEngine();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Analyze an event and determine the best CLI to handle it
|
|
84
|
+
*/
|
|
85
|
+
route(event: MiaCodeEvent): RoutingResult {
|
|
86
|
+
// Convert to format expected by processor
|
|
87
|
+
const processedEvent = {
|
|
88
|
+
content: event.content,
|
|
89
|
+
type: event.type,
|
|
90
|
+
source: event.source,
|
|
91
|
+
...event.metadata,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Run three-universe analysis
|
|
95
|
+
const analysis = this.processor.process(processedEvent, this.mapEventType(event.type));
|
|
96
|
+
|
|
97
|
+
// Map lead universe to CLI
|
|
98
|
+
const leadCli = UNIVERSE_TO_CLI[analysis.leadUniverse] as "miaco" | "miatel" | "miawa";
|
|
99
|
+
|
|
100
|
+
// Determine suggested action based on analysis
|
|
101
|
+
const suggestedAction = this.deriveSuggestedAction(analysis);
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
leadCli,
|
|
105
|
+
leadUniverse: analysis.leadUniverse,
|
|
106
|
+
analysis,
|
|
107
|
+
suggestedAction,
|
|
108
|
+
coherence: analysis.coherenceScore,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Record a story beat and update coherence tracking
|
|
114
|
+
*/
|
|
115
|
+
recordBeat(content: string, cli: "miaco" | "miatel" | "miawa"): StoryBeat {
|
|
116
|
+
this.beatSequence++;
|
|
117
|
+
|
|
118
|
+
// Classify emotional tone
|
|
119
|
+
const toneResult = classifyEmotionalTone(content);
|
|
120
|
+
|
|
121
|
+
// Determine narrative function from content
|
|
122
|
+
const narrativeFunction = this.inferNarrativeFunction(content);
|
|
123
|
+
|
|
124
|
+
// Map CLI to universe
|
|
125
|
+
const leadUniverse = CLI_TO_UNIVERSE[cli];
|
|
126
|
+
|
|
127
|
+
// Create the beat
|
|
128
|
+
const beat = createStoryBeat(
|
|
129
|
+
`beat_${this.beatSequence}`,
|
|
130
|
+
this.beatSequence,
|
|
131
|
+
content,
|
|
132
|
+
narrativeFunction,
|
|
133
|
+
Math.ceil(this.beatSequence / 10), // Rough act calculation
|
|
134
|
+
{
|
|
135
|
+
emotionalTone: toneResult.classification,
|
|
136
|
+
leadUniverse,
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
this.beatHistory.push(beat);
|
|
141
|
+
return beat;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Analyze coherence of accumulated beats
|
|
146
|
+
*/
|
|
147
|
+
analyzeCoherence(): CoherenceResult | null {
|
|
148
|
+
if (this.beatHistory.length === 0) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const result = this.coherenceEngine.analyze(this.beatHistory);
|
|
152
|
+
// Handle case where result is CoherenceEngineState
|
|
153
|
+
if ('coherenceScore' in result && result.coherenceScore) {
|
|
154
|
+
return result as CoherenceResult;
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get trinity assessment (Mia/Miette/Ava8 perspectives on quality)
|
|
161
|
+
*/
|
|
162
|
+
getTrinityAssessment(): { mia: string; miette: string; ava8: string } | null {
|
|
163
|
+
const result = this.analyzeCoherence();
|
|
164
|
+
if (!result) return null;
|
|
165
|
+
return {
|
|
166
|
+
mia: result.trinityAssessment.mia,
|
|
167
|
+
miette: result.trinityAssessment.miette,
|
|
168
|
+
ava8: result.trinityAssessment.ava8,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Get gaps that need addressing
|
|
174
|
+
*/
|
|
175
|
+
getGaps(): Array<{ type: string; severity: string; description: string }> {
|
|
176
|
+
const result = this.analyzeCoherence();
|
|
177
|
+
if (!result) return [];
|
|
178
|
+
return result.gaps.map(gap => ({
|
|
179
|
+
type: gap.gapType,
|
|
180
|
+
severity: gap.severity,
|
|
181
|
+
description: gap.description,
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Reset the router (clear beat history)
|
|
187
|
+
*/
|
|
188
|
+
reset(): void {
|
|
189
|
+
this.beatHistory = [];
|
|
190
|
+
this.beatSequence = 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private mapEventType(type: MiaCodeEvent["type"]): string {
|
|
194
|
+
const mapping: Record<string, string> = {
|
|
195
|
+
user_input: "user.input",
|
|
196
|
+
agent_action: "agent.action",
|
|
197
|
+
chart_update: "github.push",
|
|
198
|
+
beat_created: "agent.action",
|
|
199
|
+
ceremony_action: "system.event",
|
|
200
|
+
};
|
|
201
|
+
return mapping[type] || "system.event";
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private inferNarrativeFunction(content: string): NarrativeFunction {
|
|
205
|
+
const lower = content.toLowerCase();
|
|
206
|
+
|
|
207
|
+
if (lower.includes("begin") || lower.includes("start") || lower.includes("init")) {
|
|
208
|
+
return NarrativeFunction.INCITING_INCIDENT;
|
|
209
|
+
}
|
|
210
|
+
if (lower.includes("complete") || lower.includes("finish") || lower.includes("done")) {
|
|
211
|
+
return NarrativeFunction.RESOLUTION;
|
|
212
|
+
}
|
|
213
|
+
if (lower.includes("problem") || lower.includes("issue") || lower.includes("bug")) {
|
|
214
|
+
return NarrativeFunction.COMPLICATION;
|
|
215
|
+
}
|
|
216
|
+
if (lower.includes("fix") || lower.includes("resolve") || lower.includes("solved")) {
|
|
217
|
+
return NarrativeFunction.RESOLUTION;
|
|
218
|
+
}
|
|
219
|
+
if (lower.includes("major") || lower.includes("significant") || lower.includes("breakthrough")) {
|
|
220
|
+
return NarrativeFunction.TURNING_POINT;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return NarrativeFunction.RISING_ACTION;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private deriveSuggestedAction(analysis: ThreeUniverseAnalysis): string {
|
|
227
|
+
const engineer = analysis.engineer;
|
|
228
|
+
const ceremony = analysis.ceremony;
|
|
229
|
+
const storyEngine = analysis.storyEngine;
|
|
230
|
+
|
|
231
|
+
// Use highest confidence perspective's suggestion
|
|
232
|
+
if (engineer.confidence >= ceremony.confidence && engineer.confidence >= storyEngine.confidence) {
|
|
233
|
+
return engineer.suggestedFlows[0] || "analyze";
|
|
234
|
+
}
|
|
235
|
+
if (ceremony.confidence >= storyEngine.confidence) {
|
|
236
|
+
return ceremony.suggestedFlows[0] || "witness";
|
|
237
|
+
}
|
|
238
|
+
return storyEngine.suggestedFlows[0] || "narrate";
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Re-export useful types
|
|
243
|
+
export {
|
|
244
|
+
Universe,
|
|
245
|
+
ThreeUniverseAnalysis,
|
|
246
|
+
StoryBeat,
|
|
247
|
+
NarrativeFunction,
|
|
248
|
+
EmotionalTone,
|
|
249
|
+
CoherenceResult,
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// Export singleton for easy use
|
|
253
|
+
let routerInstance: NarrativeRouter | null = null;
|
|
254
|
+
|
|
255
|
+
export function getNarrativeRouter(): NarrativeRouter {
|
|
256
|
+
if (!routerInstance) {
|
|
257
|
+
routerInstance = new NarrativeRouter();
|
|
258
|
+
}
|
|
259
|
+
return routerInstance;
|
|
260
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrative Tracing Integration for mia-code
|
|
3
|
+
*
|
|
4
|
+
* Integrates @langchain/narrative-tracing for observability that I published as : ava-langchain-narrative-tracing and not @langchain/narrative-tracing
|
|
5
|
+
* across mia-code operations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
NarrativeTracingHandler,
|
|
10
|
+
NarrativeEventType,
|
|
11
|
+
NarrativeMetrics,
|
|
12
|
+
createNarrativeMetrics,
|
|
13
|
+
} from "ava-langchain-narrative-tracing";
|
|
14
|
+
|
|
15
|
+
import { Universe, ThreeUniverseAnalysis } from "./router.js";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* mia-code operation types
|
|
19
|
+
*/
|
|
20
|
+
export type MiaCodeOperation =
|
|
21
|
+
| "chart_create"
|
|
22
|
+
| "chart_update"
|
|
23
|
+
| "chart_complete"
|
|
24
|
+
| "beat_create"
|
|
25
|
+
| "beat_analyze"
|
|
26
|
+
| "ceremony_init"
|
|
27
|
+
| "ceremony_advance"
|
|
28
|
+
| "user_input"
|
|
29
|
+
| "agent_response"
|
|
30
|
+
| "routing_decision";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* MiaCodeTracer - Wraps NarrativeTracingHandler for mia-code specific operations
|
|
34
|
+
*/
|
|
35
|
+
export class MiaCodeTracer {
|
|
36
|
+
private handler: NarrativeTracingHandler;
|
|
37
|
+
private metrics: NarrativeMetrics;
|
|
38
|
+
private sessionId: string;
|
|
39
|
+
private startTime: number;
|
|
40
|
+
|
|
41
|
+
constructor(options: {
|
|
42
|
+
sessionId: string;
|
|
43
|
+
storyId?: string;
|
|
44
|
+
publicKey?: string;
|
|
45
|
+
secretKey?: string;
|
|
46
|
+
}) {
|
|
47
|
+
this.sessionId = options.sessionId;
|
|
48
|
+
this.startTime = Date.now();
|
|
49
|
+
|
|
50
|
+
this.handler = new NarrativeTracingHandler({
|
|
51
|
+
storyId: options.storyId || `mia_${options.sessionId}`,
|
|
52
|
+
sessionId: options.sessionId,
|
|
53
|
+
publicKey: options.publicKey || process.env.LANGFUSE_PUBLIC_KEY,
|
|
54
|
+
secretKey: options.secretKey || process.env.LANGFUSE_SECRET_KEY,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
this.metrics = createNarrativeMetrics();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Start tracing a session
|
|
62
|
+
*/
|
|
63
|
+
startSession(): string {
|
|
64
|
+
const traceId = this.handler.startStoryGeneration();
|
|
65
|
+
return traceId;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Log a chart operation (miaco)
|
|
70
|
+
*/
|
|
71
|
+
logChartOperation(
|
|
72
|
+
chartId: string,
|
|
73
|
+
operation: "create" | "update" | "complete" | "add_step",
|
|
74
|
+
data: Record<string, unknown>
|
|
75
|
+
): void {
|
|
76
|
+
this.handler.logEvent({
|
|
77
|
+
eventType: NarrativeEventType.BEAT_CREATED,
|
|
78
|
+
beatId: chartId,
|
|
79
|
+
metadata: {
|
|
80
|
+
cli: "miaco",
|
|
81
|
+
operation,
|
|
82
|
+
...data,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
this.metrics.beatsGenerated++;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Log a beat operation (miatel)
|
|
90
|
+
*/
|
|
91
|
+
logBeatOperation(
|
|
92
|
+
beatId: string,
|
|
93
|
+
content: string,
|
|
94
|
+
sequence: number,
|
|
95
|
+
narrativeFunction: string
|
|
96
|
+
): void {
|
|
97
|
+
this.handler.logBeatCreation(
|
|
98
|
+
beatId,
|
|
99
|
+
content,
|
|
100
|
+
sequence,
|
|
101
|
+
narrativeFunction
|
|
102
|
+
);
|
|
103
|
+
this.metrics.beatsGenerated++;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Log a ceremony operation (miawa)
|
|
108
|
+
*/
|
|
109
|
+
logCeremonyOperation(
|
|
110
|
+
ceremonyId: string,
|
|
111
|
+
operation: "init" | "advance" | "close",
|
|
112
|
+
movement?: string,
|
|
113
|
+
data?: Record<string, unknown>
|
|
114
|
+
): void {
|
|
115
|
+
this.handler.logEvent({
|
|
116
|
+
eventType: NarrativeEventType.CHARACTER_ARC_UPDATED,
|
|
117
|
+
metadata: {
|
|
118
|
+
cli: "miawa",
|
|
119
|
+
operation,
|
|
120
|
+
movement,
|
|
121
|
+
ceremonyId,
|
|
122
|
+
...data,
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Log a three-universe routing decision
|
|
129
|
+
*/
|
|
130
|
+
logRoutingDecision(analysis: ThreeUniverseAnalysis, targetCli: string): void {
|
|
131
|
+
this.handler.logThreeUniverseAnalysis({
|
|
132
|
+
eventId: `route_${Date.now()}`,
|
|
133
|
+
engineerIntent: analysis.engineer.intent,
|
|
134
|
+
engineerConfidence: analysis.engineer.confidence,
|
|
135
|
+
ceremonyIntent: analysis.ceremony.intent,
|
|
136
|
+
ceremonyConfidence: analysis.ceremony.confidence,
|
|
137
|
+
storyEngineIntent: analysis.storyEngine.intent,
|
|
138
|
+
storyEngineConfidence: analysis.storyEngine.confidence,
|
|
139
|
+
leadUniverse: this.universeToString(analysis.leadUniverse),
|
|
140
|
+
coherenceScore: analysis.coherenceScore,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
this.handler.logRoutingDecision({
|
|
144
|
+
decisionId: `decision_${Date.now()}`,
|
|
145
|
+
backend: targetCli,
|
|
146
|
+
flow: analysis.engineer.suggestedFlows[0] || "default",
|
|
147
|
+
score: analysis.coherenceScore,
|
|
148
|
+
leadUniverse: this.universeToString(analysis.leadUniverse),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
this.metrics.routingDecisions++;
|
|
152
|
+
|
|
153
|
+
// Update alignment metrics
|
|
154
|
+
this.metrics.engineerAlignment =
|
|
155
|
+
(this.metrics.engineerAlignment + analysis.engineer.confidence) / 2;
|
|
156
|
+
this.metrics.ceremonyAlignment =
|
|
157
|
+
(this.metrics.ceremonyAlignment + analysis.ceremony.confidence) / 2;
|
|
158
|
+
this.metrics.storyEngineAlignment =
|
|
159
|
+
(this.metrics.storyEngineAlignment + analysis.storyEngine.confidence) / 2;
|
|
160
|
+
this.metrics.crossUniverseCoherence =
|
|
161
|
+
(this.metrics.crossUniverseCoherence + analysis.coherenceScore) / 2;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Log a gap identified in the narrative
|
|
166
|
+
*/
|
|
167
|
+
logGap(type: string, severity: number, description: string): void {
|
|
168
|
+
this.handler.logGapIdentified(type, description, severity);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Log user input
|
|
173
|
+
*/
|
|
174
|
+
logUserInput(content: string): void {
|
|
175
|
+
this.handler.logEvent({
|
|
176
|
+
eventType: NarrativeEventType.BEAT_CREATED,
|
|
177
|
+
beatId: `input_${Date.now()}`,
|
|
178
|
+
metadata: { type: "user_input", content: content.slice(0, 200) },
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Log agent response
|
|
184
|
+
*/
|
|
185
|
+
logAgentResponse(content: string, cli: string): void {
|
|
186
|
+
this.handler.logEvent({
|
|
187
|
+
eventType: NarrativeEventType.BEAT_ENRICHED,
|
|
188
|
+
beatId: `response_${Date.now()}`,
|
|
189
|
+
metadata: { type: "agent_response", cli, content: content.slice(0, 200) },
|
|
190
|
+
});
|
|
191
|
+
this.metrics.enrichmentsApplied++;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Get correlation headers for external calls
|
|
196
|
+
*/
|
|
197
|
+
getCorrelationHeaders(): Record<string, string> {
|
|
198
|
+
return {
|
|
199
|
+
"X-Mia-Session-Id": this.sessionId,
|
|
200
|
+
"X-Mia-Trace-Start": this.startTime.toString(),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Get current metrics
|
|
206
|
+
*/
|
|
207
|
+
getMetrics(): NarrativeMetrics {
|
|
208
|
+
this.metrics.totalGenerationTimeMs = Date.now() - this.startTime;
|
|
209
|
+
if (this.metrics.beatsGenerated > 0) {
|
|
210
|
+
this.metrics.averageBeatTimeMs =
|
|
211
|
+
this.metrics.totalGenerationTimeMs / this.metrics.beatsGenerated;
|
|
212
|
+
}
|
|
213
|
+
return { ...this.metrics };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* End session and flush traces
|
|
218
|
+
*/
|
|
219
|
+
async endSession(): Promise<void> {
|
|
220
|
+
this.handler.endStoryGeneration(Date.now() - this.startTime);
|
|
221
|
+
await this.handler.flush();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private universeToString(universe: Universe): string {
|
|
225
|
+
const mapping: Record<Universe, string> = {
|
|
226
|
+
[Universe.ENGINEER]: "engineer",
|
|
227
|
+
[Universe.CEREMONY]: "ceremony",
|
|
228
|
+
[Universe.STORY_ENGINE]: "story_engine",
|
|
229
|
+
};
|
|
230
|
+
return mapping[universe] || "unknown";
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Export types
|
|
235
|
+
export { NarrativeEventType, NarrativeMetrics };
|
|
236
|
+
|
|
237
|
+
// Singleton tracer instance per session
|
|
238
|
+
const tracers: Map<string, MiaCodeTracer> = new Map();
|
|
239
|
+
|
|
240
|
+
export function getTracer(sessionId: string): MiaCodeTracer {
|
|
241
|
+
if (!tracers.has(sessionId)) {
|
|
242
|
+
tracers.set(sessionId, new MiaCodeTracer({ sessionId }));
|
|
243
|
+
}
|
|
244
|
+
return tracers.get(sessionId)!;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function removeTracer(sessionId: string): void {
|
|
248
|
+
tracers.delete(sessionId);
|
|
249
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import { MiaCodeSessionMeta, ChatMessage } from "./types.js";
|
|
5
|
+
|
|
6
|
+
const SESSIONS_FILE = path.join(os.homedir(), ".mia-code-sessions.json");
|
|
7
|
+
const HISTORY_DIR = path.join(os.homedir(), ".mia-code-history");
|
|
8
|
+
|
|
9
|
+
interface SessionIndex {
|
|
10
|
+
byProjectRoot: Record<string, MiaCodeSessionMeta>;
|
|
11
|
+
byId: Record<string, MiaCodeSessionMeta>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function loadIndex(): SessionIndex {
|
|
15
|
+
if (!fs.existsSync(SESSIONS_FILE)) {
|
|
16
|
+
return { byProjectRoot: {}, byId: {} };
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const raw = fs.readFileSync(SESSIONS_FILE, "utf8");
|
|
20
|
+
const parsed = JSON.parse(raw) as SessionIndex;
|
|
21
|
+
return {
|
|
22
|
+
byProjectRoot: parsed.byProjectRoot || {},
|
|
23
|
+
byId: parsed.byId || {}
|
|
24
|
+
};
|
|
25
|
+
} catch {
|
|
26
|
+
return { byProjectRoot: {}, byId: {} };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function saveIndex(index: SessionIndex): void {
|
|
31
|
+
fs.writeFileSync(SESSIONS_FILE, JSON.stringify(index, null, 2), "utf8");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function rememberSession(meta: MiaCodeSessionMeta): void {
|
|
35
|
+
const idx = loadIndex();
|
|
36
|
+
if (meta.projectRoot) {
|
|
37
|
+
idx.byProjectRoot[meta.projectRoot] = meta;
|
|
38
|
+
}
|
|
39
|
+
idx.byId[meta.id] = meta;
|
|
40
|
+
saveIndex(idx);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function markSessionInitialized(id: string): void {
|
|
44
|
+
const idx = loadIndex();
|
|
45
|
+
const session = idx.byId[id];
|
|
46
|
+
if (session) {
|
|
47
|
+
session.initialized = true;
|
|
48
|
+
if (session.projectRoot) {
|
|
49
|
+
idx.byProjectRoot[session.projectRoot] = session;
|
|
50
|
+
}
|
|
51
|
+
saveIndex(idx);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isSessionInitialized(id: string): boolean {
|
|
56
|
+
const idx = loadIndex();
|
|
57
|
+
return idx.byId[id]?.initialized ?? false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function getLastSessionForProject(projectRoot: string): MiaCodeSessionMeta | null {
|
|
61
|
+
const idx = loadIndex();
|
|
62
|
+
return idx.byProjectRoot[projectRoot] ?? null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function getSessionById(id: string): MiaCodeSessionMeta | null {
|
|
66
|
+
const idx = loadIndex();
|
|
67
|
+
return idx.byId[id] ?? null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function listSessions(): MiaCodeSessionMeta[] {
|
|
71
|
+
const idx = loadIndex();
|
|
72
|
+
return Object.values(idx.byId);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function clearSessions(): void {
|
|
76
|
+
saveIndex({ byProjectRoot: {}, byId: {} });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ── Chat history persistence ────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
function ensureHistoryDir(): void {
|
|
82
|
+
if (!fs.existsSync(HISTORY_DIR)) {
|
|
83
|
+
fs.mkdirSync(HISTORY_DIR, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function historyFile(sessionId: string): string {
|
|
88
|
+
// Sanitize session ID for safe filenames
|
|
89
|
+
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
90
|
+
return path.join(HISTORY_DIR, `${safe}.jsonl`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function saveChatMessage(sessionId: string, msg: ChatMessage): void {
|
|
94
|
+
ensureHistoryDir();
|
|
95
|
+
const line = JSON.stringify(msg) + "\n";
|
|
96
|
+
fs.appendFileSync(historyFile(sessionId), line, "utf8");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function loadChatHistory(sessionId: string): ChatMessage[] {
|
|
100
|
+
const file = historyFile(sessionId);
|
|
101
|
+
if (!fs.existsSync(file)) return [];
|
|
102
|
+
try {
|
|
103
|
+
const raw = fs.readFileSync(file, "utf8");
|
|
104
|
+
return raw
|
|
105
|
+
.split("\n")
|
|
106
|
+
.filter(l => l.trim())
|
|
107
|
+
.map(l => JSON.parse(l) as ChatMessage);
|
|
108
|
+
} catch {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type Role = "user" | "assistant" | "system";
|
|
2
|
+
|
|
3
|
+
export type Engine = "gemini" | "claude" | "copilot";
|
|
4
|
+
|
|
5
|
+
export interface MiaCodeConfig {
|
|
6
|
+
engine: Engine;
|
|
7
|
+
geminiBinary: string;
|
|
8
|
+
claudeBinary: string;
|
|
9
|
+
copilotBinary: string;
|
|
10
|
+
model: string;
|
|
11
|
+
headlessOutputFormat: "json" | "stream-json";
|
|
12
|
+
defaultMode: "code" | "chat";
|
|
13
|
+
defaultProjectRoot: string | null;
|
|
14
|
+
yoloMode: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface MiaCodeSessionMeta {
|
|
18
|
+
id: string;
|
|
19
|
+
startedAt: string;
|
|
20
|
+
model: string;
|
|
21
|
+
projectRoot: string | null;
|
|
22
|
+
initialized?: boolean; // Has engine acknowledged this session?
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ChatMessage {
|
|
26
|
+
role: "user" | "assistant";
|
|
27
|
+
text: string;
|
|
28
|
+
timestamp: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface GeminiJsonEvent {
|
|
32
|
+
type: "init" | "message" | "tool_use" | "tool_result" | "error" | "result" | string;
|
|
33
|
+
session_id?: string;
|
|
34
|
+
timestamp?: string;
|
|
35
|
+
role?: Role;
|
|
36
|
+
text?: string;
|
|
37
|
+
content?: string;
|
|
38
|
+
tool?: {
|
|
39
|
+
name: string;
|
|
40
|
+
input: unknown;
|
|
41
|
+
};
|
|
42
|
+
result?: unknown;
|
|
43
|
+
error?: {
|
|
44
|
+
code: string;
|
|
45
|
+
message: string;
|
|
46
|
+
};
|
|
47
|
+
raw?: unknown;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|