dsh-sun-space 0.2.3 → 0.2.5

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/bundle.patch.yml CHANGED
@@ -1,4 +1,7 @@
1
1
  # sun-space bundle 补丁(npm 包分发形态,package.json dsh.bundle.patch 指向本文件)。
2
+ # 本层不覆写任何基础组件行——DSH 运行期间安装/升级/卸载均可用(无 bundle-in-use 拦截)。
3
+ # dws 锁文件(~/.dws/.data.lock)的沙箱 EPERM 由 Worker persona 的 DWS_CONFIG_DIR 自愈指示兜底
4
+ # (凭证在 Keychain,换配置目录不影响认证;0.2.4 起生效,体验优先于全局白名单)。
2
5
  # 与 cordis.patch.yml(本机开发态,绝对路径直挂仓库文件)内容等价,差异两处:
3
6
  # ① 插件与工具模块用包名引用(安装后由 loader 从 profile node_modules 解析);
4
7
  # ② 沙箱白名单 HOME 化(跨机器)。
@@ -6,14 +9,6 @@
6
9
  - insert:
7
10
  # dws CLI 需写自身数据锁(~/.dws/.data.lock)——沙箱白名单放行(E2E R4 发现)。
8
11
  # HOME 化以支持跨机器分发;覆盖行必须带 name 且 config 需完整复刻 base(否则行被禁用)。
9
- - id: sandbox-policy
10
- name: '@deepseek-ai/dsh-sandbox-policy'
11
- config:
12
- mode: !!js process.env.DSH_PERMISSION_MODE ?? 'workspace-write'
13
- workspaceRoot: !!js process.cwd()
14
- additionalWritableRoots:
15
- - !!js process.env.HOME + '/.dws'
16
-
17
12
  - id: sun-space
18
13
  name: 'dsh-sun-space'
19
14
 
@@ -67,6 +62,7 @@
67
62
  prefix: >-
68
63
  You are a Sun Worker executor. 专注完成单一任务:读、检索、执行、验证。
69
64
  你没有面向人的工具——结论只写给 Router。查询自由;写操作先 --dry-run;
65
+ dws 命令若报 open ~/.dws/.data.lock EPERM:export DWS_CONFIG_DIR=$(mktemp -d) 后重试一次(沙箱无白名单环境的标准自愈,凭证在 Keychain 不受影响);
70
66
  禁止 dws oa task approve|reject、rm -rf、dws api POST/DELETE。
71
67
  任务产物一律用 sun_artifact_write 落库(task_id 由 Router 给出),
72
68
  不要用相对路径写文件。
package/cordis.patch.yml CHANGED
@@ -3,7 +3,9 @@
3
3
  # 双预设:sun-router(只分派)/ sun-worker(只执行)。工具白名单由组合本身保证
4
4
  # (Spike A 结论),guard 由 worker-guard 在组合内挂载。
5
5
  - insert:
6
- # dws CLI 需写自身数据锁(~/.dws/.data.lock)——沙箱白名单放行(E2E R4 发现;
6
+ # 本文件含 dsh-sandbox-policy 覆写行:仅本机开发/生产态保留(dws 白名单,免去 Worker 自愈);
7
+ # 分发形态(bundle.patch.yml)已移除覆写以保证运行期可装可卸,EPERM 由 Worker persona 自愈。
8
+ # dws CLI 需写自身数据锁(~/.dws/.data.lock)——沙箱白名单放行(E2E R4 发现;
7
9
  # Router 临场自愈方案为 DWS_CONFIG_DIR 临时目录,此为正式修复,二选一即可)。
8
10
  # 覆盖行必须带 name 且 config 需完整复刻 base(否则行被禁用,连锁 15 服务失效)
9
11
  - id: sandbox-policy
@@ -67,6 +69,7 @@
67
69
  prefix: >-
68
70
  You are a Sun Worker executor. 专注完成单一任务:读、检索、执行、验证。
69
71
  你没有面向人的工具——结论只写给 Router。查询自由;写操作先 --dry-run;
72
+ dws 命令若报 open ~/.dws/.data.lock EPERM:export DWS_CONFIG_DIR=$(mktemp -d) 后重试一次(沙箱无白名单环境的标准自愈,凭证在 Keychain 不受影响);
70
73
  禁止 dws oa task approve|reject、rm -rf、dws api POST/DELETE。
