happy2 0.0.16 → 0.0.17

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 (64) hide show
  1. package/Dockerfile +30 -0
  2. package/README.md +170 -0
  3. package/deploy/config.yaml +56 -0
  4. package/deploy/happy2-server.yaml +140 -0
  5. package/deploy/happy2-web.yaml +87 -0
  6. package/package.json +3 -2
  7. package/packages/happy2-server/README.md +70 -15
  8. package/packages/happy2-server/dist/backend.d.ts +12 -0
  9. package/packages/happy2-server/dist/backend.d.ts.map +1 -0
  10. package/packages/happy2-server/dist/backend.js +48 -0
  11. package/packages/happy2-server/dist/backend.js.map +1 -0
  12. package/packages/happy2-server/dist/cli.js +6 -25
  13. package/packages/happy2-server/dist/cli.js.map +1 -1
  14. package/packages/happy2-server/dist/index.d.ts +2 -0
  15. package/packages/happy2-server/dist/index.d.ts.map +1 -1
  16. package/packages/happy2-server/dist/index.js +2 -0
  17. package/packages/happy2-server/dist/index.js.map +1 -1
  18. package/packages/happy2-server/dist/modules/agents/daemon.d.ts +4 -0
  19. package/packages/happy2-server/dist/modules/agents/daemon.d.ts.map +1 -1
  20. package/packages/happy2-server/dist/modules/agents/daemon.js +40 -0
  21. package/packages/happy2-server/dist/modules/agents/daemon.js.map +1 -1
  22. package/packages/happy2-server/dist/modules/config/defaults.d.ts +4 -4
  23. package/packages/happy2-server/dist/modules/config/defaults.d.ts.map +1 -1
  24. package/packages/happy2-server/dist/modules/config/defaults.js +8 -8
  25. package/packages/happy2-server/dist/modules/config/defaults.js.map +1 -1
  26. package/packages/happy2-server/dist/modules/config/loader.d.ts +2 -2
  27. package/packages/happy2-server/dist/modules/config/loader.d.ts.map +1 -1
  28. package/packages/happy2-server/dist/modules/config/loader.js +83 -73
  29. package/packages/happy2-server/dist/modules/config/loader.js.map +1 -1
  30. package/packages/happy2-server/dist/modules/config/loader.test.js +35 -0
  31. package/packages/happy2-server/dist/modules/config/loader.test.js.map +1 -1
  32. package/packages/happy2-server/dist/modules/config/runtime.d.ts +1 -1
  33. package/packages/happy2-server/dist/modules/config/runtime.d.ts.map +1 -1
  34. package/packages/happy2-server/dist/modules/config/runtime.js +17 -4
  35. package/packages/happy2-server/dist/modules/config/runtime.js.map +1 -1
  36. package/packages/happy2-server/dist/modules/config/runtime.test.d.ts +2 -0
  37. package/packages/happy2-server/dist/modules/config/runtime.test.d.ts.map +1 -0
  38. package/packages/happy2-server/dist/modules/config/runtime.test.js +99 -0
  39. package/packages/happy2-server/dist/modules/config/runtime.test.js.map +1 -0
  40. package/packages/happy2-server/dist/runner.js +29 -12
  41. package/packages/happy2-server/dist/runner.js.map +1 -1
  42. package/packages/happy2-server/dist/runnerCommand.d.ts +21 -0
  43. package/packages/happy2-server/dist/runnerCommand.d.ts.map +1 -0
  44. package/packages/happy2-server/dist/runnerCommand.js +97 -0
  45. package/packages/happy2-server/dist/runnerCommand.js.map +1 -0
  46. package/packages/happy2-server/dist/runnerCommand.test.d.ts +2 -0
  47. package/packages/happy2-server/dist/runnerCommand.test.d.ts.map +1 -0
  48. package/packages/happy2-server/dist/runnerCommand.test.js +59 -0
  49. package/packages/happy2-server/dist/runnerCommand.test.js.map +1 -0
  50. package/packages/happy2-server/dist/standalone.d.ts +2 -5
  51. package/packages/happy2-server/dist/standalone.d.ts.map +1 -1
  52. package/packages/happy2-server/dist/standalone.js +14 -65
  53. package/packages/happy2-server/dist/standalone.js.map +1 -1
  54. package/packages/happy2-server/dist/web/assets/index-B51jYSrY.css +2 -0
  55. package/packages/happy2-server/dist/web/assets/index-szUjvBO1.js +39 -0
  56. package/packages/happy2-server/dist/web/index.html +2 -2
  57. package/packages/happy2-server/dist/web.d.ts +12 -0
  58. package/packages/happy2-server/dist/web.d.ts.map +1 -0
  59. package/packages/happy2-server/dist/web.js +89 -0
  60. package/packages/happy2-server/dist/web.js.map +1 -0
  61. package/packages/happy2-server/happy2.example.toml +3 -5
  62. package/packages/happy2-server/Dockerfile +0 -18
  63. package/packages/happy2-server/dist/web/assets/index-BxtJtZpt.js +0 -39
  64. package/packages/happy2-server/dist/web/assets/index-m8C1tSYV.css +0 -2
