@pachca/cli 2026.9.1 → 2026.10.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 (76) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +17 -5
  3. package/dist/base-command.js +47 -0
  4. package/dist/client.js +2 -1
  5. package/dist/commands/auth/login.js +4 -4
  6. package/dist/commands/bots/create-token.js +84 -0
  7. package/dist/commands/bots/create.js +33 -6
  8. package/dist/commands/bots/delete-token.js +46 -0
  9. package/dist/commands/bots/delete.js +1 -1
  10. package/dist/commands/bots/get.js +1 -1
  11. package/dist/commands/bots/list-company.js +1 -1
  12. package/dist/commands/bots/list-events.js +1 -1
  13. package/dist/commands/bots/list-scopes.js +32 -0
  14. package/dist/commands/bots/list-tokens.js +94 -0
  15. package/dist/commands/bots/list.js +3 -3
  16. package/dist/commands/bots/recreate-token-self.js +1 -1
  17. package/dist/commands/bots/recreate-token.js +2 -2
  18. package/dist/commands/bots/reissue-token.js +37 -0
  19. package/dist/commands/bots/remove-avatar.js +42 -0
  20. package/dist/commands/bots/remove-event.js +1 -1
  21. package/dist/commands/bots/rotate-client-secret.js +30 -0
  22. package/dist/commands/bots/update-avatar.js +51 -0
  23. package/dist/commands/bots/update-token.js +60 -0
  24. package/dist/commands/bots/update.js +37 -8
  25. package/dist/commands/chats/create.js +1 -0
  26. package/dist/commands/chats/download-export.js +1 -1
  27. package/dist/commands/chats/get.js +1 -1
  28. package/dist/commands/chats/list-company.js +1 -1
  29. package/dist/commands/chats/list.js +1 -1
  30. package/dist/commands/chats/mark-unread.js +44 -0
  31. package/dist/commands/chats/remove-avatar.js +45 -0
  32. package/dist/commands/chats/request-export.js +4 -2
  33. package/dist/commands/chats/update-avatar.js +54 -0
  34. package/dist/commands/drafts/create.js +1 -1
  35. package/dist/commands/drafts/list.js +1 -1
  36. package/dist/commands/drafts/update.js +1 -1
  37. package/dist/commands/files/direct-url.js +8 -4
  38. package/dist/commands/group-tags/get.js +1 -1
  39. package/dist/commands/group-tags/list-users.js +2 -2
  40. package/dist/commands/group-tags/list.js +3 -3
  41. package/dist/commands/members/add.js +2 -2
  42. package/dist/commands/members/list.js +2 -2
  43. package/dist/commands/members/remove-group-tag.js +1 -1
  44. package/dist/commands/members/remove.js +1 -1
  45. package/dist/commands/members/update.js +1 -1
  46. package/dist/commands/messages/create.js +9 -10
  47. package/dist/commands/messages/get.js +1 -1
  48. package/dist/commands/messages/list.js +1 -1
  49. package/dist/commands/messages/update.js +2 -2
  50. package/dist/commands/profile/update-status.js +3 -32
  51. package/dist/commands/reactions/list.js +1 -1
  52. package/dist/commands/read-member/list-readers.js +1 -1
  53. package/dist/commands/search/list-chats.js +2 -2
  54. package/dist/commands/search/list-messages.js +6 -6
  55. package/dist/commands/search/list-users.js +4 -4
  56. package/dist/commands/security/list.js +2 -2
  57. package/dist/commands/tasks/create.js +1 -1
  58. package/dist/commands/tasks/get.js +1 -1
  59. package/dist/commands/tasks/list.js +6 -6
  60. package/dist/commands/tasks/update.js +1 -1
  61. package/dist/commands/threads/get.js +1 -1
  62. package/dist/commands/threads/list.js +2 -2
  63. package/dist/commands/upload.js +5 -2
  64. package/dist/commands/users/create.js +1 -1
  65. package/dist/commands/users/get.js +1 -1
  66. package/dist/commands/users/list.js +1 -1
  67. package/dist/commands/users/update-status.js +3 -32
  68. package/dist/commands/users/update.js +2 -2
  69. package/dist/commands/views/open.js +2 -2
  70. package/dist/data/alternatives.json +17 -5
  71. package/dist/data/changelog.json +146 -0
  72. package/dist/data/endpoints.json +1 -1
  73. package/dist/data/workflows.json +60 -9
  74. package/dist/oauth.js +28 -3
  75. package/oclif.manifest.json +1 -1
  76. package/package.json +1 -1