71
74
  任务产物一律用 sun_artifact_write 落库(task_id 由 Router 给出),
72
75
  不要用相对路径写文件。
package/lib/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
3
4
  import { execFile } from "node:child_process";
4
5
  // \0rolldown/runtime.js
5
6
  var __defProp = Object.defineProperty;
@@ -12,6 +13,38 @@ var __exportAll = (all, no_symbols) => {
12
13
  if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
13
14
  return target;
14
15
  };
16
+ // src/vault-path.ts
17
+ /**
18
+ * vault 路径解析——唯一事实源,全插件共享(source/router-tools/worker-vault/worker-watchdog)。
19
+ *
20
+ * 解析优先级:
21
+ * ① 环境变量 SUN_VAULT(启动命令注入,随进程生效)
22
+ * ② 实例启动目录下的 sun-space.config.json 的 vault 字段(持久化配置,重启不丢)
23
+ * ③ 默认约定 ~/Workspace/sun-vault
24
+ *
25
+ * 解析结果同时写入 <实例cwd>/sun-space.json(仅 vault 字段),作为浏览器端(孙学空间)
26
+ * 的发现通道——浏览器读不到进程环境,靠这个文件拿到真实 vault 路径(workspaceFiles
27
+ * 的相对路径读取以会话工作区根为基准,即实例 cwd,两者同目录)。
28
+ *
29
+ * 注意:本文件不携带任何个人路径;个人 vault 位置只存在于①/②(均不入库)。
30
+ */
31
+ const DEFAULT_VAULT_DIRNAME = "sun-vault";
32
+ /** 解析 vault 绝对路径(① env ② 实例目录配置文件 ③ 默认约定)。 */
33
+ function resolveVaultPath(cwd = process.cwd(), home = process.env.HOME ?? "") {
34
+ if (process.env.SUN_VAULT && process.env.SUN_VAULT.trim() !== "") return process.env.SUN_VAULT;
35
+ try {
36
+ const cfg = JSON.parse(readFileSync(join(cwd, "sun-space.config.json"), "utf8"));
37
+ if (typeof cfg?.vault === "string" && cfg.vault.startsWith("/")) return cfg.vault;
38
+ } catch {}
39
+ return join(home, "Workspace", DEFAULT_VAULT_DIRNAME);
40
+ }
41
+ const VAULT = resolveVaultPath();
42
+ /** 把解析结果落盘为客户端发现文件(apply 时调用,尽力而为)。 */
43
+ function publishVaultForClient(cwd = process.cwd()) {
44
+ try {
45
+ writeFileSync(join(cwd, "sun-space.json"), JSON.stringify({ vault: VAULT }, null, 2), "utf8");
46
+ } catch {}
47
+ }
15
48
  // src/dws.ts
