@byline/host-tanstack-start 1.8.2 → 1.9.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.
@@ -0,0 +1,34 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ /**
9
+ * Bridges the `@byline/ai` plugins to TanStack Start's RPC transport.
10
+ *
11
+ * The plugins make `fetch(endpoint, init)` calls. We substitute a
12
+ * fetch-shaped adapter that invokes `executeAiInstruction` (a server
13
+ * function with admin-auth enforcement) and returns its `Response` —
14
+ * preserving the NDJSON streaming wire format the plugins already
15
+ * understand.
16
+ *
17
+ * Hosts mount `<BylineAiAdminProvider>` once inside the admin shell.
18
+ */
19
+ import type { ReactNode } from 'react';
20
+ /**
21
+ * `fetch`-shaped adapter that dispatches the body to the
22
+ * `executeAiInstruction` server function. The `input` URL is ignored —
23
+ * the server function handles routing and auth.
24
+ */
25
+ export declare const aiFetchAdapter: typeof fetch;
26
+ /**
27
+ * Single-line provider mount for the admin shell. Wires `@byline/ai`'s
28
+ * public config to the host-side server function. Set `enabled={false}`
29
+ * to allow wrapper fields to hide AI affordances globally.
30
+ */
31
+ export declare function BylineAiAdminProvider({ children, enabled, }: {
32
+ children: ReactNode;
33
+ enabled?: boolean;
34
+ }): import("react").JSX.Element;
@@ -0,0 +1,33 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { AiPublicConfigProvider } from "@byline/ai";
3
+ import { executeAiInstruction } from "../server-fns/ai/index.js";
4
+ const aiFetchAdapter = async (_input, init)=>{
5
+ const bodyText = 'string' == typeof init?.body ? init.body : init?.body == null ? '' : await new Response(init.body).text();
6
+ let payload;
7
+ try {
8
+ payload = JSON.parse(bodyText);
9
+ } catch {
10
+ return new Response(JSON.stringify({
11
+ error: 'Invalid JSON payload'
12
+ }), {
13
+ status: 400,
14
+ headers: {
15
+ 'Content-Type': 'application/json'
16
+ }
17
+ });
18
+ }
19
+ return executeAiInstruction({
20
+ data: payload,
21
+ signal: init?.signal ?? void 0
22
+ });
23
+ };
24
+ function BylineAiAdminProvider({ children, enabled }) {
25
+ return /*#__PURE__*/ jsx(AiPublicConfigProvider, {
26
+ config: {
27
+ fetch: aiFetchAdapter,
28
+ enabled
29
+ },
30
+ children: children
31
+ });
32
+ }
33
+ export { BylineAiAdminProvider, aiFetchAdapter };
@@ -10,6 +10,7 @@ import { AdminMenuDrawer } from "../admin-shell/chrome/menu-drawer.js";
10
10
  import { AdminMenuProvider } from "../admin-shell/chrome/menu-provider.js";
11
11
  import { RouteError, RouteNotFound } from "../admin-shell/chrome/route-error.js";
12
12
  import { bylineAdminServices } from "../integrations/byline-admin-services.js";
13
+ import { BylineAiAdminProvider } from "../integrations/byline-ai.js";
13
14
  import { bylineFieldServices } from "../integrations/byline-field-services.js";
14
15
  import { getCurrentAdminUser } from "../server-fns/auth/index.js";