@@ -13,8 +13,8 @@
13
13
  background: #131217;
14
14
  }
15
15
  </style>
16
- <script type="module" crossorigin src="/assets/index-BxtJtZpt.js"></script>
17
- <link rel="stylesheet" crossorigin href="/assets/index-m8C1tSYV.css">
16
+ <script type="module" crossorigin src="/assets/index-szUjvBO1.js"></script>
17
+ <link rel="stylesheet" crossorigin href="/assets/index-B51jYSrY.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="root"></div>
@@ -0,0 +1,12 @@
1
+ import type { RunningHappy2 } from "./backend.js";
2
+ export interface WebOptions {
3
+ backendUrl: string;
4
+ host?: string;
5
+ logger?: boolean;
6
+ port?: number;
7
+ trustedProxyHops?: number;
8
+ webRoot?: string;
9
+ }
10
+ /** Serves the Happy (2) SPA and proxies its versioned API to a separate backend origin. */
11
+ export declare function startWebHappy2(options: WebOptions): Promise<RunningHappy2>;
12
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../sources/web.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,UAAU;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2FAA2F;AAC3F,wBAAsB,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAgEhF"}
@@ -0,0 +1,89 @@
1
+ import { access } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import Fastify from "fastify";
4
+ import proxy from "@fastify/http-proxy";
5
+ import staticFiles from "@fastify/static";
6
+ /** Serves the Happy (2) SPA and proxies its versioned API to a separate backend origin. */
7
+ export async function startWebHappy2(options) {
8
+ const backendUrl = normalizedBackendUrl(options.backendUrl);
9
+ const webRoot = options.webRoot ?? join(import.meta.dirname, "web");
10
+ await access(join(webRoot, "index.html"));
11
+ const gateway = Fastify({
12
+ logger: options.logger ?? true,
13
+ trustProxy: options.trustedProxyHops ?? 0,
14
+ });
15
+ try {
16
+ await gateway.register(proxy, {
17
+ upstream: backendUrl,
18
+ prefix: "/v0",
19
+ rewritePrefix: "/v0",
20
+ httpMethods: ["GET", "POST"],
21
+ replyOptions: {
22
+ rewriteRequestHeaders: (request, headers) => {
23
+ const forwarded = { ...headers };
24
+ delete forwarded["x-forwarded-host"];
25
+ return {
26
+ ...forwarded,
27
+ "x-forwarded-for": request.ip,
28
+ "x-forwarded-proto": request.protocol,
29
+ ...(request.host ? { "x-forwarded-host": request.host } : {}),
30
+ };
31
+ },
32
+ },
33
+ });
34
+ await gateway.register(staticFiles, {
35
+ root: webRoot,
36
+ wildcard: false,
37
+ index: "index.html",
38
+ });
39
+ gateway.setNotFoundHandler((request, reply) => {
40
+ if ((request.method === "GET" || request.method === "HEAD") &&
41
+ !request.url.startsWith("/v0") &&
42
+ request.headers.accept?.includes("text/html")) {
43
+ return reply.type("text/html; charset=utf-8").sendFile("index.html");
44
+ }
45
+ return reply.code(404).send({ error: "not_found" });
46
+ });
47
+ const url = await gateway.listen({
48
+ host: options.host ?? "127.0.0.1",
49
+ port: options.port ?? 3000,
50
+ });
51
+ let closed = false;
52
+ const close = async () => {
53
+ if (closed)
54
+ return;
55
+ closed = true;
56
+ await gateway.close();
57
+ };
58
+ return {
59
+ url,
60
+ close,
61
+ async [Symbol.asyncDispose]() {
62
+ await close();
63
+ },
64
+ };
65
+ }
66
+ catch (error) {
67
+ await gateway.close().catch(() => undefined);
68
+ throw error;
69
+ }
70
+ }
71
+ function normalizedBackendUrl(value) {
72
+ let url;
73
+ try {
74
+ url = new URL(value);
75
+ }
76
+ catch {
77
+ throw new Error("Happy (2) web backend URL must be an absolute HTTP(S) URL.");
78
+ }
79
+ if ((url.protocol !== "http:" && url.protocol !== "https:") ||
80
+ url.username ||
81
+ url.password ||
82
+ url.pathname !== "/" ||
83
+ url.search ||
84
+ url.hash) {
85
+ throw new Error("Happy (2) web backend URL must be an HTTP(S) origin without credentials, path, query, or fragment.");
86
+ }
87
+ return url.origin;
88
+ }
89
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../sources/web.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,9 @@ public_url = "http://127.0.0.1:3000"
10
10
  trusted_proxy_hops = 0
11
11
 
12
12
  [plugins]
13
+ # Immutable installed package snapshots live here. Keep this persistent so a
14
+ # bundled plugin continues to run until an explicit upgrade replaces it.
15
+ directory = "plugins"
13
16
  # Dedicated capability-only listener reached by plugin containers through the
14
17
  # happy2.host.internal container-host mapping.
15
18
  # The cross-platform host-gateway path requires a non-loopback bind. Firewall
@@ -56,11 +59,6 @@ malware_scan_timeout_seconds = 120
56
59
  # "deny" quarantines files when the scanner is unavailable; "allow" fails open.
57
60
  malware_scan_failure_mode = "deny"
58
61
 
59
- [plugins]
60
- # Immutable installed package snapshots live here. Keep this persistent so a
61
- # bundled plugin continues to run until an explicit upgrade replaces it.
62
- directory = "plugins"
63
-
64
62
  [security]
65
63
  integration_secret_env = "HAPPY2_INTEGRATION_SECRET"
66
64
 
@@ -1,18 +0,0 @@
1
- # Build from the repository root:
2
- # docker build -f packages/happy2-server/Dockerfile -t slopus/happy2 .
3
- FROM node:22-bookworm-slim AS build
4
- WORKDIR /workspace
5
- RUN corepack enable
6
- COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
7
- COPY packages/happy2-server/package.json packages/happy2-server/package.json
8
- RUN pnpm install --frozen-lockfile
9
- COPY packages/happy2-server packages/happy2-server
10
- RUN pnpm --filter happy2-server build:server \
11
- && pnpm --filter happy2-server --prod deploy /app
12
-
13
- FROM node:22-bookworm-slim
14
- ENV NODE_ENV=production
15
- WORKDIR /app
16
- COPY --from=build /app ./
17
- EXPOSE 3000
18
- ENTRYPOINT ["node", "dist/cli.js"]