@pachca/cli 2026.10.3 → 2026.10.4
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 +25 -0
- package/README.md +5 -5
- package/README.template.md +5 -5
- package/dist/base-command.js +68 -36
- package/dist/client.js +2 -1
- package/dist/commands/api.js +3 -3
- package/dist/commands/auth/login.js +12 -9
- package/dist/commands/bots/create.js +1 -1
- package/dist/commands/bots/list-company.js +4 -2
- package/dist/commands/bots/list-events.js +4 -2
- package/dist/commands/bots/list-tokens.js +4 -2
- package/dist/commands/bots/list.js +4 -2
- package/dist/commands/bots/update.js +4 -3
- package/dist/commands/chats/list-company.js +4 -2
- package/dist/commands/chats/list.js +4 -2
- package/dist/commands/doctor.js +60 -35
- package/dist/commands/drafts/create.js +5 -2
- package/dist/commands/drafts/list.js +4 -2
- package/dist/commands/drafts/update.js +6 -3
- package/dist/commands/group-tags/list-users.js +4 -2
- package/dist/commands/group-tags/list.js +4 -2
- package/dist/commands/important-messages/list.js +4 -2
- package/dist/commands/members/add.js +1 -1
- package/dist/commands/members/list.js +4 -2
- package/dist/commands/messages/create.js +5 -3
- package/dist/commands/messages/list.js +4 -2
- package/dist/commands/messages/update.js +4 -2
- package/dist/commands/reactions/list.js +4 -2
- package/dist/commands/read-member/list-readers.js +4 -2
- package/dist/commands/search/list-chats.js +4 -2
- package/dist/commands/search/list-messages.js +4 -2
- package/dist/commands/search/list-users.js +4 -2
- package/dist/commands/security/list.js +4 -2
- package/dist/commands/tasks/create.js +3 -1
- package/dist/commands/tasks/list.js +4 -2
- package/dist/commands/tasks/update.js +3 -1
- package/dist/commands/threads/list.js +4 -2
- package/dist/commands/upload.js +27 -8
- package/dist/commands/users/list.js +4 -2
- package/dist/commands/users/update.js +1 -1
- package/dist/commands/views/open.js +1 -0
- package/dist/data/changelog.json +111 -0
- package/dist/data/endpoints.json +1 -1
- package/dist/hooks/init.js +8 -4
- package/dist/lib/flags.js +25 -0
- package/dist/oauth.js +2 -1
- package/dist/profiles.js +22 -4
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
|
@@ -50,6 +50,7 @@ export default class SearchListUsers extends BaseCommand {
|
|
|
50
50
|
let nextCursor = undefined;
|
|
51
51
|
let pages = 0;
|
|
52
52
|
const seenCursors = new Set();
|
|
53
|
+
let total;
|
|
53
54
|
while (pages < 500) {
|
|
54
55
|
const query = {
|
|
55
56
|
query: flags['query'],
|
|
@@ -70,7 +71,7 @@ export default class SearchListUsers extends BaseCommand {
|
|
|
70
71
|
const paginate = meta?.paginate;
|
|
71
72
|
nextCursor = paginate?.next_page;
|
|
72
73
|
pages++;
|
|
73
|
-
// Условие конца:
|
|
74
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
74
75
|
const hasNext = paginate?.has_next;
|
|
75
76
|
if (typeof hasNext === 'boolean') {
|
|
76
77
|
if (!hasNext)
|
|
@@ -80,7 +81,8 @@ export default class SearchListUsers extends BaseCommand {
|
|
|
80
81
|
break;
|
|
81
82
|
}
|
|
82
83
|
if (process.stderr.isTTY) {
|
|
83
|
-
|
|
84
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
85
|
+
total ??= meta?.total;
|
|
84
86
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
85
87
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
86
88
|
}
|
|
@@ -53,6 +53,7 @@ export default class SecurityList extends BaseCommand {
|
|
|
53
53
|
let nextCursor = undefined;
|
|
54
54
|
let pages = 0;
|
|
55
55
|
const seenCursors = new Set();
|
|
56
|
+
let total;
|
|
56
57
|
while (pages < 500) {
|
|
57
58
|
const query = {
|
|
58
59
|
'start_time': flags['start-time'],
|
|
@@ -74,7 +75,7 @@ export default class SecurityList extends BaseCommand {
|
|
|
74
75
|
const paginate = meta?.paginate;
|
|
75
76
|
nextCursor = paginate?.next_page;
|
|
76
77
|
pages++;
|
|
77
|
-
// Условие конца:
|
|
78
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
78
79
|
const hasNext = paginate?.has_next;
|
|
79
80
|
if (typeof hasNext === 'boolean') {
|
|
80
81
|
if (!hasNext)
|
|
@@ -84,7 +85,8 @@ export default class SecurityList extends BaseCommand {
|
|
|
84
85
|
break;
|
|
85
86
|
}
|
|
86
87
|
if (process.stderr.isTTY) {
|
|
87
|
-
|
|
88
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
89
|
+
total ??= meta?.total;
|
|
88
90
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
89
91
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
90
92
|
}
|
|
@@ -47,7 +47,9 @@ export default class TasksCreate extends BaseCommand {
|
|
|
47
47
|
for await (const chunk of process.stdin) {
|
|
48
48
|
chunks.push(chunk);
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
const piped = Buffer.concat(chunks).toString('utf-8').trimEnd();
|
|
51
|
+
if (piped)
|
|
52
|
+
flags['content'] = piped;
|
|
51
53
|
}
|
|
52
54
|
const missingRequired = [
|
|
53
55
|
{ flag: 'kind', label: "Тип", type: 'string' },
|
|
@@ -43,6 +43,7 @@ export default class TasksList extends BaseCommand {
|
|
|
43
43
|
let nextCursor = undefined;
|
|
44
44
|
let pages = 0;
|
|
45
45
|
const seenCursors = new Set();
|
|
46
|
+
let total;
|
|
46
47
|
while (pages < 500) {
|
|
47
48
|
const query = {
|
|
48
49
|
status: flags['status'],
|
|
@@ -61,7 +62,7 @@ export default class TasksList extends BaseCommand {
|
|
|
61
62
|
const paginate = meta?.paginate;
|
|
62
63
|
nextCursor = paginate?.next_page;
|
|
63
64
|
pages++;
|
|
64
|
-
// Условие конца:
|
|
65
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
65
66
|
const hasNext = paginate?.has_next;
|
|
66
67
|
if (typeof hasNext === 'boolean') {
|
|
67
68
|
if (!hasNext)
|
|
@@ -71,7 +72,8 @@ export default class TasksList extends BaseCommand {
|
|
|
71
72
|
break;
|
|
72
73
|
}
|
|
73
74
|
if (process.stderr.isTTY) {
|
|
74
|
-
|
|
75
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
76
|
+
total ??= meta?.total;
|
|
75
77
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
76
78
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
77
79
|
}
|
|
@@ -53,7 +53,9 @@ export default class TasksUpdate extends BaseCommand {
|
|
|
53
53
|
for await (const chunk of process.stdin) {
|
|
54
54
|
chunks.push(chunk);
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
const piped = Buffer.concat(chunks).toString('utf-8').trimEnd();
|
|
57
|
+
if (piped)
|
|
58
|
+
flags['content'] = piped;
|
|
57
59
|
}
|
|
58
60
|
const body = { task: {
|
|
59
61
|
kind: flags['kind'],
|
|
@@ -36,6 +36,7 @@ export default class ThreadsList extends BaseCommand {
|
|
|
36
36
|
let nextCursor = undefined;
|
|
37
37
|
let pages = 0;
|
|
38
38
|
const seenCursors = new Set();
|
|
39
|
+
let total;
|
|
39
40
|
while (pages < 500) {
|
|
40
41
|
const query = {
|
|
41
42
|
'last_message_at_after': flags['last-message-at-after'],
|
|
@@ -52,7 +53,7 @@ export default class ThreadsList extends BaseCommand {
|
|
|
52
53
|
const paginate = meta?.paginate;
|
|
53
54
|
nextCursor = paginate?.next_page;
|
|
54
55
|
pages++;
|
|
55
|
-
// Условие конца:
|
|
56
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
56
57
|
const hasNext = paginate?.has_next;
|
|
57
58
|
if (typeof hasNext === 'boolean') {
|
|
58
59
|
if (!hasNext)
|
|
@@ -62,7 +63,8 @@ export default class ThreadsList extends BaseCommand {
|
|
|
62
63
|
break;
|
|
63
64
|
}
|
|
64
65
|
if (process.stderr.isTTY) {
|
|
65
|
-
|
|
66
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
67
|
+
total ??= meta?.total;
|
|
66
68
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
67
69
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
68
70
|
}
|
package/dist/commands/upload.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Args } from '@oclif/core';
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { BaseCommand } from '../base-command.js';
|
|
@@ -6,7 +6,8 @@ export default class Upload extends BaseCommand {
|
|
|
6
6
|
static description = 'Загрузить файл (получает подпись и загружает автоматически)';
|
|
7
7
|
static examples = [
|
|
8
8
|
'<%= config.bin %> upload photo.jpg',
|
|
9
|
-
'cat data.csv | <%= config.bin %> upload -',
|
|
9
|
+
'cat data.csv | <%= config.bin %> upload - --name data.csv',
|
|
10
|
+
'<%= config.bin %> upload ./build/out.pdf --name report.pdf',
|
|
10
11
|
];
|
|
11
12
|
static scope = 'uploads:write';
|
|
12
13
|
static args = {
|
|
@@ -17,10 +18,20 @@ export default class Upload extends BaseCommand {
|
|
|
17
18
|
};
|
|
18
19
|
static flags = {
|
|
19
20
|
...BaseCommand.baseFlags,
|
|
21
|
+
name: Flags.string({
|
|
22
|
+
description: 'Имя файла, которым заканчивается key. Расширение name при отправке файла в сообщении должно совпадать с расширением этого имени. По умолчанию это имя загружаемого файла, а у данных из stdin имя stdin без расширения',
|
|
23
|
+
}),
|
|
20
24
|
};
|
|
21
25
|
async run() {
|
|
22
26
|
const { args, flags } = await this.parse(Upload);
|
|
23
27
|
this.parsedFlags = flags;
|
|
28
|
+
const fromStdin = args.file === '-';
|
|
29
|
+
if (flags.name !== undefined && !isPlainFileName(flags.name)) {
|
|
30
|
+
this.validationError([{ message: 'Имя файла в --name не может быть пустым и содержать / или \\', flag: 'name' }], { type: 'PACHCA_USAGE_ERROR' });
|
|
31
|
+
}
|
|
32
|
+
if (!fromStdin && !fs.existsSync(args.file)) {
|
|
33
|
+
this.validationError([{ message: `Файл не найден: ${args.file}` }], { type: 'PACHCA_USAGE_ERROR' });
|
|
34
|
+
}
|
|
24
35
|
// Step 1: Get upload params
|
|
25
36
|
const { data: uploadData } = await this.apiRequest({
|
|
26
37
|
method: 'POST',
|
|
@@ -30,19 +41,18 @@ export default class Upload extends BaseCommand {
|
|
|
30
41
|
// Step 2: Read file
|
|
31
42
|
let fileBlob;
|
|
32
43
|
let fileName;
|
|
33
|
-
|
|
44
|
+
// The key ends in this name, and the API checks the extension of `name` in
|
|
45
|
+
// a message's `files` against it. Data from stdin has no name of its own.
|
|
46
|
+
if (fromStdin) {
|
|
34
47
|
const chunks = [];
|
|
35
48
|
for await (const chunk of process.stdin)
|
|
36
49
|
chunks.push(chunk);
|
|
37
50
|
fileBlob = new Blob([Buffer.concat(chunks)]);
|
|
38
|
-
fileName = 'stdin';
|
|
51
|
+
fileName = flags.name ?? 'stdin';
|
|
39
52
|
}
|
|
40
53
|
else {
|
|
41
|
-
if (!fs.existsSync(args.file)) {
|
|
42
|
-
this.validationError([{ message: `Файл не найден: ${args.file}` }], { type: 'PACHCA_USAGE_ERROR' });
|
|
43
|
-
}
|
|
44
54
|
fileBlob = new Blob([fs.readFileSync(args.file)]);
|
|
45
|
-
fileName = path.basename(args.file);
|
|
55
|
+
fileName = flags.name ?? path.basename(args.file);
|
|
46
56
|
}
|
|
47
57
|
// Step 3: Replace ${filename} in key
|
|
48
58
|
const key = params.key.replace('${filename}', fileName);
|
|
@@ -67,7 +77,16 @@ export default class Upload extends BaseCommand {
|
|
|
67
77
|
formData,
|
|
68
78
|
noAuth: true,
|
|
69
79
|
});
|
|
80
|
+
// Said after the upload succeeds, so a failed one does not report a file as uploaded.
|
|
81
|
+
if (fromStdin && flags.name === undefined && !flags.quiet) {
|
|
82
|
+
process.stderr.write('⚠ Файл из stdin загружен под именем stdin без расширения: в name файла в сообщении расширения тоже не должно быть.\n' +
|
|
83
|
+
' Имя с расширением задаёт флаг --name, например --name report.csv\n');
|
|
84
|
+
}
|
|
70
85
|
// Output the key for use in messages
|
|
71
86
|
this.output({ key });
|
|
72
87
|
}
|
|
73
88
|
}
|
|
89
|
+
/** A bare file name: the key keeps its folder, so a path separator would move the file out of it. */
|
|
90
|
+
function isPlainFileName(name) {
|
|
91
|
+
return name.trim() !== '' && !/[\\/]/.test(name);
|
|
92
|
+
}
|
|
@@ -33,6 +33,7 @@ export default class UsersList extends BaseCommand {
|
|
|
33
33
|
let nextCursor = undefined;
|
|
34
34
|
let pages = 0;
|
|
35
35
|
const seenCursors = new Set();
|
|
36
|
+
let total;
|
|
36
37
|
while (pages < 500) {
|
|
37
38
|
const query = {
|
|
38
39
|
query: flags['query'],
|
|
@@ -48,7 +49,7 @@ export default class UsersList extends BaseCommand {
|
|
|
48
49
|
const paginate = meta?.paginate;
|
|
49
50
|
nextCursor = paginate?.next_page;
|
|
50
51
|
pages++;
|
|
51
|
-
// Условие конца:
|
|
52
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
52
53
|
const hasNext = paginate?.has_next;
|
|
53
54
|
if (typeof hasNext === 'boolean') {
|
|
54
55
|
if (!hasNext)
|
|
@@ -58,7 +59,8 @@ export default class UsersList extends BaseCommand {
|
|
|
58
59
|
break;
|
|
59
60
|
}
|
|
60
61
|
if (process.stderr.isTTY) {
|
|
61
|
-
|
|
62
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
63
|
+
total ??= meta?.total;
|
|
62
64
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
63
65
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
64
66
|
}
|
|
@@ -47,7 +47,7 @@ export default class UsersUpdate extends BaseCommand {
|
|
|
47
47
|
allowNo: true,
|
|
48
48
|
}),
|
|
49
49
|
'list-tags': Flags.string({
|
|
50
|
-
description: "Массив названий тегов, привязываемых к сотруднику. Список заменяет прежний целиком, пустой снимает все теги. Значение, которое не является массивом непустых строк, игнорируется: теги сотрудника не меняются. В тег можно добавить только бота, которого может добавить в чат любой сотрудник и у которого выключена настройка «Ограничить одним чатом». Если бот этим условиям не отвечает, а в списке есть тег, которого у него ещё нет, метод отвечает `422` на поле `group_tags` и ничего не меняет: с кодом `single_chat_bot_tag_denied`, когда бот ограничен одним чатом, и `restricted_bot_tag_denied`, когда добавлять
|
|
50
|
+
description: "Массив названий тегов, привязываемых к сотруднику. Список заменяет прежний целиком, пустой снимает все теги. Значение, которое не является массивом непустых строк, игнорируется: теги сотрудника не меняются. В тег можно добавить только бота, которого может добавить в чат любой сотрудник и у которого выключена настройка «Ограничить одним чатом». Если бот этим условиям не отвечает, а в списке есть тег, которого у него ещё нет, метод отвечает `422` на поле `group_tags` и ничего не меняет: с кодом `single_chat_bot_tag_denied`, когда бот ограничен одним чатом, и `restricted_bot_tag_denied`, когда в настройке «Кто может добавлять бота в чаты» выбран «Создатель» или «Создатель и Администраторы». Подробнее — в разделе [Бот в тегах](https://dev.pachca.com/guides/bots/settings#bot-v-tegah).",
|
|
51
51
|
}),
|
|
52
52
|
'custom-properties': Flags.string({
|
|
53
53
|
description: "Задаваемые дополнительные поля",
|
|
@@ -7,6 +7,7 @@ export default class ViewsOpen extends BaseCommand {
|
|
|
7
7
|
static scope = "views:write";
|
|
8
8
|
static apiMethod = "POST";
|
|
9
9
|
static apiPath = "/views/open";
|
|
10
|
+
static defaultColumns = ["success"];
|
|
10
11
|
static requiredFlags = ["title", "blocks", "type", "trigger-id"];
|
|
11
12
|
static args = {};
|
|
12
13
|
static flags = {
|
package/dist/data/changelog.json
CHANGED
|
@@ -1,4 +1,115 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "2026.10.4",
|
|
4
|
+
"date": "31 октября 2026",
|
|
5
|
+
"changes": [
|
|
6
|
+
{
|
|
7
|
+
"type": "-",
|
|
8
|
+
"command": "api",
|
|
9
|
+
"description": "Справка `--docs` и схема `--spec` показывают `dlp_rule_id` в деталях события `dlp_violation_detected` строкой, как его отдаёт API"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"type": "+",
|
|
13
|
+
"command": "upload",
|
|
14
|
+
"description": "Флаг `--name` задаёт имя файла, которым заканчивается `key`: так данные из stdin получают расширение и уходят в сообщение под этим именем"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"type": "-",
|
|
18
|
+
"command": "upload",
|
|
19
|
+
"description": "Файл, которого нет на диске, команда отклоняет до запроса подписи, в том числе с `--dry-run`"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"type": "~",
|
|
23
|
+
"command": "doctor",
|
|
24
|
+
"description": "Проверяет тот же токен, что и остальные команды, в том же порядке: `--token`, `--profile`, `PACHCA_TOKEN`, `PACHCA_PROFILE`, активный профиль, поэтому в CI с одной `PACHCA_TOKEN` команда проходит"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"type": "~",
|
|
28
|
+
"command": "doctor",
|
|
29
|
+
"description": "При ошибке хотя бы одной проверки команда завершается с кодом `1` в любом формате вывода, в том числе с `-o json`"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"type": "~",
|
|
33
|
+
"command": "doctor",
|
|
34
|
+
"description": "Без файла конфига команда показывает путь, по которому его ищет"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"type": "-",
|
|
38
|
+
"description": "`--dry-run` показывает запрос без входа и без `PACHCA_TOKEN`, а токен в заголовке `Authorization` заменён маской"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"type": "-",
|
|
42
|
+
"command": "files direct-url",
|
|
43
|
+
"description": "С `--dry-run` запрос показан без заголовка `Authorization`, как он и уходит в хранилище"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"type": "~",
|
|
47
|
+
"command": "bots update, drafts update",
|
|
48
|
+
"description": "Слово `null` во флаге поля, которое принимает `null`, уходит в API как JSON null: `--kind null` удаляет входящий вебхук бота, а `--parent-message-id null` снимает ответ с черновика"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"type": "-",
|
|
52
|
+
"command": "auth login",
|
|
53
|
+
"description": "Вход через браузер с `--quiet` печатает адрес и код подтверждения, а флаг убирает только строку ожидания и отчёт о входе"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "~",
|
|
57
|
+
"command": "auth login",
|
|
58
|
+
"description": "Пример в `--help` и подсказка при `--token -` без потока ввода передают токен из буфера обмена: `pbpaste | pachca auth login --token -`"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"type": "-",
|
|
62
|
+
"command": "messages create, messages update, drafts create, drafts update, tasks create, tasks update",
|
|
63
|
+
"description": "Текст из потока ввода попадает в запрос, только когда поток не пуст, а с пустым потоком, как у скрипта или агента, команда отправляет поля из флагов"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"type": "~",
|
|
67
|
+
"description": "Отказ `403` с `role_forbidden` в терминале объясняется словами: право у токена есть, но действие не разрешает роль, поэтому новый вход или токен не помогут. Вывод с `-o json` и в пайпе прежний."
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"type": "~",
|
|
71
|
+
"description": "Объяснение отказа `insufficient_scope` в терминале зависит от источника токена: с `--token` или `PACHCA_TOKEN` команда предлагает `pachca oauth token-info -o json`, а если право есть в сохранённом списке профиля, советует обновить его через `pachca auth status --remote`"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"type": "~",
|
|
75
|
+
"description": "Когда вход через браузер завершён или отозван, сообщение и подсказка `pachca auth login` называют профиль, с которым шла команда"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"type": "-",
|
|
79
|
+
"command": "api",
|
|
80
|
+
"description": "Эквивалентная команда в справке `--describe` повторяет пример запроса из спецификации и работает при копировании"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"type": "-",
|
|
84
|
+
"command": "api",
|
|
85
|
+
"description": "Пример `pachca api POST /messages` в `--help` передаёт `message[entity_id]` в кавычках и работает при копировании, а описание команды и ошибка `--describe` для неизвестного пути говорят «метод»"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"type": "~",
|
|
89
|
+
"command": "views open",
|
|
90
|
+
"description": "Выводит ответ API `{ \"success\": true }`"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"type": "~",
|
|
94
|
+
"description": "Справка команд следует обновлённым описаниям API: удаление входящего вебхука, правило совпадения команд бота, правило упоминаний в тексте сообщения, `duration_ms` и `file_type` у файлов, срок ссылки на поток событий, напоминания вместо задач, поле `scopes` у `bot_token_updated` и другие поля деталей журнала аудита, значения настройки бота у `restricted_bot_tag_denied` в подсказке `--list-tags`, добавление участников в тред, создание треда, `--skip-invite-mentions`, правка без уведомления и список прочитавших"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"type": "-",
|
|
98
|
+
"command": "api",
|
|
99
|
+
"description": "Справка `--docs` и схема `--spec` описывают `scopes` в деталях бота журнала аудита так, как его писал API до 7 октября 2026 года: список прав у `bot_token_created` и объект с `previous` и `new` у `bot_token_updated`"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"type": "~",
|
|
103
|
+
"command": "search",
|
|
104
|
+
"description": "С `--all` команды поиска останавливаются по `has_next` и показывают в терминале, сколько результатов загружено из общего числа найденных"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"type": "~",
|
|
108
|
+
"command": "api",
|
|
109
|
+
"description": "Справка `--docs` и схема `--spec` методов поиска показывают поле `has_next` в `meta.paginate`"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
},
|
|
2
113
|
{
|
|
3
114
|
"version": "2026.10.3",
|
|
4
115
|
"date": "28 октября 2026",
|