@sentry/junior 0.133.0 → 0.135.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 (69) hide show
  1. package/dist/{agent-hooks-5BUIXVIX.js → agent-hooks-EMXDAD2K.js} +9 -9
  2. package/dist/api/schema/task.d.ts +36 -0
  3. package/dist/api/schema.d.ts +1 -1
  4. package/dist/api/schema.js +1 -1
  5. package/dist/api.js +39 -20
  6. package/dist/app.js +46 -24
  7. package/dist/{catalog-runtime-VGB3DWXZ.js → catalog-runtime-NVPT6HA5.js} +5 -5
  8. package/dist/chat/agent/prompt.d.ts +7 -5
  9. package/dist/chat/agent/repository-context.d.ts +20 -0
  10. package/dist/chat/agent/sandbox.d.ts +8 -0
  11. package/dist/chat/agent/tools.d.ts +3 -0
  12. package/dist/chat/plugins/agent-hooks.d.ts +2 -2
  13. package/dist/chat/repository-instructions.d.ts +44 -0
  14. package/dist/chat/sandbox/noninteractive-command.d.ts +2 -0
  15. package/dist/chat/sandbox/sandbox.d.ts +3 -0
  16. package/dist/chat/sandbox/session.d.ts +1 -0
  17. package/dist/chat/services/context-compaction.d.ts +1 -0
  18. package/dist/chat/slack/tools/user-lookup.d.ts +2 -6
  19. package/dist/chat/tasks/execution-stats.d.ts +28 -0
  20. package/dist/chat/tools/index.d.ts +2 -0
  21. package/dist/chat/tools/sandbox/bash.d.ts +1 -0
  22. package/dist/chat/tools/system-time.d.ts +11 -1
  23. package/dist/{chunk-XTQGVNM3.js → chunk-45DPXMI3.js} +6 -12
  24. package/dist/{chunk-TU7P77FI.js → chunk-5EX36ZCD.js} +12 -12
  25. package/dist/{chunk-VL7OYSHD.js → chunk-5LD6EBH2.js} +1 -1
  26. package/dist/{chunk-HJ4KDO4N.js → chunk-6UNZ5DHG.js} +1 -1
  27. package/dist/{chunk-IVTHTAVK.js → chunk-AGAHACF7.js} +2 -2
  28. package/dist/{chunk-HX236W2U.js → chunk-CDQ4YIZM.js} +9 -0
  29. package/dist/{chunk-5ZAZHLIW.js → chunk-EBRB6ZBF.js} +1 -1
  30. package/dist/{chunk-VQA25AL4.js → chunk-EJT7EPP3.js} +6 -6
  31. package/dist/{chunk-FX6BLEDP.js → chunk-HDGTBCQR.js} +1 -1
  32. package/dist/{chunk-AH5HTUYX.js → chunk-IRTIVX42.js} +1 -1
  33. package/dist/{chunk-ECUILEUX.js → chunk-NGX2V4WY.js} +430 -29
  34. package/dist/{chunk-TBVS7GBE.js → chunk-OSCF2BDE.js} +9 -8
  35. package/dist/{chunk-HTGXUNEC.js → chunk-P2D7IW57.js} +7 -7
  36. package/dist/{chunk-EJRJWBKG.js → chunk-QQCEMMVN.js} +1 -1
  37. package/dist/{chunk-LDRO4OQ4.js → chunk-RMI6OX52.js} +2 -2
  38. package/dist/{chunk-QVEXYYFM.js → chunk-TRZSM67C.js} +11 -1
  39. package/dist/{chunk-TLN54TOQ.js → chunk-TYEDZVRM.js} +32 -32
  40. package/dist/{chunk-QWGZ273D.js → chunk-U37P4IIP.js} +81 -27
  41. package/dist/{chunk-JLN4XSPR.js → chunk-UXYZPEWP.js} +1 -1
  42. package/dist/{chunk-LNYNTR27.js → chunk-VZEKCQLD.js} +3 -3
  43. package/dist/{chunk-T5FPIBU2.js → chunk-Y6627MTY.js} +788 -674
  44. package/dist/{chunk-IKO5LFIU.js → chunk-YPKPXLMS.js} +1 -1
  45. package/dist/chunk-Z67KVHMJ.js +233 -0
  46. package/dist/{chunk-WHEMUEXT.js → chunk-ZBQIA5NI.js} +8 -6
  47. package/dist/cli/chat.js +25 -25
  48. package/dist/cli/check.js +6 -6
  49. package/dist/cli/init.js +0 -1
  50. package/dist/cli/plugins.js +12 -12
  51. package/dist/cli/snapshot-create.js +9 -9
  52. package/dist/cli/upgrade.js +7 -7
  53. package/dist/db/schema/task-executions.d.ts +110 -0
  54. package/dist/db/schema.d.ts +111 -1
  55. package/dist/{db-RICMPUFT.js → db-UA6OFL25.js} +7 -7
  56. package/dist/instrumentation.js +4 -4
  57. package/dist/nitro.js +2 -2
  58. package/dist/{oauth-callback-server-YFVS4SAX.js → oauth-callback-server-IJDYBSTX.js} +18 -18
  59. package/dist/{runner-A3LVGZR6.js → runner-K6GID4HN.js} +12 -12
  60. package/dist/{skills-P7Q6Z6PN.js → skills-KJVS753I.js} +6 -6
  61. package/dist/{validation-RYHOWBET.js → validation-7VDJGK7K.js} +6 -6
  62. package/dist/version.js +1 -1
  63. package/migrations/0019_lowly_valkyrie.sql +14 -0
  64. package/migrations/0020_restrict_task_execution_kinds.sql +2 -0
  65. package/migrations/meta/0019_snapshot.json +1904 -0
  66. package/migrations/meta/0020_snapshot.json +1848 -0
  67. package/migrations/meta/_journal.json +15 -1
  68. package/package.json +4 -4
  69. package/dist/chunk-V365UVCU.js +0 -115
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  JUNIOR_NATIVE_EVENT_NAMESPACE,
3
+ ToolInputError,
3
4
  addAgentTurnUsage,
