@rezti/dsh-rez-suite 0.1.26 → 0.1.33
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/lib/client.d.ts +7 -0
- package/lib/client.js +388 -187
- package/lib/index.d.ts +4 -0
- package/lib/index.js +85 -7
- package/lib/style.css +47 -0
- package/package.json +7 -7
- package/src/boss/mount.ts +2 -0
- package/src/client/assets/rez-mark.png +0 -0
- package/src/client/brand-mark.ts +4 -0
- package/src/client/brand.module.css +51 -0
- package/src/client/brand.ts +135 -0
- package/src/client/index.ts +11 -0
- package/src/client/locales.ts +14 -0
- package/src/client/panel/AuditTab.tsx +20 -19
- package/src/client/panel/ConfigTab.tsx +57 -39
- package/src/client/panel/StatusTab.tsx +11 -10
- package/src/client/panel/WeixinTab.tsx +9 -8
- package/src/client/panel/helpers.ts +20 -5
- package/src/client/settings-card.tsx +48 -42
- package/src/client/upgrade-button.tsx +24 -12
- package/src/index.ts +11 -0
- package/src/observe-mcp.ts +5 -2
- package/src/presets.ts +1 -0
- package/src/protocol.ts +2 -0
- package/src/store.ts +6 -0
- package/src/tianyancha.ts +79 -0
- package/templates/boss/money/AGENTS.md +2 -0
- package/templates/boss/ops/AGENTS.md +2 -0
- package/templates/boss/product/AGENTS.md +4 -0
- package/templates/staff/finance/.agents/skills/staff-finance/SKILL.md +1 -1
- package/templates/staff/finance/AGENTS.md +6 -0
- package/templates/staff/finance/MEMORY.md +1 -1
- package/templates/staff/hr/.agents/skills/staff-hr/SKILL.md +1 -1
- package/templates/staff/hr/AGENTS.md +6 -0
- package/templates/staff/hr/MEMORY.md +1 -1
- package/templates/staff/legal/.agents/skills/staff-legal/SKILL.md +1 -1
- package/templates/staff/legal/AGENTS.md +10 -0
- package/templates/staff/legal/MEMORY.md +1 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sidebar footer action: upgrade @rezti/dsh-rez-suite without a terminal.
|
|
3
3
|
* Host code still needs a process respawn; the button does that after pnpm add.
|
|
4
|
+
*
|
|
5
|
+
* `t` is the official locale seat (zh/en follows 设置 → 语言).
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
import { useEffect, useMemo, useState } from 'react'
|
|
9
|
+
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
|
|
7
10
|
import { RezApi } from './api.ts'
|
|
8
|
-
import { tt } from './panel/helpers.ts'
|
|
9
11
|
import css from './panel/panel.module.css'
|
|
10
12
|
import type { RezUpdateStatus } from '../protocol.ts'
|
|
11
13
|
|
|
@@ -24,7 +26,11 @@ function UpgradeIcon() {
|
|
|
24
26
|
)
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
async function waitUntilHostBack(
|
|
29
|
+
async function waitUntilHostBack(
|
|
30
|
+
api: RezApi,
|
|
31
|
+
timeoutMessage: string,
|
|
32
|
+
timeoutMs = 60_000,
|
|
33
|
+
): Promise<void> {
|
|
28
34
|
const deadline = Date.now() + timeoutMs
|
|
29
35
|
await new Promise((resolve) => setTimeout(resolve, 800))
|
|
30
36
|
while (Date.now() < deadline) {
|
|
@@ -35,10 +41,16 @@ async function waitUntilHostBack(api: RezApi, timeoutMs = 60_000): Promise<void>
|
|
|
35
41
|
await new Promise((resolve) => setTimeout(resolve, 700))
|
|
36
42
|
}
|
|
37
43
|
}
|
|
38
|
-
throw new Error(
|
|
44
|
+
throw new Error(timeoutMessage)
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
export function UpgradeButton({
|
|
47
|
+
export function UpgradeButton({
|
|
48
|
+
wide,
|
|
49
|
+
t,
|
|
50
|
+
}: {
|
|
51
|
+
wide: boolean
|
|
52
|
+
t: TranslateNS<'dsh-rez-suite'>
|
|
53
|
+
}) {
|
|
42
54
|
const api = useMemo(() => new RezApi(), [])
|
|
43
55
|
const [info, setInfo] = useState<RezUpdateStatus>()
|
|
44
56
|
const [busy, setBusy] = useState(false)
|
|
@@ -55,10 +67,10 @@ export function UpgradeButton({ wide }: { wide: boolean }) {
|
|
|
55
67
|
}, [api])
|
|
56
68
|
|
|
57
69
|
const label = busy
|
|
58
|
-
?
|
|
70
|
+
? t('upgrade.running')
|
|
59
71
|
: info?.outdated === true
|
|
60
|
-
?
|
|
61
|
-
:
|
|
72
|
+
? t('upgrade.label')
|
|
73
|
+
: t('upgrade.current')
|
|
62
74
|
|
|
63
75
|
const meta = note !== ''
|
|
64
76
|
? note
|
|
@@ -76,18 +88,18 @@ export function UpgradeButton({ wide }: { wide: boolean }) {
|
|
|
76
88
|
const snapshot = info ?? await api.updateStatus()
|
|
77
89
|
setInfo(snapshot)
|
|
78
90
|
if (!snapshot.outdated) {
|
|
79
|
-
setNote(
|
|
91
|
+
setNote(t('upgrade.already', { version: snapshot.installed }))
|
|
80
92
|
return
|
|
81
93
|
}
|
|
82
94
|
const result = await api.applyUpdate()
|
|
83
95
|
setInfo(result)
|
|
84
96
|
if (result.restarting) {
|
|
85
|
-
setNote(
|
|
86
|
-
await waitUntilHostBack(api)
|
|
97
|
+
setNote(t('upgrade.reloading'))
|
|
98
|
+
await waitUntilHostBack(api, t('upgrade.reloadTimeout'))
|
|
87
99
|
window.location.reload()
|
|
88
100
|
return
|
|
89
101
|
}
|
|
90
|
-
setNote(
|
|
102
|
+
setNote(t('upgrade.already', { version: result.installed }))
|
|
91
103
|
} catch (error) {
|
|
92
104
|
setNote(error instanceof Error ? error.message : String(error))
|
|
93
105
|
} finally {
|
|
@@ -101,7 +113,7 @@ export function UpgradeButton({ wide }: { wide: boolean }) {
|
|
|
101
113
|
type="button"
|
|
102
114
|
className={css.upgradeButton}
|
|
103
115
|
data-outdated={info?.outdated === true ? '' : undefined}
|
|
104
|
-
aria-label={
|
|
116
|
+
aria-label={t('upgrade.aria')}
|
|
105
117
|
disabled={busy}
|
|
106
118
|
onClick={() => { void onClick() }}
|
|
107
119
|
>
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { rezConfigTool, rezStatusTool } from './tools.ts'
|
|
|
29
29
|
import type { RezConfig } from './protocol.ts'
|
|
30
30
|
import { workspaceGuidanceFor, mountRezWorkspaces } from './boss/mount.ts'
|
|
31
31
|
import { liveSelfUpdate } from './self-update.ts'
|
|
32
|
+
import { mountTianyanchaMcp } from './tianyancha.ts'
|
|
32
33
|
|
|
33
34
|
export const name = 'rez-suite'
|
|
34
35
|
|
|
@@ -79,6 +80,10 @@ export const Config: z<RezConfig> = z.object({
|
|
|
79
80
|
enabled: z.boolean().default(true),
|
|
80
81
|
siteUrl: z.string().default(REZ_DEFAULT_CONNECTIONS.gsc.siteUrl),
|
|
81
82
|
}).default(REZ_DEFAULT_CONNECTIONS.gsc),
|
|
83
|
+
tianyancha: z.object({
|
|
84
|
+
enabled: z.boolean().default(true),
|
|
85
|
+
url: z.string().default(REZ_DEFAULT_CONNECTIONS.tianyancha.url),
|
|
86
|
+
}).default(REZ_DEFAULT_CONNECTIONS.tianyancha),
|
|
82
87
|
}).default(REZ_DEFAULT_CONNECTIONS),
|
|
83
88
|
billing: z.object({
|
|
84
89
|
inputCostPer1k: z.number().default(0.001),
|
|
@@ -96,6 +101,8 @@ export const REZ_GUIDANCE_CORE = [
|
|
|
96
101
|
'个人微信(QClaw/ClawBot):打开 设置 → 插件 → ReZ-TI → 微信 扫码,然后直接在微信里说话。消息进入网页左侧「微信」文件夹并延续同一会话,模型跟网页默认。网页归档了再从微信说话会自动恢复到侧栏。发「重启对话」会新开一条可见会话并把旧会话归档。网页端必须开着。不必再跑命令、也不要调用微信 MCP 工具。',
|
|
97
102
|
'意图用 rez_set_intent(erp/files/chat/home/auto)。审计用 rez_audit。',
|
|
98
103
|
'涉及资金、对外发送、设备控制、生产写入时先征得用户批准。',
|
|
104
|
+
'Match the user language: Chinese or English. Do not force 中文 when they write English.',
|
|
105
|
+
'制度、手册、出差/报销标准、素材路径:打开 Nextcloud Documents/Standards/INDEX.yaml,按 code 取当前 effective_from 最新且未被 replace 的条目,再按相对 uri 打开。引用带路径+生效日。找不到就说「标准文件未归档」,不要用 MEMORY 旧数字。素材文件夹用首次创建标题,不用会变的 Odoo/销售名。',
|
|
99
106
|
].join('')
|
|
100
107
|
|
|
101
108
|
export function rezGuidanceFor(role: RezConfig['role']): string {
|
|
@@ -128,6 +135,7 @@ function delegatedHost(ctx: Context, getConfig: () => RezConfig): McpHost {
|
|
|
128
135
|
export function apply(ctx: Context, config?: RezConfig): void {
|
|
129
136
|
let current: () => RezConfig = () => normalize(config)
|
|
130
137
|
const syncWorkspaces = mountRezWorkspaces(ctx, () => current().role)
|
|
138
|
+
const syncTianyancha = mountTianyanchaMcp(ctx, () => current().role)
|
|
131
139
|
|
|
132
140
|
const tokens = new TokenManager(joinTokenDb())
|
|
133
141
|
const host = delegatedHost(ctx, () => current())
|
|
@@ -145,6 +153,7 @@ export function apply(ctx: Context, config?: RezConfig): void {
|
|
|
145
153
|
saveConfig(value)
|
|
146
154
|
current = () => value
|
|
147
155
|
syncWorkspaces()
|
|
156
|
+
syncTianyancha()
|
|
148
157
|
try {
|
|
149
158
|
const settings = ctx.get('settings') as { update?: (namespace: unknown, value: unknown) => Promise<void> } | undefined
|
|
150
159
|
if (settings?.update !== undefined) await settings.update(REZ_SETTINGS_NAMESPACE, value)
|
|
@@ -198,10 +207,12 @@ export function apply(ctx: Context, config?: RezConfig): void {
|
|
|
198
207
|
current = source
|
|
199
208
|
sync()
|
|
200
209
|
syncWorkspaces()
|
|
210
|
+
syncTianyancha()
|
|
201
211
|
},
|
|
202
212
|
onChange: () => {
|
|
203
213
|
sync()
|
|
204
214
|
syncWorkspaces()
|
|
215
|
+
syncTianyancha()
|
|
205
216
|
},
|
|
206
217
|
})
|
|
207
218
|
|
package/src/observe-mcp.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { lastMcpStartError, REZ_CREDENTIAL_REFS, secretConfigured, type RezSystem } from '@rezti/dsh-rez-sso'
|
|
10
10
|
import type { RezConfig, RezServerStatus, RezTestResult } from './protocol.ts'
|
|
11
11
|
|
|
12
|
-
export const COMPOSED_SERVERS = ['odoo', 'nextcloud', 'wechat', 'homeassistant', 'tapd', 'gsc'] as const
|
|
12
|
+
export const COMPOSED_SERVERS = ['odoo', 'nextcloud', 'wechat', 'homeassistant', 'tapd', 'gsc', 'tianyancha'] as const
|
|
13
13
|
|
|
14
14
|
export type ComposedServer = (typeof COMPOSED_SERVERS)[number]
|
|
15
15
|
|
|
@@ -102,7 +102,10 @@ export function observeServer(
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
export function observeComposedServers(input: ObserveInput): RezServerStatus[] {
|
|
105
|
-
|
|
105
|
+
const servers = input.config.role === 'boss'
|
|
106
|
+
? COMPOSED_SERVERS
|
|
107
|
+
: COMPOSED_SERVERS.filter((server) => server !== 'tianyancha')
|
|
108
|
+
return servers.map(server => observeServer(server, input))
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
export function testComposedServers(input: ObserveInput): RezTestResult[] {
|
package/src/presets.ts
CHANGED
|
@@ -127,6 +127,7 @@ const COMPILED: Record<Exclude<RezRoleId, 'all' | 'boss'>, { server: RezServerId
|
|
|
127
127
|
|
|
128
128
|
/** Whether one MCP tool may be registered for the selected role. */
|
|
129
129
|
export function isToolAllowed(role: RezRoleId, server: string, rawName: string): boolean {
|
|
130
|
+
if (server === 'tianyancha') return role === 'boss'
|
|
130
131
|
if (role === 'all' || role === 'boss') return true
|
|
131
132
|
const rules = COMPILED[role]
|
|
132
133
|
return rules.some(rule => rule.server === server && rule.test.test(rawName))
|
package/src/protocol.ts
CHANGED
|
@@ -48,6 +48,7 @@ export interface RezConnections {
|
|
|
48
48
|
homeassistant: { enabled: boolean; url: string }
|
|
49
49
|
tapd: { enabled: boolean; workspaceId: string; nickName: string }
|
|
50
50
|
gsc: { enabled: boolean; siteUrl: string }
|
|
51
|
+
tianyancha: { enabled: boolean; url: string }
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
export interface RezPublicConnection {
|
|
@@ -90,6 +91,7 @@ export interface RezPublicConfig {
|
|
|
90
91
|
homeassistant: RezPublicConnection
|
|
91
92
|
tapd: RezPublicConnection
|
|
92
93
|
gsc: RezPublicConnection
|
|
94
|
+
tianyancha: RezPublicConnection
|
|
93
95
|
}
|
|
94
96
|
billing: { inputCostPer1k: number; outputCostPer1k: number; monthlyBudget: number }
|
|
95
97
|
}
|
package/src/store.ts
CHANGED
|
@@ -125,6 +125,12 @@ export function publicConfig(config: RezConfig): RezPublicConfig {
|
|
|
125
125
|
secretConfigured: secretConfigured('gsc'),
|
|
126
126
|
secretRef: REZ_CREDENTIAL_REFS.gsc,
|
|
127
127
|
},
|
|
128
|
+
tianyancha: {
|
|
129
|
+
enabled: connections.tianyancha.enabled,
|
|
130
|
+
url: connections.tianyancha.url,
|
|
131
|
+
secretConfigured: secretConfigured('tianyancha'),
|
|
132
|
+
secretRef: REZ_CREDENTIAL_REFS.tianyancha,
|
|
133
|
+
},
|
|
128
134
|
},
|
|
129
135
|
billing: { ...config.billing },
|
|
130
136
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TianyanCha official MCP for the 法务助理 workspace.
|
|
3
|
+
* Reuse https://mcp.tianyancha.com/mcp via dsh-mcp-client. Do not spawn a
|
|
4
|
+
* local 162-tool catalog — tools/list only exposes a few agent entrypoints.
|
|
5
|
+
* Start the client only when suite role is boss so other identities never
|
|
6
|
+
* see mcp__tianyancha__* in the prompt.
|
|
7
|
+
*/
|
|
8
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
9
|
+
import { loadRezConnections, startMcpWhenSecret } from '@rezti/dsh-rez-sso'
|
|
10
|
+
import type { RezRoleId } from './protocol.ts'
|
|
11
|
+
|
|
12
|
+
export const TIANYANCHA_MCP_URL = 'https://mcp.tianyancha.com/mcp'
|
|
13
|
+
|
|
14
|
+
export function shouldStartTianyancha(role: RezRoleId): boolean {
|
|
15
|
+
return role === 'boss'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function bearerAuthorization(secret: string): string {
|
|
19
|
+
const trimmed = secret.trim()
|
|
20
|
+
if (/^bearer\s+/i.test(trimmed)) return 'Bearer ' + trimmed.replace(/^bearer\s+/i, '')
|
|
21
|
+
return 'Bearer ' + trimmed
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function tianyanchaMcpConfig(secret: string): Record<string, unknown> {
|
|
25
|
+
const { url } = loadRezConnections().tianyancha
|
|
26
|
+
return {
|
|
27
|
+
serverName: 'tianyancha',
|
|
28
|
+
transport: 'streamable-http',
|
|
29
|
+
url: url.length > 0 ? url : TIANYANCHA_MCP_URL,
|
|
30
|
+
headers: { Authorization: bearerAuthorization(secret) },
|
|
31
|
+
failOnStartupError: false,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Start when role is boss; dispose the mcp-client fiber when the identity leaves. */
|
|
36
|
+
export function mountTianyanchaMcp(
|
|
37
|
+
ctx: Context,
|
|
38
|
+
getRole: () => RezRoleId,
|
|
39
|
+
start: typeof startMcpWhenSecret = startMcpWhenSecret,
|
|
40
|
+
): () => void {
|
|
41
|
+
let session: (() => void) | undefined
|
|
42
|
+
let pending = false
|
|
43
|
+
|
|
44
|
+
const ensure = (): void => {
|
|
45
|
+
void (async () => {
|
|
46
|
+
const want = shouldStartTianyancha(getRole())
|
|
47
|
+
if (!want) {
|
|
48
|
+
session?.()
|
|
49
|
+
session = undefined
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
if (session !== undefined || pending) return
|
|
53
|
+
pending = true
|
|
54
|
+
let raced = false
|
|
55
|
+
try {
|
|
56
|
+
const dispose = await start(ctx, {
|
|
57
|
+
system: 'tianyancha',
|
|
58
|
+
label: '天眼查',
|
|
59
|
+
config: tianyanchaMcpConfig,
|
|
60
|
+
})
|
|
61
|
+
if (!shouldStartTianyancha(getRole())) {
|
|
62
|
+
raced = true
|
|
63
|
+
dispose()
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
session = dispose
|
|
67
|
+
} catch (error: unknown) {
|
|
68
|
+
const why = error instanceof Error ? error.message : String(error)
|
|
69
|
+
console.error('[dsh-rez-suite] tianyancha MCP start failed:', why)
|
|
70
|
+
} finally {
|
|
71
|
+
pending = false
|
|
72
|
+
if (raced && shouldStartTianyancha(getRole()) && session === undefined) ensure()
|
|
73
|
+
}
|
|
74
|
+
})()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
ensure()
|
|
78
|
+
return ensure
|
|
79
|
+
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
你是雷泽智能老板的**产品简报官**,不是固件工程师,不是项目经理堆 Story 的人。
|
|
4
4
|
|
|
5
|
+
语言:用户用中文就中文,用英文就英文;结构不变。不要因为本文件是中文就强制中文。
|
|
6
|
+
|
|
5
7
|
## 每次回答(无 BOOTSTRAP.md 之后)
|
|
6
8
|
|
|
7
9
|
严格四段:
|
|
@@ -37,4 +39,6 @@
|
|
|
37
39
|
|
|
38
40
|
- 货好不好、该不该做:主销 SKU、退货/客诉、认证与交期、明确停做的事。
|
|
39
41
|
- TAPD 只读阻塞和等老板拍板的;Odoo 只读退货/质量相关。
|
|
42
|
+
- 新产品或改产品 Wiki:Wiki **必须**同时写死 Nextcloud RAW 路径,以及 Git 3D 源路径 `products/{slug}/models` 与 `products/{slug}/motion`。缺任一项就说「Wiki 未归档」,不要猜路径。
|
|
43
|
+
- 问某产品素材在哪:打开 Nextcloud `Documents/Standards/INDEX.yaml`,再按相对 uri 读路径规则;加上该产品 Wiki **首次创建标题**,不要用会变的 Odoo `name` / 销售标题。
|
|
40
44
|
- 禁止在这里写固件、开辅线、做 HA Add-on、做微信通道。那些走仓库和员工机。
|
|
@@ -3,4 +3,4 @@ name: staff-finance
|
|
|
3
3
|
description: 财务助理。全员报销;审批/报表/过账仅当当前 Odoo 帐号能看见对应单据。不自审不自过账。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
完整规矩在工作区 `AGENTS.md`。先 `mcp__odoo__get_current_context`。报销走 `hr.expense` / `hr.expense.sheet
|
|
6
|
+
完整规矩在工作区 `AGENTS.md`。先 `mcp__odoo__get_current_context`。报销走 `hr.expense` / `hr.expense.sheet`。搞钱室不要在这里做。问制度/报销标准先打开 Nextcloud `Documents/Standards/INDEX.yaml`,再按相对 uri 读,不要把手册写入 MEMORY。用户用中文就中文、用英文就英文。
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
你是雷泽智能的**财务助理**(报销是给所有人的入口)。同一套工作区全员能进。能看见哪张单、能不能提交/批准/过账,一律以**当前 Odoo 登录帐号**为准。Harness **只做选择**:起草、列待办、让人点选项;**不自审、不自过账、不编分录**。
|
|
4
4
|
|
|
5
|
+
语言:用户用中文就中文,用英文就英文;结构不变。不要因为本文件是中文就强制中文。
|
|
6
|
+
|
|
5
7
|
战略回款简报请去 **搞钱** 室。本室做单据流。
|
|
6
8
|
|
|
7
9
|
## 每次开场
|
|
@@ -52,6 +54,10 @@
|
|
|
52
54
|
|
|
53
55
|
沉淀:默认公司、常用费用产品、是否要发票。禁止写密钥、完整卡号、未获批的付款指令。
|
|
54
56
|
|
|
57
|
+
## 公司标准(Nextcloud INDEX)
|
|
58
|
+
|
|
59
|
+
问制度、手册、报销/出差标准、素材路径:打开 Nextcloud `Documents/Standards/INDEX.yaml`,再按相对 uri 读。按 `code` 找当前 `effective_from` 最新且未被 replace 的条目。引用时带路径 + 生效日。找不到就说「标准文件未归档」,不要用 MEMORY 里的旧数字。禁止把手册全文写入 MEMORY。
|
|
60
|
+
|
|
55
61
|
## 范围与红线
|
|
56
62
|
|
|
57
63
|
- 只用 `mcp__odoo__*`。费用模型已开放读写;工资单模型若列表里没有就不要编。
|
|
@@ -3,4 +3,4 @@ name: staff-hr
|
|
|
3
3
|
description: 人事助理。全员请假/查自己;主管批假;权限完全跟当前 Odoo 帐号。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
完整规矩在工作区 `AGENTS.md`。先 `mcp__odoo__get_current_context`。有 `BOOTSTRAP.md`
|
|
6
|
+
完整规矩在工作区 `AGENTS.md`。先 `mcp__odoo__get_current_context`。有 `BOOTSTRAP.md` 时正事优先再三拍。问制度/出差标准先打开 Nextcloud `Documents/Standards/INDEX.yaml`,再按相对 uri 读,不要把手册写入 MEMORY。用户用中文就中文、用英文就英文。
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
你是雷泽智能的**人事助理**。同一套工作区给所有人用。能看见、能提交、能审批,一律以**当前 Odoo 登录帐号**的权限组 / 记录规则 / 公司为准。Harness 只帮人选动作、填草稿、解释状态,**不代替 Odoo 审核**。
|
|
4
4
|
|
|
5
|
+
语言:用户用中文就中文,用英文就英文;结构不变。不要因为本文件是中文就强制中文。
|
|
6
|
+
|
|
5
7
|
## 每次开场
|
|
6
8
|
|
|
7
9
|
1. 调 `mcp__odoo__get_current_context`,记住用户、时区、当前公司、可切换公司。
|
|
@@ -36,6 +38,10 @@
|
|
|
36
38
|
|
|
37
39
|
新的偏好、默认公司、常请假类型:追加 `memory/YYYY-MM-DD.md`,更新 `PRIORITIES.md`(最多 5 条)。禁止写密钥、完整身份证号、银行帐号。
|
|
38
40
|
|
|
41
|
+
## 公司标准(Nextcloud INDEX)
|
|
42
|
+
|
|
43
|
+
问制度、手册、出差标准、素材路径:打开 Nextcloud `Documents/Standards/INDEX.yaml`,再按相对 uri 读。按 `code` 找当前 `effective_from` 最新且未被 replace 的条目。引用时带路径 + 生效日。找不到就说「标准文件未归档」,不要用 MEMORY 里的旧数字。禁止把手册全文写入 MEMORY。
|
|
44
|
+
|
|
39
45
|
## 范围与红线
|
|
40
46
|
|
|
41
47
|
- 走现成 `mcp__odoo__*`(`hr.leave`、`hr.leave.allocation`、`hr.employee` 等)。不自写人事系统。
|
|
@@ -3,4 +3,4 @@ name: staff-legal
|
|
|
3
3
|
description: 法务助理。全员可问制度、整理风险;能看哪些合同跟当前 Odoo/Nextcloud 帐号。不下具约束力的法律结论。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
完整规矩在工作区 `AGENTS.md`。先 `mcp__odoo__get_current_context
|
|
6
|
+
完整规矩在工作区 `AGENTS.md`。先 `mcp__odoo__get_current_context`。不是律师。问制度先打开 Nextcloud `Documents/Standards/INDEX.yaml`,再按相对 uri 读,不要把手册写入 MEMORY。有 `mcp__tianyancha__*` 才查工商(仅老板身份会挂上)。用户用中文就中文、用英文就英文。
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
你是雷泽智能的**法务助理**。同一套工作区全员能进。能看哪些合同、客户、附件,以**当前 Odoo / Nextcloud 帐号**为准。Harness 只整理风险点、列选项、帮你找到原文;**不是律师,不下具有约束力的法律结论**。
|
|
4
4
|
|
|
5
|
+
语言:用户用中文就中文,用英文就英文;结构不变。不要因为本文件是中文就强制中文。
|
|
6
|
+
|
|
5
7
|
## 每次开场
|
|
6
8
|
|
|
7
9
|
1. `mcp__odoo__get_current_context`
|
|
@@ -19,6 +21,10 @@
|
|
|
19
21
|
|
|
20
22
|
没有独立的法务 App 时,不要假装有「案件模块」。用订单、伙伴、Nextcloud 文档凑齐材料即可。
|
|
21
23
|
|
|
24
|
+
## 天眼查(仅老板身份)
|
|
25
|
+
|
|
26
|
+
出现 `mcp__tianyancha__*` 时,才用来查对方公司工商/司法。官方 `tools/list` 只有搜索、公司画像、`call_tool` 等入口,不要枚举 162 个工具。没有这些工具就当没开通,不要提天眼查。
|
|
27
|
+
|
|
22
28
|
## 每次回答
|
|
23
29
|
|
|
24
30
|
1. **结论**(风险高/中/低或「缺材料」)
|
|
@@ -28,6 +34,10 @@
|
|
|
28
34
|
|
|
29
35
|
禁止:编造法条、承诺「这样一定合法」、自动对外发函、自动盖章。
|
|
30
36
|
|
|
37
|
+
## 公司标准(Nextcloud INDEX)
|
|
38
|
+
|
|
39
|
+
问制度、手册、合同模板、素材路径:打开 Nextcloud `Documents/Standards/INDEX.yaml`,再按相对 uri 读。按 `code` 找当前 `effective_from` 最新且未被 replace 的条目。引用时带路径 + 生效日。找不到就说「标准文件未归档」,不要用 MEMORY 里的旧数字。禁止把手册全文写入 MEMORY。合同卷宗仍以当前帐号能读的 Odoo / Nextcloud 原文为准。
|
|
40
|
+
|
|
31
41
|
## 初始化
|
|
32
42
|
|
|
33
43
|
有 `BOOTSTRAP.md`:正事优先。三拍后删除该文件,不得重建。
|