dsh-line-bot 0.2.2 → 0.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0
4
+
5
+ - 新增「模型與接口來源」:可選這個 DSH profile 已註冊的 provider 與模型、推理強度;留空則跟隨 DSH 預設。
6
+ - DeepSeek 餘額只適用 `deepseek-account`:切成其他 provider 時,餘額卡會反白停用、不再抓餘額,也不會主動提醒儲值。
7
+ - 面板順序調整:LINE 憑證移到第 2、Cloudflare Tunnel 第 3,模型與來源第 4。
8
+
9
+ ## 0.3.1
10
+
11
+ - 修好 Windows 安裝:`npx dsh-line-bot install` 現在會找到 DeepSeek Harness 內建的 pnpm(`%LOCALAPPDATA%\Programs\…`、`%PROGRAMFILES%`),也會正確透過 `shell` 執行 `dsh.cmd` / `pnpm.cmd`。
12
+ - 找不到 pnpm 時的錯誤訊息補上 Windows 的建議(`npm install -g pnpm` 或改用面板安裝)。
13
+
14
+ ## 0.3.0
15
+
16
+ - 新增「個人記憶」:每位使用者一份長期記憶(`<DSH_HOME>/line-bot/memories.json`),角色可在對話中自己呼叫 `line_memory_add` 記下重要資訊、用 `line_memory_forget` 忘掉、用 `line_memory_list` 確認。
17
+ - 有期限的記憶可帶 `ttlDays`,到期由排程自動刪除;每天(預設 4 點,面板可調)角色會自己整理一次,清掉過期或不再成立的內容。
18
+ - 每輪只注入最近 N 筆/限量字元;面板「個人記憶」卡可查看、刪除、立即清理、立即整理,並調整每人上限與每日整理時間。
19
+ - README 五種語言補上個人記憶說明。
20
+
3
21
  ## 0.2.1
4
22
 
5
23
  - 新增「DeepSeek 餘額」:每輪把錢包餘額放進角色背景資訊;低於門檻時由角色用自己的語氣主動提醒儲值(冷卻、靜音時段、可在面板調整)。
package/README.en.md CHANGED
@@ -73,7 +73,11 @@ At the top of the panel is a **sticky save bar**: "Save changes / Refresh" stays
73
73
  | Overview | Green-light status for webhook server / tunnel / LINE / persona / proactive messages, public URL, one-click bring-up and start/stop |
74
74
  | LINE credentials | Channel ID, Channel Secret, Access Token, auto-issue, loading animation, bot info, webhook apply/test, allow-list |
75
75
  | 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 |
76
+ | Model & provider | Pick the provider/model and reasoning effort for LINE replies; disables DeepSeek balance when the provider is not deepseek-account |
76
77
  | 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 |
78
+ | Tieba learning sync | Writes the tone samples learned while browsing Tieba back into the persona's "Tieba tone" section, preview diff, sync now |
79
+ | Personal memory | Per-user long-term memory, expiry cleanup, daily self-review, manual delete |
80
+ | DeepSeek balance | Current balance, per-turn context, low-balance proactive reminder, threshold and cooldown (deepseek-account only) |
77
81
  | Proactive messages | Toggle, probability, interval, daily/monthly caps, minimum gap, quiet hours, idle, target users, prompt, send a test now, statistics |
78
82
  | Users | The DSH session each LINE user maps to, their own workspace folder, their current persona (editable), message count, last interaction, clear memory / reset session |
79
83
  | Advanced | Port, Agent provider/model/effort/cwd/timeout, one workspace per user (and its root), welcome/error/empty replies, logs, reload host modules (dev) |
@@ -94,6 +98,15 @@ At the top of the panel is a **sticky save bar**: "Save changes / Refresh" stays
94
98
  4. It takes the last assistant text from the session events and replies with LINE reply; if the reply token has expired it falls back to push.
95
99
  5. The proactive-message scheduler checks once a minute (interval, quiet hours, caps, probability); when conditions are met it asks the Agent to say something on its own and pushes it.
96
100
 
101
+ ## Model & provider
102
+
103
+ The "Model & provider" card chooses the provider/model used for LINE replies:
104
+
105
+ - Providers come from this DSH profile; models are fetched live and the first one is preselected when you pick a provider.
106
+ - "Follow DSH default" leaves the choice to `agentDefaultModel` (the panel shows the effective value).
107
+ - Reasoning effort can stay empty to use the provider default.
108
+ - DeepSeek balance and low-balance reminders only work when the provider is `deepseek-account`; other providers grey out that card, and switching back restores it.
109
+
97
110
  ## Persona sources
