@bli-cockpit/cli 0.2.163 → 0.2.165

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.
@@ -0,0 +1,92 @@
1
+ /**
2
+ * `cockpit github` — a pull request's live state, and merge / retitle / re-run
3
+ * on the person's say-so (BLI-12385).
4
+ *
5
+ * The SAME door JARVIS's chat tools stand on (`POST /api/github/pull-request`,
6
+ * opted into the device token in `route-caller-census.test.ts`): GitHub's own
7
+ * answer, your own GitHub login's permission checked by GitHub, and the same
8
+ * two steps. Run a write without `--confirm` and it prints what would happen
9
+ * and an eight-character code; run it again with `--confirm <code>` and it does
10
+ * it. Nothing about the gate is decided on this side.
11
+ *
12
+ * A refusal keeps the door's own `reason` label and sentence verbatim
13
+ * (`github_login_unknown`, `github_permission_insufficient`, ...).
14
+ */
15
+ import { askAgentDoor, emitAgentDoor, failAgentDoor, openAgentDoor } from "./agent-door.js";
16
+ import { writeLine } from "./cli-io.js";
17
+ const TAG = "[github cli]";
18
+ const DEADLINE_MS = 60_000;
19
+ export function buildGithubBody(command) {
20
+ const body = {
21
+ action: command.action === "pr" ? "read" : command.action,
22
+ repo: command.repo,
23
+ };
24
+ if (command.pullNumber !== undefined)
25
+ body["pullNumber"] = command.pullNumber;
26
+ if (command.runId !== undefined)
27
+ body["runId"] = command.runId;
28
+ if (command.title !== undefined)
29
+ body["title"] = command.title;
30
+ if (command.method !== undefined)
31
+ body["method"] = command.method;
32
+ if (command.claim !== undefined)
33
+ body["claim"] = command.claim;
34
+ if (command.confirm !== undefined)
35
+ body["confirm"] = command.confirm;
36
+ return body;
37
+ }
38
+ export async function runGithub(command, io) {
39
+ const door = await openAgentDoor("github", command, io);
40
+ const answer = await askAgentDoor(door, {
41
+ path: "/api/github/pull-request",
42
+ method: "POST",
43
+ label: `github-${command.action}`,
44
+ timeoutMs: DEADLINE_MS,
45
+ body: buildGithubBody(command),
46
+ });
47
+ if (!answer.ok)
48
+ return failAgentDoor(door, TAG, answer.reason, answer.detail);
49
+ const result = answer.body.result ?? {};
50
+ writeLine(io.stderr, `${TAG} ${command.action} ${JSON.stringify({
51
+ repo: command.repo,
52
+ pull_number: command.pullNumber ?? null,
53
+ status: result["status"] ?? null,
54
+ reason: result["reason"] ?? null,
55
+ })}`);
56
+ if (door.json)
57
+ return emitAgentDoor(door, answer.body);
58
+ return command.action === "pr" ? renderRead(door, result) : renderWrite(door, command, result);
59
+ }
60
+ function renderRead(door, result) {
61
+ const summary = typeof result["summary"] === "string" ? result["summary"] : "GitHub returned no summary.";
62
+ writeLine(door.io.stdout, summary);
63
+ if (typeof result["note"] === "string" && result["note"])
64
+ writeLine(door.io.stdout, result["note"]);
65
+ // A read GitHub could not answer is not a clean zero: say so in the exit code.
66
+ return result["status"] === "read_failed" || result["status"] === "unconfigured" ? 1 : 0;
67
+ }
68
+ function renderWrite(door, command, result) {
69
+ if (result["status"] === "needs_confirmation") {
70
+ const code = String(result["confirmationCode"] ?? "");
71
+ writeLine(door.io.stdout, `Would ${String(result["preview"] ?? "make this change")}`);
72
+ writeLine(door.io.stdout, `Nothing has been changed. To go ahead, run:`);
73
+ writeLine(door.io.stdout, ` ${rerunCommand(command, code)}`);
74
+ return 0;
75
+ }
76
+ writeLine(door.io.stdout, String(result["sayThis"] ?? "Done."));
77
+ return 0;
78
+ }
79
+ /** The exact second step, with the same arguments, so the code stays valid. */
80
+ function rerunCommand(command, code) {
81
+ const parts = ["cockpit", "github", command.action, command.repo];
82
+ if (command.pullNumber !== undefined)
83
+ parts.push(String(command.pullNumber));
84
+ if (command.runId !== undefined)
85
+ parts.push("--run", String(command.runId));
86
+ if (command.title !== undefined)
87
+ parts.push("--title", JSON.stringify(command.title));
88
+ if (command.method !== undefined)
89
+ parts.push("--method", command.method);
90
+ parts.push("--confirm", code);
91
+ return parts.join(" ");
92
+ }
@@ -91,6 +91,8 @@ export function parseOpsArgs(args) {
91
91
  "--models",
92
92
  "--turns",
93
93
  "--tool-router",
94
+ // BLI-12507: the MCP's `people: true`. Per-device and per-person rows in --json.
95
+ "--people",
94
96
  "--person",
95
97
  "--dry-run",
96
98
  "--json",
@@ -134,6 +136,7 @@ export function parseOpsArgs(args) {
134
136
  models: values.booleans.has("--models"),
135
137
  turns: values.booleans.has("--turns"),
136
138
  toolRouter: values.booleans.has("--tool-router"),
139
+ people: values.booleans.has("--people"),
137
140
  ...(memoryDays === undefined ? {} : { memoryDays: Number(memoryDays) }),
138
141
  ...base,
139
142
  };
@@ -0,0 +1,81 @@
1
+ /**
2
+ * `cockpit github` argument parsing (BLI-12385).
3
+ *
4
+ * cockpit github pr <owner/repo> <n> [--claim merged|open|closed|ci_green|mergeable]
5
+ * cockpit github merge <owner/repo> <n> [--method squash|merge|rebase] [--confirm <code>]
6
+ * cockpit github retitle <owner/repo> <n> --title "<text>" [--confirm <code>]
7
+ * cockpit github rerun <owner/repo> (<n> | --run <id>) [--confirm <code>]
8
+ *
9
+ * Without `--confirm` a write only previews and prints a code; with it, it
10
+ * executes. The server judges everything else (org, permission, code), so this
11
+ * file refuses only what could not be a request at all.
12
+ */
13
+ import { optionalNonEmpty, optionalPositiveInteger, optionalUrl, parseNamedArgs, } from "./local-arg-values.js";
14
+ export const GITHUB_ACTIONS = ["pr", "merge", "retitle", "rerun"];
15
+ export const GITHUB_MERGE_METHODS = ["squash", "merge", "rebase"];
16
+ export const GITHUB_CLAIMS = ["merged", "open", "closed", "ci_green", "mergeable"];
17
+ const REPO_PATTERN = /^[A-Za-z0-9_.-]+(\/[A-Za-z0-9_.-]+)?$/;
18
+ export function parseGithubArgs(args) {
19
+ const values = parseNamedArgs(args, {
20
+ allowedFlags: ["--home", "--dashboard-url", "--claim", "--method", "--title", "--run", "--confirm", "--json"],
21
+ valueFlags: ["--home", "--dashboard-url", "--claim", "--method", "--title", "--run", "--confirm"],
22
+ });
23
+ const action = values.positionals[0];
24
+ if (!action || !GITHUB_ACTIONS.includes(action)) {
25
+ throw new Error(`github action must be one of ${GITHUB_ACTIONS.join(", ")}.`);
26
+ }
27
+ const repo = values.positionals[1];
28
+ if (!repo || !REPO_PATTERN.test(repo)) {
29
+ throw new Error(`github ${action} needs a repo, e.g. BLI-INC/bli-cockpit.`);
30
+ }
31
+ const numberText = values.positionals[2];
32
+ if (values.positionals.length > 3)
33
+ throw new Error(`github ${action} takes a repo and a pull request number only.`);
34
+ const pullNumber = numberText === undefined ? undefined : optionalPositiveInteger(numberText, "pull request number");
35
+ const runId = optionalPositiveInteger(values.flags.get("--run"), "--run");
36
+ if (action === "rerun") {
37
+ if ((pullNumber === undefined) === (runId === undefined)) {
38
+ throw new Error("github rerun needs exactly one of a pull request number or --run <id>.");
39
+ }
40
+ }
41
+ else if (pullNumber === undefined) {
42
+ throw new Error(`github ${action} needs a pull request number.`);
43
+ }
44
+ const only = (flag, allowed) => {
45
+ if (values.flags.has(flag) && !allowed.includes(action)) {
46
+ throw new Error(`${flag} belongs to \`cockpit github ${allowed.join("|")}\`.`);
47
+ }
48
+ };
49
+ only("--claim", ["pr"]);
50
+ only("--method", ["merge"]);
51
+ only("--title", ["retitle"]);
52
+ only("--run", ["rerun"]);
53
+ if (values.flags.has("--confirm") && action === "pr") {
54
+ throw new Error("--confirm belongs to merge, retitle and rerun; pr only reads.");
55
+ }
56
+ const title = optionalNonEmpty(values.flags.get("--title"));
57
+ if (action === "retitle" && !title)
58
+ throw new Error("github retitle needs --title \"<new title>\".");
59
+ const method = optionalNonEmpty(values.flags.get("--method"));
60
+ if (method && !GITHUB_MERGE_METHODS.includes(method)) {
61
+ throw new Error(`--method must be one of ${GITHUB_MERGE_METHODS.join(", ")}; got ${method}.`);
62
+ }
63
+ const claim = optionalNonEmpty(values.flags.get("--claim"));
64
+ if (claim && !GITHUB_CLAIMS.includes(claim)) {
65
+ throw new Error(`--claim must be one of ${GITHUB_CLAIMS.join(", ")}; got ${claim}.`);
66
+ }
67
+ return {
68
+ kind: "github",
69
+ action,
70
+ repo,
71
+ ...(pullNumber === undefined ? {} : { pullNumber }),
72
+ ...(runId === undefined ? {} : { runId }),
73
+ ...(title ? { title } : {}),
74
+ ...(method ? { method: method } : {}),
75
+ ...(claim ? { claim } : {}),
76
+ ...(values.flags.get("--confirm") ? { confirm: values.flags.get("--confirm").trim() } : {}),
77
+ homeDir: optionalNonEmpty(values.flags.get("--home")),
78
+ dashboardUrl: optionalUrl(values.flags.get("--dashboard-url")),
79
+ json: values.booleans.has("--json"),
80
+ };
81
+ }
@@ -32,6 +32,7 @@ export { parseBriefArgs, WORKBOOK_MIN_WIDTH, parseWorkbookArgs, parseNotesArgs,
32
32
  export { SCOUT_MIN_PREFIX_LENGTH, parseScoutArgs, parseOpsArgs, SLACK_WORKSPACE_KEYS, parseSlackArgs, parseSettingsArgs, parseTeamArgs, parseModelArgs, } from "./local-args-tower-admin.js";
33
33
  export { parseDocsArgs, parseMsgArgs, } from "./local-args-tower-docs-msg.js";
34
34
  export { ISSUE_STATES, parseIssueArgs, parseProjectArgs, } from "./local-args-tower-work.js";
35
+ export { parseGithubArgs } from "./local-args-tower-github.js";
35
36
  export { SEARCH_KINDS, parseSearchArgs } from "./local-args-tower-search.js";
36
37
  export { parseModelsArgs } from "./local-args-tower-models.js";
37
38
  export { parseMailArgs } from "./local-args-tower-mail.js";
@@ -18,7 +18,7 @@
18
18
  import { parseRootsArgs } from "./roots.js";
19
19
  import { SURFACE_ALIASES } from "./local-help.js";
20
20
  import { parseAgentRulesArgs, parseAnalyzeArgs, parseAutostartArgs, parseBackfillArgs, parseCleanArgs, parseDoctorArgs, parseInstallArgs, parseLoginArgs, parseMemoryArgs, parseLogoutArgs, parseOnboardArgs, parseReleaseArgs, parseServeArgs, parseSessionsArgs, parseSourcesArgs, parseStartArgs, parseStatusArgs, parseSyncArgs, parseUpdateArgs, } from "./local-args-collector.js";
21
- import { parseBriefArgs, parseCorrectArgs, parseDocsArgs, parseIssueArgs, parseJarvisArgs, parseMailArgs, parseCalArgs, parseModelArgs, parseMsgArgs, parseNotesArgs, parseOpsArgs, parseProjectArgs, parseModelsArgs, parseScoutArgs, parseSearchArgs, parseSettingsArgs, parseSlackArgs, parseTeamArgs, parseWorkbookArgs, parseUsageArgs, parseCareersArgs, parseRenameArgs, } from "./local-args-tower.js";
21
+ import { parseBriefArgs, parseCorrectArgs, parseDocsArgs, parseIssueArgs, parseJarvisArgs, parseMailArgs, parseCalArgs, parseModelArgs, parseMsgArgs, parseNotesArgs, parseOpsArgs, parseProjectArgs, parseModelsArgs, parseScoutArgs, parseGithubArgs, parseSearchArgs, parseSettingsArgs, parseSlackArgs, parseTeamArgs, parseWorkbookArgs, parseUsageArgs, parseCareersArgs, parseRenameArgs, } from "./local-args-tower.js";
22
22
  // `normalizeUrl` has always been part of this module's surface — `local.ts` and
23
23
  // `local-auth.ts` import it from here — so it stays exported from this address
24
24
  // even though it now lives next door. The same goes for the four names the
@@ -123,6 +123,8 @@ export function parseLocalArgs(argv) {
123
123
  return parseProjectArgs(argv.slice(1));
124
124
  case "search":
125
125
  return parseSearchArgs(argv.slice(1));
126
+ case "github":
127
+ return parseGithubArgs(argv.slice(1));
126
128
  case "release":
127
129
  return parseReleaseArgs(argv.slice(1));
128
130
  case "careers":
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `cockpit github` command shape (BLI-12385), beside `local-command-shapes.ts`
3
+ * for the same reason `local-command-shapes-search.ts` is: that file sits at the
4
+ * readability ceiling.
5
+ */
6
+ export {};
@@ -10,6 +10,32 @@
10
10
  * something breaks, so it is a user-visible contract like any other.
11
11
  */
12
12
  export const TOWER_OPS_COMMAND_HELP = [
13
+ [
14
+ "github",
15
+ [
16
+ "Usage: cockpit github <pr|merge|retitle|rerun> <owner/repo> <n> [--claim <state>] [--method squash|merge|rebase] [--title \"<text>\"] [--run <id>] [--confirm <code>] [--json]",
17
+ "",
18
+ " cockpit github pr <owner/repo> <n> [--claim merged|open|closed|ci_green|mergeable]",
19
+ " GitHub's own record of one pull request: merged or not, by whom, mergeable,",
20
+ " draft, title and CI. GitHub is the source of truth. --claim compares a state",
21
+ " somebody told you against GitHub's answer and prints the correction.",
22
+ " cockpit github merge|retitle|rerun <owner/repo> <n>",
23
+ " The same three changes JARVIS can make, in TWO STEPS. Without --confirm it",
24
+ " changes nothing: it prints what would happen and an eight-character code, plus",
25
+ " the exact command to run next. Run that command (--confirm <code>) to do it.",
26
+ " A code is signed to you, the repo, the pull request and the exact change, so a",
27
+ " reworded --title or a new head commit needs a new code.",
28
+ " merge takes --method squash (default), merge or rebase. retitle needs --title.",
29
+ " rerun re-runs the FAILED jobs: pass a pull request number, or --run <id> for one run.",
30
+ " Writes run only if YOUR OWN GitHub login (on the roster) has write, maintain or",
31
+ " admin on the repo; otherwise the refusal github_login_unknown or",
32
+ " github_permission_insufficient is printed as written. Only BLI-INC repos.",
33
+ "--json writes one object to stdout: { ok, result } where result is the read, the",
34
+ "preview { status: \"needs_confirmation\", confirmationCode, preview } or the outcome",
35
+ "{ status: \"done\", ... }; a refusal is { ok: false, error, detail } and exits 1.",
36
+ "The bli-tower MCP server has the twins: github_pr, github_merge, github_retitle, github_rerun.",
37
+ ],
38
+ ],
13
39
  [
14
40
  "jarvis",
15
41
  [
@@ -89,13 +115,15 @@ export const TOWER_OPS_COMMAND_HELP = [
89
115
  [
90
116
  "ops",
91
117
  [
92
- "Usage: cockpit ops [status [--job <id>] [--coverage] [--skips] [--memory [--memory-days N]] [--models] [--turns] [--tool-router] | recompile --person <email|name|id> [--dry-run]] [--json]",
118
+ "Usage: cockpit ops [status [--job <id>] [--coverage] [--skips] [--memory [--memory-days N]] [--models] [--turns] [--tool-router] [--people] | recompile --person <email|name|id> [--dry-run]] [--json]",
93
119
  "",
94
120
  " cockpit ops status",
95
121
  " One line per scheduled job: when it last produced something, and whether that",
96
122
  " is late FOR THAT JOB. A once-daily job quiet for 18 hours reads ok; a",
97
123
  " quarter-hourly one does not. Every line names the schedule it is judged against.",
98
124
  " --turns adds 30-day JARVIS turn aggregates; --tool-router adds the shadow-router agreement board.",
125
+ " --json carries the fleet and coverage SUMMARIES only (about 150 KB lighter);",
126
+ " --people --json adds every per-device and per-person row. The text board always prints them.",
99
127
  " A job that is not ok also prints what its artifact does and does not prove —",
100
128
  " several only write a row when there is something new, so quiet can mean a quiet",
101
129
  " week rather than a broken cron.",
@@ -73,6 +73,7 @@ export const rootCommandNames = new Set([
73
73
  "cal",
74
74
  "project",
75
75
  "search",
76
+ "github",
76
77
  "release",
77
78
  "careers",
78
79
  "rename",
@@ -126,6 +127,7 @@ export function localCommandHelp(command) {
126
127
  " cockpit mail [accounts|add-imap --address <a>|inbox|read <thread>|search \"<words>\"|send --account <id> --to <a> --subject <s>|attachment <id> --out <path>|sync <account>|detach <account>] [--account <id>] [--limit <n>] [--unread] [--label <l>] [--file <path>] [--dashboard-url <url>] [--json]",
127
128
  " cockpit cal [today|week|next|find \"<words>\"|calendars|add-ical|create --calendar <id> --title <t> --at <iso> --until <iso>|share <id> --org-visible|--private|sync <id> [--full]|detach <id>] [--tz <zone>] [--offset <n>] [--hours <n>] [--from <d> --to <d>] [--calendar <id>] [--limit <n>] [--all] [--dashboard-url <url>] [--json]",
128
129
  " cockpit project [list] [--archived] [--dashboard-url <url>] [--json]",
130
+ " cockpit github <pr|merge|retitle|rerun> <owner/repo> <n> [--claim <state>] [--method squash|merge|rebase] [--title \"<text>\"] [--run <id>] [--confirm <code>] [--dashboard-url <url>] [--json]",
129
131
  ` cockpit search "<words>" [--kind ${SEARCH_KINDS.join(",")}] [--limit <n>] [--dashboard-url <url>] [--json]`,
130
132
  " cockpit release [--dry-run] [--skip-checks] [--no-floor] [--tag <tag>] [--access <public|restricted>] [--otp <code>]",
131
133
  " cockpit careers [list|show <id>|rescreen <id>|send-takehome <id>|decide <id> --decision <passed_on|archived|reopen>|followup <id> [--record-sent-at <iso>]|interview <id> <--at <iso>|--clear>|grade <id> [--now]|resume <id> [--out <path>]|takehome show <role>|takehome set <role> --body-file <path>|settings show|settings set --enabled <true|false> --followup-enabled <true|false> --followup-after-days <n> --takehome-window-hours <n>] [--role <slug>] [--min-score <n>] [--since <date>] [--stage <s>] [--force] [--json]",
@@ -44,6 +44,7 @@ import { runIssue } from "./issue.js";
44
44
  import { runCal } from "./cal.js";
45
45
  import { runMail } from "./mail.js";
46
46
  import { runProject } from "./project.js";
47
+ import { runGithub } from "./github.js";
47
48
  import { runSearch } from "./search.js";
48
49
  import { runCareers } from "./careers.js";
49
50
  import { runRename } from "./rename-scope.js";
@@ -231,6 +232,8 @@ export async function runLocalCockpitCli(argv, io = defaultIo()) {
231
232
  return await runProject(command, io);
232
233
  case "search":
233
234
  return await runSearch(command, io);
235
+ case "github":
236
+ return await runGithub(command, io);
234
237
  case "release":
235
238
  return await runRelease(command, io);
236
239
  case "careers":
@@ -111,14 +111,24 @@ function isUnhealthyPipeline(row) {
111
111
  }
112
112
  function writeOpsStatusOutput(command, io, payload, memory, models, turns, toolRouter) {
113
113
  if (command.json) {
114
- writeJsonOpsStatus(io, payload, memory, models, turns, toolRouter);
114
+ writeJsonOpsStatus(command.people === true, io, payload, memory, models, turns, toolRouter);
115
115
  return;
116
116
  }
117
117
  writeHumanOpsStatus(command, io, payload, memory, models, turns, toolRouter);
118
118
  }
119
- function writeJsonOpsStatus(io, payload, memory, models, turns, toolRouter) {
119
+ /** The block without its per-device / per-person rows unless `--people` asked for them. */
120
+ function summaryOnly(block, withPeople) {
121
+ if (withPeople)
122
+ return block;
123
+ const { devices: _devices, people: _people, ...rest } = block;
124
+ return rest;
125
+ }
126
+ function writeJsonOpsStatus(withPeople, io, payload, memory, models, turns, toolRouter) {
120
127
  writeLine(io.stdout, JSON.stringify({
121
128
  ...payload,
129
+ // BLI-12507: the MCP's rule, so one board reads the same on both doors.
130
+ ...(payload.fleet ? { fleet: summaryOnly(payload.fleet, withPeople) } : {}),
131
+ ...(payload.coverage ? { coverage: summaryOnly(payload.coverage, withPeople) } : {}),
122
132
  ...(memory
123
133
  ? { memory: memory.section, hooks: memory.hooks, experience: memory.experience }
124
134
  : {}),
@@ -134,6 +144,13 @@ function writeHumanOpsStatus(command, io, payload, memory, models, turns, toolRo
134
144
  })) {
135
145
  writeLine(io.stdout, line);
136
146
  }
147
+ // BLI-12507: a section the server could not read inside its budget is named
148
+ // here, never a silent gap in the board.
149
+ const unreadable = asRecord(payload)["unreadableSections"];
150
+ if (Array.isArray(unreadable) && unreadable.length > 0) {
151
+ writeLine(io.stdout, "");
152
+ writeLine(io.stdout, `NOT READ ${unreadable.join(", ")} (reader_timeout or read failure; see the Tower log)`);
153
+ }
137
154
  if (memory?.section) {
138
155
  for (const line of renderMemoryUsage(memory.section, (text) => dim(text, styled))) {
139
156
  writeLine(io.stdout, line);
@@ -195,6 +212,10 @@ function createOpsStatusReadLog(command, payload, rows, unhealthy, memory, model
195
212
  unhealthy: unhealthy.length,
196
213
  unhealthy_ids: unhealthy.map((row) => row.id ?? "?"),
197
214
  with_skips: Boolean(command.skips),
215
+ people_rows: Boolean(command.people) || !command.json ? "included" : "summary_only",
216
+ unreadable_sections: Array.isArray(asRecord(payload)["unreadableSections"])
217
+ ? asRecord(payload)["unreadableSections"]
218
+ : [],
198
219
  // The laptops (BLI-3550), counted on the same line: a run that shows a
199
220
  // green board and says nothing about the fleet cannot answer "was
200
221
  // anybody's machine dead this morning?".
@@ -21,7 +21,7 @@ export async function runCockpitCli(argv, io) {
21
21
  }
22
22
 
23
23
  if (command === "--version" || command === "-V" || command === "version") {
24
- writeLine(io?.stdout ?? process.stdout, "0.2.163");
24
+ writeLine(io?.stdout ?? process.stdout, "0.2.165");
25
25
  return 0;
26
26
  }
27
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bli-cockpit/cli",
3
- "version": "0.2.163",
3
+ "version": "0.2.165",
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.45",
31
- "@bli-cockpit/mcp": "0.1.81",
31
+ "@bli-cockpit/mcp": "0.1.83",
32
32
  "@bli-cockpit/telemetry-core": "0.1.57"
33
33
  },
34
34
  "repository": {