@vinaverse/client 0.1.0-alpha.3 → 0.1.0-alpha.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/dist/{chunk-AWHPWRGT.js → chunk-MKUNSAMT.js} +73 -11
- package/dist/chunk-MKUNSAMT.js.map +1 -0
- package/dist/conversation/index.cjs +198 -27
- package/dist/conversation/index.cjs.map +1 -1
- package/dist/conversation/index.d.cts +56 -5
- package/dist/conversation/index.d.ts +56 -5
- package/dist/conversation/index.js +130 -22
- package/dist/conversation/index.js.map +1 -1
- package/dist/index.cjs +70 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{session--W6JXfwo.d.cts → session-C3qZwGPG.d.cts} +130 -7
- package/dist/{session--W6JXfwo.d.ts → session-C3qZwGPG.d.ts} +130 -7
- package/package.json +4 -4
- package/dist/chunk-AWHPWRGT.js.map +0 -1
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// src/contract.ts
|
|
4
4
|
var CONTRACT = {
|
|
5
|
-
api: "v1-draft.
|
|
6
|
-
commit: "
|
|
5
|
+
api: "v1-draft.20",
|
|
6
|
+
commit: "5f6f41bdbfbdd6eadf21180eed1ffddfa5310355"
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
// src/errors.ts
|
|
@@ -36,7 +36,8 @@ var CARD_KINDS = {
|
|
|
36
36
|
document: true,
|
|
37
37
|
question: true,
|
|
38
38
|
proposal: true,
|
|
39
|
-
next_step: true
|
|
39
|
+
next_step: true,
|
|
40
|
+
links: true
|
|
40
41
|
};
|
|
41
42
|
function isKnownCard(card) {
|
|
42
43
|
return Object.hasOwn(CARD_KINDS, card.kind);
|
|
@@ -416,7 +417,9 @@ var ConversationEngine = class {
|
|
|
416
417
|
this.takeover = null;
|
|
417
418
|
this.cutOff("interrupted");
|
|
418
419
|
if (event.resumed !== true) return;
|
|
419
|
-
if (event.transcript !== void 0) {
|
|
420
|
+
if (event.transcript !== void 0 && transcriptHasIds(event.transcript)) {
|
|
421
|
+
this.mergeTranscript(asArray(event.transcript));
|
|
422
|
+
} else if (event.transcript !== void 0) {
|
|
420
423
|
this.messages = [];
|
|
421
424
|
this.replaced = this.cards;
|
|
422
425
|
this.cards = /* @__PURE__ */ new Map();
|
|
@@ -438,7 +441,61 @@ var ConversationEngine = class {
|
|
|
438
441
|
this.hold(card, str(card.turn_id));
|
|
439
442
|
this.replaced = null;
|
|
440
443
|
}
|
|
441
|
-
|
|
444
|
+
/**
|
|
445
|
+
* A transcript merged by key: an item the app holds keeps its place, with the text the server recorded; one it does
|
|
446
|
+
* not hold goes just after the nearest earlier item it does (just before the first later one when none came before,
|
|
447
|
+
* at the end when it holds none of them). Nothing the app holds is dropped.
|
|
448
|
+
*/
|
|
449
|
+
mergeTranscript(items) {
|
|
450
|
+
const seqOf = (key) => key === void 0 ? void 0 : (this.messages.find((m) => m.key === key) ?? this.cards.get(key))?.seq;
|
|
451
|
+
const keys = items.map(
|
|
452
|
+
(item) => item.role === "card" ? str(item.card?.id) : transcriptKey(str(item.role) ?? "", str(item.id), str(item.at))
|
|
453
|
+
);
|
|
454
|
+
let prev;
|
|
455
|
+
items.forEach((item, i) => {
|
|
456
|
+
const key = keys[i];
|
|
457
|
+
if (key === void 0) return;
|
|
458
|
+
const known = seqOf(key);
|
|
459
|
+
let at;
|
|
460
|
+
if (known === void 0) {
|
|
461
|
+
const near = prev ?? keys.slice(i + 1).map(seqOf).find((q) => q !== void 0);
|
|
462
|
+
if (near !== void 0) {
|
|
463
|
+
const seqs = [...this.messages, ...this.cards.values()].map(
|
|
464
|
+
(h) => h.seq
|
|
465
|
+
);
|
|
466
|
+
const bound = prev === void 0 ? Math.max(near - 1, ...seqs.filter((q) => q < near)) : Math.min(...seqs.filter((q) => q > near));
|
|
467
|
+
if (Number.isFinite(bound)) at = (near + bound) / 2;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
if (item.role === "card") this.hold(item.card, void 0, at);
|
|
471
|
+
else {
|
|
472
|
+
const text = str(item.text) ?? "";
|
|
473
|
+
const partial = item.interrupted === true ? "interrupted" : void 0;
|
|
474
|
+
if (known === void 0)
|
|
475
|
+
this.say(
|
|
476
|
+
str(item.role) ?? "",
|
|
477
|
+
text,
|
|
478
|
+
key,
|
|
479
|
+
partial ? { partial } : {},
|
|
480
|
+
at
|
|
481
|
+
);
|
|
482
|
+
else
|
|
483
|
+
this.messages = this.messages.map((m) => {
|
|
484
|
+
if (m.key !== key) return m;
|
|
485
|
+
const { partial: local, ...rest } = m;
|
|
486
|
+
const kept = partial ?? (local === "interrupted" ? void 0 : local);
|
|
487
|
+
return {
|
|
488
|
+
...rest,
|
|
489
|
+
text: text || m.text,
|
|
490
|
+
...kept ? { partial: kept } : {}
|
|
491
|
+
};
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
prev = seqOf(key);
|
|
495
|
+
});
|
|
496
|
+
this.messages.sort((a, b) => a.seq - b.seq);
|
|
497
|
+
}
|
|
498
|
+
hold(raw, turnId, at) {
|
|
442
499
|
if (!raw) return;
|
|
443
500
|
const id = str(raw.id);
|
|
444
501
|
if (id === void 0) return;
|
|
@@ -452,7 +509,7 @@ var ConversationEngine = class {
|
|
|
452
509
|
locked: lockedFrom(question),
|
|
453
510
|
...turnId !== void 0 ? { turnId } : {},
|
|
454
511
|
// A card still held keeps its place when it is drawn again (a reconnect's pending cards, a repeated ui.cards).
|
|
455
|
-
seq: this.cards.get(id)?.seq ?? this.seq++
|
|
512
|
+
seq: this.cards.get(id)?.seq ?? at ?? this.seq++
|
|
456
513
|
};
|
|
457
514
|
for (const held of this.held) {
|
|
458
515
|
const sent = this.inputs.get(held);
|
|
@@ -548,9 +605,9 @@ var ConversationEngine = class {
|
|
|
548
605
|
this.unqueue(id);
|
|
549
606
|
}
|
|
550
607
|
/** Adds a message once: a key already held (a frame seen twice) changes nothing. */
|
|
551
|
-
say(role, text, key, extra = {}, seq
|
|
608
|
+
say(role, text, key, extra = {}, seq) {
|
|
552
609
|
if (this.messages.some((m) => m.key === key)) return;
|
|
553
|
-
this.messages.push({ role, text, key, seq
|
|
610
|
+
this.messages.push({ role, text, key, seq: seq ?? this.seq++, ...extra });
|
|
554
611
|
}
|
|
555
612
|
/** The turn's streamed text, kept as the agent's message when the turn ends without its `message.completed`. */
|
|
556
613
|
cutOff(partial) {
|
|
@@ -645,6 +702,11 @@ function transcriptKey(role, id, at) {
|
|
|
645
702
|
if (role === "staff") return `s:${id}`;
|
|
646
703
|
return id;
|
|
647
704
|
}
|
|
705
|
+
function transcriptHasIds(transcript) {
|
|
706
|
+
return asArray(transcript).every(
|
|
707
|
+
(item) => item.role === "card" ? str(item.card?.id) !== void 0 : str(item.id) !== void 0
|
|
708
|
+
);
|
|
709
|
+
}
|
|
648
710
|
function lockedFrom(question) {
|
|
649
711
|
if (!question) return [];
|
|
650
712
|
if (question.state !== "open") {
|
|
@@ -1467,7 +1529,8 @@ function buildTimeline(input, previous) {
|
|
|
1467
1529
|
type: "card",
|
|
1468
1530
|
key: card.id,
|
|
1469
1531
|
card,
|
|
1470
|
-
busy: input.busy.has(card.id),
|
|
1532
|
+
busy: !input.inert?.has(card.id) && input.busy.has(card.id),
|
|
1533
|
+
...input.inert?.has(card.id) ? { restored: true } : {},
|
|
1471
1534
|
...input.decisionErrors?.has(card.id) ? { decisionError: true } : {}
|
|
1472
1535
|
},
|
|
1473
1536
|
order: input.cardOrder?.get(card.id) ?? card.seq
|
|
@@ -1499,17 +1562,10 @@ function buildTimeline(input, previous) {
|
|
|
1499
1562
|
});
|
|
1500
1563
|
}
|
|
1501
1564
|
live.sort((a, b) => a.order - b.order);
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
if (!transcript)
|
|
1507
|
-
for (const item of input.history) {
|
|
1508
|
-
const current = liveByKey.get(item.key);
|
|
1509
|
-
items.push(current ?? item);
|
|
1510
|
-
if (current) placed.add(item.key);
|
|
1511
|
-
}
|
|
1512
|
-
for (const { item } of live) if (!placed.has(item.key)) items.push(item);
|
|
1565
|
+
const items = mergeByKey(
|
|
1566
|
+
input.transcriptSeen === true ? [] : input.history,
|
|
1567
|
+
live.map((l) => l.item)
|
|
1568
|
+
);
|
|
1513
1569
|
let same = items.length === previous.length;
|
|
1514
1570
|
const shared = items.map((item, i) => {
|
|
1515
1571
|
const prev = before.get(item.key);
|
|
@@ -1519,6 +1575,24 @@ function buildTimeline(input, previous) {
|
|
|
1519
1575
|
});
|
|
1520
1576
|
return same ? previous : shared;
|
|
1521
1577
|
}
|
|
1578
|
+
function mergeByKey(history, live) {
|
|
1579
|
+
if (!history.length) return [...live];
|
|
1580
|
+
const items = [...history];
|
|
1581
|
+
const at = (key) => items.findIndex((item) => item.key === key);
|
|
1582
|
+
let last = -1;
|
|
1583
|
+
live.forEach((item, i) => {
|
|
1584
|
+
const found = at(item.key);
|
|
1585
|
+
if (found >= 0) {
|
|
1586
|
+
items[found] = item;
|
|
1587
|
+
last = found;
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
const next = live.slice(i + 1).map((l) => at(l.key)).find((p) => p >= 0);
|
|
1591
|
+
last = next === void 0 ? items.length : last >= 0 ? last + 1 : next;
|
|
1592
|
+
items.splice(last, 0, item);
|
|
1593
|
+
});
|
|
1594
|
+
return items;
|
|
1595
|
+
}
|
|
1522
1596
|
function messageItem(m) {
|
|
1523
1597
|
const role = m.role === "assistant" ? "agent" : m.role;
|
|
1524
1598
|
return {
|
|
@@ -1593,6 +1667,8 @@ var ConversationStore = class {
|
|
|
1593
1667
|
readySession = null;
|
|
1594
1668
|
cardOrder = /* @__PURE__ */ new Map();
|
|
1595
1669
|
kept = [];
|
|
1670
|
+
/** Cards an earlier session drew, kept by a merged transcript: drawn as restored, taking no tap. */
|
|
1671
|
+
inert = /* @__PURE__ */ new Set();
|
|
1596
1672
|
locale;
|
|
1597
1673
|
/** The request for a session in flight, to abort when it is no longer wanted. */
|
|
1598
1674
|
fetching = null;
|
|
@@ -1634,6 +1710,8 @@ var ConversationStore = class {
|
|
|
1634
1710
|
this.live();
|
|
1635
1711
|
if (this.session) {
|
|
1636
1712
|
if (this.session.status === "idle") this.session.connect();
|
|
1713
|
+
else if (this.session.status === "unauthorized")
|
|
1714
|
+
void this.resumeWith("resume");
|
|
1637
1715
|
return;
|
|
1638
1716
|
}
|
|
1639
1717
|
void this.ensureSession("open");
|
|
@@ -1698,9 +1776,19 @@ var ConversationStore = class {
|
|
|
1698
1776
|
session.close();
|
|
1699
1777
|
this.update();
|
|
1700
1778
|
}
|
|
1701
|
-
/**
|
|
1702
|
-
|
|
1779
|
+
/**
|
|
1780
|
+
* Back in the foreground, or the person acted while away: a new connection to the same session, with a fresh secret
|
|
1781
|
+
* when the backend gives one. A session that passed its end meanwhile is never reopened (a fresh secret cannot bring
|
|
1782
|
+
* back an expired tool token): the person's action continues the conversation in a new session from `getSession`,
|
|
1783
|
+
* and until then nothing connects.
|
|
1784
|
+
*/
|
|
1785
|
+
async wake(byPerson = false) {
|
|
1703
1786
|
const info = this.info;
|
|
1787
|
+
if (info && this.sessionOver()) {
|
|
1788
|
+
if (byPerson) await this.resumeWith("resume");
|
|
1789
|
+
else this.update();
|
|
1790
|
+
return;
|
|
1791
|
+
}
|
|
1704
1792
|
this.suspended = false;
|
|
1705
1793
|
if (!info) return;
|
|
1706
1794
|
let next = info;
|
|
@@ -1740,7 +1828,7 @@ var ConversationStore = class {
|
|
|
1740
1828
|
}
|
|
1741
1829
|
if (this.suspended) {
|
|
1742
1830
|
this.early.set(id, text);
|
|
1743
|
-
void this.wake();
|
|
1831
|
+
void this.wake(true);
|
|
1744
1832
|
this.update();
|
|
1745
1833
|
return id;
|
|
1746
1834
|
}
|
|
@@ -1750,6 +1838,12 @@ var ConversationStore = class {
|
|
|
1750
1838
|
this.update();
|
|
1751
1839
|
return id;
|
|
1752
1840
|
}
|
|
1841
|
+
if (this.sessionOver()) {
|
|
1842
|
+
this.early.set(id, text);
|
|
1843
|
+
void this.resumeWith("resume");
|
|
1844
|
+
this.update();
|
|
1845
|
+
return id;
|
|
1846
|
+
}
|
|
1753
1847
|
this.nextId = id;
|
|
1754
1848
|
this.session.sendText(text);
|
|
1755
1849
|
this.nextId = null;
|
|
@@ -1886,11 +1980,21 @@ var ConversationStore = class {
|
|
|
1886
1980
|
}
|
|
1887
1981
|
open(info) {
|
|
1888
1982
|
this.info = info;
|
|
1983
|
+
this.suspended = false;
|
|
1984
|
+
const refreshSecret = this.options.refreshSecret;
|
|
1889
1985
|
const session = new VinaverseSession({
|
|
1890
1986
|
...this.options.transport,
|
|
1891
1987
|
session: info,
|
|
1892
1988
|
engine: this.engine,
|
|
1893
|
-
...
|
|
1989
|
+
...refreshSecret ? {
|
|
1990
|
+
// Past the session's end a fresh secret cannot help: refused here, and the store rolls over instead.
|
|
1991
|
+
refreshSecret: (id) => this.sessionOver() ? Promise.reject(
|
|
1992
|
+
new VinaverseClientError(
|
|
1993
|
+
"needs_new_session",
|
|
1994
|
+
"This session has ended."
|
|
1995
|
+
)
|
|
1996
|
+
) : refreshSecret(id)
|
|
1997
|
+
} : {},
|
|
1894
1998
|
createId: () => this.nextId ?? (this.options.createId ?? randomId)()
|
|
1895
1999
|
});
|
|
1896
2000
|
this.session = session;
|
|
@@ -1898,7 +2002,9 @@ var ConversationStore = class {
|
|
|
1898
2002
|
session.on("state", () => this.update()),
|
|
1899
2003
|
session.on("status", (status) => this.statusChanged(status)),
|
|
1900
2004
|
session.on("event", (event) => this.event(event)),
|
|
1901
|
-
session.on("error", (error) =>
|
|
2005
|
+
session.on("error", (error) => {
|
|
2006
|
+
if (!this.sessionOver()) this.options.onError?.(error);
|
|
2007
|
+
})
|
|
1902
2008
|
);
|
|
1903
2009
|
session.setForeground(this.foreground);
|
|
1904
2010
|
session.connect();
|
|
@@ -1925,6 +2031,10 @@ var ConversationStore = class {
|
|
|
1925
2031
|
this.resuming = this.fetchSession(reason).then((info) => {
|
|
1926
2032
|
this.resuming = null;
|
|
1927
2033
|
if (!info || this.disposed || !this.session) return;
|
|
2034
|
+
if (this.session.status === "closed") {
|
|
2035
|
+
this.open(info);
|
|
2036
|
+
return;
|
|
2037
|
+
}
|
|
1928
2038
|
this.info = info;
|
|
1929
2039
|
this.session.resume(info);
|
|
1930
2040
|
this.flushEarly();
|
|
@@ -1939,10 +2049,18 @@ var ConversationStore = class {
|
|
|
1939
2049
|
}
|
|
1940
2050
|
reconnectIfDown() {
|
|
1941
2051
|
const session = this.session;
|
|
1942
|
-
if (session && session.status === "idle" && this.
|
|
2052
|
+
if (session && session.status === "idle" && !this.sessionOver() && // past its end: the person's next action gets a new session
|
|
2053
|
+
this.nextFrom(this.engine.state()) === null)
|
|
1943
2054
|
session.connect();
|
|
1944
2055
|
}
|
|
2056
|
+
/** A refusal already led to a new session, and none has been ready since: another refusal is no cue. */
|
|
2057
|
+
rolled = false;
|
|
1945
2058
|
statusChanged(status) {
|
|
2059
|
+
if (status === "ready") this.rolled = false;
|
|
2060
|
+
if (status === "unauthorized" && !this.rolled) {
|
|
2061
|
+
this.rolled = true;
|
|
2062
|
+
void this.resumeWith("resume");
|
|
2063
|
+
}
|
|
1946
2064
|
if (status === "idle")
|
|
1947
2065
|
this.offlineAfterRetries = this.lastStatus === "reconnecting";
|
|
1948
2066
|
else if (status !== "reconnecting") this.offlineAfterRetries = false;
|
|
@@ -1967,9 +2085,18 @@ var ConversationStore = class {
|
|
|
1967
2085
|
const session = frame.session?.id;
|
|
1968
2086
|
const moved = typeof session === "string" && session !== this.readySession;
|
|
1969
2087
|
if (typeof session === "string") this.readySession = session;
|
|
1970
|
-
if (frame.resumed === true && Array.isArray(frame.transcript)) {
|
|
2088
|
+
if (frame.resumed === true && Array.isArray(frame.transcript) && !transcriptHasIds(frame.transcript)) {
|
|
1971
2089
|
this.transcriptSeen = true;
|
|
1972
2090
|
this.anchorCards(moved);
|
|
2091
|
+
} else if (moved && frame.resumed === true) {
|
|
2092
|
+
const pending = new Set(
|
|
2093
|
+
(Array.isArray(frame.pending_cards) ? frame.pending_cards : []).map(
|
|
2094
|
+
(c) => str2(c.id)
|
|
2095
|
+
)
|
|
2096
|
+
);
|
|
2097
|
+
for (const card of this.engine.state().cards)
|
|
2098
|
+
if (pending.has(card.id)) this.inert.delete(card.id);
|
|
2099
|
+
else this.inert.add(card.id);
|
|
1973
2100
|
}
|
|
1974
2101
|
return;
|
|
1975
2102
|
}
|
|
@@ -2128,6 +2255,7 @@ var ConversationStore = class {
|
|
|
2128
2255
|
transcriptSeen: this.transcriptSeen,
|
|
2129
2256
|
cardOrder: this.cardOrder,
|
|
2130
2257
|
kept: this.kept,
|
|
2258
|
+
inert: this.inert,
|
|
2131
2259
|
system: this.system
|
|
2132
2260
|
},
|
|
2133
2261
|
prev?.items ?? NO_ITEMS
|
|
@@ -2144,6 +2272,7 @@ var ConversationStore = class {
|
|
|
2144
2272
|
next,
|
|
2145
2273
|
agent: sameAgent(prev?.agent, name, avatarUrl) ? prev.agent : { name, avatarUrl },
|
|
2146
2274
|
disclosure: s.disclosure ?? this.info?.disclosure ?? null,
|
|
2275
|
+
welcome: this.info?.welcome ?? null,
|
|
2147
2276
|
takeover: s.takeover,
|
|
2148
2277
|
items,
|
|
2149
2278
|
activity: prev && sameTools(prev.activity, activity) ? prev.activity : activity,
|
|
@@ -2250,6 +2379,11 @@ var ConversationStore = class {
|
|
|
2250
2379
|
}, PERSIST_DELAY);
|
|
2251
2380
|
}
|
|
2252
2381
|
// ------------------------------------------------------------ guards
|
|
2382
|
+
/** Past the session's end (`expires_at`), when the backend passed it on. */
|
|
2383
|
+
sessionOver() {
|
|
2384
|
+
const end = this.info?.expires_at;
|
|
2385
|
+
return end !== void 0 && Date.now() >= Date.parse(end);
|
|
2386
|
+
}
|
|
2253
2387
|
live() {
|
|
2254
2388
|
if (this.disposed)
|
|
2255
2389
|
throw new VinaverseClientError(
|
|
@@ -2303,6 +2437,42 @@ function shallowEqual(a, b) {
|
|
|
2303
2437
|
return a.status === b.status && a.banner === b.banner && a.next === b.next && a.agent.name === b.agent.name && a.agent.avatarUrl === b.agent.avatarUrl && a.disclosure === b.disclosure && a.takeover?.by === b.takeover?.by && a.takeover?.at === b.takeover?.at && a.takeover === null === (b.takeover === null) && a.items === b.items && a.activity === b.activity && a.responding === b.responding && a.openQuestion === b.openQuestion && a.answersNeedWebSocket === b.answersNeedWebSocket && a.turnsLeft === b.turnsLeft && a.history === b.history;
|
|
2304
2438
|
}
|
|
2305
2439
|
|
|
2440
|
+
// src/conversation/modes.ts
|
|
2441
|
+
function createConversationsByMode(options) {
|
|
2442
|
+
const { getSession, modes = [], ...shared } = options;
|
|
2443
|
+
const base = shared.persistenceKey ?? "vinaverse.conversation";
|
|
2444
|
+
const stores = /* @__PURE__ */ new Map();
|
|
2445
|
+
const get = (mode) => {
|
|
2446
|
+
let store = stores.get(mode);
|
|
2447
|
+
if (!store) {
|
|
2448
|
+
store = createConversation({
|
|
2449
|
+
...shared,
|
|
2450
|
+
persistenceKey: `${base}.${mode}`,
|
|
2451
|
+
getSession: (request) => getSession({ ...request, mode })
|
|
2452
|
+
});
|
|
2453
|
+
stores.set(mode, store);
|
|
2454
|
+
}
|
|
2455
|
+
return store;
|
|
2456
|
+
};
|
|
2457
|
+
return {
|
|
2458
|
+
get,
|
|
2459
|
+
select(mode) {
|
|
2460
|
+
for (const [other, store] of stores)
|
|
2461
|
+
if (other !== mode) store.setForeground(false);
|
|
2462
|
+
return get(mode);
|
|
2463
|
+
},
|
|
2464
|
+
dispose() {
|
|
2465
|
+
for (const store of stores.values()) store.dispose();
|
|
2466
|
+
stores.clear();
|
|
2467
|
+
},
|
|
2468
|
+
clear() {
|
|
2469
|
+
for (const mode of /* @__PURE__ */ new Set([...stores.keys(), ...modes]))
|
|
2470
|
+
get(mode).clear();
|
|
2471
|
+
stores.clear();
|
|
2472
|
+
}
|
|
2473
|
+
};
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2306
2476
|
exports.CONTRACT = CONTRACT;
|
|
2307
2477
|
exports.ConversationStore = ConversationStore;
|
|
2308
2478
|
exports.MAX_TEXT = MAX_TEXT;
|
|
@@ -2310,6 +2480,7 @@ exports.VinaverseClientError = VinaverseClientError;
|
|
|
2310
2480
|
exports.answerProblem = answerProblem;
|
|
2311
2481
|
exports.codePoints = codePoints;
|
|
2312
2482
|
exports.createConversation = createConversation;
|
|
2483
|
+
exports.createConversationsByMode = createConversationsByMode;
|
|
2313
2484
|
exports.isAllowedLink = isAllowedLink;
|
|
2314
2485
|
exports.isKnownCard = isKnownCard;
|
|
2315
2486
|
exports.isValidLinkPrefix = isValidLinkPrefix;
|