98
111
 
99
112
  - **dafeiyu (optional)**: when `dsh-persona-dafeiyu` is installed, the panel lists its personas (built-in + your own); LINE selects them per session, without changing other GUI conversations. It must be in `session` mode; the panel tells you and offers a one-click switch.
@@ -141,6 +154,16 @@ The **DeepSeek balance** card reads the wallet balance of the DeepSeek account D
141
154
  - Requires DSH to be signed in to a DeepSeek account (deepseek-account). If it is not, the card explains why and everything else keeps working.
142
155
  - The threshold is money, not tokens: Platform shows a wallet balance, and token conversion varies by model and cache hits.
143
156
 
157
+ ## Personal memory
158
+
159
+ The character keeps its own memory at `<DSH_HOME>/line-bot/memories.json`, separated per user:
160
+
161
+ - When something important comes up (preferences, current situation, promises, notable events), it saves it with `line_memory_add` on its own.
162
+ - Time-limited items (exams, trips, short-term situations) can carry an expiry date and are deleted automatically; you can also just tell it to forget something.
163
+ - Once a day (4 AM by default, configurable in the panel) it reviews the list and removes expired items, one-off events that are over, or facts that no longer hold.
164
+ - Each turn only injects the most recent N entries (20 entries / 2000 characters by default); the rest stay in the file. The per-user cap defaults to 120 entries and evicts the oldest.
165
+ - Passwords, tokens, ID numbers and similar secrets should not be stored; it avoids them.
166
+ - The "Personal memory" panel card shows what it remembers, lets you delete entries, prune expired ones, or trigger a review right away.
144
167
  ## Troubleshooting
145
168
 
146
169
  - **The panel says "cannot connect to the LINE Bot runtime"**: webServer may not be ready yet; refresh. If it still fails, look for `[line-bot]` messages in the DSH logs.
package/README.ja.md CHANGED
@@ -73,7 +73,11 @@ dsh plugin --profile desktop add dsh-line-bot
73
73
  | 概要 | webhook サーバー/トンネル/LINE/ペルソナ/自発メッセージの状態、公開 URL、ワンクリック起動と停止 |
74
74
  | LINE 認証情報 | Channel ID、Channel Secret、Access Token、自動発行、ローディング表示、bot 情報、webhook の適用/テスト、許可リスト |
75
75
  | Cloudflare Tunnel | quick/API トークンモード、トークン、hostname、トンネル名、Account/Zone ID、cloudflared のダウンロード、起動/停止、webhook 自動設定、独自の公開 URL |
76
+ | モデルとプロバイダー | LINE 返信で使う provider/モデルと推論強度を選択。deepseek-account 以外では DeepSeek 残高を自動で無効化 |
76
77
  | 返信ペルソナ | ペルソナ選択(大肥魚またはプラグインのカスタム)、カスタムペルソナの追加・編集・削除、現在のペルソナをカスタムに複製、強制適用、ユーザーによる切り替え許可、大肥魚を session モードに切り替え、Agent 返信のテスト |
78
+ | 貼吧学習の同期 | 貼吧で学んだ口調をペルソナの「貼吧学来的口气」節に書き戻す、差分プレビュー、今すぐ同期 |
79
+ | 個人メモリ | ユーザーごとの長期記憶、期限切れの自動削除、毎日の自己整理、手動削除 |
80
+ | DeepSeek 残高 | 現在の残高、毎ターンの注入、残高が少ないときの主動リマインド、しきい値とクールダウン(deepseek-account のみ) |
77
81
  | 自発メッセージ | オン/オフ、確率、間隔、1 日/1 か月の上限、最短間隔、静かな時間帯、idle、対象ユーザー、プロンプト、今すぐ試送、統計 |
78
82
  | ユーザー | LINE ユーザーごとに対応する DSH セッション、専用ワークスペース、現在のペルソナ(直接変更可)、メッセージ数、最終やりとり、メモリ消去/セッション再作成 |
79
83
  | 詳細設定 | ポート、Agent の provider/model/effort/cwd/タイムアウト、ユーザーごとのワークスペース(ルート含む)、ウェルカム/エラー/空返信、ログ、開発用 host リロード |
@@ -94,6 +98,15 @@ dsh plugin --profile desktop add dsh-line-bot
94
98
  4. セッションイベントから最後の assistant テキストを取り出し、LINE の reply で返信します。reply token が切れていたら自動で push に切り替えます。