15
16
  function createAdminLayoutRoute(path, opts = {}) {
@@ -36,22 +37,24 @@ function createAdminLayoutRoute(path, opts = {}) {
36
37
  services: bylineAdminServices,
37
38
  children: /*#__PURE__*/ jsx(BylineFieldServicesProvider, {
38
39
  services: bylineFieldServices,
39
- children: /*#__PURE__*/ jsxs(AdminMenuProvider, {
40
- children: [
41
- /*#__PURE__*/ jsx(AdminAppBar, {
42
- user: user
43
- }),
44
- /*#__PURE__*/ jsxs("main", {
45
- className: classnames('byline-admin-layout-main', admin_layout_module.main),
46
- children: [
47
- /*#__PURE__*/ jsx(DrawerToggle, {}),
48
- /*#__PURE__*/ jsx(AdminMenuDrawer, {}),
49
- /*#__PURE__*/ jsx(Content, {
50
- children: /*#__PURE__*/ jsx(Outlet, {})
51
- })
52
- ]
53
- })
54
- ]
40
+ children: /*#__PURE__*/ jsx(BylineAiAdminProvider, {
41
+ children: /*#__PURE__*/ jsxs(AdminMenuProvider, {
42
+ children: [
43
+ /*#__PURE__*/ jsx(AdminAppBar, {
44
+ user: user
45
+ }),
46
+ /*#__PURE__*/ jsxs("main", {
47
+ className: classnames('byline-admin-layout-main', admin_layout_module.main),
48
+ children: [
49
+ /*#__PURE__*/ jsx(DrawerToggle, {}),
50
+ /*#__PURE__*/ jsx(AdminMenuDrawer, {}),
51
+ /*#__PURE__*/ jsx(Content, {
52
+ children: /*#__PURE__*/ jsx(Outlet, {})
53
+ })
54
+ ]
55
+ })
56
+ ]
57
+ })
55
58
  })
56
59
  })
57
60
  });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ import type { ExecuteInstructionOptions, ExecuteInstructionParams } from '@byline/ai';
9
+ /**
10
+ * Wire shape — the same as `ExecuteInstruction` minus the in-process-only
11
+ * `signal` (an AbortSignal can't be serialized across the RPC boundary;
12
+ * the client passes its signal separately as a fetcher option).
13
+ */
14
+ type ExecuteAiInstructionInput = {
15
+ params: ExecuteInstructionParams;
16
+ options?: Omit<ExecuteInstructionOptions, 'signal'>;
17
+ };
18
+ export declare const executeAiInstruction: import("@tanstack/react-start").RequiredFetcher<undefined, (input: ExecuteAiInstructionInput) => ExecuteAiInstructionInput, Promise<Response>>;
19
+ export {};
@@ -0,0 +1,49 @@
1
+ import { createServerFn } from "@tanstack/react-start";
2
+ import { executeInstruction, executeInstructionStreaming } from "@byline/ai/server";
3
+ import { getAdminRequestContext } from "../../auth/auth-context.js";
4
+ const executeAiInstruction = createServerFn({
5
+ method: 'POST'
6
+ }).inputValidator((input)=>input).handler(async ({ data })=>{
7
+ await getAdminRequestContext();
8
+ if (data.options?.streaming) {
9
+ const streamResult = executeInstructionStreaming(data.params, data.options);
10
+ const ndjson = new ReadableStream({
11
+ async start (controller) {
12
+ const encoder = new TextEncoder();
13
+ const enqueue = (obj)=>{
14
+ controller.enqueue(encoder.encode(`${JSON.stringify(obj)}\n`));
15
+ };
16
+ try {
17
+ for await (const chunk of streamResult.text)enqueue({
18
+ type: 'delta',
19
+ text: chunk
20
+ });
21
+ const finalState = await streamResult.final;
22
+ enqueue({
23
+ type: 'final',
24
+ state: finalState
25
+ });
26
+ } catch (err) {
27
+ enqueue({
28
+ type: 'error',
29
+ message: err instanceof Error ? err.message : 'AI stream error'
30
+ });
31
+ } finally{
32
+ controller.close();
33
+ }
34
+ }
35
+ });
36
+ return new Response(ndjson, {
37
+ headers: {
38
+ 'Content-Type': 'application/x-ndjson; charset=utf-8'
39
+ }
40
+ });
41
+ }
42
+ const state = await executeInstruction(data.params, data.options);
43
+ return new Response(JSON.stringify(state), {
44
+ headers: {
45
+ 'Content-Type': 'application/json; charset=utf-8'
46
+ }
47
+ });
48
+ });
49
+ export { executeAiInstruction };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ /**
9
+ * Admin-only AI server functions backing the `@byline/ai` plugins.
10
+ *
11
+ * The plugins use a `fetch`-shaped API; the host adapter ships a
12
+ * `aiFetchAdapter` in `@byline/host-tanstack-start/integrations/byline-ai`
13
+ * that wraps `executeAiInstruction` so the plugins remain transport-agnostic.
14
+ */
15
+ export { executeAiInstruction } from './execute';
@@ -0,0 +1 @@
1
+ export { executeAiInstruction } from "./execute.js";
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": false,
4
4
  "type": "module",
5
5
  "license": "MPL-2.0",
6
- "version": "1.8.2",
6
+ "version": "1.9.0",
7
7
  "engines": {
8
8
  "node": ">=20.9.0"
9
9
  },
@@ -45,6 +45,10 @@
45
45
  "types": "./dist/server-fns/admin-account/index.d.ts",
46
46
  "import": "./dist/server-fns/admin-account/index.js"
47
47
  },
48
+ "./server-fns/ai": {
49
+ "types": "./dist/server-fns/ai/index.d.ts",
50
+ "import": "./dist/server-fns/ai/index.js"
51
+ },
48
52
  "./server-fns/admin-permissions": {
49
53
  "types": "./dist/server-fns/admin-permissions/index.d.ts",
50
54
  "import": "./dist/server-fns/admin-permissions/index.js"
@@ -101,11 +105,12 @@
101
105
  "react-swipeable": "^7.0.2",
102
106
  "uuid": "^14.0.0",
103
107
  "zod": "^4.4.2",
104
- "@byline/auth": "1.8.2",
105
- "@byline/core": "1.8.2",
106
- "@byline/client": "1.8.2",
107
- "@byline/admin": "1.8.2",
108
- "@byline/ui": "1.8.2"
108
+ "@byline/admin": "1.9.0",
109
+ "@byline/ai": "1.9.0",
110
+ "@byline/client": "1.9.0",
111
+ "@byline/core": "1.9.0",
112
+ "@byline/auth": "1.9.0",
113
+ "@byline/ui": "1.9.0"
109
114
  },
110
115
  "peerDependencies": {
111
116
  "@tanstack/react-router": "^1.167.0",
@@ -0,0 +1,82 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ /**
10
+ * Bridges the `@byline/ai` plugins to TanStack Start's RPC transport.
11
+ *
12
+ * The plugins make `fetch(endpoint, init)` calls. We substitute a
13
+ * fetch-shaped adapter that invokes `executeAiInstruction` (a server
14
+ * function with admin-auth enforcement) and returns its `Response` —
15
+ * preserving the NDJSON streaming wire format the plugins already
16
+ * understand.
17
+ *
18
+ * Hosts mount `<BylineAiAdminProvider>` once inside the admin shell.
19
+ */
20
+
21
+ import type { ReactNode } from 'react'
22
+
23
+ import {
24
+ AiPublicConfigProvider,
25
+ type ExecuteInstructionOptions,
26
+ type ExecuteInstructionParams,
27
+ } from '@byline/ai'
28
+
29
+ import { executeAiInstruction } from '../server-fns/ai/index.js'
30
+
31
+ type ExecuteAiInstructionWire = {
32
+ params: ExecuteInstructionParams
33
+ options?: Omit<ExecuteInstructionOptions, 'signal'>
34
+ }
35
+
36
+ /**
37
+ * `fetch`-shaped adapter that dispatches the body to the
38
+ * `executeAiInstruction` server function. The `input` URL is ignored —
39
+ * the server function handles routing and auth.
40
+ */
41
+ export const aiFetchAdapter: typeof fetch = async (_input, init) => {
42
+ const bodyText =
43
+ typeof init?.body === 'string'
44
+ ? init.body
45
+ : init?.body == null
46
+ ? ''
47
+ : await new Response(init.body as BodyInit).text()
48
+
49
+ let payload: ExecuteAiInstructionWire
50
+ try {
51
+ payload = JSON.parse(bodyText) as ExecuteAiInstructionWire
52
+ } catch {
53
+ return new Response(JSON.stringify({ error: 'Invalid JSON payload' }), {
54
+ status: 400,
55
+ headers: { 'Content-Type': 'application/json' },
56
+ })
57
+ }
58
+
59
+ return executeAiInstruction({
60
+ data: payload,
61
+ signal: init?.signal ?? undefined,
62
+ })
63
+ }
64
+
65
+ /**
66
+ * Single-line provider mount for the admin shell. Wires `@byline/ai`'s
67
+ * public config to the host-side server function. Set `enabled={false}`
68
+ * to allow wrapper fields to hide AI affordances globally.
69
+ */
70
+ export function BylineAiAdminProvider({
71
+ children,
72
+ enabled,
73
+ }: {
74
+ children: ReactNode
75
+ enabled?: boolean
76
+ }) {
77
+ return (
78
+ <AiPublicConfigProvider config={{ fetch: aiFetchAdapter, enabled }}>
79
+ {children}
80
+ </AiPublicConfigProvider>
81
+ )
82
+ }
@@ -32,6 +32,7 @@ import { AdminMenuDrawer } from '../admin-shell/chrome/menu-drawer.js'
32
32
  import { AdminMenuProvider } from '../admin-shell/chrome/menu-provider.js'
33
33
  import { RouteError, RouteNotFound } from '../admin-shell/chrome/route-error.js'
34
34
  import { bylineAdminServices } from '../integrations/byline-admin-services.js'
35
+ import { BylineAiAdminProvider } from '../integrations/byline-ai.js'
35
36
  import { bylineFieldServices } from '../integrations/byline-field-services.js'
36
37
  import { getCurrentAdminUser } from '../server-fns/auth/index.js'
37
38
 
@@ -67,16 +68,18 @@ export function createAdminLayoutRoute(path: string, opts: AdminLayoutOpts = {})
67
68
  return (
68
69
  <BylineAdminServicesProvider services={bylineAdminServices}>
69
70
  <BylineFieldServicesProvider services={bylineFieldServices}>
70
- <AdminMenuProvider>
71
- <AdminAppBar user={user} />
72
- <main className={cx('byline-admin-layout-main', layoutStyles.main)}>
73
- <DrawerToggle />
74
- <AdminMenuDrawer />
75
- <Content>
76
- <Outlet />
77
- </Content>
78
- </main>
79
- </AdminMenuProvider>
71
+ <BylineAiAdminProvider>
72
+ <AdminMenuProvider>
73
+ <AdminAppBar user={user} />
74
+ <main className={cx('byline-admin-layout-main', layoutStyles.main)}>
75
+ <DrawerToggle />
76
+ <AdminMenuDrawer />
77
+ <Content>
78
+ <Outlet />
79
+ </Content>
80
+ </main>
81
+ </AdminMenuProvider>
82
+ </BylineAiAdminProvider>
80
83
  </BylineFieldServicesProvider>
81
84
  </BylineAdminServicesProvider>
82
85
  )
@@ -0,0 +1,79 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ /**
10
+ * Admin-only AI execute server function.
11
+ *
12
+ * Accepts an `ExecuteInstruction` payload, calls
13
+ * `executeInstruction` / `executeInstructionStreaming` from `@byline/ai`,
14
+ * and returns the result as a `Response` — JSON for non-streaming and
15
+ * NDJSON (`{ type: 'delta' | 'final' | 'error' }` lines) for streaming.
16
+ *
17
+ * Auth is enforced by `getAdminRequestContext()`, which throws
18
+ * `ERR_UNAUTHENTICATED` when no valid admin session is present.
19
+ */
20
+
21
+ import { createServerFn } from '@tanstack/react-start'
22
+
23
+ import type { ExecuteInstructionOptions, ExecuteInstructionParams } from '@byline/ai'
24
+ // Server-only execute API — kept on the `/server` subpath so the browser
25
+ // barrel for `@byline/ai` stays free of pino + the provider SDKs.
26
+ import { executeInstruction, executeInstructionStreaming } from '@byline/ai/server'
27
+
28
+ import { getAdminRequestContext } from '../../auth/auth-context.js'
29
+
30
+ /**
31
+ * Wire shape — the same as `ExecuteInstruction` minus the in-process-only
32
+ * `signal` (an AbortSignal can't be serialized across the RPC boundary;
33
+ * the client passes its signal separately as a fetcher option).
34
+ */
35
+ type ExecuteAiInstructionInput = {
36
+ params: ExecuteInstructionParams
37
+ options?: Omit<ExecuteInstructionOptions, 'signal'>
38
+ }
39
+
40
+ export const executeAiInstruction = createServerFn({ method: 'POST' })
41
+ .inputValidator((input: ExecuteAiInstructionInput) => input)
42
+ .handler(async ({ data }): Promise<Response> => {
43
+ // Throws ERR_UNAUTHENTICATED if there is no admin session.
44
+ await getAdminRequestContext()
45
+
46
+ if (data.options?.streaming) {
47
+ const streamResult = executeInstructionStreaming(data.params, data.options)
48
+ const ndjson = new ReadableStream<Uint8Array>({
49
+ async start(controller) {
50
+ const encoder = new TextEncoder()
51
+ const enqueue = (obj: unknown) => {
52
+ controller.enqueue(encoder.encode(`${JSON.stringify(obj)}\n`))
53
+ }
54
+ try {
55
+ for await (const chunk of streamResult.text) {
56
+ enqueue({ type: 'delta', text: chunk })
57
+ }
58
+ const finalState = await streamResult.final
59
+ enqueue({ type: 'final', state: finalState })
60
+ } catch (err) {
61
+ enqueue({
62
+ type: 'error',
63
+ message: err instanceof Error ? err.message : 'AI stream error',
64
+ })
65
+ } finally {
66
+ controller.close()
67
+ }
68
+ },
69
+ })
70
+ return new Response(ndjson, {
71
+ headers: { 'Content-Type': 'application/x-ndjson; charset=utf-8' },
72
+ })
73
+ }
74
+
75
+ const state = await executeInstruction(data.params, data.options)
76
+ return new Response(JSON.stringify(state), {
77
+ headers: { 'Content-Type': 'application/json; charset=utf-8' },
78
+ })
79
+ })
@@ -0,0 +1,17 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ /**
10
+ * Admin-only AI server functions backing the `@byline/ai` plugins.
11
+ *
12
+ * The plugins use a `fetch`-shaped API; the host adapter ships a
13
+ * `aiFetchAdapter` in `@byline/host-tanstack-start/integrations/byline-ai`
14
+ * that wraps `executeAiInstruction` so the plugins remain transport-agnostic.
15
+ */
16
+
17
+ export { executeAiInstruction } from './execute'