dsh-sun-space 0.2.4 → 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/lib/index.mjs +38 -6
- package/lib/router-tools.mjs +28 -2
- package/lib/worker-vault.mjs +27 -1
- package/package.json +1 -1
- package/src/client.js +10 -3
package/lib/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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
|
|
136
|
-
const SNAPSHOT_FILE = `${VAULT
|
|
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
|
}
|
package/lib/router-tools.mjs
CHANGED
|
@@ -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 外任务必传(如
|
|
548
|
+
description: "可选:Worker 的工作目录(绝对路径)。不传则随当前工作区。代码开发等 vault 外任务必传(如 ~/Workspace/<repo>)"
|
|
523
549
|
}
|
|
524
550
|
},
|
|
525
551
|
required: ["task_id", "prompt"]
|
package/lib/worker-vault.mjs
CHANGED
|
@@ -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
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 = '
|
|
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
|
|
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
|
|
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, [
|