@bli-cockpit/cli 0.2.122 → 0.2.123
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/commands/careers.js
CHANGED
|
@@ -2,7 +2,8 @@ import { readFile } from 'node:fs/promises';
|
|
|
2
2
|
import { askAgentDoor, emitAgentDoor, failAgentDoor, openAgentDoor } from './agent-door.js';
|
|
3
3
|
/**
|
|
4
4
|
* `cockpit careers` — application review (BLI-3706) and, since BLI-4460, the
|
|
5
|
-
* pipeline: invite, decide, the role's take-home and the
|
|
5
|
+
* pipeline: invite, decide, the role's take-home and the settings. BLI-4461
|
|
6
|
+
* added `grade`, which puts one submission back in the grader's queue.
|
|
6
7
|
*
|
|
7
8
|
* Every verb goes through the SAME Tower door its MCP twin calls; nothing here
|
|
8
9
|
* decides policy. The take-home body arrives from a FILE rather than a flag,
|
|
@@ -41,6 +42,10 @@ async function planCareersRequest(command) {
|
|
|
41
42
|
case 'show': return { path: application, method: 'GET' };
|
|
42
43
|
case 'rescreen': return { path: `${application}/rescreen`, method: 'POST' };
|
|
43
44
|
case 'invite': return { path: `${application}/invite`, method: 'POST' };
|
|
45
|
+
// The grader itself runs on Railway, because it needs a clone and yt-dlp.
|
|
46
|
+
// This door re-queues the row; `--now` is passed through and the answer
|
|
47
|
+
// names where the run actually happens rather than implying it ran here.
|
|
48
|
+
case 'grade': return { path: `${application}/grade`, method: 'POST', body: { now: command.now === true } };
|
|
44
49
|
case 'decide': return { path: `${application}/decide`, method: 'POST', body: { decision: command.decision } };
|
|
45
50
|
case 'takehome-show': return { path: takehomePath(command), method: 'GET' };
|
|
46
51
|
case 'takehome-set': return { path: takehomePath(command), method: 'PUT', body: await takehomeBody(command) };
|
|
@@ -81,8 +86,12 @@ function settingsBody(command) {
|
|
|
81
86
|
body.attention_min_score = command.attentionMinScore;
|
|
82
87
|
if (command.inviteAccountId !== undefined)
|
|
83
88
|
body.invite_account_id = command.inviteAccountId;
|
|
89
|
+
if (command.bookingLink !== undefined)
|
|
90
|
+
body.booking_link = command.bookingLink;
|
|
91
|
+
if (command.graderModel !== undefined)
|
|
92
|
+
body.grader_model = command.graderModel;
|
|
84
93
|
if (Object.keys(body).length === 0) {
|
|
85
|
-
throw new Error('careers settings set needs at least one of --enabled, --auto-invite-min-score, --attention-min-score or --
|
|
94
|
+
throw new Error('careers settings set needs at least one of --enabled, --auto-invite-min-score, --attention-min-score, --account, --booking-link or --grader-model.');
|
|
86
95
|
}
|
|
87
96
|
return body;
|
|
88
97
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { optionalNonEmpty, optionalUrl, parseNamedArgs } from './local-arg-values.js';
|
|
2
|
-
const ACTIONS = ['list', 'show', 'rescreen', 'invite', 'decide', 'takehome-show', 'takehome-set', 'settings-show', 'settings-set'];
|
|
2
|
+
const ACTIONS = ['list', 'show', 'rescreen', 'invite', 'decide', 'grade', 'takehome-show', 'takehome-set', 'settings-show', 'settings-set'];
|
|
3
3
|
const DECISIONS = ['passed_on', 'archived', 'reopen'];
|
|
4
4
|
/** Verbs that name an application id, a role slug, or nothing at all. */
|
|
5
|
-
const NEEDS_ID = ['show', 'rescreen', 'invite', 'decide'];
|
|
5
|
+
const NEEDS_ID = ['show', 'rescreen', 'invite', 'decide', 'grade'];
|
|
6
6
|
const NEEDS_ROLE = ['takehome-show', 'takehome-set'];
|
|
7
7
|
export function parseCareersArgs(args) {
|
|
8
|
-
const valueFlags = ['--role', '--min-score', '--since', '--home', '--dashboard-url', '--decision', '--stage', '--subject', '--body-file', '--link', '--pass-score', '--account', '--auto-invite-min-score', '--attention-min-score', '--enabled'];
|
|
9
|
-
const values = parseNamedArgs(args, { allowedFlags: [...valueFlags, '--json'], valueFlags });
|
|
8
|
+
const valueFlags = ['--role', '--min-score', '--since', '--home', '--dashboard-url', '--decision', '--stage', '--subject', '--body-file', '--link', '--pass-score', '--account', '--auto-invite-min-score', '--attention-min-score', '--enabled', '--booking-link', '--grader-model'];
|
|
9
|
+
const values = parseNamedArgs(args, { allowedFlags: [...valueFlags, '--json', '--now'], valueFlags });
|
|
10
10
|
const positionals = [...values.positionals];
|
|
11
11
|
// `takehome show` and `settings set` are two words a person types and one
|
|
12
12
|
// action everything downstream reads.
|
|
@@ -52,11 +52,34 @@ export function parseCareersArgs(args) {
|
|
|
52
52
|
subject: optionalNonEmpty(values.flags.get('--subject')), bodyFile: optionalNonEmpty(values.flags.get('--body-file')),
|
|
53
53
|
link: optionalNonEmpty(values.flags.get('--link')), passScore,
|
|
54
54
|
inviteAccountId: optionalNonEmpty(values.flags.get('--account')),
|
|
55
|
+
bookingLink: httpsFlag(values.flags.get('--booking-link')),
|
|
56
|
+
graderModel: optionalNonEmpty(values.flags.get('--grader-model')),
|
|
57
|
+
now: values.booleans.has('--now'),
|
|
55
58
|
autoInviteMinScore, attentionMinScore,
|
|
56
59
|
autoInviteEnabled: enabledRaw === undefined ? undefined : enabledRaw === 'true',
|
|
57
60
|
homeDir: optionalNonEmpty(values.flags.get('--home')), dashboardUrl: optionalUrl(values.flags.get('--dashboard-url')), json: values.booleans.has('--json'),
|
|
58
61
|
};
|
|
59
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* BLI-4461: a booking link goes into an email a stranger clicks, so the
|
|
65
|
+
* terminal refuses anything but https here as well as on the server. Two
|
|
66
|
+
* checks, one rule, and the local one costs no round trip.
|
|
67
|
+
*/
|
|
68
|
+
function httpsFlag(raw) {
|
|
69
|
+
const value = optionalUrl(raw);
|
|
70
|
+
if (value === undefined)
|
|
71
|
+
return undefined;
|
|
72
|
+
let parsed;
|
|
73
|
+
try {
|
|
74
|
+
parsed = new URL(value);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
throw new Error('--booking-link must be an https URL.');
|
|
78
|
+
}
|
|
79
|
+
if (parsed.protocol !== 'https:')
|
|
80
|
+
throw new Error('--booking-link must be an https URL.');
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
60
83
|
function numberFlag(raw, flag, min, max) {
|
|
61
84
|
if (raw === undefined)
|
|
62
85
|
return undefined;
|
|
@@ -25,16 +25,17 @@ export const TOWER_COMMAND_HELP = [
|
|
|
25
25
|
[
|
|
26
26
|
"careers",
|
|
27
27
|
[
|
|
28
|
-
"Usage: cockpit careers [list|show <id>|rescreen <id>|invite <id>|decide <id> --decision <d>|takehome show <role>|takehome set <role>|settings show|settings set] [flags]",
|
|
28
|
+
"Usage: cockpit careers [list|show <id>|rescreen <id>|invite <id>|decide <id> --decision <d>|grade <id>|takehome show <role>|takehome set <role>|settings show|settings set] [flags]",
|
|
29
29
|
"",
|
|
30
30
|
"Super-admin application review and pipeline. Lists at most 100 matches with total and has_more; use filters to narrow.",
|
|
31
31
|
"list [--role <slug>] [--min-score <n>] [--since <date>] [--stage <screened|invited|submitted|graded|booking_sent|passed_on|archived>] — the board, newest first, with the two thresholds in force.",
|
|
32
32
|
"invite <id> — sends that role's take-home from the configured mailbox, whatever the screening scored. Only a row still at `screened`.",
|
|
33
33
|
"decide <id> --decision <passed_on|archived|reopen> — your own call on a row; `reopen` puts it back to `screened`.",
|
|
34
|
+
"grade <id> [--now]: puts one submission back in the take-home grader's queue. The grader runs on Railway every 15 minutes; --now says so rather than pretending the run happened here.",
|
|
34
35
|
"takehome show <role> — the subject, body, link and the reviewer's rubric for that role.",
|
|
35
36
|
"takehome set <role> [--subject <s>] [--body-file <path>] [--link <url>] [--pass-score <0-10>] — the body comes from a FILE and must keep {first_name} and {link}.",
|
|
36
37
|
"settings show — the bar, the attention threshold, whether automatic sending is on, and which mailbox it goes out from.",
|
|
37
|
-
"settings set [--enabled true|false] [--auto-invite-min-score <0-100>] [--attention-min-score <0-100>] [--account <mailbox uuid>]
|
|
38
|
+
"settings set [--enabled true|false] [--auto-invite-min-score <0-100>] [--attention-min-score <0-100>] [--account <mailbox uuid>] [--booking-link <https url>] [--grader-model <provider:model>]: each takes effect on the next run, no deploy.",
|
|
38
39
|
],
|
|
39
40
|
],
|
|
40
41
|
[
|
|
@@ -104,7 +104,7 @@ export function localCommandHelp(command) {
|
|
|
104
104
|
" cockpit project [list] [--archived] [--dashboard-url <url>] [--json]",
|
|
105
105
|
` cockpit search "<words>" [--kind ${SEARCH_KINDS.join(",")}] [--limit <n>] [--dashboard-url <url>] [--json]`,
|
|
106
106
|
" cockpit release [--dry-run] [--skip-checks] [--no-floor] [--tag <tag>] [--access <public|restricted>] [--otp <code>]",
|
|
107
|
-
" cockpit careers [list|show <id>|rescreen <id>|invite <id>|decide <id> --decision <passed_on|archived|reopen>|takehome show <role>|takehome set <role> --body-file <path>|settings show|settings set --enabled <true|false>] [--role <slug>] [--min-score <n>] [--since <date>] [--stage <s>] [--json]",
|
|
107
|
+
" cockpit careers [list|show <id>|rescreen <id>|invite <id>|decide <id> --decision <passed_on|archived|reopen>|grade <id> [--now]|takehome show <role>|takehome set <role> --body-file <path>|settings show|settings set --enabled <true|false>] [--role <slug>] [--min-score <n>] [--since <date>] [--stage <s>] [--json]",
|
|
108
108
|
" cockpit usage sessions [--task <BLI-NNNN> | --subject <name>] [--repo <label>] [--since <window>] [--json]",
|
|
109
109
|
" cockpit usage sessions --session <id> [--from-window <n>] [--json]",
|
|
110
110
|
" --by-topic groups work types; --by-subject groups open subjects from session summaries.",
|
|
@@ -15,7 +15,7 @@ export async function runCockpitCli(argv, io) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
if (command === "--version" || command === "-V" || command === "version") {
|
|
18
|
-
writeLine(io?.stdout ?? process.stdout, "0.2.
|
|
18
|
+
writeLine(io?.stdout ?? process.stdout, "0.2.123");
|
|
19
19
|
return 0;
|
|
20
20
|
}
|
|
21
21
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bli-cockpit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.123",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@bli-cockpit/memory-mcp": "0.1.32",
|
|
31
|
-
"@bli-cockpit/mcp": "0.1.
|
|
31
|
+
"@bli-cockpit/mcp": "0.1.50",
|
|
32
32
|
"@bli-cockpit/telemetry-core": "0.1.48"
|
|
33
33
|
}
|
|
34
34
|
}
|