@sentry/junior 0.118.0 → 0.120.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.
Files changed (56) hide show
  1. package/dist/{agent-hooks-J2FB7XD6.js → agent-hooks-5DDPWRYO.js} +8 -8
  2. package/dist/api/conversations/detail.d.ts +17 -0
  3. package/dist/api/conversations/event-list.d.ts +17 -0
  4. package/dist/api/schema/conversation.d.ts +68 -0
  5. package/dist/api/schema.js +1 -1
  6. package/dist/api.js +103 -82
  7. package/dist/app.js +24 -24
  8. package/dist/build/copy-build-content.d.ts +2 -2
  9. package/dist/{catalog-runtime-UHHLU53I.js → catalog-runtime-5KR5XBMJ.js} +7 -7
  10. package/dist/chat/discovery.d.ts +2 -0
  11. package/dist/chat/mcp/tool-manager.d.ts +14 -1
  12. package/dist/chat/plugins/types.d.ts +3 -9
  13. package/dist/chat/plugins/user-pages.d.ts +2 -1
  14. package/dist/chat/slack/tools/canvas/api.d.ts +2 -9
  15. package/dist/chat/slack/tools/canvas/markdown.d.ts +9 -0
  16. package/dist/{chunk-GT2ZUALJ.js → chunk-24B5R6OU.js} +92 -6
  17. package/dist/{chunk-L72GDKSN.js → chunk-6WX5SPI3.js} +1 -1
  18. package/dist/{chunk-3N3FMCKN.js → chunk-ALAKN7LR.js} +1 -1
  19. package/dist/{chunk-MLZFK4KP.js → chunk-ALYQOZG7.js} +1 -1
  20. package/dist/{chunk-6BGUAOYP.js → chunk-BHXW734F.js} +13 -7
  21. package/dist/{chunk-4LPPH7Y6.js → chunk-DJDGDJDF.js} +4 -4
  22. package/dist/{chunk-HWUBBHLK.js → chunk-DMKHRBI6.js} +4 -3
  23. package/dist/{chunk-QWCF4RAC.js → chunk-DWOH57FW.js} +1 -1
  24. package/dist/{chunk-7GADTCNS.js → chunk-EIVE6GL4.js} +3 -3
  25. package/dist/{chunk-6K2QE2UI.js → chunk-ERYVNWNE.js} +250 -37
  26. package/dist/{chunk-UXLYAVYL.js → chunk-GNNV3UTY.js} +1 -1
  27. package/dist/chunk-H4HBKISO.js +417 -0
  28. package/dist/{chunk-FXOYURO4.js → chunk-HDFGNU5E.js} +1 -0
  29. package/dist/{chunk-PJPKHGLG.js → chunk-JQWP6V22.js} +4 -11
  30. package/dist/{chunk-KC5EE27Y.js → chunk-M243JMZH.js} +2 -2
  31. package/dist/{chunk-7SM3P4XR.js → chunk-O2ULQJWR.js} +82 -1
  32. package/dist/{chunk-B3IT5END.js → chunk-OOUNJNMR.js} +16 -152
  33. package/dist/{chunk-HN6LFYG3.js → chunk-Q3RL6A4E.js} +2 -2
  34. package/dist/{chunk-3MUSSFMP.js → chunk-QOQPPRFS.js} +221 -14
  35. package/dist/{chunk-S6R23MFB.js → chunk-TKUCRFNX.js} +12 -225
  36. package/dist/{chunk-PWRFTDTY.js → chunk-VURFJVFH.js} +2 -2
  37. package/dist/{chunk-3LGCVRBQ.js → chunk-XAI2HNAY.js} +9 -5
  38. package/dist/{chunk-4SOQPUF4.js → chunk-YEAOUT5W.js} +1 -1
  39. package/dist/cli/chat.js +24 -24
  40. package/dist/cli/check.js +8 -8
  41. package/dist/cli/init.js +2 -2
  42. package/dist/cli/plugins.js +13 -13
  43. package/dist/cli/snapshot-create.js +11 -11
  44. package/dist/cli/upgrade.js +8 -8
  45. package/dist/{db-PMRHFSYL.js → db-T4ZY64PB.js} +6 -6
  46. package/dist/{discovery-RMHYSRL7.js → discovery-GUFTFBTL.js} +3 -1
  47. package/dist/instrumentation.js +3 -3
  48. package/dist/nitro.js +24 -7
  49. package/dist/{oauth-callback-server-QJUC7S4X.js → oauth-callback-server-LQ6DFI26.js} +17 -17
  50. package/dist/{runner-PZMV6JQW.js → runner-D3ZU6TJH.js} +10 -10
  51. package/dist/{skills-W4JETYSV.js → skills-JMXY7LIY.js} +8 -8
  52. package/dist/{validation-IJLNHZSU.js → validation-OEPJS7JX.js} +8 -8
  53. package/dist/version.js +1 -1
  54. package/package.json +8 -7
  55. package/skills/jr-rpc/SKILL.md +40 -0
  56. package/dist/chunk-3V7OFJZC.js +0 -264
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-UXLYAVYL.js";
3
+ } from "./chunk-GNNV3UTY.js";
4
4
  import {
5
5
  logWarn
6
- } from "./chunk-MLZFK4KP.js";
6
+ } from "./chunk-ALYQOZG7.js";
7
7
  import {
8
8
  skillRoots
9
- } from "./chunk-3V7OFJZC.js";
9
+ } from "./chunk-H4HBKISO.js";
10
10
 
