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
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { workflowSuccess } from './operations/types.js';
|
|
2
|
+
import { getWorkflowOperation } from './operations/registry.js';
|
|
3
|
+
import { assertNoForbiddenKeys, asObject } from './operations/shared.js';
|
|
4
|
+
import { WorkflowCliError, CLARIFICATION_SUBTYPE } from './errors.js';
|
|
5
|
+
/**
|
|
6
|
+
* 幂等回报:一次性 continuation 被**重复执行**时,若上一次已经执行成功,就不能把成功报成失败。
|
|
7
|
+
*
|
|
8
|
+
* 场景(2026-09-16 线上):apply 命令被执行两次——沙箱内首跑已成功写入并消费句柄,宿主逃逸重跑
|
|
9
|
+
* 只能报 `continuation_consumed`,把**已经生效的写入表达成失败**;模型无法分辨真假,只能靠三次
|
|
10
|
+
* 零散查询把真相拼回来。现在底层(continuation.ts)会把「上一次已成功」标成
|
|
11
|
+
* `continuation_already_applied`,在这一层转成**成功信封**(`status: ALREADY_APPLIED`),
|
|
12
|
+
* 并把上一次的执行结果一并回给调用方。
|
|
13
|
+
*/
|
|
14
|
+
function idempotentReplayEnvelope(error, operation) {
|
|
15
|
+
if (!(error instanceof WorkflowCliError) || error.subtype !== 'continuation_already_applied')
|
|
16
|
+
return null;
|
|
17
|
+
const details = (error.details ?? {});
|
|
18
|
+
const finishedAt = Number(details.finishedAt);
|
|
19
|
+
const onlyCommitted = details.stage === 'committed' && details.result == null;
|
|
20
|
+
const previous = typeof details.operation === 'string' && details.operation ? details.operation : operation;
|
|
21
|
+
// 单命令写操作(没有 Prepare 可重跑,如 workflow.batchSubmit)不能沿用"不要重跑 Prepare"的措辞。
|
|
22
|
+
const hasPrepare = /Apply$/u.test(previous);
|
|
23
|
+
const retryHint = hasPrepare
|
|
24
|
+
? '不要重跑 Prepare,也不要再次提交'
|
|
25
|
+
: '不要重复提交同一批 requestId';
|
|
26
|
+
return workflowSuccess(operation, {
|
|
27
|
+
status: 'ALREADY_APPLIED',
|
|
28
|
+
operation: previous,
|
|
29
|
+
requestId: typeof details.requestId === 'string' && details.requestId ? details.requestId : null,
|
|
30
|
+
confirmedAt: Number.isFinite(finishedAt) ? new Date(finishedAt).toISOString() : null,
|
|
31
|
+
previousResult: details.result ?? null,
|
|
32
|
+
note: onlyCommitted
|
|
33
|
+
? '该 continuation 对应的上一次执行已经写入成功(服务端已返回成功回执,只是没来得及写回本地结果),'
|
|
34
|
+
+ `本次未重复执行——${retryHint};目标流程按上面的 requestId 查即可。`
|
|
35
|
+
: `该 continuation 已经执行过且已成功,本次未重复写入(幂等回报)——${retryHint}。`,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 名称→ID 澄清:查询参数里的名称**匹配不到**、或**匹配到多个且其中没有全名精确匹配**时,
|
|
40
|
+
* 不能把结果当成「查到了 0 条流程」——那是把「没听懂你的条件」伪装成「查无数据」。
|
|
41
|
+
*
|
|
42
|
+
* 底层解析函数(`read.ts`)无法直接产出信封,故以 `needs_clarification` 错误向上抛;在这一层
|
|
43
|
+
* 转成**成功信封**(`ok:true` + `status: NEEDS_CLARIFICATION`),把候选与澄清问题原样带回给模型。
|
|
44
|
+
*
|
|
45
|
+
* 形态对齐 V11.3:`e10_workflow.py:10356-10400` 与 `resolve_system_name_condition`(L8262)
|
|
46
|
+
* 都返回 `success:true` + `needClarification:true`(多命中时带 `candidates` +
|
|
47
|
+
* `clarificationType` + `clarificationKeyword`)。与 `workflow.createList` 已有的
|
|
48
|
+
* `ok:true` + `status:NEEDS_SELECTION` 是同一套约定。
|
|
49
|
+
*
|
|
50
|
+
* 注意:这是「本次查询**未执行**」的语义,不是「查询已执行且结果为空」——
|
|
51
|
+
* 文案必须让模型把候选原样摆给用户,而不是转述成「无匹配流程」。
|
|
52
|
+
*/
|
|
53
|
+
function clarificationEnvelope(error, operation) {
|
|
54
|
+
if (!(error instanceof WorkflowCliError) || error.subtype !== CLARIFICATION_SUBTYPE)
|
|
55
|
+
return null;
|
|
56
|
+
const details = (error.details ?? {});
|
|
57
|
+
const candidates = Array.isArray(details.candidates) ? details.candidates : [];
|
|
58
|
+
const question = typeof details.clarificationQuestion === 'string' && details.clarificationQuestion
|
|
59
|
+
? details.clarificationQuestion
|
|
60
|
+
: error.message;
|
|
61
|
+
return workflowSuccess(operation, {
|
|
62
|
+
type: 'workflowClarification',
|
|
63
|
+
status: 'NEEDS_CLARIFICATION',
|
|
64
|
+
clarificationType: details.clarificationType ?? null,
|
|
65
|
+
clarificationKeyword: details.clarificationKeyword ?? null,
|
|
66
|
+
clarificationQuestion: question,
|
|
67
|
+
candidates,
|
|
68
|
+
candidateCount: candidates.length,
|
|
69
|
+
note: '这不是失败,也**不代表查询已执行**:本次查询已停止,没有返回任何流程数据。'
|
|
70
|
+
+ '请把澄清问题与候选**原样**交给用户确认(逐条列出「名称(ID)」),'
|
|
71
|
+
+ '拿到确认后用「名称(ID)」格式重发同一条命令。'
|
|
72
|
+
+ '**不要**把本次结果转述成「没有匹配的流程」「查询结果为 0 条」或自行挑一个候选继续查。'
|
|
73
|
+
+ (candidates.length === 0
|
|
74
|
+
? '当前没有任何候选——请让用户给出准确的完整名称(或纠正名称里的错别字)后重发。'
|
|
75
|
+
: ''),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 写入成功后回写 continuation 的执行结果(best-effort),使重复执行能回报「上一次已成功」,
|
|
80
|
+
* 而不是一句无法分辨的「已使用」。
|
|
81
|
+
*
|
|
82
|
+
* 只覆盖**apply 自带 continuation 入参**的高风险写操作:表单系的 `xxxPrepare` 消费的是上一步
|
|
83
|
+
* (createForm/editLoad)签发的租约,不属于本操作自身的执行结果,不能在此回写。
|
|
84
|
+
*/
|
|
85
|
+
async function settleAppliedContinuation(input, result, context, definition) {
|
|
86
|
+
if (definition.risk !== 'high-risk-write')
|
|
87
|
+
return;
|
|
88
|
+
// 单条/批量/共享的句柄入参叫 `continuation`;发起(createApply)与修改(editApply)的句柄
|
|
89
|
+
// 从 createForm/editLoad 一路传下来,入参名是 `context`(同一个本机托管句柄)。
|
|
90
|
+
// 原先只认 `continuation` ⇒ 发起/修改成功后从不回写结果,重放只能报"已使用",
|
|
91
|
+
// 模型被迫反查 OA 才能确认到底有没有发起(2026-09-16 线上)。
|
|
92
|
+
const raw = typeof input.continuation === 'string' ? input.continuation
|
|
93
|
+
: typeof input.context === 'string' ? input.context : '';
|
|
94
|
+
const reference = raw.trim();
|
|
95
|
+
if (!reference)
|
|
96
|
+
return;
|
|
97
|
+
await context.continuation.settle(reference, result.data, definition.action || definition.name);
|
|
98
|
+
}
|
|
99
|
+
export async function executeWorkflowOperation(operation, rawInput, context) {
|
|
100
|
+
const definition = getWorkflowOperation(operation);
|
|
101
|
+
const input = asObject(rawInput);
|
|
102
|
+
assertNoForbiddenKeys(input);
|
|
103
|
+
let result;
|
|
104
|
+
try {
|
|
105
|
+
result = await definition.handler(input, context);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
// 澄清要先于幂等回报判断:澄清是**本次查询的前提条件没满足**,与 continuation 无关。
|
|
109
|
+
const clarified = clarificationEnvelope(error, operation);
|
|
110
|
+
if (clarified)
|
|
111
|
+
return clarified;
|
|
112
|
+
const replayed = idempotentReplayEnvelope(error, operation);
|
|
113
|
+
if (replayed)
|
|
114
|
+
return replayed;
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
await settleAppliedContinuation(input, result, context, definition);
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { homedir, tmpdir } from 'node:os';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
function stateRoot(ctx) {
|
|
6
|
+
const configured = ctx?.config?.path();
|
|
7
|
+
if (configured)
|
|
8
|
+
return resolve(configured, '..');
|
|
9
|
+
return process.env.WEAVER_WORK_CLI_HOME
|
|
10
|
+
|| process.env.WORK_CLI_HOME
|
|
11
|
+
|| resolve(homedir(), '.weaver-work-cli');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 本地状态可写根目录列表(主目录 → 系统临时目录回退)。
|
|
15
|
+
*
|
|
16
|
+
* 沙箱/受限环境下主状态目录可能不可写。序号索引属于「查询后定位」的便利设施,
|
|
17
|
+
* **任何落盘失败都不得让读操作失败**;主目录不可写时退回临时目录,保证同一台机器上
|
|
18
|
+
* 后续 `--index` 定位仍可用。
|
|
19
|
+
*/
|
|
20
|
+
function stateRoots(ctx) {
|
|
21
|
+
const primary = stateRoot(ctx);
|
|
22
|
+
const fallback = resolve(tmpdir(), 'weaver-work-cli');
|
|
23
|
+
return primary === fallback ? [primary] : [primary, fallback];
|
|
24
|
+
}
|
|
25
|
+
function indexPath(root) {
|
|
26
|
+
return resolve(root, 'state', 'workflow', 'search-index.json');
|
|
27
|
+
}
|
|
28
|
+
export function workflowIndexFile(ctx) {
|
|
29
|
+
return indexPath(stateRoot(ctx));
|
|
30
|
+
}
|
|
31
|
+
/** 本地状态文件路径(主目录优先,调用方在写失败时自行回退)。 */
|
|
32
|
+
export function workflowStateFile(name, ctx) {
|
|
33
|
+
return resolve(stateRoot(ctx), 'state', 'workflow', name);
|
|
34
|
+
}
|
|
35
|
+
export function workflowFallbackStateFile(name) {
|
|
36
|
+
return resolve(tmpdir(), 'weaver-work-cli', 'state', 'workflow', name);
|
|
37
|
+
}
|
|
38
|
+
/** 读取本地状态文件(主目录 → 回退目录),不存在或不可读返回 null。 */
|
|
39
|
+
export async function readStateFile(name, ctx) {
|
|
40
|
+
for (const root of stateRoots(ctx)) {
|
|
41
|
+
const file = resolve(root, 'state', 'workflow', name);
|
|
42
|
+
if (!existsSync(file))
|
|
43
|
+
continue;
|
|
44
|
+
try {
|
|
45
|
+
return await readFile(file, 'utf8');
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 落盘单个状态文件:**直接覆盖写**。
|
|
55
|
+
*
|
|
56
|
+
* 与 V11.3 的 `save_session_maps` / `save_config` / `_save_runtime_file_cache` 一致
|
|
57
|
+
* (Python 侧 `Path.write_text` 直接覆盖目标文件)。
|
|
58
|
+
*
|
|
59
|
+
* 此前实现是「写固定名 `*.tmp` + `rename` 原子替换」,但在宿主沙箱里 `rename` 实测恒被拦
|
|
60
|
+
* (EPERM,且该标志是进程内记忆、CLI 每次命令都是新进程,于是每次落盘都要重试一次),
|
|
61
|
+
* 于是每次落盘都额外产生两次**删除**动作:`rename` 被宿主视作「删除目标文件」、失败路径里的
|
|
62
|
+
* `unlink(tmp)` 被视作「删除临时文件」。宿主因此弹出文件删除审批(审计日志里成对出现的
|
|
63
|
+
* `search-index.json` + `search-index.json.tmp` 即由此而来),并留下 `.tmp` 残留。
|
|
64
|
+
* 本文件只承载「查询后定位」的便利设施(见文件头注释),不值得为原子替换付出这类环境代价,
|
|
65
|
+
* 故对齐 V11.3 直接覆盖写,写路径**不产生任何删除动作**。
|
|
66
|
+
*/
|
|
67
|
+
async function writeStatePayload(file, payload) {
|
|
68
|
+
await writeFile(file, payload, { mode: 0o600 });
|
|
69
|
+
if (process.platform !== 'win32')
|
|
70
|
+
await chmod(file, 0o600).catch(() => undefined);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 尽力写入本地状态文件,返回实际写入路径;全部失败返回 null(调用方按"无落盘"降级)。
|
|
74
|
+
* 语义:本地状态是缓存/便利设施,写入失败绝不能向上抛错。
|
|
75
|
+
*/
|
|
76
|
+
export async function writeStateFileBestEffort(name, payload, ctx) {
|
|
77
|
+
const roots = stateRoots(ctx);
|
|
78
|
+
for (const root of roots) {
|
|
79
|
+
const file = resolve(root, 'state', 'workflow', name);
|
|
80
|
+
try {
|
|
81
|
+
await mkdir(dirname(file), { recursive: true, mode: 0o700 });
|
|
82
|
+
await writeStatePayload(file, payload);
|
|
83
|
+
return file;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function emptyIndex() {
|
|
92
|
+
return { queryId: '', updatedAt: '', groups: {}, items: [] };
|
|
93
|
+
}
|
|
94
|
+
function asItems(value) {
|
|
95
|
+
if (!Array.isArray(value))
|
|
96
|
+
return [];
|
|
97
|
+
return value.filter((item) => Boolean(item) && typeof item === 'object');
|
|
98
|
+
}
|
|
99
|
+
function asGroups(value) {
|
|
100
|
+
const groups = {};
|
|
101
|
+
if (!value || typeof value !== 'object')
|
|
102
|
+
return groups;
|
|
103
|
+
for (const [kind, raw] of Object.entries(value)) {
|
|
104
|
+
if (!raw || typeof raw !== 'object')
|
|
105
|
+
continue;
|
|
106
|
+
const record = raw;
|
|
107
|
+
groups[kind] = {
|
|
108
|
+
...record,
|
|
109
|
+
kind,
|
|
110
|
+
items: asItems(record.items),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return groups;
|
|
114
|
+
}
|
|
115
|
+
export async function loadSearchIndex(ctx) {
|
|
116
|
+
for (const root of stateRoots(ctx)) {
|
|
117
|
+
const file = indexPath(root);
|
|
118
|
+
if (!existsSync(file))
|
|
119
|
+
continue;
|
|
120
|
+
try {
|
|
121
|
+
const parsed = JSON.parse(await readFile(file, 'utf8'));
|
|
122
|
+
return {
|
|
123
|
+
queryId: typeof parsed.queryId === 'string' ? parsed.queryId : '',
|
|
124
|
+
updatedAt: typeof parsed.updatedAt === 'string' ? parsed.updatedAt : '',
|
|
125
|
+
groups: asGroups(parsed.groups),
|
|
126
|
+
items: asItems(parsed.items),
|
|
127
|
+
...(parsed.summary && typeof parsed.summary === 'object'
|
|
128
|
+
? { summary: parsed.summary }
|
|
129
|
+
: {}),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return emptyIndex();
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 落盘序号索引。**best-effort**:主状态目录不可写时回退临时目录,全部失败也不抛错
|
|
140
|
+
* ——索引只是"查询后按序号定位"的便利设施,不能让读操作本身失败
|
|
141
|
+
* (直接覆盖写,写路径零删除动作;受限环境下也不会因碰删除而被宿主拦下)。
|
|
142
|
+
*/
|
|
143
|
+
export async function saveSearchIndex(entry, ctx) {
|
|
144
|
+
const index = {
|
|
145
|
+
queryId: entry.queryId || newDateQueryId(),
|
|
146
|
+
updatedAt: new Date().toISOString(),
|
|
147
|
+
groups: asGroups(entry.groups),
|
|
148
|
+
items: asItems(entry.items),
|
|
149
|
+
...(entry.summary && typeof entry.summary === 'object'
|
|
150
|
+
? { summary: entry.summary }
|
|
151
|
+
: {}),
|
|
152
|
+
};
|
|
153
|
+
const payload = JSON.stringify(index, null, 2);
|
|
154
|
+
for (const root of stateRoots(ctx)) {
|
|
155
|
+
const file = indexPath(root);
|
|
156
|
+
try {
|
|
157
|
+
await mkdir(dirname(file), { recursive: true, mode: 0o700 });
|
|
158
|
+
await writeStatePayload(file, payload);
|
|
159
|
+
return index;
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return index;
|
|
166
|
+
}
|
|
167
|
+
function newDateQueryId() {
|
|
168
|
+
return new Date().toISOString();
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* 按 `--group` + `--index` 定位条目。
|
|
172
|
+
*
|
|
173
|
+
* - `group` 省略时在平铺条目里按序取第 `index` 条;
|
|
174
|
+
* - `group` 命中分组时在该分组条目里取第 `index` 条(1 基)。
|
|
175
|
+
* 返回 null 表示定位不到(调用方按"索引失效,需要重新查询"处理)。
|
|
176
|
+
*/
|
|
177
|
+
export function findIndexedItem(index, group, position) {
|
|
178
|
+
const list = group ? index.groups[group]?.items ?? [] : index.items;
|
|
179
|
+
if (!Number.isInteger(position) || position < 1 || position > list.length)
|
|
180
|
+
return null;
|
|
181
|
+
return list[position - 1] ?? null;
|
|
182
|
+
}
|
package/docs/SKILL.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- `src/internal/e10`:E10 session、profile、auth 文件和 API client。
|
|
9
9
|
- `src/shortcuts`:面向人和 Agent 的高层业务 CLI 能力,按业务模块分目录;模块内每个业务 operation 用相对独立的 class 封装。使用 Skill Maker 新增业务模块时,默认同步生成或更新对应 shortcut。
|
|
10
10
|
- `skills`:随包发布的 Agent Skill,按业务模块分目录;每个模块对应一个独立 Skill,入口 `SKILL.md` 只做路由,具体操作细节放到 `references/`,公共约束通过 `weaver-e10-shared` 复用。
|
|
11
|
-
- `skill-template`:新增或重写业务 Skill 的模板来源;结构参考飞书 CLI 的 `skill-template
|
|
11
|
+
- `skill-template`:新增或重写业务 Skill 的模板来源;结构参考飞书 CLI 的 `skill-template`,用于保持入口、路由关键词、业务域说明、产品元信息和 reference 拆分方式一致。
|
|
12
12
|
|
|
13
13
|
使用内置 docs 命令可以把当前文档目录复制到业务工作区:
|
|
14
14
|
|
|
@@ -21,9 +21,9 @@ weaver-work-cli docs copy
|
|
|
21
21
|
业务 Skill 目录约定:
|
|
22
22
|
|
|
23
23
|
```text
|
|
24
|
+
skill-template/product.json 共享产品元信息模板;打包/安装时注入到每个 Skill 产物。
|
|
24
25
|
skills/weaver-e10-<name>/
|
|
25
26
|
SKILL.md 入口路由:共享规则、schema、reference 索引、禁用边界。
|
|
26
|
-
product.json 可选:Skill 包元信息。
|
|
27
27
|
references/ 具体业务 reference,按用户意图和 operation 分文件。
|
|
28
28
|
```
|
|
29
29
|
|
|
@@ -35,6 +35,8 @@ skills/weaver-e10-<name>/
|
|
|
35
35
|
- `fna`:E10 齐业成费控中心(预算查询/费用中心/借款管理/发票核销)。源码说明先读 `docs/fna.md`;面向 Agent 时先读 `skills/weaver-e10-qiyecheng/SKILL.md`,再按入口路由读取对应 reference。写操作(提醒还款/催票)走 prepare/apply 确认链。
|
|
36
36
|
- `plan`:E10 计划报告(报告查询/新建/修改/发布/撤回/提交提醒/评论),自动适配标准版与 e10-ebuilder 两套报告接口链路。源码说明先读 `docs/plan.md`;面向 Agent 时先读 `skills/weaver-e10-plan/SKILL.md`,再按入口路由读取对应 reference。写操作走 prepare/apply 确认链。
|
|
37
37
|
- `esb`:E10 ESB 中心自定义触发动作流(入参模板查询 + 触发)。源码说明先读 `docs/esb.md`;面向 Agent 时先读 `skills/weaver-e10-esb/SKILL.md`,再按入口路由读取对应 reference。触发动作流是写操作,走 prepare/apply 确认链。
|
|
38
|
-
- `
|
|
38
|
+
- `okr`:E10 OKR 目标管理(目标分页查询/详情、关键成果查询与保存、目标对齐、目标评论、详情页链接),按 `ver_name` 自动适配 e10 标准版与 e10-ebuilder 两套接口链路。源码说明先读 `docs/okr.md`;面向 Agent 时先读 `skills/weaver-e10-okr/SKILL.md`,再按入口路由读取对应 reference。写操作(新建/编辑目标、保存关键成果、添加目标对齐)走 prepare/apply 确认链。
|
|
39
|
+
- `ebuilder-form`:E10 eBuilder 表单(菜单定位、List/NList 分页和配置、字段/选项/浏览字段解析、OpenAPI 与已发布自定义接口读写)。源码说明先读 `docs/ebuilder-form.md`;面向 Agent 时先读 `skills/weaver-e10-ebuilder-form/SKILL.md`,再按入口路由读取对应 reference。写操作走 prepare/apply 确认链。
|
|
40
|
+
- `skill-maker`:把用户提供的新业务模块文档或代码转换成 `weaver-e10-*` Agent Skill,通过源资料指纹检测更新;每次创建或更新 Skill 后先询问是否现在进行 Skill 质检,用户确认后用泛微技能检测工具做发布前静态质检,并在检测通过后询问是否安装到当前智能体。面向 Agent 时先读 `skills/weaver-e10-skill-maker/SKILL.md`。
|
|
39
41
|
|
|
40
42
|
Agent 调用业务能力时优先使用 `weaver-work-cli --json <command> run <operation> --input-json '<json>'`;复杂或多行 JSON 用 UTF-8 文件和 `--input <path>`,只有确认当前 shell 能稳定传管道时才使用 `--input -`。不要绕过 CLI 直接拼业务 HTTP。新增业务模块时,如果源资料不足以实现 CLI,先向用户列出缺口并确认,不生成假 operation。
|
package/docs/_catalog.md
CHANGED
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
| 齐业成费控中心(预算/费用中心/借款管理/发票核销)、fna operation、提醒还款与催票 prepare/apply | `docs/fna.md` |
|
|
14
14
|
| 文书定档案管理(全宗/检索/借阅车/借阅单/发起借阅/预归档上传)、wenshuding operation | `docs/wenshuding.md` |
|
|
15
15
|
| 计划报告管理(报告查询/新建/修改/发布/撤回/提交提醒/评论)、plan operation、写操作 prepare/apply | `docs/plan.md` |
|
|
16
|
+
| OKR 目标管理(目标查询/详情、关键成果、目标对齐、评论)、okr operation、标准版与 ebuilder 双链路、写操作 prepare/apply | `docs/okr.md` |
|
|
17
|
+
| eBuilder 表单(菜单定位、List/NList、字段/浏览、OpenAPI 与自定义接口)、ebuilder-form operation、写操作 prepare/apply | `docs/ebuilder-form.md` |
|
|
16
18
|
| E10 ESB 中心自定义触发动作流(入参模板查询 / prepare-apply 触发)、esb operation | `docs/esb.md` |
|
|
19
|
+
| 事井然项目管理(项目/任务/字典/字段解析)、project operation、写操作 prepare/apply | `docs/project.md` |
|
|
17
20
|
| 快速安装 CLI,并使用 CLI/Skill Maker 生成、验证、打包和安装业务模块 Skill | `docs/operation-manual.md` |
|
|
18
21
|
| 把随包 Agent Skill 安装/升级到本机 Agent(Codex/WorkBuddy 目录、从本地仓库发布最新版) | `docs/agent-skill-install.md` |
|
|
19
22
|
| Agent 调用业票通 CLI 的入口路由 | `skills/weaver-e10-yepiaotong/SKILL.md` |
|
|
@@ -26,11 +29,17 @@
|
|
|
26
29
|
| Agent 调用齐业成费控 CLI 的具体 reference | `skills/weaver-e10-qiyecheng/references/` |
|
|
27
30
|
| Agent 调用计划报告 CLI 的入口路由 | `skills/weaver-e10-plan/SKILL.md` |
|
|
28
31
|
| Agent 调用计划报告 CLI 的具体 reference | `skills/weaver-e10-plan/references/` |
|
|
32
|
+
| Agent 调用 OKR 目标管理 CLI 的入口路由 | `skills/weaver-e10-okr/SKILL.md` |
|
|
33
|
+
| Agent 调用 OKR 目标管理 CLI 的具体 reference | `skills/weaver-e10-okr/references/` |
|
|
29
34
|
| Agent 调用 ESB 动作流 CLI 的入口路由 | `skills/weaver-e10-esb/SKILL.md` |
|
|
30
35
|
| Agent 调用 ESB 动作流 CLI 的具体 reference | `skills/weaver-e10-esb/references/` |
|
|
36
|
+
| Agent 调用 eBuilder 表单 CLI 的入口路由 | `skills/weaver-e10-ebuilder-form/SKILL.md` |
|
|
37
|
+
| Agent 调用 eBuilder 表单 CLI 的具体 reference | `skills/weaver-e10-ebuilder-form/references/` |
|
|
31
38
|
| Agent 调用会议管理 CLI 的入口路由 | `skills/weaver-e10-meeting/SKILL.md` |
|
|
32
39
|
| Agent 调用会议管理 CLI 的具体 reference | `skills/weaver-e10-meeting/references/` |
|
|
33
|
-
| 易秒办即时通讯(消息/群组/会话/系统消息)、
|
|
40
|
+
| 易秒办即时通讯(消息/群组/会话/系统消息)、im operation、写操作 prepare/apply | `docs/im.md` |
|
|
34
41
|
| Agent 调用易秒办 CLI 的入口路由 | `skills/weaver-e10-yimiaoban/SKILL.md` |
|
|
35
42
|
| Agent 调用易秒办 CLI 的具体 reference | `skills/weaver-e10-yimiaoban/references/` |
|
|
43
|
+
| Agent 调用事井然项目管理 CLI 的入口路由 | `skills/weaver-e10-shijingran/SKILL.md` |
|
|
44
|
+
| Agent 调用事井然项目管理 CLI 的具体 reference | `skills/weaver-e10-shijingran/references/` |
|
|
36
45
|
| 将新业务模块文档或代码同步转换为 weaver-work-cli 业务 CLI 与 Skill、检测源资料更新 | `skills/weaver-e10-skill-maker/SKILL.md` |
|
package/docs/agent-invoice.md
CHANGED
|
@@ -55,7 +55,7 @@ weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"s
|
|
|
55
55
|
|
|
56
56
|
1. 查询个人票夹和企业票夹,确认目标不存在。
|
|
57
57
|
2. `invoice.ocr.preview` 预览文件识别结果,预览阶段固定不保存。
|
|
58
|
-
3. 用户确认后执行 `invoice.import.prepare`,输入必须显式包含 `validate` 和 `syncToOa`;默认传 `validate=true`、`syncToOa=true`,表示导入时请求服务端查验并按服务端要求同步 OA
|
|
58
|
+
3. 用户确认后执行 `invoice.import.prepare`,输入必须显式包含 `validate` 和 `syncToOa`;默认传 `validate=true`、`syncToOa=true`,表示导入时请求服务端查验并按服务端要求同步 OA。使用 `filedMap` 时保持 JSON 对象输入,不要转成字符串。
|
|
59
59
|
4. 把 prepare 返回的 `continuation` 原样交给 `invoice.import.apply`,并传 `confirm=true`。
|
|
60
60
|
5. 使用返回的 `fid` 回查详情,按实际结果报告查验状态、写入状态和附件信息。
|
|
61
61
|
|
|
@@ -63,7 +63,7 @@ weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"s
|
|
|
63
63
|
|
|
64
64
|
删除、编辑、新增同样必须使用 `prepare -> apply`。出现 `partial/write_uncertain` 时停止,不能自动重试写操作。
|
|
65
65
|
|
|
66
|
-
处理“把发票填进流程表单”的场景,使用 `invoice.browse-field.data` 生成浏览按钮控件所需 JSON。处理“报销发票/自动填单”时,先读取 `invoice-reim.md`,用报销相关只读 operation 获取事前申请、工作流、表单结构、预填信息和人员上级;Agent
|
|
66
|
+
处理“把发票填进流程表单”的场景,使用 `invoice.browse-field.data` 生成浏览按钮控件所需 JSON。处理“报销发票/自动填单”时,先读取 `invoice-reim.md`,用报销相关只读 operation 获取事前申请、工作流、表单结构、预填信息和人员上级;Agent 组装报销单结构化 JSON 后,必须通过 `invoice.reim.flow.create.prepare/apply` 或 `invoice.reim.flow.update.prepare/apply` 写入,创建报销单的 `work_flow_id/mainFormId/request_name/main_fields/detail_rows` 等字段在 operation 顶层传入,不包通用 `payload`。处理“开票/存台账”时,先读取 `invoice-issuing.md` 和 `invoice-issuing-field-rules.md`,从用户输入或附件提取购方、税号、明细、税率和金额;资料不足时追问用户补齐,再走 `invoice.issuing.make.prepare/apply`。当前修正资料包没有客户档案查询或红字发票红冲接口,`invoice.customer.*` 和 `invoice.red.*` 不能调用或绕过。
|
|
67
67
|
|
|
68
68
|
## 暂缓能力
|
|
69
69
|
|
|
@@ -115,7 +115,7 @@ weaver-work-cli skills install skill-maker --target-dir "$HOME/.workbuddy/skills
|
|
|
115
115
|
2. **`skills install` 是拷贝语义**:装出的是真实副本,不与源目录联动。之后源里改动 Skill,已安装目录不会自动更新,需重跑安装;覆盖安装只写入与覆盖同名文件,**不会清理目标里已不存在的旧文件**,需要干净结果时先整目录移除再安装。
|
|
116
116
|
3. **目标目录已有旧条目(旧副本或软链)时不能直接覆盖**:命令内部是递归拷贝,目标为软链时会报 `ERR_FS_CP_DIR_TO_NON_DIR` 失败;先移除该条目再安装(移除软链只断链,不影响其指向的目录)。
|
|
117
117
|
4. **本机 CLI 若为 `npm link` 指向本地仓库**,`skills list/install` 反映的是仓库当前工作区内容,包含未提交改动——开发期可直接发布最新工作区。
|
|
118
|
-
5. 拷贝会过滤 dotfiles、`scripts/`、`assets/`、`node_modules/`;`SKILL.md`、`references
|
|
118
|
+
5. 拷贝会过滤 dotfiles、`scripts/`、`assets/`、`node_modules/`;`SKILL.md`、`references/` 会完整拷贝,`product.json` 由 `skill-template/product.json` 和 `package.json` 注入到每个安装产物。
|
|
119
119
|
|
|
120
120
|
## 首次安装
|
|
121
121
|
|
|
@@ -195,7 +195,7 @@ diff -q skills/weaver-e10-shared/SKILL.md "$HOME/.workbuddy/skills/weaver-e10-sh
|
|
|
195
195
|
|
|
196
196
|
安装本身不校验业务 API。要确认对 Agent 生效:
|
|
197
197
|
|
|
198
|
-
- 目录结构正确:用户主目录下的 `.workbuddy/skills/weaver-e10-yepiaotong` 包含 `SKILL.md
|
|
198
|
+
- 目录结构正确:用户主目录下的 `.workbuddy/skills/weaver-e10-yepiaotong` 包含 `SKILL.md`、安装生成的 `product.json`、`references/`,且 `weaver-e10-shared` 包含 `SKILL.md`、`references/`。
|
|
199
199
|
- 内容一致:Windows 使用上述 `Get-FileHash`,macOS/Linux 使用上述 `diff -q`;或用 `weaver-work-cli skills read weaver-e10-yepiaotong` 与仓库内容比对。
|
|
200
200
|
- **Agent 需重新加载**:新建会话或按 Agent 规则重载 Skill 后才读取新内容;已打开的会话不会热更新。
|
|
201
201
|
- 业务可用性:安装后仍需完成 E10 登录(`weaver-work-cli auth login --base-url "<E10_BASE_URL>" --agent_type "<当前智能体名称>"`),并可按 `weaver-work-cli invoice schema` 验证 operation 契约。
|
package/docs/e10-auth.md
CHANGED
|
@@ -38,7 +38,9 @@ weaver-work-cli auth export-weaver-env
|
|
|
38
38
|
环境变量推断当前宿主,最后回落为 `weaver-work-cli`。浏览器授权地址会同时携带
|
|
39
39
|
`agent_type=<value>` 和 `from=<value>`,其中 `from` 用于 E10 授权确认页展示客户端名称。
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
XiaoE 宿主环境中,`auth login` / `auth oidc` / `auth xiaoe` 会先尝试读取宿主 `xiaoeUserData/tokens.py`;脚本不可用(不存在、执行失败,或所用 Python 缺少 `requests` 等依赖)时,CLI 改用内置的原生等价实现读取 XiaoE 客户端本地会话(macOS `~/Library/Application Support/XiaoE/Robots/*/user_settings.json`,Windows `%LOCALAPPDATA%/XiaoE/Robots/*/user_settings.json`,或 `XIAOE_USER_TOKEN`)并换取 `eteamId`,该链路不依赖本机 Python 环境;仍没有可用凭证时,再从 `XIAOE_*` 环境变量读取当前域名对应的统一登录凭证。凭证可用时,CLI 直接保存登录态,保存的 `agentType` 固定为 `XiaoE`;凭证只返回 `eteamId` 时,会使用凭证中的域名或资料包默认域名 `https://www.e-cology.com.cn`;仍没有可用凭证时才考虑当前 profile 配置。业务命令在未显式指定 `--auth` / `--profile` 时,也会自动优先尝试 XiaoE 统一登录。XiaoE 凭证校验失败、当前域名不在支持范围内,或用户切换了访问域名时,`auth xiaoe` 会先反馈未拿到登录信息的原因,再自动降级到原浏览器 OAuth2.0 登录。
|
|
42
|
+
|
|
43
|
+
脚本链路按 `python3`、`/usr/bin/python3`、`python` 顺序探测可用解释器;可用 `XIAOE_TOKEN_SCRIPT_PYTHON` 指定解释器,用 `XIAOE_TOKEN_SCRIPT_PATH` 指定脚本路径。
|
|
42
44
|
|
|
43
45
|
无法使用浏览器回调时,可以用 `auth set` 直接写入浏览器中复制到的
|
|
44
46
|
`ETEAMSID`。命令会调用 `teamsCheck` 解析当前用户、租户和组织信息,并写入
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# eBuilder 表单 CLI
|
|
2
|
+
|
|
3
|
+
`ebuilder-form` 将 eBuilder 菜单定位、List/NList 页面查询、字段/选项/浏览字段解析、OpenAPI 表单数据和已发布自定义接口统一成 `weaver-work-cli` shortcut。
|
|
4
|
+
|
|
5
|
+
## 命令
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
weaver-work-cli ebuilder-form --help
|
|
9
|
+
weaver-work-cli ebuilder-form schema
|
|
10
|
+
weaver-work-cli --json ebuilder-form run <operation> --input-json '<json>'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
复杂 JSON 使用 UTF-8 文件和 `--input <path>`。Agent Skill 入口是 `skills/weaver-e10-ebuilder-form/SKILL.md`。
|
|
14
|
+
|
|
15
|
+
## Operation 分组
|
|
16
|
+
|
|
17
|
+
| 分组 | Operation |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| 上下文 | `ebuilder-form.menu.search`、`ebuilder-form.context.resolve`、`ebuilder-form.views.list` |
|
|
20
|
+
| List/NList | `ebuilder-form.list.config`、`ebuilder-form.list.query`、`ebuilder-form.nlist.config`、`ebuilder-form.nlist.query` |
|
|
21
|
+
| 字段与浏览 | `ebuilder-form.fields.get`、`ebuilder-form.options.get`、`ebuilder-form.mapping.get`、`ebuilder-form.browser.resolve` |
|
|
22
|
+
| OpenAPI 只读 | `ebuilder-form.openapi.detail`、`ebuilder-form.openapi.query`、`ebuilder-form.openapi.count` |
|
|
23
|
+
| OpenAPI 写入 | `ebuilder-form.openapi.add/update/delete.prepare` → `*.apply` |
|
|
24
|
+
| 自定义接口 | `ebuilder-form.custom.detail/query/count`、`ebuilder-form.custom.add/update/delete.prepare` → `*.apply` |
|
|
25
|
+
|
|
26
|
+
## 关键实现规则
|
|
27
|
+
|
|
28
|
+
- `SEARCH` 菜单映射为 `List`,`VIEWPORT` 菜单映射为 `NList`。
|
|
29
|
+
- `/api/ebuilder/form/**` 根据 `isIndependentDeploy(appId)` 路由到 `/api/ebuilder` 或 `/api/ebuilder{appId}`;`/api/ebuilder/common/**` 和浏览接口不拼 appId。
|
|
30
|
+
- List 查询必须另调 `getListDataCount` 取真实总数。
|
|
31
|
+
- NList 查询会把 `customConfig` JSON 编成 eBuilder 运行时要求的 LZW 数字串。
|
|
32
|
+
- OpenAPI 写入默认 `fieldNoFindIgnore=false`、`checkRight=true`。
|
|
33
|
+
- 自定义字段若字段定义中 `name == id`,写入键使用 `config.dataKey`。
|
|
34
|
+
- 新增、修改、删除都是高风险写操作,必须走 continuation 绑定的 prepare/apply 确认链。
|
|
35
|
+
|
|
36
|
+
## 不在范围
|
|
37
|
+
|
|
38
|
+
本模块不创建菜单、不改页面配置、不调用 `/api/bs/`、不上传文件、不做 OCR、不读本地凭证目录,也不根据字段标题猜浏览接口。
|
package/docs/im.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# 易秒办即时通讯(im)
|
|
2
|
+
|
|
3
|
+
`im` 是 E10 易秒办即时通讯的聚合命令,覆盖**消息(msg)**、**必达(ding)**、**群组(group)**、**会话(session)**、**系统消息(sysmsg)**,以及支撑能力人员解析(person)、文件上传/预览/下载(file)、用户状态与免打扰设置(user)、i18n 标签(i18n)。
|
|
4
|
+
|
|
5
|
+
Skill 名与命令名不同:Skill 目录是 `skills/weaver-e10-yimiaoban`,CLI 命令后缀是 `im`(`weaver-work-cli im ...`)。
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
weaver-work-cli im --help
|
|
9
|
+
weaver-work-cli im schema
|
|
10
|
+
weaver-work-cli --json im run <operation> --input-json '{"key":"value"}'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`schema` 是能力清单的唯一事实来源,包含每个 operation 的 `inputSchema`、`risk`、`requiresConfirmation` 和 `deprecatedInputAliases`。
|
|
14
|
+
|
|
15
|
+
## 实现位置
|
|
16
|
+
|
|
17
|
+
| 路径 | 职责 |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `src/shortcuts/im/index.ts` | 命令注册与 JSON envelope |
|
|
20
|
+
| `src/shortcuts/im/manifest.ts` | `schema` 契约 |
|
|
21
|
+
| `src/shortcuts/im/host.ts` | E10 会话桥接、认证头、executeIm/文件上传、hrm 人员解析、i18n、媒体 URL |
|
|
22
|
+
| `src/shortcuts/im/continuation.ts` | 写操作确认链的 HMAC-SHA256 token |
|
|
23
|
+
| `src/shortcuts/im/operations/` | 按业务域拆分的 operation 实现 |
|
|
24
|
+
| `src/shortcuts/im/operations/registry.ts` | operation 注册表与去重校验 |
|
|
25
|
+
| `skills/weaver-e10-yimiaoban/` | Agent Skill(入口 + 按能力拆分的 reference) |
|
|
26
|
+
|
|
27
|
+
## 认证
|
|
28
|
+
|
|
29
|
+
复用 `src/internal/e10` 的 E10 会话(`requireE10Session`),请求自动携带 `Cookie`、`eteamsid` 与 `X-Requested-With: XMLHttpRequest`。IM 接口前缀 `/api/em/msg/executeIm`,必达例外走 `/api/em/msg/createDing`。业务代码不接触认证目录,路径强制以 `/api/` 开头。
|
|
30
|
+
|
|
31
|
+
## 红线(模块内强制)
|
|
32
|
+
|
|
33
|
+
- 请求体禁止传操作人字段(`user`/`sender`/`creator`/`operator`),操作者由 `eteamsid` 识别。
|
|
34
|
+
- 本人 IM 身份(`imCid`/`imUid`)只用于本机组装搜索条件、撤回/必达消息体、建群自检和「我」的判定(`teamsCheck` 解析,进程内缓存),**绝不入请求体**,也不接受调用方传入。
|
|
35
|
+
- 人名一律走 hrm:`/api/hrm/common/getEmployeeByIds` 解析,禁止用 IM 群成员 `name` 字段展示姓名。
|
|
36
|
+
- uid/cid/群 id 是 uint64,一律字符串传输且非 0。
|
|
37
|
+
- 过滤全部服务端完成;有界区间自动翻页(最多 100 页),无界区间只拉一页。
|
|
38
|
+
- 时间范围查询换算为消息 id 区间(`MakeMinAndMaxIdByTm`),跨度 > 7 天自动收敛为该范围最后 7 个自然日并在响应里给出提示。
|
|
39
|
+
- 全空白文本不算内容(拒绝发送空白消息);普通请求 15 秒超时即失败不重试(上传 15/60 秒)。
|
|
40
|
+
- 媒体只给需登录态的 URL,真要看内容用 `im.file.download` 落地到本地(父目录须存在、拒绝覆盖)。
|
|
41
|
+
- 消息内容完整透出,不截断;展示规则见 Skill `references/safety-boundaries.md`。
|
|
42
|
+
|
|
43
|
+
## 消息拉取与展示
|
|
44
|
+
|
|
45
|
+
`im.msg.sync.single`(对方 `fromUid`+`fromCid` 必填)、`im.msg.sync.group`(`groupId` 必填,type=0 固定)为倒序拉取:
|
|
46
|
+
|
|
47
|
+
- 每页默认 50 条、上限 50;**有界区间**(`from`/`to`、缺省当天或显式 `end`/`endId`)自动循环翻页拉完再返回;**无界区间**(`latest:true`)只拉一页,用 `nextStart` 续拉。
|
|
48
|
+
- `actionMsg.code=1303` 表示无聊天记录,按成功空列表处理,并返回 `empty:true` + `emptyReason`(区分当天无消息/时间范围无消息/会话无历史)。
|
|
49
|
+
- 响应带 `pages`/`autoPaged`/`pageSize`/`exhausted`/`hasMore`/`nextStart`/`range`/`rangeShrink`;消息按消息 id 从新到旧排序。
|
|
50
|
+
|
|
51
|
+
返回的 `messages[]` 已按 msgParser 语义解析为结构化行:
|
|
52
|
+
|
|
53
|
+
- `msgid`;`sender`(自己显示「我」);`time`;`typeName`;`content` 完整正文(@ 提及已还原、媒体显示 `[图片]名称`/`[视频]名称`/`[文件]名称`);`must` 必达标记。
|
|
54
|
+
- `fileName`:媒体消息原始文件名;`media`:图片/视频/文件的预览与下载 URL(需登录态)。
|
|
55
|
+
|
|
56
|
+
## 系统消息
|
|
57
|
+
|
|
58
|
+
`im.sysmsg.query` 与聊天消息同一分页口径;`start` 为排除边界(返回 id `< start`),返回 `dealMode` 表示该分组以处理状态(`已处理/未处理`)还是阅读状态(`已读/未读`)为准。分组/类型 id 来自 `im.sysmsg.groupSearch` / `im.sysmsg.typeSync`。
|
|
59
|
+
|
|
60
|
+
## 写协议与 continuation
|
|
61
|
+
|
|
62
|
+
所有写操作(send/withdraw/top.set/ding/group 系列)统一 `prepare → apply`:
|
|
63
|
+
|
|
64
|
+
- `prepare`:只读校验(成员解析、源消息读取、接收人计算),返回 `summary` + `continuation`(HMAC-SHA256 签名,10 分钟有效,含 baseUrl/profile/userId 指纹与 snapshot 指纹)。
|
|
65
|
+
- `apply`:必须 `confirm:true` + 有效 continuation;校验租户/账号一致(`context_mismatch`)与目标指纹(`target_changed`);执行后不确定结果返回 `partial/write_uncertain`,禁止自动重试。
|
|
66
|
+
|
|
67
|
+
会话提醒设置(`im.user.setRemind`,接口 `POST /api/em/msg/executeIm/user/setMsgRemind`)走同一确认链:`sessionType` 取 `1` 单聊会话(`toUid`+`toCid`)、`2` 群聊会话(`groupId`)、`4` 系统会话(`group`);`reminder` 取 `0` 消息接收提醒 / `1` 消息接收但不提醒(免打扰)。操作者身份由 CLI 用当前登录人填充,调用方不能自带。
|
|
68
|
+
|
|
69
|
+
## 分组速览(以 schema 为准)
|
|
70
|
+
|
|
71
|
+
| 前缀 | 覆盖 |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `im.person.*` | resolve / resolveByIds |
|
|
74
|
+
| `im.msg.sync.*` / `im.msg.top.sync` / `im.msg.read.*` | 消息拉取/置顶/阅读状态 |
|
|
75
|
+
| `im.msg.send.*` / `im.msg.withdraw` / `im.msg.top.set` | 发送/撤回/置顶(写,两段式) |
|
|
76
|
+
| `im.ding.send.*` | 必达/转必达(写,两段式) |
|
|
77
|
+
| `im.group.search/info/users/admins/exist/userExist/announce.*` | 群读 |
|
|
78
|
+
| `im.group.create/invite/kick/exit/destroy/join/modify/rename/announce.modify` | 群写(两段式) |
|
|
79
|
+
| `im.session.list` / `im.sysmsg.*` | 会话与系统消息 |
|
|
80
|
+
| `im.file.upload/preview/download` / `im.user.state` / `im.user.setRemind` / `im.i18n.labels` | 文件/状态/免打扰/翻译 |
|
|
81
|
+
|
|
82
|
+
## 平台示例
|
|
83
|
+
|
|
84
|
+
Windows PowerShell:
|
|
85
|
+
|
|
86
|
+
```powershell
|
|
87
|
+
weaver-work-cli --json im run im.msg.sync.group --input-json '{"groupId":"1788334281700000004","num":50,"latest":true}'
|
|
88
|
+
weaver-work-cli --json im run im.group.users --input-json '{"groupId":"1788334281700000004"}'
|
|
89
|
+
weaver-work-cli --json im run im.session.list --input-json '{"num":20}'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
macOS/Linux(bash/zsh):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
weaver-work-cli --json im run im.msg.sync.group --input-json '{"groupId":"1788334281700000004","num":50,"latest":true}'
|
|
96
|
+
weaver-work-cli --json im run im.group.users --input-json '{"groupId":"1788334281700000004"}'
|
|
97
|
+
weaver-work-cli --json im run im.session.list --input-json '{"num":20}'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 关联文档
|
|
101
|
+
|
|
102
|
+
- Agent 路由入口:`skills/weaver-e10-yimiaoban/SKILL.md`
|
|
103
|
+
- 条件化细节:`skills/weaver-e10-yimiaoban/references/`
|
|
104
|
+
- 源资料清单与影响索引:`skills/weaver-e10-yimiaoban/references/source-manifest.json`
|
package/docs/invoice.md
CHANGED
|
@@ -55,7 +55,7 @@ weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"s
|
|
|
55
55
|
| `invoice.upload` | 外部制品 | 固定上传 `ocr=0`,只取上传文件 ID,不做上传阶段解析 |
|
|
56
56
|
| `invoice.ocr.preview` | 上传+只读 | 固定 `flag=13`、`is_sync=1`、`is_save=1`,不保存票夹 |
|
|
57
57
|
| `invoice.validate.preview` | 外部查询 | 先取详情,固定 `flag=100`、`is_save=1`,不回写查验结果 |
|
|
58
|
-
| `invoice.import.prepare/apply` | 高风险写 | continuation 绑定本地文件 SHA-256;导入默认推荐 `validate=true`、`syncToOa=true` |
|
|
58
|
+
| `invoice.import.prepare/apply` | 高风险写 | continuation 绑定本地文件 SHA-256 或远程 URL;导入默认推荐 `validate=true`、`syncToOa=true`,`filedMap` 在 inputSchema 中保持 JSON object |
|
|
59
59
|
| `invoice.add.prepare/apply` | 高风险写 | 单张票面校验、重复检查、确认后新增并回查 |
|
|
60
60
|
| `invoice.update.prepare/apply` | 高风险写 | 基于完整详情修改白名单字段,保留附件并回查 |
|
|
61
61
|
| `invoice.download` | 本地文件写 | 先校验 `fileId` 属于目标 `fid`,拒绝覆盖 |
|
|
@@ -68,8 +68,8 @@ weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"s
|
|
|
68
68
|
| `invoice.reim.row-info` | 只读 | 使用 urlencoded 请求获取单张发票明细行预填信息 |
|
|
69
69
|
| `invoice.reim.employee-superiors` | 只读 | 获取当前人员和上级信息 |
|
|
70
70
|
| `invoice.reim.field.search` | 只读 | 搜索表单关联字段值,用于用户修正或出差客户确认 |
|
|
71
|
-
| `invoice.reim.flow.create.prepare/apply` | 高风险写 | continuation 绑定已组装报销单
|
|
72
|
-
| `invoice.reim.flow.update.prepare/apply` | 高风险写 | continuation
|
|
71
|
+
| `invoice.reim.flow.create.prepare/apply` | 高风险写 | continuation 绑定已组装报销单 JSON;`work_flow_id/mainFormId/request_name/main_fields/detail_rows` 等字段在 schema 顶层逐项暴露,确认后调用 `createFlowNew` |
|
|
72
|
+
| `invoice.reim.flow.update.prepare/apply` | 高风险写 | continuation 绑定更新报销单 JSON;确认后调用 `updateFlow` |
|
|
73
73
|
| `invoice.issuing.make.prepare/apply` | 高风险写 | 固定销方信息,确认后调用 `makeInvoice` 开票或存台账 |
|
|
74
74
|
|
|
75
75
|
共享、转让和标签仍暂不暴露给 Agent:新版源资料给出了提交接口,但还缺少稳定的接收人 `appid/cid/uid` 解析来源、标签关系查询和写后回查契约。
|
|
@@ -118,9 +118,9 @@ weaver-work-cli --json invoice run invoice.reim.flow.create.prepare --input ./re
|
|
|
118
118
|
weaver-work-cli --json invoice run invoice.issuing.make.prepare --input ./issuing.json
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
导入发票文件或远程 URL 时,面向 Agent 的正常链路是先 `invoice.ocr.preview`,再 `invoice.import.prepare` 使用 `validate=true`、`syncToOa=true`。只有用户明确要求跳过查验或离线导入时才传 `validate=false`;`validate=false` 表示跳过查验,不能描述为“查验通过”。`filedMap`、嵌套字段映射等 JSON 参数在 `--input-json` 中保持对象,CLI 只在 multipart 提交前序列化。
|
|
122
122
|
|
|
123
|
-
报销单创建和开票/存台账只接受 Agent
|
|
123
|
+
报销单创建和开票/存台账只接受 Agent 已组装好的结构化 JSON。CLI 不负责猜测事前申请匹配、出差客户或税率;这些规则在 Skill reference 中指导 Agent 组装和展示预览。报销单创建的字段必须在 operation 顶层逐项传入,不再包一层通用 `payload`。当前修正资料包没有客户档案查询或红字发票红冲接口,`invoice.customer.*` 和 `invoice.red.*` 不暴露为 operation,Agent 不能绕过 CLI 调用原始接口。写操作出现网络中断、部分成功、缺少回执 ID 或回查失败时,CLI 返回 `partial/write_uncertain`,Agent 禁止自动重复提交。
|
|
124
124
|
|
|
125
125
|
## 编辑白名单
|
|
126
126
|
|