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,172 @@
1
+ import { logger } from "@elizaos/core";
2
+
3
+ //#region src/api/subscription-routes.ts
4
+ async function handleSubscriptionRoutes(ctx) {
5
+ const { req, res, method, pathname, state, readJsonBody, json, error } = ctx;
6
+ if (!pathname.startsWith("/api/subscription/")) return false;
7
+ if (method === "GET" && pathname === "/api/subscription/status") {
8
+ try {
9
+ const { getSubscriptionStatus } = await import("./auth/index.js");
10
+ json(res, { providers: getSubscriptionStatus() });
11
+ } catch (err) {
12
+ logger.error(`[api] Failed to get subscription status: ${err instanceof Error ? err.stack : err}`);
13
+ error(res, "Failed to get subscription status", 500);
14
+ }
15
+ return true;
16
+ }
17
+ if (method === "POST" && pathname === "/api/subscription/anthropic/start") {
18
+ try {
19
+ const { startAnthropicLogin } = await import("./auth/index.js");
20
+ const flow = await startAnthropicLogin();
21
+ state._anthropicFlow = flow;
22
+ json(res, { authUrl: flow.authUrl });
23
+ } catch (err) {
24
+ logger.error(`[api] Failed to start Anthropic login: ${err instanceof Error ? err.stack : err}`);
25
+ error(res, "Failed to start Anthropic login", 500);
26
+ }
27
+ return true;
28
+ }
29
+ if (method === "POST" && pathname === "/api/subscription/anthropic/exchange") {
30
+ const body = await readJsonBody(req, res);
31
+ if (!body) return true;
32
+ if (!body.code) {
33
+ error(res, "Missing code", 400);
34
+ return true;
35
+ }
36
+ try {
37
+ const { saveCredentials, applySubscriptionCredentials } = await import("./auth/index.js");
38
+ const flow = state._anthropicFlow;
39
+ if (!flow) {
40
+ error(res, "No active flow — call /start first", 400);
41
+ return true;
42
+ }
43
+ flow.submitCode(body.code);
44
+ const credentials = await flow.credentials;
45
+ saveCredentials("anthropic-subscription", credentials);
46
+ await applySubscriptionCredentials(state.config);
47
+ delete state._anthropicFlow;
48
+ json(res, {
49
+ success: true,
50
+ expiresAt: credentials.expires
51
+ });
52
+ } catch (err) {
53
+ logger.error(`[api] Anthropic exchange failed: ${err instanceof Error ? err.stack : err}`);
54
+ error(res, "Anthropic exchange failed", 500);
55
+ }
56
+ return true;
57
+ }
58
+ if (method === "POST" && pathname === "/api/subscription/anthropic/setup-token") {
59
+ const body = await readJsonBody(req, res);
60
+ if (!body) return true;
61
+ if (!body.token || !body.token.startsWith("sk-ant-")) {
62
+ error(res, "Invalid token format — expected sk-ant-oat01-...", 400);
63
+ return true;
64
+ }
65
+ try {
66
+ process.env.ANTHROPIC_API_KEY = body.token.trim();
67
+ if (!state.config.env) state.config.env = {};
68
+ state.config.env.ANTHROPIC_API_KEY = body.token.trim();
69
+ ctx.saveConfig(state.config);
70
+ json(res, { success: true });
71
+ } catch (err) {
72
+ logger.error(`[api] Failed to save setup token: ${err instanceof Error ? err.stack : err}`);
73
+ error(res, "Failed to save setup token", 500);
74
+ }
75
+ return true;
76
+ }
77
+ if (method === "POST" && pathname === "/api/subscription/openai/start") {
78
+ try {
79
+ const { startCodexLogin } = await import("./auth/index.js");
80
+ if (state._codexFlow) try {
81
+ state._codexFlow.close();
82
+ } catch (err) {
83
+ logger.debug(`[api] OAuth flow cleanup failed: ${err instanceof Error ? err.message : err}`);
84
+ }
85
+ clearTimeout(state._codexFlowTimer);
86
+ const flow = await startCodexLogin();
87
+ state._codexFlow = flow;
88
+ state._codexFlowTimer = setTimeout(() => {
89
+ try {
90
+ flow.close();
91
+ } catch (err) {
92
+ logger.debug(`[api] OAuth flow cleanup failed: ${err instanceof Error ? err.message : err}`);
93
+ }
94
+ delete state._codexFlow;
95
+ delete state._codexFlowTimer;
96
+ }, 600 * 1e3);
97
+ json(res, {
98
+ authUrl: flow.authUrl,
99
+ state: flow.state,
100
+ instructions: "Open the URL in your browser. After login, if auto-redirect doesn't work, paste the full redirect URL."
101
+ });
102
+ } catch (err) {
103
+ logger.error(`[api] Failed to start OpenAI login: ${err instanceof Error ? err.stack : err}`);
104
+ error(res, "Failed to start OpenAI login", 500);
105
+ }
106
+ return true;
107
+ }
108
+ if (method === "POST" && pathname === "/api/subscription/openai/exchange") {
109
+ const body = await readJsonBody(req, res);
110
+ if (!body) return true;
111
+ try {
112
+ const { saveCredentials, applySubscriptionCredentials } = await import("./auth/index.js");
113
+ const flow = state._codexFlow;
114
+ if (!flow) {
115
+ error(res, "No active flow — call /start first", 400);
116
+ return true;
117
+ }
118
+ if (body.code) flow.submitCode(body.code);
119
+ else if (!body.waitForCallback) {
120
+ error(res, "Provide either code or set waitForCallback: true", 400);
121
+ return true;
122
+ }
123
+ let credentials;
124
+ try {
125
+ credentials = await flow.credentials;
126
+ } catch (err) {
127
+ try {
128
+ flow.close();
129
+ } catch (closeErr) {
130
+ logger.debug(`[api] OAuth flow cleanup failed: ${closeErr instanceof Error ? closeErr.message : closeErr}`);
131
+ }
132
+ delete state._codexFlow;
133
+ clearTimeout(state._codexFlowTimer);
134
+ delete state._codexFlowTimer;
135
+ logger.error(`[api] OpenAI exchange failed: ${err instanceof Error ? err.stack : err}`);
136
+ error(res, "OpenAI exchange failed", 500);
137
+ return true;
138
+ }
139
+ saveCredentials("openai-codex", credentials);
140
+ await applySubscriptionCredentials(state.config);
141
+ flow.close();
142
+ delete state._codexFlow;
143
+ clearTimeout(state._codexFlowTimer);
144
+ delete state._codexFlowTimer;
145
+ json(res, {
146
+ success: true,
147
+ expiresAt: credentials.expires
148
+ });
149
+ } catch (err) {
150
+ logger.error(`[api] OpenAI exchange failed: ${err instanceof Error ? err.stack : err}`);
151
+ error(res, "OpenAI exchange failed", 500);
152
+ }
153
+ return true;
154
+ }
155
+ if (method === "DELETE" && pathname.startsWith("/api/subscription/")) {
156
+ const provider = pathname.split("/").pop();
157
+ if (provider === "anthropic-subscription" || provider === "openai-codex") try {
158
+ const { deleteCredentials } = await import("./auth/index.js");
159
+ deleteCredentials(provider);
160
+ json(res, { success: true });
161
+ } catch (err) {
162
+ logger.error(`[api] Failed to delete credentials: ${err instanceof Error ? err.stack : err}`);
163
+ error(res, "Failed to delete credentials", 500);
164
+ }
165
+ else error(res, `Unknown provider: ${provider}`, 400);
166
+ return true;
167
+ }
168
+ return false;
169
+ }
170
+
171
+ //#endregion
172
+ export { handleSubscriptionRoutes };
@@ -0,0 +1,19 @@
1
+ //#region src/terminal/links.ts
2
+ const DOCS_ROOT = "https://docs.milady.ai";
3
+ function formatTerminalLink(label, url, opts) {
4
+ const safeLabel = label.replaceAll("\x1B", "");
5
+ const safeUrl = url.replaceAll("\x1B", "");
6
+ if (!(opts?.force ?? Boolean(process.stdout.isTTY))) return opts?.fallback ?? `${safeLabel} (${safeUrl})`;
7
+ return `\u001b]8;;${safeUrl}\u0007${safeLabel}\u001b]8;;\u0007`;
8
+ }
9
+ function formatDocsLink(path, label, opts) {
10
+ const trimmed = path.trim();
11
+ const url = trimmed.startsWith("http") ? trimmed : `${DOCS_ROOT}${trimmed.startsWith("/") ? trimmed : `/${trimmed}`}`;
12
+ return formatTerminalLink(label ?? url, url, {
13
+ fallback: opts?.fallback ?? url,
14
+ force: opts?.force
15
+ });
16
+ }
17
+
18
+ //#endregion
19
+ export { formatDocsLink };
@@ -0,0 +1,14 @@
1
+ //#region src/terminal/palette.ts
2
+ const CLI_PALETTE = {
3
+ accent: "#FF5A2D",
4
+ accentBright: "#FF7A3D",
5
+ accentDim: "#D14A22",
6
+ info: "#FF8A5B",
7
+ success: "#2FBF71",
8
+ warn: "#FFB020",
9
+ error: "#E23D2D",
10
+ muted: "#8B7F77"
11
+ };
12
+
13
+ //#endregion
14
+ export { CLI_PALETTE };
@@ -0,0 +1,25 @@
1
+ import { CLI_PALETTE } from "./palette.js";
2
+ import chalk, { Chalk } from "chalk";
3
+
4
+ //#region src/terminal/theme.ts
5
+ const hasForceColor = typeof process.env.FORCE_COLOR === "string" && process.env.FORCE_COLOR.trim().length > 0 && process.env.FORCE_COLOR.trim() !== "0";
6
+ const baseChalk = process.env.NO_COLOR !== void 0 && !hasForceColor ? new Chalk({ level: 0 }) : chalk;
7
+ const hex = (value) => baseChalk.hex(value);
8
+ const theme = {
9
+ accent: hex(CLI_PALETTE.accent),
10
+ accentBright: hex(CLI_PALETTE.accentBright),
11
+ accentDim: hex(CLI_PALETTE.accentDim),
12
+ info: hex(CLI_PALETTE.info),
13
+ success: hex(CLI_PALETTE.success),
14
+ warn: hex(CLI_PALETTE.warn),
15
+ error: hex(CLI_PALETTE.error),
16
+ muted: hex(CLI_PALETTE.muted),
17
+ heading: baseChalk.bold.hex(CLI_PALETTE.accent),
18
+ command: hex(CLI_PALETTE.accentBright),
19
+ option: hex(CLI_PALETTE.warn)
20
+ };
21
+ const cyberGreen = hex("#00FF41");
22
+ const isRich = () => Boolean(baseChalk.level > 0);
23
+
24
+ //#endregion
25
+ export { cyberGreen, isRich, theme };
@@ -0,0 +1,24 @@
1
+ import { parseClampedInteger } from "./utils/number-parsing.js";
2
+
3
+ //#region src/api/terminal-run-limits.ts
4
+ const TERMINAL_RUN_MAX_CONCURRENT_DEFAULT = 2;
5
+ const TERMINAL_RUN_MAX_CONCURRENT_CAP = 16;
6
+ const TERMINAL_RUN_MAX_DURATION_MS_DEFAULT = 300 * 1e3;
7
+ const TERMINAL_RUN_MAX_DURATION_MS_CAP = 3600 * 1e3;
8
+ function resolveTerminalRunLimits() {
9
+ return {
10
+ maxConcurrent: parseClampedInteger(process.env.MILADY_TERMINAL_MAX_CONCURRENT ?? process.env.MILAIDY_TERMINAL_MAX_CONCURRENT, {
11
+ fallback: TERMINAL_RUN_MAX_CONCURRENT_DEFAULT,
12
+ min: 1,
13
+ max: TERMINAL_RUN_MAX_CONCURRENT_CAP
14
+ }),
15
+ maxDurationMs: parseClampedInteger(process.env.MILADY_TERMINAL_MAX_DURATION_MS ?? process.env.MILAIDY_TERMINAL_MAX_DURATION_MS, {
16
+ fallback: TERMINAL_RUN_MAX_DURATION_MS_DEFAULT,
17
+ min: 1e3,
18
+ max: TERMINAL_RUN_MAX_DURATION_MS_CAP
19
+ })
20
+ };
21
+ }
22
+
23
+ //#endregion
24
+ export { resolveTerminalRunLimits };
@@ -0,0 +1,158 @@
1
+ import { isLoopbackHost } from "./security/network-policy.js";
2
+ import { parsePositiveInteger } from "./utils/number-parsing.js";
3
+
4
+ //#region src/api/training-routes.ts
5
+ function resolveOllamaUrlRejection(rawUrl) {
6
+ const trimmed = rawUrl.trim();
7
+ if (!trimmed) return null;
8
+ let parsed;
9
+ try {
10
+ parsed = new URL(trimmed);
11
+ } catch {
12
+ return "ollamaUrl must be a valid URL";
13
+ }
14
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return "ollamaUrl must use http:// or https://";
15
+ if (!isLoopbackHost(parsed.hostname)) return "ollamaUrl must target a loopback host (localhost, 127.0.0.1, or ::1)";
16
+ return null;
17
+ }
18
+ async function handleTrainingRoutes(ctx) {
19
+ const { req, res, method, pathname, runtime, trainingService, json, error, readJsonBody } = ctx;
20
+ if (!pathname.startsWith("/api/training")) return false;
21
+ if (method === "GET" && pathname === "/api/training/status") {
22
+ json(res, {
23
+ ...trainingService.getStatus(),
24
+ runtimeAvailable: runtime !== null
25
+ });
26
+ return true;
27
+ }
28
+ if (method === "GET" && pathname === "/api/training/trajectories") {
29
+ const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
30
+ const limit = parsePositiveInteger(url.searchParams.get("limit"), 100);
31
+ const offset = Math.max(0, Number(url.searchParams.get("offset") ?? "0"));
32
+ json(res, await trainingService.listTrajectories({
33
+ limit,
34
+ offset
35
+ }));
36
+ return true;
37
+ }
38
+ const trajectoryMatch = /^\/api\/training\/trajectories\/([^/]+)$/.exec(pathname);
39
+ if (method === "GET" && trajectoryMatch) {
40
+ const trajectoryId = decodeURIComponent(trajectoryMatch[1]);
41
+ const detail = await trainingService.getTrajectoryById(trajectoryId);
42
+ if (!detail) {
43
+ error(res, "Trajectory not found", 404);
44
+ return true;
45
+ }
46
+ json(res, { trajectory: detail });
47
+ return true;
48
+ }
49
+ if (method === "GET" && pathname === "/api/training/datasets") {
50
+ json(res, { datasets: trainingService.listDatasets() });
51
+ return true;
52
+ }
53
+ if (method === "POST" && pathname === "/api/training/datasets/build") {
54
+ const body = await readJsonBody(req, res);
55
+ if (!body) return true;
56
+ json(res, { dataset: await trainingService.buildDataset({
57
+ limit: body.limit,
58
+ minLlmCallsPerTrajectory: body.minLlmCallsPerTrajectory
59
+ }) }, 201);
60
+ return true;
61
+ }
62
+ if (method === "GET" && pathname === "/api/training/jobs") {
63
+ json(res, { jobs: trainingService.listJobs() });
64
+ return true;
65
+ }
66
+ if (method === "POST" && pathname === "/api/training/jobs") {
67
+ const body = await readJsonBody(req, res);
68
+ if (!body) return true;
69
+ try {
70
+ json(res, { job: await trainingService.startTrainingJob({
71
+ datasetId: body.datasetId,
72
+ maxTrajectories: body.maxTrajectories,
73
+ backend: body.backend,
74
+ model: body.model,
75
+ iterations: body.iterations,
76
+ batchSize: body.batchSize,
77
+ learningRate: body.learningRate
78
+ }) }, 201);
79
+ } catch (err) {
80
+ error(res, err instanceof Error ? err.message : String(err), 400);
81
+ }
82
+ return true;
83
+ }
84
+ const jobMatch = /^\/api\/training\/jobs\/([^/]+)$/.exec(pathname);
85
+ if (method === "GET" && jobMatch) {
86
+ const jobId = decodeURIComponent(jobMatch[1]);
87
+ const job = trainingService.getJob(jobId);
88
+ if (!job) {
89
+ error(res, "Training job not found", 404);
90
+ return true;
91
+ }
92
+ json(res, { job });
93
+ return true;
94
+ }
95
+ const cancelMatch = /^\/api\/training\/jobs\/([^/]+)\/cancel$/.exec(pathname);
96
+ if (method === "POST" && cancelMatch) {
97
+ const jobId = decodeURIComponent(cancelMatch[1]);
98
+ try {
99
+ json(res, { job: await trainingService.cancelJob(jobId) });
100
+ } catch (err) {
101
+ error(res, err instanceof Error ? err.message : String(err), 404);
102
+ }
103
+ return true;
104
+ }
105
+ if (method === "GET" && pathname === "/api/training/models") {
106
+ json(res, { models: trainingService.listModels() });
107
+ return true;
108
+ }
109
+ const importMatch = /^\/api\/training\/models\/([^/]+)\/import-ollama$/.exec(pathname);
110
+ if (method === "POST" && importMatch) {
111
+ const modelId = decodeURIComponent(importMatch[1]);
112
+ const body = await readJsonBody(req, res);
113
+ if (!body) return true;
114
+ if (body.ollamaUrl !== void 0 && typeof body.ollamaUrl !== "string") {
115
+ error(res, "ollamaUrl must be a string", 400);
116
+ return true;
117
+ }
118
+ if (typeof body.ollamaUrl === "string") {
119
+ const ollamaUrlRejection = resolveOllamaUrlRejection(body.ollamaUrl);
120
+ if (ollamaUrlRejection) {
121
+ error(res, ollamaUrlRejection, 400);
122
+ return true;
123
+ }
124
+ }
125
+ try {
126
+ json(res, { model: await trainingService.importModelToOllama(modelId, body) });
127
+ } catch (err) {
128
+ error(res, err instanceof Error ? err.message : String(err), 400);
129
+ }
130
+ return true;
131
+ }
132
+ const activateMatch = /^\/api\/training\/models\/([^/]+)\/activate$/.exec(pathname);
133
+ if (method === "POST" && activateMatch) {
134
+ const modelId = decodeURIComponent(activateMatch[1]);
135
+ const body = await readJsonBody(req, res);
136
+ if (!body) return true;
137
+ try {
138
+ json(res, await trainingService.activateModel(modelId, body.providerModel));
139
+ } catch (err) {
140
+ error(res, err instanceof Error ? err.message : String(err), 400);
141
+ }
142
+ return true;
143
+ }
144
+ const benchmarkMatch = /^\/api\/training\/models\/([^/]+)\/benchmark$/.exec(pathname);
145
+ if (method === "POST" && benchmarkMatch) {
146
+ const modelId = decodeURIComponent(benchmarkMatch[1]);
147
+ try {
148
+ json(res, await trainingService.benchmarkModel(modelId));
149
+ } catch (err) {
150
+ error(res, err instanceof Error ? err.message : String(err), 400);
151
+ }
152
+ return true;
153
+ }
154
+ return false;
155
+ }
156
+
157
+ //#endregion
158
+ export { handleTrainingRoutes };