@quiel/cli 0.4.2 → 0.5.1
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 +8 -5
- package/dist/cli.js +1323 -845
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -115,6 +115,51 @@ var maskKeyValue = maskValueGroup(KEY_VALUE_RE);
|
|
|
115
115
|
var maskFlagSpace = maskValueGroup(FLAG_SPACE_RE);
|
|
116
116
|
var maskAuthHeader = maskValueGroup(AUTH_HEADER_RE);
|
|
117
117
|
|
|
118
|
+
// ../shared/src/deploy/affected-services.ts
|
|
119
|
+
var RULES = [
|
|
120
|
+
// Приложения — каждое только в свой образ.
|
|
121
|
+
{ prefix: "apps/web/", services: ["web"] },
|
|
122
|
+
{ prefix: "apps/realtime/", services: ["realtime"] },
|
|
123
|
+
{ prefix: "apps/worker/", services: ["worker"] },
|
|
124
|
+
{ prefix: "apps/docs/", services: ["docs"] },
|
|
125
|
+
// Клиент публикуется в npm и на стенде не работает.
|
|
126
|
+
//
|
|
127
|
+
// ПУТЬ — `packages/mcp-client/`, и это не придирка: раньше здесь стояло
|
|
128
|
+
// `packages/cli/`, каталога с таким именем в репозитории нет никогда не
|
|
129
|
+
// было, и правило не совпадало ни с чем. Правка клиента молча
|
|
130
|
+
// проваливалась в «закрыто по умолчанию» и пересобирала все образы.
|
|
131
|
+
// Тест это подтверждал — он спрашивал про такой же выдуманный путь.
|
|
132
|
+
{ prefix: "packages/mcp-client/", services: [] },
|
|
133
|
+
// Схема и клиент БД: три сервиса ходят в базу, плюс сам мигратор.
|
|
134
|
+
{ prefix: "packages/db/", services: ["web", "realtime", "worker", "migrate"] },
|
|
135
|
+
// Клиент GitHub App: веб (подключение, список репозиториев) и realtime
|
|
136
|
+
// (открытие pull request диспетчером).
|
|
137
|
+
{ prefix: "packages/github/", services: ["web", "realtime"] },
|
|
138
|
+
// Письма: веб шлёт magic link и подтверждения, воркер — уведомления и
|
|
139
|
+
// дайджест. Realtime почту не трогает.
|
|
140
|
+
{ prefix: "packages/mail/", services: ["web", "worker"] },
|
|
141
|
+
// Общие типы и общий конфиг — под ними все.
|
|
142
|
+
{ prefix: "packages/shared/", services: "all" },
|
|
143
|
+
{ prefix: "packages/config/", services: "all" },
|
|
144
|
+
// Сборка и окружение — тоже все.
|
|
145
|
+
{ prefix: "docker/", services: "all" },
|
|
146
|
+
// Комплект логотипа: аватар для GitHub и правила использования. Сам
|
|
147
|
+
// логотип в продукте живёт не здесь — разметка встроена в компоненты
|
|
148
|
+
// (`apps/*/src/components/brand/`), иконки лежат в `apps/*/public/`, и
|
|
149
|
+
// оба пути закрыты правилами приложений выше. Тут только справочные
|
|
150
|
+
// файлы для людей.
|
|
151
|
+
{ prefix: "brand/", services: [] },
|
|
152
|
+
// Вспомогательные скрипты выкладки исполняются в CI, из проверенного
|
|
153
|
+
// коммита, и ни в один образ не попадают. Их правка меняет то, КАК
|
|
154
|
+
// считается список сервисов, но не содержимое стенда.
|
|
155
|
+
{ prefix: "scripts/", services: [] },
|
|
156
|
+
// Документы проекта и настройки CI стенда не касаются.
|
|
157
|
+
{ prefix: "docs/", services: [] },
|
|
158
|
+
{ prefix: ".github/", services: [] },
|
|
159
|
+
{ prefix: ".claude/", services: [] }
|
|
160
|
+
];
|
|
161
|
+
var RULE_PREFIXES = RULES.map((rule) => rule.prefix);
|
|
162
|
+
|
|
118
163
|
// ../shared/src/docs/links.ts
|
|
119
164
|
var DocsPage = {
|
|
120
165
|
START: "start",
|
|
@@ -186,40 +231,11 @@ var UpdateAgentSchema = z5.object({
|
|
|
186
231
|
message: "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u043E \u043F\u043E\u043B\u0435"
|
|
187
232
|
});
|
|
188
233
|
|
|
189
|
-
// ../shared/src/dto/
|
|
190
|
-
import { z as
|
|
191
|
-
var PASSWORD_MIN_LENGTH = 10;
|
|
192
|
-
var PASSWORD_MAX_LENGTH = 128;
|
|
193
|
-
var PasswordSchema = z6.string().min(PASSWORD_MIN_LENGTH, `\u041F\u0430\u0440\u043E\u043B\u044C \u043A\u043E\u0440\u043E\u0447\u0435 ${PASSWORD_MIN_LENGTH} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432`).max(PASSWORD_MAX_LENGTH, `\u041F\u0430\u0440\u043E\u043B\u044C \u0434\u043B\u0438\u043D\u043D\u0435\u0435 ${PASSWORD_MAX_LENGTH} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432`);
|
|
194
|
-
var EmailSchema = z6.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u043E\u0447\u0442\u0443").email("\u041F\u043E\u0445\u043E\u0436\u0435, \u0432 \u0430\u0434\u0440\u0435\u0441\u0435 \u043E\u043F\u0435\u0447\u0430\u0442\u043A\u0430").toLowerCase();
|
|
195
|
-
var RegisterSchema = z6.object({
|
|
196
|
-
name: z6.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0438\u043C\u044F").max(120),
|
|
197
|
-
email: EmailSchema,
|
|
198
|
-
password: PasswordSchema
|
|
199
|
-
}).refine(
|
|
200
|
-
(value) => {
|
|
201
|
-
const localPart = value.email.split("@")[0] ?? "";
|
|
202
|
-
return localPart.length < 3 || !value.password.toLowerCase().includes(localPart);
|
|
203
|
-
},
|
|
204
|
-
{ message: "\u041F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0434\u043E\u043B\u0436\u0435\u043D \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0442\u044C \u0430\u0434\u0440\u0435\u0441 \u043F\u043E\u0447\u0442\u044B", path: ["password"] }
|
|
205
|
-
);
|
|
206
|
-
var LoginSchema = z6.object({
|
|
207
|
-
email: EmailSchema,
|
|
208
|
-
// На входе НЕ применяем правила длины: пароль мог быть задан раньше, по
|
|
209
|
-
// другим правилам, и «слишком короткий» на форме входа — это отказ в
|
|
210
|
-
// доступе законному владельцу, а заодно подсказка перебирающему, что
|
|
211
|
-
// проверять длину не нужно.
|
|
212
|
-
password: z6.string().min(1, "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u044C")
|
|
213
|
-
});
|
|
214
|
-
var ForgotPasswordSchema = z6.object({ email: EmailSchema });
|
|
215
|
-
var ResetPasswordSchema = z6.object({
|
|
216
|
-
token: z6.string().min(1),
|
|
217
|
-
password: PasswordSchema
|
|
218
|
-
});
|
|
219
|
-
var ResendVerificationSchema = z6.object({ email: EmailSchema });
|
|
234
|
+
// ../shared/src/dto/attachment.ts
|
|
235
|
+
import { z as z7 } from "zod";
|
|
220
236
|
|
|
221
237
|
// ../shared/src/dto/document.ts
|
|
222
|
-
import { z as
|
|
238
|
+
import { z as z6 } from "zod";
|
|
223
239
|
|
|
224
240
|
// ../shared/src/enums/project.ts
|
|
225
241
|
var ProjectStatus = {
|
|
@@ -272,32 +288,32 @@ var ALLOWED_DOCUMENT_MIME_TYPES = [
|
|
|
272
288
|
"image/webp"
|
|
273
289
|
];
|
|
274
290
|
var MAX_DOCUMENT_FILE_SIZE_BYTES = 20 * 1024 * 1024;
|
|
275
|
-
var DocumentFileNameSchema =
|
|
276
|
-
var RequestDocumentUploadUrlSchema =
|
|
291
|
+
var DocumentFileNameSchema = z6.string().trim().min(1, "\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(255, "\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 255 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
292
|
+
var RequestDocumentUploadUrlSchema = z6.object({
|
|
277
293
|
fileName: DocumentFileNameSchema,
|
|
278
|
-
mimeType:
|
|
294
|
+
mimeType: z6.enum(ALLOWED_DOCUMENT_MIME_TYPES, {
|
|
279
295
|
message: `\u0422\u0438\u043F \u0444\u0430\u0439\u043B\u0430 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F. \u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u044B: ${ALLOWED_DOCUMENT_MIME_TYPES.join(", ")}`
|
|
280
296
|
}),
|
|
281
|
-
size:
|
|
297
|
+
size: z6.number().int().positive().max(
|
|
282
298
|
MAX_DOCUMENT_FILE_SIZE_BYTES,
|
|
283
299
|
`\u0424\u0430\u0439\u043B \u0431\u043E\u043B\u044C\u0448\u0435 ${MAX_DOCUMENT_FILE_SIZE_BYTES / (1024 * 1024)} \u041C\u0438\u0411`
|
|
284
300
|
)
|
|
285
301
|
});
|
|
286
|
-
var DocumentKindSchema =
|
|
302
|
+
var DocumentKindSchema = z6.enum([
|
|
287
303
|
DocumentKind.SPEC,
|
|
288
304
|
DocumentKind.PLAN,
|
|
289
305
|
DocumentKind.DATA,
|
|
290
306
|
DocumentKind.DECISION,
|
|
291
307
|
DocumentKind.OTHER
|
|
292
308
|
]);
|
|
293
|
-
var DocumentTitleSchema =
|
|
294
|
-
var DocumentContentMdSchema =
|
|
295
|
-
var DocumentFileRefSchema =
|
|
296
|
-
fileKey:
|
|
309
|
+
var DocumentTitleSchema = z6.string().trim().min(1, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(200, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 200 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
310
|
+
var DocumentContentMdSchema = z6.string().min(1, "\u0421\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u043E\u0435 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u044B\u043C").max(5e5, "\u0422\u0435\u043A\u0441\u0442 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 500 000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
311
|
+
var DocumentFileRefSchema = z6.object({
|
|
312
|
+
fileKey: z6.string().min(1),
|
|
297
313
|
fileName: DocumentFileNameSchema,
|
|
298
|
-
mimeType:
|
|
314
|
+
mimeType: z6.enum(ALLOWED_DOCUMENT_MIME_TYPES)
|
|
299
315
|
});
|
|
300
|
-
var CreateDocumentSchema =
|
|
316
|
+
var CreateDocumentSchema = z6.object({
|
|
301
317
|
kind: DocumentKindSchema,
|
|
302
318
|
title: DocumentTitleSchema,
|
|
303
319
|
contentMd: DocumentContentMdSchema.optional(),
|
|
@@ -306,7 +322,7 @@ var CreateDocumentSchema = z7.object({
|
|
|
306
322
|
message: "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u043B\u0438\u0431\u043E contentMd, \u043B\u0438\u0431\u043E file \u2014 \u043D\u0435 \u043E\u0431\u0430 \u0438 \u043D\u0435 \u043D\u0438 \u043E\u0434\u043D\u043E\u0433\u043E",
|
|
307
323
|
path: ["contentMd"]
|
|
308
324
|
});
|
|
309
|
-
var UpdateDocumentSchema =
|
|
325
|
+
var UpdateDocumentSchema = z6.object({
|
|
310
326
|
kind: DocumentKindSchema.optional(),
|
|
311
327
|
title: DocumentTitleSchema.optional(),
|
|
312
328
|
contentMd: DocumentContentMdSchema.optional(),
|
|
@@ -317,37 +333,108 @@ var UpdateDocumentSchema = z7.object({
|
|
|
317
333
|
message: "\u041D\u0435\u043B\u044C\u0437\u044F \u043E\u0434\u043D\u043E\u0432\u0440\u0435\u043C\u0435\u043D\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C contentMd \u0438 file",
|
|
318
334
|
path: ["contentMd"]
|
|
319
335
|
});
|
|
320
|
-
var ListDocumentsQuerySchema =
|
|
336
|
+
var ListDocumentsQuerySchema = z6.object({
|
|
321
337
|
kind: DocumentKindSchema.optional()
|
|
322
338
|
});
|
|
323
339
|
|
|
324
|
-
// ../shared/src/dto/
|
|
340
|
+
// ../shared/src/dto/attachment.ts
|
|
341
|
+
var AttachmentFileKeySchema = z7.string().min(1, "\u041A\u043B\u044E\u0447 \u0444\u0430\u0439\u043B\u0430 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D").max(1024, "\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u043A\u043B\u044E\u0447 \u0444\u0430\u0439\u043B\u0430").regex(/^attachments\//, "\u041A\u043B\u044E\u0447 \u0444\u0430\u0439\u043B\u0430 \u043D\u0435 \u0438\u0437 \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0430 \u0432\u043B\u043E\u0436\u0435\u043D\u0438\u0439");
|
|
342
|
+
var AttachmentInputSchema = z7.object({
|
|
343
|
+
fileKey: AttachmentFileKeySchema,
|
|
344
|
+
fileName: DocumentFileNameSchema,
|
|
345
|
+
mimeType: z7.enum(ALLOWED_DOCUMENT_MIME_TYPES, {
|
|
346
|
+
message: `\u0422\u0438\u043F \u0444\u0430\u0439\u043B\u0430 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F. \u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u044B: ${ALLOWED_DOCUMENT_MIME_TYPES.join(", ")}`
|
|
347
|
+
}),
|
|
348
|
+
size: z7.number().int().positive().max(MAX_DOCUMENT_FILE_SIZE_BYTES)
|
|
349
|
+
});
|
|
350
|
+
var MAX_ATTACHMENTS_PER_ITEM = 10;
|
|
351
|
+
var AttachmentListSchema = z7.array(AttachmentInputSchema).max(MAX_ATTACHMENTS_PER_ITEM, `\u041D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 ${MAX_ATTACHMENTS_PER_ITEM} \u0444\u0430\u0439\u043B\u043E\u0432`).refine(
|
|
352
|
+
(items) => new Set(items.map((item) => item.fileKey)).size === items.length,
|
|
353
|
+
"\u041E\u0434\u0438\u043D \u0438 \u0442\u043E\u0442 \u0436\u0435 \u0444\u0430\u0439\u043B \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D \u0434\u0432\u0430\u0436\u0434\u044B"
|
|
354
|
+
);
|
|
355
|
+
var attachmentSchema = z7.object({
|
|
356
|
+
id: z7.string(),
|
|
357
|
+
fileName: z7.string(),
|
|
358
|
+
mimeType: z7.string(),
|
|
359
|
+
size: z7.number().int().nonnegative(),
|
|
360
|
+
createdAt: z7.string(),
|
|
361
|
+
/**
|
|
362
|
+
* Временная ссылка на скачивание.
|
|
363
|
+
*
|
|
364
|
+
* ПУСТАЯ СТРОКА — РАБОЧИЙ СЛУЧАЙ, а не ошибка: хранилище может быть не
|
|
365
|
+
* настроено или отказать. Тогда и человек, и агент всё равно узнают,
|
|
366
|
+
* что файл ЕСТЬ, — а молчаливое «вложений нет» было бы хуже. Тот же
|
|
367
|
+
* приём, что у файлов документов (`dispatcher/context.ts`).
|
|
368
|
+
*/
|
|
369
|
+
downloadUrl: z7.string(),
|
|
370
|
+
expiresInSeconds: z7.number().int().positive()
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// ../shared/src/dto/auth.ts
|
|
325
374
|
import { z as z8 } from "zod";
|
|
326
|
-
var
|
|
327
|
-
var
|
|
328
|
-
var
|
|
329
|
-
var
|
|
375
|
+
var PASSWORD_MIN_LENGTH = 10;
|
|
376
|
+
var PASSWORD_MAX_LENGTH = 128;
|
|
377
|
+
var PasswordSchema = z8.string().min(PASSWORD_MIN_LENGTH, `\u041F\u0430\u0440\u043E\u043B\u044C \u043A\u043E\u0440\u043E\u0447\u0435 ${PASSWORD_MIN_LENGTH} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432`).max(PASSWORD_MAX_LENGTH, `\u041F\u0430\u0440\u043E\u043B\u044C \u0434\u043B\u0438\u043D\u043D\u0435\u0435 ${PASSWORD_MAX_LENGTH} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432`);
|
|
378
|
+
var EmailSchema = z8.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u043E\u0447\u0442\u0443").email("\u041F\u043E\u0445\u043E\u0436\u0435, \u0432 \u0430\u0434\u0440\u0435\u0441\u0435 \u043E\u043F\u0435\u0447\u0430\u0442\u043A\u0430").toLowerCase();
|
|
379
|
+
var RegisterSchema = z8.object({
|
|
380
|
+
name: z8.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0438\u043C\u044F").max(120),
|
|
381
|
+
email: EmailSchema,
|
|
382
|
+
password: PasswordSchema
|
|
383
|
+
}).refine(
|
|
384
|
+
(value) => {
|
|
385
|
+
const localPart = value.email.split("@")[0] ?? "";
|
|
386
|
+
return localPart.length < 3 || !value.password.toLowerCase().includes(localPart);
|
|
387
|
+
},
|
|
388
|
+
{ message: "\u041F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0434\u043E\u043B\u0436\u0435\u043D \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0442\u044C \u0430\u0434\u0440\u0435\u0441 \u043F\u043E\u0447\u0442\u044B", path: ["password"] }
|
|
389
|
+
);
|
|
390
|
+
var LoginSchema = z8.object({
|
|
391
|
+
email: EmailSchema,
|
|
392
|
+
// На входе НЕ применяем правила длины: пароль мог быть задан раньше, по
|
|
393
|
+
// другим правилам, и «слишком короткий» на форме входа — это отказ в
|
|
394
|
+
// доступе законному владельцу, а заодно подсказка перебирающему, что
|
|
395
|
+
// проверять длину не нужно.
|
|
396
|
+
password: z8.string().min(1, "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u044C")
|
|
397
|
+
});
|
|
398
|
+
var ForgotPasswordSchema = z8.object({ email: EmailSchema });
|
|
399
|
+
var ResetPasswordSchema = z8.object({
|
|
400
|
+
token: z8.string().min(1),
|
|
401
|
+
password: PasswordSchema
|
|
402
|
+
});
|
|
403
|
+
var ResendVerificationSchema = z8.object({ email: EmailSchema });
|
|
404
|
+
|
|
405
|
+
// ../shared/src/dto/milestone.ts
|
|
406
|
+
import { z as z9 } from "zod";
|
|
407
|
+
var MilestoneNameSchema = z9.string().trim().min(1, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(150, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 150 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
408
|
+
var MilestoneDescriptionSchema = z9.string().max(5e3, "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 5000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
409
|
+
var MilestoneStatusSchema = z9.enum([MilestoneStatus.OPEN, MilestoneStatus.DONE]);
|
|
410
|
+
var CreateMilestoneSchema = z9.object({
|
|
330
411
|
name: MilestoneNameSchema,
|
|
331
412
|
description: MilestoneDescriptionSchema.optional(),
|
|
332
|
-
dueAt:
|
|
413
|
+
dueAt: z9.coerce.date().optional(),
|
|
333
414
|
status: MilestoneStatusSchema.default(MilestoneStatus.OPEN)
|
|
334
415
|
});
|
|
335
|
-
var UpdateMilestoneSchema =
|
|
416
|
+
var UpdateMilestoneSchema = z9.object({
|
|
336
417
|
name: MilestoneNameSchema.optional(),
|
|
337
418
|
description: MilestoneDescriptionSchema.nullable().optional(),
|
|
338
|
-
dueAt:
|
|
419
|
+
dueAt: z9.coerce.date().nullable().optional(),
|
|
339
420
|
status: MilestoneStatusSchema.optional()
|
|
340
421
|
}).refine((data) => Object.keys(data).length > 0, {
|
|
341
422
|
message: "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u043E \u043F\u043E\u043B\u0435"
|
|
342
423
|
});
|
|
343
|
-
var ReorderMilestonesSchema =
|
|
344
|
-
orderedIds:
|
|
424
|
+
var ReorderMilestonesSchema = z9.object({
|
|
425
|
+
orderedIds: z9.array(z9.string().min(1)).min(1, "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D id")
|
|
345
426
|
});
|
|
346
427
|
|
|
347
428
|
// ../shared/src/dto/organization.ts
|
|
348
|
-
import { z as
|
|
429
|
+
import { z as z10 } from "zod";
|
|
349
430
|
|
|
350
431
|
// ../shared/src/enums/organization.ts
|
|
432
|
+
var Plan = {
|
|
433
|
+
SELF_HOSTED: "SELF_HOSTED",
|
|
434
|
+
FREE: "FREE",
|
|
435
|
+
TEAM: "TEAM",
|
|
436
|
+
ENTERPRISE: "ENTERPRISE"
|
|
437
|
+
};
|
|
351
438
|
var OrgRole = {
|
|
352
439
|
OWNER: "OWNER",
|
|
353
440
|
ADMIN: "ADMIN",
|
|
@@ -355,78 +442,78 @@ var OrgRole = {
|
|
|
355
442
|
};
|
|
356
443
|
|
|
357
444
|
// ../shared/src/dto/organization.ts
|
|
358
|
-
var OrgSlugSchema =
|
|
445
|
+
var OrgSlugSchema = z10.string().min(2, "Slug \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u043A\u043E\u0440\u043E\u0447\u0435 2 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432").max(50, "Slug \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 50 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432").regex(
|
|
359
446
|
/^[a-z0-9]+(-[a-z0-9]+)*$/,
|
|
360
447
|
"Slug: \u0441\u0442\u0440\u043E\u0447\u043D\u044B\u0435 \u043B\u0430\u0442\u0438\u043D\u0441\u043A\u0438\u0435 \u0431\u0443\u043A\u0432\u044B, \u0446\u0438\u0444\u0440\u044B \u0438 \u0434\u0435\u0444\u0438\u0441, \u0431\u0435\u0437 \u0434\u0435\u0444\u0438\u0441\u0430 \u043F\u043E \u043A\u0440\u0430\u044F\u043C"
|
|
361
448
|
);
|
|
362
|
-
var OrgNameSchema =
|
|
363
|
-
var CreateOrganizationSchema =
|
|
449
|
+
var OrgNameSchema = z10.string().trim().min(1, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(100, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 100 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
450
|
+
var CreateOrganizationSchema = z10.object({
|
|
364
451
|
name: OrgNameSchema,
|
|
365
452
|
slug: OrgSlugSchema.optional()
|
|
366
453
|
});
|
|
367
|
-
var UpdateOrganizationSchema =
|
|
454
|
+
var UpdateOrganizationSchema = z10.object({
|
|
368
455
|
name: OrgNameSchema.optional(),
|
|
369
456
|
slug: OrgSlugSchema.optional()
|
|
370
457
|
}).refine((data) => data.name !== void 0 || data.slug !== void 0, {
|
|
371
458
|
message: "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u043E \u043F\u043E\u043B\u0435 \u2014 name \u0438\u043B\u0438 slug"
|
|
372
459
|
});
|
|
373
|
-
var InviteMemberSchema =
|
|
374
|
-
email:
|
|
375
|
-
orgRole:
|
|
460
|
+
var InviteMemberSchema = z10.object({
|
|
461
|
+
email: z10.email("\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 email"),
|
|
462
|
+
orgRole: z10.enum([OrgRole.ADMIN, OrgRole.MEMBER]).default(OrgRole.MEMBER)
|
|
376
463
|
});
|
|
377
464
|
var INVITATION_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
378
|
-
var InvitationTokenSchema =
|
|
379
|
-
var AcceptInvitationSchema =
|
|
465
|
+
var InvitationTokenSchema = z10.string().min(16, "\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 \u0442\u043E\u043A\u0435\u043D \u043F\u0440\u0438\u0433\u043B\u0430\u0448\u0435\u043D\u0438\u044F");
|
|
466
|
+
var AcceptInvitationSchema = z10.object({
|
|
380
467
|
token: InvitationTokenSchema
|
|
381
468
|
});
|
|
382
|
-
var OrganizationMemberDTOSchema =
|
|
383
|
-
type:
|
|
469
|
+
var OrganizationMemberDTOSchema = z10.object({
|
|
470
|
+
type: z10.literal("member"),
|
|
384
471
|
/** id записи Membership — тот же id принимает `DELETE .../members/:id`. */
|
|
385
|
-
id:
|
|
386
|
-
userId:
|
|
387
|
-
name:
|
|
388
|
-
email:
|
|
389
|
-
image:
|
|
390
|
-
orgRole:
|
|
391
|
-
createdAt:
|
|
392
|
-
});
|
|
393
|
-
var OrganizationInvitationDTOSchema =
|
|
394
|
-
type:
|
|
472
|
+
id: z10.string(),
|
|
473
|
+
userId: z10.string(),
|
|
474
|
+
name: z10.string().nullable(),
|
|
475
|
+
email: z10.string().nullable(),
|
|
476
|
+
image: z10.string().nullable(),
|
|
477
|
+
orgRole: z10.enum([OrgRole.OWNER, OrgRole.ADMIN, OrgRole.MEMBER]),
|
|
478
|
+
createdAt: z10.coerce.date()
|
|
479
|
+
});
|
|
480
|
+
var OrganizationInvitationDTOSchema = z10.object({
|
|
481
|
+
type: z10.literal("invitation"),
|
|
395
482
|
/** id записи Invitation — тот же id принимает `DELETE .../members/:id`. */
|
|
396
|
-
id:
|
|
397
|
-
email:
|
|
398
|
-
orgRole:
|
|
483
|
+
id: z10.string(),
|
|
484
|
+
email: z10.string(),
|
|
485
|
+
orgRole: z10.enum([OrgRole.ADMIN, OrgRole.MEMBER]),
|
|
399
486
|
/** `expired` — вычисляется на сервере сравнением `expiresAt` с текущим временем. */
|
|
400
|
-
status:
|
|
401
|
-
invitedByName:
|
|
402
|
-
expiresAt:
|
|
403
|
-
createdAt:
|
|
487
|
+
status: z10.enum(["pending", "expired"]),
|
|
488
|
+
invitedByName: z10.string().nullable(),
|
|
489
|
+
expiresAt: z10.coerce.date(),
|
|
490
|
+
createdAt: z10.coerce.date()
|
|
404
491
|
});
|
|
405
|
-
var OrganizationMembersListItemSchema =
|
|
492
|
+
var OrganizationMembersListItemSchema = z10.discriminatedUnion("type", [
|
|
406
493
|
OrganizationMemberDTOSchema,
|
|
407
494
|
OrganizationInvitationDTOSchema
|
|
408
495
|
]);
|
|
409
496
|
|
|
410
497
|
// ../shared/src/dto/profile.ts
|
|
411
|
-
import { z as
|
|
412
|
-
var ProfileNameSchema =
|
|
413
|
-
var UpdateProfileSchema =
|
|
498
|
+
import { z as z11 } from "zod";
|
|
499
|
+
var ProfileNameSchema = z11.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0438\u043C\u044F").max(120);
|
|
500
|
+
var UpdateProfileSchema = z11.object({
|
|
414
501
|
name: ProfileNameSchema
|
|
415
502
|
});
|
|
416
|
-
var ChangePasswordSchema =
|
|
417
|
-
currentPassword:
|
|
503
|
+
var ChangePasswordSchema = z11.object({
|
|
504
|
+
currentPassword: z11.string().min(1).max(200).optional(),
|
|
418
505
|
newPassword: PasswordSchema
|
|
419
506
|
});
|
|
420
|
-
var RequestEmailChangeSchema =
|
|
507
|
+
var RequestEmailChangeSchema = z11.object({
|
|
421
508
|
newEmail: EmailSchema,
|
|
422
509
|
/** Нужен, если у аккаунта есть пароль — см. `ChangePasswordSchema`. */
|
|
423
|
-
currentPassword:
|
|
510
|
+
currentPassword: z11.string().min(1).max(200).optional()
|
|
424
511
|
});
|
|
425
|
-
var ConfirmEmailChangeSchema =
|
|
426
|
-
token:
|
|
512
|
+
var ConfirmEmailChangeSchema = z11.object({
|
|
513
|
+
token: z11.string().min(1)
|
|
427
514
|
});
|
|
428
|
-
var UpdateAvatarSchema =
|
|
429
|
-
fileKey:
|
|
515
|
+
var UpdateAvatarSchema = z11.object({
|
|
516
|
+
fileKey: z11.string().min(1).max(500)
|
|
430
517
|
});
|
|
431
518
|
var ALLOWED_AVATAR_MIME_TYPES = [
|
|
432
519
|
"image/jpeg",
|
|
@@ -435,23 +522,23 @@ var ALLOWED_AVATAR_MIME_TYPES = [
|
|
|
435
522
|
"image/gif"
|
|
436
523
|
];
|
|
437
524
|
var MAX_AVATAR_FILE_SIZE_BYTES = 2 * 1024 * 1024;
|
|
438
|
-
var RequestAvatarUploadUrlSchema =
|
|
439
|
-
fileName:
|
|
440
|
-
mimeType:
|
|
441
|
-
size:
|
|
525
|
+
var RequestAvatarUploadUrlSchema = z11.object({
|
|
526
|
+
fileName: z11.string().trim().min(1).max(200),
|
|
527
|
+
mimeType: z11.enum(ALLOWED_AVATAR_MIME_TYPES),
|
|
528
|
+
size: z11.number().int().positive().max(MAX_AVATAR_FILE_SIZE_BYTES)
|
|
442
529
|
});
|
|
443
|
-
var UnlinkAccountSchema =
|
|
444
|
-
provider:
|
|
530
|
+
var UnlinkAccountSchema = z11.object({
|
|
531
|
+
provider: z11.string().trim().min(1).max(50)
|
|
445
532
|
});
|
|
446
533
|
|
|
447
534
|
// ../shared/src/dto/project.ts
|
|
448
|
-
import { z as
|
|
535
|
+
import { z as z15 } from "zod";
|
|
449
536
|
|
|
450
537
|
// ../shared/src/settings/project-settings.ts
|
|
451
|
-
import { z as
|
|
538
|
+
import { z as z14 } from "zod";
|
|
452
539
|
|
|
453
540
|
// ../shared/src/dto/task-template.ts
|
|
454
|
-
import { z as
|
|
541
|
+
import { z as z13 } from "zod";
|
|
455
542
|
|
|
456
543
|
// ../shared/src/enums/task.ts
|
|
457
544
|
var TaskType = {
|
|
@@ -509,42 +596,42 @@ var EventKind = {
|
|
|
509
596
|
};
|
|
510
597
|
|
|
511
598
|
// ../shared/src/dto/task.ts
|
|
512
|
-
import { z as
|
|
599
|
+
import { z as z12 } from "zod";
|
|
513
600
|
var taskTypeValues = Object.values(TaskType);
|
|
514
601
|
var taskStatusValues = Object.values(TaskStatus);
|
|
515
602
|
var priorityValues = Object.values(Priority);
|
|
516
603
|
var executorValues = Object.values(Executor);
|
|
517
604
|
var testResultValues = Object.values(TestResult);
|
|
518
|
-
var TaskTypeSchema =
|
|
519
|
-
var TaskStatusSchema =
|
|
520
|
-
var TaskPrioritySchema =
|
|
521
|
-
var TaskExecutorSchema =
|
|
522
|
-
var TaskTestResultSchema =
|
|
523
|
-
var TaskTitleSchema =
|
|
524
|
-
var TaskDescriptionSchema =
|
|
525
|
-
var TaskLabelSchema =
|
|
526
|
-
var TaskLabelsSchema =
|
|
527
|
-
var TaskMetadataSchema =
|
|
528
|
-
var TaskAcceptanceSchema =
|
|
529
|
-
var TaskEstimateMinSchema =
|
|
530
|
-
var TaskOrderSchema =
|
|
531
|
-
var TaskResultMdSchema =
|
|
532
|
-
var TaskResultLinkKindSchema =
|
|
533
|
-
var TaskResultLinkSchema =
|
|
605
|
+
var TaskTypeSchema = z12.enum(taskTypeValues);
|
|
606
|
+
var TaskStatusSchema = z12.enum(taskStatusValues);
|
|
607
|
+
var TaskPrioritySchema = z12.enum(priorityValues);
|
|
608
|
+
var TaskExecutorSchema = z12.enum(executorValues);
|
|
609
|
+
var TaskTestResultSchema = z12.enum(testResultValues);
|
|
610
|
+
var TaskTitleSchema = z12.string().trim().min(1, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(300, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 300 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
611
|
+
var TaskDescriptionSchema = z12.string().max(5e4, "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 50000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
612
|
+
var TaskLabelSchema = z12.string().trim().min(1).max(40, "\u041C\u0435\u0442\u043A\u0430 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 40 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
613
|
+
var TaskLabelsSchema = z12.array(TaskLabelSchema).max(30, "\u041D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 30 \u043C\u0435\u0442\u043E\u043A");
|
|
614
|
+
var TaskMetadataSchema = z12.record(z12.string(), z12.unknown());
|
|
615
|
+
var TaskAcceptanceSchema = z12.string().max(2e4, "\u041A\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u043F\u0440\u0438\u0451\u043C\u043A\u0438 \u0434\u043E\u043B\u0436\u043D\u044B \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 20000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
616
|
+
var TaskEstimateMinSchema = z12.number().int("\u041E\u0446\u0435\u043D\u043A\u0430 \u2014 \u0446\u0435\u043B\u043E\u0435 \u0447\u0438\u0441\u043B\u043E \u043C\u0438\u043D\u0443\u0442").positive("\u041E\u0446\u0435\u043D\u043A\u0430 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043F\u043E\u043B\u043E\u0436\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0439").max(1e5);
|
|
617
|
+
var TaskOrderSchema = z12.number().finite("order \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043A\u043E\u043D\u0435\u0447\u043D\u044B\u043C \u0447\u0438\u0441\u043B\u043E\u043C");
|
|
618
|
+
var TaskResultMdSchema = z12.string().max(5e4);
|
|
619
|
+
var TaskResultLinkKindSchema = z12.enum(["pr", "commit", "url"]);
|
|
620
|
+
var TaskResultLinkSchema = z12.object({
|
|
534
621
|
kind: TaskResultLinkKindSchema,
|
|
535
|
-
url:
|
|
536
|
-
label:
|
|
622
|
+
url: z12.string().url("\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 URL"),
|
|
623
|
+
label: z12.string().max(200).optional()
|
|
537
624
|
});
|
|
538
|
-
var TaskResultLinksSchema =
|
|
539
|
-
var TaskLastErrorSchema =
|
|
540
|
-
var IdSchema =
|
|
541
|
-
var CreateTaskSchema =
|
|
625
|
+
var TaskResultLinksSchema = z12.array(TaskResultLinkSchema).max(50);
|
|
626
|
+
var TaskLastErrorSchema = z12.string().max(5e3);
|
|
627
|
+
var IdSchema = z12.string().min(1);
|
|
628
|
+
var CreateTaskSchema = z12.object({
|
|
542
629
|
title: TaskTitleSchema,
|
|
543
630
|
descriptionMd: TaskDescriptionSchema.default(""),
|
|
544
631
|
type: TaskTypeSchema.default(TaskType.FEATURE),
|
|
545
632
|
priority: TaskPrioritySchema.default(Priority.P2),
|
|
546
633
|
executor: TaskExecutorSchema.default(Executor.ANY),
|
|
547
|
-
roleKey:
|
|
634
|
+
roleKey: z12.string().min(1).max(60).optional(),
|
|
548
635
|
assigneeId: IdSchema.optional(),
|
|
549
636
|
milestoneId: IdSchema.optional(),
|
|
550
637
|
parentId: IdSchema.optional(),
|
|
@@ -552,19 +639,31 @@ var CreateTaskSchema = z11.object({
|
|
|
552
639
|
metadata: TaskMetadataSchema.default({}),
|
|
553
640
|
acceptance: TaskAcceptanceSchema.optional(),
|
|
554
641
|
estimateMin: TaskEstimateMinSchema.optional(),
|
|
555
|
-
dueAt:
|
|
642
|
+
dueAt: z12.coerce.date().optional(),
|
|
556
643
|
/** Позиция в колонке BACKLOG; если не передан — сервер ставит в конец (apps/web/src/lib/tasks/order.ts). */
|
|
557
|
-
order: TaskOrderSchema.optional()
|
|
644
|
+
order: TaskOrderSchema.optional(),
|
|
645
|
+
/**
|
|
646
|
+
* Файлы, приложенные человеком при постановке задачи (задача владельца
|
|
647
|
+
* 18.09.2026).
|
|
648
|
+
*
|
|
649
|
+
* Уже ЗАГРУЖЕННЫЕ: браузер кладёт их прямо в MinIO по подписанной
|
|
650
|
+
* ссылке, сюда приезжают только ключи. Сервер сверяет ключ с проектом и
|
|
651
|
+
* проверяет, что объект существует, — доверять клиенту здесь нельзя.
|
|
652
|
+
*
|
|
653
|
+
* Поле необязательное, и старый клиент, не знающий о нём, продолжает
|
|
654
|
+
* создавать задачи как раньше.
|
|
655
|
+
*/
|
|
656
|
+
attachments: AttachmentListSchema.default([])
|
|
558
657
|
});
|
|
559
|
-
var UpdateTaskSchema =
|
|
658
|
+
var UpdateTaskSchema = z12.object({
|
|
560
659
|
title: TaskTitleSchema.optional(),
|
|
561
660
|
descriptionMd: TaskDescriptionSchema.optional(),
|
|
562
661
|
type: TaskTypeSchema.optional(),
|
|
563
662
|
status: TaskStatusSchema.optional(),
|
|
564
|
-
statusComment:
|
|
663
|
+
statusComment: z12.string().max(2e4).optional(),
|
|
565
664
|
priority: TaskPrioritySchema.optional(),
|
|
566
665
|
executor: TaskExecutorSchema.optional(),
|
|
567
|
-
roleKey:
|
|
666
|
+
roleKey: z12.string().min(1).max(60).nullable().optional(),
|
|
568
667
|
assigneeId: IdSchema.nullable().optional(),
|
|
569
668
|
milestoneId: IdSchema.nullable().optional(),
|
|
570
669
|
parentId: IdSchema.nullable().optional(),
|
|
@@ -572,7 +671,7 @@ var UpdateTaskSchema = z11.object({
|
|
|
572
671
|
metadata: TaskMetadataSchema.optional(),
|
|
573
672
|
acceptance: TaskAcceptanceSchema.nullable().optional(),
|
|
574
673
|
estimateMin: TaskEstimateMinSchema.nullable().optional(),
|
|
575
|
-
dueAt:
|
|
674
|
+
dueAt: z12.coerce.date().nullable().optional(),
|
|
576
675
|
order: TaskOrderSchema.optional(),
|
|
577
676
|
resultMd: TaskResultMdSchema.nullable().optional(),
|
|
578
677
|
resultLinks: TaskResultLinksSchema.nullable().optional(),
|
|
@@ -583,55 +682,55 @@ var UpdateTaskSchema = z11.object({
|
|
|
583
682
|
});
|
|
584
683
|
var TASK_LIST_DEFAULT_LIMIT = 25;
|
|
585
684
|
var TASK_LIST_MAX_LIMIT = 100;
|
|
586
|
-
var TaskListQuerySchema =
|
|
587
|
-
status:
|
|
588
|
-
role:
|
|
589
|
-
assignee:
|
|
590
|
-
milestone:
|
|
591
|
-
label:
|
|
685
|
+
var TaskListQuerySchema = z12.object({
|
|
686
|
+
status: z12.string().max(500).optional(),
|
|
687
|
+
role: z12.string().max(500).optional(),
|
|
688
|
+
assignee: z12.string().max(500).optional(),
|
|
689
|
+
milestone: z12.string().max(500).optional(),
|
|
690
|
+
label: z12.string().max(500).optional(),
|
|
592
691
|
// §16.3 ТЗ перечисляет приоритет и тип среди фильтров доски и списка.
|
|
593
692
|
// Без них интерфейсу пришлось бы фильтровать уже загруженную страницу —
|
|
594
693
|
// на проекте крупнее одной страницы это даёт неверный результат.
|
|
595
|
-
priority:
|
|
596
|
-
type:
|
|
597
|
-
q:
|
|
598
|
-
cursor:
|
|
599
|
-
limit:
|
|
600
|
-
});
|
|
601
|
-
var BulkTaskIdsSchema =
|
|
602
|
-
var BulkTaskActionSchema =
|
|
603
|
-
|
|
604
|
-
action:
|
|
694
|
+
priority: z12.string().max(100).optional(),
|
|
695
|
+
type: z12.string().max(200).optional(),
|
|
696
|
+
q: z12.string().trim().max(200).optional(),
|
|
697
|
+
cursor: z12.string().max(4e3).optional(),
|
|
698
|
+
limit: z12.coerce.number().int().min(1).max(TASK_LIST_MAX_LIMIT).default(TASK_LIST_DEFAULT_LIMIT)
|
|
699
|
+
});
|
|
700
|
+
var BulkTaskIdsSchema = z12.array(IdSchema).min(1, "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u0443 \u0437\u0430\u0434\u0430\u0447\u0443").max(500, "\u041D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 500 \u0437\u0430\u0434\u0430\u0447 \u0437\u0430 \u043E\u0434\u0438\u043D \u0437\u0430\u043F\u0440\u043E\u0441");
|
|
701
|
+
var BulkTaskActionSchema = z12.discriminatedUnion("action", [
|
|
702
|
+
z12.object({
|
|
703
|
+
action: z12.literal("status"),
|
|
605
704
|
taskIds: BulkTaskIdsSchema,
|
|
606
705
|
status: TaskStatusSchema,
|
|
607
|
-
comment:
|
|
706
|
+
comment: z12.string().max(2e4).optional()
|
|
608
707
|
}),
|
|
609
|
-
|
|
610
|
-
action:
|
|
708
|
+
z12.object({
|
|
709
|
+
action: z12.literal("milestone"),
|
|
611
710
|
taskIds: BulkTaskIdsSchema,
|
|
612
711
|
milestoneId: IdSchema.nullable()
|
|
613
712
|
}),
|
|
614
|
-
|
|
615
|
-
action:
|
|
713
|
+
z12.object({
|
|
714
|
+
action: z12.literal("role"),
|
|
616
715
|
taskIds: BulkTaskIdsSchema,
|
|
617
|
-
roleKey:
|
|
716
|
+
roleKey: z12.string().min(1).max(60).nullable()
|
|
618
717
|
}),
|
|
619
|
-
|
|
620
|
-
action:
|
|
718
|
+
z12.object({
|
|
719
|
+
action: z12.literal("delete"),
|
|
621
720
|
taskIds: BulkTaskIdsSchema
|
|
622
721
|
})
|
|
623
722
|
]);
|
|
624
|
-
var BulkTaskResultItemSchema =
|
|
625
|
-
taskId:
|
|
626
|
-
ok:
|
|
627
|
-
error:
|
|
723
|
+
var BulkTaskResultItemSchema = z12.object({
|
|
724
|
+
taskId: z12.string(),
|
|
725
|
+
ok: z12.boolean(),
|
|
726
|
+
error: z12.object({ code: z12.string(), message: z12.string() }).optional()
|
|
628
727
|
});
|
|
629
728
|
|
|
630
729
|
// ../shared/src/dto/task-template.ts
|
|
631
|
-
var TaskTemplateNameSchema =
|
|
632
|
-
var TaskTemplateSchema =
|
|
730
|
+
var TaskTemplateNameSchema = z13.string().trim().min(1, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(100, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 100 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
731
|
+
var TaskTemplateSchema = z13.object({
|
|
633
732
|
/** Генерируется сервером при создании (`crypto.randomUUID()`), не вводится человеком. */
|
|
634
|
-
id:
|
|
733
|
+
id: z13.string().min(1),
|
|
635
734
|
/** Имя шаблона в списке выбора — НЕ заголовок будущей задачи (то поле — `title` ниже). */
|
|
636
735
|
name: TaskTemplateNameSchema,
|
|
637
736
|
type: TaskTypeSchema,
|
|
@@ -645,7 +744,7 @@ var TaskTemplateSchema = z12.object({
|
|
|
645
744
|
descriptionMd: TaskDescriptionSchema.default(""),
|
|
646
745
|
priority: TaskPrioritySchema.default(Priority.P2),
|
|
647
746
|
executor: TaskExecutorSchema.default(Executor.ANY),
|
|
648
|
-
roleKey:
|
|
747
|
+
roleKey: z13.string().min(1).max(60).optional(),
|
|
649
748
|
labels: TaskLabelsSchema.default([]),
|
|
650
749
|
acceptance: TaskAcceptanceSchema.optional(),
|
|
651
750
|
estimateMin: TaskEstimateMinSchema.optional()
|
|
@@ -661,23 +760,23 @@ var TaskTemplateSchema = z12.object({
|
|
|
661
760
|
// метаданные — редкий случай для многоразового шаблона, при
|
|
662
761
|
// необходимости человек добавит их на созданной задаче.
|
|
663
762
|
});
|
|
664
|
-
var TaskTemplatesSchema =
|
|
763
|
+
var TaskTemplatesSchema = z13.array(TaskTemplateSchema).max(50, "\u041D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 50 \u0448\u0430\u0431\u043B\u043E\u043D\u043E\u0432");
|
|
665
764
|
var TaskTemplateInputSchema = TaskTemplateSchema.omit({ id: true });
|
|
666
765
|
|
|
667
766
|
// ../shared/src/settings/project-settings.ts
|
|
668
767
|
var taskStatusValues2 = Object.values(TaskStatus);
|
|
669
|
-
var TaskStatusSchema2 =
|
|
670
|
-
var BoardSettingsSchema =
|
|
671
|
-
hiddenStatuses:
|
|
672
|
-
mergedColumns:
|
|
673
|
-
});
|
|
674
|
-
var NotificationSettingsSchema =
|
|
675
|
-
telegram:
|
|
676
|
-
email:
|
|
677
|
-
});
|
|
678
|
-
var ProjectSettingsSchema =
|
|
679
|
-
autoAccept:
|
|
680
|
-
requireTests:
|
|
768
|
+
var TaskStatusSchema2 = z14.enum(taskStatusValues2);
|
|
769
|
+
var BoardSettingsSchema = z14.object({
|
|
770
|
+
hiddenStatuses: z14.array(TaskStatusSchema2).default([]),
|
|
771
|
+
mergedColumns: z14.array(z14.array(TaskStatusSchema2)).default([])
|
|
772
|
+
});
|
|
773
|
+
var NotificationSettingsSchema = z14.object({
|
|
774
|
+
telegram: z14.boolean().default(false),
|
|
775
|
+
email: z14.boolean().default(false)
|
|
776
|
+
});
|
|
777
|
+
var ProjectSettingsSchema = z14.object({
|
|
778
|
+
autoAccept: z14.boolean().default(false),
|
|
779
|
+
requireTests: z14.boolean().default(true),
|
|
681
780
|
/**
|
|
682
781
|
* Не давать человеку принять задачу, пока проверки GitHub по последнему
|
|
683
782
|
* коммиту красные.
|
|
@@ -699,7 +798,7 @@ var ProjectSettingsSchema = z13.object({
|
|
|
699
798
|
* настройке — иначе получилось бы обещание, которого настройка не
|
|
700
799
|
* держит.
|
|
701
800
|
*/
|
|
702
|
-
requireGreenChecks:
|
|
801
|
+
requireGreenChecks: z14.boolean().default(false),
|
|
703
802
|
/**
|
|
704
803
|
* Заводить задачу на ревью, когда для задачи открывается pull request.
|
|
705
804
|
*
|
|
@@ -711,19 +810,19 @@ var ProjectSettingsSchema = z13.object({
|
|
|
711
810
|
* начать плодить задачи в уже работающих проектах — не то, чего от
|
|
712
811
|
* обновления ждут.
|
|
713
812
|
*/
|
|
714
|
-
reviewTaskOnPr:
|
|
813
|
+
reviewTaskOnPr: z14.boolean().default(false),
|
|
715
814
|
/**
|
|
716
815
|
* Ключ роли, на которую вешается задача ревью (`RoleDefinition.key`).
|
|
717
816
|
* Пусто — задача заводится без роли и видна всей команде проекта.
|
|
718
817
|
*/
|
|
719
|
-
reviewRoleKey:
|
|
720
|
-
maxParallelTasksPerAgent:
|
|
721
|
-
leaseTtlSec:
|
|
722
|
-
taskTimeoutMin:
|
|
723
|
-
contextResetAfterTasks:
|
|
724
|
-
branchTemplate:
|
|
725
|
-
commitTemplate:
|
|
726
|
-
stopPatternsOverride:
|
|
818
|
+
reviewRoleKey: z14.string().trim().min(1).max(60).optional(),
|
|
819
|
+
maxParallelTasksPerAgent: z14.number().int().positive().default(1),
|
|
820
|
+
leaseTtlSec: z14.number().int().positive().default(120),
|
|
821
|
+
taskTimeoutMin: z14.number().int().positive().default(90),
|
|
822
|
+
contextResetAfterTasks: z14.number().int().positive().default(8),
|
|
823
|
+
branchTemplate: z14.string().min(1).default("task/{key}-{slug}"),
|
|
824
|
+
commitTemplate: z14.string().min(1).default("{key}: {title}"),
|
|
825
|
+
stopPatternsOverride: z14.array(z14.string()).optional(),
|
|
727
826
|
notifications: NotificationSettingsSchema.default({ telegram: false, email: false }),
|
|
728
827
|
board: BoardSettingsSchema.default({ hiddenStatuses: [], mergedColumns: [] }),
|
|
729
828
|
// Шаблоны задач (§16.3 ТЗ: «Шаблоны задач по типу (настраиваются в
|
|
@@ -733,32 +832,32 @@ var ProjectSettingsSchema = z13.object({
|
|
|
733
832
|
});
|
|
734
833
|
|
|
735
834
|
// ../shared/src/dto/project.ts
|
|
736
|
-
var ProjectKeySchema =
|
|
737
|
-
var ProjectNameSchema =
|
|
738
|
-
var ProjectDescriptionSchema =
|
|
835
|
+
var ProjectKeySchema = z15.string().min(2, "\u041A\u043B\u044E\u0447 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u043A\u043E\u0440\u043E\u0447\u0435 2 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432").max(8, "\u041A\u043B\u044E\u0447 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 8 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432").regex(/^[A-Z][A-Z0-9]*$/, "\u041A\u043B\u044E\u0447: \u0437\u0430\u0433\u043B\u0430\u0432\u043D\u044B\u0435 \u043B\u0430\u0442\u0438\u043D\u0441\u043A\u0438\u0435 \u0431\u0443\u043A\u0432\u044B \u0438 \u0446\u0438\u0444\u0440\u044B, \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442\u0441\u044F \u0441 \u0431\u0443\u043A\u0432\u044B");
|
|
836
|
+
var ProjectNameSchema = z15.string().trim().min(1, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(100, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 100 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
837
|
+
var ProjectDescriptionSchema = z15.string().max(5e3, "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 5000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
739
838
|
var ProjectSettingsRecordSchema = ProjectSettingsSchema.extend({
|
|
740
|
-
autonomousConfirmedAt:
|
|
839
|
+
autonomousConfirmedAt: z15.coerce.date().optional()
|
|
741
840
|
});
|
|
742
841
|
var UpdateProjectSettingsSchema = ProjectSettingsRecordSchema.partial();
|
|
743
|
-
var ProjectModeSchema =
|
|
744
|
-
var ProjectStatusSchema =
|
|
842
|
+
var ProjectModeSchema = z15.enum([ProjectMode.AUTONOMOUS, ProjectMode.APPROVAL]);
|
|
843
|
+
var ProjectStatusSchema = z15.enum([
|
|
745
844
|
ProjectStatus.ACTIVE,
|
|
746
845
|
ProjectStatus.PAUSED,
|
|
747
846
|
ProjectStatus.ARCHIVED
|
|
748
847
|
]);
|
|
749
|
-
var GitModeSchema =
|
|
750
|
-
var ProjectDateSchema =
|
|
751
|
-
var NewProjectMilestoneSchema =
|
|
752
|
-
name:
|
|
848
|
+
var GitModeSchema = z15.enum([GitMode.DIRECT, GitMode.PR]);
|
|
849
|
+
var ProjectDateSchema = z15.coerce.date();
|
|
850
|
+
var NewProjectMilestoneSchema = z15.object({
|
|
851
|
+
name: z15.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435").max(200),
|
|
753
852
|
dueAt: ProjectDateSchema.optional()
|
|
754
853
|
});
|
|
755
|
-
var CreateProjectSchema =
|
|
854
|
+
var CreateProjectSchema = z15.object({
|
|
756
855
|
name: ProjectNameSchema,
|
|
757
856
|
key: ProjectKeySchema.optional(),
|
|
758
857
|
description: ProjectDescriptionSchema.optional(),
|
|
759
858
|
mode: ProjectModeSchema.default(ProjectMode.APPROVAL),
|
|
760
859
|
gitMode: GitModeSchema.default(GitMode.DIRECT),
|
|
761
|
-
autonomousConfirmed:
|
|
860
|
+
autonomousConfirmed: z15.boolean().optional(),
|
|
762
861
|
startAt: ProjectDateSchema.optional(),
|
|
763
862
|
targetAt: ProjectDateSchema.optional(),
|
|
764
863
|
/**
|
|
@@ -767,15 +866,15 @@ var CreateProjectSchema = z14.object({
|
|
|
767
866
|
* второго запроса проект оставался бы без людей, и человек не понял
|
|
768
867
|
* бы, создался он или нет.
|
|
769
868
|
*/
|
|
770
|
-
memberIds:
|
|
771
|
-
milestones:
|
|
869
|
+
memberIds: z15.array(z15.string().min(1)).max(100).optional(),
|
|
870
|
+
milestones: z15.array(NewProjectMilestoneSchema).max(50).optional()
|
|
772
871
|
}).refine((data) => !data.startAt || !data.targetAt || data.startAt <= data.targetAt, {
|
|
773
872
|
// Срок раньше начала — почти всегда опечатка в одном из полей, и
|
|
774
873
|
// молча сохранённая, она потом показывается как «просрочен с первого дня».
|
|
775
874
|
message: "\u0414\u0430\u0442\u0430 \u0446\u0435\u043B\u0438 \u0440\u0430\u043D\u044C\u0448\u0435 \u0434\u0430\u0442\u044B \u043D\u0430\u0447\u0430\u043B\u0430",
|
|
776
875
|
path: ["targetAt"]
|
|
777
876
|
});
|
|
778
|
-
var UpdateProjectSchema =
|
|
877
|
+
var UpdateProjectSchema = z15.object({
|
|
779
878
|
name: ProjectNameSchema.optional(),
|
|
780
879
|
key: ProjectKeySchema.optional(),
|
|
781
880
|
description: ProjectDescriptionSchema.nullable().optional(),
|
|
@@ -785,28 +884,28 @@ var UpdateProjectSchema = z14.object({
|
|
|
785
884
|
startAt: ProjectDateSchema.nullable().optional(),
|
|
786
885
|
targetAt: ProjectDateSchema.nullable().optional(),
|
|
787
886
|
settings: UpdateProjectSettingsSchema.optional(),
|
|
788
|
-
autonomousConfirmed:
|
|
887
|
+
autonomousConfirmed: z15.boolean().optional()
|
|
789
888
|
}).refine((data) => Object.keys(data).length > 0, {
|
|
790
889
|
message: "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u043E \u043F\u043E\u043B\u0435"
|
|
791
890
|
});
|
|
792
891
|
|
|
793
892
|
// ../shared/src/dto/repository.ts
|
|
794
|
-
import { z as
|
|
795
|
-
var RepositoryUrlSchema =
|
|
893
|
+
import { z as z16 } from "zod";
|
|
894
|
+
var RepositoryUrlSchema = z16.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0430\u0434\u0440\u0435\u0441 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F").max(500).refine(
|
|
796
895
|
(value) => /^(https?:\/\/|ssh:\/\/|git@)/.test(value),
|
|
797
896
|
"\u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u043B\u0436\u0435\u043D \u043D\u0430\u0447\u0438\u043D\u0430\u0442\u044C\u0441\u044F \u0441 https://, ssh:// \u0438\u043B\u0438 git@"
|
|
798
897
|
).refine(
|
|
799
898
|
(value) => inferGitProvider(value) !== GitProvider.GITHUB,
|
|
800
899
|
"\u0420\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0438 GitHub \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0430\u044E\u0442\u0441\u044F \u0447\u0435\u0440\u0435\u0437 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u2014 \u0432\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0438\u0437 \u0441\u043F\u0438\u0441\u043A\u0430"
|
|
801
900
|
);
|
|
802
|
-
var DefaultBranchSchema =
|
|
803
|
-
var PathHintSchema =
|
|
804
|
-
var CreateRepositorySchema =
|
|
901
|
+
var DefaultBranchSchema = z16.string().trim().min(1).max(200);
|
|
902
|
+
var PathHintSchema = z16.string().trim().max(300);
|
|
903
|
+
var CreateRepositorySchema = z16.object({
|
|
805
904
|
url: RepositoryUrlSchema,
|
|
806
905
|
defaultBranch: DefaultBranchSchema.optional(),
|
|
807
906
|
pathHint: PathHintSchema.optional()
|
|
808
907
|
});
|
|
809
|
-
var UpdateRepositorySchema =
|
|
908
|
+
var UpdateRepositorySchema = z16.object({
|
|
810
909
|
url: RepositoryUrlSchema.optional(),
|
|
811
910
|
defaultBranch: DefaultBranchSchema.optional(),
|
|
812
911
|
// `null` — «убрать путь», отличается от «поле не прислали».
|
|
@@ -814,11 +913,11 @@ var UpdateRepositorySchema = z15.object({
|
|
|
814
913
|
}).refine((data) => Object.keys(data).length > 0, {
|
|
815
914
|
message: "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u043E \u043F\u043E\u043B\u0435"
|
|
816
915
|
});
|
|
817
|
-
var ConnectGithubRepositorySchema =
|
|
916
|
+
var ConnectGithubRepositorySchema = z16.object({
|
|
818
917
|
/** Идентификатор НАШЕЙ записи установки, а не номер установки в GitHub. */
|
|
819
|
-
installationId:
|
|
918
|
+
installationId: z16.string().min(1, "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0430\u043A\u043A\u0430\u0443\u043D\u0442 GitHub"),
|
|
820
919
|
/** `owner/repo` — ровно в том виде, в каком его отдал GitHub. */
|
|
821
|
-
fullName:
|
|
920
|
+
fullName: z16.string().trim().min(3, "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0439").max(300).regex(/^[^/\s]+\/[^/\s]+$/, "\u041E\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044F owner/repo"),
|
|
822
921
|
pathHint: PathHintSchema.optional()
|
|
823
922
|
});
|
|
824
923
|
function extractHost(url) {
|
|
@@ -839,26 +938,26 @@ function inferGitProvider(url) {
|
|
|
839
938
|
}
|
|
840
939
|
|
|
841
940
|
// ../shared/src/dto/role.ts
|
|
842
|
-
import { z as
|
|
843
|
-
var RoleNameSchema =
|
|
844
|
-
var RoleColorSchema =
|
|
845
|
-
var CreateRoleSchema =
|
|
941
|
+
import { z as z17 } from "zod";
|
|
942
|
+
var RoleNameSchema = z17.string().trim().min(1, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(60, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 60 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
943
|
+
var RoleColorSchema = z17.string().regex(/^#[0-9a-fA-F]{6}$/, "\u0426\u0432\u0435\u0442: hex-\u0444\u043E\u0440\u043C\u0430\u0442, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 #3B82F6");
|
|
944
|
+
var CreateRoleSchema = z17.object({
|
|
846
945
|
name: RoleNameSchema,
|
|
847
946
|
color: RoleColorSchema,
|
|
848
|
-
defaultTrustProfileId:
|
|
947
|
+
defaultTrustProfileId: z17.string().optional()
|
|
849
948
|
});
|
|
850
|
-
var UpdateRoleSchema =
|
|
949
|
+
var UpdateRoleSchema = z17.object({
|
|
851
950
|
name: RoleNameSchema.optional(),
|
|
852
951
|
color: RoleColorSchema.optional(),
|
|
853
|
-
defaultTrustProfileId:
|
|
952
|
+
defaultTrustProfileId: z17.string().nullable().optional()
|
|
854
953
|
}).refine((data) => Object.keys(data).length > 0, {
|
|
855
954
|
message: "\u041D\u0443\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u043E \u043F\u043E\u043B\u0435"
|
|
856
955
|
});
|
|
857
956
|
|
|
858
957
|
// ../shared/src/dto/saved-filter.ts
|
|
859
|
-
import { z as
|
|
860
|
-
var SavedFilterNameSchema =
|
|
861
|
-
var SavedFilterQuerySchema =
|
|
958
|
+
import { z as z18 } from "zod";
|
|
959
|
+
var SavedFilterNameSchema = z18.string().trim().min(1, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E").max(80, "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 80 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
960
|
+
var SavedFilterQuerySchema = z18.object({
|
|
862
961
|
/**
|
|
863
962
|
* Статусы задач. Появились позже остальных полей — 11 сентября 2026,
|
|
864
963
|
* когда список и доска стали двумя видами одной страницы: у списка
|
|
@@ -868,20 +967,20 @@ var SavedFilterQuerySchema = z17.object({
|
|
|
868
967
|
* до этого дня, поля не содержат вовсе, и без значения по умолчанию
|
|
869
968
|
* разбор ронял бы чужой сохранённый фильтр.
|
|
870
969
|
*/
|
|
871
|
-
statuses:
|
|
872
|
-
roles:
|
|
873
|
-
assignees:
|
|
874
|
-
milestones:
|
|
875
|
-
labels:
|
|
876
|
-
priorities:
|
|
877
|
-
types:
|
|
878
|
-
q:
|
|
879
|
-
});
|
|
880
|
-
var CreateSavedFilterSchema =
|
|
970
|
+
statuses: z18.array(TaskStatusSchema).max(11).default([]),
|
|
971
|
+
roles: z18.array(z18.string().min(1)).max(50).default([]),
|
|
972
|
+
assignees: z18.array(z18.string().min(1)).max(50).default([]),
|
|
973
|
+
milestones: z18.array(z18.string().min(1)).max(50).default([]),
|
|
974
|
+
labels: z18.array(TaskLabelSchema).max(30).default([]),
|
|
975
|
+
priorities: z18.array(TaskPrioritySchema).max(4).default([]),
|
|
976
|
+
types: z18.array(TaskTypeSchema).max(7).default([]),
|
|
977
|
+
q: z18.string().trim().max(200).default("")
|
|
978
|
+
});
|
|
979
|
+
var CreateSavedFilterSchema = z18.object({
|
|
881
980
|
name: SavedFilterNameSchema,
|
|
882
981
|
query: SavedFilterQuerySchema
|
|
883
982
|
});
|
|
884
|
-
var UpdateSavedFilterSchema =
|
|
983
|
+
var UpdateSavedFilterSchema = z18.object({
|
|
885
984
|
name: SavedFilterNameSchema.optional(),
|
|
886
985
|
query: SavedFilterQuerySchema.optional()
|
|
887
986
|
}).refine((data) => Object.keys(data).length > 0, {
|
|
@@ -889,20 +988,20 @@ var UpdateSavedFilterSchema = z17.object({
|
|
|
889
988
|
});
|
|
890
989
|
|
|
891
990
|
// ../shared/src/dto/task-dependency.ts
|
|
892
|
-
import { z as
|
|
893
|
-
var TaskDependencyKindSchema =
|
|
894
|
-
var IdSchema2 =
|
|
895
|
-
var CreateTaskDependencySchema =
|
|
991
|
+
import { z as z19 } from "zod";
|
|
992
|
+
var TaskDependencyKindSchema = z19.enum([DepKind.BLOCKS, DepKind.RELATES]);
|
|
993
|
+
var IdSchema2 = z19.string().min(1);
|
|
994
|
+
var CreateTaskDependencySchema = z19.object({
|
|
896
995
|
toId: IdSchema2,
|
|
897
996
|
kind: TaskDependencyKindSchema.default(DepKind.BLOCKS)
|
|
898
997
|
});
|
|
899
|
-
var DeleteTaskDependencySchema =
|
|
998
|
+
var DeleteTaskDependencySchema = z19.object({
|
|
900
999
|
toId: IdSchema2
|
|
901
1000
|
});
|
|
902
1001
|
|
|
903
1002
|
// ../shared/src/dto/task-event.ts
|
|
904
|
-
import { z as
|
|
905
|
-
var TaskEventKindSchema =
|
|
1003
|
+
import { z as z20 } from "zod";
|
|
1004
|
+
var TaskEventKindSchema = z20.enum([
|
|
906
1005
|
EventKind.COMMENT,
|
|
907
1006
|
EventKind.STATUS,
|
|
908
1007
|
EventKind.ASSIGN,
|
|
@@ -913,58 +1012,58 @@ var TaskEventKindSchema = z19.enum([
|
|
|
913
1012
|
EventKind.APPROVAL,
|
|
914
1013
|
EventKind.SYSTEM
|
|
915
1014
|
]);
|
|
916
|
-
var TaskCommentBodySchema =
|
|
917
|
-
var CreateTaskEventSchema =
|
|
1015
|
+
var TaskCommentBodySchema = z20.string().trim().min(1, "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u044B\u043C").max(2e4, "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 20000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
1016
|
+
var CreateTaskEventSchema = z20.object({
|
|
918
1017
|
bodyMd: TaskCommentBodySchema
|
|
919
1018
|
});
|
|
920
|
-
var TaskCommentPayloadSchema =
|
|
921
|
-
var TaskEditPayloadSchema =
|
|
922
|
-
fields:
|
|
1019
|
+
var TaskCommentPayloadSchema = z20.object({ bodyMd: TaskCommentBodySchema });
|
|
1020
|
+
var TaskEditPayloadSchema = z20.object({
|
|
1021
|
+
fields: z20.record(z20.string(), z20.object({ from: z20.unknown(), to: z20.unknown() }))
|
|
923
1022
|
});
|
|
924
|
-
var TaskAssignPayloadSchema =
|
|
925
|
-
from:
|
|
926
|
-
to:
|
|
1023
|
+
var TaskAssignPayloadSchema = z20.object({
|
|
1024
|
+
from: z20.string().nullable(),
|
|
1025
|
+
to: z20.string().nullable()
|
|
927
1026
|
});
|
|
928
1027
|
var TASK_EVENT_LIST_DEFAULT_LIMIT = 25;
|
|
929
1028
|
var TASK_EVENT_LIST_MAX_LIMIT = 100;
|
|
930
|
-
var ListTaskEventsQuerySchema =
|
|
1029
|
+
var ListTaskEventsQuerySchema = z20.object({
|
|
931
1030
|
/** CSV нескольких kind — как остальные CSV-фильтры задач (lib/tasks/filters.ts). */
|
|
932
|
-
kind:
|
|
933
|
-
cursor:
|
|
934
|
-
limit:
|
|
1031
|
+
kind: z20.string().max(300).optional(),
|
|
1032
|
+
cursor: z20.string().max(4e3).optional(),
|
|
1033
|
+
limit: z20.coerce.number().int().min(1).max(TASK_EVENT_LIST_MAX_LIMIT).default(TASK_EVENT_LIST_DEFAULT_LIMIT)
|
|
935
1034
|
});
|
|
936
1035
|
|
|
937
1036
|
// ../shared/src/dto/task-transition.ts
|
|
938
|
-
import { z as
|
|
939
|
-
var CommentSchema =
|
|
940
|
-
var TransitionTaskSchema =
|
|
1037
|
+
import { z as z21 } from "zod";
|
|
1038
|
+
var CommentSchema = z21.string().max(2e4, "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 20000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
1039
|
+
var TransitionTaskSchema = z21.object({
|
|
941
1040
|
to: TaskStatusSchema,
|
|
942
1041
|
comment: CommentSchema.optional()
|
|
943
1042
|
});
|
|
944
|
-
var AcceptTaskSchema =
|
|
1043
|
+
var AcceptTaskSchema = z21.object({
|
|
945
1044
|
comment: CommentSchema.optional()
|
|
946
1045
|
});
|
|
947
|
-
var ReturnTaskSchema =
|
|
1046
|
+
var ReturnTaskSchema = z21.object({
|
|
948
1047
|
comment: CommentSchema.min(1, "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u0441 \u043F\u0440\u0430\u0432\u043A\u0430\u043C\u0438 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D")
|
|
949
1048
|
});
|
|
950
|
-
var ReopenTaskSchema =
|
|
1049
|
+
var ReopenTaskSchema = z21.object({
|
|
951
1050
|
reason: CommentSchema.optional()
|
|
952
1051
|
});
|
|
953
|
-
var RequeueTaskSchema =
|
|
1052
|
+
var RequeueTaskSchema = z21.object({
|
|
954
1053
|
reason: CommentSchema.optional()
|
|
955
1054
|
});
|
|
956
1055
|
|
|
957
1056
|
// ../shared/src/dto/trash.ts
|
|
958
|
-
import { z as
|
|
959
|
-
var CommentSchema2 =
|
|
960
|
-
var RestoreTaskSchema =
|
|
1057
|
+
import { z as z22 } from "zod";
|
|
1058
|
+
var CommentSchema2 = z22.string().max(2e4, "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 20000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432");
|
|
1059
|
+
var RestoreTaskSchema = z22.object({
|
|
961
1060
|
comment: CommentSchema2.optional()
|
|
962
1061
|
});
|
|
963
1062
|
var TASK_TRASH_LIST_DEFAULT_LIMIT = 25;
|
|
964
1063
|
var TASK_TRASH_LIST_MAX_LIMIT = 100;
|
|
965
|
-
var TaskTrashListQuerySchema =
|
|
966
|
-
cursor:
|
|
967
|
-
limit:
|
|
1064
|
+
var TaskTrashListQuerySchema = z22.object({
|
|
1065
|
+
cursor: z22.string().max(4e3).optional(),
|
|
1066
|
+
limit: z22.coerce.number().int().min(1).max(TASK_TRASH_LIST_MAX_LIMIT).default(TASK_TRASH_LIST_DEFAULT_LIMIT)
|
|
968
1067
|
});
|
|
969
1068
|
|
|
970
1069
|
// ../shared/src/enums/collaboration.ts
|
|
@@ -1009,7 +1108,7 @@ var FAILING_CHECK_CONCLUSIONS = [
|
|
|
1009
1108
|
];
|
|
1010
1109
|
|
|
1011
1110
|
// ../shared/src/events/agent-events.ts
|
|
1012
|
-
import { z as
|
|
1111
|
+
import { z as z23 } from "zod";
|
|
1013
1112
|
var agentStatusValues = Object.values(AgentStatus);
|
|
1014
1113
|
var agentModeValues = Object.values(AgentMode);
|
|
1015
1114
|
var taskStatusValues3 = Object.values(TaskStatus);
|
|
@@ -1022,40 +1121,40 @@ var gitModeValues = Object.values(GitMode);
|
|
|
1022
1121
|
var questionStatusValues = Object.values(QuestionStatus);
|
|
1023
1122
|
var approvalKindValues = Object.values(ApprovalKind);
|
|
1024
1123
|
var approvalStatusValues = Object.values(ApprovalStatus);
|
|
1025
|
-
var trustBashModeSchema =
|
|
1026
|
-
var trustFilesModeSchema =
|
|
1027
|
-
var trustRulesSchema =
|
|
1028
|
-
bash:
|
|
1124
|
+
var trustBashModeSchema = z23.enum(["allow", "approve", "deny"]);
|
|
1125
|
+
var trustFilesModeSchema = z23.enum(["allow", "approve"]);
|
|
1126
|
+
var trustRulesSchema = z23.object({
|
|
1127
|
+
bash: z23.object({
|
|
1029
1128
|
mode: trustBashModeSchema,
|
|
1030
1129
|
// Regex-строки (§14.3 ТЗ) — не z.instanceof(RegExp): TrustRules это Json,
|
|
1031
1130
|
// должен сериализоваться в БД/по сокету как обычные строки.
|
|
1032
|
-
stopPatterns:
|
|
1033
|
-
allowPatterns:
|
|
1131
|
+
stopPatterns: z23.array(z23.string().min(1)),
|
|
1132
|
+
allowPatterns: z23.array(z23.string().min(1)).optional()
|
|
1034
1133
|
}),
|
|
1035
|
-
files:
|
|
1134
|
+
files: z23.object({
|
|
1036
1135
|
mode: trustFilesModeSchema,
|
|
1037
|
-
protectedPaths:
|
|
1136
|
+
protectedPaths: z23.array(z23.string().min(1))
|
|
1038
1137
|
}),
|
|
1039
|
-
git:
|
|
1040
|
-
allowPushDefault:
|
|
1041
|
-
allowForcePush:
|
|
1138
|
+
git: z23.object({
|
|
1139
|
+
allowPushDefault: z23.boolean(),
|
|
1140
|
+
allowForcePush: z23.boolean()
|
|
1042
1141
|
}),
|
|
1043
|
-
network:
|
|
1044
|
-
allowSsh:
|
|
1045
|
-
sshHostsAllow:
|
|
1142
|
+
network: z23.object({
|
|
1143
|
+
allowSsh: z23.boolean(),
|
|
1144
|
+
sshHostsAllow: z23.array(z23.string().min(1)).optional()
|
|
1046
1145
|
}),
|
|
1047
|
-
approvalTtlMin:
|
|
1048
|
-
});
|
|
1049
|
-
var agentSummarySchema =
|
|
1050
|
-
id:
|
|
1051
|
-
projectId:
|
|
1052
|
-
membershipId:
|
|
1053
|
-
name:
|
|
1054
|
-
roleKeys:
|
|
1055
|
-
status:
|
|
1056
|
-
mode:
|
|
1057
|
-
lastSeenAt:
|
|
1058
|
-
clientVersion:
|
|
1146
|
+
approvalTtlMin: z23.number().int().positive()
|
|
1147
|
+
});
|
|
1148
|
+
var agentSummarySchema = z23.object({
|
|
1149
|
+
id: z23.string().min(1),
|
|
1150
|
+
projectId: z23.string().min(1),
|
|
1151
|
+
membershipId: z23.string().min(1),
|
|
1152
|
+
name: z23.string().min(1),
|
|
1153
|
+
roleKeys: z23.array(z23.string().min(1)),
|
|
1154
|
+
status: z23.enum(agentStatusValues),
|
|
1155
|
+
mode: z23.enum(agentModeValues),
|
|
1156
|
+
lastSeenAt: z23.string().datetime().nullable(),
|
|
1157
|
+
clientVersion: z23.string().nullable(),
|
|
1059
1158
|
/**
|
|
1060
1159
|
* Вид агентской программы — СТРОКА, а не `agentKindSchema`.
|
|
1061
1160
|
*
|
|
@@ -1073,20 +1172,20 @@ var agentSummarySchema = z22.object({
|
|
|
1073
1172
|
* Поймано тестом `cli/connect.test.ts`, который как раз отвечает
|
|
1074
1173
|
* ack-ом без этого поля.
|
|
1075
1174
|
*/
|
|
1076
|
-
kind:
|
|
1077
|
-
currentTaskId:
|
|
1078
|
-
tasksCompletedInSession:
|
|
1079
|
-
});
|
|
1080
|
-
var agentCurrentTaskSummarySchema =
|
|
1081
|
-
id:
|
|
1082
|
-
number:
|
|
1083
|
-
title:
|
|
1084
|
-
status:
|
|
1085
|
-
});
|
|
1086
|
-
var agentHelloPayloadSchema =
|
|
1087
|
-
clientVersion:
|
|
1088
|
-
cwd:
|
|
1089
|
-
os:
|
|
1175
|
+
kind: z23.string().nullable().default(null),
|
|
1176
|
+
currentTaskId: z23.string().nullable(),
|
|
1177
|
+
tasksCompletedInSession: z23.number().int().nonnegative()
|
|
1178
|
+
});
|
|
1179
|
+
var agentCurrentTaskSummarySchema = z23.object({
|
|
1180
|
+
id: z23.string().min(1),
|
|
1181
|
+
number: z23.number().int().positive(),
|
|
1182
|
+
title: z23.string().min(1),
|
|
1183
|
+
status: z23.enum(taskStatusValues3)
|
|
1184
|
+
});
|
|
1185
|
+
var agentHelloPayloadSchema = z23.object({
|
|
1186
|
+
clientVersion: z23.string().min(1),
|
|
1187
|
+
cwd: z23.string().min(1),
|
|
1188
|
+
os: z23.string().min(1),
|
|
1090
1189
|
/**
|
|
1091
1190
|
* Какую агентскую программу человек подключил (реестр `AGENT_KINDS`).
|
|
1092
1191
|
*
|
|
@@ -1103,13 +1202,13 @@ var agentHelloPayloadSchema = z22.object({
|
|
|
1103
1202
|
* терпимости — опечатка вида доедет до БД; там она видна как
|
|
1104
1203
|
* «неизвестный агент», и это несопоставимо дешевле.
|
|
1105
1204
|
*/
|
|
1106
|
-
agentKind:
|
|
1205
|
+
agentKind: z23.string().min(1).max(64).optional(),
|
|
1107
1206
|
/**
|
|
1108
1207
|
* Версия самой агентской программы: Claude Code, Codex, Cursor…
|
|
1109
1208
|
* `clientVersion` выше — версия НАШЕГО пакета `@quiel/cli`, это разные
|
|
1110
1209
|
* числа, и путать их дорого при разборе инцидента.
|
|
1111
1210
|
*/
|
|
1112
|
-
agentVersion:
|
|
1211
|
+
agentVersion: z23.string().min(1).optional(),
|
|
1113
1212
|
/**
|
|
1114
1213
|
* Прежнее имя `agentVersion`, когда вид агента был ровно один.
|
|
1115
1214
|
*
|
|
@@ -1118,176 +1217,192 @@ var agentHelloPayloadSchema = z22.object({
|
|
|
1118
1217
|
* неподнявшиеся клиенты отваливаются». Новый клиент шлёт его только
|
|
1119
1218
|
* для Claude Code — для Codex поле с таким именем было бы неправдой.
|
|
1120
1219
|
*/
|
|
1121
|
-
claudeVersion:
|
|
1220
|
+
claudeVersion: z23.string().min(1).optional(),
|
|
1122
1221
|
// Роли, которыми клиент СЕБЯ считает — информационно (лог/диагностика
|
|
1123
1222
|
// рассинхрона), не авторизация: авторизующие `Agent.roleKeys` идут из
|
|
1124
1223
|
// БД (заданы при создании агента, REST §12 ТЗ), этот payload их не
|
|
1125
1224
|
// меняет. См. блок «ВОПРОСЫ» отчёта P2-03.
|
|
1126
|
-
roleKeys:
|
|
1127
|
-
resumeToken:
|
|
1225
|
+
roleKeys: z23.array(z23.string().min(1)),
|
|
1226
|
+
resumeToken: z23.string().min(1).optional()
|
|
1128
1227
|
});
|
|
1129
|
-
var agentHelloAckSchema =
|
|
1228
|
+
var agentHelloAckSchema = z23.object({
|
|
1130
1229
|
agent: agentSummarySchema,
|
|
1131
1230
|
trust: trustRulesSchema,
|
|
1132
1231
|
currentTask: agentCurrentTaskSummarySchema.optional(),
|
|
1133
|
-
mode:
|
|
1232
|
+
mode: z23.enum(agentModeValues)
|
|
1134
1233
|
});
|
|
1135
|
-
var agentHeartbeatPayloadSchema =
|
|
1136
|
-
currentTaskId:
|
|
1137
|
-
resumeToken:
|
|
1138
|
-
status:
|
|
1234
|
+
var agentHeartbeatPayloadSchema = z23.object({
|
|
1235
|
+
currentTaskId: z23.string().min(1).optional(),
|
|
1236
|
+
resumeToken: z23.string().min(1).optional(),
|
|
1237
|
+
status: z23.enum(agentStatusValues)
|
|
1139
1238
|
});
|
|
1140
|
-
var agentHeartbeatAckSchema =
|
|
1141
|
-
ok:
|
|
1142
|
-
leaseExpiresAt:
|
|
1239
|
+
var agentHeartbeatAckSchema = z23.object({
|
|
1240
|
+
ok: z23.boolean(),
|
|
1241
|
+
leaseExpiresAt: z23.string().datetime().optional()
|
|
1143
1242
|
});
|
|
1144
|
-
var agentModePayloadSchema =
|
|
1145
|
-
mode:
|
|
1243
|
+
var agentModePayloadSchema = z23.object({
|
|
1244
|
+
mode: z23.enum(agentModeValues)
|
|
1146
1245
|
});
|
|
1147
|
-
var agentModeAckSchema =
|
|
1148
|
-
ok:
|
|
1149
|
-
mode:
|
|
1246
|
+
var agentModeAckSchema = z23.object({
|
|
1247
|
+
ok: z23.boolean(),
|
|
1248
|
+
mode: z23.enum(agentModeValues).optional()
|
|
1150
1249
|
});
|
|
1151
|
-
var taskPayloadMilestoneSchema =
|
|
1152
|
-
name:
|
|
1153
|
-
dueAt:
|
|
1250
|
+
var taskPayloadMilestoneSchema = z23.object({
|
|
1251
|
+
name: z23.string().min(1),
|
|
1252
|
+
dueAt: z23.string().datetime().nullable()
|
|
1154
1253
|
});
|
|
1155
|
-
var
|
|
1156
|
-
|
|
1254
|
+
var agentAttachmentSchema = z23.object({
|
|
1255
|
+
fileName: z23.string(),
|
|
1256
|
+
mimeType: z23.string(),
|
|
1257
|
+
size: z23.number().int().nonnegative(),
|
|
1258
|
+
downloadUrl: z23.string(),
|
|
1259
|
+
expiresInSeconds: z23.number().int().positive()
|
|
1260
|
+
});
|
|
1261
|
+
var taskPayloadTaskSchema = z23.object({
|
|
1262
|
+
id: z23.string().min(1),
|
|
1157
1263
|
/** Человекочитаемый ключ вида `ATL-42` (§7.5 ТЗ), НЕ то же, что `id`. */
|
|
1158
|
-
key:
|
|
1159
|
-
title:
|
|
1160
|
-
descriptionMd:
|
|
1161
|
-
type:
|
|
1162
|
-
priority:
|
|
1163
|
-
acceptance:
|
|
1164
|
-
attempts:
|
|
1165
|
-
reviewNotes:
|
|
1166
|
-
metadata:
|
|
1167
|
-
labels:
|
|
1168
|
-
milestone: taskPayloadMilestoneSchema.optional()
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1264
|
+
key: z23.string().min(1),
|
|
1265
|
+
title: z23.string().min(1),
|
|
1266
|
+
descriptionMd: z23.string(),
|
|
1267
|
+
type: z23.enum(taskTypeValues2),
|
|
1268
|
+
priority: z23.enum(priorityValues2),
|
|
1269
|
+
acceptance: z23.string(),
|
|
1270
|
+
attempts: z23.number().int().nonnegative(),
|
|
1271
|
+
reviewNotes: z23.string().optional(),
|
|
1272
|
+
metadata: z23.record(z23.string(), z23.unknown()),
|
|
1273
|
+
labels: z23.array(z23.string()),
|
|
1274
|
+
milestone: taskPayloadMilestoneSchema.optional(),
|
|
1275
|
+
/**
|
|
1276
|
+
* Файлы, приложенные человеком к задаче (задача владельца 18.09.2026).
|
|
1277
|
+
*
|
|
1278
|
+
* `default([])` НЕ УКРАШЕНИЕ: клиент 0.4.x про это поле не знает, а
|
|
1279
|
+
* сервер может оказаться новее его. Без умолчания старый клиент валил
|
|
1280
|
+
* бы разбор payload'а целиком — то есть переставал брать задачи из-за
|
|
1281
|
+
* поля, которое ему не нужно.
|
|
1282
|
+
*/
|
|
1283
|
+
attachments: z23.array(agentAttachmentSchema).default([])
|
|
1284
|
+
});
|
|
1285
|
+
var taskPayloadRepoSchema = z23.object({
|
|
1286
|
+
url: z23.string().min(1),
|
|
1287
|
+
defaultBranch: z23.string().min(1),
|
|
1288
|
+
pathHint: z23.string().nullable()
|
|
1289
|
+
});
|
|
1290
|
+
var taskPayloadProjectSchema = z23.object({
|
|
1291
|
+
key: z23.string().min(1),
|
|
1292
|
+
name: z23.string().min(1),
|
|
1293
|
+
mode: z23.enum(projectModeValues),
|
|
1294
|
+
gitMode: z23.enum(gitModeValues),
|
|
1295
|
+
repos: z23.array(taskPayloadRepoSchema),
|
|
1181
1296
|
/** Готовое имя ветки, `task/ATL-42-add-login` — считает сервер, не модель. */
|
|
1182
|
-
branchName:
|
|
1297
|
+
branchName: z23.string().min(1),
|
|
1183
1298
|
/** Префикс сообщения коммита, `ATL-42:`. */
|
|
1184
|
-
commitPrefix:
|
|
1299
|
+
commitPrefix: z23.string().min(1)
|
|
1185
1300
|
});
|
|
1186
|
-
var taskPayloadDependencySchema =
|
|
1187
|
-
key:
|
|
1188
|
-
title:
|
|
1189
|
-
status:
|
|
1190
|
-
resultMd:
|
|
1191
|
-
resultLinks:
|
|
1301
|
+
var taskPayloadDependencySchema = z23.object({
|
|
1302
|
+
key: z23.string().min(1),
|
|
1303
|
+
title: z23.string().min(1),
|
|
1304
|
+
status: z23.enum(taskStatusValues3),
|
|
1305
|
+
resultMd: z23.string().optional(),
|
|
1306
|
+
resultLinks: z23.array(z23.string()).optional()
|
|
1192
1307
|
});
|
|
1193
|
-
var taskPayloadOpenQuestionSchema =
|
|
1194
|
-
id:
|
|
1195
|
-
textMd:
|
|
1196
|
-
answerMd:
|
|
1308
|
+
var taskPayloadOpenQuestionSchema = z23.object({
|
|
1309
|
+
id: z23.string().min(1),
|
|
1310
|
+
textMd: z23.string(),
|
|
1311
|
+
answerMd: z23.string().optional()
|
|
1197
1312
|
});
|
|
1198
|
-
var taskPayloadTrustSchema =
|
|
1199
|
-
profileKey:
|
|
1200
|
-
summary:
|
|
1313
|
+
var taskPayloadTrustSchema = z23.object({
|
|
1314
|
+
profileKey: z23.string().min(1),
|
|
1315
|
+
summary: z23.string()
|
|
1201
1316
|
});
|
|
1202
|
-
var taskPayloadLeaseSchema =
|
|
1203
|
-
resumeToken:
|
|
1204
|
-
expiresAt:
|
|
1317
|
+
var taskPayloadLeaseSchema = z23.object({
|
|
1318
|
+
resumeToken: z23.string().min(1),
|
|
1319
|
+
expiresAt: z23.string().datetime()
|
|
1205
1320
|
});
|
|
1206
|
-
var taskPayloadSchema =
|
|
1321
|
+
var taskPayloadSchema = z23.object({
|
|
1207
1322
|
task: taskPayloadTaskSchema,
|
|
1208
1323
|
project: taskPayloadProjectSchema,
|
|
1209
|
-
dependencies:
|
|
1210
|
-
openQuestions:
|
|
1324
|
+
dependencies: z23.array(taskPayloadDependencySchema),
|
|
1325
|
+
openQuestions: z23.array(taskPayloadOpenQuestionSchema),
|
|
1211
1326
|
trust: taskPayloadTrustSchema,
|
|
1212
1327
|
lease: taskPayloadLeaseSchema
|
|
1213
1328
|
});
|
|
1214
|
-
var taskClaimPayloadSchema =
|
|
1329
|
+
var taskClaimPayloadSchema = z23.object({
|
|
1215
1330
|
/**
|
|
1216
1331
|
* Потолок 600 с — тот же, что §10.3 задаёт для `ask_human`
|
|
1217
1332
|
* («long-poll до 600 с»). Без верхней границы клиент может попросить
|
|
1218
1333
|
* сервер держать ack сутками, а это утечка обработчиков на сервере.
|
|
1219
1334
|
*/
|
|
1220
|
-
waitSec:
|
|
1221
|
-
});
|
|
1222
|
-
var taskClaimAckSchema =
|
|
1223
|
-
var taskStartPayloadSchema =
|
|
1224
|
-
taskId:
|
|
1225
|
-
resumeToken:
|
|
1226
|
-
});
|
|
1227
|
-
var taskStartAckSchema =
|
|
1228
|
-
var taskProgressLevelSchema =
|
|
1229
|
-
var taskProgressPayloadSchema =
|
|
1230
|
-
taskId:
|
|
1231
|
-
note:
|
|
1335
|
+
waitSec: z23.number().int().min(0).max(600)
|
|
1336
|
+
});
|
|
1337
|
+
var taskClaimAckSchema = z23.union([taskPayloadSchema, z23.object({ empty: z23.literal(true) })]);
|
|
1338
|
+
var taskStartPayloadSchema = z23.object({
|
|
1339
|
+
taskId: z23.string().min(1),
|
|
1340
|
+
resumeToken: z23.string().min(1)
|
|
1341
|
+
});
|
|
1342
|
+
var taskStartAckSchema = z23.object({ ok: z23.boolean() });
|
|
1343
|
+
var taskProgressLevelSchema = z23.enum(["debug", "info", "warn", "error"]);
|
|
1344
|
+
var taskProgressPayloadSchema = z23.object({
|
|
1345
|
+
taskId: z23.string().min(1),
|
|
1346
|
+
note: z23.string().min(1),
|
|
1232
1347
|
level: taskProgressLevelSchema.default("info")
|
|
1233
1348
|
});
|
|
1234
|
-
var taskProgressAckSchema =
|
|
1235
|
-
var taskReleasePayloadSchema =
|
|
1236
|
-
taskId:
|
|
1237
|
-
reason:
|
|
1349
|
+
var taskProgressAckSchema = z23.object({ ok: z23.boolean() });
|
|
1350
|
+
var taskReleasePayloadSchema = z23.object({
|
|
1351
|
+
taskId: z23.string().min(1),
|
|
1352
|
+
reason: z23.string().min(1)
|
|
1238
1353
|
});
|
|
1239
|
-
var taskReleaseAckSchema =
|
|
1240
|
-
var taskGetPayloadSchema =
|
|
1241
|
-
taskId:
|
|
1354
|
+
var taskReleaseAckSchema = z23.object({ ok: z23.boolean() });
|
|
1355
|
+
var taskGetPayloadSchema = z23.object({
|
|
1356
|
+
taskId: z23.string().min(1)
|
|
1242
1357
|
});
|
|
1243
1358
|
var taskGetAckSchema = taskPayloadSchema.omit({ lease: true }).extend({
|
|
1244
1359
|
lease: taskPayloadLeaseSchema.optional()
|
|
1245
1360
|
});
|
|
1246
|
-
var reportStatusSchema =
|
|
1247
|
-
var reportLinkSchema =
|
|
1248
|
-
kind:
|
|
1249
|
-
url:
|
|
1250
|
-
title:
|
|
1361
|
+
var reportStatusSchema = z23.enum(["success", "partial", "failed"]);
|
|
1362
|
+
var reportLinkSchema = z23.object({
|
|
1363
|
+
kind: z23.enum(["commit", "pr", "doc", "other"]),
|
|
1364
|
+
url: z23.string().min(1),
|
|
1365
|
+
title: z23.string().optional()
|
|
1251
1366
|
});
|
|
1252
|
-
var reportPayloadSchema =
|
|
1253
|
-
taskId:
|
|
1367
|
+
var reportPayloadSchema = z23.object({
|
|
1368
|
+
taskId: z23.string().min(1),
|
|
1254
1369
|
/**
|
|
1255
1370
|
* Ключ идемпотентности (P2-13): пара `taskId + resumeToken` однозначно
|
|
1256
1371
|
* определяет одну попытку сдачи. Повтор с тем же resumeToken обязан
|
|
1257
1372
|
* вернуть тот же `taskStatus`, а не сдать задачу дважды — модель
|
|
1258
1373
|
* ретраит вызов тула при обрыве связи, и это норма.
|
|
1259
1374
|
*/
|
|
1260
|
-
resumeToken:
|
|
1375
|
+
resumeToken: z23.string().min(1),
|
|
1261
1376
|
status: reportStatusSchema,
|
|
1262
|
-
resultMd:
|
|
1263
|
-
links:
|
|
1264
|
-
testResult:
|
|
1265
|
-
nextSteps:
|
|
1377
|
+
resultMd: z23.string().min(1),
|
|
1378
|
+
links: z23.array(reportLinkSchema),
|
|
1379
|
+
testResult: z23.enum(testResultValues2),
|
|
1380
|
+
nextSteps: z23.string().optional()
|
|
1266
1381
|
});
|
|
1267
|
-
var reportAckSchema =
|
|
1268
|
-
taskStatus:
|
|
1382
|
+
var reportAckSchema = z23.object({
|
|
1383
|
+
taskStatus: z23.enum(taskStatusValues3),
|
|
1269
1384
|
/** true, если этот ack — повтор уже принятой сдачи (идемпотентность). */
|
|
1270
|
-
duplicate:
|
|
1385
|
+
duplicate: z23.boolean().optional()
|
|
1271
1386
|
});
|
|
1272
|
-
var contextIncludeSchema =
|
|
1273
|
-
var contextGetPayloadSchema =
|
|
1274
|
-
taskId:
|
|
1275
|
-
include:
|
|
1387
|
+
var contextIncludeSchema = z23.enum(["spec", "decisions", "documents", "related", "repo"]);
|
|
1388
|
+
var contextGetPayloadSchema = z23.object({
|
|
1389
|
+
taskId: z23.string().min(1).optional(),
|
|
1390
|
+
include: z23.array(contextIncludeSchema).min(1)
|
|
1276
1391
|
});
|
|
1277
|
-
var contextDocumentFileSchema =
|
|
1392
|
+
var contextDocumentFileSchema = z23.object({
|
|
1278
1393
|
/** Имя как у человека на диске: `Спецификация v2.pdf`. */
|
|
1279
|
-
fileName:
|
|
1394
|
+
fileName: z23.string().min(1),
|
|
1280
1395
|
/** Временная ссылка на скачивание — агент читает файл сам. */
|
|
1281
|
-
downloadUrl:
|
|
1396
|
+
downloadUrl: z23.string().min(1),
|
|
1282
1397
|
/** Сколько секунд ссылка живёт: успеть скачать, а не отложить на потом. */
|
|
1283
|
-
expiresInSeconds:
|
|
1398
|
+
expiresInSeconds: z23.number().int().positive()
|
|
1284
1399
|
});
|
|
1285
|
-
var contextDocumentSchema =
|
|
1286
|
-
id:
|
|
1287
|
-
title:
|
|
1288
|
-
kind:
|
|
1400
|
+
var contextDocumentSchema = z23.object({
|
|
1401
|
+
id: z23.string().min(1),
|
|
1402
|
+
title: z23.string().min(1),
|
|
1403
|
+
kind: z23.string().min(1),
|
|
1289
1404
|
/** Текст документа. Пусто, если документ — файл: тогда заполнен `file`. */
|
|
1290
|
-
contentMd:
|
|
1405
|
+
contentMd: z23.string(),
|
|
1291
1406
|
/**
|
|
1292
1407
|
* Заполнен, если документ — файл.
|
|
1293
1408
|
*
|
|
@@ -1297,7 +1412,7 @@ var contextDocumentSchema = z22.object({
|
|
|
1297
1412
|
*/
|
|
1298
1413
|
file: contextDocumentFileSchema.nullable().optional()
|
|
1299
1414
|
});
|
|
1300
|
-
var contextPayloadSchema =
|
|
1415
|
+
var contextPayloadSchema = z23.object({
|
|
1301
1416
|
/**
|
|
1302
1417
|
* Замечания платформы к этому контексту — для агента, словами.
|
|
1303
1418
|
*
|
|
@@ -1312,341 +1427,377 @@ var contextPayloadSchema = z22.object({
|
|
|
1312
1427
|
* гаданию. Пустой ответ, который не объясняет свою пустоту, — та же
|
|
1313
1428
|
* молчаливая ошибка, что и пустая строка вместо файла.
|
|
1314
1429
|
*/
|
|
1315
|
-
notes:
|
|
1430
|
+
notes: z23.array(z23.string()).optional(),
|
|
1316
1431
|
spec: contextDocumentSchema.nullable().optional(),
|
|
1317
|
-
decisions:
|
|
1432
|
+
decisions: z23.array(contextDocumentSchema).optional(),
|
|
1318
1433
|
/** Все документы проекта — любого типа, включая спецификацию и решения. */
|
|
1319
|
-
documents:
|
|
1320
|
-
related:
|
|
1321
|
-
repo:
|
|
1322
|
-
repos:
|
|
1323
|
-
branchName:
|
|
1324
|
-
commitPrefix:
|
|
1434
|
+
documents: z23.array(contextDocumentSchema).optional(),
|
|
1435
|
+
related: z23.array(taskPayloadDependencySchema).optional(),
|
|
1436
|
+
repo: z23.object({
|
|
1437
|
+
repos: z23.array(taskPayloadRepoSchema),
|
|
1438
|
+
branchName: z23.string().optional(),
|
|
1439
|
+
commitPrefix: z23.string().optional()
|
|
1325
1440
|
}).optional()
|
|
1326
1441
|
});
|
|
1327
|
-
var agentRateLimitedPayloadSchema =
|
|
1328
|
-
retryAfterSec:
|
|
1329
|
-
taskId:
|
|
1442
|
+
var agentRateLimitedPayloadSchema = z23.object({
|
|
1443
|
+
retryAfterSec: z23.number().int().positive().optional(),
|
|
1444
|
+
taskId: z23.string().min(1).optional()
|
|
1330
1445
|
});
|
|
1331
|
-
var agentRateLimitedAckSchema =
|
|
1332
|
-
ok:
|
|
1446
|
+
var agentRateLimitedAckSchema = z23.object({
|
|
1447
|
+
ok: z23.boolean(),
|
|
1333
1448
|
/** Когда задача вернётся в очередь (§9.4 ТЗ: «через 2 ч»). */
|
|
1334
|
-
requeueAt:
|
|
1449
|
+
requeueAt: z23.string().datetime().optional()
|
|
1335
1450
|
});
|
|
1336
|
-
var projectStatePayloadSchema =
|
|
1337
|
-
projectId:
|
|
1338
|
-
paused:
|
|
1339
|
-
mode:
|
|
1451
|
+
var projectStatePayloadSchema = z23.object({
|
|
1452
|
+
projectId: z23.string().min(1),
|
|
1453
|
+
paused: z23.boolean(),
|
|
1454
|
+
mode: z23.enum(projectModeValues),
|
|
1340
1455
|
/** Причина паузы для модели; при `paused: false` не заполняется. */
|
|
1341
|
-
reason:
|
|
1342
|
-
});
|
|
1343
|
-
var questionSummarySchema =
|
|
1344
|
-
id:
|
|
1345
|
-
taskId:
|
|
1346
|
-
textMd:
|
|
1347
|
-
options:
|
|
1348
|
-
blocking:
|
|
1349
|
-
status:
|
|
1350
|
-
answerMd:
|
|
1351
|
-
answeredAt:
|
|
1352
|
-
createdAt:
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1456
|
+
reason: z23.string().optional()
|
|
1457
|
+
});
|
|
1458
|
+
var questionSummarySchema = z23.object({
|
|
1459
|
+
id: z23.string().min(1),
|
|
1460
|
+
taskId: z23.string().min(1).nullable(),
|
|
1461
|
+
textMd: z23.string(),
|
|
1462
|
+
options: z23.array(z23.string()),
|
|
1463
|
+
blocking: z23.boolean(),
|
|
1464
|
+
status: z23.enum(questionStatusValues),
|
|
1465
|
+
answerMd: z23.string().nullable(),
|
|
1466
|
+
answeredAt: z23.string().datetime().nullable(),
|
|
1467
|
+
createdAt: z23.string().datetime(),
|
|
1468
|
+
/**
|
|
1469
|
+
* Файлы, приложенные человеком К ОТВЕТУ (задача владельца 18.09.2026).
|
|
1470
|
+
*
|
|
1471
|
+
* Тот же вид, что у вложений задачи, и по той же причине ссылкой, а не
|
|
1472
|
+
* содержимым. `default([])` — чтобы клиент 0.4.x, не знающий поля, не
|
|
1473
|
+
* валил разбор ack'а целиком.
|
|
1474
|
+
*/
|
|
1475
|
+
attachments: z23.array(agentAttachmentSchema).default([])
|
|
1476
|
+
});
|
|
1477
|
+
var questionAskPayloadSchema = z23.object({
|
|
1478
|
+
taskId: z23.string().min(1).optional(),
|
|
1479
|
+
textMd: z23.string().min(1),
|
|
1480
|
+
targetRole: z23.string().min(1).optional(),
|
|
1481
|
+
targetMemberId: z23.string().min(1).optional(),
|
|
1482
|
+
options: z23.array(z23.string().min(1)).optional(),
|
|
1483
|
+
blocking: z23.boolean(),
|
|
1484
|
+
/**
|
|
1485
|
+
* Попросить человека приложить файл к ответу (задача владельца
|
|
1486
|
+
* 18.09.2026: «агент может попросить файлы»).
|
|
1487
|
+
*
|
|
1488
|
+
* ПРОСЬБА, А НЕ ТРЕБОВАНИЕ: форма ответа открывается сразу с выбором
|
|
1489
|
+
* файла, но ответить без вложений по-прежнему можно. Обязать человека
|
|
1490
|
+
* нельзя — он может и не иметь того файла, о котором речь.
|
|
1491
|
+
*/
|
|
1492
|
+
wantsFiles: z23.boolean().optional(),
|
|
1361
1493
|
/** Сколько ждать ответ в этом же вызове. 0 — не ждать, вернуть вопрос сразу. */
|
|
1362
|
-
waitSec:
|
|
1494
|
+
waitSec: z23.number().int().min(0).max(600).optional()
|
|
1363
1495
|
}).refine((v) => Boolean(v.targetRole) !== Boolean(v.targetMemberId), {
|
|
1364
1496
|
message: "\u041D\u0443\u0436\u0435\u043D \u0440\u043E\u0432\u043D\u043E \u043E\u0434\u0438\u043D \u0430\u0434\u0440\u0435\u0441\u0430\u0442: targetRole \u0418\u041B\u0418 targetMemberId"
|
|
1365
1497
|
});
|
|
1366
|
-
var questionAskAckSchema =
|
|
1498
|
+
var questionAskAckSchema = z23.object({
|
|
1367
1499
|
question: questionSummarySchema
|
|
1368
1500
|
});
|
|
1369
|
-
var questionWaitPayloadSchema =
|
|
1370
|
-
questionId:
|
|
1371
|
-
waitSec:
|
|
1501
|
+
var questionWaitPayloadSchema = z23.object({
|
|
1502
|
+
questionId: z23.string().min(1),
|
|
1503
|
+
waitSec: z23.number().int().min(0).max(600)
|
|
1372
1504
|
});
|
|
1373
|
-
var questionWaitAckSchema =
|
|
1505
|
+
var questionWaitAckSchema = z23.object({
|
|
1374
1506
|
question: questionSummarySchema
|
|
1375
1507
|
});
|
|
1376
|
-
var
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1508
|
+
var taskUsageEntrySchema = z23.object({
|
|
1509
|
+
/** Как модель назвал сам агент (`claude-opus-5`). Строка: список моделей меняется чаще схемы. */
|
|
1510
|
+
model: z23.string().min(1).max(200),
|
|
1511
|
+
/** Сколько обращений к модели дали эти числа. */
|
|
1512
|
+
requests: z23.number().int().nonnegative(),
|
|
1513
|
+
inputTokens: z23.number().int().nonnegative(),
|
|
1514
|
+
outputTokens: z23.number().int().nonnegative(),
|
|
1515
|
+
cacheReadTokens: z23.number().int().nonnegative(),
|
|
1516
|
+
cacheCreationTokens: z23.number().int().nonnegative()
|
|
1517
|
+
});
|
|
1518
|
+
var taskUsagePayloadSchema = z23.object({
|
|
1519
|
+
taskId: z23.string().min(1),
|
|
1520
|
+
/** Не больше десяти моделей за порцию — их у задачи одна-две, остальное признак ошибки. */
|
|
1521
|
+
entries: z23.array(taskUsageEntrySchema).min(1).max(10)
|
|
1522
|
+
});
|
|
1523
|
+
var taskUsageAckSchema = z23.object({ ok: z23.boolean() });
|
|
1524
|
+
var sessionLimitReachedPayloadSchema = z23.object({
|
|
1525
|
+
tasksCompletedInSession: z23.number().int().nonnegative()
|
|
1526
|
+
});
|
|
1527
|
+
var taskCreatePayloadSchema = z23.object({
|
|
1528
|
+
title: z23.string().min(1),
|
|
1529
|
+
descriptionMd: z23.string(),
|
|
1530
|
+
roleKey: z23.string().min(1).optional(),
|
|
1531
|
+
assigneeId: z23.string().min(1).optional(),
|
|
1532
|
+
type: z23.enum(taskTypeValues2),
|
|
1533
|
+
priority: z23.enum(priorityValues2),
|
|
1534
|
+
executor: z23.enum(executorValues2),
|
|
1535
|
+
blocksCurrent: z23.boolean(),
|
|
1536
|
+
acceptance: z23.string().optional(),
|
|
1537
|
+
labels: z23.array(z23.string().min(1)).optional()
|
|
1387
1538
|
}).refine((v) => Boolean(v.roleKey) !== Boolean(v.assigneeId), {
|
|
1388
1539
|
message: "\u041D\u0443\u0436\u0435\u043D \u0440\u043E\u0432\u043D\u043E \u043E\u0434\u0438\u043D \u0430\u0434\u0440\u0435\u0441\u0430\u0442: roleKey \u0418\u041B\u0418 assigneeId"
|
|
1389
1540
|
});
|
|
1390
|
-
var taskBriefSchema =
|
|
1391
|
-
id:
|
|
1392
|
-
key:
|
|
1393
|
-
title:
|
|
1394
|
-
type:
|
|
1395
|
-
status:
|
|
1396
|
-
priority:
|
|
1397
|
-
roleKey:
|
|
1398
|
-
assigneeId:
|
|
1399
|
-
labels:
|
|
1400
|
-
updatedAt:
|
|
1401
|
-
});
|
|
1402
|
-
var taskCreateAckSchema =
|
|
1541
|
+
var taskBriefSchema = z23.object({
|
|
1542
|
+
id: z23.string().min(1),
|
|
1543
|
+
key: z23.string().min(1),
|
|
1544
|
+
title: z23.string().min(1),
|
|
1545
|
+
type: z23.enum(taskTypeValues2),
|
|
1546
|
+
status: z23.enum(taskStatusValues3),
|
|
1547
|
+
priority: z23.enum(priorityValues2),
|
|
1548
|
+
roleKey: z23.string().min(1).nullable(),
|
|
1549
|
+
assigneeId: z23.string().min(1).nullable(),
|
|
1550
|
+
labels: z23.array(z23.string()),
|
|
1551
|
+
updatedAt: z23.string().datetime()
|
|
1552
|
+
});
|
|
1553
|
+
var taskCreateAckSchema = z23.object({
|
|
1403
1554
|
task: taskBriefSchema,
|
|
1404
1555
|
/** Во что ушла ТЕКУЩАЯ задача автора, если `blocksCurrent: true`. */
|
|
1405
|
-
currentTaskStatus:
|
|
1556
|
+
currentTaskStatus: z23.enum(taskStatusValues3).optional()
|
|
1406
1557
|
});
|
|
1407
|
-
var taskListPayloadSchema =
|
|
1408
|
-
status:
|
|
1409
|
-
roleKey:
|
|
1558
|
+
var taskListPayloadSchema = z23.object({
|
|
1559
|
+
status: z23.array(z23.enum(taskStatusValues3)).optional(),
|
|
1560
|
+
roleKey: z23.string().min(1).optional(),
|
|
1410
1561
|
/** Поиск по заголовку, без учёта регистра. */
|
|
1411
|
-
query:
|
|
1412
|
-
limit:
|
|
1413
|
-
});
|
|
1414
|
-
var taskListAckSchema =
|
|
1415
|
-
tasks:
|
|
1416
|
-
});
|
|
1417
|
-
var taskUpdatePayloadSchema =
|
|
1418
|
-
taskId:
|
|
1419
|
-
patch:
|
|
1420
|
-
progressNote:
|
|
1421
|
-
labels:
|
|
1422
|
-
estimateMin:
|
|
1562
|
+
query: z23.string().min(1).optional(),
|
|
1563
|
+
limit: z23.number().int().min(1).max(100).optional()
|
|
1564
|
+
});
|
|
1565
|
+
var taskListAckSchema = z23.object({
|
|
1566
|
+
tasks: z23.array(taskBriefSchema)
|
|
1567
|
+
});
|
|
1568
|
+
var taskUpdatePayloadSchema = z23.object({
|
|
1569
|
+
taskId: z23.string().min(1),
|
|
1570
|
+
patch: z23.object({
|
|
1571
|
+
progressNote: z23.string().min(1).optional(),
|
|
1572
|
+
labels: z23.array(z23.string().min(1)).optional(),
|
|
1573
|
+
estimateMin: z23.number().int().positive().optional()
|
|
1423
1574
|
}).refine((v) => Object.keys(v).length > 0, { message: "patch \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u044B\u043C" })
|
|
1424
1575
|
});
|
|
1425
|
-
var taskUpdateAckSchema =
|
|
1576
|
+
var taskUpdateAckSchema = z23.object({
|
|
1426
1577
|
task: taskBriefSchema
|
|
1427
1578
|
});
|
|
1428
|
-
var modeSetPayloadSchema =
|
|
1429
|
-
mode:
|
|
1579
|
+
var modeSetPayloadSchema = z23.object({
|
|
1580
|
+
mode: z23.enum(agentModeValues)
|
|
1430
1581
|
});
|
|
1431
|
-
var agentPausePayloadSchema =
|
|
1432
|
-
reason:
|
|
1582
|
+
var agentPausePayloadSchema = z23.object({
|
|
1583
|
+
reason: z23.string().min(1)
|
|
1433
1584
|
});
|
|
1434
1585
|
var trustUpdatedPayloadSchema = trustRulesSchema;
|
|
1435
|
-
var leaseLostPayloadSchema =
|
|
1436
|
-
taskId:
|
|
1437
|
-
reason:
|
|
1438
|
-
});
|
|
1439
|
-
var taskUpdatedAgentPayloadSchema =
|
|
1440
|
-
taskId:
|
|
1441
|
-
patch:
|
|
1442
|
-
});
|
|
1443
|
-
var questionAnsweredPayloadSchema =
|
|
1444
|
-
questionId:
|
|
1445
|
-
answerMd:
|
|
1446
|
-
});
|
|
1447
|
-
var approvalSummarySchema =
|
|
1448
|
-
id:
|
|
1449
|
-
taskId:
|
|
1450
|
-
kind:
|
|
1451
|
-
summary:
|
|
1452
|
-
status:
|
|
1453
|
-
expiresAt:
|
|
1454
|
-
decidedAt:
|
|
1455
|
-
createdAt:
|
|
1456
|
-
});
|
|
1457
|
-
var approvalRequestPayloadSchema =
|
|
1458
|
-
taskId:
|
|
1459
|
-
kind:
|
|
1460
|
-
summary:
|
|
1461
|
-
command:
|
|
1462
|
-
cwd:
|
|
1463
|
-
host:
|
|
1464
|
-
diff:
|
|
1586
|
+
var leaseLostPayloadSchema = z23.object({
|
|
1587
|
+
taskId: z23.string().min(1),
|
|
1588
|
+
reason: z23.string().min(1)
|
|
1589
|
+
});
|
|
1590
|
+
var taskUpdatedAgentPayloadSchema = z23.object({
|
|
1591
|
+
taskId: z23.string().min(1),
|
|
1592
|
+
patch: z23.record(z23.string(), z23.unknown()).optional()
|
|
1593
|
+
});
|
|
1594
|
+
var questionAnsweredPayloadSchema = z23.object({
|
|
1595
|
+
questionId: z23.string().min(1),
|
|
1596
|
+
answerMd: z23.string()
|
|
1597
|
+
});
|
|
1598
|
+
var approvalSummarySchema = z23.object({
|
|
1599
|
+
id: z23.string().min(1),
|
|
1600
|
+
taskId: z23.string().min(1),
|
|
1601
|
+
kind: z23.enum(approvalKindValues),
|
|
1602
|
+
summary: z23.string(),
|
|
1603
|
+
status: z23.enum(approvalStatusValues),
|
|
1604
|
+
expiresAt: z23.string().datetime(),
|
|
1605
|
+
decidedAt: z23.string().datetime().nullable(),
|
|
1606
|
+
createdAt: z23.string().datetime()
|
|
1607
|
+
});
|
|
1608
|
+
var approvalRequestPayloadSchema = z23.object({
|
|
1609
|
+
taskId: z23.string().min(1),
|
|
1610
|
+
kind: z23.enum(approvalKindValues),
|
|
1611
|
+
summary: z23.string().min(1),
|
|
1612
|
+
command: z23.string().min(1),
|
|
1613
|
+
cwd: z23.string().min(1),
|
|
1614
|
+
host: z23.string().min(1).optional(),
|
|
1615
|
+
diff: z23.string().optional(),
|
|
1465
1616
|
/** Сколько ждать решения в этом же вызове; 0 — не ждать. Потолок — как у вопросов. */
|
|
1466
|
-
waitSec:
|
|
1617
|
+
waitSec: z23.number().int().min(0).max(600).optional()
|
|
1467
1618
|
});
|
|
1468
|
-
var approvalRequestAckSchema =
|
|
1619
|
+
var approvalRequestAckSchema = z23.object({
|
|
1469
1620
|
approval: approvalSummarySchema,
|
|
1470
1621
|
/** Приходит только при `APPROVED` — одноразовый, привязан к команде и каталогу (§14.4 ТЗ). */
|
|
1471
|
-
oneTimeToken:
|
|
1622
|
+
oneTimeToken: z23.string().min(1).optional()
|
|
1472
1623
|
});
|
|
1473
|
-
var approvalWaitPayloadSchema =
|
|
1474
|
-
approvalId:
|
|
1475
|
-
waitSec:
|
|
1624
|
+
var approvalWaitPayloadSchema = z23.object({
|
|
1625
|
+
approvalId: z23.string().min(1),
|
|
1626
|
+
waitSec: z23.number().int().min(0).max(600)
|
|
1476
1627
|
});
|
|
1477
1628
|
var approvalWaitAckSchema = approvalRequestAckSchema;
|
|
1478
|
-
var approvalDecidedPayloadSchema =
|
|
1479
|
-
approvalId:
|
|
1480
|
-
status:
|
|
1481
|
-
oneTimeToken:
|
|
1482
|
-
});
|
|
1483
|
-
var agentPresenceUiPayloadSchema =
|
|
1484
|
-
projectId:
|
|
1485
|
-
agentId:
|
|
1486
|
-
status:
|
|
1487
|
-
lastSeenAt:
|
|
1488
|
-
currentTaskId:
|
|
1489
|
-
});
|
|
1490
|
-
var taskOpenPrPayloadSchema =
|
|
1491
|
-
taskId:
|
|
1629
|
+
var approvalDecidedPayloadSchema = z23.object({
|
|
1630
|
+
approvalId: z23.string().min(1),
|
|
1631
|
+
status: z23.enum([ApprovalStatus.APPROVED, ApprovalStatus.REJECTED]),
|
|
1632
|
+
oneTimeToken: z23.string().min(1).optional()
|
|
1633
|
+
});
|
|
1634
|
+
var agentPresenceUiPayloadSchema = z23.object({
|
|
1635
|
+
projectId: z23.string().min(1),
|
|
1636
|
+
agentId: z23.string().min(1),
|
|
1637
|
+
status: z23.enum(agentStatusValues),
|
|
1638
|
+
lastSeenAt: z23.string().datetime(),
|
|
1639
|
+
currentTaskId: z23.string().nullable().optional()
|
|
1640
|
+
});
|
|
1641
|
+
var taskOpenPrPayloadSchema = z23.object({
|
|
1642
|
+
taskId: z23.string().min(1),
|
|
1492
1643
|
/** Ветка, которую клиент уже отправил на remote. */
|
|
1493
|
-
branchName:
|
|
1644
|
+
branchName: z23.string().min(1),
|
|
1494
1645
|
/** Rebase на основную ветку не прошёл — PR помечается «conflicts» (§13.1 ТЗ). */
|
|
1495
|
-
conflicted:
|
|
1646
|
+
conflicted: z23.boolean().optional(),
|
|
1496
1647
|
/** Только пути файлов, никогда содержимое (§18 ТЗ). */
|
|
1497
|
-
conflictedFiles:
|
|
1648
|
+
conflictedFiles: z23.array(z23.string().min(1)).max(100).optional()
|
|
1498
1649
|
});
|
|
1499
|
-
var taskOpenPrAckSchema =
|
|
1500
|
-
url:
|
|
1501
|
-
number:
|
|
1650
|
+
var taskOpenPrAckSchema = z23.object({
|
|
1651
|
+
url: z23.string().url(),
|
|
1652
|
+
number: z23.number().int().positive(),
|
|
1502
1653
|
/** `false` — PR уже существовал для этой ветки, повторно не создавали. */
|
|
1503
|
-
created:
|
|
1654
|
+
created: z23.boolean()
|
|
1504
1655
|
});
|
|
1505
1656
|
|
|
1506
1657
|
// ../shared/src/events/ticket.ts
|
|
1507
|
-
import { z as
|
|
1508
|
-
var realtimeTicketPayloadSchema =
|
|
1509
|
-
sub:
|
|
1510
|
-
orgIds:
|
|
1511
|
-
projectIds:
|
|
1512
|
-
iat:
|
|
1513
|
-
exp:
|
|
1514
|
-
jti:
|
|
1658
|
+
import { z as z24 } from "zod";
|
|
1659
|
+
var realtimeTicketPayloadSchema = z24.object({
|
|
1660
|
+
sub: z24.string().min(1),
|
|
1661
|
+
orgIds: z24.array(z24.string().min(1)),
|
|
1662
|
+
projectIds: z24.array(z24.string().min(1)),
|
|
1663
|
+
iat: z24.number().int().positive(),
|
|
1664
|
+
exp: z24.number().int().positive(),
|
|
1665
|
+
jti: z24.string().min(1)
|
|
1515
1666
|
});
|
|
1516
|
-
var roomJoinRequestSchema =
|
|
1517
|
-
room:
|
|
1518
|
-
projectId:
|
|
1667
|
+
var roomJoinRequestSchema = z24.object({
|
|
1668
|
+
room: z24.string().min(1),
|
|
1669
|
+
projectId: z24.string().min(1).optional()
|
|
1519
1670
|
});
|
|
1520
1671
|
|
|
1521
1672
|
// ../shared/src/events/ui-events.ts
|
|
1522
|
-
import { z as
|
|
1673
|
+
import { z as z25 } from "zod";
|
|
1523
1674
|
var taskStatusValues4 = Object.values(TaskStatus);
|
|
1524
|
-
var taskCreatedPayloadSchema =
|
|
1525
|
-
taskId:
|
|
1526
|
-
projectId:
|
|
1527
|
-
orgId:
|
|
1528
|
-
});
|
|
1529
|
-
var taskUpdatedPayloadSchema =
|
|
1530
|
-
taskId:
|
|
1531
|
-
projectId:
|
|
1532
|
-
orgId:
|
|
1675
|
+
var taskCreatedPayloadSchema = z25.object({
|
|
1676
|
+
taskId: z25.string().min(1),
|
|
1677
|
+
projectId: z25.string().min(1),
|
|
1678
|
+
orgId: z25.string().min(1)
|
|
1679
|
+
});
|
|
1680
|
+
var taskUpdatedPayloadSchema = z25.object({
|
|
1681
|
+
taskId: z25.string().min(1),
|
|
1682
|
+
projectId: z25.string().min(1),
|
|
1683
|
+
orgId: z25.string().min(1),
|
|
1533
1684
|
// Необязательный частичный diff — подсказка для оптимистичного мерджа на
|
|
1534
1685
|
// клиенте. Не гарантирует полноты: клиент обязан доверять только REST.
|
|
1535
|
-
patch:
|
|
1686
|
+
patch: z25.record(z25.string(), z25.unknown()).optional()
|
|
1536
1687
|
});
|
|
1537
|
-
var taskDeletedPayloadSchema =
|
|
1538
|
-
taskId:
|
|
1539
|
-
projectId:
|
|
1540
|
-
orgId:
|
|
1688
|
+
var taskDeletedPayloadSchema = z25.object({
|
|
1689
|
+
taskId: z25.string().min(1),
|
|
1690
|
+
projectId: z25.string().min(1),
|
|
1691
|
+
orgId: z25.string().min(1)
|
|
1541
1692
|
});
|
|
1542
|
-
var taskMovedPayloadSchema =
|
|
1543
|
-
taskId:
|
|
1544
|
-
projectId:
|
|
1545
|
-
orgId:
|
|
1693
|
+
var taskMovedPayloadSchema = z25.object({
|
|
1694
|
+
taskId: z25.string().min(1),
|
|
1695
|
+
projectId: z25.string().min(1),
|
|
1696
|
+
orgId: z25.string().min(1),
|
|
1546
1697
|
// Новый статус/позиция — нужны доске (P1-11) для немедленного
|
|
1547
1698
|
// перемещения карточки без ожидания REST-рефетча.
|
|
1548
|
-
status:
|
|
1549
|
-
order:
|
|
1699
|
+
status: z25.enum(taskStatusValues4),
|
|
1700
|
+
order: z25.number()
|
|
1550
1701
|
});
|
|
1551
|
-
var notificationNewPayloadSchema =
|
|
1552
|
-
notificationId:
|
|
1702
|
+
var notificationNewPayloadSchema = z25.object({
|
|
1703
|
+
notificationId: z25.string().min(1),
|
|
1553
1704
|
// userId, не membershipId: `apps/realtime` адресует личную комнату
|
|
1554
1705
|
// `user:{userId}` (см. rooms.ts) — так же, как ticket.sub.
|
|
1555
|
-
userId:
|
|
1556
|
-
kind:
|
|
1557
|
-
title:
|
|
1558
|
-
body:
|
|
1559
|
-
link:
|
|
1560
|
-
});
|
|
1561
|
-
var futurePlaceholderPayloadSchema =
|
|
1562
|
-
projectId:
|
|
1706
|
+
userId: z25.string().min(1),
|
|
1707
|
+
kind: z25.string().min(1),
|
|
1708
|
+
title: z25.string().min(1),
|
|
1709
|
+
body: z25.string().optional(),
|
|
1710
|
+
link: z25.string().optional()
|
|
1711
|
+
});
|
|
1712
|
+
var futurePlaceholderPayloadSchema = z25.object({
|
|
1713
|
+
projectId: z25.string().min(1)
|
|
1563
1714
|
}).loose();
|
|
1564
|
-
var questionEventPayloadSchema =
|
|
1565
|
-
questionId:
|
|
1566
|
-
projectId:
|
|
1567
|
-
orgId:
|
|
1568
|
-
taskId:
|
|
1715
|
+
var questionEventPayloadSchema = z25.object({
|
|
1716
|
+
questionId: z25.string().min(1),
|
|
1717
|
+
projectId: z25.string().min(1),
|
|
1718
|
+
orgId: z25.string().min(1),
|
|
1719
|
+
taskId: z25.string().min(1).nullable().optional(),
|
|
1569
1720
|
/** Кому адресован — роль или конкретный участник; для фильтра «мне» в UI. */
|
|
1570
|
-
targetRole:
|
|
1571
|
-
targetMemberId:
|
|
1572
|
-
blocking:
|
|
1721
|
+
targetRole: z25.string().min(1).nullable().optional(),
|
|
1722
|
+
targetMemberId: z25.string().min(1).nullable().optional(),
|
|
1723
|
+
blocking: z25.boolean().optional()
|
|
1573
1724
|
});
|
|
1574
1725
|
var envelopeExtra = {
|
|
1575
|
-
publishedAt:
|
|
1726
|
+
publishedAt: z25.string().datetime().optional()
|
|
1576
1727
|
};
|
|
1577
|
-
var uiEventEnvelopeSchema =
|
|
1578
|
-
|
|
1579
|
-
event:
|
|
1728
|
+
var uiEventEnvelopeSchema = z25.discriminatedUnion("event", [
|
|
1729
|
+
z25.object({
|
|
1730
|
+
event: z25.literal("task:created"),
|
|
1580
1731
|
payload: taskCreatedPayloadSchema,
|
|
1581
1732
|
...envelopeExtra
|
|
1582
1733
|
}),
|
|
1583
|
-
|
|
1584
|
-
event:
|
|
1734
|
+
z25.object({
|
|
1735
|
+
event: z25.literal("task:updated"),
|
|
1585
1736
|
payload: taskUpdatedPayloadSchema,
|
|
1586
1737
|
...envelopeExtra
|
|
1587
1738
|
}),
|
|
1588
|
-
|
|
1589
|
-
event:
|
|
1739
|
+
z25.object({
|
|
1740
|
+
event: z25.literal("task:deleted"),
|
|
1590
1741
|
payload: taskDeletedPayloadSchema,
|
|
1591
1742
|
...envelopeExtra
|
|
1592
1743
|
}),
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
event:
|
|
1744
|
+
z25.object({ event: z25.literal("task:moved"), payload: taskMovedPayloadSchema, ...envelopeExtra }),
|
|
1745
|
+
z25.object({
|
|
1746
|
+
event: z25.literal("notification:new"),
|
|
1596
1747
|
payload: notificationNewPayloadSchema,
|
|
1597
1748
|
...envelopeExtra
|
|
1598
1749
|
}),
|
|
1599
1750
|
// Заготовки под фазу 2+ (§11.3 ТЗ упоминает `question:*`/`approval:*` как
|
|
1600
1751
|
// группы, а не точные имена — ниже разумное предположение, подлежит
|
|
1601
1752
|
// уточнению, см. «ВОПРОСЫ» в отчёте P1-10).
|
|
1602
|
-
|
|
1603
|
-
event:
|
|
1753
|
+
z25.object({
|
|
1754
|
+
event: z25.literal("agent:presence"),
|
|
1604
1755
|
payload: futurePlaceholderPayloadSchema,
|
|
1605
1756
|
...envelopeExtra
|
|
1606
1757
|
}),
|
|
1607
|
-
|
|
1608
|
-
event:
|
|
1758
|
+
z25.object({
|
|
1759
|
+
event: z25.literal("question:new"),
|
|
1609
1760
|
payload: questionEventPayloadSchema,
|
|
1610
1761
|
...envelopeExtra
|
|
1611
1762
|
}),
|
|
1612
|
-
|
|
1613
|
-
event:
|
|
1763
|
+
z25.object({
|
|
1764
|
+
event: z25.literal("question:answered"),
|
|
1614
1765
|
payload: questionEventPayloadSchema,
|
|
1615
1766
|
...envelopeExtra
|
|
1616
1767
|
}),
|
|
1617
|
-
|
|
1618
|
-
event:
|
|
1768
|
+
z25.object({
|
|
1769
|
+
event: z25.literal("question:dismissed"),
|
|
1619
1770
|
payload: questionEventPayloadSchema,
|
|
1620
1771
|
...envelopeExtra
|
|
1621
1772
|
}),
|
|
1622
|
-
|
|
1623
|
-
event:
|
|
1773
|
+
z25.object({
|
|
1774
|
+
event: z25.literal("approval:requested"),
|
|
1624
1775
|
payload: futurePlaceholderPayloadSchema,
|
|
1625
1776
|
...envelopeExtra
|
|
1626
1777
|
}),
|
|
1627
|
-
|
|
1628
|
-
event:
|
|
1778
|
+
z25.object({
|
|
1779
|
+
event: z25.literal("approval:decided"),
|
|
1629
1780
|
payload: futurePlaceholderPayloadSchema,
|
|
1630
1781
|
...envelopeExtra
|
|
1631
1782
|
}),
|
|
1632
|
-
|
|
1633
|
-
event:
|
|
1783
|
+
z25.object({
|
|
1784
|
+
event: z25.literal("audit:appended"),
|
|
1634
1785
|
payload: futurePlaceholderPayloadSchema,
|
|
1635
1786
|
...envelopeExtra
|
|
1636
1787
|
}),
|
|
1637
|
-
|
|
1788
|
+
z25.object({
|
|
1638
1789
|
// Состояние проекта изменилось (OQ-30). Единственное событие этого
|
|
1639
1790
|
// канала, которое realtime рассылает НЕ только в `/ui`, но и агентам
|
|
1640
1791
|
// проекта: §17 ТЗ обещает «при PAUSED агентам шлётся agent:pause», а
|
|
1641
1792
|
// одностороннего agent:pause на рукопожатии для этого мало — снятие
|
|
1642
1793
|
// паузы до подключённого агента не доходит вовсе. Веб публикует одно
|
|
1643
1794
|
// событие, realtime разводит его по обоим namespace.
|
|
1644
|
-
event:
|
|
1645
|
-
payload:
|
|
1646
|
-
projectId:
|
|
1647
|
-
paused:
|
|
1648
|
-
mode:
|
|
1649
|
-
reason:
|
|
1795
|
+
event: z25.literal("project:state"),
|
|
1796
|
+
payload: z25.object({
|
|
1797
|
+
projectId: z25.string().min(1),
|
|
1798
|
+
paused: z25.boolean(),
|
|
1799
|
+
mode: z25.string().min(1),
|
|
1800
|
+
reason: z25.string().optional()
|
|
1650
1801
|
}),
|
|
1651
1802
|
...envelopeExtra
|
|
1652
1803
|
})
|
|
@@ -1664,14 +1815,14 @@ var PRIORITY_VALUES = new Set(Object.values(Priority));
|
|
|
1664
1815
|
var EXECUTOR_VALUES = new Set(Object.values(Executor));
|
|
1665
1816
|
|
|
1666
1817
|
// ../shared/src/import/types.ts
|
|
1667
|
-
import { z as
|
|
1668
|
-
var ImportTargetStatusSchema =
|
|
1818
|
+
import { z as z26 } from "zod";
|
|
1819
|
+
var ImportTargetStatusSchema = z26.enum([
|
|
1669
1820
|
TaskStatus.BACKLOG,
|
|
1670
1821
|
TaskStatus.READY,
|
|
1671
1822
|
TaskStatus.DONE
|
|
1672
1823
|
]);
|
|
1673
|
-
var ImportRowKeySchema =
|
|
1674
|
-
var ImportTaskInputSchema =
|
|
1824
|
+
var ImportRowKeySchema = z26.string().trim().min(1).max(100);
|
|
1825
|
+
var ImportTaskInputSchema = z26.object({
|
|
1675
1826
|
key: ImportRowKeySchema,
|
|
1676
1827
|
title: TaskTitleSchema,
|
|
1677
1828
|
descriptionMd: TaskDescriptionSchema.default(""),
|
|
@@ -1679,21 +1830,217 @@ var ImportTaskInputSchema = z25.object({
|
|
|
1679
1830
|
priority: TaskPrioritySchema.default(Priority.P2),
|
|
1680
1831
|
executor: TaskExecutorSchema.default(Executor.ANY),
|
|
1681
1832
|
status: ImportTargetStatusSchema.default(TaskStatus.BACKLOG),
|
|
1682
|
-
roleKey:
|
|
1683
|
-
milestoneId:
|
|
1833
|
+
roleKey: z26.string().trim().min(1).max(60).optional(),
|
|
1834
|
+
milestoneId: z26.string().min(1).optional(),
|
|
1684
1835
|
labels: TaskLabelsSchema.default([]),
|
|
1685
1836
|
metadata: TaskMetadataSchema.default({}),
|
|
1686
1837
|
acceptance: TaskAcceptanceSchema.optional(),
|
|
1687
1838
|
estimateMin: TaskEstimateMinSchema.optional(),
|
|
1688
1839
|
parentKey: ImportRowKeySchema.optional()
|
|
1689
1840
|
});
|
|
1690
|
-
var ImportTasksRequestSchema =
|
|
1691
|
-
tasks:
|
|
1841
|
+
var ImportTasksRequestSchema = z26.object({
|
|
1842
|
+
tasks: z26.array(ImportTaskInputSchema).min(1, "\u041D\u0443\u0436\u043D\u0430 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u0430 \u0437\u0430\u0434\u0430\u0447\u0430").max(500, "\u041D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 500 \u0437\u0430\u0434\u0430\u0447 \u0437\u0430 \u043E\u0434\u0438\u043D \u0438\u043C\u043F\u043E\u0440\u0442")
|
|
1692
1843
|
});
|
|
1693
1844
|
|
|
1845
|
+
// ../shared/src/integrations/registry.ts
|
|
1846
|
+
var IntegrationStatus = {
|
|
1847
|
+
/** Работает и проверена вживую. */
|
|
1848
|
+
READY: "ready",
|
|
1849
|
+
/** Запланирована, но ещё не сделана. Показываем, чтобы не обещать голосом. */
|
|
1850
|
+
PLANNED: "planned"
|
|
1851
|
+
};
|
|
1852
|
+
var IntegrationKey = {
|
|
1853
|
+
GITHUB: "github",
|
|
1854
|
+
TELEGRAM: "telegram",
|
|
1855
|
+
WEBHOOKS: "webhooks"
|
|
1856
|
+
};
|
|
1857
|
+
var INTEGRATIONS = [
|
|
1858
|
+
{
|
|
1859
|
+
key: IntegrationKey.GITHUB,
|
|
1860
|
+
status: IntegrationStatus.READY,
|
|
1861
|
+
scope: "org",
|
|
1862
|
+
requiresOrgAdmin: true
|
|
1863
|
+
},
|
|
1864
|
+
{
|
|
1865
|
+
// Организация может принести СВОЙ токен бота (платные тарифы), а
|
|
1866
|
+
// привязку чата каждый делает себе сам — отсюда `both`.
|
|
1867
|
+
key: IntegrationKey.TELEGRAM,
|
|
1868
|
+
status: IntegrationStatus.READY,
|
|
1869
|
+
scope: "both",
|
|
1870
|
+
requiresOrgAdmin: false
|
|
1871
|
+
},
|
|
1872
|
+
{
|
|
1873
|
+
// Одна механика вместо десяти интеграций: Zapier, n8n, Make и любой
|
|
1874
|
+
// свой эндпоинт. Пока не сделана — и список об этом честно говорит.
|
|
1875
|
+
key: IntegrationKey.WEBHOOKS,
|
|
1876
|
+
status: IntegrationStatus.PLANNED,
|
|
1877
|
+
scope: "org",
|
|
1878
|
+
requiresOrgAdmin: true
|
|
1879
|
+
}
|
|
1880
|
+
];
|
|
1881
|
+
var PLANS_WITH_OWN_TELEGRAM_BOT = [
|
|
1882
|
+
Plan.SELF_HOSTED,
|
|
1883
|
+
Plan.TEAM,
|
|
1884
|
+
Plan.ENTERPRISE
|
|
1885
|
+
];
|
|
1886
|
+
var BY_KEY = new Map(INTEGRATIONS.map((info) => [info.key, info]));
|
|
1887
|
+
|
|
1888
|
+
// ../shared/src/notifications/kinds.ts
|
|
1889
|
+
var NotificationChannel = {
|
|
1890
|
+
INAPP: "inapp",
|
|
1891
|
+
TELEGRAM: "telegram",
|
|
1892
|
+
EMAIL: "email",
|
|
1893
|
+
PUSH: "push"
|
|
1894
|
+
};
|
|
1895
|
+
var NOTIFICATION_CHANNELS = Object.values(NotificationChannel);
|
|
1896
|
+
var NotificationUrgency = {
|
|
1897
|
+
BLOCKING: "blocking",
|
|
1898
|
+
ACTIONABLE: "actionable",
|
|
1899
|
+
INFORMATIONAL: "informational",
|
|
1900
|
+
SCHEDULED: "scheduled"
|
|
1901
|
+
};
|
|
1902
|
+
var ALL = [
|
|
1903
|
+
NotificationChannel.INAPP,
|
|
1904
|
+
NotificationChannel.TELEGRAM,
|
|
1905
|
+
NotificationChannel.EMAIL,
|
|
1906
|
+
NotificationChannel.PUSH
|
|
1907
|
+
];
|
|
1908
|
+
var FAST = [
|
|
1909
|
+
NotificationChannel.INAPP,
|
|
1910
|
+
NotificationChannel.TELEGRAM,
|
|
1911
|
+
NotificationChannel.PUSH
|
|
1912
|
+
];
|
|
1913
|
+
var QUIET = [NotificationChannel.INAPP];
|
|
1914
|
+
var SLOW = [
|
|
1915
|
+
NotificationChannel.INAPP,
|
|
1916
|
+
NotificationChannel.TELEGRAM,
|
|
1917
|
+
NotificationChannel.EMAIL
|
|
1918
|
+
];
|
|
1919
|
+
function defaultsFor(urgency) {
|
|
1920
|
+
if (urgency === NotificationUrgency.BLOCKING) return FAST;
|
|
1921
|
+
if (urgency === NotificationUrgency.ACTIONABLE) return ALL;
|
|
1922
|
+
if (urgency === NotificationUrgency.SCHEDULED) return SLOW;
|
|
1923
|
+
return QUIET;
|
|
1924
|
+
}
|
|
1925
|
+
function kind(value, label, description, urgency) {
|
|
1926
|
+
return { kind: value, label, description, urgency, defaultChannels: defaultsFor(urgency) };
|
|
1927
|
+
}
|
|
1928
|
+
var NOTIFICATION_KINDS = [
|
|
1929
|
+
kind(
|
|
1930
|
+
"question",
|
|
1931
|
+
"\u0412\u043E\u043F\u0440\u043E\u0441 \u043E\u0442 \u0430\u0433\u0435\u043D\u0442\u0430",
|
|
1932
|
+
"\u0410\u0433\u0435\u043D\u0442 \u0443\u043F\u0451\u0440\u0441\u044F \u0432 \u0442\u043E, \u0447\u0435\u0433\u043E \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0440\u0435\u0448\u0438\u0442\u044C \u0441\u0430\u043C, \u0438 \u0436\u0434\u0451\u0442 \u043E\u0442\u0432\u0435\u0442\u0430.",
|
|
1933
|
+
NotificationUrgency.BLOCKING
|
|
1934
|
+
),
|
|
1935
|
+
kind(
|
|
1936
|
+
"approval_requested",
|
|
1937
|
+
"\u0417\u0430\u043F\u0440\u043E\u0441 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F",
|
|
1938
|
+
"\u0410\u0433\u0435\u043D\u0442 \u043F\u0440\u043E\u0441\u0438\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044C \u043E\u043F\u0430\u0441\u043D\u0443\u044E \u043A\u043E\u043C\u0430\u043D\u0434\u0443. \u041F\u043E\u043A\u0430 \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u0442\u0435 \u2014 \u043E\u043D\u0430 \u043D\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u0441\u044F.",
|
|
1939
|
+
NotificationUrgency.BLOCKING
|
|
1940
|
+
),
|
|
1941
|
+
kind(
|
|
1942
|
+
"task_assigned",
|
|
1943
|
+
"\u0412\u0430\u043C \u043D\u0430\u0437\u043D\u0430\u0447\u0438\u043B\u0438 \u0437\u0430\u0434\u0430\u0447\u0443",
|
|
1944
|
+
"\u0417\u0430\u0434\u0430\u0447\u0443 \u043D\u0430\u0437\u043D\u0430\u0447\u0438\u043B\u0438 \u043B\u0438\u0447\u043D\u043E \u043D\u0430 \u0432\u0430\u0441.",
|
|
1945
|
+
NotificationUrgency.ACTIONABLE
|
|
1946
|
+
),
|
|
1947
|
+
kind(
|
|
1948
|
+
"task_review",
|
|
1949
|
+
"\u0417\u0430\u0434\u0430\u0447\u0430 \u043D\u0430 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0435",
|
|
1950
|
+
"\u0420\u0430\u0431\u043E\u0442\u0430 \u0441\u0434\u0430\u043D\u0430 \u0438 \u0436\u0434\u0451\u0442 \u0432\u0430\u0448\u0435\u0439 \u043F\u0440\u0438\u0451\u043C\u043A\u0438.",
|
|
1951
|
+
NotificationUrgency.ACTIONABLE
|
|
1952
|
+
),
|
|
1953
|
+
kind(
|
|
1954
|
+
"task_returned",
|
|
1955
|
+
"\u0417\u0430\u0434\u0430\u0447\u0443 \u0432\u0435\u0440\u043D\u0443\u043B\u0438 \u0441 \u043F\u0440\u0430\u0432\u043A\u0430\u043C\u0438",
|
|
1956
|
+
"\u0412\u0430\u0448\u0443 \u0440\u0430\u0431\u043E\u0442\u0443 \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u043B\u0438 \u043D\u0430 \u0434\u043E\u0440\u0430\u0431\u043E\u0442\u043A\u0443.",
|
|
1957
|
+
NotificationUrgency.ACTIONABLE
|
|
1958
|
+
),
|
|
1959
|
+
kind(
|
|
1960
|
+
"task_failed",
|
|
1961
|
+
"\u0417\u0430\u0434\u0430\u0447\u0430 \u043F\u0440\u043E\u0432\u0430\u043B\u0435\u043D\u0430",
|
|
1962
|
+
"\u0422\u0440\u0435\u0442\u0438\u0439 \u0432\u043E\u0437\u0432\u0440\u0430\u0442 \u043F\u043E\u0434\u0440\u044F\u0434 \u2014 \u0437\u0430\u0434\u0430\u0447\u0430 \u0443\u0448\u043B\u0430 \u0432 \xAB\u041F\u0440\u043E\u0432\u0430\u043B\u0435\u043D\u0430\xBB.",
|
|
1963
|
+
NotificationUrgency.ACTIONABLE
|
|
1964
|
+
),
|
|
1965
|
+
kind(
|
|
1966
|
+
"AGENT_LEASE_EXPIRED",
|
|
1967
|
+
"\u0410\u0433\u0435\u043D\u0442 \u043F\u043E\u0442\u0435\u0440\u044F\u043B \u0437\u0430\u0434\u0430\u0447\u0443",
|
|
1968
|
+
"\u0410\u0440\u0435\u043D\u0434\u0430 \u0438\u0441\u0442\u0435\u043A\u043B\u0430: \u0430\u0433\u0435\u043D\u0442 \u043E\u0442\u0432\u0430\u043B\u0438\u043B\u0441\u044F, \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u0435\u0440\u043D\u0443\u043B\u0430\u0441\u044C \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u044C.",
|
|
1969
|
+
NotificationUrgency.ACTIONABLE
|
|
1970
|
+
),
|
|
1971
|
+
kind(
|
|
1972
|
+
"AGENT_RATE_LIMITED_REQUEUE",
|
|
1973
|
+
"\u0410\u0433\u0435\u043D\u0442 \u0443\u043F\u0451\u0440\u0441\u044F \u0432 \u043B\u0438\u043C\u0438\u0442",
|
|
1974
|
+
"\u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u0430\u0433\u0435\u043D\u0442\u0430 \u0438\u0441\u0447\u0435\u0440\u043F\u0430\u043D\u0430, \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u044C.",
|
|
1975
|
+
NotificationUrgency.ACTIONABLE
|
|
1976
|
+
),
|
|
1977
|
+
kind(
|
|
1978
|
+
"agent_session_limit",
|
|
1979
|
+
"\u0421\u0435\u0441\u0441\u0438\u044F \u0430\u0433\u0435\u043D\u0442\u0430 \u0438\u0441\u0447\u0435\u0440\u043F\u0430\u043D\u0430",
|
|
1980
|
+
"\u0410\u0433\u0435\u043D\u0442 \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u043B \u043F\u043E\u0434\u0440\u044F\u0434 \u0441\u0442\u043E\u043B\u044C\u043A\u043E \u0437\u0430\u0434\u0430\u0447, \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u043E \u0434\u043E \u043E\u0447\u0438\u0441\u0442\u043A\u0438 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u0430.",
|
|
1981
|
+
NotificationUrgency.INFORMATIONAL
|
|
1982
|
+
),
|
|
1983
|
+
kind(
|
|
1984
|
+
"task_auto_accepted",
|
|
1985
|
+
"\u0417\u0430\u0434\u0430\u0447\u0430 \u043F\u0440\u0438\u043D\u044F\u0442\u0430 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438",
|
|
1986
|
+
"\u041F\u0440\u043E\u0435\u043A\u0442 \u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043D \u043D\u0430 \u0430\u0432\u0442\u043E\u043F\u0440\u0438\u0451\u043C\u043A\u0443 \u2014 \u0440\u0430\u0431\u043E\u0442\u0430 \u0437\u0430\u0447\u0442\u0435\u043D\u0430 \u0431\u0435\u0437 \u0432\u0430\u0448\u0435\u0433\u043E \u0443\u0447\u0430\u0441\u0442\u0438\u044F.",
|
|
1987
|
+
NotificationUrgency.INFORMATIONAL
|
|
1988
|
+
),
|
|
1989
|
+
kind(
|
|
1990
|
+
"DAILY_DIGEST",
|
|
1991
|
+
"\u0415\u0436\u0435\u0434\u043D\u0435\u0432\u043D\u044B\u0439 \u0434\u0430\u0439\u0434\u0436\u0435\u0441\u0442",
|
|
1992
|
+
"\u0421\u0432\u043E\u0434\u043A\u0430 \u0437\u0430 \u0441\u0443\u0442\u043A\u0438: \u0447\u0442\u043E \u0441\u043B\u0443\u0447\u0438\u043B\u043E\u0441\u044C \u0438 \u0447\u0442\u043E \u043E\u0442 \u0432\u0430\u0441 \u0436\u0434\u0443\u0442. \u041F\u0440\u0438\u0445\u043E\u0434\u0438\u0442 \u043F\u043E \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0435.",
|
|
1993
|
+
NotificationUrgency.SCHEDULED
|
|
1994
|
+
)
|
|
1995
|
+
];
|
|
1996
|
+
var BY_KIND2 = new Map(NOTIFICATION_KINDS.map((info) => [info.kind, info]));
|
|
1997
|
+
|
|
1998
|
+
// ../shared/src/notifications/prefs.ts
|
|
1999
|
+
import { z as z27 } from "zod";
|
|
2000
|
+
var NotificationChannelFlagsSchema = z27.object({
|
|
2001
|
+
inapp: z27.boolean().optional(),
|
|
2002
|
+
telegram: z27.boolean().optional(),
|
|
2003
|
+
email: z27.boolean().optional(),
|
|
2004
|
+
push: z27.boolean().optional()
|
|
2005
|
+
}).partial();
|
|
2006
|
+
var NotificationPrefsSchema = z27.object({
|
|
2007
|
+
/** Подписка на ежедневный дайджест. Ключ существует с фазы 5, читает `jobs/digest.ts`. */
|
|
2008
|
+
digest: z27.boolean().optional(),
|
|
2009
|
+
/**
|
|
2010
|
+
* Выключатели каналов целиком: «почту мне не слать никогда».
|
|
2011
|
+
* Отсутствие ключа означает «по умолчанию», а не «выключено».
|
|
2012
|
+
*/
|
|
2013
|
+
channels: NotificationChannelFlagsSchema.optional(),
|
|
2014
|
+
/**
|
|
2015
|
+
* Точечно по видам: `{ task_review: { email: false } }`.
|
|
2016
|
+
*
|
|
2017
|
+
* Ключ — `Notification.kind` как строка, а не enum: в базе уже лежат
|
|
2018
|
+
* виды, а список будет расти. Неизвестный вид здесь никого не ломает
|
|
2019
|
+
* — он просто ни с чем не совпадёт.
|
|
2020
|
+
*/
|
|
2021
|
+
kinds: z27.record(z27.string(), NotificationChannelFlagsSchema).optional()
|
|
2022
|
+
}).passthrough();
|
|
2023
|
+
|
|
2024
|
+
// ../shared/src/onboarding/steps.ts
|
|
2025
|
+
var OnboardingStep = {
|
|
2026
|
+
/** Создать организацию. Без неё в системе не работает ничего. */
|
|
2027
|
+
ORGANIZATION: "organization",
|
|
2028
|
+
PROJECT: "project",
|
|
2029
|
+
AGENT: "agent",
|
|
2030
|
+
TEAM: "team",
|
|
2031
|
+
NOTIFICATIONS: "notifications"
|
|
2032
|
+
};
|
|
2033
|
+
var ONBOARDING_STEPS = [
|
|
2034
|
+
{ step: OnboardingStep.ORGANIZATION, required: true, ownerOnly: false },
|
|
2035
|
+
{ step: OnboardingStep.PROJECT, required: false, ownerOnly: true },
|
|
2036
|
+
{ step: OnboardingStep.AGENT, required: false, ownerOnly: false },
|
|
2037
|
+
{ step: OnboardingStep.TEAM, required: false, ownerOnly: true },
|
|
2038
|
+
{ step: OnboardingStep.NOTIFICATIONS, required: false, ownerOnly: false }
|
|
2039
|
+
];
|
|
2040
|
+
|
|
1694
2041
|
// ../shared/src/settings/org-settings.ts
|
|
1695
|
-
import { z as
|
|
1696
|
-
var OrgSettingsSchema =
|
|
2042
|
+
import { z as z28 } from "zod";
|
|
2043
|
+
var OrgSettingsSchema = z28.object({}).passthrough();
|
|
1697
2044
|
|
|
1698
2045
|
// ../shared/src/task-state.ts
|
|
1699
2046
|
var TASK_TRANSITIONS = [
|
|
@@ -2925,24 +3272,24 @@ function upsertClaudeMdSection(existingContent) {
|
|
|
2925
3272
|
// src/config/claude-settings.ts
|
|
2926
3273
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
2927
3274
|
import { join as join2 } from "path";
|
|
2928
|
-
import { z as
|
|
2929
|
-
var HookCommandEntrySchema =
|
|
2930
|
-
type:
|
|
2931
|
-
command:
|
|
2932
|
-
timeout:
|
|
3275
|
+
import { z as z29 } from "zod";
|
|
3276
|
+
var HookCommandEntrySchema = z29.object({
|
|
3277
|
+
type: z29.literal("command"),
|
|
3278
|
+
command: z29.string().min(1),
|
|
3279
|
+
timeout: z29.number().int().positive().optional()
|
|
2933
3280
|
}).passthrough();
|
|
2934
|
-
var HookMatcherGroupSchema =
|
|
2935
|
-
matcher:
|
|
2936
|
-
hooks:
|
|
3281
|
+
var HookMatcherGroupSchema = z29.object({
|
|
3282
|
+
matcher: z29.string().optional(),
|
|
3283
|
+
hooks: z29.array(HookCommandEntrySchema)
|
|
2937
3284
|
}).passthrough();
|
|
2938
|
-
var McpServerEntrySchema =
|
|
2939
|
-
command:
|
|
2940
|
-
args:
|
|
3285
|
+
var McpServerEntrySchema = z29.object({
|
|
3286
|
+
command: z29.string().min(1),
|
|
3287
|
+
args: z29.array(z29.string()).optional()
|
|
2941
3288
|
}).passthrough();
|
|
2942
|
-
var ClaudeSettingsSchema =
|
|
2943
|
-
mcpServers:
|
|
2944
|
-
hooks:
|
|
2945
|
-
env:
|
|
3289
|
+
var ClaudeSettingsSchema = z29.object({
|
|
3290
|
+
mcpServers: z29.record(z29.string(), McpServerEntrySchema).optional(),
|
|
3291
|
+
hooks: z29.record(z29.string(), z29.array(HookMatcherGroupSchema)).optional(),
|
|
3292
|
+
env: z29.record(z29.string(), z29.string()).optional()
|
|
2946
3293
|
}).passthrough();
|
|
2947
3294
|
var CLAUDE_SETTINGS_RELATIVE_PATH = join2(".claude", "settings.json");
|
|
2948
3295
|
var CLI_BIN = "quiel";
|
|
@@ -3047,13 +3394,13 @@ function clearPendingApproval(state, approvalId) {
|
|
|
3047
3394
|
}
|
|
3048
3395
|
|
|
3049
3396
|
// src/state/schema.ts
|
|
3050
|
-
import { z as
|
|
3397
|
+
import { z as z30 } from "zod";
|
|
3051
3398
|
var STATE_SCHEMA_VERSION = 1;
|
|
3052
|
-
var CurrentTaskSchema =
|
|
3053
|
-
taskId:
|
|
3399
|
+
var CurrentTaskSchema = z30.object({
|
|
3400
|
+
taskId: z30.string().min(1),
|
|
3054
3401
|
/** Человекочитаемый ключ вроде `REL-42` — для текста в хуках. Необязателен: на первых порах может быть неизвестен. */
|
|
3055
|
-
taskKey:
|
|
3056
|
-
resumeToken:
|
|
3402
|
+
taskKey: z30.string().min(1).optional(),
|
|
3403
|
+
resumeToken: z30.string().min(1),
|
|
3057
3404
|
/**
|
|
3058
3405
|
* Каталог, в котором агент работает над этой задачей (`.claude/worktrees/…`).
|
|
3059
3406
|
*
|
|
@@ -3067,7 +3414,7 @@ var CurrentTaskSchema = z28.object({
|
|
|
3067
3414
|
* в чекауте), а у состояний, записанных прежними версиями клиента,
|
|
3068
3415
|
* поля просто нет.
|
|
3069
3416
|
*/
|
|
3070
|
-
worktreeDir:
|
|
3417
|
+
worktreeDir: z30.string().min(1).optional(),
|
|
3071
3418
|
/**
|
|
3072
3419
|
* Git-режим проекта (§13.1 ТЗ) — `DIRECT` или `PR`.
|
|
3073
3420
|
*
|
|
@@ -3081,58 +3428,71 @@ var CurrentTaskSchema = z28.object({
|
|
|
3081
3428
|
* Необязательно: состояния, записанные прежними версиями клиента, поля
|
|
3082
3429
|
* не имеют — тогда `submit_work` работает как раньше, в режиме DIRECT.
|
|
3083
3430
|
*/
|
|
3084
|
-
gitMode:
|
|
3085
|
-
});
|
|
3086
|
-
var TrustCacheSchema =
|
|
3087
|
-
profileKey:
|
|
3088
|
-
updatedAt:
|
|
3089
|
-
rules:
|
|
3090
|
-
bash:
|
|
3091
|
-
mode:
|
|
3092
|
-
stopPatterns:
|
|
3093
|
-
allowPatterns:
|
|
3431
|
+
gitMode: z30.enum([GitMode.DIRECT, GitMode.PR]).optional()
|
|
3432
|
+
});
|
|
3433
|
+
var TrustCacheSchema = z30.object({
|
|
3434
|
+
profileKey: z30.string().min(1),
|
|
3435
|
+
updatedAt: z30.string(),
|
|
3436
|
+
rules: z30.object({
|
|
3437
|
+
bash: z30.object({
|
|
3438
|
+
mode: z30.enum(["allow", "approve", "deny"]),
|
|
3439
|
+
stopPatterns: z30.array(z30.string()).default([]),
|
|
3440
|
+
allowPatterns: z30.array(z30.string()).optional()
|
|
3094
3441
|
}),
|
|
3095
|
-
files:
|
|
3096
|
-
mode:
|
|
3097
|
-
protectedPaths:
|
|
3442
|
+
files: z30.object({
|
|
3443
|
+
mode: z30.enum(["allow", "approve"]),
|
|
3444
|
+
protectedPaths: z30.array(z30.string()).default([])
|
|
3098
3445
|
}).optional(),
|
|
3099
|
-
git:
|
|
3100
|
-
network:
|
|
3101
|
-
approvalTtlMin:
|
|
3446
|
+
git: z30.object({ allowPushDefault: z30.boolean(), allowForcePush: z30.boolean() }).optional(),
|
|
3447
|
+
network: z30.object({ allowSsh: z30.boolean(), sshHostsAllow: z30.array(z30.string()).optional() }).optional(),
|
|
3448
|
+
approvalTtlMin: z30.number().int().positive().optional()
|
|
3102
3449
|
}).passthrough()
|
|
3103
3450
|
}).nullable();
|
|
3104
|
-
var ApprovedCommandSchema =
|
|
3105
|
-
token:
|
|
3106
|
-
command:
|
|
3107
|
-
cwd:
|
|
3108
|
-
expiresAt:
|
|
3109
|
-
createdAt:
|
|
3110
|
-
});
|
|
3111
|
-
var PendingApprovalSchema =
|
|
3112
|
-
command:
|
|
3113
|
-
cwd:
|
|
3114
|
-
createdAt:
|
|
3115
|
-
});
|
|
3116
|
-
var AgentModeSchema =
|
|
3451
|
+
var ApprovedCommandSchema = z30.object({
|
|
3452
|
+
token: z30.string().min(1),
|
|
3453
|
+
command: z30.string().min(1),
|
|
3454
|
+
cwd: z30.string().min(1),
|
|
3455
|
+
expiresAt: z30.string(),
|
|
3456
|
+
createdAt: z30.string()
|
|
3457
|
+
});
|
|
3458
|
+
var PendingApprovalSchema = z30.object({
|
|
3459
|
+
command: z30.string().min(1),
|
|
3460
|
+
cwd: z30.string().min(1),
|
|
3461
|
+
createdAt: z30.string()
|
|
3462
|
+
});
|
|
3463
|
+
var AgentModeSchema = z30.enum([AgentMode.AUTONOMOUS, AgentMode.MANUAL]);
|
|
3117
3464
|
var DEFAULT_CONTEXT_RESET_AFTER_TASKS = ProjectSettingsSchema.parse({}).contextResetAfterTasks;
|
|
3118
|
-
var ClientStateSchema =
|
|
3119
|
-
version:
|
|
3465
|
+
var ClientStateSchema = z30.object({
|
|
3466
|
+
version: z30.literal(STATE_SCHEMA_VERSION).default(STATE_SCHEMA_VERSION),
|
|
3120
3467
|
mode: AgentModeSchema.default(AgentMode.MANUAL),
|
|
3121
3468
|
currentTask: CurrentTaskSchema.nullable().default(null),
|
|
3122
3469
|
/** Счётчик сдач задач в текущей «сессии» (§10.4 ТЗ). Сбрасывается `SessionStart` при `source ∈ {startup, clear}` — см. src/hooks/session-start.ts. */
|
|
3123
|
-
tasksCompletedInSession:
|
|
3470
|
+
tasksCompletedInSession: z30.number().int().nonnegative().default(0),
|
|
3124
3471
|
/** Кэш `ProjectSettings.contextResetAfterTasks` (§7.2 ТЗ) — сколько задач подряд можно сдать, прежде чем `Stop`-хук попросит `/clear`. */
|
|
3125
|
-
contextResetAfterTasks:
|
|
3472
|
+
contextResetAfterTasks: z30.number().int().positive().default(DEFAULT_CONTEXT_RESET_AFTER_TASKS),
|
|
3126
3473
|
/** Кэш стоп-паттернов/правил доверия для `PreToolUse` фазы 4. */
|
|
3127
3474
|
trust: TrustCacheSchema.default(null),
|
|
3128
3475
|
/** Снимок задачи на момент последнего `PreCompact` — пишет src/hooks/pre-compact.ts, читает SessionStart(source="compact"), чтобы напомнить модели, чем она занималась. */
|
|
3129
|
-
lastPreCompact: CurrentTaskSchema.extend({ savedAt:
|
|
3476
|
+
lastPreCompact: CurrentTaskSchema.extend({ savedAt: z30.string() }).nullable().default(null),
|
|
3130
3477
|
/** Кэш одноразовых токенов подтверждения (§14.4 ТЗ), ключ — `hashCommandKey(command, cwd)`. Читает/жжёт `PreToolUse` (`hooks/pre-tool-use.ts`), пишут `request_approval`/`wait_approval` и пуш `approval:decided` (`socket/client.ts`). */
|
|
3131
|
-
approvedCommands:
|
|
3478
|
+
approvedCommands: z30.record(z30.string(), ApprovedCommandSchema).default({}),
|
|
3132
3479
|
/** Незавершённые запросы подтверждения, ключ — `approvalId`. См. `PendingApprovalSchema`. */
|
|
3133
|
-
pendingApprovals:
|
|
3480
|
+
pendingApprovals: z30.record(z30.string(), PendingApprovalSchema).default({}),
|
|
3481
|
+
/**
|
|
3482
|
+
* Сколько байтов транскрипта уже посчитано в расход токенов (вопрос
|
|
3483
|
+
* владельца 18.09.2026).
|
|
3484
|
+
*
|
|
3485
|
+
* Ключ — путь к файлу транскрипта: у сессии он свой, а `/clear` заводит
|
|
3486
|
+
* новый. Значение — смещение в БАЙТАХ, не в символах: кириллица в
|
|
3487
|
+
* транскрипте обычное дело.
|
|
3488
|
+
*
|
|
3489
|
+
* Без этого смещения каждый ход агента пересчитывал бы файл с начала, и
|
|
3490
|
+
* расход задачи рос бы квадратично — по числам это выглядело бы как
|
|
3491
|
+
* «агент потратил в сто раз больше», и проверить было бы нечем.
|
|
3492
|
+
*/
|
|
3493
|
+
usageOffsets: z30.record(z30.string(), z30.number().int().nonnegative()).default({}),
|
|
3134
3494
|
/** Штамп последней записи файла — выставляется в state/store.ts при каждом `writeState`. */
|
|
3135
|
-
updatedAt:
|
|
3495
|
+
updatedAt: z30.string().default(() => (/* @__PURE__ */ new Date()).toISOString())
|
|
3136
3496
|
});
|
|
3137
3497
|
function createDefaultState() {
|
|
3138
3498
|
return ClientStateSchema.parse({});
|
|
@@ -3184,18 +3544,18 @@ function updateState(patch, filePath = getStateFilePath()) {
|
|
|
3184
3544
|
}
|
|
3185
3545
|
|
|
3186
3546
|
// src/config/schema.ts
|
|
3187
|
-
import { z as
|
|
3547
|
+
import { z as z31 } from "zod";
|
|
3188
3548
|
var PROJECT_CONFIG_SCHEMA_VERSION = 1;
|
|
3189
|
-
var ProjectConfigSchema =
|
|
3190
|
-
version:
|
|
3549
|
+
var ProjectConfigSchema = z31.object({
|
|
3550
|
+
version: z31.literal(PROJECT_CONFIG_SCHEMA_VERSION).default(PROJECT_CONFIG_SCHEMA_VERSION),
|
|
3191
3551
|
/** URL платформы (§10.1 ТЗ), например `https://quiel.example.com`. */
|
|
3192
|
-
url:
|
|
3552
|
+
url: z31.string().trim().url("\u041D\u0443\u0436\u0435\u043D \u043F\u043E\u043B\u043D\u044B\u0439 URL, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 https://quiel.example.com"),
|
|
3193
3553
|
/** Ключ проекта на платформе (OQ-11), например `REL`. */
|
|
3194
|
-
projectKey:
|
|
3554
|
+
projectKey: z31.string().trim().min(1, "\u041A\u043B\u044E\u0447 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D"),
|
|
3195
3555
|
/** Идентификатор агента — см. комментарий выше. */
|
|
3196
|
-
agentId:
|
|
3556
|
+
agentId: z31.string().trim().min(1, "ID \u0430\u0433\u0435\u043D\u0442\u0430 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D"),
|
|
3197
3557
|
/** Человекочитаемое имя агента (§7.4 ТЗ: «odya-macbook») — необязательно, только для локального отображения. */
|
|
3198
|
-
agentName:
|
|
3558
|
+
agentName: z31.string().trim().min(1).optional(),
|
|
3199
3559
|
/** Роли, с которыми агент забирает задачи — подмножество ролей участника (§7.4 ТЗ). */
|
|
3200
3560
|
roleKeys: AgentRoleKeysSchema,
|
|
3201
3561
|
/**
|
|
@@ -3228,19 +3588,19 @@ var ProjectConfigSchema = z29.object({
|
|
|
3228
3588
|
* абсолютный путь вроде `/Users/odya/...` у коллеги на другой машине
|
|
3229
3589
|
* оказался бы битым. Режим переносим — это соглашение проекта.
|
|
3230
3590
|
*/
|
|
3231
|
-
worktrees:
|
|
3591
|
+
worktrees: z31.enum(["isolated", "checkout"]).default("isolated")
|
|
3232
3592
|
});
|
|
3233
|
-
var CredentialsEntrySchema =
|
|
3234
|
-
url:
|
|
3235
|
-
token:
|
|
3236
|
-
projectKey:
|
|
3593
|
+
var CredentialsEntrySchema = z31.object({
|
|
3594
|
+
url: z31.string().trim().url(),
|
|
3595
|
+
token: z31.string().min(1),
|
|
3596
|
+
projectKey: z31.string().min(1),
|
|
3237
3597
|
/** Когда записали — для диагностики (`quiel status`), не для логики. */
|
|
3238
|
-
savedAt:
|
|
3598
|
+
savedAt: z31.string()
|
|
3239
3599
|
});
|
|
3240
3600
|
var CREDENTIALS_SCHEMA_VERSION = 1;
|
|
3241
|
-
var CredentialsFileSchema =
|
|
3242
|
-
version:
|
|
3243
|
-
agents:
|
|
3601
|
+
var CredentialsFileSchema = z31.object({
|
|
3602
|
+
version: z31.literal(CREDENTIALS_SCHEMA_VERSION).default(CREDENTIALS_SCHEMA_VERSION),
|
|
3603
|
+
agents: z31.record(z31.string(), CredentialsEntrySchema).default({})
|
|
3244
3604
|
});
|
|
3245
3605
|
function createEmptyCredentialsFile() {
|
|
3246
3606
|
return CredentialsFileSchema.parse({});
|
|
@@ -3321,13 +3681,13 @@ function ensureWorktreesIgnored(dir) {
|
|
|
3321
3681
|
// src/config/mcp-json.ts
|
|
3322
3682
|
import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
3323
3683
|
import { join as join6 } from "path";
|
|
3324
|
-
import { z as
|
|
3325
|
-
var McpServerEntrySchema2 =
|
|
3326
|
-
command:
|
|
3327
|
-
args:
|
|
3684
|
+
import { z as z32 } from "zod";
|
|
3685
|
+
var McpServerEntrySchema2 = z32.object({
|
|
3686
|
+
command: z32.string().min(1).optional(),
|
|
3687
|
+
args: z32.array(z32.string()).optional()
|
|
3328
3688
|
}).passthrough();
|
|
3329
|
-
var McpJsonSchema =
|
|
3330
|
-
mcpServers:
|
|
3689
|
+
var McpJsonSchema = z32.object({
|
|
3690
|
+
mcpServers: z32.record(z32.string(), McpServerEntrySchema2).optional()
|
|
3331
3691
|
}).passthrough();
|
|
3332
3692
|
var MCP_JSON_RELATIVE_PATH = ".mcp.json";
|
|
3333
3693
|
function mergeQuielMcpJson(existing) {
|
|
@@ -3516,11 +3876,11 @@ var claudeCodeInstaller = {
|
|
|
3516
3876
|
};
|
|
3517
3877
|
|
|
3518
3878
|
// src/agents/codex.ts
|
|
3519
|
-
import { z as
|
|
3879
|
+
import { z as z33 } from "zod";
|
|
3520
3880
|
var CODEX_HOOKS_PATH = ".codex/hooks.json";
|
|
3521
3881
|
var CODEX_CONFIG_PATH = ".codex/config.toml";
|
|
3522
|
-
var CodexHooksFileSchema =
|
|
3523
|
-
hooks:
|
|
3882
|
+
var CodexHooksFileSchema = z33.object({
|
|
3883
|
+
hooks: z33.record(z33.string(), z33.array(z33.object({}).passthrough())).optional()
|
|
3524
3884
|
}).passthrough();
|
|
3525
3885
|
function mcpServerTable() {
|
|
3526
3886
|
return [
|
|
@@ -3570,16 +3930,16 @@ var codexInstaller = {
|
|
|
3570
3930
|
};
|
|
3571
3931
|
|
|
3572
3932
|
// src/agents/cursor.ts
|
|
3573
|
-
import { z as
|
|
3933
|
+
import { z as z34 } from "zod";
|
|
3574
3934
|
var CURSOR_HOOKS_PATH = ".cursor/hooks.json";
|
|
3575
3935
|
var CURSOR_MCP_PATH = ".cursor/mcp.json";
|
|
3576
|
-
var CursorHookEntrySchema =
|
|
3577
|
-
var CursorHooksFileSchema =
|
|
3578
|
-
version:
|
|
3579
|
-
hooks:
|
|
3936
|
+
var CursorHookEntrySchema = z34.object({ command: z34.string().min(1) }).passthrough();
|
|
3937
|
+
var CursorHooksFileSchema = z34.object({
|
|
3938
|
+
version: z34.number().optional(),
|
|
3939
|
+
hooks: z34.record(z34.string(), z34.array(CursorHookEntrySchema)).optional()
|
|
3580
3940
|
}).passthrough();
|
|
3581
|
-
var CursorMcpFileSchema =
|
|
3582
|
-
mcpServers:
|
|
3941
|
+
var CursorMcpFileSchema = z34.object({
|
|
3942
|
+
mcpServers: z34.record(z34.string(), z34.object({}).passthrough()).optional()
|
|
3583
3943
|
}).passthrough();
|
|
3584
3944
|
var CURSOR_HOOKS = {
|
|
3585
3945
|
sessionStart: `${CLI_BIN} hook session-start --format cursor`,
|
|
@@ -3643,7 +4003,7 @@ var cursorInstaller = {
|
|
|
3643
4003
|
};
|
|
3644
4004
|
|
|
3645
4005
|
// src/agents/opencode.ts
|
|
3646
|
-
import { z as
|
|
4006
|
+
import { z as z35 } from "zod";
|
|
3647
4007
|
|
|
3648
4008
|
// src/agents/opencode-plugin.ts
|
|
3649
4009
|
var OPENCODE_PLUGIN_FILENAME = "quiel.js";
|
|
@@ -3693,9 +4053,9 @@ export const QuielPlugin = async ({ directory }) => {
|
|
|
3693
4053
|
// src/agents/opencode.ts
|
|
3694
4054
|
var OPENCODE_CONFIG_PATH = "opencode.json";
|
|
3695
4055
|
var OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
3696
|
-
var OpencodeConfigSchema =
|
|
3697
|
-
$schema:
|
|
3698
|
-
mcp:
|
|
4056
|
+
var OpencodeConfigSchema = z35.object({
|
|
4057
|
+
$schema: z35.string().optional(),
|
|
4058
|
+
mcp: z35.record(z35.string(), z35.object({}).passthrough()).optional()
|
|
3699
4059
|
}).passthrough();
|
|
3700
4060
|
var opencodeInstaller = {
|
|
3701
4061
|
kind: AgentKind.OPENCODE,
|
|
@@ -3740,8 +4100,8 @@ var VERSION_ENV = {
|
|
|
3740
4100
|
[AgentKind.CLAUDE_CODE]: "CLAUDE_CODE_VERSION"
|
|
3741
4101
|
};
|
|
3742
4102
|
var UNKNOWN_AGENT_VERSION = "unknown";
|
|
3743
|
-
function readAgentVersion(
|
|
3744
|
-
const name = VERSION_ENV[
|
|
4103
|
+
function readAgentVersion(kind2, env = process.env) {
|
|
4104
|
+
const name = VERSION_ENV[kind2];
|
|
3745
4105
|
const value = name ? env[name] : void 0;
|
|
3746
4106
|
return value && value.trim().length > 0 ? value.trim() : UNKNOWN_AGENT_VERSION;
|
|
3747
4107
|
}
|
|
@@ -3753,12 +4113,12 @@ var INSTALLERS = [
|
|
|
3753
4113
|
cursorInstaller,
|
|
3754
4114
|
opencodeInstaller
|
|
3755
4115
|
];
|
|
3756
|
-
var
|
|
3757
|
-
function installerFor(
|
|
3758
|
-
const installer =
|
|
4116
|
+
var BY_KIND3 = new Map(INSTALLERS.map((i) => [i.kind, i]));
|
|
4117
|
+
function installerFor(kind2) {
|
|
4118
|
+
const installer = BY_KIND3.get(kind2);
|
|
3759
4119
|
if (!installer) {
|
|
3760
4120
|
throw new Error(
|
|
3761
|
-
`\u0414\u043B\u044F \u0432\u0438\u0434\u0430 \u0430\u0433\u0435\u043D\u0442\u0430 ${
|
|
4121
|
+
`\u0414\u043B\u044F \u0432\u0438\u0434\u0430 \u0430\u0433\u0435\u043D\u0442\u0430 ${kind2} \u043D\u0435\u0442 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0449\u0438\u043A\u0430. \u041E\u0431\u043D\u043E\u0432\u0438\u0442\u0435 @quiel/cli: \u0432\u0438\u0434\u0438\u043C\u043E, \u0440\u0435\u0435\u0441\u0442\u0440 \u043D\u043E\u0432\u0435\u0435 \u044D\u0442\u043E\u0433\u043E \u043F\u0430\u043A\u0435\u0442\u0430.`
|
|
3762
4122
|
);
|
|
3763
4123
|
}
|
|
3764
4124
|
return installer;
|
|
@@ -3820,10 +4180,11 @@ var createSocket = (url, options) => io(url, {
|
|
|
3820
4180
|
// src/hooks/audit-sender.ts
|
|
3821
4181
|
var DEFAULT_CONNECT_TIMEOUT_MS = 3e3;
|
|
3822
4182
|
var DEFAULT_FLUSH_GRACE_MS = 150;
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
4183
|
+
var WIRE_EVENTS = /* @__PURE__ */ new Set(["audit:command", "task:usage", "session-limit-reached"]);
|
|
4184
|
+
function sendHookActions(actions, options = {}) {
|
|
4185
|
+
const wireActions = actions.filter((action) => WIRE_EVENTS.has(action.type));
|
|
4186
|
+
if (wireActions.length === 0) return;
|
|
4187
|
+
void dispatch(wireActions, options).catch(() => {
|
|
3827
4188
|
});
|
|
3828
4189
|
}
|
|
3829
4190
|
async function dispatch(actions, options) {
|
|
@@ -3838,7 +4199,7 @@ async function dispatch(actions, options) {
|
|
|
3838
4199
|
});
|
|
3839
4200
|
try {
|
|
3840
4201
|
await connectOnce(socket, options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS);
|
|
3841
|
-
for (const action of actions) socket.emit(
|
|
4202
|
+
for (const action of actions) socket.emit(action.type, action.payload);
|
|
3842
4203
|
await sleep(options.flushGraceMs ?? DEFAULT_FLUSH_GRACE_MS);
|
|
3843
4204
|
} finally {
|
|
3844
4205
|
socket.disconnect();
|
|
@@ -3855,7 +4216,7 @@ function trimTrailingSlash(url) {
|
|
|
3855
4216
|
}
|
|
3856
4217
|
|
|
3857
4218
|
// src/hooks/format.ts
|
|
3858
|
-
import { z as
|
|
4219
|
+
import { z as z36 } from "zod";
|
|
3859
4220
|
var HOOK_FORMATS = ["claude", "cursor", "opencode"];
|
|
3860
4221
|
function asHookFormat(raw) {
|
|
3861
4222
|
const value = raw.trim().toLowerCase();
|
|
@@ -3868,18 +4229,18 @@ var CLAUDE_EVENT = {
|
|
|
3868
4229
|
"pre-tool-use": "PreToolUse",
|
|
3869
4230
|
"pre-compact": "PreCompact"
|
|
3870
4231
|
};
|
|
3871
|
-
var CursorShellInputSchema =
|
|
3872
|
-
var CursorStopInputSchema =
|
|
4232
|
+
var CursorShellInputSchema = z36.object({ command: z36.string(), cwd: z36.string().optional() }).passthrough();
|
|
4233
|
+
var CursorStopInputSchema = z36.object({ status: z36.string().optional(), loop_count: z36.number().optional() }).passthrough();
|
|
3873
4234
|
function cursorPermission(decision) {
|
|
3874
4235
|
if (decision === "deny") return "deny";
|
|
3875
4236
|
if (decision === "allow") return "allow";
|
|
3876
4237
|
return "ask";
|
|
3877
4238
|
}
|
|
3878
|
-
var OpencodePayloadSchema =
|
|
3879
|
-
directory:
|
|
3880
|
-
input:
|
|
3881
|
-
output:
|
|
3882
|
-
event:
|
|
4239
|
+
var OpencodePayloadSchema = z36.object({
|
|
4240
|
+
directory: z36.string().optional(),
|
|
4241
|
+
input: z36.object({ tool: z36.string().optional() }).passthrough().optional(),
|
|
4242
|
+
output: z36.object({ args: z36.record(z36.string(), z36.unknown()).optional() }).passthrough().optional(),
|
|
4243
|
+
event: z36.object({ type: z36.string().optional() }).passthrough().optional()
|
|
3883
4244
|
}).passthrough();
|
|
3884
4245
|
var OPENCODE_TOOLS = {
|
|
3885
4246
|
bash: { name: "Bash", arg: "command", field: "command" },
|
|
@@ -4581,6 +4942,9 @@ var askHumanInputShape = {
|
|
|
4581
4942
|
targetMemberId: questionAskPayloadSchema.shape.targetMemberId.describe(
|
|
4582
4943
|
"ID \u043A\u043E\u043D\u043A\u0440\u0435\u0442\u043D\u043E\u0433\u043E \u0443\u0447\u0430\u0441\u0442\u043D\u0438\u043A\u0430 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u2014 \u0430\u0434\u0440\u0435\u0441\u0430\u0442 \u0432\u043E\u043F\u0440\u043E\u0441\u0430. \u041D\u0443\u0436\u0435\u043D \u0420\u041E\u0412\u041D\u041E \u041E\u0414\u0418\u041D \u0430\u0434\u0440\u0435\u0441\u0430\u0442: targetRole \u0418\u041B\u0418 targetMemberId, \u043D\u0435 \u043E\u0431\u0430 \u0441\u0440\u0430\u0437\u0443 \u0438 \u043D\u0435 \u043D\u0438 \u043E\u0434\u043D\u043E\u0433\u043E."
|
|
4583
4944
|
),
|
|
4945
|
+
wantsFiles: questionAskPayloadSchema.shape.wantsFiles.describe(
|
|
4946
|
+
"\u041F\u043E\u043F\u0440\u043E\u0441\u0438\u0442\u044C \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u043F\u0440\u0438\u043B\u043E\u0436\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u043A \u043E\u0442\u0432\u0435\u0442\u0443 (\u0441\u043A\u0440\u0438\u043D\u0448\u043E\u0442, \u043B\u043E\u0433, \u0432\u044B\u0433\u0440\u0443\u0437\u043A\u0443). \u0424\u043E\u0440\u043C\u0430 \u043E\u0442\u0432\u0435\u0442\u0430 \u043E\u0442\u043A\u0440\u043E\u0435\u0442\u0441\u044F \u0441\u0440\u0430\u0437\u0443 \u0441 \u0432\u044B\u0431\u043E\u0440\u043E\u043C \u0444\u0430\u0439\u043B\u0430. \u042D\u0442\u043E \u041F\u0420\u041E\u0421\u042C\u0411\u0410, \u0430 \u043D\u0435 \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u0435: \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0432\u043F\u0440\u0430\u0432\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u0442\u044C \u0431\u0435\u0437 \u0444\u0430\u0439\u043B\u043E\u0432, \u0438 \u0442\u043E\u0433\u0434\u0430 `attachments` \u0432 \u043E\u0442\u0432\u0435\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u043F\u0443\u0441\u0442\u044B\u043C."
|
|
4947
|
+
),
|
|
4584
4948
|
options: questionAskPayloadSchema.shape.options.describe(
|
|
4585
4949
|
"\u0412\u0430\u0440\u0438\u0430\u043D\u0442\u044B \u043E\u0442\u0432\u0435\u0442\u0430 (\u043F\u043E\u043A\u0430\u0436\u0443\u0442\u0441\u044F \u043A\u043D\u043E\u043F\u043A\u0430\u043C\u0438 \u0432 UI/Telegram). \u041D\u0435 \u043F\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0439 \u2014 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u043E\u0442\u0432\u0435\u0442\u0438\u0442 \u0441\u0432\u043E\u0431\u043E\u0434\u043D\u044B\u043C \u0442\u0435\u043A\u0441\u0442\u043E\u043C."
|
|
4586
4950
|
),
|
|
@@ -4600,6 +4964,7 @@ async function askHumanHandler(args, runtime) {
|
|
|
4600
4964
|
...args.targetRole ? { targetRole: args.targetRole } : {},
|
|
4601
4965
|
...args.targetMemberId ? { targetMemberId: args.targetMemberId } : {},
|
|
4602
4966
|
...args.options && args.options.length > 0 ? { options: args.options } : {},
|
|
4967
|
+
...args.wantsFiles ? { wantsFiles: true } : {},
|
|
4603
4968
|
blocking: args.blocking,
|
|
4604
4969
|
waitSec
|
|
4605
4970
|
});
|
|
@@ -4656,10 +5021,20 @@ async function waitAnswerHandler(args, runtime) {
|
|
|
4656
5021
|
`\u0412\u043E\u043F\u0440\u043E\u0441 ${result.data.question.id} \u0432\u0441\u0451 \u0435\u0449\u0451 \u0431\u0435\u0437 \u043E\u0442\u0432\u0435\u0442\u0430 (\u0436\u0434\u0430\u043B ${waitSec} \u0441). \u0412\u044B\u0437\u043E\u0432\u0438 wait_answer \u0435\u0449\u0451 \u0440\u0430\u0437 \u0441 \u0442\u0435\u043C \u0436\u0435 questionId, \u043A\u043E\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0443\u043C\u0435\u0441\u0442\u043D\u043E.`
|
|
4657
5022
|
);
|
|
4658
5023
|
}
|
|
5024
|
+
function describeAnswerAttachments(question) {
|
|
5025
|
+
if (question.attachments.length === 0) return "";
|
|
5026
|
+
const lines = question.attachments.map(
|
|
5027
|
+
(file) => file.downloadUrl ? `- ${file.fileName} (${file.mimeType}) \u2014 \u0441\u043A\u0430\u0447\u0430\u0439: ${file.downloadUrl}` : `- ${file.fileName} (${file.mimeType}) \u2014 \u0441\u0441\u044B\u043B\u043A\u0430 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430, \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442`
|
|
5028
|
+
);
|
|
5029
|
+
return `
|
|
5030
|
+
|
|
5031
|
+
\u041A \u043E\u0442\u0432\u0435\u0442\u0443 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u044B \u0444\u0430\u0439\u043B\u044B (${question.attachments.length}). \u042D\u0442\u043E \u0447\u0430\u0441\u0442\u044C \u043E\u0442\u0432\u0435\u0442\u0430: \u0441\u043A\u0430\u0447\u0430\u0439 \u0438 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0439 \u041A\u0410\u0416\u0414\u042B\u0419, \u0441\u0441\u044B\u043B\u043A\u0438 \u0436\u0438\u0432\u0443\u0442 ${question.attachments[0]?.expiresInSeconds ?? 300} \u0441 \u2014 \u043D\u0435 \u043E\u0442\u043A\u043B\u0430\u0434\u044B\u0432\u0430\u0439.
|
|
5032
|
+
` + lines.join("\n");
|
|
5033
|
+
}
|
|
4659
5034
|
function describeSettledQuestion(question) {
|
|
4660
5035
|
if (question.status === QuestionStatus.ANSWERED) {
|
|
4661
5036
|
return `\u0412\u043E\u043F\u0440\u043E\u0441 ${question.id} \u043F\u043E\u043B\u0443\u0447\u0438\u043B \u043E\u0442\u0432\u0435\u0442:
|
|
4662
|
-
${question.answerMd ?? ""}`;
|
|
5037
|
+
${question.answerMd ?? ""}${describeAnswerAttachments(question)}`;
|
|
4663
5038
|
}
|
|
4664
5039
|
if (question.status === QuestionStatus.DISMISSED) {
|
|
4665
5040
|
return `\u0412\u043E\u043F\u0440\u043E\u0441 ${question.id} \u043E\u0442\u043A\u043B\u043E\u043D\u0451\u043D (DISMISSED) \u2014 \u043E\u0442\u0432\u0435\u0442\u0430 \u043D\u0435 \u0431\u0443\u0434\u0435\u0442. \u0420\u0435\u0448\u0438, \u043A\u0430\u043A \u0434\u0435\u0439\u0441\u0442\u0432\u043E\u0432\u0430\u0442\u044C \u0434\u0430\u043B\u044C\u0448\u0435, \u0441\u0430\u043C, \u0438\u043B\u0438 \u0437\u0430\u0434\u0430\u0439 \u0432\u043E\u043F\u0440\u043E\u0441 \u0437\u0430\u043D\u043E\u0432\u043E.`;
|
|
@@ -4670,15 +5045,15 @@ ${question.answerMd ?? ""}`;
|
|
|
4670
5045
|
// package.json
|
|
4671
5046
|
var package_default = {
|
|
4672
5047
|
name: "@quiel/cli",
|
|
4673
|
-
version: "0.
|
|
5048
|
+
version: "0.5.1",
|
|
4674
5049
|
description: "CLI \u0438 MCP-\u0441\u0435\u0440\u0432\u0435\u0440 Quiel: \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0430\u0435\u0442 \u0430\u0433\u0435\u043D\u0442\u0430 \u0443\u0447\u0430\u0441\u0442\u043D\u0438\u043A\u0430 (Claude Code, Codex, Cursor, OpenCode) \u043A \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u0435",
|
|
4675
|
-
homepage: "https://quiel.
|
|
5050
|
+
homepage: "https://quiel.app",
|
|
4676
5051
|
repository: {
|
|
4677
5052
|
type: "git",
|
|
4678
|
-
url: "git+https://github.com/Quiel-
|
|
5053
|
+
url: "git+https://github.com/Quiel-App/quiel-cli.git"
|
|
4679
5054
|
},
|
|
4680
5055
|
bugs: {
|
|
4681
|
-
url: "https://github.com/Quiel-
|
|
5056
|
+
url: "https://github.com/Quiel-App/quiel-cli/issues"
|
|
4682
5057
|
},
|
|
4683
5058
|
keywords: [
|
|
4684
5059
|
"quiel",
|
|
@@ -5639,7 +6014,7 @@ async function settleApproval(ack, commandCwd, runtime, waitSecUsed) {
|
|
|
5639
6014
|
}
|
|
5640
6015
|
|
|
5641
6016
|
// src/mcp/set-mode.ts
|
|
5642
|
-
import { z as
|
|
6017
|
+
import { z as z37 } from "zod";
|
|
5643
6018
|
|
|
5644
6019
|
// src/cli/mode.ts
|
|
5645
6020
|
function parseModeArg(raw) {
|
|
@@ -5680,7 +6055,7 @@ async function requestModeChange(modeArg, options = {}) {
|
|
|
5680
6055
|
|
|
5681
6056
|
// src/mcp/set-mode.ts
|
|
5682
6057
|
var setModeInputShape = {
|
|
5683
|
-
mode:
|
|
6058
|
+
mode: z37.enum(["auto", "manual"]).describe("auto \u2014 \u0432\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0430\u0432\u0442\u043E\u043D\u043E\u043C\u043D\u044B\u0439 \u0440\u0435\u0436\u0438\u043C \u0430\u0433\u0435\u043D\u0442\u0430, manual \u2014 \u0432\u044B\u043A\u043B\u044E\u0447\u0438\u0442\u044C (\xA710.2 \u0422\u0417)")
|
|
5684
6059
|
};
|
|
5685
6060
|
async function setModeHandler(args, runtime) {
|
|
5686
6061
|
const result = await requestModeChange(args.mode, {
|
|
@@ -5695,20 +6070,20 @@ async function setModeHandler(args, runtime) {
|
|
|
5695
6070
|
}
|
|
5696
6071
|
|
|
5697
6072
|
// src/mcp/submit-work.ts
|
|
5698
|
-
import { z as
|
|
6073
|
+
import { z as z38 } from "zod";
|
|
5699
6074
|
var submitWorkInputShape = {
|
|
5700
|
-
branchName:
|
|
6075
|
+
branchName: z38.string().min(1).describe(
|
|
5701
6076
|
"\u0418\u043C\u044F \u0432\u0435\u0442\u043A\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u0431\u0435\u0440\u0438 \u0440\u043E\u0432\u043D\u043E \u0438\u0437 project.branchName \u0432 TaskPayload, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0432\u0435\u0440\u043D\u0443\u043B next_task. \u041D\u0435 \u043F\u0440\u0438\u0434\u0443\u043C\u044B\u0432\u0430\u0439 \u0441\u0432\u043E\u0451."
|
|
5702
6077
|
),
|
|
5703
|
-
defaultBranch:
|
|
5704
|
-
commitPrefix:
|
|
5705
|
-
taskKey:
|
|
5706
|
-
taskTitle:
|
|
5707
|
-
repoRoot:
|
|
5708
|
-
testsPassed:
|
|
6078
|
+
defaultBranch: z38.string().min(1).describe("\u041E\u0441\u043D\u043E\u0432\u043D\u0430\u044F \u0432\u0435\u0442\u043A\u0430 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F \u2014 \u0438\u0437 project.repos[].defaultBranch."),
|
|
6079
|
+
commitPrefix: z38.string().min(1).describe('\u041F\u0440\u0435\u0444\u0438\u043A\u0441 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F \u043A\u043E\u043C\u043C\u0438\u0442\u0430 \u2014 \u0438\u0437 project.commitPrefix, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 "ATL-42:".'),
|
|
6080
|
+
taskKey: z38.string().min(1).describe("\u041A\u043B\u044E\u0447 \u0437\u0430\u0434\u0430\u0447\u0438, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 ATL-42 \u2014 \u0438\u0437 task.key."),
|
|
6081
|
+
taskTitle: z38.string().min(1).describe("\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u0438\u0437 task.title."),
|
|
6082
|
+
repoRoot: z38.string().min(1).optional().describe("\u041A\u043E\u0440\u0435\u043D\u044C git-\u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F. \u041F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u2014 \u0440\u0430\u0431\u043E\u0447\u0438\u0439 \u043A\u0430\u0442\u0430\u043B\u043E\u0433 \u043F\u0440\u043E\u0435\u043A\u0442\u0430."),
|
|
6083
|
+
testsPassed: z38.boolean().optional().describe(
|
|
5709
6084
|
"\u041F\u0440\u043E\u0448\u043B\u0438 \u043B\u0438 \u0442\u0435\u0441\u0442\u044B. \u0415\u0441\u043B\u0438 \u043F\u0440\u043E\u0435\u043A\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u0435\u043B\u0451\u043D\u044B\u0445 \u0442\u0435\u0441\u0442\u043E\u0432, \u0430 \u0437\u0434\u0435\u0441\u044C false \u2014 \u0441\u0434\u0430\u0447\u0430 \u043D\u0435 \u0441\u043E\u0441\u0442\u043E\u0438\u0442\u0441\u044F, \u0438 \u044D\u0442\u043E \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E."
|
|
5710
6085
|
),
|
|
5711
|
-
requireTestsPassed:
|
|
6086
|
+
requireTestsPassed: z38.boolean().optional().describe("ProjectSettings.requireTests \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u2014 \u0438\u0437 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u0430 \u0437\u0430\u0434\u0430\u0447\u0438.")
|
|
5712
6087
|
};
|
|
5713
6088
|
async function submitWorkHandler(args, runtime) {
|
|
5714
6089
|
const state = readState(runtime.stateFilePath);
|
|
@@ -5943,6 +6318,7 @@ ${JSON.stringify(result.data.task, null, 2)}`
|
|
|
5943
6318
|
}
|
|
5944
6319
|
|
|
5945
6320
|
// src/mcp/register-tools.ts
|
|
6321
|
+
var ATTACHMENTS_HINT = "\u0412\u0410\u0416\u041D\u041E: \u0443 \u0437\u0430\u0434\u0430\u0447\u0438 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u043E\u043B\u0435 `attachments` \u2014 \u0444\u0430\u0439\u043B\u044B, \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u043D\u044B\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u043E\u043C \u043A \u043F\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0435 (\u043C\u0430\u043A\u0435\u0442, \u043B\u043E\u0433, \u0432\u044B\u0433\u0440\u0443\u0437\u043A\u0430). \u042D\u0442\u043E \u0427\u0410\u0421\u0422\u042C \u0417\u0410\u0414\u0410\u041D\u0418\u042F, \u0430 \u043D\u0435 \u0443\u043A\u0440\u0430\u0448\u0435\u043D\u0438\u0435: \u0441\u043A\u0430\u0447\u0430\u0439 \u043A\u0430\u0436\u0434\u044B\u0439 \u043F\u043E `downloadUrl` \u0438 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0439 \u041F\u0415\u0420\u0415\u0414 \u0440\u0430\u0431\u043E\u0442\u043E\u0439. \u0421\u0441\u044B\u043B\u043A\u0430 \u0436\u0438\u0432\u0451\u0442 `expiresInSeconds` \u0441\u0435\u043A\u0443\u043D\u0434 \u2014 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u0439 \u0441\u0440\u0430\u0437\u0443, \u0430 \u043D\u0435 \u043E\u0442\u043A\u043B\u0430\u0434\u044B\u0432\u0430\u0439. \u041F\u0443\u0441\u0442\u0430\u044F `downloadUrl` \u043E\u0437\u043D\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043E \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E: \u0442\u043E\u0433\u0434\u0430 \u0441\u043F\u0440\u043E\u0441\u0438 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0447\u0435\u0440\u0435\u0437 `ask_human`, \u0430 \u043D\u0435 \u0440\u0430\u0431\u043E\u0442\u0430\u0439 \u0431\u0435\u0437 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\u043E\u0432. \u041F\u0443\u0441\u0442\u043E\u0439 \u0441\u043F\u0438\u0441\u043E\u043A `attachments` \u2014 \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E, \u0444\u0430\u0439\u043B\u043E\u0432 \u043F\u0440\u043E\u0441\u0442\u043E \u043D\u0435\u0442.";
|
|
5946
6322
|
function registerTools(server, runtime) {
|
|
5947
6323
|
server.registerTool(
|
|
5948
6324
|
"set_mode",
|
|
@@ -5957,7 +6333,7 @@ function registerTools(server, runtime) {
|
|
|
5957
6333
|
"next_task",
|
|
5958
6334
|
{
|
|
5959
6335
|
title: "\u0412\u0437\u044F\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0443\u044E \u0437\u0430\u0434\u0430\u0447\u0443",
|
|
5960
|
-
description: "\u0411\u043B\u043E\u043A\u0438\u0440\u0443\u044E\u0449\u0438\u0439 \u0432\u044B\u0437\u043E\u0432: \u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0438 \u0437\u0430\u0431\u0440\u0430\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0443\u044E \u0437\u0430\u0434\u0430\u0447\u0443 \u0438\u0437 \u043E\u0447\u0435\u0440\u0435\u0434\u0438 \u0434\u0438\u0441\u043F\u0435\u0442\u0447\u0435\u0440\u0430 (\xA79.1, \xA710.3 \u0422\u0417). \u041F\u0440\u043E\u0434\u0432\u0438\u0433\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 ASSIGNED \u2192 IN_PROGRESS. \u041F\u0443\u0441\u0442\u043E\u0439 \u043E\u0442\u0432\u0435\u0442 ({empty:true}) \u2014 \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0438\u0441\u0445\u043E\u0434, \u0437\u0430\u0434\u0430\u0447 \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u043D\u0435\u0442, \u043D\u0435 \u043E\u0448\u0438\u0431\u043A\u0430.",
|
|
6336
|
+
description: "\u0411\u043B\u043E\u043A\u0438\u0440\u0443\u044E\u0449\u0438\u0439 \u0432\u044B\u0437\u043E\u0432: \u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0438 \u0437\u0430\u0431\u0440\u0430\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0443\u044E \u0437\u0430\u0434\u0430\u0447\u0443 \u0438\u0437 \u043E\u0447\u0435\u0440\u0435\u0434\u0438 \u0434\u0438\u0441\u043F\u0435\u0442\u0447\u0435\u0440\u0430 (\xA79.1, \xA710.3 \u0422\u0417). \u041F\u0440\u043E\u0434\u0432\u0438\u0433\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 ASSIGNED \u2192 IN_PROGRESS. \u041F\u0443\u0441\u0442\u043E\u0439 \u043E\u0442\u0432\u0435\u0442 ({empty:true}) \u2014 \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0438\u0441\u0445\u043E\u0434, \u0437\u0430\u0434\u0430\u0447 \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u043D\u0435\u0442, \u043D\u0435 \u043E\u0448\u0438\u0431\u043A\u0430. " + ATTACHMENTS_HINT,
|
|
5961
6337
|
inputSchema: nextTaskInputShape
|
|
5962
6338
|
},
|
|
5963
6339
|
(args) => nextTaskHandler(args, runtime)
|
|
@@ -5966,7 +6342,7 @@ function registerTools(server, runtime) {
|
|
|
5966
6342
|
"get_task",
|
|
5967
6343
|
{
|
|
5968
6344
|
title: "\u041F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443",
|
|
5969
|
-
description: "\u0421\u0432\u0435\u0436\u0438\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043F\u043E id, \u0432\u043A\u043B\u044E\u0447\u0430\u044F \u043E\u0442\u0432\u0435\u0442\u044B \u043D\u0430 \u043E\u0442\u043A\u0440\u044B\u0442\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B (\xA710.3 \u0422\u0417).",
|
|
6345
|
+
description: "\u0421\u0432\u0435\u0436\u0438\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043F\u043E id, \u0432\u043A\u043B\u044E\u0447\u0430\u044F \u043E\u0442\u0432\u0435\u0442\u044B \u043D\u0430 \u043E\u0442\u043A\u0440\u044B\u0442\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B (\xA710.3 \u0422\u0417). " + ATTACHMENTS_HINT,
|
|
5970
6346
|
inputSchema: getTaskInputShape
|
|
5971
6347
|
},
|
|
5972
6348
|
(args) => getTaskHandler(args, runtime)
|
|
@@ -6181,13 +6557,13 @@ function formatConnectResult(result) {
|
|
|
6181
6557
|
}
|
|
6182
6558
|
|
|
6183
6559
|
// src/hooks/pre-compact.ts
|
|
6184
|
-
import { z as
|
|
6185
|
-
var PreCompactInputSchema =
|
|
6186
|
-
hook_event_name:
|
|
6187
|
-
session_id:
|
|
6188
|
-
cwd:
|
|
6189
|
-
trigger:
|
|
6190
|
-
custom_instructions:
|
|
6560
|
+
import { z as z39 } from "zod";
|
|
6561
|
+
var PreCompactInputSchema = z39.object({
|
|
6562
|
+
hook_event_name: z39.literal("PreCompact"),
|
|
6563
|
+
session_id: z39.string(),
|
|
6564
|
+
cwd: z39.string(),
|
|
6565
|
+
trigger: z39.enum(["manual", "auto"]),
|
|
6566
|
+
custom_instructions: z39.string().nullable()
|
|
6191
6567
|
}).passthrough();
|
|
6192
6568
|
function preCompactHook(_input, state, now = () => (/* @__PURE__ */ new Date()).toISOString()) {
|
|
6193
6569
|
const lastPreCompact = state.currentTask ? { ...state.currentTask, savedAt: now() } : null;
|
|
@@ -6196,14 +6572,14 @@ function preCompactHook(_input, state, now = () => (/* @__PURE__ */ new Date()).
|
|
|
6196
6572
|
|
|
6197
6573
|
// src/hooks/pre-tool-use.ts
|
|
6198
6574
|
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3 } from "path";
|
|
6199
|
-
import { z as
|
|
6200
|
-
var PreToolUseInputSchema =
|
|
6201
|
-
hook_event_name:
|
|
6202
|
-
session_id:
|
|
6203
|
-
cwd:
|
|
6204
|
-
tool_name:
|
|
6205
|
-
tool_input:
|
|
6206
|
-
tool_use_id:
|
|
6575
|
+
import { z as z40 } from "zod";
|
|
6576
|
+
var PreToolUseInputSchema = z40.object({
|
|
6577
|
+
hook_event_name: z40.literal("PreToolUse"),
|
|
6578
|
+
session_id: z40.string(),
|
|
6579
|
+
cwd: z40.string(),
|
|
6580
|
+
tool_name: z40.string(),
|
|
6581
|
+
tool_input: z40.record(z40.string(), z40.unknown()),
|
|
6582
|
+
tool_use_id: z40.string()
|
|
6207
6583
|
}).passthrough();
|
|
6208
6584
|
var NO_TRUST_CACHE_REASON = "\u041A\u044D\u0448 \u043F\u0440\u0430\u0432\u0438\u043B \u0434\u043E\u0432\u0435\u0440\u0438\u044F (TrustRules) \u043F\u0443\u0441\u0442 \u2014 \u043A\u043B\u0438\u0435\u043D\u0442 \u043D\u0438 \u0440\u0430\u0437\u0443 \u043D\u0435 \u043F\u043E\u043B\u0443\u0447\u0430\u043B \u0438\u0445 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 (\u043D\u0435\u0442 agent:hello/trust:updated). \u041E\u043F\u0440\u0435\u0434\u0435\u043B\u0438\u0442\u044C \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0439 \u043F\u0440\u043E\u0444\u0438\u043B\u044C (full/guarded/approve-all) \u0431\u0435\u0437 \u043D\u0435\u0433\u043E \u043D\u0435\u043B\u044C\u0437\u044F, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u043F\u043E \u043F\u0440\u0430\u0432\u0438\u043B\u0443 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 (fail-closed \u043F\u0440\u0438 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E\u0441\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \xA710.4 \u0422\u0417) \u043A\u043E\u043C\u0430\u043D\u0434\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F. \u041F\u043E\u0434\u043D\u0438\u043C\u0438 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435: `quiel connect` (\u044D\u0442\u0430 \u043A\u043E\u043C\u0430\u043D\u0434\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0430 \u0438\u043C\u0435\u043D\u043D\u043E \u0434\u043B\u044F \u0442\u0430\u043A\u043E\u0433\u043E \u0441\u043B\u0443\u0447\u0430\u044F, \u0441\u043C. isBootstrapCommand) \u2014 \u043F\u043E\u0441\u043B\u0435 \u0440\u0443\u043A\u043E\u043F\u043E\u0436\u0430\u0442\u0438\u044F \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u043F\u0440\u0438\u0434\u0443\u0442, \u0438 \u043A\u043E\u043C\u0430\u043D\u0434\u044B \u043D\u0430\u0447\u043D\u0443\u0442 \u043F\u0440\u043E\u0445\u043E\u0434\u0438\u0442\u044C. \u0415\u0441\u043B\u0438 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044C, \u0432\u044B\u0437\u043E\u0432\u0438 request_approval.";
|
|
6209
6585
|
var BOOTSTRAP_COMMAND_RE = /^quiel\s+(connect|status)\b/;
|
|
@@ -6348,16 +6724,100 @@ function handleFileWrite(input, state, now) {
|
|
|
6348
6724
|
}
|
|
6349
6725
|
|
|
6350
6726
|
// src/hooks/run.ts
|
|
6351
|
-
import { z as
|
|
6727
|
+
import { z as z44 } from "zod";
|
|
6728
|
+
|
|
6729
|
+
// src/usage/read.ts
|
|
6730
|
+
import { closeSync, openSync, readSync, statSync } from "fs";
|
|
6731
|
+
|
|
6732
|
+
// src/usage/transcript.ts
|
|
6733
|
+
function emptyUsageTotals() {
|
|
6734
|
+
return {
|
|
6735
|
+
requests: 0,
|
|
6736
|
+
inputTokens: 0,
|
|
6737
|
+
outputTokens: 0,
|
|
6738
|
+
cacheReadTokens: 0,
|
|
6739
|
+
cacheCreationTokens: 0
|
|
6740
|
+
};
|
|
6741
|
+
}
|
|
6742
|
+
function toCount(value) {
|
|
6743
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
6744
|
+
}
|
|
6745
|
+
function collectUsage(chunk) {
|
|
6746
|
+
const lastBreak = chunk.lastIndexOf("\n");
|
|
6747
|
+
if (lastBreak < 0) return { consumedBytes: 0, byModel: [] };
|
|
6748
|
+
const complete = chunk.slice(0, lastBreak + 1);
|
|
6749
|
+
const byModel = /* @__PURE__ */ new Map();
|
|
6750
|
+
for (const line of complete.split("\n")) {
|
|
6751
|
+
if (line.trim().length === 0) continue;
|
|
6752
|
+
let parsed;
|
|
6753
|
+
try {
|
|
6754
|
+
parsed = JSON.parse(line);
|
|
6755
|
+
} catch {
|
|
6756
|
+
continue;
|
|
6757
|
+
}
|
|
6758
|
+
const usage = parsed.message?.usage;
|
|
6759
|
+
if (!usage) continue;
|
|
6760
|
+
const model = typeof parsed.message?.model === "string" && parsed.message.model.length > 0 ? parsed.message.model : "unknown";
|
|
6761
|
+
const totals = byModel.get(model) ?? emptyUsageTotals();
|
|
6762
|
+
totals.requests += 1;
|
|
6763
|
+
totals.inputTokens += toCount(usage.input_tokens);
|
|
6764
|
+
totals.outputTokens += toCount(usage.output_tokens);
|
|
6765
|
+
totals.cacheReadTokens += toCount(usage.cache_read_input_tokens);
|
|
6766
|
+
totals.cacheCreationTokens += toCount(usage.cache_creation_input_tokens);
|
|
6767
|
+
byModel.set(model, totals);
|
|
6768
|
+
}
|
|
6769
|
+
return {
|
|
6770
|
+
// Байты, а не символы: смещение потом уходит в чтение файла, а
|
|
6771
|
+
// русские имена и эмодзи в транскрипте занимают больше одного байта.
|
|
6772
|
+
consumedBytes: Buffer.byteLength(complete, "utf8"),
|
|
6773
|
+
byModel: [...byModel].map(([model, totals]) => ({ model, ...totals }))
|
|
6774
|
+
};
|
|
6775
|
+
}
|
|
6776
|
+
function isUsageEmpty(byModel) {
|
|
6777
|
+
return byModel.every(
|
|
6778
|
+
(row) => row.inputTokens === 0 && row.outputTokens === 0 && row.cacheReadTokens === 0 && row.cacheCreationTokens === 0
|
|
6779
|
+
);
|
|
6780
|
+
}
|
|
6781
|
+
|
|
6782
|
+
// src/usage/read.ts
|
|
6783
|
+
function readNewUsage(transcriptPath, offset) {
|
|
6784
|
+
let size;
|
|
6785
|
+
try {
|
|
6786
|
+
size = statSync(transcriptPath).size;
|
|
6787
|
+
} catch {
|
|
6788
|
+
return { byModel: [], offset };
|
|
6789
|
+
}
|
|
6790
|
+
const from = size < offset ? 0 : offset;
|
|
6791
|
+
if (size <= from) return { byModel: [], offset: from };
|
|
6792
|
+
let chunk;
|
|
6793
|
+
let fd;
|
|
6794
|
+
try {
|
|
6795
|
+
fd = openSync(transcriptPath, "r");
|
|
6796
|
+
const buffer = Buffer.allocUnsafe(size - from);
|
|
6797
|
+
const read = readSync(fd, buffer, 0, buffer.length, from);
|
|
6798
|
+
chunk = buffer.subarray(0, read).toString("utf8");
|
|
6799
|
+
} catch {
|
|
6800
|
+
return { byModel: [], offset: from };
|
|
6801
|
+
} finally {
|
|
6802
|
+
if (fd !== void 0) {
|
|
6803
|
+
try {
|
|
6804
|
+
closeSync(fd);
|
|
6805
|
+
} catch {
|
|
6806
|
+
}
|
|
6807
|
+
}
|
|
6808
|
+
}
|
|
6809
|
+
const collected = collectUsage(chunk);
|
|
6810
|
+
return { byModel: collected.byModel, offset: from + collected.consumedBytes };
|
|
6811
|
+
}
|
|
6352
6812
|
|
|
6353
6813
|
// src/hooks/session-start.ts
|
|
6354
|
-
import { z as
|
|
6355
|
-
var SessionStartInputSchema =
|
|
6356
|
-
hook_event_name:
|
|
6357
|
-
session_id:
|
|
6358
|
-
cwd:
|
|
6359
|
-
source:
|
|
6360
|
-
model:
|
|
6814
|
+
import { z as z41 } from "zod";
|
|
6815
|
+
var SessionStartInputSchema = z41.object({
|
|
6816
|
+
hook_event_name: z41.literal("SessionStart"),
|
|
6817
|
+
session_id: z41.string(),
|
|
6818
|
+
cwd: z41.string(),
|
|
6819
|
+
source: z41.enum(["startup", "resume", "clear", "compact", "fork"]),
|
|
6820
|
+
model: z41.string().optional()
|
|
6361
6821
|
}).passthrough();
|
|
6362
6822
|
var SESSION_RESET_SOURCES = /* @__PURE__ */ new Set([
|
|
6363
6823
|
"startup",
|
|
@@ -6396,13 +6856,13 @@ function sessionStartHook(input, state) {
|
|
|
6396
6856
|
}
|
|
6397
6857
|
|
|
6398
6858
|
// src/hooks/stop.ts
|
|
6399
|
-
import { z as
|
|
6400
|
-
var StopInputSchema =
|
|
6401
|
-
hook_event_name:
|
|
6402
|
-
session_id:
|
|
6403
|
-
cwd:
|
|
6404
|
-
stop_hook_active:
|
|
6405
|
-
last_assistant_message:
|
|
6859
|
+
import { z as z42 } from "zod";
|
|
6860
|
+
var StopInputSchema = z42.object({
|
|
6861
|
+
hook_event_name: z42.literal("Stop"),
|
|
6862
|
+
session_id: z42.string(),
|
|
6863
|
+
cwd: z42.string(),
|
|
6864
|
+
stop_hook_active: z42.boolean(),
|
|
6865
|
+
last_assistant_message: z42.string().optional()
|
|
6406
6866
|
}).passthrough();
|
|
6407
6867
|
function taskLabel(state) {
|
|
6408
6868
|
if (!state.currentTask) return "";
|
|
@@ -6446,8 +6906,8 @@ function stopHook(input, state) {
|
|
|
6446
6906
|
}
|
|
6447
6907
|
|
|
6448
6908
|
// src/hooks/stop-failure.ts
|
|
6449
|
-
import { z as
|
|
6450
|
-
var StopFailureErrorTypeSchema =
|
|
6909
|
+
import { z as z43 } from "zod";
|
|
6910
|
+
var StopFailureErrorTypeSchema = z43.enum([
|
|
6451
6911
|
"rate_limit",
|
|
6452
6912
|
"overloaded",
|
|
6453
6913
|
"authentication_failed",
|
|
@@ -6460,13 +6920,13 @@ var StopFailureErrorTypeSchema = z41.enum([
|
|
|
6460
6920
|
"max_output_tokens",
|
|
6461
6921
|
"unknown"
|
|
6462
6922
|
]);
|
|
6463
|
-
var StopFailureInputSchema =
|
|
6464
|
-
hook_event_name:
|
|
6465
|
-
session_id:
|
|
6466
|
-
cwd:
|
|
6923
|
+
var StopFailureInputSchema = z43.object({
|
|
6924
|
+
hook_event_name: z43.literal("StopFailure"),
|
|
6925
|
+
session_id: z43.string(),
|
|
6926
|
+
cwd: z43.string(),
|
|
6467
6927
|
error: StopFailureErrorTypeSchema,
|
|
6468
|
-
error_details:
|
|
6469
|
-
last_assistant_message:
|
|
6928
|
+
error_details: z43.unknown().optional(),
|
|
6929
|
+
last_assistant_message: z43.string().optional()
|
|
6470
6930
|
}).passthrough();
|
|
6471
6931
|
function extractRetryAfterSec(errorDetails) {
|
|
6472
6932
|
if (typeof errorDetails === "number" && Number.isFinite(errorDetails) && errorDetails >= 0) {
|
|
@@ -6495,7 +6955,7 @@ function stopFailureHook(input, _state) {
|
|
|
6495
6955
|
}
|
|
6496
6956
|
|
|
6497
6957
|
// src/hooks/run.ts
|
|
6498
|
-
var HookInputSchema =
|
|
6958
|
+
var HookInputSchema = z44.discriminatedUnion("hook_event_name", [
|
|
6499
6959
|
SessionStartInputSchema,
|
|
6500
6960
|
StopInputSchema,
|
|
6501
6961
|
StopFailureInputSchema,
|
|
@@ -6509,13 +6969,31 @@ function runHook(rawInput, stateFilePath) {
|
|
|
6509
6969
|
}
|
|
6510
6970
|
const state = readState(stateFilePath);
|
|
6511
6971
|
const result = dispatch2(parsedInput.data, state);
|
|
6512
|
-
|
|
6513
|
-
|
|
6972
|
+
const usage = collectTaskUsage(parsedInput.data, state);
|
|
6973
|
+
if (result.statePatch || usage.statePatch) {
|
|
6974
|
+
writeState({ ...state, ...result.statePatch, ...usage.statePatch }, stateFilePath);
|
|
6514
6975
|
}
|
|
6515
6976
|
return {
|
|
6516
6977
|
stdout: JSON.stringify(result.output),
|
|
6517
6978
|
exitCode: 0,
|
|
6518
|
-
serverActions: result.serverActions ?? []
|
|
6979
|
+
serverActions: [...result.serverActions ?? [], ...usage.serverActions]
|
|
6980
|
+
};
|
|
6981
|
+
}
|
|
6982
|
+
function collectTaskUsage(input, state) {
|
|
6983
|
+
if (input.hook_event_name !== "Stop") return { serverActions: [] };
|
|
6984
|
+
const transcriptPath = input.transcript_path;
|
|
6985
|
+
if (typeof transcriptPath !== "string" || transcriptPath.length === 0) {
|
|
6986
|
+
return { serverActions: [] };
|
|
6987
|
+
}
|
|
6988
|
+
const before = state.usageOffsets[transcriptPath] ?? 0;
|
|
6989
|
+
const { byModel, offset } = readNewUsage(transcriptPath, before);
|
|
6990
|
+
if (offset === before) return { serverActions: [] };
|
|
6991
|
+
const statePatch = { usageOffsets: { ...state.usageOffsets, [transcriptPath]: offset } };
|
|
6992
|
+
const taskId = state.currentTask?.taskId;
|
|
6993
|
+
if (!taskId || isUsageEmpty(byModel)) return { statePatch, serverActions: [] };
|
|
6994
|
+
return {
|
|
6995
|
+
statePatch,
|
|
6996
|
+
serverActions: [{ type: "task:usage", payload: { taskId, entries: byModel } }]
|
|
6519
6997
|
};
|
|
6520
6998
|
}
|
|
6521
6999
|
function dispatch2(input, state) {
|
|
@@ -6629,13 +7107,13 @@ var FIELD_PROMPTS = {
|
|
|
6629
7107
|
async function askAgentKind(options, prompter, interactive, cwd) {
|
|
6630
7108
|
const fromFlag = options.agent?.trim();
|
|
6631
7109
|
if (fromFlag && fromFlag.length > 0) {
|
|
6632
|
-
const
|
|
6633
|
-
if (!
|
|
7110
|
+
const kind2 = agentKindFromCliKey(fromFlag);
|
|
7111
|
+
if (!kind2) {
|
|
6634
7112
|
throw new Error(
|
|
6635
7113
|
`\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 --agent: ${fromFlag}. \u0414\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E: ${agentKindCliKeys().join(", ")}.`
|
|
6636
7114
|
);
|
|
6637
7115
|
}
|
|
6638
|
-
return
|
|
7116
|
+
return kind2;
|
|
6639
7117
|
}
|
|
6640
7118
|
if (!interactive) return DEFAULT_AGENT_KIND;
|
|
6641
7119
|
const detected = detectAgentKinds((relative3) => existsSync10(join10(cwd, relative3)));
|
|
@@ -6837,9 +7315,9 @@ async function getStatus(options = {}, deps = {}) {
|
|
|
6837
7315
|
reachability
|
|
6838
7316
|
};
|
|
6839
7317
|
}
|
|
6840
|
-
function describeAgentKindLine(
|
|
6841
|
-
const info = describeAgentKind(
|
|
6842
|
-
if (!info) return `${
|
|
7318
|
+
function describeAgentKindLine(kind2) {
|
|
7319
|
+
const info = describeAgentKind(kind2);
|
|
7320
|
+
if (!info) return `${kind2} (\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u0430\u0433\u0435\u043D\u0442 \u2014 \u043A\u043B\u0438\u0435\u043D\u0442 \u043D\u043E\u0432\u0435\u0435 \u0440\u0435\u0435\u0441\u0442\u0440\u0430?)`;
|
|
6843
7321
|
const beta = info.support === "documented" ? ", \u0431\u0435\u0442\u0430: \u0436\u0438\u0432\u044C\u0451\u043C \u043D\u0435 \u043F\u0440\u043E\u0432\u0435\u0440\u0435\u043D\u043E" : "";
|
|
6844
7322
|
return `${info.label} \u2014 ${info.vendor}${beta}`;
|
|
6845
7323
|
}
|
|
@@ -6979,14 +7457,14 @@ function createProgram() {
|
|
|
6979
7457
|
if (result.stderr.length > 0) process.stderr.write(`${result.stderr}
|
|
6980
7458
|
`);
|
|
6981
7459
|
process.exitCode = result.exitCode;
|
|
6982
|
-
if (result.execution)
|
|
7460
|
+
if (result.execution) sendHookActions(result.execution.serverActions);
|
|
6983
7461
|
return;
|
|
6984
7462
|
}
|
|
6985
7463
|
const execution = runCliHook(raw);
|
|
6986
7464
|
process.stdout.write(`${execution.stdout}
|
|
6987
7465
|
`);
|
|
6988
7466
|
process.exitCode = execution.exitCode;
|
|
6989
|
-
|
|
7467
|
+
sendHookActions(execution.serverActions);
|
|
6990
7468
|
});
|
|
6991
7469
|
program.command("mcp").description(
|
|
6992
7470
|
"\u0417\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C MCP-\u0441\u0435\u0440\u0432\u0435\u0440 \u043F\u043E stdio: 15 \u0442\u0443\u043B\u043E\u0432 (\xA710.3 \u0422\u0417 \u0438 \u0434\u0430\u043B\u0435\u0435) \u043F\u043E\u0432\u0435\u0440\u0445 \u043F\u043E\u0441\u0442\u043E\u044F\u043D\u043D\u043E\u0433\u043E \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F \u0441 \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u043E\u0439"
|