95
99
  5. 自発メッセージのスケジューラーが 1 分ごとに確認し(間隔、静かな時間帯、上限、確率)、条件を満たせば Agent に一言話してもらって push します。
96
100
 
101
+ ## モデルとプロバイダー
102
+
103
+ 「モデルとプロバイダー」カードは LINE 返信で使う provider/モデルを決めます:
104
+
105
+ - provider はこの DSH profile に登録されているもの、モデルはライブで取得し、provider を選ぶと最初のモデルが入ります。
106
+ - 「DSH のデフォルトに従う」は `agentDefaultModel` の provider/model をそのまま使います(実際の値はパネルに表示)。
107
+ - 推論強度は空欄なら provider のデフォルト。
108
+ - provider が `deepseek-account` のときだけ DeepSeek 残高と残高リマインドが動きます。他の provider ではカードがグレーアウトして無効になり、戻すと復帰します。
109
+
97
110
  ## ペルソナのソース
98
111
 
99
112
  - **大肥魚(任意)**:`dsh-persona-dafeiyu` がインストールされていると、パネルにそのペルソナ(内蔵+自作)が表示されます。LINE ではセッション単位で指定され、GUI の他の会話には影響しません。`session` モードである必要があり、パネルが案内してワンクリックで切り替えられます。
@@ -141,6 +154,16 @@ dsh plugin --profile desktop add dsh-line-bot
141
154
  - DSH が DeepSeek アカウントにログインしている必要があります。未ログインの場合はカードに理由が表示され、他の機能はそのまま使えます。
142
155
  - しきい値は金額であって token 数ではありません。
143
156
 
157
+ ## 個人メモリ
158
+
159
+ キャラクターは自分用のメモリを `<DSH_HOME>/line-bot/memories.json` に持ち、ユーザーごとに分けて保存します:
160
+
161
+ - 好み、近況、約束、重要な出来事など、あとで必要になりそうな情報は `line_memory_add` で自分から記録します。
162
+ - 期限のあるもの(試験、旅行、短期の状況)は期限日を付けられ、期限が来ると自動で削除されます。「忘れて」と言えば削除します。
163
+ - 毎日(既定は午前 4 時、パネルで変更可)一度見直し、期限切れ・終わった一度きりの出来事・もう成り立たない内容を削除します。
164
+ - 毎ターンは直近 N 件(既定 20 件・2000 文字)だけを注入し、残りはファイルに残します。1 人あたりの上限は既定 120 件で、超えると古いものから消えます。
165
+ - パスワード、token、身分証番号などの機密情報は記録しません。
166
+ - パネルの「個人メモリ」カードで、記録内容の確認、手動削除、期限切れの一括削除、今すぐの見直しができます。
144
167
  ## トラブルシューティング
145
168
 
146
169
  - **パネルに「LINE Bot ランタイムに接続できません」と出る**:webServer がまだ準備できていない可能性があります。再読み込みしてください。それでも失敗する場合は DSH ログの `[line-bot]` を確認します。
package/README.ko.md CHANGED
@@ -73,7 +73,11 @@ dsh plugin --profile desktop add dsh-line-bot
73
73
  | 개요 | webhook 서버/터널/LINE/페르소나/능동 메시지 상태, 공개 URL, 원클릭 기동과 시작/중지 |
74
74
  | LINE 자격 증명 | Channel ID, Channel Secret, Access Token, 자동 발급, 로딩 표시, bot 정보, webhook 적용/테스트, 허용 목록 |
75
75
  | Cloudflare Tunnel | quick/API 토큰 모드, 토큰, hostname, 터널 이름, Account/Zone ID, cloudflared 다운로드, 시작/중지, webhook 자동 설정, 직접 제공하는 공개 URL |
76
+ | 모델과 공급자 | LINE 답장에 쓸 provider/모델과 추론 강도 선택. deepseek-account가 아니면 DeepSeek 잔액 자동 비활성화 |
76
77
  | 답장 페르소나 | 페르소나 선택(大肥魚 또는 플러그인 커스텀), 커스텀 페르소나 추가/편집/삭제, 현재 페르소나를 커스텀으로 복사, 강제 적용, 사용자 직접 전환 허용, 大肥魚를 session 모드로 전환, Agent 답장 테스트 |