11
11
  // src/chat/skills.ts
12
12
  import fs from "fs/promises";
@@ -25,13 +25,12 @@ import {
25
25
  patchMcpAuthSession,
26
26
  resolveBaseUrl,
27
27
  selectPluginGrant,
28
- slackOutputPolicy,
29
28
  startOAuthFlow,
30
29
  surfaceFromRouting,
31
30
  toMcpProviderError,
32
31
  toolInvocationDestination,
33
32
  uploadFilesToConversation
34
- } from "./chunk-S6R23MFB.js";
33
+ } from "./chunk-TKUCRFNX.js";
35
34
  import {
36
35
  CooperativeTurnYieldError,
37
36
  JUNIOR_THREAD_STATE_TTL_MS,
@@ -73,7 +72,7 @@ import {
73
72
  stripRuntimeTurnContext,
74
73
  trimTrailingAssistantMessages,
75
74
  updateConversationStats
76
- } from "./chunk-PJPKHGLG.js";
75
+ } from "./chunk-JQWP6V22.js";
77
76
  import {
78
77
  parseSandboxEgressAuthRequiredSignal,
79
78
  parseSandboxEgressPermissionDeniedSignal,
@@ -97,10 +96,10 @@ import {
97
96
  runNonInteractiveCommand,
98
97
  throwSandboxOperationError,
99
98
  wrapSandboxSetupError
100
- } from "./chunk-4LPPH7Y6.js";
99
+ } from "./chunk-DJDGDJDF.js";
101
100
  import {
102
101
  incrementStat
103
- } from "./chunk-L72GDKSN.js";
102
+ } from "./chunk-6WX5SPI3.js";
104
103
  import {
105
104
  addAgentTurnUsage,
106
105
  hasAgentTurnUsage
@@ -122,7 +121,7 @@ import {
122
121
  normalizeSlackConversationId,
123
122
  resolveChannelCapabilities,
124
123
  withSlackRetries
125
- } from "./chunk-GT2ZUALJ.js";
124
+ } from "./chunk-24B5R6OU.js";
126
125
  import {
127
126
  KNOWN_CONVERSATION_EVENT_TYPES,
128
127
  contextProvenance,
@@ -131,7 +130,7 @@ import {
131
130
  getConversationStore,
132
131
  instructionActors,
133
132
  instructionProvenanceFor
134
- } from "./chunk-KC5EE27Y.js";
133
+ } from "./chunk-M243JMZH.js";
135
134
  import {
136
135
  SANDBOX_DATA_ROOT,
137
136
  SANDBOX_SKILLS_ROOT,
@@ -141,7 +140,7 @@ import {
141
140
  sandboxSkillFile,
142
141
  sandboxSkillPathResolution,
143
142
  sleep
144
- } from "./chunk-3N3FMCKN.js";
143
+ } from "./chunk-ALAKN7LR.js";
145
144
  import {
146
145
  ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
147
146
  COMPACTION_SUMMARY_PREFIX,
@@ -172,7 +171,7 @@ import {
172
171
  renderCurrentInstruction,
173
172
  resolveGatewayModel,
174
173
  unwrapCurrentInstruction
175
- } from "./chunk-PWRFTDTY.js";
174
+ } from "./chunk-VURFJVFH.js";
176
175
  import {
177
176
  canExposeConversationPayload,
178
177
  parseSlackThreadId,
@@ -183,16 +182,16 @@ import {
183
182
  toGenAiMessagesTraceAttributes,
184
183
  toGenAiPayloadMetadata,
185
184
  toGenAiPayloadTraceAttributes
186
- } from "./chunk-FXOYURO4.js";
185
+ } from "./chunk-HDFGNU5E.js";
187
186
  import {
188
187
  discoverSkills,
189
188
  findSkillByName,
190
189
  loadSkillsByName,
191
190
  parseSkillInvocation
192
- } from "./chunk-7GADTCNS.js";
191
+ } from "./chunk-EIVE6GL4.js";
193
192
  import {
194
193
  pluginCatalogRuntime
195
- } from "./chunk-UXLYAVYL.js";
194
+ } from "./chunk-GNNV3UTY.js";
196
195
  import {
197
196
  CredentialUnavailableError,
198
197
  OAuthProviderError,
@@ -200,7 +199,7 @@ import {
200
199
  getOAuthProviderErrorAttributes,
201
200
  resolveAuthTokenPlaceholder,
202
201
  resolvePluginCommandEnv
203
- } from "./chunk-3LGCVRBQ.js";
202
+ } from "./chunk-XAI2HNAY.js";
204
203
  import {
205
204
  credentialUserSubjectId
206
205
  } from "./chunk-W3U3YQYI.js";
