@yijiancaotang/cli 1.0.0 → 1.1.0
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 +41 -9
- package/dist/auth.js +7 -4
- package/dist/calendar-contract.js +358 -0
- package/dist/calendar-help.js +12 -0
- package/dist/calendar.js +64 -0
- package/dist/capability-result.js +5 -0
- package/dist/cli.js +12 -3
- package/dist/command-help.js +10 -5
- package/dist/commands.js +6 -0
- package/dist/doctor.js +11 -4
- package/dist/habit-read.js +3 -1
- package/dist/habit-wire.js +36 -5
- package/dist/http.js +11 -1
- package/dist/installation.js +307 -37
- package/dist/local-commands.js +107 -14
- package/dist/local-records.js +149 -0
- package/dist/managed-skill-baseline.js +35 -0
- package/dist/missing-sections.js +1 -0
- package/dist/output.js +3 -1
- package/dist/platforms.js +51 -12
- package/dist/query-search.js +3 -2
- package/dist/reviewed-managed-bundle-baseline.js +356 -0
- package/dist/schedule-contract.js +289 -0
- package/dist/schedule-help.js +35 -0
- package/dist/schedule-start-wire.js +80 -0
- package/dist/schedule.js +70 -0
- package/dist/skill-assets.js +1 -1
- package/dist/web-citations.js +1 -1
- package/dist/write-routing.js +26 -0
- package/package.json +1 -1
- package/skills/caotang-context/SKILL.md +5 -0
- package/skills/caotang-first-connect/SKILL.md +18 -6
- package/skills/caotang-project-progress/SKILL.md +6 -2
- package/skills/caotang-save-knowledge/SKILL.md +6 -4
- package/skills/caotang-schedule/SKILL.md +54 -0
- package/skills/caotang-search/SKILL.md +11 -0
- package/skills/caotang-workday/SKILL.md +56 -9
- package/skills/manifest.json +28 -6
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
// Exact runtime bytes from reviewed CLI tgz 8ce64d4ae13656763b913da10637cd20da85b6763fb7a5c02757a1417b7f8d9b.
|
|
2
|
+
// One full-content baseline only; version/receipt/directory self-reports are not evidence.
|
|
3
|
+
export const REVIEWED_MANAGED_BUNDLE_1_1_0 = {
|
|
4
|
+
"version": "1.1.0",
|
|
5
|
+
"sha": "ed87c23c98d57cd990a5212a05788cc95136b6bc810e61f30c1fbac7026c212a",
|
|
6
|
+
"files": [
|
|
7
|
+
{
|
|
8
|
+
"path": "bin/caotang.cjs",
|
|
9
|
+
"mode": 448,
|
|
10
|
+
"bytes": 861,
|
|
11
|
+
"sha256": "b1047ea22a774718e377edcb4a18e3c16ce2b101ad40c5d39721894d652f37c5"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"path": "dist/agent-identity.js",
|
|
15
|
+
"mode": 384,
|
|
16
|
+
"bytes": 1417,
|
|
17
|
+
"sha256": "e217376060e8c5a46c6c58f596f198750c3154eca561be757fee7151e3e1c86c"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": "dist/auth.js",
|
|
21
|
+
"mode": 384,
|
|
22
|
+
"bytes": 20770,
|
|
23
|
+
"sha256": "5c0917ae4b212b47091ca205d40427f8dd580bd494ccc6b5c586177bbfded0e0"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"path": "dist/calendar-contract.js",
|
|
27
|
+
"mode": 384,
|
|
28
|
+
"bytes": 24328,
|
|
29
|
+
"sha256": "3124493cea046a0f0dc6841f52610cb4e1aae78f3375de7090e378010f953807"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"path": "dist/calendar-help.js",
|
|
33
|
+
"mode": 384,
|
|
34
|
+
"bytes": 4578,
|
|
35
|
+
"sha256": "224c5eeb5376358593e04501c4d92d39174a6ca23e1d4bc46729e8f84058c37a"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"path": "dist/calendar.js",
|
|
39
|
+
"mode": 384,
|
|
40
|
+
"bytes": 3748,
|
|
41
|
+
"sha256": "b10c9135617e9c9fe6530fef32c6679ff9e6c497967308a33ddd2013469e7a6f"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"path": "dist/capability-result.js",
|
|
45
|
+
"mode": 384,
|
|
46
|
+
"bytes": 3829,
|
|
47
|
+
"sha256": "09d398275dfeb82c18bcfa0b9abe6341607678e3248eb543d944fed390a0466d"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"path": "dist/cli.js",
|
|
51
|
+
"mode": 384,
|
|
52
|
+
"bytes": 22177,
|
|
53
|
+
"sha256": "71eff64b32306430fd9c35a2ecc633dda195eec7064c3b700822de3b76940af8"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"path": "dist/command-help.js",
|
|
57
|
+
"mode": 384,
|
|
58
|
+
"bytes": 14071,
|
|
59
|
+
"sha256": "556be79209c89eef690f18866cd27803aef671279b411f73383c115a82a41cc6"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"path": "dist/commands.js",
|
|
63
|
+
"mode": 384,
|
|
64
|
+
"bytes": 23262,
|
|
65
|
+
"sha256": "cfc95b14372a105c917b588e4574458196b58bf30967591361f8bdec0493b989"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"path": "dist/config.js",
|
|
69
|
+
"mode": 384,
|
|
70
|
+
"bytes": 1289,
|
|
71
|
+
"sha256": "7a99ac4696d06db5bcecef3a9c9e406ef079ace724101bf720bf916e319bef0a"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"path": "dist/connection-copy.js",
|
|
75
|
+
"mode": 384,
|
|
76
|
+
"bytes": 2284,
|
|
77
|
+
"sha256": "5617453b07fe39ebf1fa20a4a4f64729adbfb2f93a51f9754330b2be60bb6078"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"path": "dist/context.js",
|
|
81
|
+
"mode": 384,
|
|
82
|
+
"bytes": 1885,
|
|
83
|
+
"sha256": "6c92b7c7f7d11674bebb0f6f9981794ac64a8c94f45393a9a4e5b6e92bd87616"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"path": "dist/contracts.js",
|
|
87
|
+
"mode": 384,
|
|
88
|
+
"bytes": 11,
|
|
89
|
+
"sha256": "8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"path": "dist/create-bundle.js",
|
|
93
|
+
"mode": 384,
|
|
94
|
+
"bytes": 9646,
|
|
95
|
+
"sha256": "043713b3e9d435268634aab72dc6f8a15017b5be1ecf4760bde2d788f31e95f5"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"path": "dist/create-file-failure.js",
|
|
99
|
+
"mode": 384,
|
|
100
|
+
"bytes": 1555,
|
|
101
|
+
"sha256": "690a59a4fc47b624260d753bbf79b88ecb8a83d6ee846341e3c9133779dff045"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"path": "dist/credential-store.js",
|
|
105
|
+
"mode": 384,
|
|
106
|
+
"bytes": 27762,
|
|
107
|
+
"sha256": "2bf9b031eec6cf984af30822e5fa7b5e8f8888f58d09084e723feeaf49c291a2"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"path": "dist/doctor.js",
|
|
111
|
+
"mode": 384,
|
|
112
|
+
"bytes": 17642,
|
|
113
|
+
"sha256": "c0438daeab4483a483051f9bd94beb40d5cedd11f20155506f09bbb3d5ec00c2"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"path": "dist/errors.js",
|
|
117
|
+
"mode": 384,
|
|
118
|
+
"bytes": 17485,
|
|
119
|
+
"sha256": "0634831524769f8c348aea43f8b2b90f1e5eab74f66bdf3c0ef77057c8a3e9d7"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"path": "dist/generated/knowledge-growth.js",
|
|
123
|
+
"mode": 384,
|
|
124
|
+
"bytes": 1324,
|
|
125
|
+
"sha256": "3fefbb5bd04dfef4548b21bb91b739bbdcc4f565cfd34d8cf08bdcb598d069b9"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"path": "dist/habit-day.js",
|
|
129
|
+
"mode": 384,
|
|
130
|
+
"bytes": 2697,
|
|
131
|
+
"sha256": "23bbcd87ae6af1d874c57e5601b2ac6a6d27982f94a84490fdce0a5fb565b237"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"path": "dist/habit-read.js",
|
|
135
|
+
"mode": 384,
|
|
136
|
+
"bytes": 2134,
|
|
137
|
+
"sha256": "db69e3a7ba00887367d86e101dd451efe4b993138cee6704fb96031dcbcf965f"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"path": "dist/habit-wire.js",
|
|
141
|
+
"mode": 384,
|
|
142
|
+
"bytes": 7188,
|
|
143
|
+
"sha256": "ce414a79b8e444f97a641eb048e52397bf2d5b3e162121f2f349ebfeb0d0b8f7"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"path": "dist/http.js",
|
|
147
|
+
"mode": 384,
|
|
148
|
+
"bytes": 10029,
|
|
149
|
+
"sha256": "8bdb9bede2b928037e882a9b375d0a1959d53f599b969d83fa2081248e051f67"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"path": "dist/input-validation.js",
|
|
153
|
+
"mode": 384,
|
|
154
|
+
"bytes": 4135,
|
|
155
|
+
"sha256": "c5382d9287b1f330a5468d2c3abad33903bc560182f45d69f121a132ac15e28b"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"path": "dist/installation.js",
|
|
159
|
+
"mode": 384,
|
|
160
|
+
"bytes": 39276,
|
|
161
|
+
"sha256": "4e371462d83abc0e440906cdc802a3a3713e6f62cf59c3e2e0519492a5cd08db"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"path": "dist/knowledge-growth.js",
|
|
165
|
+
"mode": 384,
|
|
166
|
+
"bytes": 4257,
|
|
167
|
+
"sha256": "18187fb1100faf0d79e32fc1bf0455ad35d59ffe94d35040b9a765d89674c12b"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"path": "dist/local-commands.js",
|
|
171
|
+
"mode": 384,
|
|
172
|
+
"bytes": 17710,
|
|
173
|
+
"sha256": "0ddde63bb06d84acce0072be202384e550c070cfddb7befb7477eb3fd6ad1e36"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"path": "dist/local-lock.js",
|
|
177
|
+
"mode": 384,
|
|
178
|
+
"bytes": 9362,
|
|
179
|
+
"sha256": "3ee54676ebb20a177bb22726ff6d08d329a511b25500e59cd969e5a27c5e417a"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"path": "dist/local-records.js",
|
|
183
|
+
"mode": 384,
|
|
184
|
+
"bytes": 8122,
|
|
185
|
+
"sha256": "a2304b1ad0ddc3107265a61faf3935b3a3f14436be275906dd9a306338fa6b77"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"path": "dist/local-types.js",
|
|
189
|
+
"mode": 384,
|
|
190
|
+
"bytes": 358,
|
|
191
|
+
"sha256": "d43abb2a72ecb33f501e5c16bf624fd971f33f3541153937060f4320d54d956f"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"path": "dist/managed-skill-baseline.js",
|
|
195
|
+
"mode": 384,
|
|
196
|
+
"bytes": 2142,
|
|
197
|
+
"sha256": "63f869e057d2bc41405facc9a4883c136955255bef2abc2c443c85e204ed8d97"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"path": "dist/missing-sections.js",
|
|
201
|
+
"mode": 384,
|
|
202
|
+
"bytes": 4216,
|
|
203
|
+
"sha256": "9ce6d37478ebc813ce9d2ee1a8372bdc8170a7867274a7bf5f817052972b88b7"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"path": "dist/onboarding.js",
|
|
207
|
+
"mode": 384,
|
|
208
|
+
"bytes": 2768,
|
|
209
|
+
"sha256": "f48693b69edadba01dc34fd4949bcd617bc3130451c4ea6c158860bc85e2aaaf"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"path": "dist/output.js",
|
|
213
|
+
"mode": 384,
|
|
214
|
+
"bytes": 3970,
|
|
215
|
+
"sha256": "0f8cdd45522f2990d77d5078820d7a6897a4e4e1c969fc729480ce14017276fc"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"path": "dist/pending-requests.js",
|
|
219
|
+
"mode": 384,
|
|
220
|
+
"bytes": 3697,
|
|
221
|
+
"sha256": "29ba9aa0af625fde56dd7d3da708d2a283d2a0aef40118f1ce16304e9ee01195"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"path": "dist/platforms.js",
|
|
225
|
+
"mode": 384,
|
|
226
|
+
"bytes": 10224,
|
|
227
|
+
"sha256": "5660acdd8f1471c7ff2df19e02ce23ebfbb5124846b2e04882a1670158ad7392"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"path": "dist/query-daily.js",
|
|
231
|
+
"mode": 384,
|
|
232
|
+
"bytes": 6188,
|
|
233
|
+
"sha256": "5648b0322f72c8296df9d3beac7a788cd94f7af9c902c46539a9ae4f36834b67"
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"path": "dist/query-search.js",
|
|
237
|
+
"mode": 384,
|
|
238
|
+
"bytes": 4015,
|
|
239
|
+
"sha256": "eeb4b76665489edd57e2ab757ce585cdf91941c08cbc088758ed88b35f130332"
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"path": "dist/query-validation.js",
|
|
243
|
+
"mode": 384,
|
|
244
|
+
"bytes": 3439,
|
|
245
|
+
"sha256": "0aa2123725ca27720eb86cfbe59cb1f6771ee2db2991150eae783db9c4c9cd79"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"path": "dist/schedule-contract.js",
|
|
249
|
+
"mode": 384,
|
|
250
|
+
"bytes": 16879,
|
|
251
|
+
"sha256": "d5f5a43e4ac33274ddf275d00dd5b3696fe125c773e117979643830b5294da6e"
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"path": "dist/schedule-help.js",
|
|
255
|
+
"mode": 384,
|
|
256
|
+
"bytes": 4821,
|
|
257
|
+
"sha256": "cc86c38e16e8660fca343dc95d2dfc9af525b41296c67db2ccd1b969f7da82f4"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"path": "dist/schedule-start-wire.js",
|
|
261
|
+
"mode": 384,
|
|
262
|
+
"bytes": 3634,
|
|
263
|
+
"sha256": "6b6b6843dd41053c3b334c0785100de90ef3f4e5af130fb839911897100161ce"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"path": "dist/schedule.js",
|
|
267
|
+
"mode": 384,
|
|
268
|
+
"bytes": 4030,
|
|
269
|
+
"sha256": "ee234a5744aa0cef9afcbd0b2ac9cb4336e7226069a148c39858fa439a25202e"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"path": "dist/skill-assets.js",
|
|
273
|
+
"mode": 384,
|
|
274
|
+
"bytes": 6960,
|
|
275
|
+
"sha256": "962171172db20f2ecc1cc0eaa9863e2f27e414b7cf1399fb224cade57b09613d"
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"path": "dist/upload.js",
|
|
279
|
+
"mode": 384,
|
|
280
|
+
"bytes": 7625,
|
|
281
|
+
"sha256": "59c862ea1d31f90e48a746f8d26fb0903c8bedd3af0f0b4624c744280359afff"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"path": "dist/web-citations.js",
|
|
285
|
+
"mode": 384,
|
|
286
|
+
"bytes": 4509,
|
|
287
|
+
"sha256": "58cd8275f992f88a030f30239bb78eb301948e40e24d9c2c0e9b4fe27aa3d00a"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"path": "dist/write-permissions.js",
|
|
291
|
+
"mode": 384,
|
|
292
|
+
"bytes": 2497,
|
|
293
|
+
"sha256": "ecaf3009ee061d246d85aef69036815c5ae778617578be7e4f3513426045cc1b"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"path": "dist/write-routing.js",
|
|
297
|
+
"mode": 384,
|
|
298
|
+
"bytes": 2629,
|
|
299
|
+
"sha256": "4acff0b485ee0c8a394adf5142122f82ca14c6d03fdaf81fd7c46aa80fe8f39c"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"path": "package.json",
|
|
303
|
+
"mode": 384,
|
|
304
|
+
"bytes": 140,
|
|
305
|
+
"sha256": "ecddc8f82d17dec46897ed0d324b24f5465451dc413a90b1e0ba7a8b0e259889"
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
"path": "skills/caotang-context/SKILL.md",
|
|
309
|
+
"mode": 384,
|
|
310
|
+
"bytes": 7260,
|
|
311
|
+
"sha256": "0580c8513de3f91c9a12cf94290200e90d1a0ee5dc2610e0654ccc3146832732"
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
"path": "skills/caotang-first-connect/SKILL.md",
|
|
315
|
+
"mode": 384,
|
|
316
|
+
"bytes": 11277,
|
|
317
|
+
"sha256": "cbbe660f4a058214ff6fbc320f999f7342457384ba9a38ce493f1dbc8eda7692"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"path": "skills/caotang-project-progress/SKILL.md",
|
|
321
|
+
"mode": 384,
|
|
322
|
+
"bytes": 9829,
|
|
323
|
+
"sha256": "1a5a2c4849aca52237a1e18f6c70bbddd2a9815260c87ce6fb26872736120c94"
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"path": "skills/caotang-save-knowledge/SKILL.md",
|
|
327
|
+
"mode": 384,
|
|
328
|
+
"bytes": 6779,
|
|
329
|
+
"sha256": "002dd420b32851b1b0a97175baaf270c44c327900c1f9ae40197673d415e10fa"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"path": "skills/caotang-schedule/SKILL.md",
|
|
333
|
+
"mode": 384,
|
|
334
|
+
"bytes": 5365,
|
|
335
|
+
"sha256": "e2f3689412b39cc1475ba56d6e6082380ed9bbc195f6fb44ed9b5e9992a787a4"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"path": "skills/caotang-search/SKILL.md",
|
|
339
|
+
"mode": 384,
|
|
340
|
+
"bytes": 9895,
|
|
341
|
+
"sha256": "d69f9e6dae707c163139ddb64eef787bd9ae1d3ca0328079353f206085edf0a2"
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
"path": "skills/caotang-workday/SKILL.md",
|
|
345
|
+
"mode": 384,
|
|
346
|
+
"bytes": 7233,
|
|
347
|
+
"sha256": "b20b3592e2d9d61d1d42638b51fdcd34bbe113b6655ec353e342e45aa7dd65cb"
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"path": "skills/manifest.json",
|
|
351
|
+
"mode": 384,
|
|
352
|
+
"bytes": 1438,
|
|
353
|
+
"sha256": "9bdbf8e82510fd51036704e8de6830a4d53bc8a6d97aad3c3a20c883c50c9939"
|
|
354
|
+
}
|
|
355
|
+
]
|
|
356
|
+
};
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
export const scheduleRoot = "/api/v1/agent";
|
|
2
|
+
export const scheduleKeyPattern = /^[A-Za-z0-9._:-]{16,128}(?![\s\S])/;
|
|
3
|
+
export const scheduleUUID = (value) => typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?![\s\S])/i.test(value);
|
|
4
|
+
const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5
|
+
const scalarText = (value) => ![...value].some(char => { const n = char.codePointAt(0); return n >= 0xd800 && n <= 0xdfff; });
|
|
6
|
+
const trim = (value) => value.replace(/^\p{White_Space}+|\p{White_Space}+$/gu, "");
|
|
7
|
+
export const validScheduleRevision = (value) => typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
8
|
+
export function validScheduleDate(value) {
|
|
9
|
+
if (typeof value !== "string" || !/^(?!0000)\d{4}-\d{2}-\d{2}(?![\s\S])/.test(value))
|
|
10
|
+
return false;
|
|
11
|
+
const date = new Date(value + "T00:00:00Z");
|
|
12
|
+
return Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === value;
|
|
13
|
+
}
|
|
14
|
+
export function validScheduleTime(value) {
|
|
15
|
+
if (typeof value !== "string" || !/^(?!0000)\d{4}-\d{2}-\d{2}T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d{1,9})?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)(?![\s\S])/.test(value))
|
|
16
|
+
return false;
|
|
17
|
+
return validScheduleDate(value.slice(0, 10)) && Number.isFinite(Date.parse(value));
|
|
18
|
+
}
|
|
19
|
+
export class ScheduleProblem extends Error {
|
|
20
|
+
code;
|
|
21
|
+
humanMessage;
|
|
22
|
+
nextAction;
|
|
23
|
+
exitCode;
|
|
24
|
+
details;
|
|
25
|
+
constructor(code, humanMessage, nextAction, exitCode = 2, details = {}) {
|
|
26
|
+
super(JSON.stringify({ code, message: humanMessage, next_action: nextAction, ...details }));
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.humanMessage = humanMessage;
|
|
29
|
+
this.nextAction = nextAction;
|
|
30
|
+
this.exitCode = exitCode;
|
|
31
|
+
this.details = details;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function scheduleInvalid() {
|
|
35
|
+
throw new ScheduleProblem("invalid_arguments", "日程命令或参数无效。", "请查看本命令帮助,只提交本人确认的字段;日期用 YYYY-MM-DD,精确时间用带时区偏移的 RFC3339。");
|
|
36
|
+
}
|
|
37
|
+
export function scheduleKey(value) {
|
|
38
|
+
if (typeof value !== "string" || !scheduleKeyPattern.test(value))
|
|
39
|
+
return scheduleInvalid();
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
export function scheduleID(value) {
|
|
43
|
+
return scheduleUUID(value) ? value : scheduleInvalid();
|
|
44
|
+
}
|
|
45
|
+
export function scheduleQuery(input) {
|
|
46
|
+
const allowed = ["view", "status", "group_by", "project_id", "q", "start_date", "end_date", "limit", "offset"];
|
|
47
|
+
const out = {};
|
|
48
|
+
for (const [name, value] of Object.entries(input)) {
|
|
49
|
+
if (!allowed.includes(name))
|
|
50
|
+
scheduleInvalid();
|
|
51
|
+
if (value === undefined)
|
|
52
|
+
continue;
|
|
53
|
+
if (name === "limit" || name === "offset") {
|
|
54
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < (name === "limit" ? 1 : 0) || (name === "limit" && value > 100))
|
|
55
|
+
scheduleInvalid();
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
if (typeof value !== "string" || value === "" || !scalarText(value) || value.includes("\0"))
|
|
59
|
+
scheduleInvalid();
|
|
60
|
+
if (name === "view" && !["pending", "workbench", "recent_completed", "history"].includes(value))
|
|
61
|
+
scheduleInvalid();
|
|
62
|
+
if (name === "status" && (!["all", "completed", "cancelled"].includes(value) || input.view !== "history"))
|
|
63
|
+
scheduleInvalid();
|
|
64
|
+
if (name === "group_by" && !["date", "project"].includes(value))
|
|
65
|
+
scheduleInvalid();
|
|
66
|
+
if (name === "project_id" && value !== "none" && !scheduleUUID(value))
|
|
67
|
+
scheduleInvalid();
|
|
68
|
+
if ((name === "start_date" || name === "end_date") && !validScheduleDate(value))
|
|
69
|
+
scheduleInvalid();
|
|
70
|
+
if (name === "q" && [...trim(value)].length > 200)
|
|
71
|
+
scheduleInvalid();
|
|
72
|
+
}
|
|
73
|
+
out[name] = value;
|
|
74
|
+
}
|
|
75
|
+
if (typeof input.start_date === "string" && typeof input.end_date === "string" && input.start_date > input.end_date)
|
|
76
|
+
scheduleInvalid();
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
export function scheduleBody(operation, value) {
|
|
80
|
+
if (!record(value))
|
|
81
|
+
return scheduleInvalid();
|
|
82
|
+
const fields = operation === "create" || operation === "update" ? ["title", "due_date", "due_at", "project_id", "confirmed"] : ["confirmed"];
|
|
83
|
+
if (Object.keys(value).some(name => !fields.includes(name)) || value.confirmed !== true)
|
|
84
|
+
return scheduleInvalid();
|
|
85
|
+
if (operation === "create" && !Object.hasOwn(value, "title"))
|
|
86
|
+
scheduleInvalid();
|
|
87
|
+
if (operation === "update" && !["title", "due_date", "due_at", "project_id"].some(name => Object.hasOwn(value, name)))
|
|
88
|
+
scheduleInvalid();
|
|
89
|
+
const out = { ...value };
|
|
90
|
+
if (Object.hasOwn(value, "title")) {
|
|
91
|
+
if (typeof value.title !== "string" || !scalarText(value.title))
|
|
92
|
+
scheduleInvalid();
|
|
93
|
+
const title = trim(value.title);
|
|
94
|
+
if (!title || [...title].length > 200 || /[\p{Cc}\u2028\u2029]/u.test(title))
|
|
95
|
+
scheduleInvalid();
|
|
96
|
+
out.title = title;
|
|
97
|
+
}
|
|
98
|
+
for (const name of ["due_date", "due_at", "project_id"]) {
|
|
99
|
+
if (!Object.hasOwn(value, name))
|
|
100
|
+
continue;
|
|
101
|
+
const item = value[name];
|
|
102
|
+
if (item === null || item === "")
|
|
103
|
+
continue;
|
|
104
|
+
if (name === "due_date" ? !validScheduleDate(item) : name === "due_at" ? !validScheduleTime(item) : !scheduleUUID(item))
|
|
105
|
+
scheduleInvalid();
|
|
106
|
+
}
|
|
107
|
+
if (value.due_date && value.due_at)
|
|
108
|
+
scheduleInvalid();
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
export function scheduleUnknown(key, status) {
|
|
112
|
+
return new ScheduleProblem("write_outcome_unknown", "日程写入结果未确认,不能视为成功。", "保留原幂等键,用 schedule status 或 get_schedule_write_status 核对同一连接的回执;不要换键、自动重试或执行依赖写入。", 6, { write_status: "unknown", idempotency_key: key, ...(status === undefined ? {} : { http_status: status }) });
|
|
113
|
+
}
|
|
114
|
+
export function scheduleFailure(status, body, capabilities, key) {
|
|
115
|
+
if (key && (status === 202 || status >= 500))
|
|
116
|
+
return scheduleUnknown(key, status);
|
|
117
|
+
const raw = record(body) ? body.code ?? body.error : undefined;
|
|
118
|
+
const consistent = record(body) && (body.code === undefined || body.code === raw) && (body.error === undefined || body.error === raw);
|
|
119
|
+
const codes = {
|
|
120
|
+
400: ["invalid_schedule_query", "invalid_schedule_id", "invalid_idempotency_key", "invalid_schedule_revision", "invalid_schedule_input", "schedule_confirmation_required"],
|
|
121
|
+
401: ["not_authenticated"], 403: ["token_scope_insufficient", "capability_disabled", "second_confirmation_required", "legal_consent_required", "account_unavailable"],
|
|
122
|
+
404: ["schedule_not_found"], 409: ["schedule_revision_conflict", "idempotency_conflict", "schedule_closed", "schedule_undo_expired"],
|
|
123
|
+
415: ["invalid_content_type"], 429: ["rate_limited"], 503: ["schedule_unavailable"]
|
|
124
|
+
};
|
|
125
|
+
const code = consistent && typeof raw === "string" && codes[status]?.includes(raw) ? raw : "request_rejected";
|
|
126
|
+
const details = { http_status: status, ...(key ? { idempotency_key: key } : {}) };
|
|
127
|
+
if (code === "capability_disabled" && record(body) && typeof body.required_capability === "string" && capabilities.includes(body.required_capability)
|
|
128
|
+
&& (!Object.hasOwn(body, "missing_sections") || Array.isArray(body.missing_sections) && body.missing_sections.length === 0))
|
|
129
|
+
details.required_capability = body.required_capability;
|
|
130
|
+
const next = status === 403 ? "请本人在网页核对账号能力、设备只读/读写范围或协议确认;不要重新授权或换入口绕过限制。"
|
|
131
|
+
: status === 409 ? "请先读取当前版本或到网页核对;撤销只在完成后的约 5 秒内有效,不自动重试或换键。"
|
|
132
|
+
: "请核对命令输入、服务版本和实际状态,不把失败或权限缺口解释为没有日程,不自动重试写入。";
|
|
133
|
+
return new ScheduleProblem(code, status === 403 ? "日程操作权限不足。" : status === 409 ? "日程状态或版本冲突,本次未确认写入。" : "日程请求未完成。", next, status === 401 ? 3 : status === 403 ? 4 : status >= 500 ? 7 : 2, details);
|
|
134
|
+
}
|
|
135
|
+
const buckets = ["overdue", "today", "tomorrow", "this_week", "later", "undated"];
|
|
136
|
+
const countNames = [...buckets, "completed", "cancelled"];
|
|
137
|
+
const natural = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
138
|
+
const safeText = (value) => typeof value === "string" && scalarText(value) && !/[\p{Cc}\u2028\u2029]/u.test(value);
|
|
139
|
+
const projectText = (value) => typeof value === "string" && scalarText(value) && [...value].length >= 1 && [...value].length <= 80;
|
|
140
|
+
function readInvalid() {
|
|
141
|
+
throw new ScheduleProblem("invalid_response", "日程读取回执无法核实。", "请核对服务版本和访问范围,不把异常响应解释为没有日程。", 7);
|
|
142
|
+
}
|
|
143
|
+
function projectItem(value) {
|
|
144
|
+
if (!record(value) || !scheduleUUID(value.id) || !validScheduleRevision(value.revision)
|
|
145
|
+
|| !safeText(value.title) || !trim(value.title) || [...value.title].length > 200
|
|
146
|
+
|| typeof value.status !== "string" || !["pending", "completed", "cancelled"].includes(value.status)
|
|
147
|
+
|| !validScheduleTime(value.created_at) || !validScheduleTime(value.updated_at))
|
|
148
|
+
return readInvalid();
|
|
149
|
+
const out = { id: value.id, title: value.title, status: value.status, revision: value.revision, created_at: value.created_at, updated_at: value.updated_at };
|
|
150
|
+
for (const name of ["due_date", "due_at", "project_id", "project_title", "project_unavailable_reason", "completed_at", "cancelled_at", "undo_until", "bucket", "closed_actor_kind", "closed_actor_name"]) {
|
|
151
|
+
if (!Object.hasOwn(value, name))
|
|
152
|
+
continue;
|
|
153
|
+
const field = value[name];
|
|
154
|
+
if (name === "project_title" ? !projectText(field) : !safeText(field) || !field)
|
|
155
|
+
readInvalid();
|
|
156
|
+
if (name === "due_date" && !validScheduleDate(field) || name === "project_id" && !scheduleUUID(field)
|
|
157
|
+
|| ["due_at", "completed_at", "cancelled_at", "undo_until"].includes(name) && !validScheduleTime(field)
|
|
158
|
+
|| name === "bucket" && !buckets.includes(field)
|
|
159
|
+
|| name === "project_unavailable_reason" && field !== "project_unavailable")
|
|
160
|
+
readInvalid();
|
|
161
|
+
out[name] = field;
|
|
162
|
+
}
|
|
163
|
+
if (out.due_date && out.due_at)
|
|
164
|
+
readInvalid();
|
|
165
|
+
if (out.project_unavailable_reason) {
|
|
166
|
+
delete out.project_id;
|
|
167
|
+
delete out.project_title;
|
|
168
|
+
}
|
|
169
|
+
else if (out.project_title && !out.project_id)
|
|
170
|
+
readInvalid();
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
export function scheduleReadResult(status, value, detail) {
|
|
174
|
+
if (status !== 200 || !record(value) || value.timezone !== "Asia/Shanghai")
|
|
175
|
+
return readInvalid();
|
|
176
|
+
if (detail)
|
|
177
|
+
return { schedule_item: projectItem(value.schedule_item), timezone: "Asia/Shanghai" };
|
|
178
|
+
if (!Array.isArray(value.items) || !Array.isArray(value.groups) || !record(value.counts)
|
|
179
|
+
|| !natural(value.total) || !natural(value.offset) || !natural(value.limit) || value.limit < 1 || value.limit > 100
|
|
180
|
+
|| typeof value.has_more !== "boolean")
|
|
181
|
+
return readInvalid();
|
|
182
|
+
const total = value.total, offset = value.offset, limit = value.limit;
|
|
183
|
+
const items = value.items.map(projectItem);
|
|
184
|
+
if (items.length !== Math.min(limit, Math.max(0, total - offset)) || value.has_more !== (offset < total && items.length < total - offset))
|
|
185
|
+
readInvalid();
|
|
186
|
+
const counts = {};
|
|
187
|
+
for (const name of countNames) {
|
|
188
|
+
if (!natural(value.counts[name]))
|
|
189
|
+
readInvalid();
|
|
190
|
+
counts[name] = value.counts[name];
|
|
191
|
+
}
|
|
192
|
+
if (Object.values(counts).reduce((sum, count) => sum + count, 0) !== total)
|
|
193
|
+
readInvalid();
|
|
194
|
+
const itemMap = new Map(), shownCounts = {};
|
|
195
|
+
for (const item of items) {
|
|
196
|
+
if (itemMap.has(item.id) || typeof item.bucket !== "string")
|
|
197
|
+
readInvalid();
|
|
198
|
+
itemMap.set(item.id, item);
|
|
199
|
+
const name = item.status === "pending" ? item.bucket : item.status;
|
|
200
|
+
shownCounts[name] = (shownCounts[name] ?? 0) + 1;
|
|
201
|
+
if (shownCounts[name] > counts[name])
|
|
202
|
+
readInvalid();
|
|
203
|
+
}
|
|
204
|
+
const groupKeys = new Set(), groupedIDs = new Set();
|
|
205
|
+
let groupTotal = 0;
|
|
206
|
+
const groups = value.groups.map(raw => {
|
|
207
|
+
if (!record(raw) || !safeText(raw.key) || !raw.key || groupKeys.has(raw.key)
|
|
208
|
+
|| !natural(raw.total) || !natural(raw.shown) || raw.shown < 1 || raw.total < raw.shown || raw.total > total
|
|
209
|
+
|| typeof raw.has_more !== "boolean" || raw.has_more !== (raw.shown < raw.total)
|
|
210
|
+
|| !Array.isArray(raw.items) || raw.items.length !== raw.shown)
|
|
211
|
+
return readInvalid();
|
|
212
|
+
groupKeys.add(raw.key);
|
|
213
|
+
groupTotal += raw.total;
|
|
214
|
+
const groupItems = raw.items.map(projectItem);
|
|
215
|
+
for (const item of groupItems) {
|
|
216
|
+
const id = item.id;
|
|
217
|
+
if (groupedIDs.has(id) || !itemMap.has(id) || JSON.stringify(itemMap.get(id)) !== JSON.stringify(item))
|
|
218
|
+
readInvalid();
|
|
219
|
+
groupedIDs.add(id);
|
|
220
|
+
}
|
|
221
|
+
const group = { key: raw.key, total: raw.total, shown: raw.shown, has_more: raw.has_more, items: groupItems };
|
|
222
|
+
if (Object.hasOwn(raw, "title")) {
|
|
223
|
+
if (!projectText(raw.title))
|
|
224
|
+
readInvalid();
|
|
225
|
+
group.title = raw.title;
|
|
226
|
+
}
|
|
227
|
+
if (Object.hasOwn(raw, "project_id")) {
|
|
228
|
+
if (!scheduleUUID(raw.project_id) || raw.key !== raw.project_id)
|
|
229
|
+
readInvalid();
|
|
230
|
+
group.project_id = raw.project_id;
|
|
231
|
+
}
|
|
232
|
+
return group;
|
|
233
|
+
});
|
|
234
|
+
if (groupedIDs.size !== items.length || groupTotal > total)
|
|
235
|
+
readInvalid();
|
|
236
|
+
return { items, groups, counts, total, limit, offset, has_more: value.has_more, timezone: "Asia/Shanghai" };
|
|
237
|
+
}
|
|
238
|
+
export function scheduleReceipt(status, value, key) {
|
|
239
|
+
if (![200, 201].includes(status) || !record(value) || !scheduleUUID(value.id) || value.write_status !== "confirmed" || typeof value.replayed !== "boolean"
|
|
240
|
+
|| value.code !== undefined || value.error !== undefined
|
|
241
|
+
|| value.read_permission_missing !== undefined && typeof value.read_permission_missing !== "boolean"
|
|
242
|
+
|| value.read_unavailable !== undefined && typeof value.read_unavailable !== "boolean")
|
|
243
|
+
throw scheduleUnknown(key, status);
|
|
244
|
+
const out = { id: value.id, write_status: "confirmed", replayed: value.replayed };
|
|
245
|
+
const missing = value.missing_sections;
|
|
246
|
+
if (value.read_permission_missing === true || value.read_unavailable === true || Array.isArray(missing) && missing.length > 0) {
|
|
247
|
+
const unavailable = value.read_unavailable === true;
|
|
248
|
+
const reason = unavailable ? "read_failed" : "capability_disabled";
|
|
249
|
+
if (!Array.isArray(missing) || missing.length !== 1 || !record(missing[0]) || missing[0].section !== "schedule_items"
|
|
250
|
+
|| missing[0].required_capability !== "read_workbench" || missing[0].reason !== reason
|
|
251
|
+
|| unavailable && value.read_permission_missing === true)
|
|
252
|
+
throw scheduleUnknown(key, status);
|
|
253
|
+
out[unavailable ? "read_unavailable" : "read_permission_missing"] = true;
|
|
254
|
+
out.missing_sections = [{ section: "schedule_items", required_capability: "read_workbench", reason }];
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
if (missing !== undefined && (!Array.isArray(missing) || missing.length !== 0))
|
|
258
|
+
throw scheduleUnknown(key, status);
|
|
259
|
+
try {
|
|
260
|
+
out.schedule_item = projectItem(value.schedule_item);
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
throw scheduleUnknown(key, status);
|
|
264
|
+
}
|
|
265
|
+
if (out.schedule_item.id !== value.id)
|
|
266
|
+
throw scheduleUnknown(key, status);
|
|
267
|
+
}
|
|
268
|
+
return out;
|
|
269
|
+
}
|
|
270
|
+
export function isScheduleHeaderPath(path, method) {
|
|
271
|
+
return method === "GET" && path === scheduleRoot + "/m1/schedule-write-status"
|
|
272
|
+
|| method === "POST" && (path === scheduleRoot + "/m2/schedule-items" || /^\/api\/v1\/agent\/m2\/schedule-items\/[^/]+\/(complete|cancel|undo)$/.test(path))
|
|
273
|
+
|| method === "PATCH" && /^\/api\/v1\/agent\/m2\/schedule-items\/[^/]+$/.test(path);
|
|
274
|
+
}
|
|
275
|
+
export function scheduleHeaders(path, method, value) {
|
|
276
|
+
if (!record(value) || Object.keys(value).some(name => !["Idempotency-Key", "If-Match"].includes(name)))
|
|
277
|
+
return scheduleInvalid();
|
|
278
|
+
const headers = { "Idempotency-Key": scheduleKey(value["Idempotency-Key"]) };
|
|
279
|
+
const revisionRequired = method !== "GET" && path !== scheduleRoot + "/m2/schedule-items";
|
|
280
|
+
if (revisionRequired) {
|
|
281
|
+
const revision = value["If-Match"];
|
|
282
|
+
if (typeof revision !== "string" || !/^"[1-9]\d*"(?![\s\S])/.test(revision) || !validScheduleRevision(Number(revision.slice(1, -1))))
|
|
283
|
+
return scheduleInvalid();
|
|
284
|
+
headers["If-Match"] = revision;
|
|
285
|
+
}
|
|
286
|
+
else if (value["If-Match"] !== undefined)
|
|
287
|
+
scheduleInvalid();
|
|
288
|
+
return headers;
|
|
289
|
+
}
|