npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@94ai/aisdk

v1.1.2

Published

94AI-弹屏SDK

Readme

概述

主体功能用于来电接听前后,订阅获取关于会话内容的消息推送,实现弹屏展示通话记录内容的相关业务。

旧版弹屏sdk会在坐席接听那刻一次性推送ai和用户聊天的全部消息

新版弹屏sdk会在话术触发转人工后,开始不断推送ai和用户聊天的消息,以及坐席接听后和用户的聊天记录,直到用户或坐席挂断通话。

一个坐席只允许一处登录,多处登录会互踢,被踢的坐席默认会定时3s尝试重新登录连接,此时如果异地登录的账号仍在线则会一直做检测能否登录,直到异地登录的账号退出,多处登录互踢的情况同理。

安装

npm设置私库源

  • 参考 《获取94ai前端sdk通用流程》 密码:dbb9
  • 执行install命令安装@94ai/aisdk
$ yarn add @94ai/aisdk
# or
$ npm i @94ai/aisdk
# or
$ pnpm add @94ai/aisdk

获取javascript文件

  • 参考 《获取94ai前端sdk通用流程》 密码:dbb9
  • 执行npx -y @94ai/aisdk -- sdk-umd,之后在当前执行命令路径下获取到94aisdk-1.1.2.umd.min.js

tip 获取旧版sdk 执行npx -y @94ai/aisdk -- sdk-umd --old,之后在当前执行命令路径下获取到94aisdk-1.1.1-old.umd.min.js

使用

初始化&销毁SDK实例

作为npm包使用

import { aiSDK } from '@94ai/aisdk' // or const { aiSDK } = require('@94ai/aisdk')

export interface UserInfo {
  userId: string,
  userType: string,
  token: string
  companyId: string
  orgId: string
  oldId: string
  chainId: string
  account:string
  userName: string
  userTypeName: string
}

export interface SDKConfig {
  corpId: string,
  secretId: string,
  agentId: string,
  onSuccess?: Function,
  onError?: Function,
  onMessage?: Function,
  onReconnect?: Function
  onSessionEnd?: Function
  onKicked?: Function
}

export interface PushData {
  /**
   * 任务 ID
   */
  taskId: string
  /**
   * 分机号
   */
  extensionNumber: string
  /**
   * 外呼 ID
   */
  callid: string
  /**
   * 外呼 ID
   */
  callId: string
  /**
   * 外呼类型
   */
  callType: CallType
  /**
   * 意向标签
   */
  intentTag: string
  /**
   * 外呼号码
   */
  number: string
  /**
   * 号码 ID
   */
  numberMD5: string
  /**
   * 分配坐席 ID
   */
  agentId: number
  /**
   * 坐席标签
   */
  agentTag: string
  /**
   * 用户标签
   */
  tag: string
  /**
   * AI 话术 ID
   */
  templateId: string
  chats: {
    /**
     * 说话内容
     */
    "content": string,
    /**
     * 说话时间
     */
    "createTime": string,
    /**
     * 说话号码
     */
    "fromNumber": string
  }[]
}

export type Context = SDKConfig & UserInfo

aiSDK.init({  // 👈 初始化SDK实例连接
  secretId: '50ab02d3a42f788e6d8f7da1c01a68d7', //必填,secretID
  corpId: '392f9b20cf5ff706', //必填,公司ID
  agentId: '1860', //必填,坐席ID
  onError(err: Error, context: Context) { // 👈 所有出错信息回调函数
    console.log(err.message)
  },
  onSuccess(context: Context) {
    console.log('注册订阅成功')
  },
  onKicked(context: Context) { // 👈  一个坐席只允许一处登录,多处登录会互踢,被踢的坐席默认会定时3s尝试重新登录连接,此时如果异地登录的账号仍在线则会一直做检测能否登录,直到异地登录的账号退出,多处登录互踢的情况同理。
    console.log('坐席异地登录,当前被踢出') // 如果不需要重连机制可以在这里执行aiSDK.destroy(),之后如果需要手动连接请再执行aiSDK.init(param)
  },
  onReconnect(context: Context) { // 👈 当出现服务异常或网络异常或被踢导致连接终断,会尝试重连,重连前会回调该函数,如果不需要重连机制也可以在这里执行aiSDK.destroy()
    console.log('尝试重连中...')
  },
  onSessionEnd(callId: string, context: Context) {  // 👈 当一个外呼会话结束会执行此回调
    console.log('当前呼叫会话callId:' + callId + '已结束' )
  },
  onMessage(message: PushData, context: Context) {
    // 来电弹屏信息回调函数  👈 根据message.callId区分不同会话,同个会话callId相同会有多次推送,一个坐席会话结束订阅推送会自动终止查询,如需提前终止查询可以执行aiSDK.stopPolling()
    console.log(message)
    console.log('')
  },
})