@@ -224,7 +223,7 @@ import {
224
223
  summarizeMessageText,
225
224
  withLogContext,
226
225
  withSpan
227
- } from "./chunk-MLZFK4KP.js";
226
+ } from "./chunk-ALYQOZG7.js";
228
227
  import {
229
228
  parseSlackChannelId,
230
229
  parseSlackMessageTs,
@@ -238,7 +237,7 @@ import {
238
237
  listReferenceFiles,
239
238
  soulPathCandidates,
240
239
  worldPathCandidates
241
- } from "./chunk-3V7OFJZC.js";
240
+ } from "./chunk-H4HBKISO.js";
242
241
 
243
242
  // src/chat/configuration/defaults.ts
244
243
  var installDefaults = {};
@@ -1861,13 +1860,11 @@ function buildOutputSection(platform) {
1861
1860
  "</output>"
1862
1861
  ].join("\n");
1863
1862
  }
1864
- const openTag = `<output format="slack-markdown" max_inline_chars="${slackOutputPolicy.maxInlineChars}" max_inline_lines="${slackOutputPolicy.maxInlineLines}">`;
1865
1863
  return [
1866
- openTag,
1864
+ `<output format="slack-markdown">`,
1865
+ "- Default to the shortest complete reply\u2014usually 1\u20135 sentences and under 800 characters. Include only the outcome, decisive evidence, and any blocker or required next action. If useful detail would exceed that, put it in a Slack canvas and reply with the link. An explicit user request for detail overrides this target.",
1867
1866
  "- Start with the answer or result, not internal process narration.",
1868
1867
  "- Use Slack-flavored Markdown: **bold** section labels, `code`, [text](url) links, bullet lists, and fenced code blocks. No hash-prefixed headings and no tables. When the answer primarily lists several URLs, show each URL bare instead of as a labeled link.",
1869
- "- Default to one compact thread reply containing the conclusion and only decisive evidence or action. Do not split an explainer across multiple Slack messages.",
1870
- "- Put plans, research, and other long or multi-section explainers in a Slack canvas; reply with one or two short sentences plus the link, without recapping the canvas.",
1871
1868
  "- End every turn with a final user-facing markdown response unless the Slack action rules allow a no-reply completion.",
1872
1869
  "</output>"
1873
1870
  ].join("\n");