16
49
  /**
17
50
  * dws 执行器:单次命令调用(无长连接)。供 sun_notify / Source 轮询使用。
@@ -121,7 +154,7 @@ var source_exports = /* @__PURE__ */ __exportAll({
121
154
  CREDENTIAL_ALERT_COOLDOWN_MS: () => CREDENTIAL_ALERT_COOLDOWN_MS,
122
155
  CREDENTIAL_ALERT_STREAK: () => 2,
123
156
  TRIGGER_TTL_MS: () => TRIGGER_TTL_MS,
124
- VAULT: () => VAULT$1,
157
+ VAULT: () => VAULT,
125
158
  apply: () => apply$2,
126
159
  inject: () => inject$2,
127
160
  parseTriggerTs: () => parseTriggerTs,
@@ -129,11 +162,10 @@ var source_exports = /* @__PURE__ */ __exportAll({
129
162
  shouldAlertCredential: () => shouldAlertCredential
130
163
  });
131
164
  const inject$2 = ["timer"];
132
- const VAULT$1 = process.env.SUN_VAULT ?? `${process.env.HOME}/Workspace/云顶天宫`;
133
165
  /** 轮询周期(毫秒):纯程序层,可调密。 */
134
166
  const POLL_MS = 18e5;
135
- const TRIGGER_DIR$1 = `${VAULT$1}/90-Meta/triggers`;
136
- const SNAPSHOT_FILE = `${VAULT$1}/90-Meta/mock-data/last-snapshot.json`;
167
+ const TRIGGER_DIR$1 = `${VAULT}/90-Meta/triggers`;
168
+ const SNAPSHOT_FILE = `${VAULT}/90-Meta/mock-data/last-snapshot.json`;
137
169
  /** trigger 文件 TTL:超过即视为已消费/过期,轮询成功路径顺带清理。 */
138
170
  const TRIGGER_TTL_MS = 6048e5;
139
171
  const CREDENTIAL_ALERT_COOLDOWN_MS = 36e5;
@@ -286,7 +318,6 @@ var worker_watchdog_exports = /* @__PURE__ */ __exportAll({
286
318
  });
287
319
  const name$1 = "worker-watchdog";
288
320
  const inject$1 = ["timer"];
289
- const VAULT = process.env.SUN_VAULT ?? `${process.env.HOME}/Workspace/云顶天宫`;
290
321
  const TRIGGER_DIR = `${VAULT}/90-Meta/triggers`;
291
322
  /** 默认停滞阈值 15 分钟:长思考/长命令完成后即重置计时,真卡死撑不到这么久。 */
292
323
  const DEFAULT_STALL_MS = 9e5;
@@ -430,6 +461,7 @@ function apply$1(ctx) {
430
461
  const name = "sun-space";
431
462
  const inject = ["timer", "tools"];
432
463
  function apply(ctx) {
464
+ publishVaultForClient();
433
465
  ctx.plugin(source_exports);
434
466
  ctx.plugin(worker_watchdog_exports);
435
467
  }
@@ -1,6 +1,7 @@
1
1
  import { appendFile, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
2
2
  import { join, resolve, sep } from "node:path";
3
3
  import { execFile } from "node:child_process";
4
+ import { readFileSync } from "node:fs";
4
5
  // src/vault.ts
5
6
  /**
6
7
  * vault 访问:路径守卫 + frontmatter 解析/序列化。纯函数为主,可单测。
@@ -183,9 +184,34 @@ async function dingSelf(userId, content, type = "app") {
183
184
  ]);
184
185
  return { ok: data?.ok === true || data?.success === true || data?.data?.success === true };
185
186
  }
187
+ // src/vault-path.ts
188
+ /**
189
+ * vault 路径解析——唯一事实源,全插件共享(source/router-tools/worker-vault/worker-watchdog)。
190
+ *
191
+ * 解析优先级:
192
+ * ① 环境变量 SUN_VAULT(启动命令注入,随进程生效)
193
+ * ② 实例启动目录下的 sun-space.config.json 的 vault 字段(持久化配置,重启不丢)
194
+ * ③ 默认约定 ~/Workspace/sun-vault
195
+ *
196
+ * 解析结果同时写入 <实例cwd>/sun-space.json(仅 vault 字段),作为浏览器端(孙学空间)
197
+ * 的发现通道——浏览器读不到进程环境,靠这个文件拿到真实 vault 路径(workspaceFiles
198
+ * 的相对路径读取以会话工作区根为基准,即实例 cwd,两者同目录)。
199
+ *
200
+ * 注意:本文件不携带任何个人路径;个人 vault 位置只存在于①/②(均不入库)。
201
+ */
202
+ const DEFAULT_VAULT_DIRNAME = "sun-vault";
203
+ /** 解析 vault 绝对路径(① env ② 实例目录配置文件 ③ 默认约定)。 */
204
+ function resolveVaultPath(cwd = process.cwd(), home = process.env.HOME ?? "") {
205
+ if (process.env.SUN_VAULT && process.env.SUN_VAULT.trim() !== "") return process.env.SUN_VAULT;
206
+ try {
207
+ const cfg = JSON.parse(readFileSync(join(cwd, "sun-space.config.json"), "utf8"));
208
+ if (typeof cfg?.vault === "string" && cfg.vault.startsWith("/")) return cfg.vault;
209
+ } catch {}
210
+ return join(home, "Workspace", DEFAULT_VAULT_DIRNAME);
211
+ }
212
+ const VAULT = resolveVaultPath();
186
213
  // src/router-tools.ts
187
214
  const inject = ["tools", "subagents"];
188
- const VAULT = process.env.SUN_VAULT ?? `${process.env.HOME}/Workspace/云顶天宫`;
189
215
  const text = (s) => [{
190
216
  type: "text",
191
217
  text: s
@@ -519,7 +545,7 @@ function apply(ctx) {
519
545
  },
520
546
  cwd: {
521
547
  type: "string",
522
- description: "可选:Worker 的工作目录(绝对路径)。不传则随当前工作区。代码开发等 vault 外任务必传(如 /Users/40huo/Workspace/<repo>)"
548
+ description: "可选:Worker 的工作目录(绝对路径)。不传则随当前工作区。代码开发等 vault 外任务必传(如 ~/Workspace/<repo>)"
523
549
  }
524
550
  },
525
551
  required: ["task_id", "prompt"]
@@ -1,5 +1,6 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { join, resolve, sep } from "node:path";
3
+ import { readFileSync } from "node:fs";
3
4
  // src/vault.ts
4
5
  /**
5
6
  * vault 访问:路径守卫 + frontmatter 解析/序列化。纯函数为主,可单测。
@@ -26,9 +27,34 @@ function resolveWithin(vaultRoot, rel, roots, kind) {
26
27
  function resolveSafe(vaultRoot, rel) {
27
28
  return resolveWithin(vaultRoot, rel, WRITABLE_ROOTS, "writable");
28
29
  }
30
+ // src/vault-path.ts
31
+ /**
32
+ * vault 路径解析——唯一事实源,全插件共享(source/router-tools/worker-vault/worker-watchdog)。
33
+ *
34
+ * 解析优先级:
35
+ * ① 环境变量 SUN_VAULT(启动命令注入,随进程生效)
36
+ * ② 实例启动目录下的 sun-space.config.json 的 vault 字段(持久化配置,重启不丢)
37
+ * ③ 默认约定 ~/Workspace/sun-vault
38
+ *
39
+ * 解析结果同时写入 <实例cwd>/sun-space.json(仅 vault 字段),作为浏览器端(孙学空间)
40
+ * 的发现通道——浏览器读不到进程环境,靠这个文件拿到真实 vault 路径(workspaceFiles
41
+ * 的相对路径读取以会话工作区根为基准,即实例 cwd,两者同目录)。
42
+ *
43
+ * 注意:本文件不携带任何个人路径;个人 vault 位置只存在于①/②(均不入库)。
44
+ */
45
+ const DEFAULT_VAULT_DIRNAME = "sun-vault";
46
+ /** 解析 vault 绝对路径(① env ② 实例目录配置文件 ③ 默认约定)。 */
47
+ function resolveVaultPath(cwd = process.cwd(), home = process.env.HOME ?? "") {
48
+ if (process.env.SUN_VAULT && process.env.SUN_VAULT.trim() !== "") return process.env.SUN_VAULT;
49
+ try {
50
+ const cfg = JSON.parse(readFileSync(join(cwd, "sun-space.config.json"), "utf8"));
51
+ if (typeof cfg?.vault === "string" && cfg.vault.startsWith("/")) return cfg.vault;
52
+ } catch {}
53
+ return join(home, "Workspace", DEFAULT_VAULT_DIRNAME);
54
+ }
55
+ const VAULT = resolveVaultPath();
29
56
  // src/worker-vault.ts
30
57
  const inject = ["tools"];
31
- const VAULT = process.env.SUN_VAULT ?? `${process.env.HOME}/Workspace/云顶天宫`;
32
58
  const TASK_ID = /^T-\d{8}-\d{2}$/;
33
59
  /** 纯函数:拼装受控产物路径;非法输入抛 VaultPathError。可单测。 */
34
60
  function artifactPath(taskId, filename) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-sun-space",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "description": "Sun Space:DeepSeek Harness 个人超智能体插件——Router/Worker 双预设工具白名单、钉钉待办轮询、Obsidian 知识库落库、会话工作台与定时任务管理。",
6
6
  "exports": {
package/src/client.js CHANGED
@@ -17,7 +17,7 @@ window.__ModuleLoader__.load({
17
17
  let hostCtx = null
18
18
 
19
19
  const PANEL_ID = 'sun-space'
20
- const VAULT_DIRNAME = '云顶天宫' // vault 目录名约定;绝对路径动态发现,见 resolveVault
20
+ const VAULT_DIRNAME = 'sun-vault' // vault 目录名约定;绝对路径动态发现,见 resolveVault
21
21
  // 架构 §4.1 不变量:呈现层不得持有会话 id / vault 绝对路径常量(Router 会话会轮换,机器会换)。
22
22
  // 会话解析链:session/list(sun-router 会话)→ 90-Meta/system/state.json 裁决 → updatedAt 最新兜底。
23
23
  // vault 解析链:会话 cwd 推 HOME → 约定布局探测 state.json → state.json 的 vault 字段裁决(跨机自愈)。
@@ -96,13 +96,20 @@ window.__ModuleLoader__.load({
96
96
  }).then(v => v.text || '')
97
97
 
98
98
  // ===== vault 绝对路径发现(跨机器;呈现层不持常量,架构 §4.1 同款不变量)=====
99
- // 链:会话 cwd 推 HOME → 约定布局 <HOME>/Workspace/云顶天宫 探测 state.json → state.json.vault 字段裁决。
99
+ // 链:会话 cwd 推 HOME → 约定布局 <HOME>/Workspace/sun-vault 探测 state.json → state.json.vault 字段裁决。
100
100
  // state.json.vault 由 Router 自登记/晨报自检维护(server 端 VAULT 是唯一事实源)。
101
101
  async function resolveVault() {
102
102
  const v = await gw('session/list', {})
103
103
  const items = Array.isArray(v?.items) ? v.items : Object.values(v?.items ?? v ?? {})
104
104
  const scope = items.find(s => s?.projections?.values?.agentPreset === 'sun-router')?.sessionId ?? items[0]?.sessionId
105
105
  if (!scope) return null
106
+ // ① 插件落盘的运行配置(实例 cwd 的 sun-space.json;相对路径以会话工作区根解析,即实例 cwd)
107
+ try {
108
+ const raw = await readVaultFile(scope, 'sun-space.json', 4)
109
+ const cfg = JSON.parse(raw)
110
+ if (cfg?.vault && cfg.vault.startsWith('/')) return cfg.vault
111
+ } catch { /* 无发现文件 → 走约定探测 */ }
112
+ // ② 约定布局探测(默认 ~/Workspace/sun-vault;自定义 vault 路径由①覆盖)
106
113
  const homes = [...new Set(items.map(s => String(s.cwd || '')).filter(c => c.startsWith('/')).map(c => c.split('/').slice(0, 3).join('/')))]
107
114
  const candidates = [...new Set(homes.map(h => `${h}/Workspace/${VAULT_DIRNAME}`))]
108
115
  for (const cand of candidates) {
@@ -380,7 +387,7 @@ window.__ModuleLoader__.load({
380
387
  const steps = [
381
388
  { n: 1, ok: checks.presets, title: '确认依赖插件', desc: checks.presets ? '智能体协作 / 子智能体插件已启用' : '打开插件面板,启用 sun-space / 智能体协作相关插件后重启实例', action: checks.presets ? null : 'plugins' },
382
389
  { n: 2, ok: !!checks.routerSession, title: '创建 Router 会话', desc: checks.routerSession ? `已就绪:${checks.routerSession.slice(0, 28)}…` : '一键创建 sun-router 预设会话并自动登记(孙学空间与定时任务都挂在这上面)', action: checks.presets && !checks.routerSession ? 'create-router' : null },
383
- { n: 3, ok: checks.vault, title: '知识库就绪', desc: checks.vault ? `已就绪:${checks.vaultPath}` : `用 Obsidian 打开(或创建)~/Workspace/云顶天宫 并放好 90-Meta 骨架;自定义位置让 Router 把绝对路径写进 state.json 的 vault 字段`, action: null },
390
+ { n: 3, ok: checks.vault, title: '知识库就绪', desc: checks.vault ? `已就绪:${checks.vaultPath}` : `用 Obsidian 打开(或创建)~/Workspace/sun-vault 并放好 90-Meta 骨架;自定义位置让 Router 把绝对路径写进 state.json 的 vault 字段`, action: null },
384
391
  ]
385
392
  const allOk = steps.every(x => x.ok)
386
393
  return h('div', null, [