@vinaverse/client 0.0.0-stage → 0.1.0-alpha.10

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 (49) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +202 -2
  3. package/dist/agent/index.cjs +3319 -0
  4. package/dist/agent/index.cjs.map +1 -0
  5. package/dist/agent/index.d.cts +57 -0
  6. package/dist/agent/index.d.ts +57 -0
  7. package/dist/agent/index.js +99 -0
  8. package/dist/agent/index.js.map +1 -0
  9. package/dist/backend/index.cjs +268 -0
  10. package/dist/backend/index.cjs.map +1 -0
  11. package/dist/backend/index.d.cts +72 -0
  12. package/dist/backend/index.d.ts +72 -0
  13. package/dist/backend/index.js +250 -0
  14. package/dist/backend/index.js.map +1 -0
  15. package/dist/chunk-46D3FSLU.js +997 -0
  16. package/dist/chunk-46D3FSLU.js.map +1 -0
  17. package/dist/chunk-GWLLUOFY.js +1374 -0
  18. package/dist/chunk-GWLLUOFY.js.map +1 -0
  19. package/dist/chunk-O3NLAZGZ.js +859 -0
  20. package/dist/chunk-O3NLAZGZ.js.map +1 -0
  21. package/dist/chunk-YNUHXJD6.js +9 -0
  22. package/dist/chunk-YNUHXJD6.js.map +1 -0
  23. package/dist/contract-DmQs8amJ.d.cts +6 -0
  24. package/dist/contract-DmQs8amJ.d.ts +6 -0
  25. package/dist/conversation/index.cjs +2510 -0
  26. package/dist/conversation/index.cjs.map +1 -0
  27. package/dist/conversation/index.d.cts +65 -0
  28. package/dist/conversation/index.d.ts +65 -0
  29. package/dist/conversation/index.js +134 -0
  30. package/dist/conversation/index.js.map +1 -0
  31. package/dist/index.cjs +1390 -0
  32. package/dist/index.cjs.map +1 -0
  33. package/dist/index.d.cts +11 -0
  34. package/dist/index.d.ts +11 -0
  35. package/dist/index.js +4 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/runtime-CISPp9nJ.d.cts +371 -0
  38. package/dist/runtime-Z1RI10lU.d.ts +371 -0
  39. package/dist/session-CPz4pcPu.d.cts +3651 -0
  40. package/dist/session-CPz4pcPu.d.ts +3651 -0
  41. package/dist/store-BxiicOKG.d.cts +414 -0
  42. package/dist/store-DZka9T2-.d.ts +414 -0
  43. package/dist/testing/index.cjs +274 -0
  44. package/dist/testing/index.cjs.map +1 -0
  45. package/dist/testing/index.d.cts +60 -0
  46. package/dist/testing/index.d.ts +60 -0
  47. package/dist/testing/index.js +259 -0
  48. package/dist/testing/index.js.map +1 -0
  49. package/package.json +151 -3
