@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.
Files changed (3) hide show
  1. package/README.md +8 -5
  2. package/dist/cli.js +1323 -845
  3. 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/auth.ts
190
- import { z as z6 } from "zod";
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 z7 } from "zod";
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 = z7.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");
276
- var RequestDocumentUploadUrlSchema = z7.object({
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: z7.enum(ALLOWED_DOCUMENT_MIME_TYPES, {
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: z7.number().int().positive().max(
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 = z7.enum([
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 = z7.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");
294
- var DocumentContentMdSchema = z7.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");
295
- var DocumentFileRefSchema = z7.object({
296
- fileKey: z7.string().min(1),
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: z7.enum(ALLOWED_DOCUMENT_MIME_TYPES)
314
+ mimeType: z6.enum(ALLOWED_DOCUMENT_MIME_TYPES)
299
315
  });
300
- var CreateDocumentSchema = z7.object({
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 = z7.object({
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 = z7.object({
336
+ var ListDocumentsQuerySchema = z6.object({
321
337
  kind: DocumentKindSchema.optional()
322
338
  });
323
339
 
324
- // ../shared/src/dto/milestone.ts
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 MilestoneNameSchema = z8.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");
327
- var MilestoneDescriptionSchema = z8.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");
328
- var MilestoneStatusSchema = z8.enum([MilestoneStatus.OPEN, MilestoneStatus.DONE]);
329
- var CreateMilestoneSchema = z8.object({
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: z8.coerce.date().optional(),
413
+ dueAt: z9.coerce.date().optional(),
333
414
  status: MilestoneStatusSchema.default(MilestoneStatus.OPEN)
334
415
  });
335
- var UpdateMilestoneSchema = z8.object({
416
+ var UpdateMilestoneSchema = z9.object({
336
417
  name: MilestoneNameSchema.optional(),
337
418
  description: MilestoneDescriptionSchema.nullable().optional(),
338
- dueAt: z8.coerce.date().nullable().optional(),
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 = z8.object({
344
- orderedIds: z8.array(z8.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")
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 z9 } from "zod";
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 = z9.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(
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 = 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(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");
363
- var CreateOrganizationSchema = z9.object({
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 = z9.object({
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 = z9.object({
374
- email: z9.email("\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 email"),
375
- orgRole: z9.enum([OrgRole.ADMIN, OrgRole.MEMBER]).default(OrgRole.MEMBER)
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 = z9.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");
379
- var AcceptInvitationSchema = z9.object({
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 = z9.object({
383
- type: z9.literal("member"),
469
+ var OrganizationMemberDTOSchema = z10.object({
470
+ type: z10.literal("member"),
384
471
  /** id записи Membership — тот же id принимает `DELETE .../members/:id`. */
385
- id: z9.string(),
386
- userId: z9.string(),
387
- name: z9.string().nullable(),
388
- email: z9.string().nullable(),
389
- image: z9.string().nullable(),
390
- orgRole: z9.enum([OrgRole.OWNER, OrgRole.ADMIN, OrgRole.MEMBER]),
391
- createdAt: z9.coerce.date()
392
- });
393
- var OrganizationInvitationDTOSchema = z9.object({
394
- type: z9.literal("invitation"),
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: z9.string(),
397
- email: z9.string(),
398
- orgRole: z9.enum([OrgRole.ADMIN, OrgRole.MEMBER]),
483
+ id: z10.string(),
484
+ email: z10.string(),
485
+ orgRole: z10.enum([OrgRole.ADMIN, OrgRole.MEMBER]),
399
486
  /** `expired` — вычисляется на сервере сравнением `expiresAt` с текущим временем. */
400
- status: z9.enum(["pending", "expired"]),
401
- invitedByName: z9.string().nullable(),
402
- expiresAt: z9.coerce.date(),
403
- createdAt: z9.coerce.date()
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 = z9.discriminatedUnion("type", [
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 z10 } from "zod";
412
- var ProfileNameSchema = z10.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0438\u043C\u044F").max(120);
413
- var UpdateProfileSchema = z10.object({
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 = z10.object({
417
- currentPassword: z10.string().min(1).max(200).optional(),
503
+ var ChangePasswordSchema = z11.object({
504
+ currentPassword: z11.string().min(1).max(200).optional(),
418
505
  newPassword: PasswordSchema
419
506
  });
420
- var RequestEmailChangeSchema = z10.object({
507
+ var RequestEmailChangeSchema = z11.object({
421
508
  newEmail: EmailSchema,
422
509
  /** Нужен, если у аккаунта есть пароль — см. `ChangePasswordSchema`. */
423
- currentPassword: z10.string().min(1).max(200).optional()
510
+ currentPassword: z11.string().min(1).max(200).optional()
424
511
  });
425
- var ConfirmEmailChangeSchema = z10.object({
426
- token: z10.string().min(1)
512
+ var ConfirmEmailChangeSchema = z11.object({
513
+ token: z11.string().min(1)
427
514
  });
428
- var UpdateAvatarSchema = z10.object({
429
- fileKey: z10.string().min(1).max(500)
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 = z10.object({
439
- fileName: z10.string().trim().min(1).max(200),
440
- mimeType: z10.enum(ALLOWED_AVATAR_MIME_TYPES),
441
- size: z10.number().int().positive().max(MAX_AVATAR_FILE_SIZE_BYTES)
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 = z10.object({
444
- provider: z10.string().trim().min(1).max(50)
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 z14 } from "zod";
535
+ import { z as z15 } from "zod";
449
536
 
450
537
  // ../shared/src/settings/project-settings.ts
451
- import { z as z13 } from "zod";
538
+ import { z as z14 } from "zod";
452
539
 
453
540
  // ../shared/src/dto/task-template.ts
454
- import { z as z12 } from "zod";
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 z11 } from "zod";
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 = z11.enum(taskTypeValues);
519
- var TaskStatusSchema = z11.enum(taskStatusValues);
520
- var TaskPrioritySchema = z11.enum(priorityValues);
521
- var TaskExecutorSchema = z11.enum(executorValues);
522
- var TaskTestResultSchema = z11.enum(testResultValues);
523
- var TaskTitleSchema = z11.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");
524
- var TaskDescriptionSchema = z11.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");
525
- var TaskLabelSchema = z11.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");
526
- var TaskLabelsSchema = z11.array(TaskLabelSchema).max(30, "\u041D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 30 \u043C\u0435\u0442\u043E\u043A");
527
- var TaskMetadataSchema = z11.record(z11.string(), z11.unknown());
528
- var TaskAcceptanceSchema = z11.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");
529
- var TaskEstimateMinSchema = z11.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);
530
- var TaskOrderSchema = z11.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");
531
- var TaskResultMdSchema = z11.string().max(5e4);
532
- var TaskResultLinkKindSchema = z11.enum(["pr", "commit", "url"]);
533
- var TaskResultLinkSchema = z11.object({
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: z11.string().url("\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 URL"),
536
- label: z11.string().max(200).optional()
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 = z11.array(TaskResultLinkSchema).max(50);
539
- var TaskLastErrorSchema = z11.string().max(5e3);
540
- var IdSchema = z11.string().min(1);
541
- var CreateTaskSchema = z11.object({
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: z11.string().min(1).max(60).optional(),
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: z11.coerce.date().optional(),
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 = z11.object({
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: z11.string().max(2e4).optional(),
663
+ statusComment: z12.string().max(2e4).optional(),
565
664
  priority: TaskPrioritySchema.optional(),
566
665
  executor: TaskExecutorSchema.optional(),
567
- roleKey: z11.string().min(1).max(60).nullable().optional(),
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: z11.coerce.date().nullable().optional(),
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 = z11.object({
587
- status: z11.string().max(500).optional(),
588
- role: z11.string().max(500).optional(),
589
- assignee: z11.string().max(500).optional(),
590
- milestone: z11.string().max(500).optional(),
591
- label: z11.string().max(500).optional(),
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: z11.string().max(100).optional(),
596
- type: z11.string().max(200).optional(),
597
- q: z11.string().trim().max(200).optional(),
598
- cursor: z11.string().max(4e3).optional(),
599
- limit: z11.coerce.number().int().min(1).max(TASK_LIST_MAX_LIMIT).default(TASK_LIST_DEFAULT_LIMIT)
600
- });
601
- var BulkTaskIdsSchema = z11.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");
602
- var BulkTaskActionSchema = z11.discriminatedUnion("action", [
603
- z11.object({
604
- action: z11.literal("status"),
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: z11.string().max(2e4).optional()
706
+ comment: z12.string().max(2e4).optional()
608
707
  }),
609
- z11.object({
610
- action: z11.literal("milestone"),
708
+ z12.object({
709
+ action: z12.literal("milestone"),
611
710
  taskIds: BulkTaskIdsSchema,
612
711
  milestoneId: IdSchema.nullable()
613
712
  }),
614
- z11.object({
615
- action: z11.literal("role"),
713
+ z12.object({
714
+ action: z12.literal("role"),
616
715
  taskIds: BulkTaskIdsSchema,
617
- roleKey: z11.string().min(1).max(60).nullable()
716
+ roleKey: z12.string().min(1).max(60).nullable()
618
717
  }),
619
- z11.object({
620
- action: z11.literal("delete"),
718
+ z12.object({
719
+ action: z12.literal("delete"),
621
720
  taskIds: BulkTaskIdsSchema
622
721
  })
623
722
  ]);
624
- var BulkTaskResultItemSchema = z11.object({
625
- taskId: z11.string(),
626
- ok: z11.boolean(),
627
- error: z11.object({ code: z11.string(), message: z11.string() }).optional()
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 = 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(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");
632
- var TaskTemplateSchema = z12.object({
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: z12.string().min(1),
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: z12.string().min(1).max(60).optional(),
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 = z12.array(TaskTemplateSchema).max(50, "\u041D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 50 \u0448\u0430\u0431\u043B\u043E\u043D\u043E\u0432");
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 = z13.enum(taskStatusValues2);
670
- var BoardSettingsSchema = z13.object({
671
- hiddenStatuses: z13.array(TaskStatusSchema2).default([]),
672
- mergedColumns: z13.array(z13.array(TaskStatusSchema2)).default([])
673
- });
674
- var NotificationSettingsSchema = z13.object({
675
- telegram: z13.boolean().default(false),
676
- email: z13.boolean().default(false)
677
- });
678
- var ProjectSettingsSchema = z13.object({
679
- autoAccept: z13.boolean().default(false),
680
- requireTests: z13.boolean().default(true),
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: z13.boolean().default(false),
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: z13.boolean().default(false),
813
+ reviewTaskOnPr: z14.boolean().default(false),
715
814
  /**
716
815
  * Ключ роли, на которую вешается задача ревью (`RoleDefinition.key`).
717
816
  * Пусто — задача заводится без роли и видна всей команде проекта.
718
817
  */
719
- reviewRoleKey: z13.string().trim().min(1).max(60).optional(),
720
- maxParallelTasksPerAgent: z13.number().int().positive().default(1),
721
- leaseTtlSec: z13.number().int().positive().default(120),
722
- taskTimeoutMin: z13.number().int().positive().default(90),
723
- contextResetAfterTasks: z13.number().int().positive().default(8),
724
- branchTemplate: z13.string().min(1).default("task/{key}-{slug}"),
725
- commitTemplate: z13.string().min(1).default("{key}: {title}"),
726
- stopPatternsOverride: z13.array(z13.string()).optional(),
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 = z14.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");
737
- var ProjectNameSchema = z14.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");
738
- var ProjectDescriptionSchema = z14.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");
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: z14.coerce.date().optional()
839
+ autonomousConfirmedAt: z15.coerce.date().optional()
741
840
  });
742
841
  var UpdateProjectSettingsSchema = ProjectSettingsRecordSchema.partial();
743
- var ProjectModeSchema = z14.enum([ProjectMode.AUTONOMOUS, ProjectMode.APPROVAL]);
744
- var ProjectStatusSchema = z14.enum([
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 = z14.enum([GitMode.DIRECT, GitMode.PR]);
750
- var ProjectDateSchema = z14.coerce.date();
751
- var NewProjectMilestoneSchema = z14.object({
752
- name: z14.string().trim().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435").max(200),
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 = z14.object({
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: z14.boolean().optional(),
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: z14.array(z14.string().min(1)).max(100).optional(),
771
- milestones: z14.array(NewProjectMilestoneSchema).max(50).optional()
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 = z14.object({
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: z14.boolean().optional()
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 z15 } from "zod";
795
- var RepositoryUrlSchema = z15.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(
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 = z15.string().trim().min(1).max(200);
803
- var PathHintSchema = z15.string().trim().max(300);
804
- var CreateRepositorySchema = z15.object({
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 = z15.object({
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 = z15.object({
916
+ var ConnectGithubRepositorySchema = z16.object({
818
917
  /** Идентификатор НАШЕЙ записи установки, а не номер установки в GitHub. */
819
- installationId: z15.string().min(1, "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0430\u043A\u043A\u0430\u0443\u043D\u0442 GitHub"),
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: z15.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"),
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 z16 } from "zod";
843
- var RoleNameSchema = z16.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");
844
- var RoleColorSchema = z16.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");
845
- var CreateRoleSchema = z16.object({
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: z16.string().optional()
947
+ defaultTrustProfileId: z17.string().optional()
849
948
  });
850
- var UpdateRoleSchema = z16.object({
949
+ var UpdateRoleSchema = z17.object({
851
950
  name: RoleNameSchema.optional(),
852
951
  color: RoleColorSchema.optional(),
853
- defaultTrustProfileId: z16.string().nullable().optional()
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 z17 } from "zod";
860
- var SavedFilterNameSchema = 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(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");
861
- var SavedFilterQuerySchema = z17.object({
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: z17.array(TaskStatusSchema).max(11).default([]),
872
- roles: z17.array(z17.string().min(1)).max(50).default([]),
873
- assignees: z17.array(z17.string().min(1)).max(50).default([]),
874
- milestones: z17.array(z17.string().min(1)).max(50).default([]),
875
- labels: z17.array(TaskLabelSchema).max(30).default([]),
876
- priorities: z17.array(TaskPrioritySchema).max(4).default([]),
877
- types: z17.array(TaskTypeSchema).max(7).default([]),
878
- q: z17.string().trim().max(200).default("")
879
- });
880
- var CreateSavedFilterSchema = z17.object({
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 = z17.object({
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 z18 } from "zod";
893
- var TaskDependencyKindSchema = z18.enum([DepKind.BLOCKS, DepKind.RELATES]);
894
- var IdSchema2 = z18.string().min(1);
895
- var CreateTaskDependencySchema = z18.object({
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 = z18.object({
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 z19 } from "zod";
905
- var TaskEventKindSchema = z19.enum([
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 = z19.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");
917
- var CreateTaskEventSchema = z19.object({
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 = z19.object({ bodyMd: TaskCommentBodySchema });
921
- var TaskEditPayloadSchema = z19.object({
922
- fields: z19.record(z19.string(), z19.object({ from: z19.unknown(), to: z19.unknown() }))
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 = z19.object({
925
- from: z19.string().nullable(),
926
- to: z19.string().nullable()
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 = z19.object({
1029
+ var ListTaskEventsQuerySchema = z20.object({
931
1030
  /** CSV нескольких kind — как остальные CSV-фильтры задач (lib/tasks/filters.ts). */
932
- kind: z19.string().max(300).optional(),
933
- cursor: z19.string().max(4e3).optional(),
934
- limit: z19.coerce.number().int().min(1).max(TASK_EVENT_LIST_MAX_LIMIT).default(TASK_EVENT_LIST_DEFAULT_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 z20 } from "zod";
939
- var CommentSchema = z20.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");
940
- var TransitionTaskSchema = z20.object({
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 = z20.object({
1043
+ var AcceptTaskSchema = z21.object({
945
1044
  comment: CommentSchema.optional()
946
1045
  });
947
- var ReturnTaskSchema = z20.object({
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 = z20.object({
1049
+ var ReopenTaskSchema = z21.object({
951
1050
  reason: CommentSchema.optional()
952
1051
  });
953
- var RequeueTaskSchema = z20.object({
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 z21 } from "zod";
959
- var CommentSchema2 = 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");
960
- var RestoreTaskSchema = z21.object({
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 = z21.object({
966
- cursor: z21.string().max(4e3).optional(),
967
- limit: z21.coerce.number().int().min(1).max(TASK_TRASH_LIST_MAX_LIMIT).default(TASK_TRASH_LIST_DEFAULT_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 z22 } from "zod";
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 = z22.enum(["allow", "approve", "deny"]);
1026
- var trustFilesModeSchema = z22.enum(["allow", "approve"]);
1027
- var trustRulesSchema = z22.object({
1028
- bash: z22.object({
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: z22.array(z22.string().min(1)),
1033
- allowPatterns: z22.array(z22.string().min(1)).optional()
1131
+ stopPatterns: z23.array(z23.string().min(1)),
1132
+ allowPatterns: z23.array(z23.string().min(1)).optional()
1034
1133
  }),
1035
- files: z22.object({
1134
+ files: z23.object({
1036
1135
  mode: trustFilesModeSchema,
1037
- protectedPaths: z22.array(z22.string().min(1))
1136
+ protectedPaths: z23.array(z23.string().min(1))
1038
1137
  }),
1039
- git: z22.object({
1040
- allowPushDefault: z22.boolean(),
1041
- allowForcePush: z22.boolean()
1138
+ git: z23.object({
1139
+ allowPushDefault: z23.boolean(),
1140
+ allowForcePush: z23.boolean()
1042
1141
  }),
1043
- network: z22.object({
1044
- allowSsh: z22.boolean(),
1045
- sshHostsAllow: z22.array(z22.string().min(1)).optional()
1142
+ network: z23.object({
1143
+ allowSsh: z23.boolean(),
1144
+ sshHostsAllow: z23.array(z23.string().min(1)).optional()
1046
1145
  }),
1047
- approvalTtlMin: z22.number().int().positive()
1048
- });
1049
- var agentSummarySchema = z22.object({
1050
- id: z22.string().min(1),
1051
- projectId: z22.string().min(1),
1052
- membershipId: z22.string().min(1),
1053
- name: z22.string().min(1),
1054
- roleKeys: z22.array(z22.string().min(1)),
1055
- status: z22.enum(agentStatusValues),
1056
- mode: z22.enum(agentModeValues),
1057
- lastSeenAt: z22.string().datetime().nullable(),
1058
- clientVersion: z22.string().nullable(),
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: z22.string().nullable().default(null),
1077
- currentTaskId: z22.string().nullable(),
1078
- tasksCompletedInSession: z22.number().int().nonnegative()
1079
- });
1080
- var agentCurrentTaskSummarySchema = z22.object({
1081
- id: z22.string().min(1),
1082
- number: z22.number().int().positive(),
1083
- title: z22.string().min(1),
1084
- status: z22.enum(taskStatusValues3)
1085
- });
1086
- var agentHelloPayloadSchema = z22.object({
1087
- clientVersion: z22.string().min(1),
1088
- cwd: z22.string().min(1),
1089
- os: z22.string().min(1),
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: z22.string().min(1).max(64).optional(),
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: z22.string().min(1).optional(),
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: z22.string().min(1).optional(),
1220
+ claudeVersion: z23.string().min(1).optional(),
1122
1221
  // Роли, которыми клиент СЕБЯ считает — информационно (лог/диагностика
1123
1222
  // рассинхрона), не авторизация: авторизующие `Agent.roleKeys` идут из
1124
1223
  // БД (заданы при создании агента, REST §12 ТЗ), этот payload их не
1125
1224
  // меняет. См. блок «ВОПРОСЫ» отчёта P2-03.
1126
- roleKeys: z22.array(z22.string().min(1)),
1127
- resumeToken: z22.string().min(1).optional()
1225
+ roleKeys: z23.array(z23.string().min(1)),
1226
+ resumeToken: z23.string().min(1).optional()
1128
1227
  });
1129
- var agentHelloAckSchema = z22.object({
1228
+ var agentHelloAckSchema = z23.object({
1130
1229
  agent: agentSummarySchema,
1131
1230
  trust: trustRulesSchema,
1132
1231
  currentTask: agentCurrentTaskSummarySchema.optional(),
1133
- mode: z22.enum(agentModeValues)
1232
+ mode: z23.enum(agentModeValues)
1134
1233
  });
1135
- var agentHeartbeatPayloadSchema = z22.object({
1136
- currentTaskId: z22.string().min(1).optional(),
1137
- resumeToken: z22.string().min(1).optional(),
1138
- status: z22.enum(agentStatusValues)
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 = z22.object({
1141
- ok: z22.boolean(),
1142
- leaseExpiresAt: z22.string().datetime().optional()
1239
+ var agentHeartbeatAckSchema = z23.object({
1240
+ ok: z23.boolean(),
1241
+ leaseExpiresAt: z23.string().datetime().optional()
1143
1242
  });
1144
- var agentModePayloadSchema = z22.object({
1145
- mode: z22.enum(agentModeValues)
1243
+ var agentModePayloadSchema = z23.object({
1244
+ mode: z23.enum(agentModeValues)
1146
1245
  });
1147
- var agentModeAckSchema = z22.object({
1148
- ok: z22.boolean(),
1149
- mode: z22.enum(agentModeValues).optional()
1246
+ var agentModeAckSchema = z23.object({
1247
+ ok: z23.boolean(),
1248
+ mode: z23.enum(agentModeValues).optional()
1150
1249
  });
1151
- var taskPayloadMilestoneSchema = z22.object({
1152
- name: z22.string().min(1),
1153
- dueAt: z22.string().datetime().nullable()
1250
+ var taskPayloadMilestoneSchema = z23.object({
1251
+ name: z23.string().min(1),
1252
+ dueAt: z23.string().datetime().nullable()
1154
1253
  });
1155
- var taskPayloadTaskSchema = z22.object({
1156
- id: z22.string().min(1),
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: z22.string().min(1),
1159
- title: z22.string().min(1),
1160
- descriptionMd: z22.string(),
1161
- type: z22.enum(taskTypeValues2),
1162
- priority: z22.enum(priorityValues2),
1163
- acceptance: z22.string(),
1164
- attempts: z22.number().int().nonnegative(),
1165
- reviewNotes: z22.string().optional(),
1166
- metadata: z22.record(z22.string(), z22.unknown()),
1167
- labels: z22.array(z22.string()),
1168
- milestone: taskPayloadMilestoneSchema.optional()
1169
- });
1170
- var taskPayloadRepoSchema = z22.object({
1171
- url: z22.string().min(1),
1172
- defaultBranch: z22.string().min(1),
1173
- pathHint: z22.string().nullable()
1174
- });
1175
- var taskPayloadProjectSchema = z22.object({
1176
- key: z22.string().min(1),
1177
- name: z22.string().min(1),
1178
- mode: z22.enum(projectModeValues),
1179
- gitMode: z22.enum(gitModeValues),
1180
- repos: z22.array(taskPayloadRepoSchema),
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: z22.string().min(1),
1297
+ branchName: z23.string().min(1),
1183
1298
  /** Префикс сообщения коммита, `ATL-42:`. */
1184
- commitPrefix: z22.string().min(1)
1299
+ commitPrefix: z23.string().min(1)
1185
1300
  });
1186
- var taskPayloadDependencySchema = z22.object({
1187
- key: z22.string().min(1),
1188
- title: z22.string().min(1),
1189
- status: z22.enum(taskStatusValues3),
1190
- resultMd: z22.string().optional(),
1191
- resultLinks: z22.array(z22.string()).optional()
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 = z22.object({
1194
- id: z22.string().min(1),
1195
- textMd: z22.string(),
1196
- answerMd: z22.string().optional()
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 = z22.object({
1199
- profileKey: z22.string().min(1),
1200
- summary: z22.string()
1313
+ var taskPayloadTrustSchema = z23.object({
1314
+ profileKey: z23.string().min(1),
1315
+ summary: z23.string()
1201
1316
  });
1202
- var taskPayloadLeaseSchema = z22.object({
1203
- resumeToken: z22.string().min(1),
1204
- expiresAt: z22.string().datetime()
1317
+ var taskPayloadLeaseSchema = z23.object({
1318
+ resumeToken: z23.string().min(1),
1319
+ expiresAt: z23.string().datetime()
1205
1320
  });
1206
- var taskPayloadSchema = z22.object({
1321
+ var taskPayloadSchema = z23.object({
1207
1322
  task: taskPayloadTaskSchema,
1208
1323
  project: taskPayloadProjectSchema,
1209
- dependencies: z22.array(taskPayloadDependencySchema),
1210
- openQuestions: z22.array(taskPayloadOpenQuestionSchema),
1324
+ dependencies: z23.array(taskPayloadDependencySchema),
1325
+ openQuestions: z23.array(taskPayloadOpenQuestionSchema),
1211
1326
  trust: taskPayloadTrustSchema,
1212
1327
  lease: taskPayloadLeaseSchema
1213
1328
  });
1214
- var taskClaimPayloadSchema = z22.object({
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: z22.number().int().min(0).max(600)
1221
- });
1222
- var taskClaimAckSchema = z22.union([taskPayloadSchema, z22.object({ empty: z22.literal(true) })]);
1223
- var taskStartPayloadSchema = z22.object({
1224
- taskId: z22.string().min(1),
1225
- resumeToken: z22.string().min(1)
1226
- });
1227
- var taskStartAckSchema = z22.object({ ok: z22.boolean() });
1228
- var taskProgressLevelSchema = z22.enum(["debug", "info", "warn", "error"]);
1229
- var taskProgressPayloadSchema = z22.object({
1230
- taskId: z22.string().min(1),
1231
- note: z22.string().min(1),
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 = z22.object({ ok: z22.boolean() });
1235
- var taskReleasePayloadSchema = z22.object({
1236
- taskId: z22.string().min(1),
1237
- reason: z22.string().min(1)
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 = z22.object({ ok: z22.boolean() });
1240
- var taskGetPayloadSchema = z22.object({
1241
- taskId: z22.string().min(1)
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 = z22.enum(["success", "partial", "failed"]);
1247
- var reportLinkSchema = z22.object({
1248
- kind: z22.enum(["commit", "pr", "doc", "other"]),
1249
- url: z22.string().min(1),
1250
- title: z22.string().optional()
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 = z22.object({
1253
- taskId: z22.string().min(1),
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: z22.string().min(1),
1375
+ resumeToken: z23.string().min(1),
1261
1376
  status: reportStatusSchema,
1262
- resultMd: z22.string().min(1),
1263
- links: z22.array(reportLinkSchema),
1264
- testResult: z22.enum(testResultValues2),
1265
- nextSteps: z22.string().optional()
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 = z22.object({
1268
- taskStatus: z22.enum(taskStatusValues3),
1382
+ var reportAckSchema = z23.object({
1383
+ taskStatus: z23.enum(taskStatusValues3),
1269
1384
  /** true, если этот ack — повтор уже принятой сдачи (идемпотентность). */
1270
- duplicate: z22.boolean().optional()
1385
+ duplicate: z23.boolean().optional()
1271
1386
  });
1272
- var contextIncludeSchema = z22.enum(["spec", "decisions", "documents", "related", "repo"]);
1273
- var contextGetPayloadSchema = z22.object({
1274
- taskId: z22.string().min(1).optional(),
1275
- include: z22.array(contextIncludeSchema).min(1)
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 = z22.object({
1392
+ var contextDocumentFileSchema = z23.object({
1278
1393
  /** Имя как у человека на диске: `Спецификация v2.pdf`. */
1279
- fileName: z22.string().min(1),
1394
+ fileName: z23.string().min(1),
1280
1395
  /** Временная ссылка на скачивание — агент читает файл сам. */
1281
- downloadUrl: z22.string().min(1),
1396
+ downloadUrl: z23.string().min(1),
1282
1397
  /** Сколько секунд ссылка живёт: успеть скачать, а не отложить на потом. */
1283
- expiresInSeconds: z22.number().int().positive()
1398
+ expiresInSeconds: z23.number().int().positive()
1284
1399
  });
1285
- var contextDocumentSchema = z22.object({
1286
- id: z22.string().min(1),
1287
- title: z22.string().min(1),
1288
- kind: z22.string().min(1),
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: z22.string(),
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 = z22.object({
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: z22.array(z22.string()).optional(),
1430
+ notes: z23.array(z23.string()).optional(),
1316
1431
  spec: contextDocumentSchema.nullable().optional(),
1317
- decisions: z22.array(contextDocumentSchema).optional(),
1432
+ decisions: z23.array(contextDocumentSchema).optional(),
1318
1433
  /** Все документы проекта — любого типа, включая спецификацию и решения. */
1319
- documents: z22.array(contextDocumentSchema).optional(),
1320
- related: z22.array(taskPayloadDependencySchema).optional(),
1321
- repo: z22.object({
1322
- repos: z22.array(taskPayloadRepoSchema),
1323
- branchName: z22.string().optional(),
1324
- commitPrefix: z22.string().optional()
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 = z22.object({
1328
- retryAfterSec: z22.number().int().positive().optional(),
1329
- taskId: z22.string().min(1).optional()
1442
+ var agentRateLimitedPayloadSchema = z23.object({
1443
+ retryAfterSec: z23.number().int().positive().optional(),
1444
+ taskId: z23.string().min(1).optional()
1330
1445
  });
1331
- var agentRateLimitedAckSchema = z22.object({
1332
- ok: z22.boolean(),
1446
+ var agentRateLimitedAckSchema = z23.object({
1447
+ ok: z23.boolean(),
1333
1448
  /** Когда задача вернётся в очередь (§9.4 ТЗ: «через 2 ч»). */
1334
- requeueAt: z22.string().datetime().optional()
1449
+ requeueAt: z23.string().datetime().optional()
1335
1450
  });
1336
- var projectStatePayloadSchema = z22.object({
1337
- projectId: z22.string().min(1),
1338
- paused: z22.boolean(),
1339
- mode: z22.enum(projectModeValues),
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: z22.string().optional()
1342
- });
1343
- var questionSummarySchema = z22.object({
1344
- id: z22.string().min(1),
1345
- taskId: z22.string().min(1).nullable(),
1346
- textMd: z22.string(),
1347
- options: z22.array(z22.string()),
1348
- blocking: z22.boolean(),
1349
- status: z22.enum(questionStatusValues),
1350
- answerMd: z22.string().nullable(),
1351
- answeredAt: z22.string().datetime().nullable(),
1352
- createdAt: z22.string().datetime()
1353
- });
1354
- var questionAskPayloadSchema = z22.object({
1355
- taskId: z22.string().min(1).optional(),
1356
- textMd: z22.string().min(1),
1357
- targetRole: z22.string().min(1).optional(),
1358
- targetMemberId: z22.string().min(1).optional(),
1359
- options: z22.array(z22.string().min(1)).optional(),
1360
- blocking: z22.boolean(),
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: z22.number().int().min(0).max(600).optional()
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 = z22.object({
1498
+ var questionAskAckSchema = z23.object({
1367
1499
  question: questionSummarySchema
1368
1500
  });
1369
- var questionWaitPayloadSchema = z22.object({
1370
- questionId: z22.string().min(1),
1371
- waitSec: z22.number().int().min(0).max(600)
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 = z22.object({
1505
+ var questionWaitAckSchema = z23.object({
1374
1506
  question: questionSummarySchema
1375
1507
  });
1376
- var taskCreatePayloadSchema = z22.object({
1377
- title: z22.string().min(1),
1378
- descriptionMd: z22.string(),
1379
- roleKey: z22.string().min(1).optional(),
1380
- assigneeId: z22.string().min(1).optional(),
1381
- type: z22.enum(taskTypeValues2),
1382
- priority: z22.enum(priorityValues2),
1383
- executor: z22.enum(executorValues2),
1384
- blocksCurrent: z22.boolean(),
1385
- acceptance: z22.string().optional(),
1386
- labels: z22.array(z22.string().min(1)).optional()
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 = z22.object({
1391
- id: z22.string().min(1),
1392
- key: z22.string().min(1),
1393
- title: z22.string().min(1),
1394
- type: z22.enum(taskTypeValues2),
1395
- status: z22.enum(taskStatusValues3),
1396
- priority: z22.enum(priorityValues2),
1397
- roleKey: z22.string().min(1).nullable(),
1398
- assigneeId: z22.string().min(1).nullable(),
1399
- labels: z22.array(z22.string()),
1400
- updatedAt: z22.string().datetime()
1401
- });
1402
- var taskCreateAckSchema = z22.object({
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: z22.enum(taskStatusValues3).optional()
1556
+ currentTaskStatus: z23.enum(taskStatusValues3).optional()
1406
1557
  });
1407
- var taskListPayloadSchema = z22.object({
1408
- status: z22.array(z22.enum(taskStatusValues3)).optional(),
1409
- roleKey: z22.string().min(1).optional(),
1558
+ var taskListPayloadSchema = z23.object({
1559
+ status: z23.array(z23.enum(taskStatusValues3)).optional(),
1560
+ roleKey: z23.string().min(1).optional(),
1410
1561
  /** Поиск по заголовку, без учёта регистра. */
1411
- query: z22.string().min(1).optional(),
1412
- limit: z22.number().int().min(1).max(100).optional()
1413
- });
1414
- var taskListAckSchema = z22.object({
1415
- tasks: z22.array(taskBriefSchema)
1416
- });
1417
- var taskUpdatePayloadSchema = z22.object({
1418
- taskId: z22.string().min(1),
1419
- patch: z22.object({
1420
- progressNote: z22.string().min(1).optional(),
1421
- labels: z22.array(z22.string().min(1)).optional(),
1422
- estimateMin: z22.number().int().positive().optional()
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 = z22.object({
1576
+ var taskUpdateAckSchema = z23.object({
1426
1577
  task: taskBriefSchema
1427
1578
  });
1428
- var modeSetPayloadSchema = z22.object({
1429
- mode: z22.enum(agentModeValues)
1579
+ var modeSetPayloadSchema = z23.object({
1580
+ mode: z23.enum(agentModeValues)
1430
1581
  });
1431
- var agentPausePayloadSchema = z22.object({
1432
- reason: z22.string().min(1)
1582
+ var agentPausePayloadSchema = z23.object({
1583
+ reason: z23.string().min(1)
1433
1584
  });
1434
1585
  var trustUpdatedPayloadSchema = trustRulesSchema;
1435
- var leaseLostPayloadSchema = z22.object({
1436
- taskId: z22.string().min(1),
1437
- reason: z22.string().min(1)
1438
- });
1439
- var taskUpdatedAgentPayloadSchema = z22.object({
1440
- taskId: z22.string().min(1),
1441
- patch: z22.record(z22.string(), z22.unknown()).optional()
1442
- });
1443
- var questionAnsweredPayloadSchema = z22.object({
1444
- questionId: z22.string().min(1),
1445
- answerMd: z22.string()
1446
- });
1447
- var approvalSummarySchema = z22.object({
1448
- id: z22.string().min(1),
1449
- taskId: z22.string().min(1),
1450
- kind: z22.enum(approvalKindValues),
1451
- summary: z22.string(),
1452
- status: z22.enum(approvalStatusValues),
1453
- expiresAt: z22.string().datetime(),
1454
- decidedAt: z22.string().datetime().nullable(),
1455
- createdAt: z22.string().datetime()
1456
- });
1457
- var approvalRequestPayloadSchema = z22.object({
1458
- taskId: z22.string().min(1),
1459
- kind: z22.enum(approvalKindValues),
1460
- summary: z22.string().min(1),
1461
- command: z22.string().min(1),
1462
- cwd: z22.string().min(1),
1463
- host: z22.string().min(1).optional(),
1464
- diff: z22.string().optional(),
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: z22.number().int().min(0).max(600).optional()
1617
+ waitSec: z23.number().int().min(0).max(600).optional()
1467
1618
  });
1468
- var approvalRequestAckSchema = z22.object({
1619
+ var approvalRequestAckSchema = z23.object({
1469
1620
  approval: approvalSummarySchema,
1470
1621
  /** Приходит только при `APPROVED` — одноразовый, привязан к команде и каталогу (§14.4 ТЗ). */
1471
- oneTimeToken: z22.string().min(1).optional()
1622
+ oneTimeToken: z23.string().min(1).optional()
1472
1623
  });
1473
- var approvalWaitPayloadSchema = z22.object({
1474
- approvalId: z22.string().min(1),
1475
- waitSec: z22.number().int().min(0).max(600)
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 = z22.object({
1479
- approvalId: z22.string().min(1),
1480
- status: z22.enum([ApprovalStatus.APPROVED, ApprovalStatus.REJECTED]),
1481
- oneTimeToken: z22.string().min(1).optional()
1482
- });
1483
- var agentPresenceUiPayloadSchema = z22.object({
1484
- projectId: z22.string().min(1),
1485
- agentId: z22.string().min(1),
1486
- status: z22.enum(agentStatusValues),
1487
- lastSeenAt: z22.string().datetime(),
1488
- currentTaskId: z22.string().nullable().optional()
1489
- });
1490
- var taskOpenPrPayloadSchema = z22.object({
1491
- taskId: z22.string().min(1),
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: z22.string().min(1),
1644
+ branchName: z23.string().min(1),
1494
1645
  /** Rebase на основную ветку не прошёл — PR помечается «conflicts» (§13.1 ТЗ). */
1495
- conflicted: z22.boolean().optional(),
1646
+ conflicted: z23.boolean().optional(),
1496
1647
  /** Только пути файлов, никогда содержимое (§18 ТЗ). */
1497
- conflictedFiles: z22.array(z22.string().min(1)).max(100).optional()
1648
+ conflictedFiles: z23.array(z23.string().min(1)).max(100).optional()
1498
1649
  });
1499
- var taskOpenPrAckSchema = z22.object({
1500
- url: z22.string().url(),
1501
- number: z22.number().int().positive(),
1650
+ var taskOpenPrAckSchema = z23.object({
1651
+ url: z23.string().url(),
1652
+ number: z23.number().int().positive(),
1502
1653
  /** `false` — PR уже существовал для этой ветки, повторно не создавали. */
1503
- created: z22.boolean()
1654
+ created: z23.boolean()
1504
1655
  });
1505
1656
 
1506
1657
  // ../shared/src/events/ticket.ts
1507
- import { z as z23 } from "zod";
1508
- var realtimeTicketPayloadSchema = z23.object({
1509
- sub: z23.string().min(1),
1510
- orgIds: z23.array(z23.string().min(1)),
1511
- projectIds: z23.array(z23.string().min(1)),
1512
- iat: z23.number().int().positive(),
1513
- exp: z23.number().int().positive(),
1514
- jti: z23.string().min(1)
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 = z23.object({
1517
- room: z23.string().min(1),
1518
- projectId: z23.string().min(1).optional()
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 z24 } from "zod";
1673
+ import { z as z25 } from "zod";
1523
1674
  var taskStatusValues4 = Object.values(TaskStatus);
1524
- var taskCreatedPayloadSchema = z24.object({
1525
- taskId: z24.string().min(1),
1526
- projectId: z24.string().min(1),
1527
- orgId: z24.string().min(1)
1528
- });
1529
- var taskUpdatedPayloadSchema = z24.object({
1530
- taskId: z24.string().min(1),
1531
- projectId: z24.string().min(1),
1532
- orgId: z24.string().min(1),
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: z24.record(z24.string(), z24.unknown()).optional()
1686
+ patch: z25.record(z25.string(), z25.unknown()).optional()
1536
1687
  });
1537
- var taskDeletedPayloadSchema = z24.object({
1538
- taskId: z24.string().min(1),
1539
- projectId: z24.string().min(1),
1540
- orgId: z24.string().min(1)
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 = z24.object({
1543
- taskId: z24.string().min(1),
1544
- projectId: z24.string().min(1),
1545
- orgId: z24.string().min(1),
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: z24.enum(taskStatusValues4),
1549
- order: z24.number()
1699
+ status: z25.enum(taskStatusValues4),
1700
+ order: z25.number()
1550
1701
  });
1551
- var notificationNewPayloadSchema = z24.object({
1552
- notificationId: z24.string().min(1),
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: z24.string().min(1),
1556
- kind: z24.string().min(1),
1557
- title: z24.string().min(1),
1558
- body: z24.string().optional(),
1559
- link: z24.string().optional()
1560
- });
1561
- var futurePlaceholderPayloadSchema = z24.object({
1562
- projectId: z24.string().min(1)
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 = z24.object({
1565
- questionId: z24.string().min(1),
1566
- projectId: z24.string().min(1),
1567
- orgId: z24.string().min(1),
1568
- taskId: z24.string().min(1).nullable().optional(),
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: z24.string().min(1).nullable().optional(),
1571
- targetMemberId: z24.string().min(1).nullable().optional(),
1572
- blocking: z24.boolean().optional()
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: z24.string().datetime().optional()
1726
+ publishedAt: z25.string().datetime().optional()
1576
1727
  };
1577
- var uiEventEnvelopeSchema = z24.discriminatedUnion("event", [
1578
- z24.object({
1579
- event: z24.literal("task:created"),
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
- z24.object({
1584
- event: z24.literal("task:updated"),
1734
+ z25.object({
1735
+ event: z25.literal("task:updated"),
1585
1736
  payload: taskUpdatedPayloadSchema,
1586
1737
  ...envelopeExtra
1587
1738
  }),
1588
- z24.object({
1589
- event: z24.literal("task:deleted"),
1739
+ z25.object({
1740
+ event: z25.literal("task:deleted"),
1590
1741
  payload: taskDeletedPayloadSchema,
1591
1742
  ...envelopeExtra
1592
1743
  }),
1593
- z24.object({ event: z24.literal("task:moved"), payload: taskMovedPayloadSchema, ...envelopeExtra }),
1594
- z24.object({
1595
- event: z24.literal("notification:new"),
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
- z24.object({
1603
- event: z24.literal("agent:presence"),
1753
+ z25.object({
1754
+ event: z25.literal("agent:presence"),
1604
1755
  payload: futurePlaceholderPayloadSchema,
1605
1756
  ...envelopeExtra
1606
1757
  }),
1607
- z24.object({
1608
- event: z24.literal("question:new"),
1758
+ z25.object({
1759
+ event: z25.literal("question:new"),
1609
1760
  payload: questionEventPayloadSchema,
1610
1761
  ...envelopeExtra
1611
1762
  }),
1612
- z24.object({
1613
- event: z24.literal("question:answered"),
1763
+ z25.object({
1764
+ event: z25.literal("question:answered"),
1614
1765
  payload: questionEventPayloadSchema,
1615
1766
  ...envelopeExtra
1616
1767
  }),
1617
- z24.object({
1618
- event: z24.literal("question:dismissed"),
1768
+ z25.object({
1769
+ event: z25.literal("question:dismissed"),
1619
1770
  payload: questionEventPayloadSchema,
1620
1771
  ...envelopeExtra
1621
1772
  }),
1622
- z24.object({
1623
- event: z24.literal("approval:requested"),
1773
+ z25.object({
1774
+ event: z25.literal("approval:requested"),
1624
1775
  payload: futurePlaceholderPayloadSchema,
1625
1776
  ...envelopeExtra
1626
1777
  }),
1627
- z24.object({
1628
- event: z24.literal("approval:decided"),
1778
+ z25.object({
1779
+ event: z25.literal("approval:decided"),
1629
1780
  payload: futurePlaceholderPayloadSchema,
1630
1781
  ...envelopeExtra
1631
1782
  }),
1632
- z24.object({
1633
- event: z24.literal("audit:appended"),
1783
+ z25.object({
1784
+ event: z25.literal("audit:appended"),
1634
1785
  payload: futurePlaceholderPayloadSchema,
1635
1786
  ...envelopeExtra
1636
1787
  }),
1637
- z24.object({
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: z24.literal("project:state"),
1645
- payload: z24.object({
1646
- projectId: z24.string().min(1),
1647
- paused: z24.boolean(),
1648
- mode: z24.string().min(1),
1649
- reason: z24.string().optional()
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 z25 } from "zod";
1668
- var ImportTargetStatusSchema = z25.enum([
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 = z25.string().trim().min(1).max(100);
1674
- var ImportTaskInputSchema = z25.object({
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: z25.string().trim().min(1).max(60).optional(),
1683
- milestoneId: z25.string().min(1).optional(),
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 = z25.object({
1691
- tasks: z25.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")
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 z26 } from "zod";
1696
- var OrgSettingsSchema = z26.object({}).passthrough();
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 z27 } from "zod";
2929
- var HookCommandEntrySchema = z27.object({
2930
- type: z27.literal("command"),
2931
- command: z27.string().min(1),
2932
- timeout: z27.number().int().positive().optional()
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 = z27.object({
2935
- matcher: z27.string().optional(),
2936
- hooks: z27.array(HookCommandEntrySchema)
3281
+ var HookMatcherGroupSchema = z29.object({
3282
+ matcher: z29.string().optional(),
3283
+ hooks: z29.array(HookCommandEntrySchema)
2937
3284
  }).passthrough();
2938
- var McpServerEntrySchema = z27.object({
2939
- command: z27.string().min(1),
2940
- args: z27.array(z27.string()).optional()
3285
+ var McpServerEntrySchema = z29.object({
3286
+ command: z29.string().min(1),
3287
+ args: z29.array(z29.string()).optional()
2941
3288
  }).passthrough();
2942
- var ClaudeSettingsSchema = z27.object({
2943
- mcpServers: z27.record(z27.string(), McpServerEntrySchema).optional(),
2944
- hooks: z27.record(z27.string(), z27.array(HookMatcherGroupSchema)).optional(),
2945
- env: z27.record(z27.string(), z27.string()).optional()
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 z28 } from "zod";
3397
+ import { z as z30 } from "zod";
3051
3398
  var STATE_SCHEMA_VERSION = 1;
3052
- var CurrentTaskSchema = z28.object({
3053
- taskId: z28.string().min(1),
3399
+ var CurrentTaskSchema = z30.object({
3400
+ taskId: z30.string().min(1),
3054
3401
  /** Человекочитаемый ключ вроде `REL-42` — для текста в хуках. Необязателен: на первых порах может быть неизвестен. */
3055
- taskKey: z28.string().min(1).optional(),
3056
- resumeToken: z28.string().min(1),
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: z28.string().min(1).optional(),
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: z28.enum([GitMode.DIRECT, GitMode.PR]).optional()
3085
- });
3086
- var TrustCacheSchema = z28.object({
3087
- profileKey: z28.string().min(1),
3088
- updatedAt: z28.string(),
3089
- rules: z28.object({
3090
- bash: z28.object({
3091
- mode: z28.enum(["allow", "approve", "deny"]),
3092
- stopPatterns: z28.array(z28.string()).default([]),
3093
- allowPatterns: z28.array(z28.string()).optional()
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: z28.object({
3096
- mode: z28.enum(["allow", "approve"]),
3097
- protectedPaths: z28.array(z28.string()).default([])
3442
+ files: z30.object({
3443
+ mode: z30.enum(["allow", "approve"]),
3444
+ protectedPaths: z30.array(z30.string()).default([])
3098
3445
  }).optional(),
3099
- git: z28.object({ allowPushDefault: z28.boolean(), allowForcePush: z28.boolean() }).optional(),
3100
- network: z28.object({ allowSsh: z28.boolean(), sshHostsAllow: z28.array(z28.string()).optional() }).optional(),
3101
- approvalTtlMin: z28.number().int().positive().optional()
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 = z28.object({
3105
- token: z28.string().min(1),
3106
- command: z28.string().min(1),
3107
- cwd: z28.string().min(1),
3108
- expiresAt: z28.string(),
3109
- createdAt: z28.string()
3110
- });
3111
- var PendingApprovalSchema = z28.object({
3112
- command: z28.string().min(1),
3113
- cwd: z28.string().min(1),
3114
- createdAt: z28.string()
3115
- });
3116
- var AgentModeSchema = z28.enum([AgentMode.AUTONOMOUS, AgentMode.MANUAL]);
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 = z28.object({
3119
- version: z28.literal(STATE_SCHEMA_VERSION).default(STATE_SCHEMA_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: z28.number().int().nonnegative().default(0),
3470
+ tasksCompletedInSession: z30.number().int().nonnegative().default(0),
3124
3471
  /** Кэш `ProjectSettings.contextResetAfterTasks` (§7.2 ТЗ) — сколько задач подряд можно сдать, прежде чем `Stop`-хук попросит `/clear`. */
3125
- contextResetAfterTasks: z28.number().int().positive().default(DEFAULT_CONTEXT_RESET_AFTER_TASKS),
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: z28.string() }).nullable().default(null),
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: z28.record(z28.string(), ApprovedCommandSchema).default({}),
3478
+ approvedCommands: z30.record(z30.string(), ApprovedCommandSchema).default({}),
3132
3479
  /** Незавершённые запросы подтверждения, ключ — `approvalId`. См. `PendingApprovalSchema`. */
3133
- pendingApprovals: z28.record(z28.string(), PendingApprovalSchema).default({}),
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: z28.string().default(() => (/* @__PURE__ */ new Date()).toISOString())
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 z29 } from "zod";
3547
+ import { z as z31 } from "zod";
3188
3548
  var PROJECT_CONFIG_SCHEMA_VERSION = 1;
3189
- var ProjectConfigSchema = z29.object({
3190
- version: z29.literal(PROJECT_CONFIG_SCHEMA_VERSION).default(PROJECT_CONFIG_SCHEMA_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: z29.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"),
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: z29.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"),
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: z29.string().trim().min(1, "ID \u0430\u0433\u0435\u043D\u0442\u0430 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D"),
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: z29.string().trim().min(1).optional(),
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: z29.enum(["isolated", "checkout"]).default("isolated")
3591
+ worktrees: z31.enum(["isolated", "checkout"]).default("isolated")
3232
3592
  });
3233
- var CredentialsEntrySchema = z29.object({
3234
- url: z29.string().trim().url(),
3235
- token: z29.string().min(1),
3236
- projectKey: z29.string().min(1),
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: z29.string()
3598
+ savedAt: z31.string()
3239
3599
  });
3240
3600
  var CREDENTIALS_SCHEMA_VERSION = 1;
3241
- var CredentialsFileSchema = z29.object({
3242
- version: z29.literal(CREDENTIALS_SCHEMA_VERSION).default(CREDENTIALS_SCHEMA_VERSION),
3243
- agents: z29.record(z29.string(), CredentialsEntrySchema).default({})
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 z30 } from "zod";
3325
- var McpServerEntrySchema2 = z30.object({
3326
- command: z30.string().min(1).optional(),
3327
- args: z30.array(z30.string()).optional()
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 = z30.object({
3330
- mcpServers: z30.record(z30.string(), McpServerEntrySchema2).optional()
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 z31 } from "zod";
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 = z31.object({
3523
- hooks: z31.record(z31.string(), z31.array(z31.object({}).passthrough())).optional()
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 z32 } from "zod";
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 = z32.object({ command: z32.string().min(1) }).passthrough();
3577
- var CursorHooksFileSchema = z32.object({
3578
- version: z32.number().optional(),
3579
- hooks: z32.record(z32.string(), z32.array(CursorHookEntrySchema)).optional()
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 = z32.object({
3582
- mcpServers: z32.record(z32.string(), z32.object({}).passthrough()).optional()
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 z33 } from "zod";
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 = z33.object({
3697
- $schema: z33.string().optional(),
3698
- mcp: z33.record(z33.string(), z33.object({}).passthrough()).optional()
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(kind, env = process.env) {
3744
- const name = VERSION_ENV[kind];
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 BY_KIND2 = new Map(INSTALLERS.map((i) => [i.kind, i]));
3757
- function installerFor(kind) {
3758
- const installer = BY_KIND2.get(kind);
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 ${kind} \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.`
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
- function sendAuditActions(actions, options = {}) {
3824
- const auditActions = actions.filter((action) => action.type === "audit:command");
3825
- if (auditActions.length === 0) return;
3826
- void dispatch(auditActions, options).catch(() => {
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("audit:command", action.payload);
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 z34 } from "zod";
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 = z34.object({ command: z34.string(), cwd: z34.string().optional() }).passthrough();
3872
- var CursorStopInputSchema = z34.object({ status: z34.string().optional(), loop_count: z34.number().optional() }).passthrough();
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 = z34.object({
3879
- directory: z34.string().optional(),
3880
- input: z34.object({ tool: z34.string().optional() }).passthrough().optional(),
3881
- output: z34.object({ args: z34.record(z34.string(), z34.unknown()).optional() }).passthrough().optional(),
3882
- event: z34.object({ type: z34.string().optional() }).passthrough().optional()
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.4.2",
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.ai",
5050
+ homepage: "https://quiel.app",
4676
5051
  repository: {
4677
5052
  type: "git",
4678
- url: "git+https://github.com/Quiel-AI/quiel-cli.git"
5053
+ url: "git+https://github.com/Quiel-App/quiel-cli.git"
4679
5054
  },
4680
5055
  bugs: {
4681
- url: "https://github.com/Quiel-AI/quiel-cli/issues"
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 z35 } from "zod";
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: z35.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)")
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 z36 } from "zod";
6073
+ import { z as z38 } from "zod";
5699
6074
  var submitWorkInputShape = {
5700
- branchName: z36.string().min(1).describe(
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: z36.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."),
5704
- commitPrefix: z36.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:".'),
5705
- taskKey: z36.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."),
5706
- taskTitle: z36.string().min(1).describe("\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u0438\u0437 task.title."),
5707
- repoRoot: z36.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."),
5708
- testsPassed: z36.boolean().optional().describe(
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: z36.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.")
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 z37 } from "zod";
6185
- var PreCompactInputSchema = z37.object({
6186
- hook_event_name: z37.literal("PreCompact"),
6187
- session_id: z37.string(),
6188
- cwd: z37.string(),
6189
- trigger: z37.enum(["manual", "auto"]),
6190
- custom_instructions: z37.string().nullable()
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 z38 } from "zod";
6200
- var PreToolUseInputSchema = z38.object({
6201
- hook_event_name: z38.literal("PreToolUse"),
6202
- session_id: z38.string(),
6203
- cwd: z38.string(),
6204
- tool_name: z38.string(),
6205
- tool_input: z38.record(z38.string(), z38.unknown()),
6206
- tool_use_id: z38.string()
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 z42 } from "zod";
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 z39 } from "zod";
6355
- var SessionStartInputSchema = z39.object({
6356
- hook_event_name: z39.literal("SessionStart"),
6357
- session_id: z39.string(),
6358
- cwd: z39.string(),
6359
- source: z39.enum(["startup", "resume", "clear", "compact", "fork"]),
6360
- model: z39.string().optional()
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 z40 } from "zod";
6400
- var StopInputSchema = z40.object({
6401
- hook_event_name: z40.literal("Stop"),
6402
- session_id: z40.string(),
6403
- cwd: z40.string(),
6404
- stop_hook_active: z40.boolean(),
6405
- last_assistant_message: z40.string().optional()
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 z41 } from "zod";
6450
- var StopFailureErrorTypeSchema = z41.enum([
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 = z41.object({
6464
- hook_event_name: z41.literal("StopFailure"),
6465
- session_id: z41.string(),
6466
- cwd: z41.string(),
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: z41.unknown().optional(),
6469
- last_assistant_message: z41.string().optional()
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 = z42.discriminatedUnion("hook_event_name", [
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
- if (result.statePatch) {
6513
- writeState({ ...state, ...result.statePatch }, stateFilePath);
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 kind = agentKindFromCliKey(fromFlag);
6633
- if (!kind) {
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 kind;
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(kind) {
6841
- const info = describeAgentKind(kind);
6842
- if (!info) return `${kind} (\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?)`;
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) sendAuditActions(result.execution.serverActions);
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
- sendAuditActions(execution.serverActions);
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"