@@ -158,7 +158,7 @@
158
158
  "notes": "`last_message_at_after`/`last_message_at_before` — ISO-8601, UTC+0. `limit` 1-50 (по умолчанию 50). Сортировка — по убыванию времени последнего сообщения."
159
159
  },
160
160
  {
161
- "description": "Если в ответе `meta.paginate.next_page` — пройди по страницам через `--cursor`",
161
+ "description": "Пока `meta.paginate.has_next` равен `true`, бери следующую страницу через `--cursor=<next_page>`",
162
162
  "command": "pachca threads list --last-message-at-after=2026-05-19T00:00:00.000Z --cursor=<next_page>"
163
163
  },
164
164
  {
@@ -343,6 +343,21 @@
343
343
  }
344
344
  ]
345
345
  },
346
+ {
347
+ "title": "Поставить или убрать аватар чата",
348
+ "skill": "pachca-chats",
349
+ "steps": [
350
+ {
351
+ "description": "Загрузи аватар беседы или канала",
352
+ "command": "pachca chats update-avatar <ID> --file=<путь_к_файлу>",
353
+ "notes": "Файл передается в формате multipart/form-data: jpg, jpeg, png или gif. У личного чата и треда аватара нет — ответ 403"
354
+ },
355
+ {
356
+ "description": "Чтобы убрать аватар, удали его",
357
+ "command": "pachca chats remove-avatar <ID> --force"
358
+ }
359
+ ]
360
+ },
346
361
  {
347
362
  "title": "Создать проектную беседу из шаблона",
348
363
  "skill": "pachca-chats",
@@ -362,13 +377,13 @@
362
377
  "skill": "pachca-chats",
363
378
  "steps": [
364
379
  {
365
- "description": "Запроси экспорт",
366
- "command": "pachca chats request-export --start-at=<YYYY-MM-DD> --end-at=<YYYY-MM-DD> --webhook-url=<URL>",
367
- "notes": "`start_at`, `end_at` (YYYY-MM-DD). Запрос асинхронный: ответ приходит пустым, без номера выгрузки. `webhook_url` формально не обязателен, но без него номер взять неоткуда — присылай его всегда"
380
+ "description": "Запроси экспорт и возьми номер выгрузки из `data.id`",
381
+ "command": "pachca chats request-export --start-at=<YYYY-MM-DD> --end-at=<YYYY-MM-DD>",
382
+ "notes": "`start_at`, `end_at` (YYYY-MM-DD). Номер приходит с заголовком `Prefer: return=representation` и ответом `202`, CLI и SDK шлют его сами. Без заголовка ответ `204` без тела"
368
383
  },
369
384
  {
370
385
  "description": "Скачай файл экспорта",
371
- "command": "pachca chats download-export <export_id>",
386
+ "command": "pachca chats download-export <id>",
372
387
  "notes": "Сервер вернёт 302, HTTP-клиент скачает файл автоматически"
373
388
  }
374
389
  ]
@@ -456,12 +471,44 @@
456
471
  "skill": "pachca-bots",
457
472
  "steps": [
458
473
  {
459
- "description": "Пользовательским токеном (администратор, владелец компании или создатель бота) — перевыпусти токен по `id` бота. Прежний токен инвалидируется сразу",
474
+ "description": "Пользовательским токеном (создатель бота или администратор, если бот открыт администраторам) — перевыпусти основной токен по `id` бота: тот, что без имени, а если такого нет, самый старый. Прежнее значение инвалидируется сразу",
460
475
  "command": "pachca bots recreate-token <bot_id>"
461
476
  },
462
477
  {
463
- "description": "Или: бот перевыпускает собственный токен своим же токеном (скоуп `bot_self:write`). Токен, которым выполнен запрос, инвалидируется сразу — обязательно сохрани новый `access_token` из ответа, иначе бот потеряет доступ к API",
478
+ "description": "Или: бот перевыпускает свой основной токен сам (скоуп `bot_self:write`). Если запрос сделан основным токеном, он инвалидируется сразу — обязательно сохрани новый `access_token` из ответа, иначе бот потеряет доступ к API",
464
479
  "command": "pachca bots recreate-token-self"
480
+ },
481
+ {
482
+ "description": "Отдельный токен бота перевыпускай по его `id` из `pachca bots list-tokens`: значение меняется, имя и права остаются",
483
+ "command": "pachca bots reissue-token <bot_id> <token_id>"
484
+ }
485
+ ]
486
+ },
487
+ {
488
+ "title": "Выпустить боту отдельный токен",
489
+ "skill": "pachca-bots",
490
+ "steps": [
491
+ {
492
+ "description": "Пользовательским токеном (создатель бота или администратор, если бот открыт администраторам) получи каталог прав, которые можно выдать этому боту",
493
+ "command": "pachca bots list-scopes <bot_id>"
494
+ },
495
+ {
496
+ "description": "Выпусти токен с именем и правами из каталога. Без `--scopes` токен выпускается без прав, право не из каталога отклоняется с `400`",
497
+ "command": "pachca bots create-token <bot_id> --name=\"Сервер уведомлений\" --scopes='[\"messages:create\"]'"
498
+ }
499
+ ]
500
+ },
501
+ {
502
+ "title": "Включить боту авторизацию от имени сотрудника",
503
+ "skill": "pachca-bots",
504
+ "steps": [
505
+ {
506
+ "description": "Пользовательским токеном (создатель бота или администратор, если бот открыт администраторам) включи авторизацию: где хранится секрет, адреса возврата и права, которые бот попросит у сотрудника. Права бери из `pachca bots list-scopes`",
507
+ "command": "pachca bots update <bot_id> --oauth-client='{\"confidential\":true,\"redirect_uris\":[\"https://example.com/oauth/callback\"],\"scopes\":[\"messages:read\",\"messages:create\"]}'"
508
+ },
509
+ {
510
+ "description": "Чтобы бот появился в витрине, добавь описание и опубликуй страницу",
511
+ "command": "pachca bots update <bot_id> --promo='{\"description\":\"Собирает сводку по задачам\",\"published\":true}'"
465
512
  }
466
513
  ]
467
514
  },
