querysub 0.683.0 → 0.685.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "querysub",
3
- "version": "0.683.0",
3
+ "version": "0.685.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
@@ -14,6 +14,7 @@ module.hotreload = false;
14
14
 
15
15
  const PARALLEL_FILE_SEARCHES = 4;
16
16
  const DEFAULT_LIMIT = 100;
17
+ const MAX_LIMIT = 10_000;
17
18
  // Compressed input bytes of downloaded files to keep resident.
18
19
  const DOWNLOAD_CACHE_MAX_BYTES = 1024 ** 3;
19
20
  // Decoded output bytes (estimated via serialized length) of decoded files to keep resident. Sized independently of the download cache because the decoded form is much larger than the compressed download.
@@ -125,6 +126,9 @@ export async function searchStorageLogsForMCP(config: {
125
126
  throw new Error(`startTime (${startTime}) must be < endTime (${endTime})`);
126
127
  }
127
128
  let limit = config.limit ?? DEFAULT_LIMIT;
129
+ if (limit > MAX_LIMIT) {
130
+ throw new Error(`limit ${limit} > ${MAX_LIMIT}. This endpoint returns projected rows over a socket, it is not a bulk export. If you need to aggregate large volumes, list the log files and download + parse them directly.`);
131
+ }
128
132
  let direction = config.direction ?? "fromEnd";
129
133
  let columns = config.columns && (config.columns.includes("time") ? config.columns : ["time", ...config.columns]);
130
134
  let clauses = parseSearchClauses(query);
@@ -32,6 +32,7 @@ const COMMENT_TEXTAREA_COLLAPSED_HEIGHT = 40;
32
32
  export const STATE_HUES: Record<TicketState, number> = {
33
33
  "investigation": 45,
34
34
  "code-change": 210,
35
+ "manual-fix-required": 20,
35
36
  "fixed": 120,
36
37
  "not-a-bug": 280,
37
38
  "confused": 330,
@@ -331,9 +332,6 @@ class TicketDetail extends qreact.Component<{ ticketId: string }> {
331
332
 
332
333
  let sortedComments = [...ticket.comments];
333
334
  sort(sortedComments, x => -x.time);
334
- // Chronological, because patches on the same file build on each other in the order they were proposed.
335
- let patchComments = ticket.comments.filter(c => c.kind === "patch" && c.patchFiles);
336
- sort(patchComments, x => x.time);
337
335
  return <div className={css.vbox(16).pad2(16).fillBoth.maxWidth("100%").minHeight(0)}>
338
336
  <div className={css.hbox(16).alignItems("center")}>
339
337
  <ATag values={[ticketIdURL.getOverride("")]}>← All Tickets</ATag>
@@ -411,21 +409,6 @@ class TicketDetail extends qreact.Component<{ ticketId: string }> {
411
409
  <div className={css.vbox(12).fillWidth.flexGrow(1).minHeight(0).overflowAuto}>
412
410
  <div className={css.hbox(16).alignItems("center")}>
413
411
  <h3 className={css.margin(0)}>Comments ({sortedComments.length})</h3>
414
- {patchComments.length > 0 && (
415
- <Button
416
- hue={120}
417
- onClick={() => {
418
- let ticketId = this.props.ticketId;
419
- let commentIds = patchComments.map(c => c.id);
420
- Querysub.onCommitFinished(async () => {
421
- await getController().applyPatches.promise(ticketId, commentIds);
422
- resetTicketData();
423
- });
424
- }}
425
- >
426
- Apply All Patches ({patchComments.length})
427
- </Button>
428
- )}
429
412
  </div>
430
413
  {sortedComments.map(comment => (
431
414
  <TicketCommentItem key={comment.id} ticketId={this.props.ticketId} comment={comment} />
@@ -661,6 +644,22 @@ class TicketCommentItem extends qreact.Component<{
661
644
  >
662
645
  Delete
663
646
  </Button>
647
+ {comment.kind === "patch" && comment.patchFiles && (
648
+ <Button
649
+ hue={120}
650
+ flavor="small"
651
+ onClick={() => {
652
+ let ticketId = this.props.ticketId;
653
+ let commentId = comment.id;
654
+ Querysub.onCommitFinished(async () => {
655
+ await getController().applyPatches.promise(ticketId, [commentId]);
656
+ resetTicketData();
657
+ });
658
+ }}
659
+ >
660
+ Apply Patch
661
+ </Button>
662
+ )}
664
663
  {searchInfo && (
665
664
  <>
666
665
  <span className={css.fontSize(12).whiteSpace("nowrap")}>{searchInfo.rangeText}</span>
@@ -399,11 +399,11 @@ Query syntax (case-insensitive substring match by default):
399
399
  },
400
400
  {
401
401
  name: "setTicketState",
402
- description: `Set the state of the ticket you are investigating. Use "code-change" once you have proposed patches, "not-a-bug" if the error should simply be ignored, or "confused" if you genuinely cannot figure out what is going on.`,
402
+ description: `Set the state of the ticket you are investigating. Use "code-change" once you have proposed patches, "manual-fix-required" if you know what is wrong but cannot express the fix as a patch, "not-a-bug" if the error should simply be ignored, or "confused" if you genuinely cannot figure out what is going on.`,
403
403
  inputSchema: {
404
404
  type: "object",
405
405
  properties: {
406
- state: { type: "string", enum: ["code-change", "not-a-bug", "confused"] },
406
+ state: { type: "string", enum: ["code-change", "manual-fix-required", "not-a-bug", "confused"] },
407
407
  },
408
408
  required: ["state"],
409
409
  },
@@ -504,8 +504,8 @@ async function callTool(toolName: string, args: Record<string, unknown>): Promis
504
504
  result = await getNodeInfos();
505
505
  } else if (toolName === "setTicketState") {
506
506
  let state = String(args.state ?? "") as TicketState;
507
- if (state !== "code-change" && state !== "not-a-bug" && state !== "confused") {
508
- throw new Error(`setTicketState only allows "code-change", "not-a-bug", or "confused"`);
507
+ if (state !== "code-change" && state !== "manual-fix-required" && state !== "not-a-bug" && state !== "confused") {
508
+ throw new Error(`setTicketState only allows "code-change", "manual-fix-required", "not-a-bug", or "confused"`);
509
509
  }
510
510
  let service = await ticketService();
511
511
  await service.setTicketState(ticketId, state);
@@ -673,7 +673,7 @@ PHASE 2 — FIX. Only after you have added your diagnosis comment, decide on the
673
673
  3. Gathering more information: if you could NOT determine the root cause from the available logs, propose patches that ADD logging statements to the relevant code paths so the next investigation has the information it needs.
674
674
  Each patch file entry is { file, oldText, newText }: oldText must be copied exactly from the current file contents and should be unique within the file; it is replaced with newText. An empty oldText creates a new file. Relative file paths are resolved against the application repository (${process.cwd()}) first, then against the querysub repository (${QUERYSUB_ROOT}) — whichever contains the file. Absolute paths also work. Keep patches minimal and follow the style of the surrounding code.
675
675
 
676
- When you are done, call mcp__autofixer__setTicketState with "code-change" if you proposed patches, or "not-a-bug" if the error should simply be ignored without any code change. If you are confused and just cannot figure out what is going on — the logs and code don't add up, and you can't even propose useful additional logging — add a comment explaining what you tried and what confused you, then call mcp__autofixer__setTicketState with "confused". Do NOT edit files directly — only propose changes through mcp__autofixer__addPatch.
676
+ When you are done, call mcp__autofixer__setTicketState with "code-change" if you proposed patches, or "not-a-bug" if the error should simply be ignored without any code change. If you diagnosed the problem but the fix cannot be expressed as a patch — it needs a design decision, a change outside these repositories, or manual intervention on a machine — add a comment saying exactly what a human has to do, then call mcp__autofixer__setTicketState with "manual-fix-required". If you are confused and just cannot figure out what is going on — the logs and code don't add up, and you can't even propose useful additional logging — add a comment explaining what you tried and what confused you, then call mcp__autofixer__setTicketState with "confused". Do NOT edit files directly — only propose changes through mcp__autofixer__addPatch.
677
677
 
678
678
  ==== TICKET ====
679
679
  Title: ${ticket.title}
@@ -1,7 +1,7 @@
1
1
  import { LogDatum } from "../diskLogger";
2
2
 
3
- export type TicketState = "investigation" | "code-change" | "fixed" | "not-a-bug" | "confused" | "timed-out";
4
- export const TICKET_STATES: TicketState[] = ["investigation", "code-change", "fixed", "not-a-bug", "confused", "timed-out"];
3
+ export type TicketState = "investigation" | "code-change" | "manual-fix-required" | "fixed" | "not-a-bug" | "confused" | "timed-out";
4
+ export const TICKET_STATES: TicketState[] = ["investigation", "code-change", "manual-fix-required", "fixed", "not-a-bug", "confused", "timed-out"];
5
5
 
6
6
  export const TICKET_FINAL_STATES: TicketState[] = ["fixed", "not-a-bug"];
7
7
  export function isTicketFinished(state: TicketState): boolean {