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.
Files changed (241) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +7 -0
  2. package/dist/actions/emote.js +64 -0
  3. package/dist/actions/restart.js +81 -0
  4. package/dist/actions/send-message.js +152 -0
  5. package/dist/agent-admin-routes.js +82 -0
  6. package/dist/agent-lifecycle-routes.js +79 -0
  7. package/dist/agent-transfer-routes.js +102 -0
  8. package/dist/api/agent-admin-routes.js +82 -0
  9. package/dist/api/agent-lifecycle-routes.js +79 -0
  10. package/dist/api/agent-transfer-routes.js +102 -0
  11. package/dist/api/apps-hyperscape-routes.js +58 -0
  12. package/dist/api/apps-routes.js +114 -0
  13. package/dist/api/auth-routes.js +56 -0
  14. package/dist/api/autonomy-routes.js +44 -0
  15. package/dist/api/bug-report-routes.js +111 -0
  16. package/dist/api/character-routes.js +195 -0
  17. package/dist/api/cloud-routes.js +330 -0
  18. package/dist/api/cloud-status-routes.js +155 -0
  19. package/dist/api/compat-utils.js +111 -0
  20. package/dist/api/database.js +735 -0
  21. package/dist/api/diagnostics-routes.js +205 -0
  22. package/dist/api/drop-service.js +134 -0
  23. package/dist/api/early-logs.js +86 -0
  24. package/dist/api/http-helpers.js +131 -0
  25. package/dist/api/knowledge-routes.js +534 -0
  26. package/dist/api/memory-bounds.js +71 -0
  27. package/dist/api/models-routes.js +28 -0
  28. package/dist/api/og-tracker.js +36 -0
  29. package/dist/api/permissions-routes.js +109 -0
  30. package/dist/api/plugin-validation.js +198 -0
  31. package/dist/api/provider-switch-config.js +41 -0
  32. package/dist/api/registry-routes.js +86 -0
  33. package/dist/api/registry-service.js +164 -0
  34. package/dist/api/sandbox-routes.js +1112 -0
  35. package/dist/api/server.js +7949 -0
  36. package/dist/api/subscription-routes.js +172 -0
  37. package/dist/api/terminal-run-limits.js +24 -0
  38. package/dist/api/training-routes.js +158 -0
  39. package/dist/api/trajectory-routes.js +300 -0
  40. package/dist/api/trigger-routes.js +246 -0
  41. package/dist/api/twitter-verify.js +134 -0
  42. package/dist/api/tx-service.js +108 -0
  43. package/dist/api/wallet-routes.js +266 -0
  44. package/dist/api/wallet.js +568 -0
  45. package/dist/api/whatsapp-routes.js +182 -0
  46. package/dist/api/zip-utils.js +109 -0
  47. package/dist/apps-hyperscape-routes.js +58 -0
  48. package/dist/apps-routes.js +114 -0
  49. package/dist/ascii.js +20 -0
  50. package/dist/auth/anthropic.js +44 -0
  51. package/dist/auth/apply-stealth.js +41 -0
  52. package/dist/auth/claude-code-stealth.js +78 -0
  53. package/dist/auth/credentials.js +156 -0
  54. package/dist/auth/index.js +5 -0
  55. package/dist/auth/openai-codex.js +66 -0
  56. package/dist/auth/types.js +9 -0
  57. package/dist/auth-routes.js +56 -0
  58. package/dist/autonomy-routes.js +44 -0
  59. package/dist/bug-report-routes.js +111 -0
  60. package/dist/build-info.json +6 -0
  61. package/dist/character-routes.js +195 -0
  62. package/dist/cli/argv.js +63 -0
  63. package/dist/cli/banner.js +34 -0
  64. package/dist/cli/cli-name.js +21 -0
  65. package/dist/cli/cli-utils.js +16 -0
  66. package/dist/cli/git-commit.js +78 -0
  67. package/dist/cli/parse-duration.js +15 -0
  68. package/dist/cli/plugins-cli.js +590 -0
  69. package/dist/cli/profile-utils.js +9 -0
  70. package/dist/cli/profile.js +95 -0
  71. package/dist/cli/program/build-program.js +17 -0
  72. package/dist/cli/program/command-registry.js +23 -0
  73. package/dist/cli/program/help.js +47 -0
  74. package/dist/cli/program/preaction.js +33 -0
  75. package/dist/cli/program/register.config.js +106 -0
  76. package/dist/cli/program/register.configure.js +20 -0
  77. package/dist/cli/program/register.dashboard.js +124 -0
  78. package/dist/cli/program/register.models.js +23 -0
  79. package/dist/cli/program/register.setup.js +36 -0
  80. package/dist/cli/program/register.start.js +22 -0
  81. package/dist/cli/program/register.subclis.js +70 -0
  82. package/dist/cli/program/register.tui.js +163 -0
  83. package/dist/cli/program/register.update.js +154 -0
  84. package/dist/cli/program.js +3 -0
  85. package/dist/cli/run-main.js +37 -0
  86. package/dist/cli/version.js +7 -0
  87. package/dist/cloud/validate-url.js +93 -0
  88. package/dist/cloud-routes.js +330 -0
  89. package/dist/cloud-status-routes.js +155 -0
  90. package/dist/compat-utils.js +111 -0
  91. package/dist/config/config.js +69 -0
  92. package/dist/config/env-vars.js +19 -0
  93. package/dist/config/includes.js +121 -0
  94. package/dist/config/object-utils.js +7 -0
  95. package/dist/config/paths.js +38 -0
  96. package/dist/config/plugin-auto-enable.js +231 -0
  97. package/dist/config/schema.js +864 -0
  98. package/dist/config/telegram-custom-commands.js +76 -0
  99. package/dist/config/zod-schema.agent-runtime.js +519 -0
  100. package/dist/config/zod-schema.core.js +538 -0
  101. package/dist/config/zod-schema.hooks.js +103 -0
  102. package/dist/config/zod-schema.js +488 -0
  103. package/dist/config/zod-schema.providers-core.js +785 -0
  104. package/dist/config/zod-schema.session.js +73 -0
  105. package/dist/core-plugins.js +37 -0
  106. package/dist/custom-actions.js +250 -0
  107. package/dist/database.js +735 -0
  108. package/dist/diagnostics/integration-observability.js +57 -0
  109. package/dist/diagnostics-routes.js +205 -0
  110. package/dist/drop-service.js +134 -0
  111. package/dist/early-logs.js +24 -0
  112. package/dist/eliza.js +2061 -0
  113. package/dist/emotes/catalog.js +271 -0
  114. package/dist/entry.js +40 -0
  115. package/dist/hooks/discovery.js +167 -0
  116. package/dist/hooks/eligibility.js +64 -0
  117. package/dist/hooks/index.js +4 -0
  118. package/dist/hooks/loader.js +147 -0
  119. package/dist/hooks/registry.js +55 -0
  120. package/dist/http-helpers.js +131 -0
  121. package/dist/index.js +49 -0
  122. package/dist/knowledge-routes.js +534 -0
  123. package/dist/memory-bounds.js +71 -0
  124. package/dist/milady-plugin.js +90 -0
  125. package/dist/models-routes.js +28 -0
  126. package/dist/onboarding-names.js +78 -0
  127. package/dist/onboarding-presets.js +922 -0
  128. package/dist/package.json +1 -0
  129. package/dist/permissions-routes.js +109 -0
  130. package/dist/plugin-validation.js +107 -0
  131. package/dist/plugins/whatsapp/actions.js +91 -0
  132. package/dist/plugins/whatsapp/index.js +16 -0
  133. package/dist/plugins/whatsapp/service.js +270 -0
  134. package/dist/provider-switch-config.js +41 -0
  135. package/dist/providers/admin-trust.js +46 -0
  136. package/dist/providers/autonomous-state.js +101 -0
  137. package/dist/providers/session-bridge.js +86 -0
  138. package/dist/providers/session-utils.js +36 -0
  139. package/dist/providers/simple-mode.js +50 -0
  140. package/dist/providers/ui-catalog.js +15 -0
  141. package/dist/providers/workspace-provider.js +93 -0
  142. package/dist/providers/workspace.js +348 -0
  143. package/dist/registry-routes.js +86 -0
  144. package/dist/registry-service.js +164 -0
  145. package/dist/restart.js +40 -0
  146. package/dist/runtime/core-plugins.js +37 -0
  147. package/dist/runtime/custom-actions.js +250 -0
  148. package/dist/runtime/eliza.js +2061 -0
  149. package/dist/runtime/embedding-manager-support.js +185 -0
  150. package/dist/runtime/embedding-manager.js +193 -0
  151. package/dist/runtime/embedding-presets.js +54 -0
  152. package/dist/runtime/embedding-state.js +8 -0
  153. package/dist/runtime/milady-plugin.js +90 -0
  154. package/dist/runtime/onboarding-names.js +78 -0
  155. package/dist/runtime/restart.js +40 -0
  156. package/dist/runtime/version.js +7 -0
  157. package/dist/sandbox-routes.js +1112 -0
  158. package/dist/security/audit-log.js +149 -0
  159. package/dist/security/network-policy.js +70 -0
  160. package/dist/server.js +7949 -0
  161. package/dist/services/agent-export.js +559 -0
  162. package/dist/services/app-manager.js +389 -0
  163. package/dist/services/browser-capture.js +86 -0
  164. package/dist/services/fallback-training-service.js +128 -0
  165. package/dist/services/mcp-marketplace.js +134 -0
  166. package/dist/services/plugin-installer.js +396 -0
  167. package/dist/services/plugin-manager-types.js +15 -0
  168. package/dist/services/registry-client-app-meta.js +144 -0
  169. package/dist/services/registry-client-endpoints.js +166 -0
  170. package/dist/services/registry-client-local.js +271 -0
  171. package/dist/services/registry-client-network.js +93 -0
  172. package/dist/services/registry-client-queries.js +70 -0
  173. package/dist/services/registry-client.js +157 -0
  174. package/dist/services/sandbox-engine.js +511 -0
  175. package/dist/services/sandbox-manager.js +297 -0
  176. package/dist/services/self-updater.js +175 -0
  177. package/dist/services/skill-catalog-client.js +119 -0
  178. package/dist/services/skill-marketplace.js +521 -0
  179. package/dist/services/stream-manager.js +236 -0
  180. package/dist/services/update-checker.js +121 -0
  181. package/dist/services/update-notifier.js +29 -0
  182. package/dist/services/version-compat.js +78 -0
  183. package/dist/services/whatsapp-pairing.js +196 -0
  184. package/dist/shared/ui-catalog-prompt.js +728 -0
  185. package/dist/subscription-routes.js +172 -0
  186. package/dist/terminal/links.js +19 -0
  187. package/dist/terminal/palette.js +14 -0
  188. package/dist/terminal/theme.js +25 -0
  189. package/dist/terminal-run-limits.js +24 -0
  190. package/dist/training-routes.js +158 -0
  191. package/dist/trajectory-routes.js +300 -0
  192. package/dist/trigger-routes.js +246 -0
  193. package/dist/triggers/action.js +218 -0
  194. package/dist/triggers/runtime.js +281 -0
  195. package/dist/triggers/scheduling.js +295 -0
  196. package/dist/triggers/types.js +5 -0
  197. package/dist/tui/components/assistant-message.js +76 -0
  198. package/dist/tui/components/chat-editor.js +34 -0
  199. package/dist/tui/components/embeddings-overlay.js +46 -0
  200. package/dist/tui/components/footer.js +60 -0
  201. package/dist/tui/components/index.js +15 -0
  202. package/dist/tui/components/modal-frame.js +45 -0
  203. package/dist/tui/components/modal-style.js +15 -0
  204. package/dist/tui/components/model-selector.js +70 -0
  205. package/dist/tui/components/pinned-chat-layout.js +46 -0
  206. package/dist/tui/components/plugins-endpoints-tab.js +196 -0
  207. package/dist/tui/components/plugins-installed-tab-view.js +69 -0
  208. package/dist/tui/components/plugins-installed-tab.js +319 -0
  209. package/dist/tui/components/plugins-overlay-catalog.js +81 -0
  210. package/dist/tui/components/plugins-overlay-data-api.js +21 -0
  211. package/dist/tui/components/plugins-overlay-data-shared.js +20 -0
  212. package/dist/tui/components/plugins-overlay-data.js +323 -0
  213. package/dist/tui/components/plugins-overlay.js +117 -0
  214. package/dist/tui/components/plugins-store-tab.js +148 -0
  215. package/dist/tui/components/settings-overlay.js +61 -0
  216. package/dist/tui/components/status-bar.js +64 -0
  217. package/dist/tui/components/tool-execution.js +68 -0
  218. package/dist/tui/components/user-message.js +22 -0
  219. package/dist/tui/eliza-tui-bridge.js +606 -0
  220. package/dist/tui/index.js +370 -0
  221. package/dist/tui/modal-presets.js +33 -0
  222. package/dist/tui/model-spec.js +46 -0
  223. package/dist/tui/sse-parser.js +78 -0
  224. package/dist/tui/theme.js +110 -0
  225. package/dist/tui/titlebar-spinner.js +62 -0
  226. package/dist/tui/tui-app.js +311 -0
  227. package/dist/tui/ws-client.js +215 -0
  228. package/dist/twitter-verify.js +134 -0
  229. package/dist/tx-service.js +108 -0
  230. package/dist/utils/exec-safety.js +17 -0
  231. package/dist/utils/globals.js +20 -0
  232. package/dist/utils/milady-root.js +61 -0
  233. package/dist/utils/number-parsing.js +37 -0
  234. package/dist/version-resolver.js +37 -0
  235. package/dist/version.js +7 -0
  236. package/dist/wallet-routes.js +266 -0
  237. package/dist/wallet.js +568 -0
  238. package/dist/whatsapp-routes.js +182 -0
  239. package/dist/zip-utils.js +109 -0
  240. package/milady.mjs +14 -0
  241. package/package.json +111 -0
