repowisestage 0.0.47 → 0.0.48

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.
Files changed (2) hide show
  1. package/dist/bin/repowise.js +181 -61
  2. package/package.json +1 -1
@@ -1316,6 +1316,7 @@ var init_sidecar_client = __esm({
1316
1316
  // ../listener/dist/lsp/lsp-tools.js
1317
1317
  var lsp_tools_exports = {};
1318
1318
  __export(lsp_tools_exports, {
1319
+ emptyLspResult: () => emptyLspResult,
1319
1320
  lspCallHierarchy: () => lspCallHierarchy,
1320
1321
  lspDefinition: () => lspDefinition,
1321
1322
  lspDocumentSymbol: () => lspDocumentSymbol,
@@ -1357,6 +1358,25 @@ function pickAvailableConfig(configs, isAvailable) {
1357
1358
  }
1358
1359
  return null;
1359
1360
  }
1361
+ function emptyLspResult(reason, details) {
1362
+ if (reason === "unsupported-language") {
1363
+ return {
1364
+ ok: false,
1365
+ reason,
1366
+ isError: true,
1367
+ error: "unsupported-language" + (details?.language ? `: ${details.language}` : "") + " \u2014 no LSP server registered for this file extension.",
1368
+ hint: "RepoWise auto-installs LSP servers for known languages (TS/JS, Python, Go, Rust, Ruby, etc.). For an unsupported language fall back to graph-only tools: `find_symbol`, `find_callers`, `find_references`, `get_call_graph`."
1369
+ };
1370
+ }
1371
+ const triedFrag = details?.tried && details.tried.length > 0 ? ` (tried: ${details.tried.join(", ")})` : "";
1372
+ return {
1373
+ ok: false,
1374
+ reason,
1375
+ isError: true,
1376
+ error: `no-server-available${triedFrag} \u2014 the LSP binary for this language isn't on PATH or in the listener's install dir.`,
1377
+ hint: "The listener auto-installs npm-based LSP servers (pyright, typescript-language-server, etc.) on boot. If the install failed, check listener stderr for the underlying npm error. Non-npm servers (gopls, rust-analyzer, sourcekit-lsp, ruby-lsp) need manual install \u2014 see the listener log for the per-language hint. Until then, use graph-only tools (`find_symbol`, `find_callers`, etc.) for this file."
1378
+ };
1379
+ }
1360
1380
  function toOneIndexed(pos) {
1361
1381
  return { line: pos.line + 1, column: pos.character + 1 };
1362
1382
  }
@@ -1419,13 +1439,13 @@ function normalizeLocations(raw, repoRoot) {
1419
1439
  async function getSession(deps, file) {
1420
1440
  const language = detectLanguage(file);
1421
1441
  if (!language)
1422
- return { ok: false, reason: "unsupported-language" };
1442
+ return emptyLspResult("unsupported-language");
1423
1443
  const configs = LSP_REGISTRY[language];
1424
1444
  const config2 = pickAvailableConfig(configs, deps.binaryAvailable);
1425
1445
  if (!config2) {
1426
- const tried = configs.map((c) => c.command).join(", ");
1427
- console.warn(`[lsp:${language}] no server available on PATH \u2014 tried: ${tried}`);
1428
- return { ok: false, reason: "no-server-available" };
1446
+ const tried = configs.map((c) => c.command);
1447
+ console.warn(`[lsp:${language}] no server available on PATH \u2014 tried: ${tried.join(", ")}`);
1448
+ return emptyLspResult("no-server-available", { language, tried });
1429
1449
  }
1430
1450
  const session = await deps.workspaces.getOrOpen({
1431
1451
  repoRoot: deps.repoRoot,
@@ -1438,7 +1458,7 @@ async function getSession(deps, file) {
1438
1458
  async function lspDefinition(deps, req) {
1439
1459
  const got = await getSession(deps, req.file);
1440
1460
  if (!got.ok)
1441
- return { ok: false, reason: got.reason };
1461
+ return got;
1442
1462
  const result = await got.session.client.request("textDocument/definition", {
1443
1463
  textDocument: { uri: got.uri },
1444
1464
  position: toZeroIndexed(req.position)
@@ -1448,7 +1468,7 @@ async function lspDefinition(deps, req) {
1448
1468
  async function lspReferences(deps, req) {
1449
1469
  const got = await getSession(deps, req.file);
1450
1470
  if (!got.ok)
1451
- return { ok: false, reason: got.reason };
1471
+ return got;
1452
1472
  const result = await got.session.client.request("textDocument/references", {
1453
1473
  textDocument: { uri: got.uri },
1454
1474
  position: toZeroIndexed(req.position),
@@ -1459,7 +1479,7 @@ async function lspReferences(deps, req) {
1459
1479
  async function lspHover(deps, req) {
1460
1480
  const got = await getSession(deps, req.file);
1461
1481
  if (!got.ok)
1462
- return { ok: false, reason: got.reason };
1482
+ return got;
1463
1483
  const result = await got.session.client.request("textDocument/hover", {
1464
1484
  textDocument: { uri: got.uri },
1465
1485
  position: toZeroIndexed(req.position)
@@ -1502,7 +1522,7 @@ function normalizeHoverContents(contents) {
1502
1522
  async function lspCallHierarchy(deps, req) {
1503
1523
  const got = await getSession(deps, req.file);
1504
1524
  if (!got.ok)
1505
- return { ok: false, reason: got.reason };
1525
+ return got;
1506
1526
  const limit = req.limit ?? 200;
1507
1527
  const prepared = await got.session.client.request("textDocument/prepareCallHierarchy", {
1508
1528
  textDocument: { uri: got.uri },
@@ -1541,7 +1561,7 @@ async function lspCallHierarchy(deps, req) {
1541
1561
  async function lspImplementation(deps, req) {
1542
1562
  const got = await getSession(deps, req.file);
1543
1563
  if (!got.ok)
1544
- return { ok: false, reason: got.reason };
1564
+ return got;
1545
1565
  const result = await got.session.client.request("textDocument/implementation", {
1546
1566
  textDocument: { uri: got.uri },
1547
1567
  position: toZeroIndexed(req.position)
@@ -1551,7 +1571,7 @@ async function lspImplementation(deps, req) {
1551
1571
  async function lspTypeHierarchy(deps, req) {
1552
1572
  const got = await getSession(deps, req.file);
1553
1573
  if (!got.ok)
1554
- return { ok: false, reason: got.reason };
1574
+ return got;
1555
1575
  const limit = req.limit ?? 200;
1556
1576
  const prepared = await got.session.client.request("textDocument/prepareTypeHierarchy", {
1557
1577
  textDocument: { uri: got.uri },
@@ -1587,8 +1607,11 @@ async function lspTypeHierarchy(deps, req) {
1587
1607
  }
1588
1608
  async function lspWorkspaceSymbol(deps, req) {
1589
1609
  const sessions = deps.workspaces.activeSessions().filter((s) => !req.language || s.language === req.language);
1590
- if (sessions.length === 0)
1591
- return { ok: false, reason: "no-server-available" };
1610
+ if (sessions.length === 0) {
1611
+ return emptyLspResult("no-server-available", {
1612
+ language: req.language
1613
+ });
1614
+ }
1592
1615
  const symbols = [];
1593
1616
  for (const session of sessions) {
1594
1617
  const raw = await session.client.request("workspace/symbol", { query: req.query });
@@ -1616,7 +1639,7 @@ async function lspWorkspaceSymbol(deps, req) {
1616
1639
  async function lspDocumentSymbol(deps, req) {
1617
1640
  const got = await getSession(deps, req.file);
1618
1641
  if (!got.ok)
1619
- return { ok: false, reason: got.reason };
1642
+ return got;
1620
1643
  const raw = await got.session.client.request("textDocument/documentSymbol", {
1621
1644
  textDocument: { uri: got.uri }
1622
1645
  });
@@ -4333,8 +4356,8 @@ var TOOL_CATALOG = [
4333
4356
  },
4334
4357
  {
4335
4358
  name: "search_pattern",
4336
- description: "Regex-match symbol names across the graph.",
4337
- whenToUse: 'Use when the user asks for a pattern rather than a literal substring \u2014 e.g. "anything ending in `Repository`", "every `handle*` function". For plain substring search use `find_symbol`.',
4359
+ description: "JavaScript-flavor regex match against symbol names. Uses `new RegExp(pattern, flags)` \u2014 no Python-only constructs (`(?P<name>...)`, `(?i)`-style inline flags, `\\A` / `\\Z` anchors).",
4360
+ whenToUse: 'Use when the user asks for a pattern rather than a literal substring \u2014 e.g. "anything ending in `Repository`", "every `handle*` function". For plain substring search use `find_symbol`. For case-insensitive matching set `flags: "i"`, NOT a `(?i)` prefix.',
4338
4361
  inputSchema: {
4339
4362
  type: "object",
4340
4363
  properties: {
@@ -4801,16 +4824,31 @@ function listEdges(graphJson, req) {
4801
4824
  freshness: freshnessEnvelope(graph)
4802
4825
  };
4803
4826
  }
4827
+ function detectCommonRegexMistake(pattern) {
4828
+ if (/\(\?P</.test(pattern)) {
4829
+ return "Python named groups `(?P<name>\u2026)` aren't supported. Use `(?<name>\u2026)` (JS named-group syntax) or just `(\u2026)`.";
4830
+ }
4831
+ if (/^\(\?[ims]+\)/.test(pattern)) {
4832
+ return 'Python-style inline flags `(?i)` aren\'t supported. Pass them as the `flags` parameter, e.g. `flags: "i"`.';
4833
+ }
4834
+ if (/\\A|\\Z/.test(pattern)) {
4835
+ return "Python anchors `\\A` / `\\Z` are valid JS regex but match LITERAL `A` / `Z`, not start-of-string / end-of-string. Use `^` / `$` (JS anchors) with the `m` flag for multiline.";
4836
+ }
4837
+ return void 0;
4838
+ }
4804
4839
  var MAX_PATTERN_LENGTH = 200;
4805
4840
  var REDOS_PATTERN = /(\([^)]*[+*]\)|\[[^\]]*[+*]\])[+*?]/;
4806
4841
  function searchPattern(graphJson, req) {
4807
4842
  const graph = graphJson;
4808
4843
  if (!req.pattern || req.pattern.length > MAX_PATTERN_LENGTH) {
4844
+ const reason = !req.pattern ? "Empty pattern \u2014 pass a non-empty regex string." : `Pattern exceeds ${MAX_PATTERN_LENGTH.toString()} chars (${req.pattern.length.toString()} chars). Use a tighter expression or filter via \`kind\` / \`language\` / \`file\`.`;
4809
4845
  return {
4810
4846
  matches: [],
4811
4847
  coverage: coverageEnvelope(graph, 0),
4812
4848
  freshness: freshnessEnvelope(graph),
4813
- unsafePattern: true
4849
+ unsafePattern: true,
4850
+ error: reason,
4851
+ isError: true
4814
4852
  };
4815
4853
  }
4816
4854
  if (REDOS_PATTERN.test(req.pattern)) {
@@ -4818,19 +4856,26 @@ function searchPattern(graphJson, req) {
4818
4856
  matches: [],
4819
4857
  coverage: coverageEnvelope(graph, 0),
4820
4858
  freshness: freshnessEnvelope(graph),
4821
- unsafePattern: true
4859
+ unsafePattern: true,
4860
+ error: "Pattern rejected by ReDoS guard \u2014 nested quantifiers like `(a+)+` or `[\u2026]*+` can cause catastrophic backtracking. Flatten the quantifiers or split into multiple calls.",
4861
+ isError: true
4822
4862
  };
4823
4863
  }
4824
4864
  const flags = (req.flags ?? "").replace(/g/g, "");
4825
4865
  let re;
4826
4866
  try {
4827
4867
  re = new RegExp(req.pattern, flags);
4828
- } catch {
4868
+ } catch (err) {
4869
+ const msg = err instanceof Error ? err.message : String(err);
4870
+ const hint = detectCommonRegexMistake(req.pattern);
4829
4871
  return {
4830
4872
  matches: [],
4831
4873
  coverage: coverageEnvelope(graph, 0),
4832
4874
  freshness: freshnessEnvelope(graph),
4833
- invalidPattern: true
4875
+ invalidPattern: true,
4876
+ error: msg,
4877
+ ...hint ? { hint } : {},
4878
+ isError: true
4834
4879
  };
4835
4880
  }
4836
4881
  const kinds = normaliseFilter(req.kind);
@@ -4866,10 +4911,12 @@ function searchPattern(graphJson, req) {
4866
4911
  return bScore - aScore;
4867
4912
  return a.id.localeCompare(b.id);
4868
4913
  });
4914
+ const proactiveHint = matches.length === 0 ? detectCommonRegexMistake(req.pattern) : void 0;
4869
4915
  return {
4870
4916
  matches: matches.slice(0, limit),
4871
4917
  coverage: coverageEnvelope(graph, matches.length),
4872
- freshness: freshnessEnvelope(graph)
4918
+ freshness: freshnessEnvelope(graph),
4919
+ ...proactiveHint ? { hint: proactiveHint } : {}
4873
4920
  };
4874
4921
  }
4875
4922
  function batchQuery(graphJson, req) {
@@ -4893,11 +4940,7 @@ function batchQuery(graphJson, req) {
4893
4940
  try {
4894
4941
  switch (toolName) {
4895
4942
  case "find_symbol":
4896
- return {
4897
- ok: true,
4898
- tool: toolName,
4899
- result: findSymbol(graph, args)
4900
- };
4943
+ return { ok: true, tool: toolName, result: findSymbol(graph, args) };
4901
4944
  case "get_symbol":
4902
4945
  return { ok: true, tool: toolName, result: getSymbol(graph, args) };
4903
4946
  case "get_impact":
@@ -4910,11 +4953,47 @@ function batchQuery(graphJson, req) {
4910
4953
  tool: toolName,
4911
4954
  result: searchPattern(graph, args)
4912
4955
  };
4956
+ // The 7 graph tools below were advertised by the schema's
4957
+ // whenToUse but missing from the switch — Claude calling
4958
+ // batch_query with `find_callers` etc. used to hit the
4959
+ // "unsupported sub-query tool" branch and bail. Wired up here
4960
+ // so the catalog promise matches the implementation.
4961
+ case "find_callers":
4962
+ return {
4963
+ ok: true,
4964
+ tool: toolName,
4965
+ result: findCallers(graph, args)
4966
+ };
4967
+ case "find_references":
4968
+ return {
4969
+ ok: true,
4970
+ tool: toolName,
4971
+ result: findReferences(graph, args)
4972
+ };
4973
+ case "get_deps":
4974
+ return { ok: true, tool: toolName, result: getDeps(graph, args) };
4975
+ case "get_call_graph":
4976
+ return {
4977
+ ok: true,
4978
+ tool: toolName,
4979
+ result: getCallGraph(graph, args)
4980
+ };
4981
+ case "find_tests_for_symbol":
4982
+ return {
4983
+ ok: true,
4984
+ tool: toolName,
4985
+ result: findTestsForSymbol(graph, args)
4986
+ };
4987
+ case "get_todos":
4988
+ return { ok: true, tool: toolName, result: getTodos(graph, args) };
4989
+ case "get_freshness":
4990
+ return { ok: true, tool: toolName, result: getFreshness(graph) };
4913
4991
  default:
4914
4992
  return {
4915
4993
  ok: false,
4916
4994
  tool: toolName,
4917
- error: `unsupported sub-query tool: ${String(toolName)}`
4995
+ error: `unsupported sub-query tool: ${String(toolName)}`,
4996
+ hint: `Supported tools: find_symbol, get_symbol, get_impact, list_edges, search_pattern, find_callers, find_references, get_deps, get_call_graph, find_tests_for_symbol, get_todos, get_freshness.`
4918
4997
  };
4919
4998
  }
4920
4999
  } catch (err) {
@@ -4925,7 +5004,15 @@ function batchQuery(graphJson, req) {
4925
5004
  };
4926
5005
  }
4927
5006
  });
4928
- return { results, freshness: freshnessEnvelope(graph), droppedCount };
5007
+ const failedCount = results.filter((r) => !r.ok).length;
5008
+ const isError = queries.length > 0 && failedCount === queries.length;
5009
+ return {
5010
+ results,
5011
+ freshness: freshnessEnvelope(graph),
5012
+ droppedCount,
5013
+ failedCount,
5014
+ ...isError ? { isError: true } : {}
5015
+ };
4929
5016
  }
4930
5017
  function findCallers(graphJson, req) {
4931
5018
  const graph = graphJson;
@@ -5181,62 +5268,73 @@ function handleRequest(req, res, options, sessions, secretCtx) {
5181
5268
  }).catch((err) => sendJson(res, 500, { error: err instanceof Error ? err.message : String(err) }));
5182
5269
  return;
5183
5270
  }
5184
- function validationError(msg) {
5185
- return { __validationError: msg };
5271
+ function validationError(error, hint) {
5272
+ return { __validationError: { error, hint } };
5186
5273
  }
5187
5274
  function isValidationError(v) {
5188
5275
  return typeof v === "object" && v !== null && "__validationError" in v;
5189
5276
  }
5277
+ const HINT_USE_FIND_SYMBOL_FIRST = "To get a valid `id`, call `find_symbol` (fuzzy name match) or `search_pattern` (regex) first; pass the resulting `matches[].id` here.";
5190
5278
  const toolDispatch = {
5191
5279
  "/mcp/tools/find_symbol": (g, b) => {
5192
- if (typeof b["query"] !== "string")
5193
- return validationError("query required (string)");
5280
+ if (typeof b["query"] !== "string") {
5281
+ return validationError("query required (string)", "Pass a name or substring to fuzzy-match against. For regex use `search_pattern`.");
5282
+ }
5194
5283
  return findSymbol(g, b);
5195
5284
  },
5196
5285
  "/mcp/tools/get_symbol": (g, b) => {
5197
- if (typeof b["id"] !== "string")
5198
- return validationError("id required (string)");
5286
+ if (typeof b["id"] !== "string") {
5287
+ return validationError("id required (string)", HINT_USE_FIND_SYMBOL_FIRST);
5288
+ }
5199
5289
  return getSymbol(g, b);
5200
5290
  },
5201
5291
  "/mcp/tools/get_impact": (g, b) => {
5202
- if (typeof b["id"] !== "string")
5203
- return validationError("id required (string)");
5292
+ if (typeof b["id"] !== "string") {
5293
+ return validationError("id required (string)", HINT_USE_FIND_SYMBOL_FIRST);
5294
+ }
5204
5295
  return getImpact(g, b);
5205
5296
  },
5206
5297
  "/mcp/tools/list_edges": (g, b) => listEdges(g, b),
5207
5298
  "/mcp/tools/search_pattern": (g, b) => {
5208
- if (typeof b["pattern"] !== "string")
5209
- return validationError("pattern required (string)");
5299
+ if (typeof b["pattern"] !== "string") {
5300
+ return validationError("pattern required (string)", "Pattern is a JavaScript regex string (no Python `(?P<>` / `(?i)` syntax). For literal substring search use `find_symbol` instead.");
5301
+ }
5210
5302
  return searchPattern(g, b);
5211
5303
  },
5212
5304
  "/mcp/tools/batch_query": (g, b) => {
5213
- if (!Array.isArray(b["queries"]))
5214
- return validationError("queries required (array)");
5305
+ if (!Array.isArray(b["queries"])) {
5306
+ return validationError("queries required (array)", "Pass an array of `{tool, params}` (or `{tool, arguments}`) objects. Up to 10 sub-queries per batch. See the schema for valid `tool` values.");
5307
+ }
5215
5308
  return batchQuery(g, b);
5216
5309
  },
5217
5310
  "/mcp/tools/find_callers": (g, b) => {
5218
- if (typeof b["id"] !== "string")
5219
- return validationError("id required (string)");
5311
+ if (typeof b["id"] !== "string") {
5312
+ return validationError("id required (string)", HINT_USE_FIND_SYMBOL_FIRST);
5313
+ }
5220
5314
  return findCallers(g, b);
5221
5315
  },
5222
5316
  "/mcp/tools/find_references": (g, b) => {
5223
- if (typeof b["id"] !== "string")
5224
- return validationError("id required (string)");
5317
+ if (typeof b["id"] !== "string") {
5318
+ return validationError("id required (string)", HINT_USE_FIND_SYMBOL_FIRST);
5319
+ }
5225
5320
  return findReferences(g, b);
5226
5321
  },
5227
5322
  "/mcp/tools/get_deps": (g, b) => {
5228
- if (typeof b["file"] !== "string")
5229
- return validationError("file required (string)");
5323
+ if (typeof b["file"] !== "string") {
5324
+ return validationError("file required (string)", "Pass a repo-relative file path (e.g., `src/main.py`, NOT an absolute path or symbol id).");
5325
+ }
5230
5326
  return getDeps(g, b);
5231
5327
  },
5232
5328
  "/mcp/tools/get_call_graph": (g, b) => {
5233
- if (typeof b["id"] !== "string")
5234
- return validationError("id required (string)");
5329
+ if (typeof b["id"] !== "string") {
5330
+ return validationError("id required (string)", HINT_USE_FIND_SYMBOL_FIRST);
5331
+ }
5235
5332
  return getCallGraph(g, b);
5236
5333
  },
5237
5334
  "/mcp/tools/find_tests_for_symbol": (g, b) => {
5238
- if (typeof b["id"] !== "string")
5239
- return validationError("id required (string)");
5335
+ if (typeof b["id"] !== "string") {
5336
+ return validationError("id required (string)", HINT_USE_FIND_SYMBOL_FIRST);
5337
+ }
5240
5338
  return findTestsForSymbol(g, b);
5241
5339
  },
5242
5340
  "/mcp/tools/get_todos": (g, b) => getTodos(g, b),
@@ -5297,11 +5395,11 @@ function handleRequest(req, res, options, sessions, secretCtx) {
5297
5395
  const root = getRepoIdToRoot().get(session.repoId) ?? fallbackRoot;
5298
5396
  if (!root) {
5299
5397
  return {
5300
- ok: false,
5301
- status: 400,
5302
- body: {
5398
+ ok: true,
5399
+ value: {
5303
5400
  error: "unknown_repo",
5304
- message: `no workspace root registered for repoId ${session.repoId}`
5401
+ hint: `LSP tool dispatch needs a workspace root for repoId ${session.repoId}, but none is registered. This usually means the listener hasn't yet reconciled the repo's localPath. Use graph-only tools (find_symbol, find_callers, etc.) until reconcile completes.`,
5402
+ isError: true
5305
5403
  }
5306
5404
  };
5307
5405
  }
@@ -5315,11 +5413,25 @@ function handleRequest(req, res, options, sessions, secretCtx) {
5315
5413
  dispatchSessionTool(req, res, url, sessions, options.mcpLogger, async (session, body) => {
5316
5414
  const graph = options.graphCache.peek(session.repoId);
5317
5415
  if (!graph) {
5318
- return { ok: false, status: 503, body: { error: "graph_not_loaded" } };
5416
+ return {
5417
+ ok: true,
5418
+ value: {
5419
+ error: "graph_not_loaded",
5420
+ hint: "The graph for this repo is still downloading or has been invalidated. Retry in a few seconds; if the problem persists, the listener may not have completed the initial sync.",
5421
+ isError: true
5422
+ }
5423
+ };
5319
5424
  }
5320
5425
  const raw = handler(graph, body);
5321
5426
  if (isValidationError(raw)) {
5322
- return { ok: false, status: 400, body: { error: raw.__validationError } };
5427
+ return {
5428
+ ok: true,
5429
+ value: {
5430
+ error: raw.__validationError.error,
5431
+ hint: raw.__validationError.hint,
5432
+ isError: true
5433
+ }
5434
+ };
5323
5435
  }
5324
5436
  const resolved = await Promise.race([
5325
5437
  raw instanceof Promise ? raw : Promise.resolve(raw),
@@ -5396,12 +5508,18 @@ function dispatchSessionTool(req, res, url, sessions, logger, handler) {
5396
5508
  });
5397
5509
  logToStdout("error", tool, session.repoId, Date.now() - startedAt, safeMsg);
5398
5510
  if (isTimeout) {
5399
- return sendJson(res, 504, { error: "tool-timeout", tool });
5511
+ return sendJson(res, 200, {
5512
+ error: `tool-timeout: ${tool} exceeded its execution budget`,
5513
+ hint: "The tool was killed at its per-tool timeout. Try a narrower query (smaller limit, depth, or filter) or split into multiple calls.",
5514
+ isError: true,
5515
+ tool
5516
+ });
5400
5517
  }
5401
- return sendJson(res, 500, {
5402
- error: "tool_error",
5403
- tool,
5404
- message: safeMsg
5518
+ return sendJson(res, 200, {
5519
+ error: `tool_error: ${safeMsg}`,
5520
+ hint: "The tool threw an unexpected exception. This is a server-side bug \u2014 file an issue with the tool name and the error text.",
5521
+ isError: true,
5522
+ tool
5405
5523
  });
5406
5524
  }
5407
5525
  }).catch((err) => {
@@ -10738,11 +10856,13 @@ async function routeMessage(endpoint, repoId, message, postJson, getJson, header
10738
10856
  sessionState.sessionId = fresh;
10739
10857
  result = await callTool(fresh);
10740
10858
  }
10859
+ const inner = result ?? {};
10741
10860
  return {
10742
10861
  jsonrpc: "2.0",
10743
10862
  id: rpcId,
10744
10863
  result: {
10745
- content: [{ type: "text", text: JSON.stringify(result) }]
10864
+ content: [{ type: "text", text: JSON.stringify(result) }],
10865
+ ...inner.isError === true ? { isError: true } : {}
10746
10866
  }
10747
10867
  };
10748
10868
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repowisestage",
3
- "version": "0.0.47",
3
+ "version": "0.0.48",
4
4
  "type": "module",
5
5
  "description": "AI-optimized codebase context generator",
6
6
  "bin": {