@@ -6493,6 +6490,7 @@ var McpToolManager = class {
6493
6490
  try {
6494
6491
  const client = await this.getClient(plugin);
6495
6492
  const tools = this.filterListedTools(plugin, await client.listTools());
6493
+ this.assertWrappedToolsAvailable(plugin, tools);
6496
6494
  this.toolsByProvider.set(
6497
6495
  provider,
6498
6496
  tools.map((tool) => this.toManagedTool(plugin, client, tool))
@@ -6543,8 +6541,26 @@ var McpToolManager = class {
6543
6541
  `Plugin ${plugin.manifest.name} MCP discovery missing allowlisted tools: ${missingTools.join(", ")}`
6544
6542
  );
6545
6543
  }
6546
- const allowedToolSet = new Set(allowedTools);
6547
- return tools.filter((tool) => allowedToolSet.has(tool.name));
6544
+ const loadedToolSet = /* @__PURE__ */ new Set([
6545
+ ...allowedTools,
6546
+ ...plugin.manifest.mcp?.wrappedTools ?? []
6547
+ ]);
6548
+ return tools.filter((tool) => loadedToolSet.has(tool.name));
6549
+ }
6550
+ assertWrappedToolsAvailable(plugin, tools) {
6551
+ const wrappedTools = plugin.manifest.mcp?.wrappedTools ?? [];
6552
+ if (wrappedTools.length === 0) {
6553
+ return;
6554
+ }
6555
+ const availableToolNames = new Set(tools.map((tool) => tool.name));
6556
+ const missingTools = wrappedTools.filter(
6557
+ (toolName) => !availableToolNames.has(toolName)
6558
+ );
6559
+ if (missingTools.length > 0) {
6560
+ throw new Error(
6561
+ `Plugin ${plugin.manifest.name} MCP discovery missing wrapped tools: ${missingTools.join(", ")}`
6562
+ );
6563
+ }
6548
6564
  }
6549
6565
  async getClient(plugin) {
6550
6566
  const existing = this.clientsByProvider.get(plugin.manifest.name);
@@ -6630,8 +6646,13 @@ var McpToolManager = class {
6630
6646
  "gen_ai.tool.call.result": resultAttribute
6631
6647
  });
6632
6648
  }
6649
+ const providerContent = boundMcpContent(
6650
+ toAgentToolContent(result)
6651
+ );
6633
6652
  return {
6634
- content: toModelVisibleMcpContent(result)
6653
+ content: toModelVisibleMcpContent(result),
6654
+ providerContent,
6655
+ ...result.structuredContent !== void 0 ? { structuredContent: result.structuredContent } : {}
6635
6656
  };