// 如果使用的是vue,参考如下销毁,其他框架同理
onUnmounted(() => {
  aiSDK.destory() // 👈 销毁SDK实例&连接
})

作为JavaScript使用

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>94AI-SDK Demo v1.1.1</title>
</head>
<body>
94AI-SDK Demo
<div style="padding: 10px">
  <div style="padding: 5px">secretID secretId: <input type="text" id="secretId"></div>
  <div style="padding: 5px">公司ID corpId: <input type="text" id="corpId"></div>
  <div style="padding: 5px"> 坐席ID agentId: <input type="text" id="agentId"></div>
  <button type="button" id="submit">注册</button>
  <button type="button" id="logout">退出</button>
</div>
<div id="angent-message-container"></div>
<script src="94aisdk-1.1.2.umd.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
  var angentMessageContainer = document.getElementById('angent-message-container')
  var secretId = document.getElementById('secretId')
  var corpId = document.getElementById('corpId')
  var agentId = document.getElementById('agentId')
  var secretId_storage = localStorage.getItem('secretId')
  var corpId_storage = localStorage.getItem('corpId')
  var agentId_storage = localStorage.getItem('agentId')
  // 设置默认值
  secretId.value = secretId_storage ? secretId_storage : 'db4985b726d673db5db408901b873f3e'
  corpId.value = corpId_storage ? corpId_storage : '17687fc0006b7248'
  agentId.value = agentId_storage ? agentId_storage : '1859'
  var dynamicGenerateDom = (message) => {
    var container = document.createElement('div')
    var agentIdShow = document.createElement('div')
    var agentTag = document.createElement('div')
    var callId = document.createElement('div')
    var callType = document.createElement('div')
    var number = document.createElement('div')
    var numberMD5 = document.createElement('div')
    var templateId = document.createElement('div')
    var tag = document.createElement('div')
    var taskId = document.createElement('div')
    var hr1 = document.createElement('hr')
    var hr2 = document.createElement('hr')
    var chatsLog = document.createElement('div')
    agentIdShow.innerHTML = `<span>agentId:  ${ message.agentId }</span>`
    agentTag.innerHTML = `<span>agentTag:  ${ message.agentTag }</span>`
    callId.innerHTML = `<span>callId:  ${ message.callId }</span>`
    callType.innerHTML = `<span>callType:  ${ message.callType }</span>`
    number.innerHTML = `<span>number:  ${ message.number }</span>`
    numberMD5.innerHTML = `<span>numberMD5:  ${ message.numberMD5 }</span>`
    templateId.innerHTML = `<span>templateId:  ${ message.templateId }</span>`
    tag.innerHTML = `<span>tag:  ${ message.tag }</span>`
    taskId.innerHTML = `<span>taskId:  ${ message.taskId }</span>`
    chatsLog.innerHTML = `<span>chatsLog:  ${ JSON.stringify(message.chats) }</span>`
    container.id = message.callId
    container.appendChild(agentIdShow)
    container.appendChild(agentTag)
    container.appendChild(callId)
    container.appendChild(callType)
    container.appendChild(number)
    container.appendChild(numberMD5)
    container.appendChild(templateId)
    container.appendChild(tag)
    container.appendChild(taskId)
    container.appendChild(hr1)
    container.appendChild(chatsLog)
    container.appendChild(hr2)
    angentMessageContainer.appendChild(container)
  }
  var modifyDialogueRecord = (conversation, message) => {
    conversation.children[0].innerHTML = `<span>agentId:  ${ message.agentId }</span>`
    conversation.children[1].innerHTML = `<span>agentTag:  ${ message.agentTag }</span>`
    conversation.children[2].innerHTML = `<span>callId:  ${ message.callId }</span>`
    conversation.children[3].innerHTML = `<span>callType:  ${ message.callType }</span>`
    conversation.children[4].innerHTML = `<span>number:  ${ message.number }</span>`
    conversation.children[5].innerHTML = `<span>numberMD5:  ${ message.numberMD5 }</span>`
    conversation.children[6].innerHTML = `<span>templateId:  ${ message.templateId }</span>`
    conversation.children[7].innerHTML = `<span>tag:  ${ message.tag }</span>`
    conversation.children[8].innerHTML = `<span>taskId:  ${ message.taskId }</span>`
    conversation.children[10].innerHTML = `<pre>chatsLog:  ${ JSON.stringify(message.chats, null, 4) }</pre>`
  }
  submit.onclick = () => {
    // 保存输入的id信息
    localStorage.setItem('secretId', secretId.value)
    localStorage.setItem('corpId', corpId.value)
    localStorage.setItem('agentId', agentId.value)
    var aiSDKObject = {
      // 开发环境
      secretId: secretId.value, // 必填,secretID
      corpId: corpId.value, // 必填,公司ID
      agentId: agentId.value, // 必填,坐席ID
      onError(err, context) { // 👈 所有出错信息回调函数
        console.log(err.message)
      },
      onSuccess(context) {
        console.log('注册订阅成功')
      },
      onKicked(context) { // 👈 一个坐席只允许一处登录,多处登录会互踢,被踢的坐席默认会定时3s尝试重新登录连接,此时如果异地登录的账号仍在线则会一直做检测能否登录,直到异地登录的账号退出,多处登录互踢的情况同理。
        console.log('坐席异地登录,当前被踢出') // 如果不需要重连机制可以在这里执行aiSDK.destroy(),之后如果需要手动连接请再执行aiSDK.init(param)
      },
      onReconnect(context) { // 👈 当出现服务异常或网络异常或被踢导致连接终断,会尝试重连,重连前会回调该函数,如果不需要重连机制也可以在这里执行aiSDK.destroy(),,之后如果需要手动连接请再执行aiSDK.init(param)
        console.log('尝试重连中...')
      },
      onSessionEnd(callId, context) {  // 👈 当一个【外呼会话结束】时会执行此回调,可以用来执行【销毁】 挂载到页面已结束的会话记录
        console.log('当前呼叫会话callId:' + callId + '已结束')
      },
      // 来电弹屏信息回调函数
      onMessage(message, context) {
        const conversation = document.getElementById(message.callId)
        if (conversation) {// 如果是同一会话,则更新
          modifyDialogueRecord(conversation, message)
        } else { // 如果是不同会话则创建
          dynamicGenerateDom(message)
        }
      },
      // 呼叫中
      onCalling(callbackData, context) {
        console.log('===============呼叫中start报文===============')
        console.log('callbackData:' + callbackData)
        console.log(callbackData)
        console.log('context:')
        console.log(context)
        console.log('===============呼叫中end报文===============')
      },
      // 转接人工
      onEavesdrop(callbackData, context) {
        console.log('===============转接人工start报文===============')
        console.log('callbackData:' + callbackData)
        console.log(callbackData)
        console.log('context:')
        console.log(context)
        console.log('===============转接人工end报文===============')
      },
      // 接听
      onAnswer(callbackData, context) {
        console.log('===============接听start报文===============')
        console.log('callbackData:' + callbackData)
        console.log(callbackData)
        console.log('context:')
        console.log(context)
        console.log('===============接听end报文===============')
      },
      // 挂断
      onHangup(callbackData, context) {
        console.log('===============挂断start报文===============')
        console.log('callbackData:' + callbackData)
        console.log(callbackData)
        console.log('context:')
        console.log(context)
        console.log('===============挂断end报文===============')
      }
    }
    aiSDK.init(aiSDKObject) // 初始化SDK
  }
  logout.onclick = () => {
    aiSDK.destroy()
  }
})
document.addEventListener('unload', () => {
  aiSDK.destroy()
})
</script>
</body>
</html>

