@junejs/server 0.1.2 → 0.2.0

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 (130) hide show
  1. package/assets/icon-latin.LICENSE.txt +92 -0
  2. package/assets/icon-latin.ttf +0 -0
  3. package/dist/adapter-DcZ-W1-7.d.ts +62 -0
  4. package/dist/adapter.d.ts +2 -56
  5. package/dist/adapter.js +62 -5
  6. package/dist/agent-compile.d.ts +38 -0
  7. package/dist/agent-compile.js +145 -0
  8. package/dist/agent-discover.d.ts +4 -4
  9. package/dist/agent-discover.js +30 -44
  10. package/dist/agent-durable.d.ts +94 -19
  11. package/dist/agent-durable.js +647 -32
  12. package/dist/agent-native.d.ts +44 -13
  13. package/dist/agent-native.js +264 -27
  14. package/dist/app.d.ts +5 -5
  15. package/dist/app.js +42 -10
  16. package/dist/blob.d.ts +4 -5
  17. package/dist/build.d.ts +8 -29
  18. package/dist/build.js +138 -289
  19. package/dist/client-bundle.d.ts +8 -9
  20. package/dist/client-bundle.js +1 -1
  21. package/dist/config-freeze-CyXvNqi2.d.ts +17 -0
  22. package/dist/config-freeze.d.ts +2 -0
  23. package/dist/config-freeze.js +54 -0
  24. package/dist/config-loader.d.ts +3 -4
  25. package/dist/connection-auth.d.ts +38 -0
  26. package/dist/connection-auth.js +31 -0
  27. package/dist/content-freeze-CyiW2fRK.d.ts +4 -0
  28. package/dist/content-freeze.d.ts +2 -0
  29. package/dist/content-freeze.js +83 -0
  30. package/dist/content.d.ts +22 -9
  31. package/dist/content.js +43 -3
  32. package/dist/core-version.d.ts +4 -0
  33. package/dist/core-version.js +12 -0
  34. package/dist/css-modules-ambient.d.ts +2 -1
  35. package/dist/css-modules.d.ts +10 -11
  36. package/dist/css.d.ts +9 -10
  37. package/dist/d1-migrate.d.ts +6 -7
  38. package/dist/d1-migrate.js +3 -2
  39. package/dist/db.d.ts +2 -2
  40. package/dist/deploy.d.ts +3 -4
  41. package/dist/deploy.js +3 -2
  42. package/dist/dev-reload.d.ts +3 -4
  43. package/dist/dev.d.ts +8 -5
  44. package/dist/dev.js +40 -9
  45. package/dist/favicon.d.ts +37 -0
  46. package/dist/favicon.js +248 -0
  47. package/dist/host.d.ts +6 -5
  48. package/dist/host.js +2 -1
  49. package/dist/icon-letter.d.ts +3 -0
  50. package/dist/icon-letter.js +8 -0
  51. package/dist/index.d.ts +11 -5
  52. package/dist/index.js +9 -3
  53. package/dist/instrumentation.d.ts +2 -3
  54. package/dist/instrumentation.js +2 -1
  55. package/dist/island-registry.d.ts +6 -7
  56. package/dist/isolate-local.d.ts +5 -0
  57. package/dist/isolate-local.js +12 -0
  58. package/dist/kv.d.ts +3 -4
  59. package/dist/llms-links.d.ts +9 -0
  60. package/dist/llms-links.js +65 -0
  61. package/dist/manifest-CwTT1zVs.d.ts +11 -0
  62. package/dist/manifest.d.ts +2 -0
  63. package/dist/manifest.js +113 -0
  64. package/dist/negotiate.d.ts +4 -3
  65. package/dist/negotiate.js +24 -14
  66. package/dist/{pipeline-CCp9idQ4.d.ts → pipeline-BHUjBO0G.d.ts} +13 -1
  67. package/dist/pipeline.d.ts +2 -2
  68. package/dist/pipeline.js +286 -35
  69. package/dist/resources.d.ts +5 -6
  70. package/dist/route-rank.d.ts +10 -0
  71. package/dist/route-rank.js +38 -0
  72. package/dist/route-scan-BMbBzPIB.d.ts +20 -0
  73. package/dist/route-scan.d.ts +2 -0
  74. package/dist/route-scan.js +100 -0
  75. package/dist/router.d.ts +12 -13
  76. package/dist/router.js +58 -44
  77. package/dist/rsc-build.d.ts +6 -7
  78. package/dist/rsc-bundle.d.ts +6 -7
  79. package/dist/rsc-manifest.d.ts +5 -6
  80. package/dist/rsc-runtime/flight-render-routes.d.ts +3 -4
  81. package/dist/rsc-runtime/flight-render.d.ts +2 -3
  82. package/dist/rsc-runtime/flight-to-html.d.ts +2 -3
  83. package/dist/rsc-runtime/flight-to-html.js +3 -2
  84. package/dist/rsc-runtime/rsc-worker.js +11 -8
  85. package/dist/rsc-runtime/rsdw-shims.d.ts +2 -1
  86. package/dist/segment.d.ts +4 -5
  87. package/dist/sqlite-driver.d.ts +11 -11
  88. package/dist/sqlite-driver.js +17 -4
  89. package/dist/static-files.d.ts +4 -5
  90. package/dist/tsconfig-jsx.d.ts +4 -4
  91. package/dist/tsconfig-jsx.js +1 -1
  92. package/dist/turn-events.d.ts +4 -0
  93. package/dist/turn-events.js +46 -0
  94. package/dist/web-manifest.d.ts +5 -0
  95. package/dist/web-manifest.js +42 -0
  96. package/dist/worker-2qbQjj2c.d.ts +64 -0
  97. package/dist/worker.d.ts +2 -56
  98. package/dist/worker.js +121 -103
  99. package/package.json +22 -9
  100. package/src/adapter.ts +84 -3
  101. package/src/agent-compile.ts +271 -0
  102. package/src/agent-discover.ts +77 -63
  103. package/src/agent-durable.ts +998 -30
  104. package/src/agent-native.ts +370 -35
  105. package/src/app.ts +75 -6
  106. package/src/build.ts +237 -444
  107. package/src/config-freeze.ts +109 -0
  108. package/src/connection-auth.ts +101 -0
  109. package/src/content-freeze.ts +151 -0
  110. package/src/content.ts +55 -4
  111. package/src/core-version.ts +34 -0
  112. package/src/dev.ts +41 -8
  113. package/src/favicon.ts +325 -0
  114. package/src/host.ts +4 -3
  115. package/src/icon-letter.ts +14 -0
  116. package/src/index.ts +22 -0
  117. package/src/isolate-local.ts +33 -0
  118. package/src/llms-links.ts +96 -0
  119. package/src/manifest.ts +130 -0
  120. package/src/negotiate.ts +39 -15
  121. package/src/pipeline.ts +494 -44
  122. package/src/route-rank.ts +60 -0
  123. package/src/route-scan.ts +161 -0
  124. package/src/router.ts +75 -58
  125. package/src/rsc-runtime/rsc-worker.tsx +5 -4
  126. package/src/sqlite-driver.ts +36 -6
  127. package/src/tsconfig-jsx.ts +2 -2
  128. package/src/turn-events.ts +43 -0
  129. package/src/web-manifest.ts +38 -0
  130. package/src/worker.ts +197 -117
