dsh-line-bot 0.9.5 → 0.9.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.6
4
+
5
+ - 回覆可分段送出:依空行(段落)或每個換行拆成多個 LINE 訊息框,最多 5 則;超過 5 段會把後面的段落併進最後一則。
6
+ - 面板「LINE 憑證」新增「分段傳送(多個訊息框)」開關與分段方式(空行分段/每個換行)。
7
+ - 主動訊息、餘額提醒與一般回覆都套用同一套分段規則。
8
+
3
9
  ## 0.9.5
4
10
 
5
11
  - 主動傳訊改成每位使用者各自倒數:在「最短~最長間隔」之間隨機挑時間,時間到且沉默夠久才可能開口,不再用全域擲骰。
package/README.en.md CHANGED
@@ -13,6 +13,7 @@ Built in:
13
13
  - **LINE credentials**: fill in Channel ID + Channel Secret and it issues an access token automatically (`/v2/oauth/accessToken`, about 30 days, auto-renewed near expiry); you can also paste an existing Channel Access Token.
14
14
  - **Personas**: pick any built-in or custom persona from the dafeiyu plugin in the panel, or use the plugin's own custom personas (stored in `<DSH_HOME>/line-bot/personas.json`, add/edit/import). Persona selection is per-session and does not affect other conversations in the GUI.
15
15
  - **Proactive messages**: a scheduler built into the plugin (no launchd). Each user gets an independent randomized countdown (between a minimum and maximum interval); it only speaks when the countdown is due and the user has been idle long enough. Configurable min/max interval, daily/monthly caps, minimum gap, quiet hours, idle time, unanswered limit (pause after that many unanswered proactive messages, reset when the user replies), target users and prompt. The Agent can reply `SKIP` when it is not a good moment.
16
+ - **Split replies**: optionally split a reply into up to five LINE bubbles by blank line (paragraph) or every newline, instead of one long bubble; the panel can change the mode or turn it off.
16
17
  - **Full settings panel**: every setting lives under Settings → LINE Bot and is stored in `<DSH_HOME>/line-bot/config.json` (mode 600).
17
18
 