@@ -470,11 +517,11 @@
470
517
  "skill": "pachca-bots",
471
518
  "steps": [
472
519
  {
473
- "description": "Пользовательским токеном (скоуп `bots:read`) получи список ботов, доступных тебе для редактирования: созданных тобой и тех, чьи настройки открывают тебе доступ. Фильтруй по имени параметром `query`, следующую страницу бери из `meta.paginate.next_page`",
520
+ "description": "Пользовательским токеном (скоуп `bots:read`) получи список ботов, доступных тебе для редактирования: созданных тобой и тех, чьи настройки открывают тебе доступ. Фильтруй по имени параметром `query`. Пока `meta.paginate.has_next` равен `true`, следующую страницу бери из `meta.paginate.next_page`",
474
521
  "command": "pachca bots list --query=\"задач\""
475
522
  },
476
523
  {
477
- "description": "Возьми `id` нужного бота из списка и удали его (скоуп `bots:write`). Доступно администратору, владельцу компании или создателю бота — владельцы чатов удалять бота не могут. Прежний токен инвалидируется сразу, бот исключается из всех чатов, его исходящий вебхук удаляется",
524
+ "description": "Возьми `id` нужного бота из списка и удали его (скоуп `bots:write`). Доступно создателю бота и администратору, если бот открыт администраторам, — владельцы чатов удалять бота не могут. Все токены бота инвалидируются сразу, бот исключается из всех чатов, его вебхуки удаляются",
478
525
  "command": "pachca bots delete <bot_id>"
479
526
  }
480
527
  ]
