@skrr-ai/cli 0.1.120 → 0.1.122
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/dist/base-command.js +11 -2
- package/dist/commands/actions/publish.js +4 -0
- package/dist/commands/agent/message/context.d.ts +1 -0
- package/dist/commands/agent/message/context.js +3 -2
- package/dist/commands/agent/message/send.js +6 -1
- package/dist/commands/search/agents.js +5 -1
- package/dist/commands/search/all.js +74 -22
- package/dist/commands/search/skills.d.ts +1 -0
- package/dist/commands/search/skills.js +12 -1
- package/dist/commands/search/spaces.d.ts +8 -1
- package/dist/commands/search/spaces.js +50 -12
- package/dist/commands/search/tasks.d.ts +13 -2
- package/dist/commands/search/tasks.js +78 -14
- package/dist/commands/search/teams.js +5 -1
- package/dist/commands/search/workspace.d.ts +19 -0
- package/dist/commands/search/workspace.js +126 -0
- package/dist/commands/skills/browse.d.ts +1 -0
- package/dist/commands/skills/browse.js +8 -1
- package/dist/commands/skills/search.d.ts +1 -0
- package/dist/commands/skills/search.js +12 -1
- package/dist/commands/spaces/list.d.ts +1 -0
- package/dist/commands/spaces/list.js +12 -3
- package/dist/commands/spaces/search.d.ts +1 -0
- package/dist/commands/spaces/search.js +9 -0
- package/dist/commands/store/gallery-admissions/approve.d.ts +16 -0
- package/dist/commands/store/gallery-admissions/approve.js +36 -0
- package/dist/commands/store/gallery-admissions/list.d.ts +9 -0
- package/dist/commands/store/gallery-admissions/list.js +49 -0
- package/dist/commands/store/gallery-admissions/preview.d.ts +15 -0
- package/dist/commands/store/gallery-admissions/preview.js +48 -0
- package/dist/commands/store/gallery-admissions/refuse.d.ts +15 -0
- package/dist/commands/store/gallery-admissions/refuse.js +35 -0
- package/dist/commands/store/gallery-admissions/show.d.ts +12 -0
- package/dist/commands/store/gallery-admissions/show.js +55 -0
- package/dist/commands/tasks/list.js +8 -0
- package/dist/commands/tasks/search.d.ts +1 -0
- package/dist/commands/tasks/search.js +9 -0
- package/dist/generated/agent-guides.json +11 -11
- package/dist/lib/api-error-reason.d.ts +2 -0
- package/dist/lib/api-error-reason.js +14 -0
- package/dist/lib/api-fetch.js +3 -0
- package/dist/lib/command-miss.js +1 -0
- package/dist/lib/search-display.d.ts +7 -0
- package/dist/lib/search-display.js +31 -0
- package/dist/lib/skill-store-pagination.d.ts +8 -0
- package/dist/lib/skill-store-pagination.js +35 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.d.ts +10 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.js +147 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonConsentProof.d.ts +20 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonConsentProof.js +72 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/desktopDaemonProof.d.ts +21 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/desktopDaemonProof.js +96 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +2 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +102 -20
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/independentMachineReservation.d.ts +27 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/independentMachineReservation.js +161 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/independentMachineScopes.d.ts +26 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/independentMachineScopes.js +41 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +15 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/macos.js +20 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.d.ts +10 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.js +172 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonConsentProof.d.ts +20 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonConsentProof.js +43 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/desktopDaemonProof.d.ts +21 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/desktopDaemonProof.js +62 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +2 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +133 -25
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/independentMachineReservation.d.ts +27 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/independentMachineReservation.js +132 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/independentMachineScopes.d.ts +26 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/independentMachineScopes.js +15 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/macos.js +28 -15
- package/dist/node_modules/@skrr-ai/auth-core/package.json +31 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +7728 -7666
- package/oclif.manifest.json +1180 -101
- package/package.json +1 -1
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.taskSearchRow = taskSearchRow;
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
|
+
const search_query_1 = require("../../lib/search-query");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
7
|
const base_command_1 = require("../../base-command");
|
|
7
8
|
const format_1 = require("../../lib/format");
|
|
8
9
|
const web_url_1 = require("../../lib/web-url");
|
|
10
|
+
const tasks_1 = require("../../lib/tasks");
|
|
11
|
+
const search_display_1 = require("../../lib/search-display");
|
|
9
12
|
/**
|
|
10
13
|
* One task document → one search-result row.
|
|
11
14
|
*
|
|
@@ -19,57 +22,114 @@ const web_url_1 = require("../../lib/web-url");
|
|
|
19
22
|
*/
|
|
20
23
|
function taskSearchRow(t) {
|
|
21
24
|
return {
|
|
22
|
-
ref: (0, format_1.formatCell)(t.identifier ?? (t.taskNumber ? `#${t.taskNumber}` : undefined)),
|
|
23
|
-
title: (0, format_1.formatCell)(t.title),
|
|
24
|
-
status: (0, format_1.formatCell)(t.status),
|
|
25
|
-
priority: (0, format_1.formatCell)(t.priority),
|
|
25
|
+
ref: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(t.identifier ?? (t.taskNumber ? `#${t.taskNumber}` : undefined))),
|
|
26
|
+
title: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(t.title)),
|
|
27
|
+
status: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(t.status)),
|
|
28
|
+
priority: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(t.priority)),
|
|
26
29
|
// Why this row matched — ref / title / description / comment. The search
|
|
27
30
|
// covers descriptions and comment bodies, so without it a hit whose title
|
|
28
31
|
// has nothing to do with the query reads like a broken search.
|
|
29
|
-
match: (0, format_1.formatCell)(t._matchField),
|
|
30
|
-
id: (0, format_1.formatCell)(t.id ?? t._id),
|
|
32
|
+
match: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(t._matchField)),
|
|
33
|
+
id: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(t.id ?? t._id)),
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
36
|
class SearchTasks extends base_command_1.BaseCommand {
|
|
34
|
-
static description = 'Search
|
|
37
|
+
static description = 'Search visible tasks by title, ref, or description';
|
|
35
38
|
static examples = [
|
|
39
|
+
'<%= config.bin %> tasks search "login bug"',
|
|
40
|
+
'<%= config.bin %> tasks search login --status backlog --status review --priority high',
|
|
36
41
|
'<%= config.bin %> search tasks --query "login bug"',
|
|
37
42
|
'<%= config.bin %> search tasks --query watcher --status backlog',
|
|
38
43
|
'<%= config.bin %> search tasks --query "cloud coding" --space "Dogfood Lab" --json',
|
|
39
44
|
];
|
|
45
|
+
static args = { query: core_1.Args.string({ description: 'Search term', ignoreStdin: true }) };
|
|
40
46
|
static flags = {
|
|
41
47
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
42
|
-
query: core_1.Flags.string({ char: 'q', description: 'Search query'
|
|
48
|
+
query: core_1.Flags.string({ char: 'q', description: 'Search query' }),
|
|
43
49
|
// Resolved by name via the BaseCommand parse hook, so `--space "Dogfood
|
|
44
50
|
// Lab"` works here exactly as it does on `tasks list`.
|
|
45
51
|
space: core_1.Flags.string({ description: 'Restrict to one space (id or title)' }),
|
|
46
|
-
|
|
52
|
+
goal: core_1.Flags.string({ description: 'Filter by goal ID' }),
|
|
53
|
+
project: core_1.Flags.string({ description: 'Filter by project ID' }),
|
|
54
|
+
status: core_1.Flags.string({ description: 'Filter by task status (repeatable, OR)', multiple: true }),
|
|
55
|
+
'status-type': core_1.Flags.string({
|
|
56
|
+
description: 'Filter by workflow type (repeatable, OR)',
|
|
57
|
+
options: ['backlog', 'unstarted', 'started', 'review', 'completed', 'cancelled', 'triage', 'failed', 'blocked', 'hidden'],
|
|
58
|
+
multiple: true,
|
|
59
|
+
}),
|
|
60
|
+
open: core_1.Flags.boolean({ description: 'Only open workflow types', exclusive: ['status-type', 'status'] }),
|
|
61
|
+
priority: core_1.Flags.string({ description: 'Filter by task priority', options: [...tasks_1.TASK_PRIORITIES] }),
|
|
62
|
+
tag: core_1.Flags.string({ description: 'Filter by tag (repeatable, AND)', multiple: true }),
|
|
63
|
+
'label-id': core_1.Flags.string({ description: 'Filter by label ID (repeatable, AND)', multiple: true }),
|
|
47
64
|
'include-archived': core_1.Flags.boolean({ description: 'Include archived tasks' }),
|
|
48
65
|
limit: core_1.Flags.integer({ description: 'Max results', default: 20 }),
|
|
66
|
+
cursor: core_1.Flags.string({ description: 'Continue from a previous page' }),
|
|
49
67
|
};
|
|
50
68
|
async run() {
|
|
51
69
|
this.requireAuth();
|
|
52
|
-
const { flags } = await this.parse(SearchTasks);
|
|
70
|
+
const { args, flags } = await this.parse(SearchTasks);
|
|
71
|
+
const query = (0, search_query_1.resolveSearchQuery)(this, args.query, flags.query, 'search tasks');
|
|
53
72
|
let response;
|
|
54
73
|
try {
|
|
55
74
|
response = await data_provider_1.dataService.listTasks({
|
|
56
|
-
q:
|
|
75
|
+
q: query,
|
|
57
76
|
...(flags.space ? { spaceId: flags.space } : {}),
|
|
58
|
-
...(flags.
|
|
77
|
+
...(flags.goal ? { goalId: flags.goal } : {}),
|
|
78
|
+
...(flags.project ? { projectId: flags.project } : {}),
|
|
79
|
+
...(flags.status?.length ? { status: flags.status.length === 1 ? flags.status[0] : flags.status } : {}),
|
|
80
|
+
...(flags.open
|
|
81
|
+
? { statusType: [...data_provider_1.TASK_WORKFLOW_TYPE_BANDS.open] }
|
|
82
|
+
: flags['status-type']?.length
|
|
83
|
+
? { statusType: (flags['status-type'].length === 1 ? flags['status-type'][0] : flags['status-type']) }
|
|
84
|
+
: {}),
|
|
85
|
+
...(flags.priority ? { priority: flags.priority } : {}),
|
|
86
|
+
...(flags.tag?.length ? { tags: flags.tag } : {}),
|
|
87
|
+
...(flags['label-id']?.length ? { labelIds: flags['label-id'] } : {}),
|
|
59
88
|
...(flags['include-archived'] ? { includeArchived: true } : {}),
|
|
60
89
|
limit: flags.limit,
|
|
90
|
+
cursor: flags.cursor,
|
|
61
91
|
});
|
|
62
92
|
}
|
|
63
93
|
catch (err) {
|
|
64
94
|
this.handleApiError(err);
|
|
65
95
|
}
|
|
96
|
+
if (!(0, search_display_1.isSearchListPage)(response)) {
|
|
97
|
+
this.failWithCliError({ message: 'The server returned an invalid Task search response. Retry or check server compatibility.',
|
|
98
|
+
code: 'SEARCH_INVALID_RESPONSE', exit: 1, retryable: true });
|
|
99
|
+
}
|
|
66
100
|
if (flags.json) {
|
|
67
101
|
this.log(JSON.stringify((0, web_url_1.withDataUrls)(this.cliConfig.baseURL, response, web_url_1.taskUrlFrom), null, 2));
|
|
68
102
|
return;
|
|
69
103
|
}
|
|
70
104
|
const items = (response?.data ?? []);
|
|
105
|
+
const meta = response;
|
|
106
|
+
if (meta.degraded || meta.incomplete || meta.truncated || meta.warnings?.length)
|
|
107
|
+
this.warn('Search may be incomplete. Inspect --json diagnostics.');
|
|
108
|
+
if (meta.search?.candidates_may_be_truncated)
|
|
109
|
+
this.warn('Search index candidates may be truncated; results may be incomplete.');
|
|
110
|
+
if (meta.search?.candidate_window_unknown)
|
|
111
|
+
this.warn('The search index result window could not be checked; results may be incomplete.');
|
|
112
|
+
if (meta.search?.comment_search_incomplete)
|
|
113
|
+
this.warn('Comment search was limited or unavailable; results may be incomplete.');
|
|
114
|
+
if (meta.search?.semantics === 'case_insensitive_substring')
|
|
115
|
+
this.warn('Search is using literal database matching; typo tolerance may be unavailable.');
|
|
71
116
|
if (items.length === 0) {
|
|
72
|
-
|
|
117
|
+
if (meta.search?.backend === 'not_run' && meta.search.semantics === 'filters_exclude_all') {
|
|
118
|
+
this.log('No tasks are eligible under the current access and filters. Broaden the filters to search more tasks.');
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
this.log(`No tasks matching ${JSON.stringify(query)} on this page. Try a distinctive word or broaden the filters.`);
|
|
122
|
+
}
|
|
123
|
+
if (meta.search?.semantics === 'exact_identifier') {
|
|
124
|
+
this.log('This query was treated as an exact Task reference. Search a phrase to find text mentioning it.');
|
|
125
|
+
}
|
|
126
|
+
if (meta.search?.backend === 'meilisearch' && meta.search.semantics !== 'exact_identifier') {
|
|
127
|
+
this.log('This index does not search Task comments. A comment-only match may not appear.');
|
|
128
|
+
}
|
|
129
|
+
if (meta.next_cursor)
|
|
130
|
+
this.log(`Next page: --cursor ${(0, search_display_1.shellSearchCursor)(meta.next_cursor)}`);
|
|
131
|
+
else if (meta.has_more)
|
|
132
|
+
this.warn('More results exist, but the server did not provide a cursor.');
|
|
73
133
|
return;
|
|
74
134
|
}
|
|
75
135
|
const rows = items.map((t) => ({
|
|
@@ -83,8 +143,12 @@ class SearchTasks extends base_command_1.BaseCommand {
|
|
|
83
143
|
{ key: 'priority', header: 'PRIORITY' },
|
|
84
144
|
{ key: 'match', header: 'MATCH' },
|
|
85
145
|
{ key: 'id', header: 'ID' },
|
|
86
|
-
{ key: 'url', header: 'URL',
|
|
146
|
+
{ key: 'url', header: 'URL', verbatim: true },
|
|
87
147
|
], (line) => this.log(line));
|
|
148
|
+
if (meta.next_cursor)
|
|
149
|
+
this.log(`Next page: --cursor ${(0, search_display_1.shellSearchCursor)(meta.next_cursor)}`);
|
|
150
|
+
else if (meta.has_more)
|
|
151
|
+
this.warn('More results exist, but the server did not provide a cursor.');
|
|
88
152
|
}
|
|
89
153
|
}
|
|
90
154
|
exports.default = SearchTasks;
|
|
@@ -44,8 +44,12 @@ class SearchTeams extends base_command_1.BaseCommand {
|
|
|
44
44
|
const items = Array.isArray(r)
|
|
45
45
|
? r
|
|
46
46
|
: (r?.data ?? []);
|
|
47
|
+
const meta = response;
|
|
48
|
+
const partial = Boolean(meta?.partial || meta?.semanticUnavailable);
|
|
49
|
+
if (partial)
|
|
50
|
+
this.warn('Team store search may be incomplete. Try again or narrow your query.');
|
|
47
51
|
if (items.length === 0) {
|
|
48
|
-
this.log('No teams found.');
|
|
52
|
+
this.log(partial ? 'No teams confirmed in the available search results.' : 'No teams found.');
|
|
49
53
|
return;
|
|
50
54
|
}
|
|
51
55
|
const rows = items.map((t) => ({
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
export { searchDisplayText } from '../../lib/search-display';
|
|
3
|
+
export declare function searchDiagnosticMessage(code: string): string;
|
|
4
|
+
/** Workspace search uses the same ACL-filtered index and result order as web. */
|
|
5
|
+
export default class SearchWorkspace extends BaseCommand {
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static args: {
|
|
9
|
+
query: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
10
|
+
};
|
|
11
|
+
static flags: {
|
|
12
|
+
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
type: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
cursor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
};
|
|
18
|
+
run(): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.searchDisplayText = void 0;
|
|
4
|
+
exports.searchDiagnosticMessage = searchDiagnosticMessage;
|
|
5
|
+
const core_1 = require("@oclif/core");
|
|
6
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
7
|
+
const base_command_1 = require("../../base-command");
|
|
8
|
+
const format_1 = require("../../lib/format");
|
|
9
|
+
const search_query_1 = require("../../lib/search-query");
|
|
10
|
+
const web_url_1 = require("../../lib/web-url");
|
|
11
|
+
const search_display_1 = require("../../lib/search-display");
|
|
12
|
+
var search_display_2 = require("../../lib/search-display");
|
|
13
|
+
Object.defineProperty(exports, "searchDisplayText", { enumerable: true, get: function () { return search_display_2.searchDisplayText; } });
|
|
14
|
+
function isSearchResponse(value) {
|
|
15
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
16
|
+
return false;
|
|
17
|
+
const response = value;
|
|
18
|
+
if (!Array.isArray(response.results) || (response.nextCursor !== null && (typeof response.nextCursor !== 'string' || !(0, search_display_1.isPrintableSearchCursor)(response.nextCursor))) ||
|
|
19
|
+
(response.diagnostics !== undefined && (!Array.isArray(response.diagnostics) || !response.diagnostics.every((item) => typeof item === 'string'))))
|
|
20
|
+
return false;
|
|
21
|
+
return response.results.every((item) => item && typeof item === 'object' && !Array.isArray(item) &&
|
|
22
|
+
['id', 'type', 'entityId', 'title', 'href'].every((field) => typeof item[field] === 'string') &&
|
|
23
|
+
item.href.startsWith('/') && !item.href.startsWith('//') && !item.href.includes('\\') &&
|
|
24
|
+
!/[\u0000-\u001f\u007f]/.test(item.href) &&
|
|
25
|
+
['identifier', 'excerpt'].every((field) => item[field] === undefined || typeof item[field] === 'string'));
|
|
26
|
+
}
|
|
27
|
+
function searchDiagnosticMessage(code) {
|
|
28
|
+
switch (code) {
|
|
29
|
+
case 'global_search_index_stale':
|
|
30
|
+
return 'The search index is catching up. Recent changes may be missing; retry shortly.';
|
|
31
|
+
case 'global_search_acl_unavailable':
|
|
32
|
+
return 'Access checks were unavailable. Results may be incomplete; retry shortly.';
|
|
33
|
+
case 'global_search_source_unavailable':
|
|
34
|
+
return 'Some current resources could not be checked. Results may be incomplete; retry shortly.';
|
|
35
|
+
case 'global_search_candidate_window_may_be_limited':
|
|
36
|
+
return 'This broad search may exceed the index result window. Narrow the query or select resource types.';
|
|
37
|
+
case 'global_search_candidate_window_unknown':
|
|
38
|
+
return 'The index result window could not be checked. Results may be incomplete; retry shortly.';
|
|
39
|
+
case 'global_search_invalid_candidate':
|
|
40
|
+
return 'The search index returned invalid candidates. Results may be incomplete; retry shortly.';
|
|
41
|
+
default:
|
|
42
|
+
return `Search may be incomplete (${(0, search_display_1.searchDisplayText)(code)}). Retry or inspect --json diagnostics.`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Workspace search uses the same ACL-filtered index and result order as web. */
|
|
46
|
+
class SearchWorkspace extends base_command_1.BaseCommand {
|
|
47
|
+
static description = 'Search supported resources in your workspace';
|
|
48
|
+
static examples = [
|
|
49
|
+
'<%= config.bin %> search workspace "deployment incident"',
|
|
50
|
+
'<%= config.bin %> search workspace pricing --type task --type wiki --json',
|
|
51
|
+
];
|
|
52
|
+
static args = { query: core_1.Args.string({ description: 'Search term', ignoreStdin: true }) };
|
|
53
|
+
static flags = {
|
|
54
|
+
query: core_1.Flags.string({ char: 'q', description: 'Search term' }),
|
|
55
|
+
type: core_1.Flags.string({ multiple: true, description: 'Limit to resource types (repeatable; for example task, space, wiki, message)' }),
|
|
56
|
+
limit: core_1.Flags.integer({ default: 25, min: 1, max: 50, description: 'Results per page' }),
|
|
57
|
+
cursor: core_1.Flags.string({ description: 'Continue from a previous page' }),
|
|
58
|
+
json: core_1.Flags.boolean({ description: 'Output structured results and diagnostics' }),
|
|
59
|
+
};
|
|
60
|
+
async run() {
|
|
61
|
+
this.requireAuth();
|
|
62
|
+
const { args, flags } = await this.parse(SearchWorkspace);
|
|
63
|
+
const query = (0, search_query_1.resolveSearchQuery)(this, args.query, flags.query, 'search workspace');
|
|
64
|
+
// Session-only tokens cannot authenticate to the JWT route. Never adopt an
|
|
65
|
+
// ambient human credential to turn this into broader authority.
|
|
66
|
+
if (this.resolvedCredential.token?.startsWith('agst_')) {
|
|
67
|
+
this.failWithCliError({
|
|
68
|
+
message: 'Workspace search is not available with a session-scoped credential. Ask the workspace owner to enable the delegated CLI surface for a new Agent session, or search in a signed-in human session. Do not substitute a personal login inside the Agent.',
|
|
69
|
+
code: 'GLOBAL_SEARCH_SESSION_UNSUPPORTED', exit: 2, retryable: false,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
let response;
|
|
73
|
+
try {
|
|
74
|
+
response = await data_provider_1.dataService.searchGlobal({ query, types: flags.type, limit: flags.limit, cursor: flags.cursor });
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
const code = (0, base_command_1.apiRefusal)(err).code;
|
|
78
|
+
if (code === 'SEARCH_WORKSPACE_REQUIRED' || code === 'SEARCH_WORKSPACE_FORBIDDEN') {
|
|
79
|
+
this.failWithCliError({
|
|
80
|
+
message: `Choose a workspace you belong to: run \`${this.config.bin} workspaces list\`, then \`${this.config.bin} workspaces use <workspace>\`, or pass --workspace <workspace-id>.`,
|
|
81
|
+
code, status: 403, exit: 3, retryable: false,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (code === 'INVALID_SEARCH_TYPE') {
|
|
85
|
+
const allowed = (0, base_command_1.apiRefusal)(err).body?.supportedTypes;
|
|
86
|
+
const types = Array.isArray(allowed)
|
|
87
|
+
? allowed.filter((type) => typeof type === 'string').map(search_display_1.searchDisplayText).filter(Boolean)
|
|
88
|
+
: [];
|
|
89
|
+
this.failWithCliError({
|
|
90
|
+
message: types.length
|
|
91
|
+
? `Unknown search type. Choose from: ${types.join(', ')}.`
|
|
92
|
+
: 'Unknown search type. Run the command without --type to search all supported types.',
|
|
93
|
+
code, status: 400, exit: 2, retryable: false,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
this.handleApiError(err);
|
|
97
|
+
}
|
|
98
|
+
if (!isSearchResponse(response) || (flags.cursor && response.nextCursor === flags.cursor)) {
|
|
99
|
+
this.failWithCliError({ message: 'The server returned an invalid workspace search response. Retry or check server compatibility.',
|
|
100
|
+
code: 'GLOBAL_SEARCH_INVALID_RESPONSE', exit: 1, retryable: true });
|
|
101
|
+
}
|
|
102
|
+
const results = response.results.map((item) => ({
|
|
103
|
+
...item,
|
|
104
|
+
url: `${(0, web_url_1.webOrigin)(this.cliConfig.baseURL)}${item.href}`,
|
|
105
|
+
}));
|
|
106
|
+
if (flags.json) {
|
|
107
|
+
this.log(JSON.stringify({ ...response, results }, null, 2));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
for (const diagnostic of new Set(response.diagnostics || []))
|
|
111
|
+
this.warn(searchDiagnosticMessage(diagnostic));
|
|
112
|
+
if (results.length) {
|
|
113
|
+
(0, format_1.renderTable)(results.map((item) => ({ type: (0, search_display_1.searchDisplayText)(item.type), id: (0, search_display_1.searchDisplayText)(item.identifier || item.entityId), title: (0, search_display_1.searchDisplayText)(item.title), excerpt: (0, search_display_1.searchDisplayText)(item.excerpt || ''), url: (0, search_display_1.searchDisplayText)(item.url || '-') })), [
|
|
114
|
+
{ key: 'type', header: 'TYPE' }, { key: 'id', header: 'ID' },
|
|
115
|
+
{ key: 'title', header: 'TITLE', maxWidth: 45 }, { key: 'excerpt', header: 'EXCERPT', maxWidth: 60 },
|
|
116
|
+
{ key: 'url', header: 'URL', verbatim: true },
|
|
117
|
+
], (line) => this.log(line));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.log('No results in this page of supported workspace resources.');
|
|
121
|
+
}
|
|
122
|
+
if (response.nextCursor)
|
|
123
|
+
this.log(`Next page: --cursor ${(0, search_display_1.shellSearchCursor)(response.nextCursor)}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
exports.default = SearchWorkspace;
|
|
@@ -16,6 +16,7 @@ export default class SkillsBrowse extends BaseCommand {
|
|
|
16
16
|
category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
17
|
sort: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
18
|
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
cursor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
20
|
};
|
|
20
21
|
run(): Promise<void>;
|
|
21
22
|
}
|
|
@@ -7,6 +7,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
7
7
|
const base_command_1 = require("../../base-command");
|
|
8
8
|
const format_1 = require("../../lib/format");
|
|
9
9
|
const usd_micros_1 = require("../../lib/usd-micros");
|
|
10
|
+
const skill_store_pagination_1 = require("../../lib/skill-store-pagination");
|
|
10
11
|
function skillBrowseDescription(skill) {
|
|
11
12
|
const description = String(skill.description ?? '').trim();
|
|
12
13
|
if (description && description !== '>' && description !== '|')
|
|
@@ -43,6 +44,7 @@ class SkillsBrowse extends base_command_1.BaseCommand {
|
|
|
43
44
|
options: ['newest', 'popular', 'rating'],
|
|
44
45
|
}),
|
|
45
46
|
limit: core_1.Flags.integer({ description: 'Maximum number of results', default: 20 }),
|
|
47
|
+
cursor: core_1.Flags.string({ description: 'Continue from a previous page' }),
|
|
46
48
|
};
|
|
47
49
|
async run() {
|
|
48
50
|
this.requireAuth();
|
|
@@ -59,6 +61,7 @@ class SkillsBrowse extends base_command_1.BaseCommand {
|
|
|
59
61
|
category: flags.category,
|
|
60
62
|
sort: flags.sort ? sortMap[flags.sort] : undefined,
|
|
61
63
|
limit: flags.limit,
|
|
64
|
+
cursor: flags.cursor,
|
|
62
65
|
});
|
|
63
66
|
}
|
|
64
67
|
catch (err) {
|
|
@@ -71,7 +74,10 @@ class SkillsBrowse extends base_command_1.BaseCommand {
|
|
|
71
74
|
const r = response;
|
|
72
75
|
const items = Array.isArray(r) ? r : (r?.data ?? []);
|
|
73
76
|
if (items.length === 0) {
|
|
74
|
-
this.log(
|
|
77
|
+
this.log((0, skill_store_pagination_1.skillStorePageState)(response, flags.cursor).hasMore
|
|
78
|
+
? 'No skills on this page. More candidates remain.'
|
|
79
|
+
: 'No skills found.');
|
|
80
|
+
(0, skill_store_pagination_1.reportSkillStorePage)(response, flags.cursor, (message) => this.log(message), (message) => this.warn(message));
|
|
75
81
|
return;
|
|
76
82
|
}
|
|
77
83
|
const rows = items.map(skillBrowseRow);
|
|
@@ -83,6 +89,7 @@ class SkillsBrowse extends base_command_1.BaseCommand {
|
|
|
83
89
|
{ key: 'installs', header: 'INSTALLS' },
|
|
84
90
|
{ key: 'description', header: 'DESCRIPTION', maxWidth: 60 },
|
|
85
91
|
], (line) => this.log(line));
|
|
92
|
+
(0, skill_store_pagination_1.reportSkillStorePage)(response, flags.cursor, (message) => this.log(message), (message) => this.warn(message));
|
|
86
93
|
}
|
|
87
94
|
}
|
|
88
95
|
exports.default = SkillsBrowse;
|
|
@@ -17,6 +17,7 @@ export default class SkillsSearch extends BaseCommand {
|
|
|
17
17
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
18
|
category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
19
|
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
cursor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
21
|
};
|
|
21
22
|
run(): Promise<void>;
|
|
22
23
|
}
|
|
@@ -6,6 +6,7 @@ const base_command_1 = require("../../base-command");
|
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
7
|
const search_query_1 = require("../../lib/search-query");
|
|
8
8
|
const usd_micros_1 = require("../../lib/usd-micros");
|
|
9
|
+
const skill_store_pagination_1 = require("../../lib/skill-store-pagination");
|
|
9
10
|
class SkillsSearch extends base_command_1.BaseCommand {
|
|
10
11
|
static description = 'Search skills in the skrr store by keyword (same as `search skills`)';
|
|
11
12
|
static examples = [
|
|
@@ -37,6 +38,7 @@ class SkillsSearch extends base_command_1.BaseCommand {
|
|
|
37
38
|
query: core_1.Flags.string({ char: 'q', description: 'Search query' }),
|
|
38
39
|
category: core_1.Flags.string({ description: 'Filter by category' }),
|
|
39
40
|
limit: core_1.Flags.integer({ description: 'Maximum number of results', default: 20 }),
|
|
41
|
+
cursor: core_1.Flags.string({ description: 'Continue from a previous page' }),
|
|
40
42
|
};
|
|
41
43
|
async run() {
|
|
42
44
|
this.requireAuth();
|
|
@@ -48,6 +50,7 @@ class SkillsSearch extends base_command_1.BaseCommand {
|
|
|
48
50
|
q: query,
|
|
49
51
|
category: flags.category,
|
|
50
52
|
limit: flags.limit,
|
|
53
|
+
cursor: flags.cursor,
|
|
51
54
|
});
|
|
52
55
|
}
|
|
53
56
|
catch (err) {
|
|
@@ -59,8 +62,15 @@ class SkillsSearch extends base_command_1.BaseCommand {
|
|
|
59
62
|
}
|
|
60
63
|
const r = response;
|
|
61
64
|
const items = Array.isArray(r) ? r : (r?.data ?? []);
|
|
65
|
+
const incomplete = (0, skill_store_pagination_1.skillStoreSearchIncomplete)(response);
|
|
66
|
+
if (incomplete)
|
|
67
|
+
this.warn('Skill store search may be incomplete. Try again or narrow your query.');
|
|
62
68
|
if (items.length === 0) {
|
|
63
|
-
this.log(
|
|
69
|
+
this.log((0, skill_store_pagination_1.skillStorePageState)(response, flags.cursor).hasMore
|
|
70
|
+
? 'No skills matched on this page. More candidates remain.'
|
|
71
|
+
: incomplete ? 'No skills confirmed in the available search results.'
|
|
72
|
+
: `No skills found matching '${query}'.`);
|
|
73
|
+
(0, skill_store_pagination_1.reportSkillStorePage)(response, flags.cursor, (message) => this.log(message), (message) => this.warn(message));
|
|
64
74
|
return;
|
|
65
75
|
}
|
|
66
76
|
const rows = items.map((s) => ({
|
|
@@ -79,6 +89,7 @@ class SkillsSearch extends base_command_1.BaseCommand {
|
|
|
79
89
|
{ key: 'installs', header: 'INSTALLS' },
|
|
80
90
|
{ key: 'description', header: 'DESCRIPTION', maxWidth: 60 },
|
|
81
91
|
], (line) => this.log(line));
|
|
92
|
+
(0, skill_store_pagination_1.reportSkillStorePage)(response, flags.cursor, (message) => this.log(message), (message) => this.warn(message));
|
|
82
93
|
}
|
|
83
94
|
}
|
|
84
95
|
exports.default = SkillsSearch;
|
|
@@ -25,6 +25,7 @@ export default class SpacesList extends BaseCommand {
|
|
|
25
25
|
status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
26
26
|
label: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
27
|
'include-archived': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
28
|
+
'archived-only': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
28
29
|
q: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
29
30
|
match: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
30
31
|
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -15,7 +15,7 @@ function noSpacesMatchedMessage(q, bin = 'skrr', mode = 'fuzzy') {
|
|
|
15
15
|
: mode === 'phrase'
|
|
16
16
|
? 'Phrase matches use a literal case-insensitive substring; word order matters.'
|
|
17
17
|
: 'Fuzzy discovery can use tokenized, typo-tolerant search or a substring fallback.';
|
|
18
|
-
return (`No spaces matched ${JSON.stringify(q)}.\n` +
|
|
18
|
+
return (`No spaces matched ${JSON.stringify(q)} on this page.\n` +
|
|
19
19
|
` → ${explanation} Fields: title, description and identifier.\n` +
|
|
20
20
|
` → retry with one distinctive word, or list them all with \`${bin} spaces list\`.`);
|
|
21
21
|
}
|
|
@@ -45,6 +45,7 @@ class SpacesList extends base_command_1.BaseCommand {
|
|
|
45
45
|
'<%= config.bin %> spaces list --q "always on" --match phrase',
|
|
46
46
|
'<%= config.bin %> spaces list --q "My workspace" --match exact --json',
|
|
47
47
|
'<%= config.bin %> spaces list --include-archived --json',
|
|
48
|
+
'<%= config.bin %> spaces list --archived-only --json',
|
|
48
49
|
'<%= config.bin %> spaces list --compact --json',
|
|
49
50
|
'<%= config.bin %> spaces list --fields id,identifier,title --ndjson',
|
|
50
51
|
];
|
|
@@ -62,7 +63,8 @@ class SpacesList extends base_command_1.BaseCommand {
|
|
|
62
63
|
description: 'Filter by label ID (repeatable). Multiple labels AND together — a space must carry all of them.',
|
|
63
64
|
multiple: true,
|
|
64
65
|
}),
|
|
65
|
-
'include-archived': core_1.Flags.boolean({ description: 'Include archived spaces' }),
|
|
66
|
+
'include-archived': core_1.Flags.boolean({ description: 'Include archived spaces', exclusive: ['archived-only'] }),
|
|
67
|
+
'archived-only': core_1.Flags.boolean({ description: 'List only archived spaces', exclusive: ['include-archived'] }),
|
|
66
68
|
q: core_1.Flags.string({
|
|
67
69
|
description: 'Search title, description, or identifier. Default fuzzy discovery may tokenize and tolerate typos; ' +
|
|
68
70
|
'use --match phrase for a literal substring or --match exact for whole-field equality. Maximum 200 characters.',
|
|
@@ -86,6 +88,7 @@ class SpacesList extends base_command_1.BaseCommand {
|
|
|
86
88
|
...(flags.label?.length ? { labelIds: flags.label } : {}),
|
|
87
89
|
...(flags.q ? { q: flags.q, ...(flags.match ? { match: flags.match } : {}) } : {}),
|
|
88
90
|
includeArchived: flags['include-archived'],
|
|
91
|
+
archivedOnly: flags['archived-only'],
|
|
89
92
|
limit: flags.limit,
|
|
90
93
|
cursor: flags.cursor,
|
|
91
94
|
});
|
|
@@ -107,6 +110,8 @@ class SpacesList extends base_command_1.BaseCommand {
|
|
|
107
110
|
}
|
|
108
111
|
const r = response;
|
|
109
112
|
const items = r?.data ?? [];
|
|
113
|
+
if (flags.q && (r?.degraded || r?.warnings?.length))
|
|
114
|
+
this.warn('Search may be incomplete. Inspect --json diagnostics.');
|
|
110
115
|
if (r?.search) {
|
|
111
116
|
this.log(`Search: ${r.search.mode}; ${r.search.semantics}; backend=${r.search.backend}.`);
|
|
112
117
|
if (r.search.candidates_may_be_truncated) {
|
|
@@ -116,7 +121,11 @@ class SpacesList extends base_command_1.BaseCommand {
|
|
|
116
121
|
if (items.length === 0) {
|
|
117
122
|
this.log(flags.q
|
|
118
123
|
? noSpacesMatchedMessage(flags.q, this.config.bin, r?.search?.mode ?? 'fuzzy')
|
|
119
|
-
:
|
|
124
|
+
: flags['archived-only'] || flags.status || flags.label?.length || r?.next_cursor
|
|
125
|
+
? 'No spaces on this page under the current filters.'
|
|
126
|
+
: noSpacesEmptyMessage(this.config.bin));
|
|
127
|
+
if (r?.next_cursor)
|
|
128
|
+
this.log(`Next page: --cursor ${r.next_cursor}`);
|
|
120
129
|
return;
|
|
121
130
|
}
|
|
122
131
|
const rows = items.map((s) => ({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../search/spaces';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
// Both spellings share one implementation and result contract.
|
|
8
|
+
var spaces_1 = require("../search/spaces");
|
|
9
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(spaces_1).default; } });
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
export default class StoreGalleryAdmissionsApprove extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static args: {
|
|
5
|
+
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static flags: {
|
|
8
|
+
kind: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
revision: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
digest: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'images-reviewed': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
note: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../../base-command");
|
|
6
|
+
class StoreGalleryAdmissionsApprove extends base_command_1.BaseCommand {
|
|
7
|
+
static description = 'Approve the exact frozen gallery revision inspected by a curator';
|
|
8
|
+
static args = { id: core_1.Args.string({ description: 'Gallery review request ID', required: true, ignoreStdin: true }) };
|
|
9
|
+
static flags = {
|
|
10
|
+
kind: core_1.Flags.string({ options: ['action', 'service'], required: true }),
|
|
11
|
+
revision: core_1.Flags.integer({ required: true, min: 0, description: 'Revision from the review details' }),
|
|
12
|
+
digest: core_1.Flags.string({ required: true, description: 'Digest from the review details' }),
|
|
13
|
+
'images-reviewed': core_1.Flags.boolean({ description: 'Confirm you inspected every image in this frozen revision' }),
|
|
14
|
+
note: core_1.Flags.string({ description: 'Decision note' }),
|
|
15
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
16
|
+
};
|
|
17
|
+
async run() {
|
|
18
|
+
this.requireAuth();
|
|
19
|
+
const { args, flags } = await this.parse(StoreGalleryAdmissionsApprove);
|
|
20
|
+
try {
|
|
21
|
+
if (!flags['images-reviewed'])
|
|
22
|
+
throw new Error('Inspect every image, then pass --images-reviewed to confirm.');
|
|
23
|
+
const result = await data_provider_1.dataService.approveStoreGalleryAdmission(flags.kind, args.id, {
|
|
24
|
+
revision: flags.revision, digest: flags.digest, imagesReviewed: true, ...(flags.note ? { note: flags.note } : {}),
|
|
25
|
+
});
|
|
26
|
+
if (flags.json)
|
|
27
|
+
this.log(JSON.stringify(result, null, 2));
|
|
28
|
+
else
|
|
29
|
+
this.log(`Approved gallery revision ${flags.revision}.`);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
this.handleApiError(err);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.default = StoreGalleryAdmissionsApprove;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
export default class StoreGalleryAdmissionsList extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static flags: {
|
|
5
|
+
state: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../../base-command");
|
|
6
|
+
const list_output_1 = require("../../../lib/list-output");
|
|
7
|
+
class StoreGalleryAdmissionsList extends base_command_1.BaseCommand {
|
|
8
|
+
static description = 'List frozen Store gallery revisions awaiting curator review';
|
|
9
|
+
static flags = {
|
|
10
|
+
state: core_1.Flags.string({ options: ['pending_review', 'refused'], default: 'pending_review', description: 'Review state to list' }),
|
|
11
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
this.requireAuth();
|
|
15
|
+
const { flags } = await this.parse(StoreGalleryAdmissionsList);
|
|
16
|
+
try {
|
|
17
|
+
const reviews = [];
|
|
18
|
+
const seen = new Set();
|
|
19
|
+
let cursor;
|
|
20
|
+
do {
|
|
21
|
+
const page = await data_provider_1.dataService.getStoreGalleryAdmissions({
|
|
22
|
+
state: flags.state,
|
|
23
|
+
...(cursor ? { cursor } : {}),
|
|
24
|
+
});
|
|
25
|
+
reviews.push(...page.reviews);
|
|
26
|
+
cursor = page.nextCursor || undefined;
|
|
27
|
+
if (cursor && seen.has(cursor))
|
|
28
|
+
throw new Error('Gallery admission queue returned a repeated cursor');
|
|
29
|
+
if (cursor)
|
|
30
|
+
seen.add(cursor);
|
|
31
|
+
} while (cursor);
|
|
32
|
+
if (flags.json) {
|
|
33
|
+
this.printJsonResult((0, list_output_1.listResult)({ data: reviews, reviews, nextCursor: null }));
|
|
34
|
+
}
|
|
35
|
+
else if (!reviews.length) {
|
|
36
|
+
this.log(flags.state === 'refused' ? 'No refused gallery reviews.' : 'Nothing waiting for gallery review.');
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
for (const review of reviews) {
|
|
40
|
+
this.log(`${review.entityType}\t${review.id}\t${review.entityId}\trevision ${review.revision}\t${review.digest}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
this.handleApiError(err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.default = StoreGalleryAdmissionsList;
|