@@ -0,0 +1,182 @@
1
+ import { readJsonBody as readJsonBody$1, sendJson } from "./http-helpers.js";
2
+ import { WhatsAppPairingSession, sanitizeAccountId, whatsappAuthExists, whatsappLogout } from "../services/whatsapp-pairing.js";
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+
6
+ //#region src/api/whatsapp-routes.ts
7
+ /**
8
+ * WhatsApp API routes: pair, status, stop, disconnect.
9
+ *
10
+ * Extracted from the main server handler for testability.
11
+ */
12
+ const MAX_BODY_BYTES = 1048576;
13
+ /** Maximum concurrent pairing sessions to prevent resource exhaustion. */
14
+ const MAX_PAIRING_SESSIONS = 10;
15
+ async function readJsonBody(req, res) {
16
+ return readJsonBody$1(req, res, { maxBytes: MAX_BODY_BYTES });
17
+ }
18
+ function json(res, data, status = 200) {
19
+ sendJson(res, data, status);
20
+ }
21
+ /** Returns `true` if handled, `false` to fall through. */
22
+ async function handleWhatsAppRoute(req, res, pathname, method, state) {
23
+ if (!pathname.startsWith("/api/whatsapp")) return false;
24
+ if (method === "POST" && pathname === "/api/whatsapp/pair") {
25
+ const body = await readJsonBody(req, res);
26
+ let accountId;
27
+ try {
28
+ accountId = sanitizeAccountId(body && typeof body.accountId === "string" && body.accountId.trim() ? body.accountId.trim() : "default");
29
+ } catch (err) {
30
+ json(res, { error: err.message }, 400);
31
+ return true;
32
+ }
33
+ if (!state.whatsappPairingSessions.has(accountId) && state.whatsappPairingSessions.size >= MAX_PAIRING_SESSIONS) {
34
+ json(res, { error: `Too many concurrent pairing sessions (max ${MAX_PAIRING_SESSIONS})` }, 429);
35
+ return true;
36
+ }
37
+ const authDir = path.join(state.workspaceDir, "whatsapp-auth", accountId);
38
+ state.whatsappPairingSessions?.get(accountId)?.stop();
39
+ const session = new WhatsAppPairingSession({
40
+ authDir,
41
+ accountId,
42
+ onEvent: (event) => {
43
+ state.broadcastWs?.(event);
44
+ if (event.status === "connected") {
45
+ if (!state.config.connectors) state.config.connectors = {};
46
+ state.config.connectors.whatsapp = {
47
+ ...state.config.connectors.whatsapp ?? {},
48
+ authDir,
49
+ enabled: true
50
+ };
51
+ try {
52
+ state.saveConfig();
53
+ } catch {}
54
+ }
55
+ }
56
+ });
57
+ state.whatsappPairingSessions.set(accountId, session);
58
+ try {
59
+ await session.start();
60
+ json(res, {
61
+ ok: true,
62
+ accountId,
63
+ status: session.getStatus()
64
+ });
65
+ } catch (err) {
66
+ json(res, {
67
+ ok: false,
68
+ error: err instanceof Error ? err.message : String(err)
69
+ }, 500);
70
+ }
71
+ return true;
72
+ }
73
+ if (method === "GET" && pathname === "/api/whatsapp/status") {
74
+ const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
75
+ let accountId;
76
+ try {
77
+ accountId = sanitizeAccountId(url.searchParams.get("accountId") || "default");
78
+ } catch (err) {
79
+ json(res, { error: err.message }, 400);
80
+ return true;
81
+ }
82
+ const session = state.whatsappPairingSessions?.get(accountId);
83
+ let serviceConnected = false;
84
+ let servicePhone = null;
85
+ if (state.runtime) try {
86
+ const waService = state.runtime.getService("whatsapp");
87
+ if (waService) {
88
+ serviceConnected = Boolean(waService.connected);
89
+ servicePhone = waService.phoneNumber ?? null;
90
+ }
91
+ } catch {}
92
+ json(res, {
93
+ accountId,
94
+ status: session?.getStatus() ?? "idle",
95
+ authExists: whatsappAuthExists(state.workspaceDir, accountId),
96
+ serviceConnected,
97
+ servicePhone
98
+ });
99
+ return true;
100
+ }
101
+ if (method === "POST" && pathname === "/api/whatsapp/pair/stop") {
102
+ const body = await readJsonBody(req, res);
103
+ let accountId;
104
+ try {
105
+ accountId = sanitizeAccountId(body && typeof body.accountId === "string" && body.accountId.trim() ? body.accountId.trim() : "default");
106
+ } catch (err) {
107
+ json(res, { error: err.message }, 400);
108
+ return true;
109
+ }
110
+ const session = state.whatsappPairingSessions?.get(accountId);
111
+ if (session) {
112
+ session.stop();
113
+ state.whatsappPairingSessions?.delete(accountId);
114
+ }
115
+ json(res, {
116
+ ok: true,
117
+ accountId,
118
+ status: "idle"
119
+ });
120
+ return true;
121
+ }
122
+ if (method === "POST" && pathname === "/api/whatsapp/disconnect") {
123
+ const body = await readJsonBody(req, res);
124
+ let accountId;
125
+ try {
126
+ accountId = sanitizeAccountId(body && typeof body.accountId === "string" && body.accountId.trim() ? body.accountId.trim() : "default");
127
+ } catch (err) {
128
+ json(res, { error: err.message }, 400);
129
+ return true;
130
+ }
131
+ const session = state.whatsappPairingSessions?.get(accountId);
132
+ if (session) {
133
+ session.stop();
134
+ state.whatsappPairingSessions?.delete(accountId);
135
+ }
136
+ try {
137
+ await whatsappLogout(state.workspaceDir, accountId);
138
+ } catch (logoutErr) {
139
+ console.warn(`[whatsapp] Logout failed for ${accountId}, deleting auth files directly:`, logoutErr instanceof Error ? logoutErr.message : String(logoutErr));
140
+ const authDir = path.join(state.workspaceDir, "whatsapp-auth", accountId);
141
+ try {
142
+ fs.rmSync(authDir, {
143
+ recursive: true,
144
+ force: true
145
+ });
146
+ } catch {}
147
+ }
148
+ if (state.config.connectors) {
149
+ delete state.config.connectors.whatsapp;
150
+ try {
151
+ state.saveConfig();
152
+ } catch {}
153
+ }
154
+ json(res, {
155
+ ok: true,
156
+ accountId
157
+ });
158
+ return true;
159
+ }
160
+ return false;
161
+ }
162
+ /**
163
+ * When WhatsApp is connected via QR code (Baileys auth on disk), mark the
164
+ * plugin entry as configured and clear validation errors so the UI doesn't
165
+ * show misleading "missing API key" warnings.
166
+ */
167
+ function applyWhatsAppQrOverride(plugins, workspaceDir) {
168
+ try {
169
+ const waCredsPath = path.join(workspaceDir, "whatsapp-auth", "default", "creds.json");
170
+ if (fs.existsSync(waCredsPath)) {
171
+ const waPlugin = plugins.find((p) => p.id === "whatsapp");
172
+ if (waPlugin) {
173
+ waPlugin.validationErrors = [];
174
+ waPlugin.configured = true;
175
+ waPlugin.qrConnected = true;
176
+ }
177
+ }
178
+ } catch {}
179
+ }
180
+
181
+ //#endregion
182
+ export { applyWhatsAppQrOverride, handleWhatsAppRoute };
@@ -0,0 +1,109 @@
1
+ //#region src/api/zip-utils.ts
2
+ const CRC32_TABLE = new Uint32Array(256);
3
+ for (let i = 0; i < 256; i += 1) {
4
+ let crc = i;
5
+ for (let j = 0; j < 8; j += 1) if ((crc & 1) === 1) crc = crc >>> 1 ^ 3988292384;
6
+ else crc >>>= 1;
7
+ CRC32_TABLE[i] = crc >>> 0;
8
+ }
9
+ function normalizeZipEntryName(name) {
10
+ const normalized = name.replaceAll("\\", "/").replace(/^\/+/, "");
11
+ if (!normalized) throw new Error("ZIP entry name cannot be empty");
12
+ if (normalized.includes("\0")) throw new Error("ZIP entry name contains invalid null byte");
13
+ const parts = normalized.split("/");
14
+ for (const part of parts) if (part === "." || part === "..") throw new Error(`ZIP entry name is not safe: ${name}`);
15
+ return normalized;
16
+ }
17
+ function toBuffer(data) {
18
+ if (Buffer.isBuffer(data)) return data;
19
+ if (typeof data === "string") return Buffer.from(data, "utf-8");
20
+ return Buffer.from(data);
21
+ }
22
+ function crc32(buffer) {
23
+ let crc = 4294967295;
24
+ for (const byte of buffer) {
25
+ const index = (crc ^ byte) & 255;
26
+ crc = crc >>> 8 ^ (CRC32_TABLE[index] ?? 0);
27
+ }
28
+ return (crc ^ 4294967295) >>> 0;
29
+ }
30
+ function toDosDateTime(date) {
31
+ const year = Math.min(Math.max(date.getFullYear(), 1980), 2107);
32
+ const month = Math.min(Math.max(date.getMonth() + 1, 1), 12);
33
+ const day = Math.min(Math.max(date.getDate(), 1), 31);
34
+ const hours = Math.min(Math.max(date.getHours(), 0), 23);
35
+ const minutes = Math.min(Math.max(date.getMinutes(), 0), 59);
36
+ const seconds = Math.min(Math.max(Math.floor(date.getSeconds() / 2), 0), 29);
37
+ const dosDate = year - 1980 << 9 | month << 5 | day;
38
+ const dosTime = hours << 11 | minutes << 5 | seconds;
39
+ return {
40
+ date: dosDate & 65535,
41
+ time: dosTime & 65535
42
+ };
43
+ }
44
+ function createZipArchive(entries) {
45
+ if (entries.length > 65535) throw new Error("ZIP export supports up to 65535 files");
46
+ const fileParts = [];
47
+ const centralDirectoryParts = [];
48
+ let offset = 0;
49
+ for (const entry of entries) {
50
+ const name = normalizeZipEntryName(entry.name);
51
+ const nameBuffer = Buffer.from(name, "utf-8");
52
+ const dataBuffer = toBuffer(entry.data);
53
+ const checksum = crc32(dataBuffer);
54
+ const { date, time } = toDosDateTime(entry.mtime ?? /* @__PURE__ */ new Date());
55
+ const localHeader = Buffer.alloc(30 + nameBuffer.length);
56
+ localHeader.writeUInt32LE(67324752, 0);
57
+ localHeader.writeUInt16LE(20, 4);
58
+ localHeader.writeUInt16LE(0, 6);
59
+ localHeader.writeUInt16LE(0, 8);
60
+ localHeader.writeUInt16LE(time, 10);
61
+ localHeader.writeUInt16LE(date, 12);
62
+ localHeader.writeUInt32LE(checksum, 14);
63
+ localHeader.writeUInt32LE(dataBuffer.length, 18);
64
+ localHeader.writeUInt32LE(dataBuffer.length, 22);
65
+ localHeader.writeUInt16LE(nameBuffer.length, 26);
66
+ localHeader.writeUInt16LE(0, 28);
67
+ nameBuffer.copy(localHeader, 30);
68
+ const centralHeader = Buffer.alloc(46 + nameBuffer.length);
69
+ centralHeader.writeUInt32LE(33639248, 0);
70
+ centralHeader.writeUInt16LE(20, 4);
71
+ centralHeader.writeUInt16LE(20, 6);
72
+ centralHeader.writeUInt16LE(0, 8);
73
+ centralHeader.writeUInt16LE(0, 10);
74
+ centralHeader.writeUInt16LE(time, 12);
75
+ centralHeader.writeUInt16LE(date, 14);
76
+ centralHeader.writeUInt32LE(checksum, 16);
77
+ centralHeader.writeUInt32LE(dataBuffer.length, 20);
78
+ centralHeader.writeUInt32LE(dataBuffer.length, 24);
79
+ centralHeader.writeUInt16LE(nameBuffer.length, 28);
80
+ centralHeader.writeUInt16LE(0, 30);
81
+ centralHeader.writeUInt16LE(0, 32);
82
+ centralHeader.writeUInt16LE(0, 34);
83
+ centralHeader.writeUInt16LE(0, 36);
84
+ centralHeader.writeUInt32LE(0, 38);
85
+ centralHeader.writeUInt32LE(offset, 42);
86
+ nameBuffer.copy(centralHeader, 46);
87
+ fileParts.push(localHeader, dataBuffer);
88
+ centralDirectoryParts.push(centralHeader);
89
+ offset += localHeader.length + dataBuffer.length;
90
+ }
91
+ const centralDirectory = Buffer.concat(centralDirectoryParts);
92
+ const endOfCentralDirectory = Buffer.alloc(22);
93
+ endOfCentralDirectory.writeUInt32LE(101010256, 0);
94
+ endOfCentralDirectory.writeUInt16LE(0, 4);
95
+ endOfCentralDirectory.writeUInt16LE(0, 6);
96
+ endOfCentralDirectory.writeUInt16LE(entries.length, 8);
97
+ endOfCentralDirectory.writeUInt16LE(entries.length, 10);
98
+ endOfCentralDirectory.writeUInt32LE(centralDirectory.length, 12);
99
+ endOfCentralDirectory.writeUInt32LE(offset, 16);
100
+ endOfCentralDirectory.writeUInt16LE(0, 20);
101
+ return Buffer.concat([
102
+ ...fileParts,
103
+ centralDirectory,
104
+ endOfCentralDirectory
105
+ ]);
106
+ }
107
+
108
+ //#endregion
109
+ export { createZipArchive };
@@ -0,0 +1,58 @@
1
+ //#region src/api/apps-hyperscape-routes.ts
2
+ async function handleAppsHyperscapeRoutes(ctx) {
3
+ const { req, res, method, pathname, relayHyperscapeApi, readJsonBody, error } = ctx;
4
+ if (method === "GET" && pathname === "/api/apps/hyperscape/embedded-agents") {
5
+ await relayHyperscapeApi("GET", "/api/embedded-agents");
6
+ return true;
7
+ }
8
+ if (method === "POST" && pathname === "/api/apps/hyperscape/embedded-agents") {
9
+ await relayHyperscapeApi("POST", "/api/embedded-agents");
10
+ return true;
11
+ }
12
+ if (method === "POST") {
13
+ const embeddedActionMatch = pathname.match(/^\/api\/apps\/hyperscape\/embedded-agents\/([^/]+)\/(start|stop|pause|resume|command)$/);
14
+ if (embeddedActionMatch) {
15
+ const characterId = decodeURIComponent(embeddedActionMatch[1]);
16
+ const action = embeddedActionMatch[2];
17
+ await relayHyperscapeApi("POST", `/api/embedded-agents/${encodeURIComponent(characterId)}/${action}`);
18
+ return true;
19
+ }
20
+ const messageMatch = pathname.match(/^\/api\/apps\/hyperscape\/agents\/([^/]+)\/message$/);
21
+ if (messageMatch) {
22
+ const agentId = decodeURIComponent(messageMatch[1]);
23
+ const body = await readJsonBody(req, res);
24
+ if (!body) return true;
25
+ const content = body.content?.trim();
26
+ if (!content) {
27
+ error(res, "content is required");
28
+ return true;
29
+ }
30
+ await relayHyperscapeApi("POST", `/api/embedded-agents/${encodeURIComponent(agentId)}/command`, {
31
+ rawBodyOverride: JSON.stringify({
32
+ command: "chat",
33
+ data: { message: content }
34
+ }),
35
+ contentTypeOverride: "application/json"
36
+ });
37
+ return true;
38
+ }
39
+ }
40
+ if (method === "GET") {
41
+ const goalMatch = pathname.match(/^\/api\/apps\/hyperscape\/agents\/([^/]+)\/goal$/);
42
+ if (goalMatch) {
43
+ const agentId = decodeURIComponent(goalMatch[1]);
44
+ await relayHyperscapeApi("GET", `/api/agents/${encodeURIComponent(agentId)}/goal`);
45
+ return true;
46
+ }
47
+ const quickActionsMatch = pathname.match(/^\/api\/apps\/hyperscape\/agents\/([^/]+)\/quick-actions$/);
48
+ if (quickActionsMatch) {
49
+ const agentId = decodeURIComponent(quickActionsMatch[1]);
50
+ await relayHyperscapeApi("GET", `/api/agents/${encodeURIComponent(agentId)}/quick-actions`);
51
+ return true;
52
+ }
53
+ }
54
+ return false;
55
+ }
56
+
57
+ //#endregion
58
+ export { handleAppsHyperscapeRoutes };
@@ -0,0 +1,114 @@
1
+ //#region src/api/apps-routes.ts
2
+ function isNonAppRegistryPlugin(plugin) {
3
+ if (plugin.kind === "app") return false;
4
+ const name = plugin.name.toLowerCase();
5
+ const npmPackage = plugin.npm.package.toLowerCase();
6
+ return !name.includes("/app-") && !npmPackage.includes("/app-");
7
+ }
8
+ function isNonAppSearchResult(plugin) {
9
+ const name = plugin.name.toLowerCase();
10
+ const npmPackage = plugin.npmPackage.toLowerCase();
11
+ return !name.includes("/app-") && !npmPackage.includes("/app-");
12
+ }
13
+ async function handleAppsRoutes(ctx) {
14
+ const { req, res, method, pathname, url, appManager, getPluginManager, parseBoundedLimit, readJsonBody, json, error, runtime } = ctx;
15
+ if (method === "GET" && pathname === "/api/apps") {
16
+ const pluginManager = getPluginManager();
17
+ json(res, await appManager.listAvailable(pluginManager));
18
+ return true;
19
+ }
20
+ if (method === "GET" && pathname === "/api/apps/search") {
21
+ const query = url.searchParams.get("q") ?? "";
22
+ if (!query.trim()) {
23
+ json(res, []);
24
+ return true;
25
+ }
26
+ const limit = parseBoundedLimit(url.searchParams.get("limit"));
27
+ const pluginManager = getPluginManager();
28
+ json(res, await appManager.search(pluginManager, query, limit));
29
+ return true;
30
+ }
31
+ if (method === "GET" && pathname === "/api/apps/installed") {
32
+ const pluginManager = getPluginManager();
33
+ json(res, await appManager.listInstalled(pluginManager));
34
+ return true;
35
+ }
36
+ if (method === "POST" && pathname === "/api/apps/launch") {
37
+ const body = await readJsonBody(req, res);
38
+ if (!body) return true;
39
+ if (!body.name?.trim()) {
40
+ error(res, "name is required");
41
+ return true;
42
+ }
43
+ const pluginManager = getPluginManager();
44
+ json(res, await appManager.launch(pluginManager, body.name.trim(), (_progress) => {}, runtime));
45
+ return true;
46
+ }
47
+ if (method === "POST" && pathname === "/api/apps/stop") {
48
+ const body = await readJsonBody(req, res);
49
+ if (!body) return true;
50
+ if (!body.name?.trim()) {
51
+ error(res, "name is required");
52
+ return true;
53
+ }
54
+ const appName = body.name.trim();
55
+ const pluginManager = getPluginManager();
56
+ json(res, await appManager.stop(pluginManager, appName));
57
+ return true;
58
+ }
59
+ if (method === "GET" && pathname.startsWith("/api/apps/info/")) {
60
+ const appName = decodeURIComponent(pathname.slice(15));
61
+ if (!appName) {
62
+ error(res, "app name is required");
63
+ return true;
64
+ }
65
+ const pluginManager = getPluginManager();
66
+ const info = await appManager.getInfo(pluginManager, appName);
67
+ if (!info) {
68
+ error(res, `App "${appName}" not found in registry`, 404);
69
+ return true;
70
+ }
71
+ json(res, info);
72
+ return true;
73
+ }
74
+ if (method === "GET" && pathname === "/api/apps/plugins") {
75
+ try {
76
+ const registry = await getPluginManager().refreshRegistry();
77
+ json(res, Array.from(registry.values()).filter(isNonAppRegistryPlugin));
78
+ } catch (err) {
79
+ error(res, `Failed to list plugins: ${err instanceof Error ? err.message : String(err)}`, 502);
80
+ }
81
+ return true;
82
+ }
83
+ if (method === "GET" && pathname === "/api/apps/plugins/search") {
84
+ const query = url.searchParams.get("q") ?? "";
85
+ if (!query.trim()) {
86
+ json(res, []);
87
+ return true;
88
+ }
89
+ try {
90
+ const limit = parseBoundedLimit(url.searchParams.get("limit"));
91
+ json(res, (await getPluginManager().searchRegistry(query, limit)).filter(isNonAppSearchResult));
92
+ } catch (err) {
93
+ error(res, `Plugin search failed: ${err instanceof Error ? err.message : String(err)}`, 502);
94
+ }
95
+ return true;
96
+ }
97
+ if (method === "POST" && pathname === "/api/apps/refresh") {
98
+ try {
99
+ const registry = await getPluginManager().refreshRegistry();
100
+ const count = Array.from(registry.values()).filter(isNonAppRegistryPlugin).length;
101
+ json(res, {
102
+ ok: true,
103
+ count
104
+ });
105
+ } catch (err) {
106
+ error(res, `Refresh failed: ${err instanceof Error ? err.message : String(err)}`, 502);
107
+ }
108
+ return true;
109
+ }
110
+ return false;
111
+ }
112
+
113
+ //#endregion
114
+ export { handleAppsRoutes };
package/dist/ascii.js ADDED
@@ -0,0 +1,20 @@
1
+ //#region src/ascii.ts
2
+ const ascii = `
3
+ miladym iladym
4
+ iladymil ady
5
+ mil ad
6
+ ymi ladymila
7
+ dym ila dymila
8
+ dy miladymil ady milady
9
+ miladymilad ymila dymilady
10
+ mi ladymila dymiladymil
11
+ adymiladymiladymi l adymila d
12
+ ym iladymiladymil ad ymilad y
13
+ m il adymiladym i l ad y
14
+ mi ladymila dy mi
15
+ la dy mil
16
+ ad ym
17
+ iladym`;
18
+
19
+ //#endregion
20
+ export { ascii };
@@ -0,0 +1,44 @@
1
+ import { loginAnthropic, refreshAnthropicToken } from "@mariozechner/pi-ai";
2
+
3
+ //#region src/auth/anthropic.ts
4
+ /**
5
+ * Anthropic OAuth flow (Claude Pro/Max subscription)
6
+ *
7
+ * Wraps @mariozechner/pi-ai's loginAnthropic for server-side use.
8
+ * The pi-ai callback API is adapted to a start/exchange pattern
9
+ * for HTTP route handlers.
10
+ */
11
+ /**
12
+ * Start the Anthropic OAuth flow.
13
+ * Returns an auth URL and a way to submit the code + get credentials.
14
+ */
15
+ async function startAnthropicLogin() {
16
+ let authUrl = "";
17
+ let resolveCode = null;
18
+ let resolveUrlReady = null;
19
+ const codePromise = new Promise((resolve) => {
20
+ resolveCode = resolve;
21
+ });
22
+ const urlReady = new Promise((resolve) => {
23
+ resolveUrlReady = resolve;
24
+ });
25
+ const credentials = loginAnthropic((url) => {
26
+ authUrl = url;
27
+ resolveUrlReady?.();
28
+ }, () => codePromise);
29
+ await urlReady;
30
+ return {
31
+ authUrl,
32
+ submitCode: (code) => resolveCode?.(code),
33
+ credentials
34
+ };
35
+ }
36
+ /**
37
+ * Refresh an expired Anthropic token.
38
+ */
39
+ async function refreshAnthropicToken$1(refreshToken) {
40
+ return refreshAnthropicToken(refreshToken);
41
+ }
42
+
43
+ //#endregion
44
+ export { refreshAnthropicToken$1 as refreshAnthropicToken, startAnthropicLogin };
@@ -0,0 +1,41 @@
1
+ import { installClaudeCodeStealthFetchInterceptor } from "./claude-code-stealth.js";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ //#region src/auth/apply-stealth.ts
7
+ /**
8
+ * Walk up from `startDir` until we find a directory containing package.json
9
+ * with name "milaidy". Returns the directory path, or falls back to `startDir`.
10
+ */
11
+ /** @internal Exported for testing only. */
12
+ function findProjectRoot(startDir) {
13
+ let dir = startDir;
14
+ const { root } = path.parse(dir);
15
+ while (dir !== root) {
16
+ const pkgPath = path.join(dir, "package.json");
17
+ try {
18
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
19
+ if (typeof pkg.name === "string" && pkg.name.toLowerCase() === "milaidy") return dir;
20
+ } catch {}
21
+ dir = path.dirname(dir);
22
+ }
23
+ return startDir;
24
+ }
25
+ function applyClaudeCodeStealth() {
26
+ if (!process.env.ANTHROPIC_API_KEY?.startsWith("sk-ant-oat")) return;
27
+ installClaudeCodeStealthFetchInterceptor();
28
+ }
29
+ const OPENAI_STEALTH_GUARD = Symbol.for("milady.openaiCodexStealthInstalled");
30
+ async function applyOpenAICodexStealth() {
31
+ if (globalThis[OPENAI_STEALTH_GUARD]) return;
32
+ const apiKey = process.env.OPENAI_API_KEY;
33
+ if (!apiKey) return;
34
+ if (apiKey.startsWith("sk-")) return;
35
+ const projectRoot = findProjectRoot(path.dirname(fileURLToPath(import.meta.url)));
36
+ await import(path.join(projectRoot, "openai-codex-stealth.mjs"));
37
+ globalThis[OPENAI_STEALTH_GUARD] = true;
38
+ }
39
+
40
+ //#endregion
41
+ export { applyClaudeCodeStealth, applyOpenAICodexStealth };
@@ -0,0 +1,78 @@
1
+ //#region src/auth/claude-code-stealth.ts
2
+ const STEALTH_GUARD = Symbol.for("milady.claudeCodeStealthInstalled");
3
+ const CLAUDE_CODE_VERSION = "2.1.2";
4
+ const CLAUDE_CODE_SYSTEM_PREFIX = "You are Claude Code, Anthropic's official CLI for Claude.";
5
+ const ANTHROPIC_BETA = "claude-code-20250219,oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14,interleaved-thinking-2025-05-14";
6
+ function isSetupToken(value) {
7
+ return typeof value === "string" && value.startsWith("sk-ant-oat");
8
+ }
9
+ function getUrl(input) {
10
+ try {
11
+ if (typeof input === "string") return new URL(input);
12
+ if (input instanceof URL) return input;
13
+ return new URL(input.url);
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ function addSystemPrefix(body) {
19
+ if (!body || typeof body !== "object") return body;
20
+ const next = body;
21
+ const prefix = {
22
+ type: "text",
23
+ text: CLAUDE_CODE_SYSTEM_PREFIX
24
+ };
25
+ if (Array.isArray(next.system)) {
26
+ if (!next.system.some((block) => block?.text?.startsWith("You are Claude Code"))) next.system.unshift(prefix);
27
+ } else if (typeof next.system === "string") next.system = [prefix, {
28
+ type: "text",
29
+ text: next.system
30
+ }];
31
+ else next.system = [prefix];
32
+ return next;
33
+ }
34
+ function installClaudeCodeStealthFetchInterceptor() {
35
+ if (globalThis[STEALTH_GUARD]) return;
36
+ const originalFetch = globalThis.fetch.bind(globalThis);
37
+ const stealthFetch = async function stealthFetch(input, init) {
38
+ const url = getUrl(input);
39
+ if (!url || url.hostname !== "api.anthropic.com") return originalFetch(input, init);
40
+ const request = input instanceof Request ? input : null;
41
+ const headers = new Headers(init?.headers ?? request?.headers ?? void 0);
42
+ const apiKey = headers.get("x-api-key");
43
+ const authHeader = headers.get("authorization");
44
+ const bearerToken = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
45
+ const setupToken = isSetupToken(apiKey) ? apiKey : isSetupToken(bearerToken) ? bearerToken : null;
46
+ if (!setupToken) return originalFetch(input, init);
47
+ headers.delete("x-api-key");
48
+ headers.set("authorization", `Bearer ${setupToken}`);
49
+ headers.set("anthropic-beta", ANTHROPIC_BETA);
50
+ headers.set("user-agent", `claude-cli/${CLAUDE_CODE_VERSION} (external, cli)`);
51
+ headers.set("x-app", "cli");
52
+ let body = init?.body ?? request?.body;
53
+ if (typeof body === "string") try {
54
+ const updated = addSystemPrefix(JSON.parse(body));
55
+ body = JSON.stringify(updated);
56
+ console.log(`[stealth] Patched Anthropic request for ${String(updated.model ?? "unknown-model")}`);
57
+ } catch {
58
+ console.log("[stealth] Anthropic request body was not JSON; skipping system prefix");
59
+ }
60
+ const nextInit = {
61
+ ...init,
62
+ headers,
63
+ body: init ? body : void 0
64
+ };
65
+ if (request && !init) return originalFetch(new Request(request, {
66
+ headers,
67
+ body: typeof body === "string" ? body : void 0
68
+ }));
69
+ return originalFetch(input, nextInit);
70
+ };
71
+ if ("preconnect" in globalThis.fetch) stealthFetch.preconnect = globalThis.fetch.preconnect;
72
+ globalThis.fetch = stealthFetch;
73
+ globalThis[STEALTH_GUARD] = true;
74
+ console.log("[stealth] Claude Code setup token runtime support enabled");
75
+ }
76
+
77
+ //#endregion
78
+ export { installClaudeCodeStealthFetchInterceptor };