package/src/app.ts CHANGED
@@ -18,21 +18,25 @@ import type { ComponentType } from "react";
18
18
  import { routeFromModule } from "@junejs/core/route";
19
19
  import {
20
20
  resolveAgent,
21
+ deployOrigin,
21
22
  resolveClientRouter,
22
23
  resolveSpeculationRules,
23
24
  type JuneConfig,
24
25
  } from "@junejs/core/config";
25
26
  import type { DocumentConfig } from "@junejs/core/document";
26
27
  import { runWithTrace, type RequestTrace } from "@junejs/core/instrumentation";
28
+ import { blobFileStore, memoryFileStore } from "@junejs/core/agent-files";
29
+ import type { JuneBlob } from "@junejs/core/resources";
27
30
 
28
31
  import { findMiddlewareFile, isResourceFile, listRoutes, matchRouteTree, resolveNotFound, routeFiles, type SegmentMatch } from "./router";
32
+ import { routeProblems, scanRoutes } from "./route-scan";
29
33
  import { createPipeline, type ExtraHandler, type LayoutComponent, type MiddlewareHandler, type Pipeline, type Resolved, type ResourceHandler } from "./pipeline";
30
34
  import { discoverAgent } from "./agent-discover";
31
- import { createAgentRuntime, mountAgent } from "./agent-native";
32
- import { buildSystemPrompt } from "@junejs/core/agent-config";
35
+ import { createAgentRuntime, mountAgent, toAgentDef, type InProcessRuntime } from "./agent-native";
33
36
  import { anthropic } from "@junejs/core/agent-models";
