@datalayer/agent-runtimes 1.5.23 → 1.5.25
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-embed/chunks/{CellSidebarExtension-CDnzN9Cb.js → CellSidebarExtension-B-73cmcQ.js} +1 -1
- package/dist-embed/chunks/{ChatView-BjZ993Ch.js → ChatView-CUWE6I5M.js} +3 -3
- package/dist-embed/chunks/{DeckComponent-Cb4_dZpN.js → DeckComponent-ymp4My5d.js} +1 -1
- package/dist-embed/chunks/{DocumentView-Caxb2xz-.js → DocumentView-i99p_Qzt.js} +1 -1
- package/dist-embed/chunks/{EphemeralDocument-DIHjR5l8.js → EphemeralDocument--pV47gPl.js} +1 -1
- package/dist-embed/chunks/{EphemeralNotebook-1Rwa3anx.js → EphemeralNotebook-BqccUXGd.js} +1 -1
- package/dist-embed/chunks/{ExcalidrawComponent-vJQwgcUt.js → ExcalidrawComponent-DgSMy796.js} +1 -1
- package/dist-embed/chunks/{ExcalidrawModal-BDgjdSz2.js → ExcalidrawModal-DFJW9pQh.js} +1 -1
- package/dist-embed/chunks/{JupyterLexicalExtension-_7FM5Om8.js → JupyterLexicalExtension-CqDatsgf.js} +5 -5
- package/dist-embed/chunks/{KernelVariables-CKIqy599.js → KernelVariables-CS6h5HyK.js} +1 -1
- package/dist-embed/chunks/{NotebookToolSurfaces-YAM1bvZS.js → NotebookToolSurfaces-CTLbTvsS.js} +1 -1
- package/dist-embed/chunks/{NotebookView-C8RCvsR1.js → NotebookView-BJpTApeL.js} +1 -1
- package/dist-embed/chunks/{Output-BWClePP-.js → Output-no9rnFJ7.js} +1 -1
- package/dist-embed/chunks/{SandboxDetailsDialog-CDSxIC0-.js → SandboxDetailsDialog-BAv6RMed.js} +1 -1
- package/dist-embed/chunks/{SchemaForm-CO_2yGg2.js → SchemaForm-CE5NfpBU.js} +1 -1
- package/dist-embed/chunks/{WidgetVariableView--osoOLv8.js → WidgetVariableView-V4DsgfIK.js} +1 -1
- package/dist-embed/chunks/{YouTubePlugin-BB7Z7INn.js → YouTubePlugin-CpgyVTwG.js} +1 -1
- package/dist-embed/chunks/{ar-SA-G6X2FPQ2-D6Ko4I2x.js → ar-SA-G6X2FPQ2-DwUjDWHp.js} +1 -1
- package/dist-embed/chunks/{az-AZ-76LH7QW2-B3UhxnSz.js → az-AZ-76LH7QW2-DROX4pJc.js} +1 -1
- package/dist-embed/chunks/{bg-BG-XCXSNQG7-BS-QRZjB.js → bg-BG-XCXSNQG7-DPLzP9Bm.js} +1 -1
- package/dist-embed/chunks/{bn-BD-2XOGV67Q-DNg0uIV0.js → bn-BD-2XOGV67Q-CCOU2J2j.js} +1 -1
- package/dist-embed/chunks/{ca-ES-6MX7JW3Y-Bn4yHfTY.js → ca-ES-6MX7JW3Y-3RgFapBd.js} +1 -1
- package/dist-embed/chunks/{cs-CZ-2BRQDIVT-DUGnyonZ.js → cs-CZ-2BRQDIVT-BJS7ofhJ.js} +1 -1
- package/dist-embed/chunks/{da-DK-5WZEPLOC-Is8nybqO.js → da-DK-5WZEPLOC-BHDT0zzh.js} +1 -1
- package/dist-embed/chunks/{de-DE-XR44H4JA-D54sMa4L.js → de-DE-XR44H4JA-CWVJKc9t.js} +1 -1
- package/dist-embed/chunks/{el-GR-BZB4AONW-CvM3SWat.js → el-GR-BZB4AONW-2z8DB9lI.js} +1 -1
- package/dist-embed/chunks/{es-ES-U4NZUMDT-BZDRRuRf.js → es-ES-U4NZUMDT-DzXGWPd4.js} +1 -1
- package/dist-embed/chunks/{eu-ES-A7QVB2H4-DAmknI9y.js → eu-ES-A7QVB2H4-CslHE4iE.js} +1 -1
- package/dist-embed/chunks/{fa-IR-HGAKTJCU-CQhKri4O.js → fa-IR-HGAKTJCU-CBWUHs2r.js} +1 -1
- package/dist-embed/chunks/{fi-FI-Z5N7JZ37-DzEDoP64.js → fi-FI-Z5N7JZ37-MAr8kZMI.js} +1 -1
- package/dist-embed/chunks/{fr-FR-RHASNOE6-DiSkyvEB.js → fr-FR-RHASNOE6-BUz3aHQJ.js} +1 -1
- package/dist-embed/chunks/{gl-ES-HMX3MZ6V-3AJMzY-I.js → gl-ES-HMX3MZ6V-DvzQmDYv.js} +1 -1
- package/dist-embed/chunks/{he-IL-6SHJWFNN-Cuh5an4X.js → he-IL-6SHJWFNN-DKR3cKyQ.js} +1 -1
- package/dist-embed/chunks/{hi-IN-IWLTKZ5I-BbeuFB83.js → hi-IN-IWLTKZ5I-C4tyBNwa.js} +1 -1
- package/dist-embed/chunks/{hu-HU-A5ZG7DT2-C1OMfhob.js → hu-HU-A5ZG7DT2-C8BnBgH5.js} +1 -1
- package/dist-embed/chunks/{id-ID-SAP4L64H-BzKILJTZ.js → id-ID-SAP4L64H-Bn1hY5OS.js} +1 -1
- package/dist-embed/chunks/{index-CPpm1tqJ.js → index-5N0EOEHV.js} +1 -1
- package/dist-embed/chunks/{index-f418CYn7.js → index-BKB97UwL.js} +1 -1
- package/dist-embed/chunks/{index-CyQgE_Es.js → index-BN8Bbau-.js} +2 -2
- package/dist-embed/chunks/{index-CKFrz1es.js → index-BTdq_niO.js} +1 -1
- package/dist-embed/chunks/{index-D4QM3qbA.js → index-Bhzj1Pnv.js} +1 -1
- package/dist-embed/chunks/{index-BMandbJB.js → index-BzMt3uYX.js} +1 -1
- package/dist-embed/chunks/{index-DLimRfHQ.js → index-CCRwowMu.js} +1 -1
- package/dist-embed/chunks/{index-BFdE0KFI.js → index-CEbnhuIo.js} +1 -1
- package/dist-embed/chunks/{index-CAd5YQQl.js → index-CZB8DyUw.js} +1 -1
- package/dist-embed/chunks/{index-BO6VQLH6.js → index-Cd5CgKFr.js} +1 -1
- package/dist-embed/chunks/{index-D64QvG43.js → index-CkQ6IAoY.js} +1 -1
- package/dist-embed/chunks/{index-BktUM85c.js → index-Coj9opLJ.js} +1 -1
- package/dist-embed/chunks/{index-dYwQAVs_.js → index-D9_026K2.js} +1 -1
- package/dist-embed/chunks/{index-SbFvdBPQ.js → index-DVaPKQyL.js} +1 -1
- package/dist-embed/chunks/{index-f9WZsG2n.js → index-DWfzdTZo.js} +1 -1
- package/dist-embed/chunks/{index-DY8mjz1l.js → index-DdBQBN76.js} +1 -1
- package/dist-embed/chunks/{index-DEjLPUAD.js → index-Di3aBGLV.js} +1 -1
- package/dist-embed/chunks/{index-Cu0bp_EI.js → index-Gngo0bXi.js} +1 -1
- package/dist-embed/chunks/{index-DyVR0igi.js → index-S4sn4R3i.js} +1 -1
- package/dist-embed/chunks/{index-noRoZrq5.js → index-Z2pxzg3H.js} +1 -1
- package/dist-embed/chunks/{index-PqsSImlj.js → index-_H5U6gal.js} +1 -1
- package/dist-embed/chunks/{index-x45cMPwN.js → index-_nsBY26B.js} +1 -1
- package/dist-embed/chunks/{index-CM7xo08K.js → index-b6e3y1R-.js} +1 -1
- package/dist-embed/chunks/{index-wk9vl2uW.js → index-szXn1pzS.js} +1 -1
- package/dist-embed/chunks/{index.esm-p0OnSU9h.js → index.esm-nZym6gpK.js} +1 -1
- package/dist-embed/chunks/isEqual-g-jK7vY0.js +1 -0
- package/dist-embed/chunks/{it-IT-JPQ66NNP-DuG05fUR.js → it-IT-JPQ66NNP-DEiaanA7.js} +1 -1
- package/dist-embed/chunks/{ja-JP-DBVTYXUO-DeDfL3Bk.js → ja-JP-DBVTYXUO-Bb0GBZrQ.js} +1 -1
- package/dist-embed/chunks/{kaa-6HZHGXH3-BRKFVG6s.js → kaa-6HZHGXH3-DxqTv9uN.js} +1 -1
- package/dist-embed/chunks/{kab-KAB-ZGHBKWFO-Uqakmhz5.js → kab-KAB-ZGHBKWFO-D0V0yQgV.js} +1 -1
- package/dist-embed/chunks/{kk-KZ-P5N5QNE5-DWMXMIAK.js → kk-KZ-P5N5QNE5-CYyEyHXW.js} +1 -1
- package/dist-embed/chunks/{km-KH-HSX4SM5Z-BXNl9QnV.js → km-KH-HSX4SM5Z-CCTEGikY.js} +1 -1
- package/dist-embed/chunks/{ko-KR-MTYHY66A-BZgIqTuN.js → ko-KR-MTYHY66A-C-QDut19.js} +1 -1
- package/dist-embed/chunks/{ku-TR-6OUDTVRD-CQNa5i5U.js → ku-TR-6OUDTVRD-CIqn8p2Y.js} +1 -1
- package/dist-embed/chunks/{lt-LT-XHIRWOB4-BQW2k7iv.js → lt-LT-XHIRWOB4-BDLUWFPH.js} +1 -1
- package/dist-embed/chunks/{lv-LV-5QDEKY6T-B0HRRCC4.js → lv-LV-5QDEKY6T-BItabIJP.js} +1 -1
- package/dist-embed/chunks/{mr-IN-CRQNXWMA-DXR6sWSH.js → mr-IN-CRQNXWMA-DXXb8N2w.js} +1 -1
- package/dist-embed/chunks/{my-MM-5M5IBNSE-BZ5_9oCm.js → my-MM-5M5IBNSE-TidIfjqS.js} +1 -1
- package/dist-embed/chunks/{nb-NO-T6EIAALU-CBtv36wZ.js → nb-NO-T6EIAALU-DEINynK7.js} +1 -1
- package/dist-embed/chunks/{nl-NL-IS3SIHDZ-CcqE3cY8.js → nl-NL-IS3SIHDZ-D04rJzNe.js} +1 -1
- package/dist-embed/chunks/{nn-NO-6E72VCQL-Cl9wPgpU.js → nn-NO-6E72VCQL-oWFzCtpf.js} +1 -1
- package/dist-embed/chunks/{oc-FR-POXYY2M6-CQEkV2p1.js → oc-FR-POXYY2M6-BmFfP6hk.js} +1 -1
- package/dist-embed/chunks/{pa-IN-N4M65BXN-CaE6yG0U.js → pa-IN-N4M65BXN-RkXrgKXw.js} +1 -1
- package/dist-embed/chunks/{percentages-BXMCSKIN-Bk5xifLL.js → percentages-BXMCSKIN-BL_DuU3S.js} +3 -3
- package/dist-embed/chunks/{pl-PL-T2D74RX3-M1pQcF2j.js → pl-PL-T2D74RX3-DqxkHzTj.js} +1 -1
- package/dist-embed/chunks/{pt-BR-5N22H2LF-BFDHu72z.js → pt-BR-5N22H2LF-DFA-wWC5.js} +1 -1
- package/dist-embed/chunks/{pt-PT-UZXXM6DQ-DFcZY1Gz.js → pt-PT-UZXXM6DQ-Z5jw_7aw.js} +1 -1
- package/dist-embed/chunks/{renderer-Dy4lZ1KZ.js → renderer-DKKfWkWv.js} +1 -1
- package/dist-embed/chunks/{ro-RO-JPDTUUEW-BGm_Xwik.js → ro-RO-JPDTUUEW-DjC09bHq.js} +1 -1
- package/dist-embed/chunks/{ru-RU-B4JR7IUQ-BsrZ_x8p.js → ru-RU-B4JR7IUQ-CqwD7Yik.js} +1 -1
- package/dist-embed/chunks/{si-LK-N5RQ5JYF-BfaYS44g.js → si-LK-N5RQ5JYF-OVf4k6G3.js} +1 -1
- package/dist-embed/chunks/{sk-SK-C5VTKIMK-D-K9yMTN.js → sk-SK-C5VTKIMK-BG__kjLT.js} +1 -1
- package/dist-embed/chunks/{sl-SI-NN7IZMDC-B48XvZUw.js → sl-SI-NN7IZMDC-CIgxidVH.js} +1 -1
- package/dist-embed/chunks/{subset-shared.chunk-DzA7mJjZ.js → subset-shared.chunk-BR0LJHtQ.js} +1 -1
- package/dist-embed/chunks/{subset-worker.chunk-CsTEdHAt.js → subset-worker.chunk-52aAcjvz.js} +1 -1
- package/dist-embed/chunks/{sv-SE-XGPEYMSR-DfhLO_Vt.js → sv-SE-XGPEYMSR-CYHz3xCa.js} +1 -1
- package/dist-embed/chunks/{ta-IN-2NMHFXQM-EZA_oxSt.js → ta-IN-2NMHFXQM-BphRr9QY.js} +1 -1
- package/dist-embed/chunks/{th-TH-HPSO5L25-G9vy_zQH.js → th-TH-HPSO5L25-Ba2-2Bo0.js} +1 -1
- package/dist-embed/chunks/{tr-TR-DEFEU3FU-DBj_G5CD.js → tr-TR-DEFEU3FU-CRKE7Roy.js} +1 -1
- package/dist-embed/chunks/{uk-UA-QMV73CPH-DN7lMu5H.js → uk-UA-QMV73CPH-DlNE5CAT.js} +1 -1
- package/dist-embed/chunks/{vi-VN-M7AON7JQ-LoT02qgd.js → vi-VN-M7AON7JQ-Cp44PRXY.js} +1 -1
- package/dist-embed/chunks/{zh-CN-LNUGB5OW-CjexwOqT.js → zh-CN-LNUGB5OW-JHqqwp0j.js} +1 -1
- package/dist-embed/chunks/{zh-HK-E62DVLB3-B0ys_HV6.js → zh-HK-E62DVLB3-YEs97mA8.js} +1 -1
- package/dist-embed/chunks/{zh-TW-RAJ6MFWO-tQJWLJuU.js → zh-TW-RAJ6MFWO-CgmeTbuy.js} +1 -1
- package/dist-embed/datalayer-app-main.js +65 -65
- package/lib/apps/plugins/pap-sign-in/signIn.d.ts +3 -89
- package/lib/apps/plugins/pap-sign-in/signIn.js +5 -142
- package/lib/chat/messages/ChatMessageList.js +3 -1
- package/lib/chat/presence/Presence.d.ts +4 -4
- package/lib/chat/presence/Presence.js +3 -2
- package/lib/chat/presence/presenceStatus.d.ts +3 -34
- package/lib/chat/presence/presenceStatus.js +4 -46
- package/lib/portable/conversation.d.ts +3 -0
- package/lib/portable/conversation.js +15 -1
- package/lib/portable/direct.d.ts +100 -0
- package/lib/portable/direct.js +172 -0
- package/lib/portable/displays.d.ts +109 -0
- package/lib/portable/displays.js +261 -0
- package/lib/portable/fixtures.d.ts +11 -0
- package/lib/portable/fixtures.js +72 -0
- package/lib/portable/index.d.ts +6 -0
- package/lib/portable/index.js +10 -0
- package/lib/portable/presence.d.ts +47 -0
- package/lib/portable/presence.js +71 -0
- package/lib/portable/signIn.d.ts +96 -0
- package/lib/portable/signIn.js +148 -0
- package/lib/portable/views.d.ts +147 -0
- package/lib/portable/views.js +52 -0
- package/lib/runtimes/__tests__/fixtures/accounting-agent-card.json +1 -1
- package/package.json +1 -1
- package/dist-embed/chunks/isEqual-Cwjr2skl.js +0 -1
|
@@ -1,93 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* What the gateway's `pap_sign_in`
|
|
3
|
-
*
|
|
4
|
-
* company themselves — on the company's page (`direct`), by entering a
|
|
5
|
-
* code there (`device`), or by typing what the company asks on Datalayer's
|
|
6
|
-
* own page (`mediated`), never in the conversation. The chat shows the link,
|
|
7
|
-
* the code and until when; the agent never sees what the person types. A
|
|
8
|
-
* business over PACT answers its `pact_sign_in` the same way (a `device`
|
|
9
|
-
* sign-in at the business).
|
|
10
|
-
*
|
|
11
|
-
* Pure: no React. A test reaches it without a chat around it.
|
|
2
|
+
* What the gateway's `pap_sign_in` answers, read and checked: kept in
|
|
3
|
+
* `portable/signIn`, which Datalayer Mobile reads too (MOBILE M-037).
|
|
12
4
|
*
|
|
13
5
|
* @module apps/plugins/pap-sign-in/signIn
|
|
14
6
|
*/
|
|
15
|
-
|
|
16
|
-
export type PapSignInWaiting = {
|
|
17
|
-
mode: 'direct' | 'device' | 'mediated';
|
|
18
|
-
/** The company's page — Datalayer's own, for `mediated` — `https` only. */
|
|
19
|
-
open: string;
|
|
20
|
-
/** The page's domain, read from its address: what the person can trust. */
|
|
21
|
-
host: string;
|
|
22
|
-
/**
|
|
23
|
-
* The company's domain, when the gateway names it: for a bound `direct`
|
|
24
|
-
* sign-in the page opened is Datalayer's start link (PAP_DATALAYER P-04),
|
|
25
|
-
* which sends the person on to the company and takes them back only from it.
|
|
26
|
-
*/
|
|
27
|
-
company?: string;
|
|
28
|
-
/** The code to enter, for `device`. */
|
|
29
|
-
code?: string;
|
|
30
|
-
/** Where the company sent a code, for `mediated`, when it did. */
|
|
31
|
-
sentTo?: string;
|
|
32
|
-
/** Until when, ISO 8601. */
|
|
33
|
-
expiresAt?: string;
|
|
34
|
-
/**
|
|
35
|
-
* What the company said it needs (its `authorization` event's scope,
|
|
36
|
-
* PAP_DATALAYER P-02): what the person is asked to allow there.
|
|
37
|
-
*/
|
|
38
|
-
needs?: string[];
|
|
39
|
-
};
|
|
40
|
-
/** What the card says. */
|
|
41
|
-
export declare const PAP_SIGN_IN_WORDS: {
|
|
42
|
-
readonly title: (host: string) => string;
|
|
43
|
-
readonly direct: "Open the company’s page through Datalayer, sign in there, and this conversation goes on once you are back.";
|
|
44
|
-
readonly device: "Open the company’s page and enter this code there.";
|
|
45
|
-
/** `mediated`: the page is Datalayer's, which names the company and asks what it asks. */
|
|
46
|
-
readonly mediatedTitle: (host: string) => string;
|
|
47
|
-
readonly mediated: "Open this page: it names the company and asks what the company needs. Type it there, never in this conversation.";
|
|
48
|
-
readonly sentTo: (to: string) => string;
|
|
49
|
-
readonly needs: (scopes: string[]) => string;
|
|
50
|
-
readonly open: (host: string) => string;
|
|
51
|
-
readonly code: "Your code";
|
|
52
|
-
readonly copy: "Copy the code";
|
|
53
|
-
readonly copied: "Copied";
|
|
54
|
-
readonly until: (at: string) => string;
|
|
55
|
-
readonly checkAgain: "I have signed in: check again";
|
|
56
|
-
readonly tellMe: "Tell me when you are done.";
|
|
57
|
-
readonly checkMessage: (host: string) => string;
|
|
58
|
-
readonly refused: "This sign-in link cannot be opened safely, so it is not shown.";
|
|
59
|
-
readonly qr: (host: string) => string;
|
|
60
|
-
/** Once the person's browser came back from the company (P-04), said under the card. */
|
|
61
|
-
readonly returned: {
|
|
62
|
-
readonly signed_in: (company: string) => string;
|
|
63
|
-
readonly denied: (company: string) => string;
|
|
64
|
-
readonly refused: (company: string) => string;
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Where Datalayer's `/pap/signed-in` page says a Direct Sign-In came back
|
|
69
|
-
* (PAP_DATALAYER P-04): the card waiting for that company hears it in the
|
|
70
|
-
* person's tab, so the conversation goes on there.
|
|
71
|
-
*/
|
|
72
|
-
export declare const PAP_SIGN_IN_CHANNEL = "datalayer-pap-sign-in";
|
|
73
|
-
/** How a Direct Sign-In came back. */
|
|
74
|
-
export type PapSignInReturn = keyof typeof PAP_SIGN_IN_WORDS.returned;
|
|
75
|
-
/** What a message on the channel says of this company's sign-in, or `null`: another company's, or not one. */
|
|
76
|
-
export declare function signInReturnOf(message: unknown, company: string): PapSignInReturn | null;
|
|
77
|
-
/**
|
|
78
|
-
* `pap_sign_in` — or a business's `pact_sign_in` (PI-56) — as the gateway
|
|
79
|
-
* names it with or without a prefix.
|
|
80
|
-
*/
|
|
81
|
-
export declare const PAP_SIGN_IN_TOOL: RegExp;
|
|
82
|
-
/** Whether a tool is `pap_sign_in` or `pact_sign_in`, as the gateway names it with or without a prefix. */
|
|
83
|
-
export declare const isPapSignInTool: (name: string) => boolean;
|
|
84
|
-
/** The page's address, `https` only; `null` for anything else. */
|
|
85
|
-
export declare function safeSignInUrl(open: unknown): URL | null;
|
|
86
|
-
/**
|
|
87
|
-
* The sign-in waiting for the person, or why it is not shown: `null` for a
|
|
88
|
-
* result that is not one (another status: the chat's default row says it),
|
|
89
|
-
* `{ refused }` for a link that is not `https`.
|
|
90
|
-
*/
|
|
91
|
-
export declare function readPapSignIn(result: unknown): PapSignInWaiting | {
|
|
92
|
-
refused: string;
|
|
93
|
-
} | null;
|
|
7
|
+
export * from '../../../portable/signIn';
|
|
@@ -2,147 +2,10 @@
|
|
|
2
2
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
/** What the card says. */
|
|
6
|
-
export const PAP_SIGN_IN_WORDS = {
|
|
7
|
-
title: (host) => `Sign in at ${host}`,
|
|
8
|
-
direct: 'Open the company’s page through Datalayer, sign in there, and this conversation goes on once you are back.',
|
|
9
|
-
device: 'Open the company’s page and enter this code there.',
|
|
10
|
-
/** `mediated`: the page is Datalayer's, which names the company and asks what it asks. */
|
|
11
|
-
mediatedTitle: (host) => `Sign in through ${host}`,
|
|
12
|
-
mediated: 'Open this page: it names the company and asks what the company needs. Type it there, never in this conversation.',
|
|
13
|
-
sentTo: (to) => `The company sent a code to ${to}.`,
|
|
14
|
-
needs: (scopes) => `It needs: ${scopes.join(', ')}.`,
|
|
15
|
-
open: (host) => `Open ${host}`,
|
|
16
|
-
code: 'Your code',
|
|
17
|
-
copy: 'Copy the code',
|
|
18
|
-
copied: 'Copied',
|
|
19
|
-
until: (at) => `Until ${new Date(at).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })}.`,
|
|
20
|
-
checkAgain: 'I have signed in: check again',
|
|
21
|
-
tellMe: 'Tell me when you are done.',
|
|
22
|
-
checkMessage: (host) => `I have signed in at ${host}. Please check again.`,
|
|
23
|
-
refused: 'This sign-in link cannot be opened safely, so it is not shown.',
|
|
24
|
-
qr: (host) => `A code to scan to open ${host} on your phone`,
|
|
25
|
-
/** Once the person's browser came back from the company (P-04), said under the card. */
|
|
26
|
-
returned: {
|
|
27
|
-
signed_in: (company) => `Signed in at ${company}: checking again.`,
|
|
28
|
-
denied: (company) => `You did not sign in at ${company}: ask again when you want to.`,
|
|
29
|
-
refused: (company) => `That sign-in at ${company} was refused, and nothing was kept: start it again here.`,
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
5
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
6
|
+
* What the gateway's `pap_sign_in` answers, read and checked: kept in
|
|
7
|
+
* `portable/signIn`, which Datalayer Mobile reads too (MOBILE M-037).
|
|
8
|
+
*
|
|
9
|
+
* @module apps/plugins/pap-sign-in/signIn
|
|
36
10
|
*/
|
|
37
|
-
export
|
|
38
|
-
/** One OAuth scope token (RFC 6749 §3.3). */
|
|
39
|
-
const SCOPE = /^[\x21\x23-\x5B\x5D-\x7E]{1,128}$/;
|
|
40
|
-
const DOMAIN = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/;
|
|
41
|
-
/** What a message on the channel says of this company's sign-in, or `null`: another company's, or not one. */
|
|
42
|
-
export function signInReturnOf(message, company) {
|
|
43
|
-
if (!message || typeof message !== 'object' || Array.isArray(message)) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const said = message;
|
|
47
|
-
const outcome = said.outcome;
|
|
48
|
-
return said.company === company &&
|
|
49
|
-
(outcome === 'signed_in' || outcome === 'denied' || outcome === 'refused')
|
|
50
|
-
? outcome
|
|
51
|
-
: null;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* `pap_sign_in` — or a business's `pact_sign_in` (PI-56) — as the gateway
|
|
55
|
-
* names it with or without a prefix.
|
|
56
|
-
*/
|
|
57
|
-
export const PAP_SIGN_IN_TOOL = /(^|[_.:\-/])pa(?:p|ct)_sign_in$/;
|
|
58
|
-
/** Whether a tool is `pap_sign_in` or `pact_sign_in`, as the gateway names it with or without a prefix. */
|
|
59
|
-
export const isPapSignInTool = (name) => PAP_SIGN_IN_TOOL.test(name);
|
|
60
|
-
/** An MCP result's own object: its structured content, or the JSON of its text. */
|
|
61
|
-
function unwrapped(result) {
|
|
62
|
-
let value = result;
|
|
63
|
-
if (typeof value === 'string') {
|
|
64
|
-
try {
|
|
65
|
-
value = JSON.parse(value);
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
const data = value;
|
|
75
|
-
if (data.structuredContent && typeof data.structuredContent === 'object') {
|
|
76
|
-
return unwrapped(data.structuredContent);
|
|
77
|
-
}
|
|
78
|
-
if (Array.isArray(data.content)) {
|
|
79
|
-
const text = data.content.find(part => part?.type === 'text' && typeof part.text === 'string');
|
|
80
|
-
return text ? unwrapped(text.text) : null;
|
|
81
|
-
}
|
|
82
|
-
// FastMCP wraps a non-object answer as `{result: …}`.
|
|
83
|
-
if (data.result && typeof data.result === 'object' && !('status' in data)) {
|
|
84
|
-
return unwrapped(data.result);
|
|
85
|
-
}
|
|
86
|
-
return data;
|
|
87
|
-
}
|
|
88
|
-
/** The page's address, `https` only; `null` for anything else. */
|
|
89
|
-
export function safeSignInUrl(open) {
|
|
90
|
-
if (typeof open !== 'string') {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
try {
|
|
94
|
-
const url = new URL(open);
|
|
95
|
-
return url.protocol === 'https:' && url.hostname ? url : null;
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* The sign-in waiting for the person, or why it is not shown: `null` for a
|
|
103
|
-
* result that is not one (another status: the chat's default row says it),
|
|
104
|
-
* `{ refused }` for a link that is not `https`.
|
|
105
|
-
*/
|
|
106
|
-
export function readPapSignIn(result) {
|
|
107
|
-
const data = unwrapped(result);
|
|
108
|
-
if (!data || data.status !== 'waiting_for_the_person') {
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
if (data.mode !== 'direct' &&
|
|
112
|
-
data.mode !== 'device' &&
|
|
113
|
-
data.mode !== 'mediated') {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
const url = safeSignInUrl(data.open);
|
|
117
|
-
if (!url) {
|
|
118
|
-
return { refused: PAP_SIGN_IN_WORDS.refused };
|
|
119
|
-
}
|
|
120
|
-
if (data.mode === 'device' && (typeof data.code !== 'string' || !data.code)) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
// A bound Direct Sign-In opens Datalayer's start link: the card names the company the gateway
|
|
124
|
-
// names (`PapSignIn.company`); without one, the page's own domain is the company's.
|
|
125
|
-
const company = typeof data.company === 'string' && DOMAIN.test(data.company)
|
|
126
|
-
? data.company
|
|
127
|
-
: '';
|
|
128
|
-
// What the company said it needs: scope tokens only, anything else not shown.
|
|
129
|
-
const needs = Array.isArray(data.needs)
|
|
130
|
-
? data.needs.filter((scope) => typeof scope === 'string' && SCOPE.test(scope))
|
|
131
|
-
: [];
|
|
132
|
-
return {
|
|
133
|
-
mode: data.mode,
|
|
134
|
-
open: url.toString(),
|
|
135
|
-
host: url.hostname,
|
|
136
|
-
...(company ? { company } : {}),
|
|
137
|
-
...(typeof data.code === 'string' && data.code ? { code: data.code } : {}),
|
|
138
|
-
...(data.mode === 'mediated' &&
|
|
139
|
-
typeof data.sent_to === 'string' &&
|
|
140
|
-
data.sent_to
|
|
141
|
-
? { sentTo: data.sent_to }
|
|
142
|
-
: {}),
|
|
143
|
-
...(typeof data.expires_at === 'string' && data.expires_at
|
|
144
|
-
? { expiresAt: data.expires_at }
|
|
145
|
-
: {}),
|
|
146
|
-
...(needs.length > 0 ? { needs } : {}),
|
|
147
|
-
};
|
|
148
|
-
}
|
|
11
|
+
export * from '../../../portable/signIn';
|
|
@@ -539,6 +539,8 @@ export function ChatMessageList({ displayItems, actOn, upload, isLoading, isStre
|
|
|
539
539
|
}
|
|
540
540
|
}
|
|
541
541
|
}
|
|
542
|
+
// The host's footer, asked once: a row only when it draws something.
|
|
543
|
+
const messageFooter = renderMessageFooter?.(message);
|
|
542
544
|
return (_jsx(Box, { "data-chat-message": message.role, display: "flex", flexDirection: "column", alignItems: isUser ? 'flex-end' : 'flex-start', px: padding, py: compact ? '2px' : 1, children: _jsxs(Box, { display: "flex", gap: 2, flexDirection: isUser ? 'row-reverse' : 'row', alignItems: "flex-start",
|
|
543
545
|
/*
|
|
544
546
|
Full width, always.
|
|
@@ -611,7 +613,7 @@ export function ChatMessageList({ displayItems, actOn, upload, isLoading, isStre
|
|
|
611
613
|
whiteSpace: 'pre-wrap',
|
|
612
614
|
wordBreak: 'break-word',
|
|
613
615
|
}, children: [message.metadata?.input === 'voice' ? (_jsx(Box, { as: "span", "data-spoken": "", title: "Said aloud", "aria-label": "Said aloud:", display: "inline-flex", verticalAlign: "text-bottom", mr: 1, opacity: 0.85, children: _jsx(MicrophoneIcon, { size: 14, "aria-hidden": "true" }) })) : null, text] }));
|
|
614
|
-
})()) : message.live && !getMessageText(message) ? (_jsx(TypingDots, { size: 6 })) : (_jsx(ChatMarkdown, { density: density, text: getMessageText(message) || (isStreaming ? '...' : '') }))] }), message.displays?.length ? (_jsx(Box, { "data-chat-displays": "", display: "flex", flexDirection: "column", gap: 2, mt: 2, width: "100%", children: message.displays.map(display => platform ? (_jsx(ReactorDisplay, { display: display, act: actOn?.(display), upload: upload }, display.id)) : (_jsx(DisplayText, { display: display }, display.id))) })) : null,
|
|
616
|
+
})()) : message.live && !getMessageText(message) ? (_jsx(TypingDots, { size: 6 })) : (_jsx(ChatMarkdown, { density: density, text: getMessageText(message) || (isStreaming ? '...' : '') }))] }), message.displays?.length ? (_jsx(Box, { "data-chat-displays": "", display: "flex", flexDirection: "column", gap: 2, mt: 2, width: "100%", children: message.displays.map(display => platform ? (_jsx(ReactorDisplay, { display: display, act: actOn?.(display), upload: upload }, display.id)) : (_jsx(DisplayText, { display: display }, display.id))) })) : null, messageFooter ? (_jsx(Box, { display: "flex", gap: 2, alignItems: "center", mt: 1, flexWrap: "wrap", flexDirection: isUser ? 'row-reverse' : 'row', children: messageFooter })) : null] })] }) }, message.id));
|
|
615
617
|
};
|
|
616
618
|
return (_jsxs(_Fragment, { children: [displayItems.map((item, index) => {
|
|
617
619
|
const itemUI = renderItem(item, index);
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* @module chat/presence/Presence
|
|
10
10
|
*/
|
|
11
11
|
import type { ReactNode } from 'react';
|
|
12
|
-
import { type
|
|
12
|
+
import { type PresenceLineProps } from '../../portable/views';
|
|
13
|
+
import type { PresenceState } from './presenceStatus';
|
|
13
14
|
/**
|
|
14
15
|
* A face at `size`: an emoji drawn in Fluent Emoji, the same on every
|
|
15
16
|
* platform (LOOP T-20) — the system's, as text, only for one Datalayer ships
|
|
@@ -28,6 +29,5 @@ export declare function PresenceFace({ face, size, state, }: {
|
|
|
28
29
|
size: number;
|
|
29
30
|
state: PresenceState;
|
|
30
31
|
}): import("react").JSX.Element;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}): import("react").JSX.Element;
|
|
32
|
+
/** The line beside its face: `portable/views`' contract, as Datalayer Mobile draws it too. */
|
|
33
|
+
export declare function PresenceLine({ state }: PresenceLineProps): import("react").JSX.Element;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { Box } from '@datalayer/primer-addons';
|
|
3
3
|
import { Text } from '@primer/react';
|
|
4
4
|
import { FluentEmoji } from '@datalayer/core/lib/components/emoji';
|
|
5
|
-
import {
|
|
5
|
+
import { presenceLine } from '../../portable/views';
|
|
6
6
|
const ACCENT = 'var(--theme-accent)';
|
|
7
7
|
/**
|
|
8
8
|
* A face at `size`: an emoji drawn in Fluent Emoji, the same on every
|
|
@@ -22,6 +22,7 @@ export function PresenceFace({ face, size, state, }) {
|
|
|
22
22
|
},
|
|
23
23
|
} }), _jsx(Box, { as: "span", display: "inline-flex", opacity: paused ? 0.55 : 1, filter: paused ? 'grayscale(0.6)' : 'none', transition: "opacity var(--theme-motion-status, 0ms) var(--theme-motion-easing, ease)", children: _jsx(FaceDrawing, { face: face, size: size }) })] }));
|
|
24
24
|
}
|
|
25
|
+
/** The line beside its face: `portable/views`' contract, as Datalayer Mobile draws it too. */
|
|
25
26
|
export function PresenceLine({ state }) {
|
|
26
27
|
return (_jsx(Text, { role: "status", "aria-live": "polite", "data-presence-line": state, sx: {
|
|
27
28
|
fontSize: 0,
|
|
@@ -29,5 +30,5 @@ export function PresenceLine({ state }) {
|
|
|
29
30
|
fontWeight: state === 'waiting' ? 'semibold' : 'normal',
|
|
30
31
|
whiteSpace: 'nowrap',
|
|
31
32
|
flexShrink: 0,
|
|
32
|
-
}, children:
|
|
33
|
+
}, children: presenceLine({ state }) }));
|
|
33
34
|
}
|
|
@@ -1,38 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* What an application is doing, in plain words (LOOP T-08):
|
|
3
|
-
*
|
|
2
|
+
* What an application is doing, in plain words (LOOP T-08): kept in
|
|
3
|
+
* `portable/presence`, which Datalayer Mobile reads too (MOBILE M-030).
|
|
4
4
|
*
|
|
5
5
|
* @module chat/presence/presenceStatus
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
* The states a person is told about. Paused is its deployment's: its owner
|
|
9
|
-
* paused it (LOOP R-17), and it answers nobody until it is resumed.
|
|
10
|
-
*/
|
|
11
|
-
export type PresenceState = 'idle' | 'thinking' | 'working' | 'waiting' | 'paused';
|
|
12
|
-
/** The line each state is said by. */
|
|
13
|
-
export declare const PRESENCE_LINES: Record<PresenceState, string>;
|
|
14
|
-
/** The newest tool call of the conversation, as far as presence reads it. */
|
|
15
|
-
export interface PresenceTool {
|
|
16
|
-
/** It has not returned. */
|
|
17
|
-
open: boolean;
|
|
18
|
-
/** It waits on a person's approval. */
|
|
19
|
-
pendingApproval: boolean;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* The state, from whether a turn is running, the newest tool call, and
|
|
23
|
-
* whether its deployment is paused.
|
|
24
|
-
*
|
|
25
|
-
* Paused wins: a paused application does nothing, whatever its last turn
|
|
26
|
-
* left behind.
|
|
27
|
-
* Waiting for an approval is said whether or not the turn is still
|
|
28
|
-
* streaming — the stream may end while the approval is asked. A tool that
|
|
29
|
-
* has not returned counts as work only during a turn: a stopped turn can
|
|
30
|
-
* leave one open, and the application is not working then.
|
|
31
|
-
*/
|
|
32
|
-
export declare function presenceState(busy: boolean, tool?: PresenceTool, paused?: boolean): PresenceState;
|
|
33
|
-
/**
|
|
34
|
-
* The newest tool call of the conversation: whether it has not returned, and
|
|
35
|
-
* whether it waits on a person's approval. A tool call is an item with a
|
|
36
|
-
* tool name and a call id; it has returned once it is complete or failed.
|
|
37
|
-
*/
|
|
38
|
-
export declare function presenceToolOf(items: readonly unknown[]): PresenceTool;
|
|
7
|
+
export { PRESENCE_LINES, presenceOfConversation, presenceState, presenceToolOf, type PresenceState, type PresenceTool, } from '../../portable/presence';
|
|
@@ -2,52 +2,10 @@
|
|
|
2
2
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
/** The line each state is said by. */
|
|
6
|
-
export const PRESENCE_LINES = {
|
|
7
|
-
idle: 'Ready',
|
|
8
|
-
thinking: 'Thinking…',
|
|
9
|
-
working: 'Working…',
|
|
10
|
-
waiting: 'Waiting for you',
|
|
11
|
-
paused: 'Paused',
|
|
12
|
-
};
|
|
13
5
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
6
|
+
* What an application is doing, in plain words (LOOP T-08): kept in
|
|
7
|
+
* `portable/presence`, which Datalayer Mobile reads too (MOBILE M-030).
|
|
16
8
|
*
|
|
17
|
-
*
|
|
18
|
-
* left behind.
|
|
19
|
-
* Waiting for an approval is said whether or not the turn is still
|
|
20
|
-
* streaming — the stream may end while the approval is asked. A tool that
|
|
21
|
-
* has not returned counts as work only during a turn: a stopped turn can
|
|
22
|
-
* leave one open, and the application is not working then.
|
|
9
|
+
* @module chat/presence/presenceStatus
|
|
23
10
|
*/
|
|
24
|
-
export
|
|
25
|
-
if (paused) {
|
|
26
|
-
return 'paused';
|
|
27
|
-
}
|
|
28
|
-
if (tool?.open && tool.pendingApproval) {
|
|
29
|
-
return 'waiting';
|
|
30
|
-
}
|
|
31
|
-
if (!busy) {
|
|
32
|
-
return 'idle';
|
|
33
|
-
}
|
|
34
|
-
return tool?.open ? 'working' : 'thinking';
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* The newest tool call of the conversation: whether it has not returned, and
|
|
38
|
-
* whether it waits on a person's approval. A tool call is an item with a
|
|
39
|
-
* tool name and a call id; it has returned once it is complete or failed.
|
|
40
|
-
*/
|
|
41
|
-
export function presenceToolOf(items) {
|
|
42
|
-
for (let index = items.length - 1; index >= 0; index -= 1) {
|
|
43
|
-
const item = items[index];
|
|
44
|
-
if (typeof item.toolName === 'string' && item.toolCallId) {
|
|
45
|
-
const open = item.status !== 'complete' && item.status !== 'error';
|
|
46
|
-
const pendingApproval = open &&
|
|
47
|
-
item.result
|
|
48
|
-
?.pending_approval === true;
|
|
49
|
-
return { open, pendingApproval };
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return { open: false, pendingApproval: false };
|
|
53
|
-
}
|
|
11
|
+
export { PRESENCE_LINES, presenceOfConversation, presenceState, presenceToolOf, } from '../../portable/presence';
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* @module portable/conversation
|
|
22
22
|
*/
|
|
23
23
|
import { type AgUiEvent } from './agui';
|
|
24
|
+
import { type ProtocolDisplay } from './displays';
|
|
24
25
|
/** How many rows a conversation keeps: its newest. */
|
|
25
26
|
export declare const ITEM_LIMIT = 400;
|
|
26
27
|
/** How many characters of an answer are kept. */
|
|
@@ -51,6 +52,8 @@ export type ConversationItem = {
|
|
|
51
52
|
/** Its result in words, cut at its limit. */
|
|
52
53
|
result: string;
|
|
53
54
|
error: string;
|
|
55
|
+
/** The protocol display its result carries, read strictly (`portable/displays`, MOBILE M-037). */
|
|
56
|
+
display: ProtocolDisplay | null;
|
|
54
57
|
} | {
|
|
55
58
|
kind: 'step';
|
|
56
59
|
id: string;
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* @module portable/conversation
|
|
26
26
|
*/
|
|
27
27
|
import { REACTOR_UI_NAME, toolResultOf, UI_ON_RUN, } from './agui';
|
|
28
|
+
import { displayOfToolResult } from './displays';
|
|
28
29
|
import { RUN_END_WORDS } from './records';
|
|
29
30
|
import { messagesOfThread } from './thread';
|
|
30
31
|
/** How many rows a conversation keeps: its newest. */
|
|
@@ -56,6 +57,17 @@ const appended = (kept, delta, limit) => {
|
|
|
56
57
|
}
|
|
57
58
|
return cut(kept + delta, limit);
|
|
58
59
|
};
|
|
60
|
+
/** A result as the model read it: the page's `_meta` (its display) is the card's, not words. */
|
|
61
|
+
function withoutMeta(result) {
|
|
62
|
+
if (result &&
|
|
63
|
+
typeof result === 'object' &&
|
|
64
|
+
!Array.isArray(result) &&
|
|
65
|
+
'_meta' in result) {
|
|
66
|
+
const { _meta: _page, ...view } = result;
|
|
67
|
+
return view;
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
59
71
|
/** A result in words. */
|
|
60
72
|
function said(result) {
|
|
61
73
|
if (result === undefined || result === null) {
|
|
@@ -214,6 +226,7 @@ export function reduceConversation(state, event) {
|
|
|
214
226
|
status: 'running',
|
|
215
227
|
result: '',
|
|
216
228
|
error: '',
|
|
229
|
+
display: null,
|
|
217
230
|
},
|
|
218
231
|
], 1);
|
|
219
232
|
}
|
|
@@ -232,8 +245,9 @@ export function reduceConversation(state, event) {
|
|
|
232
245
|
? {
|
|
233
246
|
...item,
|
|
234
247
|
status: result.success ? 'complete' : 'error',
|
|
235
|
-
result: cut(said(result.result), TOOL_TEXT_LIMIT),
|
|
248
|
+
result: cut(said(withoutMeta(result.result)), TOOL_TEXT_LIMIT),
|
|
236
249
|
error: result.error ?? '',
|
|
250
|
+
display: displayOfToolResult(item.name, result.result, item.id),
|
|
237
251
|
}
|
|
238
252
|
: item) ?? noted(state, event));
|
|
239
253
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Direct Conversation the person types in themselves (PAP_DATALAYER P-08,
|
|
3
|
+
* MOBILE M-038): a linked sub-conversation under the one a company answered
|
|
4
|
+
* in, where the person's own words go to the company as `sender: human`,
|
|
5
|
+
* never through the application's model, until the company closes it.
|
|
6
|
+
*
|
|
7
|
+
* Each message takes a one-use ticket IAM gives the person for one
|
|
8
|
+
* application, one company and one conversation (`POST /pap/my/direct`, with
|
|
9
|
+
* their own sign-in), then goes to the gateway with it (`POST
|
|
10
|
+
* /api/mcp/v1/pap/direct`); the company's replies are read back from the
|
|
11
|
+
* cursor last read (`GET /api/mcp/v1/pap/direct`), never by sending again.
|
|
12
|
+
* One client for every page (the Studio's chat, Datalayer Mobile): the
|
|
13
|
+
* addresses, the person's sign-in and `fetch` are given.
|
|
14
|
+
*
|
|
15
|
+
* Pure but for the given `fetch`: no React, DOM or storage.
|
|
16
|
+
*
|
|
17
|
+
* @module portable/direct
|
|
18
|
+
*/
|
|
19
|
+
/** Where the person writes: the application, the company by its domain, and the conversation there. */
|
|
20
|
+
export type DirectTarget = {
|
|
21
|
+
appUid: string;
|
|
22
|
+
company: string;
|
|
23
|
+
conversationId: string;
|
|
24
|
+
};
|
|
25
|
+
/** One reply of the company, and who wrote it there. */
|
|
26
|
+
export type DirectReply = {
|
|
27
|
+
text: string;
|
|
28
|
+
from: 'agent' | 'human';
|
|
29
|
+
};
|
|
30
|
+
/** What the company answered, and where the conversation stands. */
|
|
31
|
+
export type DirectAnswer = {
|
|
32
|
+
directConversation: string;
|
|
33
|
+
replies: DirectReply[];
|
|
34
|
+
status: string;
|
|
35
|
+
responder: string;
|
|
36
|
+
cursor: string;
|
|
37
|
+
/** The `PapReplies` display, when the company wrote anything. */
|
|
38
|
+
display: unknown;
|
|
39
|
+
};
|
|
40
|
+
/** The longest message the gateway takes. */
|
|
41
|
+
export declare const DIRECT_MAX = 4000;
|
|
42
|
+
/** What a page says around the person's own words. */
|
|
43
|
+
export declare const DIRECT_WORDS: {
|
|
44
|
+
readonly notConfigured: "Datalayer is not configured to send your words to a company here.";
|
|
45
|
+
readonly signIn: "Sign in to Datalayer first: only you write in your Direct Conversation.";
|
|
46
|
+
readonly tooLong: "Write a message of at most 4000 characters.";
|
|
47
|
+
readonly empty: "Write something to send.";
|
|
48
|
+
readonly unread: (company: string) => string;
|
|
49
|
+
readonly write: (company: string) => string;
|
|
50
|
+
readonly says: (company: string) => string;
|
|
51
|
+
readonly writing: (company: string) => string;
|
|
52
|
+
readonly how: "What you write here goes to the company as your own words, never through the application. The company’s answers appear here.";
|
|
53
|
+
readonly you: "You";
|
|
54
|
+
readonly agent: "Its agent";
|
|
55
|
+
readonly human: "One of its people";
|
|
56
|
+
readonly back: "Back to the application";
|
|
57
|
+
readonly closed: (company: string) => string;
|
|
58
|
+
readonly locked: (company: string) => string;
|
|
59
|
+
};
|
|
60
|
+
/** The addresses of IAM and the gateway, the person's sign-in, and `fetch`. */
|
|
61
|
+
export type DirectClientOptions = {
|
|
62
|
+
iamUrl: string;
|
|
63
|
+
gatewayUrl: string;
|
|
64
|
+
getAccessToken: () => string | undefined;
|
|
65
|
+
fetch: typeof fetch;
|
|
66
|
+
};
|
|
67
|
+
/** The gateway's answer, read whole or refused. */
|
|
68
|
+
export declare function directAnswerOf(raw: unknown, company: string): DirectAnswer;
|
|
69
|
+
/** IAM's ticket and the gateway's Direct Conversation routes, as the person. */
|
|
70
|
+
export declare function directClient({ iamUrl, gatewayUrl, getAccessToken, fetch: fetcher, }: DirectClientOptions): {
|
|
71
|
+
ticket: (target: DirectTarget) => Promise<string>;
|
|
72
|
+
/**
|
|
73
|
+
* The person's own words, sent as theirs: a ticket, then the words with
|
|
74
|
+
* it. Refused in the gateway's sentence, and never retried.
|
|
75
|
+
*/
|
|
76
|
+
send: (target: DirectTarget, text: string) => Promise<DirectAnswer>;
|
|
77
|
+
/** What the company wrote since `cursor`: read, never sent again. */
|
|
78
|
+
read: (target: DirectTarget, cursor?: string) => Promise<DirectAnswer>;
|
|
79
|
+
};
|
|
80
|
+
export type DirectClient = ReturnType<typeof directClient>;
|
|
81
|
+
/** One line of the Direct Conversation: the person's, or the company's (its agent or one of its people). */
|
|
82
|
+
export type DirectLine = {
|
|
83
|
+
from: 'you' | 'agent' | 'human';
|
|
84
|
+
text: string;
|
|
85
|
+
};
|
|
86
|
+
/** A Direct Conversation open under its parent: the parent's composer is locked while it is. */
|
|
87
|
+
export type DirectOpen = {
|
|
88
|
+
/** Before the first words, the conversation it opens under; after, the Direct Conversation itself. */
|
|
89
|
+
target: DirectTarget;
|
|
90
|
+
lines: DirectLine[];
|
|
91
|
+
cursor: string;
|
|
92
|
+
/** Closed by the company: nothing more is sent, and the parent is talked to again. */
|
|
93
|
+
closed: boolean;
|
|
94
|
+
};
|
|
95
|
+
/** A Direct Conversation opened under the conversation a company answered in. */
|
|
96
|
+
export declare const openDirect: (target: DirectTarget) => DirectOpen;
|
|
97
|
+
/** The open conversation with what the company answered, and the person's words when they sent some. */
|
|
98
|
+
export declare function withDirectAnswer(open: DirectOpen, answer: DirectAnswer, mine?: string): DirectOpen;
|
|
99
|
+
/** Who wrote a line, said apart: the person, the company's agent, one of its people. */
|
|
100
|
+
export declare const directAuthor: (line: DirectLine) => string;
|