@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.
- package/dist/{agent-hooks-5BUIXVIX.js → agent-hooks-EMXDAD2K.js} +9 -9
- package/dist/api/schema/task.d.ts +36 -0
- package/dist/api/schema.d.ts +1 -1
- package/dist/api/schema.js +1 -1
- package/dist/api.js +39 -20
- package/dist/app.js +46 -24
- package/dist/{catalog-runtime-VGB3DWXZ.js → catalog-runtime-NVPT6HA5.js} +5 -5
- package/dist/chat/agent/prompt.d.ts +7 -5
- package/dist/chat/agent/repository-context.d.ts +20 -0
- package/dist/chat/agent/sandbox.d.ts +8 -0
- package/dist/chat/agent/tools.d.ts +3 -0
- package/dist/chat/plugins/agent-hooks.d.ts +2 -2
- package/dist/chat/repository-instructions.d.ts +44 -0
- package/dist/chat/sandbox/noninteractive-command.d.ts +2 -0
- package/dist/chat/sandbox/sandbox.d.ts +3 -0
- package/dist/chat/sandbox/session.d.ts +1 -0
- package/dist/chat/services/context-compaction.d.ts +1 -0
- package/dist/chat/slack/tools/user-lookup.d.ts +2 -6
- package/dist/chat/tasks/execution-stats.d.ts +28 -0
- package/dist/chat/tools/index.d.ts +2 -0
- package/dist/chat/tools/sandbox/bash.d.ts +1 -0
- package/dist/chat/tools/system-time.d.ts +11 -1
- package/dist/{chunk-XTQGVNM3.js → chunk-45DPXMI3.js} +6 -12
- package/dist/{chunk-TU7P77FI.js → chunk-5EX36ZCD.js} +12 -12
- package/dist/{chunk-VL7OYSHD.js → chunk-5LD6EBH2.js} +1 -1
- package/dist/{chunk-HJ4KDO4N.js → chunk-6UNZ5DHG.js} +1 -1
- package/dist/{chunk-IVTHTAVK.js → chunk-AGAHACF7.js} +2 -2
- package/dist/{chunk-HX236W2U.js → chunk-CDQ4YIZM.js} +9 -0
- package/dist/{chunk-5ZAZHLIW.js → chunk-EBRB6ZBF.js} +1 -1
- package/dist/{chunk-VQA25AL4.js → chunk-EJT7EPP3.js} +6 -6
- package/dist/{chunk-FX6BLEDP.js → chunk-HDGTBCQR.js} +1 -1
- package/dist/{chunk-AH5HTUYX.js → chunk-IRTIVX42.js} +1 -1
- package/dist/{chunk-ECUILEUX.js → chunk-NGX2V4WY.js} +430 -29
- package/dist/{chunk-TBVS7GBE.js → chunk-OSCF2BDE.js} +9 -8
- package/dist/{chunk-HTGXUNEC.js → chunk-P2D7IW57.js} +7 -7
- package/dist/{chunk-EJRJWBKG.js → chunk-QQCEMMVN.js} +1 -1
- package/dist/{chunk-LDRO4OQ4.js → chunk-RMI6OX52.js} +2 -2
- package/dist/{chunk-QVEXYYFM.js → chunk-TRZSM67C.js} +11 -1
- package/dist/{chunk-TLN54TOQ.js → chunk-TYEDZVRM.js} +32 -32
- package/dist/{chunk-QWGZ273D.js → chunk-U37P4IIP.js} +81 -27
- package/dist/{chunk-JLN4XSPR.js → chunk-UXYZPEWP.js} +1 -1
- package/dist/{chunk-LNYNTR27.js → chunk-VZEKCQLD.js} +3 -3
- package/dist/{chunk-T5FPIBU2.js → chunk-Y6627MTY.js} +788 -674
- package/dist/{chunk-IKO5LFIU.js → chunk-YPKPXLMS.js} +1 -1
- package/dist/chunk-Z67KVHMJ.js +233 -0
- package/dist/{chunk-WHEMUEXT.js → chunk-ZBQIA5NI.js} +8 -6
- package/dist/cli/chat.js +25 -25
- package/dist/cli/check.js +6 -6
- package/dist/cli/init.js +0 -1
- package/dist/cli/plugins.js +12 -12
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +7 -7
- package/dist/db/schema/task-executions.d.ts +110 -0
- package/dist/db/schema.d.ts +111 -1
- package/dist/{db-RICMPUFT.js → db-UA6OFL25.js} +7 -7
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-YFVS4SAX.js → oauth-callback-server-IJDYBSTX.js} +18 -18
- package/dist/{runner-A3LVGZR6.js → runner-K6GID4HN.js} +12 -12
- package/dist/{skills-P7Q6Z6PN.js → skills-KJVS753I.js} +6 -6
- package/dist/{validation-RYHOWBET.js → validation-7VDJGK7K.js} +6 -6
- package/dist/version.js +1 -1
- package/migrations/0019_lowly_valkyrie.sql +14 -0
- package/migrations/0020_restrict_task_execution_kinds.sql +2 -0
- package/migrations/meta/0019_snapshot.json +1904 -0
- package/migrations/meta/0020_snapshot.json +1848 -0
- package/migrations/meta/_journal.json +15 -1
- package/package.json +4 -4
- 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-
|
|
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-
|
|
21
|
+
} from "./chunk-VZEKCQLD.js";
|
|
21
22
|
import {
|
|
23
|
+
SANDBOX_WORKSPACE_ROOT,
|
|
22
24
|
getStateAdapter,
|
|
23
25
|
sleep
|
|
24
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-TYEDZVRM.js";
|
|
25
27
|
import {
|
|
26
28
|
botConfig,
|
|
27
29
|
escapeXml,
|
|
28
30
|
resolveGatewayModel,
|
|
29
31
|
unwrapCurrentInstruction
|
|
30
|
-
} from "./chunk-
|
|
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-
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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(
|
|
1567
|
-
if (!runtimeContext || runtimeContext.length === 0) return
|
|
1568
|
-
const
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
1581
|
-
|
|
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
|
|
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-
|
|
5
|
+
} from "./chunk-TYEDZVRM.js";
|
|
6
6
|
import {
|
|
7
7
|
toOptionalTrimmed
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RMI6OX52.js";
|
|
9
9
|
import {
|
|
10
10
|
pluginCatalogRuntime
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-UXYZPEWP.js";
|
|
12
12
|
import {
|
|
13
13
|
setSpanAttributes,
|
|
14
14
|
setSpanStatus,
|
|
15
15
|
withSpan
|
|
16
|
-
} from "./chunk-
|
|
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
|
|
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(
|
|
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-
|
|
9
|
+
} from "./chunk-ZBQIA5NI.js";
|
|
10
10
|
import {
|
|
11
11
|
getDb,
|
|
12
12
|
parseDestination
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-VZEKCQLD.js";
|
|
14
14
|
import {
|
|
15
15
|
acquireActiveLock,
|
|
16
16
|
getStateAdapter,
|
|
17
17
|
sleep
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-TYEDZVRM.js";
|
|
19
19
|
import {
|
|
20
20
|
normalizeSlackEmojiName
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-RMI6OX52.js";
|
|
22
22
|
import {
|
|
23
23
|
pluginCatalogRuntime
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-UXYZPEWP.js";
|
|
25
25
|
import {
|
|
26
26
|
fetchWithBoundedOAuthErrorBodies
|
|
27
|
-
} from "./chunk-
|
|
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-
|
|
36
|
+
} from "./chunk-QQCEMMVN.js";
|
|
37
37
|
|
|
38
38
|
// src/chat/capabilities/router.ts
|
|
39
39
|
var ProviderCredentialRouter = class {
|