78
+ | 貼吧 학습 동기화 | 貼吧에서 배운 말투를 페르소나의 「貼吧学来的口气」 섹션으로 기록, 차이 미리보기, 지금 동기화 |
79
+ | 개인 기억 | 사용자별 장기 기억, 만료 자동 삭제, 매일 자기 정리, 수동 삭제 |
80
+ | DeepSeek 잔액 | 현재 잔액, 매 턴 주입, 잔액이 적을 때 캐릭터가 먼저 알림, 기준 금액과 쿨다운(deepseek-account 전용) |
77
81
  | 능동 메시지 | 켜기/끄기, 확률, 간격, 일일/월간 상한, 최소 간격, 조용한 시간대, idle, 대상 사용자, 프롬프트, 지금 시험 발송, 통계 |
78
82
  | 사용자 | LINE 사용자별 DSH 세션, 전용 작업 폴더, 현재 페르소나(직접 변경 가능), 메시지 수, 마지막 상호작용, 기억 지우기/세션 재설정 |
79
83
  | 고급 설정 | 포트, Agent provider/model/effort/cwd/타임아웃, 사용자별 작업 폴더(루트 포함), 환영/오류/빈 답장, 로그, 개발용 host 리로드 |
@@ -94,6 +98,15 @@ dsh plugin --profile desktop add dsh-line-bot
94
98
  4. 세션 이벤트에서 마지막 assistant 텍스트를 꺼내 LINE reply로 답장합니다. reply token이 만료되었으면 자동으로 push로 전환합니다.
95
99
  5. 능동 메시지 스케줄러가 1분마다 확인하고(간격, 조용한 시간대, 상한, 확률) 조건을 만족하면 Agent에게 한마디 하게 한 뒤 push합니다.
96
100
 
101
+ ## 모델과 공급자
102
+
103
+ 「모델과 공급자」카드는 LINE 답장에 쓸 provider/모델을 정합니다:
104
+
105
+ - provider는 이 DSH profile에 등록된 목록, 모델은 실시간으로 읽어 오며 provider를 고르면 첫 모델이 자동 입력됩니다.
106
+ - 「DSH 기본값 따르기」는 `agentDefaultModel`의 provider/모델을 그대로 씁니다(패널에 실제 값 표시).
107
+ - 추론 강도는 비워 두면 provider 기본값.
108
+ - provider가 `deepseek-account`일 때만 DeepSeek 잔액과 잔액 알림이 동작합니다. 다른 provider에서는 카드가 회색으로 비활성화되고, 돌아오면 복구됩니다.
109
+
97
110
  ## 페르소나 출처
98
111
 
99
112
  - **大肥魚(선택)**: `dsh-persona-dafeiyu`가 설치되어 있으면 패널에 그 페르소나(내장+직접 만든 것)가 나옵니다. LINE에서는 세션 단위로 지정되며 GUI의 다른 대화는 바뀌지 않습니다. `session` 모드여야 하며, 패널이 안내하고 원클릭으로 전환할 수 있습니다.
@@ -141,6 +154,16 @@ dsh plugin --profile desktop add dsh-line-bot
141
154
  - DSH가 DeepSeek 계정(deepseek-account)에 로그인되어 있어야 합니다. 아니면 카드에 이유가 표시되며 다른 기능은 그대로 동작합니다.
142
155
  - 기준값은 금액이며 token 수가 아닙니다.
143
156
 
157
+ ## 개인 기억
158
+
159
+ 캐릭터는 `<DSH_HOME>/line-bot/memories.json`에 자기 기억을 저장하며, 사용자별로 분리됩니다:
160
+
161
+ - 선호, 근황, 약속, 중요한 사건처럼 나중에 쓸 만한 정보는 `line_memory_add`로 스스로 기록합니다.
162
+ - 기한이 있는 일(시험, 여행, 단기 상황)은 만료일을 붙일 수 있고, 기한이 지나면 자동으로 삭제됩니다. "잊어줘"라고 하면 지웁니다.
163
+ - 매일(기본 새벽 4시, 패널에서 변경 가능) 한 번 정리하며, 만료된 항목·끝난 일회성 사건·더 이상 맞지 않는 내용을 삭제합니다.
164
+ - 매 턴에는 최근 N개(기본 20개·2000자)만 주입하고 나머지는 파일에 남깁니다. 사용자당 상한은 기본 120개이며, 넘으면 오래된 것부터 지웁니다.
165
+ - 비밀번호, token, 신분증 번호 같은 민감 정보는 기록하지 않습니다.
166
+ - 패널의 "개인 기억" 카드에서 기록 내용 확인, 수동 삭제, 만료 일괄 정리, 지금 정리를 할 수 있습니다.
144
167
  ## 문제 해결
