@sentry/junior 0.31.0 → 0.32.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.d.ts +2 -0
- package/dist/app.js +238 -69
- package/dist/{chunk-LEYD42MR.js → chunk-3M7ZD6FF.js} +1 -1
- package/dist/{chunk-3SH2A7VQ.js → chunk-EHXMTKBA.js} +1 -1
- package/dist/{chunk-RZJDO55D.js → chunk-XARRBRQV.js} +4 -0
- package/dist/cli/check.js +2 -2
- package/dist/cli/snapshot-warmup.js +2 -2
- package/package.json +1 -1
package/dist/app.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { Hono } from 'hono';
|
|
|
4
4
|
type WaitUntilFn = (task: Promise<unknown> | (() => Promise<unknown>)) => void;
|
|
5
5
|
|
|
6
6
|
interface JuniorAppOptions {
|
|
7
|
+
/** Install-wide provider defaults (`provider.key` format). Channel overrides take precedence. */
|
|
8
|
+
configDefaults?: Record<string, unknown>;
|
|
7
9
|
pluginPackages?: string[];
|
|
8
10
|
waitUntil?: WaitUntilFn;
|
|
9
11
|
}
|
package/dist/app.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
findSkillByName,
|
|
4
4
|
loadSkillsByName,
|
|
5
5
|
parseSkillInvocation
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-EHXMTKBA.js";
|
|
7
7
|
import {
|
|
8
8
|
GEN_AI_PROVIDER_NAME,
|
|
9
9
|
MISSING_GATEWAY_CREDENTIALS_ERROR,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
runNonInteractiveCommand,
|
|
31
31
|
sandboxSkillDir,
|
|
32
32
|
sandboxSkillFile
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-3M7ZD6FF.js";
|
|
34
34
|
import {
|
|
35
35
|
CredentialUnavailableError,
|
|
36
36
|
buildOAuthTokenRequest,
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
getPluginOAuthConfig,
|
|
47
47
|
getPluginProviders,
|
|
48
48
|
hasRequiredOAuthScope,
|
|
49
|
+
isPluginConfigKey,
|
|
49
50
|
isPluginProvider,
|
|
50
51
|
isRecord,
|
|
51
52
|
logError,
|
|
@@ -63,7 +64,7 @@ import {
|
|
|
63
64
|
toOptionalString,
|
|
64
65
|
withContext,
|
|
65
66
|
withSpan
|
|
66
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-XARRBRQV.js";
|
|
67
68
|
import "./chunk-Z3YD6NHK.js";
|
|
68
69
|
import {
|
|
69
70
|
discoverInstalledPluginPackageContent,
|
|
@@ -78,6 +79,26 @@ import "./chunk-2KG3PWR4.js";
|
|
|
78
79
|
// src/app.ts
|
|
79
80
|
import { Hono } from "hono";
|
|
80
81
|
|
|
82
|
+
// src/chat/configuration/defaults.ts
|
|
83
|
+
var installDefaults = {};
|
|
84
|
+
function setConfigDefaults(defaults) {
|
|
85
|
+
if (!defaults) {
|
|
86
|
+
installDefaults = {};
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
for (const key of Object.keys(defaults)) {
|
|
90
|
+
if (!isPluginConfigKey(key)) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`configDefaults: "${key}" is not a registered plugin config key`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
installDefaults = { ...defaults };
|
|
97
|
+
}
|
|
98
|
+
function getConfigDefaults() {
|
|
99
|
+
return installDefaults;
|
|
100
|
+
}
|
|
101
|
+
|
|
81
102
|
// src/handlers/diagnostics.ts
|
|
82
103
|
import { readFileSync } from "fs";
|
|
83
104
|
import path from "path";
|
|
@@ -2925,7 +2946,9 @@ function formatLoadedSkillsForPrompt(skills) {
|
|
|
2925
2946
|
lines.push(
|
|
2926
2947
|
` <skill name="${escapeXml(skill.name)}" location="${escapeXml(`${skillDir}/SKILL.md`)}">`
|
|
2927
2948
|
);
|
|
2928
|
-
lines.push(
|
|
2949
|
+
lines.push(
|
|
2950
|
+
`Skill directory: ${escapeXml(skillDir)}. Resolve relative paths there; for skill-owned bash commands, cd there first or use absolute paths.`
|
|
2951
|
+
);
|
|
2929
2952
|
lines.push("");
|
|
2930
2953
|
lines.push(skill.body);
|
|
2931
2954
|
lines.push(" </skill>");
|
|
@@ -3031,31 +3054,111 @@ function formatThreadParticipantsLines(participants) {
|
|
|
3031
3054
|
return `- ${parts.join(", ")}`;
|
|
3032
3055
|
});
|
|
3033
3056
|
}
|
|
3057
|
+
function formatSlackCapabilityNames(capabilities) {
|
|
3058
|
+
const names = [
|
|
3059
|
+
capabilities?.canCreateCanvas ? "canvas_create" : "",
|
|
3060
|
+
capabilities?.canPostToChannel ? "channel_post" : "",
|
|
3061
|
+
capabilities?.canAddReactions ? "reaction_add" : ""
|
|
3062
|
+
].filter(Boolean);
|
|
3063
|
+
return names.length > 0 ? names.join(", ") : "none";
|
|
3064
|
+
}
|
|
3034
3065
|
var HEADER = "You are a Slack-based helper assistant. The behavior and output blocks below are authoritative; the personality block sets voice only.";
|
|
3035
|
-
var
|
|
3036
|
-
"-
|
|
3037
|
-
"-
|
|
3038
|
-
"-
|
|
3066
|
+
var TOOL_POLICY_RULES = [
|
|
3067
|
+
"- Tool schemas are the source of truth for parameters; tool names are case-sensitive, so call tools exactly by their exposed names and do not invent arguments.",
|
|
3068
|
+
"- Use tools for actionable work and for facts that are mutable, external, repository-backed, provider-backed, or requested as verified/current. Stable general knowledge and already-provided context may be answered directly.",
|
|
3069
|
+
"- Verification source order: conversation/thread context; user-provided attachments, links, and reference files; local/sandbox files when present; loaded skill references; repository/provider tools; public web. Use the nearest authoritative available source before weaker sources.",
|
|
3070
|
+
"- For repository or implementation questions, inspect the target repository first: local checkout when present, otherwise the configured GitHub/source provider. Do not treat loaded skill files as repo source unless the user asks about the skill. Cite file paths, symbols, PRs/issues, commits, or URLs that support the answer.",
|
|
3071
|
+
`- Sandbox-backed file and shell tools operate in an isolated workspace rooted at ${SANDBOX_WORKSPACE_ROOT}; readFile/writeFile paths are sandbox-workspace paths, bash runs inside that workspace, and attachFile accepts absolute or workspace-relative sandbox paths.`,
|
|
3072
|
+
"- If a sandbox-backed tool reports that sandbox execution is unavailable, treat that as a blocker for local file/shell inspection; do not pretend host files were inspected.",
|
|
3073
|
+
"- For user-provided URLs, use `webFetch`; for discovery, use `webSearch` then fetch/read promising sources; for current time/date context, use `systemTime`.",
|
|
3074
|
+
"- If the first result is empty, stale, ambiguous, or incomplete, try a focused alternate query, path, command, or source before concluding the answer cannot be verified."
|
|
3075
|
+
];
|
|
3076
|
+
var TOOL_CALL_STYLE_RULES = [
|
|
3077
|
+
"- For routine low-risk tool use, call the tool directly without narrating the obvious step first.",
|
|
3078
|
+
"- Briefly narrate only when it helps the user understand multi-step work, sensitive actions, destructive actions, or a notable change in approach.",
|
|
3079
|
+
"- When a first-class tool exists for an action, use it directly instead of asking the user to run an equivalent command, slash command, or manual lookup.",
|
|
3080
|
+
"- Keep tool-call explanations separate from final answers; final answers should report results, evidence, or blockers."
|
|
3081
|
+
];
|
|
3082
|
+
var SKILL_POLICY_RULES = [
|
|
3083
|
+
"- Before answering, scan `<available-skills>`. For matching operational or conceptual provider/repository workflow questions, load the most specific skill; do not answer from memory first. If none fits, do not load a skill.",
|
|
3084
|
+
"- Never load multiple skills up front. After `loadSkill`, follow `<loaded-skills>` and resolve relative references under that skill's location.",
|
|
3085
|
+
"- For explicit `/skill` triggers, treat that skill as selected unless the tool says it is unavailable.",
|
|
3086
|
+
"- For active MCP catalogs, use `searchMcpTools` to inspect descriptors before `callMcpTool`; pass exact returned `tool_name` values and put provider fields inside `arguments`.",
|
|
3087
|
+
"- Run authenticated provider commands directly after resolving target defaults; let the runtime handle auth pauses/resumes.",
|
|
3088
|
+
"- Run `jr-rpc config get|set|unset|list` as standalone bash commands for conversation-scoped provider defaults; do not chain them with `cd`, `&&`, pipes, or provider commands."
|
|
3089
|
+
];
|
|
3090
|
+
var EXECUTION_CONTRACT_RULES = [
|
|
3091
|
+
"- Actionable request: act in this turn.",
|
|
3092
|
+
"- Continue until done or genuinely blocked. Do not finish with a plan, promise, or offer to check next when an available tool or source can move the request forward.",
|
|
3093
|
+
"- Completion means the final answer covers the user's actual ask, including requested follow-up checks, and is grounded in the best evidence you could access.",
|
|
3094
|
+
"- Ask the user only for missing access, approval, or a decision that blocks safe progress. Ask one focused question; otherwise infer conservatively and continue.",
|
|
3095
|
+
"- For conflicting evidence, compare sources and state which source is authoritative for the answer.",
|
|
3096
|
+
"- For non-trivial or long-running work, call `reportProgress` early when available, then only when the major phase changes. Routine tool calls should stay silent."
|
|
3097
|
+
];
|
|
3098
|
+
var CONVERSATION_RULES = [
|
|
3039
3099
|
"- In thread follow-ups, answer from prior thread context; do not repeat resolved clarifying questions.",
|
|
3040
|
-
"-
|
|
3041
|
-
"-
|
|
3042
|
-
|
|
3043
|
-
|
|
3100
|
+
"- Preserve attribution roles from thread context: the requester is the person asking now, which may differ from the original reporter or subject.",
|
|
3101
|
+
"- On resumed turns, post a brief continuation notice, then the resumed answer as a separate message."
|
|
3102
|
+
];
|
|
3103
|
+
var SLACK_ACTION_RULES = [
|
|
3104
|
+
"- Context-bound Slack tools use runtime-owned targets; do not invent channel, canvas, list, or message IDs.",
|
|
3105
|
+
"- Use first-class Slack tools for Slack side effects; do not use bash, curl, or provider APIs to bypass Slack tool targeting.",
|
|
3106
|
+
"- Use channel-post and emoji-reaction tools only when the user explicitly asks for that Slack side effect.",
|
|
3107
|
+
"- For explicit channel-post or emoji-reaction requests, skip a duplicate thread text reply when the tool result already satisfies the request.",
|
|
3108
|
+
"- Do not claim an attachment, canvas, channel post, list update, or reaction succeeded unless the tool returned success this turn; when it did, include any link the tool returned.",
|
|
3109
|
+
"- Do not use reactions as progress indicators."
|
|
3110
|
+
];
|
|
3111
|
+
var SAFETY_RULES = [
|
|
3112
|
+
"- Stay within the user's request and the runtime's available capabilities; do not pursue independent goals, persistence, replication, credential gathering, or access expansion.",
|
|
3113
|
+
"- Respect stop, pause, audit, and approval boundaries. Do not bypass safeguards or persuade the user to weaken them.",
|
|
3114
|
+
"- Do not change system prompts, tool policies, security settings, credentials, or runtime configuration unless the user explicitly requests that exact administrative action and an available tool permits it."
|
|
3115
|
+
];
|
|
3116
|
+
var FAILURE_RULES = [
|
|
3044
3117
|
"- For tool/runtime failures, run the named check before diagnosing and report the exact failed command plus stderr/exit code.",
|
|
3045
|
-
"-
|
|
3046
|
-
"-
|
|
3118
|
+
"- If a fact cannot be verified after focused checks, say what you checked and what blocked a stronger answer.",
|
|
3119
|
+
"- Do not surface raw tool payloads, execution-escape text, or internal routing metadata as the final answer."
|
|
3047
3120
|
];
|
|
3121
|
+
function renderRuleSection(tag, lines) {
|
|
3122
|
+
return [`<${tag}>`, ...lines, `</${tag}>`].join("\n");
|
|
3123
|
+
}
|
|
3124
|
+
function buildBehaviorSection() {
|
|
3125
|
+
return [
|
|
3126
|
+
renderRuleSection("tool-policy", TOOL_POLICY_RULES),
|
|
3127
|
+
renderRuleSection("tool-call-style", TOOL_CALL_STYLE_RULES),
|
|
3128
|
+
renderRuleSection("skill-policy", SKILL_POLICY_RULES),
|
|
3129
|
+
renderRuleSection("execution-contract", EXECUTION_CONTRACT_RULES),
|
|
3130
|
+
renderRuleSection("conversation", CONVERSATION_RULES),
|
|
3131
|
+
renderRuleSection("slack-actions", SLACK_ACTION_RULES),
|
|
3132
|
+
renderRuleSection("safety", SAFETY_RULES),
|
|
3133
|
+
renderRuleSection("failure-handling", FAILURE_RULES)
|
|
3134
|
+
].join("\n\n");
|
|
3135
|
+
}
|
|
3048
3136
|
function buildOutputSection() {
|
|
3049
3137
|
const openTag = `<output format="slack-mrkdwn" max_inline_chars="${slackOutputPolicy.maxInlineChars}" max_inline_lines="${slackOutputPolicy.maxInlineLines}">`;
|
|
3050
3138
|
return [
|
|
3051
3139
|
openTag,
|
|
3140
|
+
"- Start with the answer or result, not internal process narration.",
|
|
3052
3141
|
"- Use Slack-friendly mrkdwn: bolded section labels instead of headings, no markdown tables or markdown links, and plain URLs.",
|
|
3053
3142
|
"- Keep replies brief and scannable; use bullets or short code blocks when helpful, and one compact thread reply when it fits.",
|
|
3054
|
-
"- When a research or document-style answer would benefit from continuation, multiple sections, or future reference value, create a Slack canvas and keep the thread reply to
|
|
3055
|
-
"-
|
|
3143
|
+
"- When a research or document-style answer would benefit from continuation, multiple sections, or future reference value, create a Slack canvas and keep the thread reply to one or two short sentences plus the link; do not recap the canvas contents.",
|
|
3144
|
+
"- Unless a successful Slack side-effect tool intentionally satisfied the request by itself, end every turn with a final user-facing markdown response.",
|
|
3056
3145
|
"</output>"
|
|
3057
3146
|
].join("\n");
|
|
3058
3147
|
}
|
|
3148
|
+
function buildRuntimeSection(params) {
|
|
3149
|
+
const lines = [
|
|
3150
|
+
`- version: ${escapeXml(getRuntimeMetadata().version ?? "unknown")}`,
|
|
3151
|
+
params.modelId ? `- model: ${escapeXml(params.modelId)}` : "",
|
|
3152
|
+
params.fastModelId ? `- fast_model: ${escapeXml(params.fastModelId)}` : "",
|
|
3153
|
+
params.thinkingLevel ? `- thinking: ${escapeXml(params.thinkingLevel)}` : "",
|
|
3154
|
+
params.channelId ? "- channel: slack" : "",
|
|
3155
|
+
params.channelId ? `- slack_capabilities: ${escapeXml(
|
|
3156
|
+
formatSlackCapabilityNames(params.slackCapabilities)
|
|
3157
|
+
)}` : "",
|
|
3158
|
+
`- sandbox_workspace: ${escapeXml(SANDBOX_WORKSPACE_ROOT)}`
|
|
3159
|
+
].filter(Boolean);
|
|
3160
|
+
return renderTagBlock("runtime", lines.join("\n"));
|
|
3161
|
+
}
|
|
3059
3162
|
function buildContextSection(params) {
|
|
3060
3163
|
const blocks = [];
|
|
3061
3164
|
if (JUNIOR_WORLD) {
|
|
@@ -3070,10 +3173,6 @@ function buildContextSection(params) {
|
|
|
3070
3173
|
])
|
|
3071
3174
|
);
|
|
3072
3175
|
}
|
|
3073
|
-
const runtimeVersion = getRuntimeMetadata().version;
|
|
3074
|
-
if (runtimeVersion) {
|
|
3075
|
-
blocks.push([`<runtime version="${escapeXml(runtimeVersion)}" />`]);
|
|
3076
|
-
}
|
|
3077
3176
|
blocks.push(
|
|
3078
3177
|
renderIdentityBlock("assistant", {
|
|
3079
3178
|
user_name: params.assistant?.userName ?? botConfig.userName,
|
|
@@ -3106,7 +3205,7 @@ function buildContextSection(params) {
|
|
|
3106
3205
|
if (configLines) {
|
|
3107
3206
|
blocks.push(
|
|
3108
3207
|
renderTag("configuration", [
|
|
3109
|
-
"
|
|
3208
|
+
"Install and conversation-scoped defaults. Channel overrides take precedence; follow explicit user input when it conflicts.",
|
|
3110
3209
|
...configLines
|
|
3111
3210
|
])
|
|
3112
3211
|
);
|
|
@@ -3145,6 +3244,13 @@ function buildSystemPrompt(params) {
|
|
|
3145
3244
|
const sections = [
|
|
3146
3245
|
HEADER,
|
|
3147
3246
|
renderTagBlock("personality", JUNIOR_PERSONALITY.trim()),
|
|
3247
|
+
renderTagBlock("behavior", buildBehaviorSection()),
|
|
3248
|
+
buildOutputSection(),
|
|
3249
|
+
buildCapabilitiesSection({
|
|
3250
|
+
availableSkills: params.availableSkills,
|
|
3251
|
+
activeSkills: params.activeSkills,
|
|
3252
|
+
activeMcpCatalogs: params.activeMcpCatalogs ?? []
|
|
3253
|
+
}),
|
|
3148
3254
|
buildContextSection({
|
|
3149
3255
|
assistant: params.assistant,
|
|
3150
3256
|
requester: params.requester,
|
|
@@ -3154,13 +3260,7 @@ function buildSystemPrompt(params) {
|
|
|
3154
3260
|
invocation: params.invocation,
|
|
3155
3261
|
turnState: params.turnState
|
|
3156
3262
|
}),
|
|
3157
|
-
|
|
3158
|
-
availableSkills: params.availableSkills,
|
|
3159
|
-
activeSkills: params.activeSkills,
|
|
3160
|
-
activeMcpCatalogs: params.activeMcpCatalogs ?? []
|
|
3161
|
-
}),
|
|
3162
|
-
renderTagBlock("behavior", BEHAVIOR_RULES.join("\n")),
|
|
3163
|
-
buildOutputSection()
|
|
3263
|
+
buildRuntimeSection(params.runtime ?? {})
|
|
3164
3264
|
];
|
|
3165
3265
|
return sections.join("\n\n");
|
|
3166
3266
|
}
|
|
@@ -4808,7 +4908,7 @@ function resolveMcpArguments(input) {
|
|
|
4808
4908
|
}
|
|
4809
4909
|
function createCallMcpToolTool(mcpToolManager, getActiveSkills) {
|
|
4810
4910
|
return tool({
|
|
4811
|
-
description: "Call an active MCP tool by exact tool_name. Use loadSkill to activate the provider, then searchMcpTools to discover tool names and schemas;
|
|
4911
|
+
description: "Call an active MCP tool by exact tool_name. Use loadSkill to activate the provider, then searchMcpTools to discover tool names and schemas; copy required provider fields into arguments. Do not call with only tool_name unless the discovered tool has no arguments. Authorization is handled by the runtime when required.",
|
|
4812
4912
|
inputSchema: Type4.Object(
|
|
4813
4913
|
{
|
|
4814
4914
|
tool_name: Type4.String({
|
|
@@ -4817,7 +4917,7 @@ function createCallMcpToolTool(mcpToolManager, getActiveSkills) {
|
|
|
4817
4917
|
}),
|
|
4818
4918
|
arguments: Type4.Optional(
|
|
4819
4919
|
Type4.Record(Type4.String(), Type4.Unknown(), {
|
|
4820
|
-
description:
|
|
4920
|
+
description: 'Arguments matching the disclosed MCP tool schema, for example { "query": "..." } when searchMcpTools shows query is required.'
|
|
4821
4921
|
})
|
|
4822
4922
|
)
|
|
4823
4923
|
},
|
|
@@ -4875,13 +4975,15 @@ async function loadSkillFromHost(availableSkills, skillName) {
|
|
|
4875
4975
|
skill_name: skill.name,
|
|
4876
4976
|
description: skill.description,
|
|
4877
4977
|
skill_dir: skillDir,
|
|
4978
|
+
working_directory: skillDir,
|
|
4878
4979
|
location: skillFilePath,
|
|
4980
|
+
path_resolution: `Resolve relative paths in this skill against ${skillDir}. For bash commands from this skill, cd to ${skillDir} first or use absolute paths.`,
|
|
4879
4981
|
instructions: loaded.body
|
|
4880
4982
|
};
|
|
4881
4983
|
}
|
|
4882
4984
|
function createLoadSkillTool(availableSkills, options) {
|
|
4883
4985
|
return tool({
|
|
4884
|
-
description: "Load a skill by name
|
|
4986
|
+
description: "Load a skill by name for this turn. The result includes working_directory; resolve skill paths there and run skill-owned bash commands from there or with absolute paths. When the result includes mcp_provider, use searchMcpTools before callMcpTool. Use when a request clearly matches a known skill.",
|
|
4885
4987
|
inputSchema: Type5.Object({
|
|
4886
4988
|
skill_name: Type5.String({
|
|
4887
4989
|
minLength: 1,
|
|
@@ -5694,7 +5796,7 @@ function mergeRecentCanvases(existing, created) {
|
|
|
5694
5796
|
}
|
|
5695
5797
|
function createSlackCanvasCreateTool(context, state) {
|
|
5696
5798
|
return tool({
|
|
5697
|
-
description: "Create a Slack canvas for long-form output in the active assistant context channel. Use when the answer is better as a reusable document than a thread reply: long-form research, timelines, bios/profiles, structured notes, plans, comparisons, or anything likely to exceed one compact Slack reply. After creating it,
|
|
5799
|
+
description: "Create a Slack canvas for long-form output in the active assistant context channel. Use when the answer is better as a reusable document than a thread reply: long-form research, timelines, bios/profiles, structured notes, plans, comparisons, or anything likely to exceed one compact Slack reply. After creating it, reply with one or two short sentences plus the canvas link; do not recap the canvas contents. Do not use for short answers that fit cleanly in one normal thread reply.",
|
|
5698
5800
|
inputSchema: Type12.Object({
|
|
5699
5801
|
title: Type12.String({
|
|
5700
5802
|
minLength: 1,
|
|
@@ -6435,25 +6537,24 @@ async function fetchWithPinnedLookup(url, resolved, signal) {
|
|
|
6435
6537
|
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
6436
6538
|
});
|
|
6437
6539
|
response.on("end", () => {
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
}
|
|
6445
|
-
continue;
|
|
6446
|
-
}
|
|
6447
|
-
if (typeof value === "string") {
|
|
6448
|
-
headers.set(name, value);
|
|
6540
|
+
try {
|
|
6541
|
+
signal.removeEventListener("abort", onAbort);
|
|
6542
|
+
const headers = new Headers();
|
|
6543
|
+
const rawHeaders = response.rawHeaders;
|
|
6544
|
+
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
6545
|
+
headers.append(rawHeaders[i], rawHeaders[i + 1]);
|
|
6449
6546
|
}
|
|
6547
|
+
const rawStatus = response.statusCode ?? 500;
|
|
6548
|
+
const status = rawStatus >= 200 && rawStatus <= 599 ? rawStatus : 502;
|
|
6549
|
+
resolve(
|
|
6550
|
+
new Response(Buffer.concat(chunks), {
|
|
6551
|
+
status,
|
|
6552
|
+
headers
|
|
6553
|
+
})
|
|
6554
|
+
);
|
|
6555
|
+
} catch (error) {
|
|
6556
|
+
reject(error);
|
|
6450
6557
|
}
|
|
6451
|
-
resolve(
|
|
6452
|
-
new Response(Buffer.concat(chunks), {
|
|
6453
|
-
status: response.statusCode ?? 500,
|
|
6454
|
-
headers
|
|
6455
|
-
})
|
|
6456
|
-
);
|
|
6457
6558
|
});
|
|
6458
6559
|
}
|
|
6459
6560
|
);
|
|
@@ -6544,9 +6645,7 @@ async function readResponseBody(response, maxBytes) {
|
|
|
6544
6645
|
}
|
|
6545
6646
|
chunks.push(value);
|
|
6546
6647
|
}
|
|
6547
|
-
return new TextDecoder().decode(
|
|
6548
|
-
Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)))
|
|
6549
|
-
);
|
|
6648
|
+
return new TextDecoder().decode(Buffer.concat(chunks));
|
|
6550
6649
|
}
|
|
6551
6650
|
|
|
6552
6651
|
// src/chat/tools/web/fetch-content.ts
|
|
@@ -7484,7 +7583,17 @@ if (args.length === 0 || args[0] === "--version" || args[0] === "version") {
|
|
|
7484
7583
|
process.exit(0);
|
|
7485
7584
|
}
|
|
7486
7585
|
|
|
7487
|
-
if (args[0] === "
|
|
7586
|
+
if (args[0] === "--help" || args[0] === "help") {
|
|
7587
|
+
outputText("USAGE\\n sentry issue list|view|events ...\\n sentry org list|view ...\\n sentry log list|view ...\\n sentry trace list|view|logs ...\\n sentry api ...\\n");
|
|
7588
|
+
process.exit(0);
|
|
7589
|
+
}
|
|
7590
|
+
|
|
7591
|
+
if (args.includes("--help")) {
|
|
7592
|
+
outputText("sentry eval stub help\\n");
|
|
7593
|
+
process.exit(0);
|
|
7594
|
+
}
|
|
7595
|
+
|
|
7596
|
+
if (args[0] === "issue" && args[1] === "list") {
|
|
7488
7597
|
if (hasFlag("--json")) {
|
|
7489
7598
|
outputJson([]);
|
|
7490
7599
|
} else {
|
|
@@ -7493,7 +7602,7 @@ if (args[0] === "issues" && args[1] === "list") {
|
|
|
7493
7602
|
process.exit(0);
|
|
7494
7603
|
}
|
|
7495
7604
|
|
|
7496
|
-
if (args[0] === "
|
|
7605
|
+
if (args[0] === "org" && args[1] === "list") {
|
|
7497
7606
|
if (hasFlag("--json")) {
|
|
7498
7607
|
outputJson([{ slug: "getsentry", name: "Sentry" }]);
|
|
7499
7608
|
} else {
|
|
@@ -8948,6 +9057,8 @@ function trimTrailingAssistantMessages(messages) {
|
|
|
8948
9057
|
// src/chat/services/reply-delivery-plan.ts
|
|
8949
9058
|
var REACTION_ONLY_ACK_RE = /^(?::[a-z0-9_+-]+:|[\p{Extended_Pictographic}\uFE0F\u200D]+)$/u;
|
|
8950
9059
|
var REDUNDANT_REACTION_ACK_TEXT = ["done", "got it", "ok", "okay"];
|
|
9060
|
+
var REACTION_INTENT_RE = /\b(react|reaction|emoji|thumbs?\s*up|acknowledge)\b/i;
|
|
9061
|
+
var REACTION_WITH_REPLY_INTENT_RE = /\b(confirm|explain|reply|respond|say|tell|summari[sz]e|why)\b/i;
|
|
8951
9062
|
function normalizeReactionAckText(text) {
|
|
8952
9063
|
return text.trim().toLowerCase().replace(/[!.]+$/g, "");
|
|
8953
9064
|
}
|
|
@@ -8964,6 +9075,13 @@ function isRedundantReactionAckText(text) {
|
|
|
8964
9075
|
normalized
|
|
8965
9076
|
);
|
|
8966
9077
|
}
|
|
9078
|
+
function isReactionOnlyIntent(text) {
|
|
9079
|
+
const normalized = text.trim();
|
|
9080
|
+
if (!normalized) {
|
|
9081
|
+
return false;
|
|
9082
|
+
}
|
|
9083
|
+
return REACTION_INTENT_RE.test(normalized) && !REACTION_WITH_REPLY_INTENT_RE.test(normalized);
|
|
9084
|
+
}
|
|
8967
9085
|
function buildReplyDeliveryPlan(args) {
|
|
8968
9086
|
const mode = args.explicitChannelPostIntent && args.channelPostPerformed ? "channel_only" : "thread";
|
|
8969
9087
|
let attachFiles = "none";
|
|
@@ -9024,6 +9142,22 @@ Note: No file was attached in this turn. I need to attach the file before claimi
|
|
|
9024
9142
|
}
|
|
9025
9143
|
|
|
9026
9144
|
// src/chat/services/turn-result.ts
|
|
9145
|
+
var POST_CANVAS_REPLY_MAX_CHARS = 700;
|
|
9146
|
+
var POST_CANVAS_REPLY_MAX_LINES = 8;
|
|
9147
|
+
function isVerbosePostCanvasReply(text) {
|
|
9148
|
+
const lines = text.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
9149
|
+
return text.length > POST_CANVAS_REPLY_MAX_CHARS || lines.length > POST_CANVAS_REPLY_MAX_LINES;
|
|
9150
|
+
}
|
|
9151
|
+
function getCreatedCanvasUrl(artifactStatePatch) {
|
|
9152
|
+
if (artifactStatePatch.lastCanvasUrl) {
|
|
9153
|
+
return artifactStatePatch.lastCanvasUrl;
|
|
9154
|
+
}
|
|
9155
|
+
return artifactStatePatch.recentCanvases?.find((canvas) => canvas.url)?.url;
|
|
9156
|
+
}
|
|
9157
|
+
function buildBriefPostCanvasReply(artifactStatePatch) {
|
|
9158
|
+
const canvasUrl = getCreatedCanvasUrl(artifactStatePatch);
|
|
9159
|
+
return canvasUrl ? `I created a canvas with the full reference: ${canvasUrl}` : "I created a canvas with the full reference.";
|
|
9160
|
+
}
|
|
9027
9161
|
function buildTurnResult(input) {
|
|
9028
9162
|
const {
|
|
9029
9163
|
newMessages,
|
|
@@ -9053,6 +9187,7 @@ function buildTurnResult(input) {
|
|
|
9053
9187
|
const channelPostPerformed = successfulToolNames.has(
|
|
9054
9188
|
"slackChannelPostMessage"
|
|
9055
9189
|
);
|
|
9190
|
+
const canvasCreated = successfulToolNames.has("slackCanvasCreate");
|
|
9056
9191
|
const reactionPerformed = successfulToolNames.has("slackMessageAddReaction");
|
|
9057
9192
|
const baseDeliveryPlan = buildReplyDeliveryPlan({
|
|
9058
9193
|
explicitChannelPostIntent,
|
|
@@ -9085,7 +9220,9 @@ function buildTurnResult(input) {
|
|
|
9085
9220
|
const usedPrimaryText = Boolean(primaryText);
|
|
9086
9221
|
const outcome = primaryText ? stopReason === "error" ? "provider_error" : "success" : sideEffectOnlySuccess ? "success" : "execution_failure";
|
|
9087
9222
|
const fallbackText = buildExecutionFailureMessage(toolErrorCount);
|
|
9088
|
-
const
|
|
9223
|
+
const suppressReactionOnlyText = reactionPerformed && !channelPostPerformed && replyFiles.length === 0 && Boolean(primaryText) && isReactionOnlyIntent(userInput);
|
|
9224
|
+
const rawResponseText = suppressReactionOnlyText ? "" : primaryText || (sideEffectOnlySuccess ? "" : fallbackText);
|
|
9225
|
+
const responseText = canvasCreated && isVerbosePostCanvasReply(rawResponseText) ? buildBriefPostCanvasReply(artifactStatePatch) : rawResponseText;
|
|
9089
9226
|
const escapedOrRawPayload = Boolean(primaryText) && (isExecutionEscapeResponse(primaryText) || isRawToolPayloadResponse(primaryText));
|
|
9090
9227
|
const resolvedText = escapedOrRawPayload ? fallbackText : enforceAttachmentClaimTruth(responseText, replyFiles.length > 0);
|
|
9091
9228
|
const deliveryPlan = reactionPerformed && !resolvedText && replyFiles.length === 0 && !channelPostPerformed ? {
|
|
@@ -9149,7 +9286,13 @@ var turnExecutionProfileSchema = z.object({
|
|
|
9149
9286
|
confidence: z.number().min(0).max(1),
|
|
9150
9287
|
reason: z.string().min(1)
|
|
9151
9288
|
});
|
|
9152
|
-
var DEFAULT_THINKING_LEVEL = "
|
|
9289
|
+
var DEFAULT_THINKING_LEVEL = "medium";
|
|
9290
|
+
var THINKING_LEVEL_RANK = {
|
|
9291
|
+
none: 0,
|
|
9292
|
+
low: 1,
|
|
9293
|
+
medium: 2,
|
|
9294
|
+
high: 3
|
|
9295
|
+
};
|
|
9153
9296
|
function trimContextForRouter(text) {
|
|
9154
9297
|
const trimmed = text?.trim();
|
|
9155
9298
|
if (!trimmed) {
|
|
@@ -9172,13 +9315,14 @@ function trimContextForRouter(text) {
|
|
|
9172
9315
|
}
|
|
9173
9316
|
function buildClassifierSystemPrompt() {
|
|
9174
9317
|
return [
|
|
9175
|
-
"You route assistant turns to the
|
|
9318
|
+
"You route assistant turns to the thinking level most likely to produce a complete, source-grounded answer.",
|
|
9176
9319
|
"Choose exactly one bucket: none, low, medium, or high.",
|
|
9177
9320
|
"",
|
|
9178
|
-
"Use none for greetings, acknowledgments, and
|
|
9179
|
-
"Use low for
|
|
9180
|
-
"Use medium for
|
|
9321
|
+
"Use none only for greetings, acknowledgments, and turns that need no substantive assistant work.",
|
|
9322
|
+
"Use low rarely: only for deterministic one-step answers or transformations with no tools, no current/external facts, no thread-background interpretation, and no source verification.",
|
|
9323
|
+
"Use medium for normal assistant work: explanations, source-backed checks, thread follow-ups, tool choice, likely tool use, ambiguous asks, multi-step analysis, or anything where a confident but shallow answer would be risky.",
|
|
9181
9324
|
"Use high for code changes, debugging/root-cause analysis, research-heavy work, non-trivial drafting, or explicit requests to be thorough.",
|
|
9325
|
+
"When unsure between two non-none buckets, choose the higher bucket. Do not use low as the default.",
|
|
9182
9326
|
"",
|
|
9183
9327
|
"Classify based on the substance of the task, not the length of the current message. When the current instruction is a short affirmation (for example: 'go', 'do it', 'yes please', 'proceed') and the thread-background contains a pending task, classify the pending task \u2014 not the affirmation.",
|
|
9184
9328
|
"",
|
|
@@ -9251,15 +9395,31 @@ async function selectTurnThinkingLevel(args) {
|
|
|
9251
9395
|
},
|
|
9252
9396
|
prompt
|
|
9253
9397
|
});
|
|
9398
|
+
const normalizedSelection = applyThinkingFloor(selection, {
|
|
9399
|
+
minimum: trimmedContext || turnBlockCount > 0 ? "medium" : void 0
|
|
9400
|
+
});
|
|
9254
9401
|
setSpanAttributes({
|
|
9255
|
-
"app.ai.thinking_level":
|
|
9256
|
-
"app.ai.thinking_level_reason":
|
|
9257
|
-
...
|
|
9402
|
+
"app.ai.thinking_level": normalizedSelection.thinkingLevel,
|
|
9403
|
+
"app.ai.thinking_level_reason": normalizedSelection.reason,
|
|
9404
|
+
...normalizedSelection.confidence !== void 0 ? {
|
|
9405
|
+
"app.ai.thinking_level_confidence": normalizedSelection.confidence
|
|
9406
|
+
} : {}
|
|
9258
9407
|
});
|
|
9259
|
-
return
|
|
9408
|
+
return normalizedSelection;
|
|
9260
9409
|
}
|
|
9261
9410
|
);
|
|
9262
9411
|
}
|
|
9412
|
+
function applyThinkingFloor(selection, args) {
|
|
9413
|
+
const minimum = args.minimum;
|
|
9414
|
+
if (!minimum || selection.thinkingLevel === "none" || THINKING_LEVEL_RANK[selection.thinkingLevel] >= THINKING_LEVEL_RANK[minimum]) {
|
|
9415
|
+
return selection;
|
|
9416
|
+
}
|
|
9417
|
+
return {
|
|
9418
|
+
...selection,
|
|
9419
|
+
thinkingLevel: minimum,
|
|
9420
|
+
reason: `thinking_floor:${minimum}:${selection.reason}`
|
|
9421
|
+
};
|
|
9422
|
+
}
|
|
9263
9423
|
async function classifyTurn(args) {
|
|
9264
9424
|
try {
|
|
9265
9425
|
const result = await args.completeObject({
|
|
@@ -9278,7 +9438,7 @@ async function classifyTurn(args) {
|
|
|
9278
9438
|
return {
|
|
9279
9439
|
confidence: parsed.confidence,
|
|
9280
9440
|
thinkingLevel: DEFAULT_THINKING_LEVEL,
|
|
9281
|
-
reason: `
|
|
9441
|
+
reason: `low_confidence_medium_default:${reason}`
|
|
9282
9442
|
};
|
|
9283
9443
|
}
|
|
9284
9444
|
return {
|
|
@@ -10013,6 +10173,7 @@ async function generateAssistantReply(messageText, context = {}) {
|
|
|
10013
10173
|
timeoutResumeSliceId = currentSliceId;
|
|
10014
10174
|
const persistedConfigurationValues = context.channelConfiguration ? await context.channelConfiguration.resolveValues() : {};
|
|
10015
10175
|
configurationValues = {
|
|
10176
|
+
...getConfigDefaults(),
|
|
10016
10177
|
...context.configuration ?? {},
|
|
10017
10178
|
...persistedConfigurationValues
|
|
10018
10179
|
};
|
|
@@ -10215,6 +10376,8 @@ async function generateAssistantReply(messageText, context = {}) {
|
|
|
10215
10376
|
assistantUserName: context.assistant?.userName,
|
|
10216
10377
|
modelId: botConfig.modelId
|
|
10217
10378
|
});
|
|
10379
|
+
const toolChannelId = context.toolChannelId ?? context.correlation?.channelId;
|
|
10380
|
+
const channelCapabilities = resolveChannelCapabilities(toolChannelId);
|
|
10218
10381
|
const tools = createTools(
|
|
10219
10382
|
availableSkills,
|
|
10220
10383
|
{
|
|
@@ -10268,10 +10431,8 @@ async function generateAssistantReply(messageText, context = {}) {
|
|
|
10268
10431
|
}
|
|
10269
10432
|
},
|
|
10270
10433
|
{
|
|
10271
|
-
channelId:
|
|
10272
|
-
channelCapabilities
|
|
10273
|
-
context.toolChannelId ?? context.correlation?.channelId
|
|
10274
|
-
),
|
|
10434
|
+
channelId: toolChannelId,
|
|
10435
|
+
channelCapabilities,
|
|
10275
10436
|
messageTs: context.correlation?.messageTs,
|
|
10276
10437
|
threadTs: context.correlation?.threadTs,
|
|
10277
10438
|
userText: userInput,
|
|
@@ -10300,6 +10461,13 @@ async function generateAssistantReply(messageText, context = {}) {
|
|
|
10300
10461
|
availableSkills,
|
|
10301
10462
|
activeSkills,
|
|
10302
10463
|
activeMcpCatalogs,
|
|
10464
|
+
runtime: {
|
|
10465
|
+
channelId: toolChannelId,
|
|
10466
|
+
fastModelId: botConfig.fastModelId,
|
|
10467
|
+
modelId: botConfig.modelId,
|
|
10468
|
+
slackCapabilities: channelCapabilities,
|
|
10469
|
+
thinkingLevel: thinkingSelection.thinkingLevel
|
|
10470
|
+
},
|
|
10303
10471
|
invocation: skillInvocation,
|
|
10304
10472
|
assistant: context.assistant,
|
|
10305
10473
|
requester: context.requester,
|
|
@@ -15881,6 +16049,7 @@ async function createApp(options) {
|
|
|
15881
16049
|
setPluginPackages(
|
|
15882
16050
|
options?.pluginPackages ?? await resolveBuildPluginPackages()
|
|
15883
16051
|
);
|
|
16052
|
+
setConfigDefaults(options?.configDefaults);
|
|
15884
16053
|
const waitUntil = options?.waitUntil ?? await defaultWaitUntil();
|
|
15885
16054
|
const app = new Hono();
|
|
15886
16055
|
app.onError((err, c) => {
|
|
@@ -2725,6 +2725,9 @@ function getPluginDefinition(provider) {
|
|
|
2725
2725
|
function isPluginProvider(provider) {
|
|
2726
2726
|
return ensurePluginsLoaded().pluginsByName.has(provider);
|
|
2727
2727
|
}
|
|
2728
|
+
function isPluginConfigKey(key) {
|
|
2729
|
+
return ensurePluginsLoaded().pluginConfigKeys.has(key);
|
|
2730
|
+
}
|
|
2728
2731
|
function createPluginBroker(provider, deps) {
|
|
2729
2732
|
const plugin = ensurePluginsLoaded().pluginsByName.get(provider);
|
|
2730
2733
|
if (!plugin) {
|
|
@@ -2787,5 +2790,6 @@ export {
|
|
|
2787
2790
|
getPluginForSkillPath,
|
|
2788
2791
|
getPluginDefinition,
|
|
2789
2792
|
isPluginProvider,
|
|
2793
|
+
isPluginConfigKey,
|
|
2790
2794
|
createPluginBroker
|
|
2791
2795
|
};
|
package/dist/cli/check.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseSkillFile
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-EHXMTKBA.js";
|
|
4
4
|
import {
|
|
5
5
|
parsePluginManifest
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-XARRBRQV.js";
|
|
7
7
|
import "../chunk-Z3YD6NHK.js";
|
|
8
8
|
import "../chunk-XPXD3FCE.js";
|
|
9
9
|
import "../chunk-2KG3PWR4.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
disconnectStateAdapter,
|
|
3
3
|
resolveRuntimeDependencySnapshot
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-3M7ZD6FF.js";
|
|
5
5
|
import {
|
|
6
6
|
getPluginProviders,
|
|
7
7
|
getPluginRuntimeDependencies,
|
|
8
8
|
getPluginRuntimePostinstall
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-XARRBRQV.js";
|
|
10
10
|
import "../chunk-Z3YD6NHK.js";
|
|
11
11
|
import "../chunk-XPXD3FCE.js";
|
|
12
12
|
import "../chunk-2KG3PWR4.js";
|