@signalcore/ui 0.1.0 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +896 -513
- package/dist/AgentAbout.d.ts +186 -0
- package/dist/AgentAbout.js +1020 -0
- package/dist/AgentAbout.js.map +1 -0
- package/dist/AgentCard.d.ts +49 -0
- package/dist/AgentCard.js +77 -0
- package/dist/AgentCard.js.map +1 -0
- package/dist/AgentChat.d.ts +233 -0
- package/dist/AgentChat.js +1127 -0
- package/dist/AgentChat.js.map +1 -0
- package/dist/AgentSpace.d.ts +112 -0
- package/dist/AgentSpace.js +339 -0
- package/dist/AgentSpace.js.map +1 -0
- package/dist/AgentTasks.d.ts +48 -0
- package/dist/AgentTasks.js +120 -0
- package/dist/AgentTasks.js.map +1 -0
- package/dist/BrowserView.d.ts +52 -0
- package/dist/BrowserView.js +328 -0
- package/dist/BrowserView.js.map +1 -0
- package/dist/FileView.d.ts +63 -0
- package/dist/FileView.js +449 -0
- package/dist/FileView.js.map +1 -0
- package/dist/Modes.d.ts +13 -0
- package/dist/Modes.js +75 -0
- package/dist/Modes.js.map +1 -0
- package/dist/VoiceCall.d.ts +91 -0
- package/dist/VoiceCall.js +302 -0
- package/dist/VoiceCall.js.map +1 -0
- package/dist/about.d.ts +212 -0
- package/dist/about.js +136 -0
- package/dist/about.js.map +1 -0
- package/dist/agentIcons.d.ts +33 -0
- package/dist/agentIcons.js +36 -0
- package/dist/agentIcons.js.map +1 -0
- package/dist/automation/Automation.d.ts +35 -0
- package/dist/automation/Automation.js +268 -0
- package/dist/automation/Automation.js.map +1 -0
- package/dist/automation/RunView.d.ts +25 -0
- package/dist/automation/RunView.js +187 -0
- package/dist/automation/RunView.js.map +1 -0
- package/dist/automation/cron.d.ts +41 -0
- package/dist/automation/cron.js +169 -0
- package/dist/automation/cron.js.map +1 -0
- package/dist/automation/marks.js +121 -0
- package/dist/automation/marks.js.map +1 -0
- package/dist/automation/messages.d.ts +113 -0
- package/dist/automation/messages.js +113 -0
- package/dist/automation/messages.js.map +1 -0
- package/dist/automation/record.d.ts +47 -0
- package/dist/automation/record.js +177 -0
- package/dist/automation/record.js.map +1 -0
- package/dist/automation/types.d.ts +143 -0
- package/dist/automation/when.d.ts +36 -0
- package/dist/automation/when.js +168 -0
- package/dist/automation/when.js.map +1 -0
- package/dist/blocks.d.ts +185 -0
- package/dist/browser.js +292 -0
- package/dist/browser.js.map +1 -0
- package/dist/call.d.ts +89 -0
- package/dist/call.js +218 -0
- package/dist/call.js.map +1 -0
- package/dist/channelParts.js +26 -0
- package/dist/channelParts.js.map +1 -0
- package/dist/classes.js +8 -3
- package/dist/classes.js.map +1 -0
- package/dist/client.d.ts +146 -54
- package/dist/client.js +204 -1
- package/dist/client.js.map +1 -0
- package/dist/conversationFiles.js +46 -0
- package/dist/conversationFiles.js.map +1 -0
- package/dist/credentials.d.ts +45 -0
- package/dist/credentials.js +98 -0
- package/dist/credentials.js.map +1 -0
- package/dist/dev.js +17 -0
- package/dist/dev.js.map +1 -0
- package/dist/es.d.ts +17 -0
- package/dist/es.js +382 -0
- package/dist/es.js.map +1 -0
- package/dist/files.d.ts +21 -0
- package/dist/files.js +214 -0
- package/dist/files.js.map +1 -0
- package/dist/frames.d.ts +115 -0
- package/dist/frames.js +219 -0
- package/dist/frames.js.map +1 -0
- package/dist/icons.js +29 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +63 -60
- package/dist/index.js +59 -45
- package/dist/kit/AudioPlayer.d.ts +20 -0
- package/dist/kit/AudioPlayer.js +116 -0
- package/dist/kit/AudioPlayer.js.map +1 -0
- package/dist/kit/Button.d.ts +29 -0
- package/dist/kit/Button.js +59 -0
- package/dist/kit/Button.js.map +1 -0
- package/dist/kit/Card.d.ts +16 -0
- package/dist/kit/Card.js +36 -0
- package/dist/kit/Card.js.map +1 -0
- package/dist/kit/Chart.js +152 -0
- package/dist/kit/Chart.js.map +1 -0
- package/dist/kit/Choices.d.ts +21 -0
- package/dist/kit/Choices.js +99 -0
- package/dist/kit/Choices.js.map +1 -0
- package/dist/kit/Combobox.d.ts +26 -0
- package/dist/kit/Combobox.js +190 -0
- package/dist/kit/Combobox.js.map +1 -0
- package/dist/kit/DateField.d.ts +17 -0
- package/dist/kit/DateField.js +133 -0
- package/dist/kit/DateField.js.map +1 -0
- package/dist/kit/Field.d.ts +40 -0
- package/dist/kit/Field.js +98 -0
- package/dist/kit/Field.js.map +1 -0
- package/dist/kit/FileField.d.ts +113 -0
- package/dist/kit/FileField.js +341 -0
- package/dist/kit/FileField.js.map +1 -0
- package/dist/kit/FileMark.d.ts +15 -0
- package/dist/kit/FileMark.js +39 -0
- package/dist/kit/FileMark.js.map +1 -0
- package/dist/kit/Inputs.d.ts +59 -0
- package/dist/kit/Inputs.js +205 -0
- package/dist/kit/Inputs.js.map +1 -0
- package/dist/kit/List.d.ts +47 -0
- package/dist/kit/List.js +85 -0
- package/dist/kit/List.js.map +1 -0
- package/dist/kit/Mark.d.ts +30 -0
- package/dist/kit/Mark.js +27 -0
- package/dist/kit/Mark.js.map +1 -0
- package/dist/kit/MarkStack.d.ts +15 -0
- package/dist/kit/MarkStack.js +26 -0
- package/dist/kit/MarkStack.js.map +1 -0
- package/dist/kit/Note.d.ts +11 -0
- package/dist/kit/Note.js +31 -0
- package/dist/kit/Note.js.map +1 -0
- package/dist/kit/Popover.js +90 -0
- package/dist/kit/Popover.js.map +1 -0
- package/dist/kit/RangeField.d.ts +14 -0
- package/dist/kit/RangeField.js +47 -0
- package/dist/kit/RangeField.js.map +1 -0
- package/dist/kit/RatingField.d.ts +14 -0
- package/dist/kit/RatingField.js +50 -0
- package/dist/kit/RatingField.js.map +1 -0
- package/dist/kit/Stat.d.ts +26 -0
- package/dist/kit/Stat.js +46 -0
- package/dist/kit/Stat.js.map +1 -0
- package/dist/kit/Switch.d.ts +14 -0
- package/dist/kit/Switch.js +21 -0
- package/dist/kit/Switch.js.map +1 -0
- package/dist/kit/Tag.d.ts +16 -0
- package/dist/kit/Tag.js +20 -0
- package/dist/kit/Tag.js.map +1 -0
- package/dist/kit/Tile.d.ts +34 -0
- package/dist/kit/Tile.js +52 -0
- package/dist/kit/Tile.js.map +1 -0
- package/dist/kit/TimeField.d.ts +31 -0
- package/dist/kit/TimeField.js +109 -0
- package/dist/kit/TimeField.js.map +1 -0
- package/dist/kit/context.d.ts +22 -0
- package/dist/kit/context.js +46 -0
- package/dist/kit/context.js.map +1 -0
- package/dist/kit/dates.d.ts +14 -0
- package/dist/kit/dates.js +129 -0
- package/dist/kit/dates.js.map +1 -0
- package/dist/kit/messages.d.ts +99 -0
- package/dist/kit/messages.js +66 -0
- package/dist/kit/messages.js.map +1 -0
- package/dist/kit/numbers.d.ts +12 -0
- package/dist/kit/numbers.js +40 -0
- package/dist/kit/numbers.js.map +1 -0
- package/dist/kit/options.d.ts +10 -0
- package/dist/kit/options.js +23 -0
- package/dist/kit/options.js.map +1 -0
- package/dist/kit/uploads.d.ts +42 -0
- package/dist/kit/uploads.js +165 -0
- package/dist/kit/uploads.js.map +1 -0
- package/dist/kit/waveform.js +76 -0
- package/dist/kit/waveform.js.map +1 -0
- package/dist/locale.d.ts +1 -0
- package/dist/locale.js +1 -0
- package/dist/markdown.js +84 -0
- package/dist/markdown.js.map +1 -0
- package/dist/marks.js +217 -0
- package/dist/marks.js.map +1 -0
- package/dist/reveal.js +48 -0
- package/dist/reveal.js.map +1 -0
- package/dist/stepGlyphs.js +62 -0
- package/dist/stepGlyphs.js.map +1 -0
- package/dist/surface/Form.js +264 -0
- package/dist/surface/Form.js.map +1 -0
- package/dist/surface/Markdown.js +42 -0
- package/dist/surface/Markdown.js.map +1 -0
- package/dist/surface/Surface.d.ts +31 -17
- package/dist/surface/Surface.js +480 -57
- package/dist/surface/Surface.js.map +1 -0
- package/dist/surface/scope.d.ts +32 -0
- package/dist/surface/scope.js +23 -0
- package/dist/surface/scope.js.map +1 -0
- package/dist/surface/values.d.ts +44 -0
- package/dist/surface/values.js +237 -0
- package/dist/surface/values.js.map +1 -0
- package/dist/tint.d.ts +10 -0
- package/dist/tint.js +19 -0
- package/dist/tint.js.map +1 -0
- package/dist/types.d.ts +541 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/useAgentFace.d.ts +18 -0
- package/dist/useAgentFace.js +45 -0
- package/dist/useAgentFace.js.map +1 -0
- package/dist/useCall.d.ts +39 -0
- package/dist/useCall.js +273 -0
- package/dist/useCall.js.map +1 -0
- package/dist/useConversation.d.ts +77 -0
- package/dist/useConversation.js +523 -0
- package/dist/useConversation.js.map +1 -0
- package/dist/useDictation.d.ts +17 -0
- package/dist/useDictation.js +68 -0
- package/dist/useDictation.js.map +1 -0
- package/dist/useLive.d.ts +26 -0
- package/dist/useLive.js +88 -0
- package/dist/useLive.js.map +1 -0
- package/dist/usePolled.js +68 -0
- package/dist/usePolled.js.map +1 -0
- package/dist/voice/Orb.d.ts +10 -9
- package/dist/voice/Orb.js +43 -39
- package/dist/voice/Orb.js.map +1 -0
- package/dist/voice/StillOrb.js +33 -0
- package/dist/voice/StillOrb.js.map +1 -0
- package/dist/voice/WebGLOrb.js +98 -0
- package/dist/voice/WebGLOrb.js.map +1 -0
- package/dist/voice/fluidDots.js +161 -0
- package/dist/voice/fluidDots.js.map +1 -0
- package/dist/voice/motion.js +84 -0
- package/dist/voice/motion.js.map +1 -0
- package/dist/voice/orbs.d.ts +32 -0
- package/dist/voice/orbs.js +16 -0
- package/dist/voice/orbs.js.map +1 -0
- package/dist/voice/useReducedMotion.js +16 -16
- package/dist/voice/useReducedMotion.js.map +1 -0
- package/dist/voice/wave.js +116 -0
- package/dist/voice/wave.js.map +1 -0
- package/dist/voice/webgl.js +177 -0
- package/dist/voice/webgl.js.map +1 -0
- package/dist/widget.js +284 -8
- package/package.json +49 -39
- package/src/AgentAbout.tsx +1621 -0
- package/src/AgentCard.tsx +123 -0
- package/src/AgentChat.tsx +1812 -0
- package/src/AgentSpace.tsx +540 -0
- package/src/AgentTasks.tsx +163 -0
- package/src/BrowserView.tsx +442 -0
- package/src/FileView.tsx +620 -0
- package/src/Modes.tsx +112 -0
- package/src/VoiceCall.tsx +411 -0
- package/src/about.ts +355 -0
- package/src/agentIcons.ts +56 -0
- package/src/automation/Automation.tsx +308 -0
- package/src/automation/RunView.tsx +213 -0
- package/src/automation/cron.ts +196 -0
- package/src/automation/marks.tsx +144 -0
- package/src/automation/messages.ts +231 -0
- package/src/automation/record.ts +206 -0
- package/src/automation/types.ts +146 -0
- package/src/automation/when.ts +195 -0
- package/src/blocks.ts +249 -0
- package/src/browser.ts +334 -0
- package/src/call.ts +300 -0
- package/src/channelParts.ts +17 -0
- package/src/classes.ts +10 -0
- package/src/client.ts +397 -0
- package/src/conversationFiles.ts +54 -0
- package/src/credentials.ts +158 -0
- package/src/dev.ts +20 -0
- package/src/es.ts +423 -0
- package/src/files.ts +238 -0
- package/src/frames.ts +291 -0
- package/src/icons.tsx +49 -0
- package/src/index.ts +271 -0
- package/src/kit/AudioPlayer.tsx +129 -0
- package/src/kit/Button.tsx +97 -0
- package/src/kit/Card.tsx +47 -0
- package/src/kit/Chart.tsx +129 -0
- package/src/kit/Choices.tsx +131 -0
- package/src/kit/Combobox.tsx +247 -0
- package/src/kit/DateField.tsx +156 -0
- package/src/kit/Field.tsx +137 -0
- package/src/kit/FileField.tsx +492 -0
- package/src/kit/FileMark.tsx +56 -0
- package/src/kit/Inputs.tsx +250 -0
- package/src/kit/List.tsx +135 -0
- package/src/kit/Mark.tsx +64 -0
- package/src/kit/MarkStack.tsx +29 -0
- package/src/kit/Note.tsx +42 -0
- package/src/kit/Popover.tsx +121 -0
- package/src/kit/RangeField.tsx +53 -0
- package/src/kit/RatingField.tsx +62 -0
- package/src/kit/Stat.tsx +60 -0
- package/src/kit/Switch.tsx +28 -0
- package/src/kit/Tag.tsx +32 -0
- package/src/kit/Tile.tsx +74 -0
- package/src/kit/TimeField.tsx +157 -0
- package/src/kit/context.tsx +246 -0
- package/src/kit/dates.ts +150 -0
- package/src/kit/messages.ts +160 -0
- package/src/kit/numbers.ts +44 -0
- package/src/kit/options.ts +30 -0
- package/src/kit/uploads.ts +244 -0
- package/src/kit/waveform.ts +84 -0
- package/src/locale.ts +6 -0
- package/src/markdown.ts +69 -0
- package/src/marks.tsx +328 -0
- package/src/reveal.ts +52 -0
- package/src/stepGlyphs.ts +83 -0
- package/src/styles.css +6970 -0
- package/src/surface/Form.tsx +299 -0
- package/src/surface/Markdown.tsx +55 -0
- package/src/surface/Surface.tsx +605 -0
- package/src/surface/scope.ts +82 -0
- package/src/surface/values.ts +361 -0
- package/src/tint.ts +14 -0
- package/src/types.ts +604 -0
- package/src/useAgentFace.ts +47 -0
- package/src/useCall.ts +292 -0
- package/src/useConversation.ts +627 -0
- package/src/useDictation.ts +83 -0
- package/src/useLive.ts +115 -0
- package/src/usePolled.ts +60 -0
- package/src/voice/Orb.tsx +45 -0
- package/src/voice/StillOrb.tsx +29 -0
- package/src/voice/WebGLOrb.tsx +98 -0
- package/src/voice/fluidDots.tsx +171 -0
- package/src/voice/motion.ts +112 -0
- package/src/voice/orbs.ts +39 -0
- package/src/voice/useReducedMotion.ts +24 -0
- package/src/voice/wave.tsx +129 -0
- package/src/voice/webgl.ts +209 -0
- package/src/widget/css.d.ts +5 -0
- package/src/widget/element.tsx +535 -0
- package/src/widget/index.ts +10 -0
- package/src/widget/mount.ts +27 -0
- package/src/widget/widget.css +253 -0
- package/dist/SignalcoreProvider.d.ts +0 -113
- package/dist/SignalcoreProvider.js +0 -84
- package/dist/automations/AppMarks.d.ts +0 -11
- package/dist/automations/AppMarks.js +0 -18
- package/dist/automations/AutomationCard.d.ts +0 -27
- package/dist/automations/AutomationCard.js +0 -53
- package/dist/automations/AutomationsWindow.d.ts +0 -38
- package/dist/automations/AutomationsWindow.js +0 -57
- package/dist/automations/Card.d.ts +0 -46
- package/dist/automations/Card.js +0 -45
- package/dist/automations/ScheduleMarks.d.ts +0 -13
- package/dist/automations/ScheduleMarks.js +0 -24
- package/dist/automations/presentationIcons.d.ts +0 -7
- package/dist/automations/presentationIcons.js +0 -67
- package/dist/automations/schedule.d.ts +0 -25
- package/dist/automations/schedule.js +0 -59
- package/dist/automations/time.d.ts +0 -3
- package/dist/automations/time.js +0 -25
- package/dist/browser/BrowserView.d.ts +0 -43
- package/dist/browser/BrowserView.js +0 -94
- package/dist/browser/room.d.ts +0 -21
- package/dist/browser/room.js +0 -33
- package/dist/browser/useBrowserSession.d.ts +0 -17
- package/dist/browser/useBrowserSession.js +0 -67
- package/dist/builder/BuilderChat.d.ts +0 -32
- package/dist/builder/BuilderChat.js +0 -41
- package/dist/builder/BuilderTranscript.d.ts +0 -49
- package/dist/builder/BuilderTranscript.js +0 -62
- package/dist/builder/StatusLine.d.ts +0 -8
- package/dist/builder/StatusLine.js +0 -17
- package/dist/builder/answer.d.ts +0 -7
- package/dist/builder/answer.js +0 -8
- package/dist/builder/blocks.d.ts +0 -31
- package/dist/builder/blocks.js +0 -74
- package/dist/builder/items.d.ts +0 -15
- package/dist/builder/items.js +0 -21
- package/dist/builder/steps.d.ts +0 -20
- package/dist/builder/steps.js +0 -120
- package/dist/builder/time.d.ts +0 -4
- package/dist/builder/time.js +0 -24
- package/dist/builder/useBuildSession.d.ts +0 -36
- package/dist/builder/useBuildSession.js +0 -130
- package/dist/builder/workingOn.d.ts +0 -7
- package/dist/builder/workingOn.js +0 -15
- package/dist/chat/AgentChat.d.ts +0 -37
- package/dist/chat/AgentChat.js +0 -21
- package/dist/chat/ChatView.d.ts +0 -25
- package/dist/chat/ChatView.js +0 -34
- package/dist/chat/Composer.d.ts +0 -20
- package/dist/chat/Composer.js +0 -22
- package/dist/chat/MessageRow.d.ts +0 -22
- package/dist/chat/MessageRow.js +0 -32
- package/dist/chat/arrival.d.ts +0 -15
- package/dist/chat/arrival.js +0 -25
- package/dist/chat/history.d.ts +0 -24
- package/dist/chat/history.js +0 -45
- package/dist/chat/moments.d.ts +0 -25
- package/dist/chat/moments.js +0 -72
- package/dist/chat/types.d.ts +0 -12
- package/dist/chat/types.js +0 -1
- package/dist/chat/useComposer.d.ts +0 -46
- package/dist/chat/useComposer.js +0 -62
- package/dist/chat/useConversation.d.ts +0 -35
- package/dist/chat/useConversation.js +0 -71
- package/dist/chat/useStickToBottom.d.ts +0 -9
- package/dist/chat/useStickToBottom.js +0 -33
- package/dist/chat/useTurns.d.ts +0 -49
- package/dist/chat/useTurns.js +0 -111
- package/dist/classes.d.ts +0 -2
- package/dist/development.d.ts +0 -5
- package/dist/development.js +0 -8
- package/dist/flow/FlowWindow.d.ts +0 -42
- package/dist/flow/FlowWindow.js +0 -126
- package/dist/flow/index.d.ts +0 -16
- package/dist/flow/index.js +0 -16
- package/dist/flow/kinds.d.ts +0 -23
- package/dist/flow/kinds.js +0 -48
- package/dist/flow/map.d.ts +0 -44
- package/dist/flow/map.js +0 -225
- package/dist/flow/nodePaths.d.ts +0 -7
- package/dist/flow/nodePaths.js +0 -17
- package/dist/flow/relations.d.ts +0 -42
- package/dist/flow/relations.js +0 -174
- package/dist/host.d.ts +0 -124
- package/dist/host.js +0 -1
- package/dist/live/LiveView.d.ts +0 -28
- package/dist/live/LiveView.js +0 -55
- package/dist/live/capture.d.ts +0 -20
- package/dist/live/capture.js +0 -100
- package/dist/live/follow.d.ts +0 -26
- package/dist/live/follow.js +0 -72
- package/dist/live/paint.d.ts +0 -13
- package/dist/live/paint.js +0 -77
- package/dist/live/useLiveStream.d.ts +0 -16
- package/dist/live/useLiveStream.js +0 -57
- package/dist/look.d.ts +0 -33
- package/dist/look.js +0 -241
- package/dist/messages/en.d.ts +0 -3
- package/dist/messages/en.js +0 -251
- package/dist/messages/es.d.ts +0 -3
- package/dist/messages/es.js +0 -251
- package/dist/messages/index.d.ts +0 -16
- package/dist/messages/index.js +0 -33
- package/dist/messages/types.d.ts +0 -246
- package/dist/messages/types.js +0 -1
- package/dist/parts/Button.d.ts +0 -18
- package/dist/parts/Button.js +0 -17
- package/dist/parts/Icon.d.ts +0 -39
- package/dist/parts/Icon.js +0 -37
- package/dist/parts/Input.d.ts +0 -6
- package/dist/parts/Input.js +0 -11
- package/dist/parts/Spinner.d.ts +0 -2
- package/dist/parts/Spinner.js +0 -7
- package/dist/patterns.d.ts +0 -15
- package/dist/patterns.js +0 -5
- package/dist/presets.d.ts +0 -82
- package/dist/presets.js +0 -81
- package/dist/primitives.d.ts +0 -22
- package/dist/primitives.js +0 -58
- package/dist/request/RequestCard.d.ts +0 -34
- package/dist/request/RequestCard.js +0 -101
- package/dist/request/approval/ApprovalPreview.d.ts +0 -5
- package/dist/request/approval/ApprovalPreview.js +0 -27
- package/dist/request/approval/shapes.d.ts +0 -32
- package/dist/request/approval/shapes.js +0 -68
- package/dist/request/apps.d.ts +0 -11
- package/dist/request/apps.js +0 -27
- package/dist/request/cards.d.ts +0 -12
- package/dist/request/cards.js +0 -24
- package/dist/request/deliver.d.ts +0 -12
- package/dist/request/deliver.js +0 -21
- package/dist/request/handOver.d.ts +0 -18
- package/dist/request/handOver.js +0 -33
- package/dist/request/kinds/Approval.d.ts +0 -3
- package/dist/request/kinds/Approval.js +0 -9
- package/dist/request/kinds/Choice.d.ts +0 -3
- package/dist/request/kinds/Choice.js +0 -8
- package/dist/request/kinds/Connect.d.ts +0 -9
- package/dist/request/kinds/Connect.js +0 -119
- package/dist/request/kinds/FreeText.d.ts +0 -3
- package/dist/request/kinds/FreeText.js +0 -20
- package/dist/request/kinds/HandOver.d.ts +0 -13
- package/dist/request/kinds/HandOver.js +0 -20
- package/dist/request/kinds/Secret.d.ts +0 -7
- package/dist/request/kinds/Secret.js +0 -49
- package/dist/request/kinds/Upload.d.ts +0 -6
- package/dist/request/kinds/Upload.js +0 -47
- package/dist/request/types.d.ts +0 -83
- package/dist/request/types.js +0 -1
- package/dist/safeUrl.d.ts +0 -6
- package/dist/safeUrl.js +0 -8
- package/dist/stream/builder.d.ts +0 -176
- package/dist/stream/builder.js +0 -202
- package/dist/stream/reduce.d.ts +0 -51
- package/dist/stream/reduce.js +0 -58
- package/dist/stream/untilAborted.d.ts +0 -7
- package/dist/stream/untilAborted.js +0 -32
- package/dist/stream/useRunStream.d.ts +0 -26
- package/dist/stream/useRunStream.js +0 -137
- package/dist/styles.css +0 -2318
- package/dist/surface/HostNode.d.ts +0 -14
- package/dist/surface/HostNode.js +0 -30
- package/dist/surface/Node.d.ts +0 -7
- package/dist/surface/Node.js +0 -49
- package/dist/surface/SurfaceBoundary.d.ts +0 -26
- package/dist/surface/SurfaceBoundary.js +0 -20
- package/dist/surface/bindings.d.ts +0 -14
- package/dist/surface/bindings.js +0 -37
- package/dist/surface/check.d.ts +0 -27
- package/dist/surface/check.js +0 -102
- package/dist/surface/format.d.ts +0 -10
- package/dist/surface/format.js +0 -32
- package/dist/surface/hosts.d.ts +0 -6
- package/dist/surface/hosts.js +0 -11
- package/dist/surface/scene.d.ts +0 -21
- package/dist/surface/scene.js +0 -8
- package/dist/surface/templates/Browser.d.ts +0 -6
- package/dist/surface/templates/Browser.js +0 -11
- package/dist/surface/templates/Chart.d.ts +0 -6
- package/dist/surface/templates/Chart.js +0 -13
- package/dist/surface/templates/Choices.d.ts +0 -3
- package/dist/surface/templates/Choices.js +0 -12
- package/dist/surface/templates/Form.d.ts +0 -3
- package/dist/surface/templates/Form.js +0 -44
- package/dist/surface/templates/KeyValue.d.ts +0 -3
- package/dist/surface/templates/KeyValue.js +0 -7
- package/dist/surface/templates/Layout.d.ts +0 -5
- package/dist/surface/templates/Layout.js +0 -16
- package/dist/surface/templates/Live.d.ts +0 -6
- package/dist/surface/templates/Live.js +0 -9
- package/dist/surface/templates/Media.d.ts +0 -5
- package/dist/surface/templates/Media.js +0 -13
- package/dist/surface/templates/Slots.d.ts +0 -3
- package/dist/surface/templates/Slots.js +0 -19
- package/dist/surface/templates/Table.d.ts +0 -3
- package/dist/surface/templates/Table.js +0 -12
- package/dist/surface/templates/Text.d.ts +0 -4
- package/dist/surface/templates/Text.js +0 -15
- package/dist/surface/templates/index.d.ts +0 -7
- package/dist/surface/templates/index.js +0 -32
- package/dist/surface/types.d.ts +0 -68
- package/dist/surface/types.js +0 -6
- package/dist/theme.d.ts +0 -62
- package/dist/theme.js +0 -9
- package/dist/useTokens.d.ts +0 -7
- package/dist/useTokens.js +0 -41
- package/dist/voice/VoiceWindow.d.ts +0 -18
- package/dist/voice/VoiceWindow.js +0 -35
- package/dist/voice/index.d.ts +0 -13
- package/dist/voice/index.js +0 -12
- package/dist/voice/meter.d.ts +0 -16
- package/dist/voice/meter.js +0 -52
- package/dist/voice/orbColors.d.ts +0 -16
- package/dist/voice/orbColors.js +0 -75
- package/dist/voice/pushable.d.ts +0 -16
- package/dist/voice/pushable.js +0 -56
- package/dist/voice/useDictation.d.ts +0 -24
- package/dist/voice/useDictation.js +0 -60
- package/dist/voice/useReducedMotion.d.ts +0 -5
- package/dist/voice/useVoice.d.ts +0 -70
- package/dist/voice/useVoice.js +0 -197
- package/dist/voice/useVoicePrimitives.d.ts +0 -7
- package/dist/voice/useVoicePrimitives.js +0 -11
- package/dist/voice/voice.d.ts +0 -55
- package/dist/voice/voice.js +0 -9
- package/dist/voice/webSpeech.d.ts +0 -33
- package/dist/voice/webSpeech.js +0 -258
- package/dist/widget.js.map +0 -1
- package/dist/windows/AgentSpace.d.ts +0 -78
- package/dist/windows/AgentSpace.js +0 -135
- package/dist/windows/Captions.d.ts +0 -13
- package/dist/windows/Captions.js +0 -22
- package/dist/windows/Dock.d.ts +0 -37
- package/dist/windows/Dock.js +0 -22
- package/dist/windows/Journal.d.ts +0 -15
- package/dist/windows/Journal.js +0 -19
- package/dist/windows/KindMark.d.ts +0 -7
- package/dist/windows/KindMark.js +0 -31
- package/dist/windows/Pending.d.ts +0 -8
- package/dist/windows/Pending.js +0 -17
- package/dist/windows/Stage.d.ts +0 -18
- package/dist/windows/Stage.js +0 -21
- package/dist/windows/StatusLabel.d.ts +0 -9
- package/dist/windows/StatusLabel.js +0 -7
- package/dist/windows/Strip.d.ts +0 -17
- package/dist/windows/Strip.js +0 -42
- package/dist/windows/SurfaceWindow.d.ts +0 -20
- package/dist/windows/SurfaceWindow.js +0 -12
- package/dist/windows/WindowFrame.d.ts +0 -23
- package/dist/windows/WindowFrame.js +0 -22
- package/dist/windows/hearing.d.ts +0 -11
- package/dist/windows/hearing.js +0 -26
- package/dist/windows/kinds.d.ts +0 -47
- package/dist/windows/kinds.js +0 -28
- package/dist/windows/reduce.d.ts +0 -98
- package/dist/windows/reduce.js +0 -151
- package/dist/windows/registry.d.ts +0 -18
- package/dist/windows/registry.js +0 -61
- package/dist/windows/reveal.d.ts +0 -9
- package/dist/windows/reveal.js +0 -6
- package/dist/windows/space.d.ts +0 -21
- package/dist/windows/space.js +0 -6
- package/dist/windows/status.d.ts +0 -11
- package/dist/windows/status.js +0 -30
- package/dist/windows/types.d.ts +0 -15
- package/dist/windows/types.js +0 -1
- package/dist/windows/useLoaded.d.ts +0 -44
- package/dist/windows/useLoaded.js +0 -58
- package/dist/windows/useUnread.d.ts +0 -7
- package/dist/windows/useUnread.js +0 -21
- package/dist/windows/useWindows.d.ts +0 -70
- package/dist/windows/useWindows.js +0 -60
package/src/client.ts
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import type { AboutOut, MemoryFact } from "./about";
|
|
2
|
+
import type { Automation, AutomationView, RunRecord, Task } from "./automation/types";
|
|
3
|
+
import { signerOf, type Credentials, type Speaker } from "./credentials";
|
|
4
|
+
import type {
|
|
5
|
+
AgentFace,
|
|
6
|
+
WidgetConfig,
|
|
7
|
+
CallToken,
|
|
8
|
+
Channel,
|
|
9
|
+
Conversation,
|
|
10
|
+
ConversationDetail,
|
|
11
|
+
ConversationFile,
|
|
12
|
+
FileAt,
|
|
13
|
+
FileLink,
|
|
14
|
+
FilePreview,
|
|
15
|
+
StoredFile,
|
|
16
|
+
} from "./types";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* What the API answered when it was not a success: its status, its sentence (`detail`, written
|
|
20
|
+
* to be shown) and its `code`, for a host to word in its own language.
|
|
21
|
+
*/
|
|
22
|
+
export class ApiError extends Error {
|
|
23
|
+
readonly status: number;
|
|
24
|
+
readonly detail: string;
|
|
25
|
+
/** What went wrong, by name (`not_found`, `no_calls`); null when the answer named nothing. */
|
|
26
|
+
readonly code: string | null;
|
|
27
|
+
|
|
28
|
+
constructor(status: number, detail: string, code: string | null = null) {
|
|
29
|
+
super(detail);
|
|
30
|
+
this.name = "ApiError";
|
|
31
|
+
this.status = status;
|
|
32
|
+
this.detail = detail;
|
|
33
|
+
this.code = code;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
38
|
+
typeof value === "object" && value !== null;
|
|
39
|
+
|
|
40
|
+
const isIssue = (value: unknown): value is { msg: string } =>
|
|
41
|
+
isRecord(value) && typeof value.msg === "string";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Reads an error body: `{code, detail: "message"}`, or FastAPI's 422 `{detail: [{msg, …}, …]}`
|
|
45
|
+
* (the first issue speaks for all). A body with neither is named by its status alone.
|
|
46
|
+
*/
|
|
47
|
+
export function parseError(status: number, body: unknown): ApiError {
|
|
48
|
+
const detail = isRecord(body) ? body.detail : undefined;
|
|
49
|
+
const code = isRecord(body) && typeof body.code === "string" ? body.code : null;
|
|
50
|
+
if (typeof detail === "string" && detail !== "") return new ApiError(status, detail, code);
|
|
51
|
+
if (Array.isArray(detail)) {
|
|
52
|
+
const issue = detail.find(isIssue);
|
|
53
|
+
if (issue) return new ApiError(status, issue.msg);
|
|
54
|
+
}
|
|
55
|
+
return new ApiError(status, `HTTP ${status}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** A body read as JSON, or null when it is not. */
|
|
59
|
+
function readJson(text: string): unknown {
|
|
60
|
+
try {
|
|
61
|
+
return JSON.parse(text) as unknown;
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Where the API is, and who calls it (`Credentials`: the cookie, a person's token, a token asked
|
|
69
|
+
* of the host's backend, or a publishable key and its visitor).
|
|
70
|
+
*/
|
|
71
|
+
export type ClientOptions = Credentials & {
|
|
72
|
+
/**
|
|
73
|
+
* The API's origin and prefix: `/api` in our own app (the cookie's, on the page's origin), the
|
|
74
|
+
* public `https://…/v1` from a host's page.
|
|
75
|
+
*/
|
|
76
|
+
baseUrl: string;
|
|
77
|
+
/** A host's own `fetch`, when the global one is not the right one. */
|
|
78
|
+
fetch?: typeof fetch | undefined;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** The files under one owner: the organization's, or an agent's own. */
|
|
82
|
+
export interface Files {
|
|
83
|
+
/** Every file, by path. */
|
|
84
|
+
list: () => Promise<StoredFile[]>;
|
|
85
|
+
/**
|
|
86
|
+
* Stores the bytes under the path (replacing a file of the same name), with the blob's type
|
|
87
|
+
* as the file's; `searchable` makes it knowledge `search_files` reads (text, PDF).
|
|
88
|
+
*/
|
|
89
|
+
put: (path: string, blob: Blob, searchable: boolean) => Promise<StoredFile>;
|
|
90
|
+
delete: (path: string) => Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** How an upload goes: how much of it has gone, and how to let it go. */
|
|
94
|
+
export interface UploadOptions {
|
|
95
|
+
/** Hears the share sent so far, from 0 to 1, as it goes. */
|
|
96
|
+
onProgress?: ((share: number) => void) | undefined;
|
|
97
|
+
/** Aborting it stops the upload, and the promise rejects with an `AbortError`. */
|
|
98
|
+
signal?: AbortSignal | undefined;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The API, as far as this package reaches it. */
|
|
102
|
+
export interface Client {
|
|
103
|
+
/**
|
|
104
|
+
* The widget's agent and look, by the publishable key it speaks with (a web channel's key).
|
|
105
|
+
*/
|
|
106
|
+
widget: () => Promise<WidgetConfig>;
|
|
107
|
+
/**
|
|
108
|
+
* Who the page speaks for, by its credentials: the business (our own app's cookie) or a person
|
|
109
|
+
* it serves (a token, a publishable key's visitor). What waits for the business's yes is
|
|
110
|
+
* answered by the business alone.
|
|
111
|
+
*/
|
|
112
|
+
who: Speaker;
|
|
113
|
+
agents: {
|
|
114
|
+
/** What a person may know of the agent: its name, role, mark, and whether it takes calls. */
|
|
115
|
+
face: (id: string) => Promise<AgentFace>;
|
|
116
|
+
/** What the agent says about itself (null until it has written it) and the facts it rests on. */
|
|
117
|
+
about: (id: string) => Promise<AboutOut>;
|
|
118
|
+
/** Has the agent write about itself anew (a model call, a few seconds); answers like `about`. */
|
|
119
|
+
describe: (id: string) => Promise<AboutOut>;
|
|
120
|
+
/** The agent's own files, by path. */
|
|
121
|
+
files: (id: string) => Promise<StoredFile[]>;
|
|
122
|
+
/** Stores a file of the agent's own; see `Files.put`. */
|
|
123
|
+
putFile: (id: string, path: string, blob: Blob, searchable: boolean) => Promise<StoredFile>;
|
|
124
|
+
deleteFile: (id: string, path: string) => Promise<void>;
|
|
125
|
+
/** What the agent remembered, newest first. */
|
|
126
|
+
memories: (id: string) => Promise<MemoryFact[]>;
|
|
127
|
+
/** Takes one memory from it. */
|
|
128
|
+
forget: (id: string, memoryId: string) => Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* The owner's call with the agent, from the browser (v3/VOICE.md): the call and its
|
|
131
|
+
* conversation (a test) made now, and where to join it (`VoiceCall`'s `connect`).
|
|
132
|
+
*/
|
|
133
|
+
call: (id: string) => Promise<CallToken>;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* The organization's files, shared by every agent; and the preview of any file the caller may
|
|
137
|
+
* read, the organization's, an agent's own or a conversation's (`preview`).
|
|
138
|
+
*/
|
|
139
|
+
files: Files & {
|
|
140
|
+
/** What a viewer draws of the file, by its `kind` (v3/FILES.md, Preview). */
|
|
141
|
+
preview: (at: FileAt) => Promise<FilePreview>;
|
|
142
|
+
};
|
|
143
|
+
/** What an agent does on its own (v3/AUTOMATIONS.md). */
|
|
144
|
+
automations: {
|
|
145
|
+
/** The agent's automations, each as it stands now with its newest run. */
|
|
146
|
+
list: (agentId: string) => Promise<Automation[]>;
|
|
147
|
+
/** One of them by its name, with its newest runs. */
|
|
148
|
+
get: (agentId: string, name: string) => Promise<AutomationView>;
|
|
149
|
+
};
|
|
150
|
+
runs: {
|
|
151
|
+
/** One run of an automation with its record: every call it made, step by step. */
|
|
152
|
+
get: (id: string) => Promise<RunRecord>;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* The tasks an agent runs for contacts, each with its newest runs: a person's own only (what
|
|
156
|
+
* they asked the agent for in their conversations); the business's, every one.
|
|
157
|
+
*/
|
|
158
|
+
tasks: {
|
|
159
|
+
list: (agentId: string) => Promise<Task[]>;
|
|
160
|
+
/** Pauses it, or turns it on again; answers it as it stands. */
|
|
161
|
+
switch: (agentId: string, taskId: string, on: boolean) => Promise<Task>;
|
|
162
|
+
remove: (agentId: string, taskId: string) => Promise<void>;
|
|
163
|
+
};
|
|
164
|
+
/** Where people write to the organization's agents (v3/CHANNELS.md). */
|
|
165
|
+
channels: {
|
|
166
|
+
/** The organization's channels, or one agent's: the disconnected ones too. */
|
|
167
|
+
list: (agentId?: string) => Promise<Channel[]>;
|
|
168
|
+
};
|
|
169
|
+
conversations: {
|
|
170
|
+
/** One conversation with its messages. */
|
|
171
|
+
get: (id: string) => Promise<ConversationDetail>;
|
|
172
|
+
/** A new conversation with an agent. */
|
|
173
|
+
start: (agentId: string) => Promise<Conversation>;
|
|
174
|
+
/** The files that arrived in a conversation: attached, sent through a form. */
|
|
175
|
+
files: (id: string) => Promise<ConversationFile[]>;
|
|
176
|
+
/**
|
|
177
|
+
* Stores a file in the conversation as the person picks it, to say it or send it through a
|
|
178
|
+
* form by its id: its bytes as they are, under its type and name.
|
|
179
|
+
*/
|
|
180
|
+
upload: (id: string, file: File, options?: UploadOptions) => Promise<ConversationFile>;
|
|
181
|
+
/**
|
|
182
|
+
* Where a picture, a video or a sound of the conversation plays from in the page's own
|
|
183
|
+
* player: an address that needs no credential, for an hour, streamed as the player seeks.
|
|
184
|
+
*/
|
|
185
|
+
play: (id: string, fileId: string) => Promise<string>;
|
|
186
|
+
/**
|
|
187
|
+
* A call with the agent from the browser, for whoever may talk to it (a person, as theirs):
|
|
188
|
+
* the call and its own conversation made now, where what is said lands, and where to join it
|
|
189
|
+
* (`VoiceCall`'s `connect`).
|
|
190
|
+
*/
|
|
191
|
+
call: (agentId: string) => Promise<CallToken>;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* The conversation's socket address, signed in: `ws:` beside `http:`, `wss:` beside `https:`,
|
|
195
|
+
* with the token (and the visitor) in its query, since a browser's socket takes no header.
|
|
196
|
+
* `fresh` asks the host's backend for a new token first (`getToken`), for a socket that could
|
|
197
|
+
* not open with the last one.
|
|
198
|
+
*/
|
|
199
|
+
liveUrl: (conversationId: string, options?: { fresh?: boolean | undefined }) => Promise<string>;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const seg = encodeURIComponent;
|
|
203
|
+
|
|
204
|
+
/** A file's path in a URL: each name of it encoded, the slashes between them kept. */
|
|
205
|
+
const filePath = (path: string): string => path.split("/").map(seg).join("/");
|
|
206
|
+
|
|
207
|
+
/** Where a file's preview is read: under its conversation, its agent or the organization. */
|
|
208
|
+
const previewPath = (at: FileAt): string => {
|
|
209
|
+
if ("conversationId" in at) {
|
|
210
|
+
return `/conversations/${seg(at.conversationId)}/files/${seg(at.fileId)}/preview`;
|
|
211
|
+
}
|
|
212
|
+
const owner = "agentId" in at ? `/agents/${seg(at.agentId)}` : "";
|
|
213
|
+
return `${owner}/files/${filePath(at.path)}/preview`;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* The API under `baseUrl`: JSON in and out, an `ApiError` for anything but a success, signed in
|
|
220
|
+
* the one way `options` gives. A token asked of the host's backend (`getToken`) that the API
|
|
221
|
+
* refuses (401: it expired) is asked for once more, and the request sent again with it.
|
|
222
|
+
*/
|
|
223
|
+
export function createClient(options: ClientOptions): Client {
|
|
224
|
+
const { baseUrl, fetch: call = fetch } = options;
|
|
225
|
+
const signer = signerOf(options);
|
|
226
|
+
|
|
227
|
+
/** One request with the cookie or the credential's headers; a body goes as it is, typed. */
|
|
228
|
+
async function attempt(method: Method, path: string, body: Blob | undefined) {
|
|
229
|
+
const signed = await signer.sign();
|
|
230
|
+
const response = await call(`${baseUrl}${path}`, {
|
|
231
|
+
method,
|
|
232
|
+
credentials: signer.credentials,
|
|
233
|
+
headers:
|
|
234
|
+
body === undefined ? signed.headers : { ...signed.headers, "Content-Type": body.type },
|
|
235
|
+
...(body === undefined ? {} : { body }),
|
|
236
|
+
});
|
|
237
|
+
return { response, signed };
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function send(method: Method, path: string, body?: Blob): Promise<Response> {
|
|
241
|
+
let { response, signed } = await attempt(method, path, body);
|
|
242
|
+
if (response.status === 401 && signed.renew !== null) {
|
|
243
|
+
signed.renew();
|
|
244
|
+
({ response } = await attempt(method, path, body));
|
|
245
|
+
}
|
|
246
|
+
if (!response.ok) {
|
|
247
|
+
const answer: unknown = await response.json().catch(() => null);
|
|
248
|
+
throw parseError(response.status, answer);
|
|
249
|
+
}
|
|
250
|
+
return response;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function json<T>(method: Method, path: string, body?: Blob): Promise<T> {
|
|
254
|
+
return (await (await send(method, path, body)).json()) as T;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** A request whose answer has no body (204). */
|
|
258
|
+
async function run(method: Method, path: string): Promise<void> {
|
|
259
|
+
await send(method, path);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** The four of `Files` under a prefix: `/files`, or `/agents/{id}/files`. */
|
|
263
|
+
const filesUnder = (prefix: string): Files => ({
|
|
264
|
+
list: () => json("GET", prefix),
|
|
265
|
+
put: (path, blob, searchable) =>
|
|
266
|
+
json("PUT", `${prefix}/${filePath(path)}?searchable=${searchable}`, blob),
|
|
267
|
+
delete: (path) => run("DELETE", `${prefix}/${filePath(path)}`),
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const own = (id: string) => filesUnder(`/agents/${seg(id)}/files`);
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* A file sent by XMLHttpRequest, the one way a browser tells how much of a body has gone; the
|
|
274
|
+
* cookie goes as with `fetch` on the same origin, any other credential as its headers. Refused
|
|
275
|
+
* with a token asked of the host's backend, it is sent once more with a new one.
|
|
276
|
+
*/
|
|
277
|
+
async function sendFile(
|
|
278
|
+
path: string,
|
|
279
|
+
file: File,
|
|
280
|
+
options: UploadOptions = {},
|
|
281
|
+
): Promise<ConversationFile> {
|
|
282
|
+
const signed = await signer.sign();
|
|
283
|
+
try {
|
|
284
|
+
return await post(path, file, signed.headers, options);
|
|
285
|
+
} catch (error) {
|
|
286
|
+
const expired = error instanceof ApiError && error.status === 401;
|
|
287
|
+
if (!expired || signed.renew === null) throw error;
|
|
288
|
+
signed.renew();
|
|
289
|
+
return post(path, file, (await signer.sign()).headers, options);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function post(
|
|
294
|
+
path: string,
|
|
295
|
+
file: File,
|
|
296
|
+
headers: Readonly<Record<string, string>>,
|
|
297
|
+
{ onProgress, signal }: UploadOptions,
|
|
298
|
+
): Promise<ConversationFile> {
|
|
299
|
+
return new Promise((resolve, reject) => {
|
|
300
|
+
const aborted = () => new DOMException("The upload was aborted", "AbortError");
|
|
301
|
+
if (signal?.aborted) {
|
|
302
|
+
reject(aborted());
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const request = new XMLHttpRequest();
|
|
306
|
+
const abort = () => {
|
|
307
|
+
request.abort();
|
|
308
|
+
};
|
|
309
|
+
request.open("POST", `${baseUrl}${path}`);
|
|
310
|
+
for (const [name, value] of Object.entries(headers)) request.setRequestHeader(name, value);
|
|
311
|
+
request.setRequestHeader("Content-Type", file.type || "application/octet-stream");
|
|
312
|
+
request.setRequestHeader("X-File-Name", encodeURIComponent(file.name));
|
|
313
|
+
request.upload.addEventListener("progress", (event) => {
|
|
314
|
+
if (event.lengthComputable && event.total > 0) onProgress?.(event.loaded / event.total);
|
|
315
|
+
});
|
|
316
|
+
request.addEventListener("loadend", () => {
|
|
317
|
+
signal?.removeEventListener("abort", abort);
|
|
318
|
+
});
|
|
319
|
+
request.addEventListener("load", () => {
|
|
320
|
+
const body = readJson(request.responseText);
|
|
321
|
+
if (request.status >= 200 && request.status < 300) resolve(body as ConversationFile);
|
|
322
|
+
else reject(parseError(request.status, body));
|
|
323
|
+
});
|
|
324
|
+
request.addEventListener("error", () => {
|
|
325
|
+
reject(new ApiError(0, "The upload could not reach the server"));
|
|
326
|
+
});
|
|
327
|
+
request.addEventListener("abort", () => {
|
|
328
|
+
reject(aborted());
|
|
329
|
+
});
|
|
330
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
331
|
+
request.send(file);
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return {
|
|
336
|
+
widget: () => json("GET", "/channels/web/widget"),
|
|
337
|
+
who: signer.who,
|
|
338
|
+
agents: {
|
|
339
|
+
face: (id) => json("GET", `/agents/${seg(id)}/face`),
|
|
340
|
+
about: (id) => json("GET", `/agents/${seg(id)}/about`),
|
|
341
|
+
describe: (id) => json("POST", `/agents/${seg(id)}/describe`),
|
|
342
|
+
files: (id) => own(id).list(),
|
|
343
|
+
putFile: (id, path, blob, searchable) => own(id).put(path, blob, searchable),
|
|
344
|
+
deleteFile: (id, path) => own(id).delete(path),
|
|
345
|
+
memories: (id) => json("GET", `/agents/${seg(id)}/memories`),
|
|
346
|
+
forget: (id, memoryId) => run("DELETE", `/agents/${seg(id)}/memories/${seg(memoryId)}`),
|
|
347
|
+
call: (id) => json("POST", `/agents/${seg(id)}/voice/token`),
|
|
348
|
+
},
|
|
349
|
+
files: { ...filesUnder("/files"), preview: (at) => json("GET", previewPath(at)) },
|
|
350
|
+
automations: {
|
|
351
|
+
list: (agentId) => json("GET", `/agents/${seg(agentId)}/automations`),
|
|
352
|
+
get: (agentId, name) => json("GET", `/agents/${seg(agentId)}/automations/${seg(name)}`),
|
|
353
|
+
},
|
|
354
|
+
runs: {
|
|
355
|
+
get: (id) => json("GET", `/runs/${seg(id)}`),
|
|
356
|
+
},
|
|
357
|
+
tasks: {
|
|
358
|
+
list: (agentId) => json("GET", `/agents/${seg(agentId)}/tasks`),
|
|
359
|
+
switch: (agentId, taskId, on) =>
|
|
360
|
+
json(
|
|
361
|
+
"PATCH",
|
|
362
|
+
`/agents/${seg(agentId)}/tasks/${seg(taskId)}`,
|
|
363
|
+
new Blob([JSON.stringify({ on })], { type: "application/json" }),
|
|
364
|
+
),
|
|
365
|
+
remove: (agentId, taskId) => run("DELETE", `/agents/${seg(agentId)}/tasks/${seg(taskId)}`),
|
|
366
|
+
},
|
|
367
|
+
channels: {
|
|
368
|
+
list: (agentId) =>
|
|
369
|
+
json("GET", agentId === undefined ? "/channels" : `/channels?agent=${seg(agentId)}`),
|
|
370
|
+
},
|
|
371
|
+
conversations: {
|
|
372
|
+
get: (id) => json("GET", `/conversations/${seg(id)}`),
|
|
373
|
+
start: (agentId) => json("POST", `/agents/${seg(agentId)}/conversations`),
|
|
374
|
+
files: (id) => json("GET", `/conversations/${seg(id)}/files`),
|
|
375
|
+
upload: (id, file, options) => sendFile(`/conversations/${seg(id)}/files`, file, options),
|
|
376
|
+
play: async (id, fileId) => {
|
|
377
|
+
const link = await json<FileLink>(
|
|
378
|
+
"GET",
|
|
379
|
+
`/conversations/${seg(id)}/files/${seg(fileId)}/link`,
|
|
380
|
+
);
|
|
381
|
+
return new URL(`${baseUrl}${link.path}`, window.location.href).href;
|
|
382
|
+
},
|
|
383
|
+
call: (agentId) => json("POST", `/agents/${seg(agentId)}/calls`),
|
|
384
|
+
},
|
|
385
|
+
liveUrl: async (conversationId, { fresh = false } = {}) => {
|
|
386
|
+
const url = new URL(
|
|
387
|
+
`${baseUrl}/conversations/${seg(conversationId)}/live`,
|
|
388
|
+
window.location.href,
|
|
389
|
+
);
|
|
390
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
391
|
+
for (const [name, value] of Object.entries(await signer.query(fresh))) {
|
|
392
|
+
url.searchParams.set(name, value);
|
|
393
|
+
}
|
|
394
|
+
return url.href;
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useMemo, useRef, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import type { Client } from "./client";
|
|
4
|
+
import type { FileHost } from "./kit/uploads";
|
|
5
|
+
import type { Attachment, Message } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A conversation's files, as its chat's pieces reach them: an upload to it (the composer's, a
|
|
9
|
+
* form's file field), every file known by id (said in its messages, uploaded here, or read back
|
|
10
|
+
* once when one is asked for that neither has), where one plays from, and the host's way to
|
|
11
|
+
* open one.
|
|
12
|
+
*/
|
|
13
|
+
export function useConversationFiles(
|
|
14
|
+
client: Client,
|
|
15
|
+
conversationId: string,
|
|
16
|
+
messages: readonly Message[],
|
|
17
|
+
open: ((file: Attachment) => void) | undefined,
|
|
18
|
+
): FileHost {
|
|
19
|
+
const [kept, setKept] = useState<ReadonlyMap<string, Attachment>>(() => new Map());
|
|
20
|
+
const listed = useRef(false);
|
|
21
|
+
|
|
22
|
+
const known = useMemo(() => {
|
|
23
|
+
const all = new Map(kept);
|
|
24
|
+
for (const message of messages) for (const file of message.files ?? []) all.set(file.id, file);
|
|
25
|
+
return all;
|
|
26
|
+
}, [messages, kept]);
|
|
27
|
+
|
|
28
|
+
const keep = (files: readonly Attachment[]) => {
|
|
29
|
+
setKept((now) => {
|
|
30
|
+
const next = new Map(now);
|
|
31
|
+
for (const file of files) next.set(file.id, file);
|
|
32
|
+
return next;
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
known,
|
|
38
|
+
open,
|
|
39
|
+
play: (file) => client.conversations.play(conversationId, file.id),
|
|
40
|
+
upload: async (file, progress, signal) => {
|
|
41
|
+
const stored = await client.conversations.upload(conversationId, file, {
|
|
42
|
+
onProgress: progress,
|
|
43
|
+
signal,
|
|
44
|
+
});
|
|
45
|
+
keep([stored]);
|
|
46
|
+
return stored;
|
|
47
|
+
},
|
|
48
|
+
find: (ids) => {
|
|
49
|
+
if (listed.current || ids.every((id) => known.has(id))) return;
|
|
50
|
+
listed.current = true;
|
|
51
|
+
client.conversations.files(conversationId).then(keep, () => undefined);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who a client calls as, one way at a time (v3/README.md, Credentials): the owner's session cookie
|
|
3
|
+
* in our own app; a person's token, given as it is or asked of the host's backend (and asked again
|
|
4
|
+
* once it expires); or an anonymous visitor of a site, by the site's publishable key and the id
|
|
5
|
+
* the page keeps for them.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
type Way = "credentials" | "token" | "getToken" | "publishableKey" | "visitorId";
|
|
9
|
+
|
|
10
|
+
/** One way of signing in, with none of the others beside it. */
|
|
11
|
+
type Alone<T> = T & { [K in Exclude<Way, keyof T>]?: never };
|
|
12
|
+
|
|
13
|
+
export type Credentials =
|
|
14
|
+
/** Our app, on the API's own origin (`/api`): the session cookie the browser holds. */
|
|
15
|
+
| Alone<{ credentials: "cookie" }>
|
|
16
|
+
/** A person's token the host's backend minted (`POST /v1/tokens`), used as it is. */
|
|
17
|
+
| Alone<{ token: string }>
|
|
18
|
+
/**
|
|
19
|
+
* A person's token asked of the host's backend: when first needed, and once more each time the
|
|
20
|
+
* API refuses the one kept (it lasts an hour).
|
|
21
|
+
*/
|
|
22
|
+
| Alone<{ getToken: () => Promise<string> }>
|
|
23
|
+
/**
|
|
24
|
+
* An anonymous visitor (the widget): the site's publishable key, and who they are, an id the
|
|
25
|
+
* page keeps; one is made and kept in `localStorage` when none is given.
|
|
26
|
+
*/
|
|
27
|
+
| Alone<{ publishableKey: string; visitorId?: string | undefined }>;
|
|
28
|
+
|
|
29
|
+
/** What one request carries to say who calls, and how to have it anew once it is refused. */
|
|
30
|
+
export interface Signed {
|
|
31
|
+
headers: Readonly<Record<string, string>>;
|
|
32
|
+
/** Lets go of a token the API refused, for the next request to ask for another; null: none. */
|
|
33
|
+
renew: (() => void) | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Who a page speaks for: the business (the owner, in our own app) or a person it serves (a token's
|
|
38
|
+
* person, a publishable key's visitor). The API lets each answer different things: a yes the
|
|
39
|
+
* business decides is the business's alone.
|
|
40
|
+
*/
|
|
41
|
+
export type Speaker = "business" | "person";
|
|
42
|
+
|
|
43
|
+
/** How every request and socket of a client says who calls. */
|
|
44
|
+
export interface Signer {
|
|
45
|
+
who: Speaker;
|
|
46
|
+
/** What `fetch` sends of the browser's own: the cookie on the page's origin, or nothing. */
|
|
47
|
+
credentials: RequestCredentials;
|
|
48
|
+
sign: () => Promise<Signed>;
|
|
49
|
+
/**
|
|
50
|
+
* What a socket carries in its address instead (a browser's socket takes no header); `fresh`
|
|
51
|
+
* asks for a new token first, for a socket that could not open with the last one.
|
|
52
|
+
*/
|
|
53
|
+
query: (fresh: boolean) => Promise<Readonly<Record<string, string>>>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Where the page keeps its visitor's id, for every SignalCore widget on the site. */
|
|
57
|
+
export const VISITOR_KEY = "signalcore.visitor";
|
|
58
|
+
|
|
59
|
+
/** What the API takes as a visitor's id: 16 to 128 letters, digits, `_` and `-`. */
|
|
60
|
+
const VISITOR = /^[A-Za-z0-9_-]{16,128}$/;
|
|
61
|
+
|
|
62
|
+
/** A new visitor's id: 32 hex characters of the browser's own randomness (any page has it). */
|
|
63
|
+
function newVisitor(): string {
|
|
64
|
+
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
65
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The visitor this page speaks for: the one kept in `localStorage`, else a new one kept there for
|
|
70
|
+
* their next visit; where the page can't keep anything (a private window, storage blocked), a new
|
|
71
|
+
* one for this page alone.
|
|
72
|
+
*/
|
|
73
|
+
export function keptVisitor(): string {
|
|
74
|
+
try {
|
|
75
|
+
const kept = localStorage.getItem(VISITOR_KEY);
|
|
76
|
+
if (kept !== null && VISITOR.test(kept)) return kept;
|
|
77
|
+
const made = newVisitor();
|
|
78
|
+
localStorage.setItem(VISITOR_KEY, made);
|
|
79
|
+
return made;
|
|
80
|
+
} catch {
|
|
81
|
+
return newVisitor();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** A credential that never changes: the same headers and the same query, nothing to renew. */
|
|
86
|
+
const fixed = (
|
|
87
|
+
who: Speaker,
|
|
88
|
+
credentials: RequestCredentials,
|
|
89
|
+
headers: Record<string, string>,
|
|
90
|
+
query: Record<string, string>,
|
|
91
|
+
): Signer => ({
|
|
92
|
+
who,
|
|
93
|
+
credentials,
|
|
94
|
+
sign: () => Promise.resolve({ headers, renew: null }),
|
|
95
|
+
query: () => Promise.resolve(query),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* A token asked of the host's backend: when first needed, then kept. A refusal lets it go, once
|
|
100
|
+
* however many requests were refused with it, so the next request asks for another; one that
|
|
101
|
+
* could not be had is asked for again next time.
|
|
102
|
+
*/
|
|
103
|
+
function fetched(getToken: () => Promise<string>): Signer {
|
|
104
|
+
let current: Promise<string> | null = null;
|
|
105
|
+
const latest = (): Promise<string> => {
|
|
106
|
+
if (current !== null) return current;
|
|
107
|
+
const asked = Promise.resolve().then(getToken);
|
|
108
|
+
current = asked;
|
|
109
|
+
asked.catch(() => {
|
|
110
|
+
if (current === asked) current = null;
|
|
111
|
+
});
|
|
112
|
+
return asked;
|
|
113
|
+
};
|
|
114
|
+
return {
|
|
115
|
+
who: "person",
|
|
116
|
+
credentials: "omit",
|
|
117
|
+
sign: async () => {
|
|
118
|
+
const used = latest();
|
|
119
|
+
const token = await used;
|
|
120
|
+
return {
|
|
121
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
122
|
+
renew: () => {
|
|
123
|
+
if (current === used) current = null;
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
query: async (fresh) => {
|
|
128
|
+
if (fresh) current = null;
|
|
129
|
+
return { token: await latest() };
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* How a client signs in with what it was given. The API's public prefix reads the header (the
|
|
136
|
+
* socket, its query) and never a cookie, so only our own app sends the browser's.
|
|
137
|
+
*/
|
|
138
|
+
export function signerOf(given: Credentials): Signer {
|
|
139
|
+
if (given.credentials === "cookie") return fixed("business", "same-origin", {}, {});
|
|
140
|
+
if (typeof given.token === "string") {
|
|
141
|
+
const { token } = given;
|
|
142
|
+
return fixed("person", "omit", { Authorization: `Bearer ${token}` }, { token });
|
|
143
|
+
}
|
|
144
|
+
if (typeof given.getToken === "function") return fetched(given.getToken);
|
|
145
|
+
if (typeof given.publishableKey === "string") {
|
|
146
|
+
const key = given.publishableKey;
|
|
147
|
+
const visitor = given.visitorId ?? keptVisitor();
|
|
148
|
+
return fixed(
|
|
149
|
+
"person",
|
|
150
|
+
"omit",
|
|
151
|
+
{ Authorization: `Bearer ${key}`, "SignalCore-Visitor": visitor },
|
|
152
|
+
{ token: key, visitor },
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
throw new TypeError(
|
|
156
|
+
'createClient takes one way to sign in: credentials: "cookie", token, getToken or publishableKey',
|
|
157
|
+
);
|
|
158
|
+
}
|
package/src/dev.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the page runs a development build, as React tells it: a host's bundler writes in
|
|
3
|
+
* `process.env.NODE_ENV`; a page without one has no `process`, and counts as production.
|
|
4
|
+
*/
|
|
5
|
+
declare const process: { env: { NODE_ENV?: string } };
|
|
6
|
+
|
|
7
|
+
function development(): boolean {
|
|
8
|
+
try {
|
|
9
|
+
return process.env.NODE_ENV !== "production";
|
|
10
|
+
} catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const DEV = development();
|
|
16
|
+
|
|
17
|
+
/** A note for the developer of the page, in development only: what the package let pass, and why. */
|
|
18
|
+
export function note(...said: unknown[]): void {
|
|
19
|
+
if (DEV) console.debug("[signalcore]", ...said);
|
|
20
|
+
}
|