145
168
 
146
169
  - **패널에 "LINE Bot 런타임에 연결할 수 없습니다"**: webServer가 아직 준비되지 않았을 수 있습니다. 새로 고침하세요. 그래도 실패하면 DSH 로그의 `[line-bot]` 메시지를 확인합니다.
package/README.md CHANGED
@@ -73,7 +73,11 @@ dsh plugin --profile desktop add dsh-line-bot
73
73
  | 狀態總覽 | webhook server/隧道/LINE/人設/主動傳訊的綠燈狀態、公開網址、一鍵上線與啟停 |
74
74
  | LINE 憑證 | Channel ID、Channel Secret、Access Token、自動簽發、loading 動畫、bot 資訊、webhook 套用/測試、白名單 |
75
75
  | Cloudflare Tunnel | quick/API Token 模式、Token、hostname、隧道名稱、Account/Zone ID、下載 cloudflared、啟停、自動設定 webhook、自行提供的公開網址 |
76
+ | 模型與接口來源 | 選擇 LINE 回覆的 provider/模型與推理強度;非 deepseek-account 時自動停用 DeepSeek 餘額 |
76
77
  | 回覆人設 | 選擇人設(大肥魚或插件自訂)、新增/編輯/刪除自訂人設、把目前人設複製成自訂、強制套用、允許使用者自己換人設、切換大肥魚 session 模式、測試 Agent 回覆 |
78
+ | 貼吧學習同步 | 把刷貼吧學到的語氣寫回人設的「貼吧學來的口氣」段、預覽差異、立即同步 |
79
+ | 個人記憶 | 每位使用者分開的長期記憶、到期自動刪、每日請角色整理、手動刪除 |
80
+ | DeepSeek 餘額 | 目前餘額、每輪注入、低於門檻時由角色主動提醒、提醒門檻與冷卻(僅 deepseek-account) |
77
81
  | 主動傳訊 | 開關、機率、間隔、每日/每月上限、最短間隔、安靜時段、idle、指定對象、提示詞、立即試傳、統計 |
78
82
  | 使用者 | 每位 LINE 使用者對應的 DSH session、專屬工作資料夾、目前人設(可直接改)、訊息數、上次互動、清空記憶/重設 session |
79
83
  | 進階設定 | 連接埠、Agent provider/model/effort/cwd/逾時、一人一個工作資料夾(含根目錄)、歡迎/錯誤/空回覆、日誌、開發用 host 重新載入 |
@@ -94,6 +98,15 @@ dsh plugin --profile desktop add dsh-line-bot
94
98
  4. 從 session 事件取出最後一段 assistant 文字,用 LINE reply 回覆;reply token 過期就自動改 push。
95
99
  5. 主動傳訊排程器每分鐘檢查一次(間隔、安靜時段、上限、機率),符合條件就請 Agent 主動說一句,再 push 出去。
96
100
 
101
+ ## 模型與接口來源
102
+
103
+ 「模型與接口來源」卡決定 LINE 回覆要用哪個 provider/模型:
104
+
105
+ - 來源清單來自這個 DSH profile 已註冊的 provider;模型清單即時讀取,選 provider 後會自動帶入第一個模型。
106
+ - 「跟隨 DSH 預設」=不覆寫,使用 `agentDefaultModel` 目前的 provider/model(面板會顯示實際值)。
107
+ - 推理強度可留空跟隨 provider 預設。
108
+ - 只有 provider 是 `deepseek-account` 時,DeepSeek 餘額與低餘額提醒才會運作;切到其他來源時該卡會反白停用,切回即恢復。
109
+
97
110
  ## 人設來源
98
111
 
99
112
  - **大肥魚(選用)**:有安裝 `dsh-persona-dafeiyu` 時,面板會列出它的人設(內建+你自訂的),LINE 會逐 session 指定,不會改到 GUI 其他對話。需要它處於 `session` 模式;面板會提示並可一鍵切換。
@@ -141,6 +154,16 @@ dsh plugin --profile desktop add dsh-line-bot
141
154
  - 需要 DSH 已登入 DeepSeek 帳號(deepseek-account)。沒登入或該 profile 沒掛這個服務時,卡片會顯示原因,其餘功能不受影響。
