@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
package/dist/base-command.js
CHANGED
|
@@ -33,6 +33,7 @@ const json_mode_1 = require("./lib/json-mode");
|
|
|
33
33
|
const failed_lookup_1 = require("./lib/failed-lookup");
|
|
34
34
|
const internal_id_1 = require("./lib/internal-id");
|
|
35
35
|
const http_error_1 = require("./lib/http-error");
|
|
36
|
+
const api_error_reason_1 = require("./lib/api-error-reason");
|
|
36
37
|
const guide_pointer_1 = require("./lib/guide-pointer");
|
|
37
38
|
// Re-exported from its home in `lib/keychain`, beside the other profile
|
|
38
39
|
// functions. It lived here while `init()` was its only caller; a lib module
|
|
@@ -1722,7 +1723,7 @@ class BaseCommand extends core_1.Command {
|
|
|
1722
1723
|
code: bodyCode || 'FORBIDDEN',
|
|
1723
1724
|
status: e.status,
|
|
1724
1725
|
exit: 3,
|
|
1725
|
-
retryable: edgeRefusal,
|
|
1726
|
+
retryable: typeof body?.retryable === 'boolean' ? body.retryable : edgeRefusal,
|
|
1726
1727
|
});
|
|
1727
1728
|
}
|
|
1728
1729
|
else if (e.status === 404) {
|
|
@@ -2229,6 +2230,12 @@ function refusalCodeOf(body) {
|
|
|
2229
2230
|
const direct = stringProp(body ?? null, 'code') || stringProp(body ?? null, 'errorType');
|
|
2230
2231
|
if (direct)
|
|
2231
2232
|
return direct;
|
|
2233
|
+
// Session-scoped Task routes return `{ok:false, reason}`. This is an
|
|
2234
|
+
// application refusal, not a bodyless edge error. Preserve its spelling so
|
|
2235
|
+
// an Agent can distinguish a stale session from a Task authorization stop.
|
|
2236
|
+
const reason = (0, api_error_reason_1.reasonOnlyCode)(body);
|
|
2237
|
+
if (reason)
|
|
2238
|
+
return reason;
|
|
2232
2239
|
const legacy = stringProp(body ?? null, 'error');
|
|
2233
2240
|
return legacy && LEGACY_ERROR_FIELD_CODE.test(legacy) ? legacy.toUpperCase() : undefined;
|
|
2234
2241
|
}
|
|
@@ -2696,7 +2703,9 @@ function errorBodyMessage(body) {
|
|
|
2696
2703
|
const nested = record.error && typeof record.error === 'object' && !Array.isArray(record.error)
|
|
2697
2704
|
? record.error.message
|
|
2698
2705
|
: undefined;
|
|
2699
|
-
|
|
2706
|
+
const reason = (0, api_error_reason_1.reasonOnlyCode)(record);
|
|
2707
|
+
return text(record.message) ?? text(record.error) ?? text(nested) ??
|
|
2708
|
+
(reason ? `Request refused: ${reason}` : undefined);
|
|
2700
2709
|
}
|
|
2701
2710
|
/**
|
|
2702
2711
|
* The `details` of a CLI error envelope, in ONE shape. The server's refusal body becomes the
|
|
@@ -37,6 +37,10 @@ class ActionsPublish extends base_command_1.BaseCommand {
|
|
|
37
37
|
this.log(JSON.stringify(response, null, 2));
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
+
if (response.requiresReview) {
|
|
41
|
+
this.log('Action submitted for review. It will be listed after approval.');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
40
44
|
this.log(flags.unpublish ? 'Unpublished action listing:' : 'Published action listing:');
|
|
41
45
|
(0, action_listings_1.renderActionListing)(response.listing, (line) => this.log(line));
|
|
42
46
|
}
|
|
@@ -14,6 +14,7 @@ export default class AgentMessageContext extends BaseCommand {
|
|
|
14
14
|
agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
15
|
task: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
16
|
run: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
18
|
};
|
|
18
19
|
run(): Promise<void>;
|
|
19
20
|
}
|
|
@@ -26,8 +26,9 @@ class AgentMessageContext extends base_command_1.BaseCommand {
|
|
|
26
26
|
run: core_1.Flags.string({
|
|
27
27
|
description: 'Optional run context to narrow recent updates (refused inside a daemon session — the session path is already bound to its own run)',
|
|
28
28
|
}),
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
json: core_1.Flags.boolean({
|
|
30
|
+
description: 'Accepted for consistency; this command always outputs JSON',
|
|
31
|
+
}),
|
|
31
32
|
};
|
|
32
33
|
async run() {
|
|
33
34
|
const { args, flags } = await this.parse(AgentMessageContext);
|
|
@@ -161,7 +161,7 @@ class AgentMessageSend extends base_command_1.BaseCommand {
|
|
|
161
161
|
allowNo: true,
|
|
162
162
|
}),
|
|
163
163
|
task: core_1.Flags.string({
|
|
164
|
-
description: 'Manual
|
|
164
|
+
description: 'Manual task context (ID, reference, or title); managed sessions derive it server-side',
|
|
165
165
|
}),
|
|
166
166
|
space: core_1.Flags.string({ description: 'Optional space context for manual tools' }),
|
|
167
167
|
goal: core_1.Flags.string({ description: 'Optional goal context for manual tools' }),
|
|
@@ -234,6 +234,11 @@ class AgentMessageSend extends base_command_1.BaseCommand {
|
|
|
234
234
|
retryable: false,
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
|
+
// Manual task context accepts the same titles and references as task
|
|
238
|
+
// commands. Managed sessions must leave the claim-derived context alone.
|
|
239
|
+
if (!sessionContext && payload.destination.kind === 'app_owner_dm' && payload.context?.taskId) {
|
|
240
|
+
payload.context.taskId = await this.resolveTaskReference(payload.context.taskId);
|
|
241
|
+
}
|
|
237
242
|
const segmentationAdvisory = messageSegmentationAdvisory({
|
|
238
243
|
destination: payload.destination,
|
|
239
244
|
text: payload.content.text,
|
|
@@ -83,8 +83,12 @@ class SearchAgents extends base_command_1.BaseCommand {
|
|
|
83
83
|
const items = Array.isArray(r)
|
|
84
84
|
? r
|
|
85
85
|
: (r?.data ?? []);
|
|
86
|
+
const meta = response;
|
|
87
|
+
const partial = Boolean(meta?.partial || meta?.semanticUnavailable);
|
|
88
|
+
if (partial)
|
|
89
|
+
this.warn('Agent store search may be incomplete. Try again or narrow your query.');
|
|
86
90
|
if (items.length === 0) {
|
|
87
|
-
this.log('No agents found.');
|
|
91
|
+
this.log(partial ? 'No agents confirmed in the available search results.' : 'No agents found.');
|
|
88
92
|
return;
|
|
89
93
|
}
|
|
90
94
|
const rows = items.map((item) => ({
|
|
@@ -7,6 +7,8 @@ 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 web_url_1 = require("../../lib/web-url");
|
|
10
|
+
const skill_store_pagination_1 = require("../../lib/skill-store-pagination");
|
|
11
|
+
const search_display_1 = require("../../lib/search-display");
|
|
10
12
|
/**
|
|
11
13
|
* One store document → one row of the merged agent/skill/team table.
|
|
12
14
|
*
|
|
@@ -47,9 +49,9 @@ function storeSearchRow(type, doc) {
|
|
|
47
49
|
// `OSK-S-12`) — that is what a person types back into `tasks show` /
|
|
48
50
|
// `spaces show`, and the UUID is still one `--json` away. Spaces created
|
|
49
51
|
// before refs existed fall through to the UUID until backfilled.
|
|
50
|
-
id: (0, format_1.formatCell)(doc.identifier ?? doc.id ?? doc._id ?? doc.slug),
|
|
51
|
-
name: (0, format_1.formatCell)(doc.name ?? doc.title),
|
|
52
|
-
description: plainDescription(doc.description),
|
|
52
|
+
id: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(doc.identifier ?? doc.id ?? doc._id ?? doc.slug)),
|
|
53
|
+
name: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(doc.name ?? doc.title)),
|
|
54
|
+
description: (0, search_display_1.searchDisplayText)(plainDescription(doc.description)),
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
// No single `getStoreAll` exists in data-service — compose by fanning out to
|
|
@@ -73,24 +75,44 @@ class SearchAll extends base_command_1.BaseCommand {
|
|
|
73
75
|
async run() {
|
|
74
76
|
this.requireAuth();
|
|
75
77
|
const { flags } = await this.parse(SearchAll);
|
|
78
|
+
const validBucket = (value) => {
|
|
79
|
+
const rows = Array.isArray(value) ? value
|
|
80
|
+
: value && typeof value === 'object' ? value.data : undefined;
|
|
81
|
+
return Array.isArray(rows) && rows.every((row) => row && typeof row === 'object' && !Array.isArray(row));
|
|
82
|
+
};
|
|
76
83
|
const items = (b) => Array.isArray(b) ? b : (b?.data ?? []);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
]
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
const names = ['agents', 'skills', 'teams', 'tasks', 'spaces'];
|
|
85
|
+
const outcomes = await Promise.allSettled([
|
|
86
|
+
data_provider_1.dataService.getStoreAgents({ q: flags.query, limit: flags.limit }),
|
|
87
|
+
data_provider_1.dataService.getStoreSkills({ q: flags.query, limit: flags.limit }),
|
|
88
|
+
data_provider_1.dataService.getStoreTeams({ q: flags.query, limit: flags.limit }),
|
|
89
|
+
data_provider_1.dataService.listTasks({ q: flags.query, limit: flags.limit }),
|
|
90
|
+
data_provider_1.dataService.listSpaces({ q: flags.query, limit: flags.limit }),
|
|
91
|
+
]);
|
|
92
|
+
const [agents, skills, teams, tasks, spaces] = outcomes.map((outcome) => outcome.status === 'fulfilled' && validBucket(outcome.value) ? outcome.value : undefined);
|
|
93
|
+
const failed = names.filter((_, index) => outcomes[index].status === 'rejected' ||
|
|
94
|
+
(outcomes[index].status === 'fulfilled' && !validBucket(outcomes[index].value)));
|
|
95
|
+
const pageInfo = Object.fromEntries(names.map((name, index) => {
|
|
96
|
+
const outcome = outcomes[index];
|
|
97
|
+
const page = outcome.status === 'fulfilled' && !Array.isArray(outcome.value)
|
|
98
|
+
? outcome.value
|
|
99
|
+
: undefined;
|
|
100
|
+
const skillPage = name === 'skills' && outcome.status === 'fulfilled'
|
|
101
|
+
? (0, skill_store_pagination_1.skillStorePageState)(outcome.value)
|
|
102
|
+
: undefined;
|
|
103
|
+
return [name, failed.includes(name) ? { status: 'failed', ...(outcome.status === 'fulfilled' ? { reason: 'invalid_response' } : {}) } : {
|
|
104
|
+
status: 'ok', ...(page?.has_more !== undefined ? { has_more: page.has_more } : {}),
|
|
105
|
+
...(skillPage?.nextCursor ? { next_cursor: skillPage.nextCursor } : page?.next_cursor ? { next_cursor: page.next_cursor } : {}),
|
|
106
|
+
...(skillPage?.invalidCursor ? { incomplete: true } : {}),
|
|
107
|
+
...(page?.warnings ? { warnings: page.warnings } : {}),
|
|
108
|
+
...(page?.degraded ? { degraded: true } : {}),
|
|
109
|
+
...(page?.incomplete ? { incomplete: true } : {}),
|
|
110
|
+
...(page?.truncated ? { truncated: true } : {}),
|
|
111
|
+
...(page?.partial ? { partial: true } : {}),
|
|
112
|
+
...(page?.semanticUnavailable ? { semanticUnavailable: true } : {}),
|
|
113
|
+
...(page?.search ? { search: page.search } : {}),
|
|
114
|
+
}];
|
|
115
|
+
}));
|
|
94
116
|
if (flags.json) {
|
|
95
117
|
this.log(JSON.stringify({
|
|
96
118
|
agents: items(agents).map((agent) => ({
|
|
@@ -107,9 +129,30 @@ class SearchAll extends base_command_1.BaseCommand {
|
|
|
107
129
|
...space,
|
|
108
130
|
url: (0, web_url_1.spaceUrlFrom)(this.cliConfig.baseURL, space),
|
|
109
131
|
})),
|
|
132
|
+
sources: pageInfo,
|
|
110
133
|
}, null, 2));
|
|
134
|
+
if (failed.length)
|
|
135
|
+
this.exit(1);
|
|
111
136
|
return;
|
|
112
137
|
}
|
|
138
|
+
if (failed.length)
|
|
139
|
+
this.warn(`Some sources failed: ${failed.join(', ')}. Results are incomplete; retry those searches.`);
|
|
140
|
+
for (const [name, info] of Object.entries(pageInfo)) {
|
|
141
|
+
if (('degraded' in info && info.degraded) || ('incomplete' in info && info.incomplete) ||
|
|
142
|
+
('truncated' in info && info.truncated) || ('partial' in info && info.partial) ||
|
|
143
|
+
('semanticUnavailable' in info && info.semanticUnavailable) || ('warnings' in info && info.warnings?.length) ||
|
|
144
|
+
('search' in info && (info.search?.candidates_may_be_truncated || info.search?.candidate_window_unknown || info.search?.comment_search_incomplete))) {
|
|
145
|
+
this.warn(`${name} search may be incomplete; inspect --json diagnostics.`);
|
|
146
|
+
}
|
|
147
|
+
if ('has_more' in info && info.has_more) {
|
|
148
|
+
if (name === 'skills' && 'next_cursor' in info && info.next_cursor) {
|
|
149
|
+
this.warn(`skills has more candidates. Repeat the query with search skills --cursor ${info.next_cursor}.`);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
this.warn(`${name} has more results. Use its dedicated search command to page through them.`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
113
156
|
// Your own work first — when both a task and a store agent mention the
|
|
114
157
|
// query, the task is almost always what you were looking for.
|
|
115
158
|
const rows = [
|
|
@@ -129,7 +172,14 @@ class SearchAll extends base_command_1.BaseCommand {
|
|
|
129
172
|
...items(teams).map((t) => storeSearchRow('team', t)),
|
|
130
173
|
];
|
|
131
174
|
if (rows.length === 0) {
|
|
132
|
-
|
|
175
|
+
const hasMore = Object.values(pageInfo).some((info) => 'has_more' in info && info.has_more);
|
|
176
|
+
const incomplete = Object.values(pageInfo).some((info) => ('degraded' in info && info.degraded) || ('incomplete' in info && info.incomplete) ||
|
|
177
|
+
('truncated' in info && info.truncated) || ('partial' in info && info.partial) ||
|
|
178
|
+
('semanticUnavailable' in info && info.semanticUnavailable) || ('warnings' in info && info.warnings?.length) ||
|
|
179
|
+
('search' in info && (info.search?.candidates_may_be_truncated || info.search?.candidate_window_unknown || info.search?.comment_search_incomplete)));
|
|
180
|
+
this.log(failed.length ? 'No results from the sources that answered.' : hasMore ? 'No results on these pages. More candidates remain.' : incomplete ? 'No confirmed results. Some sources may be incomplete.' : 'No results.');
|
|
181
|
+
if (failed.length)
|
|
182
|
+
this.exit(1);
|
|
133
183
|
return;
|
|
134
184
|
}
|
|
135
185
|
(0, format_1.renderTable)(rows, [
|
|
@@ -137,8 +187,10 @@ class SearchAll extends base_command_1.BaseCommand {
|
|
|
137
187
|
{ key: 'id', header: 'ID', verbatim: true },
|
|
138
188
|
{ key: 'name', header: 'NAME', maxWidth: 30 },
|
|
139
189
|
{ key: 'description', header: 'DESCRIPTION', maxWidth: 60 },
|
|
140
|
-
{ key: 'url', header: 'URL',
|
|
190
|
+
{ key: 'url', header: 'URL', verbatim: true },
|
|
141
191
|
], (line) => this.log(line));
|
|
192
|
+
if (failed.length)
|
|
193
|
+
this.exit(1);
|
|
142
194
|
}
|
|
143
195
|
}
|
|
144
196
|
exports.default = SearchAll;
|
|
@@ -17,6 +17,7 @@ export default class SearchSkills 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
|
}
|
|
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
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
|
+
const skill_store_pagination_1 = require("../../lib/skill-store-pagination");
|
|
8
9
|
class SearchSkills extends base_command_1.BaseCommand {
|
|
9
10
|
static description = 'Search skills in the skrr store by keyword (same as `skills search`)';
|
|
10
11
|
static examples = [
|
|
@@ -43,6 +44,7 @@ class SearchSkills extends base_command_1.BaseCommand {
|
|
|
43
44
|
description: 'Maximum number of results',
|
|
44
45
|
default: 20,
|
|
45
46
|
}),
|
|
47
|
+
cursor: core_1.Flags.string({ description: 'Continue from a previous page' }),
|
|
46
48
|
};
|
|
47
49
|
async run() {
|
|
48
50
|
this.requireAuth();
|
|
@@ -54,6 +56,7 @@ class SearchSkills extends base_command_1.BaseCommand {
|
|
|
54
56
|
q: query,
|
|
55
57
|
category: flags.category,
|
|
56
58
|
limit: flags.limit,
|
|
59
|
+
cursor: flags.cursor,
|
|
57
60
|
});
|
|
58
61
|
}
|
|
59
62
|
catch (err) {
|
|
@@ -65,8 +68,15 @@ class SearchSkills extends base_command_1.BaseCommand {
|
|
|
65
68
|
}
|
|
66
69
|
const r = response;
|
|
67
70
|
const items = Array.isArray(r) ? r : (r?.data ?? []);
|
|
71
|
+
const incomplete = (0, skill_store_pagination_1.skillStoreSearchIncomplete)(response);
|
|
72
|
+
if (incomplete)
|
|
73
|
+
this.warn('Skill store search may be incomplete. Try again or narrow your query.');
|
|
68
74
|
if (items.length === 0) {
|
|
69
|
-
this.log(
|
|
75
|
+
this.log((0, skill_store_pagination_1.skillStorePageState)(response, flags.cursor).hasMore
|
|
76
|
+
? 'No skills matched on this page. More candidates remain.'
|
|
77
|
+
: incomplete ? 'No skills confirmed in the available search results.'
|
|
78
|
+
: `No skills found matching '${query}'.`);
|
|
79
|
+
(0, skill_store_pagination_1.reportSkillStorePage)(response, flags.cursor, (message) => this.log(message), (message) => this.warn(message));
|
|
70
80
|
return;
|
|
71
81
|
}
|
|
72
82
|
const rows = items.map((s) => ({
|
|
@@ -85,6 +95,7 @@ class SearchSkills extends base_command_1.BaseCommand {
|
|
|
85
95
|
{ key: 'installs', header: 'INSTALLS' },
|
|
86
96
|
{ key: 'description', header: 'DESCRIPTION', maxWidth: 60 },
|
|
87
97
|
], (line) => this.log(line));
|
|
98
|
+
(0, skill_store_pagination_1.reportSkillStorePage)(response, flags.cursor, (message) => this.log(message), (message) => this.warn(message));
|
|
88
99
|
}
|
|
89
100
|
}
|
|
90
101
|
exports.default = SearchSkills;
|
|
@@ -16,12 +16,19 @@ export declare function spaceSearchRow(s: Record<string, unknown>): {
|
|
|
16
16
|
export default class SearchSpaces extends BaseCommand {
|
|
17
17
|
static description: string;
|
|
18
18
|
static examples: string[];
|
|
19
|
+
static args: {
|
|
20
|
+
query: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
21
|
+
};
|
|
19
22
|
static flags: {
|
|
20
23
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
|
-
query: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
|
+
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
25
|
status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
26
|
+
label: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
27
|
'include-archived': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
28
|
+
'archived-only': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
24
29
|
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
30
|
+
cursor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
31
|
+
match: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
32
|
};
|
|
26
33
|
run(): Promise<void>;
|
|
27
34
|
}
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.spaceSearchRow = spaceSearchRow;
|
|
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 search_display_1 = require("../../lib/search-display");
|
|
9
11
|
/**
|
|
10
12
|
* One space document → one search-result row.
|
|
11
13
|
*
|
|
@@ -15,12 +17,12 @@ const web_url_1 = require("../../lib/web-url");
|
|
|
15
17
|
*/
|
|
16
18
|
function spaceSearchRow(s) {
|
|
17
19
|
return {
|
|
18
|
-
id: (0, format_1.formatCell)(s.id ?? s._id),
|
|
20
|
+
id: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(s.id ?? s._id)),
|
|
19
21
|
// Absent on spaces created before identifiers existed and not yet
|
|
20
22
|
// backfilled, so this renders "-" rather than "undefined".
|
|
21
|
-
ref: (0, format_1.formatCell)(s.identifier),
|
|
22
|
-
title: (0, format_1.formatCell)(s.title),
|
|
23
|
-
status: (0, format_1.formatCell)(s.status),
|
|
23
|
+
ref: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(s.identifier)),
|
|
24
|
+
title: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(s.title)),
|
|
25
|
+
status: (0, search_display_1.searchDisplayText)((0, format_1.formatCell)(s.status)),
|
|
24
26
|
archived: s.archivedAt ? 'yes' : 'no',
|
|
25
27
|
};
|
|
26
28
|
}
|
|
@@ -29,42 +31,74 @@ class SearchSpaces extends base_command_1.BaseCommand {
|
|
|
29
31
|
// `--space` here would be resolved as a space reference by the BaseCommand
|
|
30
32
|
// parse hook, so this command deliberately uses `--query` like its siblings.
|
|
31
33
|
static examples = [
|
|
34
|
+
'<%= config.bin %> spaces search "always on" --match phrase',
|
|
32
35
|
'<%= config.bin %> search spaces --query dogfood',
|
|
33
36
|
'<%= config.bin %> search spaces --query "always on" --json',
|
|
34
37
|
'<%= config.bin %> search spaces --query retired --include-archived',
|
|
38
|
+
'<%= config.bin %> spaces search retired --archived-only',
|
|
35
39
|
];
|
|
40
|
+
static args = { query: core_1.Args.string({ description: 'Search term', ignoreStdin: true }) };
|
|
36
41
|
static flags = {
|
|
37
42
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
38
|
-
query: core_1.Flags.string({ char: 'q', description: 'Search query'
|
|
39
|
-
status: core_1.Flags.string({ description: 'Filter by space status' }),
|
|
40
|
-
|
|
43
|
+
query: core_1.Flags.string({ char: 'q', description: 'Search query' }),
|
|
44
|
+
status: core_1.Flags.string({ description: 'Filter by space status', options: [...data_provider_1.SPACE_STATUSES] }),
|
|
45
|
+
label: core_1.Flags.string({ description: 'Filter by label ID; repeat to require all labels', multiple: true }),
|
|
46
|
+
'include-archived': core_1.Flags.boolean({ description: 'Include archived spaces', exclusive: ['archived-only'] }),
|
|
47
|
+
'archived-only': core_1.Flags.boolean({ description: 'Search only archived spaces', exclusive: ['include-archived'] }),
|
|
41
48
|
limit: core_1.Flags.integer({ description: 'Max results', default: 20 }),
|
|
49
|
+
cursor: core_1.Flags.string({ description: 'Continue from a previous page' }),
|
|
50
|
+
match: core_1.Flags.string({ description: 'Matching policy', options: ['fuzzy', 'phrase', 'exact'] }),
|
|
42
51
|
};
|
|
43
52
|
async run() {
|
|
44
53
|
this.requireAuth();
|
|
45
|
-
const { flags } = await this.parse(SearchSpaces);
|
|
54
|
+
const { args, flags } = await this.parse(SearchSpaces);
|
|
55
|
+
const query = (0, search_query_1.resolveSearchQuery)(this, args.query, flags.query, 'search spaces');
|
|
46
56
|
let response;
|
|
47
57
|
try {
|
|
48
58
|
response = await data_provider_1.dataService.listSpaces({
|
|
49
|
-
q:
|
|
59
|
+
q: query,
|
|
50
60
|
...(flags.status ? { status: flags.status } : {}),
|
|
61
|
+
...(flags.label?.length ? { labelIds: flags.label } : {}),
|
|
51
62
|
includeArchived: flags['include-archived'],
|
|
63
|
+
archivedOnly: flags['archived-only'],
|
|
52
64
|
limit: flags.limit,
|
|
65
|
+
cursor: flags.cursor,
|
|
66
|
+
...(flags.match ? { match: flags.match } : {}),
|
|
53
67
|
});
|
|
54
68
|
}
|
|
55
69
|
catch (err) {
|
|
56
70
|
this.handleApiError(err);
|
|
57
71
|
}
|
|
72
|
+
if (!(0, search_display_1.isSearchListPage)(response)) {
|
|
73
|
+
this.failWithCliError({ message: 'The server returned an invalid Space search response. Retry or check server compatibility.',
|
|
74
|
+
code: 'SEARCH_INVALID_RESPONSE', exit: 1, retryable: true });
|
|
75
|
+
}
|
|
76
|
+
if (flags.match && response?.search?.mode !== flags.match) {
|
|
77
|
+
this.error('The server did not confirm the requested matching policy. Upgrade the server before relying on this result.');
|
|
78
|
+
}
|
|
58
79
|
if (flags.json) {
|
|
59
80
|
this.log(JSON.stringify((0, web_url_1.withDataUrls)(this.cliConfig.baseURL, response, web_url_1.spaceUrlFrom), null, 2));
|
|
60
81
|
return;
|
|
61
82
|
}
|
|
62
83
|
const items = (response?.data ?? []);
|
|
84
|
+
const meta = response;
|
|
85
|
+
if (meta.degraded || meta.warnings?.length)
|
|
86
|
+
this.warn('Search may be incomplete. Inspect --json diagnostics.');
|
|
87
|
+
if (meta.search?.candidates_may_be_truncated)
|
|
88
|
+
this.warn('Search index candidates may be truncated; results may be incomplete.');
|
|
89
|
+
if (meta.search?.candidate_window_unknown)
|
|
90
|
+
this.warn('The search index result window could not be checked; results may be incomplete.');
|
|
91
|
+
if (meta.search?.backend === 'database' && (!flags.match || flags.match === 'fuzzy'))
|
|
92
|
+
this.warn('Search is using literal database matching; typo tolerance may be unavailable.');
|
|
63
93
|
if (items.length === 0) {
|
|
64
|
-
const hint = flags['include-archived']
|
|
94
|
+
const hint = flags['include-archived'] || flags['archived-only']
|
|
65
95
|
? ''
|
|
66
96
|
: ' (archived spaces are excluded — add --include-archived)';
|
|
67
|
-
this.log(`No spaces matching ${JSON.stringify(
|
|
97
|
+
this.log(`No spaces matching ${JSON.stringify(query)} on this page${hint}. Try a distinctive word or broaden the filters.`);
|
|
98
|
+
if (meta.next_cursor)
|
|
99
|
+
this.log(`Next page: --cursor ${(0, search_display_1.shellSearchCursor)(meta.next_cursor)}`);
|
|
100
|
+
else if (meta.has_more)
|
|
101
|
+
this.warn('More results exist, but the server did not provide a cursor.');
|
|
68
102
|
return;
|
|
69
103
|
}
|
|
70
104
|
const rows = items.map((s) => ({
|
|
@@ -77,8 +111,12 @@ class SearchSpaces extends base_command_1.BaseCommand {
|
|
|
77
111
|
{ key: 'status', header: 'STATUS' },
|
|
78
112
|
{ key: 'archived', header: 'ARCHIVED' },
|
|
79
113
|
{ key: 'id', header: 'ID' },
|
|
80
|
-
{ key: 'url', header: 'URL',
|
|
114
|
+
{ key: 'url', header: 'URL', verbatim: true },
|
|
81
115
|
], (line) => this.log(line));
|
|
116
|
+
if (meta.next_cursor)
|
|
117
|
+
this.log(`Next page: --cursor ${(0, search_display_1.shellSearchCursor)(meta.next_cursor)}`);
|
|
118
|
+
else if (meta.has_more)
|
|
119
|
+
this.warn('More results exist, but the server did not provide a cursor.');
|
|
82
120
|
}
|
|
83
121
|
}
|
|
84
122
|
exports.default = SearchSpaces;
|
|
@@ -21,13 +21,24 @@ export declare function taskSearchRow(t: Record<string, unknown>): {
|
|
|
21
21
|
export default class SearchTasks extends BaseCommand {
|
|
22
22
|
static description: string;
|
|
23
23
|
static examples: string[];
|
|
24
|
+
static args: {
|
|
25
|
+
query: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
26
|
+
};
|
|
24
27
|
static flags: {
|
|
25
28
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
-
query: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
29
|
+
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
30
|
space: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
|
-
|
|
31
|
+
goal: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
32
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
33
|
+
status: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
34
|
+
'status-type': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
|
+
open: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
36
|
+
priority: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
38
|
+
'label-id': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
29
39
|
'include-archived': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
30
40
|
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
41
|
+
cursor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
31
42
|
};
|
|
32
43
|
run(): Promise<void>;
|
|
33
44
|
}
|