@@ -539,6 +586,10 @@
539
586
  "title": "Обработка событий через историю (polling)",
540
587
  "skill": "pachca-bots",
541
588
  "steps": [
589
+ {
590
+ "description": "Включи историю событий флагом `--events-history-enabled` (Webhook URL для этого не нужен) или настройкой «Сохранять историю событий» на вкладке «Исходящий вебхук» — в интерфейсе она появляется после включения вебхука",
591
+ "command": "pachca bots update <bot_id> --events-history-enabled"
592
+ },
542
593
  {
543
594
  "description": "Получи накопленные события",
544
595
  "command": "pachca bots list-events --all"
package/dist/oauth.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { spawn, spawnSync } from 'node:child_process';
2
+ import * as os from 'node:os';
2
3
  import { getBaseUrl } from './client.js';
3
4
  /** Uses the global timer on purpose: `node:timers/promises` is not fakeable in tests. */
4
5
  function delay(ms) {
@@ -19,6 +20,8 @@ const DEVICE_CODE_GRANT = 'urn:ietf:params:oauth:grant-type:device_code';
19
20
  const MIN_POLL_INTERVAL_SECONDS = 5;
20
21
  /** RFC 8628: on `slow_down` the client raises its interval by 5 seconds. */
21
22
  const SLOW_DOWN_STEP_SECONDS = 5;
23
+ /** The backend keeps a device name of at most this many characters. */
24
+ const DEVICE_NAME_MAX_LENGTH = 255;
22
25
  export class OAuthError extends Error {
23
26
  code;
24
27
  description;
@@ -76,9 +79,31 @@ async function postForm(endpoint, params) {
76
79
  }
77
80
  return body;
78
81
  }
79
- /** Step 1 — ask the server for a device code and the code the user types in. */
80
- export async function requestDeviceCode() {
81
- const body = (await postForm('device_authorization', { client_id: CLI_CLIENT_ID }));
82
+ /**
83
+ * What the token list on the «API» page calls this login.
84
+ *
85
+ * Every login is a row there, revoked one by one, so the rows have to tell
86
+ * machines apart: the machine name, plus the profile unless it is the default —
87
+ * two logins from one laptop differ by nothing else. The page joins a row's
88
+ * fields with « · », so the profile goes in parentheses rather than after one.
89
+ */
90
+ export function deviceName(profile, hostname = os.hostname()) {
91
+ const machine = hostname.trim().replace(/\.local$/i, '');
92
+ const name = profile === 'default' ? machine : machine ? `${machine} (${profile})` : profile;
93
+ // Counted in characters, as the backend counts them, so a cut never splits one.
94
+ return Array.from(name).slice(0, DEVICE_NAME_MAX_LENGTH).join('') || undefined;
95
+ }
96
+ /**
97
+ * Step 1 — ask the server for a device code and the code the user types in.
98
+ *
99
+ * A server older than device names drops the extra parameter without a word,
100
+ * so it is sent regardless of which server the CLI talks to.
101
+ */
102
+ export async function requestDeviceCode(device) {
103
+ const params = { client_id: CLI_CLIENT_ID };
104
+ if (device)
105
+ params.device_name = device;
106
+ const body = (await postForm('device_authorization', params));
82
107
  if (!body?.device_code || !body.user_code || !body.verification_uri) {
83
108
  throw new OAuthError('invalid_response', 'Сервер вернул неполный ответ на запрос кода');
84
109
  }