@staff0rd/assist 0.578.0 → 0.580.0

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/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.578.0",
9
+ version: "0.580.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -3883,7 +3883,7 @@ function collectHashComments(content, options2) {
3883
3883
  function collectComments(sourceFile) {
3884
3884
  const seen = /* @__PURE__ */ new Set();
3885
3885
  const comments3 = [];
3886
- const collect6 = (node) => {
3886
+ const collect7 = (node) => {
3887
3887
  for (const range of [
3888
3888
  ...node.getLeadingCommentRanges(),
3889
3889
  ...node.getTrailingCommentRanges()
@@ -3894,8 +3894,8 @@ function collectComments(sourceFile) {
3894
3894
  comments3.push({ pos, text: range.getText() });
3895
3895
  }
3896
3896
  };
3897
- collect6(sourceFile);
3898
- sourceFile.forEachDescendant(collect6);
3897
+ collect7(sourceFile);
3898
+ sourceFile.forEachDescendant(collect7);
3899
3899
  return comments3;
3900
3900
  }
3901
3901
 
@@ -13973,6 +13973,12 @@ ${quoted}
13973
13973
  }
13974
13974
 
13975
13975
  // src/commands/sessions/shared/toPreviewDecision.ts
13976
+ function toSelection(value) {
13977
+ const selection = value;
13978
+ if (typeof selection?.topLeft !== "string" || typeof selection.bottomRight !== "string")
13979
+ return void 0;
13980
+ return { topLeft: selection.topLeft, bottomRight: selection.bottomRight };
13981
+ }
13976
13982
  function toPreviewDecision(msg) {
13977
13983
  if (msg.decision !== "approve" && msg.decision !== "reject") return null;
13978
13984
  return {
@@ -13983,7 +13989,8 @@ function toPreviewDecision(msg) {
13983
13989
  body: typeof msg.body === "string" ? msg.body : void 0,
13984
13990
  reviewAfter: msg.reviewAfter === true,
13985
13991
  announceAfter: msg.announceAfter === true,
13986
- draft: typeof msg.draft === "boolean" ? msg.draft : void 0
13992
+ draft: typeof msg.draft === "boolean" ? msg.draft : void 0,
13993
+ selection: toSelection(msg.selection)
13987
13994
  };
13988
13995
  }
13989
13996
 
@@ -21035,6 +21042,38 @@ function applyAndVerifySubtree(target, plan2, context) {
21035
21042
  writeLineNow(chalk163.green("Subtree normalised"));
21036
21043
  }
21037
21044
 
21045
+ // src/commands/github/issue/fixStructure/assertChainTypesExist.ts
21046
+ function assertChainTypesExist(chain2, issueTypes) {
21047
+ const missing = chain2.filter(
21048
+ (level) => !issueTypes.some(
21049
+ (type) => normaliseTypeName(type.name) === normaliseTypeName(level)
21050
+ )
21051
+ );
21052
+ if (missing.length === 0) return;
21053
+ throw new Error(
21054
+ `The organisation has no ${missing.join(", ")} issue type${missing.length === 1 ? "" : "s"}. It has ${issueTypes.map((type) => type.name).join(", ")}`
21055
+ );
21056
+ }
21057
+
21058
+ // src/commands/github/issue/fixStructure/parseTypeChain.ts
21059
+ function parseTypeChain(value) {
21060
+ const chain2 = value.split(/[,>]/).map((name) => name.trim()).filter((name) => name.length > 0);
21061
+ if (chain2.length < 2) {
21062
+ throw new Error(
21063
+ `--type-chain needs at least two levels, like Epic,Story,Subtask, not "${value}"`
21064
+ );
21065
+ }
21066
+ const seen = /* @__PURE__ */ new Set();
21067
+ for (const level of chain2) {
21068
+ const key = normaliseTypeName(level);
21069
+ if (seen.has(key)) {
21070
+ throw new Error(`--type-chain repeats ${level}; each level must differ`);
21071
+ }
21072
+ seen.add(key);
21073
+ }
21074
+ return chain2;
21075
+ }
21076
+
21038
21077
  // src/commands/github/issue/fixStructure/printFixStructurePlan.ts
21039
21078
  import chalk164 from "chalk";
21040
21079
  function annotate(entry) {
@@ -21168,9 +21207,11 @@ var defaultTypeChain = ["Epic", "Story", "Subtask"];
21168
21207
 
21169
21208
  // src/commands/github/issue/fixStructure/fixStructure.ts
21170
21209
  function fixStructure(target, options2) {
21171
- const chain2 = defaultTypeChain;
21172
21210
  try {
21211
+ const chain2 = options2.typeChain ? parseTypeChain(options2.typeChain) : defaultTypeChain;
21173
21212
  const resolved = resolveFixStructureTarget(target, options2.repo);
21213
+ const issueTypes = resolveOrgIssueTypes(resolved.owner);
21214
+ assertChainTypesExist(chain2, issueTypes);
21174
21215
  const root = fetchRootIssue(resolved);
21175
21216
  const { index: index3, asserted } = resolveRootLevelIndex(
21176
21217
  chain2,
@@ -21181,8 +21222,8 @@ function fixStructure(target, options2) {
21181
21222
  chain: chain2,
21182
21223
  rootLevelIndex: index3,
21183
21224
  rootAsserted: asserted,
21184
- issueTypes: resolveOrgIssueTypes(resolved.owner),
21185
- stripLabels: []
21225
+ issueTypes,
21226
+ stripLabels: options2.stripLabel ?? []
21186
21227
  };
21187
21228
  const plan2 = planSubtree(root, context);
21188
21229
  printFixStructurePlan(plan2, chain2, options2.apply === true);
@@ -21197,18 +21238,31 @@ function fixStructure(target, options2) {
21197
21238
  // src/commands/github/issue/fixStructure/registerFixStructure.ts
21198
21239
  var chain = defaultTypeChain.join(" > ");
21199
21240
  var levels = defaultTypeChain.map((name) => name.toLowerCase()).join("|");
21241
+ function collect4(value, previous) {
21242
+ return previous.concat([value]);
21243
+ }
21200
21244
  function registerFixStructure(issueCommand) {
21201
21245
  issueCommand.command("fix-structure <target>").description("Normalise the issue types across one issue subtree").option(
21202
21246
  "-R, --repo <owner/repo>",
21203
21247
  "Repository a bare issue number belongs to"
21204
21248
  ).option(
21205
21249
  "--level <level>",
21206
- `The target's own position in the ${chain} chain, when it cannot be inferred from its type`
21250
+ "The target's own position in the type chain, when it cannot be inferred from its type"
21251
+ ).option(
21252
+ "--type-chain <names>",
21253
+ `Comma-separated issue type chain, parent level first (default: ${defaultTypeChain.join(",")})`
21254
+ ).option(
21255
+ "--strip-label <label>",
21256
+ "Legacy marker label to remove from every issue in the subtree that carries it (repeatable)",
21257
+ collect4,
21258
+ []
21207
21259
  ).option("--apply", "Write the planned changes instead of reporting them").addHelpText(
21208
21260
  "after",
21209
21261
  `
21210
- Walks the subtree reachable from <target> via sub-issues and reports the type each issue should carry: every level below the target is typed to the next level down the ${chain} chain. Nothing outside the subtree is ever read or written.
21211
- The target's own level is inferred from its issue type, so aiming at a story types its children as subtasks. When the target's type is not in the chain the level cannot be inferred, and --level ${levels} asserts it instead \u2014 which also plans the target's own type.
21262
+ Walks the subtree reachable from <target> via sub-issues and reports the type each issue should carry: every level below the target is typed to the next level down the chain. Nothing outside the subtree is ever read or written.
21263
+ The chain defaults to ${chain} and --type-chain replaces it, so a backlog on other type names is normalised the same way; every level named must already exist as an issue type on the organisation, or the run fails listing the ones that do.
21264
+ The target's own level is inferred from its issue type, so aiming at a story types its children as subtasks. When the target's type is not in the chain the level cannot be inferred, and --level ${levels} (or whichever levels --type-chain names) asserts it instead \u2014 which also plans the target's own type.
21265
+ No label is touched unless --strip-label names it; each one is repeatable, matched case-insensitively, and removed by the label id found on that issue, since label ids differ per repository.
21212
21266
  The target is owner/repo#number, a github.com issue URL, or a bare number with --repo.
21213
21267
  Without --apply nothing is written. With --apply each write is announced before it is issued, and the subtree is re-walked afterwards so any residual drift fails the run.
21214
21268
  Anything nested below the leaf level fails the run before a single write, naming the offender and its parent.`
@@ -22939,6 +22993,45 @@ function parseAnchorId(value) {
22939
22993
  return link3 ? decodeURIComponent(link3[1]).trim() : trimmed;
22940
22994
  }
22941
22995
 
22996
+ // src/commands/miro/pickAnchors.ts
22997
+ import { randomUUID as randomUUID12 } from "crypto";
22998
+
22999
+ // src/commands/miro/isBox.ts
23000
+ var boxTypes = /* @__PURE__ */ new Set(["shape", "sticky_note"]);
23001
+ function isBox(item) {
23002
+ return boxTypes.has(item.type) && item.text.length > 0;
23003
+ }
23004
+
23005
+ // src/commands/miro/encodeMiroBoardPreview.ts
23006
+ function encodeMiroBoardPreview(items2) {
23007
+ const preview = { boxes: items2.filter(isBox) };
23008
+ return JSON.stringify(preview);
23009
+ }
23010
+
23011
+ // src/commands/miro/pickAnchors.ts
23012
+ var skipAdvice = "Re-run with --top-left <id|link> --bottom-right <id|link> to skip the picker.";
23013
+ async function pickAnchors(sessionId, items2) {
23014
+ const decision = await awaitPreviewApproval(
23015
+ "Miro anchor selection",
23016
+ {
23017
+ sessionId,
23018
+ requestId: randomUUID12(),
23019
+ title: "Pick the top-left then the bottom-right box",
23020
+ body: encodeMiroBoardPreview(items2),
23021
+ prNumber: null,
23022
+ kind: "miro-board"
23023
+ },
23024
+ { rejectionAdvice: `Nothing was extracted. ${skipAdvice}` }
23025
+ );
23026
+ const selection = decision.selection;
23027
+ if (!selection)
23028
+ throw new MiroExtractError(`The picker returned no boxes. ${skipAdvice}`);
23029
+ console.log(
23030
+ `Anchors: --top-left ${selection.topLeft} --bottom-right ${selection.bottomRight}`
23031
+ );
23032
+ return [selection.topLeft, selection.bottomRight];
23033
+ }
23034
+
22942
23035
  // src/commands/miro/readMiroItems.ts
22943
23036
  import { readFileSync as readFileSync40 } from "fs";
22944
23037
  function tryParse(text18) {
@@ -22980,7 +23073,6 @@ function readMiroItems(file) {
22980
23073
  }
22981
23074
 
22982
23075
  // src/commands/miro/selectBoxes.ts
22983
- var boxTypes = /* @__PURE__ */ new Set(["shape", "sticky_note"]);
22984
23076
  function findAnchor(items2, id) {
22985
23077
  const anchor = items2.find((item) => item.id === id);
22986
23078
  if (!anchor)
@@ -22989,9 +23081,6 @@ function findAnchor(items2, id) {
22989
23081
  );
22990
23082
  return anchor;
22991
23083
  }
22992
- function isBox(item) {
22993
- return boxTypes.has(item.type) && item.text.length > 0;
22994
- }
22995
23084
  function centreInside(rect, item) {
22996
23085
  const x = (item.left + item.right) / 2;
22997
23086
  const y = (item.top + item.bottom) / 2;
@@ -23017,16 +23106,24 @@ function requireItems(file) {
23017
23106
  );
23018
23107
  return file;
23019
23108
  }
23020
- function requireAnchors(options2) {
23021
- if (!options2.topLeft || !options2.bottomRight)
23109
+ function anchorSource(options2) {
23110
+ if (options2.topLeft && options2.bottomRight)
23111
+ return {
23112
+ pick: false,
23113
+ topLeft: parseAnchorId(options2.topLeft),
23114
+ bottomRight: parseAnchorId(options2.bottomRight)
23115
+ };
23116
+ const sessionId = process.env.ASSIST_SESSION_ID;
23117
+ if (process.env.ASSIST_SESSION !== "1" || !sessionId)
23022
23118
  throw new MiroExtractError(
23023
- "Both --top-left <id|link> and --bottom-right <id|link> are required."
23119
+ "Both --top-left <id|link> and --bottom-right <id|link> are required: there is no assist session to host the picker pane."
23024
23120
  );
23025
- return [parseAnchorId(options2.topLeft), parseAnchorId(options2.bottomRight)];
23121
+ return { pick: true, sessionId };
23026
23122
  }
23027
- function runExtract(options2) {
23028
- const [topLeft, bottomRight] = requireAnchors(options2);
23123
+ async function runExtract(options2) {
23124
+ const source = anchorSource(options2);
23029
23125
  const items2 = normaliseItems(readMiroItems(requireItems(options2.items)));
23126
+ const [topLeft, bottomRight] = source.pick ? await pickAnchors(source.sessionId, items2) : [source.topLeft, source.bottomRight];
23030
23127
  const boxes = selectBoxes(items2, topLeft, bottomRight);
23031
23128
  process.stdout.write(stringify(boxes.map((box) => box.text)));
23032
23129
  }
@@ -23036,7 +23133,7 @@ function registerMiro(program2) {
23036
23133
  const miroCommand = program2.command("miro").description("Miro board utilities");
23037
23134
  miroCommand.command("extract").description("Print the text of every box inside a rectangle on a board").option("--items <file>", "File of raw board_list_items response pages").option(
23038
23135
  "--top-left <id>",
23039
- "Widget id or ?moveToWidget=<id> link of the top-left box"
23136
+ "Widget id or ?moveToWidget=<id> link of the top-left box (omit both anchors to pick them in the assist web UI)"
23040
23137
  ).option(
23041
23138
  "--bottom-right <id>",
23042
23139
  "Widget id or ?moveToWidget=<id> link of the bottom-right box"
@@ -23868,13 +23965,13 @@ function postReviewComment(vars) {
23868
23965
  }
23869
23966
 
23870
23967
  // src/commands/prs/reviewProposedPrComment.ts
23871
- import { randomUUID as randomUUID12 } from "crypto";
23968
+ import { randomUUID as randomUUID13 } from "crypto";
23872
23969
  async function reviewProposedPrComment(title, body, prNumber) {
23873
23970
  const sessionId = process.env.ASSIST_SESSION_ID;
23874
23971
  if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
23875
23972
  await awaitPreviewApproval("PR comment preview", {
23876
23973
  sessionId,
23877
- requestId: randomUUID12(),
23974
+ requestId: randomUUID13(),
23878
23975
  title,
23879
23976
  body,
23880
23977
  prNumber,
@@ -24000,7 +24097,7 @@ async function comment2(path80, line, body, startLine) {
24000
24097
  }
24001
24098
 
24002
24099
  // src/commands/prs/edit.ts
24003
- import { randomUUID as randomUUID13 } from "crypto";
24100
+ import { randomUUID as randomUUID14 } from "crypto";
24004
24101
 
24005
24102
  // src/commands/prs/appendScreenshots.ts
24006
24103
  function appendScreenshots(body, screenshots) {
@@ -24197,7 +24294,7 @@ async function edit(options2) {
24197
24294
  if (process.env.ASSIST_SESSION === "1" && sessionId) {
24198
24295
  const decision = await awaitPreviewApproval("PR preview", {
24199
24296
  sessionId,
24200
- requestId: randomUUID13(),
24297
+ requestId: randomUUID14(),
24201
24298
  title: options2.title ?? title,
24202
24299
  body: newBody,
24203
24300
  prNumber: number
@@ -24908,7 +25005,7 @@ async function placePr(prNumber, title, body, options2) {
24908
25005
  }
24909
25006
 
24910
25007
  // src/commands/prs/previewAndPlace.ts
24911
- import { randomUUID as randomUUID14 } from "crypto";
25008
+ import { randomUUID as randomUUID15 } from "crypto";
24912
25009
 
24913
25010
  // src/commands/sessions/shared/requestSession.ts
24914
25011
  function parseIncoming(line, type) {
@@ -25043,7 +25140,7 @@ function warn(reason4) {
25043
25140
  async function previewAndPlace(args) {
25044
25141
  const decision = await awaitPreviewApproval("PR preview", {
25045
25142
  sessionId: args.sessionId,
25046
- requestId: randomUUID14(),
25143
+ requestId: randomUUID15(),
25047
25144
  title: args.title,
25048
25145
  body: args.body,
25049
25146
  prNumber: args.prNumber,
@@ -25259,7 +25356,7 @@ ${prConcisenessGuidance}
25259
25356
  }
25260
25357
 
25261
25358
  // src/commands/registerPrsEdit.ts
25262
- function collect4(value, previous) {
25359
+ function collect5(value, previous) {
25263
25360
  return previous.concat([value]);
25264
25361
  }
25265
25362
  function registerPrsEdit(prsCommand) {
@@ -25268,7 +25365,7 @@ function registerPrsEdit(prsCommand) {
25268
25365
  ).option("-t, --title <title>", "New title for the pull request").option("--what <what>", "Replace the ## What section").option("--why <why>", "Replace the ## Why section").option("--how <how>", "Replace the ## How section").option(
25269
25366
  "--resolves <key>",
25270
25367
  "Jira issue key resolved by this PR, appended to ## Why (repeatable)",
25271
- collect4,
25368
+ collect5,
25272
25369
  []
25273
25370
  ).addHelpText("after", () => editHelpText()).action(edit);
25274
25371
  }
@@ -25368,7 +25465,7 @@ ${confirm}
25368
25465
  }
25369
25466
 
25370
25467
  // src/commands/registerPrsRaise.ts
25371
- function collect5(value, previous) {
25468
+ function collect6(value, previous) {
25372
25469
  return previous.concat([value]);
25373
25470
  }
25374
25471
  function registerPrsRaise(prsCommand) {
@@ -25377,7 +25474,7 @@ function registerPrsRaise(prsCommand) {
25377
25474
  ).option("-t, --title <title>", "Title for the pull request").option("--what <what>", "What the change does (## What section)").option("--why <why>", "Why the change is needed (## Why section)").option("--how <how>", "How the change works (optional ## How section)").option(
25378
25475
  "--resolves <key>",
25379
25476
  "Jira issue key resolved by this PR, appended to ## Why (repeatable)",
25380
- collect5,
25477
+ collect6,
25381
25478
  []
25382
25479
  ).option(
25383
25480
  "--force",
@@ -25385,15 +25482,15 @@ function registerPrsRaise(prsCommand) {
25385
25482
  ).option("-B, --base <branch>", "Branch into which the pull request merges").option("-H, --head <branch>", "Branch that contains the commits").option("-d, --draft", "Mark the pull request as a draft").option(
25386
25483
  "--no-draft",
25387
25484
  "Create a ready-for-review pull request, overriding prs.draft"
25388
- ).option("-w, --web", "Open the browser to create the pull request").option("-l, --label <label>", "Add a label (repeatable)", collect5, []).option(
25485
+ ).option("-w, --web", "Open the browser to create the pull request").option("-l, --label <label>", "Add a label (repeatable)", collect6, []).option(
25389
25486
  "-a, --assignee <login>",
25390
25487
  "Assign a person by login (repeatable)",
25391
- collect5,
25488
+ collect6,
25392
25489
  []
25393
25490
  ).option(
25394
25491
  "-r, --reviewer <handle>",
25395
25492
  "Request a review (repeatable)",
25396
- collect5,
25493
+ collect6,
25397
25494
  []
25398
25495
  ).option("-m, --milestone <name>", "Add the pull request to a milestone").addHelpText("after", () => raiseHelpText()).action(raise);
25399
25496
  configHelp(raiseCommand, prsRaiseConfigHelp);
@@ -27515,10 +27612,10 @@ function registerRefactor(program2) {
27515
27612
  }
27516
27613
 
27517
27614
  // src/commands/review/checkoutOnlySession.ts
27518
- import { randomUUID as randomUUID15 } from "crypto";
27615
+ import { randomUUID as randomUUID16 } from "crypto";
27519
27616
  async function checkoutOnlySession(number) {
27520
27617
  await checkoutPr(number);
27521
- const claudeSessionId = randomUUID15();
27618
+ const claudeSessionId = randomUUID16();
27522
27619
  emitActivity({ kind: "command", name: "review", claudeSessionId });
27523
27620
  const { done: done2 } = spawnClaude("", {
27524
27621
  permissionMode: "acceptEdits",
@@ -32959,7 +33056,7 @@ var ClientHub = class extends Set {
32959
33056
  };
32960
33057
 
32961
33058
  // src/commands/sessions/daemon/createSession.ts
32962
- import { randomUUID as randomUUID16 } from "crypto";
33059
+ import { randomUUID as randomUUID17 } from "crypto";
32963
33060
 
32964
33061
  // src/commands/sessions/daemon/sessionBase.ts
32965
33062
  function sessionBase(id, status3) {
@@ -33155,7 +33252,7 @@ function spawnRun(opts) {
33155
33252
  function createSession(id, { prompt, cwd, design, auto, harness, holdPty } = {}) {
33156
33253
  if (harness && harness !== "claude")
33157
33254
  return createHarnessSession(id, harness, prompt, cwd, holdPty);
33158
- const claudeSessionId = randomUUID16();
33255
+ const claudeSessionId = randomUUID17();
33159
33256
  return {
33160
33257
  ...sessionBase(id, prompt ? "running" : "waiting"),
33161
33258
  name: `Session ${id}`,
@@ -33754,7 +33851,8 @@ var PREVIEW_KINDS = [
33754
33851
  "pr-comment",
33755
33852
  "github-issue",
33756
33853
  "github-issue-comment",
33757
- "github-issue-edit"
33854
+ "github-issue-edit",
33855
+ "miro-board"
33758
33856
  ];
33759
33857
  function isPreviewKind(value) {
33760
33858
  return PREVIEW_KINDS.includes(value);
@@ -33767,6 +33865,7 @@ function previewTargetLabel(kind, itemType, prNumber, draft) {
33767
33865
  if (kind === "github-issue-comment") return "github issue comment";
33768
33866
  if (kind === "github-issue-edit") return "github issue edit";
33769
33867
  if (kind === "github-issue") return "github issue";
33868
+ if (kind === "miro-board") return "miro anchors";
33770
33869
  if (kind === "backlog-item") return `backlog ${itemType}`;
33771
33870
  if (prNumber !== null) return `edit #${prNumber}`;
33772
33871
  return draft ? "create draft" : "create";
@@ -35226,7 +35325,7 @@ function codexRespawnPlan(session) {
35226
35325
  }
35227
35326
 
35228
35327
  // src/commands/sessions/daemon/interactiveRespawnPlan.ts
35229
- import { randomUUID as randomUUID17 } from "crypto";
35328
+ import { randomUUID as randomUUID18 } from "crypto";
35230
35329
  function interactiveRespawnPlan(session, resumes) {
35231
35330
  const { claudeSessionId, cwd, initialPrompt, design, auto } = session;
35232
35331
  if (!resumes) return null;
@@ -35246,7 +35345,7 @@ function interactiveRespawnPlan(session, resumes) {
35246
35345
  return null;
35247
35346
  }
35248
35347
  function freshClaudePlan(session, prompt, cwd) {
35249
- const claudeSessionId = randomUUID17();
35348
+ const claudeSessionId = randomUUID18();
35250
35349
  return {
35251
35350
  spawn: () => {
35252
35351
  session.claudeSessionId = claudeSessionId;
@@ -36131,10 +36230,10 @@ function startReusedRunPty(session, assistArgs, itemId2, hold, clients, onStatus
36131
36230
  }
36132
36231
 
36133
36232
  // src/commands/sessions/daemon/createWatcherSession.ts
36134
- import { randomUUID as randomUUID18 } from "crypto";
36233
+ import { randomUUID as randomUUID19 } from "crypto";
36135
36234
  var WATCH_PROMPT = "/watch";
36136
36235
  function createWatcherSession(id, cwd) {
36137
- const claudeSessionId = randomUUID18();
36236
+ const claudeSessionId = randomUUID19();
36138
36237
  return {
36139
36238
  ...sessionBase(id, "running"),
36140
36239
  name: `Session ${id}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.578.0",
3
+ "version": "0.580.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {