@aihu/app 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -21,7 +21,7 @@ npm install @aihu/app
21
21
  bun add @aihu/app
22
22
  ```
23
23
 
24
- <sub><i>Auto-generated against `@aihu/app@0.1.1`.</i></sub>
24
+ <sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
25
25
 
26
26
  <!-- END_AUTOGEN: install -->
27
27
 
@@ -32,13 +32,13 @@ bun add @aihu/app
32
32
 
33
33
  | | |
34
34
  |---|---|
35
- | **Version** | `0.1.1` |
35
+ | **Version** | `0.1.3` |
36
36
  | **Tier** | B — Meta-framework — top-level integration of runtime, router, adapter |
37
- | **Bundle size** | 764 B (gz) — limit 800 B |
37
+ | **Bundle size** | 800 B (gz) — limit 800 B |
38
38
  | **Published files** | 3 entries |
39
39
  | **License** | MIT |
40
40
 
41
- <sub><i>Auto-generated against `@aihu/app@0.1.1`.</i></sub>
41
+ <sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
42
42
 
43
43
  <!-- END_AUTOGEN: stats -->
44
44
 
@@ -52,7 +52,7 @@ bun add @aihu/app
52
52
  | `.` | `./dist/index.js` | `—` |
53
53
  | `./client` | `./dist/client.js` | `—` |
54
54
 
55
- <sub><i>Auto-generated against `@aihu/app@0.1.1`.</i></sub>
55
+ <sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
56
56
 
57
57
  <!-- END_AUTOGEN: exports -->
58
58
 
@@ -69,7 +69,7 @@ bun add @aihu/app
69
69
  - `@aihu/signals` — `workspace:*`
70
70
  - `vite` — `>=5.0.0`
71
71
 
72
- <sub><i>Auto-generated against `@aihu/app@0.1.1`.</i></sub>
72
+ <sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
73
73
 
74
74
  <!-- END_AUTOGEN: deps -->
75
75
 
@@ -83,7 +83,7 @@ bun add @aihu/app
83
83
  - [@aihu/adapter-cloudflare](../adapter-cloudflare)
84
84
  - [Aihu framework root](../../README.md)
85
85
 
86
- <sub><i>Auto-generated against `@aihu/app@0.1.1`.</i></sub>
86
+ <sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
87
87
 
88
88
  <!-- END_AUTOGEN: see-also -->
89
89
 
@@ -94,6 +94,6 @@ bun add @aihu/app
94
94
 
95
95
  MIT — see [LICENSE](../../LICENSE).
96
96
 
97
- <sub><i>Auto-generated against `@aihu/app@0.1.1`.</i></sub>
97
+ <sub><i>Auto-generated against `@aihu/app@0.1.3`.</i></sub>
98
98
 
99
99
  <!-- END_AUTOGEN: license -->
package/dist/client.d.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  //#region src/client.d.ts
2
+ /**
3
+ * Rendering mode passed from the server config into the client bootstrap.
4
+ * Inlined here to avoid importing @aihu/server into the client bundle.
5
+ * Must stay in sync with RenderingMode in @aihu/server.
6
+ */
7
+ type AppRenderingMode = 'ssr' | 'spa' | 'hybrid';
2
8
  /** Inline runtime configuration accepted by createApp(). All fields optional. */
3
9
  interface AppConfig {
4
10
  /** Id of the outlet element in index.html. Default: 'outlet' */
@@ -12,6 +18,20 @@ interface AppConfig {
12
18
  * createApp({ provide: { supabase, checkAuth } })
13
19
  */
14
20
  provide?: Record<string, unknown>;
21
+ /**
22
+ * Rendering mode from the server config. Controls whether the client
23
+ * wires the hydration function into the runtime.
24
+ *
25
+ * - 'ssr' | 'hybrid' (default): wires _setHydrate so the client can
26
+ * take over from server-rendered HTML without re-creating DOM.
27
+ * - 'spa': skips _setHydrate — no SSR HTML to hydrate, mount-only.
28
+ *
29
+ * Pass `defineAihuConfig(…).rendering?.mode` from your server config.
30
+ * Default: 'ssr' (hydration wired).
31
+ */
32
+ rendering?: {
33
+ mode?: AppRenderingMode;
34
+ };
15
35
  }
16
36
  /**
17
37
  * Bootstrap the aihu SPA.
@@ -28,5 +48,5 @@ interface AppConfig {
28
48
  */
29
49
  declare function createApp(config?: AppConfig): void;
30
50
  //#endregion
31
- export { AppConfig, createApp };
51
+ export { AppConfig, AppRenderingMode, createApp };
32
52
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"mappings":";;UAQiB,SAAA;EAAS;EAExB,QAAA;EASgB;;;;;;AAgBlB;;EAhBE,OAAA,GAAU,MAAA;AAAA;;;;;;;;;;;;;;iBAgBI,SAAA,CAAU,MAAA,GAAS,SAAA"}
1
+ {"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"mappings":";;AAYA;;;;KAAY,gBAAA;AAGZ;AAAA,UAAiB,SAAA;;EAEf,QAAA;EAAA;;;;;;;;EASA,OAAA,GAAU,MAAA;EA4Ba;;;;;;;;;;;EAhBvB,SAAA;IAAc,IAAA,GAAO,gBAAA;EAAA;AAAA;;;;;;;;;;;;;;iBAgBP,SAAA,CAAU,MAAA,GAAS,SAAA"}
package/dist/client.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"virtual:aihu-routes";import{mount as t}from"@aihu/arbor";import{createRouter as n}from"@aihu/router";import{_setMount as r,_setSignal as i}from"@aihu/runtime";import{signal as a}from"@aihu/signals";function o(o){o?.provide&&Object.assign(globalThis,o.provide),r(t),i(a);let s=o?.outletId??`outlet`,c=document.getElementById(s);if(!c)throw Error(`@aihu/app: no element with id="${s}" found. Add <div id="${s}"></div> to your index.html`);let l=c,u=n(e);async function d(t){if(!t){let t=e.find(e=>e.pattern===`*`||e.name===`not-found`);if(t){await t.module();let e=t.name;if(e?.includes(`-`)){l.replaceChildren(document.createElement(e));return}}let n=document.createElement(`p`);n.style.cssText=`font-family:system-ui;padding:2rem;color:#888`,n.textContent=`404 — page not found`,l.replaceChildren(n);return}await t.route.module();let n=t.route.name;if(!n?.includes(`-`))return;let r=document.createElement(n);if(t.params)for(let[e,n]of Object.entries(t.params))r.setAttribute(e,String(n));l.replaceChildren(r)}d(u.match(location.pathname)),document.addEventListener(`click`,e=>{let t=e.target.closest(`a`);if(!t)return;let n=t.getAttribute(`href`);!n||n.startsWith(`http`)||n.startsWith(`//`)||n.startsWith(`mailto:`)||(e.preventDefault(),history.pushState({},``,n),d(u.match(location.pathname)))}),window.addEventListener(`popstate`,()=>{d(u.match(location.pathname))})}export{o as createApp};
1
+ import e from"virtual:aihu-routes";import{hydrate as t,mount as n}from"@aihu/arbor";import{createRouter as r}from"@aihu/router";import{_setHydrate as i,_setMount as a,_setSignal as o}from"@aihu/runtime";import{signal as s}from"@aihu/signals";function c(c){c?.provide&&Object.assign(globalThis,c.provide),a(n),o(s),c?.rendering?.mode!==`spa`&&i(t);let l=c?.outletId??`outlet`,u=document.getElementById(l);if(!u)throw Error(`@aihu/app: no element with id="${l}" found. Add <div id="${l}"></div> to your index.html`);let d=u,f=r(e);async function p(t){if(!t){let t=e.find(e=>e.pattern===`*`||e.name===`not-found`);if(t){await t.module();let e=t.name;if(e?.includes(`-`)){d.replaceChildren(document.createElement(e));return}}let n=document.createElement(`p`);n.style.cssText=`font-family:system-ui;padding:2rem;color:#888`,n.textContent=`404 — page not found`,d.replaceChildren(n);return}await t.route.module();let n=t.route.name;if(!n?.includes(`-`))return;let r=document.createElement(n);if(t.params)for(let[e,n]of Object.entries(t.params))r.setAttribute(e,String(n));d.replaceChildren(r)}p(f.match(location.pathname)),document.addEventListener(`click`,e=>{let t=e.target.closest(`a`);if(!t)return;let n=t.getAttribute(`href`);!n||n.startsWith(`http`)||n.startsWith(`//`)||n.startsWith(`mailto:`)||(e.preventDefault(),history.pushState({},``,n),p(f.match(location.pathname)))}),window.addEventListener(`popstate`,()=>{p(f.match(location.pathname))})}export{c as createApp};
2
2
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["import routes from 'virtual:aihu-routes'\nimport { mount } from '@aihu/arbor'\nimport type { MatchResult, RouteDefinition } from '@aihu/router'\nimport { createRouter } from '@aihu/router'\nimport { _setMount, _setSignal } from '@aihu/runtime'\nimport { signal } from '@aihu/signals'\n\n/** Inline runtime configuration accepted by createApp(). All fields optional. */\nexport interface AppConfig {\n /** Id of the outlet element in index.html. Default: 'outlet' */\n outletId?: string\n /**\n * App-level values hoisted into globalThis before any component runs.\n * Use this for singletons (db clients, auth helpers, i18n) that are\n * referenced as bare identifiers inside @state blocks.\n *\n * @example\n * createApp({ provide: { supabase, checkAuth } })\n */\n provide?: Record<string, unknown>\n}\n\n/**\n * Bootstrap the aihu SPA.\n *\n * - Wires the aihu runtime (mount + signal) — idempotent if called multiple times\n * - Creates the router from virtual:aihu-routes\n * - Renders the current route\n * - Installs SPA click interception and popstate listeners\n *\n * @example\n * // src/main.ts\n * import { createApp } from '@aihu/app/client'\n * createApp()\n */\nexport function createApp(config?: AppConfig): void {\n // Hoist provided values into globalThis before any component runs so that\n // @state blocks can reference them as bare identifiers.\n if (config?.provide) {\n Object.assign(globalThis, config.provide)\n }\n\n // Wire runtime — null-guarded in @aihu/runtime, safe to call multiple times\n _setMount(mount)\n _setSignal(signal as Parameters<typeof _setSignal>[0])\n\n const outletId = config?.outletId ?? 'outlet'\n const outletEl = document.getElementById(outletId)\n if (!outletEl) {\n throw new Error(\n `@aihu/app: no element with id=\"${outletId}\" found. Add <div id=\"${outletId}\"></div> to your index.html`,\n )\n }\n const outlet: HTMLElement = outletEl\n\n const router = createRouter(routes)\n\n async function render(match: MatchResult | null): Promise<void> {\n if (!match) {\n // Check for a 404/not-found route by convention before falling back inline\n const notFoundRoute = (routes as RouteDefinition[]).find(\n (r) => r.pattern === '*' || r.name === 'not-found',\n )\n if (notFoundRoute) {\n await notFoundRoute.module()\n const tag = notFoundRoute.name\n if (tag?.includes('-')) {\n outlet.replaceChildren(document.createElement(tag))\n return\n }\n }\n // Inline fallback 404\n const p = document.createElement('p')\n p.style.cssText = 'font-family:system-ui;padding:2rem;color:#888'\n p.textContent = '404 — page not found'\n outlet.replaceChildren(p)\n return\n }\n\n // Import the page module — registers its custom element + auto-wires runtime\n await match.route.module()\n const tag = match.route.name\n if (!tag?.includes('-')) return\n\n const el = document.createElement(tag)\n\n // Flat per-attribute route params (A4 protocol — replaces JSON route attribute)\n if (match.params) {\n for (const [key, val] of Object.entries(match.params)) {\n el.setAttribute(key, String(val))\n }\n }\n\n outlet.replaceChildren(el)\n }\n\n // Initial render\n render(router.match(location.pathname))\n\n // SPA click interception — handles <a> links within the app\n document.addEventListener('click', (e) => {\n const a = (e.target as Element).closest('a') as HTMLAnchorElement | null\n if (!a) return\n const href = a.getAttribute('href')\n if (!href || href.startsWith('http') || href.startsWith('//') || href.startsWith('mailto:'))\n return\n e.preventDefault()\n history.pushState({}, '', href)\n render(router.match(location.pathname))\n })\n\n // Browser back/forward\n window.addEventListener('popstate', () => {\n render(router.match(location.pathname))\n })\n}\n"],"mappings":"oNAmCA,SAAgB,EAAU,EAA0B,CAG9C,GAAQ,SACV,OAAO,OAAO,WAAY,EAAO,QAAQ,CAI3C,EAAU,EAAM,CAChB,EAAW,EAA2C,CAEtD,IAAM,EAAW,GAAQ,UAAY,SAC/B,EAAW,SAAS,eAAe,EAAS,CAClD,GAAI,CAAC,EACH,MAAU,MACR,kCAAkC,EAAS,wBAAwB,EAAS,6BAC7E,CAEH,IAAM,EAAsB,EAEtB,EAAS,EAAa,EAAO,CAEnC,eAAe,EAAO,EAA0C,CAC9D,GAAI,CAAC,EAAO,CAEV,IAAM,EAAiB,EAA6B,KACjD,GAAM,EAAE,UAAY,KAAO,EAAE,OAAS,YACxC,CACD,GAAI,EAAe,CACjB,MAAM,EAAc,QAAQ,CAC5B,IAAM,EAAM,EAAc,KAC1B,GAAI,GAAK,SAAS,IAAI,CAAE,CACtB,EAAO,gBAAgB,SAAS,cAAc,EAAI,CAAC,CACnD,QAIJ,IAAM,EAAI,SAAS,cAAc,IAAI,CACrC,EAAE,MAAM,QAAU,gDAClB,EAAE,YAAc,uBAChB,EAAO,gBAAgB,EAAE,CACzB,OAIF,MAAM,EAAM,MAAM,QAAQ,CAC1B,IAAM,EAAM,EAAM,MAAM,KACxB,GAAI,CAAC,GAAK,SAAS,IAAI,CAAE,OAEzB,IAAM,EAAK,SAAS,cAAc,EAAI,CAGtC,GAAI,EAAM,OACR,IAAK,GAAM,CAAC,EAAK,KAAQ,OAAO,QAAQ,EAAM,OAAO,CACnD,EAAG,aAAa,EAAK,OAAO,EAAI,CAAC,CAIrC,EAAO,gBAAgB,EAAG,CAI5B,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,CAGvC,SAAS,iBAAiB,QAAU,GAAM,CACxC,IAAM,EAAK,EAAE,OAAmB,QAAQ,IAAI,CAC5C,GAAI,CAAC,EAAG,OACR,IAAM,EAAO,EAAE,aAAa,OAAO,CAC/B,CAAC,GAAQ,EAAK,WAAW,OAAO,EAAI,EAAK,WAAW,KAAK,EAAI,EAAK,WAAW,UAAU,GAE3F,EAAE,gBAAgB,CAClB,QAAQ,UAAU,EAAE,CAAE,GAAI,EAAK,CAC/B,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,GACvC,CAGF,OAAO,iBAAiB,eAAkB,CACxC,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,EACvC"}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["import routes from 'virtual:aihu-routes'\nimport { hydrate, mount } from '@aihu/arbor'\nimport type { MatchResult, RouteDefinition } from '@aihu/router'\nimport { createRouter } from '@aihu/router'\nimport { _setHydrate, _setMount, _setSignal } from '@aihu/runtime'\nimport { signal } from '@aihu/signals'\n\n/**\n * Rendering mode passed from the server config into the client bootstrap.\n * Inlined here to avoid importing @aihu/server into the client bundle.\n * Must stay in sync with RenderingMode in @aihu/server.\n */\nexport type AppRenderingMode = 'ssr' | 'spa' | 'hybrid'\n\n/** Inline runtime configuration accepted by createApp(). All fields optional. */\nexport interface AppConfig {\n /** Id of the outlet element in index.html. Default: 'outlet' */\n outletId?: string\n /**\n * App-level values hoisted into globalThis before any component runs.\n * Use this for singletons (db clients, auth helpers, i18n) that are\n * referenced as bare identifiers inside @state blocks.\n *\n * @example\n * createApp({ provide: { supabase, checkAuth } })\n */\n provide?: Record<string, unknown>\n /**\n * Rendering mode from the server config. Controls whether the client\n * wires the hydration function into the runtime.\n *\n * - 'ssr' | 'hybrid' (default): wires _setHydrate so the client can\n * take over from server-rendered HTML without re-creating DOM.\n * - 'spa': skips _setHydrate — no SSR HTML to hydrate, mount-only.\n *\n * Pass `defineAihuConfig(…).rendering?.mode` from your server config.\n * Default: 'ssr' (hydration wired).\n */\n rendering?: { mode?: AppRenderingMode }\n}\n\n/**\n * Bootstrap the aihu SPA.\n *\n * - Wires the aihu runtime (mount + signal) — idempotent if called multiple times\n * - Creates the router from virtual:aihu-routes\n * - Renders the current route\n * - Installs SPA click interception and popstate listeners\n *\n * @example\n * // src/main.ts\n * import { createApp } from '@aihu/app/client'\n * createApp()\n */\nexport function createApp(config?: AppConfig): void {\n // Hoist provided values into globalThis before any component runs so that\n // @state blocks can reference them as bare identifiers.\n if (config?.provide) {\n Object.assign(globalThis, config.provide)\n }\n\n // Wire runtime — null-guarded in @aihu/runtime, safe to call multiple times\n _setMount(mount)\n _setSignal(signal as Parameters<typeof _setSignal>[0])\n if (config?.rendering?.mode !== 'spa') {\n _setHydrate(hydrate as Parameters<typeof _setHydrate>[0])\n }\n\n const outletId = config?.outletId ?? 'outlet'\n const outletEl = document.getElementById(outletId)\n if (!outletEl) {\n throw new Error(\n `@aihu/app: no element with id=\"${outletId}\" found. Add <div id=\"${outletId}\"></div> to your index.html`,\n )\n }\n const outlet: HTMLElement = outletEl\n\n const router = createRouter(routes)\n\n async function render(match: MatchResult | null): Promise<void> {\n if (!match) {\n // Check for a 404/not-found route by convention before falling back inline\n const notFoundRoute = (routes as RouteDefinition[]).find(\n (r) => r.pattern === '*' || r.name === 'not-found',\n )\n if (notFoundRoute) {\n await notFoundRoute.module()\n const tag = notFoundRoute.name\n if (tag?.includes('-')) {\n outlet.replaceChildren(document.createElement(tag))\n return\n }\n }\n // Inline fallback 404\n const p = document.createElement('p')\n p.style.cssText = 'font-family:system-ui;padding:2rem;color:#888'\n p.textContent = '404 — page not found'\n outlet.replaceChildren(p)\n return\n }\n\n // Import the page module — registers its custom element + auto-wires runtime\n await match.route.module()\n const tag = match.route.name\n if (!tag?.includes('-')) return\n\n const el = document.createElement(tag)\n\n // Flat per-attribute route params (A4 protocol — replaces JSON route attribute)\n if (match.params) {\n for (const [key, val] of Object.entries(match.params)) {\n el.setAttribute(key, String(val))\n }\n }\n\n outlet.replaceChildren(el)\n }\n\n // Initial render\n render(router.match(location.pathname))\n\n // SPA click interception — handles <a> links within the app\n document.addEventListener('click', (e) => {\n const a = (e.target as Element).closest('a') as HTMLAnchorElement | null\n if (!a) return\n const href = a.getAttribute('href')\n if (!href || href.startsWith('http') || href.startsWith('//') || href.startsWith('mailto:'))\n return\n e.preventDefault()\n history.pushState({}, '', href)\n render(router.match(location.pathname))\n })\n\n // Browser back/forward\n window.addEventListener('popstate', () => {\n render(router.match(location.pathname))\n })\n}\n"],"mappings":"kPAsDA,SAAgB,EAAU,EAA0B,CAG9C,GAAQ,SACV,OAAO,OAAO,WAAY,EAAO,QAAQ,CAI3C,EAAU,EAAM,CAChB,EAAW,EAA2C,CAClD,GAAQ,WAAW,OAAS,OAC9B,EAAY,EAA6C,CAG3D,IAAM,EAAW,GAAQ,UAAY,SAC/B,EAAW,SAAS,eAAe,EAAS,CAClD,GAAI,CAAC,EACH,MAAU,MACR,kCAAkC,EAAS,wBAAwB,EAAS,6BAC7E,CAEH,IAAM,EAAsB,EAEtB,EAAS,EAAa,EAAO,CAEnC,eAAe,EAAO,EAA0C,CAC9D,GAAI,CAAC,EAAO,CAEV,IAAM,EAAiB,EAA6B,KACjD,GAAM,EAAE,UAAY,KAAO,EAAE,OAAS,YACxC,CACD,GAAI,EAAe,CACjB,MAAM,EAAc,QAAQ,CAC5B,IAAM,EAAM,EAAc,KAC1B,GAAI,GAAK,SAAS,IAAI,CAAE,CACtB,EAAO,gBAAgB,SAAS,cAAc,EAAI,CAAC,CACnD,QAIJ,IAAM,EAAI,SAAS,cAAc,IAAI,CACrC,EAAE,MAAM,QAAU,gDAClB,EAAE,YAAc,uBAChB,EAAO,gBAAgB,EAAE,CACzB,OAIF,MAAM,EAAM,MAAM,QAAQ,CAC1B,IAAM,EAAM,EAAM,MAAM,KACxB,GAAI,CAAC,GAAK,SAAS,IAAI,CAAE,OAEzB,IAAM,EAAK,SAAS,cAAc,EAAI,CAGtC,GAAI,EAAM,OACR,IAAK,GAAM,CAAC,EAAK,KAAQ,OAAO,QAAQ,EAAM,OAAO,CACnD,EAAG,aAAa,EAAK,OAAO,EAAI,CAAC,CAIrC,EAAO,gBAAgB,EAAG,CAI5B,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,CAGvC,SAAS,iBAAiB,QAAU,GAAM,CACxC,IAAM,EAAK,EAAE,OAAmB,QAAQ,IAAI,CAC5C,GAAI,CAAC,EAAG,OACR,IAAM,EAAO,EAAE,aAAa,OAAO,CAC/B,CAAC,GAAQ,EAAK,WAAW,OAAO,EAAI,EAAK,WAAW,KAAK,EAAI,EAAK,WAAW,UAAU,GAE3F,EAAE,gBAAgB,CAClB,QAAQ,UAAU,EAAE,CAAE,GAAI,EAAK,CAC/B,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,GACvC,CAGF,OAAO,iBAAiB,eAAkB,CACxC,EAAO,EAAO,MAAM,SAAS,SAAS,CAAC,EACvC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aihu/app",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,15 +28,15 @@
28
28
  "prepublishOnly": "bun run build"
29
29
  },
30
30
  "peerDependencies": {
31
- "@aihu/arbor": "workspace:*",
32
- "@aihu/router": "workspace:*",
33
- "@aihu/runtime": "workspace:*",
34
- "@aihu/signals": "workspace:*",
31
+ "@aihu/arbor": "0.1.3",
32
+ "@aihu/router": "0.1.0",
33
+ "@aihu/runtime": "0.1.3",
34
+ "@aihu/signals": "0.1.0",
35
35
  "vite": ">=5.0.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@aihu/agent-readiness": "workspace:*",
39
- "@aihu/compiler": "workspace:*"
38
+ "@aihu/agent-readiness": "0.1.0",
39
+ "@aihu/compiler": "0.2.0"
40
40
  },
41
41
  "description": "Top-level app integration — wires runtime, router, and adapters into a Vite app.",
42
42
  "repository": {