miladyai 2.0.0-alpha.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.js +7 -0
- package/dist/actions/emote.js +64 -0
- package/dist/actions/restart.js +81 -0
- package/dist/actions/send-message.js +152 -0
- package/dist/agent-admin-routes.js +82 -0
- package/dist/agent-lifecycle-routes.js +79 -0
- package/dist/agent-transfer-routes.js +102 -0
- package/dist/api/agent-admin-routes.js +82 -0
- package/dist/api/agent-lifecycle-routes.js +79 -0
- package/dist/api/agent-transfer-routes.js +102 -0
- package/dist/api/apps-hyperscape-routes.js +58 -0
- package/dist/api/apps-routes.js +114 -0
- package/dist/api/auth-routes.js +56 -0
- package/dist/api/autonomy-routes.js +44 -0
- package/dist/api/bug-report-routes.js +111 -0
- package/dist/api/character-routes.js +195 -0
- package/dist/api/cloud-routes.js +330 -0
- package/dist/api/cloud-status-routes.js +155 -0
- package/dist/api/compat-utils.js +111 -0
- package/dist/api/database.js +735 -0
- package/dist/api/diagnostics-routes.js +205 -0
- package/dist/api/drop-service.js +134 -0
- package/dist/api/early-logs.js +86 -0
- package/dist/api/http-helpers.js +131 -0
- package/dist/api/knowledge-routes.js +534 -0
- package/dist/api/memory-bounds.js +71 -0
- package/dist/api/models-routes.js +28 -0
- package/dist/api/og-tracker.js +36 -0
- package/dist/api/permissions-routes.js +109 -0
- package/dist/api/plugin-validation.js +198 -0
- package/dist/api/provider-switch-config.js +41 -0
- package/dist/api/registry-routes.js +86 -0
- package/dist/api/registry-service.js +164 -0
- package/dist/api/sandbox-routes.js +1112 -0
- package/dist/api/server.js +7949 -0
- package/dist/api/subscription-routes.js +172 -0
- package/dist/api/terminal-run-limits.js +24 -0
- package/dist/api/training-routes.js +158 -0
- package/dist/api/trajectory-routes.js +300 -0
- package/dist/api/trigger-routes.js +246 -0
- package/dist/api/twitter-verify.js +134 -0
- package/dist/api/tx-service.js +108 -0
- package/dist/api/wallet-routes.js +266 -0
- package/dist/api/wallet.js +568 -0
- package/dist/api/whatsapp-routes.js +182 -0
- package/dist/api/zip-utils.js +109 -0
- package/dist/apps-hyperscape-routes.js +58 -0
- package/dist/apps-routes.js +114 -0
- package/dist/ascii.js +20 -0
- package/dist/auth/anthropic.js +44 -0
- package/dist/auth/apply-stealth.js +41 -0
- package/dist/auth/claude-code-stealth.js +78 -0
- package/dist/auth/credentials.js +156 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/openai-codex.js +66 -0
- package/dist/auth/types.js +9 -0
- package/dist/auth-routes.js +56 -0
- package/dist/autonomy-routes.js +44 -0
- package/dist/bug-report-routes.js +111 -0
- package/dist/build-info.json +6 -0
- package/dist/character-routes.js +195 -0
- package/dist/cli/argv.js +63 -0
- package/dist/cli/banner.js +34 -0
- package/dist/cli/cli-name.js +21 -0
- package/dist/cli/cli-utils.js +16 -0
- package/dist/cli/git-commit.js +78 -0
- package/dist/cli/parse-duration.js +15 -0
- package/dist/cli/plugins-cli.js +590 -0
- package/dist/cli/profile-utils.js +9 -0
- package/dist/cli/profile.js +95 -0
- package/dist/cli/program/build-program.js +17 -0
- package/dist/cli/program/command-registry.js +23 -0
- package/dist/cli/program/help.js +47 -0
- package/dist/cli/program/preaction.js +33 -0
- package/dist/cli/program/register.config.js +106 -0
- package/dist/cli/program/register.configure.js +20 -0
- package/dist/cli/program/register.dashboard.js +124 -0
- package/dist/cli/program/register.models.js +23 -0
- package/dist/cli/program/register.setup.js +36 -0
- package/dist/cli/program/register.start.js +22 -0
- package/dist/cli/program/register.subclis.js +70 -0
- package/dist/cli/program/register.tui.js +163 -0
- package/dist/cli/program/register.update.js +154 -0
- package/dist/cli/program.js +3 -0
- package/dist/cli/run-main.js +37 -0
- package/dist/cli/version.js +7 -0
- package/dist/cloud/validate-url.js +93 -0
- package/dist/cloud-routes.js +330 -0
- package/dist/cloud-status-routes.js +155 -0
- package/dist/compat-utils.js +111 -0
- package/dist/config/config.js +69 -0
- package/dist/config/env-vars.js +19 -0
- package/dist/config/includes.js +121 -0
- package/dist/config/object-utils.js +7 -0
- package/dist/config/paths.js +38 -0
- package/dist/config/plugin-auto-enable.js +231 -0
- package/dist/config/schema.js +864 -0
- package/dist/config/telegram-custom-commands.js +76 -0
- package/dist/config/zod-schema.agent-runtime.js +519 -0
- package/dist/config/zod-schema.core.js +538 -0
- package/dist/config/zod-schema.hooks.js +103 -0
- package/dist/config/zod-schema.js +488 -0
- package/dist/config/zod-schema.providers-core.js +785 -0
- package/dist/config/zod-schema.session.js +73 -0
- package/dist/core-plugins.js +37 -0
- package/dist/custom-actions.js +250 -0
- package/dist/database.js +735 -0
- package/dist/diagnostics/integration-observability.js +57 -0
- package/dist/diagnostics-routes.js +205 -0
- package/dist/drop-service.js +134 -0
- package/dist/early-logs.js +24 -0
- package/dist/eliza.js +2061 -0
- package/dist/emotes/catalog.js +271 -0
- package/dist/entry.js +40 -0
- package/dist/hooks/discovery.js +167 -0
- package/dist/hooks/eligibility.js +64 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/loader.js +147 -0
- package/dist/hooks/registry.js +55 -0
- package/dist/http-helpers.js +131 -0
- package/dist/index.js +49 -0
- package/dist/knowledge-routes.js +534 -0
- package/dist/memory-bounds.js +71 -0
- package/dist/milady-plugin.js +90 -0
- package/dist/models-routes.js +28 -0
- package/dist/onboarding-names.js +78 -0
- package/dist/onboarding-presets.js +922 -0
- package/dist/package.json +1 -0
- package/dist/permissions-routes.js +109 -0
- package/dist/plugin-validation.js +107 -0
- package/dist/plugins/whatsapp/actions.js +91 -0
- package/dist/plugins/whatsapp/index.js +16 -0
- package/dist/plugins/whatsapp/service.js +270 -0
- package/dist/provider-switch-config.js +41 -0
- package/dist/providers/admin-trust.js +46 -0
- package/dist/providers/autonomous-state.js +101 -0
- package/dist/providers/session-bridge.js +86 -0
- package/dist/providers/session-utils.js +36 -0
- package/dist/providers/simple-mode.js +50 -0
- package/dist/providers/ui-catalog.js +15 -0
- package/dist/providers/workspace-provider.js +93 -0
- package/dist/providers/workspace.js +348 -0
- package/dist/registry-routes.js +86 -0
- package/dist/registry-service.js +164 -0
- package/dist/restart.js +40 -0
- package/dist/runtime/core-plugins.js +37 -0
- package/dist/runtime/custom-actions.js +250 -0
- package/dist/runtime/eliza.js +2061 -0
- package/dist/runtime/embedding-manager-support.js +185 -0
- package/dist/runtime/embedding-manager.js +193 -0
- package/dist/runtime/embedding-presets.js +54 -0
- package/dist/runtime/embedding-state.js +8 -0
- package/dist/runtime/milady-plugin.js +90 -0
- package/dist/runtime/onboarding-names.js +78 -0
- package/dist/runtime/restart.js +40 -0
- package/dist/runtime/version.js +7 -0
- package/dist/sandbox-routes.js +1112 -0
- package/dist/security/audit-log.js +149 -0
- package/dist/security/network-policy.js +70 -0
- package/dist/server.js +7949 -0
- package/dist/services/agent-export.js +559 -0
- package/dist/services/app-manager.js +389 -0
- package/dist/services/browser-capture.js +86 -0
- package/dist/services/fallback-training-service.js +128 -0
- package/dist/services/mcp-marketplace.js +134 -0
- package/dist/services/plugin-installer.js +396 -0
- package/dist/services/plugin-manager-types.js +15 -0
- package/dist/services/registry-client-app-meta.js +144 -0
- package/dist/services/registry-client-endpoints.js +166 -0
- package/dist/services/registry-client-local.js +271 -0
- package/dist/services/registry-client-network.js +93 -0
- package/dist/services/registry-client-queries.js +70 -0
- package/dist/services/registry-client.js +157 -0
- package/dist/services/sandbox-engine.js +511 -0
- package/dist/services/sandbox-manager.js +297 -0
- package/dist/services/self-updater.js +175 -0
- package/dist/services/skill-catalog-client.js +119 -0
- package/dist/services/skill-marketplace.js +521 -0
- package/dist/services/stream-manager.js +236 -0
- package/dist/services/update-checker.js +121 -0
- package/dist/services/update-notifier.js +29 -0
- package/dist/services/version-compat.js +78 -0
- package/dist/services/whatsapp-pairing.js +196 -0
- package/dist/shared/ui-catalog-prompt.js +728 -0
- package/dist/subscription-routes.js +172 -0
- package/dist/terminal/links.js +19 -0
- package/dist/terminal/palette.js +14 -0
- package/dist/terminal/theme.js +25 -0
- package/dist/terminal-run-limits.js +24 -0
- package/dist/training-routes.js +158 -0
- package/dist/trajectory-routes.js +300 -0
- package/dist/trigger-routes.js +246 -0
- package/dist/triggers/action.js +218 -0
- package/dist/triggers/runtime.js +281 -0
- package/dist/triggers/scheduling.js +295 -0
- package/dist/triggers/types.js +5 -0
- package/dist/tui/components/assistant-message.js +76 -0
- package/dist/tui/components/chat-editor.js +34 -0
- package/dist/tui/components/embeddings-overlay.js +46 -0
- package/dist/tui/components/footer.js +60 -0
- package/dist/tui/components/index.js +15 -0
- package/dist/tui/components/modal-frame.js +45 -0
- package/dist/tui/components/modal-style.js +15 -0
- package/dist/tui/components/model-selector.js +70 -0
- package/dist/tui/components/pinned-chat-layout.js +46 -0
- package/dist/tui/components/plugins-endpoints-tab.js +196 -0
- package/dist/tui/components/plugins-installed-tab-view.js +69 -0
- package/dist/tui/components/plugins-installed-tab.js +319 -0
- package/dist/tui/components/plugins-overlay-catalog.js +81 -0
- package/dist/tui/components/plugins-overlay-data-api.js +21 -0
- package/dist/tui/components/plugins-overlay-data-shared.js +20 -0
- package/dist/tui/components/plugins-overlay-data.js +323 -0
- package/dist/tui/components/plugins-overlay.js +117 -0
- package/dist/tui/components/plugins-store-tab.js +148 -0
- package/dist/tui/components/settings-overlay.js +61 -0
- package/dist/tui/components/status-bar.js +64 -0
- package/dist/tui/components/tool-execution.js +68 -0
- package/dist/tui/components/user-message.js +22 -0
- package/dist/tui/eliza-tui-bridge.js +606 -0
- package/dist/tui/index.js +370 -0
- package/dist/tui/modal-presets.js +33 -0
- package/dist/tui/model-spec.js +46 -0
- package/dist/tui/sse-parser.js +78 -0
- package/dist/tui/theme.js +110 -0
- package/dist/tui/titlebar-spinner.js +62 -0
- package/dist/tui/tui-app.js +311 -0
- package/dist/tui/ws-client.js +215 -0
- package/dist/twitter-verify.js +134 -0
- package/dist/tx-service.js +108 -0
- package/dist/utils/exec-safety.js +17 -0
- package/dist/utils/globals.js +20 -0
- package/dist/utils/milady-root.js +61 -0
- package/dist/utils/number-parsing.js +37 -0
- package/dist/version-resolver.js +37 -0
- package/dist/version.js +7 -0
- package/dist/wallet-routes.js +266 -0
- package/dist/wallet.js +568 -0
- package/dist/whatsapp-routes.js +182 -0
- package/dist/zip-utils.js +109 -0
- package/milady.mjs +14 -0
- package/package.json +111 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
//#region src/emotes/catalog.ts
|
|
2
|
+
const EMOTE_CATALOG = [
|
|
3
|
+
{
|
|
4
|
+
id: "wave",
|
|
5
|
+
name: "Wave",
|
|
6
|
+
description: "Waves both hands in greeting",
|
|
7
|
+
glbPath: "/animations/emotes/waving-both-hands.glb",
|
|
8
|
+
duration: 2.5,
|
|
9
|
+
loop: false,
|
|
10
|
+
category: "greeting"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: "kiss",
|
|
14
|
+
name: "Kiss",
|
|
15
|
+
description: "Blows a kiss",
|
|
16
|
+
glbPath: "/animations/emotes/kiss.glb",
|
|
17
|
+
duration: 2,
|
|
18
|
+
loop: false,
|
|
19
|
+
category: "greeting"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: "crying",
|
|
23
|
+
name: "Crying",
|
|
24
|
+
description: "Cries sadly",
|
|
25
|
+
glbPath: "/animations/emotes/crying.glb",
|
|
26
|
+
duration: 3,
|
|
27
|
+
loop: true,
|
|
28
|
+
category: "emotion"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "sorrow",
|
|
32
|
+
name: "Sorrow",
|
|
33
|
+
description: "Expresses deep sorrow",
|
|
34
|
+
glbPath: "/animations/emotes/sorrow.glb",
|
|
35
|
+
duration: 3,
|
|
36
|
+
loop: true,
|
|
37
|
+
category: "emotion"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "rude-gesture",
|
|
41
|
+
name: "Rude Gesture",
|
|
42
|
+
description: "Makes a rude gesture",
|
|
43
|
+
glbPath: "/animations/emotes/rude-gesture.glb",
|
|
44
|
+
duration: 2,
|
|
45
|
+
loop: false,
|
|
46
|
+
category: "emotion"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "looking-around",
|
|
50
|
+
name: "Looking Around",
|
|
51
|
+
description: "Looks around nervously",
|
|
52
|
+
glbPath: "/animations/emotes/looking-around.glb",
|
|
53
|
+
duration: 3,
|
|
54
|
+
loop: true,
|
|
55
|
+
category: "emotion"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "dance-happy",
|
|
59
|
+
name: "Happy Dance",
|
|
60
|
+
description: "Happy dance",
|
|
61
|
+
glbPath: "/animations/emotes/dance-happy.glb",
|
|
62
|
+
duration: 4,
|
|
63
|
+
loop: true,
|
|
64
|
+
category: "dance"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: "dance-breaking",
|
|
68
|
+
name: "Breaking",
|
|
69
|
+
description: "Breakdance moves",
|
|
70
|
+
glbPath: "/animations/emotes/dance-breaking.glb",
|
|
71
|
+
duration: 4,
|
|
72
|
+
loop: true,
|
|
73
|
+
category: "dance"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "dance-hiphop",
|
|
77
|
+
name: "Hip Hop",
|
|
78
|
+
description: "Hip hop dance",
|
|
79
|
+
glbPath: "/animations/emotes/dance-hiphop.glb",
|
|
80
|
+
duration: 4,
|
|
81
|
+
loop: true,
|
|
82
|
+
category: "dance"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "dance-popping",
|
|
86
|
+
name: "Popping",
|
|
87
|
+
description: "Popping dance moves",
|
|
88
|
+
glbPath: "/animations/emotes/dance-popping.glb",
|
|
89
|
+
duration: 4,
|
|
90
|
+
loop: true,
|
|
91
|
+
category: "dance"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "hook-punch",
|
|
95
|
+
name: "Hook Punch",
|
|
96
|
+
description: "Throws a hook punch",
|
|
97
|
+
glbPath: "/animations/emotes/hook-punch.glb",
|
|
98
|
+
duration: 1.5,
|
|
99
|
+
loop: false,
|
|
100
|
+
category: "combat"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: "punching",
|
|
104
|
+
name: "Punching",
|
|
105
|
+
description: "Throws punches",
|
|
106
|
+
glbPath: "/animations/emotes/punching.glb",
|
|
107
|
+
duration: 2,
|
|
108
|
+
loop: false,
|
|
109
|
+
category: "combat"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: "firing-gun",
|
|
113
|
+
name: "Firing Gun",
|
|
114
|
+
description: "Fires a gun",
|
|
115
|
+
glbPath: "/animations/emotes/firing-gun.glb",
|
|
116
|
+
duration: 2,
|
|
117
|
+
loop: false,
|
|
118
|
+
category: "combat"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: "sword-swing",
|
|
122
|
+
name: "Sword Swing",
|
|
123
|
+
description: "Swings a sword",
|
|
124
|
+
glbPath: "/animations/emotes/sword_swing.glb",
|
|
125
|
+
duration: 2,
|
|
126
|
+
loop: false,
|
|
127
|
+
category: "combat"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: "chopping",
|
|
131
|
+
name: "Chopping",
|
|
132
|
+
description: "Chops with an axe",
|
|
133
|
+
glbPath: "/animations/emotes/chopping.glb",
|
|
134
|
+
duration: 2,
|
|
135
|
+
loop: false,
|
|
136
|
+
category: "combat"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: "spell-cast",
|
|
140
|
+
name: "Spell Cast",
|
|
141
|
+
description: "Casts a magic spell",
|
|
142
|
+
glbPath: "/animations/emotes/spell-cast.glb",
|
|
143
|
+
duration: 2.5,
|
|
144
|
+
loop: false,
|
|
145
|
+
category: "combat"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: "range",
|
|
149
|
+
name: "Range",
|
|
150
|
+
description: "Fires a ranged weapon",
|
|
151
|
+
glbPath: "/animations/emotes/range.glb",
|
|
152
|
+
duration: 2,
|
|
153
|
+
loop: false,
|
|
154
|
+
category: "combat"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "death",
|
|
158
|
+
name: "Death",
|
|
159
|
+
description: "Falls down defeated",
|
|
160
|
+
glbPath: "/animations/emotes/death.glb",
|
|
161
|
+
duration: 3,
|
|
162
|
+
loop: false,
|
|
163
|
+
category: "combat"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "idle",
|
|
167
|
+
name: "Idle",
|
|
168
|
+
description: "Stands idle",
|
|
169
|
+
glbPath: "/animations/emotes/idle.glb",
|
|
170
|
+
duration: 5,
|
|
171
|
+
loop: true,
|
|
172
|
+
category: "idle"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: "talk",
|
|
176
|
+
name: "Talk",
|
|
177
|
+
description: "Talks animatedly",
|
|
178
|
+
glbPath: "/animations/emotes/talk.glb",
|
|
179
|
+
duration: 3,
|
|
180
|
+
loop: true,
|
|
181
|
+
category: "idle"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: "squat",
|
|
185
|
+
name: "Squat",
|
|
186
|
+
description: "Squats down",
|
|
187
|
+
glbPath: "/animations/emotes/squat.glb",
|
|
188
|
+
duration: 3,
|
|
189
|
+
loop: true,
|
|
190
|
+
category: "idle"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
id: "fishing",
|
|
194
|
+
name: "Fishing",
|
|
195
|
+
description: "Casts a fishing line",
|
|
196
|
+
glbPath: "/animations/emotes/fishing.glb",
|
|
197
|
+
duration: 5,
|
|
198
|
+
loop: true,
|
|
199
|
+
category: "idle"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: "float",
|
|
203
|
+
name: "Float",
|
|
204
|
+
description: "Floats in the air",
|
|
205
|
+
glbPath: "/animations/emotes/float.glb",
|
|
206
|
+
duration: 4,
|
|
207
|
+
loop: true,
|
|
208
|
+
category: "idle"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
id: "jump",
|
|
212
|
+
name: "Jump",
|
|
213
|
+
description: "Jumps up",
|
|
214
|
+
glbPath: "/animations/emotes/jump.glb",
|
|
215
|
+
duration: 1.5,
|
|
216
|
+
loop: false,
|
|
217
|
+
category: "movement"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
id: "flip",
|
|
221
|
+
name: "Flip",
|
|
222
|
+
description: "Does a backflip",
|
|
223
|
+
glbPath: "/animations/emotes/flip.glb",
|
|
224
|
+
duration: 2,
|
|
225
|
+
loop: false,
|
|
226
|
+
category: "movement"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
id: "run",
|
|
230
|
+
name: "Run",
|
|
231
|
+
description: "Runs in place",
|
|
232
|
+
glbPath: "/animations/emotes/run.glb",
|
|
233
|
+
duration: 3,
|
|
234
|
+
loop: true,
|
|
235
|
+
category: "movement"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: "walk",
|
|
239
|
+
name: "Walk",
|
|
240
|
+
description: "Walks in place",
|
|
241
|
+
glbPath: "/animations/emotes/walk.glb",
|
|
242
|
+
duration: 3,
|
|
243
|
+
loop: true,
|
|
244
|
+
category: "movement"
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: "crawling",
|
|
248
|
+
name: "Crawling",
|
|
249
|
+
description: "Crawls on the ground",
|
|
250
|
+
glbPath: "/animations/emotes/crawling.glb",
|
|
251
|
+
duration: 3,
|
|
252
|
+
loop: true,
|
|
253
|
+
category: "movement"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: "fall",
|
|
257
|
+
name: "Fall",
|
|
258
|
+
description: "Falls down",
|
|
259
|
+
glbPath: "/animations/emotes/fall.glb",
|
|
260
|
+
duration: 2,
|
|
261
|
+
loop: false,
|
|
262
|
+
category: "movement"
|
|
263
|
+
}
|
|
264
|
+
];
|
|
265
|
+
/**
|
|
266
|
+
* Map for O(1) emote lookup by ID
|
|
267
|
+
*/
|
|
268
|
+
const EMOTE_BY_ID = new Map(EMOTE_CATALOG.map((emote) => [emote.id, emote]));
|
|
269
|
+
|
|
270
|
+
//#endregion
|
|
271
|
+
export { EMOTE_BY_ID, EMOTE_CATALOG };
|
package/dist/entry.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { applyCliProfileEnv, parseCliProfileArgs } from "./cli/profile.js";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
|
|
5
|
+
//#region src/entry.ts
|
|
6
|
+
/**
|
|
7
|
+
* CLI entry point for Milady.
|
|
8
|
+
*
|
|
9
|
+
* This file is built by tsdown into dist/entry.js and invoked by milady.mjs.
|
|
10
|
+
* It bootstraps the CLI: normalizes env, applies profile settings,
|
|
11
|
+
* and delegates to the Commander-based CLI.
|
|
12
|
+
*/
|
|
13
|
+
process.title = "milady";
|
|
14
|
+
if (process.argv.includes("--no-color")) {
|
|
15
|
+
process.env.NO_COLOR = "1";
|
|
16
|
+
process.env.FORCE_COLOR = "0";
|
|
17
|
+
}
|
|
18
|
+
if (!process.env.LOG_LEVEL) if (process.argv.includes("--debug")) process.env.LOG_LEVEL = "debug";
|
|
19
|
+
else if (process.argv.includes("--verbose")) process.env.LOG_LEVEL = "info";
|
|
20
|
+
else process.env.LOG_LEVEL = "error";
|
|
21
|
+
if (!process.env.NODE_LLAMA_CPP_LOG_LEVEL) {
|
|
22
|
+
const logLevel = String(process.env.LOG_LEVEL).toLowerCase();
|
|
23
|
+
process.env.NODE_LLAMA_CPP_LOG_LEVEL = logLevel === "debug" ? "debug" : logLevel === "info" ? "info" : "error";
|
|
24
|
+
}
|
|
25
|
+
const parsed = parseCliProfileArgs(process.argv);
|
|
26
|
+
if (!parsed.ok) {
|
|
27
|
+
console.error(`[milady] ${parsed.error}`);
|
|
28
|
+
process.exit(2);
|
|
29
|
+
}
|
|
30
|
+
if (parsed.profile) {
|
|
31
|
+
applyCliProfileEnv({ profile: parsed.profile });
|
|
32
|
+
process.argv = parsed.argv;
|
|
33
|
+
}
|
|
34
|
+
import("./cli/run-main.js").then(({ runCli }) => runCli(process.argv)).catch((error) => {
|
|
35
|
+
console.error("[milady] Failed to start CLI:", error instanceof Error ? error.stack ?? error.message : error);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
export { };
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { logger } from "@elizaos/core";
|
|
4
|
+
import { readFile, readdir, stat } from "node:fs/promises";
|
|
5
|
+
|
|
6
|
+
//#region src/hooks/discovery.ts
|
|
7
|
+
/**
|
|
8
|
+
* Discover hooks from workspace, managed (~/.milady/hooks/), and bundled dirs.
|
|
9
|
+
* Later sources win on name conflicts.
|
|
10
|
+
*/
|
|
11
|
+
const HOOK_MD = "HOOK.md";
|
|
12
|
+
const HANDLER_NAMES = [
|
|
13
|
+
"handler.ts",
|
|
14
|
+
"handler",
|
|
15
|
+
"index.ts",
|
|
16
|
+
"index"
|
|
17
|
+
];
|
|
18
|
+
function parseFrontmatter(content) {
|
|
19
|
+
const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
20
|
+
if (!fmMatch) return null;
|
|
21
|
+
const fmBlock = fmMatch[1];
|
|
22
|
+
const result = {
|
|
23
|
+
name: "",
|
|
24
|
+
description: ""
|
|
25
|
+
};
|
|
26
|
+
for (const line of fmBlock.split("\n")) {
|
|
27
|
+
const kvMatch = line.match(/^(\w+):\s*(.+)/);
|
|
28
|
+
if (!kvMatch) continue;
|
|
29
|
+
const [, key, rawValue] = kvMatch;
|
|
30
|
+
const value = rawValue.replace(/^["']|["']$/g, "").trim();
|
|
31
|
+
switch (key) {
|
|
32
|
+
case "name":
|
|
33
|
+
result.name = value;
|
|
34
|
+
break;
|
|
35
|
+
case "description":
|
|
36
|
+
result.description = value;
|
|
37
|
+
break;
|
|
38
|
+
case "homepage":
|
|
39
|
+
result.homepage = value;
|
|
40
|
+
break;
|
|
41
|
+
case "metadata":
|
|
42
|
+
try {
|
|
43
|
+
const metaStart = fmBlock.indexOf("metadata:");
|
|
44
|
+
if (metaStart !== -1) {
|
|
45
|
+
const jsonMatch = fmBlock.slice(metaStart + 9).trim().match(/\{[\s\S]*\}/);
|
|
46
|
+
if (jsonMatch) result.metadata = JSON.parse(jsonMatch[0]);
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
try {
|
|
50
|
+
result.metadata = JSON.parse(value);
|
|
51
|
+
} catch {
|
|
52
|
+
logger.warn(`[hooks] Failed to parse metadata in HOOK.md`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return result.name ? result : null;
|
|
59
|
+
}
|
|
60
|
+
function extractMetadata(frontmatter) {
|
|
61
|
+
const milady = frontmatter.metadata?.milady;
|
|
62
|
+
if (!milady) return void 0;
|
|
63
|
+
return {
|
|
64
|
+
always: milady.always,
|
|
65
|
+
hookKey: milady.hookKey,
|
|
66
|
+
emoji: milady.emoji,
|
|
67
|
+
homepage: milady.homepage ?? frontmatter.homepage,
|
|
68
|
+
events: Array.isArray(milady.events) ? milady.events : [],
|
|
69
|
+
export: milady.export,
|
|
70
|
+
os: milady.os,
|
|
71
|
+
requires: milady.requires,
|
|
72
|
+
install: milady.install
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async function isDirectory(path) {
|
|
76
|
+
try {
|
|
77
|
+
return (await stat(path)).isDirectory();
|
|
78
|
+
} catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function fileExists(path) {
|
|
83
|
+
try {
|
|
84
|
+
return (await stat(path)).isFile();
|
|
85
|
+
} catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function findHandlerPath(dir) {
|
|
90
|
+
for (const name of HANDLER_NAMES) {
|
|
91
|
+
const p = join(dir, name);
|
|
92
|
+
if (await fileExists(p)) return p;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
async function loadHookFromDir(dir, source, pluginId) {
|
|
97
|
+
const hookMdPath = join(dir, HOOK_MD);
|
|
98
|
+
if (!await fileExists(hookMdPath)) return null;
|
|
99
|
+
const handlerPath = await findHandlerPath(dir);
|
|
100
|
+
if (!handlerPath) {
|
|
101
|
+
logger.warn(`[hooks] Hook at ${dir} has HOOK.md but no handler`);
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const frontmatter = parseFrontmatter(await readFile(hookMdPath, "utf-8"));
|
|
106
|
+
if (!frontmatter) {
|
|
107
|
+
logger.warn(`[hooks] Invalid frontmatter in ${hookMdPath}`);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const metadata = extractMetadata(frontmatter);
|
|
111
|
+
return {
|
|
112
|
+
hook: {
|
|
113
|
+
name: frontmatter.name,
|
|
114
|
+
description: frontmatter.description,
|
|
115
|
+
source,
|
|
116
|
+
pluginId,
|
|
117
|
+
filePath: hookMdPath,
|
|
118
|
+
baseDir: dir,
|
|
119
|
+
handlerPath
|
|
120
|
+
},
|
|
121
|
+
frontmatter,
|
|
122
|
+
metadata
|
|
123
|
+
};
|
|
124
|
+
} catch (err) {
|
|
125
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
126
|
+
logger.warn(`[hooks] Error loading hook from ${dir}: ${msg}`);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function scanHooksDir(dir, source) {
|
|
131
|
+
if (!await isDirectory(dir)) return [];
|
|
132
|
+
const entries = [];
|
|
133
|
+
try {
|
|
134
|
+
const items = await readdir(dir);
|
|
135
|
+
for (const item of items) {
|
|
136
|
+
const itemPath = join(dir, item);
|
|
137
|
+
if (!await isDirectory(itemPath)) continue;
|
|
138
|
+
const entry = await loadHookFromDir(itemPath, source);
|
|
139
|
+
if (entry) entries.push(entry);
|
|
140
|
+
}
|
|
141
|
+
} catch (err) {
|
|
142
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
143
|
+
logger.warn(`[hooks] Error scanning ${dir}: ${msg}`);
|
|
144
|
+
}
|
|
145
|
+
return entries;
|
|
146
|
+
}
|
|
147
|
+
/** Precedence: extra (lowest) -> bundled -> managed -> workspace (highest). */
|
|
148
|
+
async function discoverHooks(options = {}) {
|
|
149
|
+
const seen = /* @__PURE__ */ new Map();
|
|
150
|
+
if (options.extraDirs) for (const dir of options.extraDirs) {
|
|
151
|
+
const resolved = resolve(dir.replace(/^~/, homedir()));
|
|
152
|
+
for (const entry of await scanHooksDir(resolved, "milady-managed")) seen.set(entry.hook.name, entry);
|
|
153
|
+
}
|
|
154
|
+
if (options.bundledDir) for (const entry of await scanHooksDir(options.bundledDir, "milady-bundled")) seen.set(entry.hook.name, entry);
|
|
155
|
+
const managedDir = join(homedir(), ".milady", "hooks");
|
|
156
|
+
for (const entry of await scanHooksDir(managedDir, "milady-managed")) seen.set(entry.hook.name, entry);
|
|
157
|
+
if (options.workspacePath) {
|
|
158
|
+
const wsHooksDir = join(options.workspacePath.replace(/^~/, homedir()), "hooks");
|
|
159
|
+
for (const entry of await scanHooksDir(wsHooksDir, "milady-workspace")) seen.set(entry.hook.name, entry);
|
|
160
|
+
}
|
|
161
|
+
const all = Array.from(seen.values());
|
|
162
|
+
logger.info(`[hooks] Discovered ${all.length} hooks`);
|
|
163
|
+
return all;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
//#endregion
|
|
167
|
+
export { discoverHooks };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { platform } from "node:os";
|
|
2
|
+
import { delimiter } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
|
|
5
|
+
//#region src/hooks/eligibility.ts
|
|
6
|
+
/**
|
|
7
|
+
* Hook eligibility: checks OS, binary, env, and config requirements.
|
|
8
|
+
*/
|
|
9
|
+
function binaryExists(name) {
|
|
10
|
+
const pathDirs = (process.env.PATH ?? "").split(delimiter);
|
|
11
|
+
for (const dir of pathDirs) if (existsSync(`${dir}/${name}`)) return true;
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
function resolveConfigPath(config, pathStr) {
|
|
15
|
+
const parts = pathStr.split(".");
|
|
16
|
+
let current = config;
|
|
17
|
+
for (const part of parts) {
|
|
18
|
+
if (current === null || current === void 0 || typeof current !== "object") return;
|
|
19
|
+
current = current[part];
|
|
20
|
+
}
|
|
21
|
+
return current;
|
|
22
|
+
}
|
|
23
|
+
function isConfigPathTruthy(config, pathStr) {
|
|
24
|
+
const value = resolveConfigPath(config, pathStr);
|
|
25
|
+
return value !== void 0 && value !== null && value !== false && value !== "" && value !== 0;
|
|
26
|
+
}
|
|
27
|
+
function checkEligibility(metadata, hookConfig, miladyConfig = {}) {
|
|
28
|
+
const missing = [];
|
|
29
|
+
if (!metadata) return {
|
|
30
|
+
eligible: true,
|
|
31
|
+
missing: []
|
|
32
|
+
};
|
|
33
|
+
if (metadata.os && metadata.os.length > 0) {
|
|
34
|
+
if (!metadata.os.includes(platform())) missing.push(`OS: requires ${metadata.os.join("|")}, current: ${platform()}`);
|
|
35
|
+
}
|
|
36
|
+
if (metadata.always) return {
|
|
37
|
+
eligible: missing.length === 0,
|
|
38
|
+
missing
|
|
39
|
+
};
|
|
40
|
+
if (metadata.requires?.bins) {
|
|
41
|
+
for (const bin of metadata.requires.bins) if (!binaryExists(bin)) missing.push(`Binary missing: ${bin}`);
|
|
42
|
+
}
|
|
43
|
+
if (metadata.requires?.anyBins && metadata.requires.anyBins.length > 0) {
|
|
44
|
+
if (!metadata.requires.anyBins.some(binaryExists)) missing.push(`None of: ${metadata.requires.anyBins.join(", ")}`);
|
|
45
|
+
}
|
|
46
|
+
if (metadata.requires?.env) for (const envVar of metadata.requires.env) {
|
|
47
|
+
const hasInProcess = Boolean(process.env[envVar]);
|
|
48
|
+
const hasInHookConfig = Boolean(hookConfig?.env?.[envVar]);
|
|
49
|
+
if (!hasInProcess && !hasInHookConfig) missing.push(`Env missing: ${envVar}`);
|
|
50
|
+
}
|
|
51
|
+
if (metadata.requires?.config) {
|
|
52
|
+
for (const configPath of metadata.requires.config) if (!isConfigPathTruthy(miladyConfig, configPath)) missing.push(`Config missing: ${configPath}`);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
eligible: missing.length === 0,
|
|
56
|
+
missing
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function resolveHookConfig(internalConfig, hookKey) {
|
|
60
|
+
return internalConfig?.entries?.[hookKey];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
export { checkEligibility, resolveHookConfig };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { discoverHooks } from "./discovery.js";
|
|
2
|
+
import { checkEligibility, resolveHookConfig } from "./eligibility.js";
|
|
3
|
+
import { clearHooks, registerHook } from "./registry.js";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { resolve, sep } from "node:path";
|
|
6
|
+
import { logger } from "@elizaos/core";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
8
|
+
|
|
9
|
+
//#region src/hooks/loader.ts
|
|
10
|
+
/**
|
|
11
|
+
* Hook Loader — load and register hooks into the event system.
|
|
12
|
+
*
|
|
13
|
+
* Orchestrates discovery -> eligibility -> loading -> registration.
|
|
14
|
+
*
|
|
15
|
+
* @module hooks/loader
|
|
16
|
+
*/
|
|
17
|
+
/** Directories from which hook modules may be loaded. */
|
|
18
|
+
function getSafeHookRoots(workspacePath, bundledDir) {
|
|
19
|
+
const roots = [resolve(homedir(), ".milady", "hooks")];
|
|
20
|
+
if (bundledDir) roots.push(resolve(bundledDir));
|
|
21
|
+
if (workspacePath) roots.push(resolve(workspacePath.replace(/^~/, homedir()), "hooks"));
|
|
22
|
+
return roots;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Ensure a module path resolves to a file under one of the allowed hook
|
|
26
|
+
* roots. Blocks absolute paths to arbitrary locations and path-traversal
|
|
27
|
+
* attacks (e.g. "../../etc/malicious").
|
|
28
|
+
*/
|
|
29
|
+
function isPathUnderRoots(modulePath, roots) {
|
|
30
|
+
const resolved = resolve(modulePath);
|
|
31
|
+
return roots.some((root) => {
|
|
32
|
+
const r = root.endsWith(sep) ? root : root + sep;
|
|
33
|
+
return resolved.startsWith(r) || resolved === root;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Dynamically import a hook handler module.
|
|
38
|
+
* Uses cache-busting query parameter for dev mode hot reload.
|
|
39
|
+
*/
|
|
40
|
+
async function loadHandlerModule(handlerPath, exportName = "default") {
|
|
41
|
+
try {
|
|
42
|
+
const handler = (await import(`${pathToFileURL(handlerPath).href}?t=${Date.now()}`))[exportName];
|
|
43
|
+
if (typeof handler !== "function") {
|
|
44
|
+
logger.warn(`[hooks] Handler at ${handlerPath} does not export a function as "${exportName}"`);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return handler;
|
|
48
|
+
} catch (err) {
|
|
49
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
50
|
+
logger.error(`[hooks] Failed to load handler ${handlerPath}: ${msg}`);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Discover, filter, load, and register all hooks.
|
|
56
|
+
*
|
|
57
|
+
* This is the main entry point called during gateway startup.
|
|
58
|
+
*/
|
|
59
|
+
async function loadHooks(options = {}) {
|
|
60
|
+
const { internalConfig, miladyConfig = {} } = options;
|
|
61
|
+
if (internalConfig?.enabled === false) {
|
|
62
|
+
logger.info("[hooks] Internal hooks disabled");
|
|
63
|
+
return {
|
|
64
|
+
discovered: 0,
|
|
65
|
+
eligible: 0,
|
|
66
|
+
registered: 0,
|
|
67
|
+
skipped: [],
|
|
68
|
+
failed: []
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
clearHooks();
|
|
72
|
+
const safeExtraDirs = [...options.extraDirs ?? []];
|
|
73
|
+
const miladyHome = resolve(homedir(), ".milady");
|
|
74
|
+
for (const dir of internalConfig?.load?.extraDirs ?? []) {
|
|
75
|
+
const resolved = resolve(dir.replace(/^~/, homedir()));
|
|
76
|
+
if (resolved.startsWith(miladyHome + sep) || resolved === miladyHome) safeExtraDirs.push(dir);
|
|
77
|
+
else logger.warn(`[hooks] Rejected config extraDir "${dir}": must be under ~/.milady/`);
|
|
78
|
+
}
|
|
79
|
+
const entries = await discoverHooks({
|
|
80
|
+
workspacePath: options.workspacePath,
|
|
81
|
+
bundledDir: options.bundledDir,
|
|
82
|
+
extraDirs: safeExtraDirs
|
|
83
|
+
});
|
|
84
|
+
const result = {
|
|
85
|
+
discovered: entries.length,
|
|
86
|
+
eligible: 0,
|
|
87
|
+
registered: 0,
|
|
88
|
+
skipped: [],
|
|
89
|
+
failed: []
|
|
90
|
+
};
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
const hookConfig = resolveHookConfig(internalConfig, entry.metadata?.hookKey ?? entry.hook.name);
|
|
93
|
+
const eligibility = checkEligibility(entry.metadata, hookConfig, miladyConfig);
|
|
94
|
+
if (!eligibility.eligible) {
|
|
95
|
+
result.skipped.push(`${entry.hook.name}: ${eligibility.missing.join(", ")}`);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
result.eligible++;
|
|
99
|
+
if (hookConfig?.enabled === false) {
|
|
100
|
+
result.skipped.push(`${entry.hook.name}: disabled in config`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const exportName = entry.metadata?.export ?? "default";
|
|
104
|
+
const handler = await loadHandlerModule(entry.hook.handlerPath, exportName);
|
|
105
|
+
if (!handler) {
|
|
106
|
+
result.failed.push(entry.hook.name);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const events = entry.metadata?.events ?? [];
|
|
110
|
+
if (events.length === 0) {
|
|
111
|
+
logger.warn(`[hooks] Hook "${entry.hook.name}" has no events configured`);
|
|
112
|
+
result.skipped.push(`${entry.hook.name}: no events`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
for (const eventKey of events) registerHook(eventKey, handler);
|
|
116
|
+
const emoji = entry.metadata?.emoji ?? "🔗";
|
|
117
|
+
logger.info(`[hooks] ${emoji} Registered: ${entry.hook.name} -> ${events.join(", ")}`);
|
|
118
|
+
result.registered++;
|
|
119
|
+
}
|
|
120
|
+
if (internalConfig?.handlers) {
|
|
121
|
+
const safeRoots = getSafeHookRoots(options.workspacePath, options.bundledDir);
|
|
122
|
+
for (const legacyHandler of internalConfig.handlers) {
|
|
123
|
+
if (!isPathUnderRoots(legacyHandler.module, safeRoots)) {
|
|
124
|
+
logger.warn(`[hooks] Rejected legacy handler: module path "${legacyHandler.module}" is outside allowed hook directories`);
|
|
125
|
+
result.failed.push(legacyHandler.module);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const handler = await loadHandlerModule(legacyHandler.module, legacyHandler.export ?? "default");
|
|
130
|
+
if (handler) {
|
|
131
|
+
registerHook(legacyHandler.event, handler);
|
|
132
|
+
logger.info(`[hooks] Registered legacy handler: ${legacyHandler.event} -> ${legacyHandler.module}`);
|
|
133
|
+
result.registered++;
|
|
134
|
+
} else result.failed.push(legacyHandler.module);
|
|
135
|
+
} catch (err) {
|
|
136
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
137
|
+
logger.warn(`[hooks] Failed to load legacy handler: ${msg}`);
|
|
138
|
+
result.failed.push(legacyHandler.module);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
logger.info(`[hooks] Load complete: ${result.registered}/${result.discovered} registered, ${result.skipped.length} skipped, ${result.failed.length} failed`);
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
//#endregion
|
|
147
|
+
export { loadHooks };
|