@v-office/website-chat 0.0.0 → 1.0.1

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,46 @@
1
+ import { Spec } from "@json-render/core";
2
+ //#region src/protocol.d.ts
3
+ /** The languages the chat speaks; the widget's `locale` picks one. */
4
+ declare const CHAT_LOCALES: readonly ["de", "en"];
5
+ type ChatLocale = (typeof CHAT_LOCALES)[number];
6
+ /** The path both requests go to, below the service's endpoint. */
7
+ declare const CHAT_PATH = "/v1/chat";
8
+ /** Longest visitor message the service takes. */
9
+ declare const MAX_MESSAGE_CHARS = 2000;
10
+ /** How long the service keeps a conversation after its last message. The widget forgets its own copy
11
+ * after the same time, so it never shows a conversation the service no longer knows. */
12
+ declare const SESSION_TTL_S: number;
13
+ /** `GET <endpoint>/v1/chat`. */
14
+ interface ChatAvailability {
15
+ readonly available: boolean;
16
+ }
17
+ /** `POST <endpoint>/v1/chat`. */
18
+ interface ChatRequest {
19
+ /** The session the service answered with; `null` for the first message. */
20
+ readonly sessionId: string | null;
21
+ readonly message: string;
22
+ readonly locale: ChatLocale;
23
+ /** The widget's package version: the service offers only components it can render. */
24
+ readonly clientVersion: string;
25
+ }
26
+ /** Why the chat cannot answer: switched off, its budget spent, a reply still running, too many
27
+ * messages, or anything else. The widget shows its fallback (search and contact links). */
28
+ type ChatUnavailableReason = "off" | "budget" | "busy" | "limit" | "error";
29
+ /** One server-sent event (`event: <type>`, `data: <json>`), in order. */
30
+ type ChatEvent = {
31
+ readonly type: "session";
32
+ readonly sessionId: string;
33
+ } | {
34
+ readonly type: "text";
35
+ readonly delta: string;
36
+ } | {
37
+ readonly type: "ui";
38
+ readonly spec: Spec;
39
+ } | {
40
+ readonly type: "done";
41
+ } | {
42
+ readonly type: "unavailable";
43
+ readonly reason: ChatUnavailableReason;
44
+ };
45
+ //#endregion
46
+ export { ChatLocale as a, MAX_MESSAGE_CHARS as c, ChatEvent as i, SESSION_TTL_S as l, CHAT_PATH as n, ChatRequest as o, ChatAvailability as r, ChatUnavailableReason as s, CHAT_LOCALES as t };
@@ -0,0 +1,12 @@
1
+ //#region src/protocol.ts
2
+ /** The languages the chat speaks; the widget's `locale` picks one. */
3
+ const CHAT_LOCALES = ["de", "en"];
4
+ /** The path both requests go to, below the service's endpoint. */
5
+ const CHAT_PATH = "/v1/chat";
6
+ /** Longest visitor message the service takes. */
7
+ const MAX_MESSAGE_CHARS = 2e3;
8
+ /** How long the service keeps a conversation after its last message. The widget forgets its own copy
9
+ * after the same time, so it never shows a conversation the service no longer knows. */
10
+ const SESSION_TTL_S = 7200;
11
+ //#endregion
12
+ export { SESSION_TTL_S as i, CHAT_PATH as n, MAX_MESSAGE_CHARS as r, CHAT_LOCALES as t };
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ <!-- generated by `node .github/release/cli.mts index`; do not edit by hand -->
4
+
5
+ Release notes of `@v-office/website-chat`, newest first. Each version has its own directory.
6
+
7
+ - `versions/1.0.1/CHANGELOG.md`: release notes for 1.0.1
8
+ - `versions/1.0.0/CHANGELOG.md`: release notes for 1.0.0
@@ -0,0 +1,8 @@
1
+ # Migration
2
+
3
+ <!-- generated by `node .github/release/cli.mts index`; do not edit by hand -->
4
+
5
+ Migration guides of `@v-office/website-chat`, newest first. Apply them in order when skipping versions.
6
+
7
+ - `versions/1.0.1/MIGRATION.md`: Migration: 1.0.0 to 1.0.1
8
+ - `versions/1.0.0/MIGRATION.md`: Migration: 1.0.0
@@ -0,0 +1,37 @@
1
+ # Changelog: 1.0.0
2
+
3
+ The first release: the AI chat of a v-office website. A visitor asks for a stay; the chat searches the
4
+ agency's rentals, shows them as cards with the PMS's prices, and links each stay to its rental page with
5
+ the dates and party filled in, where the site's own Quote and checkout take over. The chat never books
6
+ and has no form of its own.
7
+
8
+ ## Added
9
+
10
+ - `WebsiteChat`, rendered in a Shadow DOM so the site's CSS and the chat's cannot affect each other. It
11
+ asks the chat service whether the website's chat is on and renders nothing otherwise.
12
+ - An entry pill in the corner of every page, frosted glass with a ring running round it until the
13
+ visitor has asked something. On a phone it is one tap; on a wide screen the visitor types into it.
14
+ Once a conversation exists it offers to continue it.
15
+ - The panel loads on the first open: a card at the screen's edge over the dimmed page, a sheet from
16
+ the bottom on a phone. Start suggestions, a waiting indicator, results side by side where there is
17
+ room, a button for a new conversation.
18
+ - The conversation follows the visitor from page to page within the tab, for as long as the chat
19
+ service keeps it (two hours after the last message), so a link from the chat to a rental page
20
+ does not lose it.
21
+ - A start step: nothing is sent to the AI provider before the visitor reads what the chat does and
22
+ presses "Start chat". A message typed into the entry pill waits there until then.
23
+ - Looks: three template themes (`classic`, `soft`, `minimal`), the site's `primary` and `secondary`
24
+ colours, the pill and panel on the `right` or `left`, the site's font, and `--chat-top` /
25
+ `--chat-width` for a sticky header and a wider panel.
26
+ - Copy in German and English (`DEFAULT_COPY`), each string overridable through `copy`.
27
+ - `./catalog`: the components the chat service places and the wire protocol. Sites do not import it.
28
+ - Rentals: `RentalCard` (photo gallery, rating, facts, the visitor's wishes the search that found it applied),
29
+ `RentalCarousel` (several cards side by side, swipeable), `Compare` (two or three rentals column
30
+ by column), `ReviewSummary` (the PMS's rating, grade, category ratings and a few review texts),
31
+ `RentalFacts` (a rental's facts in the PMS's groups), `RentalMap` (where it is; the map loads
32
+ from OpenFreeMap only when the visitor taps it).
33
+ - Stays: `StayQuote`, `PriceBreakdown` (the quote's lines and total), `AlternativeStays` (other
34
+ free periods as tappable choices), `AvailabilityCalendar` (free and taken days by month),
35
+ `PriceCalendar` (the total at the arrivals around the asked one, cheapest marked).
36
+ - Actions: `StayLink`, `ContactLink`, `QuickReplies` (short answers a visitor taps to send).
37
+ Every figure in them comes from the PMS; the AI places them by id only.
@@ -0,0 +1,51 @@
1
+ # Migration: 1.0.0
2
+
3
+ A new package: nothing to migrate. To add the chat to a site:
4
+
5
+ ## 1. Install
6
+
7
+ ```sh
8
+ pnpm add --save-exact @v-office/website-chat@1.0.0
9
+ ```
10
+
11
+ Its peers are React `^19.2.3` and `@v-office/website-headless` 1.1 or later, which a site with the
12
+ platform components has.
13
+
14
+ ## 2. Render it once, in the layout
15
+
16
+ ```astro
17
+ ---
18
+ import { WebsiteChat } from "@v-office/website-chat";
19
+ ---
20
+ <WebsiteChat
21
+ client:idle
22
+ endpoint={import.meta.env.PUBLIC_CHAT_ENDPOINT}
23
+ locale="de"
24
+ searchPath="/suche"
25
+ contactPath="/kontakt"
26
+ />
27
+ ```
28
+
29
+ - `endpoint` is the AI Studio chat service of the site's environment. AI Studio's builds set
30
+ `PUBLIC_CHAT_ENDPOINT` to it: pass it as shown and keep no value in the site's `.env`. Without it
31
+ (a build outside AI Studio) the widget renders nothing.
32
+ - `searchPath` and `contactPath` are the site's own routes: the chat links a rental without a page to the
33
+ search, and sends a visitor who wants to write to the contact page.
34
+ - Optional: `theme` (`"classic"`, `"soft"`, `"minimal"`), `colors={{ primary, secondary }}`,
35
+ `position` (`"right"` or `"left"`), `copy` (overrides of single fields of `DEFAULT_COPY`: a string, or the `suggestions` list).
36
+ - A site with a sticky header sets its height as `--chat-top` on an element around the widget (for
37
+ example `:root { --chat-top: 72px; }`), so the panel and the dimmed page start below the header.
38
+ - With Astro's `<ClientRouter />`, add `transition:persist="website-chat"` so a reply still being
39
+ written keeps going across page transitions. The panel closes on a page change either way, as on a
40
+ full page load, and the next page offers to continue the conversation.
41
+
42
+ ## 3. Consent
43
+
44
+ The chat sends what a visitor types to an AI provider, so nothing is sent before the visitor reads
45
+ what that means and presses the chat's own "Start chat" button. The chat does not read the site's
46
+ consent manager; nothing to configure there.
47
+
48
+ ## 4. Switch it on
49
+
50
+ The chat stays hidden until an agent switches it on for the website in AI Studio (website settings,
51
+ "Website chat"). Switching it off hides it again without a rebuild.
@@ -0,0 +1,14 @@
1
+ # Changelog: 1.0.1
2
+
3
+ The chat's map card now shows its map. In 1.0.0, tapping "Karte laden" brought the button back
4
+ instead of a map on every site.
5
+
6
+ ## Fixed
7
+
8
+ - `RentalMap` loads MapLibre as bundlers hand it over: maplibre-gl ships a UMD bundle, which
9
+ arrives as the module's default export, and 1.0.0 looked for named exports only, so the map
10
+ could not start and the card offered its tap again.
11
+
12
+ ## Changed
13
+
14
+ - Nothing else. Props, copy and the map's tap-to-load behaviour are unchanged.
@@ -0,0 +1,9 @@
1
+ # Migration: 1.0.0 to 1.0.1
2
+
3
+ No changes required.
4
+
5
+ ## 1. Upgrade
6
+
7
+ ```sh
8
+ pnpm add --save-exact @v-office/website-chat@1.0.1
9
+ ```
package/package.json CHANGED
@@ -1,9 +1,68 @@
1
1
  {
2
2
  "name": "@v-office/website-chat",
3
- "version": "0.0.0",
4
- "description": "Placeholder that holds the name on npm until the first release",
3
+ "version": "1.0.1",
4
+ "description": "The AI chat of v-office websites: a launcher and a lazily loaded chat panel in a Shadow DOM, talking to the AI Studio chat service, and the json-render catalog (./catalog) the service places its rental cards, stays and links from. Styled through CSS custom properties and curated template themes; consumers need no Tailwind",
5
5
  "license": "UNLICENSED",
6
- "repository": { "type": "git", "url": "git+https://github.com/vofficeGmbh/ai-studio.git", "directory": "packages/website-chat" },
7
- "files": ["README.md"],
8
- "publishConfig": { "access": "public" }
9
- }
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/vofficeGmbh/ai-studio.git",
9
+ "directory": "packages/website-chat"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "instructions"
15
+ ],
16
+ "type": "module",
17
+ "sideEffects": false,
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": "./dist/index.js",
21
+ "./catalog": "./dist/catalog.js",
22
+ "./package.json": "./package.json"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "dependencies": {
28
+ "@json-render/core": "0.21.0",
29
+ "@json-render/react": "0.21.0",
30
+ "maplibre-gl": "^5.24.0",
31
+ "zod": "^4.3.6"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "26.5.1",
35
+ "@types/react": "19.3.0",
36
+ "@types/react-dom": "19.3.0",
37
+ "@v-office/website-headless": "1.1.1",
38
+ "@v-office/website-sdk": "2.34.0",
39
+ "jsdom": "30.0.1",
40
+ "oxfmt": "0.67.0",
41
+ "oxlint": "1.82.0",
42
+ "oxlint-plugin-react-doctor": "0.9.14",
43
+ "react": "19.3.0",
44
+ "react-dom": "19.3.0",
45
+ "tsdown": "0.23.0",
46
+ "typescript": "7.0.2",
47
+ "vitest": "5.0.0"
48
+ },
49
+ "peerDependencies": {
50
+ "@v-office/website-headless": ">=1.1.0 <2",
51
+ "react": "^19.2.3",
52
+ "react-dom": "^19.2.3"
53
+ },
54
+ "engines": {
55
+ "node": "^22.0.0 || ^24.0.0 || ^25.0.0 || >=26.0.0"
56
+ },
57
+ "scripts": {
58
+ "build": "tsdown",
59
+ "dev": "tsdown --watch",
60
+ "typecheck": "tsc --noEmit",
61
+ "lint": "oxlint .",
62
+ "lint:fix": "oxlint --fix .",
63
+ "fmt": "oxfmt",
64
+ "fmt:check": "oxfmt --check",
65
+ "check": "pnpm run typecheck && pnpm run lint && pnpm run fmt:check",
66
+ "test": "vitest run && node --test test/dist.node.mjs"
67
+ }
68
+ }