142
155
  - 門檻用的是錢包金額,不是 token 數:DeepSeek 平台顯示的是金額,token 換算會隨模型與快取變動。
143
156
 
157
+ ## 個人記憶
158
+
159
+ 角色有一份自己的記憶,存在 `<DSH_HOME>/line-bot/memories.json`,每位使用者分開:
160
+
161
+ - 對話中出現它覺得重要的資訊(喜好、近況、承諾、重要事件),它會自己用 `line_memory_add` 記下來,不用你交代。
162
+ - 有期限的事(考試、旅行、短期狀況)可以標到期日,時間到自動刪除;你也可以直接叫它「忘掉這件事」。
163
+ - 每天(預設凌晨 4 點,面板可改)它會自己整理一次:把過期、一次事件已結束、或明顯不再成立的記憶刪掉。
164
+ - 每輪只帶入最近的 N 筆(預設 20 筆、2000 字),其餘仍留在檔案裡;每人上限預設 120 筆,超過時刪最舊的。
165
+ - 密碼、token、證件號等敏感資料不該叫它記,它也會避免。
166
+ - 面板的「個人記憶」卡可以看目前記了什麼、手動刪除、立即清理到期、或現在就叫它整理一次。
144
167
  ## 疑難排解
145
168
 
146
169
  - **面板顯示「無法連線到 LINE Bot 執行期」**:webServer 可能還沒就緒,重新整理即可;仍失敗就看 DSH 日誌裡 `[line-bot]` 的訊息。
package/README.zh-CN.md CHANGED
@@ -73,7 +73,11 @@ dsh plugin --profile desktop add dsh-line-bot
73
73
  | 状态总览 | webhook server/隧道/LINE/人设/主动传讯的绿灯状态、公开网址、一键上线与启停 |
74
74
  | LINE 凭证 | Channel ID、Channel Secret、Access Token、自动签发、loading 动画、bot 信息、webhook 套用/测试、白名单 |
75
75
  | Cloudflare Tunnel | quick/API Token 模式、Token、hostname、隧道名称、Account/Zone ID、下载 cloudflared、启停、自动设置 webhook、自行提供的公开网址 |
76
+ | 模型与接口来源 | 选择 LINE 回复的 provider/模型与推理强度;非 deepseek-account 时自动停用 DeepSeek 余额 |
76
77
  | 回复人设 | 选择人设(大肥鱼或插件自定义)、新增/编辑/删除自定义人设、把目前人设复制成自定义、强制套用、允许用户自己换人设、切换大肥鱼 session 模式、测试 Agent 回复 |
78
+ | 贴吧学习同步 | 把刷贴吧学到的语气写回人设的「贴吧学来的口气」段、预览差异、立即同步 |
79
+ | 个人记忆 | 每位用户分开的长期记忆、到期自动删除、每日请角色整理、手动删除 |
80
+ | DeepSeek 余额 | 当前余额、每轮注入、低于门槛时由角色主动提醒、提醒门槛与冷却(仅 deepseek-account) |
77
81
  | 主动传讯 | 开关、概率、间隔、每日/每月上限、最短间隔、安静时段、idle、指定对象、提示词、立即试传、统计 |
78
82
  | 用户 | 每位 LINE 用户对应的 DSH session、专属工作文件夹、目前人设(可直接改)、消息数、上次互动、清空记忆/重设 session |
79
83
  | 高级设置 | 端口、Agent provider/model/effort/cwd/超时、一人一个工作文件夹(含根目录)、欢迎/错误/空回复、日志、开发用 host 重新载入 |
@@ -94,6 +98,15 @@ dsh plugin --profile desktop add dsh-line-bot
94
98
  4. 从 session 事件取出最后一段 assistant 文字,用 LINE reply 回复;reply token 过期就自动改 push。
95
99
  5. 主动传讯排程器每分钟检查一次(间隔、安静时段、上限、概率),符合条件就请 Agent 主动说一句,再 push 出去。
96
100
 
101
+ ## 模型与接口来源
102
+
103
+ 「模型与接口来源」卡决定 LINE 回复要用哪个 provider/模型:
104
+
105
+ - 来源清单来自这个 DSH profile 已注册的 provider;模型清单即时读取,选 provider 后会自动带入第一个模型。
106
+ - 「跟随 DSH 默认」=不覆写,使用 `agentDefaultModel` 目前的 provider/model(面板会显示实际值)。
107
+ - 推理强度可留空跟随 provider 默认。
108
+ - 只有 provider 是 `deepseek-account` 时,DeepSeek 余额与低余额提醒才会运作;切到其他来源时该卡会反白停用,切回即恢复。
109
+
97
110
  ## 人设来源
