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.
Files changed (225) hide show
  1. package/README.md +14 -9
  2. package/dist/cmd/skills/index.js +60 -0
  3. package/dist/internal/e10/auth/commands.js +44 -31
  4. package/dist/internal/e10/auth/session.js +44 -3
  5. package/dist/internal/e10/auth/xiaoe.js +363 -11
  6. package/dist/internal/e10/context.js +4 -2
  7. package/dist/internal/skills/detector.js +42 -0
  8. package/dist/internal/skills/install.js +50 -3
  9. package/dist/shortcuts/archive/render/search-format.js +12 -3
  10. package/dist/shortcuts/ebuilder-form/continuation.js +70 -0
  11. package/dist/shortcuts/ebuilder-form/errors.js +54 -0
  12. package/dist/shortcuts/ebuilder-form/host.js +1238 -0
  13. package/dist/shortcuts/ebuilder-form/index.js +108 -0
  14. package/dist/shortcuts/ebuilder-form/manifest.js +347 -0
  15. package/dist/shortcuts/ebuilder-form/operations/read.js +157 -0
  16. package/dist/shortcuts/ebuilder-form/operations/registry.js +56 -0
  17. package/dist/shortcuts/ebuilder-form/operations/shared.js +132 -0
  18. package/dist/shortcuts/ebuilder-form/operations/types.js +19 -0
  19. package/dist/shortcuts/ebuilder-form/operations/write.js +277 -0
  20. package/dist/shortcuts/ebuilder-form/operations.js +8 -0
  21. package/dist/shortcuts/ehr/operations/salary.js +2 -140
  22. package/dist/shortcuts/im/continuation.js +70 -0
  23. package/dist/shortcuts/{yimiaoban → im}/errors.js +14 -14
  24. package/dist/shortcuts/{yimiaoban → im}/host.js +26 -26
  25. package/dist/shortcuts/{yimiaoban → im}/index.js +42 -42
  26. package/dist/shortcuts/{yimiaoban → im}/manifest.js +7 -6
  27. package/dist/shortcuts/{yimiaoban → im}/operations/file-user.js +54 -41
  28. package/dist/shortcuts/{yimiaoban → im}/operations/group-read.js +46 -44
  29. package/dist/shortcuts/{yimiaoban → im}/operations/group-write.js +113 -66
  30. package/dist/shortcuts/{yimiaoban → im}/operations/msg-sync.js +164 -141
  31. package/dist/shortcuts/{yimiaoban → im}/operations/msg-write.js +47 -47
  32. package/dist/shortcuts/{yimiaoban → im}/operations/person.js +10 -10
  33. package/dist/shortcuts/{yimiaoban → im}/operations/registry.js +10 -8
  34. package/dist/shortcuts/{yimiaoban → im}/operations/session.js +82 -83
  35. package/dist/shortcuts/im/operations/shared.js +442 -0
  36. package/dist/shortcuts/{yimiaoban → im}/operations/types.js +1 -1
  37. package/dist/shortcuts/im/operations/user-remind.js +201 -0
  38. package/dist/shortcuts/{yimiaoban → im}/operations/write-util.js +7 -7
  39. package/dist/shortcuts/{yimiaoban → im}/operations.js +3 -3
  40. package/dist/shortcuts/index.js +10 -2
  41. package/dist/shortcuts/invoice/manifest.js +113 -10
  42. package/dist/shortcuts/invoice/operations/import.js +39 -14
  43. package/dist/shortcuts/invoice/operations/reim.js +38 -18
  44. package/dist/shortcuts/invoice/operations/shared.js +35 -6
  45. package/dist/shortcuts/jiuchuanhui/manifest.js +3 -3
  46. package/dist/shortcuts/jiuchuanhui/operations/registry.js +2 -2
  47. package/dist/shortcuts/{yimiaoban → okr}/continuation.js +10 -10
  48. package/dist/shortcuts/okr/errors.js +70 -0
  49. package/dist/shortcuts/okr/host.js +169 -0
  50. package/dist/shortcuts/okr/index.js +155 -0
  51. package/dist/shortcuts/okr/manifest.js +70 -0
  52. package/dist/shortcuts/okr/operations/link.js +305 -0
  53. package/dist/shortcuts/okr/operations/read.js +481 -0
  54. package/dist/shortcuts/okr/operations/registry.js +31 -0
  55. package/dist/shortcuts/okr/operations/shared.js +381 -0
  56. package/dist/shortcuts/okr/operations/types.js +88 -0
  57. package/dist/shortcuts/okr/operations/write.js +838 -0
  58. package/dist/shortcuts/okr/operations.js +8 -0
  59. package/dist/shortcuts/project/continuation.js +70 -0
  60. package/dist/shortcuts/project/errors.js +53 -0
  61. package/dist/shortcuts/project/host.js +160 -0
  62. package/dist/shortcuts/project/index.js +106 -0
  63. package/dist/shortcuts/project/manifest.js +36 -0
  64. package/dist/shortcuts/project/operations/read.js +551 -0
  65. package/dist/shortcuts/project/operations/registry.js +31 -0
  66. package/dist/shortcuts/project/operations/shared.js +68 -0
  67. package/dist/shortcuts/project/operations/types.js +39 -0
  68. package/dist/shortcuts/project/operations/write.js +266 -0
  69. package/dist/shortcuts/project/operations.js +8 -0
  70. package/dist/shortcuts/workflow/continuation.js +508 -0
  71. package/dist/shortcuts/workflow/endpoints.js +149 -0
  72. package/dist/shortcuts/workflow/errors.js +112 -0
  73. package/dist/shortcuts/workflow/host.js +224 -0
  74. package/dist/shortcuts/workflow/index.js +116 -0
  75. package/dist/shortcuts/workflow/manifest.js +30 -0
  76. package/dist/shortcuts/workflow/operations/form.js +4159 -0
  77. package/dist/shortcuts/workflow/operations/read.js +3778 -0
  78. package/dist/shortcuts/workflow/operations/registry.js +33 -0
  79. package/dist/shortcuts/workflow/operations/shared.js +167 -0
  80. package/dist/shortcuts/workflow/operations/types.js +44 -0
  81. package/dist/shortcuts/workflow/operations/write.js +1991 -0
  82. package/dist/shortcuts/workflow/operations.js +119 -0
  83. package/dist/shortcuts/workflow/state.js +182 -0
  84. package/docs/SKILL.md +5 -3
  85. package/docs/_catalog.md +10 -1
  86. package/docs/agent-invoice.md +2 -2
  87. package/docs/agent-skill-install.md +2 -2
  88. package/docs/e10-auth.md +3 -1
  89. package/docs/ebuilder-form.md +38 -0
  90. package/docs/im.md +104 -0
  91. package/docs/invoice.md +5 -5
  92. package/docs/okr.md +122 -0
  93. package/docs/operation-manual.md +10 -7
  94. package/docs/project.md +69 -0
  95. package/docs/skill-review-2026-09-19.md +68 -0
  96. package/package.json +3 -2
  97. package/scripts/package-skill.mjs +38 -11
  98. package/scripts/sync-connector-skills.mjs +172 -0
  99. package/skill-template/business-info.json +357 -16
  100. package/skill-template/domains/ebuilder-form.md +5 -0
  101. package/skill-template/domains/okr.md +18 -0
  102. package/skill-template/domains/shijingran.md +3 -0
  103. package/skill-template/domains/skill-maker.md +4 -4
  104. package/skill-template/domains/workflow.md +22 -0
  105. package/skill-template/domains/yepiaotong.md +4 -2
  106. package/skill-template/domains/yimiaoban.md +13 -10
  107. package/skill-template/product.json +5 -0
  108. package/skill-template/skill-template.md +1 -0
  109. package/skills/weaver-e10-calendar/SKILL.md +5 -1
  110. package/skills/weaver-e10-calendar/references/calendar-query.md +7 -0
  111. package/skills/weaver-e10-calendar/references/source-manifest.json +314 -32
  112. package/skills/weaver-e10-ebuilder-form/SKILL.md +123 -0
  113. package/skills/weaver-e10-ebuilder-form/references/context-routing.md +90 -0
  114. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +86 -0
  115. package/skills/weaver-e10-ebuilder-form/references/disabled-capabilities.md +50 -0
  116. package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +100 -0
  117. package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +91 -0
  118. package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +74 -0
  119. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +86 -0
  120. package/skills/weaver-e10-ebuilder-form/references/source-manifest.json +107 -0
  121. package/skills/weaver-e10-esb/SKILL.md +1 -1
  122. package/skills/weaver-e10-esb/references/source-manifest.json +15 -14
  123. package/skills/weaver-e10-hrm/SKILL.md +1 -1
  124. package/skills/weaver-e10-hrm/references/source-manifest.json +357 -38
  125. package/skills/weaver-e10-jiuchuanhui/SKILL.md +22 -4
  126. package/skills/weaver-e10-jiuchuanhui/references/clue.md +4 -2
  127. package/skills/weaver-e10-jiuchuanhui/references/contact.md +1 -1
  128. package/skills/weaver-e10-jiuchuanhui/references/customer.md +3 -3
  129. package/skills/weaver-e10-jiuchuanhui/references/disabled-capabilities.md +1 -1
  130. package/skills/weaver-e10-jiuchuanhui/references/discovery-config.md +10 -10
  131. package/skills/weaver-e10-jiuchuanhui/references/general-helpers.md +3 -3
  132. package/skills/weaver-e10-jiuchuanhui/references/sale.md +7 -7
  133. package/skills/weaver-e10-jiuchuanhui/references/source-manifest.json +3 -3
  134. package/skills/weaver-e10-jucailin/SKILL.md +2 -2
  135. package/skills/weaver-e10-mail/SKILL.md +22 -6
  136. package/skills/weaver-e10-meeting/SKILL.md +22 -1
  137. package/skills/weaver-e10-okr/SKILL.md +139 -0
  138. package/skills/weaver-e10-okr/references/okr-align.md +59 -0
  139. package/skills/weaver-e10-okr/references/okr-keyresult.md +68 -0
  140. package/skills/weaver-e10-okr/references/okr-link-routing.md +67 -0
  141. package/skills/weaver-e10-okr/references/okr-query.md +105 -0
  142. package/skills/weaver-e10-okr/references/okr-write.md +94 -0
  143. package/skills/weaver-e10-okr/references/source-manifest.json +672 -0
  144. package/skills/weaver-e10-plan/SKILL.md +3 -3
  145. package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
  146. package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
  147. package/skills/weaver-e10-qiyecheng/SKILL.md +21 -1
  148. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +17 -17
  149. package/skills/weaver-e10-shared/SKILL.md +79 -11
  150. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +41 -8
  151. package/skills/weaver-e10-shared/references/non-interactive-environment.md +78 -0
  152. package/skills/weaver-e10-shared/references/weaver-e10-installation.md +39 -0
  153. package/skills/weaver-e10-shijingran/SKILL.md +83 -0
  154. package/skills/weaver-e10-shijingran/references/field-resolution.md +105 -0
  155. package/skills/weaver-e10-shijingran/references/operations.md +154 -0
  156. package/skills/weaver-e10-shijingran/references/source-manifest.json +1380 -0
  157. package/skills/weaver-e10-shijingran/references/write-operations.md +90 -0
  158. package/skills/weaver-e10-skill-maker/SKILL.md +26 -9
  159. package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +39 -8
  160. package/skills/weaver-e10-skill-maker/references/detector-validation.md +25 -8
  161. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +66 -5
  162. package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +86 -0
  163. package/skills/weaver-e10-skill-maker/references/source-update-detection.md +59 -5
  164. package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +16 -8
  165. package/skills/weaver-e10-wenshuding/SKILL.md +28 -4
  166. package/skills/weaver-e10-wenshuding/references/archive-search.md +14 -0
  167. package/skills/weaver-e10-wenshuding/references/source-manifest.json +27 -26
  168. package/skills/weaver-e10-workflow/SKILL.md +250 -0
  169. package/skills/weaver-e10-workflow/references/source-manifest.json +1062 -0
  170. package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +96 -0
  171. package/skills/weaver-e10-workflow/references/workflow-batch.md +275 -0
  172. package/skills/weaver-e10-workflow/references/workflow-create.md +182 -0
  173. package/skills/weaver-e10-workflow/references/workflow-edit.md +106 -0
  174. package/skills/weaver-e10-workflow/references/workflow-memory.md +165 -0
  175. package/skills/weaver-e10-workflow/references/workflow-operate.md +153 -0
  176. package/skills/weaver-e10-workflow/references/workflow-query.md +821 -0
  177. package/skills/weaver-e10-workflow/references/workflow-share.md +117 -0
  178. package/skills/weaver-e10-workflow/references/workflow-view.md +189 -0
  179. package/skills/weaver-e10-yepiaotong/SKILL.md +28 -28
  180. package/skills/weaver-e10-yepiaotong/references/invoice-disabled-capabilities.md +11 -5
  181. package/skills/weaver-e10-yepiaotong/references/invoice-import.md +14 -8
  182. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +9 -43
  183. package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +8 -0
  184. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +13 -17
  185. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +6 -7
  186. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +2 -2
  187. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +1155 -553
  188. package/skills/weaver-e10-yimiaoban/SKILL.md +56 -38
  189. package/skills/weaver-e10-yimiaoban/references/ding-write.md +8 -8
  190. package/skills/weaver-e10-yimiaoban/references/error-codes.md +16 -0
  191. package/skills/weaver-e10-yimiaoban/references/field-resolution.md +10 -10
  192. package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +12 -12
  193. package/skills/weaver-e10-yimiaoban/references/group-read.md +16 -16
  194. package/skills/weaver-e10-yimiaoban/references/group-write.md +17 -15
  195. package/skills/weaver-e10-yimiaoban/references/msg-read.md +21 -17
  196. package/skills/weaver-e10-yimiaoban/references/msg-write.md +10 -10
  197. package/skills/weaver-e10-yimiaoban/references/person.md +6 -6
  198. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +15 -11
  199. package/skills/weaver-e10-yimiaoban/references/session-sysmsg.md +11 -10
  200. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +2164 -154
  201. package/skills/weaver-e10-yimiaoban/references/user-remind.md +75 -0
  202. package/skills/weaver-e10-ziguanjia/SKILL.md +4 -2
  203. package/skills/weaver-e10-ziguanjia/references/source-manifest.json +99 -29
  204. package/tools/weaver-skill-detector-1.0.13/SKILL.md +253 -0
  205. package/tools/weaver-skill-detector-1.0.13/_meta.json +6 -0
  206. package/tools/weaver-skill-detector-1.0.13/references/checklist.md +298 -0
  207. package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +4190 -0
  208. package/dist/shortcuts/yimiaoban/operations/shared.js +0 -236
  209. package/docs/yimiaoban.md +0 -86
  210. package/skills/weaver-e10-calendar/product.json +0 -8
  211. package/skills/weaver-e10-esb/product.json +0 -8
  212. package/skills/weaver-e10-hrm/product.json +0 -8
  213. package/skills/weaver-e10-jiuchuanhui/product.json +0 -8
  214. package/skills/weaver-e10-jucailin/product.json +0 -8
  215. package/skills/weaver-e10-mail/product.json +0 -8
  216. package/skills/weaver-e10-meeting/product.json +0 -8
  217. package/skills/weaver-e10-plan/product.json +0 -8
  218. package/skills/weaver-e10-qiyecheng/product.json +0 -8
  219. package/skills/weaver-e10-skill-maker/product.json +0 -8
  220. package/skills/weaver-e10-wenshuding/product.json +0 -8
  221. package/skills/weaver-e10-yepiaotong/product.json +0 -8
  222. package/skills/weaver-e10-yepiaotong/references/invoice-red.md +0 -261
  223. package/skills/weaver-e10-yimiaoban/product.json +0 -8
  224. package/skills/weaver-e10-ziguanjia/product.json +0 -8
  225. /package/dist/shortcuts/{yimiaoban → im}/operations/msg-parse.js +0 -0
