dsh-sun-space 0.2.7 → 0.2.9
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 +68 -20
- package/lib/router-tools.mjs +25 -16
- package/lib/worker-vault.mjs +25 -16
- package/package.json +1 -1
- package/src/client.js +23 -14
package/lib/index.mjs
CHANGED
|
@@ -18,28 +18,32 @@ var __exportAll = (all, no_symbols) => {
|
|
|
18
18
|
/**
|
|
19
19
|
* vault 路径解析——唯一事实源,全插件共享(source/router-tools/worker-vault/worker-watchdog)。
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* 解析优先级(vaultPath() 每次调用重读,运行期变更即时生效):
|
|
22
22
|
* ① 环境变量 SUN_VAULT(启动命令注入,随进程生效)
|
|
23
23
|
* ② ~/.dsh/state/sun-space/config.json 的 vault 字段(用户手写,持久化,不入库)
|
|
24
|
-
* ③
|
|
24
|
+
* ③ ~/.dsh/state/sun-space/state.json 的 vault 字段(Router 会话创建时插件自动登记 = 用户选定的工作区目录)
|
|
25
|
+
* ④ 默认约定 ~/Workspace/sun-vault
|
|
25
26
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* ③ 的设计动机:用户的 vault 就是他在 DSH 里选定的那个目录——Router 会话创建时
|
|
28
|
+
* 插件自动把该会话 cwd 登记为 vault 根(registerVaultRootFromSession),无需任何
|
|
29
|
+
* 手工配置。①② 供自定义/覆盖;④ 仅在全新裸环境兜底。
|
|
29
30
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
31
|
+
* 解析结果写回 state.json,作为浏览器端(孙学空间)的发现通道——浏览器经
|
|
32
|
+
* workspaceFiles/read 以绝对路径读取该文件(工作区外绝对路径读取被宿主允许)。
|
|
33
|
+
*
|
|
34
|
+
* 目录约定沿用 DSH 官方先例:~/.dsh/state/<插件名>/(session-superagent 同款)。
|
|
35
|
+
* 本文件不携带任何个人路径;个人 vault 位置只存在于①②③(均不入库)。
|
|
32
36
|
*/
|
|
33
37
|
const DEFAULT_VAULT_DIRNAME = "sun-vault";
|
|
34
38
|
/** 插件自有状态目录(<DSH_HOME 或 ~/>/.dsh/state/sun-space/),沿用官方 state/<插件名> 约定。
|
|
35
39
|
* 跟随 DSH_HOME:多实例(隔离 HOME 的测试环境)之间状态互不串扰。 */
|
|
36
40
|
const stateDir = () => join(process.env.DSH_HOME ?? homedir(), ".dsh", "state", "sun-space");
|
|
37
|
-
/**
|
|
38
|
-
function computeVaultPath(envValue, configJson, home = homedir()) {
|
|
41
|
+
/** 纯函数:四级优先解析(测试与 vaultPath 共用)。 */
|
|
42
|
+
function computeVaultPath(envValue, configJson, stateJson, home = homedir()) {
|
|
39
43
|
if (envValue && envValue.trim() !== "") return envValue;
|
|
40
|
-
try {
|
|
41
|
-
const
|
|
42
|
-
if (typeof
|
|
44
|
+
for (const raw of [configJson, stateJson]) try {
|
|
45
|
+
const parsed = JSON.parse(raw ?? "");
|
|
46
|
+
if (typeof parsed?.vault === "string" && parsed.vault.startsWith("/")) return parsed.vault;
|
|
43
47
|
} catch {}
|
|
44
48
|
return join(home, "Workspace", DEFAULT_VAULT_DIRNAME);
|
|
45
49
|
}
|
|
@@ -48,32 +52,67 @@ let cached = {
|
|
|
48
52
|
key: "",
|
|
49
53
|
value: ""
|
|
50
54
|
};
|
|
51
|
-
/**
|
|
55
|
+
/** 运行期解析:每次调用重读状态目录(60s 微缓存防抖),登记/手改后即时生效。 */
|
|
52
56
|
function vaultPath(now = Date.now()) {
|
|
53
57
|
const dir = stateDir();
|
|
54
58
|
let configJson;
|
|
59
|
+
let stateJson;
|
|
55
60
|
try {
|
|
56
61
|
configJson = readFileSync(join(dir, "config.json"), "utf8");
|
|
57
62
|
} catch {}
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
try {
|
|
64
|
+
stateJson = readFileSync(join(dir, "state.json"), "utf8");
|
|
65
|
+
} catch {}
|
|
66
|
+
const key = `${configJson ?? ""}|${stateJson ?? ""}`;
|
|
67
|
+
if (now - cached.at < 6e4 && cached.key === key) return cached.value;
|
|
68
|
+
const value = computeVaultPath(process.env.SUN_VAULT, configJson, stateJson);
|
|
60
69
|
cached = {
|
|
61
70
|
at: now,
|
|
62
|
-
key
|
|
71
|
+
key,
|
|
63
72
|
value
|
|
64
73
|
};
|
|
65
74
|
return value;
|
|
66
75
|
}
|
|
67
76
|
vaultPath();
|
|
77
|
+
/**
|
|
78
|
+
* Router 会话创建时登记 vault 根("当前目录作为 vault"语义的落点)。
|
|
79
|
+
* 仅在更高优先级来源(env/config/state)均未设置时才登记首个值——
|
|
80
|
+
* 多 Router 并存或重复创建时第一个登记者生效。
|
|
81
|
+
* 尽力而为:任何失败静默退场(最坏是回退到约定路径)。
|
|
82
|
+
*/
|
|
83
|
+
function registerVaultRootFromSession(cwd, now = /* @__PURE__ */ new Date()) {
|
|
84
|
+
if (!cwd || !cwd.startsWith("/")) return false;
|
|
85
|
+
if (process.env.SUN_VAULT?.trim()) return false;
|
|
86
|
+
try {
|
|
87
|
+
const dir = stateDir();
|
|
88
|
+
mkdirSync(dir, { recursive: true });
|
|
89
|
+
const p = join(dir, "state.json");
|
|
90
|
+
let state = {};
|
|
91
|
+
try {
|
|
92
|
+
state = JSON.parse(readFileSync(p, "utf8"));
|
|
93
|
+
} catch {}
|
|
94
|
+
if (state.vault && state.vault.startsWith("/")) return false;
|
|
95
|
+
state.vault = cwd;
|
|
96
|
+
state.updatedAt = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}T${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
|
|
97
|
+
writeFileSync(p, JSON.stringify(state, null, 2), "utf8");
|
|
98
|
+
return true;
|
|
99
|
+
} catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
68
103
|
/** 把解析结果写回状态目录的 state.json(apply 时调用,尽力而为),供客户端发现。 */
|
|
69
104
|
function publishVaultState(now = /* @__PURE__ */ new Date()) {
|
|
70
105
|
try {
|
|
71
106
|
const dir = stateDir();
|
|
72
107
|
mkdirSync(dir, { recursive: true });
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
108
|
+
const p = join(dir, "state.json");
|
|
109
|
+
let state = {};
|
|
110
|
+
try {
|
|
111
|
+
state = JSON.parse(readFileSync(p, "utf8"));
|
|
112
|
+
} catch {}
|
|
113
|
+
state.vault = vaultPath(now.getTime());
|
|
114
|
+
state.updatedAt = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}T${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
|
|
115
|
+
writeFileSync(p, JSON.stringify(state, null, 2), "utf8");
|
|
77
116
|
} catch {}
|
|
78
117
|
}
|
|
79
118
|
// src/dws.ts
|
|
@@ -493,5 +532,14 @@ function apply(ctx) {
|
|
|
493
532
|
publishVaultState();
|
|
494
533
|
ctx.plugin(source_exports);
|
|
495
534
|
ctx.plugin(worker_watchdog_exports);
|
|
535
|
+
try {
|
|
536
|
+
ctx.on("agent/created", (...args) => {
|
|
537
|
+
const agent = args[0]?.agent;
|
|
538
|
+
const header = agent?.session?.header;
|
|
539
|
+
if (header?.agentPreset !== "sun-router") return;
|
|
540
|
+
const cwd = header.cwd ?? agent?.cwd;
|
|
541
|
+
registerVaultRootFromSession(typeof cwd === "string" ? cwd : void 0);
|
|
542
|
+
});
|
|
543
|
+
} catch {}
|
|
496
544
|
}
|
|
497
545
|
export { apply, inject, name };
|
package/lib/router-tools.mjs
CHANGED
|
@@ -189,28 +189,32 @@ async function dingSelf(userId, content, type = "app") {
|
|
|
189
189
|
/**
|
|
190
190
|
* vault 路径解析——唯一事实源,全插件共享(source/router-tools/worker-vault/worker-watchdog)。
|
|
191
191
|
*
|
|
192
|
-
*
|
|
192
|
+
* 解析优先级(vaultPath() 每次调用重读,运行期变更即时生效):
|
|
193
193
|
* ① 环境变量 SUN_VAULT(启动命令注入,随进程生效)
|
|
194
194
|
* ② ~/.dsh/state/sun-space/config.json 的 vault 字段(用户手写,持久化,不入库)
|
|
195
|
-
* ③
|
|
195
|
+
* ③ ~/.dsh/state/sun-space/state.json 的 vault 字段(Router 会话创建时插件自动登记 = 用户选定的工作区目录)
|
|
196
|
+
* ④ 默认约定 ~/Workspace/sun-vault
|
|
196
197
|
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
198
|
+
* ③ 的设计动机:用户的 vault 就是他在 DSH 里选定的那个目录——Router 会话创建时
|
|
199
|
+
* 插件自动把该会话 cwd 登记为 vault 根(registerVaultRootFromSession),无需任何
|
|
200
|
+
* 手工配置。①② 供自定义/覆盖;④ 仅在全新裸环境兜底。
|
|
200
201
|
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
202
|
+
* 解析结果写回 state.json,作为浏览器端(孙学空间)的发现通道——浏览器经
|
|
203
|
+
* workspaceFiles/read 以绝对路径读取该文件(工作区外绝对路径读取被宿主允许)。
|
|
204
|
+
*
|
|
205
|
+
* 目录约定沿用 DSH 官方先例:~/.dsh/state/<插件名>/(session-superagent 同款)。
|
|
206
|
+
* 本文件不携带任何个人路径;个人 vault 位置只存在于①②③(均不入库)。
|
|
203
207
|
*/
|
|
204
208
|
const DEFAULT_VAULT_DIRNAME = "sun-vault";
|
|
205
209
|
/** 插件自有状态目录(<DSH_HOME 或 ~/>/.dsh/state/sun-space/),沿用官方 state/<插件名> 约定。
|
|
206
210
|
* 跟随 DSH_HOME:多实例(隔离 HOME 的测试环境)之间状态互不串扰。 */
|
|
207
211
|
const stateDir = () => join(process.env.DSH_HOME ?? homedir(), ".dsh", "state", "sun-space");
|
|
208
|
-
/**
|
|
209
|
-
function computeVaultPath(envValue, configJson, home = homedir()) {
|
|
212
|
+
/** 纯函数:四级优先解析(测试与 vaultPath 共用)。 */
|
|
213
|
+
function computeVaultPath(envValue, configJson, stateJson, home = homedir()) {
|
|
210
214
|
if (envValue && envValue.trim() !== "") return envValue;
|
|
211
|
-
try {
|
|
212
|
-
const
|
|
213
|
-
if (typeof
|
|
215
|
+
for (const raw of [configJson, stateJson]) try {
|
|
216
|
+
const parsed = JSON.parse(raw ?? "");
|
|
217
|
+
if (typeof parsed?.vault === "string" && parsed.vault.startsWith("/")) return parsed.vault;
|
|
214
218
|
} catch {}
|
|
215
219
|
return join(home, "Workspace", DEFAULT_VAULT_DIRNAME);
|
|
216
220
|
}
|
|
@@ -219,18 +223,23 @@ let cached = {
|
|
|
219
223
|
key: "",
|
|
220
224
|
value: ""
|
|
221
225
|
};
|
|
222
|
-
/**
|
|
226
|
+
/** 运行期解析:每次调用重读状态目录(60s 微缓存防抖),登记/手改后即时生效。 */
|
|
223
227
|
function vaultPath(now = Date.now()) {
|
|
224
228
|
const dir = stateDir();
|
|
225
229
|
let configJson;
|
|
230
|
+
let stateJson;
|
|
226
231
|
try {
|
|
227
232
|
configJson = readFileSync(join(dir, "config.json"), "utf8");
|
|
228
233
|
} catch {}
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
try {
|
|
235
|
+
stateJson = readFileSync(join(dir, "state.json"), "utf8");
|
|
236
|
+
} catch {}
|
|
237
|
+
const key = `${configJson ?? ""}|${stateJson ?? ""}`;
|
|
238
|
+
if (now - cached.at < 6e4 && cached.key === key) return cached.value;
|
|
239
|
+
const value = computeVaultPath(process.env.SUN_VAULT, configJson, stateJson);
|
|
231
240
|
cached = {
|
|
232
241
|
at: now,
|
|
233
|
-
key
|
|
242
|
+
key,
|
|
234
243
|
value
|
|
235
244
|
};
|
|
236
245
|
return value;
|
package/lib/worker-vault.mjs
CHANGED
|
@@ -32,28 +32,32 @@ function resolveSafe(vaultRoot, rel) {
|
|
|
32
32
|
/**
|
|
33
33
|
* vault 路径解析——唯一事实源,全插件共享(source/router-tools/worker-vault/worker-watchdog)。
|
|
34
34
|
*
|
|
35
|
-
*
|
|
35
|
+
* 解析优先级(vaultPath() 每次调用重读,运行期变更即时生效):
|
|
36
36
|
* ① 环境变量 SUN_VAULT(启动命令注入,随进程生效)
|
|
37
37
|
* ② ~/.dsh/state/sun-space/config.json 的 vault 字段(用户手写,持久化,不入库)
|
|
38
|
-
* ③
|
|
38
|
+
* ③ ~/.dsh/state/sun-space/state.json 的 vault 字段(Router 会话创建时插件自动登记 = 用户选定的工作区目录)
|
|
39
|
+
* ④ 默认约定 ~/Workspace/sun-vault
|
|
39
40
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
41
|
+
* ③ 的设计动机:用户的 vault 就是他在 DSH 里选定的那个目录——Router 会话创建时
|
|
42
|
+
* 插件自动把该会话 cwd 登记为 vault 根(registerVaultRootFromSession),无需任何
|
|
43
|
+
* 手工配置。①② 供自定义/覆盖;④ 仅在全新裸环境兜底。
|
|
43
44
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
45
|
+
* 解析结果写回 state.json,作为浏览器端(孙学空间)的发现通道——浏览器经
|
|
46
|
+
* workspaceFiles/read 以绝对路径读取该文件(工作区外绝对路径读取被宿主允许)。
|
|
47
|
+
*
|
|
48
|
+
* 目录约定沿用 DSH 官方先例:~/.dsh/state/<插件名>/(session-superagent 同款)。
|
|
49
|
+
* 本文件不携带任何个人路径;个人 vault 位置只存在于①②③(均不入库)。
|
|
46
50
|
*/
|
|
47
51
|
const DEFAULT_VAULT_DIRNAME = "sun-vault";
|
|
48
52
|
/** 插件自有状态目录(<DSH_HOME 或 ~/>/.dsh/state/sun-space/),沿用官方 state/<插件名> 约定。
|
|
49
53
|
* 跟随 DSH_HOME:多实例(隔离 HOME 的测试环境)之间状态互不串扰。 */
|
|
50
54
|
const stateDir = () => join(process.env.DSH_HOME ?? homedir(), ".dsh", "state", "sun-space");
|
|
51
|
-
/**
|
|
52
|
-
function computeVaultPath(envValue, configJson, home = homedir()) {
|
|
55
|
+
/** 纯函数:四级优先解析(测试与 vaultPath 共用)。 */
|
|
56
|
+
function computeVaultPath(envValue, configJson, stateJson, home = homedir()) {
|
|
53
57
|
if (envValue && envValue.trim() !== "") return envValue;
|
|
54
|
-
try {
|
|
55
|
-
const
|
|
56
|
-
if (typeof
|
|
58
|
+
for (const raw of [configJson, stateJson]) try {
|
|
59
|
+
const parsed = JSON.parse(raw ?? "");
|
|
60
|
+
if (typeof parsed?.vault === "string" && parsed.vault.startsWith("/")) return parsed.vault;
|
|
57
61
|
} catch {}
|
|
58
62
|
return join(home, "Workspace", DEFAULT_VAULT_DIRNAME);
|
|
59
63
|
}
|
|
@@ -62,18 +66,23 @@ let cached = {
|
|
|
62
66
|
key: "",
|
|
63
67
|
value: ""
|
|
64
68
|
};
|
|
65
|
-
/**
|
|
69
|
+
/** 运行期解析:每次调用重读状态目录(60s 微缓存防抖),登记/手改后即时生效。 */
|
|
66
70
|
function vaultPath(now = Date.now()) {
|
|
67
71
|
const dir = stateDir();
|
|
68
72
|
let configJson;
|
|
73
|
+
let stateJson;
|
|
69
74
|
try {
|
|
70
75
|
configJson = readFileSync(join(dir, "config.json"), "utf8");
|
|
71
76
|
} catch {}
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
try {
|
|
78
|
+
stateJson = readFileSync(join(dir, "state.json"), "utf8");
|
|
79
|
+
} catch {}
|
|
80
|
+
const key = `${configJson ?? ""}|${stateJson ?? ""}`;
|
|
81
|
+
if (now - cached.at < 6e4 && cached.key === key) return cached.value;
|
|
82
|
+
const value = computeVaultPath(process.env.SUN_VAULT, configJson, stateJson);
|
|
74
83
|
cached = {
|
|
75
84
|
at: now,
|
|
76
|
-
key
|
|
85
|
+
key,
|
|
77
86
|
value
|
|
78
87
|
};
|
|
79
88
|
return value;
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -130,9 +130,11 @@ window.__ModuleLoader__.load({
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
// ===== Router 会话解析(架构 §4.1 不变量:会话会轮换,呈现层只认 vault state.json + 动态发现)=====
|
|
133
|
-
async function resolveRouterSession(vault) {
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
async function resolveRouterSession(vault, items) {
|
|
134
|
+
if (!items) {
|
|
135
|
+
const v = await gw('session/list', {})
|
|
136
|
+
items = Array.isArray(v?.items) ? v.items : Object.values(v?.items ?? v ?? {})
|
|
137
|
+
}
|
|
136
138
|
// 注意:cwd 是"工作区分桶路径"(实例 boot cwd),不是 vault——过滤只看预设(踩坑 5 延伸)
|
|
137
139
|
const candidates = items.filter(s => s?.projections?.values?.agentPreset === 'sun-router')
|
|
138
140
|
if (!candidates.length) return null
|
|
@@ -151,7 +153,7 @@ window.__ModuleLoader__.load({
|
|
|
151
153
|
|
|
152
154
|
// ===== 初始化检查(在任何会话的 tab 上都能跑;① 用当前会话作 workspaceFiles scope)=====
|
|
153
155
|
async function runInitChecks(currentSessionId) {
|
|
154
|
-
const c = { vault: false, presets: false, routerSession: null, vaultPath: null, notes: [] }
|
|
156
|
+
const c = { vault: false, presets: false, routerSession: null, vaultPath: null, currentCwd: null, notes: [] }
|
|
155
157
|
// ① 知识库:vault 路径动态发现 + runbook 探测
|
|
156
158
|
const vault = await resolveVault()
|
|
157
159
|
c.vaultPath = vault
|
|
@@ -176,9 +178,14 @@ window.__ModuleLoader__.load({
|
|
|
176
178
|
c.presets = false
|
|
177
179
|
c.notes.push('预设服务不可达 → 确认 Harness 实例在线、插件已启用')
|
|
178
180
|
}
|
|
179
|
-
// ③ Router
|
|
181
|
+
// ③ Router 会话:动态解析 + 首个 sun-router 会话创建时自动登记其 cwd 为 vault 根
|
|
182
|
+
// ("当前目录作为 vault"语义的插件层落点;env/config 更高优先级不受影响)
|
|
180
183
|
try {
|
|
181
|
-
|
|
184
|
+
const sl = await gw('session/list', {})
|
|
185
|
+
const items = Array.isArray(sl?.items) ? sl.items : Object.values(sl?.items ?? {})
|
|
186
|
+
c.currentCwd = (items.find(s => s.sessionId === currentSessionId) ?? {}).cwd ?? null
|
|
187
|
+
// vault 根登记由宿主插件在 sun-router 会话创建时自动完成(index.ts agent/created 钩子)
|
|
188
|
+
c.routerSession = vault ? await resolveRouterSession(vault, items) : null
|
|
182
189
|
if (!c.routerSession) c.notes.push('Router 会话不存在 → 点下方「创建 Router 会话」(sun-router 预设,随当前工作区),创建后自动登记 state.json')
|
|
183
190
|
} catch {
|
|
184
191
|
c.notes.push('会话列表不可达 → 重试或检查实例')
|
|
@@ -186,9 +193,10 @@ window.__ModuleLoader__.load({
|
|
|
186
193
|
return c
|
|
187
194
|
}
|
|
188
195
|
|
|
189
|
-
async function createRouterSession() {
|
|
190
|
-
//
|
|
191
|
-
|
|
196
|
+
async function createRouterSession(cwd) {
|
|
197
|
+
// cwd 可选:一键初始化时传当前会话的工作区目录——Router 会话落在用户选的工作区
|
|
198
|
+
//(session/create 带 cwd 还会自动注册该工作区);不传则随宿主项目目录(踩坑 5)
|
|
199
|
+
return gw('session/create', cwd ? { cwd, agentPreset: 'sun-router' } : { agentPreset: 'sun-router' })
|
|
192
200
|
}
|
|
193
201
|
|
|
194
202
|
|
|
@@ -252,19 +260,20 @@ window.__ModuleLoader__.load({
|
|
|
252
260
|
// 插件运行期动态解析(vaultPath())保证它写入"当前生效"的知识库路径。
|
|
253
261
|
async function createRouterAndInit(checks, onRetry) {
|
|
254
262
|
try {
|
|
255
|
-
const
|
|
263
|
+
const cwd = checks.currentCwd
|
|
264
|
+
const v = await createRouterSession(cwd)
|
|
256
265
|
const sid = typeof v === 'string' ? v : (v?.sessionId ?? v)
|
|
257
266
|
if (!sid) return
|
|
258
267
|
await gw('session/prompt', {
|
|
259
268
|
requestId: 'sun-init-' + Date.now(),
|
|
260
269
|
sessionId: sid,
|
|
261
270
|
mode: 'queue',
|
|
262
|
-
content: [{ type: 'text', text: `【孙学空间初始化】你是新环境的 Sun Router(你的会话 id:${sid}
|
|
263
|
-
1) 用 sun_vault_write
|
|
271
|
+
content: [{ type: 'text', text: `【孙学空间初始化】你是新环境的 Sun Router(你的会话 id:${sid})。你的工作目录即知识库根(vault)。按顺序完成:
|
|
272
|
+
1) 用 sun_vault_write 创建知识库骨架(vault 即你的工作目录,已在会话创建时自动登记):
|
|
264
273
|
- 90-Meta/schemas.md:frontmatter 契约最小集(通用字段 type/id/status/created/updated;task 的 status 枚举 proposed|running|need-confirm|done|blocked|dropped;写入纪律:Journal 由 Router 独占、日期一律本地时间 YYYY-MM-DDTHH:mm 不带时区后缀、结论必注出处)
|
|
265
274
|
- 90-Meta/runbook.md:初始版(# Sun 行为手册 + v0.1 版本行 + §1 角色:Router 只分派不执行 + §2 沟通规范:IM ≤100 字结论先行 + §3 打扰分级:info 攒批/ask 立即/urgent 加 DING)
|
|
266
275
|
- 90-Meta/memory.md:初始版(# 关于用户,待填充)
|
|
267
|
-
2) 用 sun_vault_write 写 90-Meta/system/state.json:{"routerSession": "${sid}", "vault": "
|
|
276
|
+
2) 用 sun_vault_write 写 90-Meta/system/state.json:{"routerSession": "${sid}", "vault": "<你的工作目录绝对路径>", "updatedAt": "<本地时间 YYYY-MM-DDTHH:mm>"}(自登记,供孙学空间发现与轮换机制使用)
|
|
268
277
|
3) 完成后列出生成的文件清单与知识库路径。` }],
|
|
269
278
|
clientTimeZone: 'Asia/Shanghai',
|
|
270
279
|
})
|
|
@@ -403,7 +412,7 @@ window.__ModuleLoader__.load({
|
|
|
403
412
|
function OnboardPanel({ checks, currentSessionId, onRetry }) {
|
|
404
413
|
const steps = [
|
|
405
414
|
{ n: 1, ok: checks.presets, title: '确认依赖插件', desc: checks.presets ? '智能体协作 / 子智能体插件已启用' : '打开插件面板,启用 sun-space / 智能体协作相关插件后重启实例', action: checks.presets ? null : 'plugins' },
|
|
406
|
-
{ n: 2, ok: !!checks.routerSession, title: '一键初始化(Router 会话 + 知识库)', desc: checks.routerSession ? `已就绪:${checks.routerSession.slice(0, 28)}…` : '
|
|
415
|
+
{ n: 2, ok: !!checks.routerSession, title: '一键初始化(Router 会话 + 知识库)', desc: checks.routerSession ? `已就绪:${checks.routerSession.slice(0, 28)}…` : `一键完成:以当前工作区目录${checks.currentCwd ? `(${checks.currentCwd})` : ''}为知识库根 → 创建 Router 会话 → 写入 90-Meta 骨架 → 自登记(仅 ~/.dsh 登记需一次批准)`, action: checks.presets && !checks.routerSession ? 'create-router' : null },
|
|
407
416
|
{ n: 3, ok: checks.vault, title: '知识库就绪', desc: checks.vault ? `已就绪:${checks.vaultPath}` : (checks.routerSession ? '知识库骨架缺失 → 点下方按钮让 Router 补建' : '完成第②步后自动创建'), action: checks.presets && checks.routerSession && !checks.vault ? 'init-skeleton' : null },
|
|
408
417
|
]
|
|
409
418
|
const allOk = steps.every(x => x.ok)
|