@talk2view/sdk 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +291 -69
- package/dist/assistant-ui/convert.d.ts +40 -0
- package/dist/assistant-ui/convert.d.ts.map +1 -0
- package/dist/assistant-ui/convert.js +113 -0
- package/dist/assistant-ui/convert.js.map +1 -0
- package/dist/assistant-ui/dictation.d.ts +39 -0
- package/dist/assistant-ui/dictation.d.ts.map +1 -0
- package/dist/assistant-ui/dictation.js +128 -0
- package/dist/assistant-ui/dictation.js.map +1 -0
- package/dist/assistant-ui/index.d.ts +37 -0
- package/dist/assistant-ui/index.d.ts.map +1 -0
- package/dist/assistant-ui/index.js +224 -0
- package/dist/assistant-ui/index.js.map +1 -0
- package/dist/auth.d.ts +26 -4
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +82 -17
- package/dist/auth.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -4
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +5 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +28 -6
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +63 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +231 -37
- package/dist/index.js.map +1 -1
- package/dist/react/T2VProvider.d.ts +2 -2
- package/dist/react/T2VProvider.d.ts.map +1 -1
- package/dist/react/T2VProvider.js +1 -1
- package/dist/react/T2VProvider.js.map +1 -1
- package/dist/react/index.d.ts +14 -14
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +7 -7
- package/dist/react/index.js.map +1 -1
- package/dist/react/usePartnerConfig.d.ts +1 -1
- package/dist/react/usePartnerConfig.d.ts.map +1 -1
- package/dist/react/usePartnerConfig.js +1 -1
- package/dist/react/usePartnerConfig.js.map +1 -1
- package/dist/react/useT2VAuth.d.ts +9 -2
- package/dist/react/useT2VAuth.d.ts.map +1 -1
- package/dist/react/useT2VAuth.js +26 -7
- package/dist/react/useT2VAuth.js.map +1 -1
- package/dist/react/useT2VChat.d.ts +3 -3
- package/dist/react/useT2VChat.d.ts.map +1 -1
- package/dist/react/useT2VChat.js +1 -1
- package/dist/react/useT2VChat.js.map +1 -1
- package/dist/react/useT2VTools.d.ts +1 -1
- package/dist/react/useT2VTools.d.ts.map +1 -1
- package/dist/react/useT2VTools.js +1 -1
- package/dist/react/useT2VTools.js.map +1 -1
- package/dist/react/useUserPreferences.d.ts +1 -1
- package/dist/react/useUserPreferences.d.ts.map +1 -1
- package/dist/react/useUserPreferences.js +1 -1
- package/dist/react/useUserPreferences.js.map +1 -1
- package/dist/sessions.d.ts +3 -3
- package/dist/sessions.d.ts.map +1 -1
- package/dist/skills.d.ts +2 -2
- package/dist/skills.d.ts.map +1 -1
- package/dist/streaming.d.ts +1 -1
- package/dist/streaming.d.ts.map +1 -1
- package/dist/tools.d.ts +2 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/types.d.ts +146 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/components/ApprovalCard.d.ts +1 -1
- package/dist/ui/components/ApprovalCard.d.ts.map +1 -1
- package/dist/ui/components/ChatHeader.js +1 -1
- package/dist/ui/components/ChatHeader.js.map +1 -1
- package/dist/ui/components/ChatPanel.d.ts +1 -1
- package/dist/ui/components/ChatPanel.d.ts.map +1 -1
- package/dist/ui/components/ChatPanel.js +14 -13
- package/dist/ui/components/ChatPanel.js.map +1 -1
- package/dist/ui/components/ChatWidget.d.ts +1 -1
- package/dist/ui/components/ChatWidget.d.ts.map +1 -1
- package/dist/ui/components/ChatWidget.js +2 -2
- package/dist/ui/components/ChatWidget.js.map +1 -1
- package/dist/ui/components/Composer.d.ts.map +1 -1
- package/dist/ui/components/Composer.js +13 -6
- package/dist/ui/components/Composer.js.map +1 -1
- package/dist/ui/components/LoginForm.d.ts.map +1 -1
- package/dist/ui/components/LoginForm.js +19 -5
- package/dist/ui/components/LoginForm.js.map +1 -1
- package/dist/ui/components/MarkdownRenderer.d.ts +4 -0
- package/dist/ui/components/MarkdownRenderer.d.ts.map +1 -1
- package/dist/ui/components/MarkdownRenderer.js +7 -35
- package/dist/ui/components/MarkdownRenderer.js.map +1 -1
- package/dist/ui/components/MessageActions.js +1 -1
- package/dist/ui/components/MessageActions.js.map +1 -1
- package/dist/ui/components/MessageBubble.d.ts +1 -1
- package/dist/ui/components/MessageBubble.d.ts.map +1 -1
- package/dist/ui/components/MessageBubble.js +9 -9
- package/dist/ui/components/MessageBubble.js.map +1 -1
- package/dist/ui/components/MessageList.js +2 -2
- package/dist/ui/components/MessageList.js.map +1 -1
- package/dist/ui/components/SettingsPanel.js +6 -6
- package/dist/ui/components/SettingsPanel.js.map +1 -1
- package/dist/ui/components/Talk2View.d.ts +1 -1
- package/dist/ui/components/Talk2View.d.ts.map +1 -1
- package/dist/ui/components/Talk2View.js +16 -12
- package/dist/ui/components/Talk2View.js.map +1 -1
- package/dist/ui/components/ThinkingBlock.js +2 -2
- package/dist/ui/components/ThinkingBlock.js.map +1 -1
- package/dist/ui/components/WelcomeScreen.js +2 -2
- package/dist/ui/components/WelcomeScreen.js.map +1 -1
- package/dist/ui/context.d.ts +4 -2
- package/dist/ui/context.d.ts.map +1 -1
- package/dist/ui/context.js.map +1 -1
- package/dist/ui/index.d.ts +27 -26
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +21 -20
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/safeMarkdown.d.ts +17 -0
- package/dist/ui/safeMarkdown.d.ts.map +1 -0
- package/dist/ui/safeMarkdown.js +196 -0
- package/dist/ui/safeMarkdown.js.map +1 -0
- package/dist/ui/theme.d.ts +1 -1
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/utils.d.ts +1 -1
- package/dist/ui/utils.d.ts.map +1 -1
- package/package.json +26 -2
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/** Option ids the stock assistant-ui approval card sends back; we map them onto `HumanDecision`. */
|
|
2
|
+
export const APPROVAL_OPTION_IDS = {
|
|
3
|
+
once: 'allow-once',
|
|
4
|
+
always: 'allow-always',
|
|
5
|
+
deny: 'reject-once',
|
|
6
|
+
};
|
|
7
|
+
const APPROVAL_OPTIONS = [
|
|
8
|
+
{ id: APPROVAL_OPTION_IDS.once, kind: 'allow-once', label: 'Allow once' },
|
|
9
|
+
{ id: APPROVAL_OPTION_IDS.always, kind: 'allow-always', label: 'Always allow' },
|
|
10
|
+
{ id: APPROVAL_OPTION_IDS.deny, kind: 'reject-once', label: 'Deny' },
|
|
11
|
+
];
|
|
12
|
+
/** Stable id for a completed step: steps carry no id of their own. */
|
|
13
|
+
export function stepToolCallId(messageId, index) {
|
|
14
|
+
return `${messageId}:step:${index}`;
|
|
15
|
+
}
|
|
16
|
+
function stepPart(messageId, step, index) {
|
|
17
|
+
const denied = step.status === 'denied';
|
|
18
|
+
return {
|
|
19
|
+
type: 'tool-call',
|
|
20
|
+
toolCallId: stepToolCallId(messageId, index),
|
|
21
|
+
toolName: step.name,
|
|
22
|
+
args: (step.args ?? {}),
|
|
23
|
+
// A running step has no result yet, which is how assistant-ui shows a spinner.
|
|
24
|
+
...(step.status === 'running'
|
|
25
|
+
? {}
|
|
26
|
+
: { result: step.result ?? (denied ? 'Denied by the user' : ''), isError: denied }),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** The approval gate assistant-ui draws for a tool call that needs a decision. */
|
|
30
|
+
export function approvalPart(approval) {
|
|
31
|
+
return {
|
|
32
|
+
type: 'tool-call',
|
|
33
|
+
toolCallId: approval.toolCallId,
|
|
34
|
+
toolName: approval.toolName,
|
|
35
|
+
args: approval.arguments,
|
|
36
|
+
approval: {
|
|
37
|
+
id: approval.toolCallId,
|
|
38
|
+
prompt: approval.description,
|
|
39
|
+
display: 'decision',
|
|
40
|
+
// A reason may accompany the decision; the SDK forwards it as feedback.
|
|
41
|
+
allowFreeform: true,
|
|
42
|
+
options: APPROVAL_OPTIONS,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The SDK records a `running` step for the tool awaiting approval, so the
|
|
48
|
+
* gate replaces that step rather than sitting beside it; the part keeps the
|
|
49
|
+
* engine's tool-call id so the decision can be matched back.
|
|
50
|
+
*/
|
|
51
|
+
function withApprovalGate(parts, approval) {
|
|
52
|
+
const gate = approvalPart(approval);
|
|
53
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
54
|
+
const p = parts[i];
|
|
55
|
+
if (p.type === 'tool-call' && p.toolName === approval.toolName && p.result === undefined) {
|
|
56
|
+
return [...parts.slice(0, i), gate, ...parts.slice(i + 1)];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return [...parts, gate];
|
|
60
|
+
}
|
|
61
|
+
function attachmentType(mime) {
|
|
62
|
+
return mime.startsWith('image/') ? 'image' : 'document';
|
|
63
|
+
}
|
|
64
|
+
function toThreadAttachment(a) {
|
|
65
|
+
return {
|
|
66
|
+
id: a.id,
|
|
67
|
+
type: attachmentType(a.mime_type),
|
|
68
|
+
name: a.filename,
|
|
69
|
+
contentType: a.mime_type,
|
|
70
|
+
status: { type: 'complete' },
|
|
71
|
+
// The engine resolves the bytes by id; nothing is inlined into the message.
|
|
72
|
+
content: [],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** Convert one SDK message for assistant-ui. */
|
|
76
|
+
export function toThreadMessage(msg, ctx) {
|
|
77
|
+
if (msg.role === 'user') {
|
|
78
|
+
return {
|
|
79
|
+
id: msg.id,
|
|
80
|
+
role: 'user',
|
|
81
|
+
createdAt: msg.timestamp,
|
|
82
|
+
content: [{ type: 'text', text: msg.content }],
|
|
83
|
+
...(msg.attachments?.length ? { attachments: msg.attachments.map(toThreadAttachment) } : {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
let parts = (msg.steps ?? []).map((step, i) => stepPart(msg.id, step, i));
|
|
87
|
+
const waiting = ctx.isLast && ctx.pendingApproval ? ctx.pendingApproval : null;
|
|
88
|
+
if (waiting)
|
|
89
|
+
parts = withApprovalGate(parts, waiting);
|
|
90
|
+
if (msg.plan)
|
|
91
|
+
parts.push({ type: 'data-plan', data: { markdown: msg.plan } });
|
|
92
|
+
if (msg.content || parts.length === 0)
|
|
93
|
+
parts.push({ type: 'text', text: msg.content });
|
|
94
|
+
const status = waiting
|
|
95
|
+
? { type: 'requires-action', reason: 'tool-calls' }
|
|
96
|
+
: msg.isStreaming
|
|
97
|
+
? { type: 'running' }
|
|
98
|
+
: ctx.isLast && ctx.error
|
|
99
|
+
? { type: 'incomplete', reason: 'error', error: ctx.error }
|
|
100
|
+
: { type: 'complete', reason: 'stop' };
|
|
101
|
+
return { id: msg.id, role: 'assistant', createdAt: msg.timestamp, content: parts, status };
|
|
102
|
+
}
|
|
103
|
+
/** Turn the stock approval card's answer into the SDK's `HumanDecision`. */
|
|
104
|
+
export function toHumanDecision(response) {
|
|
105
|
+
const feedback = response.text ?? response.reason;
|
|
106
|
+
const action = response.optionId === APPROVAL_OPTION_IDS.always
|
|
107
|
+
? 'always'
|
|
108
|
+
: response.optionId === APPROVAL_OPTION_IDS.once || (response.optionId === undefined && response.approved)
|
|
109
|
+
? 'once'
|
|
110
|
+
: 'deny';
|
|
111
|
+
return feedback ? { action, feedback } : { action };
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/assistant-ui/convert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dictation for assistant-ui's composer, transcribed by Talk2View.
|
|
3
|
+
*
|
|
4
|
+
* assistant-ui shows its mic button whenever the runtime has a dictation
|
|
5
|
+
* adapter. This one records with MediaRecorder and sends the clip to the
|
|
6
|
+
* engine's speech-to-text endpoint (`t2v.transcribe`) when the end-user stops
|
|
7
|
+
* — the same flow as the first-party composer in `/ui`, so the partner's
|
|
8
|
+
* speech-to-text models, language setting and billing all apply.
|
|
9
|
+
*/
|
|
10
|
+
import type { DictationAdapter } from '@assistant-ui/react';
|
|
11
|
+
import type { Talk2View } from '../index.js';
|
|
12
|
+
export interface Talk2ViewDictationOptions {
|
|
13
|
+
/** Speech-to-text model id (one of `t2v.listAudioModels()`). */
|
|
14
|
+
model?: string;
|
|
15
|
+
/** Spoken language hint, e.g. `'en'`. Omit to let the model detect it. */
|
|
16
|
+
language?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Called when the microphone is refused or transcription fails. assistant-ui
|
|
19
|
+
* has no surface for a dictation error, so without this the mic just stops.
|
|
20
|
+
*/
|
|
21
|
+
onError?: (error: unknown) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Where a dictation is up to. assistant-ui reports "listening" for the whole
|
|
24
|
+
* time, including the wait for the transcript after the end-user stops —
|
|
25
|
+
* use this to show that wait as its own state (`'transcribing'`).
|
|
26
|
+
*/
|
|
27
|
+
onPhaseChange?: (phase: Talk2ViewDictationPhase) => void;
|
|
28
|
+
}
|
|
29
|
+
export type Talk2ViewDictationPhase = 'listening' | 'transcribing' | 'idle';
|
|
30
|
+
/** The client, as far as dictation needs it. Only `transcribe` is required. */
|
|
31
|
+
export type Talk2ViewDictationClient = Pick<Talk2View, 'transcribe'> & Partial<Pick<Talk2View, 'ensureSession' | 'getConfig' | 'warmUp'>>;
|
|
32
|
+
/** Used when neither the caller nor the partner configuration names a model. */
|
|
33
|
+
export declare const DEFAULT_DICTATION_MODEL = "faster-whisper-base";
|
|
34
|
+
/**
|
|
35
|
+
* @param getOptions read when a recording is sent, so a settings change
|
|
36
|
+
* applies to the next dictation without rebuilding the runtime.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createTalk2ViewDictationAdapter(t2v: Talk2ViewDictationClient, getOptions?: () => Talk2ViewDictationOptions): DictationAdapter;
|
|
39
|
+
//# sourceMappingURL=dictation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictation.d.ts","sourceRoot":"","sources":["../../src/assistant-ui/dictation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,yBAAyB;IACxC,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG,cAAc,GAAG,MAAM,CAAC;AAE5E,+EAA+E;AAC/E,MAAM,MAAM,wBAAwB,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,GAClE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,GAAG,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC;AAErE,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAW7D;;;GAGG;AACH,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,wBAAwB,EAC7B,UAAU,GAAE,MAAM,yBAAsC,GACvD,gBAAgB,CAgHlB"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/** Used when neither the caller nor the partner configuration names a model. */
|
|
2
|
+
export const DEFAULT_DICTATION_MODEL = 'faster-whisper-base';
|
|
3
|
+
function subscribe(set, cb) {
|
|
4
|
+
set.add(cb);
|
|
5
|
+
return () => {
|
|
6
|
+
set.delete(cb);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* @param getOptions read when a recording is sent, so a settings change
|
|
11
|
+
* applies to the next dictation without rebuilding the runtime.
|
|
12
|
+
*/
|
|
13
|
+
export function createTalk2ViewDictationAdapter(t2v, getOptions = () => ({})) {
|
|
14
|
+
return {
|
|
15
|
+
listen() {
|
|
16
|
+
const onStart = new Set();
|
|
17
|
+
const onEnd = new Set();
|
|
18
|
+
const onSpeech = new Set();
|
|
19
|
+
const chunks = [];
|
|
20
|
+
let stream = null;
|
|
21
|
+
let recorder = null;
|
|
22
|
+
let cancelled = false;
|
|
23
|
+
let settle;
|
|
24
|
+
const settled = new Promise((resolve) => {
|
|
25
|
+
settle = resolve;
|
|
26
|
+
});
|
|
27
|
+
const releaseMic = () => stream?.getTracks().forEach((track) => track.stop());
|
|
28
|
+
const phase = (next) => getOptions().onPhaseChange?.(next);
|
|
29
|
+
const finish = (reason) => {
|
|
30
|
+
releaseMic();
|
|
31
|
+
session.status = { type: 'ended', reason };
|
|
32
|
+
phase('idle');
|
|
33
|
+
settle();
|
|
34
|
+
};
|
|
35
|
+
// A logged-out visitor's first action can be the mic. Start the session
|
|
36
|
+
// and mint their key now, while they talk. The two are kept apart: the
|
|
37
|
+
// model lookup below needs only the session, and the mint is seconds long
|
|
38
|
+
// — a short clip must not wait for it. `async` wrappers so a client whose
|
|
39
|
+
// method throws synchronously cannot take the mic down with it.
|
|
40
|
+
const startSession = async () => void (await t2v.ensureSession?.());
|
|
41
|
+
const warm = async () => void (await t2v.warmUp?.());
|
|
42
|
+
const warming = warm().catch(() => undefined);
|
|
43
|
+
// Without ensureSession() the warm-up is the only thing that starts one.
|
|
44
|
+
const ready = t2v.ensureSession ? startSession().catch(() => undefined) : warming;
|
|
45
|
+
const partnerModel = ready
|
|
46
|
+
.then(() => t2v.getConfig?.())
|
|
47
|
+
.then((config) => config?.default_stt_model || undefined)
|
|
48
|
+
.catch(() => undefined);
|
|
49
|
+
const session = {
|
|
50
|
+
status: { type: 'starting' },
|
|
51
|
+
// Resolves only once the transcript has been delivered: the composer
|
|
52
|
+
// unsubscribes as soon as stop() settles, and the clip is transcribed
|
|
53
|
+
// after the recording ends, not during it.
|
|
54
|
+
stop: async () => {
|
|
55
|
+
if (recorder?.state === 'recording')
|
|
56
|
+
recorder.stop();
|
|
57
|
+
else if (session.status.type !== 'ended' && !recorder)
|
|
58
|
+
cancelled = true;
|
|
59
|
+
await settled;
|
|
60
|
+
},
|
|
61
|
+
cancel: () => {
|
|
62
|
+
cancelled = true;
|
|
63
|
+
if (recorder?.state === 'recording')
|
|
64
|
+
recorder.stop();
|
|
65
|
+
else if (session.status.type !== 'ended')
|
|
66
|
+
finish('cancelled');
|
|
67
|
+
},
|
|
68
|
+
onSpeechStart: (cb) => subscribe(onStart, cb),
|
|
69
|
+
onSpeechEnd: (cb) => subscribe(onEnd, cb),
|
|
70
|
+
onSpeech: (cb) => subscribe(onSpeech, cb),
|
|
71
|
+
};
|
|
72
|
+
void (async () => {
|
|
73
|
+
try {
|
|
74
|
+
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
75
|
+
if (cancelled)
|
|
76
|
+
return finish('cancelled');
|
|
77
|
+
const mimeType = MediaRecorder.isTypeSupported('audio/webm;codecs=opus')
|
|
78
|
+
? 'audio/webm;codecs=opus'
|
|
79
|
+
: 'audio/webm';
|
|
80
|
+
recorder = new MediaRecorder(stream, { mimeType });
|
|
81
|
+
recorder.ondataavailable = (e) => {
|
|
82
|
+
if (e.data.size > 0)
|
|
83
|
+
chunks.push(e.data);
|
|
84
|
+
};
|
|
85
|
+
recorder.onstop = async () => {
|
|
86
|
+
// The clip is complete: the browser's recording indicator goes off
|
|
87
|
+
// now, not after the engine answers.
|
|
88
|
+
releaseMic();
|
|
89
|
+
if (cancelled || chunks.length === 0)
|
|
90
|
+
return finish(cancelled ? 'cancelled' : 'stopped');
|
|
91
|
+
phase('transcribing');
|
|
92
|
+
try {
|
|
93
|
+
const { model: chosen, language } = getOptions();
|
|
94
|
+
const model = chosen || (await partnerModel);
|
|
95
|
+
const form = new FormData();
|
|
96
|
+
form.append('file', new Blob(chunks, { type: mimeType }), 'recording.webm');
|
|
97
|
+
form.append('model', model || DEFAULT_DICTATION_MODEL);
|
|
98
|
+
if (language)
|
|
99
|
+
form.append('language', language);
|
|
100
|
+
const transcript = (await t2v.transcribe(form)).text.trim();
|
|
101
|
+
if (transcript && !cancelled) {
|
|
102
|
+
// The composer appends on a final `onSpeech`; `onSpeechEnd` only closes the session.
|
|
103
|
+
onSpeech.forEach((cb) => cb({ transcript, isFinal: true }));
|
|
104
|
+
onEnd.forEach((cb) => cb({ transcript }));
|
|
105
|
+
}
|
|
106
|
+
finish(cancelled ? 'cancelled' : 'stopped');
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
getOptions().onError?.(error);
|
|
110
|
+
finish('error');
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
recorder.start();
|
|
114
|
+
session.status = { type: 'running' };
|
|
115
|
+
phase('listening');
|
|
116
|
+
onStart.forEach((cb) => cb());
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
// Microphone refused, or no MediaRecorder in this browser.
|
|
120
|
+
getOptions().onError?.(error);
|
|
121
|
+
finish('error');
|
|
122
|
+
}
|
|
123
|
+
})();
|
|
124
|
+
return session;
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=dictation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictation.js","sourceRoot":"","sources":["../../src/assistant-ui/dictation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AssistantRuntime } from '@assistant-ui/react';
|
|
2
|
+
import { Talk2View } from '../index.js';
|
|
3
|
+
import type { ClientTool, ClientToolSchema, T2VConfig } from '../types.js';
|
|
4
|
+
import { type Talk2ViewDictationOptions } from './dictation.js';
|
|
5
|
+
export type { Talk2ViewDictationClient, Talk2ViewDictationPhase } from './dictation.js';
|
|
6
|
+
export { toThreadMessage, toHumanDecision, APPROVAL_OPTION_IDS } from './convert.js';
|
|
7
|
+
export type { ConvertContext } from './convert.js';
|
|
8
|
+
export { createTalk2ViewDictationAdapter, DEFAULT_DICTATION_MODEL } from './dictation.js';
|
|
9
|
+
export type { Talk2ViewDictationOptions } from './dictation.js';
|
|
10
|
+
/** Options shared by both forms of the hook. */
|
|
11
|
+
export interface Talk2ViewRuntimeOptions {
|
|
12
|
+
/** Sent with every message. */
|
|
13
|
+
systemPrompt?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Client tools the agent may call; handlers run in your app. Registered
|
|
16
|
+
* with the engine whenever the set of schemas changes (compared by value,
|
|
17
|
+
* so an inline array is fine).
|
|
18
|
+
*/
|
|
19
|
+
tools?: (ClientToolSchema | ClientTool)[];
|
|
20
|
+
/**
|
|
21
|
+
* Model for the next message — for example the end-user's choice from a
|
|
22
|
+
* settings screen. Unlike the client's `model`, changing it keeps the chat.
|
|
23
|
+
*/
|
|
24
|
+
model?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Turn on assistant-ui's mic button, transcribed by Talk2View. `true` uses
|
|
27
|
+
* the default speech-to-text model; pass `{ model, language }` to choose.
|
|
28
|
+
*/
|
|
29
|
+
dictation?: boolean | Talk2ViewDictationOptions;
|
|
30
|
+
}
|
|
31
|
+
export interface UseTalk2ViewRuntimeOptions extends T2VConfig, Talk2ViewRuntimeOptions {
|
|
32
|
+
}
|
|
33
|
+
/** Create a Talk2View client and expose it as an assistant-ui runtime. */
|
|
34
|
+
export declare function useTalk2ViewRuntime(options: UseTalk2ViewRuntimeOptions): AssistantRuntime;
|
|
35
|
+
/** Expose an existing client (for example the one from `useT2V()`) as an assistant-ui runtime. */
|
|
36
|
+
export declare function useTalk2ViewRuntimeForClient(t2v: Talk2View, { systemPrompt, tools, model, dictation }?: Talk2ViewRuntimeOptions): AssistantRuntime;
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assistant-ui/index.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAEV,gBAAgB,EAKjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,KAAK,EAEV,UAAU,EACV,gBAAgB,EAGhB,SAAS,EACV,MAAM,aAAa,CAAC;AAErB,OAAO,EAAmC,KAAK,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AACjG,YAAY,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAExF,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACrF,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,+BAA+B,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,YAAY,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAEhE,gDAAgD;AAChD,MAAM,WAAW,uBAAuB;IACtC,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,CAAC,gBAAgB,GAAG,UAAU,CAAC,EAAE,CAAC;IAC1C;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;CACjD;AAED,MAAM,WAAW,0BAA2B,SAAQ,SAAS,EAAE,uBAAuB;CAAG;AAKzF,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,gBAAgB,CAezF;AAED,kGAAkG;AAClG,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,SAAS,EACd,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAE,uBAA4B,GACtE,gBAAgB,CAiMlB"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* assistant-ui runtime for Talk2View.
|
|
3
|
+
*
|
|
4
|
+
* Talk2View plugs into assistant-ui the way its other backends do — at the
|
|
5
|
+
* runtime seam, not by shipping a fork of its components. Hand the runtime to
|
|
6
|
+
* `<AssistantRuntimeProvider>` and render the stock `<Thread />` (or the
|
|
7
|
+
* primitives): messages stream, client tools run in your app, and tool
|
|
8
|
+
* approvals appear as assistant-ui's own approval card.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { AssistantRuntimeProvider } from '@assistant-ui/react';
|
|
13
|
+
* import { useTalk2ViewRuntime } from '@talk2view/sdk/assistant-ui';
|
|
14
|
+
*
|
|
15
|
+
* function Chat() {
|
|
16
|
+
* const runtime = useTalk2ViewRuntime({ partnerKey: 'pk_live_...', tools });
|
|
17
|
+
* return (
|
|
18
|
+
* <AssistantRuntimeProvider runtime={runtime}>
|
|
19
|
+
* <Thread />
|
|
20
|
+
* </AssistantRuntimeProvider>
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* `@assistant-ui/react` is an optional peer dependency: it is only loaded by
|
|
26
|
+
* this entry point, never by `@talk2view/sdk`, `/react` or `/ui`.
|
|
27
|
+
*
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
*/
|
|
30
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
31
|
+
import { useExternalStoreRuntime } from '@assistant-ui/react';
|
|
32
|
+
import { Talk2View } from '../index.js';
|
|
33
|
+
import { ATTACHMENT_ACCEPT } from '../constants.js';
|
|
34
|
+
import { toHumanDecision, toThreadMessage } from './convert.js';
|
|
35
|
+
import { createTalk2ViewDictationAdapter } from './dictation.js';
|
|
36
|
+
export { toThreadMessage, toHumanDecision, APPROVAL_OPTION_IDS } from './convert.js';
|
|
37
|
+
export { createTalk2ViewDictationAdapter, DEFAULT_DICTATION_MODEL } from './dictation.js';
|
|
38
|
+
/** What Stop means while a tool call is waiting on the end-user. */
|
|
39
|
+
const CANCELLED_APPROVAL_FEEDBACK = 'Cancelled by the user';
|
|
40
|
+
/** Create a Talk2View client and expose it as an assistant-ui runtime. */
|
|
41
|
+
export function useTalk2ViewRuntime(options) {
|
|
42
|
+
const { systemPrompt, tools, model: messageModel, dictation, ...config } = options;
|
|
43
|
+
// A new client only when the connection details change. `model` is not one
|
|
44
|
+
// of them here: it travels with each message, so an end-user can switch
|
|
45
|
+
// models from a settings screen without losing the chat.
|
|
46
|
+
const t2v = useMemo(() => new Talk2View(config),
|
|
47
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
|
+
[config.partnerKey, config.baseUrl, config.debug, config.anonymousAutoStart]);
|
|
49
|
+
const runtime = useTalk2ViewRuntimeForClient(t2v, { systemPrompt, tools, model: messageModel, dictation });
|
|
50
|
+
// Declared after the subscriptions above so, on a client swap or unmount,
|
|
51
|
+
// React runs their cleanup first and destroys the client last.
|
|
52
|
+
useEffect(() => () => t2v.destroy(), [t2v]);
|
|
53
|
+
return runtime;
|
|
54
|
+
}
|
|
55
|
+
/** Expose an existing client (for example the one from `useT2V()`) as an assistant-ui runtime. */
|
|
56
|
+
export function useTalk2ViewRuntimeForClient(t2v, { systemPrompt, tools, model, dictation } = {}) {
|
|
57
|
+
const [messages, setMessages] = useState(t2v.messages);
|
|
58
|
+
const [isLoading, setIsLoading] = useState(t2v.isLoading);
|
|
59
|
+
const [error, setError] = useState(t2v.error);
|
|
60
|
+
const [pendingApproval, setPendingApproval] = useState(t2v.pendingApproval);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
setMessages(t2v.messages);
|
|
63
|
+
setIsLoading(t2v.isLoading);
|
|
64
|
+
setError(t2v.error);
|
|
65
|
+
setPendingApproval(t2v.pendingApproval);
|
|
66
|
+
const unsubs = [
|
|
67
|
+
t2v.on('messagesChange', setMessages),
|
|
68
|
+
t2v.on('loadingChange', setIsLoading),
|
|
69
|
+
t2v.on('errorChange', setError),
|
|
70
|
+
t2v.on('approvalChange', setPendingApproval),
|
|
71
|
+
];
|
|
72
|
+
return () => unsubs.forEach((u) => u());
|
|
73
|
+
}, [t2v]);
|
|
74
|
+
// Register tools the way <Talk2View> does: schemas to the engine, handlers
|
|
75
|
+
// locally. Keyed by value so a partner's inline `tools` array does not
|
|
76
|
+
// re-register on every render (this hook re-renders on every stream chunk).
|
|
77
|
+
const schemas = useMemo(() => (tools ?? []).map((tool) => {
|
|
78
|
+
const { execute: _execute, ...schema } = tool;
|
|
79
|
+
return schema;
|
|
80
|
+
}), [tools]);
|
|
81
|
+
const schemaKey = useMemo(() => JSON.stringify(schemas), [schemas]);
|
|
82
|
+
const registered = useRef(null);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (schemas.length === 0)
|
|
85
|
+
return;
|
|
86
|
+
for (const tool of tools ?? []) {
|
|
87
|
+
if ('execute' in tool && tool.execute)
|
|
88
|
+
t2v.tools.handle(tool.name, tool.execute);
|
|
89
|
+
}
|
|
90
|
+
if (registered.current?.t2v === t2v && registered.current.key === schemaKey)
|
|
91
|
+
return;
|
|
92
|
+
registered.current = { t2v, key: schemaKey };
|
|
93
|
+
t2v.tools.register(schemas).catch(() => { });
|
|
94
|
+
}, [t2v, tools, schemas, schemaKey]);
|
|
95
|
+
// Uploaded files, by the id assistant-ui hands back in the composed message.
|
|
96
|
+
const uploaded = useRef(new Map());
|
|
97
|
+
const attachments = useMemo(() => ({
|
|
98
|
+
accept: ATTACHMENT_ACCEPT,
|
|
99
|
+
async add({ file }) {
|
|
100
|
+
return {
|
|
101
|
+
id: pendingId(),
|
|
102
|
+
type: file.type.startsWith('image/') ? 'image' : 'document',
|
|
103
|
+
name: file.name,
|
|
104
|
+
contentType: file.type,
|
|
105
|
+
file,
|
|
106
|
+
status: { type: 'requires-action', reason: 'composer-send' },
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
async send(pending) {
|
|
110
|
+
const stored = await t2v.uploadAttachment(pending.file, pending.file.name);
|
|
111
|
+
uploaded.current.set(stored.id, stored);
|
|
112
|
+
return {
|
|
113
|
+
id: stored.id,
|
|
114
|
+
type: pending.type,
|
|
115
|
+
name: stored.filename,
|
|
116
|
+
contentType: stored.mime_type,
|
|
117
|
+
status: { type: 'complete' },
|
|
118
|
+
// The engine resolves the bytes by id; nothing is inlined.
|
|
119
|
+
content: [],
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
async remove() {
|
|
123
|
+
// Uploads are cheap and expire server-side; nothing to undo client-side.
|
|
124
|
+
},
|
|
125
|
+
}), [t2v]);
|
|
126
|
+
// One adapter per client; the options are read when a clip is sent, so a
|
|
127
|
+
// settings change applies to the next dictation without a new runtime.
|
|
128
|
+
const dictationOptions = useRef({});
|
|
129
|
+
dictationOptions.current = typeof dictation === 'object' ? dictation : {};
|
|
130
|
+
const dictationEnabled = Boolean(dictation);
|
|
131
|
+
const dictationAdapter = useMemo(() => (dictationEnabled ? createTalk2ViewDictationAdapter(t2v, () => dictationOptions.current) : null), [t2v, dictationEnabled]);
|
|
132
|
+
// A turn that fails before its first text chunk leaves no assistant message
|
|
133
|
+
// behind (the SDK drops the empty one), and assistant-ui can only show an
|
|
134
|
+
// error on an assistant message — so give it one to show it on.
|
|
135
|
+
const threadMessages = useMemo(() => {
|
|
136
|
+
const last = messages[messages.length - 1];
|
|
137
|
+
if (error && last && last.role !== 'assistant') {
|
|
138
|
+
return [...messages, { id: `${last.id}:error`, role: 'assistant', content: '', timestamp: new Date() }];
|
|
139
|
+
}
|
|
140
|
+
return messages;
|
|
141
|
+
}, [messages, error]);
|
|
142
|
+
const convertMessage = useCallback((msg, idx) => toThreadMessage(msg, { isLast: idx === threadMessages.length - 1, pendingApproval, error }), [threadMessages.length, pendingApproval, error]);
|
|
143
|
+
const onNew = useCallback(async (message) => {
|
|
144
|
+
const text = message.content
|
|
145
|
+
.filter((p) => p.type === 'text')
|
|
146
|
+
.map((p) => p.text)
|
|
147
|
+
.join('\n');
|
|
148
|
+
const files = (message.attachments ?? []).map((a) => {
|
|
149
|
+
const stored = uploaded.current.get(a.id);
|
|
150
|
+
uploaded.current.delete(a.id);
|
|
151
|
+
// The id is the engine's whichever way we got here; rebuild the rest
|
|
152
|
+
// if the upload happened before this hook instance existed.
|
|
153
|
+
return stored ?? { id: a.id, filename: a.name, mime_type: a.contentType ?? '', size_bytes: a.file?.size ?? 0 };
|
|
154
|
+
});
|
|
155
|
+
await t2v.sendMessage(text, {
|
|
156
|
+
...(systemPrompt ? { systemPrompt } : {}),
|
|
157
|
+
...(model ? { model } : {}),
|
|
158
|
+
...(files.length ? { attachments: files } : {}),
|
|
159
|
+
});
|
|
160
|
+
}, [t2v, systemPrompt, model]);
|
|
161
|
+
// assistant-ui puts a reload action on every assistant message; the SDK
|
|
162
|
+
// can only regenerate the latest turn — the one started by the last user
|
|
163
|
+
// message. That includes the error card and every segment of that turn;
|
|
164
|
+
// reload of an older reply is a no-op rather than a silent rewrite of the
|
|
165
|
+
// newest one.
|
|
166
|
+
const onReload = useCallback(async (parentId) => {
|
|
167
|
+
const lastUser = [...messages].reverse().find((m) => m.role === 'user');
|
|
168
|
+
if (!lastUser || parentId !== lastUser.id)
|
|
169
|
+
return;
|
|
170
|
+
await t2v.retryLastMessage();
|
|
171
|
+
}, [t2v, messages]);
|
|
172
|
+
// Stop while a tool call waits on the end-user: the SDK is not streaming,
|
|
173
|
+
// so stop() would do nothing — deny the call instead, which is what a
|
|
174
|
+
// partner expects Stop to mean there.
|
|
175
|
+
const onCancel = useCallback(async () => {
|
|
176
|
+
if (t2v.pendingApproval) {
|
|
177
|
+
await t2v.approveToolCall({ action: 'deny', feedback: CANCELLED_APPROVAL_FEEDBACK });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
t2v.stop();
|
|
181
|
+
}, [t2v]);
|
|
182
|
+
const adapter = useMemo(() => ({
|
|
183
|
+
messages: threadMessages,
|
|
184
|
+
// A turn waiting on an approval is still in progress: the engine holds
|
|
185
|
+
// the interrupt, and a second message would land on top of it.
|
|
186
|
+
isRunning: isLoading || pendingApproval !== null,
|
|
187
|
+
convertMessage,
|
|
188
|
+
onNew,
|
|
189
|
+
onCancel,
|
|
190
|
+
onReload,
|
|
191
|
+
onRespondToToolApproval: async (response) => {
|
|
192
|
+
// Only the current gate can be answered; a stale card is ignored.
|
|
193
|
+
if (response.approvalId !== t2v.pendingApproval?.toolCallId)
|
|
194
|
+
return;
|
|
195
|
+
await t2v.approveToolCall(toHumanDecision(response));
|
|
196
|
+
},
|
|
197
|
+
adapters: { attachments, ...(dictationAdapter ? { dictation: dictationAdapter } : {}) },
|
|
198
|
+
}), [threadMessages, isLoading, pendingApproval, convertMessage, onNew, onCancel, onReload, t2v, attachments, dictationAdapter]);
|
|
199
|
+
const runtime = useExternalStoreRuntime(adapter);
|
|
200
|
+
// First character typed = intent. Mint the end-user's key while they finish
|
|
201
|
+
// the sentence. Not on mount and not on focus: the composer autofocuses when a
|
|
202
|
+
// chat opens, and a visitor who opens it and leaves should cost nothing.
|
|
203
|
+
// A ref, not a local: the effect re-runs under StrictMode and must not
|
|
204
|
+
// re-arm. It remembers which client it warmed, so a new client gets its own.
|
|
205
|
+
const warmedFor = useRef(null);
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
const composer = runtime.thread.composer;
|
|
208
|
+
const check = () => {
|
|
209
|
+
if (warmedFor.current === t2v || !composer.getState().text)
|
|
210
|
+
return;
|
|
211
|
+
warmedFor.current = t2v;
|
|
212
|
+
void t2v.warmUp();
|
|
213
|
+
};
|
|
214
|
+
check();
|
|
215
|
+
return composer.subscribe(check);
|
|
216
|
+
}, [runtime, t2v]);
|
|
217
|
+
return runtime;
|
|
218
|
+
}
|
|
219
|
+
let pendingCounter = 0;
|
|
220
|
+
function pendingId() {
|
|
221
|
+
pendingCounter += 1;
|
|
222
|
+
return `pending-${Date.now()}-${pendingCounter}`;
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assistant-ui/index.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auth module — login, signup, refresh, logout, auth state management.
|
|
3
3
|
*/
|
|
4
|
-
import type { T2VClient } from './client';
|
|
5
|
-
import type { User } from './types';
|
|
4
|
+
import type { T2VClient } from './client.js';
|
|
5
|
+
import type { SignupOutcome, User } from './types.js';
|
|
6
6
|
type AuthStateCallback = (user: User | null) => void;
|
|
7
|
+
export type PopupProvider = 'google' | 'apple';
|
|
7
8
|
export declare class T2VAuth {
|
|
8
9
|
private readonly client;
|
|
9
10
|
private listeners;
|
|
@@ -28,16 +29,37 @@ export declare class T2VAuth {
|
|
|
28
29
|
/** True if the current session is an anonymous demo session. */
|
|
29
30
|
isAnonymous(): boolean;
|
|
30
31
|
/**
|
|
31
|
-
* Create a
|
|
32
|
+
* Create a permanent account.
|
|
33
|
+
*
|
|
34
|
+
* From an anonymous session this CONVERTS in place (same user id — history
|
|
35
|
+
* and purchases stay). The server emails a confirmation link; until it is
|
|
36
|
+
* clicked the session remains anonymous and `confirmationRequired` is true.
|
|
37
|
+
* A 409 means the email already has an account → we sign into it instead.
|
|
32
38
|
*/
|
|
33
|
-
signup(email: string, password: string): Promise<
|
|
39
|
+
signup(email: string, password: string): Promise<SignupOutcome>;
|
|
34
40
|
/**
|
|
35
41
|
* Authenticate with email and password.
|
|
36
42
|
*/
|
|
37
43
|
login(email: string, password: string): Promise<User>;
|
|
38
44
|
private oauthAbort?;
|
|
45
|
+
private popupProviders;
|
|
46
|
+
/**
|
|
47
|
+
* Which popup sign-ins work from this page. They work on any https:// website;
|
|
48
|
+
* on one the partner has not registered, the end-user first sees a Talk2View
|
|
49
|
+
* screen naming the site (the partner's key is public — this is what stops
|
|
50
|
+
* another site quietly using it). Partners who only allow their registered
|
|
51
|
+
* websites get an empty list elsewhere. Never rejects.
|
|
52
|
+
*/
|
|
53
|
+
getPopupProviders(): Promise<PopupProvider[]>;
|
|
39
54
|
/** Sign in with Google via a popup (engine-mediated OAuth). */
|
|
40
55
|
signInWithGoogle(): Promise<User>;
|
|
56
|
+
/**
|
|
57
|
+
* Sign in with Apple via a popup (engine-mediated OAuth). An account made
|
|
58
|
+
* with Apple in a native app has no password, so on the web this is its only
|
|
59
|
+
* way in. Needs an engine that offers Apple in the popup flow; an older one
|
|
60
|
+
* answers the popup with 404 and this rejects when the attempt expires.
|
|
61
|
+
*/
|
|
62
|
+
signInWithApple(): Promise<User>;
|
|
41
63
|
signInWithOAuth(provider: string): Promise<User>;
|
|
42
64
|
private pollOAuthExchange;
|
|
43
65
|
/** Abortable delay used by the OAuth poll loop. */
|