Files
dsh_ai1net_server/归档/poc-dsh-local/patch-seed-workspace.py
T

88 lines
3.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# 档案 24 后续:预置默认工作区(编辑器要求"必须选工作区"才能开会话 → 平台直接种 ws)
# 用法: python3 patch-seed-workspace.py /opt/dshs
import io
import os
import sys
root = sys.argv[1] if len(sys.argv) > 1 else '.'
p = os.path.join(root, 'src/supervisor/orchestrator.ts')
s = io.open(p, encoding='utf-8').read()
def sub(old, new, cnt=1):
global s
assert old in s, 'anchor not found:\n' + old[:200]
s = s.replace(old, new, cnt)
# 1) 补 fs 导入
sub(
"import { chmodSync, mkdirSync, writeFileSync } from 'node:fs'",
"import { chmodSync, chownSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'",
)
# 2) 在 spawnInstance 里对 main 预置工作区
sub(
""" const map = role === 'main' ? this.mains : this.watchdogs
map.set(userId, instance)""",
""" const map = role === 'main' ? this.mains : this.watchdogs
map.set(userId, instance)
// 档案 24 后续:main 启动前预置默认工作区(编辑器要求"必须选择工作区"才能开始会话;
// 平台直接把用户 ws 种进 workspace 存储 → 用户开箱即用、且 UI 只显示短标题而非完整路径)。
if (isMain) await this.seedDefaultWorkspace(userId)""",
)
# 3) 新增 seedDefaultWorkspace 方法(放在 writePatch 之前)
sub(
""" /** Materialize the rendered patch so the dsh CLI can `--patch <file>` it.""",
""" /**
* 预置默认工作区(幂等,仅在工作区列表为空时写入):
* 把 `<userRoot>/ws` 以短标题「我的工作区」写进 `<home>/storages/workspace.json`,
* 使新用户/清空后无需手动选择工作区即可开始会话;已有工作区时**不覆盖**用户现状。
* 失败不阻断启动(只记日志)。
*/
private async seedDefaultWorkspace(userId: string): Promise<void> {
const root = userRoot(this.config.dataRoot, userId)
const dir = join(homeRoot(root), 'storages')
const file = join(dir, 'workspace.json')
try {
mkdirSync(dir, { recursive: true })
let existing: { global?: { workspaceIds?: unknown } } | undefined
try {
existing = JSON.parse(readFileSync(file, 'utf8')) as { global?: { workspaceIds?: unknown } }
} catch {
existing = undefined
}
const ids = existing?.global?.workspaceIds
if (Array.isArray(ids) && ids.length > 0) return // 已有工作区 → 尊重用户现状
const ws = workspaceRoot(root)
const id = randomUUID()
const now = new Date().toISOString()
const seed = {
unit: { name: 'workspace', version: 2 },
global: { initialized: true, workspaceIds: [id], archivedSessionIds: [] },
tables: {
workspaces: {
[id]: { path: ws, title: '我的工作区', sessionIds: [], createdAt: now, updatedAt: now },
},
},
}
writeFileSync(file, JSON.stringify(seed, null, 2) + '\\n')
const uid = await this.resolveUid(userId)
chownSync(file, uid, uid) // 实例以该 uid 运行,需可读写
chownSync(dir, uid, uid)
process.stderr.write(`[seed-workspace] ${userId} → ${ws}\\n`)
} catch (err) {
process.stderr.write(
`[seed-workspace] failed for ${userId}: ${err instanceof Error ? err.message : String(err)}\\n`,
)
}
}
/** Materialize the rendered patch so the dsh CLI can `--patch <file>` it.""",
)
io.open(p, 'w', encoding='utf-8', newline='').write(s)
print('patched: fs import + spawnInstance 调用 + seedDefaultWorkspace 方法')