secretId(必填)

类型:string

由 94AI 运营提供

corpId(必填)

类型:string

由 94AI 运营提供

sid(必填)

类型:string

管理员账号登录 94AI 决策平台,进入坐席管理列表页,查看坐席 ID

参数说明

onSuccess(context)

返回值:void

onError(err,context)

返回值:void

| 参数名 | 中文名 | 类型 | 必填 | 说明 | | ------ | -------- | ------ | ---- | -------- | | err.message | 错误信息 | String | Y | 例:秘钥错误!企业不存在或者accessToken不存在!坐席不存在! |

onReconnect(context)

返回值:void

onKicked(context)

返回值:void

onSessionEnd(callId, context)

返回值:void

onMessage(msg,context)

返回值:void

| 参数名 | 中文名 | 类型 | 必填 | 说明 | | ---------- | ----------- | ------ | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | msg.agentId | 分配坐席 ID | Number | Y | 分配坐席 ID | | msg.agentTag | 坐席标签 | String | Y | 建议填写坐席在贵司业务系统唯一标识,用于查询对应 agentId;可以为空。 | | msg.callId | 外呼 ID | String | Y | 例:9b2eb6b8-7a27-4357-b5ec-104450086e24 | | msg.callType | 外呼类型 | Number | Y | 1001:坐席-人工外呼1002:坐席-AI 外呼-不转人工1003:坐席-AI 外呼-接通转人工1004:坐席-AI 外呼-智能转人工2001:批量-预测外呼2002:批量-AI 外呼-不转人工2003:批量-AI 外呼-接通转人工2004:批量-AI 外呼-智能转人工2005:批量-语音通知 | | msg.number | 外呼号码 | String | Y | 外呼号码,需要根据后台设置,控制是否脱敏 | | msg.numberMD5 | 号码 ID | String | Y | 外呼号码 ID | | msg.templateId | AI 话术 ID | Number | Y | 外呼的话术模板 ID,可以为空 | | msg.tag | 用户标签 | String | Y | 用户标签,最多 50 个字符 | | msg.taskId | 任务 ID | String | Y | 决策系统中的任务编号 | | msg.chats | 对话记录 | Array | Y | 聊天记录,可以为空例:[{"fromNumber":"0","content": "你好,请问您是王小帅吗?","createTime": "2019-01-09 14:14:19"},{"fromNumber":"7945bd83237335e5376ff44d62e4f0ae","content": "嗯","createTime": "2019-01-09 14:14:20"},{"fromNumber":"0","content": "您在九四平台有一笔贷款,本期应还金额 100 元,已经逾期 1 天了,请问您今天晚上 12 点之前能完成还款吗?","createTime": "2019-01-09 14:14:21"}] |

chats

| 参数名 | 中文名 | 类型 | 必填 | 说明 | | ---------- | -------- | ------ | ---- | ---------------------------------- | | content | 说话内容 | String | Y | 说话内容 | | createTime | 说话时间 | String | Y | 说话时间,格式:2019-01-09 14:14:19 | | fromNumber | 说话号码 | String | Y | 说话号码,其中 0 为机器人 |

Demo:

{
    "number": "13661634186",
    "callId": "1",
    "numberMD5": "md4",
    "templateId": 1,
    "agentTag": "agent tag",
    "agentId": 1,
    "callType": 1,
    "taskId": "1",
    "tag": "tag",
    "chats": [
      {
        "content": "hello world906",
        "createTime": "2021-8-5 19:39:03",
        "fromNumber": "136616325478"
      },
      {
        "content": "hello world559",
        "createTime": "2021-8-5 19:39:03",
        "fromNumber": "136616325478"
      },
      ...
    ]
  }
}