@@ -0,0 +1,57 @@
1
+ import { S as Schemas, C as CardLink } from '../session-CPz4pcPu.cjs';
2
+ export { A as AgentBackend, a as AgentClock, b as AgentConversation, c as AgentConversationState, d as AgentEntryPoint, e as AgentEvent, f as AgentEventType, g as AgentFailure, h as AgentFailureReason, i as AgentInsecureAddresses, j as AgentKey, k as AgentPlace, l as AgentRating, m as AgentRefusal, n as AgentRetryPolicy, o as AgentRuntime, p as AgentRuntimeOptions, q as AgentSessionRequest, r as AgentStatus, s as AgentStatusRead, t as AgentStatusState, u as AgentWarning, v as agentKey, w as createAgentRuntime, x as greetedKey, y as hashKey, z as isRefusal } from '../runtime-CISPp9nJ.cjs';
3
+ import '../store-BxiicOKG.cjs';
4
+
5
+ /** An amount in minor units with its ISO 4217 currency. */
6
+ interface AgentMoney {
7
+ readonly amount: number;
8
+ readonly currency: string;
9
+ }
10
+ interface AgentCardAction {
11
+ readonly action: string;
12
+ readonly label: string;
13
+ readonly deepLink: string | null;
14
+ }
15
+ /** What a card is about, as the tenant's tools name it: a UI routes a tap on the card here. */
16
+ interface AgentCardTarget {
17
+ readonly type: string;
18
+ readonly id: string;
19
+ }
20
+ interface ReadCard {
21
+ readonly id: string;
22
+ readonly kind: Schemas['Card']['kind'];
23
+ /** `professional` and `workspace`: drawn as a listing (photo, rating, price from, next open time). */
24
+ readonly listing: boolean;
25
+ readonly title: string;
26
+ readonly subtitle: string | null;
27
+ readonly body: string | null;
28
+ readonly badges: readonly string[];
29
+ readonly actions: readonly AgentCardAction[];
30
+ readonly target: AgentCardTarget | null;
31
+ /** The hero photo: the first https image, else `image_url`; `ratio` is width / height when both are known. */
32
+ readonly hero: {
33
+ readonly url: string;
34
+ readonly ratio: number | null;
35
+ } | null;
36
+ readonly rating: {
37
+ readonly stars: number;
38
+ readonly count: number;
39
+ } | null;
40
+ readonly priceFrom: AgentMoney | null;
41
+ readonly price: AgentMoney | null;
42
+ readonly nextAvailable: string | null;
43
+ readonly startsAt: string | null;
44
+ /** Cards one turn draws together; `carousel` draws them in a row, anything else a list. */
45
+ readonly group: {
46
+ readonly id: string;
47
+ readonly layout: 'list' | 'carousel';
48
+ } | null;
49
+ /** A `links` card's links, each with a label of at most 40 code points and a known purpose. */
50
+ readonly links: readonly CardLink[];
51
+ /** A `proposal` card's proposal id. */
52
+ readonly proposalId: string | null;
53
+ }
54
+ /** The contract's card (a `HeldCard`'s `card`, or a frame's), read for drawing; null for a kind this client skips. */
55
+ declare function readCard(value: unknown): ReadCard | null;
56
+
57
+ export { type AgentCardAction, type AgentCardTarget, type AgentMoney, type ReadCard, readCard };
@@ -0,0 +1,57 @@
1
+ import { S as Schemas, C as CardLink } from '../session-CPz4pcPu.js';
2
+ export { A as AgentBackend, a as AgentClock, b as AgentConversation, c as AgentConversationState, d as AgentEntryPoint, e as AgentEvent, f as AgentEventType, g as AgentFailure, h as AgentFailureReason, i as AgentInsecureAddresses, j as AgentKey, k as AgentPlace, l as AgentRating, m as AgentRefusal, n as AgentRetryPolicy, o as AgentRuntime, p as AgentRuntimeOptions, q as AgentSessionRequest, r as AgentStatus, s as AgentStatusRead, t as AgentStatusState, u as AgentWarning, v as agentKey, w as createAgentRuntime, x as greetedKey, y as hashKey, z as isRefusal } from '../runtime-Z1RI10lU.js';
3
+ import '../store-DZka9T2-.js';
4
+
5
+ /** An amount in minor units with its ISO 4217 currency. */
6
+ interface AgentMoney {
7
+ readonly amount: number;
8
+ readonly currency: string;
9
+ }
10
+ interface AgentCardAction {
11
+ readonly action: string;
12
+ readonly label: string;
13
+ readonly deepLink: string | null;
14
+ }
15
+ /** What a card is about, as the tenant's tools name it: a UI routes a tap on the card here. */
16
+ interface AgentCardTarget {
17
+ readonly type: string;
18
+ readonly id: string;
19
+ }
20
+ interface ReadCard {
21
+ readonly id: string;
22
+ readonly kind: Schemas['Card']['kind'];
23
+ /** `professional` and `workspace`: drawn as a listing (photo, rating, price from, next open time). */
24
+ readonly listing: boolean;
25
+ readonly title: string;
26
+ readonly subtitle: string | null;
27
+ readonly body: string | null;
28
+ readonly badges: readonly string[];
29
+ readonly actions: readonly AgentCardAction[];
30
+ readonly target: AgentCardTarget | null;
31
+ /** The hero photo: the first https image, else `image_url`; `ratio` is width / height when both are known. */
32
+ readonly hero: {
33
+ readonly url: string;
34
+ readonly ratio: number | null;
35
+ } | null;
36
+ readonly rating: {
37
+ readonly stars: number;
38
+ readonly count: number;
39
+ } | null;
40
+ readonly priceFrom: AgentMoney | null;
41
+ readonly price: AgentMoney | null;
42
+ readonly nextAvailable: string | null;
43
+ readonly startsAt: string | null;
44
+ /** Cards one turn draws together; `carousel` draws them in a row, anything else a list. */
45
+ readonly group: {
46
+ readonly id: string;
47
+ readonly layout: 'list' | 'carousel';
48
+ } | null;
49
+ /** A `links` card's links, each with a label of at most 40 code points and a known purpose. */
50
+ readonly links: readonly CardLink[];
51
+ /** A `proposal` card's proposal id. */
52
+ readonly proposalId: string | null;
53
+ }
54
+ /** The contract's card (a `HeldCard`'s `card`, or a frame's), read for drawing; null for a kind this client skips. */
55
+ declare function readCard(value: unknown): ReadCard | null;
56
+
57
+ export { type AgentCardAction, type AgentCardTarget, type AgentMoney, type ReadCard, readCard };
@@ -0,0 +1,99 @@
1
+ export { AgentRefusal, agentKey, createAgentRuntime, greetedKey, hashKey, isRefusal } from '../chunk-O3NLAZGZ.js';
2
+ import '../chunk-46D3FSLU.js';
3
+ import { isKnownCard } from '../chunk-GWLLUOFY.js';
4
+
5
+ // src/agent/cards.ts
6
+ var LISTING = /* @__PURE__ */ new Set(["professional", "workspace"]);
7
+ var PURPOSES = /* @__PURE__ */ new Set(["help", "support", "policy", "contact", "feedback"]);
8
+ var GROUP_ID = /^[A-Za-z0-9_-]{1,64}$/;
9
+ var CURRENCY = /^[A-Z]{3}$/;
10
+ var isFields = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
11
+ var text = (v) => typeof v === "string" ? v : null;
12
+ var whole = (v) => typeof v === "number" && Number.isInteger(v) ? v : null;
13
+ var list = (v) => Array.isArray(v) ? v : [];
14
+ var https = (v) => {
15
+ const url = text(v);
16
+ return url !== null && /^https:\/\//i.test(url) ? url : null;
17
+ };
18
+ var instant = (v) => {
19
+ const at = text(v);
20
+ return at !== null && !Number.isNaN(Date.parse(at)) ? at : null;
21
+ };
22
+ function money(v) {
23
+ if (!isFields(v)) return null;
24
+ const amount = whole(v.amount);
25
+ const currency = text(v.currency);
26
+ return amount !== null && amount >= 0 && currency !== null && CURRENCY.test(currency) ? { amount, currency } : null;
27
+ }
28
+ function hero(card) {
29
+ for (const image of list(card.images)) {
30
+ if (!isFields(image)) continue;
31
+ const url = https(image.url);
32
+ if (url === null) continue;
33
+ const width = whole(image.width);
34
+ const height = whole(image.height);
35
+ return {
36
+ url,
37
+ ratio: width && height && width > 0 && height > 0 ? width / height : null
38
+ };
39
+ }
40
+ const legacy = https(card.image_url);
41
+ return legacy === null ? null : { url: legacy, ratio: null };
42
+ }
43
+ function readCard(value) {
44
+ if (!isFields(value)) return null;
45
+ const id = text(value.id);
46
+ const kind = text(value.kind);
47
+ const title = text(value.title);
48
+ if (id === null || kind === null || title === null) return null;
49
+ if (!isKnownCard({ kind })) return null;
50
+ const rating = isFields(value.rating) ? value.rating : null;
51
+ const ppm = whole(rating?.value_ppm);
52
+ const count = whole(rating?.count);
53
+ const group = isFields(value.group) ? value.group : null;
54
+ const groupId = text(group?.id);
55
+ const ref = isFields(value.ref) ? value.ref : null;
56
+ const refType = text(ref?.type);
57
+ const refId = text(ref?.id);
58
+ const proposal = isFields(value.proposal) ? value.proposal : null;
59
+ return {
60
+ id,
61
+ kind,
62
+ listing: LISTING.has(kind),
63
+ title,
64
+ subtitle: text(value.subtitle),
65
+ body: text(value.body),
66
+ badges: list(value.badges).filter(
67
+ (b) => typeof b === "string"
68
+ ),
69
+ actions: list(value.actions).flatMap((a) => {
70
+ if (!isFields(a)) return [];
71
+ const action = text(a.action);
72
+ const label = text(a.label);
73
+ return action === null || label === null ? [] : [{ action, label, deepLink: text(a.deep_link) }];
74
+ }),
75
+ target: refType !== null && refId !== null ? { type: refType, id: refId } : null,
76
+ hero: hero(value),
77
+ rating: ppm !== null && count !== null && ppm >= 0 && ppm <= 5e6 && count >= 0 ? { stars: ppm / 1e6, count } : null,
78
+ priceFrom: money(value.price_from),
79
+ price: money(value.price),
80
+ nextAvailable: instant(value.next_available),
81
+ startsAt: instant(value.starts_at),
82
+ group: groupId !== null && GROUP_ID.test(groupId) ? {
83
+ id: groupId,
84
+ layout: group?.layout === "carousel" ? "carousel" : "list"
85
+ } : null,
86
+ links: list(value.links).flatMap((l) => {
87
+ if (!isFields(l)) return [];
88
+ const label = text(l.label);
89
+ const url = text(l.url)?.trim() ?? "";
90
+ const purpose = text(l.purpose);
91
+ return label && [...label].length <= 40 && url && purpose && PURPOSES.has(purpose) ? [{ label, url, purpose }] : [];
92
+ }),
93
+ proposalId: kind === "proposal" ? text(proposal?.id) : null
94
+ };
95
+ }
96
+
97
+ export { readCard };
98
+ //# sourceMappingURL=index.js.map
99
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/agent/cards.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// A card as a UI draws it: the contract's card read once, every field checked, so a renderer never meets a bad value\n// (a photo that is not https, a rating out of range, a group id the contract would refuse). A kind this client does not\n// know is null: the UI skips it (§5).\nimport type { CardLink, Schemas } from '../events.js';\nimport { isKnownCard } from '../events.js';\n\ntype Fields = Readonly<Record<string, unknown>>;\n\n/** An amount in minor units with its ISO 4217 currency. */\nexport interface AgentMoney {\n readonly amount: number;\n readonly currency: string;\n}\n\nexport interface AgentCardAction {\n readonly action: string;\n readonly label: string;\n readonly deepLink: string | null;\n}\n\n/** What a card is about, as the tenant's tools name it: a UI routes a tap on the card here. */\nexport interface AgentCardTarget {\n readonly type: string;\n readonly id: string;\n}\n\nexport interface ReadCard {\n readonly id: string;\n readonly kind: Schemas['Card']['kind'];\n /** `professional` and `workspace`: drawn as a listing (photo, rating, price from, next open time). */\n readonly listing: boolean;\n readonly title: string;\n readonly subtitle: string | null;\n readonly body: string | null;\n readonly badges: readonly string[];\n readonly actions: readonly AgentCardAction[];\n readonly target: AgentCardTarget | null;\n /** The hero photo: the first https image, else `image_url`; `ratio` is width / height when both are known. */\n readonly hero: { readonly url: string; readonly ratio: number | null } | null;\n readonly rating: { readonly stars: number; readonly count: number } | null;\n readonly priceFrom: AgentMoney | null;\n readonly price: AgentMoney | null;\n readonly nextAvailable: string | null;\n readonly startsAt: string | null;\n /** Cards one turn draws together; `carousel` draws them in a row, anything else a list. */\n readonly group: {\n readonly id: string;\n readonly layout: 'list' | 'carousel';\n } | null;\n /** A `links` card's links, each with a label of at most 40 code points and a known purpose. */\n readonly links: readonly CardLink[];\n /** A `proposal` card's proposal id. */\n readonly proposalId: string | null;\n}\n\nconst LISTING = new Set(['professional', 'workspace']);\nconst PURPOSES = new Set(['help', 'support', 'policy', 'contact', 'feedback']);\nconst GROUP_ID = /^[A-Za-z0-9_-]{1,64}$/;\nconst CURRENCY = /^[A-Z]{3}$/;\n\nconst isFields = (v: unknown): v is Fields =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\nconst text = (v: unknown): string | null => (typeof v === 'string' ? v : null);\nconst whole = (v: unknown): number | null =>\n typeof v === 'number' && Number.isInteger(v) ? v : null;\nconst list = (v: unknown): readonly unknown[] => (Array.isArray(v) ? v : []);\nconst https = (v: unknown): string | null => {\n const url = text(v);\n return url !== null && /^https:\\/\\//i.test(url) ? url : null;\n};\nconst instant = (v: unknown): string | null => {\n const at = text(v);\n return at !== null && !Number.isNaN(Date.parse(at)) ? at : null;\n};\n\nfunction money(v: unknown): AgentMoney | null {\n if (!isFields(v)) return null;\n const amount = whole(v.amount);\n const currency = text(v.currency);\n return amount !== null &&\n amount >= 0 &&\n currency !== null &&\n CURRENCY.test(currency)\n ? { amount, currency }\n : null;\n}\n\nfunction hero(card: Fields): ReadCard['hero'] {\n for (const image of list(card.images)) {\n if (!isFields(image)) continue;\n const url = https(image.url);\n if (url === null) continue;\n const width = whole(image.width);\n const height = whole(image.height);\n return {\n url,\n ratio: width && height && width > 0 && height > 0 ? width / height : null,\n };\n }\n const legacy = https(card.image_url);\n return legacy === null ? null : { url: legacy, ratio: null };\n}\n\n/** The contract's card (a `HeldCard`'s `card`, or a frame's), read for drawing; null for a kind this client skips. */\nexport function readCard(value: unknown): ReadCard | null {\n if (!isFields(value)) return null;\n const id = text(value.id);\n const kind = text(value.kind);\n const title = text(value.title);\n if (id === null || kind === null || title === null) return null;\n if (!isKnownCard({ kind })) return null;\n const rating = isFields(value.rating) ? value.rating : null;\n const ppm = whole(rating?.value_ppm);\n const count = whole(rating?.count);\n const group = isFields(value.group) ? value.group : null;\n const groupId = text(group?.id);\n const ref = isFields(value.ref) ? value.ref : null;\n const refType = text(ref?.type);\n const refId = text(ref?.id);\n const proposal = isFields(value.proposal) ? value.proposal : null;\n return {\n id,\n kind: kind as ReadCard['kind'],\n listing: LISTING.has(kind),\n title,\n subtitle: text(value.subtitle),\n body: text(value.body),\n badges: list(value.badges).filter(\n (b): b is string => typeof b === 'string',\n ),\n actions: list(value.actions).flatMap((a) => {\n if (!isFields(a)) return [];\n const action = text(a.action);\n const label = text(a.label);\n return action === null || label === null\n ? []\n : [{ action, label, deepLink: text(a.deep_link) }];\n }),\n target:\n refType !== null && refId !== null ? { type: refType, id: refId } : null,\n hero: hero(value),\n rating:\n ppm !== null &&\n count !== null &&\n ppm >= 0 &&\n ppm <= 5_000_000 &&\n count >= 0\n ? { stars: ppm / 1_000_000, count }\n : null,\n priceFrom: money(value.price_from),\n price: money(value.price),\n nextAvailable: instant(value.next_available),\n startsAt: instant(value.starts_at),\n group:\n groupId !== null && GROUP_ID.test(groupId)\n ? {\n id: groupId,\n layout: group?.layout === 'carousel' ? 'carousel' : 'list',\n }\n : null,\n links: list(value.links).flatMap((l) => {\n if (!isFields(l)) return [];\n const label = text(l.label);\n const url = text(l.url)?.trim() ?? '';\n const purpose = text(l.purpose);\n return label &&\n [...label].length <= 40 &&\n url &&\n purpose &&\n PURPOSES.has(purpose)\n ? [{ label, url, purpose: purpose as CardLink['purpose'] }]\n : [];\n }),\n proposalId: kind === 'proposal' ? text(proposal?.id) : null,\n };\n}\n"]}
@@ -0,0 +1,268 @@
1
+ 'use strict';
2
+
3
+ // src/agent/runtime.ts
4
+ var AgentRefusal = class extends Error {
5
+ constructor(kind, options = {}) {
6
+ super(
7
+ options.message ?? (kind === "ended" ? "The conversation is over." : "No agent now.")
8
+ );
9
+ this.kind = kind;
10
+ this.name = "AgentRefusal";
11
+ this.reason = options.reason ?? (kind === "ended" ? "ended" : "unknown");
12
+ this.code = options.code ?? null;
13
+ }
14
+ kind;
15
+ reason;
16
+ code;
17
+ };
18
+
19
+ // src/backend/index.ts
20
+ var OUTCOMES = {
21
+ conversation_not_found: { status: 404, client: "end", reason: "not_found" },
22
+ conversation_expired: { status: 410, client: "end", reason: "expired" },
23
+ conversation_mismatch: { status: 409, client: "end", reason: "mismatch" },
24
+ conversation_completed: { status: 409, client: "end", reason: "completed" },
25
+ session_closed: { status: 409, client: "rollover", reason: "ended" },
26
+ feature_off: { status: 403, client: "off", reason: "off" },
27
+ rate_limited: { status: 429, client: "wait", reason: "rate_limited" },
28
+ unauthorized: { status: 401, client: "sign_in", reason: "auth" },
29
+ forbidden_ownership: { status: 403, client: "refuse", reason: "forbidden" },
30
+ context_conflict: { status: 409, client: "resend", reason: "conflict" },
31
+ unavailable: { status: 503, client: "retry", reason: "server" },
32
+ unknown_open: { status: 409, client: "keep_open_id", reason: "unknown_open" }
33
+ };
34
+ var header = (headers, name) => {
35
+ if (!headers) return null;
36
+ if (typeof headers.get === "function")
37
+ return headers.get(name);
38
+ const found = Object.entries(headers).find(
39
+ ([k]) => k.toLowerCase() === name.toLowerCase()
40
+ );
41
+ return found ? found[1] : null;
42
+ };
43
+ function uncappedRetryAfterMs(body, headers) {
44
+ const given = body?.retry_after;
45
+ if (typeof given === "number" && given >= 0) return given * 1e3;
46
+ const raw = header(headers, "retry-after");
47
+ if (!raw) return void 0;
48
+ const seconds = Number(raw);
49
+ if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
50
+ const at = Date.parse(raw);
51
+ return Number.isNaN(at) ? void 0 : Math.max(0, at - Date.now());
52
+ }
53
+ function parsed(body) {
54
+ let value = body;
55
+ if (typeof value === "string") {
56
+ try {
57
+ value = JSON.parse(value);
58
+ } catch {
59
+ return null;
60
+ }
61
+ }
62
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
63
+ }
64
+ function unreachable(reason, extra, message) {
65
+ return Object.assign(new Error(message), {
66
+ name: "AgentUnreachable",
67
+ retryable: true,
68
+ reason,
69
+ ...extra
70
+ });
71
+ }
72
+ function decodeBackendFailure(status, body, headers) {
73
+ if (typeof status !== "number")
74
+ return unreachable(
75
+ "network",
76
+ { outcome: "unavailable" },
77
+ status instanceof Error ? status.message : "No answer from the backend."
78
+ );
79
+ const json = parsed(body);
80
+ const named = json?.version === 1 ? json.outcome : void 0;
81
+ const known = typeof named === "string" && Object.hasOwn(OUTCOMES, named) && OUTCOMES[named].status === status ? named : null;
82
+ const outcome = known ?? (status === 401 ? "unauthorized" : status === 429 ? "rate_limited" : "unavailable");
83
+ const retryable = known ? outcome === "rate_limited" || outcome === "unavailable" && json?.retryable === true : status === 429 || status === 408 || status >= 500;
84
+ const wait = retryAfterMs(known ? json : null, headers);
85
+ const extra = {
86
+ status,
87
+ outcome,
88
+ ...known && typeof json?.code === "string" ? { gatewayCode: json.code } : {},
89
+ ...known && typeof json?.open_id === "string" ? { openId: json.open_id } : {},
90
+ ...known === "context_conflict" && typeof json?.current_revision === "number" ? { currentRevision: json.current_revision } : {},
91
+ ...wait !== void 0 ? { retryAfterMs: wait } : {}
92
+ };
93
+ const message = `Backend answered ${status} (${outcome}).`;
94
+ const { client, reason } = OUTCOMES[outcome];
95
+ const said = known || outcome !== "unavailable" || retryable ? reason : "unknown";
96
+ if (retryable) return unreachable(said, extra, message);
97
+ return Object.assign(
98
+ new AgentRefusal(
99
+ client === "end" || client === "rollover" ? "ended" : "unavailable",
100
+ {
101
+ reason: said,
102
+ code: outcome,
103
+ message
104
+ }
105
+ ),
106
+ extra,
107
+ { retryable: false }
108
+ );
109
+ }
110
+ function backendRoutes(base) {
111
+ const at = (path) => `${base.replace(/\/$/, "")}/vinaverse/agent/${path}`;
112
+ return {
113
+ session: at("session"),
114
+ refresh: at("session/refresh"),
115
+ status: at("status"),
116
+ feedback: at("feedback"),
117
+ end: at("end"),
118
+ context: at("context"),
119
+ delete: at("conversations/{conversation_id}")
120
+ };
121
+ }
122
+ var screenContext = (place, revision) => place ? {
123
+ screen: place.screen,
124
+ ...place.entity ? { entity: place.entity } : {},
125
+ ...place.filters ? { filters: place.filters } : {},
126
+ revision
127
+ } : null;
128
+ function backendFromFetch(options) {
129
+ const { routes } = options;
130
+ const doFetch = options.fetch ?? ((input, init) => fetch(input, init));
131
+ const call = async (method, url, body, field, signal) => {
132
+ let response;
133
+ try {
134
+ response = await doFetch(url, {
135
+ method,
136
+ headers: {
137
+ accept: "application/json",
138
+ ...body === void 0 ? {} : { "content-type": "application/json" },
139
+ ...await options.headers?.()
140
+ },
141
+ ...body === void 0 ? {} : { body: JSON.stringify(body) },
142
+ ...signal ? { signal } : {}
143
+ });
144
+ } catch (error) {
145
+ throw decodeBackendFailure(error);
146
+ }
147
+ const text = await response.text().catch(() => "");
148
+ if (!response.ok)
149
+ throw decodeBackendFailure(response.status, text, response.headers);
150
+ if (!field) return void 0;
151
+ const got = parsed(text);
152
+ if (got?.version !== 1 || typeof got[field] !== "object" || !got[field])
153
+ throw decodeBackendFailure(response.status, text, response.headers);
154
+ return got[field];
155
+ };
156
+ const backend = {
157
+ openSession: async (request) => await call(
158
+ "POST",
159
+ routes.session,
160
+ {
161
+ open_id: request.openId,
162
+ conversation_id: request.conversationId,
163
+ reason: request.reason,
164
+ mode: request.key.mode,
165
+ scope: request.key.scope ?? null,
166
+ thread: request.key.thread ?? "chat",
167
+ agent: request.agent,
168
+ screen_context: screenContext(request.place, request.placeRevision),
169
+ entry_point: request.entryPoint,
170
+ ...request.locale !== void 0 ? { locale: request.locale } : {},
171
+ ...request.timeZone !== void 0 ? { time_zone: request.timeZone } : {}
172
+ },
173
+ "session",
174
+ request.signal
175
+ )
176
+ };
177
+ const { refresh, status, feedback, end, context } = routes;
178
+ const remove = routes.delete;
179
+ return {
180
+ ...backend,
181
+ ...refresh ? {
182
+ async refreshSecret(sessionId) {
183
+ const s = await call(
184
+ "POST",
185
+ refresh,
186
+ { session_id: sessionId },
187
+ "client_secret"
188
+ );
189
+ if (typeof s.value !== "string" || typeof s.expires_at !== "string")
190
+ throw decodeBackendFailure(200);
191
+ return { value: s.value, expires_at: s.expires_at };
192
+ }
193
+ } : {},
194
+ ...status ? {
195
+ async status(signal) {
196
+ const s = await call(
197
+ "GET",
198
+ status,
199
+ void 0,
200
+ "status",
201
+ signal
202
+ );
203
+ const f = s.features ?? {};
204
+ const name = typeof s.display_name === "string" ? s.display_name : null;
205
+ const avatar = typeof s.avatar_url === "string" ? s.avatar_url : null;
206
+ return {
207
+ available: s.available === true,
208
+ launcher: s.launcher === true,
209
+ displayName: name,
210
+ avatarUrl: avatar,
211
+ features: {
212
+ history: f.history === true,
213
+ memory: f.memory === true,
214
+ businessAgent: f.business_agent === true,
215
+ businessSetup: f.business_setup === true
216
+ }
217
+ };
218
+ }
219
+ } : {},
220
+ ...feedback ? {
221
+ async sendFeedback(given) {
222
+ await call("POST", feedback, {
223
+ session_id: given.sessionId,
224
+ turn_id: given.turnId,
225
+ rating: given.rating
226
+ });
227
+ }
228
+ } : {},
229
+ ...end ? {
230
+ async endSessions() {
231
+ await call("POST", end, {});
232
+ }
233
+ } : {},
234
+ ...remove ? {
235
+ async deleteConversation(conversationId) {
236
+ await call(
237
+ "DELETE",
238
+ remove.replace(
239
+ "{conversation_id}",
240
+ encodeURIComponent(conversationId)
241
+ ),
242
+ void 0
243
+ );
244
+ }
245
+ } : {},
246
+ ...context ? {
247
+ async updateContext(sessionId, place, revision) {
248
+ await call("PUT", context, {
249
+ session_id: sessionId,
250
+ screen_context: screenContext(place, revision)
251
+ });
252
+ }
253
+ } : {}
254
+ };
255
+ }
256
+ var MAX_RETRY_AFTER_MS = 6e4;
257
+ function retryAfterMs(body, headers) {
258
+ const ms = uncappedRetryAfterMs(body, headers);
259
+ return ms === void 0 ? void 0 : Math.min(ms, MAX_RETRY_AFTER_MS);
260
+ }
261
+
262
+ exports.MAX_RETRY_AFTER_MS = MAX_RETRY_AFTER_MS;
263
+ exports.OUTCOMES = OUTCOMES;
264
+ exports.backendFromFetch = backendFromFetch;
265
+ exports.backendRoutes = backendRoutes;
266
+ exports.decodeBackendFailure = decodeBackendFailure;
267
+ //# sourceMappingURL=index.cjs.map
268
+ //# sourceMappingURL=index.cjs.map