6636
6657
  } catch (error) {
6637
6658
  if (error instanceof McpAuthorizationRequiredError && await this.handleAuthorizationRequired(
@@ -6642,7 +6663,9 @@ var McpToolManager = class {
6642
6663
  { type: "text", text: "Authorization pending." }
6643
6664
  ];
6644
6665
  return {
6645
- content: parkedContent
6666
+ authorizationPending: true,
6667
+ content: parkedContent,
6668
+ providerContent: parkedContent
6646
6669
  };
6647
6670
  }
6648
6671
  const errorAttributes = {
@@ -6695,10 +6718,59 @@ var McpToolManager = class {
6695
6718
  if (options.provider && provider !== options.provider) {
6696
6719
  continue;
6697
6720
  }
6698
- resolved.push(...this.toolsByProvider.get(provider) ?? []);
6721
+ const wrappedTools = new Set(
6722
+ this.pluginsByProvider.get(provider)?.manifest.mcp?.wrappedTools ?? []
6723
+ );
6724
+ resolved.push(
6725
+ ...(this.toolsByProvider.get(provider) ?? []).filter(
6726
+ (tool) => !wrappedTools.has(tool.rawName)
6727
+ )
6728
+ );
6699
6729
  }
6700
6730
  return resolved;
6701
6731
  }
6732
+ /** Call one active provider tool declared for plugin-owned wrapping. */
6733
+ async callWrappedTool(provider, rawName, args, options) {
6734
+ if (!this.activeProviders.has(provider)) {
6735
+ throw new McpToolError(`MCP provider is not active: ${provider}`);
6736
+ }
6737
+ const wrappedTools = new Set(
6738
+ this.pluginsByProvider.get(provider)?.manifest.mcp?.wrappedTools ?? []
6739
+ );
6740
+ if (!wrappedTools.has(rawName)) {
6741
+ throw new McpToolError(
6742
+ `Plugin ${provider} cannot call unwrapped MCP tool ${rawName}`
6743
+ );
6744
+ }
6745
+ const tool = (this.toolsByProvider.get(provider) ?? []).find(
6746
+ (candidate) => candidate.rawName === rawName
6747
+ );
6748
+ if (!tool) {
6749
+ throw new McpToolError(
6750
+ `MCP provider ${provider} does not expose tool ${rawName}`
6751
+ );
6752
+ }
6753
+ let result;
6754
+ try {
6755
+ result = await tool.execute(args, {
6756
+ conversationPrivacy: "private",
6757
+ ...options?.toolCallId ? { toolCallId: options.toolCallId } : {}
6758
+ });
6759
+ } catch (error) {
6760
+ if (error instanceof McpToolError) {
6761
+ return { status: "error", message: error.message };
6762
+ }
6763
+ throw error;
6764
+ }
6765
+ if (result.authorizationPending) {
6766
+ return { status: "authorization_pending" };
6767
+ }
6768
+ return {
6769
+ status: "success",
6770
+ content: result.providerContent ?? result.content,
6771
+ ...result.structuredContent !== void 0 ? { structuredContent: result.structuredContent } : {}
6772
+ };
6773
+ }
6702
6774
  toToolDescriptor(tool) {
6703
6775
  return {
6704
6776
  name: tool.name,
@@ -8647,20 +8719,156 @@ function extractCanvasId(input) {
8647
8719
  }
8648
8720
  }
8649
8721
 
8650
- // src/chat/slack/tools/canvas/api.ts
8722
+ // src/chat/slack/tools/canvas/markdown.ts
8723
+ function getListType(marker) {
8724
+ return /^\d/.test(marker) ? "numbered" : "bullet";
8725
+ }
8726
+ function getPlainListMarker(marker, type) {
8727
+ return type === "numbered" ? `${marker.match(/^\d+/)?.[0] ?? "1"}:` : "\u2022";
8728
+ }
8729
+ function getIndentWidth(whitespace, startColumn = 0) {
8730
+ let column = startColumn;
8731
+ for (const character of whitespace) {
8732
+ column += character === " " ? 4 - column % 4 : 1;
8733
+ }
8734
+ return column - startColumn;
8735
+ }
8736
+ function getLineIndent(line) {
8737
+ return getIndentWidth(line.match(/^[ \t]*/)?.[0] ?? "");
8738
+ }
8739
+ function getFence(line) {
8740
+ const match = line.match(/^([ \t]*)(`{3,}|~{3,})(.*)$/);
8741
+ const run = match?.[2];
8742
+ if (!run) return void 0;
8743
+ return {
8744
+ fence: {
8745
+ marker: run[0],
8746
+ length: run.length
8747
+ },
8748
+ indent: getIndentWidth(match[1] ?? ""),
8749
+ suffix: match[3] ?? ""
8750
+ };
8751
+ }
8752
+ function isListBlockIndent(indent, listItems2) {
8753
+ return listItems2.some(
8754
+ (item) => indent >= item.contentIndent && indent <= item.contentIndent + 3
8755
+ );
8756
+ }
8757
+ function canOpenFence(fenceLine, listItems2) {
8758
+ return fenceLine.indent <= 3 || isListBlockIndent(fenceLine.indent, listItems2);
8759
+ }
8760
+ function unwrapNestedBlockquote(line, listItems2, maxQuoteDepth = Number.POSITIVE_INFINITY) {
8761
+ const match = line.match(/^([ \t]+)((?:>[ \t]*)+)(.*)$/);
8762
+ if (!match || !isListBlockIndent(getIndentWidth(match[1] ?? ""), listItems2)) {
8763
+ return { line, quoteDepth: 0 };
8764
+ }
8765
+ let quotePrefix = match[2] ?? "";
8766
+ const quoteDepth = Math.min(
8767
+ quotePrefix.match(/>/g)?.length ?? 0,
8768
+ maxQuoteDepth
8769
+ );
8770
+ for (let index = 0; index < quoteDepth; index += 1) {
8771
+ quotePrefix = quotePrefix.replace(/^>[ \t]*/, "");
8772
+ }
8773
+ return {
8774
+ line: `${match[1]}${quotePrefix}${match[3]}`,
8775
+ quoteDepth
8776
+ };
8777
+ }
8651
8778
  function normalizeCanvasMarkdown(markdown) {
8652
8779
  let normalizedHeadingCount = 0;
8653
- const normalized = markdown.split("\n").map(
8654
- (line) => line.replace(/^(#{4,})(?=\s)/, () => {
8780
+ let normalizedMixedListCount = 0;
8781
+ let unwrappedBlockquoteCount = 0;
8782
+ let openFence;
8783
+ const listItems2 = [];
8784
+ const lines = markdown.split("\n").map((originalLine) => {
8785
+ if (openFence) {
8786
+ const unwrapped2 = openFence.quoteDepth > 0 ? unwrapNestedBlockquote(
8787
+ originalLine,
8788
+ listItems2,
8789
+ openFence.quoteDepth
8790
+ ) : { line: originalLine, quoteDepth: 0 };
8791
+ if (unwrapped2.quoteDepth > 0) {
8792
+ unwrappedBlockquoteCount += 1;
8793
+ }
8794
+ const fenceLine2 = getFence(unwrapped2.line);
8795
+ if (fenceLine2?.fence.marker === openFence.marker && fenceLine2.fence.length >= openFence.length && !fenceLine2.suffix.trim()) {
8796
+ openFence = void 0;
8797
+ }
8798
+ return unwrapped2.line;
8799
+ }
8800
+ const unwrapped = unwrapNestedBlockquote(originalLine, listItems2);
8801
+ if (unwrapped.quoteDepth > 0) {
8802
+ unwrappedBlockquoteCount += 1;
8803
+ }
8804
+ const line = unwrapped.line;
8805
+ const fenceLine = getFence(line);
8806
+ if (fenceLine && canOpenFence(fenceLine, listItems2)) {
8807
+ const rootListContentIndent2 = listItems2[0]?.contentIndent;
8808
+ if (rootListContentIndent2 !== void 0 && fenceLine.indent < rootListContentIndent2) {
8809
+ listItems2.length = 0;
8810
+ }
8811
+ openFence = {
8812
+ ...fenceLine.fence,
8813
+ quoteDepth: unwrapped.quoteDepth
8814
+ };
8815
+ return line;
8816
+ }
8817
+ const listMatch = line.match(/^([ \t]*)([-+*]|\d+[.)])([ \t]+)(.*)$/);
8818
+ if (listMatch) {
8819
+ const [, whitespace = "", marker = "", gap = "", rawContent = ""] = listMatch;
8820
+ const indent = getIndentWidth(whitespace);
8821
+ const type = getListType(marker);
8822
+ const markerEnd = indent + getIndentWidth(marker);
8823
+ const contentIndent = markerEnd + getIndentWidth(gap, markerEnd);
8824
+ const contentMatch = rawContent.match(/^(?:>[ \t]*)+(.*)$/);
8825
+ const content = contentMatch?.[1] ?? rawContent;
8826
+ if (contentMatch) {
8827
+ unwrappedBlockquoteCount += 1;
8828
+ }
8829
+ while (listItems2.length > 0 && listItems2[listItems2.length - 1].indent >= indent) {
8830
+ listItems2.pop();
8831
+ }
8832
+ const parent = listItems2[listItems2.length - 1];
8833
+ if (parent && (parent.unwrapped || parent.type !== type)) {
8834
+ listItems2.push({
8835
+ contentIndent,
8836
+ indent,
8837
+ type: parent.type,
8838
+ unwrapped: true
8839
+ });
8840
+ normalizedMixedListCount += 1;
8841
+ return `${whitespace}${getPlainListMarker(marker, type)}${gap}${content}`;
8842
+ }
8843
+ listItems2.push({ contentIndent, indent, type, unwrapped: false });
8844
+ return contentMatch ? `${whitespace}${marker}${gap}${content}` : line;
8845
+ }
8846
+ const rootListContentIndent = listItems2[0]?.contentIndent;
8847
+ if (rootListContentIndent !== void 0 && line.trim() && getLineIndent(line) < rootListContentIndent) {
8848
+ listItems2.length = 0;
8849
+ }
8850
+ const headingMatch = line.match(/^([ \t]*)#{4,}(?=[ \t])/);
8851
+ const headingIndent = headingMatch ? getIndentWidth(headingMatch[1] ?? "") : void 0;
8852
+ if (headingMatch && headingIndent !== void 0 && (headingIndent <= 3 || isListBlockIndent(headingIndent, listItems2))) {
8655
8853
  normalizedHeadingCount += 1;
8656
- return "###";
8657
- })
8658
- ).join("\n");
8854
+ return line.replace(
8855
+ /^([ \t]*)#{4,}(?=[ \t])/,
8856
+ (_, indent) => `${indent}###`
8857
+ );
8858
+ }
8859
+ return line;
8860
+ });
8861
+ const normalizedCount = normalizedHeadingCount + normalizedMixedListCount + unwrappedBlockquoteCount;
8659
8862
  return {
8660
- markdown: normalized,
8661
- normalizedHeadingCount
8863
+ markdown: lines.join("\n"),
8864
+ normalizedCount,
8865
+ normalizedHeadingCount,
8866
+ normalizedMixedListCount,
8867
+ unwrappedBlockquoteCount
8662
8868
  };
8663
8869
  }
8870
+
8871
+ // src/chat/slack/tools/canvas/api.ts
8664
8872
  async function createCanvas(input) {
8665
8873
  const client = getSlackClient();
8666
8874
  const normalizedChannelId = normalizeSlackConversationId(input.channelId);
@@ -8684,8 +8892,10 @@ async function createCanvas(input) {
8684
8892
  "app.slack.canvas.has_channel_id": Boolean(input.channelId),
8685
8893
  "app.slack.canvas.title_length": input.title.length,
8686
8894
  "app.slack.canvas.markdown_length": normalizedContent.markdown.length,
8687
- "app.slack.canvas.markdown_normalized": normalizedContent.normalizedHeadingCount > 0,
8688
- "app.slack.canvas.normalized_heading_count": normalizedContent.normalizedHeadingCount
8895
+ "app.slack.canvas.markdown_normalized": normalizedContent.normalizedCount > 0,
8896
+ "app.slack.canvas.normalized_heading_count": normalizedContent.normalizedHeadingCount,
8897
+ "app.slack.canvas.normalized_mixed_list_count": normalizedContent.normalizedMixedListCount,
8898
+ "app.slack.canvas.unwrapped_blockquote_count": normalizedContent.unwrappedBlockquoteCount
8689
8899
  }
8690
8900
  }
8691
8901
  );
