chopratejas commited on
Commit
2a2730a
·
1 Parent(s): ec4e58f

feat: add OpenClaw ContextEngine plugin (@headroom-ai/openclaw)

Browse files

- HeadroomContextEngine: implements ContextEngine interface (bootstrap, ingest,
assemble, compact, afterTurn, prepareSubagentSpawn, dispose)
- ProxyManager: auto-detects running proxy or spawns one as child process,
health checks, restart on crash, graceful shutdown
- AgentMessage ↔ OpenAI format conversion (user, assistant/tool_use, toolResult)
- headroom_retrieve CCR tool: agent can retrieve original uncompressed content
- Plugin manifest (openclaw.plugin.json) with config schema
- 11 tests (6 unit + 5 integration), all passing
- Integration tested: 100 servers compressed, 3,735 tokens saved (82%)

plugins/openclaw/.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ node_modules/
2
+ dist/
3
+ .env
plugins/openclaw/README.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # @headroom-ai/openclaw
2
+
3
+ Context compression plugin for [OpenClaw](https://github.com/openclaw/openclaw). Compresses tool outputs, code, logs, and structured data — 70-90% token savings with zero LLM calls.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install "headroom-ai[proxy]"
9
+ openclaw plugins install @headroom-ai/openclaw
10
+ ```
11
+
12
+ ## Configure
13
+
14
+ ```json
15
+ {
16
+ "plugins": {
17
+ "slots": {
18
+ "contextEngine": "headroom"
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ That's it. The plugin auto-starts the Headroom proxy if it's not already running.
25
+
26
+ ## How It Works
27
+
28
+ Every time OpenClaw assembles context for the model, the plugin compresses tool outputs and large messages:
29
+
30
+ - **JSON arrays** (tool outputs, search results) — statistical selection keeps anomalies, errors, boundaries
31
+ - **Code** — AST-aware compression via tree-sitter
32
+ - **Logs** — pattern deduplication, keeps errors and boundaries
33
+ - **Text** — ML-based token compression
34
+
35
+ Compression is lossless via CCR (Compress-Cache-Retrieve): originals are stored and the agent gets a `headroom_retrieve` tool to access full details when needed.
36
+
37
+ ## Configuration Options
38
+
39
+ | Option | Default | Description |
40
+ |--------|---------|-------------|
41
+ | `proxyUrl` | auto-detected | URL of the Headroom proxy |
42
+ | `autoStart` | `true` | Start proxy automatically if not running |
43
+ | `pythonPath` | auto-detected | Path to Python binary |
44
+ | `proxyPort` | `8787` | Port for auto-started proxy |
45
+
46
+ ## Comparison with lossless-claw
47
+
48
+ | | lossless-claw | headroom |
49
+ |---|---|---|
50
+ | Compaction method | LLM summarization (DAG) | Content-aware compression (zero LLM) |
51
+ | Cost of compaction | Tokens (LLM calls) | Zero |
52
+ | Best for | Long conversations | Tool-heavy agents with large outputs |
53
+ | Retrieval | `lcm_grep`, `lcm_expand` | `headroom_retrieve` (instant) |
54
+
55
+ ## License
56
+
57
+ Apache-2.0
plugins/openclaw/openclaw.plugin.json ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "id": "headroom",
3
+ "uiHints": {
4
+ "proxyUrl": {
5
+ "label": "Proxy URL",
6
+ "help": "URL of the Headroom proxy (auto-detected or auto-started if not set)"
7
+ },
8
+ "pythonPath": {
9
+ "label": "Python Path",
10
+ "help": "Path to Python binary (auto-detected if not set)"
11
+ },
12
+ "autoStart": {
13
+ "label": "Auto-Start Proxy",
14
+ "help": "Automatically start the Headroom proxy if not already running"
15
+ }
16
+ },
17
+ "configSchema": {
18
+ "type": "object",
19
+ "additionalProperties": false,
20
+ "properties": {
21
+ "enabled": {
22
+ "type": "boolean"
23
+ },
24
+ "proxyUrl": {
25
+ "type": "string"
26
+ },
27
+ "pythonPath": {
28
+ "type": "string"
29
+ },
30
+ "autoStart": {
31
+ "type": "boolean",
32
+ "default": true
33
+ },
34
+ "proxyPort": {
35
+ "type": "integer",
36
+ "minimum": 0,
37
+ "maximum": 65535
38
+ }
39
+ }
40
+ }
41
+ }
plugins/openclaw/package-lock.json ADDED
@@ -0,0 +1,2458 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "@headroom-ai/openclaw",
3
+ "version": "0.1.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "@headroom-ai/openclaw",
9
+ "version": "0.1.0",
10
+ "license": "Apache-2.0",
11
+ "dependencies": {
12
+ "headroom-ai": "^0.1.0"
13
+ },
14
+ "devDependencies": {
15
+ "tsup": "^8.0.0",
16
+ "typescript": "^5.5.0",
17
+ "vitest": "^2.0.0"
18
+ },
19
+ "peerDependencies": {
20
+ "openclaw": "*"
21
+ },
22
+ "peerDependenciesMeta": {
23
+ "openclaw": {
24
+ "optional": true
25
+ }
26
+ }
27
+ },
28
+ "node_modules/@esbuild/aix-ppc64": {
29
+ "version": "0.27.4",
30
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz",
31
+ "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==",
32
+ "cpu": [
33
+ "ppc64"
34
+ ],
35
+ "dev": true,
36
+ "license": "MIT",
37
+ "optional": true,
38
+ "os": [
39
+ "aix"
40
+ ],
41
+ "engines": {
42
+ "node": ">=18"
43
+ }
44
+ },
45
+ "node_modules/@esbuild/android-arm": {
46
+ "version": "0.27.4",
47
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz",
48
+ "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==",
49
+ "cpu": [
50
+ "arm"
51
+ ],
52
+ "dev": true,
53
+ "license": "MIT",
54
+ "optional": true,
55
+ "os": [
56
+ "android"
57
+ ],
58
+ "engines": {
59
+ "node": ">=18"
60
+ }
61
+ },
62
+ "node_modules/@esbuild/android-arm64": {
63
+ "version": "0.27.4",
64
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz",
65
+ "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==",
66
+ "cpu": [
67
+ "arm64"
68
+ ],
69
+ "dev": true,
70
+ "license": "MIT",
71
+ "optional": true,
72
+ "os": [
73
+ "android"
74
+ ],
75
+ "engines": {
76
+ "node": ">=18"
77
+ }
78
+ },
79
+ "node_modules/@esbuild/android-x64": {
80
+ "version": "0.27.4",
81
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz",
82
+ "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==",
83
+ "cpu": [
84
+ "x64"
85
+ ],
86
+ "dev": true,
87
+ "license": "MIT",
88
+ "optional": true,
89
+ "os": [
90
+ "android"
91
+ ],
92
+ "engines": {
93
+ "node": ">=18"
94
+ }
95
+ },
96
+ "node_modules/@esbuild/darwin-arm64": {
97
+ "version": "0.27.4",
98
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz",
99
+ "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==",
100
+ "cpu": [
101
+ "arm64"
102
+ ],
103
+ "dev": true,
104
+ "license": "MIT",
105
+ "optional": true,
106
+ "os": [
107
+ "darwin"
108
+ ],
109
+ "engines": {
110
+ "node": ">=18"
111
+ }
112
+ },
113
+ "node_modules/@esbuild/darwin-x64": {
114
+ "version": "0.27.4",
115
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz",
116
+ "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==",
117
+ "cpu": [
118
+ "x64"
119
+ ],
120
+ "dev": true,
121
+ "license": "MIT",
122
+ "optional": true,
123
+ "os": [
124
+ "darwin"
125
+ ],
126
+ "engines": {
127
+ "node": ">=18"
128
+ }
129
+ },
130
+ "node_modules/@esbuild/freebsd-arm64": {
131
+ "version": "0.27.4",
132
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz",
133
+ "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==",
134
+ "cpu": [
135
+ "arm64"
136
+ ],
137
+ "dev": true,
138
+ "license": "MIT",
139
+ "optional": true,
140
+ "os": [
141
+ "freebsd"
142
+ ],
143
+ "engines": {
144
+ "node": ">=18"
145
+ }
146
+ },
147
+ "node_modules/@esbuild/freebsd-x64": {
148
+ "version": "0.27.4",
149
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz",
150
+ "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==",
151
+ "cpu": [
152
+ "x64"
153
+ ],
154
+ "dev": true,
155
+ "license": "MIT",
156
+ "optional": true,
157
+ "os": [
158
+ "freebsd"
159
+ ],
160
+ "engines": {
161
+ "node": ">=18"
162
+ }
163
+ },
164
+ "node_modules/@esbuild/linux-arm": {
165
+ "version": "0.27.4",
166
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz",
167
+ "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==",
168
+ "cpu": [
169
+ "arm"
170
+ ],
171
+ "dev": true,
172
+ "license": "MIT",
173
+ "optional": true,
174
+ "os": [
175
+ "linux"
176
+ ],
177
+ "engines": {
178
+ "node": ">=18"
179
+ }
180
+ },
181
+ "node_modules/@esbuild/linux-arm64": {
182
+ "version": "0.27.4",
183
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz",
184
+ "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==",
185
+ "cpu": [
186
+ "arm64"
187
+ ],
188
+ "dev": true,
189
+ "license": "MIT",
190
+ "optional": true,
191
+ "os": [
192
+ "linux"
193
+ ],
194
+ "engines": {
195
+ "node": ">=18"
196
+ }
197
+ },
198
+ "node_modules/@esbuild/linux-ia32": {
199
+ "version": "0.27.4",
200
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz",
201
+ "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==",
202
+ "cpu": [
203
+ "ia32"
204
+ ],
205
+ "dev": true,
206
+ "license": "MIT",
207
+ "optional": true,
208
+ "os": [
209
+ "linux"
210
+ ],
211
+ "engines": {
212
+ "node": ">=18"
213
+ }
214
+ },
215
+ "node_modules/@esbuild/linux-loong64": {
216
+ "version": "0.27.4",
217
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz",
218
+ "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==",
219
+ "cpu": [
220
+ "loong64"
221
+ ],
222
+ "dev": true,
223
+ "license": "MIT",
224
+ "optional": true,
225
+ "os": [
226
+ "linux"
227
+ ],
228
+ "engines": {
229
+ "node": ">=18"
230
+ }
231
+ },
232
+ "node_modules/@esbuild/linux-mips64el": {
233
+ "version": "0.27.4",
234
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz",
235
+ "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==",
236
+ "cpu": [
237
+ "mips64el"
238
+ ],
239
+ "dev": true,
240
+ "license": "MIT",
241
+ "optional": true,
242
+ "os": [
243
+ "linux"
244
+ ],
245
+ "engines": {
246
+ "node": ">=18"
247
+ }
248
+ },
249
+ "node_modules/@esbuild/linux-ppc64": {
250
+ "version": "0.27.4",
251
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz",
252
+ "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==",
253
+ "cpu": [
254
+ "ppc64"
255
+ ],
256
+ "dev": true,
257
+ "license": "MIT",
258
+ "optional": true,
259
+ "os": [
260
+ "linux"
261
+ ],
262
+ "engines": {
263
+ "node": ">=18"
264
+ }
265
+ },
266
+ "node_modules/@esbuild/linux-riscv64": {
267
+ "version": "0.27.4",
268
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz",
269
+ "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==",
270
+ "cpu": [
271
+ "riscv64"
272
+ ],
273
+ "dev": true,
274
+ "license": "MIT",
275
+ "optional": true,
276
+ "os": [
277
+ "linux"
278
+ ],
279
+ "engines": {
280
+ "node": ">=18"
281
+ }
282
+ },
283
+ "node_modules/@esbuild/linux-s390x": {
284
+ "version": "0.27.4",
285
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz",
286
+ "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==",
287
+ "cpu": [
288
+ "s390x"
289
+ ],
290
+ "dev": true,
291
+ "license": "MIT",
292
+ "optional": true,
293
+ "os": [
294
+ "linux"
295
+ ],
296
+ "engines": {
297
+ "node": ">=18"
298
+ }
299
+ },
300
+ "node_modules/@esbuild/linux-x64": {
301
+ "version": "0.27.4",
302
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz",
303
+ "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==",
304
+ "cpu": [
305
+ "x64"
306
+ ],
307
+ "dev": true,
308
+ "license": "MIT",
309
+ "optional": true,
310
+ "os": [
311
+ "linux"
312
+ ],
313
+ "engines": {
314
+ "node": ">=18"
315
+ }
316
+ },
317
+ "node_modules/@esbuild/netbsd-arm64": {
318
+ "version": "0.27.4",
319
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz",
320
+ "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==",
321
+ "cpu": [
322
+ "arm64"
323
+ ],
324
+ "dev": true,
325
+ "license": "MIT",
326
+ "optional": true,
327
+ "os": [
328
+ "netbsd"
329
+ ],
330
+ "engines": {
331
+ "node": ">=18"
332
+ }
333
+ },
334
+ "node_modules/@esbuild/netbsd-x64": {
335
+ "version": "0.27.4",
336
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz",
337
+ "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==",
338
+ "cpu": [
339
+ "x64"
340
+ ],
341
+ "dev": true,
342
+ "license": "MIT",
343
+ "optional": true,
344
+ "os": [
345
+ "netbsd"
346
+ ],
347
+ "engines": {
348
+ "node": ">=18"
349
+ }
350
+ },
351
+ "node_modules/@esbuild/openbsd-arm64": {
352
+ "version": "0.27.4",
353
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz",
354
+ "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==",
355
+ "cpu": [
356
+ "arm64"
357
+ ],
358
+ "dev": true,
359
+ "license": "MIT",
360
+ "optional": true,
361
+ "os": [
362
+ "openbsd"
363
+ ],
364
+ "engines": {
365
+ "node": ">=18"
366
+ }
367
+ },
368
+ "node_modules/@esbuild/openbsd-x64": {
369
+ "version": "0.27.4",
370
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz",
371
+ "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==",
372
+ "cpu": [
373
+ "x64"
374
+ ],
375
+ "dev": true,
376
+ "license": "MIT",
377
+ "optional": true,
378
+ "os": [
379
+ "openbsd"
380
+ ],
381
+ "engines": {
382
+ "node": ">=18"
383
+ }
384
+ },
385
+ "node_modules/@esbuild/openharmony-arm64": {
386
+ "version": "0.27.4",
387
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz",
388
+ "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==",
389
+ "cpu": [
390
+ "arm64"
391
+ ],
392
+ "dev": true,
393
+ "license": "MIT",
394
+ "optional": true,
395
+ "os": [
396
+ "openharmony"
397
+ ],
398
+ "engines": {
399
+ "node": ">=18"
400
+ }
401
+ },
402
+ "node_modules/@esbuild/sunos-x64": {
403
+ "version": "0.27.4",
404
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz",
405
+ "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==",
406
+ "cpu": [
407
+ "x64"
408
+ ],
409
+ "dev": true,
410
+ "license": "MIT",
411
+ "optional": true,
412
+ "os": [
413
+ "sunos"
414
+ ],
415
+ "engines": {
416
+ "node": ">=18"
417
+ }
418
+ },
419
+ "node_modules/@esbuild/win32-arm64": {
420
+ "version": "0.27.4",
421
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz",
422
+ "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==",
423
+ "cpu": [
424
+ "arm64"
425
+ ],
426
+ "dev": true,
427
+ "license": "MIT",
428
+ "optional": true,
429
+ "os": [
430
+ "win32"
431
+ ],
432
+ "engines": {
433
+ "node": ">=18"
434
+ }
435
+ },
436
+ "node_modules/@esbuild/win32-ia32": {
437
+ "version": "0.27.4",
438
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz",
439
+ "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==",
440
+ "cpu": [
441
+ "ia32"
442
+ ],
443
+ "dev": true,
444
+ "license": "MIT",
445
+ "optional": true,
446
+ "os": [
447
+ "win32"
448
+ ],
449
+ "engines": {
450
+ "node": ">=18"
451
+ }
452
+ },
453
+ "node_modules/@esbuild/win32-x64": {
454
+ "version": "0.27.4",
455
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz",
456
+ "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==",
457
+ "cpu": [
458
+ "x64"
459
+ ],
460
+ "dev": true,
461
+ "license": "MIT",
462
+ "optional": true,
463
+ "os": [
464
+ "win32"
465
+ ],
466
+ "engines": {
467
+ "node": ">=18"
468
+ }
469
+ },
470
+ "node_modules/@jridgewell/gen-mapping": {
471
+ "version": "0.3.13",
472
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
473
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
474
+ "dev": true,
475
+ "license": "MIT",
476
+ "dependencies": {
477
+ "@jridgewell/sourcemap-codec": "^1.5.0",
478
+ "@jridgewell/trace-mapping": "^0.3.24"
479
+ }
480
+ },
481
+ "node_modules/@jridgewell/resolve-uri": {
482
+ "version": "3.1.2",
483
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
484
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
485
+ "dev": true,
486
+ "license": "MIT",
487
+ "engines": {
488
+ "node": ">=6.0.0"
489
+ }
490
+ },
491
+ "node_modules/@jridgewell/sourcemap-codec": {
492
+ "version": "1.5.5",
493
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
494
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
495
+ "dev": true,
496
+ "license": "MIT"
497
+ },
498
+ "node_modules/@jridgewell/trace-mapping": {
499
+ "version": "0.3.31",
500
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
501
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
502
+ "dev": true,
503
+ "license": "MIT",
504
+ "dependencies": {
505
+ "@jridgewell/resolve-uri": "^3.1.0",
506
+ "@jridgewell/sourcemap-codec": "^1.4.14"
507
+ }
508
+ },
509
+ "node_modules/@rollup/rollup-android-arm-eabi": {
510
+ "version": "4.60.0",
511
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.0.tgz",
512
+ "integrity": "sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==",
513
+ "cpu": [
514
+ "arm"
515
+ ],
516
+ "dev": true,
517
+ "license": "MIT",
518
+ "optional": true,
519
+ "os": [
520
+ "android"
521
+ ]
522
+ },
523
+ "node_modules/@rollup/rollup-android-arm64": {
524
+ "version": "4.60.0",
525
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.0.tgz",
526
+ "integrity": "sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==",
527
+ "cpu": [
528
+ "arm64"
529
+ ],
530
+ "dev": true,
531
+ "license": "MIT",
532
+ "optional": true,
533
+ "os": [
534
+ "android"
535
+ ]
536
+ },
537
+ "node_modules/@rollup/rollup-darwin-arm64": {
538
+ "version": "4.60.0",
539
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.0.tgz",
540
+ "integrity": "sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==",
541
+ "cpu": [
542
+ "arm64"
543
+ ],
544
+ "dev": true,
545
+ "license": "MIT",
546
+ "optional": true,
547
+ "os": [
548
+ "darwin"
549
+ ]
550
+ },
551
+ "node_modules/@rollup/rollup-darwin-x64": {
552
+ "version": "4.60.0",
553
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.0.tgz",
554
+ "integrity": "sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==",
555
+ "cpu": [
556
+ "x64"
557
+ ],
558
+ "dev": true,
559
+ "license": "MIT",
560
+ "optional": true,
561
+ "os": [
562
+ "darwin"
563
+ ]
564
+ },
565
+ "node_modules/@rollup/rollup-freebsd-arm64": {
566
+ "version": "4.60.0",
567
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.0.tgz",
568
+ "integrity": "sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==",
569
+ "cpu": [
570
+ "arm64"
571
+ ],
572
+ "dev": true,
573
+ "license": "MIT",
574
+ "optional": true,
575
+ "os": [
576
+ "freebsd"
577
+ ]
578
+ },
579
+ "node_modules/@rollup/rollup-freebsd-x64": {
580
+ "version": "4.60.0",
581
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.0.tgz",
582
+ "integrity": "sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==",
583
+ "cpu": [
584
+ "x64"
585
+ ],
586
+ "dev": true,
587
+ "license": "MIT",
588
+ "optional": true,
589
+ "os": [
590
+ "freebsd"
591
+ ]
592
+ },
593
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
594
+ "version": "4.60.0",
595
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.0.tgz",
596
+ "integrity": "sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==",
597
+ "cpu": [
598
+ "arm"
599
+ ],
600
+ "dev": true,
601
+ "license": "MIT",
602
+ "optional": true,
603
+ "os": [
604
+ "linux"
605
+ ]
606
+ },
607
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
608
+ "version": "4.60.0",
609
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.0.tgz",
610
+ "integrity": "sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==",
611
+ "cpu": [
612
+ "arm"
613
+ ],
614
+ "dev": true,
615
+ "license": "MIT",
616
+ "optional": true,
617
+ "os": [
618
+ "linux"
619
+ ]
620
+ },
621
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
622
+ "version": "4.60.0",
623
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.0.tgz",
624
+ "integrity": "sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==",
625
+ "cpu": [
626
+ "arm64"
627
+ ],
628
+ "dev": true,
629
+ "license": "MIT",
630
+ "optional": true,
631
+ "os": [
632
+ "linux"
633
+ ]
634
+ },
635
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
636
+ "version": "4.60.0",
637
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.0.tgz",
638
+ "integrity": "sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==",
639
+ "cpu": [
640
+ "arm64"
641
+ ],
642
+ "dev": true,
643
+ "license": "MIT",
644
+ "optional": true,
645
+ "os": [
646
+ "linux"
647
+ ]
648
+ },
649
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
650
+ "version": "4.60.0",
651
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.0.tgz",
652
+ "integrity": "sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==",
653
+ "cpu": [
654
+ "loong64"
655
+ ],
656
+ "dev": true,
657
+ "license": "MIT",
658
+ "optional": true,
659
+ "os": [
660
+ "linux"
661
+ ]
662
+ },
663
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
664
+ "version": "4.60.0",
665
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.0.tgz",
666
+ "integrity": "sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==",
667
+ "cpu": [
668
+ "loong64"
669
+ ],
670
+ "dev": true,
671
+ "license": "MIT",
672
+ "optional": true,
673
+ "os": [
674
+ "linux"
675
+ ]
676
+ },
677
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
678
+ "version": "4.60.0",
679
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.0.tgz",
680
+ "integrity": "sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==",
681
+ "cpu": [
682
+ "ppc64"
683
+ ],
684
+ "dev": true,
685
+ "license": "MIT",
686
+ "optional": true,
687
+ "os": [
688
+ "linux"
689
+ ]
690
+ },
691
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
692
+ "version": "4.60.0",
693
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.0.tgz",
694
+ "integrity": "sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==",
695
+ "cpu": [
696
+ "ppc64"
697
+ ],
698
+ "dev": true,
699
+ "license": "MIT",
700
+ "optional": true,
701
+ "os": [
702
+ "linux"
703
+ ]
704
+ },
705
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
706
+ "version": "4.60.0",
707
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.0.tgz",
708
+ "integrity": "sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==",
709
+ "cpu": [
710
+ "riscv64"
711
+ ],
712
+ "dev": true,
713
+ "license": "MIT",
714
+ "optional": true,
715
+ "os": [
716
+ "linux"
717
+ ]
718
+ },
719
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
720
+ "version": "4.60.0",
721
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.0.tgz",
722
+ "integrity": "sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==",
723
+ "cpu": [
724
+ "riscv64"
725
+ ],
726
+ "dev": true,
727
+ "license": "MIT",
728
+ "optional": true,
729
+ "os": [
730
+ "linux"
731
+ ]
732
+ },
733
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
734
+ "version": "4.60.0",
735
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.0.tgz",
736
+ "integrity": "sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==",
737
+ "cpu": [
738
+ "s390x"
739
+ ],
740
+ "dev": true,
741
+ "license": "MIT",
742
+ "optional": true,
743
+ "os": [
744
+ "linux"
745
+ ]
746
+ },
747
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
748
+ "version": "4.60.0",
749
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.0.tgz",
750
+ "integrity": "sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==",
751
+ "cpu": [
752
+ "x64"
753
+ ],
754
+ "dev": true,
755
+ "license": "MIT",
756
+ "optional": true,
757
+ "os": [
758
+ "linux"
759
+ ]
760
+ },
761
+ "node_modules/@rollup/rollup-linux-x64-musl": {
762
+ "version": "4.60.0",
763
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.0.tgz",
764
+ "integrity": "sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==",
765
+ "cpu": [
766
+ "x64"
767
+ ],
768
+ "dev": true,
769
+ "license": "MIT",
770
+ "optional": true,
771
+ "os": [
772
+ "linux"
773
+ ]
774
+ },
775
+ "node_modules/@rollup/rollup-openbsd-x64": {
776
+ "version": "4.60.0",
777
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.0.tgz",
778
+ "integrity": "sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==",
779
+ "cpu": [
780
+ "x64"
781
+ ],
782
+ "dev": true,
783
+ "license": "MIT",
784
+ "optional": true,
785
+ "os": [
786
+ "openbsd"
787
+ ]
788
+ },
789
+ "node_modules/@rollup/rollup-openharmony-arm64": {
790
+ "version": "4.60.0",
791
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.0.tgz",
792
+ "integrity": "sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==",
793
+ "cpu": [
794
+ "arm64"
795
+ ],
796
+ "dev": true,
797
+ "license": "MIT",
798
+ "optional": true,
799
+ "os": [
800
+ "openharmony"
801
+ ]
802
+ },
803
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
804
+ "version": "4.60.0",
805
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.0.tgz",
806
+ "integrity": "sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==",
807
+ "cpu": [
808
+ "arm64"
809
+ ],
810
+ "dev": true,
811
+ "license": "MIT",
812
+ "optional": true,
813
+ "os": [
814
+ "win32"
815
+ ]
816
+ },
817
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
818
+ "version": "4.60.0",
819
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.0.tgz",
820
+ "integrity": "sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==",
821
+ "cpu": [
822
+ "ia32"
823
+ ],
824
+ "dev": true,
825
+ "license": "MIT",
826
+ "optional": true,
827
+ "os": [
828
+ "win32"
829
+ ]
830
+ },
831
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
832
+ "version": "4.60.0",
833
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.0.tgz",
834
+ "integrity": "sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==",
835
+ "cpu": [
836
+ "x64"
837
+ ],
838
+ "dev": true,
839
+ "license": "MIT",
840
+ "optional": true,
841
+ "os": [
842
+ "win32"
843
+ ]
844
+ },
845
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
846
+ "version": "4.60.0",
847
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.0.tgz",
848
+ "integrity": "sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==",
849
+ "cpu": [
850
+ "x64"
851
+ ],
852
+ "dev": true,
853
+ "license": "MIT",
854
+ "optional": true,
855
+ "os": [
856
+ "win32"
857
+ ]
858
+ },
859
+ "node_modules/@types/estree": {
860
+ "version": "1.0.8",
861
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
862
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
863
+ "dev": true,
864
+ "license": "MIT"
865
+ },
866
+ "node_modules/@vitest/expect": {
867
+ "version": "2.1.9",
868
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz",
869
+ "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==",
870
+ "dev": true,
871
+ "license": "MIT",
872
+ "dependencies": {
873
+ "@vitest/spy": "2.1.9",
874
+ "@vitest/utils": "2.1.9",
875
+ "chai": "^5.1.2",
876
+ "tinyrainbow": "^1.2.0"
877
+ },
878
+ "funding": {
879
+ "url": "https://opencollective.com/vitest"
880
+ }
881
+ },
882
+ "node_modules/@vitest/mocker": {
883
+ "version": "2.1.9",
884
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz",
885
+ "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==",
886
+ "dev": true,
887
+ "license": "MIT",
888
+ "dependencies": {
889
+ "@vitest/spy": "2.1.9",
890
+ "estree-walker": "^3.0.3",
891
+ "magic-string": "^0.30.12"
892
+ },
893
+ "funding": {
894
+ "url": "https://opencollective.com/vitest"
895
+ },
896
+ "peerDependencies": {
897
+ "msw": "^2.4.9",
898
+ "vite": "^5.0.0"
899
+ },
900
+ "peerDependenciesMeta": {
901
+ "msw": {
902
+ "optional": true
903
+ },
904
+ "vite": {
905
+ "optional": true
906
+ }
907
+ }
908
+ },
909
+ "node_modules/@vitest/pretty-format": {
910
+ "version": "2.1.9",
911
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz",
912
+ "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==",
913
+ "dev": true,
914
+ "license": "MIT",
915
+ "dependencies": {
916
+ "tinyrainbow": "^1.2.0"
917
+ },
918
+ "funding": {
919
+ "url": "https://opencollective.com/vitest"
920
+ }
921
+ },
922
+ "node_modules/@vitest/runner": {
923
+ "version": "2.1.9",
924
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz",
925
+ "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==",
926
+ "dev": true,
927
+ "license": "MIT",
928
+ "dependencies": {
929
+ "@vitest/utils": "2.1.9",
930
+ "pathe": "^1.1.2"
931
+ },
932
+ "funding": {
933
+ "url": "https://opencollective.com/vitest"
934
+ }
935
+ },
936
+ "node_modules/@vitest/runner/node_modules/pathe": {
937
+ "version": "1.1.2",
938
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
939
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
940
+ "dev": true,
941
+ "license": "MIT"
942
+ },
943
+ "node_modules/@vitest/snapshot": {
944
+ "version": "2.1.9",
945
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz",
946
+ "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==",
947
+ "dev": true,
948
+ "license": "MIT",
949
+ "dependencies": {
950
+ "@vitest/pretty-format": "2.1.9",
951
+ "magic-string": "^0.30.12",
952
+ "pathe": "^1.1.2"
953
+ },
954
+ "funding": {
955
+ "url": "https://opencollective.com/vitest"
956
+ }
957
+ },
958
+ "node_modules/@vitest/snapshot/node_modules/pathe": {
959
+ "version": "1.1.2",
960
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
961
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
962
+ "dev": true,
963
+ "license": "MIT"
964
+ },
965
+ "node_modules/@vitest/spy": {
966
+ "version": "2.1.9",
967
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz",
968
+ "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==",
969
+ "dev": true,
970
+ "license": "MIT",
971
+ "dependencies": {
972
+ "tinyspy": "^3.0.2"
973
+ },
974
+ "funding": {
975
+ "url": "https://opencollective.com/vitest"
976
+ }
977
+ },
978
+ "node_modules/@vitest/utils": {
979
+ "version": "2.1.9",
980
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz",
981
+ "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==",
982
+ "dev": true,
983
+ "license": "MIT",
984
+ "dependencies": {
985
+ "@vitest/pretty-format": "2.1.9",
986
+ "loupe": "^3.1.2",
987
+ "tinyrainbow": "^1.2.0"
988
+ },
989
+ "funding": {
990
+ "url": "https://opencollective.com/vitest"
991
+ }
992
+ },
993
+ "node_modules/acorn": {
994
+ "version": "8.16.0",
995
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
996
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
997
+ "dev": true,
998
+ "license": "MIT",
999
+ "bin": {
1000
+ "acorn": "bin/acorn"
1001
+ },
1002
+ "engines": {
1003
+ "node": ">=0.4.0"
1004
+ }
1005
+ },
1006
+ "node_modules/any-promise": {
1007
+ "version": "1.3.0",
1008
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
1009
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
1010
+ "dev": true,
1011
+ "license": "MIT"
1012
+ },
1013
+ "node_modules/assertion-error": {
1014
+ "version": "2.0.1",
1015
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
1016
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
1017
+ "dev": true,
1018
+ "license": "MIT",
1019
+ "engines": {
1020
+ "node": ">=12"
1021
+ }
1022
+ },
1023
+ "node_modules/bundle-require": {
1024
+ "version": "5.1.0",
1025
+ "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz",
1026
+ "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==",
1027
+ "dev": true,
1028
+ "license": "MIT",
1029
+ "dependencies": {
1030
+ "load-tsconfig": "^0.2.3"
1031
+ },
1032
+ "engines": {
1033
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
1034
+ },
1035
+ "peerDependencies": {
1036
+ "esbuild": ">=0.18"
1037
+ }
1038
+ },
1039
+ "node_modules/cac": {
1040
+ "version": "6.7.14",
1041
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
1042
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
1043
+ "dev": true,
1044
+ "license": "MIT",
1045
+ "engines": {
1046
+ "node": ">=8"
1047
+ }
1048
+ },
1049
+ "node_modules/chai": {
1050
+ "version": "5.3.3",
1051
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
1052
+ "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
1053
+ "dev": true,
1054
+ "license": "MIT",
1055
+ "dependencies": {
1056
+ "assertion-error": "^2.0.1",
1057
+ "check-error": "^2.1.1",
1058
+ "deep-eql": "^5.0.1",
1059
+ "loupe": "^3.1.0",
1060
+ "pathval": "^2.0.0"
1061
+ },
1062
+ "engines": {
1063
+ "node": ">=18"
1064
+ }
1065
+ },
1066
+ "node_modules/check-error": {
1067
+ "version": "2.1.3",
1068
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
1069
+ "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
1070
+ "dev": true,
1071
+ "license": "MIT",
1072
+ "engines": {
1073
+ "node": ">= 16"
1074
+ }
1075
+ },
1076
+ "node_modules/chokidar": {
1077
+ "version": "4.0.3",
1078
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
1079
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
1080
+ "dev": true,
1081
+ "license": "MIT",
1082
+ "dependencies": {
1083
+ "readdirp": "^4.0.1"
1084
+ },
1085
+ "engines": {
1086
+ "node": ">= 14.16.0"
1087
+ },
1088
+ "funding": {
1089
+ "url": "https://paulmillr.com/funding/"
1090
+ }
1091
+ },
1092
+ "node_modules/commander": {
1093
+ "version": "4.1.1",
1094
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
1095
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
1096
+ "dev": true,
1097
+ "license": "MIT",
1098
+ "engines": {
1099
+ "node": ">= 6"
1100
+ }
1101
+ },
1102
+ "node_modules/confbox": {
1103
+ "version": "0.1.8",
1104
+ "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
1105
+ "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
1106
+ "dev": true,
1107
+ "license": "MIT"
1108
+ },
1109
+ "node_modules/consola": {
1110
+ "version": "3.4.2",
1111
+ "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
1112
+ "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
1113
+ "dev": true,
1114
+ "license": "MIT",
1115
+ "engines": {
1116
+ "node": "^14.18.0 || >=16.10.0"
1117
+ }
1118
+ },
1119
+ "node_modules/debug": {
1120
+ "version": "4.4.3",
1121
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
1122
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
1123
+ "dev": true,
1124
+ "license": "MIT",
1125
+ "dependencies": {
1126
+ "ms": "^2.1.3"
1127
+ },
1128
+ "engines": {
1129
+ "node": ">=6.0"
1130
+ },
1131
+ "peerDependenciesMeta": {
1132
+ "supports-color": {
1133
+ "optional": true
1134
+ }
1135
+ }
1136
+ },
1137
+ "node_modules/deep-eql": {
1138
+ "version": "5.0.2",
1139
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
1140
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
1141
+ "dev": true,
1142
+ "license": "MIT",
1143
+ "engines": {
1144
+ "node": ">=6"
1145
+ }
1146
+ },
1147
+ "node_modules/es-module-lexer": {
1148
+ "version": "1.7.0",
1149
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
1150
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
1151
+ "dev": true,
1152
+ "license": "MIT"
1153
+ },
1154
+ "node_modules/esbuild": {
1155
+ "version": "0.27.4",
1156
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz",
1157
+ "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==",
1158
+ "dev": true,
1159
+ "hasInstallScript": true,
1160
+ "license": "MIT",
1161
+ "bin": {
1162
+ "esbuild": "bin/esbuild"
1163
+ },
1164
+ "engines": {
1165
+ "node": ">=18"
1166
+ },
1167
+ "optionalDependencies": {
1168
+ "@esbuild/aix-ppc64": "0.27.4",
1169
+ "@esbuild/android-arm": "0.27.4",
1170
+ "@esbuild/android-arm64": "0.27.4",
1171
+ "@esbuild/android-x64": "0.27.4",
1172
+ "@esbuild/darwin-arm64": "0.27.4",
1173
+ "@esbuild/darwin-x64": "0.27.4",
1174
+ "@esbuild/freebsd-arm64": "0.27.4",
1175
+ "@esbuild/freebsd-x64": "0.27.4",
1176
+ "@esbuild/linux-arm": "0.27.4",
1177
+ "@esbuild/linux-arm64": "0.27.4",
1178
+ "@esbuild/linux-ia32": "0.27.4",
1179
+ "@esbuild/linux-loong64": "0.27.4",
1180
+ "@esbuild/linux-mips64el": "0.27.4",
1181
+ "@esbuild/linux-ppc64": "0.27.4",
1182
+ "@esbuild/linux-riscv64": "0.27.4",
1183
+ "@esbuild/linux-s390x": "0.27.4",
1184
+ "@esbuild/linux-x64": "0.27.4",
1185
+ "@esbuild/netbsd-arm64": "0.27.4",
1186
+ "@esbuild/netbsd-x64": "0.27.4",
1187
+ "@esbuild/openbsd-arm64": "0.27.4",
1188
+ "@esbuild/openbsd-x64": "0.27.4",
1189
+ "@esbuild/openharmony-arm64": "0.27.4",
1190
+ "@esbuild/sunos-x64": "0.27.4",
1191
+ "@esbuild/win32-arm64": "0.27.4",
1192
+ "@esbuild/win32-ia32": "0.27.4",
1193
+ "@esbuild/win32-x64": "0.27.4"
1194
+ }
1195
+ },
1196
+ "node_modules/estree-walker": {
1197
+ "version": "3.0.3",
1198
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
1199
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
1200
+ "dev": true,
1201
+ "license": "MIT",
1202
+ "dependencies": {
1203
+ "@types/estree": "^1.0.0"
1204
+ }
1205
+ },
1206
+ "node_modules/expect-type": {
1207
+ "version": "1.3.0",
1208
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
1209
+ "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
1210
+ "dev": true,
1211
+ "license": "Apache-2.0",
1212
+ "engines": {
1213
+ "node": ">=12.0.0"
1214
+ }
1215
+ },
1216
+ "node_modules/fdir": {
1217
+ "version": "6.5.0",
1218
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
1219
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
1220
+ "dev": true,
1221
+ "license": "MIT",
1222
+ "engines": {
1223
+ "node": ">=12.0.0"
1224
+ },
1225
+ "peerDependencies": {
1226
+ "picomatch": "^3 || ^4"
1227
+ },
1228
+ "peerDependenciesMeta": {
1229
+ "picomatch": {
1230
+ "optional": true
1231
+ }
1232
+ }
1233
+ },
1234
+ "node_modules/fix-dts-default-cjs-exports": {
1235
+ "version": "1.0.1",
1236
+ "resolved": "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz",
1237
+ "integrity": "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==",
1238
+ "dev": true,
1239
+ "license": "MIT",
1240
+ "dependencies": {
1241
+ "magic-string": "^0.30.17",
1242
+ "mlly": "^1.7.4",
1243
+ "rollup": "^4.34.8"
1244
+ }
1245
+ },
1246
+ "node_modules/fsevents": {
1247
+ "version": "2.3.3",
1248
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1249
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1250
+ "dev": true,
1251
+ "hasInstallScript": true,
1252
+ "license": "MIT",
1253
+ "optional": true,
1254
+ "os": [
1255
+ "darwin"
1256
+ ],
1257
+ "engines": {
1258
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1259
+ }
1260
+ },
1261
+ "node_modules/headroom-ai": {
1262
+ "version": "0.1.0",
1263
+ "resolved": "https://registry.npmjs.org/headroom-ai/-/headroom-ai-0.1.0.tgz",
1264
+ "integrity": "sha512-SM5i2kptwsO+KnQqpaLThZVx1ZrmobVw5JRXwF5OvnMvhV/3WbwUI+VvXHTwTCvVq+AAyhkhuVcNXod1piAVuQ==",
1265
+ "license": "Apache-2.0",
1266
+ "engines": {
1267
+ "node": ">=18.0.0"
1268
+ },
1269
+ "peerDependencies": {
1270
+ "@ai-sdk/provider": ">=1.0.0",
1271
+ "@anthropic-ai/sdk": ">=0.30.0",
1272
+ "ai": ">=6.0.0",
1273
+ "openai": ">=4.0.0"
1274
+ },
1275
+ "peerDependenciesMeta": {
1276
+ "@ai-sdk/provider": {
1277
+ "optional": true
1278
+ },
1279
+ "@anthropic-ai/sdk": {
1280
+ "optional": true
1281
+ },
1282
+ "ai": {
1283
+ "optional": true
1284
+ },
1285
+ "openai": {
1286
+ "optional": true
1287
+ }
1288
+ }
1289
+ },
1290
+ "node_modules/joycon": {
1291
+ "version": "3.1.1",
1292
+ "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
1293
+ "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==",
1294
+ "dev": true,
1295
+ "license": "MIT",
1296
+ "engines": {
1297
+ "node": ">=10"
1298
+ }
1299
+ },
1300
+ "node_modules/lilconfig": {
1301
+ "version": "3.1.3",
1302
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
1303
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
1304
+ "dev": true,
1305
+ "license": "MIT",
1306
+ "engines": {
1307
+ "node": ">=14"
1308
+ },
1309
+ "funding": {
1310
+ "url": "https://github.com/sponsors/antonk52"
1311
+ }
1312
+ },
1313
+ "node_modules/lines-and-columns": {
1314
+ "version": "1.2.4",
1315
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
1316
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
1317
+ "dev": true,
1318
+ "license": "MIT"
1319
+ },
1320
+ "node_modules/load-tsconfig": {
1321
+ "version": "0.2.5",
1322
+ "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz",
1323
+ "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==",
1324
+ "dev": true,
1325
+ "license": "MIT",
1326
+ "engines": {
1327
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
1328
+ }
1329
+ },
1330
+ "node_modules/loupe": {
1331
+ "version": "3.2.1",
1332
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
1333
+ "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
1334
+ "dev": true,
1335
+ "license": "MIT"
1336
+ },
1337
+ "node_modules/magic-string": {
1338
+ "version": "0.30.21",
1339
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
1340
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
1341
+ "dev": true,
1342
+ "license": "MIT",
1343
+ "dependencies": {
1344
+ "@jridgewell/sourcemap-codec": "^1.5.5"
1345
+ }
1346
+ },
1347
+ "node_modules/mlly": {
1348
+ "version": "1.8.2",
1349
+ "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz",
1350
+ "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==",
1351
+ "dev": true,
1352
+ "license": "MIT",
1353
+ "dependencies": {
1354
+ "acorn": "^8.16.0",
1355
+ "pathe": "^2.0.3",
1356
+ "pkg-types": "^1.3.1",
1357
+ "ufo": "^1.6.3"
1358
+ }
1359
+ },
1360
+ "node_modules/ms": {
1361
+ "version": "2.1.3",
1362
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1363
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1364
+ "dev": true,
1365
+ "license": "MIT"
1366
+ },
1367
+ "node_modules/mz": {
1368
+ "version": "2.7.0",
1369
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
1370
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
1371
+ "dev": true,
1372
+ "license": "MIT",
1373
+ "dependencies": {
1374
+ "any-promise": "^1.0.0",
1375
+ "object-assign": "^4.0.1",
1376
+ "thenify-all": "^1.0.0"
1377
+ }
1378
+ },
1379
+ "node_modules/nanoid": {
1380
+ "version": "3.3.11",
1381
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
1382
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
1383
+ "dev": true,
1384
+ "funding": [
1385
+ {
1386
+ "type": "github",
1387
+ "url": "https://github.com/sponsors/ai"
1388
+ }
1389
+ ],
1390
+ "license": "MIT",
1391
+ "bin": {
1392
+ "nanoid": "bin/nanoid.cjs"
1393
+ },
1394
+ "engines": {
1395
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1396
+ }
1397
+ },
1398
+ "node_modules/object-assign": {
1399
+ "version": "4.1.1",
1400
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1401
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
1402
+ "dev": true,
1403
+ "license": "MIT",
1404
+ "engines": {
1405
+ "node": ">=0.10.0"
1406
+ }
1407
+ },
1408
+ "node_modules/pathe": {
1409
+ "version": "2.0.3",
1410
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
1411
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
1412
+ "dev": true,
1413
+ "license": "MIT"
1414
+ },
1415
+ "node_modules/pathval": {
1416
+ "version": "2.0.1",
1417
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
1418
+ "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
1419
+ "dev": true,
1420
+ "license": "MIT",
1421
+ "engines": {
1422
+ "node": ">= 14.16"
1423
+ }
1424
+ },
1425
+ "node_modules/picocolors": {
1426
+ "version": "1.1.1",
1427
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
1428
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
1429
+ "dev": true,
1430
+ "license": "ISC"
1431
+ },
1432
+ "node_modules/picomatch": {
1433
+ "version": "4.0.4",
1434
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
1435
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
1436
+ "dev": true,
1437
+ "license": "MIT",
1438
+ "engines": {
1439
+ "node": ">=12"
1440
+ },
1441
+ "funding": {
1442
+ "url": "https://github.com/sponsors/jonschlinkert"
1443
+ }
1444
+ },
1445
+ "node_modules/pirates": {
1446
+ "version": "4.0.7",
1447
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
1448
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
1449
+ "dev": true,
1450
+ "license": "MIT",
1451
+ "engines": {
1452
+ "node": ">= 6"
1453
+ }
1454
+ },
1455
+ "node_modules/pkg-types": {
1456
+ "version": "1.3.1",
1457
+ "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
1458
+ "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
1459
+ "dev": true,
1460
+ "license": "MIT",
1461
+ "dependencies": {
1462
+ "confbox": "^0.1.8",
1463
+ "mlly": "^1.7.4",
1464
+ "pathe": "^2.0.1"
1465
+ }
1466
+ },
1467
+ "node_modules/postcss": {
1468
+ "version": "8.5.8",
1469
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
1470
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
1471
+ "dev": true,
1472
+ "funding": [
1473
+ {
1474
+ "type": "opencollective",
1475
+ "url": "https://opencollective.com/postcss/"
1476
+ },
1477
+ {
1478
+ "type": "tidelift",
1479
+ "url": "https://tidelift.com/funding/github/npm/postcss"
1480
+ },
1481
+ {
1482
+ "type": "github",
1483
+ "url": "https://github.com/sponsors/ai"
1484
+ }
1485
+ ],
1486
+ "license": "MIT",
1487
+ "dependencies": {
1488
+ "nanoid": "^3.3.11",
1489
+ "picocolors": "^1.1.1",
1490
+ "source-map-js": "^1.2.1"
1491
+ },
1492
+ "engines": {
1493
+ "node": "^10 || ^12 || >=14"
1494
+ }
1495
+ },
1496
+ "node_modules/postcss-load-config": {
1497
+ "version": "6.0.1",
1498
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
1499
+ "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
1500
+ "dev": true,
1501
+ "funding": [
1502
+ {
1503
+ "type": "opencollective",
1504
+ "url": "https://opencollective.com/postcss/"
1505
+ },
1506
+ {
1507
+ "type": "github",
1508
+ "url": "https://github.com/sponsors/ai"
1509
+ }
1510
+ ],
1511
+ "license": "MIT",
1512
+ "dependencies": {
1513
+ "lilconfig": "^3.1.1"
1514
+ },
1515
+ "engines": {
1516
+ "node": ">= 18"
1517
+ },
1518
+ "peerDependencies": {
1519
+ "jiti": ">=1.21.0",
1520
+ "postcss": ">=8.0.9",
1521
+ "tsx": "^4.8.1",
1522
+ "yaml": "^2.4.2"
1523
+ },
1524
+ "peerDependenciesMeta": {
1525
+ "jiti": {
1526
+ "optional": true
1527
+ },
1528
+ "postcss": {
1529
+ "optional": true
1530
+ },
1531
+ "tsx": {
1532
+ "optional": true
1533
+ },
1534
+ "yaml": {
1535
+ "optional": true
1536
+ }
1537
+ }
1538
+ },
1539
+ "node_modules/readdirp": {
1540
+ "version": "4.1.2",
1541
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
1542
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
1543
+ "dev": true,
1544
+ "license": "MIT",
1545
+ "engines": {
1546
+ "node": ">= 14.18.0"
1547
+ },
1548
+ "funding": {
1549
+ "type": "individual",
1550
+ "url": "https://paulmillr.com/funding/"
1551
+ }
1552
+ },
1553
+ "node_modules/resolve-from": {
1554
+ "version": "5.0.0",
1555
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
1556
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
1557
+ "dev": true,
1558
+ "license": "MIT",
1559
+ "engines": {
1560
+ "node": ">=8"
1561
+ }
1562
+ },
1563
+ "node_modules/rollup": {
1564
+ "version": "4.60.0",
1565
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.0.tgz",
1566
+ "integrity": "sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ==",
1567
+ "dev": true,
1568
+ "license": "MIT",
1569
+ "dependencies": {
1570
+ "@types/estree": "1.0.8"
1571
+ },
1572
+ "bin": {
1573
+ "rollup": "dist/bin/rollup"
1574
+ },
1575
+ "engines": {
1576
+ "node": ">=18.0.0",
1577
+ "npm": ">=8.0.0"
1578
+ },
1579
+ "optionalDependencies": {
1580
+ "@rollup/rollup-android-arm-eabi": "4.60.0",
1581
+ "@rollup/rollup-android-arm64": "4.60.0",
1582
+ "@rollup/rollup-darwin-arm64": "4.60.0",
1583
+ "@rollup/rollup-darwin-x64": "4.60.0",
1584
+ "@rollup/rollup-freebsd-arm64": "4.60.0",
1585
+ "@rollup/rollup-freebsd-x64": "4.60.0",
1586
+ "@rollup/rollup-linux-arm-gnueabihf": "4.60.0",
1587
+ "@rollup/rollup-linux-arm-musleabihf": "4.60.0",
1588
+ "@rollup/rollup-linux-arm64-gnu": "4.60.0",
1589
+ "@rollup/rollup-linux-arm64-musl": "4.60.0",
1590
+ "@rollup/rollup-linux-loong64-gnu": "4.60.0",
1591
+ "@rollup/rollup-linux-loong64-musl": "4.60.0",
1592
+ "@rollup/rollup-linux-ppc64-gnu": "4.60.0",
1593
+ "@rollup/rollup-linux-ppc64-musl": "4.60.0",
1594
+ "@rollup/rollup-linux-riscv64-gnu": "4.60.0",
1595
+ "@rollup/rollup-linux-riscv64-musl": "4.60.0",
1596
+ "@rollup/rollup-linux-s390x-gnu": "4.60.0",
1597
+ "@rollup/rollup-linux-x64-gnu": "4.60.0",
1598
+ "@rollup/rollup-linux-x64-musl": "4.60.0",
1599
+ "@rollup/rollup-openbsd-x64": "4.60.0",
1600
+ "@rollup/rollup-openharmony-arm64": "4.60.0",
1601
+ "@rollup/rollup-win32-arm64-msvc": "4.60.0",
1602
+ "@rollup/rollup-win32-ia32-msvc": "4.60.0",
1603
+ "@rollup/rollup-win32-x64-gnu": "4.60.0",
1604
+ "@rollup/rollup-win32-x64-msvc": "4.60.0",
1605
+ "fsevents": "~2.3.2"
1606
+ }
1607
+ },
1608
+ "node_modules/siginfo": {
1609
+ "version": "2.0.0",
1610
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
1611
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
1612
+ "dev": true,
1613
+ "license": "ISC"
1614
+ },
1615
+ "node_modules/source-map": {
1616
+ "version": "0.7.6",
1617
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
1618
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
1619
+ "dev": true,
1620
+ "license": "BSD-3-Clause",
1621
+ "engines": {
1622
+ "node": ">= 12"
1623
+ }
1624
+ },
1625
+ "node_modules/source-map-js": {
1626
+ "version": "1.2.1",
1627
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1628
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1629
+ "dev": true,
1630
+ "license": "BSD-3-Clause",
1631
+ "engines": {
1632
+ "node": ">=0.10.0"
1633
+ }
1634
+ },
1635
+ "node_modules/stackback": {
1636
+ "version": "0.0.2",
1637
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
1638
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
1639
+ "dev": true,
1640
+ "license": "MIT"
1641
+ },
1642
+ "node_modules/std-env": {
1643
+ "version": "3.10.0",
1644
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
1645
+ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
1646
+ "dev": true,
1647
+ "license": "MIT"
1648
+ },
1649
+ "node_modules/sucrase": {
1650
+ "version": "3.35.1",
1651
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
1652
+ "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
1653
+ "dev": true,
1654
+ "license": "MIT",
1655
+ "dependencies": {
1656
+ "@jridgewell/gen-mapping": "^0.3.2",
1657
+ "commander": "^4.0.0",
1658
+ "lines-and-columns": "^1.1.6",
1659
+ "mz": "^2.7.0",
1660
+ "pirates": "^4.0.1",
1661
+ "tinyglobby": "^0.2.11",
1662
+ "ts-interface-checker": "^0.1.9"
1663
+ },
1664
+ "bin": {
1665
+ "sucrase": "bin/sucrase",
1666
+ "sucrase-node": "bin/sucrase-node"
1667
+ },
1668
+ "engines": {
1669
+ "node": ">=16 || 14 >=14.17"
1670
+ }
1671
+ },
1672
+ "node_modules/thenify": {
1673
+ "version": "3.3.1",
1674
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
1675
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
1676
+ "dev": true,
1677
+ "license": "MIT",
1678
+ "dependencies": {
1679
+ "any-promise": "^1.0.0"
1680
+ }
1681
+ },
1682
+ "node_modules/thenify-all": {
1683
+ "version": "1.6.0",
1684
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
1685
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
1686
+ "dev": true,
1687
+ "license": "MIT",
1688
+ "dependencies": {
1689
+ "thenify": ">= 3.1.0 < 4"
1690
+ },
1691
+ "engines": {
1692
+ "node": ">=0.8"
1693
+ }
1694
+ },
1695
+ "node_modules/tinybench": {
1696
+ "version": "2.9.0",
1697
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
1698
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
1699
+ "dev": true,
1700
+ "license": "MIT"
1701
+ },
1702
+ "node_modules/tinyexec": {
1703
+ "version": "0.3.2",
1704
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
1705
+ "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
1706
+ "dev": true,
1707
+ "license": "MIT"
1708
+ },
1709
+ "node_modules/tinyglobby": {
1710
+ "version": "0.2.15",
1711
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
1712
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
1713
+ "dev": true,
1714
+ "license": "MIT",
1715
+ "dependencies": {
1716
+ "fdir": "^6.5.0",
1717
+ "picomatch": "^4.0.3"
1718
+ },
1719
+ "engines": {
1720
+ "node": ">=12.0.0"
1721
+ },
1722
+ "funding": {
1723
+ "url": "https://github.com/sponsors/SuperchupuDev"
1724
+ }
1725
+ },
1726
+ "node_modules/tinypool": {
1727
+ "version": "1.1.1",
1728
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
1729
+ "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
1730
+ "dev": true,
1731
+ "license": "MIT",
1732
+ "engines": {
1733
+ "node": "^18.0.0 || >=20.0.0"
1734
+ }
1735
+ },
1736
+ "node_modules/tinyrainbow": {
1737
+ "version": "1.2.0",
1738
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
1739
+ "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
1740
+ "dev": true,
1741
+ "license": "MIT",
1742
+ "engines": {
1743
+ "node": ">=14.0.0"
1744
+ }
1745
+ },
1746
+ "node_modules/tinyspy": {
1747
+ "version": "3.0.2",
1748
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
1749
+ "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
1750
+ "dev": true,
1751
+ "license": "MIT",
1752
+ "engines": {
1753
+ "node": ">=14.0.0"
1754
+ }
1755
+ },
1756
+ "node_modules/tree-kill": {
1757
+ "version": "1.2.2",
1758
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
1759
+ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
1760
+ "dev": true,
1761
+ "license": "MIT",
1762
+ "bin": {
1763
+ "tree-kill": "cli.js"
1764
+ }
1765
+ },
1766
+ "node_modules/ts-interface-checker": {
1767
+ "version": "0.1.13",
1768
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
1769
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
1770
+ "dev": true,
1771
+ "license": "Apache-2.0"
1772
+ },
1773
+ "node_modules/tsup": {
1774
+ "version": "8.5.1",
1775
+ "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.5.1.tgz",
1776
+ "integrity": "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==",
1777
+ "dev": true,
1778
+ "license": "MIT",
1779
+ "dependencies": {
1780
+ "bundle-require": "^5.1.0",
1781
+ "cac": "^6.7.14",
1782
+ "chokidar": "^4.0.3",
1783
+ "consola": "^3.4.0",
1784
+ "debug": "^4.4.0",
1785
+ "esbuild": "^0.27.0",
1786
+ "fix-dts-default-cjs-exports": "^1.0.0",
1787
+ "joycon": "^3.1.1",
1788
+ "picocolors": "^1.1.1",
1789
+ "postcss-load-config": "^6.0.1",
1790
+ "resolve-from": "^5.0.0",
1791
+ "rollup": "^4.34.8",
1792
+ "source-map": "^0.7.6",
1793
+ "sucrase": "^3.35.0",
1794
+ "tinyexec": "^0.3.2",
1795
+ "tinyglobby": "^0.2.11",
1796
+ "tree-kill": "^1.2.2"
1797
+ },
1798
+ "bin": {
1799
+ "tsup": "dist/cli-default.js",
1800
+ "tsup-node": "dist/cli-node.js"
1801
+ },
1802
+ "engines": {
1803
+ "node": ">=18"
1804
+ },
1805
+ "peerDependencies": {
1806
+ "@microsoft/api-extractor": "^7.36.0",
1807
+ "@swc/core": "^1",
1808
+ "postcss": "^8.4.12",
1809
+ "typescript": ">=4.5.0"
1810
+ },
1811
+ "peerDependenciesMeta": {
1812
+ "@microsoft/api-extractor": {
1813
+ "optional": true
1814
+ },
1815
+ "@swc/core": {
1816
+ "optional": true
1817
+ },
1818
+ "postcss": {
1819
+ "optional": true
1820
+ },
1821
+ "typescript": {
1822
+ "optional": true
1823
+ }
1824
+ }
1825
+ },
1826
+ "node_modules/typescript": {
1827
+ "version": "5.9.3",
1828
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
1829
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
1830
+ "dev": true,
1831
+ "license": "Apache-2.0",
1832
+ "bin": {
1833
+ "tsc": "bin/tsc",
1834
+ "tsserver": "bin/tsserver"
1835
+ },
1836
+ "engines": {
1837
+ "node": ">=14.17"
1838
+ }
1839
+ },
1840
+ "node_modules/ufo": {
1841
+ "version": "1.6.3",
1842
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz",
1843
+ "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==",
1844
+ "dev": true,
1845
+ "license": "MIT"
1846
+ },
1847
+ "node_modules/vite": {
1848
+ "version": "5.4.21",
1849
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
1850
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
1851
+ "dev": true,
1852
+ "license": "MIT",
1853
+ "dependencies": {
1854
+ "esbuild": "^0.21.3",
1855
+ "postcss": "^8.4.43",
1856
+ "rollup": "^4.20.0"
1857
+ },
1858
+ "bin": {
1859
+ "vite": "bin/vite.js"
1860
+ },
1861
+ "engines": {
1862
+ "node": "^18.0.0 || >=20.0.0"
1863
+ },
1864
+ "funding": {
1865
+ "url": "https://github.com/vitejs/vite?sponsor=1"
1866
+ },
1867
+ "optionalDependencies": {
1868
+ "fsevents": "~2.3.3"
1869
+ },
1870
+ "peerDependencies": {
1871
+ "@types/node": "^18.0.0 || >=20.0.0",
1872
+ "less": "*",
1873
+ "lightningcss": "^1.21.0",
1874
+ "sass": "*",
1875
+ "sass-embedded": "*",
1876
+ "stylus": "*",
1877
+ "sugarss": "*",
1878
+ "terser": "^5.4.0"
1879
+ },
1880
+ "peerDependenciesMeta": {
1881
+ "@types/node": {
1882
+ "optional": true
1883
+ },
1884
+ "less": {
1885
+ "optional": true
1886
+ },
1887
+ "lightningcss": {
1888
+ "optional": true
1889
+ },
1890
+ "sass": {
1891
+ "optional": true
1892
+ },
1893
+ "sass-embedded": {
1894
+ "optional": true
1895
+ },
1896
+ "stylus": {
1897
+ "optional": true
1898
+ },
1899
+ "sugarss": {
1900
+ "optional": true
1901
+ },
1902
+ "terser": {
1903
+ "optional": true
1904
+ }
1905
+ }
1906
+ },
1907
+ "node_modules/vite-node": {
1908
+ "version": "2.1.9",
1909
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz",
1910
+ "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==",
1911
+ "dev": true,
1912
+ "license": "MIT",
1913
+ "dependencies": {
1914
+ "cac": "^6.7.14",
1915
+ "debug": "^4.3.7",
1916
+ "es-module-lexer": "^1.5.4",
1917
+ "pathe": "^1.1.2",
1918
+ "vite": "^5.0.0"
1919
+ },
1920
+ "bin": {
1921
+ "vite-node": "vite-node.mjs"
1922
+ },
1923
+ "engines": {
1924
+ "node": "^18.0.0 || >=20.0.0"
1925
+ },
1926
+ "funding": {
1927
+ "url": "https://opencollective.com/vitest"
1928
+ }
1929
+ },
1930
+ "node_modules/vite-node/node_modules/pathe": {
1931
+ "version": "1.1.2",
1932
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
1933
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
1934
+ "dev": true,
1935
+ "license": "MIT"
1936
+ },
1937
+ "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
1938
+ "version": "0.21.5",
1939
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
1940
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
1941
+ "cpu": [
1942
+ "ppc64"
1943
+ ],
1944
+ "dev": true,
1945
+ "license": "MIT",
1946
+ "optional": true,
1947
+ "os": [
1948
+ "aix"
1949
+ ],
1950
+ "engines": {
1951
+ "node": ">=12"
1952
+ }
1953
+ },
1954
+ "node_modules/vite/node_modules/@esbuild/android-arm": {
1955
+ "version": "0.21.5",
1956
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
1957
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
1958
+ "cpu": [
1959
+ "arm"
1960
+ ],
1961
+ "dev": true,
1962
+ "license": "MIT",
1963
+ "optional": true,
1964
+ "os": [
1965
+ "android"
1966
+ ],
1967
+ "engines": {
1968
+ "node": ">=12"
1969
+ }
1970
+ },
1971
+ "node_modules/vite/node_modules/@esbuild/android-arm64": {
1972
+ "version": "0.21.5",
1973
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
1974
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
1975
+ "cpu": [
1976
+ "arm64"
1977
+ ],
1978
+ "dev": true,
1979
+ "license": "MIT",
1980
+ "optional": true,
1981
+ "os": [
1982
+ "android"
1983
+ ],
1984
+ "engines": {
1985
+ "node": ">=12"
1986
+ }
1987
+ },
1988
+ "node_modules/vite/node_modules/@esbuild/android-x64": {
1989
+ "version": "0.21.5",
1990
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
1991
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
1992
+ "cpu": [
1993
+ "x64"
1994
+ ],
1995
+ "dev": true,
1996
+ "license": "MIT",
1997
+ "optional": true,
1998
+ "os": [
1999
+ "android"
2000
+ ],
2001
+ "engines": {
2002
+ "node": ">=12"
2003
+ }
2004
+ },
2005
+ "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
2006
+ "version": "0.21.5",
2007
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
2008
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
2009
+ "cpu": [
2010
+ "arm64"
2011
+ ],
2012
+ "dev": true,
2013
+ "license": "MIT",
2014
+ "optional": true,
2015
+ "os": [
2016
+ "darwin"
2017
+ ],
2018
+ "engines": {
2019
+ "node": ">=12"
2020
+ }
2021
+ },
2022
+ "node_modules/vite/node_modules/@esbuild/darwin-x64": {
2023
+ "version": "0.21.5",
2024
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
2025
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
2026
+ "cpu": [
2027
+ "x64"
2028
+ ],
2029
+ "dev": true,
2030
+ "license": "MIT",
2031
+ "optional": true,
2032
+ "os": [
2033
+ "darwin"
2034
+ ],
2035
+ "engines": {
2036
+ "node": ">=12"
2037
+ }
2038
+ },
2039
+ "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
2040
+ "version": "0.21.5",
2041
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
2042
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
2043
+ "cpu": [
2044
+ "arm64"
2045
+ ],
2046
+ "dev": true,
2047
+ "license": "MIT",
2048
+ "optional": true,
2049
+ "os": [
2050
+ "freebsd"
2051
+ ],
2052
+ "engines": {
2053
+ "node": ">=12"
2054
+ }
2055
+ },
2056
+ "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
2057
+ "version": "0.21.5",
2058
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
2059
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
2060
+ "cpu": [
2061
+ "x64"
2062
+ ],
2063
+ "dev": true,
2064
+ "license": "MIT",
2065
+ "optional": true,
2066
+ "os": [
2067
+ "freebsd"
2068
+ ],
2069
+ "engines": {
2070
+ "node": ">=12"
2071
+ }
2072
+ },
2073
+ "node_modules/vite/node_modules/@esbuild/linux-arm": {
2074
+ "version": "0.21.5",
2075
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
2076
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
2077
+ "cpu": [
2078
+ "arm"
2079
+ ],
2080
+ "dev": true,
2081
+ "license": "MIT",
2082
+ "optional": true,
2083
+ "os": [
2084
+ "linux"
2085
+ ],
2086
+ "engines": {
2087
+ "node": ">=12"
2088
+ }
2089
+ },
2090
+ "node_modules/vite/node_modules/@esbuild/linux-arm64": {
2091
+ "version": "0.21.5",
2092
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
2093
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
2094
+ "cpu": [
2095
+ "arm64"
2096
+ ],
2097
+ "dev": true,
2098
+ "license": "MIT",
2099
+ "optional": true,
2100
+ "os": [
2101
+ "linux"
2102
+ ],
2103
+ "engines": {
2104
+ "node": ">=12"
2105
+ }
2106
+ },
2107
+ "node_modules/vite/node_modules/@esbuild/linux-ia32": {
2108
+ "version": "0.21.5",
2109
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
2110
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
2111
+ "cpu": [
2112
+ "ia32"
2113
+ ],
2114
+ "dev": true,
2115
+ "license": "MIT",
2116
+ "optional": true,
2117
+ "os": [
2118
+ "linux"
2119
+ ],
2120
+ "engines": {
2121
+ "node": ">=12"
2122
+ }
2123
+ },
2124
+ "node_modules/vite/node_modules/@esbuild/linux-loong64": {
2125
+ "version": "0.21.5",
2126
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
2127
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
2128
+ "cpu": [
2129
+ "loong64"
2130
+ ],
2131
+ "dev": true,
2132
+ "license": "MIT",
2133
+ "optional": true,
2134
+ "os": [
2135
+ "linux"
2136
+ ],
2137
+ "engines": {
2138
+ "node": ">=12"
2139
+ }
2140
+ },
2141
+ "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
2142
+ "version": "0.21.5",
2143
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
2144
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
2145
+ "cpu": [
2146
+ "mips64el"
2147
+ ],
2148
+ "dev": true,
2149
+ "license": "MIT",
2150
+ "optional": true,
2151
+ "os": [
2152
+ "linux"
2153
+ ],
2154
+ "engines": {
2155
+ "node": ">=12"
2156
+ }
2157
+ },
2158
+ "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
2159
+ "version": "0.21.5",
2160
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
2161
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
2162
+ "cpu": [
2163
+ "ppc64"
2164
+ ],
2165
+ "dev": true,
2166
+ "license": "MIT",
2167
+ "optional": true,
2168
+ "os": [
2169
+ "linux"
2170
+ ],
2171
+ "engines": {
2172
+ "node": ">=12"
2173
+ }
2174
+ },
2175
+ "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
2176
+ "version": "0.21.5",
2177
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
2178
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
2179
+ "cpu": [
2180
+ "riscv64"
2181
+ ],
2182
+ "dev": true,
2183
+ "license": "MIT",
2184
+ "optional": true,
2185
+ "os": [
2186
+ "linux"
2187
+ ],
2188
+ "engines": {
2189
+ "node": ">=12"
2190
+ }
2191
+ },
2192
+ "node_modules/vite/node_modules/@esbuild/linux-s390x": {
2193
+ "version": "0.21.5",
2194
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
2195
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
2196
+ "cpu": [
2197
+ "s390x"
2198
+ ],
2199
+ "dev": true,
2200
+ "license": "MIT",
2201
+ "optional": true,
2202
+ "os": [
2203
+ "linux"
2204
+ ],
2205
+ "engines": {
2206
+ "node": ">=12"
2207
+ }
2208
+ },
2209
+ "node_modules/vite/node_modules/@esbuild/linux-x64": {
2210
+ "version": "0.21.5",
2211
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
2212
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
2213
+ "cpu": [
2214
+ "x64"
2215
+ ],
2216
+ "dev": true,
2217
+ "license": "MIT",
2218
+ "optional": true,
2219
+ "os": [
2220
+ "linux"
2221
+ ],
2222
+ "engines": {
2223
+ "node": ">=12"
2224
+ }
2225
+ },
2226
+ "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
2227
+ "version": "0.21.5",
2228
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
2229
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
2230
+ "cpu": [
2231
+ "x64"
2232
+ ],
2233
+ "dev": true,
2234
+ "license": "MIT",
2235
+ "optional": true,
2236
+ "os": [
2237
+ "netbsd"
2238
+ ],
2239
+ "engines": {
2240
+ "node": ">=12"
2241
+ }
2242
+ },
2243
+ "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
2244
+ "version": "0.21.5",
2245
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
2246
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
2247
+ "cpu": [
2248
+ "x64"
2249
+ ],
2250
+ "dev": true,
2251
+ "license": "MIT",
2252
+ "optional": true,
2253
+ "os": [
2254
+ "openbsd"
2255
+ ],
2256
+ "engines": {
2257
+ "node": ">=12"
2258
+ }
2259
+ },
2260
+ "node_modules/vite/node_modules/@esbuild/sunos-x64": {
2261
+ "version": "0.21.5",
2262
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
2263
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
2264
+ "cpu": [
2265
+ "x64"
2266
+ ],
2267
+ "dev": true,
2268
+ "license": "MIT",
2269
+ "optional": true,
2270
+ "os": [
2271
+ "sunos"
2272
+ ],
2273
+ "engines": {
2274
+ "node": ">=12"
2275
+ }
2276
+ },
2277
+ "node_modules/vite/node_modules/@esbuild/win32-arm64": {
2278
+ "version": "0.21.5",
2279
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
2280
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
2281
+ "cpu": [
2282
+ "arm64"
2283
+ ],
2284
+ "dev": true,
2285
+ "license": "MIT",
2286
+ "optional": true,
2287
+ "os": [
2288
+ "win32"
2289
+ ],
2290
+ "engines": {
2291
+ "node": ">=12"
2292
+ }
2293
+ },
2294
+ "node_modules/vite/node_modules/@esbuild/win32-ia32": {
2295
+ "version": "0.21.5",
2296
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
2297
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
2298
+ "cpu": [
2299
+ "ia32"
2300
+ ],
2301
+ "dev": true,
2302
+ "license": "MIT",
2303
+ "optional": true,
2304
+ "os": [
2305
+ "win32"
2306
+ ],
2307
+ "engines": {
2308
+ "node": ">=12"
2309
+ }
2310
+ },
2311
+ "node_modules/vite/node_modules/@esbuild/win32-x64": {
2312
+ "version": "0.21.5",
2313
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
2314
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
2315
+ "cpu": [
2316
+ "x64"
2317
+ ],
2318
+ "dev": true,
2319
+ "license": "MIT",
2320
+ "optional": true,
2321
+ "os": [
2322
+ "win32"
2323
+ ],
2324
+ "engines": {
2325
+ "node": ">=12"
2326
+ }
2327
+ },
2328
+ "node_modules/vite/node_modules/esbuild": {
2329
+ "version": "0.21.5",
2330
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
2331
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
2332
+ "dev": true,
2333
+ "hasInstallScript": true,
2334
+ "license": "MIT",
2335
+ "bin": {
2336
+ "esbuild": "bin/esbuild"
2337
+ },
2338
+ "engines": {
2339
+ "node": ">=12"
2340
+ },
2341
+ "optionalDependencies": {
2342
+ "@esbuild/aix-ppc64": "0.21.5",
2343
+ "@esbuild/android-arm": "0.21.5",
2344
+ "@esbuild/android-arm64": "0.21.5",
2345
+ "@esbuild/android-x64": "0.21.5",
2346
+ "@esbuild/darwin-arm64": "0.21.5",
2347
+ "@esbuild/darwin-x64": "0.21.5",
2348
+ "@esbuild/freebsd-arm64": "0.21.5",
2349
+ "@esbuild/freebsd-x64": "0.21.5",
2350
+ "@esbuild/linux-arm": "0.21.5",
2351
+ "@esbuild/linux-arm64": "0.21.5",
2352
+ "@esbuild/linux-ia32": "0.21.5",
2353
+ "@esbuild/linux-loong64": "0.21.5",
2354
+ "@esbuild/linux-mips64el": "0.21.5",
2355
+ "@esbuild/linux-ppc64": "0.21.5",
2356
+ "@esbuild/linux-riscv64": "0.21.5",
2357
+ "@esbuild/linux-s390x": "0.21.5",
2358
+ "@esbuild/linux-x64": "0.21.5",
2359
+ "@esbuild/netbsd-x64": "0.21.5",
2360
+ "@esbuild/openbsd-x64": "0.21.5",
2361
+ "@esbuild/sunos-x64": "0.21.5",
2362
+ "@esbuild/win32-arm64": "0.21.5",
2363
+ "@esbuild/win32-ia32": "0.21.5",
2364
+ "@esbuild/win32-x64": "0.21.5"
2365
+ }
2366
+ },
2367
+ "node_modules/vitest": {
2368
+ "version": "2.1.9",
2369
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz",
2370
+ "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==",
2371
+ "dev": true,
2372
+ "license": "MIT",
2373
+ "dependencies": {
2374
+ "@vitest/expect": "2.1.9",
2375
+ "@vitest/mocker": "2.1.9",
2376
+ "@vitest/pretty-format": "^2.1.9",
2377
+ "@vitest/runner": "2.1.9",
2378
+ "@vitest/snapshot": "2.1.9",
2379
+ "@vitest/spy": "2.1.9",
2380
+ "@vitest/utils": "2.1.9",
2381
+ "chai": "^5.1.2",
2382
+ "debug": "^4.3.7",
2383
+ "expect-type": "^1.1.0",
2384
+ "magic-string": "^0.30.12",
2385
+ "pathe": "^1.1.2",
2386
+ "std-env": "^3.8.0",
2387
+ "tinybench": "^2.9.0",
2388
+ "tinyexec": "^0.3.1",
2389
+ "tinypool": "^1.0.1",
2390
+ "tinyrainbow": "^1.2.0",
2391
+ "vite": "^5.0.0",
2392
+ "vite-node": "2.1.9",
2393
+ "why-is-node-running": "^2.3.0"
2394
+ },
2395
+ "bin": {
2396
+ "vitest": "vitest.mjs"
2397
+ },
2398
+ "engines": {
2399
+ "node": "^18.0.0 || >=20.0.0"
2400
+ },
2401
+ "funding": {
2402
+ "url": "https://opencollective.com/vitest"
2403
+ },
2404
+ "peerDependencies": {
2405
+ "@edge-runtime/vm": "*",
2406
+ "@types/node": "^18.0.0 || >=20.0.0",
2407
+ "@vitest/browser": "2.1.9",
2408
+ "@vitest/ui": "2.1.9",
2409
+ "happy-dom": "*",
2410
+ "jsdom": "*"
2411
+ },
2412
+ "peerDependenciesMeta": {
2413
+ "@edge-runtime/vm": {
2414
+ "optional": true
2415
+ },
2416
+ "@types/node": {
2417
+ "optional": true
2418
+ },
2419
+ "@vitest/browser": {
2420
+ "optional": true
2421
+ },
2422
+ "@vitest/ui": {
2423
+ "optional": true
2424
+ },
2425
+ "happy-dom": {
2426
+ "optional": true
2427
+ },
2428
+ "jsdom": {
2429
+ "optional": true
2430
+ }
2431
+ }
2432
+ },
2433
+ "node_modules/vitest/node_modules/pathe": {
2434
+ "version": "1.1.2",
2435
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
2436
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
2437
+ "dev": true,
2438
+ "license": "MIT"
2439
+ },
2440
+ "node_modules/why-is-node-running": {
2441
+ "version": "2.3.0",
2442
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
2443
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
2444
+ "dev": true,
2445
+ "license": "MIT",
2446
+ "dependencies": {
2447
+ "siginfo": "^2.0.0",
2448
+ "stackback": "0.0.2"
2449
+ },
2450
+ "bin": {
2451
+ "why-is-node-running": "cli.js"
2452
+ },
2453
+ "engines": {
2454
+ "node": ">=8"
2455
+ }
2456
+ }
2457
+ }
2458
+ }
plugins/openclaw/package.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "@headroom-ai/openclaw",
3
+ "version": "0.1.0",
4
+ "description": "Headroom context compression plugin for OpenClaw — 70-90% token savings with zero LLM calls",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": ["dist", "openclaw.plugin.json", "README.md"],
9
+ "scripts": {
10
+ "build": "tsup",
11
+ "test": "vitest run",
12
+ "test:watch": "vitest",
13
+ "typecheck": "tsc --noEmit"
14
+ },
15
+ "dependencies": {
16
+ "headroom-ai": "^0.1.0"
17
+ },
18
+ "peerDependencies": {
19
+ "openclaw": "*"
20
+ },
21
+ "peerDependenciesMeta": {
22
+ "openclaw": { "optional": true }
23
+ },
24
+ "devDependencies": {
25
+ "typescript": "^5.5.0",
26
+ "vitest": "^2.0.0",
27
+ "tsup": "^8.0.0"
28
+ },
29
+ "license": "Apache-2.0"
30
+ }
plugins/openclaw/src/convert.ts ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Convert between OpenClaw's AgentMessage format and OpenAI message format.
3
+ *
4
+ * AgentMessage uses:
5
+ * role: "user" | "assistant" | "toolResult"
6
+ * content: string | ContentBlock[]
7
+ *
8
+ * OpenAI uses:
9
+ * role: "user" | "assistant" | "system" | "tool"
10
+ * content: string
11
+ * tool_calls?: ToolCall[]
12
+ * tool_call_id?: string
13
+ */
14
+
15
+ /* eslint-disable @typescript-eslint/no-explicit-any */
16
+
17
+ export interface OpenAIMessage {
18
+ role: string;
19
+ content: string | null;
20
+ tool_calls?: any[];
21
+ tool_call_id?: string;
22
+ name?: string;
23
+ }
24
+
25
+ /**
26
+ * Convert AgentMessage[] to OpenAI message format for compression.
27
+ */
28
+ export function agentToOpenAI(messages: any[]): OpenAIMessage[] {
29
+ const result: OpenAIMessage[] = [];
30
+
31
+ for (const msg of messages) {
32
+ const role = msg.role;
33
+
34
+ if (role === "system") {
35
+ result.push({
36
+ role: "system",
37
+ content: typeof msg.content === "string" ? msg.content : extractText(msg.content),
38
+ });
39
+ continue;
40
+ }
41
+
42
+ if (role === "user") {
43
+ result.push({
44
+ role: "user",
45
+ content: typeof msg.content === "string" ? msg.content : extractText(msg.content),
46
+ });
47
+ continue;
48
+ }
49
+
50
+ if (role === "assistant") {
51
+ const content = msg.content;
52
+ if (typeof content === "string") {
53
+ result.push({ role: "assistant", content });
54
+ continue;
55
+ }
56
+
57
+ // Content blocks: extract text and tool_use blocks
58
+ if (Array.isArray(content)) {
59
+ const textParts: string[] = [];
60
+ const toolCalls: any[] = [];
61
+
62
+ for (const block of content) {
63
+ if (typeof block === "string") {
64
+ textParts.push(block);
65
+ } else if (block.type === "text") {
66
+ textParts.push(block.text);
67
+ } else if (block.type === "tool_use") {
68
+ toolCalls.push({
69
+ id: block.id,
70
+ type: "function",
71
+ function: {
72
+ name: block.name,
73
+ arguments:
74
+ typeof block.input === "string"
75
+ ? block.input
76
+ : JSON.stringify(block.input ?? {}),
77
+ },
78
+ });
79
+ }
80
+ }
81
+
82
+ const openaiMsg: OpenAIMessage = {
83
+ role: "assistant",
84
+ content: textParts.length > 0 ? textParts.join("") : null,
85
+ };
86
+ if (toolCalls.length > 0) {
87
+ openaiMsg.tool_calls = toolCalls;
88
+ }
89
+ result.push(openaiMsg);
90
+ }
91
+ continue;
92
+ }
93
+
94
+ if (role === "toolResult" || role === "tool_result") {
95
+ const content =
96
+ typeof msg.content === "string"
97
+ ? msg.content
98
+ : Array.isArray(msg.content)
99
+ ? extractText(msg.content)
100
+ : JSON.stringify(msg.content);
101
+
102
+ result.push({
103
+ role: "tool",
104
+ content,
105
+ tool_call_id: msg.tool_use_id ?? msg.toolCallId ?? msg.id ?? "unknown",
106
+ });
107
+ continue;
108
+ }
109
+
110
+ // Fallback: pass through as user message
111
+ result.push({
112
+ role: "user",
113
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
114
+ });
115
+ }
116
+
117
+ return result;
118
+ }
119
+
120
+ /**
121
+ * Convert compressed OpenAI messages back to AgentMessage format.
122
+ */
123
+ export function openAIToAgent(messages: OpenAIMessage[]): any[] {
124
+ const result: any[] = [];
125
+
126
+ for (const msg of messages) {
127
+ if (msg.role === "system") {
128
+ result.push({
129
+ role: "system",
130
+ content: msg.content ?? "",
131
+ timestamp: Date.now(),
132
+ });
133
+ continue;
134
+ }
135
+
136
+ if (msg.role === "user") {
137
+ result.push({
138
+ role: "user",
139
+ content: msg.content ?? "",
140
+ timestamp: Date.now(),
141
+ });
142
+ continue;
143
+ }
144
+
145
+ if (msg.role === "assistant") {
146
+ const blocks: any[] = [];
147
+ if (msg.content) {
148
+ blocks.push({ type: "text", text: msg.content });
149
+ }
150
+ if (msg.tool_calls) {
151
+ for (const tc of msg.tool_calls) {
152
+ let input: any;
153
+ try {
154
+ input = JSON.parse(tc.function.arguments);
155
+ } catch {
156
+ input = tc.function.arguments ?? {};
157
+ }
158
+ blocks.push({
159
+ type: "tool_use",
160
+ id: tc.id,
161
+ name: tc.function.name,
162
+ input,
163
+ });
164
+ }
165
+ }
166
+ result.push({
167
+ role: "assistant",
168
+ content: blocks.length === 1 && blocks[0].type === "text" ? blocks[0].text : blocks,
169
+ timestamp: Date.now(),
170
+ });
171
+ continue;
172
+ }
173
+
174
+ if (msg.role === "tool") {
175
+ result.push({
176
+ role: "toolResult",
177
+ content: msg.content ?? "",
178
+ tool_use_id: msg.tool_call_id ?? "unknown",
179
+ timestamp: Date.now(),
180
+ });
181
+ continue;
182
+ }
183
+ }
184
+
185
+ return result;
186
+ }
187
+
188
+ /**
189
+ * Extract text from content blocks.
190
+ */
191
+ function extractText(content: any): string {
192
+ if (typeof content === "string") return content;
193
+ if (!Array.isArray(content)) return JSON.stringify(content);
194
+
195
+ return content
196
+ .map((block: any) => {
197
+ if (typeof block === "string") return block;
198
+ if (block.type === "text") return block.text;
199
+ if (block.type === "tool_result") {
200
+ return typeof block.content === "string" ? block.content : JSON.stringify(block.content);
201
+ }
202
+ return "";
203
+ })
204
+ .filter(Boolean)
205
+ .join("\n");
206
+ }
plugins/openclaw/src/engine.ts ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * HeadroomContextEngine — ContextEngine implementation for OpenClaw.
3
+ *
4
+ * Compresses tool outputs and conversation context using the Headroom proxy.
5
+ * Zero LLM calls — all compression is algorithmic (SmartCrusher, ContentRouter, etc.)
6
+ */
7
+
8
+ /* eslint-disable @typescript-eslint/no-explicit-any */
9
+
10
+ import { compress } from "headroom-ai";
11
+ import { ProxyManager, type ProxyManagerConfig, type ProxyManagerLogger } from "./proxy-manager.js";
12
+ import { agentToOpenAI, openAIToAgent } from "./convert.js";
13
+
14
+ export interface HeadroomEngineConfig extends ProxyManagerConfig {
15
+ enabled?: boolean;
16
+ }
17
+
18
+ export class HeadroomContextEngine {
19
+ readonly info = {
20
+ id: "headroom",
21
+ name: "Headroom Context Compression",
22
+ version: "0.1.0",
23
+ ownsCompaction: true,
24
+ };
25
+
26
+ private proxyManager: ProxyManager;
27
+ private proxyUrl: string | null = null;
28
+ private config: HeadroomEngineConfig;
29
+ private logger: ProxyManagerLogger;
30
+ private stats = {
31
+ totalCompressions: 0,
32
+ totalTokensSaved: 0,
33
+ totalTokensBefore: 0,
34
+ compactions: 0,
35
+ };
36
+
37
+ constructor(config: HeadroomEngineConfig = {}, logger?: ProxyManagerLogger) {
38
+ this.config = config;
39
+ this.logger = logger ?? {
40
+ info: (m) => console.log(`[headroom] ${m}`),
41
+ warn: (m) => console.warn(`[headroom] ${m}`),
42
+ error: (m) => console.error(`[headroom] ${m}`),
43
+ debug: () => {},
44
+ };
45
+ this.proxyManager = new ProxyManager(config, this.logger);
46
+ }
47
+
48
+ // === ContextEngine Lifecycle ===
49
+
50
+ async bootstrap(params: {
51
+ sessionId: string;
52
+ sessionKey?: string;
53
+ sessionFile: string;
54
+ }): Promise<{ bootstrapped: boolean; reason?: string }> {
55
+ if (this.config.enabled === false) {
56
+ return { bootstrapped: false, reason: "disabled" };
57
+ }
58
+
59
+ try {
60
+ this.proxyUrl = await this.proxyManager.start();
61
+ this.logger.info(`Engine bootstrapped (proxy: ${this.proxyUrl})`);
62
+ return { bootstrapped: true };
63
+ } catch (error) {
64
+ this.logger.error(`Bootstrap failed: ${error}`);
65
+ return { bootstrapped: false, reason: String(error) };
66
+ }
67
+ }
68
+
69
+ async ingest(params: {
70
+ sessionId: string;
71
+ message: any;
72
+ isHeartbeat?: boolean;
73
+ }): Promise<{ ingested: boolean }> {
74
+ // No-op: OpenClaw's runtime stores messages. We don't need a separate store.
75
+ return { ingested: true };
76
+ }
77
+
78
+ async ingestBatch?(params: {
79
+ sessionId: string;
80
+ messages: any[];
81
+ isHeartbeat?: boolean;
82
+ }): Promise<{ ingestedCount: number }> {
83
+ return { ingestedCount: params.messages.length };
84
+ }
85
+
86
+ /**
87
+ * Assemble context for the model — THE CORE HOOK.
88
+ *
89
+ * Converts AgentMessage[] → OpenAI format → compress() → AgentMessage[]
90
+ */
91
+ async assemble(params: {
92
+ sessionId: string;
93
+ messages: any[];
94
+ tokenBudget?: number;
95
+ model?: string;
96
+ prompt?: string;
97
+ }): Promise<{
98
+ messages: any[];
99
+ estimatedTokens: number;
100
+ systemPromptAddition?: string;
101
+ }> {
102
+ if (!this.proxyUrl || this.config.enabled === false) {
103
+ // Fallback: return messages unchanged
104
+ return { messages: params.messages, estimatedTokens: 0 };
105
+ }
106
+
107
+ try {
108
+ // Convert AgentMessage → OpenAI format
109
+ const openaiMessages = agentToOpenAI(params.messages);
110
+
111
+ // Compress via proxy
112
+ const result = await compress(openaiMessages, {
113
+ model: params.model ?? "claude-sonnet-4-5",
114
+ baseUrl: this.proxyUrl,
115
+ fallback: true,
116
+ });
117
+
118
+ if (!result.compressed || result.tokensSaved === 0) {
119
+ return { messages: params.messages, estimatedTokens: result.tokensBefore };
120
+ }
121
+
122
+ // Convert back to AgentMessage format
123
+ const compressedAgentMessages = openAIToAgent(result.messages);
124
+
125
+ // Track stats
126
+ this.stats.totalCompressions++;
127
+ this.stats.totalTokensSaved += result.tokensSaved;
128
+ this.stats.totalTokensBefore += result.tokensBefore;
129
+
130
+ this.logger.debug(
131
+ `Assembled: ${result.tokensBefore} → ${result.tokensAfter} tokens (saved ${result.tokensSaved})`,
132
+ );
133
+
134
+ return {
135
+ messages: compressedAgentMessages,
136
+ estimatedTokens: result.tokensAfter,
137
+ systemPromptAddition:
138
+ result.tokensSaved > 100
139
+ ? `[Context compressed by Headroom: ${result.tokensSaved} tokens saved. Use headroom_retrieve with the hash to get full details.]`
140
+ : undefined,
141
+ };
142
+ } catch (error) {
143
+ this.logger.error(`Assemble failed: ${error}`);
144
+ // Graceful fallback: return original messages
145
+ return { messages: params.messages, estimatedTokens: 0 };
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Compact context — zero-cost alternative to LLM summarization.
151
+ *
152
+ * Uses CCR: originals stored in proxy, agent gets compressed version + retrieval tool.
153
+ */
154
+ async compact(params: {
155
+ sessionId: string;
156
+ sessionFile: string;
157
+ tokenBudget?: number;
158
+ force?: boolean;
159
+ }): Promise<{
160
+ ok: boolean;
161
+ compacted: boolean;
162
+ reason?: string;
163
+ result?: {
164
+ tokensBefore: number;
165
+ tokensAfter?: number;
166
+ };
167
+ }> {
168
+ // Compaction is handled naturally through assemble() — each turn gets compressed.
169
+ // When compact() is explicitly called (e.g., /compact command), we report success
170
+ // because our assemble() already keeps context within budget.
171
+ this.stats.compactions++;
172
+ return {
173
+ ok: true,
174
+ compacted: true,
175
+ reason: "Headroom compresses context on every assemble() call — no separate compaction needed",
176
+ };
177
+ }
178
+
179
+ async afterTurn?(params: {
180
+ sessionId: string;
181
+ messages: any[];
182
+ prePromptMessageCount: number;
183
+ isHeartbeat?: boolean;
184
+ }): Promise<void> {
185
+ // Optional: could log stats or trigger learning
186
+ }
187
+
188
+ async prepareSubagentSpawn?(params: {
189
+ parentSessionKey: string;
190
+ childSessionKey: string;
191
+ ttlMs?: number;
192
+ }): Promise<{ rollback: () => Promise<void> } | undefined> {
193
+ // Subagent context is compressed naturally via assemble()
194
+ return undefined;
195
+ }
196
+
197
+ async onSubagentEnded?(params: {
198
+ childSessionKey: string;
199
+ reason: string;
200
+ }): Promise<void> {
201
+ // No-op
202
+ }
203
+
204
+ async dispose(): Promise<void> {
205
+ await this.proxyManager.stop();
206
+ this.logger.info(
207
+ `Engine disposed. Stats: ${this.stats.totalCompressions} compressions, ` +
208
+ `${this.stats.totalTokensSaved} tokens saved`,
209
+ );
210
+ }
211
+
212
+ // --- Public API ---
213
+
214
+ getStats() {
215
+ return { ...this.stats };
216
+ }
217
+
218
+ getProxyUrl(): string | null {
219
+ return this.proxyUrl;
220
+ }
221
+ }
plugins/openclaw/src/index.ts ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ export { default } from "./plugin/index.js";
2
+ export { HeadroomContextEngine } from "./engine.js";
3
+ export { ProxyManager } from "./proxy-manager.js";
4
+ export { agentToOpenAI, openAIToAgent } from "./convert.js";
5
+ export { createHeadroomRetrieveTool } from "./tools/headroom-retrieve.js";
plugins/openclaw/src/plugin/index.ts ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Headroom OpenClaw Plugin — register ContextEngine + CCR retrieval tool.
3
+ *
4
+ * Usage:
5
+ * openclaw plugins install @headroom-ai/openclaw
6
+ *
7
+ * Configuration (in ~/.openclaw/config.json):
8
+ * {
9
+ * "plugins": {
10
+ * "slots": { "contextEngine": "headroom" },
11
+ * "entries": {
12
+ * "headroom": {
13
+ * "config": {
14
+ * "proxyUrl": "http://localhost:8787", // optional, auto-detected
15
+ * "autoStart": true // start proxy if not running
16
+ * }
17
+ * }
18
+ * }
19
+ * }
20
+ * }
21
+ */
22
+
23
+ /* eslint-disable @typescript-eslint/no-explicit-any */
24
+
25
+ import { HeadroomContextEngine } from "../engine.js";
26
+ import { createHeadroomRetrieveTool } from "../tools/headroom-retrieve.js";
27
+
28
+ export default function headroomPlugin(api: any) {
29
+ const config = api.config?.plugins?.entries?.headroom?.config ?? {};
30
+ const logger = api.logger ?? console;
31
+
32
+ const engine = new HeadroomContextEngine(config, {
33
+ info: (m: string) => logger.info(m),
34
+ warn: (m: string) => logger.warn(m),
35
+ error: (m: string) => logger.error(m),
36
+ debug: (m: string) => logger.debug?.(m),
37
+ });
38
+
39
+ // Register as context engine
40
+ api.registerContextEngine("headroom", () => engine);
41
+
42
+ // Register CCR retrieval tool (available once proxy is running)
43
+ api.registerTool((ctx: any) => {
44
+ const proxyUrl = engine.getProxyUrl();
45
+ if (!proxyUrl) return null;
46
+ return createHeadroomRetrieveTool({ proxyUrl });
47
+ });
48
+
49
+ logger.info("[headroom] Plugin registered");
50
+ }
plugins/openclaw/src/proxy-manager.ts ADDED
@@ -0,0 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Manages the Headroom proxy process lifecycle.
3
+ *
4
+ * - Detects if a proxy is already running (e.g., user has `headroom proxy` for Claude Code)
5
+ * - If not, spawns one as a child process with auto-assigned port
6
+ * - Health checks, restart on crash, graceful shutdown
7
+ */
8
+
9
+ import { spawn, type ChildProcess } from "node:child_process";
10
+ import { createWriteStream } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { homedir } from "node:os";
13
+
14
+ const DEFAULT_PORT = 8787;
15
+ const HEALTH_CHECK_INTERVAL_MS = 30_000;
16
+ const STARTUP_TIMEOUT_MS = 15_000;
17
+ const RESTART_DELAY_MS = 2_000;
18
+ const MAX_RESTART_ATTEMPTS = 3;
19
+
20
+ export interface ProxyManagerConfig {
21
+ proxyUrl?: string;
22
+ pythonPath?: string;
23
+ autoStart?: boolean;
24
+ proxyPort?: number;
25
+ }
26
+
27
+ export interface ProxyManagerLogger {
28
+ info(message: string): void;
29
+ warn(message: string): void;
30
+ error(message: string): void;
31
+ debug(message: string): void;
32
+ }
33
+
34
+ const defaultLogger: ProxyManagerLogger = {
35
+ info: (m) => console.log(`[headroom] ${m}`),
36
+ warn: (m) => console.warn(`[headroom] ${m}`),
37
+ error: (m) => console.error(`[headroom] ${m}`),
38
+ debug: () => {},
39
+ };
40
+
41
+ export class ProxyManager {
42
+ private config: ProxyManagerConfig;
43
+ private logger: ProxyManagerLogger;
44
+ private process: ChildProcess | null = null;
45
+ private proxyUrl: string | null = null;
46
+ private weStartedIt = false;
47
+ private restartCount = 0;
48
+ private healthInterval: ReturnType<typeof setInterval> | null = null;
49
+ private disposed = false;
50
+
51
+ constructor(config: ProxyManagerConfig = {}, logger?: ProxyManagerLogger) {
52
+ this.config = config;
53
+ this.logger = logger ?? defaultLogger;
54
+ }
55
+
56
+ /**
57
+ * Ensure a proxy is available. Returns the URL.
58
+ *
59
+ * 1. If proxyUrl is configured, use it
60
+ * 2. Check if proxy is already running on default port
61
+ * 3. If autoStart, spawn one
62
+ */
63
+ async start(): Promise<string> {
64
+ // Option 1: Explicit URL configured
65
+ if (this.config.proxyUrl) {
66
+ const url = this.config.proxyUrl.replace(/\/+$/, "");
67
+ if (await this.healthCheck(url)) {
68
+ this.proxyUrl = url;
69
+ this.logger.info(`Connected to proxy at ${url}`);
70
+ return url;
71
+ }
72
+ throw new Error(`Headroom proxy not reachable at ${url}`);
73
+ }
74
+
75
+ // Option 2: Check default port
76
+ const defaultUrl = `http://127.0.0.1:${DEFAULT_PORT}`;
77
+ if (await this.healthCheck(defaultUrl)) {
78
+ this.proxyUrl = defaultUrl;
79
+ this.logger.info(`Found running proxy at ${defaultUrl}`);
80
+ this.startHealthMonitor();
81
+ return defaultUrl;
82
+ }
83
+
84
+ // Option 3: Auto-start
85
+ if (this.config.autoStart !== false) {
86
+ return this.spawnProxy();
87
+ }
88
+
89
+ throw new Error(
90
+ "Headroom proxy not running. Start with: headroom proxy --port 8787\n" +
91
+ "Or install: pip install 'headroom-ai[proxy]'",
92
+ );
93
+ }
94
+
95
+ /**
96
+ * Spawn the headroom proxy as a child process.
97
+ */
98
+ private async spawnProxy(): Promise<string> {
99
+ const pythonPath = await this.findPython();
100
+ if (!pythonPath) {
101
+ throw new Error(
102
+ "Python not found. Install Python 3.10+ and run: pip install 'headroom-ai[proxy]'",
103
+ );
104
+ }
105
+
106
+ // Check if headroom-ai is installed
107
+ const installed = await this.checkHeadroomInstalled(pythonPath);
108
+ if (!installed) {
109
+ throw new Error(
110
+ "headroom-ai Python package not found.\n" +
111
+ "Install with: pip install 'headroom-ai[proxy]'",
112
+ );
113
+ }
114
+
115
+ const port = this.config.proxyPort ?? 0; // 0 = OS picks a free port
116
+ const actualPort = port === 0 ? await this.findFreePort() : port;
117
+ const url = `http://127.0.0.1:${actualPort}`;
118
+
119
+ this.logger.info(`Starting proxy on port ${actualPort}...`);
120
+
121
+ // Log file
122
+ const logDir = join(homedir(), ".headroom", "logs");
123
+ const logPath = join(logDir, "openclaw-proxy.log");
124
+
125
+ let logStream: ReturnType<typeof createWriteStream> | null = null;
126
+ try {
127
+ const { mkdirSync } = await import("node:fs");
128
+ mkdirSync(logDir, { recursive: true });
129
+ logStream = createWriteStream(logPath, { flags: "a" });
130
+ } catch {
131
+ // Can't create log file — use /dev/null
132
+ }
133
+
134
+ const proc = spawn(
135
+ pythonPath,
136
+ ["-m", "headroom.cli", "proxy", "--port", String(actualPort)],
137
+ {
138
+ env: { ...process.env, PYTHONIOENCODING: "utf-8" },
139
+ stdio: ["ignore", logStream ? "pipe" : "ignore", logStream ? "pipe" : "ignore"],
140
+ detached: false,
141
+ },
142
+ );
143
+
144
+ if (logStream) {
145
+ proc.stdout?.pipe(logStream);
146
+ proc.stderr?.pipe(logStream);
147
+ }
148
+
149
+ proc.on("exit", (code) => {
150
+ if (!this.disposed && this.weStartedIt) {
151
+ this.logger.warn(`Proxy exited with code ${code}`);
152
+ this.handleCrash();
153
+ }
154
+ });
155
+
156
+ this.process = proc;
157
+ this.weStartedIt = true;
158
+
159
+ // Wait for healthy
160
+ const healthy = await this.waitForHealthy(url, STARTUP_TIMEOUT_MS);
161
+ if (!healthy) {
162
+ proc.kill();
163
+ this.process = null;
164
+ throw new Error(
165
+ `Proxy failed to start within ${STARTUP_TIMEOUT_MS / 1000}s. Check ${logPath}`,
166
+ );
167
+ }
168
+
169
+ this.proxyUrl = url;
170
+ this.logger.info(`Proxy started on port ${actualPort} (PID: ${proc.pid})`);
171
+ this.startHealthMonitor();
172
+ return url;
173
+ }
174
+
175
+ /**
176
+ * Stop the proxy if we started it.
177
+ */
178
+ async stop(): Promise<void> {
179
+ this.disposed = true;
180
+ if (this.healthInterval) {
181
+ clearInterval(this.healthInterval);
182
+ this.healthInterval = null;
183
+ }
184
+ if (this.process && this.weStartedIt) {
185
+ this.logger.info("Stopping proxy...");
186
+ this.process.kill("SIGTERM");
187
+ // Give it 3s to shutdown gracefully
188
+ await new Promise<void>((resolve) => {
189
+ const timeout = setTimeout(() => {
190
+ this.process?.kill("SIGKILL");
191
+ resolve();
192
+ }, 3000);
193
+ this.process?.on("exit", () => {
194
+ clearTimeout(timeout);
195
+ resolve();
196
+ });
197
+ });
198
+ this.process = null;
199
+ }
200
+ }
201
+
202
+ getUrl(): string | null {
203
+ return this.proxyUrl;
204
+ }
205
+
206
+ // --- Internal ---
207
+
208
+ private async healthCheck(url: string): Promise<boolean> {
209
+ try {
210
+ const resp = await fetch(`${url}/health`, {
211
+ signal: AbortSignal.timeout(3000),
212
+ });
213
+ return resp.ok;
214
+ } catch {
215
+ return false;
216
+ }
217
+ }
218
+
219
+ private async waitForHealthy(url: string, timeoutMs: number): Promise<boolean> {
220
+ const start = Date.now();
221
+ while (Date.now() - start < timeoutMs) {
222
+ if (await this.healthCheck(url)) return true;
223
+ await new Promise((r) => setTimeout(r, 500));
224
+ }
225
+ return false;
226
+ }
227
+
228
+ private startHealthMonitor(): void {
229
+ if (this.healthInterval) return;
230
+ this.healthInterval = setInterval(async () => {
231
+ if (this.proxyUrl && !(await this.healthCheck(this.proxyUrl))) {
232
+ this.logger.warn("Proxy health check failed");
233
+ if (this.weStartedIt) this.handleCrash();
234
+ }
235
+ }, HEALTH_CHECK_INTERVAL_MS);
236
+ }
237
+
238
+ private async handleCrash(): Promise<void> {
239
+ if (this.disposed) return;
240
+ if (this.restartCount >= MAX_RESTART_ATTEMPTS) {
241
+ this.logger.error(`Proxy crashed ${MAX_RESTART_ATTEMPTS} times. Giving up.`);
242
+ return;
243
+ }
244
+ this.restartCount++;
245
+ this.logger.info(`Restarting proxy (attempt ${this.restartCount}/${MAX_RESTART_ATTEMPTS})...`);
246
+ await new Promise((r) => setTimeout(r, RESTART_DELAY_MS));
247
+ try {
248
+ await this.spawnProxy();
249
+ } catch (e) {
250
+ this.logger.error(`Restart failed: ${e}`);
251
+ }
252
+ }
253
+
254
+ private async findPython(): Promise<string | null> {
255
+ if (this.config.pythonPath) return this.config.pythonPath;
256
+
257
+ for (const cmd of ["python3", "python"]) {
258
+ try {
259
+ const { execSync } = await import("node:child_process");
260
+ const version = execSync(`${cmd} --version 2>&1`, { encoding: "utf-8" }).trim();
261
+ if (version.includes("Python 3.")) return cmd;
262
+ } catch {
263
+ continue;
264
+ }
265
+ }
266
+ return null;
267
+ }
268
+
269
+ private async checkHeadroomInstalled(pythonPath: string): Promise<boolean> {
270
+ try {
271
+ const { execSync } = await import("node:child_process");
272
+ execSync(`${pythonPath} -c "import headroom"`, {
273
+ encoding: "utf-8",
274
+ stdio: "pipe",
275
+ });
276
+ return true;
277
+ } catch {
278
+ return false;
279
+ }
280
+ }
281
+
282
+ private async findFreePort(): Promise<number> {
283
+ const { createServer } = await import("node:net");
284
+ return new Promise((resolve, reject) => {
285
+ const server = createServer();
286
+ server.listen(0, () => {
287
+ const addr = server.address();
288
+ if (addr && typeof addr === "object") {
289
+ const port = addr.port;
290
+ server.close(() => resolve(port));
291
+ } else {
292
+ reject(new Error("Could not find free port"));
293
+ }
294
+ });
295
+ });
296
+ }
297
+ }
plugins/openclaw/src/tools/headroom-retrieve.ts ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * CCR (Compress-Cache-Retrieve) tool for OpenClaw.
3
+ *
4
+ * Allows the agent to retrieve original uncompressed content
5
+ * from the Headroom proxy's compression store.
6
+ */
7
+
8
+ /* eslint-disable @typescript-eslint/no-explicit-any */
9
+
10
+ export interface RetrieveToolConfig {
11
+ proxyUrl: string;
12
+ }
13
+
14
+ export function createHeadroomRetrieveTool(config: RetrieveToolConfig) {
15
+ return {
16
+ name: "headroom_retrieve",
17
+ description:
18
+ "Retrieve original uncompressed content from Headroom's compression store. " +
19
+ "Use when compressed context mentions a hash and you need the full details. " +
20
+ "Pass the hash from the compression marker (24 hex characters). " +
21
+ "Optionally pass a query to search within the original content.",
22
+ parameters: {
23
+ type: "object" as const,
24
+ properties: {
25
+ hash: {
26
+ type: "string",
27
+ description: "The 24-character hex hash from the compression marker",
28
+ },
29
+ query: {
30
+ type: "string",
31
+ description: "Optional search query to filter results within the original content",
32
+ },
33
+ },
34
+ required: ["hash"],
35
+ },
36
+ execute: async (args: { hash: string; query?: string }): Promise<string> => {
37
+ const { hash, query } = args;
38
+
39
+ // Validate hash format
40
+ if (!/^[a-f0-9]{24}$/i.test(hash)) {
41
+ return JSON.stringify({
42
+ error: "Invalid hash format. Expected 24 hex characters.",
43
+ });
44
+ }
45
+
46
+ try {
47
+ const url = query
48
+ ? `${config.proxyUrl}/v1/retrieve/${hash}?query=${encodeURIComponent(query)}`
49
+ : `${config.proxyUrl}/v1/retrieve/${hash}`;
50
+
51
+ const resp = await fetch(url, {
52
+ signal: AbortSignal.timeout(10_000),
53
+ });
54
+
55
+ if (!resp.ok) {
56
+ const body = await resp.text().catch(() => "");
57
+ return JSON.stringify({
58
+ error: `Retrieval failed: HTTP ${resp.status}`,
59
+ details: body,
60
+ });
61
+ }
62
+
63
+ const data = await resp.json();
64
+ return typeof data === "string" ? data : JSON.stringify(data);
65
+ } catch (error) {
66
+ return JSON.stringify({
67
+ error: `Retrieval failed: ${error}`,
68
+ hint: "The compressed content may have expired (default TTL: 5 minutes)",
69
+ });
70
+ }
71
+ },
72
+ };
73
+ }
plugins/openclaw/test/engine.test.ts ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Integration tests for HeadroomContextEngine.
3
+ *
4
+ * Tests the full flow: proxy management, AgentMessage conversion,
5
+ * compression via proxy, and round-trip back to AgentMessage.
6
+ *
7
+ * Requires: Python 3 + headroom-ai[proxy] installed
8
+ * Run: HEADROOM_INTEGRATION=1 npx vitest run test/engine.test.ts
9
+ */
10
+ import { describe, it, expect, beforeAll, afterAll } from "vitest";
11
+ import { HeadroomContextEngine } from "../src/engine.js";
12
+ import { agentToOpenAI, openAIToAgent } from "../src/convert.js";
13
+ import { ProxyManager } from "../src/proxy-manager.js";
14
+
15
+ const RUN = process.env.HEADROOM_INTEGRATION === "1";
16
+
17
+ describe("AgentMessage conversion", () => {
18
+ it("converts user message", () => {
19
+ const agent = [{ role: "user", content: "hello", timestamp: Date.now() }];
20
+ const openai = agentToOpenAI(agent);
21
+ expect(openai).toEqual([{ role: "user", content: "hello" }]);
22
+ });
23
+
24
+ it("converts assistant with tool_use blocks", () => {
25
+ const agent = [
26
+ {
27
+ role: "assistant",
28
+ content: [
29
+ { type: "text", text: "Let me search" },
30
+ { type: "tool_use", id: "tu_1", name: "search", input: { q: "test" } },
31
+ ],
32
+ timestamp: Date.now(),
33
+ },
34
+ ];
35
+ const openai = agentToOpenAI(agent);
36
+ expect(openai[0].role).toBe("assistant");
37
+ expect(openai[0].content).toBe("Let me search");
38
+ expect(openai[0].tool_calls).toHaveLength(1);
39
+ expect(openai[0].tool_calls![0].function.name).toBe("search");
40
+ });
41
+
42
+ it("converts toolResult message", () => {
43
+ const agent = [
44
+ {
45
+ role: "toolResult",
46
+ content: '{"results": [1, 2, 3]}',
47
+ tool_use_id: "tu_1",
48
+ timestamp: Date.now(),
49
+ },
50
+ ];
51
+ const openai = agentToOpenAI(agent);
52
+ expect(openai[0].role).toBe("tool");
53
+ expect(openai[0].content).toBe('{"results": [1, 2, 3]}');
54
+ expect(openai[0].tool_call_id).toBe("tu_1");
55
+ });
56
+
57
+ it("round-trips user message", () => {
58
+ const original = [{ role: "user", content: "hello", timestamp: Date.now() }];
59
+ const openai = agentToOpenAI(original);
60
+ const back = openAIToAgent(openai);
61
+ expect(back[0].role).toBe("user");
62
+ expect(back[0].content).toBe("hello");
63
+ });
64
+
65
+ it("round-trips assistant with tool calls", () => {
66
+ const original = [
67
+ {
68
+ role: "assistant",
69
+ content: [
70
+ { type: "text", text: "Searching..." },
71
+ { type: "tool_use", id: "tu_1", name: "search", input: { q: "test" } },
72
+ ],
73
+ timestamp: Date.now(),
74
+ },
75
+ ];
76
+ const openai = agentToOpenAI(original);
77
+ const back = openAIToAgent(openai);
78
+ expect(back[0].role).toBe("assistant");
79
+ const content = back[0].content;
80
+ expect(Array.isArray(content)).toBe(true);
81
+ expect(content).toContainEqual(expect.objectContaining({ type: "text", text: "Searching..." }));
82
+ expect(content).toContainEqual(
83
+ expect.objectContaining({ type: "tool_use", id: "tu_1", name: "search" }),
84
+ );
85
+ });
86
+
87
+ it("round-trips toolResult", () => {
88
+ const original = [
89
+ {
90
+ role: "toolResult",
91
+ content: '{"data": true}',
92
+ tool_use_id: "tu_1",
93
+ timestamp: Date.now(),
94
+ },
95
+ ];
96
+ const openai = agentToOpenAI(original);
97
+ const back = openAIToAgent(openai);
98
+ expect(back[0].role).toBe("toolResult");
99
+ expect(back[0].content).toBe('{"data": true}');
100
+ expect(back[0].tool_use_id).toBe("tu_1");
101
+ });
102
+ });
103
+
104
+ describe.skipIf(!RUN)("ProxyManager", () => {
105
+ it("detects running proxy or starts one", { timeout: 30000 }, async () => {
106
+ const manager = new ProxyManager({ autoStart: true });
107
+ try {
108
+ const url = await manager.start();
109
+ expect(url).toMatch(/^http:\/\/127\.0\.0\.1:\d+$/);
110
+
111
+ // Verify health
112
+ const resp = await fetch(`${url}/health`);
113
+ expect(resp.ok).toBe(true);
114
+ } finally {
115
+ await manager.stop();
116
+ }
117
+ });
118
+ });
119
+
120
+ describe.skipIf(!RUN)("HeadroomContextEngine", () => {
121
+ let engine: HeadroomContextEngine;
122
+
123
+ beforeAll(async () => {
124
+ engine = new HeadroomContextEngine({ autoStart: true });
125
+ await engine.bootstrap({
126
+ sessionId: "test-session",
127
+ sessionFile: "/tmp/test-session.jsonl",
128
+ });
129
+ }, 30000);
130
+
131
+ afterAll(async () => {
132
+ await engine.dispose();
133
+ });
134
+
135
+ it("assemble() compresses tool outputs", { timeout: 15000 }, async () => {
136
+ // Simulate an OpenClaw agent conversation with large tool result
137
+ const serverData = Array.from({ length: 100 }, (_, i) => ({
138
+ id: i + 1,
139
+ name: `server-${i + 1}`,
140
+ status: i % 15 === 0 ? "critical" : i % 5 === 0 ? "warning" : "healthy",
141
+ cpu: Math.round(Math.random() * 100),
142
+ memory: Math.round(Math.random() * 100),
143
+ region: ["us-east-1", "eu-west-1", "ap-southeast-1"][i % 3],
144
+ description: `Production server ${i + 1} running service-${["auth", "payment", "user", "api"][i % 4]}`,
145
+ lastAlert: i % 15 === 0 ? `Disk usage at ${90 + (i % 10)}%` : null,
146
+ }));
147
+
148
+ const messages = [
149
+ { role: "user", content: "Check the fleet status", timestamp: Date.now() },
150
+ {
151
+ role: "assistant",
152
+ content: [
153
+ { type: "tool_use", id: "tu_fleet", name: "getFleetStatus", input: {} },
154
+ ],
155
+ timestamp: Date.now(),
156
+ },
157
+ {
158
+ role: "toolResult",
159
+ content: JSON.stringify(serverData),
160
+ tool_use_id: "tu_fleet",
161
+ timestamp: Date.now(),
162
+ },
163
+ { role: "user", content: "Which servers are critical?", timestamp: Date.now() },
164
+ ];
165
+
166
+ const result = await engine.assemble({
167
+ sessionId: "test-session",
168
+ messages,
169
+ model: "claude-sonnet-4-5",
170
+ });
171
+
172
+ console.log(
173
+ ` assemble(): estimatedTokens=${result.estimatedTokens}, ` +
174
+ `systemPrompt=${result.systemPromptAddition ? "yes" : "no"}`,
175
+ );
176
+
177
+ // Messages should be returned (compressed or not)
178
+ expect(result.messages.length).toBeGreaterThan(0);
179
+ // First and last messages should still be user messages
180
+ expect(result.messages[0].role).toBe("user");
181
+ expect(result.messages[result.messages.length - 1].role).toBe("user");
182
+ });
183
+
184
+ it("assemble() preserves small conversations", { timeout: 15000 }, async () => {
185
+ const messages = [
186
+ { role: "user", content: "Hello", timestamp: Date.now() },
187
+ { role: "assistant", content: "Hi there!", timestamp: Date.now() },
188
+ ];
189
+
190
+ const result = await engine.assemble({
191
+ sessionId: "test-session",
192
+ messages,
193
+ });
194
+
195
+ expect(result.messages).toHaveLength(2);
196
+ expect(result.messages[0].content).toBe("Hello");
197
+ expect(result.messages[1].content).toBe("Hi there!");
198
+ });
199
+
200
+ it("compact() returns success (compression handled in assemble)", async () => {
201
+ const result = await engine.compact({
202
+ sessionId: "test-session",
203
+ sessionFile: "/tmp/test.jsonl",
204
+ });
205
+
206
+ expect(result.ok).toBe(true);
207
+ expect(result.compacted).toBe(true);
208
+ });
209
+
210
+ it("getStats() returns compression statistics", () => {
211
+ const stats = engine.getStats();
212
+ expect(stats).toHaveProperty("totalCompressions");
213
+ expect(stats).toHaveProperty("totalTokensSaved");
214
+ expect(stats.totalCompressions).toBeGreaterThanOrEqual(0);
215
+ });
216
+ });
plugins/openclaw/tsconfig.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "declaration": true,
11
+ "outDir": "dist",
12
+ "rootDir": "src",
13
+ "sourceMap": true,
14
+ "isolatedModules": true
15
+ },
16
+ "include": ["src"],
17
+ "exclude": ["node_modules", "dist", "test"]
18
+ }
plugins/openclaw/tsup.config.ts ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ entry: { index: "src/index.ts" },
5
+ format: ["esm"],
6
+ dts: true,
7
+ sourcemap: true,
8
+ clean: true,
9
+ });
plugins/openclaw/vitest.config.ts ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: "node",
7
+ },
8
+ });