4
5
  agentTurnUsageSchema,
5
6
  authenticationLinkedEvent,
6
7
  authenticationUnlinkedEvent
7
- } from "./chunk-HX236W2U.js";
8
+ } from "./chunk-CDQ4YIZM.js";
8
9
  import {
9
10
  agentHistoryItemSchema,
10
11
  bindProviderConversation,
@@ -17,17 +18,18 @@ import {
17
18
  instructionProvenanceFor,
18
19
  sanitizePostgresJson,
19
20
  withConversationEventLock
20
- } from "./chunk-LNYNTR27.js";
21
+ } from "./chunk-VZEKCQLD.js";
21
22
  import {
23
+ SANDBOX_WORKSPACE_ROOT,
22
24
  getStateAdapter,
23
25
  sleep
24
- } from "./chunk-TLN54TOQ.js";
26
+ } from "./chunk-TYEDZVRM.js";
25
27
  import {
26
28
  botConfig,
27
29
  escapeXml,
28
30
  resolveGatewayModel,
29
31
  unwrapCurrentInstruction
30
- } from "./chunk-LDRO4OQ4.js";
32
+ } from "./chunk-RMI6OX52.js";
31
33
  import {
32
34
  toStoredSlackActor
33
35
  } from "./chunk-HZF5P5UN.js";
@@ -42,19 +44,35 @@ import {
42
44
  setSpanAttributes,
43
45
  toOptionalNumber,
44
46
  toOptionalString
45
- } from "./chunk-EJRJWBKG.js";
47
+ } from "./chunk-QQCEMMVN.js";
46
48
 
47
49
  // src/chat/turn-context-tag.ts
48
50
  var TURN_CONTEXT_TAG = "runtime-turn-context";
49
51
 
50
52
  // src/chat/pi/transcript.ts
51
53
  var RUNTIME_TURN_CONTEXT_START = `<${TURN_CONTEXT_TAG}>`;
54
+ var AGENTS_INSTRUCTIONS_START = "# AGENTS.md instructions";
52
55
  function userMessageContent(message) {
53
56
  const record = message;
54
57
  return record.role === "user" && Array.isArray(record.content) ? record.content : void 0;
55
58
  }
56
59
  function isRuntimeTurnContextPart(part) {
57
- return part !== null && typeof part === "object" && part.type === "text" && typeof part.text === "string" && part.text.startsWith(RUNTIME_TURN_CONTEXT_START);
60
+ return part !== null && typeof part === "object" && part.type === "text" && typeof part.text === "string" && (part.text.startsWith(RUNTIME_TURN_CONTEXT_START) || part.text.startsWith(AGENTS_INSTRUCTIONS_START));
61
+ }
62
+ function hasCurrentInstruction(message) {
63
+ return userMessageContent(message)?.some(
64
+ (part) => part !== null && typeof part === "object" && part.type === "text" && typeof part.text === "string" && part.text.includes("<current-instruction")
65
+ ) ?? false;
66
+ }
67
+ function messageTimestamp(message) {
68
+ return message.timestamp;
69
+ }
70
+ function isStandaloneRuntimeContextMessage(messages, index) {
71
+ const message = messages[index];
72
+ const next = messages[index + 1];
73
+ return Boolean(
74
+ message && next && userMessageContent(message) && userMessageContent(next) && messageTimestamp(message) === messageTimestamp(next) && !hasCurrentInstruction(message) && hasCurrentInstruction(next)
75
+ );
58
76
  }