18
19
  > About "log in with LINE Business ID and have the panel create the bot": since 2024-09 LINE only allows creating a Messaging API channel manually in [LINE Official Account Manager](https://manager.line.biz/), with no public API; LINE Login only authenticates identity and cannot grant management rights over an Official Account. So the panel does not create the bot, but it gives you the correct entry links and automates everything after "you have the Channel ID / Secret" (issuing the token, setting the webhook, testing it).
@@ -90,7 +91,7 @@ At the top of the panel is a **sticky save bar**: "Save changes / Refresh" stays
90
91
  | Section | Contents |
91
92
  | --- | --- |
92
93
  | Overview | Green-light status for webhook server / tunnel / LINE / persona / proactive messages, public URL, one-click bring-up and start/stop |
93
- | LINE credentials | Channel ID, Channel Secret, Access Token, auto-issue, loading animation, bot info, webhook apply/test, allow-list |
94
+ | LINE credentials | Channel ID, Channel Secret, Access Token, auto-issue, loading animation, split replies, bot info, webhook apply/test, allow-list |
94
95
  | Cloudflare Tunnel | quick / API token modes, token, hostname, tunnel name, Account/Zone ID, download cloudflared, start/stop, auto-configure webhook, bring your own public URL |
95
96
  | Model & provider | Pick the provider/model and reasoning effort for LINE replies; disables DeepSeek balance when the provider is not deepseek-account |
96
97
  | Reply persona | Choose a persona (dafeiyu or a plugin custom one), add/edit/delete custom personas, copy the current persona into a custom one, enforce, allow users to switch personas, switch dafeiyu to session mode, test an Agent reply |
package/README.ja.md CHANGED
@@ -13,6 +13,7 @@ LINE 公式アカウント(Messaging API)を DeepSeek Harness につなぐ
13
13
  - **LINE 認証情報**:Channel ID と Channel Secret を入力すれば access token を自動発行(`/v2/oauth/accessToken`、約 30 日、期限が近づくと自動更新)。既存の Channel Access Token を貼り付けることもできます。
14
14
  - **ペルソナ**:パネルから大肥魚プラグインの内蔵/カスタムペルソナを選べるほか、プラグイン内蔵のカスタムペルソナ(`<DSH_HOME>/line-bot/personas.json`、追加・編集・インポート可)も使えます。ペルソナはセッション単位で指定され、GUI の他の会話には影響しません。
15
15
  - **自発メッセージ**:プラグイン内蔵のスケジューラー(launchd 不要)。ユーザーごとに独立したランダムなカウントダウン(最短~最長間隔)を持ち、時間が来て相手の沈黙が十分長いときだけ話しかけます。最短/最長間隔、1 日/1 か月の上限、最低間隔、静かな時間帯、idle、連続未返信の上限(上限に達したら一時停止、相手が返信したらリセット)、対象ユーザー、プロンプトを設定できます。Agent が「今は違う」と判断したら `SKIP` を返して見送れます。
16
+ - **分割返信**:返信を空行(段落)または改行ごとに最大 5 つの LINE メッセージに分割できます。1 つの長い吹き出しに詰め込まずに送れます。パネルで方式の切り替えやオフも可能です。
16
17
  - **充実した設定パネル**:設定はすべて「設定 → LINE Bot」にあり、`<DSH_HOME>/line-bot/config.json`(モード 600)に保存されます。
17
18
 
18
19
  > 「LINE Business ID でログインしてパネルから bot を作る」ことについて:LINE は 2024-09 以降、Messaging API チャネルの作成を [LINE Official Account Manager](https://manager.line.biz/) での手動操作のみに制限しており、公開 API はありません。LINE Login も本人確認だけで、公式アカウントの管理権限は取得できません。そのためパネルは bot を作成しませんが、正しい入口リンクを提示し、「Channel ID / Secret を取得した後」の作業(トークン発行、webhook 設定、テスト)を自動化します。
@@ -90,7 +91,7 @@ npx dsh-line-bot install --no-companions
90
91
  | セクション | 内容 |
91
92
  | --- | --- |
92
93
  | 概要 | webhook サーバー/トンネル/LINE/ペルソナ/自発メッセージの状態、公開 URL、ワンクリック起動と停止 |
93
- | LINE 認証情報 | Channel ID、Channel Secret、Access Token、自動発行、ローディング表示、bot 情報、webhook の適用/テスト、許可リスト |
94
+ | LINE 認証情報 | Channel ID、Channel Secret、Access Token、自動発行、ローディング表示、分割返信、bot 情報、webhook の適用/テスト、許可リスト |
94
95
  | Cloudflare Tunnel | quick/API トークンモード、トークン、hostname、トンネル名、Account/Zone ID、cloudflared のダウンロード、起動/停止、webhook 自動設定、独自の公開 URL |
95
96
  | モデルとプロバイダー | LINE 返信で使う provider/モデルと推論強度を選択。deepseek-account 以外では DeepSeek 残高を自動で無効化 |
96
97
  | 返信ペルソナ | ペルソナ選択(大肥魚またはプラグインのカスタム)、カスタムペルソナの追加・編集・削除、現在のペルソナをカスタムに複製、強制適用、ユーザーによる切り替え許可、大肥魚を session モードに切り替え、Agent 返信のテスト |
package/README.ko.md CHANGED
@@ -13,6 +13,7 @@ LINE 공식 계정(Messaging API)을 DeepSeek Harness에 연결하는 플러그
13
13
  - **LINE 자격 증명**: Channel ID와 Channel Secret을 입력하면 access token을 자동 발급합니다(`/v2/oauth/accessToken`, 약 30일, 만료 전 자동 갱신). 기존 Channel Access Token을 붙여 넣어도 됩니다.
14
14
  - **페르소나**: 패널에서 大肥魚 플러그인의 내장/커스텀 페르소나를 고르거나, 플러그인 내장 커스텀 페르소나(`<DSH_HOME>/line-bot/personas.json`, 추가/편집/가져오기)를 쓸 수 있습니다. 페르소나는 세션 단위로 지정되며 GUI의 다른 대화에는 영향을 주지 않습니다.
15
15
  - **능동 메시지**: 플러그인 내장 스케줄러(launchd 불필요). 사용자마다 독립적인 무작위 카운트다운(최소~최대 간격)을 가지며, 시간이 되고 상대의 침묵이 충분히 길 때만 말을 겁니다. 최소/최대 간격, 일일/월간 상한, 최소 간격, 조용한 시간대, idle, 연속 미응답 상한(도달 시 일시 중지, 상대가 답하면 초기화), 대상 사용자, 프롬프트를 설정할 수 있습니다. Agent가 지금은 아니라고 판단하면 `SKIP`을 반환해 건너뜁니다.
16
+ - **분할 답장**: 답장을 빈 줄(문단) 또는 줄바꿈마다 최대 5개의 LINE 메시지로 나눠 보낼 수 있습니다. 하나의 긴 말풍선에 몰아넣지 않습니다. 패널에서 방식을 바꾸거나 끌 수 있습니다.
16
17
  - **전체 설정 패널**: 모든 설정이 "설정 → LINE Bot"에 있으며 `<DSH_HOME>/line-bot/config.json`(모드 600)에 저장됩니다.
17
18
 
18
19
  > "LINE Business ID로 로그인해서 패널에서 bot을 만드는" 것에 대해: LINE은 2024-09부터 Messaging API 채널 생성을 [LINE Official Account Manager](https://manager.line.biz/)에서 수동으로만 허용하며 공개 API가 없습니다. LINE Login도 신원 확인일 뿐 공식 계정 관리 권한을 얻을 수 없습니다. 그래서 패널은 bot을 만들지 않지만, 올바른 진입 링크를 알려 주고 "Channel ID / Secret을 얻은 뒤"의 모든 단계(토큰 발급, webhook 설정, 테스트)를 자동화합니다.
@@ -90,7 +91,7 @@ npx dsh-line-bot install --no-companions
90
91
  | 섹션 | 내용 |
91
92
  | --- | --- |
92
93
  | 개요 | webhook 서버/터널/LINE/페르소나/능동 메시지 상태, 공개 URL, 원클릭 기동과 시작/중지 |
93
- | LINE 자격 증명 | Channel ID, Channel Secret, Access Token, 자동 발급, 로딩 표시, bot 정보, webhook 적용/테스트, 허용 목록 |
94
+ | LINE 자격 증명 | Channel ID, Channel Secret, Access Token, 자동 발급, 로딩 표시, 분할 답장, bot 정보, webhook 적용/테스트, 허용 목록 |
94
95
  | Cloudflare Tunnel | quick/API 토큰 모드, 토큰, hostname, 터널 이름, Account/Zone ID, cloudflared 다운로드, 시작/중지, webhook 자동 설정, 직접 제공하는 공개 URL |
95
96
  | 모델과 공급자 | LINE 답장에 쓸 provider/모델과 추론 강도 선택. deepseek-account가 아니면 DeepSeek 잔액 자동 비활성화 |
96
97
  | 답장 페르소나 | 페르소나 선택(大肥魚 또는 플러그인 커스텀), 커스텀 페르소나 추가/편집/삭제, 현재 페르소나를 커스텀으로 복사, 강제 적용, 사용자 직접 전환 허용, 大肥魚를 session 모드로 전환, Agent 답장 테스트 |
package/README.md CHANGED
@@ -13,6 +13,7 @@
13
13
  - **LINE 憑證**:填 Channel ID+Channel Secret 就能自動簽發 access token(`/v2/oauth/accessToken`,約 30 天,快到期會自動續簽);也可以直接貼上既有的 Channel Access Token。
14
14
  - **人設**:面板可選大肥魚插件裡任何一個內建/自訂人設,或插件內建的自訂人設(存在 `<DSH_HOME>/line-bot/personas.json`,可新增/編輯/匯入)。人設是「逐 session」指定,不會改到你 GUI 裡其他對話的人設。
15
15
  - **主動傳訊**:插件內建排程器(不用 launchd),每位使用者各自倒數(最短~最長間隔隨機);可調最短/最長間隔、每日/每月上限、兩則間距、安靜時段、對方安靜多久才可打擾、連續未回覆上限(達上限暫停,對方回話後歸零)、指定對象與提示詞;Agent 覺得不適合時可以回 `SKIP` 跳過。
16
+ - **分段回覆**:可把回覆依空行(段落)或每個換行拆成多個 LINE 訊息框,最多 5 則,不再全部擠在同一則;面板可切換分段方式或關閉。
16
17
  - **完整設定面板**:所有設定都在「設定 → LINE Bot」裡,存到 `<DSH_HOME>/line-bot/config.json`(權限 600)。
17
18
 
18
19
  > 關於「用 LINE Business ID 登入、由面板代建 bot」:LINE 自 2024-09 起只允許在 [LINE Official Account Manager](https://manager.line.biz/) 手動建立 Messaging API channel,沒有公開 API;LINE Login 也只是身分驗證,不能取得官方帳號的管理權。所以面板不代建 bot,但會給你正確的入口連結,並把「拿到 Channel ID / Secret 之後」的所有步驟自動化(簽 token、設 webhook、測試)。
@@ -90,7 +91,7 @@ npx dsh-line-bot install --no-companions
90
91
  | 區塊 | 內容 |
91
92
  | --- | --- |
92
93
  | 狀態總覽 | webhook server/隧道/LINE/人設/主動傳訊的綠燈狀態、公開網址、一鍵上線與啟停 |
93
- | LINE 憑證 | Channel ID、Channel Secret、Access Token、自動簽發、loading 動畫、bot 資訊、webhook 套用/測試、白名單 |
94
+ | LINE 憑證 | Channel ID、Channel Secret、Access Token、自動簽發、loading 動畫、分段回覆、bot 資訊、webhook 套用/測試、白名單 |
94
95
  | Cloudflare Tunnel | quick/API Token 模式、Token、hostname、隧道名稱、Account/Zone ID、下載 cloudflared、啟停、自動設定 webhook、自行提供的公開網址 |
95
96
  | 模型與接口來源 | 選擇 LINE 回覆的 provider/模型與推理強度;非 deepseek-account 時自動停用 DeepSeek 餘額 |
96
97
  | 回覆人設 | 選擇人設(大肥魚或插件自訂)、新增/編輯/刪除自訂人設、把目前人設複製成自訂、強制套用、允許使用者自己換人設、切換大肥魚 session 模式、測試 Agent 回覆 |
package/README.zh-CN.md CHANGED
@@ -13,6 +13,7 @@
13
13
  - **LINE 凭证**:填 Channel ID+Channel Secret 就能自动签发 access token(`/v2/oauth/accessToken`,约 30 天,快到期会自动续签);也可以直接贴入既有的 Channel Access Token。
14
14
  - **人设**:面板可选大肥鱼插件里任何一个内置/自定义人设,或插件内置的自定义人设(存在 `<DSH_HOME>/line-bot/personas.json`,可新增/编辑/导入)。人设是「逐 session」指定,不会改到你 GUI 里其他对话的人设。
15
15
  - **主动传讯**:插件内置排程器(不用 launchd),每位使用者各自倒数(最短~最长间隔随机);可调最短/最长间隔、每日/每月上限、两则间距、安静时段、对方安静多久才可打扰、连续未回复上限(达上限暂停,对方回话后归零)、指定对象与提示词;Agent 觉得不适合时可以回 `SKIP` 跳过。
16
+ - **分段回复**:可把回复依空行(段落)或每个换行拆成多个 LINE 消息框,最多 5 条,不再全部挤在同一条;面板可切换分段方式或关闭。
16
17
  - **完整设置面板**:所有设置都在「设置 → LINE Bot」里,存到 `<DSH_HOME>/line-bot/config.json`(权限 600)。
17
18
 
18
19
  > 关于「用 LINE Business ID 登录、由面板代建 bot」:LINE 自 2024-09 起只允许在 [LINE Official Account Manager](https://manager.line.biz/) 手动创建 Messaging API channel,没有公开 API;LINE Login 也只是身份验证,不能取得官方账号的管理权。所以面板不代建 bot,但会给你正确的入口链接,并把「拿到 Channel ID / Secret 之后」的所有步骤自动化(签 token、设 webhook、测试)。
@@ -90,7 +91,7 @@ npx dsh-line-bot install --no-companions
90
91
  | 区块 | 内容 |
91
92
  | --- | --- |
92
93
  | 状态总览 | webhook server/隧道/LINE/人设/主动传讯的绿灯状态、公开网址、一键上线与启停 |
93
- | LINE 凭证 | Channel ID、Channel Secret、Access Token、自动签发、loading 动画、bot 信息、webhook 套用/测试、白名单 |
94
+ | LINE 凭证 | Channel ID、Channel Secret、Access Token、自动签发、loading 动画、分段回复、bot 信息、webhook 套用/测试、白名单 |
94
95
  | Cloudflare Tunnel | quick/API Token 模式、Token、hostname、隧道名称、Account/Zone ID、下载 cloudflared、启停、自动设置 webhook、自行提供的公开网址 |
95
96
  | 模型与接口来源 | 选择 LINE 回复的 provider/模型与推理强度;非 deepseek-account 时自动停用 DeepSeek 余额 |
96
97
  | 回复人设 | 选择人设(大肥鱼或插件自定义)、新增/编辑/删除自定义人设、把目前人设复制成自定义、强制套用、允许用户自己换人设、切换大肥鱼 session 模式、测试 Agent 回复 |
package/client.js CHANGED
@@ -975,6 +975,14 @@ window.__ModuleLoader__.load({
975
975
  ),
976
976
  h(Toggle, { checked: line.useAutoToken !== false, onChange: (value) => update({ line: { useAutoToken: value } }), label: '自動簽發 access token', hint: '有 Channel ID+Secret 時,優先自動取得(建議開啟)' }),
977
977
  h(Toggle, { checked: line.loadingEnabled !== false, onChange: (value) => update({ line: { loadingEnabled: value } }), label: '顯示「正在輸入」動畫', hint: '回覆前呼叫 LINE 的 loading 動畫' }),
978
+ h(Toggle, { checked: line.splitMessages !== false, onChange: (value) => update({ line: { splitMessages: value } }), label: '分段傳送(多個訊息框)', hint: '把回覆依換行拆成多個訊息框;LINE 一次最多 5 則,超過的會併到最後一則' }),
979
+ h(Field, { label: '分段方式' }, h('select', {
980
+ value: line.splitMode === 'line' ? 'line' : 'paragraph',
981
+ onChange: (event) => update({ line: { splitMode: event.target.value } }),
982
+ style: { ...S.input },
983
+ },
984
+ h('option', { value: 'paragraph' }, '空行分段(推薦,段落才分)'),
985
+ h('option', { value: 'line' }, '每個換行都分段(氣泡較多)'))),
978
986
  h(Toggle, { checked: line.stickerVision !== false, onChange: (value) => update({ line: { stickerVision: value } }), label: '看得懂貼圖', hint: '收到貼圖時抓圖片給模型看;模型不支援圖片時改用 modlens 描述,再不支援才用關鍵字' }),
979
987
  h(Toggle, { checked: line.imageVision !== false, onChange: (value) => update({ line: { imageVision: value } }), label: '看得懂一般圖片', hint: '收到圖片時下載給模型看;模型不支援圖片時用 modlens 產生描述' }),
980
988
  h('div', { style: S.note }, `看圖方式:${runtime.vision?.modelSupportsImages ? '目前模型可直接看圖' : runtime.vision?.available ? '目前模型不吃圖,改用 modlens 描述' : '目前模型不吃圖,且找不到 modlens'}${runtime.vision?.lastError ? `(modlens 最近錯誤:${runtime.vision.lastError})` : ''}`),
package/lib/config.mjs CHANGED
@@ -27,6 +27,8 @@ export const DEFAULT_CONFIG = {
27
27
  loadingEnabled: true,
28
28
  stickerVision: true,
29
29
  imageVision: true,
30
+ splitMessages: true,
31
+ splitMode: 'paragraph', // paragraph | line
30
32
  accessMode: 'approval', // approval | whitelist
31
33
  allowedUserIds: [],
32
34
  welcomeText: '(已加好友)嗨,我是大肥魚~想聊什麼都可以跟我說。',
@@ -203,6 +205,8 @@ export function sanitizePatch(current, patch) {
203
205
  next.line.loadingEnabled = Boolean(next.line.loadingEnabled)
204
206
  next.line.stickerVision = Boolean(next.line.stickerVision)
205
207
  next.line.imageVision = Boolean(next.line.imageVision)
208
+ next.line.splitMessages = Boolean(next.line.splitMessages)
209
+ next.line.splitMode = next.line.splitMode === 'line' ? 'line' : 'paragraph'
206
210
  next.line.welcomeText = String(next.line.welcomeText ?? '').slice(0, 1000)
207
211
  next.line.errorReply = String(next.line.errorReply ?? '').slice(0, 500)
208
212
  next.line.emptyReply = String(next.line.emptyReply ?? '').slice(0, 500)
package/lib/host.mjs CHANGED
@@ -47,7 +47,7 @@ const { createStickerImages } = stickerImageMod
47
47
  const { createVision } = visionMod
48
48
  const { chunkText, clip, inQuietWindow, jsonFail, jsonOk, maskSecret, readJsonBody, safeArray, sleep, readJsonSafe } = utilMod
49
49
 
50
- export const VERSION = '0.9.5'
50
+ export const VERSION = '0.9.6'
51
51
 
52
52
  // 環境變數提供的 Cloudflare API Token(方便用 shell 注入、不用把 token 寫進設定檔)。
53
53
  // 設定檔裡的 token 優先;兩者都沒有時才用環境變數。
@@ -1448,6 +1448,17 @@ export async function create({ ctx, config: pluginConfig, logger: upstream }) {
1448
1448
  return bestScore >= 2 ? best : null
1449
1449
  }
1450
1450
 
1451
+ // 把回覆切成多個 LINE 訊息框。預設用空行分段(段落),也可改成每個換行一段。
1452
+ function splitReplyText(text) {
1453
+ const cfg = store.get()
1454
+ const raw = String(text || '').trim()
1455
+ if (!raw) return []
1456
+ if (cfg.line?.splitMessages === false) return [raw]
1457
+ const separator = cfg.line?.splitMode === 'line' ? /\n+/ : /\n[ \t]*\n+/
1458
+ const parts = raw.split(separator).map((part) => part.trim()).filter(Boolean)
1459
+ return parts.length > 1 ? parts : [raw]
1460
+ }
1461
+
1451
1462
  async function buildOutgoingMessages(text) {
1452
1463
  const cfg = store.get()
1453
1464
  const parsed = splitStickerMarkers(text)
@@ -1494,7 +1505,18 @@ export async function create({ ctx, config: pluginConfig, logger: upstream }) {
1494
1505
  if (imageUrls.length > 0) {
1495
1506
  messages.push(buildFlexMessage(parsed.text, imageUrls))
1496
1507
  } else if (parsed.text) {
1497
- for (const chunk of chunkText(parsed.text)) {
1508
+ const texts = []
1509
+ for (const segment of splitReplyText(parsed.text)) {
1510
+ for (const chunk of chunkText(segment)) texts.push(chunk)
1511
+ }
1512
+ // LINE 一次最多 5 則:超出時把多餘的段落併進最後一則,避免後半段被丟掉。
1513
+ if (texts.length > 5) {
1514
+ const kept = texts.slice(0, 4)
1515
+ kept.push(texts.slice(4).join('\n\n').slice(0, 4900))
1516
+ texts.length = 0
1517
+ texts.push(...kept)
1518
+ }
1519
+ for (const chunk of texts) {
1498
1520
  if (messages.length >= 5) break
1499
1521
  messages.push(chunk)
1500
1522
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-line-bot",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
4
4
  "description": "把 LINE 官方帳號(Messaging API)接進 DeepSeek Harness 的插件:內建 Cloudflare Tunnel、人設選擇(大肥魚或插件自訂)、主動傳訊與完整設定面板。",
5
5
  "type": "module",
6
6
  "main": "index.js",