dsh-model 0.21.1 → 0.21.2

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.
@@ -1,5 +1,6 @@
1
1
  // service/launchd.ts — macOS 用户级 LaunchAgent(RunAtLoad + KeepAlive)
2
2
  import { rm } from 'node:fs/promises';
3
+ import { info } from '../util/output.js';
3
4
  import { DshModelError } from '../errors.js';
4
5
  import { L } from '../i18n.js';
5
6
  import { run } from '../util/exec.js';
@@ -41,11 +42,25 @@ ${envBlock} <key>WorkingDirectory</key>
41
42
  export function launchd(spec) {
42
43
  const domain = `gui/${process.getuid?.() ?? 501}`;
43
44
  const target = `${domain}/${spec.label}`;
45
+ /**
46
+ * 被关掉的后台服务(系统设置「登录项 → 允许在后台」被关,或清理软件关的)重新允许:
47
+ * 只动 dsh-model 自己的两个服务,用户点「修复」/ 执行 setup 就是要它们跑起来(2026-10-14 实测:被关后 bootstrap 报 5: Input/output error)。
48
+ */
49
+ const reenable = async () => {
50
+ const r = await run('launchctl', ['print-disabled', domain]);
51
+ if (!new RegExp(`"${spec.label.replace(/\./g, '\\.')}" => (disabled|true)`).test(r.stdout))
52
+ return false;
53
+ await run('launchctl', ['enable', target]);
54
+ info(L(`${spec.label} 之前被 macOS 关掉了后台运行,已重新允许`, `${spec.label} had background running turned off in macOS; allowed it again`));
55
+ return true;
56
+ };
57
+ const loaded = async () => (await run('launchctl', ['print', target])).code === 0;
44
58
  const bootstrap = async () => {
59
+ await reenable();
45
60
  const r = await run('launchctl', ['bootstrap', domain, spec.file]);
46
- // 已加载时返回 5 / 37("service already loaded"),当成功
47
- if (r.code !== 0 && !/already|in progress|5:|37:/i.test(r.stderr)) {
48
- throw new DshModelError('service_failed', L(`launchctl bootstrap 失败:${r.stderr.trim()}`, `launchctl bootstrap failed: ${r.stderr.trim()}`));
61
+ // 已经加载过会报错(5 / 37 等):不看错误码,直接看它到底加载上没有
62
+ if (r.code !== 0 && !(await loaded())) {
63
+ throw new DshModelError('service_failed', L(`后台服务 ${spec.label} 没能加载:${r.stderr.trim()}`, `Could not load background service ${spec.label}: ${r.stderr.trim()}`), L('看一下「系统设置 → 通用 → 登录项与扩展 → 允许在后台」里它是否被关掉了', 'Check System Settings → General → Login Items & Extensions → Allow in the Background'));
49
64
  }
50
65
  };
51
66
  const bootout = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-model",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
4
4
  "description": "Many model sources behind one authenticated OpenAI-compatible endpoint for DeepSeek Harness (dsh) and your tools: WorkBuddy, OpenCode Zen and your CLI subscriptions (Codex, Kimi…), with a management page inside dsh. 多家模型汇成一个 OpenAI 兼容地址,dsh 和其他软件都能直接用。",
5
5
  "keywords": [
6
6
  "dsh-plugin",