59
77
  var EMBEDDED_THREAD_CONTEXT_TAGS = [
60
78
  "recent-thread-messages",
@@ -123,11 +141,14 @@ function trimTrailingAssistantMessages(messages) {
123
141
  }
124
142
  function hasRuntimeTurnContext(messages) {
125
143
  return messages.some(
126
- (message) => userMessageContent(message)?.some(isRuntimeTurnContextPart)
144
+ (message, index) => isStandaloneRuntimeContextMessage(messages, index) || userMessageContent(message)?.some(isRuntimeTurnContextPart)
127
145
  );
128
146
  }
129
147
  function retainRuntimeTurnContext(messages) {
130
- return messages.flatMap((message) => {
148
+ return messages.flatMap((message, index) => {
149
+ if (isStandaloneRuntimeContextMessage(messages, index)) {
150
+ return [message];
151
+ }
131
152
  const runtimeContent = userMessageContent(message)?.filter(isRuntimeTurnContextPart) ?? [];
132
153
  return runtimeContent.length > 0 ? [{ ...message, content: runtimeContent }] : [];
133
154
  });
@@ -147,7 +168,10 @@ function getUserMessageInstructionText(message) {
147
168
  return instructionTextForProjection(text).trim();
148
169
  }
149
170
  function stripRuntimeTurnContext(messages) {
150
- return messages.flatMap((message) => {
171
+ return messages.flatMap((message, index) => {
172
+ if (isStandaloneRuntimeContextMessage(messages, index)) {
173
+ return [];
174
+ }
151
175
  const content = userMessageContent(message);
152
176
  if (!content) return [message];
153
177
  const nextContent = content.filter(
@@ -978,7 +1002,7 @@ async function loadConnectedMcpProviders(args) {
978
1002
  );
979
1003
  return connectedMcpProvidersFromEvents(events);
980
1004
  }
981
- function messageTimestamp(message) {
1005
+ function messageTimestamp2(message) {
982
1006
  const timestamp = message.timestamp;
983
1007
  return typeof timestamp === "number" ? timestamp : Date.now();
984
1008
  }
@@ -1006,7 +1030,7 @@ async function commitAcceptedReply(args) {
1006
1030
  {
1007
1031
  idempotencyKey: `message:${args.conversationMessageId}:agent`,
1008
1032
  data: historyItemFromPiMessage(agentMessage, contextProvenance),
1009
- createdAtMs: messageTimestamp(agentMessage)
1033
+ createdAtMs: messageTimestamp2(agentMessage)
1010
1034
  }
1011
1035
  ]
1012
1036
  );
@@ -1070,7 +1094,7 @@ async function commitMessagesLocked(args, executor) {
1070
1094
  message,
1071
1095
  nextLocalProvenance[matchingPrefix + index]
1072
1096
  ),
1073
- createdAtMs: messageTimestamp(message)
1097
+ createdAtMs: messageTimestamp2(message)
1074
1098
  })),
1075
1099
  ...turnContextEvents
1076
1100
  ]);
@@ -1399,6 +1423,354 @@ import {
1399
1423
  } from "@sentry/junior-plugin-api";
1400
1424
  import { z as z2 } from "zod";
1401
1425
 
1426
+ // src/chat/repository-instructions.ts
1427
+ import { createHash as createHash2 } from "crypto";
1428
+ import path2 from "path";
1429
+
1430
+ // src/chat/tools/sandbox/file-utils.ts
1431
+ import path from "path";
1432
+ var MAX_TEXT_CHARS = 6e4;
1433
+ var RIPGREP_EXCLUDED_GLOBS = [
1434
+ "!**/.git/**",
1435
+ "!**/node_modules/**"
1436
+ ];
1437
+ var DEFAULT_SEARCH_COMMAND_TIMEOUT_MS = 3e4;
1438
+ var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
1439
+ function positiveInteger2(value) {
1440
+ if (typeof value !== "number" || !Number.isFinite(value)) {
1441
+ return void 0;
1442
+ }
1443
+ const integer = Math.floor(value);
1444
+ return integer > 0 ? integer : void 0;
1445
+ }
1446
+ function normalizeToLf(value) {
1447
+ return value.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1448
+ }
1449
+ function truncateText(value, maxChars = MAX_TEXT_CHARS) {
1450
+ if (value.length <= maxChars) {
1451
+ return { content: value, truncated: false };
1452
+ }
1453
+ const removed = value.length - maxChars;
1454
+ return {
1455
+ content: `${value.slice(0, maxChars)}
1456
+
1457
+ [output truncated: ${removed} characters removed]`,
1458
+ truncated: true
1459
+ };
1460
+ }
1461
+ function isMissingPathError(error) {
1462
+ if (!error || typeof error !== "object") {
1463
+ return false;
1464
+ }
1465
+ const candidate = error;
1466
+ if (candidate.code === "ENOENT") {
1467
+ return true;
1468
+ }
1469
+ return typeof candidate.message === "string" && candidate.message.startsWith("File not found:");
1470
+ }
1471
+ function missingPathSearchResult(params) {
1472
+ const textPath = params.displayPath ?? params.missingPath ?? params.path;
1473
+ throw new ToolInputError(`Path not found: ${textPath}`);
1474
+ }
1475
+ function escapeRegExp(value) {
1476
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1477
+ }
1478
+ function globToRegExp(pattern) {
1479
+ let source = "";
1480
+ for (let index = 0; index < pattern.length; index += 1) {
1481
+ const char = pattern[index];
1482
+ const next = pattern[index + 1];
1483
+ if (char === "*" && next === "*") {
1484
+ if (pattern[index + 2] === "/") {
1485
+ source += "(?:.*/)?";
1486
+ index += 2;
1487
+ continue;
1488
+ }
1489
+ source += ".*";
1490
+ index += 1;
1491
+ continue;
1492
+ }
1493
+ if (char === "*") {
1494
+ source += "[^/]*";
1495
+ continue;
1496
+ }
1497
+ if (char === "?") {
1498
+ source += "[^/]";
1499
+ continue;
1500
+ }
1501
+ source += escapeRegExp(char);
1502
+ }
1503
+ return new RegExp(`^${source}$`);
1504
+ }
1505
+ function matchesGlob(relativePath, pattern) {
1506
+ const matcher = globToRegExp(pattern);
1507
+ if (matcher.test(relativePath)) {
1508
+ return true;
1509
+ }
1510
+ if (pattern.startsWith("**/") && matchesGlob(relativePath, pattern.slice(3))) {
1511
+ return true;
1512
+ }
1513
+ return !pattern.includes("/") && matcher.test(path.posix.basename(relativePath));
1514
+ }
1515
+ function resolveWorkspacePath(input, fallback = ".") {
1516
+ const requested = (input ?? "").trim() || fallback;
1517
+ const absolute = requested.startsWith("/") ? requested : path.posix.join(SANDBOX_WORKSPACE_ROOT, requested);
1518
+ const normalized = path.posix.normalize(absolute);
1519
+ if (normalized !== SANDBOX_WORKSPACE_ROOT && !normalized.startsWith(`${SANDBOX_WORKSPACE_ROOT}/`)) {
1520
+ throw new ToolInputError(
1521
+ `Path must stay within ${SANDBOX_WORKSPACE_ROOT}: ${requested}`
1522
+ );
1523
+ }
1524
+ return normalized;
1525
+ }
1526
+ function getRipgrepSearchLocation(root, rootIsDirectory) {
1527
+ if (rootIsDirectory) {
1528
+ return { cwd: root, target: "." };
1529
+ }
1530
+ return {
1531
+ cwd: path.posix.dirname(root),
1532
+ target: path.posix.basename(root)
1533
+ };
1534
+ }
1535
+ async function collectFiles(params) {
1536
+ const files = [];
1537
+ let limitReached = false;
1538
+ let missingPath;
1539
+ const visit = async (dirPath) => {
1540
+ if (missingPath) {
1541
+ return;
1542
+ }
1543
+ let entries;
1544
+ try {
1545
+ entries = (await params.fs.readdir(dirPath)).sort(
1546
+ (a, b) => a.toLowerCase().localeCompare(b.toLowerCase())
1547
+ );
1548
+ } catch (error) {
1549
+ if (isMissingPathError(error)) {
1550
+ missingPath = dirPath;
1551
+ return;
1552
+ }
1553
+ throw error;
1554
+ }
1555
+ for (const entry of entries) {
1556
+ const fullPath = path.posix.join(dirPath, entry);
1557
+ let stat2;
1558
+ try {
1559
+ stat2 = await params.fs.stat(fullPath);
1560
+ } catch (error) {
1561
+ if (isMissingPathError(error)) {
1562
+ missingPath = fullPath;
1563
+ return;
1564
+ }
1565
+ throw error;
1566
+ }
1567
+ if (stat2.isDirectory()) {
1568
+ if (!SKIPPED_DIRECTORIES.has(entry)) {
1569
+ await visit(fullPath);
1570
+ }
1571
+ if (limitReached) return;
1572
+ continue;
1573
+ }
1574
+ const relativePath = path.posix.relative(params.root, fullPath);
1575
+ if (!params.pattern || matchesGlob(relativePath, params.pattern)) {
1576
+ files.push(fullPath);
1577
+ if (params.limit && files.length >= params.limit) {
1578
+ limitReached = true;
1579
+ return;
1580
+ }
1581
+ }
1582
+ }
1583
+ };
1584
+ let stat;
1585
+ try {
1586
+ stat = await params.fs.stat(params.root);
1587
+ } catch (error) {
1588
+ if (isMissingPathError(error)) {
1589
+ return {
1590
+ files,
1591
+ limitReached: false,
1592
+ missingPath: params.root,
1593
+ missingRoot: true
1594
+ };
1595
+ }
1596
+ throw error;
1597
+ }
1598
+ if (!stat.isDirectory()) {
1599
+ const relativePath = path.posix.basename(params.root);
1600
+ return {
1601
+ files: !params.pattern || matchesGlob(relativePath, params.pattern) ? [params.root] : [],
1602
+ limitReached: false,
1603
+ missingRoot: false
1604
+ };
1605
+ }
1606
+ await visit(params.root);
1607
+ return {
1608
+ files,
1609
+ limitReached,
1610
+ missingPath,
1611
+ missingRoot: missingPath === params.root
1612
+ };
1613
+ }
1614
+
1615
+ // src/chat/repository-instructions.ts
1616
+ var AGENTS_FILENAME = "AGENTS.md";
1617
+ var MAX_REPOSITORY_INSTRUCTIONS_BYTES = 32 * 1024;
1618
+ var AGENTS_REPLACEMENT_NOTICE = "These AGENTS.md instructions replace all previously provided AGENTS.md instructions.";
1619
+ var AGENTS_REMOVAL_NOTICE = "The previously provided AGENTS.md instructions no longer apply.";
1620
+ async function pathExists(fs, target) {
1621
+ try {
1622
+ await fs.stat(target);
1623
+ return true;
1624
+ } catch (error) {
1625
+ if (isMissingPathError(error)) {
1626
+ return false;
1627
+ }
1628
+ throw error;
1629
+ }
1630
+ }
1631
+ async function directoryExists(fs, target) {
1632
+ try {
1633
+ return (await fs.stat(target)).isDirectory();
1634
+ } catch (error) {
1635
+ if (isMissingPathError(error)) {
1636
+ return false;
1637
+ }
1638
+ throw error;
1639
+ }
1640
+ }
1641
+ async function findGitRoot(fs, cwd) {
1642
+ let current = cwd;
1643
+ for (; ; ) {
1644
+ if (await pathExists(fs, path2.posix.join(current, ".git"))) {
1645
+ return current;
1646
+ }
1647
+ if (current === SANDBOX_WORKSPACE_ROOT) {
1648
+ return void 0;
1649
+ }
1650
+ const parent = path2.posix.dirname(current);
1651
+ if (parent === current || parent !== SANDBOX_WORKSPACE_ROOT && !parent.startsWith(`${SANDBOX_WORKSPACE_ROOT}/`)) {
1652
+ return void 0;
1653
+ }
1654
+ current = parent;
1655
+ }
1656
+ }
1657
+ async function findSingleRepositoryDirectory(fs) {
1658
+ const entries = await fs.readdir(SANDBOX_WORKSPACE_ROOT);
1659
+ const repositories = [];
1660
+ for (const entry of entries) {
1661
+ const candidate = path2.posix.join(SANDBOX_WORKSPACE_ROOT, entry);
1662
+ if (await directoryExists(fs, candidate) && await pathExists(fs, path2.posix.join(candidate, ".git"))) {
1663
+ repositories.push(candidate);
1664
+ if (repositories.length > 1) {
1665
+ return void 0;
1666
+ }
1667
+ }
1668
+ }
1669
+ return repositories[0];
1670
+ }
1671
+ async function readInstructionFile(fs, filePath) {
1672
+ try {
1673
+ const content = await fs.readFile(filePath, { encoding: "utf8" });
1674
+ return content.trim() ? content : void 0;
1675
+ } catch (error) {
1676
+ if (isMissingPathError(error)) {
1677
+ return void 0;
1678
+ }
1679
+ throw error;
1680
+ }
1681
+ }
1682
+ async function resolveRepositoryInstructions(args) {
1683
+ const gitRoot = await findGitRoot(args.fs, args.cwd);
1684
+ if (!gitRoot) {
1685
+ return void 0;
1686
+ }
1687
+ const directories = [];
1688
+ let current = args.cwd;
1689
+ for (; ; ) {
1690
+ directories.push(current);
1691
+ if (current === gitRoot) {
1692
+ break;
1693
+ }
1694
+ current = path2.posix.dirname(current);
1695
+ }
1696
+ directories.reverse();
1697
+ const sources = [];
1698
+ let remaining = MAX_REPOSITORY_INSTRUCTIONS_BYTES;
1699
+ for (const directory of directories) {
1700
+ if (remaining <= 0) {
1701
+ break;
1702
+ }
1703
+ const filePath = path2.posix.join(directory, AGENTS_FILENAME);
1704
+ const content = await readInstructionFile(args.fs, filePath);
1705
+ if (!content) {
1706
+ continue;
1707
+ }
1708
+ const bytes = Buffer.from(content, "utf8");
1709
+ const bounded = bytes.length <= remaining ? content : bytes.subarray(0, remaining).toString("utf8");
1710
+ sources.push({ content: bounded, path: filePath });
1711
+ remaining -= Buffer.byteLength(bounded, "utf8");
1712
+ }
1713
+ if (sources.length === 0) {
1714
+ return void 0;
1715
+ }
1716
+ const text = sources.map((source) => source.content).join("\n\n");
1717
+ const fingerprint = createHash2("sha256").update(JSON.stringify({ directory: args.cwd, sources })).digest("hex");
1718
+ return { directory: args.cwd, fingerprint, sources, text };
1719
+ }
1720
+ function renderAgentsInstructions(args) {
1721
+ const directory = args.directory ? ` for ${args.directory}` : "";
1722
+ return `# AGENTS.md instructions${directory}
1723
+
1724
+ <INSTRUCTIONS>
1725
+ ${args.text}
1726
+ </INSTRUCTIONS>`;
1727
+ }
1728
+ function buildAgentsInstructionsMessage(args) {
1729
+ return {
1730
+ role: "user",
1731
+ content: [{ type: "text", text: renderAgentsInstructions(args) }],
1732
+ timestamp: args.timestamp ?? Date.now()
1733
+ };
1734
+ }
1735
+ function findVisibleAgentsInstructions(messages) {
1736
+ for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex -= 1) {
1737
+ const message = messages[messageIndex];
1738
+ if (message.role !== "user" || !Array.isArray(message.content)) {
1739
+ continue;
1740
+ }
1741
+ for (let partIndex = message.content.length - 1; partIndex >= 0; partIndex -= 1) {
1742
+ const part = message.content[partIndex];
1743
+ if (part.type !== "text" || typeof part.text !== "string" || !part.text.startsWith("# AGENTS.md instructions")) {
1744
+ continue;
1745
+ }
1746
+ const match = part.text.match(
1747
+ /^# AGENTS\.md instructions(?: for ([^\n]+))?\n\n<INSTRUCTIONS>\n([\s\S]*)\n<\/INSTRUCTIONS>$/
1748
+ );
1749
+ if (!match) {
1750
+ continue;
1751
+ }
1752
+ let text = match[2];
1753
+ if (text === AGENTS_REMOVAL_NOTICE) {
1754
+ return { active: false };
1755
+ }
1756
+ if (text.startsWith(`${AGENTS_REPLACEMENT_NOTICE}
1757
+
1758
+ `)) {
1759
+ text = text.slice(AGENTS_REPLACEMENT_NOTICE.length + 2);
1760
+ }
1761
+ return {
1762
+ active: true,
1763
+ ...match[1] ? { directory: match[1] } : {},
1764
+ text
1765
+ };
1766
+ }
1767
+ }
1768
+ return void 0;
1769
+ }
1770
+ function isAgentsInstructionsMessage(message) {
1771
+ return Boolean(findVisibleAgentsInstructions([message]));
1772
+ }
1773
+
1402
1774
  // src/chat/state/turn-session-keys.ts
1403
1775
  var AGENT_TURN_SESSION_PREFIX = "junior:agent_turn_session";
1404
1776
  function agentTurnSessionKey(conversationId, sessionId) {
@@ -1530,7 +1902,7 @@ async function recordConversationActivityMetadata(args) {
1530
1902
  });
1531
1903
  }
1532
1904
  function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessageIndex, restoreVolatileContext = true) {
1533
- const piMessages = restoreVolatileContext && (stored.state === "running" || stored.state === "awaiting_resume") ? restoreRuntimeContext(piProjection.messages, stored.runtimeContext) : piProjection.messages;
1905
+ const restoredProjection = restoreVolatileContext && (stored.state === "running" || stored.state === "awaiting_resume") ? restoreRuntimeContext(piProjection, stored.runtimeContext) : piProjection;
1534
1906
  return {
1535
1907
  version: stored.version,
1536
1908
  ...stored.channelName ? { channelName: stored.channelName } : {},
@@ -1541,8 +1913,8 @@ function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessag
1541
1913
  startedAtMs: stored.startedAtMs,
1542
1914
  lastProgressAtMs: stored.lastProgressAtMs,
1543
1915
  updatedAtMs: stored.updatedAtMs,
1544
- piMessages,
1545
- piMessageProvenance: piProjection.provenance,
1916
+ piMessages: restoredProjection.messages,
1917
+ piMessageProvenance: restoredProjection.provenance,
1546
1918
  actors: stored.actors ?? instructionActors(piProjection.provenance),
1547
1919
  cumulativeDurationMs: stored.cumulativeDurationMs,
1548
1920
  ...stored.destination ? { destination: stored.destination } : {},
@@ -1563,30 +1935,41 @@ function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessag
1563
1935
  ...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {}
1564
1936
  };
1565
1937
  }
1566
- function restoreRuntimeContext(messages, runtimeContext) {
1567
- if (!runtimeContext || runtimeContext.length === 0) return messages;
1568
- const restored = [...messages];
1938
+ function restoreRuntimeContext(projection, runtimeContext) {
1939
+ if (!runtimeContext || runtimeContext.length === 0) return projection;
1940
+ const restoredMessages = [...projection.messages];
1941
+ const restoredProvenance = [...projection.provenance];
1569
1942
  const unmatchedRuntimeContext = [];
1570
1943
  for (const runtimeMessage of runtimeContext) {
1571
1944
  const runtime = runtimeMessage;
1572
- const targetIndex = restored.findIndex((message) => {
1945
+ const targetIndex = restoredMessages.findIndex((message) => {
1573
1946
  const candidate = message;
1574
1947
  return candidate.role === "user" && candidate.timestamp === runtime.timestamp;
1575
1948
  });
1576
1949
  if (targetIndex < 0) {
1577
- unmatchedRuntimeContext.push(runtimeMessage);
1950
+ if (isAgentsInstructionsMessage(runtimeMessage)) {
1951
+ const followingIndex = restoredMessages.findIndex((message) => {
1952
+ const timestamp = message.timestamp;
1953
+ return typeof runtime.timestamp === "number" && typeof timestamp === "number" && timestamp > runtime.timestamp;
1954
+ });
1955
+ const insertionIndex = followingIndex < 0 ? restoredMessages.length : followingIndex;
1956
+ restoredMessages.splice(insertionIndex, 0, runtimeMessage);
1957
+ restoredProvenance.splice(insertionIndex, 0, contextProvenance);
1958
+ } else {
1959
+ unmatchedRuntimeContext.push(runtimeMessage);
1960
+ }
1578
1961
  continue;
1579
1962
  }
1580
- const target = restored[targetIndex];
1581
- restored[targetIndex] = {
1582
- ...restored[targetIndex],
1583
- content: [
1584
- ...Array.isArray(runtime.content) ? runtime.content : [],
1585
- ...Array.isArray(target.content) ? target.content : []
1586
- ]
1587
- };
1963
+ restoredMessages.splice(targetIndex, 0, runtimeMessage);
1964
+ restoredProvenance.splice(targetIndex, 0, contextProvenance);
1588
1965
  }
1589
- return [...unmatchedRuntimeContext, ...restored];
1966
+ return {
1967
+ messages: [...unmatchedRuntimeContext, ...restoredMessages],
1968
+ provenance: [
1969
+ ...unmatchedRuntimeContext.map(() => contextProvenance),
1970
+ ...restoredProvenance
1971
+ ]
1972
+ };
1590
1973
  }
1591
1974
  async function getStoredAgentTurnSessionRecord(conversationId, sessionId) {
1592
1975
  const stateAdapter = getStateAdapter();
@@ -2944,6 +3327,24 @@ export {
2944
3327
  recordTurnRoute,
2945
3328
  recordToolExecutionStarted,
2946
3329
  recordGuardianActionReviewed,
3330
+ MAX_TEXT_CHARS,
3331
+ RIPGREP_EXCLUDED_GLOBS,
3332
+ DEFAULT_SEARCH_COMMAND_TIMEOUT_MS,
3333
+ positiveInteger2 as positiveInteger,
3334
+ normalizeToLf,
3335
+ truncateText,
3336
+ isMissingPathError,
3337
+ missingPathSearchResult,
3338
+ resolveWorkspacePath,
3339
+ getRipgrepSearchLocation,
3340
+ collectFiles,
3341
+ AGENTS_REPLACEMENT_NOTICE,
3342
+ AGENTS_REMOVAL_NOTICE,
3343
+ findSingleRepositoryDirectory,
3344
+ resolveRepositoryInstructions,
3345
+ renderAgentsInstructions,
3346
+ buildAgentsInstructionsMessage,
3347
+ findVisibleAgentsInstructions,
2947
3348
  buildDeterministicTurnId,
2948
3349
  buildDeterministicAssistantMessageId,
2949
3350
  ConversationTurnBoundaryError,
@@ -2,18 +2,18 @@ import {
2
2
  SANDBOX_WORKSPACE_ROOT,
3
3
  getStateAdapter,
4
4
  sleep
5
- } from "./chunk-TLN54TOQ.js";
5
+ } from "./chunk-TYEDZVRM.js";
6
6
  import {
7
7
  toOptionalTrimmed
8
- } from "./chunk-LDRO4OQ4.js";
8
+ } from "./chunk-RMI6OX52.js";
9
9
  import {
10
10
  pluginCatalogRuntime
11
- } from "./chunk-JLN4XSPR.js";
11
+ } from "./chunk-UXYZPEWP.js";
12
12
  import {
13
13
  setSpanAttributes,
14
14
  setSpanStatus,
15
15
  withSpan
16
- } from "./chunk-EJRJWBKG.js";
16
+ } from "./chunk-QQCEMMVN.js";
17
17
 
18
18
  // src/chat/sandbox/resources.ts
19
19
  var configuredResources;
@@ -216,7 +216,7 @@ function buildEnvExports(options) {
216
216
  }
217
217
  return lines;
218
218
  }
219
- function toCommandScript(input) {
219
+ function buildCommandScript(input) {
220
220
  return [shellQuote(input.cmd), ...(input.args ?? []).map(shellQuote)].join(
221
221
  " "
222
222
  );
@@ -229,7 +229,7 @@ function buildNonInteractiveCommand(input) {
229
229
  cmd: "bash",
230
230
  args: [
231
231
  input.login ? "-lc" : "-c",
232
- buildNonInteractiveShellScript(toCommandScript(input), {
232
+ buildNonInteractiveShellScript(buildCommandScript(input), {
233
233
  env: input.env,
234
234
  pathPrefix: input.pathPrefix
235
235
  })
@@ -1065,6 +1065,9 @@ function isMissingError(error) {
1065
1065
  }
1066
1066
 
1067
1067
  export {
1068
+ buildCommandScript,
1069
+ buildNonInteractiveShellScript,
1070
+ runNonInteractiveCommand,
1068
1071
  isAlreadyExistsError,
1069
1072
  isSandboxUnavailableError,
1070
1073
  isSandboxMissingError,
@@ -1073,8 +1076,6 @@ export {
1073
1076
  wrapSandboxSetupError,
1074
1077
  throwSandboxOperationError,
1075
1078
  getVercelSandboxCredentials,
1076
- buildNonInteractiveShellScript,
1077
- runNonInteractiveCommand,
1078
1079
  getSandboxResourceConfig,
1079
1080
  setSandboxResourceConfig,
1080
1081
  getSandboxResources,
@@ -6,25 +6,25 @@ import {
6
6
  isDmChannel,
7
7
  normalizeSlackConversationId,
8
8
  withSlackRetries
9
- } from "./chunk-WHEMUEXT.js";
9
+ } from "./chunk-ZBQIA5NI.js";
10
10
  import {
11
11
  getDb,
12
12
  parseDestination
13
- } from "./chunk-LNYNTR27.js";
13
+ } from "./chunk-VZEKCQLD.js";
14
14
  import {
15
15
  acquireActiveLock,
16
16
  getStateAdapter,
17
17
  sleep
18
- } from "./chunk-TLN54TOQ.js";
18
+ } from "./chunk-TYEDZVRM.js";
19
19
  import {
20
20
  normalizeSlackEmojiName
21
- } from "./chunk-LDRO4OQ4.js";
21
+ } from "./chunk-RMI6OX52.js";
22
22
  import {
23
23
  pluginCatalogRuntime
24
- } from "./chunk-JLN4XSPR.js";
24
+ } from "./chunk-UXYZPEWP.js";
25
25
  import {
26
26
  fetchWithBoundedOAuthErrorBodies
27
- } from "./chunk-HJ4KDO4N.js";
27
+ } from "./chunk-6UNZ5DHG.js";
28
28
  import {
29
29
  parseSlackMessageTs,
30
30
  parseSlackUserId
@@ -33,7 +33,7 @@ import {
33
33
  isRecord,
34
34
  logInfo,
35
35
  logWarn
36
- } from "./chunk-EJRJWBKG.js";
36
+ } from "./chunk-QQCEMMVN.js";
37
37
 
38
38
  // src/chat/capabilities/router.ts
39
39
  var ProviderCredentialRouter = class {
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-6GWA276C.js";
10
10
  import {
11
11
  getDeploymentTelemetryAttributes
12
- } from "./chunk-FX6BLEDP.js";
12
+ } from "./chunk-HDGTBCQR.js";
13
13
 
14
14
  // src/chat/logging.ts
15
15
  import path from "path";