weaver-work-cli 0.1.8 → 0.1.20
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 +11 -11
- package/dist/cmd/action.js +76 -0
- package/dist/cmd/index.js +2 -0
- package/dist/cmd/refs/index.js +103 -0
- package/dist/cmd/register.js +31 -0
- package/dist/cmd/root.js +1 -0
- package/dist/cmd/setup/index.js +25 -5
- package/dist/cmd/skills/index.js +37 -5
- package/dist/core/connector.js +54 -0
- package/dist/core/context.js +2 -1
- package/dist/core/input.js +48 -0
- package/dist/core/output.js +298 -3
- package/dist/core/refs.js +432 -0
- package/dist/core/state.js +26 -0
- package/dist/internal/e10/auth/commands.js +2 -2
- package/dist/internal/e10/auth/session.js +14 -0
- package/dist/internal/e10/auth/xiaoe.js +116 -51
- package/dist/internal/e10/request-runtime.js +5 -0
- package/dist/internal/skills/install.js +148 -28
- package/dist/internal/skills/reader.js +12 -9
- package/dist/shortcuts/blog/continuation.js +74 -0
- package/dist/shortcuts/blog/errors.js +60 -0
- package/dist/shortcuts/blog/host.js +175 -0
- package/dist/shortcuts/blog/index.js +324 -0
- package/dist/shortcuts/blog/manifest.js +415 -0
- package/dist/shortcuts/blog/operations/comment.js +125 -0
- package/dist/shortcuts/blog/operations/comments.js +31 -0
- package/dist/shortcuts/blog/operations/edit.js +131 -0
- package/dist/shortcuts/blog/operations/export.js +46 -0
- package/dist/shortcuts/blog/operations/like.js +80 -0
- package/dist/shortcuts/blog/operations/publish.js +157 -0
- package/dist/shortcuts/blog/operations/query-user.js +58 -0
- package/dist/shortcuts/blog/operations/query.js +96 -0
- package/dist/shortcuts/blog/operations/registry.js +54 -0
- package/dist/shortcuts/blog/operations/remind.js +176 -0
- package/dist/shortcuts/blog/operations/shared.js +330 -0
- package/dist/shortcuts/blog/operations/types.js +16 -0
- package/dist/shortcuts/blog/operations.js +9 -0
- package/dist/shortcuts/caizhilian/continuation.js +70 -0
- package/dist/shortcuts/caizhilian/errors.js +53 -0
- package/dist/shortcuts/caizhilian/host.js +190 -0
- package/dist/shortcuts/caizhilian/index.js +186 -0
- package/dist/shortcuts/caizhilian/manifest.js +42 -0
- package/dist/shortcuts/caizhilian/operations/api.js +801 -0
- package/dist/shortcuts/caizhilian/operations/confirm.js +75 -0
- package/dist/shortcuts/caizhilian/operations/files.js +306 -0
- package/dist/shortcuts/caizhilian/operations/form.js +170 -0
- package/dist/shortcuts/caizhilian/operations/handlers/collab.js +611 -0
- package/dist/shortcuts/caizhilian/operations/handlers/document.js +890 -0
- package/dist/shortcuts/caizhilian/operations/handlers/file-collection.js +346 -0
- package/dist/shortcuts/caizhilian/operations/handlers/file-upload.js +192 -0
- package/dist/shortcuts/caizhilian/operations/handlers/fileops.js +570 -0
- package/dist/shortcuts/caizhilian/operations/handlers/folder.js +969 -0
- package/dist/shortcuts/caizhilian/operations/handlers/search.js +318 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-attach.js +294 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-backup.js +423 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-encrypt.js +238 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-storage.js +364 -0
- package/dist/shortcuts/caizhilian/operations/handlers/system.js +106 -0
- package/dist/shortcuts/caizhilian/operations/registry.js +151 -0
- package/dist/shortcuts/caizhilian/operations/shared.js +408 -0
- package/dist/shortcuts/caizhilian/operations/specs.js +623 -0
- package/dist/shortcuts/caizhilian/operations/types.js +57 -0
- package/dist/shortcuts/caizhilian/operations.js +21 -0
- package/dist/shortcuts/contract/continuation.js +70 -0
- package/dist/shortcuts/contract/errors.js +62 -0
- package/dist/shortcuts/contract/host.js +205 -0
- package/dist/shortcuts/contract/index.js +318 -0
- package/dist/shortcuts/contract/manifest.js +596 -0
- package/dist/shortcuts/contract/operations/clause-reference.js +78 -0
- package/dist/shortcuts/contract/operations/form-info.js +371 -0
- package/dist/shortcuts/contract/operations/read.js +118 -0
- package/dist/shortcuts/contract/operations/registry.js +43 -0
- package/dist/shortcuts/contract/operations/request.js +300 -0
- package/dist/shortcuts/contract/operations/shared.js +133 -0
- package/dist/shortcuts/contract/operations/subject.js +157 -0
- package/dist/shortcuts/contract/operations/template.js +81 -0
- package/dist/shortcuts/contract/operations/types.js +7 -0
- package/dist/shortcuts/contract/operations/workflow.js +52 -0
- package/dist/shortcuts/contract/operations/write.js +131 -0
- package/dist/shortcuts/contract/operations.js +8 -0
- package/dist/shortcuts/hrm/index.js +83 -2
- package/dist/shortcuts/hrm/operations/employee.js +160 -30
- package/dist/shortcuts/hrm/operations/org.js +17 -3
- package/dist/shortcuts/hrm/operations/position.js +18 -2
- package/dist/shortcuts/index.js +5 -1
- package/dist/shortcuts/invoice/index.js +74 -36
- package/dist/shortcuts/invoice/manifest.js +674 -4
- package/dist/shortcuts/invoice/markdown.js +172 -0
- package/dist/shortcuts/invoice/operations/add.js +3 -3
- package/dist/shortcuts/invoice/operations/delete.js +2 -2
- package/dist/shortcuts/invoice/operations/get.js +10 -2
- package/dist/shortcuts/invoice/operations/import.js +2 -2
- package/dist/shortcuts/invoice/operations/registry.js +8 -1
- package/dist/shortcuts/invoice/operations/reim-auto.js +719 -0
- package/dist/shortcuts/invoice/operations/reim.js +85 -2
- package/dist/shortcuts/invoice/operations/shared.js +75 -8
- package/dist/shortcuts/invoice/operations/update.js +2 -2
- package/dist/shortcuts/invoice/operations/upload-and-validate.js +93 -0
- package/dist/shortcuts/invoice/operations/validate-preview.js +2 -1
- package/dist/shortcuts/invoice/projection.js +328 -0
- package/dist/shortcuts/meeting/host.js +18 -1
- package/dist/shortcuts/meeting/manifest.js +30 -18
- package/dist/shortcuts/meeting/operations/eb/catalog.js +390 -0
- package/dist/shortcuts/meeting/operations/eb/conflict.js +389 -0
- package/dist/shortcuts/meeting/operations/eb/factory.js +389 -0
- package/dist/shortcuts/meeting/operations/eb/index.js +22 -0
- package/dist/shortcuts/meeting/operations/env.js +8 -1
- package/dist/shortcuts/meeting/operations/registry.js +2 -0
- package/dist/shortcuts/meeting/operations/signs.js +216 -2
- package/dist/shortcuts/workflow/endpoints.js +2 -1
- package/dist/shortcuts/workflow/errors.js +8 -2
- package/dist/shortcuts/workflow/host.js +6 -3
- package/dist/shortcuts/workflow/operations/form.js +931 -589
- package/dist/shortcuts/workflow/operations/read.js +128 -205
- package/dist/shortcuts/workflow/operations/shared.js +21 -0
- package/dist/shortcuts/workflow/operations/write.js +750 -52
- package/dist/shortcuts/workflow/operations.js +36 -10
- package/docs/_catalog.md +6 -0
- package/docs/agent-invoice.md +5 -1
- package/docs/agent-io-channel-design.md +468 -0
- package/docs/agent-skill-install.md +9 -4
- package/docs/blog.md +123 -0
- package/docs/caizhilian.md +304 -0
- package/docs/contract.md +91 -0
- package/docs/e10-auth.md +2 -2
- package/docs/hrm.md +19 -9
- package/docs/invoice.md +5 -1
- package/docs/meeting.md +1 -1
- package/docs/operation-manual.md +15 -3
- package/docs/skill-review-2026-09-19.md +2 -2
- package/package.json +2 -2
- package/scripts/package-skill.mjs +32 -20
- package/skill-template/business-info.json +113 -14
- package/skill-template/domains/blog.md +24 -0
- package/skill-template/domains/caizhilian.md +22 -0
- package/skill-template/domains/jinchengda.md +23 -0
- package/skill-template/domains/meeting.md +1 -1
- package/skill-template/domains/workflow.md +1 -1
- package/skill-template/skill-template.md +1 -1
- package/skills/weaver-e10-blog/SKILL.md +111 -0
- package/skills/weaver-e10-blog/references/blog-comment.md +51 -0
- package/skills/weaver-e10-blog/references/blog-comments.md +39 -0
- package/skills/weaver-e10-blog/references/blog-default-permission.md +38 -0
- package/skills/weaver-e10-blog/references/blog-disabled-capabilities.md +11 -0
- package/skills/weaver-e10-blog/references/blog-edit.md +51 -0
- package/skills/weaver-e10-blog/references/blog-export.md +42 -0
- package/skills/weaver-e10-blog/references/blog-like.md +50 -0
- package/skills/weaver-e10-blog/references/blog-publish.md +52 -0
- package/skills/weaver-e10-blog/references/blog-query-user.md +45 -0
- package/skills/weaver-e10-blog/references/blog-query.md +49 -0
- package/skills/weaver-e10-blog/references/blog-remind.md +51 -0
- package/skills/weaver-e10-blog/references/blog-resolve-users.md +38 -0
- package/skills/weaver-e10-blog/references/source-manifest.json +1540 -0
- package/skills/weaver-e10-caizhilian/SKILL.md +216 -0
- package/skills/weaver-e10-caizhilian/references/agent-entry.md +106 -0
- package/skills/weaver-e10-caizhilian/references/collaboration.md +112 -0
- package/skills/weaver-e10-caizhilian/references/document.md +111 -0
- package/skills/weaver-e10-caizhilian/references/file-collection.md +136 -0
- package/skills/weaver-e10-caizhilian/references/file-upload.md +309 -0
- package/skills/weaver-e10-caizhilian/references/files.md +120 -0
- package/skills/weaver-e10-caizhilian/references/folder.md +118 -0
- package/skills/weaver-e10-caizhilian/references/org-browser.md +104 -0
- package/skills/weaver-e10-caizhilian/references/setting-attach.md +410 -0
- package/skills/weaver-e10-caizhilian/references/setting-backup.md +372 -0
- package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +399 -0
- package/skills/weaver-e10-caizhilian/references/setting-storage.md +603 -0
- package/skills/weaver-e10-caizhilian/references/source-manifest.json +5079 -0
- package/skills/weaver-e10-caizhilian/references/withheld.md +93 -0
- package/skills/weaver-e10-caizhilian/references/write-protocol.md +120 -0
- package/skills/weaver-e10-calendar/SKILL.md +4 -3
- package/skills/weaver-e10-ebuilder-form/SKILL.md +4 -9
- package/skills/weaver-e10-ebuilder-form/references/context-routing.md +0 -9
- package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -5
- package/skills/weaver-e10-esb/SKILL.md +2 -2
- package/skills/weaver-e10-esb/references/source-manifest.json +9 -9
- package/skills/weaver-e10-hrm/SKILL.md +54 -6
- package/skills/weaver-e10-hrm/references/employee.md +89 -15
- package/skills/weaver-e10-hrm/references/org.md +7 -4
- package/skills/weaver-e10-hrm/references/position.md +14 -7
- package/skills/weaver-e10-hrm/references/source-manifest.json +1 -1
- package/skills/weaver-e10-jinchengda/SKILL.md +166 -0
- package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +82 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +69 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +78 -0
- package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +27 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-status.md +71 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-write.md +94 -0
- package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +89 -0
- package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +77 -0
- package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +66 -0
- package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +94 -0
- package/skills/weaver-e10-jinchengda/references/source-manifest.json +259 -0
- package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -11
- package/skills/weaver-e10-jucailin/SKILL.md +4 -3
- package/skills/weaver-e10-mail/SKILL.md +4 -11
- package/skills/weaver-e10-meeting/SKILL.md +66 -32
- package/skills/weaver-e10-meeting/references/meeting-change.md +5 -2
- package/skills/weaver-e10-meeting/references/meeting-create.md +2 -1
- package/skills/weaver-e10-meeting/references/meeting-eb.md +114 -0
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +9 -8
- package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +35 -7
- package/skills/weaver-e10-meeting/references/meeting-update.md +1 -1
- package/skills/weaver-e10-okr/SKILL.md +6 -11
- package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
- package/skills/weaver-e10-plan/SKILL.md +3 -3
- package/skills/weaver-e10-plan/references/plan-collect-and-compose.md +1 -1
- package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +1 -1
- package/skills/weaver-e10-plan/references/source-manifest.json +13 -13
- package/skills/weaver-e10-qiyecheng/SKILL.md +4 -10
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +9 -9
- package/skills/weaver-e10-shared/SKILL.md +36 -25
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -31
- package/skills/weaver-e10-shared/references/json-output-contract.md +20 -11
- package/skills/weaver-e10-shijingran/SKILL.md +2 -1
- package/skills/weaver-e10-shijingran/references/source-manifest.json +9 -9
- package/skills/weaver-e10-skill-maker/SKILL.md +4 -10
- package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +5 -3
- package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +12 -27
- package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +17 -5
- package/skills/weaver-e10-skill-maker/references/source-update-detection.md +4 -27
- package/skills/weaver-e10-wenshuding/SKILL.md +5 -16
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +7 -7
- package/skills/weaver-e10-workflow/SKILL.md +32 -37
- package/skills/weaver-e10-workflow/references/source-manifest.json +39 -75
- package/skills/weaver-e10-workflow/references/workflow-batch.md +90 -29
- package/skills/weaver-e10-workflow/references/workflow-create.md +79 -109
- package/skills/weaver-e10-workflow/references/workflow-memory.md +19 -9
- package/skills/weaver-e10-workflow/references/workflow-operate.md +2 -2
- package/skills/weaver-e10-workflow/references/workflow-query.md +38 -20
- package/skills/weaver-e10-workflow/references/workflow-share.md +18 -2
- package/skills/weaver-e10-workflow/references/workflow-view.md +3 -4
- package/skills/weaver-e10-yepiaotong/SKILL.md +75 -39
- package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +22 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +3 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +135 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +15 -3
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +1 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-summarize.py +217 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-upload-and-validate.md +88 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-validation-preview.md +7 -2
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +89 -9
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +1 -0
- package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +70 -49
- package/skills/weaver-e10-yepiaotong/references/reim-fast-path.md +119 -0
- package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +55 -36
- package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +4 -0
- package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +149 -0
- package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +125 -5
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +430 -63
- package/skills/weaver-e10-yimiaoban/SKILL.md +4 -12
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +3 -3
- package/skills/weaver-e10-ziguanjia/SKILL.md +2 -1
- package/skills/weaver-e10-ziguanjia/references/ziguanjia-agent-entry.md +3 -3
- package/tools/weaver-skill-detector-1.0.13/SKILL.md +9 -9
- package/tools/weaver-skill-detector-1.0.13/references/checklist.md +3 -3
- package/tools/weaver-skill-detector-1.0.13/scripts/__pycache__/validate_skill.cpython-313.pyc +0 -0
- package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +98 -91
- package/scripts/sync-connector-skills.mjs +0 -172
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* caizhilian.setting-storage — 存储设置(文件设置 → 存储设置)
|
|
3
|
+
*
|
|
4
|
+
* 覆盖「文件设置 → 存储设置」页面:
|
|
5
|
+
* - 存储实例(list/get)
|
|
6
|
+
* - 存储规则(list/form/search/save/delete/enable/order)
|
|
7
|
+
*
|
|
8
|
+
* 接口(papi 端点,带 wea_link_keep_freepass=1&tenant_langType=zh_CN):
|
|
9
|
+
* - 列实例:POST /papi/file/storage/listStorageInstance
|
|
10
|
+
* - 单实例详情:POST /papi/file/storage/getStorageInstance
|
|
11
|
+
* - 拉规则表单:GET /papi/file/storage/rule/frontComp/ruleForm
|
|
12
|
+
* - 保存规则:POST /papi/file/storage/rule/saveData
|
|
13
|
+
* - 改顺序:POST /papi/file/storage/rule/saveOrder
|
|
14
|
+
* - 改启用:POST /papi/file/storage/rule/saveOpen
|
|
15
|
+
* - 删除:POST /papi/file/storage/rule/delete
|
|
16
|
+
* - 高级搜索:POST /papi/file/storage/rule/search
|
|
17
|
+
* - 拉规则表:GET /papi/file/storage/rule/frontComp/ruleTable
|
|
18
|
+
*/
|
|
19
|
+
import { CaizhilianCliError, caizhilianValidationError } from '../../errors.js';
|
|
20
|
+
import { caizhilianSuccess } from '../types.js';
|
|
21
|
+
import { requireId } from '../shared.js';
|
|
22
|
+
const ACTION = 'caizhilian.setting-storage';
|
|
23
|
+
// ── 接口路径(papi 端点,需带通用 query)──────────────────────────────
|
|
24
|
+
const PAPI_SUFFIX = '?wea_link_keep_freepass=1&tenant_langType=zh_CN';
|
|
25
|
+
const LIST_INSTANCES_PATH = `/papi/file/storage/listStorageInstance${PAPI_SUFFIX}`;
|
|
26
|
+
const GET_INSTANCE_PATH = `/papi/file/storage/getStorageInstance${PAPI_SUFFIX}`;
|
|
27
|
+
const GET_RULE_FORM_PATH = `/papi/file/storage/rule/frontComp/ruleForm${PAPI_SUFFIX}`;
|
|
28
|
+
const SAVE_RULE_PATH = `/papi/file/storage/rule/saveData${PAPI_SUFFIX}`;
|
|
29
|
+
const SAVE_ORDER_PATH = `/papi/file/storage/rule/saveOrder${PAPI_SUFFIX}`;
|
|
30
|
+
const SAVE_OPEN_PATH = `/papi/file/storage/rule/saveOpen${PAPI_SUFFIX}`;
|
|
31
|
+
const DELETE_RULE_PATH = `/papi/file/storage/rule/delete${PAPI_SUFFIX}`;
|
|
32
|
+
const SEARCH_RULE_PATH = `/papi/file/storage/rule/search${PAPI_SUFFIX}`;
|
|
33
|
+
const GET_RULE_TABLE_PATH = `/papi/file/storage/rule/frontComp/ruleTable${PAPI_SUFFIX}`;
|
|
34
|
+
// ── 辅助函数 ──────────────────────────────────────────────
|
|
35
|
+
function asRecord(value) {
|
|
36
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
37
|
+
}
|
|
38
|
+
function asList(value) {
|
|
39
|
+
return Array.isArray(value) ? value : [];
|
|
40
|
+
}
|
|
41
|
+
function isPlainObject(value) {
|
|
42
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
43
|
+
}
|
|
44
|
+
// ── 列出存储实例 ──────────────────────────────────────────
|
|
45
|
+
async function listStorageInstances(args, env) {
|
|
46
|
+
const response = await env.host.request({
|
|
47
|
+
method: 'POST',
|
|
48
|
+
path: LIST_INSTANCES_PATH,
|
|
49
|
+
body: { pageNo: args.page_no || 1, pageSize: args.page_size || 20 },
|
|
50
|
+
operation: ACTION,
|
|
51
|
+
});
|
|
52
|
+
const data = asRecord(response);
|
|
53
|
+
if (!data.status && !data.success) {
|
|
54
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询存储实例失败'), {
|
|
55
|
+
code: data.code ?? data.status,
|
|
56
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询存储实例失败') },
|
|
57
|
+
exitCode: 1,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
const result = asRecord(data.data);
|
|
61
|
+
const instances = asList(result.data).map((item) => ({
|
|
62
|
+
id: item.id,
|
|
63
|
+
name: item.instanceName || '',
|
|
64
|
+
type: item.instanceType || '',
|
|
65
|
+
status: item.status || '',
|
|
66
|
+
create_time: item.createTime || '',
|
|
67
|
+
}));
|
|
68
|
+
return caizhilianSuccess(ACTION, {
|
|
69
|
+
total: result.total || 0,
|
|
70
|
+
page_no: args.page_no || 1,
|
|
71
|
+
page_size: args.page_size || 20,
|
|
72
|
+
instances,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// ── 获取存储实例详情 ──────────────────────────────────────
|
|
76
|
+
async function getStorageInstance(args, env) {
|
|
77
|
+
const instanceId = requireId(args.id, 'id');
|
|
78
|
+
const response = await env.host.request({
|
|
79
|
+
method: 'POST',
|
|
80
|
+
path: GET_INSTANCE_PATH,
|
|
81
|
+
body: { id: instanceId, instanceType: args.instance_type },
|
|
82
|
+
operation: ACTION,
|
|
83
|
+
});
|
|
84
|
+
const data = asRecord(response);
|
|
85
|
+
if (!data.status && !data.success) {
|
|
86
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询存储实例失败'), {
|
|
87
|
+
code: data.code ?? data.status,
|
|
88
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询存储实例失败') },
|
|
89
|
+
exitCode: 1,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const result = asRecord(data.data);
|
|
93
|
+
return caizhilianSuccess(ACTION, {
|
|
94
|
+
instance: {
|
|
95
|
+
id: instanceId,
|
|
96
|
+
form: result.weaForm || {},
|
|
97
|
+
enc_field_list: result.encFieldList || [],
|
|
98
|
+
read_only: result.readOnly ?? false,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
// ── 拉规则表单 ──────────────────────────────────────────
|
|
103
|
+
async function getRuleForm(args, env) {
|
|
104
|
+
const ruleId = args.id ? requireId(args.id, 'id') : '';
|
|
105
|
+
const url = ruleId
|
|
106
|
+
? `${GET_RULE_FORM_PATH}&defaultRule=true&id=${ruleId}&sysStorageRule=true`
|
|
107
|
+
: `${GET_RULE_FORM_PATH}&defaultRule=true&sysStorageRule=true`;
|
|
108
|
+
const response = await env.host.request({
|
|
109
|
+
method: 'GET',
|
|
110
|
+
path: url,
|
|
111
|
+
operation: ACTION,
|
|
112
|
+
});
|
|
113
|
+
const data = asRecord(response);
|
|
114
|
+
if (!data.status && !data.success) {
|
|
115
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询规则表单失败'), {
|
|
116
|
+
code: data.code ?? data.status,
|
|
117
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询规则表单失败') },
|
|
118
|
+
exitCode: 1,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const result = asRecord(data.data);
|
|
122
|
+
return caizhilianSuccess(ACTION, {
|
|
123
|
+
default_fs_rule: result.defaultFsRuleWeaForm || {},
|
|
124
|
+
fs_rule: result.fsRuleWeaForm || {},
|
|
125
|
+
default_static_rule: result.defaultStaticRuleWeaForm || {},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// ── 拉规则表 ──────────────────────────────────────────
|
|
129
|
+
async function getRuleTable(args, env) {
|
|
130
|
+
const response = await env.host.request({
|
|
131
|
+
method: 'GET',
|
|
132
|
+
path: GET_RULE_TABLE_PATH,
|
|
133
|
+
operation: ACTION,
|
|
134
|
+
});
|
|
135
|
+
const data = asRecord(response);
|
|
136
|
+
if (!data.status && !data.success) {
|
|
137
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询规则表失败'), {
|
|
138
|
+
code: data.code ?? data.status,
|
|
139
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询规则表失败') },
|
|
140
|
+
exitCode: 1,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
const result = asRecord(data.data);
|
|
144
|
+
return caizhilianSuccess(ACTION, {
|
|
145
|
+
default_fs_rule: result.defaultFsRuleWeaForm || {},
|
|
146
|
+
fs_rule_table: result.fsRuleTable || {},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
// ── 高级搜索规则 ──────────────────────────────────────────
|
|
150
|
+
async function searchRules(args, env) {
|
|
151
|
+
const conditions = args.conditions || [];
|
|
152
|
+
const ruleType = args.rule_type;
|
|
153
|
+
const body = { conditionArr: conditions };
|
|
154
|
+
if (ruleType)
|
|
155
|
+
body.ruleType = ruleType;
|
|
156
|
+
const response = await env.host.request({
|
|
157
|
+
method: 'POST',
|
|
158
|
+
path: SEARCH_RULE_PATH,
|
|
159
|
+
body,
|
|
160
|
+
operation: ACTION,
|
|
161
|
+
});
|
|
162
|
+
const data = asRecord(response);
|
|
163
|
+
if (!data.status && !data.success) {
|
|
164
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '搜索规则失败'), {
|
|
165
|
+
code: data.code ?? data.status,
|
|
166
|
+
details: { action: ACTION, message: String(data.msg || data.message || '搜索规则失败') },
|
|
167
|
+
exitCode: 1,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
const result = asRecord(data.data);
|
|
171
|
+
return caizhilianSuccess(ACTION, {
|
|
172
|
+
rules: asList(result.ruleInfoList).map((item) => ({
|
|
173
|
+
id: item.id,
|
|
174
|
+
name: item.ruleName || '',
|
|
175
|
+
type: item.ruleType || '',
|
|
176
|
+
enabled: item.openStatus ?? false,
|
|
177
|
+
create_time: item.createTime || '',
|
|
178
|
+
})),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
// ── 保存规则(prepare/apply)──────────────────────────────────────
|
|
182
|
+
async function saveRulePrepare(args, env) {
|
|
183
|
+
const ruleInfoList = args.rule_info_list;
|
|
184
|
+
if (!Array.isArray(ruleInfoList) || ruleInfoList.length === 0) {
|
|
185
|
+
throw caizhilianValidationError('list_required', 'rule_info_list 必须是非空数组');
|
|
186
|
+
}
|
|
187
|
+
// 签发 continuation
|
|
188
|
+
const continuation = await env.continuation.issue({
|
|
189
|
+
operation: 'caizhilian.setting-storage.rule.save.apply',
|
|
190
|
+
ruleInfoList,
|
|
191
|
+
defaultRule: args.default_rule ?? false,
|
|
192
|
+
});
|
|
193
|
+
return caizhilianSuccess('caizhilian.setting-storage.rule.save.prepare', {
|
|
194
|
+
rule_info_list: ruleInfoList,
|
|
195
|
+
default_rule: args.default_rule ?? false,
|
|
196
|
+
continuation,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
async function saveRuleApply(args, env, lease) {
|
|
200
|
+
const ruleInfoList = lease.payload?.ruleInfoList;
|
|
201
|
+
const defaultRule = lease.payload?.defaultRule;
|
|
202
|
+
const response = await env.host.request({
|
|
203
|
+
method: 'POST',
|
|
204
|
+
path: SAVE_RULE_PATH,
|
|
205
|
+
body: { defaultRule, ruleInfoList },
|
|
206
|
+
operation: 'caizhilian.setting-storage.rule.save.apply',
|
|
207
|
+
});
|
|
208
|
+
const data = asRecord(response);
|
|
209
|
+
if (!data.status && !data.success) {
|
|
210
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '保存规则失败'), {
|
|
211
|
+
code: data.code ?? data.status,
|
|
212
|
+
details: { action: 'caizhilian.setting-storage.rule.save.apply', message: String(data.msg || data.message || '保存规则失败') },
|
|
213
|
+
exitCode: 1,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const result = asRecord(data.data);
|
|
217
|
+
return caizhilianSuccess('caizhilian.setting-storage.rule.save.apply', {
|
|
218
|
+
rules: asList(result.ruleInfoList).map((item) => ({
|
|
219
|
+
id: item.id,
|
|
220
|
+
name: item.ruleName || '',
|
|
221
|
+
type: item.ruleType || '',
|
|
222
|
+
enabled: item.openStatus ?? false,
|
|
223
|
+
})),
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
// ── 删除规则(prepare/apply)──────────────────────────────────────
|
|
227
|
+
async function deleteRulePrepare(args, env) {
|
|
228
|
+
const ruleIds = args.rule_ids;
|
|
229
|
+
if (!Array.isArray(ruleIds) || ruleIds.length === 0) {
|
|
230
|
+
throw caizhilianValidationError('list_required', 'rule_ids 必须是非空数组');
|
|
231
|
+
}
|
|
232
|
+
// 签发 continuation
|
|
233
|
+
const continuation = await env.continuation.issue({
|
|
234
|
+
operation: 'caizhilian.setting-storage.rule.delete.apply',
|
|
235
|
+
ruleIds,
|
|
236
|
+
});
|
|
237
|
+
return caizhilianSuccess('caizhilian.setting-storage.rule.delete.prepare', {
|
|
238
|
+
rule_ids: ruleIds,
|
|
239
|
+
continuation,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
async function deleteRuleApply(args, env, lease) {
|
|
243
|
+
const ruleIds = lease.payload?.ruleIds;
|
|
244
|
+
const response = await env.host.request({
|
|
245
|
+
method: 'POST',
|
|
246
|
+
path: DELETE_RULE_PATH,
|
|
247
|
+
body: { ruleIdList: ruleIds },
|
|
248
|
+
operation: 'caizhilian.setting-storage.rule.delete.apply',
|
|
249
|
+
});
|
|
250
|
+
const data = asRecord(response);
|
|
251
|
+
if (!data.status && !data.success) {
|
|
252
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '删除规则失败'), {
|
|
253
|
+
code: data.code ?? data.status,
|
|
254
|
+
details: { action: 'caizhilian.setting-storage.rule.delete.apply', message: String(data.msg || data.message || '删除规则失败') },
|
|
255
|
+
exitCode: 1,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return caizhilianSuccess('caizhilian.setting-storage.rule.delete.apply', {
|
|
259
|
+
deleted: true,
|
|
260
|
+
rule_ids: ruleIds,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
// ── 启停规则(prepare/apply)──────────────────────────────────────
|
|
264
|
+
async function enableRulePrepare(args, env) {
|
|
265
|
+
const ruleInfoList = args.rule_info_list;
|
|
266
|
+
if (!Array.isArray(ruleInfoList) || ruleInfoList.length === 0) {
|
|
267
|
+
throw caizhilianValidationError('list_required', 'rule_info_list 必须是非空数组');
|
|
268
|
+
}
|
|
269
|
+
// 签发 continuation
|
|
270
|
+
const continuation = await env.continuation.issue({
|
|
271
|
+
operation: 'caizhilian.setting-storage.rule.enable.apply',
|
|
272
|
+
ruleInfoList,
|
|
273
|
+
});
|
|
274
|
+
return caizhilianSuccess('caizhilian.setting-storage.rule.enable.prepare', {
|
|
275
|
+
rule_info_list: ruleInfoList,
|
|
276
|
+
continuation,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
async function enableRuleApply(args, env, lease) {
|
|
280
|
+
const ruleInfoList = lease.payload?.ruleInfoList;
|
|
281
|
+
const response = await env.host.request({
|
|
282
|
+
method: 'POST',
|
|
283
|
+
path: SAVE_OPEN_PATH,
|
|
284
|
+
body: { ruleInfoList },
|
|
285
|
+
operation: 'caizhilian.setting-storage.rule.enable.apply',
|
|
286
|
+
});
|
|
287
|
+
const data = asRecord(response);
|
|
288
|
+
if (!data.status && !data.success) {
|
|
289
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '启停规则失败'), {
|
|
290
|
+
code: data.code ?? data.status,
|
|
291
|
+
details: { action: 'caizhilian.setting-storage.rule.enable.apply', message: String(data.msg || data.message || '启停规则失败') },
|
|
292
|
+
exitCode: 1,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
return caizhilianSuccess('caizhilian.setting-storage.rule.enable.apply', {
|
|
296
|
+
enabled: true,
|
|
297
|
+
rule_info_list: ruleInfoList,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
// ── 改顺序(prepare/apply)──────────────────────────────────────
|
|
301
|
+
async function saveOrderPrepare(args, env) {
|
|
302
|
+
const ruleIdList = args.rule_ids;
|
|
303
|
+
if (!Array.isArray(ruleIdList) || ruleIdList.length === 0) {
|
|
304
|
+
throw caizhilianValidationError('list_required', 'rule_ids 必须是非空数组');
|
|
305
|
+
}
|
|
306
|
+
// 签发 continuation
|
|
307
|
+
const continuation = await env.continuation.issue({
|
|
308
|
+
operation: 'caizhilian.setting-storage.rule.order.apply',
|
|
309
|
+
ruleIdList,
|
|
310
|
+
});
|
|
311
|
+
return caizhilianSuccess('caizhilian.setting-storage.rule.order.prepare', {
|
|
312
|
+
rule_ids: ruleIdList,
|
|
313
|
+
continuation,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
async function saveOrderApply(args, env, lease) {
|
|
317
|
+
const ruleIdList = lease.payload?.ruleIdList;
|
|
318
|
+
const response = await env.host.request({
|
|
319
|
+
method: 'POST',
|
|
320
|
+
path: SAVE_ORDER_PATH,
|
|
321
|
+
body: { ruleIdList },
|
|
322
|
+
operation: 'caizhilian.setting-storage.rule.order.apply',
|
|
323
|
+
});
|
|
324
|
+
const data = asRecord(response);
|
|
325
|
+
if (!data.status && !data.success) {
|
|
326
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '改顺序失败'), {
|
|
327
|
+
code: data.code ?? data.status,
|
|
328
|
+
details: { action: 'caizhilian.setting-storage.rule.order.apply', message: String(data.msg || data.message || '改顺序失败') },
|
|
329
|
+
exitCode: 1,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
return caizhilianSuccess('caizhilian.setting-storage.rule.order.apply', {
|
|
333
|
+
ordered: true,
|
|
334
|
+
rule_ids: ruleIdList,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
// ── 处理器汇总 ────────────────────────────────────────────
|
|
338
|
+
export const caizhilianSettingStorageHandlers = {
|
|
339
|
+
'caizhilian.setting-storage.instance.list': { execute: listStorageInstances },
|
|
340
|
+
'caizhilian.setting-storage.instance.get': { execute: getStorageInstance },
|
|
341
|
+
'caizhilian.setting-storage.rule.form': { execute: getRuleForm },
|
|
342
|
+
'caizhilian.setting-storage.rule.table': { execute: getRuleTable },
|
|
343
|
+
'caizhilian.setting-storage.rule.search': { execute: searchRules },
|
|
344
|
+
'caizhilian.setting-storage.rule.save': {
|
|
345
|
+
prepare: saveRulePrepare,
|
|
346
|
+
apply: saveRuleApply,
|
|
347
|
+
targetKeys: ['rule_info_list'],
|
|
348
|
+
},
|
|
349
|
+
'caizhilian.setting-storage.rule.delete': {
|
|
350
|
+
prepare: deleteRulePrepare,
|
|
351
|
+
apply: deleteRuleApply,
|
|
352
|
+
targetKeys: ['rule_ids'],
|
|
353
|
+
},
|
|
354
|
+
'caizhilian.setting-storage.rule.enable': {
|
|
355
|
+
prepare: enableRulePrepare,
|
|
356
|
+
apply: enableRuleApply,
|
|
357
|
+
targetKeys: ['rule_info_list'],
|
|
358
|
+
},
|
|
359
|
+
'caizhilian.setting-storage.rule.order': {
|
|
360
|
+
prepare: saveOrderPrepare,
|
|
361
|
+
apply: saveOrderApply,
|
|
362
|
+
targetKeys: ['rule_ids'],
|
|
363
|
+
},
|
|
364
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { CaizhilianCliError, caizhilianAuthError } from '../../errors.js';
|
|
2
|
+
import { caizhilianSuccess } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* 系统自检(1:1 对应源 scripts/system_plugins.py::CheckSystemHealthPlugin)。
|
|
5
|
+
*
|
|
6
|
+
* 源从 assets/config.json 的 health_check 块读取探测地址与判定条件:
|
|
7
|
+
* url = /api/doc/config/getUserConfiguration?configKeys
|
|
8
|
+
* http_code = 200, success_path = code, success_value = 200
|
|
9
|
+
* 这里把该配置固化为常量(weaver-work-cli 侧没有 config.json 可热改)。
|
|
10
|
+
*/
|
|
11
|
+
const HEALTH_CHECK_URL = '/api/doc/config/getUserConfiguration?configKeys';
|
|
12
|
+
const HEALTH_EXPECTED_HTTP_CODE = 200;
|
|
13
|
+
const HEALTH_EXPECTED_BUSINESS_CODE = 200;
|
|
14
|
+
/** 源 environment.provider:CLI 侧固定为内置 E10 认证。 */
|
|
15
|
+
const ENVIRONMENT_PROVIDER = 'weaver-work-cli:e10-auth';
|
|
16
|
+
function round1(value) {
|
|
17
|
+
return Math.round(value * 10) / 10;
|
|
18
|
+
}
|
|
19
|
+
/** 源「Provider 未就绪」分支:success=false + data={environment, healthy:false}。 */
|
|
20
|
+
function sessionUnavailableError(error) {
|
|
21
|
+
const message = error instanceof Error && error.message ? error.message : 'E10 登录态不可用';
|
|
22
|
+
return caizhilianAuthError('session_unavailable', message, {
|
|
23
|
+
environment: { provider: ENVIRONMENT_PROVIDER, loggedIn: false, baseUrl: '', user: '' },
|
|
24
|
+
healthy: false,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export const caizhilianSystemHandlers = {
|
|
28
|
+
'caizhilian.system.health': {
|
|
29
|
+
async execute(_args, env) {
|
|
30
|
+
const action = 'caizhilian.system.health';
|
|
31
|
+
let session;
|
|
32
|
+
try {
|
|
33
|
+
session = await env.host.getSession();
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw sessionUnavailableError(error);
|
|
37
|
+
}
|
|
38
|
+
const environment = {
|
|
39
|
+
provider: ENVIRONMENT_PROVIDER,
|
|
40
|
+
loggedIn: true,
|
|
41
|
+
baseUrl: session.baseUrl,
|
|
42
|
+
user: session.userId,
|
|
43
|
+
};
|
|
44
|
+
const startedAt = process.hrtime.bigint();
|
|
45
|
+
let statusCode = 0;
|
|
46
|
+
let businessCode = null;
|
|
47
|
+
const diagnosis = [];
|
|
48
|
+
let message;
|
|
49
|
+
try {
|
|
50
|
+
const response = await env.host.request({ method: 'GET', path: HEALTH_CHECK_URL, operation: action });
|
|
51
|
+
// host.request 仅在 HTTP 2xx 且业务成功时返回,因此这里等价于源的 http_ok && resp.success。
|
|
52
|
+
statusCode = HEALTH_EXPECTED_HTTP_CODE;
|
|
53
|
+
const record = response && typeof response === 'object' ? response : {};
|
|
54
|
+
businessCode = record.code ?? null;
|
|
55
|
+
if (businessCode !== HEALTH_EXPECTED_BUSINESS_CODE)
|
|
56
|
+
diagnosis.push('business_code_mismatch');
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error instanceof CaizhilianCliError) {
|
|
60
|
+
message = error.message;
|
|
61
|
+
if (error.type === 'network') {
|
|
62
|
+
statusCode = 0;
|
|
63
|
+
diagnosis.push('network_error');
|
|
64
|
+
}
|
|
65
|
+
else if (error.subtype === 'session_expired') {
|
|
66
|
+
statusCode = Number(error.details && error.details.httpStatus) || 401;
|
|
67
|
+
diagnosis.push('http_error', 'http_status_mismatch');
|
|
68
|
+
}
|
|
69
|
+
else if (error.subtype === 'http_error') {
|
|
70
|
+
statusCode = Number(error.code) || 0;
|
|
71
|
+
diagnosis.push('http_error');
|
|
72
|
+
if (statusCode !== HEALTH_EXPECTED_HTTP_CODE)
|
|
73
|
+
diagnosis.push('http_status_mismatch');
|
|
74
|
+
}
|
|
75
|
+
else if (error.subtype === 'business_error') {
|
|
76
|
+
statusCode = HEALTH_EXPECTED_HTTP_CODE;
|
|
77
|
+
businessCode = error.code ?? null;
|
|
78
|
+
diagnosis.push('business_code_mismatch');
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
statusCode = 0;
|
|
82
|
+
diagnosis.push('request_failed');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
message = error instanceof Error ? error.message : String(error);
|
|
87
|
+
statusCode = 0;
|
|
88
|
+
diagnosis.push('network_error');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const elapsedMs = round1(Number(process.hrtime.bigint() - startedAt) / 1e6);
|
|
92
|
+
const healthy = statusCode === HEALTH_EXPECTED_HTTP_CODE && diagnosis.length === 0;
|
|
93
|
+
return caizhilianSuccess(action, {
|
|
94
|
+
environment,
|
|
95
|
+
healthy,
|
|
96
|
+
base_url: session.baseUrl,
|
|
97
|
+
url: HEALTH_CHECK_URL,
|
|
98
|
+
status_code: statusCode,
|
|
99
|
+
business_code: businessCode,
|
|
100
|
+
diagnosis: diagnosis.length ? diagnosis.join(',') : 'ok',
|
|
101
|
+
elapsed_ms: elapsedMs,
|
|
102
|
+
...(message ? { message } : {}),
|
|
103
|
+
}, { profile: session.profile, tenantKey: session.tenantKey });
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { caizhilianValidationError } from '../errors.js';
|
|
2
|
+
import { assertLeaseArgs, assertLeaseTarget, verifyLease } from './confirm.js';
|
|
3
|
+
import { caizhilianCollabHandlers } from './handlers/collab.js';
|
|
4
|
+
import { caizhilianDocumentHandlers } from './handlers/document.js';
|
|
5
|
+
import { caizhilianFileCollectionHandlers } from './handlers/file-collection.js';
|
|
6
|
+
import { caizhilianFileopsHandlers } from './handlers/fileops.js';
|
|
7
|
+
import { caizhilianFileUploadHandlers } from './handlers/file-upload.js';
|
|
8
|
+
import { caizhilianFolderHandlers } from './handlers/folder.js';
|
|
9
|
+
import { caizhilianSearchHandlers } from './handlers/search.js';
|
|
10
|
+
import { caizhilianSettingAttachHandlers } from './handlers/setting-attach.js';
|
|
11
|
+
import { caizhilianSettingBackupHandlers } from './handlers/setting-backup.js';
|
|
12
|
+
import { caizhilianSettingEncryptHandlers } from './handlers/setting-encrypt.js';
|
|
13
|
+
import { caizhilianSettingStorageHandlers } from './handlers/setting-storage.js';
|
|
14
|
+
import { caizhilianSystemHandlers } from './handlers/system.js';
|
|
15
|
+
import { caizhilianOperationSpecs } from './specs.js';
|
|
16
|
+
import { applySchemaOf, isWriteHandler } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* 操作注册表:specs.ts 提供 WHAT(name/resource/risk/inputSchema),
|
|
19
|
+
* handlers/*.ts 提供 HOW(execute 或 prepare/apply)。
|
|
20
|
+
*
|
|
21
|
+
* 60 个 canonical spec 在这里展开成 87 条对外 operation:
|
|
22
|
+
* 33 个只读 spec → 1 条;27 个写 spec(requiresConfirmation)→ `<name>.prepare` + `<name>.apply` 2 条。
|
|
23
|
+
* 两侧必须严格一一对应:任一侧多出条目或形态不符都直接抛错,避免 schema 与实际能力漂移。
|
|
24
|
+
*/
|
|
25
|
+
const PREPARE_SUFFIX = '.prepare';
|
|
26
|
+
const APPLY_SUFFIX = '.apply';
|
|
27
|
+
function mergeHandlers(maps) {
|
|
28
|
+
const merged = {};
|
|
29
|
+
for (const map of maps) {
|
|
30
|
+
for (const [name, handler] of Object.entries(map)) {
|
|
31
|
+
if (merged[name])
|
|
32
|
+
throw new Error(`duplicate caizhilian operation handler: ${name}`);
|
|
33
|
+
merged[name] = handler;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return merged;
|
|
37
|
+
}
|
|
38
|
+
const caizhilianHandlers = mergeHandlers([
|
|
39
|
+
caizhilianDocumentHandlers,
|
|
40
|
+
caizhilianFileCollectionHandlers,
|
|
41
|
+
caizhilianFileopsHandlers,
|
|
42
|
+
caizhilianFileUploadHandlers,
|
|
43
|
+
caizhilianFolderHandlers,
|
|
44
|
+
caizhilianSearchHandlers,
|
|
45
|
+
caizhilianCollabHandlers,
|
|
46
|
+
caizhilianSettingAttachHandlers,
|
|
47
|
+
caizhilianSettingBackupHandlers,
|
|
48
|
+
caizhilianSettingEncryptHandlers,
|
|
49
|
+
caizhilianSettingStorageHandlers,
|
|
50
|
+
caizhilianSystemHandlers,
|
|
51
|
+
]);
|
|
52
|
+
/** 只读 spec:直接暴露 execute。 */
|
|
53
|
+
function readDefinition(spec, entry) {
|
|
54
|
+
return {
|
|
55
|
+
...spec,
|
|
56
|
+
handler: (args, env) => entry.execute(args, env),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** 写 spec 的 prepare:只读回查 + 组装请求体 + 签发 continuation,不产生副作用。 */
|
|
60
|
+
function prepareDefinition(spec, entry) {
|
|
61
|
+
return {
|
|
62
|
+
...spec,
|
|
63
|
+
name: `${spec.name}${PREPARE_SUFFIX}`,
|
|
64
|
+
action: `${spec.action}${PREPARE_SUFFIX}`,
|
|
65
|
+
summary: `${spec.summary}|prepare:只读校验与请求体预览,签发 apply 所需的 continuation,不产生副作用`,
|
|
66
|
+
risk: 'read-before-write',
|
|
67
|
+
requiresConfirmation: true,
|
|
68
|
+
handler: (args, env) => entry.prepare(args, env),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 写 spec 的 apply:统一的确认闸门(confirm + continuation + 环境/账号 + 入参指纹 + 目标键),
|
|
73
|
+
* 通过后才调用各 handler 自己的 apply。handler 内不重复校验票据。
|
|
74
|
+
*/
|
|
75
|
+
function applyDefinition(spec, entry) {
|
|
76
|
+
const name = `${spec.name}${APPLY_SUFFIX}`;
|
|
77
|
+
const base = spec.inputSchema;
|
|
78
|
+
return {
|
|
79
|
+
...spec,
|
|
80
|
+
name,
|
|
81
|
+
action: `${spec.action}${APPLY_SUFFIX}`,
|
|
82
|
+
summary: `${spec.summary}|apply:校验 confirm + continuation 后执行,会产生服务端副作用`,
|
|
83
|
+
requiresConfirmation: true,
|
|
84
|
+
inputSchema: applySchemaOf(spec.inputSchema, base.required ?? []),
|
|
85
|
+
handler: async (args, env) => {
|
|
86
|
+
const lease = await verifyLease(args, name, env);
|
|
87
|
+
assertLeaseArgs(lease, args, name);
|
|
88
|
+
assertLeaseTarget(lease, args, entry.targetKeys ?? [], name);
|
|
89
|
+
return entry.apply(args, env, lease);
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function buildRegistry() {
|
|
94
|
+
const registry = new Map();
|
|
95
|
+
const add = (definition) => {
|
|
96
|
+
if (registry.has(definition.name))
|
|
97
|
+
throw new Error(`duplicate caizhilian operation: ${definition.name}`);
|
|
98
|
+
registry.set(definition.name, definition);
|
|
99
|
+
};
|
|
100
|
+
for (const spec of caizhilianOperationSpecs) {
|
|
101
|
+
const entry = caizhilianHandlers[spec.name];
|
|
102
|
+
if (!entry)
|
|
103
|
+
throw new Error(`caizhilian operation ${spec.name} has no handler`);
|
|
104
|
+
if (isWriteHandler(entry)) {
|
|
105
|
+
if (!spec.requiresConfirmation) {
|
|
106
|
+
throw new Error(`caizhilian operation ${spec.name} 是 prepare/apply 形态,但 spec 未声明 requiresConfirmation`);
|
|
107
|
+
}
|
|
108
|
+
add(prepareDefinition(spec, entry));
|
|
109
|
+
add(applyDefinition(spec, entry));
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (spec.requiresConfirmation) {
|
|
113
|
+
throw new Error(`caizhilian operation ${spec.name} 声明了 requiresConfirmation,但 handler 只有 execute`);
|
|
114
|
+
}
|
|
115
|
+
add(readDefinition(spec, entry));
|
|
116
|
+
}
|
|
117
|
+
for (const name of Object.keys(caizhilianHandlers)) {
|
|
118
|
+
if (!caizhilianOperationSpecs.some((spec) => spec.name === name)) {
|
|
119
|
+
throw new Error(`caizhilian handler ${name} is not declared in specs`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return registry;
|
|
123
|
+
}
|
|
124
|
+
const caizhilianRegistry = buildRegistry();
|
|
125
|
+
export function caizhilianOperationDefinitions() {
|
|
126
|
+
return [...caizhilianRegistry.values()];
|
|
127
|
+
}
|
|
128
|
+
export function getCaizhilianOperation(operation) {
|
|
129
|
+
const definition = caizhilianRegistry.get(operation);
|
|
130
|
+
if (!definition) {
|
|
131
|
+
throw caizhilianValidationError('operation_unknown', `采知连不支持操作:${operation}`);
|
|
132
|
+
}
|
|
133
|
+
return definition;
|
|
134
|
+
}
|
|
135
|
+
export function hasCaizhilianOperation(operation) {
|
|
136
|
+
return caizhilianRegistry.has(operation);
|
|
137
|
+
}
|
|
138
|
+
/** manifest 用的契约视图(剥掉 handler)。 */
|
|
139
|
+
export function caizhilianOperationContracts() {
|
|
140
|
+
return caizhilianOperationDefinitions().map((definition) => ({
|
|
141
|
+
name: definition.name,
|
|
142
|
+
resource: definition.resource,
|
|
143
|
+
summary: definition.summary,
|
|
144
|
+
risk: definition.risk,
|
|
145
|
+
...(definition.requiresConfirmation ? { requiresConfirmation: true } : {}),
|
|
146
|
+
sourceOperation: definition.sourceOperation,
|
|
147
|
+
...(definition.deprecatedInputAliases ? { deprecatedInputAliases: definition.deprecatedInputAliases } : {}),
|
|
148
|
+
...(definition.permissions ? { permissions: definition.permissions } : {}),
|
|
149
|
+
inputSchema: definition.inputSchema,
|
|
150
|
+
}));
|
|
151
|
+
}
|