@@ -8761,8 +8971,10 @@ async function writeCanvasMarkdown(input) {
8761
8971
  "app.slack.canvas.canvas_id_prefix": input.canvasId.slice(0, 1),
8762
8972
  "app.slack.canvas.operation": "replace",
8763
8973
  "app.slack.canvas.markdown_length": normalizedContent.markdown.length,
8764
- "app.slack.canvas.markdown_normalized": normalizedContent.normalizedHeadingCount > 0,
8765
- "app.slack.canvas.normalized_heading_count": normalizedContent.normalizedHeadingCount
8974
+ "app.slack.canvas.markdown_normalized": normalizedContent.normalizedCount > 0,
8975
+ "app.slack.canvas.normalized_heading_count": normalizedContent.normalizedHeadingCount,
8976
+ "app.slack.canvas.normalized_mixed_list_count": normalizedContent.normalizedMixedListCount,
8977
+ "app.slack.canvas.unwrapped_blockquote_count": normalizedContent.unwrappedBlockquoteCount
8766
8978
  }
8767
8979
  }
8768
8980
  );
@@ -14084,7 +14296,8 @@ async function summarizeContext(args, deps) {
14084
14296
  "- The immediate next action",
14085
14297
  "- Durable constraints, user preferences, IDs, URLs, artifacts, sandbox references, auth state, and unresolved blockers",
14086
14298
  "",
14087
- "Do not write a user-facing reply, announce a plan, or imply that the task is complete unless the source history proves it is complete."
14299
+ "Do not write a user-facing reply or announce a plan.",
14300
+ "Treat the task as complete only when the source history contains concrete evidence that every requested outcome occurred. Do not infer completion from intent, plans, progress, intermediate artifacts, or adjacent tool activity. If evidence is missing or ambiguous, preserve the task as unfinished and state the next required action."
14088
14301
  ] : [
14089
14302
  "You are performing a CONTEXT CHECKPOINT COMPACTION for Junior.",
14090
14303
  "Create a concise continuation summary for the agent that will continue this Slack thread.",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createPluginCatalogRuntime
3
- } from "./chunk-3LGCVRBQ.js";
3
+ } from "./chunk-XAI2HNAY.js";
4
4
 
5
5
  // src/chat/plugins/catalog-runtime.ts
6
6
  var pluginCatalogRuntime = createPluginCatalogRuntime();