@vainplex/openclaw-cortex 0.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/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/src/boot-context.d.ts +43 -0
- package/dist/src/boot-context.d.ts.map +1 -0
- package/dist/src/boot-context.js +215 -0
- package/dist/src/boot-context.js.map +1 -0
- package/dist/src/config.d.ts +10 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +100 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/decision-tracker.d.ts +48 -0
- package/dist/src/decision-tracker.d.ts.map +1 -0
- package/dist/src/decision-tracker.js +135 -0
- package/dist/src/decision-tracker.js.map +1 -0
- package/dist/src/hooks.d.ts +7 -0
- package/dist/src/hooks.d.ts.map +1 -0
- package/dist/src/hooks.js +104 -0
- package/dist/src/hooks.js.map +1 -0
- package/dist/src/narrative-generator.d.ts +34 -0
- package/dist/src/narrative-generator.d.ts.map +1 -0
- package/dist/src/narrative-generator.js +153 -0
- package/dist/src/narrative-generator.js.map +1 -0
- package/dist/src/patterns.d.ts +24 -0
- package/dist/src/patterns.d.ts.map +1 -0
- package/dist/src/patterns.js +98 -0
- package/dist/src/patterns.js.map +1 -0
- package/dist/src/pre-compaction.d.ts +21 -0
- package/dist/src/pre-compaction.d.ts.map +1 -0
- package/dist/src/pre-compaction.js +108 -0
- package/dist/src/pre-compaction.js.map +1 -0
- package/dist/src/storage.d.ts +44 -0
- package/dist/src/storage.d.ts.map +1 -0
- package/dist/src/storage.js +126 -0
- package/dist/src/storage.js.map +1 -0
- package/dist/src/thread-tracker.d.ts +75 -0
- package/dist/src/thread-tracker.d.ts.map +1 -0
- package/dist/src/thread-tracker.js +250 -0
- package/dist/src/thread-tracker.js.map +1 -0
- package/dist/src/types.d.ts +202 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +24 -0
- package/dist/src/types.js.map +1 -0
- package/openclaw.plugin.json +154 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vainplex
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# @vainplex/openclaw-cortex
|
|
2
|
+
|
|
3
|
+
> Conversation intelligence layer for [OpenClaw](https://github.com/openclaw/openclaw) — automated thread tracking, decision extraction, boot context generation, and pre-compaction snapshots.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@vainplex/openclaw-cortex)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## What It Does
|
|
9
|
+
|
|
10
|
+
`openclaw-cortex` listens to OpenClaw message hooks and automatically:
|
|
11
|
+
|
|
12
|
+
- **📋 Tracks conversation threads** — detects topic shifts, closures, decisions, and blocking items
|
|
13
|
+
- **🎯 Extracts decisions** — recognizes when decisions are made (English + German) and logs them
|
|
14
|
+
- **🚀 Generates boot context** — assembles a dense `BOOTSTRAP.md` at session start so the agent has continuity
|
|
15
|
+
- **📸 Pre-compaction snapshots** — saves thread state + hot snapshot before memory compaction
|
|
16
|
+
- **📖 Structured narratives** — generates 24h activity summaries from threads + decisions
|
|
17
|
+
|
|
18
|
+
Works **alongside** `memory-core` (OpenClaw's built-in memory) — doesn't replace it.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# From npm
|
|
24
|
+
npm install @vainplex/openclaw-cortex
|
|
25
|
+
|
|
26
|
+
# Copy to OpenClaw extensions
|
|
27
|
+
cp -r node_modules/@vainplex/openclaw-cortex ~/.openclaw/extensions/openclaw-cortex
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or clone directly:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd ~/.openclaw/extensions
|
|
34
|
+
git clone https://github.com/alberthild/openclaw-cortex.git
|
|
35
|
+
cd openclaw-cortex && npm install && npm run build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Configure
|
|
39
|
+
|
|
40
|
+
Add to your OpenClaw config:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"plugins": {
|
|
45
|
+
"openclaw-cortex": {
|
|
46
|
+
"enabled": true,
|
|
47
|
+
"patterns": {
|
|
48
|
+
"language": "both"
|
|
49
|
+
},
|
|
50
|
+
"threadTracker": {
|
|
51
|
+
"enabled": true,
|
|
52
|
+
"pruneDays": 7,
|
|
53
|
+
"maxThreads": 50
|
|
54
|
+
},
|
|
55
|
+
"decisionTracker": {
|
|
56
|
+
"enabled": true,
|
|
57
|
+
"maxDecisions": 100,
|
|
58
|
+
"dedupeWindowHours": 24
|
|
59
|
+
},
|
|
60
|
+
"bootContext": {
|
|
61
|
+
"enabled": true,
|
|
62
|
+
"maxChars": 16000,
|
|
63
|
+
"onSessionStart": true,
|
|
64
|
+
"maxThreadsInBoot": 7,
|
|
65
|
+
"maxDecisionsInBoot": 10,
|
|
66
|
+
"decisionRecencyDays": 14
|
|
67
|
+
},
|
|
68
|
+
"preCompaction": {
|
|
69
|
+
"enabled": true,
|
|
70
|
+
"maxSnapshotMessages": 15
|
|
71
|
+
},
|
|
72
|
+
"narrative": {
|
|
73
|
+
"enabled": true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Restart OpenClaw after configuring.
|
|
81
|
+
|
|
82
|
+
## How It Works
|
|
83
|
+
|
|
84
|
+
### Hooks
|
|
85
|
+
|
|
86
|
+
| Hook | Feature | Priority |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| `message_received` | Thread + Decision Tracking | 100 |
|
|
89
|
+
| `message_sent` | Thread + Decision Tracking | 100 |
|
|
90
|
+
| `session_start` | Boot Context Generation | 10 |
|
|
91
|
+
| `before_compaction` | Pre-Compaction Snapshot | 5 |
|
|
92
|
+
| `after_compaction` | Logging | 200 |
|
|
93
|
+
|
|
94
|
+
### Output Files
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
{workspace}/
|
|
98
|
+
├── BOOTSTRAP.md # Dense boot context (regenerated each session)
|
|
99
|
+
└── memory/
|
|
100
|
+
└── reboot/
|
|
101
|
+
├── threads.json # Thread state
|
|
102
|
+
├── decisions.json # Decision log
|
|
103
|
+
├── narrative.md # 24h activity summary
|
|
104
|
+
└── hot-snapshot.md # Pre-compaction snapshot
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Pattern Languages
|
|
108
|
+
|
|
109
|
+
Thread and decision detection supports English, German, or both:
|
|
110
|
+
|
|
111
|
+
- **Decision patterns**: "we decided", "let's do", "the plan is", "wir machen", "beschlossen"
|
|
112
|
+
- **Closure patterns**: "is done", "it works", "fixed ✅", "erledigt", "gefixt"
|
|
113
|
+
- **Wait patterns**: "waiting for", "blocked by", "warte auf"
|
|
114
|
+
- **Topic patterns**: "back to", "now about", "jetzt zu", "bzgl."
|
|
115
|
+
- **Mood detection**: frustrated, excited, tense, productive, exploratory
|
|
116
|
+
|
|
117
|
+
### Graceful Degradation
|
|
118
|
+
|
|
119
|
+
- Read-only workspace → runs in-memory, skips writes
|
|
120
|
+
- Corrupt JSON → starts fresh, next write recovers
|
|
121
|
+
- Missing directories → creates them automatically
|
|
122
|
+
- Hook errors → caught and logged, never crashes the gateway
|
|
123
|
+
|
|
124
|
+
## Development
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npm install
|
|
128
|
+
npm test # 270 tests
|
|
129
|
+
npm run typecheck # TypeScript strict mode
|
|
130
|
+
npm run build # Compile to dist/
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Performance
|
|
134
|
+
|
|
135
|
+
- Zero runtime dependencies (Node built-ins only)
|
|
136
|
+
- All hook handlers are non-blocking (fire-and-forget)
|
|
137
|
+
- Atomic file writes via `.tmp` + rename
|
|
138
|
+
- Tested with 270 unit + integration tests
|
|
139
|
+
|
|
140
|
+
## Architecture
|
|
141
|
+
|
|
142
|
+
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the full design document including module diagrams, data flows, type definitions, and testing strategy.
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT — see [LICENSE](LICENSE)
|
|
147
|
+
|
|
148
|
+
## Related
|
|
149
|
+
|
|
150
|
+
- [@vainplex/nats-eventstore](https://www.npmjs.com/package/@vainplex/nats-eventstore) — Publish OpenClaw events to NATS JetStream
|
|
151
|
+
- [OpenClaw](https://github.com/openclaw/openclaw) — Multi-channel AI gateway
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "./src/types.js";
|
|
2
|
+
declare const plugin: {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
version: string;
|
|
7
|
+
register(api: OpenClawPluginApi): void;
|
|
8
|
+
};
|
|
9
|
+
export default plugin;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAe,MAAM,gBAAgB,CAAC;AAErE,QAAA,MAAM,MAAM;;;;;kBAOI,iBAAiB;CA8ChC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { registerCortexHooks } from "./src/hooks.js";
|
|
2
|
+
import { resolveConfig, resolveWorkspace } from "./src/config.js";
|
|
3
|
+
import { loadJson, rebootDir } from "./src/storage.js";
|
|
4
|
+
const plugin = {
|
|
5
|
+
id: "openclaw-cortex",
|
|
6
|
+
name: "OpenClaw Cortex",
|
|
7
|
+
description: "Conversation intelligence — thread tracking, decision extraction, boot context, pre-compaction snapshots",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
register(api) {
|
|
10
|
+
const config = resolveConfig(api.pluginConfig);
|
|
11
|
+
if (!config.enabled) {
|
|
12
|
+
api.logger.info("[cortex] Disabled via config");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
api.logger.info("[cortex] Registering conversation intelligence hooks...");
|
|
16
|
+
// Register all hook handlers
|
|
17
|
+
registerCortexHooks(api, config);
|
|
18
|
+
// Register /cortexstatus command
|
|
19
|
+
api.registerCommand({
|
|
20
|
+
name: "cortexstatus",
|
|
21
|
+
description: "Show cortex plugin status: thread count, last update, mood",
|
|
22
|
+
requireAuth: true,
|
|
23
|
+
handler: () => {
|
|
24
|
+
try {
|
|
25
|
+
const workspace = resolveWorkspace(config);
|
|
26
|
+
const data = loadJson(`${rebootDir(workspace)}/threads.json`);
|
|
27
|
+
const threads = data.threads ?? [];
|
|
28
|
+
const openCount = threads.filter(t => t.status === "open").length;
|
|
29
|
+
const closedCount = threads.filter(t => t.status === "closed").length;
|
|
30
|
+
const mood = data.session_mood ?? "neutral";
|
|
31
|
+
const updated = data.updated ?? "never";
|
|
32
|
+
return {
|
|
33
|
+
text: [
|
|
34
|
+
"**Cortex Status**",
|
|
35
|
+
`Threads: ${openCount} open, ${closedCount} closed`,
|
|
36
|
+
`Mood: ${mood}`,
|
|
37
|
+
`Updated: ${updated}`,
|
|
38
|
+
].join("\n"),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return { text: "[cortex] Status: operational (no data yet)" };
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
api.logger.info("[cortex] Ready");
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
export default plugin;
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGvD,MAAM,MAAM,GAAG;IACb,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,0GAA0G;IAC5G,OAAO,EAAE,OAAO;IAEhB,QAAQ,CAAC,GAAsB;QAC7B,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAE/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;QAE3E,6BAA6B;QAC7B,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAEjC,iCAAiC;QACjC,GAAG,CAAC,eAAe,CAAC;YAClB,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,4DAA4D;YACzE,WAAW,EAAE,IAAI;YACjB,OAAO,EAAE,GAAG,EAAE;gBACZ,IAAI,CAAC;oBACH,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;oBAC3C,MAAM,IAAI,GAAG,QAAQ,CACnB,GAAG,SAAS,CAAC,SAAS,CAAC,eAAe,CACvC,CAAC;oBACF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;oBACnC,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;oBAClE,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;oBACtE,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,IAAI,SAAS,CAAC;oBAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC;oBAExC,OAAO;wBACL,IAAI,EAAE;4BACJ,mBAAmB;4BACnB,YAAY,SAAS,UAAU,WAAW,SAAS;4BACnD,SAAS,IAAI,EAAE;4BACf,YAAY,OAAO,EAAE;yBACtB,CAAC,IAAI,CAAC,IAAI,CAAC;qBACb,CAAC;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,IAAI,EAAE,4CAA4C,EAAE,CAAC;gBAChE,CAAC;YACH,CAAC;SACF,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Thread, ExecutionMode, PluginLogger, CortexConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Determine execution mode from current hour.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getExecutionMode(): ExecutionMode;
|
|
6
|
+
/**
|
|
7
|
+
* Get sorted open threads by priority and recency.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getOpenThreads(workspace: string, limit: number): Thread[];
|
|
10
|
+
/**
|
|
11
|
+
* Generate staleness warning from integrity data.
|
|
12
|
+
*/
|
|
13
|
+
export declare function integrityWarning(workspace: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Boot Context Generator — assembles BOOTSTRAP.md from persisted state.
|
|
16
|
+
*/
|
|
17
|
+
export declare class BootContextGenerator {
|
|
18
|
+
private readonly workspace;
|
|
19
|
+
private readonly config;
|
|
20
|
+
private readonly logger;
|
|
21
|
+
constructor(workspace: string, config: CortexConfig["bootContext"], logger: PluginLogger);
|
|
22
|
+
/**
|
|
23
|
+
* Check if boot context should be generated.
|
|
24
|
+
*/
|
|
25
|
+
shouldGenerate(): boolean;
|
|
26
|
+
/** Build header section. */
|
|
27
|
+
private buildHeader;
|
|
28
|
+
/** Build state section (mode, mood, warnings). */
|
|
29
|
+
private buildState;
|
|
30
|
+
/** Build threads section. */
|
|
31
|
+
private buildThreads;
|
|
32
|
+
/** Build decisions section. */
|
|
33
|
+
private buildDecisions;
|
|
34
|
+
/**
|
|
35
|
+
* Assemble and return BOOTSTRAP.md content.
|
|
36
|
+
*/
|
|
37
|
+
generate(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Generate and write BOOTSTRAP.md to the workspace root.
|
|
40
|
+
*/
|
|
41
|
+
write(): boolean;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=boot-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boot-context.d.ts","sourceRoot":"","sources":["../../src/boot-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,MAAM,EAIN,aAAa,EACb,YAAY,EACZ,YAAY,EAEb,MAAM,YAAY,CAAC;AAIpB;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAMhD;AAgBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAazE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAuB1D;AAwCD;;GAEG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAGpC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,CAAC,aAAa,CAAC,EACnC,MAAM,EAAE,YAAY;IAOtB;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB,4BAA4B;IAC5B,OAAO,CAAC,WAAW;IASnB,kDAAkD;IAClD,OAAO,CAAC,UAAU;IAiBlB,6BAA6B;IAC7B,OAAO,CAAC,YAAY;IAgBpB,+BAA+B;IAC/B,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,QAAQ,IAAI,MAAM;IA8BlB;;OAEG;IACH,KAAK,IAAI,OAAO;CAUjB"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { MOOD_EMOJI, PRIORITY_EMOJI, PRIORITY_ORDER } from "./types.js";
|
|
3
|
+
import { loadJson, loadText, rebootDir, isFileOlderThan, saveText, ensureRebootDir } from "./storage.js";
|
|
4
|
+
/**
|
|
5
|
+
* Determine execution mode from current hour.
|
|
6
|
+
*/
|
|
7
|
+
export function getExecutionMode() {
|
|
8
|
+
const hour = new Date().getHours();
|
|
9
|
+
if (hour >= 6 && hour < 12)
|
|
10
|
+
return "Morning — brief, directive, efficient";
|
|
11
|
+
if (hour >= 12 && hour < 18)
|
|
12
|
+
return "Afternoon — execution mode";
|
|
13
|
+
if (hour >= 18 && hour < 22)
|
|
14
|
+
return "Evening — strategic, philosophical possible";
|
|
15
|
+
return "Night — emergencies only";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Load threads data from disk.
|
|
19
|
+
*/
|
|
20
|
+
function loadThreadsData(workspace) {
|
|
21
|
+
const data = loadJson(join(rebootDir(workspace), "threads.json"));
|
|
22
|
+
// Handle legacy format where data is an array
|
|
23
|
+
if (Array.isArray(data)) {
|
|
24
|
+
return { threads: data };
|
|
25
|
+
}
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get sorted open threads by priority and recency.
|
|
30
|
+
*/
|
|
31
|
+
export function getOpenThreads(workspace, limit) {
|
|
32
|
+
const data = loadThreadsData(workspace);
|
|
33
|
+
const threads = (data.threads ?? []).filter(t => t.status === "open");
|
|
34
|
+
threads.sort((a, b) => {
|
|
35
|
+
const priA = PRIORITY_ORDER[a.priority] ?? 3;
|
|
36
|
+
const priB = PRIORITY_ORDER[b.priority] ?? 3;
|
|
37
|
+
if (priA !== priB)
|
|
38
|
+
return priA - priB;
|
|
39
|
+
// More recent first
|
|
40
|
+
return b.last_activity.localeCompare(a.last_activity);
|
|
41
|
+
});
|
|
42
|
+
return threads.slice(0, limit);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Generate staleness warning from integrity data.
|
|
46
|
+
*/
|
|
47
|
+
export function integrityWarning(workspace) {
|
|
48
|
+
const data = loadThreadsData(workspace);
|
|
49
|
+
const integrity = data.integrity;
|
|
50
|
+
if (!integrity?.last_event_timestamp) {
|
|
51
|
+
return "⚠️ No integrity data — thread tracker may not have run yet.";
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const lastTs = integrity.last_event_timestamp;
|
|
55
|
+
const lastDt = new Date(lastTs.endsWith("Z") ? lastTs : lastTs + "Z");
|
|
56
|
+
const ageMin = (Date.now() - lastDt.getTime()) / 60000;
|
|
57
|
+
if (ageMin > 480) {
|
|
58
|
+
return `🚨 STALE DATA: Thread data is ${Math.round(ageMin / 60)}h old.`;
|
|
59
|
+
}
|
|
60
|
+
if (ageMin > 120) {
|
|
61
|
+
return `⚠️ Data staleness: Thread data is ${Math.round(ageMin / 60)}h old.`;
|
|
62
|
+
}
|
|
63
|
+
return "";
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return "⚠️ Could not parse integrity timestamp.";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Load hot snapshot if it's fresh (< 1 hour old).
|
|
71
|
+
*/
|
|
72
|
+
function loadHotSnapshot(workspace) {
|
|
73
|
+
const filePath = join(rebootDir(workspace), "hot-snapshot.md");
|
|
74
|
+
if (isFileOlderThan(filePath, 1))
|
|
75
|
+
return "";
|
|
76
|
+
const content = loadText(filePath);
|
|
77
|
+
return content.trim().slice(0, 1000);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Load decisions from the last N days, return last `limit` entries.
|
|
81
|
+
*/
|
|
82
|
+
function loadRecentDecisions(workspace, days, limit) {
|
|
83
|
+
const data = loadJson(join(rebootDir(workspace), "decisions.json"));
|
|
84
|
+
const decisions = Array.isArray(data.decisions) ? data.decisions : [];
|
|
85
|
+
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
86
|
+
return decisions
|
|
87
|
+
.filter(d => d.date >= cutoff)
|
|
88
|
+
.slice(-limit);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Load narrative if it's fresh (< 36 hours old).
|
|
92
|
+
*/
|
|
93
|
+
function loadNarrative(workspace) {
|
|
94
|
+
const filePath = join(rebootDir(workspace), "narrative.md");
|
|
95
|
+
if (isFileOlderThan(filePath, 36))
|
|
96
|
+
return "";
|
|
97
|
+
const content = loadText(filePath);
|
|
98
|
+
return content.trim().slice(0, 2000);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Boot Context Generator — assembles BOOTSTRAP.md from persisted state.
|
|
102
|
+
*/
|
|
103
|
+
export class BootContextGenerator {
|
|
104
|
+
workspace;
|
|
105
|
+
config;
|
|
106
|
+
logger;
|
|
107
|
+
constructor(workspace, config, logger) {
|
|
108
|
+
this.workspace = workspace;
|
|
109
|
+
this.config = config;
|
|
110
|
+
this.logger = logger;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if boot context should be generated.
|
|
114
|
+
*/
|
|
115
|
+
shouldGenerate() {
|
|
116
|
+
return this.config.enabled && this.config.onSessionStart;
|
|
117
|
+
}
|
|
118
|
+
/** Build header section. */
|
|
119
|
+
buildHeader() {
|
|
120
|
+
const now = new Date();
|
|
121
|
+
return [
|
|
122
|
+
"# Context Briefing",
|
|
123
|
+
`Generated: ${now.toISOString().slice(0, 19)}Z | Local: ${now.toTimeString().slice(0, 5)}`,
|
|
124
|
+
"",
|
|
125
|
+
].join("\n");
|
|
126
|
+
}
|
|
127
|
+
/** Build state section (mode, mood, warnings). */
|
|
128
|
+
buildState() {
|
|
129
|
+
const lines = ["## ⚡ State", `Mode: ${getExecutionMode()}`];
|
|
130
|
+
const threadsData = loadThreadsData(this.workspace);
|
|
131
|
+
const mood = (threadsData.session_mood ?? "neutral");
|
|
132
|
+
if (mood !== "neutral") {
|
|
133
|
+
lines.push(`Last session mood: ${mood} ${MOOD_EMOJI[mood] ?? ""}`);
|
|
134
|
+
}
|
|
135
|
+
const warning = integrityWarning(this.workspace);
|
|
136
|
+
if (warning) {
|
|
137
|
+
lines.push("", warning);
|
|
138
|
+
}
|
|
139
|
+
lines.push("");
|
|
140
|
+
return lines.join("\n");
|
|
141
|
+
}
|
|
142
|
+
/** Build threads section. */
|
|
143
|
+
buildThreads(threads) {
|
|
144
|
+
if (threads.length === 0)
|
|
145
|
+
return "";
|
|
146
|
+
const lines = ["## 🧵 Active Threads"];
|
|
147
|
+
for (const t of threads) {
|
|
148
|
+
const priEmoji = PRIORITY_EMOJI[t.priority] ?? "⚪";
|
|
149
|
+
const moodTag = t.mood && t.mood !== "neutral" ? ` [${t.mood}]` : "";
|
|
150
|
+
lines.push("", `### ${priEmoji} ${t.title}${moodTag}`);
|
|
151
|
+
lines.push(`Priority: ${t.priority} | Last: ${t.last_activity.slice(0, 16)}`);
|
|
152
|
+
lines.push(`Summary: ${t.summary || "no summary"}`);
|
|
153
|
+
if (t.waiting_for)
|
|
154
|
+
lines.push(`⏳ Waiting for: ${t.waiting_for}`);
|
|
155
|
+
if (t.decisions.length > 0)
|
|
156
|
+
lines.push(`Decisions: ${t.decisions.join(", ")}`);
|
|
157
|
+
}
|
|
158
|
+
lines.push("");
|
|
159
|
+
return lines.join("\n");
|
|
160
|
+
}
|
|
161
|
+
/** Build decisions section. */
|
|
162
|
+
buildDecisions(decisions) {
|
|
163
|
+
if (decisions.length === 0)
|
|
164
|
+
return "";
|
|
165
|
+
const impactEmoji = { critical: "🔴", high: "🟠", medium: "🟡", low: "🔵" };
|
|
166
|
+
const lines = ["## 🎯 Recent Decisions"];
|
|
167
|
+
for (const d of decisions) {
|
|
168
|
+
lines.push(`- ${impactEmoji[d.impact] ?? "⚪"} **${d.what}** (${d.date})`);
|
|
169
|
+
if (d.why)
|
|
170
|
+
lines.push(` Why: ${d.why.slice(0, 100)}`);
|
|
171
|
+
}
|
|
172
|
+
lines.push("");
|
|
173
|
+
return lines.join("\n");
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Assemble and return BOOTSTRAP.md content.
|
|
177
|
+
*/
|
|
178
|
+
generate() {
|
|
179
|
+
ensureRebootDir(this.workspace, this.logger);
|
|
180
|
+
const threads = getOpenThreads(this.workspace, this.config.maxThreadsInBoot);
|
|
181
|
+
const decisions = loadRecentDecisions(this.workspace, this.config.decisionRecencyDays, this.config.maxDecisionsInBoot);
|
|
182
|
+
const hot = loadHotSnapshot(this.workspace);
|
|
183
|
+
const narrative = loadNarrative(this.workspace);
|
|
184
|
+
const sections = [
|
|
185
|
+
this.buildHeader(),
|
|
186
|
+
this.buildState(),
|
|
187
|
+
hot ? `## 🔥 Last Session Snapshot\n${hot}\n` : "",
|
|
188
|
+
narrative ? `## 📖 Narrative (last 24h)\n${narrative}\n` : "",
|
|
189
|
+
this.buildThreads(threads),
|
|
190
|
+
this.buildDecisions(decisions),
|
|
191
|
+
"---",
|
|
192
|
+
`_Boot context | ${threads.length} active threads | ${decisions.length} recent decisions_`,
|
|
193
|
+
];
|
|
194
|
+
let result = sections.filter(Boolean).join("\n");
|
|
195
|
+
if (result.length > this.config.maxChars) {
|
|
196
|
+
result = result.slice(0, this.config.maxChars) + "\n\n_[truncated to token budget]_";
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Generate and write BOOTSTRAP.md to the workspace root.
|
|
202
|
+
*/
|
|
203
|
+
write() {
|
|
204
|
+
try {
|
|
205
|
+
const content = this.generate();
|
|
206
|
+
const outputPath = join(this.workspace, "BOOTSTRAP.md");
|
|
207
|
+
return saveText(outputPath, content, this.logger);
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
this.logger.warn(`[cortex] Boot context generation failed: ${err}`);
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=boot-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boot-context.js","sourceRoot":"","sources":["../../src/boot-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CortexConfig } from "./types.js";
|
|
2
|
+
export declare const DEFAULTS: CortexConfig;
|
|
3
|
+
export declare function resolveConfig(pluginConfig?: Record<string, unknown>): CortexConfig;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve workspace directory from config, hook context, env, or cwd.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveWorkspace(config: CortexConfig, ctx?: {
|
|
8
|
+
workspaceDir?: string;
|
|
9
|
+
}): string;
|
|
10
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,eAAO,MAAM,QAAQ,EAAE,YA+BtB,CAAC;AAoBF,wBAAgB,aAAa,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAyClF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EACpB,GAAG,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B,MAAM,CAIR"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export const DEFAULTS = {
|
|
2
|
+
enabled: true,
|
|
3
|
+
workspace: "",
|
|
4
|
+
threadTracker: {
|
|
5
|
+
enabled: true,
|
|
6
|
+
pruneDays: 7,
|
|
7
|
+
maxThreads: 50,
|
|
8
|
+
},
|
|
9
|
+
decisionTracker: {
|
|
10
|
+
enabled: true,
|
|
11
|
+
maxDecisions: 100,
|
|
12
|
+
dedupeWindowHours: 24,
|
|
13
|
+
},
|
|
14
|
+
bootContext: {
|
|
15
|
+
enabled: true,
|
|
16
|
+
maxChars: 16000,
|
|
17
|
+
onSessionStart: true,
|
|
18
|
+
maxThreadsInBoot: 7,
|
|
19
|
+
maxDecisionsInBoot: 10,
|
|
20
|
+
decisionRecencyDays: 14,
|
|
21
|
+
},
|
|
22
|
+
preCompaction: {
|
|
23
|
+
enabled: true,
|
|
24
|
+
maxSnapshotMessages: 15,
|
|
25
|
+
},
|
|
26
|
+
narrative: {
|
|
27
|
+
enabled: true,
|
|
28
|
+
},
|
|
29
|
+
patterns: {
|
|
30
|
+
language: "both",
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
function bool(value, fallback) {
|
|
34
|
+
return typeof value === "boolean" ? value : fallback;
|
|
35
|
+
}
|
|
36
|
+
function int(value, fallback) {
|
|
37
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
38
|
+
return Math.round(value);
|
|
39
|
+
return fallback;
|
|
40
|
+
}
|
|
41
|
+
function str(value, fallback) {
|
|
42
|
+
return typeof value === "string" ? value : fallback;
|
|
43
|
+
}
|
|
44
|
+
function lang(value) {
|
|
45
|
+
if (value === "en" || value === "de" || value === "both")
|
|
46
|
+
return value;
|
|
47
|
+
return "both";
|
|
48
|
+
}
|
|
49
|
+
export function resolveConfig(pluginConfig) {
|
|
50
|
+
const raw = pluginConfig ?? {};
|
|
51
|
+
const tt = (raw.threadTracker ?? {});
|
|
52
|
+
const dt = (raw.decisionTracker ?? {});
|
|
53
|
+
const bc = (raw.bootContext ?? {});
|
|
54
|
+
const pc = (raw.preCompaction ?? {});
|
|
55
|
+
const nr = (raw.narrative ?? {});
|
|
56
|
+
const pt = (raw.patterns ?? {});
|
|
57
|
+
return {
|
|
58
|
+
enabled: bool(raw.enabled, DEFAULTS.enabled),
|
|
59
|
+
workspace: str(raw.workspace, DEFAULTS.workspace),
|
|
60
|
+
threadTracker: {
|
|
61
|
+
enabled: bool(tt.enabled, DEFAULTS.threadTracker.enabled),
|
|
62
|
+
pruneDays: int(tt.pruneDays, DEFAULTS.threadTracker.pruneDays),
|
|
63
|
+
maxThreads: int(tt.maxThreads, DEFAULTS.threadTracker.maxThreads),
|
|
64
|
+
},
|
|
65
|
+
decisionTracker: {
|
|
66
|
+
enabled: bool(dt.enabled, DEFAULTS.decisionTracker.enabled),
|
|
67
|
+
maxDecisions: int(dt.maxDecisions, DEFAULTS.decisionTracker.maxDecisions),
|
|
68
|
+
dedupeWindowHours: int(dt.dedupeWindowHours, DEFAULTS.decisionTracker.dedupeWindowHours),
|
|
69
|
+
},
|
|
70
|
+
bootContext: {
|
|
71
|
+
enabled: bool(bc.enabled, DEFAULTS.bootContext.enabled),
|
|
72
|
+
maxChars: int(bc.maxChars, DEFAULTS.bootContext.maxChars),
|
|
73
|
+
onSessionStart: bool(bc.onSessionStart, DEFAULTS.bootContext.onSessionStart),
|
|
74
|
+
maxThreadsInBoot: int(bc.maxThreadsInBoot, DEFAULTS.bootContext.maxThreadsInBoot),
|
|
75
|
+
maxDecisionsInBoot: int(bc.maxDecisionsInBoot, DEFAULTS.bootContext.maxDecisionsInBoot),
|
|
76
|
+
decisionRecencyDays: int(bc.decisionRecencyDays, DEFAULTS.bootContext.decisionRecencyDays),
|
|
77
|
+
},
|
|
78
|
+
preCompaction: {
|
|
79
|
+
enabled: bool(pc.enabled, DEFAULTS.preCompaction.enabled),
|
|
80
|
+
maxSnapshotMessages: int(pc.maxSnapshotMessages, DEFAULTS.preCompaction.maxSnapshotMessages),
|
|
81
|
+
},
|
|
82
|
+
narrative: {
|
|
83
|
+
enabled: bool(nr.enabled, DEFAULTS.narrative.enabled),
|
|
84
|
+
},
|
|
85
|
+
patterns: {
|
|
86
|
+
language: lang(pt.language),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Resolve workspace directory from config, hook context, env, or cwd.
|
|
92
|
+
*/
|
|
93
|
+
export function resolveWorkspace(config, ctx) {
|
|
94
|
+
if (config.workspace)
|
|
95
|
+
return config.workspace;
|
|
96
|
+
if (ctx?.workspaceDir)
|
|
97
|
+
return ctx.workspaceDir;
|
|
98
|
+
return process.env.WORKSPACE_DIR ?? process.cwd();
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAiB;IACpC,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,EAAE;IACb,aAAa,EAAE;QACb,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,EAAE;KACf;IACD,eAAe,EAAE;QACf,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,GAAG;QACjB,iBAAiB,EAAE,EAAE;KACtB;IACD,WAAW,EAAE;QACX,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,KAAK;QACf,cAAc,EAAE,IAAI;QACpB,gBAAgB,EAAE,CAAC;QACnB,kBAAkB,EAAE,EAAE;QACtB,mBAAmB,EAAE,EAAE;KACxB;IACD,aAAa,EAAE;QACb,OAAO,EAAE,IAAI;QACb,mBAAmB,EAAE,EAAE;KACxB;IACD,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;KACd;IACD,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM;KACjB;CACF,CAAC;AAEF,SAAS,IAAI,CAAC,KAAc,EAAE,QAAiB;IAC7C,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AACvD,CAAC;AAED,SAAS,GAAG,CAAC,KAAc,EAAE,QAAgB;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,GAAG,CAAC,KAAc,EAAE,QAAgB;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtD,CAAC;AAED,SAAS,IAAI,CAAC,KAAc;IAC1B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACvE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,YAAsC;IAClE,MAAM,GAAG,GAAG,YAAY,IAAI,EAAE,CAAC;IAC/B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAA4B,CAAC;IAChE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAA4B,CAAC;IAClE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAA4B,CAAC;IAC9D,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAA4B,CAAC;IAChE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAA4B,CAAC;IAC5D,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAA4B,CAAC;IAE3D,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC;QAC5C,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;QACjD,aAAa,EAAE;YACb,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;YACzD,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC;YAC9D,UAAU,EAAE,GAAG,CAAC,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC;SAClE;QACD,eAAe,EAAE;YACf,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC;YAC3D,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,QAAQ,CAAC,eAAe,CAAC,YAAY,CAAC;YACzE,iBAAiB,EAAE,GAAG,CAAC,EAAE,CAAC,iBAAiB,EAAE,QAAQ,CAAC,eAAe,CAAC,iBAAiB,CAAC;SACzF;QACD,WAAW,EAAE;YACX,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC;YACvD,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC;YACzD,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,cAAc,EAAE,QAAQ,CAAC,WAAW,CAAC,cAAc,CAAC;YAC5E,gBAAgB,EAAE,GAAG,CAAC,EAAE,CAAC,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAAC,gBAAgB,CAAC;YACjF,kBAAkB,EAAE,GAAG,CAAC,EAAE,CAAC,kBAAkB,EAAE,QAAQ,CAAC,WAAW,CAAC,kBAAkB,CAAC;YACvF,mBAAmB,EAAE,GAAG,CAAC,EAAE,CAAC,mBAAmB,EAAE,QAAQ,CAAC,WAAW,CAAC,mBAAmB,CAAC;SAC3F;QACD,aAAa,EAAE;YACb,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;YACzD,mBAAmB,EAAE,GAAG,CAAC,EAAE,CAAC,mBAAmB,EAAE,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC;SAC7F;QACD,SAAS,EAAE;YACT,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC;SACtD;QACD,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC;SAC5B;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAoB,EACpB,GAA+B;IAE/B,IAAI,MAAM,CAAC,SAAS;QAAE,OAAO,MAAM,CAAC,SAAS,CAAC;IAC9C,IAAI,GAAG,EAAE,YAAY;QAAE,OAAO,GAAG,CAAC,YAAY,CAAC;IAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;AACpD,CAAC"}
|