@pachca/cli 2026.3.10 → 2026.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.4.0 (7 апреля 2026)
4
+
5
+ - **Добавлено** (profile update-avatar): Загрузка аватара профиля
6
+ - **Добавлено** (profile delete-avatar): Удаление аватара профиля
7
+ - **Добавлено** (users update-avatar): Загрузка аватара сотрудника
8
+ - **Добавлено** (users remove-avatar): Удаление аватара сотрудника
9
+ - **Изменено** (chats list, messages list): Исправлена сортировка: --order без --sort теперь корректно работает (sort по умолчанию id, order по умолчанию desc)
10
+ - **Изменено** (messages list): chat_id можно передать первым аргументом: pachca messages list 12345
11
+
3
12
  ## 2026.3.10 (21 марта 2026)
4
13
 
5
14
  - **Изменено** (messages create): Поле link_preview перемещено на верхний уровень тела запроса (раньше было внутри message)
package/README.md CHANGED
@@ -171,6 +171,8 @@ pachca guide # список всех сценариев
171
171
  |---------|---------|
172
172
  | `pachca profile get-info` | Информация о токене |
173
173
  | `pachca profile get` | Информация о профиле |
174
+ | `pachca profile update-avatar` | Загрузка аватара |
175
+ | `pachca profile delete-avatar` | Удаление аватара |
174
176
  | `pachca profile get-status` | Текущий статус |
175
177
  | `pachca profile update-status` | Новый статус |
176
178
  | `pachca profile delete-status` | Удаление статуса |
@@ -202,6 +204,8 @@ pachca guide # список всех сценариев
202
204
  | `pachca users get` | Информация о сотруднике |
203
205
  | `pachca users update` | Редактирование сотрудника |
204
206
  | `pachca users delete` | Удаление сотрудника |
207
+ | `pachca users update-avatar` | Загрузка аватара сотрудника |
208
+ | `pachca users remove-avatar` | Удаление аватара сотрудника |
205
209
  | `pachca users get-status` | Статус сотрудника |
206
210
  | `pachca users update-status` | Новый статус сотрудника |
207
211
  | `pachca users remove-status` | Удаление статуса сотрудника |
