vps-work 2.4.1 → 2.5.1
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/.well-known/skills/index.json +11 -0
- package/README.md +10 -0
- package/dist/packages/vps-work/src/bin/vps-work.js +271 -0
- package/dist/packages/vps-work/src/commands/agent/index.js +264 -0
- package/dist/packages/vps-work/src/commands/approval/index.js +7 -0
- package/dist/packages/vps-work/src/commands/approval/shortcuts.js +259 -0
- package/dist/packages/vps-work/src/commands/attendance/applications.js +21 -0
- package/dist/packages/vps-work/src/commands/attendance/index.js +9 -0
- package/dist/packages/vps-work/src/commands/attendance/scheduling.js +183 -0
- package/dist/packages/vps-work/src/commands/attendance/shortcuts.js +131 -0
- package/dist/packages/vps-work/src/commands/auth/check.js +34 -0
- package/dist/packages/vps-work/src/commands/auth/index.js +21 -0
- package/dist/packages/vps-work/src/commands/auth/list.js +50 -0
- package/dist/packages/vps-work/src/commands/auth/scopes.js +17 -0
- package/dist/packages/vps-work/src/commands/auth/status.js +127 -0
- package/dist/packages/vps-work/src/commands/auth/tenants.js +35 -0
- package/dist/packages/vps-work/src/commands/auth/use.js +40 -0
- package/dist/packages/vps-work/src/commands/calendar/index.js +7 -0
- package/dist/packages/vps-work/src/commands/calendar/shortcuts.js +598 -0
- package/dist/packages/vps-work/src/commands/catalog.js +29 -0
- package/dist/packages/vps-work/src/commands/cli-install.js +70 -0
- package/dist/packages/vps-work/src/commands/collab-invoke.js +19 -0
- package/dist/packages/vps-work/src/commands/corporate/index.js +204 -0
- package/dist/packages/vps-work/src/commands/creative/index.js +369 -0
- package/dist/packages/vps-work/src/commands/documents/index.js +991 -0
- package/dist/packages/vps-work/src/commands/drive/index.js +435 -0
- package/dist/packages/vps-work/src/commands/exec.js +46 -0
- package/dist/packages/vps-work/src/commands/hr/business.js +22 -0
- package/dist/packages/vps-work/src/commands/hr/data-view-shortcuts.js +519 -0
- package/dist/packages/vps-work/src/commands/hr/index.js +15 -0
- package/dist/packages/vps-work/src/commands/hr/job-responsibilities.js +266 -0
- package/dist/packages/vps-work/src/commands/hr/payslip.js +45 -0
- package/dist/packages/vps-work/src/commands/hr/shortcuts.js +146 -0
- package/dist/packages/vps-work/src/commands/im/im-message-payload.js +150 -0
- package/dist/packages/vps-work/src/commands/im/index.js +7 -0
- package/dist/packages/vps-work/src/commands/im/shortcuts.js +856 -0
- package/dist/packages/vps-work/src/commands/knowledge/index.js +36 -0
- package/dist/packages/vps-work/src/commands/login.js +52 -0
- package/dist/packages/vps-work/src/commands/logout.js +12 -0
- package/dist/packages/vps-work/src/commands/mail/email.js +132 -0
- package/dist/packages/vps-work/src/commands/mail/index.js +9 -0
- package/dist/packages/vps-work/src/commands/mail/shortcuts.js +43 -0
- package/dist/packages/vps-work/src/commands/meeting/index.js +7 -0
- package/dist/packages/vps-work/src/commands/meeting/shortcuts.js +120 -0
- package/dist/packages/vps-work/src/commands/odoo-invoke.js +21 -0
- package/dist/packages/vps-work/src/commands/odoo-leaf-registry.js +13 -0
- package/dist/packages/vps-work/src/commands/office/index.js +59 -0
- package/dist/packages/vps-work/src/commands/okr/index.js +7 -0
- package/dist/packages/vps-work/src/commands/okr/shortcuts.js +75 -0
- package/dist/packages/vps-work/src/commands/org-structure.js +347 -0
- package/dist/packages/vps-work/src/commands/popup/index.js +147 -0
- package/dist/packages/vps-work/src/commands/product/abnormal-statistics.js +250 -0
- package/dist/packages/vps-work/src/commands/product/data-view-shortcuts.js +253 -0
- package/dist/packages/vps-work/src/commands/product/index.js +11 -0
- package/dist/packages/vps-work/src/commands/purchase/index.js +45 -0
- package/dist/packages/vps-work/src/commands/reauth.js +127 -0
- package/dist/packages/vps-work/src/commands/report/index.js +7 -0
- package/dist/packages/vps-work/src/commands/report/missing-daily-reports.js +9 -0
- package/dist/packages/vps-work/src/commands/report/shortcuts.js +251 -0
- package/dist/packages/vps-work/src/commands/sales/index.js +11 -0
- package/dist/packages/vps-work/src/commands/sales/period-params.js +75 -0
- package/dist/packages/vps-work/src/commands/sales/shortcuts-personnel.js +124 -0
- package/dist/packages/vps-work/src/commands/sales/shortcuts.js +800 -0
- package/dist/packages/vps-work/src/commands/shortcut-common.js +88 -0
- package/dist/packages/vps-work/src/commands/shortcut-params.js +22 -0
- package/dist/packages/vps-work/src/commands/skill/index.js +136 -0
- package/dist/packages/vps-work/src/commands/skill/personal.js +167 -0
- package/dist/packages/vps-work/src/commands/store/index.js +82 -0
- package/dist/packages/vps-work/src/commands/task/index.js +7 -0
- package/dist/packages/vps-work/src/commands/task/task-center.js +595 -0
- package/dist/packages/vps-work/src/commands/tools/index.js +127 -0
- package/dist/packages/vps-work/src/commands/vemory/index.js +7 -0
- package/dist/packages/vps-work/src/commands/vemory/shortcuts.js +53 -0
- package/dist/packages/vps-work/src/commands/vertu-aisales.js +30 -0
- package/dist/packages/vps-work/src/commands/vertu-erp.js +30 -0
- package/dist/packages/vps-work/src/core/aisales-mcp-client.js +35 -0
- package/dist/packages/vps-work/src/core/auth.js +240 -0
- package/dist/packages/vps-work/src/core/cli-bin.js +11 -0
- package/dist/packages/vps-work/src/core/cli-root-help.js +190 -0
- package/dist/packages/vps-work/src/core/client.js +158 -0
- package/dist/packages/vps-work/src/core/config.js +183 -0
- package/dist/packages/vps-work/src/core/corporate-client.js +52 -0
- package/dist/packages/vps-work/src/core/creative-attachment-download.js +48 -0
- package/dist/packages/vps-work/src/core/documents-client.js +57 -0
- package/dist/packages/vps-work/src/core/endpoints.js +46 -0
- package/dist/packages/vps-work/src/core/erp-mcp-client.js +11 -0
- package/dist/packages/vps-work/src/core/errors.js +107 -0
- package/dist/packages/vps-work/src/core/execute-catalog-client.js +42 -0
- package/dist/packages/vps-work/src/core/hermes-client.js +70 -0
- package/dist/packages/vps-work/src/core/im-attachment-download.js +109 -0
- package/dist/packages/vps-work/src/core/im-client.js +64 -0
- package/dist/packages/vps-work/src/core/keychain.js +58 -0
- package/dist/packages/vps-work/src/core/mail-client.js +82 -0
- package/dist/packages/vps-work/src/core/mcp-client.js +129 -0
- package/dist/packages/vps-work/src/core/office-client.js +25 -0
- package/dist/packages/vps-work/src/core/office-files.js +82 -0
- package/dist/packages/vps-work/src/core/paths.js +70 -0
- package/dist/packages/vps-work/src/core/public-result.js +43 -0
- package/dist/packages/vps-work/src/core/sales-invoice-attachments-client.js +75 -0
- package/dist/packages/vps-work/src/core/sales-query-client.js +452 -0
- package/dist/packages/vps-work/src/core/skill-catalog.js +158 -0
- package/dist/packages/vps-work/src/core/skill-key.js +19 -0
- package/dist/packages/vps-work/src/core/v-drive-store.js +392 -0
- package/dist/packages/vps-work/src/core/vertu-agent-env.js +32 -0
- package/dist/packages/vps-work/src/core/vps-auth-scopes.js +73 -0
- package/dist/packages/vps-work/src/core/vps-service-auth.js +382 -0
- package/dist/packages/vps-work/src/core/vps-service-config.js +83 -0
- package/dist/packages/vps-work/src/core/vps-service-http.js +187 -0
- package/dist/packages/vps-work/src/utils/at-file.js +34 -0
- package/dist/packages/vps-work/src/utils/cli-option-helpers.js +52 -0
- package/dist/packages/vps-work/src/utils/frontmatter.js +26 -0
- package/dist/packages/vps-work/src/utils/normalize-argv.js +51 -0
- package/dist/packages/vps-work/src/utils/parse-json-arg.js +85 -0
- package/dist/packages/vps-work/src/utils/prompt.js +46 -0
- package/dist/packages/vps-work/src/utils/read-text.js +44 -0
- package/dist/packages/vps-work/src/utils/schema-to-options.js +307 -0
- package/dist/packages/vps-work/src/utils/unwrap-envelope.js +31 -0
- package/dist/shared/im-org-tree/index.js +200 -0
- package/dist/vps-work.cjs +246 -44
- package/package.json +1 -1
- package/scripts/package-desktop-runtime.mjs +43 -0
- package/skills/README.md +1 -0
- package/skills/vertu-aisales/SKILL.md +18 -0
- package/skills/vertu-erp/SKILL.md +17 -0
- package/skills/vps-dealer-ops/SKILL.md +92 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IM 通讯录组织架构:部门列表口径与树构建(vps-service / im-desktop 共用)。
|
|
3
|
+
* 数据源以 `/v1/im/org/departments` 返回的 VPS 原生企业组织为准。
|
|
4
|
+
*/
|
|
5
|
+
/** 身份同步占位部门在通讯录中的展示名,与 vps_org_units.unit_key=unassigned 对应。 */
|
|
6
|
+
export const UNASSIGNED_ORG_DEPARTMENT_NAME = '未分配部门';
|
|
7
|
+
/** 通讯录不展示身份同步占位部门。 */
|
|
8
|
+
export function isUnassignedDirectoryDepartment(department) {
|
|
9
|
+
return department.name.trim() === UNASSIGNED_ORG_DEPARTMENT_NAME
|
|
10
|
+
|| department.complete_name?.trim() === UNASSIGNED_ORG_DEPARTMENT_NAME;
|
|
11
|
+
}
|
|
12
|
+
export function excludeUnassignedDirectoryDepartments(departments) {
|
|
13
|
+
return departments.filter((department) => !isUnassignedDirectoryDepartment(department));
|
|
14
|
+
}
|
|
15
|
+
export function imOrgDepartmentDisplayName(department) {
|
|
16
|
+
const name = department.name.trim();
|
|
17
|
+
if (name) {
|
|
18
|
+
return name;
|
|
19
|
+
}
|
|
20
|
+
const complete = department.complete_name?.trim();
|
|
21
|
+
if (complete) {
|
|
22
|
+
return complete;
|
|
23
|
+
}
|
|
24
|
+
return `部门 ${department.department_id}`;
|
|
25
|
+
}
|
|
26
|
+
export function sortImOrgDepartmentsByName(a, b) {
|
|
27
|
+
return imOrgDepartmentDisplayName(a).localeCompare(imOrgDepartmentDisplayName(b), 'zh-CN');
|
|
28
|
+
}
|
|
29
|
+
/** 通讯录口径:去掉本部门及全部子部门都没有在职人员的节点。 */
|
|
30
|
+
export function filterImOrgDepartmentsWithSubtreeStaff(departments) {
|
|
31
|
+
const byId = new Map();
|
|
32
|
+
const childrenByParent = new Map();
|
|
33
|
+
for (const dept of departments) {
|
|
34
|
+
byId.set(dept.department_id, dept);
|
|
35
|
+
const parentId = dept.parent_id;
|
|
36
|
+
if (parentId !== null) {
|
|
37
|
+
const siblings = childrenByParent.get(parentId) ?? [];
|
|
38
|
+
siblings.push(dept.department_id);
|
|
39
|
+
childrenByParent.set(parentId, siblings);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const subtreeTotals = new Map();
|
|
43
|
+
const computeSubtreeTotal = (departmentId) => {
|
|
44
|
+
const cached = subtreeTotals.get(departmentId);
|
|
45
|
+
if (cached !== undefined) {
|
|
46
|
+
return cached;
|
|
47
|
+
}
|
|
48
|
+
const dept = byId.get(departmentId);
|
|
49
|
+
if (!dept) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
let total = dept.employee_count;
|
|
53
|
+
for (const childId of childrenByParent.get(departmentId) ?? []) {
|
|
54
|
+
total += computeSubtreeTotal(childId);
|
|
55
|
+
}
|
|
56
|
+
subtreeTotals.set(departmentId, total);
|
|
57
|
+
return total;
|
|
58
|
+
};
|
|
59
|
+
for (const dept of departments) {
|
|
60
|
+
computeSubtreeTotal(dept.department_id);
|
|
61
|
+
}
|
|
62
|
+
return departments.filter((dept) => (subtreeTotals.get(dept.department_id) ?? 0) > 0);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 构建森林:父节点不在当前列表中的部门提升为根(与 IM 通讯录一致)。
|
|
66
|
+
*/
|
|
67
|
+
export function buildImOrgDepartmentForest(departments) {
|
|
68
|
+
const nodes = new Map();
|
|
69
|
+
for (const department of departments) {
|
|
70
|
+
nodes.set(department.department_id, {
|
|
71
|
+
department,
|
|
72
|
+
children: [],
|
|
73
|
+
subtreeEmployeeCount: 0,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const roots = [];
|
|
77
|
+
for (const node of nodes.values()) {
|
|
78
|
+
const parentId = node.department.parent_id;
|
|
79
|
+
const parent = parentId !== null ? nodes.get(parentId) : undefined;
|
|
80
|
+
if (parent) {
|
|
81
|
+
parent.children.push(node);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
roots.push(node);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const fillSubtreeCount = (node) => {
|
|
88
|
+
node.subtreeEmployeeCount =
|
|
89
|
+
node.department.employee_count +
|
|
90
|
+
node.children.reduce((sum, child) => sum + fillSubtreeCount(child), 0);
|
|
91
|
+
return node.subtreeEmployeeCount;
|
|
92
|
+
};
|
|
93
|
+
roots.sort((a, b) => sortImOrgDepartmentsByName(a.department, b.department));
|
|
94
|
+
const sortRecursive = (items) => {
|
|
95
|
+
items.sort((a, b) => sortImOrgDepartmentsByName(a.department, b.department));
|
|
96
|
+
for (const item of items) {
|
|
97
|
+
sortRecursive(item.children);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
sortRecursive(roots);
|
|
101
|
+
roots.forEach(fillSubtreeCount);
|
|
102
|
+
return roots;
|
|
103
|
+
}
|
|
104
|
+
/** 企业根名称与公司名重复时,这一级只是容器:有下级则提升子部门,没有则不再单独占一层。 */
|
|
105
|
+
export function flattenDuplicateCompanyRoot(forest, companyName) {
|
|
106
|
+
const company = companyName.trim();
|
|
107
|
+
if (!company)
|
|
108
|
+
return { forest, collapsedRoots: [] };
|
|
109
|
+
const collapsedRoots = [];
|
|
110
|
+
const next = [];
|
|
111
|
+
for (const node of forest) {
|
|
112
|
+
const name = node.department.name.trim();
|
|
113
|
+
const path = node.department.complete_name?.trim() || name;
|
|
114
|
+
const sameCompany = name === company && (path === company || path === name);
|
|
115
|
+
if (!sameCompany) {
|
|
116
|
+
next.push(node);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
collapsedRoots.push(node);
|
|
120
|
+
next.push(...node.children);
|
|
121
|
+
}
|
|
122
|
+
return { forest: next, collapsedRoots };
|
|
123
|
+
}
|
|
124
|
+
function matchesImOrgDepartmentKeyword(department, keyword) {
|
|
125
|
+
const q = keyword.trim().toLowerCase();
|
|
126
|
+
if (!q) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
const haystack = [
|
|
130
|
+
department.department_id,
|
|
131
|
+
department.parent_id,
|
|
132
|
+
department.name,
|
|
133
|
+
department.complete_name,
|
|
134
|
+
department.employee_count,
|
|
135
|
+
]
|
|
136
|
+
.join(' ')
|
|
137
|
+
.toLowerCase();
|
|
138
|
+
return haystack.includes(q);
|
|
139
|
+
}
|
|
140
|
+
export function filterImOrgDepartmentForestByKeyword(nodes, keyword) {
|
|
141
|
+
if (!keyword.trim()) {
|
|
142
|
+
return nodes;
|
|
143
|
+
}
|
|
144
|
+
const filtered = [];
|
|
145
|
+
for (const node of nodes) {
|
|
146
|
+
const childMatches = filterImOrgDepartmentForestByKeyword(node.children, keyword);
|
|
147
|
+
if (matchesImOrgDepartmentKeyword(node.department, keyword) || childMatches.length > 0) {
|
|
148
|
+
filtered.push({
|
|
149
|
+
department: node.department,
|
|
150
|
+
subtreeEmployeeCount: node.subtreeEmployeeCount,
|
|
151
|
+
children: childMatches.length > 0 ? childMatches : node.children,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return filtered;
|
|
156
|
+
}
|
|
157
|
+
export function collectImOrgDepartmentForestIds(nodes) {
|
|
158
|
+
const ids = [];
|
|
159
|
+
const walk = (items) => {
|
|
160
|
+
for (const node of items) {
|
|
161
|
+
ids.push(node.department.department_id);
|
|
162
|
+
walk(node.children);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
walk(nodes);
|
|
166
|
+
return ids;
|
|
167
|
+
}
|
|
168
|
+
export function buildImOrgDepartmentChildrenIndex(departments) {
|
|
169
|
+
const childrenByParent = new Map();
|
|
170
|
+
const knownIds = new Set(departments.map((dept) => dept.department_id));
|
|
171
|
+
for (const department of departments) {
|
|
172
|
+
const parentId = department.parent_id;
|
|
173
|
+
if (parentId === null || !knownIds.has(parentId)) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const siblings = childrenByParent.get(parentId) ?? [];
|
|
177
|
+
siblings.push(department.department_id);
|
|
178
|
+
childrenByParent.set(parentId, siblings);
|
|
179
|
+
}
|
|
180
|
+
return childrenByParent;
|
|
181
|
+
}
|
|
182
|
+
export function resolveImOrgDepartmentSubtreeScope(childrenByParent, selectedDepartmentIds) {
|
|
183
|
+
if (!selectedDepartmentIds.length) {
|
|
184
|
+
return new Set();
|
|
185
|
+
}
|
|
186
|
+
const scope = new Set();
|
|
187
|
+
const walk = (departmentId) => {
|
|
188
|
+
if (scope.has(departmentId)) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
scope.add(departmentId);
|
|
192
|
+
for (const childId of childrenByParent.get(departmentId) ?? []) {
|
|
193
|
+
walk(childId);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
for (const departmentId of selectedDepartmentIds) {
|
|
197
|
+
walk(departmentId);
|
|
198
|
+
}
|
|
199
|
+
return scope;
|
|
200
|
+
}
|
package/dist/vps-work.cjs
CHANGED
|
@@ -18246,17 +18246,17 @@ var require_dns = __commonJS({
|
|
|
18246
18246
|
const timestamp = Date.now();
|
|
18247
18247
|
const records2 = { records: { 4: null, 6: null } };
|
|
18248
18248
|
let minTTL = this.#maxTTL;
|
|
18249
|
-
for (const
|
|
18250
|
-
|
|
18251
|
-
if (typeof
|
|
18252
|
-
|
|
18253
|
-
minTTL = Math.min(minTTL,
|
|
18249
|
+
for (const record4 of addresses2) {
|
|
18250
|
+
record4.timestamp = timestamp;
|
|
18251
|
+
if (typeof record4.ttl === "number") {
|
|
18252
|
+
record4.ttl = Math.min(record4.ttl, this.#maxTTL);
|
|
18253
|
+
minTTL = Math.min(minTTL, record4.ttl);
|
|
18254
18254
|
} else {
|
|
18255
|
-
|
|
18255
|
+
record4.ttl = this.#maxTTL;
|
|
18256
18256
|
}
|
|
18257
|
-
const familyRecords = records2.records[
|
|
18258
|
-
familyRecords.ips.push(
|
|
18259
|
-
records2.records[
|
|
18257
|
+
const familyRecords = records2.records[record4.family] ?? { ips: [] };
|
|
18258
|
+
familyRecords.ips.push(record4);
|
|
18259
|
+
records2.records[record4.family] = familyRecords;
|
|
18260
18260
|
}
|
|
18261
18261
|
this.storage.set(origin.hostname, records2, { ttl: minTTL });
|
|
18262
18262
|
}
|
|
@@ -54875,14 +54875,14 @@ function collaborationTurnFromHistory(out, requestId) {
|
|
|
54875
54875
|
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) continue;
|
|
54876
54876
|
const envelope = metadata[HARNESS_COLLABORATION_KIND];
|
|
54877
54877
|
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) continue;
|
|
54878
|
-
const
|
|
54879
|
-
const turn = Number(
|
|
54880
|
-
if (
|
|
54878
|
+
const record4 = envelope;
|
|
54879
|
+
const turn = Number(record4.turn);
|
|
54880
|
+
if (record4.request_id !== requestId || record4.type !== "request" && record4.type !== "response" || !Number.isInteger(turn) || turn <= 0) continue;
|
|
54881
54881
|
return {
|
|
54882
54882
|
body: typeof message.body === "string" ? message.body : "",
|
|
54883
54883
|
messageId: typeof message.id === "string" ? message.id : "",
|
|
54884
54884
|
turn,
|
|
54885
|
-
type:
|
|
54885
|
+
type: record4.type
|
|
54886
54886
|
};
|
|
54887
54887
|
}
|
|
54888
54888
|
return null;
|
|
@@ -55373,6 +55373,11 @@ async function parseJson2(res) {
|
|
|
55373
55373
|
}
|
|
55374
55374
|
async function hermesRequest(method, path3, opts = {}) {
|
|
55375
55375
|
const base = resolveHermesAgentAdminUrl(opts.baseUrl);
|
|
55376
|
+
const target = new URL(base);
|
|
55377
|
+
const trusted = new URL(resolveHermesAgentAdminUrl());
|
|
55378
|
+
if (target.origin !== trusted.origin || target.username || target.password || target.search || target.hash || target.pathname !== "/") {
|
|
55379
|
+
throw new VertuError("Hermes \u8BF7\u6C42\u76EE\u6807\u4E0D\u53D7\u4FE1\u4EFB\uFF1B\u8BF7\u7531\u5BBF\u4E3B\u914D\u7F6E\u670D\u52A1\u5730\u5740\uFF0C\u4E0D\u80FD\u901A\u8FC7\u4E34\u65F6\u53C2\u6570\u8F6C\u53D1\u51ED\u636E\u3002");
|
|
55380
|
+
}
|
|
55376
55381
|
const res = await (0, import_undici5.request)(`${base}${path3}`, {
|
|
55377
55382
|
method,
|
|
55378
55383
|
headers: headers2(),
|
|
@@ -58375,8 +58380,8 @@ function printResult(opts, result) {
|
|
|
58375
58380
|
console.log(typeof result === "string" ? result : JSON.stringify(result));
|
|
58376
58381
|
}
|
|
58377
58382
|
function outputRows(value) {
|
|
58378
|
-
const
|
|
58379
|
-
const rows2 =
|
|
58383
|
+
const record4 = asRecord2(value);
|
|
58384
|
+
const rows2 = record4 ? record4.rows : void 0;
|
|
58380
58385
|
return Array.isArray(rows2) ? rows2.filter((row) => asRecord2(row) !== null) : [];
|
|
58381
58386
|
}
|
|
58382
58387
|
function isValidateOnly2(opts) {
|
|
@@ -58407,31 +58412,31 @@ function findIdentityRecord(payload) {
|
|
|
58407
58412
|
continue;
|
|
58408
58413
|
}
|
|
58409
58414
|
seen.add(current);
|
|
58410
|
-
const
|
|
58411
|
-
if (!
|
|
58415
|
+
const record4 = asRecord2(current);
|
|
58416
|
+
if (!record4) {
|
|
58412
58417
|
continue;
|
|
58413
58418
|
}
|
|
58414
|
-
if ("employee_id" in
|
|
58415
|
-
return
|
|
58419
|
+
if ("employee_id" in record4 || "employeeId" in record4 || "manager_id" in record4 || "managerEmployeeId" in record4 || "user_id" in record4 || "employee" in record4 || "manager" in record4) {
|
|
58420
|
+
return record4;
|
|
58416
58421
|
}
|
|
58417
58422
|
for (const key of ["result", "data", "payload", "context", "user", "userinfo"]) {
|
|
58418
|
-
if (key in
|
|
58419
|
-
queue.push(
|
|
58423
|
+
if (key in record4) {
|
|
58424
|
+
queue.push(record4[key]);
|
|
58420
58425
|
}
|
|
58421
58426
|
}
|
|
58422
58427
|
}
|
|
58423
58428
|
return {};
|
|
58424
58429
|
}
|
|
58425
58430
|
function extractHrIdentity(payload) {
|
|
58426
|
-
const
|
|
58427
|
-
const employee = asRecord2(
|
|
58428
|
-
const manager = asRecord2(
|
|
58431
|
+
const record4 = findIdentityRecord(payload);
|
|
58432
|
+
const employee = asRecord2(record4.employee);
|
|
58433
|
+
const manager = asRecord2(record4.manager);
|
|
58429
58434
|
return {
|
|
58430
|
-
employeeId: numberValue(
|
|
58431
|
-
employeeName: stringValue(
|
|
58432
|
-
managerEmployeeId: numberValue(
|
|
58433
|
-
managerName: stringValue(
|
|
58434
|
-
managerUserId: numberValue(
|
|
58435
|
+
employeeId: numberValue(record4.employee_id) ?? numberValue(record4.employeeId) ?? numberValue(employee?.id),
|
|
58436
|
+
employeeName: stringValue(record4.employee_name) ?? stringValue(record4.employeeName) ?? stringValue(employee?.name) ?? stringValue(record4.name),
|
|
58437
|
+
managerEmployeeId: numberValue(record4.manager_id) ?? numberValue(record4.manager_employee_id) ?? numberValue(record4.managerEmployeeId) ?? numberValue(manager?.id),
|
|
58438
|
+
managerName: stringValue(record4.manager_name) ?? stringValue(record4.managerName) ?? stringValue(manager?.name),
|
|
58439
|
+
managerUserId: numberValue(record4.manager_user_id) ?? numberValue(record4.managerUserId) ?? numberValue(manager?.user_id) ?? numberValue(manager?.userId)
|
|
58435
58440
|
};
|
|
58436
58441
|
}
|
|
58437
58442
|
async function fetchCurrentHrIdentity(opts, cmd) {
|
|
@@ -58531,8 +58536,8 @@ function dataViewRows(value) {
|
|
|
58531
58536
|
return outputRows(value);
|
|
58532
58537
|
}
|
|
58533
58538
|
function dataViewTotalRows(value) {
|
|
58534
|
-
const
|
|
58535
|
-
const pagination = asRecord2(
|
|
58539
|
+
const record4 = asRecord2(value);
|
|
58540
|
+
const pagination = asRecord2(record4?.pagination);
|
|
58536
58541
|
return numberValue(pagination?.total_rows) ?? 0;
|
|
58537
58542
|
}
|
|
58538
58543
|
function addHeadcountOptions(cmd) {
|
|
@@ -58899,8 +58904,8 @@ function asRecord3(value) {
|
|
|
58899
58904
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
58900
58905
|
}
|
|
58901
58906
|
function rows(value) {
|
|
58902
|
-
const
|
|
58903
|
-
const raw =
|
|
58907
|
+
const record4 = asRecord3(value);
|
|
58908
|
+
const raw = record4 ? record4.rows : void 0;
|
|
58904
58909
|
return Array.isArray(raw) ? raw.filter((row) => asRecord3(row) !== null) : [];
|
|
58905
58910
|
}
|
|
58906
58911
|
function num(value) {
|
|
@@ -59310,9 +59315,9 @@ function asRecord4(value) {
|
|
|
59310
59315
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
59311
59316
|
}
|
|
59312
59317
|
function remoteMessage(value, fallback) {
|
|
59313
|
-
const
|
|
59318
|
+
const record4 = asRecord4(value);
|
|
59314
59319
|
for (const key of ["message", "error", "statusText"]) {
|
|
59315
|
-
const candidate =
|
|
59320
|
+
const candidate = record4?.[key];
|
|
59316
59321
|
if (typeof candidate === "string" && candidate.trim()) return candidate.trim();
|
|
59317
59322
|
}
|
|
59318
59323
|
return fallback;
|
|
@@ -60968,8 +60973,8 @@ function printMutationPreview(opts, method, endpoint, body) {
|
|
|
60968
60973
|
});
|
|
60969
60974
|
}
|
|
60970
60975
|
function decorateEvents(payload, scope, range, calendarId) {
|
|
60971
|
-
const
|
|
60972
|
-
const calendars = recordArray(
|
|
60976
|
+
const record4 = asRecord5(payload) ?? {};
|
|
60977
|
+
const calendars = recordArray(record4.calendars);
|
|
60973
60978
|
const calendarNames = new Map(
|
|
60974
60979
|
calendars.flatMap((calendar) => {
|
|
60975
60980
|
const id = typeof calendar.id === "string" ? calendar.id : "";
|
|
@@ -60979,7 +60984,7 @@ function decorateEvents(payload, scope, range, calendarId) {
|
|
|
60979
60984
|
if (calendarId && !calendarNames.has(calendarId)) {
|
|
60980
60985
|
throw new VertuError(`\u65E5\u5386\u4E0D\u5B58\u5728\u6216\u65E0\u6743\u67E5\u770B\uFF1A${calendarId}`);
|
|
60981
60986
|
}
|
|
60982
|
-
const rows2 = recordArray(
|
|
60987
|
+
const rows2 = recordArray(record4.events).filter((event) => !calendarId || event.calendar_id === calendarId).map((event) => ({
|
|
60983
60988
|
...event,
|
|
60984
60989
|
calendar_name: typeof event.calendar_id === "string" ? calendarNames.get(event.calendar_id) ?? null : null
|
|
60985
60990
|
}));
|
|
@@ -62058,12 +62063,12 @@ function buildPath2(path3, query2) {
|
|
|
62058
62063
|
}
|
|
62059
62064
|
function errorMessage3(payload, statusCode) {
|
|
62060
62065
|
if (typeof payload === "object" && payload !== null) {
|
|
62061
|
-
const
|
|
62062
|
-
if (typeof
|
|
62063
|
-
return
|
|
62066
|
+
const record4 = payload;
|
|
62067
|
+
if (typeof record4["error"] === "string") {
|
|
62068
|
+
return record4["error"];
|
|
62064
62069
|
}
|
|
62065
|
-
if (typeof
|
|
62066
|
-
return
|
|
62070
|
+
if (typeof record4["message"] === "string") {
|
|
62071
|
+
return record4["message"];
|
|
62067
62072
|
}
|
|
62068
62073
|
}
|
|
62069
62074
|
return `HTTP ${statusCode}`;
|
|
@@ -64840,6 +64845,199 @@ function buildExecCommand() {
|
|
|
64840
64845
|
});
|
|
64841
64846
|
}
|
|
64842
64847
|
|
|
64848
|
+
// src/core/mcp-client.ts
|
|
64849
|
+
var PROTOCOL = "2025-03-26";
|
|
64850
|
+
var MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
64851
|
+
var record3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
64852
|
+
function rpcResult(value, id) {
|
|
64853
|
+
const rpc = record3(value);
|
|
64854
|
+
if (rpc.id !== id) return void 0;
|
|
64855
|
+
if (rpc.error) throw new VertuError("MCP \u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5DE5\u5177\u53C2\u6570\u548C\u670D\u52A1\u7AEF\u6388\u6743\u3002");
|
|
64856
|
+
if (!("result" in rpc)) throw new VertuError("MCP \u8FD4\u56DE\u4E86\u65E0\u6548\u54CD\u5E94\u3002");
|
|
64857
|
+
return record3(rpc.result);
|
|
64858
|
+
}
|
|
64859
|
+
async function readResult(response, id) {
|
|
64860
|
+
const reader = response.body?.getReader();
|
|
64861
|
+
if (!reader) throw new VertuError("MCP \u8FD4\u56DE\u4E86\u7A7A\u54CD\u5E94\u3002");
|
|
64862
|
+
const sse = response.headers.get("content-type")?.includes("text/event-stream");
|
|
64863
|
+
const decoder = new TextDecoder();
|
|
64864
|
+
let buffer = "";
|
|
64865
|
+
let size = 0;
|
|
64866
|
+
try {
|
|
64867
|
+
while (true) {
|
|
64868
|
+
const chunk = await reader.read();
|
|
64869
|
+
if (chunk.done) {
|
|
64870
|
+
buffer += decoder.decode();
|
|
64871
|
+
break;
|
|
64872
|
+
}
|
|
64873
|
+
size += chunk.value.byteLength;
|
|
64874
|
+
if (size > MAX_RESPONSE_BYTES) throw new VertuError("MCP \u7ED3\u679C\u8FC7\u5927\uFF0C\u8BF7\u7F29\u5C0F\u67E5\u8BE2\u8303\u56F4\u3002");
|
|
64875
|
+
buffer += decoder.decode(chunk.value, { stream: true });
|
|
64876
|
+
if (sse) {
|
|
64877
|
+
let boundary;
|
|
64878
|
+
while (boundary = /\r?\n\r?\n/.exec(buffer)) {
|
|
64879
|
+
const frame = buffer.slice(0, boundary.index);
|
|
64880
|
+
buffer = buffer.slice(boundary.index + boundary[0].length);
|
|
64881
|
+
const data = frame.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).replace(/^ /, "")).join("\n");
|
|
64882
|
+
if (!data) continue;
|
|
64883
|
+
const result = rpcResult(JSON.parse(data), id);
|
|
64884
|
+
if (result) return result;
|
|
64885
|
+
}
|
|
64886
|
+
}
|
|
64887
|
+
}
|
|
64888
|
+
if (!sse) {
|
|
64889
|
+
const result = rpcResult(JSON.parse(buffer), id);
|
|
64890
|
+
if (result) return result;
|
|
64891
|
+
}
|
|
64892
|
+
throw new VertuError("MCP \u672A\u8FD4\u56DE\u5339\u914D\u7684\u8BF7\u6C42\u7ED3\u679C\u3002");
|
|
64893
|
+
} finally {
|
|
64894
|
+
await reader.cancel().catch(() => {
|
|
64895
|
+
});
|
|
64896
|
+
}
|
|
64897
|
+
}
|
|
64898
|
+
async function runMcp(endpoint, authorizationHeaders, allowedTools, operation) {
|
|
64899
|
+
let sessionId;
|
|
64900
|
+
let protocol = PROTOCOL;
|
|
64901
|
+
let nextId = 0;
|
|
64902
|
+
const headers3 = () => ({
|
|
64903
|
+
...authorizationHeaders,
|
|
64904
|
+
"content-type": "application/json",
|
|
64905
|
+
accept: "application/json, text/event-stream",
|
|
64906
|
+
"mcp-protocol-version": protocol,
|
|
64907
|
+
...sessionId ? { "mcp-session-id": sessionId } : {}
|
|
64908
|
+
});
|
|
64909
|
+
const send = async (method, params, notification = false) => {
|
|
64910
|
+
const id = ++nextId;
|
|
64911
|
+
const response = await fetch(endpoint, {
|
|
64912
|
+
method: "POST",
|
|
64913
|
+
headers: headers3(),
|
|
64914
|
+
redirect: "error",
|
|
64915
|
+
signal: AbortSignal.timeout(6e4),
|
|
64916
|
+
body: JSON.stringify({ jsonrpc: "2.0", ...notification ? {} : { id }, method, params })
|
|
64917
|
+
});
|
|
64918
|
+
if (!response.ok) {
|
|
64919
|
+
await response.body?.cancel();
|
|
64920
|
+
throw new VertuError(`MCP \u8BF7\u6C42\u88AB\u62D2\u7EDD\u6216\u670D\u52A1\u4E0D\u53EF\u7528\uFF08HTTP ${response.status}\uFF09\u3002`, { statusCode: response.status });
|
|
64921
|
+
}
|
|
64922
|
+
if (method === "initialize") sessionId = response.headers.get("mcp-session-id") || void 0;
|
|
64923
|
+
if (notification) {
|
|
64924
|
+
await response.body?.cancel();
|
|
64925
|
+
return {};
|
|
64926
|
+
}
|
|
64927
|
+
return readResult(response, id);
|
|
64928
|
+
};
|
|
64929
|
+
try {
|
|
64930
|
+
const initialized = await send("initialize", {
|
|
64931
|
+
protocolVersion: PROTOCOL,
|
|
64932
|
+
capabilities: {},
|
|
64933
|
+
clientInfo: { name: "vps-work", version: "1" }
|
|
64934
|
+
});
|
|
64935
|
+
if (initialized.protocolVersion !== PROTOCOL) throw new VertuError("MCP \u534F\u8BAE\u7248\u672C\u4E0D\u517C\u5BB9\u3002");
|
|
64936
|
+
protocol = initialized.protocolVersion;
|
|
64937
|
+
await send("notifications/initialized", void 0, true);
|
|
64938
|
+
const tools2 = [];
|
|
64939
|
+
const cursors = /* @__PURE__ */ new Set();
|
|
64940
|
+
let cursor;
|
|
64941
|
+
do {
|
|
64942
|
+
const page = await send("tools/list", cursor ? { cursor } : {});
|
|
64943
|
+
if (!Array.isArray(page.tools)) throw new VertuError("MCP \u5DE5\u5177\u76EE\u5F55\u65E0\u6548\u3002");
|
|
64944
|
+
tools2.push(...page.tools.map(record3).filter((tool) => allowedTools.has(String(tool.name))));
|
|
64945
|
+
cursor = typeof page.nextCursor === "string" && page.nextCursor ? page.nextCursor : void 0;
|
|
64946
|
+
if (cursor && (cursors.has(cursor) || cursors.size >= 100)) throw new VertuError("MCP \u5DE5\u5177\u76EE\u5F55\u5206\u9875\u5F02\u5E38\u3002");
|
|
64947
|
+
if (cursor) cursors.add(cursor);
|
|
64948
|
+
} while (cursor);
|
|
64949
|
+
if (!operation) return { tools: tools2 };
|
|
64950
|
+
if (!tools2.some((tool) => tool.name === operation.tool)) throw new VertuError("\u5F53\u524D MCP \u672A\u5F00\u653E\u8BE5\u5DE5\u5177\u3002");
|
|
64951
|
+
const result = await send("tools/call", { name: operation.tool, arguments: operation.arguments });
|
|
64952
|
+
if (result.isError === true) throw new VertuError("MCP \u5DE5\u5177\u6267\u884C\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u53C2\u6570\u3001SQL \u548C\u670D\u52A1\u7AEF\u6388\u6743\u3002");
|
|
64953
|
+
return result;
|
|
64954
|
+
} catch (error) {
|
|
64955
|
+
if (error instanceof VertuError) throw error;
|
|
64956
|
+
throw new VertuError("MCP \u901A\u4FE1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u548C\u670D\u52A1\u72B6\u6001\u3002");
|
|
64957
|
+
} finally {
|
|
64958
|
+
if (sessionId) {
|
|
64959
|
+
await fetch(endpoint, { method: "DELETE", headers: headers3(), redirect: "error", signal: AbortSignal.timeout(5e3) }).then((response) => response.body?.cancel()).catch(() => {
|
|
64960
|
+
});
|
|
64961
|
+
}
|
|
64962
|
+
}
|
|
64963
|
+
}
|
|
64964
|
+
|
|
64965
|
+
// src/core/aisales-mcp-client.ts
|
|
64966
|
+
var TENANT = "00000000-0000-4000-8000-000000000001";
|
|
64967
|
+
var TOOL_NAMES = /* @__PURE__ */ new Set(["business.resolve_subject", "business.catalog", "business.query", "business.compare", "business.get_evidence", "business.explain_metric", "sales.operation_summary", "sales.customer_cohort", "sales.customer_journey"]);
|
|
64968
|
+
async function listAiSalesServices() {
|
|
64969
|
+
const base = resolveVpsServiceUrl().replace(/\/+$/, "");
|
|
64970
|
+
const headers3 = vpsServiceAuthHeaders(base);
|
|
64971
|
+
if (!headers3.authorization) throw new VertuError("\u9700\u8981\u5F53\u524D\u8D26\u53F7\u7684 VPS \u767B\u5F55\u51ED\u636E\u3002");
|
|
64972
|
+
const response = await fetch(`${base}/v1/tenant/mcp/services`, {
|
|
64973
|
+
headers: headers3,
|
|
64974
|
+
redirect: "error",
|
|
64975
|
+
signal: AbortSignal.timeout(15e3)
|
|
64976
|
+
});
|
|
64977
|
+
if (!response.ok) {
|
|
64978
|
+
await response.body?.cancel();
|
|
64979
|
+
throw new VertuError(`\u65E0\u6CD5\u8BFB\u53D6\u4F01\u4E1A MCP \u6388\u6743\uFF08HTTP ${response.status}\uFF09\u3002`);
|
|
64980
|
+
}
|
|
64981
|
+
const catalog = await response.json();
|
|
64982
|
+
if (catalog.tenant_id !== TENANT) throw new VertuError("vertu-aisales \u4EC5\u5BF9\u83B7\u6388\u6743\u7684 VERTU \u4F01\u4E1A\u6210\u5458\u5F00\u653E\u3002");
|
|
64983
|
+
return (Array.isArray(catalog.items) ? catalog.items : []).filter((item) => item.capability === "vertu-aisales" && /^[0-9a-f-]{36}$/i.test(item.id)).map((item) => ({ id: item.id, name: item.name || "VERTU AI Sales" }));
|
|
64984
|
+
}
|
|
64985
|
+
async function runAiSalesMcp(operation, serviceId) {
|
|
64986
|
+
if (operation && !TOOL_NAMES.has(operation.tool)) throw new VertuError("\u672A\u77E5\u7684 VERTU AI Sales \u5DE5\u5177\uFF0C\u8BF7\u5148\u8FD0\u884C vps-work vertu-aisales tools\u3002");
|
|
64987
|
+
const services = (await listAiSalesServices()).filter((item) => !serviceId || item.id === serviceId);
|
|
64988
|
+
if (services.length !== 1) throw new VertuError(services.length ? "\u5B58\u5728\u591A\u4E2A AI Sales \u670D\u52A1\uFF0C\u8BF7\u8FD0\u884C vps-work vertu-aisales services\uFF0C\u518D\u7528 --service-id \u6307\u5B9A\u5B9E\u4F8B\u3002" : "\u5F53\u524D\u8D26\u53F7\u6CA1\u6709\u53EF\u7528\u7684 vertu-aisales \u670D\u52A1\uFF0C\u8BF7\u7531\u7BA1\u7406\u5458\u5728\u4F01\u4E1A MCP \u540E\u53F0\u5F00\u901A\u3002");
|
|
64989
|
+
const base = resolveVpsServiceUrl().replace(/\/+$/, "");
|
|
64990
|
+
return runMcp(`${base}/v1/tenant/mcp/services/${services[0].id}`, vpsServiceAuthHeaders(base), TOOL_NAMES, operation);
|
|
64991
|
+
}
|
|
64992
|
+
|
|
64993
|
+
// src/commands/vertu-aisales.ts
|
|
64994
|
+
function buildVertuAiSalesCommand() {
|
|
64995
|
+
const command = new Command("vertu-aisales").description("VERTU \u5BA2\u6237\u6C9F\u901A\u67E5\u8BE2\uFF08\u5F53\u524D\u4F01\u4E1A\u548C\u5458\u5DE5\u6570\u636E\u6388\u6743\uFF09");
|
|
64996
|
+
command.command("services").description("\u5217\u51FA\u5F53\u524D\u8D26\u53F7\u53EF\u7528\u7684 AI Sales \u670D\u52A1\u5B9E\u4F8B").action(async () => console.log(JSON.stringify({ items: await listAiSalesServices() }, null, 2)));
|
|
64997
|
+
command.command("tools").description("\u53D1\u73B0\u53EF\u8C03\u7528\u5DE5\u5177\u548C\u53C2\u6570 schema").option("--service-id <id>", "\u4F01\u4E1A MCP \u670D\u52A1\u5B9E\u4F8B ID").action(async (opts) => console.log(JSON.stringify(await runAiSalesMcp(void 0, opts.serviceId), null, 2)));
|
|
64998
|
+
command.command("call").description("\u8C03\u7528 AINativeSales \u9500\u552E\u53EA\u8BFB\u5DE5\u5177\uFF1B\u5148\u53D1\u73B0\u4E1A\u52A1\u5BF9\u8C61\u4E0E\u6307\u6807").requiredOption("--tool <name>", "tools \u8FD4\u56DE\u7684\u5DE5\u5177\u540D").option("--args <json>", "JSON \u5BF9\u8C61\uFF0C\u652F\u6301 @file / @-", "{}").option("--service-id <id>", "\u4F01\u4E1A MCP \u670D\u52A1\u5B9E\u4F8B ID").action(async (opts) => {
|
|
64999
|
+
const raw = await expandAtFileToken(opts.args, "--args");
|
|
65000
|
+
let args;
|
|
65001
|
+
try {
|
|
65002
|
+
args = JSON.parse(raw);
|
|
65003
|
+
} catch {
|
|
65004
|
+
throw new VertuError("--args \u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002");
|
|
65005
|
+
}
|
|
65006
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) throw new VertuError("--args \u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002");
|
|
65007
|
+
console.log(JSON.stringify(await runAiSalesMcp({ tool: opts.tool, arguments: args }, opts.serviceId), null, 2));
|
|
65008
|
+
});
|
|
65009
|
+
return command;
|
|
65010
|
+
}
|
|
65011
|
+
|
|
65012
|
+
// src/core/erp-mcp-client.ts
|
|
65013
|
+
var tools = /* @__PURE__ */ new Set(["erp-query", "erp-list-tables", "erp-table-columns"]);
|
|
65014
|
+
async function runErpMcp(operation, baseUrl4) {
|
|
65015
|
+
if (operation && !tools.has(operation.tool)) throw new VertuError("\u4EC5\u652F\u6301 ERP \u53EA\u8BFB\u5DE5\u5177\uFF0C\u8BF7\u5148\u8FD0\u884C vps-work vertu-erp tools\u3002");
|
|
65016
|
+
const reply = await hermesRequest("POST", "/hermes-console/api/platform-tools/vertu-erp", { baseUrl: baseUrl4, body: operation ? { action: "call", tool: operation.tool, arguments: operation.arguments } : { action: "tools" } });
|
|
65017
|
+
if (!reply.result || typeof reply.result !== "object") throw new VertuError("ERP \u670D\u52A1\u54CD\u5E94\u65E0\u6548\u3002");
|
|
65018
|
+
return reply.result;
|
|
65019
|
+
}
|
|
65020
|
+
|
|
65021
|
+
// src/commands/vertu-erp.ts
|
|
65022
|
+
function buildVertuErpCommand() {
|
|
65023
|
+
const command = new Command("vertu-erp").description("\u4F7F\u7528\u5F53\u524D\u8D26\u53F7\u83B7\u6388\u6743\u7684 ERP MCP\uFF08\u53EA\u8BFB\uFF0C\u4E0D\u81EA\u52A8\u63D0\u6743\uFF09");
|
|
65024
|
+
command.command("tools").description("\u5217\u51FA ERP \u5DE5\u5177\u53CA\u5B9E\u65F6\u53C2\u6570 schema").option("--hermes-base-url <url>", "Hermes \u670D\u52A1\u6839\u5730\u5740").action(async (opts) => {
|
|
65025
|
+
console.log(JSON.stringify(await runErpMcp(void 0, opts.hermesBaseUrl), null, 2));
|
|
65026
|
+
});
|
|
65027
|
+
command.command("call").description("\u8C03\u7528 ERP \u53EA\u8BFB\u5DE5\u5177\uFF1B\u53C2\u6570\u4EE5 tools \u8FD4\u56DE\u7684 schema \u4E3A\u51C6").requiredOption("--tool <name>", "erp-query / erp-list-tables / erp-table-columns").option("--args <json>", "JSON \u53C2\u6570\u5BF9\u8C61\uFF0C\u652F\u6301 @file \u6216 @-\uFF08\u6807\u51C6\u8F93\u5165\uFF09", "{}").option("--hermes-base-url <url>", "Hermes \u670D\u52A1\u6839\u5730\u5740").action(async (opts) => {
|
|
65028
|
+
const raw = await expandAtFileToken(opts.args, "--args");
|
|
65029
|
+
let args;
|
|
65030
|
+
try {
|
|
65031
|
+
args = JSON.parse(raw);
|
|
65032
|
+
} catch {
|
|
65033
|
+
throw new VertuError("--args \u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002");
|
|
65034
|
+
}
|
|
65035
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) throw new VertuError("--args \u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002");
|
|
65036
|
+
console.log(JSON.stringify(await runErpMcp({ tool: opts.tool, arguments: args }, opts.hermesBaseUrl), null, 2));
|
|
65037
|
+
});
|
|
65038
|
+
return command;
|
|
65039
|
+
}
|
|
65040
|
+
|
|
64843
65041
|
// src/commands/cli-install.ts
|
|
64844
65042
|
var import_node_child_process2 = require("child_process");
|
|
64845
65043
|
function assertNodeEngine() {
|
|
@@ -64923,6 +65121,8 @@ function buildCliRootHelpAfter() {
|
|
|
64923
65121
|
"USAGE:",
|
|
64924
65122
|
` ${b} catalog [--domain sales]`,
|
|
64925
65123
|
` ${b} exec --skill <key> --script <key> [--param k=v]`,
|
|
65124
|
+
` ${b} vertu-aisales tools | vertu-aisales call --tool <name> --args @params.json`,
|
|
65125
|
+
` ${b} vertu-erp tools | vertu-erp call --tool <name> --args @params.json`,
|
|
64926
65126
|
` ${b} <domain> +<shortcut> [options]`,
|
|
64927
65127
|
` ${b} auth <subcommand> [options]`,
|
|
64928
65128
|
"",
|
|
@@ -65132,7 +65332,7 @@ function rewriteLongFlag(tok) {
|
|
|
65132
65332
|
}
|
|
65133
65333
|
|
|
65134
65334
|
// src/bin/vps-work.ts
|
|
65135
|
-
var PKG_VERSION = "2.
|
|
65335
|
+
var PKG_VERSION = "2.5.1" ? "2.5.1" : "0.0.0-dev";
|
|
65136
65336
|
function smartFlagSuggest(flag, candidates) {
|
|
65137
65337
|
if (!flag.startsWith("--") || flag.length < 4) return "";
|
|
65138
65338
|
const word = flag.slice(2);
|
|
@@ -65261,6 +65461,8 @@ async function main() {
|
|
|
65261
65461
|
program2.addCommand(buildPopupCommand());
|
|
65262
65462
|
program2.addCommand(buildCatalogCommand());
|
|
65263
65463
|
program2.addCommand(buildExecCommand());
|
|
65464
|
+
program2.addCommand(buildVertuErpCommand());
|
|
65465
|
+
program2.addCommand(buildVertuAiSalesCommand());
|
|
65264
65466
|
program2.addCommand(buildSkillCommand());
|
|
65265
65467
|
const userArgv = normalizeSnakeFlags(process.argv.slice(2));
|
|
65266
65468
|
const fullArgv = [...process.argv.slice(0, 2), ...userArgv];
|
package/package.json
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Build first: npm run build. Signing key is a file outside the repository.
|
|
2
|
+
// VPS_WORK_RELEASE_KEY_FILE, VPS_WORK_RELEASE_KEY_ID, VPS_WORK_MIN_DESKTOP
|
|
3
|
+
// and VPS_WORK_RUNTIME_OUTPUT are required. This script never publishes.
|
|
4
|
+
import { createHash, createPrivateKey, sign } from 'node:crypto';
|
|
5
|
+
import { readFile, readdir, mkdir, writeFile } from 'node:fs/promises';
|
|
6
|
+
import { dirname, join, resolve } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
9
|
+
const required = name => { const value = process.env[name]; if (!value) throw Error(`Missing ${name}`); return value; };
|
|
10
|
+
const keyFile = required('VPS_WORK_RELEASE_KEY_FILE'), keyId = required('VPS_WORK_RELEASE_KEY_ID');
|
|
11
|
+
const minDesktop = required('VPS_WORK_MIN_DESKTOP'), output = resolve(required('VPS_WORK_RUNTIME_OUTPUT'));
|
|
12
|
+
const pkg = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
|
|
13
|
+
if (![pkg.version, minDesktop].every(value => /^\d+\.\d+\.\d+$/.test(value))) throw Error('Stable versions required');
|
|
14
|
+
const files = {};
|
|
15
|
+
const add = async path => {
|
|
16
|
+
const bytes = await readFile(join(root, path)), text = bytes.toString('utf8');
|
|
17
|
+
if (!Buffer.from(text).equals(bytes)) throw Error(`Runtime bundle only supports UTF-8 files: ${path}`);
|
|
18
|
+
files[path] = text;
|
|
19
|
+
};
|
|
20
|
+
const walk = async path => {
|
|
21
|
+
for (const entry of (await readdir(join(root, path), { withFileTypes: true })).sort((a,b) => a.name.localeCompare(b.name))) {
|
|
22
|
+
if (entry.isSymbolicLink()) throw Error('Runtime symlinks are not allowed');
|
|
23
|
+
if (entry.isDirectory()) await walk(`${path}/${entry.name}`);
|
|
24
|
+
else await add(`${path}/${entry.name}`);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
for (const path of ['dist/vps-work.cjs', 'dist/office-runtime.cjs', 'dist/OFFICE-LICENSE', 'dist/OFFICE-NOTICE', 'package.json', '.well-known/skills/index.json']) await add(path);
|
|
28
|
+
await walk('skills');
|
|
29
|
+
const index = JSON.parse(files['.well-known/skills/index.json']);
|
|
30
|
+
for (const skill of index.skills) for (const path of skill.files) if (!files[path]) throw Error(`Missing indexed skill file: ${path}`);
|
|
31
|
+
const bundle = Buffer.from(JSON.stringify({ files }));
|
|
32
|
+
if (bundle.length > 24 * 1024 * 1024) throw Error('Runtime exceeds desktop limit');
|
|
33
|
+
const sha256 = createHash('sha256').update(bundle).digest('hex');
|
|
34
|
+
const name = `vps-work-${pkg.version}-${sha256}.json`;
|
|
35
|
+
const payload = Buffer.from(JSON.stringify({ product: 'vps-work', version: pkg.version, minDesktop, minNode: '20.0.0',
|
|
36
|
+
url: `https://vps-download.vertu.cn/app-releases/tools/vps-work/${name}`, sha256, bytes: bundle.length }));
|
|
37
|
+
const key = createPrivateKey(await readFile(keyFile));
|
|
38
|
+
if (key.asymmetricKeyType !== 'ed25519') throw Error('Ed25519 signing key required');
|
|
39
|
+
const envelope = { payload: payload.toString('base64'), signature: sign(null, payload, key).toString('base64'), keyId };
|
|
40
|
+
await mkdir(output, { recursive: true });
|
|
41
|
+
await writeFile(join(output, name), bundle);
|
|
42
|
+
await writeFile(join(output, 'stable.json'), JSON.stringify(envelope, null, 2));
|
|
43
|
+
console.log(`Prepared ${name} and stable.json. Upload the immutable bundle first, then stable.json. Nothing was published.`);
|