98
111
 
99
112
  - **大肥鱼(可选)**:有安装 `dsh-persona-dafeiyu` 时,面板会列出它的人设(内置+你自定义的),LINE 会逐 session 指定,不会改到 GUI 其他对话。需要它处于 `session` 模式;面板会提示并可一键切换。
@@ -141,6 +154,16 @@ dsh plugin --profile desktop add dsh-line-bot
141
154
  - 需要 DSH 已登录 DeepSeek 账号(deepseek-account)。未登录或该 profile 没有这个服务时,卡片会说明原因,其他功能不受影响。
142
155
  - 门槛用的是钱包金额,不是 token 数。
143
156
 
157
+ ## 个人记忆
158
+
159
+ 角色有一份自己的记忆,保存在 `<DSH_HOME>/line-bot/memories.json`,每位用户分开:
160
+
161
+ - 对话中出现它觉得重要的信息(喜好、近况、承诺、重要事件),它会自己用 `line_memory_add` 记下来,不用你交代。
162
+ - 有期限的事(考试、旅行、短期状况)可以标到期日,时间到自动删除;你也可以直接叫它「忘掉这件事」。
163
+ - 每天(默认凌晨 4 点,面板可改)它会自己整理一次:把过期、一次性事件已结束、或明显不再成立的记忆删掉。
164
+ - 每轮只带入最近的 N 笔(默认 20 笔、2000 字),其余仍留在文件里;每人上限默认 120 笔,超过时删除最旧的。
165
+ - 密码、token、证件号等敏感资料不该叫它记,它也会避免。
166
+ - 面板的「个人记忆」卡可以看目前记了什么、手动删除、立即清理到期、或现在就叫它整理一次。
144
167
  ## 疑难排解
145
168
 
146
169
  - **面板显示「无法连接到 LINE Bot 运行时」**:webServer 可能还没就绪,刷新即可;仍失败就看 DSH 日志里 `[line-bot]` 的消息。
package/bin/cli.mjs CHANGED
@@ -16,6 +16,8 @@ import fs from 'node:fs'
16
16
  import os from 'node:os'
17
17
  import path from 'node:path'
18
18
  import { spawnSync } from 'node:child_process'
19
+
20
+ const IS_WIN = process.platform === 'win32'
19
21
  import { fileURLToPath } from 'node:url'
20
22
 
21
23
  const PKG = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
@@ -140,19 +142,54 @@ function withBundle(manifest, enabled) {
140
142
  }
141
143
  }
142
144
 
145
+ function windowsPnpmCandidates() {
146
+ const roots = [
147
+ process.env.LOCALAPPDATA && path.join(process.env.LOCALAPPDATA, 'Programs'),
148
+ process.env.PROGRAMFILES,
149
+ process.env['PROGRAMFILES(X86)'],
150
+ ].filter(Boolean)
151
+ const suffix = ['resources', 'runtime', 'primary-runtime', 'dependencies', 'pnpm', 'bin', 'pnpm.cjs']
152
+ const found = []
153
+ for (const root of roots) {
154
+ found.push(path.join(root, 'DeepSeek Harness', ...suffix))
155
+ try {
156
+ for (const name of fs.readdirSync(root)) {
157
+ if (/deepseek/i.test(name)) found.push(path.join(root, name, ...suffix))
158
+ }
159
+ } catch {
160
+ /* 目錄不存在就跳過 */
161
+ }
162
+ }
163
+ return found
164
+ }
165
+
143
166
  function findPnpm() {
144
167
  const localPnpm = process.platform === 'darwin'
145
- ? '/Applications/DeepSeek Harness.app/Contents/Resources/runtime/primary-runtime/dependencies/pnpm/bin/pnpm.cjs'
146
- : ''
147
- if (localPnpm && fs.existsSync(localPnpm)) return { kind: 'pnpm', command: process.execPath, prefix: [localPnpm] }
148
- const pnpm = spawnSync('pnpm', ['--version'], { stdio: 'ignore' })
149
- if (pnpm.status === 0) return { kind: 'pnpm', command: 'pnpm', prefix: [] }
168
+ ? ['/Applications/DeepSeek Harness.app/Contents/Resources/runtime/primary-runtime/dependencies/pnpm/bin/pnpm.cjs']
169
+ : process.platform === 'win32'
170
+ ? windowsPnpmCandidates()
171
+ : []
172
+ for (const candidate of localPnpm) {
173
+ if (fs.existsSync(candidate)) return { kind: 'pnpm', command: process.execPath, prefix: [candidate], shell: false }
174
+ }
175
+ const pnpm = spawnSync('pnpm', ['--version'], { stdio: 'ignore', shell: IS_WIN })
176
+ if (pnpm.status === 0) return { kind: 'pnpm', command: 'pnpm', prefix: [], shell: IS_WIN }
150
177
  return null
151
178
  }