@@ -0,0 +1,39 @@
1
+ export function projectSuccess(action, data, meta) {
2
+ const payload = { ok: true, action, data };
3
+ if (meta && Object.keys(meta).length > 0)
4
+ payload.meta = meta;
5
+ return payload;
6
+ }
7
+ export function schemaOf(properties, options = {}) {
8
+ return {
9
+ type: 'object',
10
+ additionalProperties: false,
11
+ properties,
12
+ ...(options.required?.length ? { required: options.required } : {}),
13
+ ...(options.oneOf?.length ? { oneOf: options.oneOf } : {}),
14
+ ...(options.anyOf?.length ? { anyOf: options.anyOf } : {}),
15
+ ...(options.description ? { description: options.description } : {}),
16
+ };
17
+ }
18
+ export const SCHEMA_ID_STRING = { type: 'string', minLength: 1, pattern: '^\\d+$' };
19
+ export const SCHEMA_PAGE_NO = { type: 'integer', minimum: 1, default: 1 };
20
+ export const SCHEMA_PAGE_SIZE = { type: 'integer', minimum: 1, maximum: 1000, default: 10 };
21
+ export const SCHEMA_FILTERS = {
22
+ type: 'object',
23
+ additionalProperties: true,
24
+ description: '源接口 mainTable 过滤字段。仅传用户明确指定的字段;空字符串会被视为未指定。',
25
+ };
26
+ export const SCHEMA_FIELDS = {
27
+ type: 'object',
28
+ additionalProperties: true,
29
+ description: '源接口 mainTable 字段。字段名和取值必须先按模块 reference 完成名称到 ID 的解析。',
30
+ };
31
+ export const SCHEMA_RECORDS = {
32
+ type: 'array',
33
+ minItems: 1,
34
+ maxItems: 100,
35
+ items: SCHEMA_FIELDS,
36
+ description: '待写入记录,最多 100 条,总大小不得超过 10M。',
37
+ };
38
+ export const SCHEMA_CONFIRM = { const: true, description: '必须为 true,表示用户已明确确认本次写入。' };
39
+ export const SCHEMA_CONTINUATION = { type: 'string', minLength: 1, description: 'prepare 返回的 continuation,必须原样传入。' };
@@ -0,0 +1,266 @@
1
+ import { projectPartialError, projectValidationError } from '../errors.js';
2
+ import { assertDatajsonSuccess } from '../host.js';
3
+ import { SCHEMA_CONFIRM, SCHEMA_CONTINUATION, SCHEMA_FIELDS, SCHEMA_ID_STRING, SCHEMA_RECORDS, projectSuccess, schemaOf, } from './types.js';
4
+ import { asObject, idString, operatorId, stableFingerprint } from './shared.js';
5
+ const WRITE_TARGETS = {
6
+ taskCreate: { entity: 'task', action: 'create', listPath: '', detailPath: '/api/ebuilder/form/formdata/v2/getFormDataByPk/queryTaskDetail', writePath: '/api/ebuilder/form/formdata/v2/saveFormData/createTask' },
7
+ taskUpdate: { entity: 'task', action: 'update', listPath: '', detailPath: '/api/ebuilder/form/formdata/v2/getFormDataByPk/queryTaskDetail', writePath: '/api/ebuilder/form/formdata/v2/updateFormData/updateTask' },
8
+ taskDelete: { entity: 'task', action: 'delete', listPath: '', detailPath: '/api/ebuilder/form/formdata/v2/getFormDataByPk/queryTaskDetail', writePath: '/api/ebuilder/form/formdata/v2/deleteFormData/deleteTask' },
9
+ projectCreate: { entity: 'project', action: 'create', listPath: '', detailPath: '/api/ebuilder/form/formdata/v2/getFormDataByPk/queryProjDetail', writePath: '/api/ebuilder/form/formdata/v2/saveFormData/createProject' },
10
+ projectUpdate: { entity: 'project', action: 'update', listPath: '', detailPath: '/api/ebuilder/form/formdata/v2/getFormDataByPk/queryProjDetail', writePath: '/api/ebuilder/form/formdata/v2/updateFormData/updateProject' },
11
+ projectDelete: { entity: 'project', action: 'delete', listPath: '', detailPath: '/api/ebuilder/form/formdata/v2/getFormDataByPk/queryProjDetail', writePath: '/api/ebuilder/form/formdata/v2/deleteFormData/deleteProject' },
12
+ };
13
+ function resolveManager(value, operator) {
14
+ return value === undefined || value === null || value === '' || value === '@me' ? operator : value;
15
+ }
16
+ function records(value) {
17
+ if (!Array.isArray(value) || value.length < 1 || value.length > 100) {
18
+ throw projectValidationError('records_invalid', 'records 必须是 1-100 条记录数组');
19
+ }
20
+ return value.map((item, index) => {
21
+ const record = asObject(item, `records[${index}]`);
22
+ if (Object.keys(record).length === 0) {
23
+ throw projectValidationError('records_invalid', `records[${index}] 不能为空对象`);
24
+ }
25
+ return record;
26
+ });
27
+ }
28
+ async function detail(host, target, id, operation) {
29
+ const response = await host.request({
30
+ method: 'POST',
31
+ path: target.detailPath,
32
+ body: {
33
+ datajson: JSON.stringify({
34
+ mainTable: { id },
35
+ header: { operator: await operatorId(host) },
36
+ }),
37
+ },
38
+ operation,
39
+ });
40
+ assertDatajsonSuccess(response, operation);
41
+ return response?.datajson ?? null;
42
+ }
43
+ async function sendWrite(host, operation, path, datajsonObject) {
44
+ let response;
45
+ try {
46
+ response = await host.request({
47
+ method: 'POST',
48
+ path,
49
+ body: { datajson: datajsonObject },
50
+ operation,
51
+ });
52
+ }
53
+ catch (error) {
54
+ if (error?.type === 'network') {
55
+ throw projectPartialError('写入请求已发出但结果不确定,请勿自动重试;先执行只读回查确认结果', {
56
+ operation,
57
+ path,
58
+ }, error.details);
59
+ }
60
+ throw error;
61
+ }
62
+ assertDatajsonSuccess(response, operation);
63
+ return response?.datajson ?? null;
64
+ }
65
+ async function verifySession(env, continuation) {
66
+ if (continuation.userId !== await operatorId(env.host)) {
67
+ throw projectValidationError('continuation_mismatch', 'continuation 与当前登录会话不匹配');
68
+ }
69
+ }
70
+ function createOperations(namePrefix, target) {
71
+ const prepareName = `${namePrefix}.prepare`;
72
+ const applyName = `${namePrefix}.apply`;
73
+ return [
74
+ {
75
+ name: prepareName,
76
+ resource: 'project',
77
+ method: 'write.prepare',
78
+ action: prepareName,
79
+ summary: `预览并生成${target.entity === 'task' ? '任务' : '项目'}创建写入 continuation,不发生写入`,
80
+ risk: 'read-before-write',
81
+ inputSchema: schemaOf({ records: SCHEMA_RECORDS }, { required: ['records'] }),
82
+ handler: async (args, env) => {
83
+ const operator = await operatorId(env.host);
84
+ const datajson = {
85
+ header: { operator },
86
+ operationinfo: {},
87
+ datas: records(args.records).map((mainTable) => ({
88
+ mainTable: { ...mainTable, manager: resolveManager(mainTable.manager, operator) },
89
+ })),
90
+ };
91
+ const continuation = await env.continuation.issue({
92
+ operation: applyName,
93
+ userId: datajson.header.operator,
94
+ datajson,
95
+ });
96
+ return projectSuccess(prepareName, {
97
+ continuation,
98
+ request: { datajson },
99
+ recordCount: datajson.datas.length,
100
+ }, { requiresConfirmation: true });
101
+ },
102
+ },
103
+ {
104
+ name: applyName,
105
+ resource: 'project',
106
+ method: 'write.apply',
107
+ action: applyName,
108
+ summary: `经用户确认后创建${target.entity === 'task' ? '任务' : '项目'}`,
109
+ risk: 'high-risk-write',
110
+ requiresConfirmation: true,
111
+ inputSchema: schemaOf({
112
+ continuation: SCHEMA_CONTINUATION,
113
+ confirm: SCHEMA_CONFIRM,
114
+ }, { required: ['continuation', 'confirm'] }),
115
+ handler: async (args, env) => {
116
+ if (args.confirm !== true)
117
+ throw projectValidationError('confirm_required', 'confirm 必须为 true');
118
+ const continuation = await env.continuation.verify(String(args.continuation), applyName);
119
+ await verifySession(env, continuation);
120
+ const datajson = asObject(continuation.datajson, 'continuation.datajson');
121
+ const response = await sendWrite(env.host, applyName, target.writePath, datajson);
122
+ return projectSuccess(applyName, response, { targetType: target.entity, writeAction: 'create' });
123
+ },
124
+ },
125
+ ];
126
+ }
127
+ function updateOperations(namePrefix, target) {
128
+ const prepareName = `${namePrefix}.prepare`;
129
+ const applyName = `${namePrefix}.apply`;
130
+ return [
131
+ {
132
+ name: prepareName,
133
+ resource: 'project',
134
+ method: 'write.prepare',
135
+ action: prepareName,
136
+ summary: `回查并预览${target.entity === 'task' ? '任务' : '项目'}更新,生成 continuation,不发生写入`,
137
+ risk: 'read-before-write',
138
+ inputSchema: schemaOf({ id: SCHEMA_ID_STRING, fields: SCHEMA_FIELDS }, { required: ['id', 'fields'] }),
139
+ handler: async (args, env) => {
140
+ const id = idString(args.id, 'id');
141
+ const fields = asObject(args.fields, 'fields');
142
+ if (Object.keys(fields).length === 0) {
143
+ throw projectValidationError('fields_required', 'fields 至少包含一个要更新的字段');
144
+ }
145
+ const operator = await operatorId(env.host);
146
+ if (fields.manager === '@me')
147
+ fields.manager = operator;
148
+ const current = await detail(env.host, target, id, `${namePrefix}.prepare`);
149
+ const datajson = {
150
+ header: { operator },
151
+ operationinfo: {},
152
+ datas: [{ mainTable: { id, ...fields } }],
153
+ };
154
+ const continuation = await env.continuation.issue({
155
+ operation: applyName,
156
+ userId: datajson.header.operator,
157
+ id,
158
+ fingerprint: stableFingerprint(current),
159
+ datajson,
160
+ });
161
+ return projectSuccess(prepareName, {
162
+ continuation,
163
+ request: { datajson },
164
+ current,
165
+ }, { requiresConfirmation: true, id });
166
+ },
167
+ },
168
+ {
169
+ name: applyName,
170
+ resource: 'project',
171
+ method: 'write.apply',
172
+ action: applyName,
173
+ summary: `经用户确认并确认目标未变化后更新${target.entity === 'task' ? '任务' : '项目'}`,
174
+ risk: 'high-risk-write',
175
+ requiresConfirmation: true,
176
+ inputSchema: schemaOf({
177
+ continuation: SCHEMA_CONTINUATION,
178
+ confirm: SCHEMA_CONFIRM,
179
+ }, { required: ['continuation', 'confirm'] }),
180
+ handler: async (args, env) => {
181
+ if (args.confirm !== true)
182
+ throw projectValidationError('confirm_required', 'confirm 必须为 true');
183
+ const continuation = await env.continuation.verify(String(args.continuation), applyName);
184
+ await verifySession(env, continuation);
185
+ const id = idString(continuation.id, 'continuation.id');
186
+ const current = await detail(env.host, target, id, applyName);
187
+ if (stableFingerprint(current) !== continuation.fingerprint) {
188
+ throw projectValidationError('target_changed', '目标数据在确认后已变化,请重新执行 prepare');
189
+ }
190
+ const datajson = asObject(continuation.datajson, 'continuation.datajson');
191
+ const response = await sendWrite(env.host, applyName, target.writePath, datajson);
192
+ return projectSuccess(applyName, response, { targetType: target.entity, writeAction: 'update', id });
193
+ },
194
+ },
195
+ ];
196
+ }
197
+ function deleteOperations(namePrefix, target) {
198
+ const prepareName = `${namePrefix}.prepare`;
199
+ const applyName = `${namePrefix}.apply`;
200
+ return [
201
+ {
202
+ name: prepareName,
203
+ resource: 'project',
204
+ method: 'write.prepare',
205
+ action: prepareName,
206
+ summary: `回查${target.entity === 'task' ? '任务' : '项目'}并生成不可逆删除 continuation,不发生删除`,
207
+ risk: 'read-before-write',
208
+ inputSchema: schemaOf({ id: SCHEMA_ID_STRING }, { required: ['id'] }),
209
+ handler: async (args, env) => {
210
+ const id = idString(args.id, 'id');
211
+ const current = await detail(env.host, target, id, prepareName);
212
+ const datajson = {
213
+ header: { operator: await operatorId(env.host) },
214
+ datas: [{ mainTable: { id } }],
215
+ };
216
+ const continuation = await env.continuation.issue({
217
+ operation: applyName,
218
+ userId: datajson.header.operator,
219
+ id,
220
+ fingerprint: stableFingerprint(current),
221
+ datajson,
222
+ });
223
+ return projectSuccess(prepareName, {
224
+ continuation,
225
+ request: { datajson },
226
+ current,
227
+ }, { requiresConfirmation: true, id, irreversible: true });
228
+ },
229
+ },
230
+ {
231
+ name: applyName,
232
+ resource: 'project',
233
+ method: 'write.apply',
234
+ action: applyName,
235
+ summary: `经用户确认并确认目标未变化后删除${target.entity === 'task' ? '任务' : '项目'},不可恢复`,
236
+ risk: 'high-risk-write',
237
+ requiresConfirmation: true,
238
+ inputSchema: schemaOf({
239
+ continuation: SCHEMA_CONTINUATION,
240
+ confirm: SCHEMA_CONFIRM,
241
+ }, { required: ['continuation', 'confirm'] }),
242
+ handler: async (args, env) => {
243
+ if (args.confirm !== true)
244
+ throw projectValidationError('confirm_required', 'confirm 必须为 true');
245
+ const continuation = await env.continuation.verify(String(args.continuation), applyName);
246
+ await verifySession(env, continuation);
247
+ const id = idString(continuation.id, 'continuation.id');
248
+ const current = await detail(env.host, target, id, applyName);
249
+ if (stableFingerprint(current) !== continuation.fingerprint) {
250
+ throw projectValidationError('target_changed', '目标数据在确认后已变化,请重新执行 prepare');
251
+ }
252
+ const datajson = asObject(continuation.datajson, 'continuation.datajson');
253
+ const response = await sendWrite(env.host, applyName, target.writePath, datajson);
254
+ return projectSuccess(applyName, response, { targetType: target.entity, writeAction: 'delete', id });
255
+ },
256
+ },
257
+ ];
258
+ }
259
+ export const projectWriteOperations = [
260
+ ...createOperations('project.task.create', WRITE_TARGETS.taskCreate),
261
+ ...updateOperations('project.task.update', WRITE_TARGETS.taskUpdate),
262
+ ...deleteOperations('project.task.delete', WRITE_TARGETS.taskDelete),
263
+ ...createOperations('project.project.create', WRITE_TARGETS.projectCreate),
264
+ ...updateOperations('project.project.update', WRITE_TARGETS.projectUpdate),
265
+ ...deleteOperations('project.project.delete', WRITE_TARGETS.projectDelete),
266
+ ];
@@ -0,0 +1,8 @@
1
+ import { getProjectOperation } from './operations/registry.js';
2
+ import { asObject, assertNoForbiddenKeys } from './operations/shared.js';
3
+ export async function executeProjectOperation(operation, rawInput, context) {
4
+ const definition = getProjectOperation(operation);
5
+ const input = asObject(rawInput);
6
+ assertNoForbiddenKeys(input);
7
+ return definition.handler(input, context);
8
+ }