package/dist/client.js CHANGED
@@ -32,7 +32,14 @@ function buildUrl(apiPath, query) {
32
32
  if (query) {
33
33
  for (const [key, value] of Object.entries(query)) {
34
34
  if (value !== undefined) {
35
- url.searchParams.set(key, String(value));
35
+ if (Array.isArray(value)) {
36
+ for (const v of value) {
37
+ url.searchParams.append(`${key}[]`, String(v));
38
+ }
39
+ }
40
+ else {
41
+ url.searchParams.set(key, String(value));
42
+ }
36
43
  }
37
44
  }
38
45
  }
@@ -43,6 +43,8 @@ export default class BotsListEvents extends BaseCommand {
43
43
  const items = body.data;
44
44
  if (items)
45
45
  allData.push(...items);
46
+ if (!items || items.length === 0)
47
+ break;
46
48
  const meta = body.meta;
47
49
  const paginate = meta?.paginate;
48
50
  nextCursor = paginate?.next_page;
@@ -15,16 +15,20 @@ export default class ChatsList extends BaseCommand {
15
15
  static args = {};
16
16
  static flags = {
17
17
  ...BaseCommand.baseFlags,
18
- sort: Flags.string({
19
- description: "Поле сортировки (id — идентификатор чата, last-message-at — дата и время создания последнего сообщения)",
20
- options: ["id", "last-message-at"],
18
+ 'sort': Flags.string({
19
+ description: "Поле сортировки",
20
+ options: ["id", "last_message_at"],
21
+ default: "id",
21
22
  }),
22
- order: Flags.string({
23
- description: "Порядок сортировки",
23
+ 'order': Flags.string({
24
+ description: "Направление сортировки",
24
25
  options: ["asc", "desc"],
26
+ default: "desc",
25
27
  }),
26
28
  'availability': Flags.string({
27
29
  description: "Параметр, который отвечает за доступность и выборку чатов для пользователя",
30
+ options: ["is_member", "public"],
31
+ default: "is_member",
28
32
  }),
29
33
  'last-message-at-after': Flags.string({
30
34
  description: "Фильтрация по времени создания последнего сообщения. Будут возвращены те чаты, время последнего созданного сообщения в которых не раньше чем указанное (в формате YYYY-MM-DDThh:mm:ss.sssZ).",
@@ -58,7 +62,8 @@ export default class ChatsList extends BaseCommand {
58
62
  const seenCursors = new Set();
59
63
  while (pages < 500) {
60
64
  const query = {
61
- ...(flags.sort ? { [`sort[${flags.sort.replace(/-/g, '_')}]`]: flags.order || 'desc' } : {}),
65
+ sort: flags['sort'],
66
+ order: flags['order'],
62
67
  availability: flags['availability'],
63
68
  'last_message_at_after': flags['last-message-at-after'],
64
69
  'last_message_at_before': flags['last-message-at-before'],
@@ -71,6 +76,8 @@ export default class ChatsList extends BaseCommand {
71
76
  const items = body.data;
72
77
  if (items)
73
78
  allData.push(...items);
79
+ if (!items || items.length === 0)
80
+ break;
74
81
  const meta = body.meta;
75
82
  const paginate = meta?.paginate;
76
83
  nextCursor = paginate?.next_page;
@@ -100,7 +107,8 @@ export default class ChatsList extends BaseCommand {
100
107
  method: 'GET',
101
108
  path: '/chats',
102
109
  query: {
103
- ...(flags.sort ? { [`sort[${flags.sort.replace(/-/g, '_')}]`]: flags.order || 'desc' } : {}),
110
+ sort: flags['sort'],
111
+ order: flags['order'],
104
112
  availability: flags['availability'],
105
113
  'last_message_at_after': flags['last-message-at-after'],
106
114
  'last_message_at_before': flags['last-message-at-before'],
@@ -48,6 +48,8 @@ export default class GroupTagsListUsers extends BaseCommand {
48
48
  const items = body.data;
49
49
  if (items)
50
50
  allData.push(...items);
51
+ if (!items || items.length === 0)
52
+ break;
51
53
  const meta = body.meta;
52
54
  const paginate = meta?.paginate;
53
55
  nextCursor = paginate?.next_page;
@@ -39,7 +39,7 @@ export default class GroupTagsList extends BaseCommand {
39
39
  const seenCursors = new Set();
40
40
  while (pages < 500) {
41
41
  const query = {
42
- names: flags['names'],
42
+ names: flags['names']?.split(','),
43
43
  limit: flags.limit,
44
44
  cursor: nextCursor,
45
45
  };
@@ -48,6 +48,8 @@ export default class GroupTagsList extends BaseCommand {
48
48
  const items = body.data;
49
49
  if (items)
50
50
  allData.push(...items);
51
+ if (!items || items.length === 0)
52
+ break;
51
53
  const meta = body.meta;
52
54
  const paginate = meta?.paginate;
53
55
  nextCursor = paginate?.next_page;
@@ -77,7 +79,7 @@ export default class GroupTagsList extends BaseCommand {
77
79
  method: 'GET',
78
80
  path: '/group_tags',
79
81
  query: {
80
- names: flags['names'],
82
+ names: flags['names']?.split(','),
81
83
  limit: flags.limit,
82
84
  cursor: flags.cursor,
83
85
  },
@@ -22,6 +22,8 @@ export default class MembersList extends BaseCommand {
22
22
  ...BaseCommand.baseFlags,
23
23
  'role': Flags.string({
24
24
  description: "Роль в чате",
25
+ options: ["all", "owner", "admin", "editor", "member"],
26
+ default: "all",
25
27
  }),
26
28
  limit: Flags.integer({
27
29
  description: 'Количество результатов на страницу',
@@ -54,6 +56,8 @@ export default class MembersList extends BaseCommand {
54
56
  const items = body.data;
55
57
  if (items)
56
58
  allData.push(...items);
59
+ if (!items || items.length === 0)
60
+ break;
57
61
  const meta = body.meta;
58
62
  const paginate = meta?.paginate;
59
63
  nextCursor = paginate?.next_page;
@@ -1,5 +1,5 @@
1
1
  // Auto-generated from openapi.yaml — DO NOT EDIT
2
- import { Flags } from '@oclif/core';
2
+ import { Args, Flags } from '@oclif/core';
3
3
  import { BaseCommand } from '../../base-command.js';
4
4
  import * as clack from '@clack/prompts';
5
5
  export default class MessagesList extends BaseCommand {
@@ -14,19 +14,26 @@ export default class MessagesList extends BaseCommand {
14
14
  static apiPath = "/messages";
15
15
  static defaultColumns = ["id", "content", "created_at", "entity_type", "entity_id"];
16
16
  static requiredFlags = ["chat-id"];
17
- static args = {};
17
+ static args = {
18
+ chat_id: Args.integer({
19
+ description: "Идентификатор чата (беседа, канал, диалог или чат треда)",
20
+ required: false,
21
+ }),
22
+ };
18
23
  static flags = {
19
24
  ...BaseCommand.baseFlags,
20
25
  'chat-id': Flags.integer({
21
26
  description: "Идентификатор чата (беседа, канал, диалог или чат треда)",
22
27
  }),
23
- sort: Flags.string({
24
- description: "Поле сортировки (id — идентификатор сообщения)",
28
+ 'sort': Flags.string({
29
+ description: "Поле сортировки",
25
30
  options: ["id"],
31
+ default: "id",
26
32
  }),
27
- order: Flags.string({
28
- description: "Порядок сортировки",
33
+ 'order': Flags.string({
34
+ description: "Направление сортировки",
29
35
  options: ["asc", "desc"],
36
+ default: "desc",
30
37
  }),
31
38
  limit: Flags.integer({
32
39
  description: 'Количество результатов на страницу',
@@ -42,6 +49,9 @@ export default class MessagesList extends BaseCommand {
42
49
  async run() {
43
50
  const { args, flags } = await this.parse(MessagesList);
44
51
  this.parsedFlags = flags;
52
+ if (args.chat_id !== undefined && flags['chat-id'] === undefined) {
53
+ flags['chat-id'] = args.chat_id;
54
+ }
45
55
  const missingRequired = [
46
56
  { flag: 'chat-id', label: "Идентификатор чата (беседа, канал, диалог или чат треда)", type: 'integer' },
47
57
  ].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
@@ -77,7 +87,8 @@ export default class MessagesList extends BaseCommand {
77
87
  while (pages < 500) {
78
88
  const query = {
79
89
  'chat_id': flags['chat-id'],
80
- ...(flags.sort ? { [`sort[${flags.sort.replace(/-/g, '_')}]`]: flags.order || 'desc' } : {}),
90
+ sort: flags['sort'],
91
+ order: flags['order'],
81
92
  limit: flags.limit,
82
93
  cursor: nextCursor,
83
94
  };
@@ -86,6 +97,8 @@ export default class MessagesList extends BaseCommand {
86
97
  const items = body.data;
87
98
  if (items)
88
99
  allData.push(...items);
100
+ if (!items || items.length === 0)
101
+ break;
89
102
  const meta = body.meta;
90
103
  const paginate = meta?.paginate;
91
104
  nextCursor = paginate?.next_page;
@@ -116,7 +129,8 @@ export default class MessagesList extends BaseCommand {
116
129
  path: '/messages',
117
130
  query: {
118
131
  'chat_id': flags['chat-id'],
119
- ...(flags.sort ? { [`sort[${flags.sort.replace(/-/g, '_')}]`]: flags.order || 'desc' } : {}),
132
+ sort: flags['sort'],
133
+ order: flags['order'],
120
134
  limit: flags.limit,
121
135
  cursor: flags.cursor,
122
136
  },
@@ -0,0 +1,41 @@
1
+ // Auto-generated from openapi.yaml — DO NOT EDIT
2
+ import { Flags } from '@oclif/core';
3
+ import { BaseCommand } from '../../base-command.js';
4
+ import * as clack from '@clack/prompts';
5
+ export default class ProfileDeleteAvatar extends BaseCommand {
6
+ static description = "Удаление аватара";
7
+ static examples = [
8
+ "Загрузить аватар профиля:\n $ pachca profile update-avatar",
9
+ "Удалить аватар профиля:\n $ pachca profile delete-avatar"
10
+ ];
11
+ static scope = "profile_avatar:write";
12
+ static apiMethod = "DELETE";
13
+ static apiPath = "/profile/avatar";
14
+ static args = {};
15
+ static flags = {
16
+ ...BaseCommand.baseFlags,
17
+ force: Flags.boolean({
18
+ description: 'Пропустить подтверждение',
19
+ default: false,
20
+ }),
21
+ };
22
+ async run() {
23
+ const { args, flags } = await this.parse(ProfileDeleteAvatar);
24
+ this.parsedFlags = flags;
25
+ if (!flags.force) {
26
+ if (!this.isInteractive()) {
27
+ this.validationError([{ message: 'Деструктивная операция требует флага --force', flag: 'force' }], { type: 'PACHCA_DESTRUCTIVE_OP_ERROR', hint: "pachca profile delete-avatar --force" });
28
+ }
29
+ const confirm = await clack.confirm({ message: 'Вы уверены?' });
30
+ if (clack.isCancel(confirm) || !confirm) {
31
+ process.stderr.write('Отменено.\n');
32
+ this.exit(0);
33
+ }
34
+ }
35
+ const { data } = await this.apiRequest({
36
+ method: 'DELETE',
37
+ path: '/profile/avatar',
38
+ });
39
+ this.success('Удалено');
40
+ }
41
+ }
@@ -0,0 +1,50 @@
1
+ // Auto-generated from openapi.yaml — DO NOT EDIT
2
+ import { Flags } from '@oclif/core';
3
+ import { BaseCommand } from '../../base-command.js';
4
+ import * as fs from 'node:fs';
5
+ import * as path from 'node:path';
6
+ export default class ProfileUpdateAvatar extends BaseCommand {
7
+ static description = "Загрузка аватара";
8
+ static examples = [
9
+ "Загрузить аватар профиля:\n $ pachca profile update-avatar",
10
+ "Удалить аватар профиля:\n $ pachca profile delete-avatar"
11
+ ];
12
+ static scope = "profile_avatar:write";
13
+ static apiMethod = "PUT";
14
+ static apiPath = "/profile/avatar";
15
+ static defaultColumns = ["image_url"];
16
+ static args = {};
17
+ static flags = {
18
+ ...BaseCommand.baseFlags,
19
+ file: Flags.string({
20
+ description: "Файл изображения для аватара",
21
+ }),
22
+ };
23
+ async run() {
24
+ const { args, flags } = await this.parse(ProfileUpdateAvatar);
25
+ this.parsedFlags = flags;
26
+ let formData;
27
+ if (flags.file) {
28
+ formData = new FormData();
29
+ if (flags.file === '-') {
30
+ const chunks = [];
31
+ for await (const chunk of process.stdin)
32
+ chunks.push(chunk);
33
+ const blob = new Blob([Buffer.concat(chunks)]);
34
+ formData.append('image', blob, 'stdin');
35
+ }
36
+ else {
37
+ const blob = new Blob([fs.readFileSync(flags.file)]);
38
+ formData.append('image', blob, path.basename(flags.file));
39
+ }
40
+ }
41
+ const { data } = await this.apiRequest({
42
+ method: 'PUT',
43
+ path: '/profile/avatar',
44
+ formData,
45
+ });
46
+ const responseBody = data;
47
+ const result = responseBody.data ?? responseBody;
48
+ this.output(result);
49
+ }
50
+ }
@@ -49,6 +49,8 @@ export default class ReactionsList extends BaseCommand {
49
49
  const items = body.data;
50
50
  if (items)
51
51
  allData.push(...items);
52
+ if (!items || items.length === 0)
53
+ break;
52
54
  const meta = body.meta;
53
55
  const paginate = meta?.paginate;
54
56
  nextCursor = paginate?.next_page;
@@ -47,6 +47,8 @@ export default class ReadMemberListReaders extends BaseCommand {
47
47
  const items = body.data;
48
48
  if (items)
49
49
  allData.push(...items);
50
+ if (!items || items.length === 0)
51
+ break;
50
52
  const meta = body.meta;
51
53
  const paginate = meta?.paginate;
52
54
  nextCursor = paginate?.next_page;
@@ -76,6 +76,8 @@ export default class SearchListChats extends BaseCommand {
76
76
  const items = body.data;
77
77
  if (items)
78
78
  allData.push(...items);
79
+ if (!items || items.length === 0)
80
+ break;
79
81
  const meta = body.meta;
80
82
  const paginate = meta?.paginate;
81
83
  nextCursor = paginate?.next_page;
@@ -62,8 +62,8 @@ export default class SearchListMessages extends BaseCommand {
62
62
  order: flags['order'],
63
63
  'created_from': flags['created-from'],
64
64
  'created_to': flags['created-to'],
65
- 'chat_ids': flags['chat-ids'],
66
- 'user_ids': flags['user-ids'],
65
+ 'chat_ids': flags['chat-ids']?.split(','),
66
+ 'user_ids': flags['user-ids']?.split(','),
67
67
  active: flags['active'],
68
68
  limit: flags.limit,
69
69
  cursor: nextCursor,
@@ -73,6 +73,8 @@ export default class SearchListMessages extends BaseCommand {
73
73
  const items = body.data;
74
74
  if (items)
75
75
  allData.push(...items);
76
+ if (!items || items.length === 0)
77
+ break;
76
78
  const meta = body.meta;
77
79
  const paginate = meta?.paginate;
78
80
  nextCursor = paginate?.next_page;
@@ -106,8 +108,8 @@ export default class SearchListMessages extends BaseCommand {
106
108
  order: flags['order'],
107
109
  'created_from': flags['created-from'],
108
110
  'created_to': flags['created-to'],
109
- 'chat_ids': flags['chat-ids'],
110
- 'user_ids': flags['user-ids'],
111
+ 'chat_ids': flags['chat-ids']?.split(','),
112
+ 'user_ids': flags['user-ids']?.split(','),
111
113
  active: flags['active'],
112
114
  limit: flags.limit,
113
115
  cursor: flags.cursor,
@@ -62,7 +62,7 @@ export default class SearchListUsers extends BaseCommand {
62
62
  order: flags['order'],
63
63
  'created_from': flags['created-from'],
64
64
  'created_to': flags['created-to'],
65
- 'company_roles': flags['company-roles'],
65
+ 'company_roles': flags['company-roles']?.split(','),
66
66
  limit: flags.limit,
67
67
  cursor: nextCursor,
68
68
  };
@@ -71,6 +71,8 @@ export default class SearchListUsers extends BaseCommand {
71
71
  const items = body.data;
72
72
  if (items)
73
73
  allData.push(...items);
74
+ if (!items || items.length === 0)
75
+ break;
74
76
  const meta = body.meta;
75
77
  const paginate = meta?.paginate;
76
78
  nextCursor = paginate?.next_page;
@@ -105,7 +107,7 @@ export default class SearchListUsers extends BaseCommand {
105
107
  order: flags['order'],
106
108
  'created_from': flags['created-from'],
107
109
  'created_to': flags['created-to'],
108
- 'company_roles': flags['company-roles'],
110
+ 'company_roles': flags['company-roles']?.split(','),
109
111
  limit: flags.limit,
110
112
  cursor: flags.cursor,
111
113
  },
@@ -75,6 +75,8 @@ export default class SecurityList extends BaseCommand {
75
75
  const items = body.data;
76
76
  if (items)
77
77
  allData.push(...items);
78
+ if (!items || items.length === 0)
79
+ break;
78
80
  const meta = body.meta;
79
81
  const paginate = meta?.paginate;
80
82
  nextCursor = paginate?.next_page;
@@ -45,6 +45,8 @@ export default class TasksList extends BaseCommand {
45
45
  const items = body.data;
46
46
  if (items)
47
47
  allData.push(...items);
48
+ if (!items || items.length === 0)
49
+ break;
48
50
  const meta = body.meta;
49
51
  const paginate = meta?.paginate;
50
52
  nextCursor = paginate?.next_page;
@@ -49,6 +49,8 @@ export default class UsersList extends BaseCommand {
49
49
  const items = body.data;
50
50
  if (items)
51
51
  allData.push(...items);
52
+ if (!items || items.length === 0)
53
+ break;
52
54
  const meta = body.meta;
53
55
  const paginate = meta?.paginate;
54
56
  nextCursor = paginate?.next_page;
@@ -0,0 +1,46 @@
1
+ // Auto-generated from openapi.yaml — DO NOT EDIT
2
+ import { Args, Flags } from '@oclif/core';
3
+ import { BaseCommand } from '../../base-command.js';
4
+ import * as clack from '@clack/prompts';
5
+ export default class UsersRemoveAvatar extends BaseCommand {
6
+ static description = "Удаление аватара сотрудника";
7
+ static examples = [
8
+ "Загрузить аватар сотрудника:\n $ pachca users update-avatar",
9
+ "Удалить аватар сотрудника:\n $ pachca users remove-avatar"
10
+ ];
11
+ static scope = "user_avatar:write";
12
+ static apiMethod = "DELETE";
13
+ static apiPath = "/users/{user_id}/avatar";
14
+ static args = {
15
+ user_id: Args.integer({
16
+ description: "Идентификатор пользователя (pachca users list)",
17
+ required: true,
18
+ }),
19
+ };
20
+ static flags = {
21
+ ...BaseCommand.baseFlags,
22
+ force: Flags.boolean({
23
+ description: 'Пропустить подтверждение',
24
+ default: false,
25
+ }),
26
+ };
27
+ async run() {
28
+ const { args, flags } = await this.parse(UsersRemoveAvatar);
29
+ this.parsedFlags = flags;
30
+ if (!flags.force) {
31
+ if (!this.isInteractive()) {
32
+ this.validationError([{ message: 'Деструктивная операция требует флага --force', flag: 'force' }], { type: 'PACHCA_DESTRUCTIVE_OP_ERROR', hint: "pachca users remove-avatar <user_id> --force" });
33
+ }
34
+ const confirm = await clack.confirm({ message: 'Вы уверены?' });
35
+ if (clack.isCancel(confirm) || !confirm) {
36
+ process.stderr.write('Отменено.\n');
37
+ this.exit(0);
38
+ }
39
+ }
40
+ const { data } = await this.apiRequest({
41
+ method: 'DELETE',
42
+ path: `/users/${args.user_id}/avatar`,
43
+ });
44
+ this.success('Удалено');
45
+ }
46
+ }
@@ -0,0 +1,55 @@
1
+ // Auto-generated from openapi.yaml — DO NOT EDIT
2
+ import { Args, Flags } from '@oclif/core';
3
+ import { BaseCommand } from '../../base-command.js';
4
+ import * as fs from 'node:fs';
5
+ import * as path from 'node:path';
6
+ export default class UsersUpdateAvatar extends BaseCommand {
7
+ static description = "Загрузка аватара сотрудника";
8
+ static examples = [
9
+ "Загрузить аватар сотрудника:\n $ pachca users update-avatar",
10
+ "Удалить аватар сотрудника:\n $ pachca users remove-avatar"
11
+ ];
12
+ static scope = "user_avatar:write";
13
+ static apiMethod = "PUT";
14
+ static apiPath = "/users/{user_id}/avatar";
15
+ static defaultColumns = ["image_url"];
16
+ static args = {
17
+ user_id: Args.integer({
18
+ description: "Идентификатор пользователя (pachca users list)",
19
+ required: true,
20
+ }),
21
+ };
22
+ static flags = {
23
+ ...BaseCommand.baseFlags,
24
+ file: Flags.string({
25
+ description: "Файл изображения для аватара",
26
+ }),
27
+ };
28
+ async run() {
29
+ const { args, flags } = await this.parse(UsersUpdateAvatar);
30
+ this.parsedFlags = flags;
31
+ let formData;
32
+ if (flags.file) {
33
+ formData = new FormData();
34
+ if (flags.file === '-') {
35
+ const chunks = [];
36
+ for await (const chunk of process.stdin)
37
+ chunks.push(chunk);
38
+ const blob = new Blob([Buffer.concat(chunks)]);
39
+ formData.append('image', blob, 'stdin');
40
+ }
41
+ else {
42
+ const blob = new Blob([fs.readFileSync(flags.file)]);
43
+ formData.append('image', blob, path.basename(flags.file));
44
+ }
45
+ }
46
+ const { data } = await this.apiRequest({
47
+ method: 'PUT',
48
+ path: `/users/${args.user_id}/avatar`,
49
+ formData,
50
+ });
51
+ const responseBody = data;
52
+ const result = responseBody.data ?? responseBody;
53
+ this.output(result);
54
+ }
55
+ }
@@ -39,6 +39,8 @@
39
39
  "threads:add": "Новый тред",
40
40
  "profile:get-info": "Информация о токене",
41
41
  "profile:get": "Информация о профиле",
42
+ "profile:update-avatar": "Загрузка аватара",
43
+ "profile:delete-avatar": "Удаление аватара",
42
44
  "profile:get-status": "Текущий статус",
43
45
  "profile:update-status": "Новый статус",
44
46
  "profile:delete-status": "Удаление статуса",
@@ -57,6 +59,8 @@
57
59
  "users:get": "Информация о сотруднике",
58
60
  "users:update": "Редактирование сотрудника",
59
61
  "users:delete": "Удаление сотрудника",
62
+ "users:update-avatar": "Загрузка аватара сотрудника",
63
+ "users:remove-avatar": "Удаление аватара сотрудника",
60
64
  "users:get-status": "Статус сотрудника",
61
65
  "users:update-status": "Новый статус сотрудника",
62
66
  "users:remove-status": "Удаление статуса сотрудника",
@@ -1,4 +1,40 @@
1
1
  [
2
+ {
3
+ "version": "2026.4.0",
4
+ "date": "7 апреля 2026",
5
+ "changes": [
6
+ {
7
+ "type": "+",
8
+ "command": "profile update-avatar",
9
+ "description": "Загрузка аватара профиля"
10
+ },
11
+ {
12
+ "type": "+",
13
+ "command": "profile delete-avatar",
14
+ "description": "Удаление аватара профиля"
15
+ },
16
+ {
17
+ "type": "+",
18
+ "command": "users update-avatar",
19
+ "description": "Загрузка аватара сотрудника"
20
+ },
21
+ {
22
+ "type": "+",
23
+ "command": "users remove-avatar",
24
+ "description": "Удаление аватара сотрудника"
25
+ },
26
+ {
27
+ "type": "~",
28
+ "command": "chats list, messages list",
29
+ "description": "Исправлена сортировка: --order без --sort теперь корректно работает (sort по умолчанию id, order по умолчанию desc)"
30
+ },
31
+ {
32
+ "type": "~",
33
+ "command": "messages list",
34
+ "description": "chat_id можно передать первым аргументом: pachca messages list 12345"
35
+ }
36
+ ]
37
+ },
2
38
  {
3
39
  "version": "2026.3.10",
4
40
  "date": "21 марта 2026",