34
37
  import { resolveBoundary } from "./segment";
35
38
  import { memoizeResources } from "./resources";
39
+ import { localBlob } from "./blob";
36
40
  import {
37
41
  findClientEntry,
38
42
  bundleClientSplit,
@@ -43,6 +47,15 @@ import { generateIslandRegistry } from "./island-registry";
43
47
  import { findGlobalCss, globalCssUsesTailwind, processCssCached, STYLES_URL } from "./css";
44
48
  import { buildModuleCss, registerCssModules, MODULE_STYLES_URL, type ModuleMaps } from "./css-modules";
45
49
  import { contentTypeFor, RESERVED_PREFIX, safeRelativePath } from "./static-files";
50
+ import {
51
+ GENERATED_ICONS,
52
+ googleFontFetcher,
53
+ publicFileCheck,
54
+ renderIcons,
55
+ resolveIcons,
56
+ type GeneratedIconFile,
57
+ type GeneratedIcons,
58
+ } from "./favicon";
46
59
 
47
60
  export type CreateAppOptions = {
48
61
  appDir: string;
@@ -56,6 +69,10 @@ export type JuneApp = {
56
69
  warmup(): Promise<void>;
57
70
  routePaths(): Promise<string[]>;
58
71
  earlyHints(): string[];
72
+ // Shut down what the app started (#317): the agent runtime built for an agent/
73
+ // directory — its pending announcement retries, its in-flight turns, its SQLite
74
+ // handle. Resolves once they finish. A no-op when no runtime was built.
75
+ close(): Promise<void>;
59
76
  };
60
77
 
61
78
  // Import a layout file's default export as a layout component (memoized), plus
@@ -133,6 +150,19 @@ export function createApp({ appDir: appDirInput, config = {} }: CreateAppOptions
133
150
  } catch {
134
151
  /* no public/ dir → nothing to serve */
135
152
  }
153
+ // Default PNG icons: linked by the document, rendered once on first request
154
+ // (a failed render is retried next time rather than memoized).
155
+ const iconPlan = resolveIcons(config.site ?? {}, publicFileCheck(publicDir));
156
+ let iconsPromise: Promise<GeneratedIcons> | undefined;
157
+ const getIcons = () =>
158
+ (iconsPromise ??= renderIcons({
159
+ site: config.site ?? {},
160
+ fetchFont: googleFontFetcher(join(dirname(appDir), "node_modules", ".cache", "june", "fonts")),
161
+ warn: (msg) => console.warn(msg),
162
+ }).catch((err) => {
163
+ iconsPromise = undefined;
164
+ throw err;
165
+ }));
136
166
  const agent = resolveAgent(config.agent);
137
167
  const speculation = config.speculation;
138
168
  // app/_client.* present → the dev document loads /client.js and we serve it
@@ -144,6 +174,7 @@ export function createApp({ appDir: appDirInput, config = {} }: CreateAppOptions
144
174
  const cssEntry = findGlobalCss(appDir);
145
175
  const docConfig: DocumentConfig = {
146
176
  site: config.site ?? {},
177
+ deployOrigin: deployOrigin(config),
147
178
  speculationRules: resolveSpeculationRules(speculation ?? undefined),
148
179
  speculationDelivery: speculation ? speculation.delivery ?? "inline" : "inline",
149
180
  viewTransitions: config.viewTransitions ?? true,
@@ -152,6 +183,7 @@ export function createApp({ appDir: appDirInput, config = {} }: CreateAppOptions
152
183
  clientRouter: resolveClientRouter(config.clientRouter),
153
184
  clientScript: clientEntry ? CLIENT_SCRIPT_URL : null,
154
185
  styles: cssEntry ? STYLES_URL : null,
186
+ icons: iconPlan.icons,
155
187
  };
156
188
 
157
189
  // CSS Modules: glob + transform app/**/*.module.css ONCE (memoized) → the maps
@@ -202,6 +234,8 @@ export function createApp({ appDir: appDirInput, config = {} }: CreateAppOptions
202
234
  // pipeline is built lazily on first fetch, memoized after.
203
235
  let pipelinePromise: Promise<Pipeline> | undefined;
204
236
  const getPipeline = (): Promise<Pipeline> => (pipelinePromise ??= buildPipeline());
237
+ // The agent runtime buildPipeline creates, kept so close() can shut it down (#317).
238
+ let agentRuntime: InProcessRuntime | undefined;
205
239
  async function buildPipeline(): Promise<Pipeline> {
206
240
  // Wire CSS Modules BEFORE any route import: the runtime interceptor must be
207
241
  // active so `import "x.module.css"` in a route resolves to the scoped map,
@@ -237,10 +271,18 @@ export function createApp({ appDir: appDirInput, config = {} }: CreateAppOptions
237
271
  // instructions live on the def (single source); the runtime injects them
238
272
  // into the model per turn via withSystem — no need to bake into anthropic().
239
273
  const model = anthropic({ model: def.model });
240
- const rt = await createAgentRuntime(
241
- { [def.name]: { model, tools: def.tools, instructions: buildSystemPrompt(def) } },
242
- { backend },
243
- );
274
+ // toAgentDef: tools, prompt AND the per-surface policies (#149) from the one
275
+ // definition — channelInstructions was previously dropped on this path (#173).
276
+ // Agent files (docs/rfc-agent-files.md) live in the app's blob resource; an app that
277
+ // declares none gets the local default directory. The memory backend keeps them in
278
+ // memory, like everything else it holds.
279
+ let blobOpened: Promise<JuneBlob> | undefined;
280
+ const files =
281
+ backend === "memory"
282
+ ? memoryFileStore()
283
+ : blobFileStore(() => (blobOpened ??= resources().then(async (r) => r.blob ?? (await localBlob().open()))));
284
+ const rt = await createAgentRuntime({ [def.name]: toAgentDef(def, model) }, { backend, files });
285
+ agentRuntime = rt;
244
286
  const mounted = mountAgent(def, rt, { chatPath: agent.runtime.chat.path, channels: agent.runtime.channels });
245
287
  agentSurface = (req) => mounted.surface(req);
246
288
  await mounted.startAll();
@@ -403,9 +445,30 @@ export function createApp({ appDir: appDirInput, config = {} }: CreateAppOptions
403
445
  }
404
446
  }
405
447
  }
448
+ // June's default PNG icons (the app has none of its own): rendered on first
449
+ // request with the same code `june build` writes them with.
450
+ if (iconPlan.generate && (request.method === "GET" || request.method === "HEAD")) {
451
+ const name = new URL(request.url).pathname.slice(1);
452
+ if ((GENERATED_ICONS as readonly string[]).includes(name)) {
453
+ return getIcons().then(
454
+ (icons) =>
455
+ new Response(request.method === "HEAD" ? null : icons[name as GeneratedIconFile], {
456
+ headers: { "content-type": contentTypeFor(name), "cache-control": "public, max-age=0, must-revalidate" },
457
+ }),
458
+ () => toPipeline(),
459
+ );
460
+ }
461
+ }
406
462
  return toPipeline();
407
463
  },
408
464
  async warmup() {
465
+ // What `june build` refuses (same-path files, a segment after an optional
466
+ // or catch-all), dev reports up front — it still serves what it can.
467
+ const problems = routeProblems(
468
+ [await scanRoutes(appDir), hasJuneRoutes ? await scanRoutes(juneRoutesDir) : []],
469
+ dirname(appDir),
470
+ );
471
+ if (problems) console.error(problems);
409
472
  const files = await routeFiles(appDir, { pageConvention: true });
410
473
  if (hasJuneRoutes) files.push(...(await routeFiles(juneRoutesDir, { pageConvention: true })));
411
474
  for (const file of files) {
@@ -416,5 +479,11 @@ export function createApp({ appDir: appDirInput, config = {} }: CreateAppOptions
416
479
  },
417
480
  routePaths,
418
481
  earlyHints: () => config.earlyHints ?? [],
482
+ async close() {
483
+ // A pipeline still being built may be about to create the runtime: let it finish
484
+ // (its failure is the fetch's to report, not close()'s).
485
+ await pipelinePromise?.catch(() => {});
486
+ await agentRuntime?.close();
487
+ },
419
488
  };
420
489
  }