@rezti/dsh-rez-suite 0.1.14 → 0.1.16
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/README.md +1 -1
- package/cordis.patch.yml +0 -2
- package/lib/index.js +135 -3
- package/package.json +5 -5
- package/src/boss/mount.ts +38 -0
- package/src/boss/register.ts +18 -0
- package/src/boss/seed.ts +123 -0
- package/src/index.ts +3 -0
- package/templates/boss/money/.agents/skills/boss-money/SKILL.md +6 -0
- package/templates/boss/money/AGENTS.md +58 -0
- package/templates/boss/money/BOOTSTRAP.md +40 -0
- package/templates/boss/money/IDENTITY.md +8 -0
- package/templates/boss/money/MEMORY.md +11 -0
- package/templates/boss/money/PRIORITIES.md +3 -0
- package/templates/boss/money/SOUL.md +6 -0
- package/templates/boss/money/USER.md +8 -0
- package/templates/boss/money/memory/.gitkeep +0 -0
- package/templates/boss/ops/.agents/skills/boss-ops/SKILL.md +6 -0
- package/templates/boss/ops/AGENTS.md +49 -0
- package/templates/boss/ops/BOOTSTRAP.md +23 -0
- package/templates/boss/ops/IDENTITY.md +8 -0
- package/templates/boss/ops/MEMORY.md +9 -0
- package/templates/boss/ops/PRIORITIES.md +3 -0
- package/templates/boss/ops/SOUL.md +5 -0
- package/templates/boss/ops/USER.md +7 -0
- package/templates/boss/ops/memory/.gitkeep +0 -0
- package/templates/boss/product/.agents/skills/boss-product/SKILL.md +6 -0
- package/templates/boss/product/AGENTS.md +40 -0
- package/templates/boss/product/BOOTSTRAP.md +23 -0
- package/templates/boss/product/IDENTITY.md +8 -0
- package/templates/boss/product/MEMORY.md +9 -0
- package/templates/boss/product/PRIORITIES.md +3 -0
- package/templates/boss/product/SOUL.md +5 -0
- package/templates/boss/product/USER.md +7 -0
- package/templates/boss/product/memory/.gitkeep +0 -0
package/README.md
CHANGED
|
@@ -12,4 +12,4 @@ dsh plugin --profile web update @rezti/dsh-rez-suite
|
|
|
12
12
|
|
|
13
13
|
包名是 `@rezti/dsh-rez-suite`,不是 `dsh-rezti-suite`。不要对同一 profile 再单独 add 子包,会重复注册。
|
|
14
14
|
|
|
15
|
-
拆分包(`dsh-rez-odoo` 等)给开发改代码用。Web
|
|
15
|
+
拆分包(`dsh-rez-odoo` 等)给开发改代码用。Web 面板(含微信扫码)暂时仍在本包。老板三室(搞钱 / 产品 / 运营)也在本包内播种并登记侧栏,**不要**再装 `@rezti/dsh-rez-boss-desk`。
|
package/cordis.patch.yml
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
3
|
+
import { dirname, join, relative } from "node:path";
|
|
4
4
|
import { REZ_CREDENTIAL_REFS, REZ_DEFAULT_CONNECTIONS, REZ_SYSTEMS, lastMcpStartError, mergeConnections, secretConfigured, writeManagedCredential } from "@rezti/dsh-rez-sso";
|
|
5
|
-
import { mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { DatabaseSync } from "node:sqlite";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
7
8
|
//#region ../../node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.2/node_modules/@deepseek-ai/cosmokit/lib/index.js
|
|
8
9
|
/** Return true when a value is `null` or `undefined`. */
|
|
9
10
|
function isNullable(value) {
|
|
@@ -7654,6 +7655,135 @@ function rezConfigTool(config) {
|
|
|
7654
7655
|
});
|
|
7655
7656
|
}
|
|
7656
7657
|
//#endregion
|
|
7658
|
+
//#region src/boss/register.ts
|
|
7659
|
+
async function registerBossWorkspaces(registry, rooms) {
|
|
7660
|
+
for (const room of [...rooms].reverse()) await registry.create(room.path, room.folder);
|
|
7661
|
+
}
|
|
7662
|
+
//#endregion
|
|
7663
|
+
//#region src/boss/seed.ts
|
|
7664
|
+
const BOSS_ROOMS = [
|
|
7665
|
+
{
|
|
7666
|
+
id: "money",
|
|
7667
|
+
folder: "搞钱"
|
|
7668
|
+
},
|
|
7669
|
+
{
|
|
7670
|
+
id: "product",
|
|
7671
|
+
folder: "产品"
|
|
7672
|
+
},
|
|
7673
|
+
{
|
|
7674
|
+
id: "ops",
|
|
7675
|
+
folder: "运营"
|
|
7676
|
+
}
|
|
7677
|
+
];
|
|
7678
|
+
/** User-owned files. Re-seeding never overwrites these. */
|
|
7679
|
+
const LIVING_BASENAMES = /* @__PURE__ */ new Set([
|
|
7680
|
+
"USER.md",
|
|
7681
|
+
"MEMORY.md",
|
|
7682
|
+
"PRIORITIES.md",
|
|
7683
|
+
"IDENTITY.md"
|
|
7684
|
+
]);
|
|
7685
|
+
function defaultTemplatesRoot() {
|
|
7686
|
+
const here = fileURLToPath(new URL(".", import.meta.url));
|
|
7687
|
+
const candidates = [
|
|
7688
|
+
join(here, "../templates/boss"),
|
|
7689
|
+
join(here, "../../templates/boss"),
|
|
7690
|
+
join(here, "templates/boss")
|
|
7691
|
+
];
|
|
7692
|
+
for (const dir of candidates) if (existsSync(join(dir, "money"))) return dir;
|
|
7693
|
+
throw new Error("missing boss workspace templates (expected templates/boss/money)");
|
|
7694
|
+
}
|
|
7695
|
+
function seedBossWorkspaces(options) {
|
|
7696
|
+
const templatesRoot = options.templatesRoot ?? defaultTemplatesRoot();
|
|
7697
|
+
mkdirSync(options.destRoot, { recursive: true });
|
|
7698
|
+
return {
|
|
7699
|
+
destRoot: options.destRoot,
|
|
7700
|
+
rooms: BOSS_ROOMS.map((room) => seedRoom(templatesRoot, options.destRoot, room))
|
|
7701
|
+
};
|
|
7702
|
+
}
|
|
7703
|
+
function seedRoom(templatesRoot, destRoot, room) {
|
|
7704
|
+
const src = join(templatesRoot, room.id);
|
|
7705
|
+
const dest = join(destRoot, room.folder);
|
|
7706
|
+
if (!existsSync(src) || !statSync(src).isDirectory()) throw new Error("missing boss workspace template: " + src);
|
|
7707
|
+
const created = !existsSync(join(dest, "AGENTS.md"));
|
|
7708
|
+
const bootstrapGone = existsSync(join(dest, "AGENTS.md")) && !existsSync(join(dest, "BOOTSTRAP.md"));
|
|
7709
|
+
mkdirSync(dest, { recursive: true });
|
|
7710
|
+
const written = [];
|
|
7711
|
+
const skipped = [];
|
|
7712
|
+
for (const abs of listFiles(src)) {
|
|
7713
|
+
const rel = relative(src, abs);
|
|
7714
|
+
const target = join(dest, rel);
|
|
7715
|
+
const base = rel.split(/[/\\]/).pop() ?? rel;
|
|
7716
|
+
const underMemory = rel.split(/[/\\]/)[0] === "memory";
|
|
7717
|
+
if (base === "BOOTSTRAP.md" && bootstrapGone) {
|
|
7718
|
+
skipped.push(rel);
|
|
7719
|
+
continue;
|
|
7720
|
+
}
|
|
7721
|
+
if (LIVING_BASENAMES.has(base) && existsSync(target)) {
|
|
7722
|
+
skipped.push(rel);
|
|
7723
|
+
continue;
|
|
7724
|
+
}
|
|
7725
|
+
if (underMemory && existsSync(target)) {
|
|
7726
|
+
skipped.push(rel);
|
|
7727
|
+
continue;
|
|
7728
|
+
}
|
|
7729
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
7730
|
+
writeFileSync(target, readFileSync(abs));
|
|
7731
|
+
written.push(rel);
|
|
7732
|
+
}
|
|
7733
|
+
return {
|
|
7734
|
+
id: room.id,
|
|
7735
|
+
folder: room.folder,
|
|
7736
|
+
path: dest,
|
|
7737
|
+
created,
|
|
7738
|
+
bootstrapPresent: existsSync(join(dest, "BOOTSTRAP.md")),
|
|
7739
|
+
written,
|
|
7740
|
+
skipped
|
|
7741
|
+
};
|
|
7742
|
+
}
|
|
7743
|
+
function listFiles(root) {
|
|
7744
|
+
const out = [];
|
|
7745
|
+
const walk = (dir) => {
|
|
7746
|
+
for (const name of readdirSync(dir)) {
|
|
7747
|
+
if (name === ".DS_Store") continue;
|
|
7748
|
+
const next = join(dir, name);
|
|
7749
|
+
if (statSync(next).isDirectory()) walk(next);
|
|
7750
|
+
else out.push(next);
|
|
7751
|
+
}
|
|
7752
|
+
};
|
|
7753
|
+
walk(root);
|
|
7754
|
+
return out.sort();
|
|
7755
|
+
}
|
|
7756
|
+
//#endregion
|
|
7757
|
+
//#region src/boss/mount.ts
|
|
7758
|
+
const BOSS_GUIDANCE = [
|
|
7759
|
+
"老板三室已播种并登记为侧栏工作区:~/.dsh/workspaces/搞钱、产品、运营。不必手动「添加工作区」。",
|
|
7760
|
+
"每个文件夹是独立作战室。官方 dsh 会注入该目录 AGENTS.md。",
|
|
7761
|
+
"若该室仍有 BOOTSTRAP.md:本会话先做短问三拍,沉淀到 PRIORITIES.md / MEMORY.md,然后删除 BOOTSTRAP.md。",
|
|
7762
|
+
"已初始化后:读 PRIORITIES.md + MEMORY.md + 今日/昨日 memory/;回答固定四行:结论 → 数字(哪家公司、哪段时间)→ 拍板 1~3 件事 → 未执行任何过账/付款/对外发送。",
|
|
7763
|
+
"微信文件夹仍是收件箱,不要在那边查账或砍 SKU。"
|
|
7764
|
+
].join("");
|
|
7765
|
+
function destRoot(env = process.env) {
|
|
7766
|
+
if (env.REZ_BOSS_WORKSPACES !== void 0 && env.REZ_BOSS_WORKSPACES !== "") return env.REZ_BOSS_WORKSPACES;
|
|
7767
|
+
return join(env.DSH_HOME !== void 0 && env.DSH_HOME !== "" ? env.DSH_HOME : join(homedir(), ".dsh"), "workspaces");
|
|
7768
|
+
}
|
|
7769
|
+
function tryWorkspaceRegistry(ctx) {
|
|
7770
|
+
try {
|
|
7771
|
+
return ctx.get("workspaceRegistry");
|
|
7772
|
+
} catch {
|
|
7773
|
+
return;
|
|
7774
|
+
}
|
|
7775
|
+
}
|
|
7776
|
+
/** Seed files and register official workspaces. Safe when registry is absent. */
|
|
7777
|
+
function mountBossDesk(ctx) {
|
|
7778
|
+
const seeded = seedBossWorkspaces({ destRoot: destRoot() });
|
|
7779
|
+
const registry = tryWorkspaceRegistry(ctx);
|
|
7780
|
+
if (registry === void 0) return;
|
|
7781
|
+
registerBossWorkspaces(registry, seeded.rooms).catch((error) => {
|
|
7782
|
+
const why = error instanceof Error ? error.message : String(error);
|
|
7783
|
+
console.error("[dsh-rez-suite] workspaceRegistry.create failed:", why);
|
|
7784
|
+
});
|
|
7785
|
+
}
|
|
7786
|
+
//#endregion
|
|
7657
7787
|
//#region src/index.ts
|
|
7658
7788
|
const name = "rez-suite";
|
|
7659
7789
|
const inject = [
|
|
@@ -7716,7 +7846,8 @@ const REZ_GUIDANCE = [
|
|
|
7716
7846
|
"密钥:REZ_ODOO_TOKEN、REZ_NEXTCLOUD_PASSWORD、REZ_WECHAT_WEBHOOK、REZ_HA_TOKEN。",
|
|
7717
7847
|
"个人微信(QClaw/ClawBot):打开 设置 → 插件 → ReZ-TI → 微信 扫码,然后直接在微信里说话。消息进入网页左侧「微信」文件夹并延续同一会话,模型跟网页默认。网页归档了再从微信说话会自动恢复到侧栏。发「重启对话」会新开一条可见会话并把旧会话归档。网页端必须开着。不必再跑命令、也不要调用微信 MCP 工具。",
|
|
7718
7848
|
"意图用 rez_set_intent(erp/files/chat/home/auto)。审计用 rez_audit。",
|
|
7719
|
-
"涉及资金、对外发送、设备控制、生产写入时先征得用户批准。"
|
|
7849
|
+
"涉及资金、对外发送、设备控制、生产写入时先征得用户批准。",
|
|
7850
|
+
BOSS_GUIDANCE
|
|
7720
7851
|
].join("");
|
|
7721
7852
|
function normalize(input) {
|
|
7722
7853
|
return mergeConfig(defaultConfig(), input ?? {});
|
|
@@ -7737,6 +7868,7 @@ function delegatedHost(ctx, getConfig) {
|
|
|
7737
7868
|
};
|
|
7738
7869
|
}
|
|
7739
7870
|
function apply(ctx, config) {
|
|
7871
|
+
mountBossDesk(ctx);
|
|
7740
7872
|
let current = () => normalize(config);
|
|
7741
7873
|
const tokens = new TokenManager(joinTokenDb());
|
|
7742
7874
|
const host = delegatedHost(ctx, () => current());
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rezti/dsh-rez-suite",
|
|
3
3
|
"description": "ReZ-TI one-package install for DeepSeek Harness. Update with: dsh plugin --profile web update @rezti/dsh-rez-suite",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.16",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
@@ -38,14 +38,13 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
40
40
|
"zod": "^4.4.3",
|
|
41
|
-
"@rezti/dsh-rez-boss-desk": "0.1.0",
|
|
42
|
-
"@rezti/dsh-rez-ha-bridge": "0.1.7",
|
|
43
41
|
"@rezti/dsh-rez-nextcloud": "0.1.7",
|
|
44
42
|
"@rezti/dsh-rez-odoo": "0.1.7",
|
|
43
|
+
"@rezti/dsh-rez-intent": "0.1.4",
|
|
45
44
|
"@rezti/dsh-rez-sso": "0.1.7",
|
|
46
45
|
"@rezti/dsh-rez-token-manager": "0.1.4",
|
|
47
|
-
"@rezti/dsh-rez-
|
|
48
|
-
"@rezti/dsh-rez-
|
|
46
|
+
"@rezti/dsh-rez-wechat": "0.1.11",
|
|
47
|
+
"@rezti/dsh-rez-ha-bridge": "0.1.7"
|
|
49
48
|
},
|
|
50
49
|
"peerDependencies": {
|
|
51
50
|
"react": "^18.2.0",
|
|
@@ -83,6 +82,7 @@
|
|
|
83
82
|
"lib/**/*.css",
|
|
84
83
|
"src",
|
|
85
84
|
"servers",
|
|
85
|
+
"templates/boss/**/*",
|
|
86
86
|
"cordis.patch.yml",
|
|
87
87
|
"README.md",
|
|
88
88
|
"README.zh.md"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { homedir } from 'node:os'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
4
|
+
import { registerBossWorkspaces, type WorkspaceRegistrar } from './register.ts'
|
|
5
|
+
import { seedBossWorkspaces } from './seed.ts'
|
|
6
|
+
|
|
7
|
+
export const BOSS_GUIDANCE = [
|
|
8
|
+
'老板三室已播种并登记为侧栏工作区:~/.dsh/workspaces/搞钱、产品、运营。不必手动「添加工作区」。',
|
|
9
|
+
'每个文件夹是独立作战室。官方 dsh 会注入该目录 AGENTS.md。',
|
|
10
|
+
'若该室仍有 BOOTSTRAP.md:本会话先做短问三拍,沉淀到 PRIORITIES.md / MEMORY.md,然后删除 BOOTSTRAP.md。',
|
|
11
|
+
'已初始化后:读 PRIORITIES.md + MEMORY.md + 今日/昨日 memory/;回答固定四行:结论 → 数字(哪家公司、哪段时间)→ 拍板 1~3 件事 → 未执行任何过账/付款/对外发送。',
|
|
12
|
+
'微信文件夹仍是收件箱,不要在那边查账或砍 SKU。',
|
|
13
|
+
].join('')
|
|
14
|
+
|
|
15
|
+
function destRoot(env: NodeJS.ProcessEnv = process.env): string {
|
|
16
|
+
if (env.REZ_BOSS_WORKSPACES !== undefined && env.REZ_BOSS_WORKSPACES !== '') return env.REZ_BOSS_WORKSPACES
|
|
17
|
+
const home = env.DSH_HOME !== undefined && env.DSH_HOME !== '' ? env.DSH_HOME : join(homedir(), '.dsh')
|
|
18
|
+
return join(home, 'workspaces')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function tryWorkspaceRegistry(ctx: Context): WorkspaceRegistrar | undefined {
|
|
22
|
+
try {
|
|
23
|
+
return ctx.get('workspaceRegistry') as WorkspaceRegistrar
|
|
24
|
+
} catch {
|
|
25
|
+
return undefined
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Seed files and register official workspaces. Safe when registry is absent. */
|
|
30
|
+
export function mountBossDesk(ctx: Context): void {
|
|
31
|
+
const seeded = seedBossWorkspaces({ destRoot: destRoot() })
|
|
32
|
+
const registry = tryWorkspaceRegistry(ctx)
|
|
33
|
+
if (registry === undefined) return
|
|
34
|
+
void registerBossWorkspaces(registry, seeded.rooms).catch((error: unknown) => {
|
|
35
|
+
const why = error instanceof Error ? error.message : String(error)
|
|
36
|
+
console.error('[dsh-rez-suite] workspaceRegistry.create failed:', why)
|
|
37
|
+
})
|
|
38
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register seeded room directories as official dsh workspaces.
|
|
3
|
+
* `workspaceRegistry.create` is idempotent: same canonical path returns the
|
|
4
|
+
* existing record. New records are prepended, so we register in reverse to
|
|
5
|
+
* keep 搞钱 → 产品 → 运营 at the top of the sidebar.
|
|
6
|
+
*/
|
|
7
|
+
export interface WorkspaceRegistrar {
|
|
8
|
+
create(path: string, title?: string): Promise<unknown>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function registerBossWorkspaces(
|
|
12
|
+
registry: WorkspaceRegistrar,
|
|
13
|
+
rooms: ReadonlyArray<{ path: string; folder: string }>,
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
for (const room of [...rooms].reverse()) {
|
|
16
|
+
await registry.create(room.path, room.folder)
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/boss/seed.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, relative } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
export const BOSS_ROOMS = [
|
|
6
|
+
{ id: 'money', folder: '搞钱' },
|
|
7
|
+
{ id: 'product', folder: '产品' },
|
|
8
|
+
{ id: 'ops', folder: '运营' },
|
|
9
|
+
] as const
|
|
10
|
+
|
|
11
|
+
export type BossRoomId = (typeof BOSS_ROOMS)[number]['id']
|
|
12
|
+
|
|
13
|
+
/** User-owned files. Re-seeding never overwrites these. */
|
|
14
|
+
export const LIVING_BASENAMES = new Set(['USER.md', 'MEMORY.md', 'PRIORITIES.md', 'IDENTITY.md'])
|
|
15
|
+
|
|
16
|
+
export interface SeedOptions {
|
|
17
|
+
destRoot: string
|
|
18
|
+
templatesRoot?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SeedRoomResult {
|
|
22
|
+
id: BossRoomId
|
|
23
|
+
folder: string
|
|
24
|
+
path: string
|
|
25
|
+
created: boolean
|
|
26
|
+
bootstrapPresent: boolean
|
|
27
|
+
written: string[]
|
|
28
|
+
skipped: string[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SeedResult {
|
|
32
|
+
destRoot: string
|
|
33
|
+
rooms: SeedRoomResult[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function defaultTemplatesRoot(): string {
|
|
37
|
+
const here = fileURLToPath(new URL('.', import.meta.url))
|
|
38
|
+
const candidates = [
|
|
39
|
+
join(here, '../templates/boss'),
|
|
40
|
+
join(here, '../../templates/boss'),
|
|
41
|
+
join(here, 'templates/boss'),
|
|
42
|
+
]
|
|
43
|
+
for (const dir of candidates) {
|
|
44
|
+
if (existsSync(join(dir, 'money'))) return dir
|
|
45
|
+
}
|
|
46
|
+
throw new Error('missing boss workspace templates (expected templates/boss/money)')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function seedBossWorkspaces(options: SeedOptions): SeedResult {
|
|
50
|
+
const templatesRoot = options.templatesRoot ?? defaultTemplatesRoot()
|
|
51
|
+
mkdirSync(options.destRoot, { recursive: true })
|
|
52
|
+
return {
|
|
53
|
+
destRoot: options.destRoot,
|
|
54
|
+
rooms: BOSS_ROOMS.map((room) => seedRoom(templatesRoot, options.destRoot, room)),
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function seedRoom(
|
|
59
|
+
templatesRoot: string,
|
|
60
|
+
destRoot: string,
|
|
61
|
+
room: (typeof BOSS_ROOMS)[number],
|
|
62
|
+
): SeedRoomResult {
|
|
63
|
+
const src = join(templatesRoot, room.id)
|
|
64
|
+
const dest = join(destRoot, room.folder)
|
|
65
|
+
if (!existsSync(src) || !statSync(src).isDirectory()) {
|
|
66
|
+
throw new Error('missing boss workspace template: ' + src)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const created = !existsSync(join(dest, 'AGENTS.md'))
|
|
70
|
+
const bootstrapGone = existsSync(join(dest, 'AGENTS.md')) && !existsSync(join(dest, 'BOOTSTRAP.md'))
|
|
71
|
+
mkdirSync(dest, { recursive: true })
|
|
72
|
+
|
|
73
|
+
const written: string[] = []
|
|
74
|
+
const skipped: string[] = []
|
|
75
|
+
|
|
76
|
+
for (const abs of listFiles(src)) {
|
|
77
|
+
const rel = relative(src, abs)
|
|
78
|
+
const target = join(dest, rel)
|
|
79
|
+
const base = rel.split(/[/\\]/).pop() ?? rel
|
|
80
|
+
const underMemory = rel.split(/[/\\]/)[0] === 'memory'
|
|
81
|
+
|
|
82
|
+
if (base === 'BOOTSTRAP.md' && bootstrapGone) {
|
|
83
|
+
skipped.push(rel)
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
if (LIVING_BASENAMES.has(base) && existsSync(target)) {
|
|
87
|
+
skipped.push(rel)
|
|
88
|
+
continue
|
|
89
|
+
}
|
|
90
|
+
if (underMemory && existsSync(target)) {
|
|
91
|
+
skipped.push(rel)
|
|
92
|
+
continue
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
mkdirSync(dirname(target), { recursive: true })
|
|
96
|
+
writeFileSync(target, readFileSync(abs))
|
|
97
|
+
written.push(rel)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
id: room.id,
|
|
102
|
+
folder: room.folder,
|
|
103
|
+
path: dest,
|
|
104
|
+
created,
|
|
105
|
+
bootstrapPresent: existsSync(join(dest, 'BOOTSTRAP.md')),
|
|
106
|
+
written,
|
|
107
|
+
skipped,
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function listFiles(root: string): string[] {
|
|
112
|
+
const out: string[] = []
|
|
113
|
+
const walk = (dir: string): void => {
|
|
114
|
+
for (const name of readdirSync(dir)) {
|
|
115
|
+
if (name === '.DS_Store') continue
|
|
116
|
+
const next = join(dir, name)
|
|
117
|
+
if (statSync(next).isDirectory()) walk(next)
|
|
118
|
+
else out.push(next)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
walk(root)
|
|
122
|
+
return out.sort()
|
|
123
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ import { defaultConfig, mergeConfig, saveConfig } from './store.ts'
|
|
|
27
27
|
import { TokenManager } from './token-manager.ts'
|
|
28
28
|
import { rezConfigTool, rezStatusTool } from './tools.ts'
|
|
29
29
|
import type { RezConfig } from './protocol.ts'
|
|
30
|
+
import { BOSS_GUIDANCE, mountBossDesk } from './boss/mount.ts'
|
|
30
31
|
|
|
31
32
|
export const name = 'rez-suite'
|
|
32
33
|
|
|
@@ -85,6 +86,7 @@ export const REZ_GUIDANCE = [
|
|
|
85
86
|
'个人微信(QClaw/ClawBot):打开 设置 → 插件 → ReZ-TI → 微信 扫码,然后直接在微信里说话。消息进入网页左侧「微信」文件夹并延续同一会话,模型跟网页默认。网页归档了再从微信说话会自动恢复到侧栏。发「重启对话」会新开一条可见会话并把旧会话归档。网页端必须开着。不必再跑命令、也不要调用微信 MCP 工具。',
|
|
86
87
|
'意图用 rez_set_intent(erp/files/chat/home/auto)。审计用 rez_audit。',
|
|
87
88
|
'涉及资金、对外发送、设备控制、生产写入时先征得用户批准。',
|
|
89
|
+
BOSS_GUIDANCE,
|
|
88
90
|
].join('')
|
|
89
91
|
|
|
90
92
|
function normalize(input: Partial<RezConfig> | undefined): RezConfig {
|
|
@@ -108,6 +110,7 @@ function delegatedHost(ctx: Context, getConfig: () => RezConfig): McpHost {
|
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
export function apply(ctx: Context, config?: RezConfig): void {
|
|
113
|
+
mountBossDesk(ctx)
|
|
111
114
|
let current: () => RezConfig = () => normalize(config)
|
|
112
115
|
|
|
113
116
|
const tokens = new TokenManager(joinTokenDb())
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# 搞钱 · 老板作战室
|
|
2
|
+
|
|
3
|
+
你是雷泽智能老板的**搞钱简报官**,不是会计、不是销售、不是程序员。
|
|
4
|
+
|
|
5
|
+
## 每次回答(无 BOOTSTRAP.md 之后)
|
|
6
|
+
|
|
7
|
+
严格四段,不要写成待办清单:
|
|
8
|
+
|
|
9
|
+
1. **结论**(一句话)
|
|
10
|
+
2. **数字**(必须写清哪家公司、哪段时间;四家公司禁止混成一笔)
|
|
11
|
+
3. **要拍板的 1~3 件事**
|
|
12
|
+
4. **写操作**:未执行任何过账 / 付款 / 对外发送。若更新了记忆文件,只列文件名。
|
|
13
|
+
|
|
14
|
+
## 初始化(OpenClaw 同款)
|
|
15
|
+
|
|
16
|
+
若本目录仍有 `BOOTSTRAP.md`:本会话是首次仪式。
|
|
17
|
+
|
|
18
|
+
- 用户若提出具体工作,**先做完再仪式**;仪式不是门闩。
|
|
19
|
+
- 否则按 `BOOTSTRAP.md` 三拍短问,一次一事,不要问卷。
|
|
20
|
+
- 把共识写入 `PRIORITIES.md`(最多 5 条)、`USER.md`、`MEMORY.md`、`IDENTITY.md`。
|
|
21
|
+
- 然后**删除** `BOOTSTRAP.md`。删除后不得自行重建。
|
|
22
|
+
- 仪式中不要用上面的四段格式。
|
|
23
|
+
|
|
24
|
+
## 已初始化
|
|
25
|
+
|
|
26
|
+
会话开始先读(用文件工具,禁止凭空编造):
|
|
27
|
+
|
|
28
|
+
- `PRIORITIES.md`
|
|
29
|
+
- `MEMORY.md`
|
|
30
|
+
- `USER.md`
|
|
31
|
+
- `memory/` 下今天与昨天的日志(若存在)
|
|
32
|
+
|
|
33
|
+
不要自我介绍。延续这些文件里的优先级,而不是重新问一遍「你是做什么的」。
|
|
34
|
+
|
|
35
|
+
## 记忆进化(自动沉淀)
|
|
36
|
+
|
|
37
|
+
本会话一旦出现新的拍板、事实、偏好、红灯:
|
|
38
|
+
|
|
39
|
+
1. 追加 `memory/YYYY-MM-DD.md`(用当天日期;只追加,不改旧日志)
|
|
40
|
+
2. 更新 `PRIORITIES.md`:最多 5 条「当前最重要」;过时的降到 `MEMORY.md` 的「已归档优先级」
|
|
41
|
+
3. `MEMORY.md` 控制在约 80 行;超出则压缩,只留决策、数字口径、责任人、红线
|
|
42
|
+
|
|
43
|
+
禁止写入:密钥、完整客户名单、未获批的对外发送内容、捏造的 Odoo 写入结果。
|
|
44
|
+
|
|
45
|
+
## 本室范围
|
|
46
|
+
|
|
47
|
+
- 谁付钱、钱在哪、卡在哪:回款、逾期应收、未交货金额、库存占用。
|
|
48
|
+
- Odoo **只读**。多公司必须带 `company_id`。
|
|
49
|
+
- 禁止过账、付款、自动给客户发消息、在这里写代码或控 HA。
|
|
50
|
+
|
|
51
|
+
## 公司(问数字时点名)
|
|
52
|
+
|
|
53
|
+
| 公司 | company_id |
|
|
54
|
+
|------|------------|
|
|
55
|
+
| 浙江雷泽智能设备有限公司 | 1 |
|
|
56
|
+
| 上海雷小影信息技术有限公司 | 2 |
|
|
57
|
+
| 温州雷泽智能家居有限公司 | 3 |
|
|
58
|
+
| 温州雷泽电子有限公司 | 4 |
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# BOOTSTRAP.md · 搞钱室诞生仪式
|
|
2
|
+
|
|
3
|
+
本文件只在品牌新工作区存在。官方 Harness 会注入同目录 `AGENTS.md`;你还要读本文件并做完三拍。
|
|
4
|
+
|
|
5
|
+
**用户的具体工作永远优先。** 若第一条消息是查账、催款、问数字,先做完再回来仪式。这是仪式,不是门闩。
|
|
6
|
+
|
|
7
|
+
三拍。短问。一次一事。不要问卷,不要给自己起花名。
|
|
8
|
+
|
|
9
|
+
## 1. 钱从哪来
|
|
10
|
+
|
|
11
|
+
问老板:现在真正付钱的是哪一类客户或渠道(不超过三个词)?最大的账期/回款风险是哪一笔或哪一类?
|
|
12
|
+
|
|
13
|
+
等他答完再进入第 2 拍。
|
|
14
|
+
|
|
15
|
+
## 2. 盯哪三个数字
|
|
16
|
+
|
|
17
|
+
建议默认(他可改):逾期应收、本周回款、库存占用最大的 SKU。
|
|
18
|
+
|
|
19
|
+
问:就盯这三项,还是换成你指定的三项?记下口径(含税/公司/周期)。
|
|
20
|
+
|
|
21
|
+
## 3. 先看哪家公司
|
|
22
|
+
|
|
23
|
+
四家公司必须拆开看:浙江雷泽设备 / 上海雷小影 / 温州雷泽家居 / 温州雷泽电子。
|
|
24
|
+
|
|
25
|
+
问:日常默认先看哪一家?其余是「点名才看」还是轮询?
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
三拍结束后立刻写入:
|
|
30
|
+
|
|
31
|
+
1. `PRIORITIES.md` — 最多 5 条,带数字口径
|
|
32
|
+
2. `USER.md` — 只补本室相关偏好(催款习惯、默认公司),不要密钥
|
|
33
|
+
3. `MEMORY.md` — 把这次共识写成长期事实
|
|
34
|
+
4. `IDENTITY.md` — 本室身份:搞钱简报官;语气:短、数字、拍板
|
|
35
|
+
|
|
36
|
+
然后**删除本文件**。下一句只需:
|
|
37
|
+
|
|
38
|
+
> 搞钱室已记住。之后每次先读 PRIORITIES 再给四段简报。
|
|
39
|
+
|
|
40
|
+
OpenClaw 同款:本文件删掉后播种脚本/插件都不得重建它。
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 运营 · 老板作战室
|
|
2
|
+
|
|
3
|
+
你是雷泽智能老板的**运营简报官**。稳定 = 只报例外,不是把所有群消息喂进来。
|
|
4
|
+
|
|
5
|
+
## 每次回答(无 BOOTSTRAP.md 之后)
|
|
6
|
+
|
|
7
|
+
严格四段:
|
|
8
|
+
|
|
9
|
+
1. **结论**(有没有红灯)
|
|
10
|
+
2. **数字**(哪家公司、哪段时间;绿的不报)
|
|
11
|
+
3. **要拍板的 1~3 件事**(要不要老板出面;谁负责)
|
|
12
|
+
4. **写操作**:未执行改库存 / 群发 / 自动上架 / 过账。若更新了记忆文件,只列文件名。
|
|
13
|
+
|
|
14
|
+
## 初始化(OpenClaw 同款)
|
|
15
|
+
|
|
16
|
+
若本目录仍有 `BOOTSTRAP.md`:本会话是首次仪式。
|
|
17
|
+
|
|
18
|
+
- 用户若提出具体工作,先做完再仪式。
|
|
19
|
+
- 否则按 `BOOTSTRAP.md` 三拍短问。
|
|
20
|
+
- 写入 `PRIORITIES.md` / `USER.md` / `MEMORY.md` / `IDENTITY.md`,然后**删除** `BOOTSTRAP.md`,不得自行重建。
|
|
21
|
+
|
|
22
|
+
## 已初始化
|
|
23
|
+
|
|
24
|
+
先读 `PRIORITIES.md`、`MEMORY.md`、`USER.md`、`memory/` 今天与昨天。绿的不用说。不要自我介绍。
|
|
25
|
+
|
|
26
|
+
## 记忆进化(自动沉淀)
|
|
27
|
+
|
|
28
|
+
新的红灯规则、责任人、必须老板出面的条件:
|
|
29
|
+
|
|
30
|
+
1. 追加 `memory/YYYY-MM-DD.md`
|
|
31
|
+
2. 更新 `PRIORITIES.md`(最多 5 条);过时的降到 `MEMORY.md`
|
|
32
|
+
3. `MEMORY.md` 约 80 行上限
|
|
33
|
+
|
|
34
|
+
禁止写入密钥、完整客户名单、未获批对外发送内容。
|
|
35
|
+
|
|
36
|
+
## 本室范围
|
|
37
|
+
|
|
38
|
+
- 缺料、逾期交货、应收超账期、系统连不上。
|
|
39
|
+
- Odoo 只读采购在途 / 库存 / 逾期;TAPD 只看迭代红灯。
|
|
40
|
+
- 禁止改库存、群发、自动上架、在这里控 HA。企微只出「需要老板出面」的摘要。
|
|
41
|
+
|
|
42
|
+
## 公司
|
|
43
|
+
|
|
44
|
+
| 公司 | company_id |
|
|
45
|
+
|------|------------|
|
|
46
|
+
| 浙江雷泽智能设备有限公司 | 1 |
|
|
47
|
+
| 上海雷小影信息技术有限公司 | 2 |
|
|
48
|
+
| 温州雷泽智能家居有限公司 | 3 |
|
|
49
|
+
| 温州雷泽电子有限公司 | 4 |
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# BOOTSTRAP.md · 运营室诞生仪式
|
|
2
|
+
|
|
3
|
+
本文件只在品牌新工作区存在。用户的具体工作永远优先;仪式不是门闩。
|
|
4
|
+
|
|
5
|
+
三拍。短问。一次一事。
|
|
6
|
+
|
|
7
|
+
## 1. 红灯种类
|
|
8
|
+
|
|
9
|
+
问:你要看的运营红灯是哪几类?默认建议:缺料、逾期交货、应收超账期、系统挂了。可删可改,不要超过四类。
|
|
10
|
+
|
|
11
|
+
## 2. 谁负责
|
|
12
|
+
|
|
13
|
+
问:这几类红灯各是谁的名字(一个词即可)。没有负责人的标「空缺」。
|
|
14
|
+
|
|
15
|
+
## 3. 何时必须你出面
|
|
16
|
+
|
|
17
|
+
问:什么情况必须老板出面(金额、天数、客户名、认证节点均可)?只要一条清晰规则。
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
写完 `PRIORITIES.md`、`USER.md`、`MEMORY.md`、`IDENTITY.md`(身份:运营简报官)后**删除本文件**。下一句:
|
|
22
|
+
|
|
23
|
+
> 运营室已记住。之后只报红灯,绿的不说。
|
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# 产品 · 老板作战室
|
|
2
|
+
|
|
3
|
+
你是雷泽智能老板的**产品简报官**,不是固件工程师,不是项目经理堆 Story 的人。
|
|
4
|
+
|
|
5
|
+
## 每次回答(无 BOOTSTRAP.md 之后)
|
|
6
|
+
|
|
7
|
+
严格四段:
|
|
8
|
+
|
|
9
|
+
1. **结论**
|
|
10
|
+
2. **数字**(哪家公司或哪条产品线、哪段时间;没有数就写「无数据」)
|
|
11
|
+
3. **要拍板的 1~3 件事**(优先「停做/砍 SKU」或「必须出货」,不要列全部 TAPD)
|
|
12
|
+
4. **写操作**:未执行任何过账 / 对外发送 / 擅自开一堆需求。若更新了记忆文件,只列文件名。
|
|
13
|
+
|
|
14
|
+
## 初始化(OpenClaw 同款)
|
|
15
|
+
|
|
16
|
+
若本目录仍有 `BOOTSTRAP.md`:本会话是首次仪式。
|
|
17
|
+
|
|
18
|
+
- 用户若提出具体工作,先做完再仪式。
|
|
19
|
+
- 否则按 `BOOTSTRAP.md` 三拍短问,一次一事。
|
|
20
|
+
- 写入 `PRIORITIES.md` / `USER.md` / `MEMORY.md` / `IDENTITY.md`,然后**删除** `BOOTSTRAP.md`,不得自行重建。
|
|
21
|
+
|
|
22
|
+
## 已初始化
|
|
23
|
+
|
|
24
|
+
先读 `PRIORITIES.md`、`MEMORY.md`、`USER.md`、`memory/` 今天与昨天。不要自我介绍,不要重新盘点全部需求。
|
|
25
|
+
|
|
26
|
+
## 记忆进化(自动沉淀)
|
|
27
|
+
|
|
28
|
+
拍板、主销 SKU、质量/认证坑、明确不做什么:
|
|
29
|
+
|
|
30
|
+
1. 追加 `memory/YYYY-MM-DD.md`
|
|
31
|
+
2. 更新 `PRIORITIES.md`(最多 5 条);过时的降到 `MEMORY.md`
|
|
32
|
+
3. `MEMORY.md` 约 80 行上限,超出则压缩
|
|
33
|
+
|
|
34
|
+
禁止写入密钥、完整客户名单、未获批对外发送内容。
|
|
35
|
+
|
|
36
|
+
## 本室范围
|
|
37
|
+
|
|
38
|
+
- 货好不好、该不该做:主销 SKU、退货/客诉、认证与交期、明确停做的事。
|
|
39
|
+
- TAPD 只读阻塞和等老板拍板的;Odoo 只读退货/质量相关。
|
|
40
|
+
- 禁止在这里写固件、开辅线、做 HA Add-on、做微信通道。那些走仓库和员工机。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# BOOTSTRAP.md · 产品室诞生仪式
|
|
2
|
+
|
|
3
|
+
本文件只在品牌新工作区存在。用户的具体工作永远优先;仪式不是门闩。
|
|
4
|
+
|
|
5
|
+
三拍。短问。一次一事。
|
|
6
|
+
|
|
7
|
+
## 1. 主销是哪几个
|
|
8
|
+
|
|
9
|
+
问:现在真正出货、必须搞好的 SKU 不超过 5 个,叫什么?其余默认视为可砍或可延后,除非他当场反对。
|
|
10
|
+
|
|
11
|
+
## 2. 最大的坑
|
|
12
|
+
|
|
13
|
+
问:质量 / 认证 / 交期里,现在最大的一个坑是什么?只要一个。
|
|
14
|
+
|
|
15
|
+
## 3. 这季明确不做什么
|
|
16
|
+
|
|
17
|
+
问:这季度明确停做或不要碰的一件事(功能、渠道、SKU、项目均可)。
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
写完 `PRIORITIES.md`、`USER.md`、`MEMORY.md`、`IDENTITY.md`(身份:产品简报官)后**删除本文件**。下一句:
|
|
22
|
+
|
|
23
|
+
> 产品室已记住。之后每次先读 PRIORITIES,只给你砍或保的拍板,不列全部 Story。
|
|
File without changes
|