weaver-work-cli 0.1.6 → 0.1.7
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 +14 -9
- package/dist/cmd/skills/index.js +60 -0
- package/dist/internal/e10/auth/commands.js +44 -31
- package/dist/internal/e10/auth/session.js +44 -3
- package/dist/internal/e10/auth/xiaoe.js +363 -11
- package/dist/internal/e10/context.js +4 -2
- package/dist/internal/skills/detector.js +42 -0
- package/dist/internal/skills/install.js +50 -3
- package/dist/shortcuts/archive/render/search-format.js +12 -3
- package/dist/shortcuts/ebuilder-form/continuation.js +70 -0
- package/dist/shortcuts/ebuilder-form/errors.js +54 -0
- package/dist/shortcuts/ebuilder-form/host.js +1238 -0
- package/dist/shortcuts/ebuilder-form/index.js +108 -0
- package/dist/shortcuts/ebuilder-form/manifest.js +347 -0
- package/dist/shortcuts/ebuilder-form/operations/read.js +157 -0
- package/dist/shortcuts/ebuilder-form/operations/registry.js +56 -0
- package/dist/shortcuts/ebuilder-form/operations/shared.js +132 -0
- package/dist/shortcuts/ebuilder-form/operations/types.js +19 -0
- package/dist/shortcuts/ebuilder-form/operations/write.js +277 -0
- package/dist/shortcuts/ebuilder-form/operations.js +8 -0
- package/dist/shortcuts/ehr/operations/salary.js +2 -140
- package/dist/shortcuts/im/continuation.js +70 -0
- package/dist/shortcuts/{yimiaoban → im}/errors.js +14 -14
- package/dist/shortcuts/{yimiaoban → im}/host.js +26 -26
- package/dist/shortcuts/{yimiaoban → im}/index.js +42 -42
- package/dist/shortcuts/{yimiaoban → im}/manifest.js +7 -6
- package/dist/shortcuts/{yimiaoban → im}/operations/file-user.js +54 -41
- package/dist/shortcuts/{yimiaoban → im}/operations/group-read.js +46 -44
- package/dist/shortcuts/{yimiaoban → im}/operations/group-write.js +113 -66
- package/dist/shortcuts/{yimiaoban → im}/operations/msg-sync.js +164 -141
- package/dist/shortcuts/{yimiaoban → im}/operations/msg-write.js +47 -47
- package/dist/shortcuts/{yimiaoban → im}/operations/person.js +10 -10
- package/dist/shortcuts/{yimiaoban → im}/operations/registry.js +10 -8
- package/dist/shortcuts/{yimiaoban → im}/operations/session.js +82 -83
- package/dist/shortcuts/im/operations/shared.js +442 -0
- package/dist/shortcuts/{yimiaoban → im}/operations/types.js +1 -1
- package/dist/shortcuts/im/operations/user-remind.js +201 -0
- package/dist/shortcuts/{yimiaoban → im}/operations/write-util.js +7 -7
- package/dist/shortcuts/{yimiaoban → im}/operations.js +3 -3
- package/dist/shortcuts/index.js +10 -2
- package/dist/shortcuts/invoice/manifest.js +113 -10
- package/dist/shortcuts/invoice/operations/import.js +39 -14
- package/dist/shortcuts/invoice/operations/reim.js +38 -18
- package/dist/shortcuts/invoice/operations/shared.js +35 -6
- package/dist/shortcuts/jiuchuanhui/manifest.js +3 -3
- package/dist/shortcuts/jiuchuanhui/operations/registry.js +2 -2
- package/dist/shortcuts/{yimiaoban → okr}/continuation.js +10 -10
- package/dist/shortcuts/okr/errors.js +70 -0
- package/dist/shortcuts/okr/host.js +169 -0
- package/dist/shortcuts/okr/index.js +155 -0
- package/dist/shortcuts/okr/manifest.js +70 -0
- package/dist/shortcuts/okr/operations/link.js +305 -0
- package/dist/shortcuts/okr/operations/read.js +481 -0
- package/dist/shortcuts/okr/operations/registry.js +31 -0
- package/dist/shortcuts/okr/operations/shared.js +381 -0
- package/dist/shortcuts/okr/operations/types.js +88 -0
- package/dist/shortcuts/okr/operations/write.js +838 -0
- package/dist/shortcuts/okr/operations.js +8 -0
- package/dist/shortcuts/project/continuation.js +70 -0
- package/dist/shortcuts/project/errors.js +53 -0
- package/dist/shortcuts/project/host.js +160 -0
- package/dist/shortcuts/project/index.js +106 -0
- package/dist/shortcuts/project/manifest.js +36 -0
- package/dist/shortcuts/project/operations/read.js +551 -0
- package/dist/shortcuts/project/operations/registry.js +31 -0
- package/dist/shortcuts/project/operations/shared.js +68 -0
- package/dist/shortcuts/project/operations/types.js +39 -0
- package/dist/shortcuts/project/operations/write.js +266 -0
- package/dist/shortcuts/project/operations.js +8 -0
- package/dist/shortcuts/workflow/continuation.js +508 -0
- package/dist/shortcuts/workflow/endpoints.js +149 -0
- package/dist/shortcuts/workflow/errors.js +112 -0
- package/dist/shortcuts/workflow/host.js +224 -0
- package/dist/shortcuts/workflow/index.js +116 -0
- package/dist/shortcuts/workflow/manifest.js +30 -0
- package/dist/shortcuts/workflow/operations/form.js +4159 -0
- package/dist/shortcuts/workflow/operations/read.js +3778 -0
- package/dist/shortcuts/workflow/operations/registry.js +33 -0
- package/dist/shortcuts/workflow/operations/shared.js +167 -0
- package/dist/shortcuts/workflow/operations/types.js +44 -0
- package/dist/shortcuts/workflow/operations/write.js +1991 -0
- package/dist/shortcuts/workflow/operations.js +119 -0
- package/dist/shortcuts/workflow/state.js +182 -0
- package/docs/SKILL.md +5 -3
- package/docs/_catalog.md +10 -1
- package/docs/agent-invoice.md +2 -2
- package/docs/agent-skill-install.md +2 -2
- package/docs/e10-auth.md +3 -1
- package/docs/ebuilder-form.md +38 -0
- package/docs/im.md +104 -0
- package/docs/invoice.md +5 -5
- package/docs/okr.md +122 -0
- package/docs/operation-manual.md +10 -7
- package/docs/project.md +69 -0
- package/docs/skill-review-2026-09-19.md +68 -0
- package/package.json +3 -2
- package/scripts/package-skill.mjs +38 -11
- package/scripts/sync-connector-skills.mjs +172 -0
- package/skill-template/business-info.json +357 -16
- package/skill-template/domains/ebuilder-form.md +5 -0
- package/skill-template/domains/okr.md +18 -0
- package/skill-template/domains/shijingran.md +3 -0
- package/skill-template/domains/skill-maker.md +4 -4
- package/skill-template/domains/workflow.md +22 -0
- package/skill-template/domains/yepiaotong.md +4 -2
- package/skill-template/domains/yimiaoban.md +13 -10
- package/skill-template/product.json +5 -0
- package/skill-template/skill-template.md +1 -0
- package/skills/weaver-e10-calendar/SKILL.md +5 -1
- package/skills/weaver-e10-calendar/references/calendar-query.md +7 -0
- package/skills/weaver-e10-calendar/references/source-manifest.json +314 -32
- package/skills/weaver-e10-ebuilder-form/SKILL.md +123 -0
- package/skills/weaver-e10-ebuilder-form/references/context-routing.md +90 -0
- package/skills/weaver-e10-ebuilder-form/references/custom-api.md +86 -0
- package/skills/weaver-e10-ebuilder-form/references/disabled-capabilities.md +50 -0
- package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +100 -0
- package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +91 -0
- package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +74 -0
- package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +86 -0
- package/skills/weaver-e10-ebuilder-form/references/source-manifest.json +107 -0
- package/skills/weaver-e10-esb/SKILL.md +1 -1
- package/skills/weaver-e10-esb/references/source-manifest.json +15 -14
- package/skills/weaver-e10-hrm/SKILL.md +1 -1
- package/skills/weaver-e10-hrm/references/source-manifest.json +357 -38
- package/skills/weaver-e10-jiuchuanhui/SKILL.md +22 -4
- package/skills/weaver-e10-jiuchuanhui/references/clue.md +4 -2
- package/skills/weaver-e10-jiuchuanhui/references/contact.md +1 -1
- package/skills/weaver-e10-jiuchuanhui/references/customer.md +3 -3
- package/skills/weaver-e10-jiuchuanhui/references/disabled-capabilities.md +1 -1
- package/skills/weaver-e10-jiuchuanhui/references/discovery-config.md +10 -10
- package/skills/weaver-e10-jiuchuanhui/references/general-helpers.md +3 -3
- package/skills/weaver-e10-jiuchuanhui/references/sale.md +7 -7
- package/skills/weaver-e10-jiuchuanhui/references/source-manifest.json +3 -3
- package/skills/weaver-e10-jucailin/SKILL.md +2 -2
- package/skills/weaver-e10-mail/SKILL.md +22 -6
- package/skills/weaver-e10-meeting/SKILL.md +22 -1
- package/skills/weaver-e10-okr/SKILL.md +139 -0
- package/skills/weaver-e10-okr/references/okr-align.md +59 -0
- package/skills/weaver-e10-okr/references/okr-keyresult.md +68 -0
- package/skills/weaver-e10-okr/references/okr-link-routing.md +67 -0
- package/skills/weaver-e10-okr/references/okr-query.md +105 -0
- package/skills/weaver-e10-okr/references/okr-write.md +94 -0
- package/skills/weaver-e10-okr/references/source-manifest.json +672 -0
- package/skills/weaver-e10-plan/SKILL.md +3 -3
- package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
- package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
- package/skills/weaver-e10-qiyecheng/SKILL.md +21 -1
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +17 -17
- package/skills/weaver-e10-shared/SKILL.md +79 -11
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +41 -8
- package/skills/weaver-e10-shared/references/non-interactive-environment.md +78 -0
- package/skills/weaver-e10-shared/references/weaver-e10-installation.md +39 -0
- package/skills/weaver-e10-shijingran/SKILL.md +83 -0
- package/skills/weaver-e10-shijingran/references/field-resolution.md +105 -0
- package/skills/weaver-e10-shijingran/references/operations.md +154 -0
- package/skills/weaver-e10-shijingran/references/source-manifest.json +1380 -0
- package/skills/weaver-e10-shijingran/references/write-operations.md +90 -0
- package/skills/weaver-e10-skill-maker/SKILL.md +26 -9
- package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +39 -8
- package/skills/weaver-e10-skill-maker/references/detector-validation.md +25 -8
- package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +66 -5
- package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +86 -0
- package/skills/weaver-e10-skill-maker/references/source-update-detection.md +59 -5
- package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +16 -8
- package/skills/weaver-e10-wenshuding/SKILL.md +28 -4
- package/skills/weaver-e10-wenshuding/references/archive-search.md +14 -0
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +27 -26
- package/skills/weaver-e10-workflow/SKILL.md +250 -0
- package/skills/weaver-e10-workflow/references/source-manifest.json +1062 -0
- package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +96 -0
- package/skills/weaver-e10-workflow/references/workflow-batch.md +275 -0
- package/skills/weaver-e10-workflow/references/workflow-create.md +182 -0
- package/skills/weaver-e10-workflow/references/workflow-edit.md +106 -0
- package/skills/weaver-e10-workflow/references/workflow-memory.md +165 -0
- package/skills/weaver-e10-workflow/references/workflow-operate.md +153 -0
- package/skills/weaver-e10-workflow/references/workflow-query.md +821 -0
- package/skills/weaver-e10-workflow/references/workflow-share.md +117 -0
- package/skills/weaver-e10-workflow/references/workflow-view.md +189 -0
- package/skills/weaver-e10-yepiaotong/SKILL.md +28 -28
- package/skills/weaver-e10-yepiaotong/references/invoice-disabled-capabilities.md +11 -5
- package/skills/weaver-e10-yepiaotong/references/invoice-import.md +14 -8
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +9 -43
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +8 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +13 -17
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +6 -7
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +2 -2
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +1155 -553
- package/skills/weaver-e10-yimiaoban/SKILL.md +56 -38
- package/skills/weaver-e10-yimiaoban/references/ding-write.md +8 -8
- package/skills/weaver-e10-yimiaoban/references/error-codes.md +16 -0
- package/skills/weaver-e10-yimiaoban/references/field-resolution.md +10 -10
- package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +12 -12
- package/skills/weaver-e10-yimiaoban/references/group-read.md +16 -16
- package/skills/weaver-e10-yimiaoban/references/group-write.md +17 -15
- package/skills/weaver-e10-yimiaoban/references/msg-read.md +21 -17
- package/skills/weaver-e10-yimiaoban/references/msg-write.md +10 -10
- package/skills/weaver-e10-yimiaoban/references/person.md +6 -6
- package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +15 -11
- package/skills/weaver-e10-yimiaoban/references/session-sysmsg.md +11 -10
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +2164 -154
- package/skills/weaver-e10-yimiaoban/references/user-remind.md +75 -0
- package/skills/weaver-e10-ziguanjia/SKILL.md +4 -2
- package/skills/weaver-e10-ziguanjia/references/source-manifest.json +99 -29
- package/tools/weaver-skill-detector-1.0.13/SKILL.md +253 -0
- package/tools/weaver-skill-detector-1.0.13/_meta.json +6 -0
- package/tools/weaver-skill-detector-1.0.13/references/checklist.md +298 -0
- package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +4190 -0
- package/dist/shortcuts/yimiaoban/operations/shared.js +0 -236
- package/docs/yimiaoban.md +0 -86
- package/skills/weaver-e10-calendar/product.json +0 -8
- package/skills/weaver-e10-esb/product.json +0 -8
- package/skills/weaver-e10-hrm/product.json +0 -8
- package/skills/weaver-e10-jiuchuanhui/product.json +0 -8
- package/skills/weaver-e10-jucailin/product.json +0 -8
- package/skills/weaver-e10-mail/product.json +0 -8
- package/skills/weaver-e10-meeting/product.json +0 -8
- package/skills/weaver-e10-plan/product.json +0 -8
- package/skills/weaver-e10-qiyecheng/product.json +0 -8
- package/skills/weaver-e10-skill-maker/product.json +0 -8
- package/skills/weaver-e10-wenshuding/product.json +0 -8
- package/skills/weaver-e10-yepiaotong/product.json +0 -8
- package/skills/weaver-e10-yepiaotong/references/invoice-red.md +0 -261
- package/skills/weaver-e10-yimiaoban/product.json +0 -8
- package/skills/weaver-e10-ziguanjia/product.json +0 -8
- /package/dist/shortcuts/{yimiaoban → im}/operations/msg-parse.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CliError, ExitCode } from '../../core/errors.js';
|
|
2
|
-
export class
|
|
2
|
+
export class ImCliError extends CliError {
|
|
3
3
|
type;
|
|
4
4
|
subtype;
|
|
5
5
|
code;
|
|
@@ -9,7 +9,7 @@ export class YmbCliError extends CliError {
|
|
|
9
9
|
partialData;
|
|
10
10
|
constructor(type, subtype, message, options = {}) {
|
|
11
11
|
super(message, options.exitCode ?? ExitCode.InternalError);
|
|
12
|
-
this.name = '
|
|
12
|
+
this.name = 'ImCliError';
|
|
13
13
|
this.type = type;
|
|
14
14
|
this.subtype = subtype;
|
|
15
15
|
this.code = options.code;
|
|
@@ -19,41 +19,41 @@ export class YmbCliError extends CliError {
|
|
|
19
19
|
this.partialData = options.partialData;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
export function
|
|
23
|
-
return new
|
|
22
|
+
export function imValidationError(subtype, message, details) {
|
|
23
|
+
return new ImCliError('validation', subtype, message, {
|
|
24
24
|
details,
|
|
25
25
|
exitCode: ExitCode.UsageError,
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
|
-
export function
|
|
29
|
-
return new
|
|
28
|
+
export function imAuthError(subtype, message, details) {
|
|
29
|
+
return new ImCliError('authentication', subtype, message, {
|
|
30
30
|
details,
|
|
31
31
|
exitCode: ExitCode.AuthError,
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
-
export function
|
|
35
|
-
return new
|
|
34
|
+
export function imNetworkError(subtype, message, options = {}) {
|
|
35
|
+
return new ImCliError('network', subtype, message, {
|
|
36
36
|
...options,
|
|
37
37
|
retryable: options.retryable ?? true,
|
|
38
38
|
exitCode: ExitCode.NetworkError,
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
-
export function
|
|
42
|
-
return new
|
|
41
|
+
export function imConfirmationError(action, details) {
|
|
42
|
+
return new ImCliError('confirmation', 'required', '该操作需要明确确认', {
|
|
43
43
|
details: { action, ...details },
|
|
44
44
|
exitCode: ExitCode.ConfirmationRequired,
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
|
-
export function
|
|
48
|
-
return new
|
|
47
|
+
export function imPartialError(message, partialData, details) {
|
|
48
|
+
return new ImCliError('partial', 'write_uncertain', message, {
|
|
49
49
|
details,
|
|
50
50
|
partialData,
|
|
51
51
|
exitCode: ExitCode.Partial,
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
/** 业务失败(HTTP 200 但接口 code 非 0 / actionMsg.code 非 0 等)。 */
|
|
55
|
-
export function
|
|
56
|
-
return new
|
|
55
|
+
export function imBusinessError(subtype, message, options = {}) {
|
|
56
|
+
return new ImCliError('api', subtype, message, {
|
|
57
57
|
...options,
|
|
58
58
|
code: options.code,
|
|
59
59
|
exitCode: 1,
|
|
@@ -5,7 +5,7 @@ import { dirname, extname, resolve } from 'node:path';
|
|
|
5
5
|
import { requireE10Session } from '../../internal/e10/context.js';
|
|
6
6
|
import { getActiveProfile } from '../../internal/e10/auth/session.js';
|
|
7
7
|
import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
|
|
8
|
-
import {
|
|
8
|
+
import { imAuthError, imNetworkError, ImCliError, imValidationError } from './errors.js';
|
|
9
9
|
export const IM_PREFIX = '/api/em/msg/executeIm';
|
|
10
10
|
function inferProfile(ctx) {
|
|
11
11
|
const options = ctx.getGlobalOptions();
|
|
@@ -13,10 +13,10 @@ function inferProfile(ctx) {
|
|
|
13
13
|
}
|
|
14
14
|
export function assertPath(requestPath) {
|
|
15
15
|
if (typeof requestPath !== 'string' || !requestPath.startsWith('/') || requestPath.startsWith('//')) {
|
|
16
|
-
throw
|
|
16
|
+
throw imValidationError('path_invalid', '请求路径必须是相对绝对路径');
|
|
17
17
|
}
|
|
18
18
|
if (/^https?:/i.test(requestPath) || /[\r\n]/.test(requestPath) || requestPath.includes('/../')) {
|
|
19
|
-
throw
|
|
19
|
+
throw imValidationError('path_invalid', '请求路径不允许跨域或路径逃逸');
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
function formBody(form) {
|
|
@@ -32,7 +32,7 @@ function formBody(form) {
|
|
|
32
32
|
}
|
|
33
33
|
function mapRuntimeNetworkError(error) {
|
|
34
34
|
if (error instanceof E10ApiError && error.type === 'network') {
|
|
35
|
-
throw
|
|
35
|
+
throw imNetworkError(error.subtype, error.message, {
|
|
36
36
|
retryable: error.retryable,
|
|
37
37
|
details: error.details,
|
|
38
38
|
});
|
|
@@ -64,7 +64,7 @@ async function md5File(filePath) {
|
|
|
64
64
|
hash.update(chunk);
|
|
65
65
|
return hash.digest('hex');
|
|
66
66
|
}
|
|
67
|
-
export function
|
|
67
|
+
export function createImHost(ctx, dependencies = {}) {
|
|
68
68
|
let e10Session = null;
|
|
69
69
|
let sessionContext = null;
|
|
70
70
|
let selfIdentity = null;
|
|
@@ -104,7 +104,7 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
104
104
|
let response;
|
|
105
105
|
try {
|
|
106
106
|
response = await (await runtime()).requestJson({
|
|
107
|
-
module: '
|
|
107
|
+
module: 'im',
|
|
108
108
|
operation,
|
|
109
109
|
method: resolvedMethod,
|
|
110
110
|
path,
|
|
@@ -120,20 +120,20 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
120
120
|
mapRuntimeNetworkError(error);
|
|
121
121
|
}
|
|
122
122
|
if (response.status === 401 || response.status === 302) {
|
|
123
|
-
throw
|
|
123
|
+
throw imAuthError('session_expired', 'E10 登录态已失效,请先向用户确认 E10 登录域名,再运行 weaver-work-cli auth login --base-url <域名> 完成登录', { httpStatus: response.status });
|
|
124
124
|
}
|
|
125
125
|
if (response.parseError) {
|
|
126
126
|
if (response.status < 200 || response.status >= 300) {
|
|
127
|
-
throw new
|
|
127
|
+
throw new ImCliError('api', 'http_error', `泛微接口 HTTP ${response.status}`, {
|
|
128
128
|
code: response.status,
|
|
129
129
|
details: { status: response.status },
|
|
130
130
|
exitCode: 1,
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
|
-
throw
|
|
133
|
+
throw imNetworkError('protocol', `接口返回不是合法 JSON(HTTP ${response.status})`, { retryable: false });
|
|
134
134
|
}
|
|
135
135
|
if (response.status < 200 || response.status >= 300) {
|
|
136
|
-
throw new
|
|
136
|
+
throw new ImCliError('api', 'http_error', `泛微接口 HTTP ${response.status}`, {
|
|
137
137
|
code: response.status,
|
|
138
138
|
details: { status: response.status },
|
|
139
139
|
exitCode: 1,
|
|
@@ -159,10 +159,10 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
159
159
|
signal: controller.signal,
|
|
160
160
|
});
|
|
161
161
|
if (resp.status === 401 || resp.status === 302) {
|
|
162
|
-
throw
|
|
162
|
+
throw imAuthError('session_expired', '登录态已失效:下载需有效登录态,请重新登录后重试');
|
|
163
163
|
}
|
|
164
164
|
if (resp.status !== 200) {
|
|
165
|
-
throw new
|
|
165
|
+
throw new ImCliError('api', 'download_failed', `下载失败 HTTP ${resp.status}`, {
|
|
166
166
|
code: resp.status,
|
|
167
167
|
exitCode: 1,
|
|
168
168
|
});
|
|
@@ -170,10 +170,10 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
170
170
|
return Buffer.from(await resp.arrayBuffer());
|
|
171
171
|
}
|
|
172
172
|
catch (error) {
|
|
173
|
-
if (error instanceof
|
|
173
|
+
if (error instanceof ImCliError)
|
|
174
174
|
throw error;
|
|
175
175
|
const message = error instanceof Error ? error.message : String(error);
|
|
176
|
-
throw
|
|
176
|
+
throw imNetworkError('transport', `下载失败:${message}`, { retryable: true });
|
|
177
177
|
}
|
|
178
178
|
finally {
|
|
179
179
|
clearTimeout(timer);
|
|
@@ -186,19 +186,19 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
186
186
|
await ensureSession();
|
|
187
187
|
const base = sessionContext?.baseUrl || '';
|
|
188
188
|
if (!base)
|
|
189
|
-
throw
|
|
189
|
+
throw imAuthError('self_identity_unavailable', '缺少 baseUrl,请先登录');
|
|
190
190
|
const res = await request({
|
|
191
191
|
method: 'POST',
|
|
192
192
|
path: `/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(base)}`,
|
|
193
193
|
body: {},
|
|
194
|
-
operation: '
|
|
194
|
+
operation: 'im.self.identity',
|
|
195
195
|
});
|
|
196
196
|
const cur = res?.currentUser || res?.data?.currentUser || {};
|
|
197
197
|
const uid = String(cur.imUid || sessionContext?.userId || '');
|
|
198
198
|
const cid = String(cur.imCid || '');
|
|
199
199
|
const name = cur.name || cur.realName || cur.userName || '';
|
|
200
200
|
if (!uid || !cid) {
|
|
201
|
-
throw
|
|
201
|
+
throw imAuthError('self_identity_incomplete', `teamsCheck 未返回完整 IM 身份(imUid=${uid || '-'}, imCid=${cid || '-'}),请确认登录态后重试`);
|
|
202
202
|
}
|
|
203
203
|
selfIdentity = { uid, cid, name };
|
|
204
204
|
return selfIdentity;
|
|
@@ -207,10 +207,10 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
207
207
|
async function uploadFile(filePath, options = {}) {
|
|
208
208
|
const abs = resolve(filePath);
|
|
209
209
|
if (!existsSync(abs))
|
|
210
|
-
throw
|
|
210
|
+
throw imValidationError('file_not_found', `文件不存在: ${abs}`);
|
|
211
211
|
const st = await stat(abs);
|
|
212
212
|
if (!st.isFile())
|
|
213
|
-
throw
|
|
213
|
+
throw imValidationError('file_invalid', `不是文件: ${abs}`);
|
|
214
214
|
const name = options.name || filePath.split(/[\\/]/).pop() || 'file';
|
|
215
215
|
const size = st.size;
|
|
216
216
|
const md5 = await md5File(abs);
|
|
@@ -243,12 +243,12 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
243
243
|
path: '/api/file/preUploadCheck',
|
|
244
244
|
multipart: preForm,
|
|
245
245
|
headers: uploadHeaders,
|
|
246
|
-
operation: '
|
|
246
|
+
operation: 'im.file.upload.check',
|
|
247
247
|
timeoutMs: 15_000,
|
|
248
248
|
});
|
|
249
249
|
const preData = preRes?.data || {};
|
|
250
250
|
if (!preData.preUploadId) {
|
|
251
|
-
throw new
|
|
251
|
+
throw new ImCliError('api', 'upload_check_failed', `preUploadCheck 失败`, { details: preRes, exitCode: 1 });
|
|
252
252
|
}
|
|
253
253
|
const preUploadId = String(preData.preUploadId);
|
|
254
254
|
const uploadType = preData.uploadType || 'common';
|
|
@@ -263,12 +263,12 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
263
263
|
path: '/api/file/valid/upload',
|
|
264
264
|
multipart: upForm,
|
|
265
265
|
headers: uploadHeaders,
|
|
266
|
-
operation: '
|
|
266
|
+
operation: 'im.file.upload.do',
|
|
267
267
|
timeoutMs: 60_000,
|
|
268
268
|
});
|
|
269
269
|
const upData = upRes?.data || {};
|
|
270
270
|
if (!upData.fileObj || (!upData.fileObj.id && !upData.fileObj.fileid)) {
|
|
271
|
-
throw new
|
|
271
|
+
throw new ImCliError('api', 'upload_failed', `valid/upload 失败`, { details: upRes, exitCode: 1 });
|
|
272
272
|
}
|
|
273
273
|
return upData.fileObj;
|
|
274
274
|
}
|
|
@@ -289,7 +289,7 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
289
289
|
path: '/api/hrm/common/getEmployeeByIds',
|
|
290
290
|
body: { userIdList: batch, externalIdList: [] },
|
|
291
291
|
headers: { devtype: '5' },
|
|
292
|
-
operation: '
|
|
292
|
+
operation: 'im.person.resolveByIds',
|
|
293
293
|
timeoutMs: 15_000,
|
|
294
294
|
});
|
|
295
295
|
const list = res?.data?.userList;
|
|
@@ -342,7 +342,7 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
342
342
|
method: 'POST',
|
|
343
343
|
path: '/api/hrm/common/browser/data/resource',
|
|
344
344
|
body: { ...baseForm, cmd: 'all', formDatas, quickSearchDatas: {}, type: 'and', current, pageSize, containsNoneAccount: false, containsPartTimeEmployee: false, containsDls: false },
|
|
345
|
-
operation: '
|
|
345
|
+
operation: 'im.person.search',
|
|
346
346
|
timeoutMs: 15_000,
|
|
347
347
|
});
|
|
348
348
|
const rows = res?.data?.data;
|
|
@@ -391,7 +391,7 @@ export function createYmbHost(ctx, dependencies = {}) {
|
|
|
391
391
|
method: 'POST',
|
|
392
392
|
path: '/api/bs/i18n/labelmanage/getHtmlLabelNames',
|
|
393
393
|
body: miss,
|
|
394
|
-
operation: '
|
|
394
|
+
operation: 'im.i18n.labels',
|
|
395
395
|
timeoutMs: 15_000,
|
|
396
396
|
});
|
|
397
397
|
const data = res?.data || {};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { ExitCode, isCliError, toErrorEnvelope } from '../../core/errors.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { createImContinuationSigner } from './continuation.js';
|
|
4
|
+
import { imValidationError } from './errors.js';
|
|
5
|
+
import { createImHost } from './host.js';
|
|
6
|
+
import { imManifest } from './manifest.js';
|
|
7
|
+
import { executeImOperation } from './operations.js';
|
|
8
8
|
function asOptions(value) {
|
|
9
9
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
10
10
|
}
|
|
@@ -22,7 +22,7 @@ export async function inputFrom(options, extra = {}) {
|
|
|
22
22
|
const opts = asOptions(options);
|
|
23
23
|
let input = {};
|
|
24
24
|
if (opts.input && opts.inputJson) {
|
|
25
|
-
throw
|
|
25
|
+
throw imValidationError('input_conflict', '不能同时传 --input 和 --input-json');
|
|
26
26
|
}
|
|
27
27
|
if (opts.inputJson) {
|
|
28
28
|
input = parseJsonInput(String(opts.inputJson), '--input-json');
|
|
@@ -33,7 +33,7 @@ export async function inputFrom(options, extra = {}) {
|
|
|
33
33
|
raw = stripBom(opts.input === '-' ? await readStdin() : await readFile(String(opts.input), 'utf8'));
|
|
34
34
|
}
|
|
35
35
|
catch {
|
|
36
|
-
throw
|
|
36
|
+
throw imValidationError('input_unreadable', `无法读取 --input:${String(opts.input)}`);
|
|
37
37
|
}
|
|
38
38
|
input = parseJsonInput(raw, '--input');
|
|
39
39
|
}
|
|
@@ -51,7 +51,7 @@ function parseJsonInput(raw, label) {
|
|
|
51
51
|
return parsed;
|
|
52
52
|
}
|
|
53
53
|
catch {
|
|
54
|
-
throw
|
|
54
|
+
throw imValidationError('input_invalid', `${label} 不是合法 JSON 对象`);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
function withJsonInputOptions(command) {
|
|
@@ -82,10 +82,10 @@ function failureEnvelope(error) {
|
|
|
82
82
|
}
|
|
83
83
|
async function executeAndPrint(ctx, operation, input) {
|
|
84
84
|
try {
|
|
85
|
-
const result = await
|
|
85
|
+
const result = await executeImOperation(operation, input, {
|
|
86
86
|
ctx,
|
|
87
|
-
host:
|
|
88
|
-
continuation:
|
|
87
|
+
host: createImHost(ctx),
|
|
88
|
+
continuation: createImContinuationSigner(ctx),
|
|
89
89
|
});
|
|
90
90
|
ctx.output.write(successEnvelope(operation, result), { json: true });
|
|
91
91
|
}
|
|
@@ -105,34 +105,34 @@ function boolOption(value) {
|
|
|
105
105
|
* 写操作一律通过 `run ...prepare`(签发 continuation)→ `run ...apply --input-json '{"confirm":true,"continuation":"..."}'`
|
|
106
106
|
* 两段式执行,便捷层不绕过确认链。
|
|
107
107
|
*/
|
|
108
|
-
export const
|
|
109
|
-
name: '
|
|
108
|
+
export const imShortcut = {
|
|
109
|
+
name: 'im',
|
|
110
110
|
description: '泛微E10易秒办(即时通讯)CLI',
|
|
111
111
|
category: 'shortcut',
|
|
112
112
|
register({ program, action }) {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
.description('Print
|
|
113
|
+
const im = program.command('im').description('泛微E10易秒办:消息/群组/会话/系统消息');
|
|
114
|
+
im.command('schema')
|
|
115
|
+
.description('Print im operation manifest for agents')
|
|
116
116
|
.action(action((ctx) => {
|
|
117
|
-
ctx.output.write(
|
|
117
|
+
ctx.output.write(imManifest, { json: true });
|
|
118
118
|
}));
|
|
119
|
-
withJsonInputOptions(
|
|
120
|
-
.description('Run
|
|
121
|
-
.argument('<operation>', 'operation name, e.g.
|
|
119
|
+
withJsonInputOptions(im.command('run')
|
|
120
|
+
.description('Run an im operation with JSON input')
|
|
121
|
+
.argument('<operation>', 'operation name, e.g. im.msg.sync.group'))
|
|
122
122
|
.action(action(async (ctx, operation, options) => {
|
|
123
123
|
await executeAndPrint(ctx, String(operation), await inputFrom(options));
|
|
124
124
|
}));
|
|
125
125
|
// ---- 高频便捷命令:会话 ----
|
|
126
|
-
const session =
|
|
126
|
+
const session = im.command('session').description('Session commands');
|
|
127
127
|
withJsonInputOptions(session.command('list')
|
|
128
128
|
.description('拉取当前用户会话列表')
|
|
129
|
-
.option('--num <n>', '单页条数(默认 20,最多 50
|
|
129
|
+
.option('--num <n>', '单页条数(默认 20,最多 50;会话列表不自动翻页)')
|
|
130
130
|
.option('--msgid <id>', '锚点消息 id')
|
|
131
131
|
.option('--flag <0|1|2>', '0 up+down / 1 up / 2 down(默认 2)')
|
|
132
132
|
.option('--type <type>', '仅展示该 session_type'))
|
|
133
133
|
.action(action(async (ctx, options) => {
|
|
134
134
|
const opts = asOptions(options);
|
|
135
|
-
await executeAndPrint(ctx, '
|
|
135
|
+
await executeAndPrint(ctx, 'im.session.list', await inputFrom(options, {
|
|
136
136
|
num: opts.num !== undefined ? Number(opts.num) : undefined,
|
|
137
137
|
msgid: opts.msgid,
|
|
138
138
|
flag: opts.flag !== undefined ? Number(opts.flag) : undefined,
|
|
@@ -140,19 +140,19 @@ export const yimiaobanShortcut = {
|
|
|
140
140
|
}));
|
|
141
141
|
}));
|
|
142
142
|
// ---- 高频便捷命令:消息 ----
|
|
143
|
-
const msg =
|
|
143
|
+
const msg = im.command('msg').description('Message commands');
|
|
144
144
|
withJsonInputOptions(msg.command('sync-single')
|
|
145
145
|
.description('拉取与某人的单聊消息')
|
|
146
146
|
.option('--from-uid <uid>', '对方 uid(必填)')
|
|
147
147
|
.option('--from-cid <cid>', '对方 cid(必填)')
|
|
148
|
-
.option('--num <n>', '
|
|
149
|
-
.option('--from <time>', '起始时间 YYYY-MM-DD[ HH:mm:ss] 或 unix
|
|
150
|
-
.option('--to <time>', '
|
|
148
|
+
.option('--num <n>', '每页数量(默认 50,最多 50)')
|
|
149
|
+
.option('--from <time>', '起始时间 YYYY-MM-DD[ HH:mm:ss] 或 unix 秒(跨度 > 7 天自动收敛)')
|
|
150
|
+
.option('--to <time>', '结束时间(跨度 > 7 天自动收敛)')
|
|
151
151
|
.option('--latest', '拉最新不限日期')
|
|
152
152
|
.option('--img-format <fmt>', 'small/large/original(默认 small)'))
|
|
153
153
|
.action(action(async (ctx, options) => {
|
|
154
154
|
const opts = asOptions(options);
|
|
155
|
-
await executeAndPrint(ctx, '
|
|
155
|
+
await executeAndPrint(ctx, 'im.msg.sync.single', await inputFrom(options, {
|
|
156
156
|
fromUid: opts.fromUid,
|
|
157
157
|
fromCid: opts.fromCid,
|
|
158
158
|
num: opts.num !== undefined ? Number(opts.num) : undefined,
|
|
@@ -165,16 +165,16 @@ export const yimiaobanShortcut = {
|
|
|
165
165
|
withJsonInputOptions(msg.command('sync-group')
|
|
166
166
|
.description('拉取某群聊天消息')
|
|
167
167
|
.option('--gid <id>', '群 id(必填)')
|
|
168
|
-
.option('--num <n>', '
|
|
169
|
-
.option('--from <time>', '
|
|
170
|
-
.option('--to <time>', '
|
|
168
|
+
.option('--num <n>', '每页数量(默认 50,最多 50)')
|
|
169
|
+
.option('--from <time>', '起始时间(跨度 > 7 天自动收敛)')
|
|
170
|
+
.option('--to <time>', '结束时间(跨度 > 7 天自动收敛)')
|
|
171
171
|
.option('--latest', '拉最新不限日期')
|
|
172
172
|
.option('--start-id <id>', '显式起始消息 id')
|
|
173
173
|
.option('--end-id <id>', '显式结束消息 id')
|
|
174
174
|
.option('--img-format <fmt>', 'small/large/original(默认 small)'))
|
|
175
175
|
.action(action(async (ctx, options) => {
|
|
176
176
|
const opts = asOptions(options);
|
|
177
|
-
await executeAndPrint(ctx, '
|
|
177
|
+
await executeAndPrint(ctx, 'im.msg.sync.group', await inputFrom(options, {
|
|
178
178
|
groupId: opts.gid,
|
|
179
179
|
num: opts.num !== undefined ? Number(opts.num) : undefined,
|
|
180
180
|
from: opts.from,
|
|
@@ -190,10 +190,10 @@ export const yimiaobanShortcut = {
|
|
|
190
190
|
.option('--gid <id>', '群 id(必填)'))
|
|
191
191
|
.action(action(async (ctx, options) => {
|
|
192
192
|
const opts = asOptions(options);
|
|
193
|
-
await executeAndPrint(ctx, '
|
|
193
|
+
await executeAndPrint(ctx, 'im.msg.top.sync', await inputFrom(options, { groupId: opts.gid }));
|
|
194
194
|
}));
|
|
195
195
|
// ---- 高频便捷命令:群组 ----
|
|
196
|
-
const group =
|
|
196
|
+
const group = im.command('group').description('Group commands');
|
|
197
197
|
withJsonInputOptions(group.command('search')
|
|
198
198
|
.description('按条件搜索群(服务端过滤)')
|
|
199
199
|
.option('--name <kw>', '群名关键字')
|
|
@@ -205,7 +205,7 @@ export const yimiaobanShortcut = {
|
|
|
205
205
|
.option('--page-size <n>', '每页大小(默认 100,最多 200)'))
|
|
206
206
|
.action(action(async (ctx, options) => {
|
|
207
207
|
const opts = asOptions(options);
|
|
208
|
-
await executeAndPrint(ctx, '
|
|
208
|
+
await executeAndPrint(ctx, 'im.group.search', await inputFrom(options, {
|
|
209
209
|
name: opts.name,
|
|
210
210
|
precise: boolOption(opts.precise),
|
|
211
211
|
type: opts.type !== undefined ? Number(opts.type) : undefined,
|
|
@@ -220,25 +220,25 @@ export const yimiaobanShortcut = {
|
|
|
220
220
|
.option('--gid <ids>', '群 id(逗号分隔或单值)'))
|
|
221
221
|
.action(action(async (ctx, options) => {
|
|
222
222
|
const opts = asOptions(options);
|
|
223
|
-
await executeAndPrint(ctx, '
|
|
223
|
+
await executeAndPrint(ctx, 'im.group.info', await inputFrom(options, { groupIds: opts.gid }));
|
|
224
224
|
}));
|
|
225
225
|
withJsonInputOptions(group.command('users')
|
|
226
226
|
.description('拉取群成员列表')
|
|
227
227
|
.option('--gid <id>', '群 id(必填)'))
|
|
228
228
|
.action(action(async (ctx, options) => {
|
|
229
229
|
const opts = asOptions(options);
|
|
230
|
-
await executeAndPrint(ctx, '
|
|
230
|
+
await executeAndPrint(ctx, 'im.group.users', await inputFrom(options, { groupId: opts.gid }));
|
|
231
231
|
}));
|
|
232
232
|
// ---- 高频便捷命令:人员解析 ----
|
|
233
|
-
withJsonInputOptions(
|
|
233
|
+
withJsonInputOptions(im.command('resolve')
|
|
234
234
|
.description('按姓名/工号/手机/邮箱模糊查询在职员工')
|
|
235
235
|
.option('--name <kw>', '查询关键字(必填)'))
|
|
236
236
|
.action(action(async (ctx, options) => {
|
|
237
237
|
const opts = asOptions(options);
|
|
238
|
-
await executeAndPrint(ctx, '
|
|
238
|
+
await executeAndPrint(ctx, 'im.person.resolve', await inputFrom(options, { name: opts.name }));
|
|
239
239
|
}));
|
|
240
240
|
// ---- 高频便捷命令:发消息(两段式,仅演示 prepare 链) ----
|
|
241
|
-
const send =
|
|
241
|
+
const send = im.command('send').description('Send message commands (two-phase prepare -> apply)');
|
|
242
242
|
withJsonInputOptions(send.command('single-prepare')
|
|
243
243
|
.description('准备发送单聊消息(只读校验并签发 continuation)')
|
|
244
244
|
.option('--to-uid <uid>', '接收人 uid(必填)')
|
|
@@ -248,7 +248,7 @@ export const yimiaobanShortcut = {
|
|
|
248
248
|
.option('--file <path>', '本地文件路径'))
|
|
249
249
|
.action(action(async (ctx, options) => {
|
|
250
250
|
const opts = asOptions(options);
|
|
251
|
-
await executeAndPrint(ctx, '
|
|
251
|
+
await executeAndPrint(ctx, 'im.msg.send.single.prepare', await inputFrom(options, {
|
|
252
252
|
toUid: opts.toUid,
|
|
253
253
|
toCid: opts.toCid,
|
|
254
254
|
txt: opts.txt,
|
|
@@ -262,7 +262,7 @@ export const yimiaobanShortcut = {
|
|
|
262
262
|
.option('--yes', 'confirm the write operation'))
|
|
263
263
|
.action(action(async (ctx, options) => {
|
|
264
264
|
const opts = asOptions(options);
|
|
265
|
-
await executeAndPrint(ctx, '
|
|
265
|
+
await executeAndPrint(ctx, 'im.msg.send.single.apply', await inputFrom(options, {
|
|
266
266
|
continuation: opts.continuation,
|
|
267
267
|
confirm: opts.yes === true ? true : undefined,
|
|
268
268
|
}));
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { imOperationDefinitions } from './operations/registry.js';
|
|
2
2
|
function buildOperations() {
|
|
3
|
-
return
|
|
3
|
+
return imOperationDefinitions().map((definition) => ({
|
|
4
4
|
name: definition.name,
|
|
5
5
|
resource: definition.resource,
|
|
6
6
|
summary: definition.summary,
|
|
7
7
|
...(definition.capability ? { capability: definition.capability } : {}),
|
|
8
8
|
risk: definition.risk,
|
|
9
9
|
...(definition.requiresConfirmation ? { requiresConfirmation: true } : {}),
|
|
10
|
+
...(definition.deprecatedInputAliases ? { deprecatedInputAliases: definition.deprecatedInputAliases } : {}),
|
|
10
11
|
inputSchema: definition.inputSchema,
|
|
11
12
|
}));
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
15
|
* 易秒办(即时通讯)模块 manifest。
|
|
15
16
|
* operations 清单直接来自 registry(含全部 prepare/apply 成对写操作),
|
|
16
|
-
* 供 `weaver-work-cli
|
|
17
|
+
* 供 `weaver-work-cli im schema` 输出给 Agent/Skill 使用。
|
|
17
18
|
*/
|
|
18
|
-
export const
|
|
19
|
+
export const imManifest = {
|
|
19
20
|
schemaVersion: 1,
|
|
20
|
-
name: '
|
|
21
|
+
name: 'im',
|
|
21
22
|
title: '泛微E10易秒办(即时通讯:消息/群组/会话/系统消息)',
|
|
22
23
|
version: '0.1.0',
|
|
23
|
-
host: 'e10-
|
|
24
|
+
host: 'e10-im',
|
|
24
25
|
status: 'builtin',
|
|
25
26
|
sourceSkill: 'weaver-e10-yimiaoban',
|
|
26
27
|
capabilities: ['person', 'msg', 'ding', 'group', 'session', 'sysmsg', 'file', 'user', 'i18n'],
|