weaver-work-cli 0.1.4 → 0.1.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/dist/internal/e10/request-runtime.js +3 -2
- package/dist/shortcuts/index.js +4 -0
- package/dist/shortcuts/meeting/continuation.js +70 -0
- package/dist/shortcuts/meeting/errors.js +63 -0
- package/dist/shortcuts/meeting/host.js +167 -0
- package/dist/shortcuts/meeting/index.js +123 -0
- package/dist/shortcuts/meeting/manifest.js +64 -0
- package/dist/shortcuts/meeting/operations/catalogs.js +58 -0
- package/dist/shortcuts/meeting/operations/change.js +242 -0
- package/dist/shortcuts/meeting/operations/conflicts.js +142 -0
- package/dist/shortcuts/meeting/operations/create.js +349 -0
- package/dist/shortcuts/meeting/operations/env.js +191 -0
- package/dist/shortcuts/meeting/operations/lifecycle.js +139 -0
- package/dist/shortcuts/meeting/operations/meetings.js +73 -0
- package/dist/shortcuts/meeting/operations/receipts.js +195 -0
- package/dist/shortcuts/meeting/operations/registry.js +47 -0
- package/dist/shortcuts/meeting/operations/rooms.js +132 -0
- package/dist/shortcuts/meeting/operations/shared.js +112 -0
- package/dist/shortcuts/meeting/operations/signs.js +41 -0
- package/dist/shortcuts/meeting/operations/types.js +25 -0
- package/dist/shortcuts/meeting/operations.js +19 -0
- package/dist/shortcuts/yimiaoban/continuation.js +70 -0
- package/dist/shortcuts/yimiaoban/errors.js +61 -0
- package/dist/shortcuts/yimiaoban/host.js +469 -0
- package/dist/shortcuts/yimiaoban/index.js +271 -0
- package/dist/shortcuts/yimiaoban/manifest.js +28 -0
- package/dist/shortcuts/yimiaoban/operations/file-user.js +288 -0
- package/dist/shortcuts/yimiaoban/operations/group-read.js +477 -0
- package/dist/shortcuts/yimiaoban/operations/group-write.js +591 -0
- package/dist/shortcuts/yimiaoban/operations/msg-parse.js +429 -0
- package/dist/shortcuts/yimiaoban/operations/msg-sync.js +519 -0
- package/dist/shortcuts/yimiaoban/operations/msg-write.js +593 -0
- package/dist/shortcuts/yimiaoban/operations/person.js +102 -0
- package/dist/shortcuts/yimiaoban/operations/registry.js +38 -0
- package/dist/shortcuts/yimiaoban/operations/session.js +437 -0
- package/dist/shortcuts/yimiaoban/operations/shared.js +236 -0
- package/dist/shortcuts/yimiaoban/operations/types.js +27 -0
- package/dist/shortcuts/yimiaoban/operations/write-util.js +78 -0
- package/dist/shortcuts/yimiaoban/operations.js +8 -0
- package/docs/_catalog.md +6 -0
- package/docs/meeting.md +48 -0
- package/docs/yimiaoban.md +86 -0
- package/package.json +1 -1
- package/skill-template/business-info.json +4 -1
- package/skill-template/domains/meeting.md +3 -0
- package/skill-template/domains/yimiaoban.md +21 -0
- package/skills/weaver-e10-calendar/SKILL.md +1 -0
- package/skills/weaver-e10-esb/SKILL.md +1 -0
- package/skills/weaver-e10-esb/references/source-manifest.json +3 -3
- package/skills/weaver-e10-hrm/SKILL.md +1 -0
- package/skills/weaver-e10-jiuchuanhui/SKILL.md +1 -0
- package/skills/weaver-e10-jucailin/SKILL.md +1 -0
- package/skills/weaver-e10-mail/SKILL.md +1 -0
- package/skills/weaver-e10-meeting/SKILL.md +106 -0
- package/skills/weaver-e10-meeting/product.json +8 -0
- package/skills/weaver-e10-meeting/references/meeting-change.md +67 -0
- package/skills/weaver-e10-meeting/references/meeting-create.md +52 -0
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +57 -0
- package/skills/weaver-e10-meeting/references/meeting-queries.md +61 -0
- package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +48 -0
- package/skills/weaver-e10-meeting/references/meeting-update.md +7 -0
- package/skills/weaver-e10-meeting/references/source-manifest.json +50 -0
- package/skills/weaver-e10-plan/SKILL.md +1 -0
- package/skills/weaver-e10-plan/references/source-manifest.json +3 -3
- package/skills/weaver-e10-qiyecheng/SKILL.md +1 -0
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +3 -3
- package/skills/weaver-e10-shared/SKILL.md +4 -0
- package/skills/weaver-e10-skill-maker/SKILL.md +1 -0
- package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +1 -1
- package/skills/weaver-e10-wenshuding/SKILL.md +1 -0
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +5 -5
- package/skills/weaver-e10-yimiaoban/SKILL.md +104 -0
- package/skills/weaver-e10-yimiaoban/product.json +8 -0
- package/skills/weaver-e10-yimiaoban/references/ding-write.md +68 -0
- package/skills/weaver-e10-yimiaoban/references/error-codes.md +85 -0
- package/skills/weaver-e10-yimiaoban/references/field-resolution.md +46 -0
- package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +54 -0
- package/skills/weaver-e10-yimiaoban/references/group-read.md +55 -0
- package/skills/weaver-e10-yimiaoban/references/group-write.md +72 -0
- package/skills/weaver-e10-yimiaoban/references/msg-read.md +59 -0
- package/skills/weaver-e10-yimiaoban/references/msg-write.md +64 -0
- package/skills/weaver-e10-yimiaoban/references/person.md +44 -0
- package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +61 -0
- package/skills/weaver-e10-yimiaoban/references/session-sysmsg.md +47 -0
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +485 -0
- package/skills/weaver-e10-ziguanjia/SKILL.md +1 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { ymbValidationError, ymbBusinessError } from '../errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* 禁止出现在输入对象中的键:
|
|
4
|
+
* - 原型污染防护:`__proto__`/`constructor`/`prototype`
|
|
5
|
+
* - 操作人红线:`user`/`sender`/`operator`(操作者由会话 eteamsid 识别,请求体一律不传)
|
|
6
|
+
*/
|
|
7
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype', 'user', 'sender', 'operator']);
|
|
8
|
+
export function asObject(value) {
|
|
9
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
10
|
+
throw ymbValidationError('input_not_object', '输入必须是 JSON 对象');
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
export function assertNoForbiddenKeys(input) {
|
|
15
|
+
for (const key of Object.keys(input)) {
|
|
16
|
+
if (FORBIDDEN_KEYS.has(key)) {
|
|
17
|
+
throw ymbValidationError('forbidden_key', `输入包含非法字段:${key}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** 校验 uid/cid 非空且非 0(易秒办红线:uid/cid 不得为 0)。 */
|
|
22
|
+
export function assertNonZeroId(value, field) {
|
|
23
|
+
if (value === undefined || value === null || value === '') {
|
|
24
|
+
throw ymbValidationError('id_required', `${field} 必填`);
|
|
25
|
+
}
|
|
26
|
+
const text = String(value).trim();
|
|
27
|
+
if (!/^\d+$/.test(text) || text === '0') {
|
|
28
|
+
throw ymbValidationError('id_invalid', `${field} 必须是非 0 数字 ID`);
|
|
29
|
+
}
|
|
30
|
+
return text;
|
|
31
|
+
}
|
|
32
|
+
/** 拆分逗号分隔 id 列表(uint64 按字符串保留),去空。 */
|
|
33
|
+
export function splitIds(value, field) {
|
|
34
|
+
if (value === undefined || value === null || value === '') {
|
|
35
|
+
throw ymbValidationError('id_list_required', `${field} 必填`);
|
|
36
|
+
}
|
|
37
|
+
const list = String(value).split(',').map((s) => s.trim()).filter(Boolean);
|
|
38
|
+
if (list.length === 0) {
|
|
39
|
+
throw ymbValidationError('id_list_empty', `${field} 不能为空`);
|
|
40
|
+
}
|
|
41
|
+
for (const item of list) {
|
|
42
|
+
if (!/^\d+$/.test(item) || item === '0') {
|
|
43
|
+
throw ymbValidationError('id_invalid', `${field} 含非法 id(必须非 0 数字):${item}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return list;
|
|
47
|
+
}
|
|
48
|
+
/** 无符号整数转换(uint32 等),拒绝小数/负数。 */
|
|
49
|
+
export function toUint(value, field) {
|
|
50
|
+
if (value === undefined || value === null || value === '')
|
|
51
|
+
return undefined;
|
|
52
|
+
const numeric = Number(value);
|
|
53
|
+
if (!Number.isInteger(numeric) || numeric < 0) {
|
|
54
|
+
throw ymbValidationError('number_invalid', `${field} 必须是非负整数`);
|
|
55
|
+
}
|
|
56
|
+
return numeric;
|
|
57
|
+
}
|
|
58
|
+
/** 正整数转换。 */
|
|
59
|
+
export function toPositiveInt(value, field) {
|
|
60
|
+
if (value === undefined || value === null || value === '')
|
|
61
|
+
return undefined;
|
|
62
|
+
const numeric = Number(value);
|
|
63
|
+
if (!Number.isInteger(numeric) || numeric <= 0) {
|
|
64
|
+
throw ymbValidationError('number_invalid', `${field} 必须是正整数`);
|
|
65
|
+
}
|
|
66
|
+
return numeric;
|
|
67
|
+
}
|
|
68
|
+
/** 移除值为 undefined 的键。 */
|
|
69
|
+
export function compact(body) {
|
|
70
|
+
for (const key of Object.keys(body)) {
|
|
71
|
+
if (body[key] === undefined)
|
|
72
|
+
delete body[key];
|
|
73
|
+
}
|
|
74
|
+
return body;
|
|
75
|
+
}
|
|
76
|
+
/** 时间(unix 秒)→ 消息 id 最小/最大值(fwutils MakeMinAndMaxIdByTm)。返回字符串(超 JS 安全整数)。 */
|
|
77
|
+
export function makeMinMaxIdByTm(tmSec) {
|
|
78
|
+
if (!tmSec || tmSec <= 0)
|
|
79
|
+
return { min: '0', max: '0' };
|
|
80
|
+
const base = BigInt(Math.floor(tmSec)) * 1000000000n;
|
|
81
|
+
return { min: base.toString(), max: (base + 999999999n).toString() };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 解析时间参数为 unix 秒(按本地时区):
|
|
85
|
+
* - 10 位纯数字:视为 unix 秒
|
|
86
|
+
* - YYYY-MM-DD:isEnd=false → 当天 00:00:00;isEnd=true → 当天 23:59:59
|
|
87
|
+
* - YYYY-MM-DD HH:mm[:ss]
|
|
88
|
+
*/
|
|
89
|
+
export function parseTimeToSec(arg, isEnd) {
|
|
90
|
+
if (arg === undefined || arg === null || arg === '')
|
|
91
|
+
return 0;
|
|
92
|
+
const s = String(arg).trim();
|
|
93
|
+
if (/^\d{10}$/.test(s))
|
|
94
|
+
return Number(s);
|
|
95
|
+
const m = s.match(/^(\d{4})-(\d{1,2})-(\d{1,2})(?:[ T](\d{1,2}):(\d{1,2})(?::(\d{1,2}))?)?$/);
|
|
96
|
+
if (!m) {
|
|
97
|
+
throw ymbValidationError('time_invalid', `无法解析时间参数: ${s}(支持 unix 秒 / YYYY-MM-DD / YYYY-MM-DD HH:mm:ss)`);
|
|
98
|
+
}
|
|
99
|
+
const hh = m[4] !== undefined ? Number(m[4]) : (isEnd ? 23 : 0);
|
|
100
|
+
const mm = m[5] !== undefined ? Number(m[5]) : (isEnd ? 59 : 0);
|
|
101
|
+
const ss = m[6] !== undefined ? Number(m[6]) : (isEnd ? 59 : 0);
|
|
102
|
+
return Math.floor(new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), hh, mm, ss).getTime() / 1000);
|
|
103
|
+
}
|
|
104
|
+
/** 当天 00:00:00 / 23:59:59 的 unix 秒(本地时区)。 */
|
|
105
|
+
export function todayRange() {
|
|
106
|
+
const now = new Date();
|
|
107
|
+
const start = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);
|
|
108
|
+
const end = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59);
|
|
109
|
+
return { fromSec: Math.floor(start.getTime() / 1000), toSec: Math.floor(end.getTime() / 1000) };
|
|
110
|
+
}
|
|
111
|
+
/** 时间展示统一格式:YYYY/M/D HH:MM:SS(unix 秒输入)。 */
|
|
112
|
+
export function formatFullTime(ts) {
|
|
113
|
+
if (ts === undefined || ts === null || ts === '')
|
|
114
|
+
return '-';
|
|
115
|
+
const d = new Date(Number(ts) * 1000);
|
|
116
|
+
if (Number.isNaN(d.getTime()))
|
|
117
|
+
return '-';
|
|
118
|
+
const p = (n) => String(n).padStart(2, '0');
|
|
119
|
+
return `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
|
|
120
|
+
}
|
|
121
|
+
/** 校验枚举取值。 */
|
|
122
|
+
export function assertEnum(value, allowed, field) {
|
|
123
|
+
const text = typeof value === 'string' ? value : String(value);
|
|
124
|
+
if (!allowed.includes(text)) {
|
|
125
|
+
throw ymbValidationError('enum_invalid', `${field} 取值必须是 ${allowed.join(' / ')} 之一`);
|
|
126
|
+
}
|
|
127
|
+
return text;
|
|
128
|
+
}
|
|
129
|
+
/** 从 IM 响应 JSON 中提取 actionMsg(路径多样兼容)。 */
|
|
130
|
+
export function findActionMsg(value) {
|
|
131
|
+
const candidate = value?.data?.actionMsg ?? value?.actionMsg;
|
|
132
|
+
if (candidate === undefined || candidate === null)
|
|
133
|
+
return null;
|
|
134
|
+
return {
|
|
135
|
+
code: candidate.code !== undefined ? candidate.code : 0,
|
|
136
|
+
message: candidate.message ?? candidate.msg ?? '',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/** 判断 IM 业务是否成功(actionMsg.code === 0)。失败抛 business_error。 */
|
|
140
|
+
export function assertImOk(value, actionLabel) {
|
|
141
|
+
const msg = findActionMsg(value);
|
|
142
|
+
if (msg === null) {
|
|
143
|
+
// 无 actionMsg 时回退顶层 code===200 && status 判定(sendDing 等路径)
|
|
144
|
+
if (Number(value?.code) === 200 && value?.status)
|
|
145
|
+
return;
|
|
146
|
+
throw ymbBusinessError('business_error', `${actionLabel}失败:缺少 actionMsg`, {
|
|
147
|
+
details: { raw: value },
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
if (Number(msg.code) === 0)
|
|
151
|
+
return;
|
|
152
|
+
const message = msg.message || `${actionLabel}失败(actionMsg.code=${msg.code})`;
|
|
153
|
+
throw ymbBusinessError('action_failed', message, { code: msg.code });
|
|
154
|
+
}
|
|
155
|
+
/** 取出响应 data 主体(兼容 data.data.data / data.data 等路径)。 */
|
|
156
|
+
export function unwrapInner(value) {
|
|
157
|
+
return value?.data?.data ?? value?.data;
|
|
158
|
+
}
|
|
159
|
+
/** 群成员条目判定(成员行至少含 uid 或 user 身份)。 */
|
|
160
|
+
function isMemberRow(value) {
|
|
161
|
+
return Boolean(value) && typeof value === 'object' && (value.uid !== undefined || value.user !== undefined);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* 从 getGroupUsers 响应主体提取成员数组。
|
|
165
|
+
* 兼容服务端历史形态:`users` / `members` / `datas`(含 `datas[].datas` 嵌套),
|
|
166
|
+
* 避免因响应包裹层不同导致「群内没有可接收成员」这类误判。
|
|
167
|
+
*/
|
|
168
|
+
export function extractGroupMembers(inner) {
|
|
169
|
+
if (!inner || typeof inner !== 'object')
|
|
170
|
+
return [];
|
|
171
|
+
for (const key of ['users', 'members']) {
|
|
172
|
+
const list = inner[key];
|
|
173
|
+
if (Array.isArray(list) && list.some(isMemberRow))
|
|
174
|
+
return list;
|
|
175
|
+
}
|
|
176
|
+
const datas = Array.isArray(inner.datas) ? inner.datas : [];
|
|
177
|
+
if (datas.some(isMemberRow))
|
|
178
|
+
return datas;
|
|
179
|
+
const nested = [];
|
|
180
|
+
for (const group of datas) {
|
|
181
|
+
if (Array.isArray(group?.datas))
|
|
182
|
+
nested.push(...group.datas);
|
|
183
|
+
}
|
|
184
|
+
return nested;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* 当前登录用户 uid(易秒办 IM uid = E10 登录 userId)。
|
|
188
|
+
* 仅用于展示层识别「我」,请求体依旧不携带任何操作人字段。
|
|
189
|
+
*/
|
|
190
|
+
export async function resolveAuthUid(host) {
|
|
191
|
+
try {
|
|
192
|
+
const session = await host.getSession();
|
|
193
|
+
return str(session?.userId);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return '';
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** 消息页最小 ser_msgid(`hasMore` 时作为下一页 `start` 锚点;服务端返回含边界那条,需按 msgid 去重)。 */
|
|
200
|
+
export function minMsgId(messages) {
|
|
201
|
+
let min = null;
|
|
202
|
+
for (const message of messages) {
|
|
203
|
+
const id = str(message?.msgid);
|
|
204
|
+
if (!/^\d+$/.test(id))
|
|
205
|
+
continue;
|
|
206
|
+
if (min === null || BigInt(id) < BigInt(min))
|
|
207
|
+
min = id;
|
|
208
|
+
}
|
|
209
|
+
return min ?? '';
|
|
210
|
+
}
|
|
211
|
+
/** 枚举值转成 string(可能为字符串数字)。 */
|
|
212
|
+
export function str(value) {
|
|
213
|
+
if (value === undefined || value === null)
|
|
214
|
+
return '';
|
|
215
|
+
return String(value);
|
|
216
|
+
}
|
|
217
|
+
/** 解析消息 JSON 字符串或对象。 */
|
|
218
|
+
export function parseMsg(value) {
|
|
219
|
+
if (!value)
|
|
220
|
+
return null;
|
|
221
|
+
if (typeof value === 'string') {
|
|
222
|
+
try {
|
|
223
|
+
return JSON.parse(value);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (typeof value === 'object')
|
|
230
|
+
return value;
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* 媒体文件上传所需文件大小上限(消息图片/文件常规场景按服务端约束执行)。
|
|
235
|
+
*/
|
|
236
|
+
export const MAX_UPLOAD_BYTES = 1024 * 1024 * 200;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const READ = 'read';
|
|
2
|
+
export const WRITE = 'write';
|
|
3
|
+
export function ymbSuccess(action, data, meta) {
|
|
4
|
+
const payload = { ok: true, action, data };
|
|
5
|
+
if (meta && Object.keys(meta).length > 0)
|
|
6
|
+
payload.meta = meta;
|
|
7
|
+
return payload;
|
|
8
|
+
}
|
|
9
|
+
/** 构造「对象类型 + 严格禁止额外字段」的 JSON Schema。 */
|
|
10
|
+
export function schemaOf(properties, options = {}) {
|
|
11
|
+
return {
|
|
12
|
+
type: 'object',
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
properties,
|
|
15
|
+
...(options.required?.length ? { required: options.required } : {}),
|
|
16
|
+
...(options.description ? { description: options.description } : {}),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export const SCHEMA_INTEGER_POSITIVE = { type: 'integer', minimum: 1 };
|
|
20
|
+
export const SCHEMA_NUMBER_POSITIVE = { type: 'number', exclusiveMinimum: 0 };
|
|
21
|
+
export const SCHEMA_ID = { oneOf: [{ type: 'integer' }, { type: 'string', pattern: '^\\d+$' }] };
|
|
22
|
+
export const SCHEMA_ID_LIST = { type: 'array', items: SCHEMA_ID };
|
|
23
|
+
export const SCHEMA_STRING = { type: 'string' };
|
|
24
|
+
export const SCHEMA_STRING_LIST = { type: 'array', items: { type: 'string' } };
|
|
25
|
+
export const SCHEMA_BOOLEAN = { type: 'boolean' };
|
|
26
|
+
export const SCHEMA_INTEGER = { type: 'integer' };
|
|
27
|
+
export const SCHEMA_NUMBER = { type: 'number' };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { ymbConfirmationError, ymbValidationError } from '../errors.js';
|
|
3
|
+
import { ymbSuccess } from './types.js';
|
|
4
|
+
import { assertNoForbiddenKeys } from './shared.js';
|
|
5
|
+
function fingerprint(value) {
|
|
6
|
+
return createHash('sha256').update(JSON.stringify(value ?? null)).digest('hex').slice(0, 32);
|
|
7
|
+
}
|
|
8
|
+
function requireConfirm(action) {
|
|
9
|
+
throw ymbConfirmationError(action, { hint: '重新调用时传入 confirm=true 与 prepare 返回的 continuation' });
|
|
10
|
+
}
|
|
11
|
+
async function verifyLease(continuationToken, action, env) {
|
|
12
|
+
const lease = await env.continuation.verify(continuationToken, action);
|
|
13
|
+
const session = await env.host.getSession();
|
|
14
|
+
if (lease.baseUrl !== session.baseUrl || lease.profile !== session.profile || lease.userId !== session.userId) {
|
|
15
|
+
throw ymbValidationError('context_mismatch', '确认上下文已变化(租户或登录账号不同),请重新执行 prepare');
|
|
16
|
+
}
|
|
17
|
+
return lease;
|
|
18
|
+
}
|
|
19
|
+
export function makeWritePair(options) {
|
|
20
|
+
return {
|
|
21
|
+
async prepare(args, env) {
|
|
22
|
+
assertNoForbiddenKeys(args);
|
|
23
|
+
const plan = await options.plan(args, env);
|
|
24
|
+
const session = await env.host.getSession();
|
|
25
|
+
const token = await env.continuation.issue({
|
|
26
|
+
operation: options.action,
|
|
27
|
+
baseUrl: session.baseUrl,
|
|
28
|
+
profile: session.profile,
|
|
29
|
+
userId: session.userId,
|
|
30
|
+
snapshotFingerprint: fingerprint(plan.snapshot),
|
|
31
|
+
plan: plan.snapshot,
|
|
32
|
+
});
|
|
33
|
+
return ymbSuccess(`${options.action}.prepare`, {
|
|
34
|
+
summary: plan.summary,
|
|
35
|
+
continuation: token,
|
|
36
|
+
hint: '确认无误后调用 ' + options.action + '.apply,传 confirm:true 与 continuation',
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
async apply(args, env) {
|
|
40
|
+
assertNoForbiddenKeys(args);
|
|
41
|
+
if (args.confirm !== true)
|
|
42
|
+
requireConfirm(options.action);
|
|
43
|
+
const lease = await verifyLease(String(args.continuation ?? ''), options.action, env);
|
|
44
|
+
const plan = lease.plan;
|
|
45
|
+
if (lease.snapshotFingerprint !== fingerprint(plan)) {
|
|
46
|
+
throw ymbValidationError('target_changed', '写入目标/内容与 prepare 时不一致,请重新执行 prepare');
|
|
47
|
+
}
|
|
48
|
+
const data = await options.execute(plan, env);
|
|
49
|
+
return ymbSuccess(`${options.action}.apply`, data);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** fileObj → 图片消息 img 对象。 */
|
|
54
|
+
export function fileObjToImg(fileObj) {
|
|
55
|
+
const img = { src: String(fileObj.id || fileObj.fileid) };
|
|
56
|
+
if (fileObj.name)
|
|
57
|
+
img.nm = String(fileObj.name);
|
|
58
|
+
if (fileObj.type)
|
|
59
|
+
img.t = String(fileObj.type);
|
|
60
|
+
if (fileObj.imgWidth !== undefined && fileObj.imgWidth !== null)
|
|
61
|
+
img.w = String(fileObj.imgWidth);
|
|
62
|
+
if (fileObj.imgHeight !== undefined && fileObj.imgHeight !== null)
|
|
63
|
+
img.h = String(fileObj.imgHeight);
|
|
64
|
+
if (fileObj.size !== undefined && fileObj.size !== null)
|
|
65
|
+
img.s = String(fileObj.size);
|
|
66
|
+
return img;
|
|
67
|
+
}
|
|
68
|
+
/** fileObj → 文件消息 file 对象。 */
|
|
69
|
+
export function fileObjToFile(fileObj) {
|
|
70
|
+
const f = { id: String(fileObj.id || fileObj.fileid) };
|
|
71
|
+
if (fileObj.name)
|
|
72
|
+
f.nm = String(fileObj.name);
|
|
73
|
+
if (fileObj.type)
|
|
74
|
+
f.t = String(fileObj.type);
|
|
75
|
+
if (fileObj.size !== undefined && fileObj.size !== null)
|
|
76
|
+
f.s = String(fileObj.size);
|
|
77
|
+
return f;
|
|
78
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { getYmbOperation } from './operations/registry.js';
|
|
2
|
+
import { asObject, assertNoForbiddenKeys } from './operations/shared.js';
|
|
3
|
+
export async function executeYmbOperation(operation, rawInput, context) {
|
|
4
|
+
const definition = getYmbOperation(operation);
|
|
5
|
+
const input = asObject(rawInput);
|
|
6
|
+
assertNoForbiddenKeys(input);
|
|
7
|
+
return definition.handler(input, context);
|
|
8
|
+
}
|
package/docs/_catalog.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
| Agent 共享规则、安装检查、JSON 输出、高风险写入 | `skills/weaver-e10-shared/SKILL.md` |
|
|
9
9
|
| Agent 共享规则细节:安装、E10 登录、JSON 输出、写入协议 | `skills/weaver-e10-shared/references/` |
|
|
10
10
|
| 业票通发票管理、报销填单、智能开票、invoice operation、写操作 prepare/apply | `docs/invoice.md` |
|
|
11
|
+
| E10 会议管理(标准版:查询/冲突/预约/回执/签到)、meeting operation、写操作 prepare/apply | `docs/meeting.md` |
|
|
11
12
|
| 聚才林人事云(人事档案/出勤/薪酬)、ehr operation、写操作 prepare/apply | `docs/ehr.md` |
|
|
12
13
|
| 齐业成费控中心(预算/费用中心/借款管理/发票核销)、fna operation、提醒还款与催票 prepare/apply | `docs/fna.md` |
|
|
13
14
|
| 文书定档案管理(全宗/检索/借阅车/借阅单/发起借阅/预归档上传)、wenshuding operation | `docs/wenshuding.md` |
|
|
@@ -27,4 +28,9 @@
|
|
|
27
28
|
| Agent 调用计划报告 CLI 的具体 reference | `skills/weaver-e10-plan/references/` |
|
|
28
29
|
| Agent 调用 ESB 动作流 CLI 的入口路由 | `skills/weaver-e10-esb/SKILL.md` |
|
|
29
30
|
| Agent 调用 ESB 动作流 CLI 的具体 reference | `skills/weaver-e10-esb/references/` |
|
|
31
|
+
| Agent 调用会议管理 CLI 的入口路由 | `skills/weaver-e10-meeting/SKILL.md` |
|
|
32
|
+
| Agent 调用会议管理 CLI 的具体 reference | `skills/weaver-e10-meeting/references/` |
|
|
33
|
+
| 易秒办即时通讯(消息/群组/会话/系统消息)、yimiaoban operation、写操作 prepare/apply | `docs/yimiaoban.md` |
|
|
34
|
+
| Agent 调用易秒办 CLI 的入口路由 | `skills/weaver-e10-yimiaoban/SKILL.md` |
|
|
35
|
+
| Agent 调用易秒办 CLI 的具体 reference | `skills/weaver-e10-yimiaoban/references/` |
|
|
30
36
|
| 将新业务模块文档或代码同步转换为 weaver-work-cli 业务 CLI 与 Skill、检测源资料更新 | `skills/weaver-e10-skill-maker/SKILL.md` |
|
package/docs/meeting.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# meeting:E10 会议管理(标准版)
|
|
2
|
+
|
|
3
|
+
## 模块来源
|
|
4
|
+
|
|
5
|
+
由 `weaver-e10-skill-maker` 按 standalone 会议 Skill(weaver-e10-meeting v2.4.2)的接口契约生成,v1 覆盖**标准版(Java REST)**能力;EB 版(eBuilder formdata)链路列入禁用边界,待后续版本。
|
|
6
|
+
|
|
7
|
+
## 命令结构
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
weaver-work-cli meeting schema # 输出 operation manifest
|
|
11
|
+
weaver-work-cli meeting run <operation> --input-json '<json>'
|
|
12
|
+
weaver-work-cli meeting today # 今天会议(meeting.list 薄包装)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## operation 表
|
|
16
|
+
|
|
17
|
+
| operation | 风险 | 说明 |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| `meeting.env.detect` | read | EB/标准模式探测(EB 冒烟优先,失败回退标准) |
|
|
20
|
+
| `meeting.calendar.base` | read | 建会前置判断(onlyFlowCreate/工作流配置) |
|
|
21
|
+
| `meeting.list` | read | 会议列表(空 body 拉全量 + `filterDate` 客户端过滤) |
|
|
22
|
+
| `meeting.detail.field` | read | 会议详情表单结构与 options |
|
|
23
|
+
| `meeting.room.list` | read | 会议室列表(带时间范围返回 `disabled` 占用判断) |
|
|
24
|
+
| `meeting.room.usage` | read | 会议室占用视图(bywhat 2=月 3=周 4=日) |
|
|
25
|
+
| `meeting.type.list` | read | 会议类型列表(可选 count) |
|
|
26
|
+
| `meeting.conflict.room` | read | 会议室冲突(cansub 语义) |
|
|
27
|
+
| `meeting.conflict.member` | read | 参会人员冲突 |
|
|
28
|
+
| `meeting.conflict.roomAttribute` | read | 会议室属性冲突 |
|
|
29
|
+
| `meeting.create.prepare` | read-before-write | 归一化 + 建会路径检查 + 强制冲突检测 + continuation |
|
|
30
|
+
| `meeting.create.apply` | high-risk-write | `operateMeetingByType SUBMIT`(需 confirm + continuation) |
|
|
31
|
+
| `meeting.receipt.list` | read | 回执列表(isMobile 托管默认 false) |
|
|
32
|
+
| `meeting.receipt.update.prepare` | read-before-write | 回查回执记录 id + 预览 |
|
|
33
|
+
| `meeting.receipt.update.apply` | high-risk-write | 回执更新(需 confirm + continuation) |
|
|
34
|
+
| `meeting.sign.list` | read | 签到记录 + 已签/未签统计 |
|
|
35
|
+
|
|
36
|
+
## 关键契约(源资料实测坑位)
|
|
37
|
+
|
|
38
|
+
- 新建会议 `operateType=SUBMIT` + `id:""` → 正常状态;`ADD` 只生成草稿,勿用。
|
|
39
|
+
- 冲突处理看接口返回 `cansub`:false=禁止提交(直接拒绝);true=仅提醒(建议换时间/地点);检测失败视为冲突。**绝不提供"强制新建"选项**。
|
|
40
|
+
- 周期会议 `finishAt` 必填(仅 1=次数 / 2=日期,禁止 0);`repeatDesc` 由 CLI 自动拼接。
|
|
41
|
+
- 回执更新必须传回执记录 `id`(prepare 自动按 `memberId` 回查);`attendStatus` 0/1/2。
|
|
42
|
+
- 超 2^53 的 id 一律字符串传递。
|
|
43
|
+
|
|
44
|
+
## 已知限制(withheld)
|
|
45
|
+
|
|
46
|
+
- EB 版业务链路(create_meeting/三件套/议题/纪要/报表)未实现。
|
|
47
|
+
- `onlyFlowCreate=1`、周期会议工作流需要 workflow 集成,`create.prepare` 会主动拒绝。
|
|
48
|
+
- 签到二维码(getQrCode 入参未确认)、签到写、会议室/类型管理、会议变更/取消/结束未实现。
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 易秒办即时通讯(yimiaoban)
|
|
2
|
+
|
|
3
|
+
`yimiaoban` 是 E10 易秒办即时通讯的聚合命令,覆盖**消息(msg)**、**必达(ding)**、**群组(group)**、**会话(session)**、**系统消息(sysmsg)**,以及支撑能力人员解析(person)、文件上传/预览(file)、用户状态(user)、i18n 标签(i18n)。
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
weaver-work-cli yimiaoban --help
|
|
7
|
+
weaver-work-cli yimiaoban schema
|
|
8
|
+
weaver-work-cli --json yimiaoban run <operation> --input -
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`schema` 是能力清单的唯一事实来源,包含每个 operation 的 `inputSchema`、`risk`、`requiresConfirmation`。
|
|
12
|
+
|
|
13
|
+
## 实现位置
|
|
14
|
+
|
|
15
|
+
| 路径 | 职责 |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `src/shortcuts/yimiaoban/index.ts` | 命令注册与 JSON envelope |
|
|
18
|
+
| `src/shortcuts/yimiaoban/manifest.ts` | `schema` 契约 |
|
|
19
|
+
| `src/shortcuts/yimiaoban/host.ts` | E10 会话桥接、认证头、executeIm/文件上传、hrm 人员解析、i18n、媒体 URL |
|
|
20
|
+
| `src/shortcuts/yimiaoban/continuation.ts` | 写操作确认链的 HMAC-SHA256 token |
|
|
21
|
+
| `src/shortcuts/yimiaoban/operations/` | 按业务域拆分的 operation 实现 |
|
|
22
|
+
| `src/shortcuts/yimiaoban/operations/registry.ts` | operation 注册表与去重校验 |
|
|
23
|
+
|
|
24
|
+
## 认证
|
|
25
|
+
|
|
26
|
+
复用 `src/internal/e10` 的 E10 会话(`requireE10Session`),请求自动携带 `Cookie`、`eteamsid` 与 `X-Requested-With: XMLHttpRequest`。IM 接口前缀 `/api/em/msg/executeIm`,必达例外走 `/api/em/msg/createDing`。业务代码不接触认证目录,路径强制以 `/api/` 开头。
|
|
27
|
+
|
|
28
|
+
## 红线(模块内强制)
|
|
29
|
+
|
|
30
|
+
- 请求体禁止传操作人字段(user/sender/creator/operator),操作者由 `eteamsid` 识别。
|
|
31
|
+
- 人名一律走 hrm:`/api/hrm/common/getEmployeeByIds` 解析,禁止用 IM 群成员 `name` 字段。
|
|
32
|
+
- uid/cid/群 id 是 uint64,一律字符串传输且非 0。
|
|
33
|
+
- 过滤全部服务端完成;分页单页默认 20(群搜索 100),不自动翻页拉全量。
|
|
34
|
+
- 时间范围查询换算为消息 id 区间(`resolveStartEnd`/`makeMinMaxIdByTm`)。
|
|
35
|
+
- 全空白文本不算内容(拒绝发送空白消息);普通请求 15 秒超时即失败不重试(上传 15/60 秒)。
|
|
36
|
+
- 媒体只给需登录态的 URL,真要看内容用 `file.download` 落地到本地(父目录须存在、拒绝覆盖)。
|
|
37
|
+
- 消息内容完整透出,不截断;展示规则见 Skill `safety-boundaries.md`。
|
|
38
|
+
|
|
39
|
+
## 消息拉取与展示
|
|
40
|
+
|
|
41
|
+
`msg.sync.single`(对方 `fromUid`+`fromCid` 必填)、`msg.sync.group`(`groupId` 必填,type=0 固定)为倒序单页拉取;`actionMsg.code=1303` 表示无聊天记录,按成功空列表处理,并返回 `empty:true` + `emptyReason`(区分当天无消息/时间范围无消息/会话无历史)。单页有更多数据时返回 `nextStart`(下页 `start` 锚点)与 `dedupeHint`(边界消息会重复,需按 `msgid` 去重)。
|
|
42
|
+
|
|
43
|
+
返回的 `messages[]` 已按 msgParser 语义解析为结构化行:
|
|
44
|
+
|
|
45
|
+
- `sender`:自己显示「我」(按会话 uid 判定),他人优先消息 `sname`、其次 hrm 姓名、最后回退 uid;`time`;`typeName`;`content`:完整正文(@ 提及已还原、媒体显示 `[图片]名称`/`[视频]名称`/`[文件]名称`)。
|
|
46
|
+
- `fileName`:媒体消息原始文件名(便于单独渲染);富文本分段解析支持图片/文件/视频/语音/位置。
|
|
47
|
+
- `media`:图片/视频/文件的预览与下载 URL(weappAuthStr 构造,需登录态)。
|
|
48
|
+
- `must`:必达标记。会话副标题媒体消息按 `[类型]名称` 展示,必达保留 `[必达]` 前缀。
|
|
49
|
+
|
|
50
|
+
## 写协议与 continuation
|
|
51
|
+
|
|
52
|
+
所有写操作(send/withdraw/top.set/ding/group 系列)统一 `prepare → apply`:
|
|
53
|
+
|
|
54
|
+
- `prepare`:只读校验(成员解析、源消息读取、接收人计算),返回 `summary` + `continuation`(HMAC-SHA256 签名,10 分钟有效,含 baseUrl/profile/userId 指纹与 snapshot 指纹)。
|
|
55
|
+
- `apply`:必须 `confirm:true` + 有效 continuation;校验租户/账号一致(`context_mismatch`)与目标指纹(`target_changed`);执行后不确定结果返回 `partial/write_uncertain`,禁止自动重试。
|
|
56
|
+
|
|
57
|
+
## 分组速览(以 schema 为准)
|
|
58
|
+
|
|
59
|
+
| 前缀 | 覆盖 |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| `yimiaoban.person.*` | resolve / resolveByIds |
|
|
62
|
+
| `yimiaoban.msg.sync.*` / `msg.top.sync` / `msg.read.*` | 消息拉取/置顶/阅读状态 |
|
|
63
|
+
| `yimiaoban.msg.send.*` / `msg.withdraw` / `msg.top.set` | 发送/撤回/置顶(写,两段式) |
|
|
64
|
+
| `yimiaoban.ding.send.*` | 必达/转必达(写,两段式) |
|
|
65
|
+
| `yimiaoban.group.search/info/users/admins/exist/userExist/announce.*` | 群读 |
|
|
66
|
+
| `yimiaoban.group.create/invite/kick/exit/destroy/join/modify/rename/announce.modify` | 群写(两段式) |
|
|
67
|
+
| `yimiaoban.session.list` / `sysmsg.*` | 会话与系统消息 |
|
|
68
|
+
| `yimiaoban.file.upload/preview/download` / `user.state` / `i18n.labels` | 文件/状态/翻译 |
|
|
69
|
+
|
|
70
|
+
## 平台示例
|
|
71
|
+
|
|
72
|
+
Windows PowerShell:
|
|
73
|
+
|
|
74
|
+
```powershell
|
|
75
|
+
weaver-work-cli --json yimiaoban run yimiaoban.msg.sync.group --input-json '{"groupId":"1788334281700000004","num":20,"latest":true}'
|
|
76
|
+
weaver-work-cli --json yimiaoban run yimiaoban.group.users --input-json '{"groupId":"1788334281700000004"}'
|
|
77
|
+
weaver-work-cli --json yimiaoban run yimiaoban.session.list --input-json '{"num":20}'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
macOS/Linux(bash/zsh):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
weaver-work-cli --json yimiaoban run yimiaoban.msg.sync.group --input-json '{"groupId":"1788334281700000004","num":20,"latest":true}'
|
|
84
|
+
weaver-work-cli --json yimiaoban run yimiaoban.group.users --input-json '{"groupId":"1788334281700000004"}'
|
|
85
|
+
weaver-work-cli --json yimiaoban run yimiaoban.session.list --input-json '{"num":20}'
|
|
86
|
+
```
|
package/package.json
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
+
"weaver-e10-calendar": ["日程", "日程管理", "创建日程", "日程列表", "日程详情", "删除日程", "日程类型", "紧急程度", "日历"],
|
|
3
|
+
"weaver-e10-meeting": ["会议", "会议室", "预约会议", "建会", "会议冲突", "签到", "回执", "会议类型", "会议室占用", "今天会议", "下一场会议", "会议列表", "请假回执"],
|
|
2
4
|
"weaver-e10-wenshuding": ["文书定", "档案", "全宗", "预归档", "档案检索", "全文检索", "借阅车", "借阅单", "借阅", "续借", "档案下载", "原文下载", "预归档上传", "电子文件库"],
|
|
3
5
|
"weaver-e10-yepiaotong": ["业票通", "发票", "票夹", "OCR", "查验", "报销发票", "自动填单", "事前申请报销", "开票", "存台账", "发票浏览按钮"],
|
|
4
6
|
"weaver-e10-jucailin": ["聚才林", "人事", "人事档案", "通讯录", "出勤", "考勤", "打卡", "申诉", "薪酬", "工资单", "社保", "招聘", "人才", "候选人", "面试", "Offer", "入职"],
|
|
@@ -11,5 +13,6 @@
|
|
|
11
13
|
"weaver-e10-jiuchuanhui": ["九氚汇", "营销管理", "CRM", "客户", "联系人", "商机", "线索", "联系计划", "联系记录", "跟进记录", "公海", "客户公海", "赢单", "输单", "线索转客户", "客户经理"],
|
|
12
14
|
"weaver-e10-skill-maker": ["业务模块 CLI", "业务模块 Skill", "生成 Skill", "生成 operation", "自定义 Skill", "能力封装", "源资料更新检测"],
|
|
13
15
|
"weaver-e10-shared": ["安装", "登录", "认证", "E10", "profile", "JSON 输出", "高风险写入"],
|
|
14
|
-
"weaver-e10-ziguanjia": ["资管家", "资产管理", "固定资产", "资产", "资产领用", "资产归还", "资产报修", "资产采购", "折旧", "资产地点", "资产状态", "资产类型"]
|
|
16
|
+
"weaver-e10-ziguanjia": ["资管家", "资产管理", "固定资产", "资产", "资产领用", "资产归还", "资产报修", "资产采购", "折旧", "资产地点", "资产状态", "资产类型"],
|
|
17
|
+
"weaver-e10-yimiaoban": ["易秒办", "即时通讯", "聊天", "单聊消息", "群聊消息", "群消息", "发消息", "撤回", "置顶", "必达", "Ding", "建群", "拉群", "群成员", "踢人", "退群", "解散群", "群公告", "群主", "管理员", "会话列表", "最近会话", "系统消息", "聊天记录", "历史消息", "发送文件", "发送图片", "在线状态", "下载附件", "查看图片"]
|
|
15
18
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# 会议(meeting)业务域
|
|
2
|
+
|
|
3
|
+
会议域覆盖 E10 标准版会议应用:环境模式探测、会议列表、会议室与占用视图、会议类型、冲突检测、预约会议(prepare/apply 确认链)、回执与签到查询。入口 `SKILL.md` 只做路由;具体命令、字段约束与失败处理拆到 `references/`(meeting-queries / meeting-create / meeting-receipts-signs)。关键安全边界:预约与回执更新是高风险写,必须走 prepare→用户确认→apply;冲突命中(含仅提醒)绝不提供"强制新建"选项;EB 版链路与工作流建会在 v1 未实现,见 manifest 的 withheldOperations。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
本业务域用于泛微 E10 易秒办即时通讯(消息/群组/会话/系统消息),包括读与写。入口 `SKILL.md` 先路由到 `weaver-e10-shared/SKILL.md`,再给出 Reference 路由表、关键差异(消息行已解析且标注「我」、人名走 hrm、uid/cid 字符串化、单页不翻全量且边界去重、时间范围转 id 区间、1303 空页说明、媒体需下载落地、展示完整不截断)与写操作 prepare→apply 协议。具体用法拆到 `references/`:
|
|
2
|
+
|
|
3
|
+
- `person.md`:姓名/工号/手机/邮箱解析、uid 批量解析(人名唯一合法来源,走 hrm)。
|
|
4
|
+
- `field-resolution.md`:名称 → ID 判定、同名消歧、未匹配处理、接口间上下文传递契约。
|
|
5
|
+
- `msg-read.md`:单聊/群聊消息拉取、群置顶、阅读状态(只读;1303=无记录按空处理)。
|
|
6
|
+
- `msg-write.md`:发单聊/群聊(文本/图片/文件)、撤回、群消息置顶的 prepare→apply 写入协议。
|
|
7
|
+
- `ding-write.md`:普通必达与转必达(createDing)、仅未读/指定接收人的 prepare→apply 写入协议。
|
|
8
|
+
- `group-read.md`:群搜索/信息/成员/群主管理员/存在性/公告(只读)。
|
|
9
|
+
- `group-write.md`:建群/邀请/踢/退/解散/申请入群/改群属性/群名/群公告的 prepare→apply 写入协议。
|
|
10
|
+
- `session-sysmsg.md`:会话列表与系统消息分组/类型/消息查询。
|
|
11
|
+
- `file-user-i18n.md`:文件上传/预览 URL/下载落地、用户在线状态、i18n 标签翻译。
|
|
12
|
+
- `safety-boundaries.md`:红线(禁操作人字段、人名走 hrm、id 非 0 字符串、不本地过滤、不自动全量翻页、拒绝空白消息、15 秒超时、未匹配不猜测、禁止拉全量统计、完整展示)、写链停止条件、已知限制、数据对不上提问模板。
|
|
13
|
+
- `error-codes.md`:业务错误码含义与处理建议(群 12xx / 消息 15xx / 数据 13xx + CLI 校验错误)。
|
|
14
|
+
- `source-manifest.json`:源资料清单与 sha256 指纹,用于源资料更新检测。
|
|
15
|
+
|
|
16
|
+
调优重点:
|
|
17
|
+
|
|
18
|
+
- `weaver-work-cli yimiaoban schema` 是 operation 合约第一信息源;所有 operation 名与 `inputSchema` 以它为准。
|
|
19
|
+
- 人名/群成员姓名一律由 CLI 走 hrm 解析;会话副标题与消息内容媒体展示用 `[图片]名称`/`[文件]名称`/`[视频]名称`、必达加 `[必达]`,媒体预览/下载 URL 需登录态,真正查看用 `file.download` 落地。
|
|
20
|
+
- 消息正文完整展示不截断;`|` 转义、换行保留提示;禁止把长文缩成摘要后再展示。
|
|
21
|
+
- 写操作只接受 CLI 签发的 continuation;`apply` 不确定结果时先只读回查,不自动重试。
|
|
@@ -17,6 +17,7 @@ cliHelp: "weaver-work-cli calendar --help"
|
|
|
17
17
|
|
|
18
18
|
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../weaver-e10-shared/SKILL.md`](../weaver-e10-shared/SKILL.md),其中包含安装、E10 认证、JSON 输出和高风险写入规则。若不存在则必须先执行 `weaver-work-cli skills install shared --skills-dir <当前Agent的Skills目录>`,若 CLI 未安装则先执行 `npm install -g weaver-work-cli`,安装或读取失败时必须停止执行。**
|
|
19
19
|
|
|
20
|
+
|
|
20
21
|
本技能覆盖日程管理业务域:**创建日程**、**查询列表**、**查询详情**、**查询总数**、**更新日程**、**删除日程**、**查询类型/紧急程度字典**、**应用版本检测**。写操作(创建/更新/删除)全部走 prepare→apply 确认协议。
|
|
21
22
|
|
|
22
23
|
## 命令入口
|
|
@@ -17,6 +17,7 @@ cliHelp: "weaver-work-cli esb --help"
|
|
|
17
17
|
|
|
18
18
|
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../weaver-e10-shared/SKILL.md`](../weaver-e10-shared/SKILL.md),其中包含安装、E10 认证、JSON 输出和高风险写入规则。若不存在则必须先执行 `weaver-work-cli skills install shared`,若 CLI 未安装则先执行 `npm install -g weaver-work-cli`,安装或读取失败时必须停止执行。**
|
|
19
19
|
|
|
20
|
+
|
|
20
21
|
本技能覆盖 ESB 中心的**自定义触发类型动作流**:取入参模板(只读)与执行动作流(写操作,需确认)。按动作流名称解析 ID、唯一值对应的 `primary_key` SQL 查询都不在本技能范围内,见「不在范围」。
|
|
21
22
|
|
|
22
23
|
## 命令入口
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
}
|
|
105
105
|
},
|
|
106
106
|
"artifactBaseline": {
|
|
107
|
-
"aggregateSha256": "
|
|
107
|
+
"aggregateSha256": "37985ab4ee42990df1edf9d9922f820f199116dfb4da0f3127402884d25e5325",
|
|
108
108
|
"files": [
|
|
109
109
|
{
|
|
110
110
|
"path": "docs/_catalog.md",
|
|
@@ -148,8 +148,8 @@
|
|
|
148
148
|
},
|
|
149
149
|
{
|
|
150
150
|
"path": "skills/weaver-e10-esb/SKILL.md",
|
|
151
|
-
"size":
|
|
152
|
-
"sha256": "
|
|
151
|
+
"size": 6799,
|
|
152
|
+
"sha256": "20b0eb14c79a31188c7dfefd4de0adc9e5c53dfb93b10bdd18d71d4c228a84b9"
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
"path": "src/shortcuts/esb/continuation.ts",
|
|
@@ -17,6 +17,7 @@ cliHelp: "weaver-work-cli hrm --help"
|
|
|
17
17
|
|
|
18
18
|
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../weaver-e10-shared/SKILL.md`](../weaver-e10-shared/SKILL.md),其中包含安装、E10 认证、JSON 输出和高风险写入规则。若不存在则必须先执行 `weaver-work-cli skills install shared --skills-dir <当前Agent的Skills目录>`,若 CLI 未安装则先执行 `npm install -g weaver-work-cli`,安装或读取失败时必须停止执行。**
|
|
19
19
|
|
|
20
|
+
|
|
20
21
|
本技能覆盖组织管理三大业务域:**员工(employee)**、**组织(org)**、**岗位(position)**,全部为只读查询,无写操作。代理商查询(`containsDls=true`)属于禁用边界,见 [`references/employee.md`](references/employee.md)。
|
|
21
22
|
|
|
22
23
|
## 命令入口
|
|
@@ -14,6 +14,7 @@ cliHelp: "weaver-work-cli jiuchuanhui --help"
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../weaver-e10-shared/SKILL.md`](../weaver-e10-shared/SKILL.md),其中包含安装、E10 认证、JSON 输出和高风险写入规则。若不存在则必须先执行 `weaver-work-cli skills install shared --skills-dir <当前Agent的Skills目录>`,若 CLI 未安装则先执行 `npm install -g weaver-work-cli`,安装或读取失败时必须停止执行。**
|
|
17
|
+
|
|
17
18
|
认证和登录态只能按共享规则通过 `weaver-work-cli auth ...` 命令判断;CLI 会自动携带完整 Cookie、`eteamsid` 与 `User-Agent: AgentType=<agentType>,IsAgent=true`,业务调用方不得覆盖这三条 header,也不得在业务 JSON 中传入这些 key。禁止直接读取、列出、打印或解析用户主目录下的 `.e10-cli`、auth、config 或 Keychain 数据。
|
|
18
19
|
所有命令通过 `weaver-work-cli --json jiuchuanhui run <operation>` 执行:简单 JSON 传 `--input-json '<json>'`,复杂或多行 JSON 先写入 UTF-8 文件再传 `--input <path>`,只有确认当前 shell 能稳定传管道时才使用 `--input -`。调用前先按需读取 references 下对应的文件,查参数结构,不要猜字段;**references 是第一信息源**,`weaver-work-cli jiuchuanhui schema` 是 operation、字段和风险等级的合约来源。
|
|
19
20
|
命令示例、提示词和临时说明必须同时兼容 Windows 和 macOS/Linux;涉及 JSON 输入、用户目录、路径分隔符、Python 启动器、文件删除、目录查看或文件比对时,同时给 Windows PowerShell 与 macOS/Linux(bash/zsh)两套示例。Agent 先根据当前系统和 shell 选择对应示例,不确定时用 `node -p "process.platform"` 判断。Windows/PowerShell 下不要使用 `printf`、`$HOME/...`、`~/...`、bash 反斜杠续行、`rm/ls/diff/python3` 等 Unix-only 写法。
|
|
@@ -17,6 +17,7 @@ cliHelp: "weaver-work-cli ehr --help"
|
|
|
17
17
|
|
|
18
18
|
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../weaver-e10-shared/SKILL.md`](../weaver-e10-shared/SKILL.md),其中包含安装、E10 认证、JSON 输出和高风险写入规则。若不存在则必须先执行 `weaver-work-cli skills install shared --skills-dir <当前Agent的Skills目录>`,若 CLI 未安装则先执行 `npm install -g weaver-work-cli`,安装或读取失败时必须停止执行。**
|
|
19
19
|
|
|
20
|
+
|
|
20
21
|
本技能覆盖聚才林业务域:**人事档案(hr)**、**出勤管理(attend)**、**薪酬管理(salary)**、**招聘(recruit,读 + 写)**。招聘写操作走 prepare→apply 确认协议;撤销类写操作不实现,原因见 [`references/safety-boundaries.md`](references/safety-boundaries.md)。
|
|
21
22
|
|
|
22
23
|
## 命令入口
|