@sentry/junior 0.60.1 → 0.61.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/app.js CHANGED
@@ -2969,13 +2969,7 @@ var editReplacementSchema = Type2.Object(
2969
2969
  );
2970
2970
  function createEditFileTool() {
2971
2971
  return tool({
2972
- description: "Edit one sandbox workspace file with exact text replacements. Use for precise changes to existing files. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff.",
2973
- promptSnippet: "existing-file exact edits; returns diff",
2974
- promptGuidelines: [
2975
- "prefer over writeFile for targeted changes",
2976
- "oldText exact, unique, non-overlapping",
2977
- "multiple same-file changes: one edits[] call"
2978
- ],
2972
+ description: "Edit one sandbox workspace file with exact text replacements. Use for precise changes to existing files; prefer this over writeFile for targeted changes. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff. Multiple changes to the same file: use one edits[] call.",
2979
2973
  prepareArguments: prepareEditFileArguments,
2980
2974
  executionMode: "sequential",
2981
2975
  inputSchema: Type2.Object(
@@ -5406,13 +5400,7 @@ function createSlackCanvasReadTool() {
5406
5400
  }
5407
5401
  function createSlackCanvasEditTool(state) {
5408
5402
  return tool({
5409
- description: "Edit one Slack canvas with exact markdown replacements. Use for precise changes to existing Canvas content. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff.",
5410
- promptSnippet: "existing-canvas exact edits; returns diff",
5411
- promptGuidelines: [
5412
- "prefer over slackCanvasWrite for targeted changes",
5413
- "oldText exact, unique, non-overlapping",
5414
- "multiple same-canvas changes: one edits[] call"
5415
- ],
5403
+ description: "Edit one Slack canvas with exact markdown replacements. Use for precise changes to existing Canvas content; prefer this over slackCanvasWrite for targeted changes. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff. Multiple changes to the same canvas: use one edits[] call.",
5416
5404
  prepareArguments: prepareCanvasEditArguments,
5417
5405
  executionMode: "sequential",
5418
5406
  inputSchema: Type16.Object(
@@ -5499,9 +5487,7 @@ function createSlackCanvasEditTool(state) {
5499
5487
  }
5500
5488
  function createSlackCanvasWriteTool(state) {
5501
5489
  return tool({
5502
- description: "Write UTF-8 markdown content to a Slack canvas. Use for deliberate full-Canvas replacement after validation. Do not use for targeted edits.",
5503
- promptSnippet: "deliberate full-canvas replacement",
5504
- promptGuidelines: ["targeted existing-canvas changes: slackCanvasEdit"],
5490
+ description: "Write UTF-8 markdown content to a Slack canvas. Use for deliberate full-Canvas replacement after validation; use slackCanvasEdit for targeted changes to existing canvas content.",
5505
5491
  executionMode: "sequential",
5506
5492
  inputSchema: Type16.Object(
5507
5493
  {
@@ -6816,7 +6802,7 @@ function createStateAdvisorSessionStore() {
6816
6802
  }
6817
6803
 
6818
6804
  // src/chat/tools/advisor/tool.ts
6819
- var ADVISOR_TOOL_DESCRIPTION = "Ask a stronger advisor for deep technical guidance. Call this when the task has a hard reasoning core: algorithm design, architecture, concurrency, security-sensitive logic, data modeling, unclear requirements, repeated failures, difficult debugging, broad refactors, or final review of nontrivial work. Pass a focused question plus curated context containing the exact evidence, constraints, current plan, alternatives, command output, code snippets, or diffs the advisor should start from. The advisor does not automatically receive the parent transcript, keeps its own advisor history for this parent conversation, can use read-only inspection tools to verify evidence, can reason deeply, and returns guidance for you to apply and verify. Follow-up calls can build on prior advisor guidance but must include any new evidence or changed constraints. Use it after initial orientation reads when repository context matters, before committing to a non-obvious implementation plan, when changing approach, when stuck, and before declaring complex work complete. Do not use it for greetings, simple deterministic edits, routine formatting, or tasks where the next action is already obvious from fresh tool output.";
6805
+ var ADVISOR_TOOL_DESCRIPTION = "Use this before committing to a non-obvious technical plan or declaring complex work complete. Call proactively after initial orientation when repository context matters \u2014 especially for architecture, algorithms, data modeling, concurrency, security-sensitive logic, unclear requirements, broad refactors, difficult debugging, repeated failures, or high-risk changes. Provide a focused question plus curated context: exact evidence, constraints, relevant code snippets, command output, diffs, current plan, and alternatives considered. The advisor does not automatically receive the parent transcript, keeps its own advisor history for this parent conversation, and can use read-only inspection tools to verify evidence. Follow-up calls can build on prior advisor guidance but must include new evidence or changed constraints. Do not use for greetings, simple deterministic edits, routine formatting, or when the next action is obvious from fresh tool output.";
6820
6806
  var ADVISOR_SYSTEM_PROMPT = [
6821
6807
  "You are a senior technical advisor for the executor.",
6822
6808
  "Analyze the executor-supplied context deeply. Use read-only tools when direct inspection or verification would materially improve the advice.",
@@ -7660,9 +7646,7 @@ function createWebSearchTool(override) {
7660
7646
  import { Type as Type24 } from "@sinclair/typebox";
7661
7647
  function createWriteFileTool() {
7662
7648
  return tool({
7663
- description: "Write UTF-8 content to a file in the sandbox workspace. Use for intentional file creation or replacement after validation. Do not use for exploratory analysis-only turns.",
7664
- promptSnippet: "new file or deliberate full-file replacement",
7665
- promptGuidelines: ["targeted existing-file changes: editFile"],
7649
+ description: "Write UTF-8 content to a file in the sandbox workspace. Use for intentional file creation or deliberate full-file replacement after validation; use editFile instead for targeted changes to existing files. Do not use for exploratory analysis-only turns.",
7666
7650
  executionMode: "sequential",
7667
7651
  inputSchema: Type24.Object(
7668
7652
  {
@@ -19637,7 +19621,7 @@ function getSlackMessageTs(message) {
19637
19621
  // src/chat/slack/assistant-thread/title.ts
19638
19622
  function maybeUpdateAssistantTitle(args) {
19639
19623
  const assistantThreadContext = args.assistantThreadContext;
19640
- if (!assistantThreadContext?.channelId || !assistantThreadContext.threadTs || !isDmChannel(assistantThreadContext.channelId)) {
19624
+ if (!assistantThreadContext?.channelId || !assistantThreadContext.threadTs) {
19641
19625
  return Promise.resolve(void 0);
19642
19626
  }
19643
19627
  const titleSourceMessage = getThreadTitleSourceMessage(args.conversation);
@@ -19647,40 +19631,12 @@ function maybeUpdateAssistantTitle(args) {
19647
19631
  if (args.artifacts.assistantTitleSourceMessageId === titleSourceMessage.id) {
19648
19632
  return Promise.resolve(void 0);
19649
19633
  }
19634
+ const isDm = isDmChannel(assistantThreadContext.channelId);
19650
19635
  return (async () => {
19636
+ let title;
19651
19637
  try {
19652
- const title = await args.generateThreadTitle(titleSourceMessage.text);
19653
- await args.getSlackAdapter().setAssistantTitle(
19654
- assistantThreadContext.channelId,
19655
- assistantThreadContext.threadTs,
19656
- title
19657
- );
19658
- return { sourceMessageId: titleSourceMessage.id, title };
19638
+ title = await args.generateThreadTitle(titleSourceMessage.text);
19659
19639
  } catch (error) {
19660
- const slackErrorCode = getSlackApiErrorCode(error);
19661
- const assistantTitleErrorAttributes = {
19662
- "app.slack.assistant_title.outcome": "permission_denied",
19663
- ...slackErrorCode ? {
19664
- "app.slack.assistant_title.error_code": slackErrorCode
19665
- } : {}
19666
- };
19667
- if (isSlackTitlePermissionError(error)) {
19668
- setSpanAttributes(assistantTitleErrorAttributes);
19669
- logError(
19670
- "thread_title_generation_permission_denied",
19671
- {
19672
- slackThreadId: args.threadId,
19673
- slackUserId: args.requesterId,
19674
- slackChannelId: args.channelId,
19675
- runId: args.runId,
19676
- assistantUserName: args.assistantUserName,
19677
- modelId: args.modelId
19678
- },
19679
- assistantTitleErrorAttributes,
19680
- "Skipping thread title update due to Slack permission error"
19681
- );
19682
- return { sourceMessageId: titleSourceMessage.id };
19683
- }
19684
19640
  logWarn(
19685
19641
  "thread_title_generation_failed",
19686
19642
  {
@@ -19698,6 +19654,56 @@ function maybeUpdateAssistantTitle(args) {
19698
19654
  );
19699
19655
  return void 0;
19700
19656
  }
19657
+ if (isDm) {
19658
+ try {
19659
+ await args.getSlackAdapter().setAssistantTitle(
19660
+ assistantThreadContext.channelId,
19661
+ assistantThreadContext.threadTs,
19662
+ title
19663
+ );
19664
+ } catch (error) {
19665
+ const slackErrorCode = getSlackApiErrorCode(error);
19666
+ const assistantTitleErrorAttributes = {
19667
+ "app.slack.assistant_title.outcome": "permission_denied",
19668
+ ...slackErrorCode ? {
19669
+ "app.slack.assistant_title.error_code": slackErrorCode
19670
+ } : {}
19671
+ };
19672
+ if (isSlackTitlePermissionError(error)) {
19673
+ setSpanAttributes(assistantTitleErrorAttributes);
19674
+ logError(
19675
+ "thread_title_generation_permission_denied",
19676
+ {
19677
+ slackThreadId: args.threadId,
19678
+ slackUserId: args.requesterId,
19679
+ slackChannelId: args.channelId,
19680
+ runId: args.runId,
19681
+ assistantUserName: args.assistantUserName,
19682
+ modelId: args.modelId
19683
+ },
19684
+ assistantTitleErrorAttributes,
19685
+ "Skipping Slack thread title update due to permission error"
19686
+ );
19687
+ } else {
19688
+ logWarn(
19689
+ "thread_title_slack_update_failed",
19690
+ {
19691
+ slackThreadId: args.threadId,
19692
+ slackUserId: args.requesterId,
19693
+ slackChannelId: args.channelId,
19694
+ runId: args.runId,
19695
+ assistantUserName: args.assistantUserName,
19696
+ modelId: args.modelId
19697
+ },
19698
+ {
19699
+ "exception.message": error instanceof Error ? error.message : String(error)
19700
+ },
19701
+ "Slack thread title update failed"
19702
+ );
19703
+ }
19704
+ }
19705
+ }
19706
+ return { sourceMessageId: titleSourceMessage.id, title };
19701
19707
  })();
19702
19708
  }
19703
19709
 
@@ -3,12 +3,17 @@ import { type ConversationMemoryService } from "@/chat/services/conversation-mem
3
3
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
4
4
  import type { ThreadConversationState } from "@/chat/state/conversation";
5
5
  /**
6
- * Best-effort assistant-thread title update for DM assistant threads.
6
+ * Best-effort conversation title generation for all Slack conversations.
7
7
  *
8
8
  * Title generation is intentionally detached from reply generation and visible
9
- * reply delivery. Stable Slack permission failures are treated as a terminal
10
- * skip for the current source message so later turns do not keep paying for
11
- * the same fast-model title generation call.
9
+ * reply delivery. For DM assistant threads the generated title is also pushed
10
+ * to Slack via `setAssistantTitle`. For channel conversations the title is
11
+ * generated and returned for dashboard reporting only — the Slack API for
12
+ * setting thread titles is DM-only and is not called.
13
+ *
14
+ * Stable Slack permission failures on DM title updates are treated as a
15
+ * terminal skip for the current source message so later turns do not keep
16
+ * paying for the same fast-model call that Slack will reject.
12
17
  */
13
18
  export declare function maybeUpdateAssistantTitle(args: {
14
19
  assistantThreadContext?: {
@@ -5,7 +5,17 @@ export interface ToolDefinition<TInputSchema extends TSchema = TSchema> {
5
5
  description: string;
6
6
  inputSchema: TInputSchema;
7
7
  annotations?: ToolAnnotations;
8
+ /**
9
+ * @deprecated Put tool-selection and usage guidance directly in `description`
10
+ * and parameter descriptions. Retained for plugin compatibility; may be
11
+ * removed in a future major version.
12
+ */
8
13
  promptSnippet?: string;
14
+ /**
15
+ * @deprecated Put tool-selection and usage guidance directly in `description`
16
+ * and parameter descriptions. Retained for plugin compatibility; may be
17
+ * removed in a future major version.
18
+ */
9
19
  promptGuidelines?: string[];
10
20
  prepareArguments?: (args: unknown) => Static<TInputSchema>;
11
21
  executionMode?: ToolExecutionMode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.60.1",
3
+ "version": "0.61.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -64,7 +64,7 @@
64
64
  "node-html-markdown": "^2.0.0",
65
65
  "yaml": "^2.9.0",
66
66
  "zod": "^4.4.3",
67
- "@sentry/junior-plugin-api": "0.60.1"
67
+ "@sentry/junior-plugin-api": "0.61.0"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@types/node": "^25.9.1",
@@ -76,7 +76,7 @@
76
76
  "typescript": "^6.0.3",
77
77
  "vercel": "^54.4.0",
78
78
  "vitest": "^4.1.7",
79
- "@sentry/junior-scheduler": "0.60.1"
79
+ "@sentry/junior-scheduler": "0.61.0"
80
80
  },
81
81
  "scripts": {
82
82
  "build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",