152
179
 
153
180
  function findDsh() {
154
- const probe = spawnSync('dsh', ['--version'], { stdio: 'ignore' })
155
- return probe.status === 0 ? 'dsh' : ''
181
+ const probe = spawnSync('dsh', ['--version'], { stdio: 'ignore', shell: IS_WIN })
182
+ return probe.status === 0 ? { command: 'dsh', shell: IS_WIN } : null
183
+ }
184
+
185
+ function quoteWin(value) {
186
+ return /[\s"]/.test(value) ? '"' + value.replace(/"/g, '\\"') + '"' : value
187
+ }
188
+
189
+ function spawnTool(tool, args, options) {
190
+ if (!tool.shell) return spawnSync(tool.command, [...(tool.prefix || []), ...args], options)
191
+ const line = [tool.command, ...args].map(quoteWin).join(' ')
192
+ return spawnSync(line, { ...options, shell: true })
156
193
  }
157
194
 
158
195
  function runInstall(profile, versionSpec, { dryRun }) {
@@ -161,18 +198,20 @@ function runInstall(profile, versionSpec, { dryRun }) {
161
198
  let result
162
199
  if (dsh) {
163
200
  const args = ['plugin', '--profile', profile, 'add', versionSpec]
164
- out(`→ ${dsh} ${args.join(' ')}`)
165
- if (!dryRun) result = spawnSync(dsh, args, { cwd: dir, stdio: 'inherit' })
201
+ out(`→ dsh ${args.join(' ')}`)
202
+ if (!dryRun) result = spawnTool(dsh, args, { cwd: dir, stdio: 'inherit' })
166
203
  } else {
167
204
  const pnpm = findPnpm()
168
205
  if (!pnpm) {
169
206
  fail(
170
- '找不到 dsh 或 pnpm。請先安裝 DeepSeek Harness 桌面版(內含 pnpm),或改用面板「設定 → 外掛 → 安裝」。',
207
+ IS_WIN
208
+ ? '找不到 dsh 或 pnpm。請先安裝 DeepSeek Harness 桌面版(內含 pnpm),或先執行「npm install -g pnpm」再重試;也可以直接用面板「設定 → 外掛 → 安裝 bundle」。'
209
+ : '找不到 dsh 或 pnpm。請先安裝 DeepSeek Harness 桌面版(內含 pnpm),或改用面板「設定 → 外掛 → 安裝」。',
171
210
  )
172
211
  }
173
- const args = [...pnpm.prefix, 'add', versionSpec, '--dir', dir]
212
+ const args = [...(pnpm.prefix || []), 'add', versionSpec, '--dir', dir]
174
213
  out(`→ ${pnpm.command} ${args.join(' ')}`)
175
- if (!dryRun) result = spawnSync(pnpm.command, args, { cwd: dir, stdio: 'inherit' })
214
+ if (!dryRun) result = spawnTool(pnpm, args, { cwd: dir, stdio: 'inherit' })
176
215
  }
177
216
  if (!dryRun && result && result.status !== 0) {
178
217
  fail(`安裝套件失敗(pnpm 結束碼 ${result.status})。請確認網路與 ${dir} 的權限後重試。`)
@@ -232,9 +271,9 @@ function commandUninstall(options) {
232
271
  const dsh = findDsh()
233
272
  if (dsh) {
234
273
  const args = ['plugin', '--profile', profile, 'remove', NAME]
235
- out(`→ ${dsh} ${args.join(' ')}`)
274
+ out(`→ dsh ${args.join(' ')}`)
236
275
  if (!options.dryRun) {
237
- const result = spawnSync(dsh, args, { cwd: dir, stdio: 'inherit' })
276
+ const result = spawnTool(dsh, args, { cwd: dir, stdio: 'inherit' })
238
277
  if (result.status !== 0) out('(pnpm 移除失敗,可能本來就沒安裝;bundle 清單已處理)')
239
278
  }
240
279
  } else {