@atlasharness/atlascode 0.1.81 → 0.1.82
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/cli.js +877 -151
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -29154,6 +29154,11 @@ var DEFAULT_HOOK_SHELL = "bash";
|
|
|
29154
29154
|
var init_getMatchingHooks = () => {};
|
|
29155
29155
|
|
|
29156
29156
|
// src/hooks/runHooks.ts
|
|
29157
|
+
function sessionEndHookTimeoutMs() {
|
|
29158
|
+
const raw = process.env.ATLAS_SESSIONEND_HOOKS_TIMEOUT_MS;
|
|
29159
|
+
const parsed = raw ? Number(raw) : NaN;
|
|
29160
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : SESSION_END_HOOK_TIMEOUT_MS_DEFAULT;
|
|
29161
|
+
}
|
|
29157
29162
|
function isSimpleModeHooksSkipped() {
|
|
29158
29163
|
const raw = process.env.ATLAS_SIMPLE;
|
|
29159
29164
|
if (raw === undefined)
|
|
@@ -29273,6 +29278,7 @@ ${r.additionalContext}` : r.additionalContext;
|
|
|
29273
29278
|
if (!acc.permissionBehavior || PERMISSION_RANK[r.permissionBehavior] > PERMISSION_RANK[acc.permissionBehavior]) {
|
|
29274
29279
|
acc.permissionBehavior = r.permissionBehavior;
|
|
29275
29280
|
acc.permissionDecisionReason = r.permissionDecisionReason;
|
|
29281
|
+
acc.permissionDecisionSource = r.source;
|
|
29276
29282
|
}
|
|
29277
29283
|
}
|
|
29278
29284
|
}
|
|
@@ -29290,12 +29296,14 @@ function runOneHook(m, port, env, signal, options) {
|
|
|
29290
29296
|
if (result.blockingError && cmd.continueOnBlock === true) {
|
|
29291
29297
|
result.continueOnBlock = true;
|
|
29292
29298
|
}
|
|
29299
|
+
result.source = m.source;
|
|
29293
29300
|
return result;
|
|
29294
29301
|
}, (e) => ({
|
|
29295
29302
|
command: cmd.command,
|
|
29296
29303
|
status: -1,
|
|
29297
29304
|
succeeded: false,
|
|
29298
|
-
stderr: e instanceof Error ? e.message : String(e)
|
|
29305
|
+
stderr: e instanceof Error ? e.message : String(e),
|
|
29306
|
+
source: m.source
|
|
29299
29307
|
}));
|
|
29300
29308
|
}
|
|
29301
29309
|
async function runHooks(hookEvent, hookInput, options = {}) {
|
|
@@ -29350,7 +29358,15 @@ async function runStopHooks(options = {}) {
|
|
|
29350
29358
|
const hookInput = { ...base, hook_event_name: "Stop" };
|
|
29351
29359
|
return runHooks("Stop", hookInput, options);
|
|
29352
29360
|
}
|
|
29353
|
-
|
|
29361
|
+
async function runSessionEndHooks(reason, options = {}) {
|
|
29362
|
+
const base = createBaseHookInput(options.permissionMode, options.sessionId, options.agentInfo);
|
|
29363
|
+
const hookInput = { ...base, hook_event_name: "SessionEnd", reason };
|
|
29364
|
+
return runHooks("SessionEnd", hookInput, {
|
|
29365
|
+
...options,
|
|
29366
|
+
timeoutMs: options.timeoutMs ?? sessionEndHookTimeoutMs()
|
|
29367
|
+
});
|
|
29368
|
+
}
|
|
29369
|
+
var MAX_HOOK_CONCURRENCY = 12, HOOK_EXECUTION_TIMEOUT_MS, SESSION_END_HOOK_TIMEOUT_MS_DEFAULT = 1500, PERMISSION_RANK;
|
|
29354
29370
|
var init_runHooks = __esm(() => {
|
|
29355
29371
|
init_createBaseHookInput();
|
|
29356
29372
|
init_getMatchingHooks();
|
|
@@ -29386,9 +29402,20 @@ async function* runHooksStream(hookEvent, hookInput, options = {}) {
|
|
|
29386
29402
|
toolUseID: options.toolUseID
|
|
29387
29403
|
};
|
|
29388
29404
|
}
|
|
29389
|
-
const
|
|
29390
|
-
|
|
29391
|
-
|
|
29405
|
+
const slots = [];
|
|
29406
|
+
let nextStart = 0;
|
|
29407
|
+
const startNext = () => {
|
|
29408
|
+
if (nextStart < matched.length) {
|
|
29409
|
+
slots[nextStart] = runOneHook(matched[nextStart], port, env, signal, options);
|
|
29410
|
+
nextStart++;
|
|
29411
|
+
}
|
|
29412
|
+
};
|
|
29413
|
+
for (let i = 0;i < Math.min(MAX_HOOK_CONCURRENCY, matched.length); i++) {
|
|
29414
|
+
startNext();
|
|
29415
|
+
}
|
|
29416
|
+
for (let i = 0;i < matched.length; i++) {
|
|
29417
|
+
const result = await slots[i];
|
|
29418
|
+
startNext();
|
|
29392
29419
|
results.push(result);
|
|
29393
29420
|
yield { kind: "hook_result", result };
|
|
29394
29421
|
mergeAggregated(aggregated, result);
|
|
@@ -30543,12 +30570,22 @@ function applyDontAskMode(decision, permissionContext, toolName) {
|
|
|
30543
30570
|
}
|
|
30544
30571
|
return decision;
|
|
30545
30572
|
}
|
|
30546
|
-
var BASH_TOOL_NAME = "Bash", hasPermissionsToUseTool = async (tool, input, context, _assistantMessage, _toolUseID, forceDecision) => {
|
|
30573
|
+
var BASH_TOOL_NAME = "Bash", PLAN_MODE_WRITE_EXEMPT_TOOL_NAMES, PLAN_MODE_WRITE_DENIED_MESSAGE = (toolName) => `Plan mode is active — ${toolName} is not allowed to make changes. ` + `Present your plan and use ExitPlanMode, or ask the user to change the permission mode.`, hasPermissionsToUseTool = async (tool, input, context, _assistantMessage, _toolUseID, forceDecision) => {
|
|
30547
30574
|
const permissionContext = context.getToolPermissionContext?.();
|
|
30548
30575
|
if (forceDecision !== undefined) {
|
|
30549
30576
|
return applyDontAskMode(forceDecision, permissionContext, tool.name);
|
|
30550
30577
|
}
|
|
30551
30578
|
const sandbox = getSandboxAccess();
|
|
30579
|
+
if (permissionContext?.mode === "plan" && !permissionContext.isBypassPermissionsModeAvailable && !PLAN_MODE_WRITE_EXEMPT_TOOL_NAMES.has(tool.name) && !(tool.isReadOnly?.(input) ?? false)) {
|
|
30580
|
+
return {
|
|
30581
|
+
behavior: "deny",
|
|
30582
|
+
message: PLAN_MODE_WRITE_DENIED_MESSAGE(tool.name),
|
|
30583
|
+
decisionReason: {
|
|
30584
|
+
type: "mode",
|
|
30585
|
+
mode: "plan"
|
|
30586
|
+
}
|
|
30587
|
+
};
|
|
30588
|
+
}
|
|
30552
30589
|
const denyRule = permissionContext ? getDenyRuleForTool(permissionContext, tool) : null;
|
|
30553
30590
|
if (denyRule) {
|
|
30554
30591
|
return {
|
|
@@ -30667,6 +30704,10 @@ var init_permissions2 = __esm(() => {
|
|
|
30667
30704
|
init_ruleMatching();
|
|
30668
30705
|
init_sandboxAccess();
|
|
30669
30706
|
init_denialMessages();
|
|
30707
|
+
PLAN_MODE_WRITE_EXEMPT_TOOL_NAMES = new Set([
|
|
30708
|
+
"EnterPlanMode",
|
|
30709
|
+
"ExitPlanMode"
|
|
30710
|
+
]);
|
|
30670
30711
|
});
|
|
30671
30712
|
|
|
30672
30713
|
// src/permissions/permissionMode.ts
|
|
@@ -46612,9 +46653,67 @@ var init_bashCommandHelpers = __esm(() => {
|
|
|
46612
46653
|
});
|
|
46613
46654
|
|
|
46614
46655
|
// src/engine/tools/bash/bashReadOnly.ts
|
|
46656
|
+
function globPatternCouldMatchWriteAction(pattern) {
|
|
46657
|
+
let regex = "^";
|
|
46658
|
+
let i = 0;
|
|
46659
|
+
while (i < pattern.length) {
|
|
46660
|
+
const c = pattern[i];
|
|
46661
|
+
if (c === "*") {
|
|
46662
|
+
regex += ".*";
|
|
46663
|
+
i++;
|
|
46664
|
+
continue;
|
|
46665
|
+
}
|
|
46666
|
+
if (c === "?") {
|
|
46667
|
+
regex += ".";
|
|
46668
|
+
i++;
|
|
46669
|
+
continue;
|
|
46670
|
+
}
|
|
46671
|
+
if (c === "[") {
|
|
46672
|
+
const close = pattern.indexOf("]", i + 1);
|
|
46673
|
+
if (close > i) {
|
|
46674
|
+
let cls = pattern.slice(i + 1, close);
|
|
46675
|
+
if (cls.startsWith("!"))
|
|
46676
|
+
cls = `^${cls.slice(1)}`;
|
|
46677
|
+
regex += `[${cls}]`;
|
|
46678
|
+
i = close + 1;
|
|
46679
|
+
continue;
|
|
46680
|
+
}
|
|
46681
|
+
}
|
|
46682
|
+
regex += c.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
46683
|
+
i++;
|
|
46684
|
+
}
|
|
46685
|
+
regex += "$";
|
|
46686
|
+
let re;
|
|
46687
|
+
try {
|
|
46688
|
+
re = new RegExp(regex);
|
|
46689
|
+
} catch {
|
|
46690
|
+
return true;
|
|
46691
|
+
}
|
|
46692
|
+
for (const action of FIND_WRITE_ACTION_TOKENS) {
|
|
46693
|
+
if (re.test(action))
|
|
46694
|
+
return true;
|
|
46695
|
+
}
|
|
46696
|
+
return false;
|
|
46697
|
+
}
|
|
46698
|
+
function isAllowedNonStringToken(token) {
|
|
46699
|
+
if (typeof token !== "object" || token === null)
|
|
46700
|
+
return false;
|
|
46701
|
+
const t = token;
|
|
46702
|
+
if (t.comment !== undefined)
|
|
46703
|
+
return true;
|
|
46704
|
+
if (t.op === "<")
|
|
46705
|
+
return true;
|
|
46706
|
+
if (t.op === "glob") {
|
|
46707
|
+
if (typeof t.pattern !== "string")
|
|
46708
|
+
return false;
|
|
46709
|
+
return !globPatternCouldMatchWriteAction(t.pattern);
|
|
46710
|
+
}
|
|
46711
|
+
return false;
|
|
46712
|
+
}
|
|
46615
46713
|
function matchReadOnlyPrefix(command) {
|
|
46616
46714
|
const trimmed = command.trim();
|
|
46617
|
-
if (trimmed.includes("&&") || trimmed.includes("||") || trimmed.includes(";") || trimmed.includes("|") || trimmed.includes("`") || trimmed.includes("$(") || trimmed.includes(">")
|
|
46715
|
+
if (trimmed.includes("&&") || trimmed.includes("||") || trimmed.includes(";") || trimmed.includes("|") || trimmed.includes("`") || trimmed.includes("$(") || trimmed.includes(">") || trimmed.includes(`
|
|
46716
|
+
`) || trimmed.includes("\r") || trimmed.includes("-delete") || trimmed.includes("-exec") || trimmed.includes("-ok") || trimmed.includes("-fprint") || trimmed.includes("-fls")) {
|
|
46618
46717
|
return null;
|
|
46619
46718
|
}
|
|
46620
46719
|
let best = null;
|
|
@@ -46624,13 +46723,31 @@ function matchReadOnlyPrefix(command) {
|
|
|
46624
46723
|
best = p;
|
|
46625
46724
|
}
|
|
46626
46725
|
}
|
|
46726
|
+
if (best === null)
|
|
46727
|
+
return null;
|
|
46728
|
+
const parsed = tryParseShellCommand(trimmed, (key) => `$${key}`);
|
|
46729
|
+
if (!parsed.success) {
|
|
46730
|
+
return null;
|
|
46731
|
+
}
|
|
46732
|
+
for (const token of parsed.tokens) {
|
|
46733
|
+
if (typeof token === "string") {
|
|
46734
|
+
if (FIND_WRITE_ACTION_TOKENS.has(token))
|
|
46735
|
+
return null;
|
|
46736
|
+
if (token.includes("[") && globPatternCouldMatchWriteAction(token)) {
|
|
46737
|
+
return null;
|
|
46738
|
+
}
|
|
46739
|
+
} else if (!isAllowedNonStringToken(token)) {
|
|
46740
|
+
return null;
|
|
46741
|
+
}
|
|
46742
|
+
}
|
|
46627
46743
|
return best;
|
|
46628
46744
|
}
|
|
46629
46745
|
function isReadOnlyCommand(command) {
|
|
46630
46746
|
return matchReadOnlyPrefix(command) !== null;
|
|
46631
46747
|
}
|
|
46632
|
-
var READ_ONLY_PREFIXES;
|
|
46748
|
+
var READ_ONLY_PREFIXES, FIND_WRITE_ACTION_TOKENS;
|
|
46633
46749
|
var init_bashReadOnly = __esm(() => {
|
|
46750
|
+
init_shellQuote();
|
|
46634
46751
|
READ_ONLY_PREFIXES = [
|
|
46635
46752
|
"ls",
|
|
46636
46753
|
"cat",
|
|
@@ -46657,6 +46774,17 @@ var init_bashReadOnly = __esm(() => {
|
|
|
46657
46774
|
"printenv",
|
|
46658
46775
|
"type"
|
|
46659
46776
|
];
|
|
46777
|
+
FIND_WRITE_ACTION_TOKENS = new Set([
|
|
46778
|
+
"-delete",
|
|
46779
|
+
"-exec",
|
|
46780
|
+
"-execdir",
|
|
46781
|
+
"-ok",
|
|
46782
|
+
"-okdir",
|
|
46783
|
+
"-fprint",
|
|
46784
|
+
"-fprint0",
|
|
46785
|
+
"-fprintf",
|
|
46786
|
+
"-fls"
|
|
46787
|
+
]);
|
|
46660
46788
|
});
|
|
46661
46789
|
|
|
46662
46790
|
// src/engine/tools/bash/abortError.ts
|
|
@@ -75335,6 +75463,27 @@ var init_tasks3 = __esm(() => {
|
|
|
75335
75463
|
init_taskOutputTool();
|
|
75336
75464
|
});
|
|
75337
75465
|
|
|
75466
|
+
// src/engine/skill/commandNameSafety.ts
|
|
75467
|
+
function isUnsafeCommandName(name) {
|
|
75468
|
+
if (name === "")
|
|
75469
|
+
return true;
|
|
75470
|
+
if (name.includes("<") || name.includes(">"))
|
|
75471
|
+
return true;
|
|
75472
|
+
return UNSAFE_NAME_CHARS_RE.test(name);
|
|
75473
|
+
}
|
|
75474
|
+
function sanitizeDisplayName(displayName, canonicalName) {
|
|
75475
|
+
if (displayName === undefined || !isUnsafeCommandName(displayName)) {
|
|
75476
|
+
return displayName;
|
|
75477
|
+
}
|
|
75478
|
+
logForDebugging(`Discarding unsafe frontmatter display name ${JSON.stringify(displayName)} for ${canonicalName}; falling back to canonical name`);
|
|
75479
|
+
return;
|
|
75480
|
+
}
|
|
75481
|
+
var UNSAFE_NAME_CHARS_RE;
|
|
75482
|
+
var init_commandNameSafety = __esm(() => {
|
|
75483
|
+
init_shared();
|
|
75484
|
+
UNSAFE_NAME_CHARS_RE = /[\u0000-\u001F\u007F-\u00A0\u00AD\u034F\u061C\u070F\u1680\u180E\u2000-\u200F\u2028\u2029\u202A-\u202E\u202F\u205F\u2060-\u2069\u3000\uFE00-\uFE0F\uFEFF\u{E0100}-\u{E01EF}]/u;
|
|
75485
|
+
});
|
|
75486
|
+
|
|
75338
75487
|
// src/engine/skill/types.ts
|
|
75339
75488
|
function getCommandName(cmd) {
|
|
75340
75489
|
return cmd.userFacingName?.() ?? cmd.name;
|
|
@@ -75457,44 +75606,129 @@ function parseArgumentNames(argumentNames) {
|
|
|
75457
75606
|
return [];
|
|
75458
75607
|
}
|
|
75459
75608
|
const isValidName = (name) => typeof name === "string" && name.trim() !== "" && !/^\d+$/.test(name);
|
|
75609
|
+
const cap = (names) => names.map((name) => name.slice(0, MAX_ARGUMENT_NAME_CHARS)).slice(0, MAX_ARGUMENT_NAMES);
|
|
75460
75610
|
if (Array.isArray(argumentNames)) {
|
|
75461
|
-
return argumentNames.filter(isValidName);
|
|
75611
|
+
return cap(argumentNames.filter(isValidName));
|
|
75462
75612
|
}
|
|
75463
75613
|
if (typeof argumentNames === "string") {
|
|
75464
|
-
return argumentNames.split(/\s+/).filter(isValidName);
|
|
75614
|
+
return cap(argumentNames.split(/\s+/).filter(isValidName));
|
|
75465
75615
|
}
|
|
75466
75616
|
return [];
|
|
75467
75617
|
}
|
|
75468
|
-
function
|
|
75618
|
+
function isWordChar2(c) {
|
|
75619
|
+
return c !== undefined && /[A-Za-z0-9_]/.test(c);
|
|
75620
|
+
}
|
|
75621
|
+
function matchPlaceholderAt(content, i, argumentNames) {
|
|
75622
|
+
if (content[i] !== "$")
|
|
75623
|
+
return null;
|
|
75624
|
+
for (let n = 0;n < argumentNames.length; n++) {
|
|
75625
|
+
const name = argumentNames[n];
|
|
75626
|
+
if (!name)
|
|
75627
|
+
continue;
|
|
75628
|
+
if (content.startsWith(`$${name}`, i)) {
|
|
75629
|
+
const after = content[i + 1 + name.length];
|
|
75630
|
+
if (after !== "[" && !isWordChar2(after)) {
|
|
75631
|
+
return { length: 1 + name.length, kind: "named", nameIndex: n };
|
|
75632
|
+
}
|
|
75633
|
+
}
|
|
75634
|
+
}
|
|
75635
|
+
INDEXED_PLACEHOLDER_RE.lastIndex = i;
|
|
75636
|
+
const indexed = INDEXED_PLACEHOLDER_RE.exec(content);
|
|
75637
|
+
if (indexed) {
|
|
75638
|
+
return {
|
|
75639
|
+
length: indexed[0].length,
|
|
75640
|
+
kind: "indexed",
|
|
75641
|
+
argIndex: parseInt(indexed[1], 10)
|
|
75642
|
+
};
|
|
75643
|
+
}
|
|
75644
|
+
if (content.startsWith("$ARGUMENTS", i)) {
|
|
75645
|
+
return { length: "$ARGUMENTS".length, kind: "bare" };
|
|
75646
|
+
}
|
|
75647
|
+
SHORTHAND_PLACEHOLDER_RE.lastIndex = i;
|
|
75648
|
+
const shorthand = SHORTHAND_PLACEHOLDER_RE.exec(content);
|
|
75649
|
+
if (shorthand && !isWordChar2(content[i + shorthand[0].length])) {
|
|
75650
|
+
return {
|
|
75651
|
+
length: shorthand[0].length,
|
|
75652
|
+
kind: "shorthand",
|
|
75653
|
+
argIndex: parseInt(shorthand[1], 10)
|
|
75654
|
+
};
|
|
75655
|
+
}
|
|
75656
|
+
return null;
|
|
75657
|
+
}
|
|
75658
|
+
function countPlaceholderOccurrences(content, argumentNames) {
|
|
75659
|
+
let count = 0;
|
|
75660
|
+
let i = 0;
|
|
75661
|
+
while (i < content.length) {
|
|
75662
|
+
const m = matchPlaceholderAt(content, i, argumentNames);
|
|
75663
|
+
if (m) {
|
|
75664
|
+
count++;
|
|
75665
|
+
i += m.length;
|
|
75666
|
+
} else {
|
|
75667
|
+
i++;
|
|
75668
|
+
}
|
|
75669
|
+
}
|
|
75670
|
+
return count;
|
|
75671
|
+
}
|
|
75672
|
+
function substituteArgumentsImpl(content, args, appendIfNoPlaceholder, argumentNames, strict) {
|
|
75469
75673
|
if (args === undefined || args === null) {
|
|
75470
75674
|
return content;
|
|
75471
75675
|
}
|
|
75472
|
-
const
|
|
75473
|
-
|
|
75474
|
-
|
|
75475
|
-
|
|
75476
|
-
|
|
75477
|
-
|
|
75478
|
-
|
|
75676
|
+
const placeholderCount = countPlaceholderOccurrences(content, argumentNames);
|
|
75677
|
+
let effectiveArgs = args;
|
|
75678
|
+
if (placeholderCount > 0 && content.length + placeholderCount * args.length > MAX_SUBSTITUTION_OUTPUT_CHARS) {
|
|
75679
|
+
if (strict)
|
|
75680
|
+
return null;
|
|
75681
|
+
const budgetPerReplacement = Math.max(0, Math.floor((MAX_SUBSTITUTION_OUTPUT_CHARS - content.length) / placeholderCount));
|
|
75682
|
+
effectiveArgs = args.slice(0, budgetPerReplacement);
|
|
75683
|
+
} else if (strict) {
|
|
75684
|
+
const appendLen = appendIfNoPlaceholder && args ? `
|
|
75685
|
+
|
|
75686
|
+
ARGUMENTS: `.length + args.length : 0;
|
|
75687
|
+
if (content.length + appendLen > MAX_SUBSTITUTION_OUTPUT_CHARS) {
|
|
75688
|
+
return null;
|
|
75689
|
+
}
|
|
75479
75690
|
}
|
|
75480
|
-
|
|
75481
|
-
|
|
75482
|
-
|
|
75483
|
-
|
|
75484
|
-
|
|
75485
|
-
|
|
75486
|
-
|
|
75487
|
-
}
|
|
75488
|
-
|
|
75489
|
-
|
|
75490
|
-
|
|
75691
|
+
const parsedArgs = parseArguments(effectiveArgs);
|
|
75692
|
+
let out = "";
|
|
75693
|
+
const appendValue = (value) => {
|
|
75694
|
+
if (out.length + value.length > MAX_SUBSTITUTION_OUTPUT_CHARS) {
|
|
75695
|
+
value = value.slice(0, Math.max(0, MAX_SUBSTITUTION_OUTPUT_CHARS - out.length));
|
|
75696
|
+
}
|
|
75697
|
+
out += value;
|
|
75698
|
+
};
|
|
75699
|
+
let matched = false;
|
|
75700
|
+
let i = 0;
|
|
75701
|
+
while (i < content.length) {
|
|
75702
|
+
const m = matchPlaceholderAt(content, i, argumentNames);
|
|
75703
|
+
if (m) {
|
|
75704
|
+
matched = true;
|
|
75705
|
+
if (m.kind === "bare")
|
|
75706
|
+
appendValue(effectiveArgs);
|
|
75707
|
+
else if (m.kind === "named")
|
|
75708
|
+
appendValue(parsedArgs[m.nameIndex] ?? "");
|
|
75709
|
+
else
|
|
75710
|
+
appendValue(parsedArgs[m.argIndex] ?? "");
|
|
75711
|
+
i += m.length;
|
|
75712
|
+
} else {
|
|
75713
|
+
out += content[i];
|
|
75714
|
+
i++;
|
|
75715
|
+
}
|
|
75716
|
+
}
|
|
75717
|
+
if (!matched && appendIfNoPlaceholder && args) {
|
|
75718
|
+
out = out + `
|
|
75491
75719
|
|
|
75492
75720
|
ARGUMENTS: ${args}`;
|
|
75493
75721
|
}
|
|
75494
|
-
return
|
|
75722
|
+
return out;
|
|
75495
75723
|
}
|
|
75724
|
+
function substituteArguments(content, args, appendIfNoPlaceholder = true, argumentNames = []) {
|
|
75725
|
+
return substituteArgumentsImpl(content, args, appendIfNoPlaceholder, argumentNames, false) ?? content;
|
|
75726
|
+
}
|
|
75727
|
+
var MAX_ARGUMENT_NAMES = 64, MAX_ARGUMENT_NAME_CHARS = 64, MAX_SUBSTITUTION_OUTPUT_CHARS = 1e6, INDEXED_PLACEHOLDER_RE, SHORTHAND_PLACEHOLDER_RE;
|
|
75496
75728
|
var init_argumentSubstitution = __esm(() => {
|
|
75497
75729
|
init_bash();
|
|
75730
|
+
INDEXED_PLACEHOLDER_RE = /\$ARGUMENTS\[(\d+)\]/y;
|
|
75731
|
+
SHORTHAND_PLACEHOLDER_RE = /\$(\d+)/y;
|
|
75498
75732
|
});
|
|
75499
75733
|
|
|
75500
75734
|
// src/engine/skill/skillModel.ts
|
|
@@ -76931,7 +77165,7 @@ function parseSkillFrontmatterFields(frontmatter, markdownContent, resolvedName,
|
|
|
76931
77165
|
logForDebugging(`Skill ${resolvedName} has invalid effort '${effortRaw}'. Valid options: ${EFFORT_LEVELS.join(", ")} or an integer`);
|
|
76932
77166
|
}
|
|
76933
77167
|
return {
|
|
76934
|
-
displayName: frontmatter.name != null ? String(frontmatter.name) : undefined,
|
|
77168
|
+
displayName: sanitizeDisplayName(frontmatter.name != null ? String(frontmatter.name) : undefined, resolvedName),
|
|
76935
77169
|
description,
|
|
76936
77170
|
hasUserSpecifiedDescription: validatedDescription !== null,
|
|
76937
77171
|
allowedTools: parseSlashCommandToolsFromFrontmatter(frontmatter["allowed-tools"]),
|
|
@@ -77042,6 +77276,7 @@ var init_skillCommand = __esm(() => {
|
|
|
77042
77276
|
init_frontmatterFields();
|
|
77043
77277
|
init_markdownLoader();
|
|
77044
77278
|
init_skillModel();
|
|
77279
|
+
init_commandNameSafety();
|
|
77045
77280
|
init_promptShellExecution();
|
|
77046
77281
|
});
|
|
77047
77282
|
|
|
@@ -77081,6 +77316,10 @@ async function loadSkillsFromSkillsDir(basePath, source) {
|
|
|
77081
77316
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
77082
77317
|
return null;
|
|
77083
77318
|
}
|
|
77319
|
+
if (isUnsafeCommandName(entry.name)) {
|
|
77320
|
+
logForDebugging(`[skills] skipping unsafe skill directory name: ${JSON.stringify(entry.name)}`);
|
|
77321
|
+
return null;
|
|
77322
|
+
}
|
|
77084
77323
|
const skillDirPath = join32(basePath, entry.name);
|
|
77085
77324
|
const skillFilePath = join32(skillDirPath, "SKILL.md");
|
|
77086
77325
|
let content;
|
|
@@ -77189,6 +77428,10 @@ async function loadSkillsFromCommandsDir(cwd) {
|
|
|
77189
77428
|
content,
|
|
77190
77429
|
source
|
|
77191
77430
|
});
|
|
77431
|
+
if (isUnsafeCommandName(cmdName)) {
|
|
77432
|
+
logForDebugging(`[skills] skipping unsafe command name: ${JSON.stringify(cmdName)}`);
|
|
77433
|
+
continue;
|
|
77434
|
+
}
|
|
77192
77435
|
const parsed = parseSkillFrontmatterFields(frontmatter, content, cmdName, "Custom command");
|
|
77193
77436
|
skills.push({
|
|
77194
77437
|
skill: createSkillCommand({
|
|
@@ -77228,6 +77471,7 @@ var init_loadSkillsDir = __esm(() => {
|
|
|
77228
77471
|
init_memory();
|
|
77229
77472
|
init_config();
|
|
77230
77473
|
init_messaging();
|
|
77474
|
+
init_commandNameSafety();
|
|
77231
77475
|
init_gitignore();
|
|
77232
77476
|
init_markdownLoader();
|
|
77233
77477
|
init_skillCommand();
|
|
@@ -77643,6 +77887,7 @@ var init_pluginIdentifier = __esm(() => {
|
|
|
77643
77887
|
|
|
77644
77888
|
// src/engine/skill/index.ts
|
|
77645
77889
|
var init_skill = __esm(() => {
|
|
77890
|
+
init_commandNameSafety();
|
|
77646
77891
|
init_frontmatterFields();
|
|
77647
77892
|
init_argumentSubstitution();
|
|
77648
77893
|
init_skillModel();
|
|
@@ -77696,6 +77941,14 @@ import { randomUUID as randomUUID14 } from "crypto";
|
|
|
77696
77941
|
async function getAllCommands() {
|
|
77697
77942
|
return getCommands(process.cwd());
|
|
77698
77943
|
}
|
|
77944
|
+
function buildUnknownSkillMessage(skillName, commands) {
|
|
77945
|
+
const available = commands.filter((c) => !c.isHidden && !c.disableModelInvocation).map((c) => c.userFacingName?.() ?? c.name);
|
|
77946
|
+
if (available.length === 0)
|
|
77947
|
+
return `Unknown skill: ${skillName}`;
|
|
77948
|
+
const listed = available.slice(0, MAX_UNKNOWN_SKILL_SUGGESTIONS);
|
|
77949
|
+
const more = available.length - listed.length;
|
|
77950
|
+
return `Unknown skill: ${skillName}. Available skills: ${listed.join(", ")}${more > 0 ? ` (and ${more} more)` : ""}`;
|
|
77951
|
+
}
|
|
77699
77952
|
function getToolUseIDFromParentMessage(parentMessage, toolName) {
|
|
77700
77953
|
if (!parentMessage)
|
|
77701
77954
|
return;
|
|
@@ -77763,7 +78016,7 @@ function skillHasOnlySafeProperties(command) {
|
|
|
77763
78016
|
}
|
|
77764
78017
|
return true;
|
|
77765
78018
|
}
|
|
77766
|
-
var SKILL_TOOL_INPUT_SCHEMA, SAFE_SKILL_PROPERTIES, SkillTool;
|
|
78019
|
+
var SKILL_TOOL_INPUT_SCHEMA, MAX_UNKNOWN_SKILL_SUGGESTIONS = 10, SAFE_SKILL_PROPERTIES, SkillTool;
|
|
77767
78020
|
var init_skillTool = __esm(() => {
|
|
77768
78021
|
init_shared();
|
|
77769
78022
|
init_permissions3();
|
|
@@ -77935,7 +78188,7 @@ var init_skillTool = __esm(() => {
|
|
|
77935
78188
|
if (!foundCommand) {
|
|
77936
78189
|
return {
|
|
77937
78190
|
result: false,
|
|
77938
|
-
message:
|
|
78191
|
+
message: buildUnknownSkillMessage(normalizedCommandName, commands),
|
|
77939
78192
|
errorCode: 2
|
|
77940
78193
|
};
|
|
77941
78194
|
}
|
|
@@ -79050,6 +79303,24 @@ function classifyToolError(error) {
|
|
|
79050
79303
|
return "UnknownError";
|
|
79051
79304
|
}
|
|
79052
79305
|
|
|
79306
|
+
// src/engine/pipeline/sanitizeUpdatedInput.ts
|
|
79307
|
+
function isPlainObject3(value) {
|
|
79308
|
+
if (typeof value !== "object" || value === null)
|
|
79309
|
+
return false;
|
|
79310
|
+
const proto = Object.getPrototypeOf(value);
|
|
79311
|
+
return proto === Object.prototype || proto === null;
|
|
79312
|
+
}
|
|
79313
|
+
function sanitizeUpdatedInput(originalInput, updatedInput) {
|
|
79314
|
+
if (!isPlainObject3(originalInput) || !isPlainObject3(updatedInput)) {
|
|
79315
|
+
return originalInput;
|
|
79316
|
+
}
|
|
79317
|
+
const result = {};
|
|
79318
|
+
for (const key of Object.keys(originalInput)) {
|
|
79319
|
+
result[key] = key in updatedInput ? updatedInput[key] : originalInput[key];
|
|
79320
|
+
}
|
|
79321
|
+
return result;
|
|
79322
|
+
}
|
|
79323
|
+
|
|
79053
79324
|
// src/engine/pipeline/schemaValidation.ts
|
|
79054
79325
|
function typeName(v) {
|
|
79055
79326
|
if (v === null)
|
|
@@ -79210,7 +79481,7 @@ async function runWithToolHeartbeat(opts, fn) {
|
|
|
79210
79481
|
var DEFAULT_TOOL_HEARTBEAT_INTERVAL_MS = 30000, MIN_TOOL_HEARTBEAT_INTERVAL_MS = 100;
|
|
79211
79482
|
|
|
79212
79483
|
// src/engine/pipeline/toolExecution.ts
|
|
79213
|
-
function mergeHookPermission(hookBehavior, gate, hookReason) {
|
|
79484
|
+
function mergeHookPermission(hookBehavior, gate, hookReason, hookSource) {
|
|
79214
79485
|
if (hookBehavior === "defer") {
|
|
79215
79486
|
return {
|
|
79216
79487
|
allowed: false,
|
|
@@ -79224,7 +79495,8 @@ function mergeHookPermission(hookBehavior, gate, hookReason) {
|
|
|
79224
79495
|
if (!gate.allowed)
|
|
79225
79496
|
return gate;
|
|
79226
79497
|
if (hookBehavior === "ask") {
|
|
79227
|
-
|
|
79498
|
+
const reason = hookSource && hookSource !== "settings" ? `hook requested confirmation (from ${hookSource})` : "hook requested confirmation";
|
|
79499
|
+
return { allowed: false, ask: true, reason };
|
|
79228
79500
|
}
|
|
79229
79501
|
return gate;
|
|
79230
79502
|
}
|
|
@@ -79295,12 +79567,12 @@ async function executeToolUse(tu, assistantMsg, deps) {
|
|
|
79295
79567
|
isError: true
|
|
79296
79568
|
};
|
|
79297
79569
|
}
|
|
79298
|
-
const effectiveInput = preOutcome?.updatedInput
|
|
79570
|
+
const effectiveInput = preOutcome?.updatedInput !== undefined ? sanitizeUpdatedInput(tu.input, preOutcome.updatedInput) : tu.input;
|
|
79299
79571
|
const gateVerdict = deps.checkPermission ? await deps.checkPermission(tool, effectiveInput, {
|
|
79300
79572
|
toolUseId: tu.id,
|
|
79301
79573
|
assistantMessage: assistantMsg
|
|
79302
79574
|
}) : { allowed: true };
|
|
79303
|
-
const verdict = mergeHookPermission(preOutcome?.hookBehavior, gateVerdict, preOutcome?.hookPermissionDecisionReason);
|
|
79575
|
+
const verdict = mergeHookPermission(preOutcome?.hookBehavior, gateVerdict, preOutcome?.hookPermissionDecisionReason, preOutcome?.hookSource);
|
|
79304
79576
|
if (verdict.deferred) {
|
|
79305
79577
|
return { deferred: true, deferReason: verdict.reason, isError: false };
|
|
79306
79578
|
}
|
|
@@ -83302,6 +83574,7 @@ function createToolHooks(opts = {}) {
|
|
|
83302
83574
|
updatedInput: r.updatedInput,
|
|
83303
83575
|
hookBehavior: r.permissionBehavior,
|
|
83304
83576
|
hookPermissionDecisionReason: r.permissionDecisionReason,
|
|
83577
|
+
hookSource: r.permissionDecisionSource,
|
|
83305
83578
|
preventContinuation: r.preventContinuation,
|
|
83306
83579
|
stopReason: r.stopReason
|
|
83307
83580
|
};
|
|
@@ -83590,6 +83863,7 @@ var init_state2 = () => {};
|
|
|
83590
83863
|
var init_hooks2 = __esm(() => {
|
|
83591
83864
|
init_toolHooks();
|
|
83592
83865
|
init_hooks();
|
|
83866
|
+
init_hooks();
|
|
83593
83867
|
});
|
|
83594
83868
|
|
|
83595
83869
|
// src/engine/goal/goalCheckIn.ts
|
|
@@ -83678,6 +83952,7 @@ var init_engine = __esm(() => {
|
|
|
83678
83952
|
init_permissions4();
|
|
83679
83953
|
init_hooks2();
|
|
83680
83954
|
init_hooks2();
|
|
83955
|
+
init_hooks2();
|
|
83681
83956
|
init_config();
|
|
83682
83957
|
init_messaging();
|
|
83683
83958
|
init_messaging();
|
|
@@ -87105,6 +87380,19 @@ var init_hooksWiring = __esm(() => {
|
|
|
87105
87380
|
init_hooks();
|
|
87106
87381
|
});
|
|
87107
87382
|
|
|
87383
|
+
// src/cli/headlessSessionEnd.ts
|
|
87384
|
+
async function runHeadlessSessionEndHooks(reason) {
|
|
87385
|
+
try {
|
|
87386
|
+
await runSessionEndHooks(reason);
|
|
87387
|
+
} catch (error) {
|
|
87388
|
+
logForDebugging2(`SessionEnd hooks (headless exit, reason=${reason}) failed: ${String(error)}`, { level: "error" });
|
|
87389
|
+
}
|
|
87390
|
+
}
|
|
87391
|
+
var init_headlessSessionEnd = __esm(() => {
|
|
87392
|
+
init_hooks();
|
|
87393
|
+
init_debugSink();
|
|
87394
|
+
});
|
|
87395
|
+
|
|
87108
87396
|
// src/cli/print.ts
|
|
87109
87397
|
import { randomUUID as randomUUID21 } from "crypto";
|
|
87110
87398
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
@@ -87864,6 +88152,7 @@ async function runHeadless(inputPrompt, options) {
|
|
|
87864
88152
|
cronScheduler.stop();
|
|
87865
88153
|
await drainToOutput();
|
|
87866
88154
|
await drainPendingBackgroundAgents(abortController.signal);
|
|
88155
|
+
await runHeadlessSessionEndHooks("prompt_input_exit");
|
|
87867
88156
|
} catch (error) {
|
|
87868
88157
|
cronScheduler.stop();
|
|
87869
88158
|
logForDebugging2(headlessErrorLine(error), { level: "error" });
|
|
@@ -87882,6 +88171,7 @@ async function runHeadless(inputPrompt, options) {
|
|
|
87882
88171
|
});
|
|
87883
88172
|
} catch {}
|
|
87884
88173
|
abortController.abort();
|
|
88174
|
+
await runHeadlessSessionEndHooks("other");
|
|
87885
88175
|
process.exitCode = 1;
|
|
87886
88176
|
}
|
|
87887
88177
|
await flushDebugSink();
|
|
@@ -87932,6 +88222,7 @@ var init_print = __esm(() => {
|
|
|
87932
88222
|
init_headlessPrompt();
|
|
87933
88223
|
init_debugSink();
|
|
87934
88224
|
init_hooksWiring();
|
|
88225
|
+
init_headlessSessionEnd();
|
|
87935
88226
|
});
|
|
87936
88227
|
|
|
87937
88228
|
// src/cli/handlers/update.ts
|
|
@@ -89320,7 +89611,7 @@ var init_cli = __esm(() => {
|
|
|
89320
89611
|
});
|
|
89321
89612
|
|
|
89322
89613
|
// node_modules/is-plain-obj/index.js
|
|
89323
|
-
function
|
|
89614
|
+
function isPlainObject4(value) {
|
|
89324
89615
|
if (typeof value !== "object" || value === null) {
|
|
89325
89616
|
return false;
|
|
89326
89617
|
}
|
|
@@ -89342,7 +89633,7 @@ var init_file_url = () => {};
|
|
|
89342
89633
|
// node_modules/execa/lib/methods/parameters.js
|
|
89343
89634
|
var normalizeParameters = (rawFile, rawArguments = [], rawOptions = {}) => {
|
|
89344
89635
|
const filePath = safeNormalizeFileUrl(rawFile, "First argument");
|
|
89345
|
-
const [commandArguments, options] =
|
|
89636
|
+
const [commandArguments, options] = isPlainObject4(rawArguments) ? [[], rawArguments] : [rawArguments, rawOptions];
|
|
89346
89637
|
if (!Array.isArray(commandArguments)) {
|
|
89347
89638
|
throw new TypeError(`Second argument must be either an array of arguments or an options object: ${commandArguments}`);
|
|
89348
89639
|
}
|
|
@@ -89354,7 +89645,7 @@ var normalizeParameters = (rawFile, rawArguments = [], rawOptions = {}) => {
|
|
|
89354
89645
|
if (nullByteArgument !== undefined) {
|
|
89355
89646
|
throw new TypeError(`Arguments cannot contain null bytes ("\\0"): ${nullByteArgument}`);
|
|
89356
89647
|
}
|
|
89357
|
-
if (!
|
|
89648
|
+
if (!isPlainObject4(options)) {
|
|
89358
89649
|
throw new TypeError(`Last argument must be an options object: ${options}`);
|
|
89359
89650
|
}
|
|
89360
89651
|
return [filePath, normalizedArguments, { __proto__: null, ...options }];
|
|
@@ -89476,7 +89767,7 @@ var isTemplateString = (templates) => Array.isArray(templates) && Array.isArray(
|
|
|
89476
89767
|
if (typeOfExpression === "number") {
|
|
89477
89768
|
return String(expression);
|
|
89478
89769
|
}
|
|
89479
|
-
if (
|
|
89770
|
+
if (isPlainObject4(expression) && (("stdout" in expression) || ("isMaxBuffer" in expression))) {
|
|
89480
89771
|
return getSubprocessResult(expression);
|
|
89481
89772
|
}
|
|
89482
89773
|
if (expression instanceof ChildProcess || Object.prototype.toString.call(expression) === "[object Promise]") {
|
|
@@ -89523,7 +89814,7 @@ var normalizeFdSpecificOptions = (options) => {
|
|
|
89523
89814
|
const optionBaseArray = Array.from({ length: stdioLength + 1 });
|
|
89524
89815
|
const optionArray = normalizeFdSpecificValue(options[optionName], optionBaseArray, optionName, stdioLength);
|
|
89525
89816
|
return addDefaultValue(optionArray, optionName);
|
|
89526
|
-
}, getStdioLength = ({ stdio }) => Array.isArray(stdio) ? Math.max(stdio.length, STANDARD_STREAMS_ALIASES.length) : STANDARD_STREAMS_ALIASES.length, normalizeFdSpecificValue = (optionValue, optionArray, optionName, stdioLength) =>
|
|
89817
|
+
}, getStdioLength = ({ stdio }) => Array.isArray(stdio) ? Math.max(stdio.length, STANDARD_STREAMS_ALIASES.length) : STANDARD_STREAMS_ALIASES.length, normalizeFdSpecificValue = (optionValue, optionArray, optionName, stdioLength) => isPlainObject4(optionValue) ? normalizeOptionObject(optionValue, optionArray, optionName, stdioLength) : optionArray.fill(optionValue), normalizeOptionObject = (optionValue, optionArray, optionName, stdioLength) => {
|
|
89527
89818
|
for (const fdName of Object.keys(optionValue).sort(compareFdName)) {
|
|
89528
89819
|
for (const fdNumber of parseFdName(fdName, optionName, stdioLength)) {
|
|
89529
89820
|
optionArray[fdNumber] = optionValue[fdName];
|
|
@@ -92770,7 +93061,7 @@ var getStdioItemType = (value, optionName) => {
|
|
|
92770
93061
|
if (value !== undefined && typeof value !== "boolean") {
|
|
92771
93062
|
throw new TypeError(`The \`${optionName}\` option must use a boolean.`);
|
|
92772
93063
|
}
|
|
92773
|
-
}, isGenerator = (value) => isAsyncGenerator(value) || isSyncGenerator(value), isAsyncGenerator = (value) => Object.prototype.toString.call(value) === "[object AsyncGeneratorFunction]", isSyncGenerator = (value) => Object.prototype.toString.call(value) === "[object GeneratorFunction]", isTransformOptions = (value) =>
|
|
93064
|
+
}, isGenerator = (value) => isAsyncGenerator(value) || isSyncGenerator(value), isAsyncGenerator = (value) => Object.prototype.toString.call(value) === "[object AsyncGeneratorFunction]", isSyncGenerator = (value) => Object.prototype.toString.call(value) === "[object GeneratorFunction]", isTransformOptions = (value) => isPlainObject4(value) && (value.transform !== undefined || value.final !== undefined), isUrl = (value) => Object.prototype.toString.call(value) === "[object URL]", isRegularUrl = (value) => isUrl(value) && value.protocol !== "file:", isFilePathObject = (value) => isPlainObject4(value) && Object.keys(value).length > 0 && Object.keys(value).every((key) => FILE_PATH_KEYS.has(key)) && isFilePathString(value.file), FILE_PATH_KEYS, isFilePathString = (file) => typeof file === "string", isStdioValueObject = (value) => isPlainObject4(value) && Object.keys(value).length > 0 && Object.keys(value).every((key) => STDIO_VALUE_KEYS.has(key)) && ("value" in value), STDIO_VALUE_KEYS, isUnknownStdioString = (type, value) => type === "native" && typeof value === "string" && !KNOWN_STDIO_STRINGS.has(value), KNOWN_STDIO_STRINGS, isReadableStream3 = (value) => Object.prototype.toString.call(value) === "[object ReadableStream]", isWritableStream2 = (value) => Object.prototype.toString.call(value) === "[object WritableStream]", isWebStream = (value) => isReadableStream3(value) || isWritableStream2(value), isTransformStream = (value) => isReadableStream3(value?.readable) && isWritableStream2(value?.writable), isAsyncIterableObject = (value) => isObject2(value) && typeof value[Symbol.asyncIterator] === "function", isIterableObject = (value) => isObject2(value) && typeof value[Symbol.iterator] === "function", isObject2 = (value) => typeof value === "object" && value !== null, TRANSFORM_TYPES, FILE_TYPES, SPECIAL_DUPLICATE_TYPES_SYNC, SPECIAL_DUPLICATE_TYPES, FORBID_DUPLICATE_TYPES, TYPE_TO_MESSAGE;
|
|
92774
93065
|
var init_type = __esm(() => {
|
|
92775
93066
|
init_uint_array();
|
|
92776
93067
|
FILE_PATH_KEYS = new Set(["file", "append"]);
|
|
@@ -92872,7 +93163,7 @@ var normalizeTransforms = (stdioItems, optionName, direction, options) => [
|
|
|
92872
93163
|
value: { transform, writableObjectMode, readableObjectMode }
|
|
92873
93164
|
};
|
|
92874
93165
|
}, normalizeTransformStream = ({ stdioItem, stdioItem: { value }, index, newTransforms, direction }) => {
|
|
92875
|
-
const { transform, objectMode } =
|
|
93166
|
+
const { transform, objectMode } = isPlainObject4(value) ? value : { transform: value };
|
|
92876
93167
|
const { writableObjectMode, readableObjectMode } = getTransformObjectModes(objectMode, index, newTransforms, direction);
|
|
92877
93168
|
return {
|
|
92878
93169
|
...stdioItem,
|
|
@@ -92885,7 +93176,7 @@ var normalizeTransforms = (stdioItems, optionName, direction, options) => [
|
|
|
92885
93176
|
binary: binaryOption = false,
|
|
92886
93177
|
preserveNewlines = false,
|
|
92887
93178
|
objectMode
|
|
92888
|
-
} =
|
|
93179
|
+
} = isPlainObject4(value) ? value : { transform: value };
|
|
92889
93180
|
const binary = binaryOption || BINARY_ENCODINGS.has(encoding);
|
|
92890
93181
|
const { writableObjectMode, readableObjectMode } = getTransformObjectModes(objectMode, index, newTransforms, direction);
|
|
92891
93182
|
return {
|
|
@@ -95580,7 +95871,7 @@ var init_abort2 = __esm(() => {
|
|
|
95580
95871
|
|
|
95581
95872
|
// node_modules/execa/lib/pipe/setup.js
|
|
95582
95873
|
var pipeToSubprocess = (sourceInfo, ...pipeArguments) => {
|
|
95583
|
-
if (
|
|
95874
|
+
if (isPlainObject4(pipeArguments[0])) {
|
|
95584
95875
|
return pipeToSubprocess.bind(undefined, {
|
|
95585
95876
|
...sourceInfo,
|
|
95586
95877
|
boundOptions: { ...sourceInfo.boundOptions, ...pipeArguments[0] }
|
|
@@ -96489,7 +96780,7 @@ var mergeOptions = (boundOptions, options) => {
|
|
|
96489
96780
|
]));
|
|
96490
96781
|
return { ...safeBoundOptions, ...mergedOptions };
|
|
96491
96782
|
}, mergeOption = (optionName, boundOptionValue, optionValue) => {
|
|
96492
|
-
if (DEEP_OPTIONS.has(optionName) &&
|
|
96783
|
+
if (DEEP_OPTIONS.has(optionName) && isPlainObject4(boundOptionValue) && isPlainObject4(optionValue)) {
|
|
96493
96784
|
return { ...boundOptionValue, ...optionValue };
|
|
96494
96785
|
}
|
|
96495
96786
|
return optionValue;
|
|
@@ -96514,7 +96805,7 @@ var createExeca = (mapArguments, boundOptions, deepOptions, setBoundExeca) => {
|
|
|
96514
96805
|
}
|
|
96515
96806
|
return boundExeca;
|
|
96516
96807
|
}, callBoundExeca = ({ mapArguments, deepOptions = {}, boundOptions = {}, setBoundExeca, createNested }, firstArgument, ...nextArguments) => {
|
|
96517
|
-
if (
|
|
96808
|
+
if (isPlainObject4(firstArgument)) {
|
|
96518
96809
|
return createNested(mapArguments, mergeOptions(boundOptions, firstArgument), setBoundExeca);
|
|
96519
96810
|
}
|
|
96520
96811
|
const { file, commandArguments, options, isSync } = parseArguments2({
|
|
@@ -98578,7 +98869,7 @@ var init_isArrayLikeObject = __esm(() => {
|
|
|
98578
98869
|
});
|
|
98579
98870
|
|
|
98580
98871
|
// node_modules/lodash-es/isPlainObject.js
|
|
98581
|
-
function
|
|
98872
|
+
function isPlainObject5(value) {
|
|
98582
98873
|
if (!isObjectLike_default(value) || _baseGetTag_default(value) != objectTag4) {
|
|
98583
98874
|
return false;
|
|
98584
98875
|
}
|
|
@@ -98599,7 +98890,7 @@ var init_isPlainObject = __esm(() => {
|
|
|
98599
98890
|
funcToString3 = funcProto3.toString;
|
|
98600
98891
|
hasOwnProperty11 = objectProto14.hasOwnProperty;
|
|
98601
98892
|
objectCtorString = funcToString3.call(Object);
|
|
98602
|
-
isPlainObject_default =
|
|
98893
|
+
isPlainObject_default = isPlainObject5;
|
|
98603
98894
|
});
|
|
98604
98895
|
|
|
98605
98896
|
// node_modules/lodash-es/_safeGet.js
|
|
@@ -102730,9 +103021,9 @@ function merge2(...objs) {
|
|
|
102730
103021
|
}
|
|
102731
103022
|
const targetKey = caseless && typeof key === "string" && findKey(result, key) || key;
|
|
102732
103023
|
const existing = hasOwnProperty14(result, targetKey) ? result[targetKey] : undefined;
|
|
102733
|
-
if (
|
|
103024
|
+
if (isPlainObject6(existing) && isPlainObject6(val)) {
|
|
102734
103025
|
result[targetKey] = merge2(existing, val);
|
|
102735
|
-
} else if (
|
|
103026
|
+
} else if (isPlainObject6(val)) {
|
|
102736
103027
|
result[targetKey] = merge2({}, val);
|
|
102737
103028
|
} else if (isArray3(val)) {
|
|
102738
103029
|
result[targetKey] = val.slice();
|
|
@@ -102835,7 +103126,7 @@ var toString3, getPrototypeOf, iterator, toStringTag, hasOwnProperty14, isUnsafe
|
|
|
102835
103126
|
}, kindOf, kindOfTest = (type) => {
|
|
102836
103127
|
type = type.toLowerCase();
|
|
102837
103128
|
return (thing) => kindOf(thing) === type;
|
|
102838
|
-
}, typeOfTest = (type) => (thing) => typeof thing === type, isArray3, isUndefined, isArrayBuffer3, isString, isFunction2, isNumber, isObject4 = (thing) => thing !== null && typeof thing === "object", isBoolean = (thing) => thing === true || thing === false,
|
|
103129
|
+
}, typeOfTest = (type) => (thing) => typeof thing === type, isArray3, isUndefined, isArrayBuffer3, isString, isFunction2, isNumber, isObject4 = (thing) => thing !== null && typeof thing === "object", isBoolean = (thing) => thing === true || thing === false, isPlainObject6 = (val) => {
|
|
102839
103130
|
if (!isObject4(val)) {
|
|
102840
103131
|
return false;
|
|
102841
103132
|
}
|
|
@@ -103111,7 +103402,7 @@ var init_utils3 = __esm(() => {
|
|
|
103111
103402
|
isNumber,
|
|
103112
103403
|
isBoolean,
|
|
103113
103404
|
isObject: isObject4,
|
|
103114
|
-
isPlainObject:
|
|
103405
|
+
isPlainObject: isPlainObject6,
|
|
103115
103406
|
isEmptyObject,
|
|
103116
103407
|
isReadableStream: isReadableStream4,
|
|
103117
103408
|
isRequest,
|
|
@@ -181149,6 +181440,7 @@ __export(exports_engineCompat, {
|
|
|
181149
181440
|
MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES: () => MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES,
|
|
181150
181441
|
MAX_GOAL_CHECKINS: () => MAX_GOAL_CHECKINS,
|
|
181151
181442
|
MAX_GOAL_CONDITION_CHARS: () => MAX_GOAL_CONDITION_CHARS,
|
|
181443
|
+
MAX_HOOK_CONCURRENCY: () => MAX_HOOK_CONCURRENCY,
|
|
181152
181444
|
MAX_PTL_RETRIES: () => MAX_PTL_RETRIES,
|
|
181153
181445
|
MAX_TRANSCRIPT_READ_BYTES: () => MAX_TRANSCRIPT_READ_BYTES,
|
|
181154
181446
|
MAX_WORKER_SPAWN_DEPTH: () => MAX_WORKER_SPAWN_DEPTH,
|
|
@@ -182435,11 +182727,12 @@ function parseArgumentNames2(argumentNames) {
|
|
|
182435
182727
|
return [];
|
|
182436
182728
|
}
|
|
182437
182729
|
const isValidName = (name) => typeof name === "string" && name.trim() !== "" && !/^\d+$/.test(name);
|
|
182730
|
+
const cap = (names) => names.map((name) => name.slice(0, MAX_ARGUMENT_NAME_CHARS2)).slice(0, MAX_ARGUMENT_NAMES2);
|
|
182438
182731
|
if (Array.isArray(argumentNames)) {
|
|
182439
|
-
return argumentNames.filter(isValidName);
|
|
182732
|
+
return cap(argumentNames.filter(isValidName));
|
|
182440
182733
|
}
|
|
182441
182734
|
if (typeof argumentNames === "string") {
|
|
182442
|
-
return argumentNames.split(/\s+/).filter(isValidName);
|
|
182735
|
+
return cap(argumentNames.split(/\s+/).filter(isValidName));
|
|
182443
182736
|
}
|
|
182444
182737
|
return [];
|
|
182445
182738
|
}
|
|
@@ -182449,36 +182742,144 @@ function generateProgressiveArgumentHint2(argNames, typedArgs) {
|
|
|
182449
182742
|
return;
|
|
182450
182743
|
return remaining.map((name) => `[${name}]`).join(" ");
|
|
182451
182744
|
}
|
|
182452
|
-
function
|
|
182745
|
+
function isWordChar3(c) {
|
|
182746
|
+
return c !== undefined && /[A-Za-z0-9_]/.test(c);
|
|
182747
|
+
}
|
|
182748
|
+
function matchPlaceholderAt2(content, i, argumentNames) {
|
|
182749
|
+
if (content[i] !== "$")
|
|
182750
|
+
return null;
|
|
182751
|
+
for (let n = 0;n < argumentNames.length; n++) {
|
|
182752
|
+
const name = argumentNames[n];
|
|
182753
|
+
if (!name)
|
|
182754
|
+
continue;
|
|
182755
|
+
if (content.startsWith(`$${name}`, i)) {
|
|
182756
|
+
const after = content[i + 1 + name.length];
|
|
182757
|
+
if (after !== "[" && !isWordChar3(after)) {
|
|
182758
|
+
return { length: 1 + name.length, kind: "named", nameIndex: n };
|
|
182759
|
+
}
|
|
182760
|
+
}
|
|
182761
|
+
}
|
|
182762
|
+
INDEXED_PLACEHOLDER_RE2.lastIndex = i;
|
|
182763
|
+
const indexed = INDEXED_PLACEHOLDER_RE2.exec(content);
|
|
182764
|
+
if (indexed) {
|
|
182765
|
+
return {
|
|
182766
|
+
length: indexed[0].length,
|
|
182767
|
+
kind: "indexed",
|
|
182768
|
+
argIndex: parseInt(indexed[1], 10)
|
|
182769
|
+
};
|
|
182770
|
+
}
|
|
182771
|
+
if (content.startsWith("$ARGUMENTS", i)) {
|
|
182772
|
+
return { length: "$ARGUMENTS".length, kind: "bare" };
|
|
182773
|
+
}
|
|
182774
|
+
SHORTHAND_PLACEHOLDER_RE2.lastIndex = i;
|
|
182775
|
+
const shorthand = SHORTHAND_PLACEHOLDER_RE2.exec(content);
|
|
182776
|
+
if (shorthand && !isWordChar3(content[i + shorthand[0].length])) {
|
|
182777
|
+
return {
|
|
182778
|
+
length: shorthand[0].length,
|
|
182779
|
+
kind: "shorthand",
|
|
182780
|
+
argIndex: parseInt(shorthand[1], 10)
|
|
182781
|
+
};
|
|
182782
|
+
}
|
|
182783
|
+
return null;
|
|
182784
|
+
}
|
|
182785
|
+
function countPlaceholderOccurrences2(content, argumentNames) {
|
|
182786
|
+
let count = 0;
|
|
182787
|
+
let i = 0;
|
|
182788
|
+
while (i < content.length) {
|
|
182789
|
+
const m = matchPlaceholderAt2(content, i, argumentNames);
|
|
182790
|
+
if (m) {
|
|
182791
|
+
count++;
|
|
182792
|
+
i += m.length;
|
|
182793
|
+
} else {
|
|
182794
|
+
i++;
|
|
182795
|
+
}
|
|
182796
|
+
}
|
|
182797
|
+
return count;
|
|
182798
|
+
}
|
|
182799
|
+
function substituteArgumentsImpl2(content, args, appendIfNoPlaceholder, argumentNames, strict) {
|
|
182453
182800
|
if (args === undefined || args === null) {
|
|
182454
182801
|
return content;
|
|
182455
182802
|
}
|
|
182456
|
-
const
|
|
182457
|
-
|
|
182458
|
-
|
|
182459
|
-
|
|
182460
|
-
|
|
182461
|
-
|
|
182462
|
-
|
|
182803
|
+
const placeholderCount = countPlaceholderOccurrences2(content, argumentNames);
|
|
182804
|
+
let effectiveArgs = args;
|
|
182805
|
+
if (placeholderCount > 0 && content.length + placeholderCount * args.length > MAX_SUBSTITUTION_OUTPUT_CHARS2) {
|
|
182806
|
+
if (strict)
|
|
182807
|
+
return null;
|
|
182808
|
+
const budgetPerReplacement = Math.max(0, Math.floor((MAX_SUBSTITUTION_OUTPUT_CHARS2 - content.length) / placeholderCount));
|
|
182809
|
+
effectiveArgs = args.slice(0, budgetPerReplacement);
|
|
182810
|
+
} else if (strict) {
|
|
182811
|
+
const appendLen = appendIfNoPlaceholder && args ? `
|
|
182812
|
+
|
|
182813
|
+
ARGUMENTS: `.length + args.length : 0;
|
|
182814
|
+
if (content.length + appendLen > MAX_SUBSTITUTION_OUTPUT_CHARS2) {
|
|
182815
|
+
return null;
|
|
182816
|
+
}
|
|
182463
182817
|
}
|
|
182464
|
-
|
|
182465
|
-
|
|
182466
|
-
|
|
182467
|
-
|
|
182468
|
-
|
|
182469
|
-
|
|
182470
|
-
|
|
182471
|
-
}
|
|
182472
|
-
|
|
182473
|
-
|
|
182474
|
-
|
|
182818
|
+
const parsedArgs = parseArguments3(effectiveArgs);
|
|
182819
|
+
let out = "";
|
|
182820
|
+
const appendValue = (value) => {
|
|
182821
|
+
if (out.length + value.length > MAX_SUBSTITUTION_OUTPUT_CHARS2) {
|
|
182822
|
+
value = value.slice(0, Math.max(0, MAX_SUBSTITUTION_OUTPUT_CHARS2 - out.length));
|
|
182823
|
+
}
|
|
182824
|
+
out += value;
|
|
182825
|
+
};
|
|
182826
|
+
let matched = false;
|
|
182827
|
+
let i = 0;
|
|
182828
|
+
while (i < content.length) {
|
|
182829
|
+
const m = matchPlaceholderAt2(content, i, argumentNames);
|
|
182830
|
+
if (m) {
|
|
182831
|
+
matched = true;
|
|
182832
|
+
if (m.kind === "bare")
|
|
182833
|
+
appendValue(effectiveArgs);
|
|
182834
|
+
else if (m.kind === "named")
|
|
182835
|
+
appendValue(parsedArgs[m.nameIndex] ?? "");
|
|
182836
|
+
else
|
|
182837
|
+
appendValue(parsedArgs[m.argIndex] ?? "");
|
|
182838
|
+
i += m.length;
|
|
182839
|
+
} else {
|
|
182840
|
+
out += content[i];
|
|
182841
|
+
i++;
|
|
182842
|
+
}
|
|
182843
|
+
}
|
|
182844
|
+
if (!matched && appendIfNoPlaceholder && args) {
|
|
182845
|
+
out = out + `
|
|
182475
182846
|
|
|
182476
182847
|
ARGUMENTS: ${args}`;
|
|
182477
182848
|
}
|
|
182478
|
-
return
|
|
182849
|
+
return out;
|
|
182479
182850
|
}
|
|
182851
|
+
function substituteArguments2(content, args, appendIfNoPlaceholder = true, argumentNames = []) {
|
|
182852
|
+
return substituteArgumentsImpl2(content, args, appendIfNoPlaceholder, argumentNames, false) ?? content;
|
|
182853
|
+
}
|
|
182854
|
+
function substituteArgumentsStrict2(content, args, appendIfNoPlaceholder = true, argumentNames = []) {
|
|
182855
|
+
return substituteArgumentsImpl2(content, args, appendIfNoPlaceholder, argumentNames, true);
|
|
182856
|
+
}
|
|
182857
|
+
var MAX_ARGUMENT_NAMES2 = 64, MAX_ARGUMENT_NAME_CHARS2 = 64, MAX_SUBSTITUTION_OUTPUT_CHARS2 = 1e6, INDEXED_PLACEHOLDER_RE2, SHORTHAND_PLACEHOLDER_RE2;
|
|
182480
182858
|
var init_argumentSubstitution2 = __esm(() => {
|
|
182481
182859
|
init_shellQuote2();
|
|
182860
|
+
INDEXED_PLACEHOLDER_RE2 = /\$ARGUMENTS\[(\d+)\]/y;
|
|
182861
|
+
SHORTHAND_PLACEHOLDER_RE2 = /\$(\d+)/y;
|
|
182862
|
+
});
|
|
182863
|
+
|
|
182864
|
+
// src/tui/utils/commandNameSafety.ts
|
|
182865
|
+
function isUnsafeCommandName2(name) {
|
|
182866
|
+
if (name === "")
|
|
182867
|
+
return true;
|
|
182868
|
+
if (name.includes("<") || name.includes(">"))
|
|
182869
|
+
return true;
|
|
182870
|
+
return UNSAFE_NAME_CHARS_RE2.test(name);
|
|
182871
|
+
}
|
|
182872
|
+
function sanitizeDisplayName2(displayName, canonicalName) {
|
|
182873
|
+
if (displayName === undefined || !isUnsafeCommandName2(displayName)) {
|
|
182874
|
+
return displayName;
|
|
182875
|
+
}
|
|
182876
|
+
logForDebugging3(`Discarding unsafe frontmatter display name ${JSON.stringify(displayName)} for ${canonicalName}; falling back to canonical name`);
|
|
182877
|
+
return;
|
|
182878
|
+
}
|
|
182879
|
+
var UNSAFE_NAME_CHARS_RE2;
|
|
182880
|
+
var init_commandNameSafety2 = __esm(() => {
|
|
182881
|
+
init_debug();
|
|
182882
|
+
UNSAFE_NAME_CHARS_RE2 = /[\u0000-\u001F\u007F-\u00A0\u00AD\u034F\u061C\u070F\u1680\u180E\u2000-\u200F\u2028\u2029\u202A-\u202E\u202F\u205F\u2060-\u2069\u3000\uFE00-\uFE0F\uFEFF\u{E0100}-\u{E01EF}]/u;
|
|
182482
182883
|
});
|
|
182483
182884
|
|
|
182484
182885
|
// src/tui/utils/generatedFiles.ts
|
|
@@ -184911,7 +185312,7 @@ class Protocol {
|
|
|
184911
185312
|
};
|
|
184912
185313
|
}
|
|
184913
185314
|
}
|
|
184914
|
-
function
|
|
185315
|
+
function isPlainObject7(value) {
|
|
184915
185316
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
184916
185317
|
}
|
|
184917
185318
|
function mergeCapabilities(base, additional) {
|
|
@@ -184922,7 +185323,7 @@ function mergeCapabilities(base, additional) {
|
|
|
184922
185323
|
if (addValue === undefined)
|
|
184923
185324
|
continue;
|
|
184924
185325
|
const baseValue = result[k];
|
|
184925
|
-
if (
|
|
185326
|
+
if (isPlainObject7(baseValue) && isPlainObject7(addValue)) {
|
|
184926
185327
|
result[k] = { ...baseValue, ...addValue };
|
|
184927
185328
|
} else {
|
|
184928
185329
|
result[k] = addValue;
|
|
@@ -201476,10 +201877,10 @@ function parseProxyResponse(socket) {
|
|
|
201476
201877
|
read();
|
|
201477
201878
|
});
|
|
201478
201879
|
}
|
|
201479
|
-
var
|
|
201880
|
+
var import_debug54, debug;
|
|
201480
201881
|
var init_parse_proxy_response = __esm(() => {
|
|
201481
|
-
|
|
201482
|
-
debug =
|
|
201882
|
+
import_debug54 = __toESM(require_src(), 1);
|
|
201883
|
+
debug = import_debug54.default("https-proxy-agent:parse-proxy-response");
|
|
201483
201884
|
});
|
|
201484
201885
|
|
|
201485
201886
|
// node_modules/proxy-agent-negotiate/dist/index.js
|
|
@@ -201532,7 +201933,7 @@ function omit2(obj, ...keys) {
|
|
|
201532
201933
|
}
|
|
201533
201934
|
return ret;
|
|
201534
201935
|
}
|
|
201535
|
-
var
|
|
201936
|
+
var import_debug55, debug2, setServernameFromNonIpHost = (options) => {
|
|
201536
201937
|
if (options.servername === undefined && options.host && !net2.isIP(options.host)) {
|
|
201537
201938
|
return {
|
|
201538
201939
|
...options,
|
|
@@ -201544,8 +201945,8 @@ var import_debug54, debug2, setServernameFromNonIpHost = (options) => {
|
|
|
201544
201945
|
var init_dist7 = __esm(() => {
|
|
201545
201946
|
init_dist6();
|
|
201546
201947
|
init_parse_proxy_response();
|
|
201547
|
-
|
|
201548
|
-
debug2 =
|
|
201948
|
+
import_debug55 = __toESM(require_src(), 1);
|
|
201949
|
+
debug2 = import_debug55.default("https-proxy-agent");
|
|
201549
201950
|
HttpsProxyAgent2 = class HttpsProxyAgent2 extends Agent2 {
|
|
201550
201951
|
constructor(proxy, opts) {
|
|
201551
201952
|
super(opts);
|
|
@@ -263020,6 +263421,9 @@ function convertToHookMatchers(sessionMatchers) {
|
|
|
263020
263421
|
return sessionMatchers.map((sm) => ({
|
|
263021
263422
|
matcher: sm.matcher,
|
|
263022
263423
|
skillRoot: sm.skillRoot,
|
|
263424
|
+
pluginRoot: sm.pluginRoot,
|
|
263425
|
+
pluginName: sm.pluginName,
|
|
263426
|
+
pluginId: sm.pluginId,
|
|
263023
263427
|
hooks: sm.hooks.map((h) => h.hook).filter((h) => h.type !== "function")
|
|
263024
263428
|
}));
|
|
263025
263429
|
}
|
|
@@ -273799,6 +274203,19 @@ async function toArray2(generator) {
|
|
|
273799
274203
|
}
|
|
273800
274204
|
return result;
|
|
273801
274205
|
}
|
|
274206
|
+
async function runWithConcurrencyLimit(tasks, limit) {
|
|
274207
|
+
const results = new Array(tasks.length);
|
|
274208
|
+
let next = 0;
|
|
274209
|
+
const worker = async () => {
|
|
274210
|
+
while (next < tasks.length) {
|
|
274211
|
+
const index = next++;
|
|
274212
|
+
results[index] = await tasks[index]();
|
|
274213
|
+
}
|
|
274214
|
+
};
|
|
274215
|
+
const workers = Math.max(1, Math.min(limit, tasks.length));
|
|
274216
|
+
await Promise.all(Array.from({ length: workers }, worker));
|
|
274217
|
+
return results;
|
|
274218
|
+
}
|
|
273802
274219
|
var NO_VALUE;
|
|
273803
274220
|
var init_generators = __esm(() => {
|
|
273804
274221
|
NO_VALUE = Symbol("NO_VALUE");
|
|
@@ -303702,11 +304119,11 @@ function byteAt2(L, charIdx) {
|
|
|
303702
304119
|
L.byteTable = t;
|
|
303703
304120
|
return t[charIdx];
|
|
303704
304121
|
}
|
|
303705
|
-
function
|
|
304122
|
+
function isWordChar4(c) {
|
|
303706
304123
|
return c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c >= "0" && c <= "9" || c === "_" || c === "/" || c === "." || c === "-" || c === "+" || c === ":" || c === "@" || c === "%" || c === "," || c === "~" || c === "^" || c === "?" || c === "*" || c === "!" || c === "=" || c === "[" || c === "]";
|
|
303707
304124
|
}
|
|
303708
304125
|
function isWordStart2(c) {
|
|
303709
|
-
return
|
|
304126
|
+
return isWordChar4(c) || c === "\\";
|
|
303710
304127
|
}
|
|
303711
304128
|
function isIdentStart2(c) {
|
|
303712
304129
|
return c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "_";
|
|
@@ -304016,7 +304433,7 @@ function nextToken2(L, ctx = "arg") {
|
|
|
304016
304433
|
advance2(L);
|
|
304017
304434
|
continue;
|
|
304018
304435
|
}
|
|
304019
|
-
if (!
|
|
304436
|
+
if (!isWordChar4(ch) && ch !== "{" && ch !== "}") {
|
|
304020
304437
|
break;
|
|
304021
304438
|
}
|
|
304022
304439
|
advance2(L);
|
|
@@ -325621,7 +326038,7 @@ function parseSkillFrontmatterFields2(frontmatter, markdownContent, resolvedName
|
|
|
325621
326038
|
logForDebugging3(`Skill ${resolvedName} has invalid effort '${effortRaw}'. Valid options: ${EFFORT_LEVELS2.join(", ")} or an integer`);
|
|
325622
326039
|
}
|
|
325623
326040
|
return {
|
|
325624
|
-
displayName: frontmatter.name != null ? String(frontmatter.name) : undefined,
|
|
326041
|
+
displayName: sanitizeDisplayName2(frontmatter.name != null ? String(frontmatter.name) : undefined, resolvedName),
|
|
325625
326042
|
description,
|
|
325626
326043
|
hasUserSpecifiedDescription: validatedDescription !== null,
|
|
325627
326044
|
allowedTools: parseSlashCommandToolsFromFrontmatter2(frontmatter["allowed-tools"]),
|
|
@@ -325737,6 +326154,10 @@ async function loadSkillsFromSkillsDir2(basePath, source) {
|
|
|
325737
326154
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
325738
326155
|
return null;
|
|
325739
326156
|
}
|
|
326157
|
+
if (isUnsafeCommandName2(entry.name)) {
|
|
326158
|
+
logForDebugging3(`[skills] skipping unsafe skill directory name: ${JSON.stringify(entry.name)}`);
|
|
326159
|
+
return null;
|
|
326160
|
+
}
|
|
325740
326161
|
const skillDirPath = join108(basePath, entry.name);
|
|
325741
326162
|
const skillFilePath = join108(skillDirPath, "SKILL.md");
|
|
325742
326163
|
let content;
|
|
@@ -325847,6 +326268,10 @@ async function loadSkillsFromCommandsDir2(cwd) {
|
|
|
325847
326268
|
content,
|
|
325848
326269
|
source
|
|
325849
326270
|
});
|
|
326271
|
+
if (isUnsafeCommandName2(cmdName)) {
|
|
326272
|
+
logForDebugging3(`[skills] skipping unsafe command name: ${JSON.stringify(cmdName)}`);
|
|
326273
|
+
continue;
|
|
326274
|
+
}
|
|
325850
326275
|
const parsed = parseSkillFrontmatterFields2(frontmatter, content, cmdName, "Custom command");
|
|
325851
326276
|
skills.push({
|
|
325852
326277
|
skill: createSkillCommand2({
|
|
@@ -325985,6 +326410,7 @@ var init_loadSkillsDir2 = __esm(() => {
|
|
|
325985
326410
|
init_bootstrapState();
|
|
325986
326411
|
init_tokenEstimation();
|
|
325987
326412
|
init_argumentSubstitution2();
|
|
326413
|
+
init_commandNameSafety2();
|
|
325988
326414
|
init_debug();
|
|
325989
326415
|
init_effort2();
|
|
325990
326416
|
init_envUtils2();
|
|
@@ -330406,7 +330832,7 @@ function createPluginCommand(commandName, file, sourceName, pluginManifest, plug
|
|
|
330406
330832
|
const argumentNames = parseArgumentNames2(frontmatter.arguments);
|
|
330407
330833
|
const whenToUse = frontmatter["when-to-use"] ?? frontmatter.when_to_use;
|
|
330408
330834
|
const version = frontmatter.version;
|
|
330409
|
-
const displayName = frontmatter.name;
|
|
330835
|
+
const displayName = sanitizeDisplayName2(frontmatter.name, commandName);
|
|
330410
330836
|
const model = frontmatter.model === "inherit" ? undefined : frontmatter.model ? parseUserSpecifiedModel2(frontmatter.model) : undefined;
|
|
330411
330837
|
const effortRaw = frontmatter["effort"];
|
|
330412
330838
|
const effort = effortRaw !== undefined ? parseEffortValue2(effortRaw) : undefined;
|
|
@@ -330591,6 +331017,7 @@ var init_loadPluginCommands = __esm(() => {
|
|
|
330591
331017
|
init_bootstrapState();
|
|
330592
331018
|
init_argumentSubstitution2();
|
|
330593
331019
|
init_debug();
|
|
331020
|
+
init_commandNameSafety2();
|
|
330594
331021
|
init_effort2();
|
|
330595
331022
|
init_envUtils2();
|
|
330596
331023
|
init_errors4();
|
|
@@ -330742,8 +331169,15 @@ var init_loadPluginCommands = __esm(() => {
|
|
|
330742
331169
|
return pluginCommands;
|
|
330743
331170
|
}));
|
|
330744
331171
|
const allCommands = perPluginCommands.flat();
|
|
330745
|
-
|
|
330746
|
-
|
|
331172
|
+
const safeCommands = allCommands.filter((cmd) => {
|
|
331173
|
+
if (isUnsafeCommandName2(cmd.name)) {
|
|
331174
|
+
logForDebugging3(`Skipping unsafe plugin command name: ${JSON.stringify(cmd.name)}`);
|
|
331175
|
+
return false;
|
|
331176
|
+
}
|
|
331177
|
+
return true;
|
|
331178
|
+
});
|
|
331179
|
+
logForDebugging3(`Total plugin commands loaded: ${safeCommands.length}`);
|
|
331180
|
+
return safeCommands;
|
|
330747
331181
|
});
|
|
330748
331182
|
getPluginSkills = memoize_default(async () => {
|
|
330749
331183
|
if (isBareMode() && getInlinePlugins().length === 0) {
|
|
@@ -330788,8 +331222,15 @@ var init_loadPluginCommands = __esm(() => {
|
|
|
330788
331222
|
return pluginSkills;
|
|
330789
331223
|
}));
|
|
330790
331224
|
const allSkills = perPluginSkills.flat();
|
|
330791
|
-
|
|
330792
|
-
|
|
331225
|
+
const safeSkills = allSkills.filter((cmd) => {
|
|
331226
|
+
if (isUnsafeCommandName2(cmd.name)) {
|
|
331227
|
+
logForDebugging3(`Skipping unsafe plugin skill name: ${JSON.stringify(cmd.name)}`);
|
|
331228
|
+
return false;
|
|
331229
|
+
}
|
|
331230
|
+
return true;
|
|
331231
|
+
});
|
|
331232
|
+
logForDebugging3(`Total plugin skills loaded: ${safeSkills.length}`);
|
|
331233
|
+
return safeSkills;
|
|
330793
331234
|
});
|
|
330794
331235
|
});
|
|
330795
331236
|
|
|
@@ -335812,6 +336253,12 @@ function mergePluginSources(sources) {
|
|
|
335812
336253
|
const marketplacePlugins = sources.marketplace.filter((p) => {
|
|
335813
336254
|
if (sessionNames.has(p.name)) {
|
|
335814
336255
|
logForDebugging3(`Plugin "${p.name}" from --plugin-dir overrides installed version`);
|
|
336256
|
+
errors.push({
|
|
336257
|
+
type: "generic-error",
|
|
336258
|
+
source: p.source,
|
|
336259
|
+
plugin: p.name,
|
|
336260
|
+
error: `Installed plugin "${p.name}" excluded (hooks and commands inactive) — overridden by --plugin-dir copy of the same name`
|
|
336261
|
+
});
|
|
335815
336262
|
return false;
|
|
335816
336263
|
}
|
|
335817
336264
|
return true;
|
|
@@ -337818,8 +338265,9 @@ function handleMessageFromStream(message, onMessage, onUpdateLength, onSetStream
|
|
|
337818
338265
|
}
|
|
337819
338266
|
}
|
|
337820
338267
|
function wrapInSystemReminder(content) {
|
|
338268
|
+
const neutralized = content.replaceAll("</system-reminder>", "</system-reminder>").replaceAll("<system-reminder>", "<system-reminder>");
|
|
337821
338269
|
return `<system-reminder>
|
|
337822
|
-
${
|
|
338270
|
+
${neutralized}
|
|
337823
338271
|
</system-reminder>`;
|
|
337824
338272
|
}
|
|
337825
338273
|
function wrapMessagesInSystemReminder(messages) {
|
|
@@ -340428,6 +340876,16 @@ async function hasPermissionsToUseToolInner(tool, input, context) {
|
|
|
340428
340876
|
throw new AbortError2;
|
|
340429
340877
|
}
|
|
340430
340878
|
let appState = context.getAppState();
|
|
340879
|
+
if (appState.toolPermissionContext.mode === "plan" && !appState.toolPermissionContext.isBypassPermissionsModeAvailable && !PLAN_MODE_WRITE_EXEMPT_TOOL_NAMES2.has(tool.name) && !(tool.isReadOnly?.(input) ?? false)) {
|
|
340880
|
+
return {
|
|
340881
|
+
behavior: "deny",
|
|
340882
|
+
message: PLAN_MODE_WRITE_DENIED_MESSAGE2(tool.name),
|
|
340883
|
+
decisionReason: {
|
|
340884
|
+
type: "mode",
|
|
340885
|
+
mode: "plan"
|
|
340886
|
+
}
|
|
340887
|
+
};
|
|
340888
|
+
}
|
|
340431
340889
|
const denyRule = getDenyRuleForTool2(appState.toolPermissionContext, tool);
|
|
340432
340890
|
if (denyRule) {
|
|
340433
340891
|
return {
|
|
@@ -340608,7 +341066,7 @@ function syncPermissionRulesFromDisk2(toolPermissionContext, rules) {
|
|
|
340608
341066
|
function getUpdatedInputOrFallback2(permissionResult, fallback) {
|
|
340609
341067
|
return ("updatedInput" in permissionResult ? permissionResult.updatedInput : undefined) ?? fallback;
|
|
340610
341068
|
}
|
|
340611
|
-
var classifierDecisionModule, autoModeStateModule3, CLASSIFIER_FAIL_CLOSED_REFRESH_MS, PERMISSION_RULE_SOURCES2, hasPermissionsToUseTool2 = async (tool, input, context, assistantMessage, toolUseID) => {
|
|
341069
|
+
var PLAN_MODE_WRITE_EXEMPT_TOOL_NAMES2, PLAN_MODE_WRITE_DENIED_MESSAGE2 = (toolName) => `Plan mode is active — ${toolName} is not allowed to make changes. ` + `Present your plan and use ExitPlanMode, or ask the user to change the permission mode.`, classifierDecisionModule, autoModeStateModule3, CLASSIFIER_FAIL_CLOSED_REFRESH_MS, PERMISSION_RULE_SOURCES2, hasPermissionsToUseTool2 = async (tool, input, context, assistantMessage, toolUseID) => {
|
|
340612
341070
|
const result = await hasPermissionsToUseToolInner(tool, input, context);
|
|
340613
341071
|
if (result.behavior === "allow") {
|
|
340614
341072
|
const appState = context.getAppState();
|
|
@@ -340841,6 +341299,10 @@ var init_permissions6 = __esm(() => {
|
|
|
340841
341299
|
init_slowOperations();
|
|
340842
341300
|
init_denialTracking();
|
|
340843
341301
|
init_yoloClassifier();
|
|
341302
|
+
PLAN_MODE_WRITE_EXEMPT_TOOL_NAMES2 = new Set([
|
|
341303
|
+
"EnterPlanMode",
|
|
341304
|
+
"ExitPlanMode"
|
|
341305
|
+
]);
|
|
340844
341306
|
classifierDecisionModule = feature("TRANSCRIPT_CLASSIFIER") ? (init_classifierDecision(), __toCommonJS(exports_classifierDecision)) : null;
|
|
340845
341307
|
autoModeStateModule3 = feature("TRANSCRIPT_CLASSIFIER") ? __toCommonJS(exports_autoModeState) : null;
|
|
340846
341308
|
CLASSIFIER_FAIL_CLOSED_REFRESH_MS = 30 * 60 * 1000;
|
|
@@ -405071,6 +405533,8 @@ async function searchSkillsAcrossMarketplaces(query) {
|
|
|
405071
405533
|
for (const d of dirEntries) {
|
|
405072
405534
|
if (!d.isDirectory())
|
|
405073
405535
|
continue;
|
|
405536
|
+
if (isUnsafeCommandName2(d.name))
|
|
405537
|
+
continue;
|
|
405074
405538
|
const skillFile = join146(skillDir, d.name, "SKILL.md");
|
|
405075
405539
|
if (seen.has(skillFile))
|
|
405076
405540
|
continue;
|
|
@@ -405082,7 +405546,7 @@ async function searchSkillsAcrossMarketplaces(query) {
|
|
|
405082
405546
|
continue;
|
|
405083
405547
|
}
|
|
405084
405548
|
const { frontmatter, content: markdown } = parseFrontmatter2(content);
|
|
405085
|
-
const resolvedName =
|
|
405549
|
+
const resolvedName = d.name;
|
|
405086
405550
|
const parsed = parseSkillFrontmatterFields2(frontmatter, markdown, resolvedName);
|
|
405087
405551
|
const installId = createPluginId(entry.name, marketplaceName);
|
|
405088
405552
|
const skill = {
|
|
@@ -405107,6 +405571,7 @@ async function searchSkillsAcrossMarketplaces(query) {
|
|
|
405107
405571
|
return results;
|
|
405108
405572
|
}
|
|
405109
405573
|
var init_skillSearch = __esm(() => {
|
|
405574
|
+
init_commandNameSafety2();
|
|
405110
405575
|
init_frontmatterParser2();
|
|
405111
405576
|
init_loadSkillsDir2();
|
|
405112
405577
|
init_marketplaceHelpers();
|
|
@@ -412471,7 +412936,7 @@ var call45 = async (_args, _context) => {
|
|
|
412471
412936
|
reloadSkillsNow();
|
|
412472
412937
|
return {
|
|
412473
412938
|
type: "text",
|
|
412474
|
-
value: "Re-scanned skill directories; in-session skill registry refreshed (new/removed/changed skills now active without restart)."
|
|
412939
|
+
value: "Re-scanned skill directories; in-session skill registry refreshed (new/removed/changed skills now active without restart). The complete skill list will be re-sent to the model with your next message."
|
|
412475
412940
|
};
|
|
412476
412941
|
};
|
|
412477
412942
|
var init_reload_skills = __esm(() => {
|
|
@@ -428505,9 +428970,144 @@ var init_combinedAbortSignal = __esm(() => {
|
|
|
428505
428970
|
init_abortController2();
|
|
428506
428971
|
});
|
|
428507
428972
|
|
|
428973
|
+
// src/tui/utils/hooks/hookInputDepth.ts
|
|
428974
|
+
function exceedsMaxNestingDepth(value) {
|
|
428975
|
+
const stack = [[value, 0]];
|
|
428976
|
+
const visited = new WeakSet;
|
|
428977
|
+
while (stack.length > 0) {
|
|
428978
|
+
const [v, depth] = stack.pop();
|
|
428979
|
+
if (depth > MAX_HOOK_INPUT_NESTING_DEPTH)
|
|
428980
|
+
return true;
|
|
428981
|
+
if (v === null || typeof v !== "object")
|
|
428982
|
+
continue;
|
|
428983
|
+
if (visited.has(v))
|
|
428984
|
+
continue;
|
|
428985
|
+
visited.add(v);
|
|
428986
|
+
let children;
|
|
428987
|
+
try {
|
|
428988
|
+
children = Array.isArray(v) ? v : Object.values(v);
|
|
428989
|
+
} catch {
|
|
428990
|
+
continue;
|
|
428991
|
+
}
|
|
428992
|
+
for (const child of children) {
|
|
428993
|
+
stack.push([child, depth + 1]);
|
|
428994
|
+
}
|
|
428995
|
+
}
|
|
428996
|
+
return false;
|
|
428997
|
+
}
|
|
428998
|
+
var MAX_HOOK_INPUT_NESTING_DEPTH = 28000;
|
|
428999
|
+
|
|
429000
|
+
// src/tui/utils/hooks/hookInputMaterialize.ts
|
|
429001
|
+
function materializeHookInput(value) {
|
|
429002
|
+
if (value === null || typeof value !== "object") {
|
|
429003
|
+
return { ok: true, value, droppedKeys: [] };
|
|
429004
|
+
}
|
|
429005
|
+
const droppedKeys = [];
|
|
429006
|
+
const visited = new WeakMap;
|
|
429007
|
+
const root = Array.isArray(value) ? [] : {};
|
|
429008
|
+
visited.set(value, root);
|
|
429009
|
+
const stack = [{ src: value, target: root }];
|
|
429010
|
+
while (stack.length > 0) {
|
|
429011
|
+
const { src, target } = stack.pop();
|
|
429012
|
+
let keys;
|
|
429013
|
+
try {
|
|
429014
|
+
keys = Object.keys(src);
|
|
429015
|
+
} catch {
|
|
429016
|
+
droppedKeys.push("<enumeration-failed>");
|
|
429017
|
+
continue;
|
|
429018
|
+
}
|
|
429019
|
+
for (const key of keys) {
|
|
429020
|
+
let child;
|
|
429021
|
+
try {
|
|
429022
|
+
child = src[key];
|
|
429023
|
+
} catch {
|
|
429024
|
+
droppedKeys.push(key);
|
|
429025
|
+
continue;
|
|
429026
|
+
}
|
|
429027
|
+
if (child === null || typeof child !== "object") {
|
|
429028
|
+
target[key] = child;
|
|
429029
|
+
} else if (visited.has(child)) {
|
|
429030
|
+
target[key] = "[Circular]";
|
|
429031
|
+
} else {
|
|
429032
|
+
const childClone = Array.isArray(child) ? [] : {};
|
|
429033
|
+
visited.set(child, childClone);
|
|
429034
|
+
target[key] = childClone;
|
|
429035
|
+
stack.push({ src: child, target: childClone });
|
|
429036
|
+
}
|
|
429037
|
+
}
|
|
429038
|
+
}
|
|
429039
|
+
return { ok: true, value: root, droppedKeys };
|
|
429040
|
+
}
|
|
429041
|
+
function stringifyWithGetterFallback(value) {
|
|
429042
|
+
try {
|
|
429043
|
+
return { ok: true, value: jsonStringify5(value), droppedKeys: [] };
|
|
429044
|
+
} catch (error) {
|
|
429045
|
+
const materialized = materializeHookInput(value);
|
|
429046
|
+
if (materialized.ok === false)
|
|
429047
|
+
return { ok: false, error };
|
|
429048
|
+
try {
|
|
429049
|
+
return {
|
|
429050
|
+
ok: true,
|
|
429051
|
+
value: jsonStringify5(materialized.value),
|
|
429052
|
+
droppedKeys: materialized.droppedKeys
|
|
429053
|
+
};
|
|
429054
|
+
} catch {
|
|
429055
|
+
return { ok: false, error };
|
|
429056
|
+
}
|
|
429057
|
+
}
|
|
429058
|
+
}
|
|
429059
|
+
var init_hookInputMaterialize = __esm(() => {
|
|
429060
|
+
init_slowOperations();
|
|
429061
|
+
});
|
|
429062
|
+
|
|
429063
|
+
// src/tui/utils/hooks/hookReentrancy.ts
|
|
429064
|
+
import { AsyncLocalStorage as AsyncLocalStorage8 } from "async_hooks";
|
|
429065
|
+
function getCallbackId(fn) {
|
|
429066
|
+
let id = callbackIds.get(fn);
|
|
429067
|
+
if (id === undefined) {
|
|
429068
|
+
id = nextCallbackId++;
|
|
429069
|
+
callbackIds.set(fn, id);
|
|
429070
|
+
}
|
|
429071
|
+
return id;
|
|
429072
|
+
}
|
|
429073
|
+
function getHookReentrancyKey(hookEvent, hook, pluginRoot) {
|
|
429074
|
+
const h = hook;
|
|
429075
|
+
const body = typeof h.callback === "function" ? `fn:${getCallbackId(h.callback)}` : String(h.command ?? h.prompt ?? h.url ?? "");
|
|
429076
|
+
return `${hookEvent}:${String(h.type)}:${pluginRoot ?? ""}:${body}`;
|
|
429077
|
+
}
|
|
429078
|
+
function isReentrantHook(hookEvent, hook, pluginRoot) {
|
|
429079
|
+
const inFlight = hookReentrancyStorage.getStore();
|
|
429080
|
+
if (inFlight === undefined)
|
|
429081
|
+
return false;
|
|
429082
|
+
return inFlight.has(getHookReentrancyKey(hookEvent, hook, pluginRoot));
|
|
429083
|
+
}
|
|
429084
|
+
function runWithHookReentrancy(hookEvent, hook, pluginRoot, fn) {
|
|
429085
|
+
const store = new Set(hookReentrancyStorage.getStore() ?? []);
|
|
429086
|
+
store.add(getHookReentrancyKey(hookEvent, hook, pluginRoot));
|
|
429087
|
+
return hookReentrancyStorage.run(store, fn);
|
|
429088
|
+
}
|
|
429089
|
+
var hookReentrancyStorage, callbackIds, nextCallbackId = 1;
|
|
429090
|
+
var init_hookReentrancy = __esm(() => {
|
|
429091
|
+
hookReentrancyStorage = new AsyncLocalStorage8;
|
|
429092
|
+
callbackIds = new WeakMap;
|
|
429093
|
+
});
|
|
429094
|
+
|
|
429095
|
+
// src/tui/utils/hooks/hookFailClosed.ts
|
|
429096
|
+
function shouldFailClosePluginHook(hookEvent, pluginRoot) {
|
|
429097
|
+
return pluginRoot !== undefined && GATE_EVENTS.has(hookEvent);
|
|
429098
|
+
}
|
|
429099
|
+
var GATE_EVENTS;
|
|
429100
|
+
var init_hookFailClosed = __esm(() => {
|
|
429101
|
+
GATE_EVENTS = new Set([
|
|
429102
|
+
"PreToolUse",
|
|
429103
|
+
"UserPromptSubmit",
|
|
429104
|
+
"PermissionRequest"
|
|
429105
|
+
]);
|
|
429106
|
+
});
|
|
429107
|
+
|
|
428508
429108
|
// src/tui/utils/hooks/hookHelpers.ts
|
|
428509
429109
|
function addArgumentsToPrompt(prompt, jsonInput) {
|
|
428510
|
-
return
|
|
429110
|
+
return substituteArgumentsStrict2(prompt, jsonInput);
|
|
428511
429111
|
}
|
|
428512
429112
|
function createStructuredOutputTool() {
|
|
428513
429113
|
return {
|
|
@@ -428555,6 +429155,19 @@ async function execPromptHook(hook, hookName, hookEvent, jsonInput, signal, tool
|
|
|
428555
429155
|
const effectiveToolUseID = toolUseID || `hook-${randomUUID41()}`;
|
|
428556
429156
|
try {
|
|
428557
429157
|
const processedPrompt = addArgumentsToPrompt(hook.prompt, jsonInput);
|
|
429158
|
+
if (processedPrompt === null) {
|
|
429159
|
+
logForDebugging3(`Hooks: hook input exceeds substitution budget — blocking (fail-closed)`);
|
|
429160
|
+
return {
|
|
429161
|
+
hook,
|
|
429162
|
+
outcome: "blocking",
|
|
429163
|
+
blockingError: {
|
|
429164
|
+
blockingError: "Hook input exceeds substitution budget; refusing to evaluate on truncated input",
|
|
429165
|
+
command: hook.prompt
|
|
429166
|
+
},
|
|
429167
|
+
preventContinuation: true,
|
|
429168
|
+
stopReason: "hook input exceeds substitution budget"
|
|
429169
|
+
};
|
|
429170
|
+
}
|
|
428558
429171
|
logForDebugging3(`Hooks: Processing prompt hook with prompt: ${processedPrompt}`);
|
|
428559
429172
|
const userMessage = createUserMessage2({ content: processedPrompt });
|
|
428560
429173
|
const messagesToQuery = messages && messages.length > 0 ? [...messages, userMessage] : [userMessage];
|
|
@@ -428701,6 +429314,17 @@ async function execAgentHook(hook, hookName, hookEvent, jsonInput, signal, toolU
|
|
|
428701
429314
|
const hookStartTime = Date.now();
|
|
428702
429315
|
try {
|
|
428703
429316
|
const processedPrompt = addArgumentsToPrompt(hook.prompt, jsonInput);
|
|
429317
|
+
if (processedPrompt === null) {
|
|
429318
|
+
logForDebugging3(`Hooks: hook input exceeds substitution budget — blocking (fail-closed)`);
|
|
429319
|
+
return {
|
|
429320
|
+
hook,
|
|
429321
|
+
outcome: "blocking",
|
|
429322
|
+
blockingError: {
|
|
429323
|
+
blockingError: "Hook input exceeds substitution budget; refusing to verify on truncated input",
|
|
429324
|
+
command: hook.prompt
|
|
429325
|
+
}
|
|
429326
|
+
};
|
|
429327
|
+
}
|
|
428704
429328
|
logForDebugging3(`Hooks: Processing agent hook with prompt: ${processedPrompt}`);
|
|
428705
429329
|
const userMessage = createUserMessage2({ content: processedPrompt });
|
|
428706
429330
|
const agentMessages = [userMessage];
|
|
@@ -429189,7 +429813,7 @@ import { randomUUID as randomUUID43 } from "crypto";
|
|
|
429189
429813
|
function getSessionEndHookTimeoutMs() {
|
|
429190
429814
|
const raw = process.env.ATLAS_SESSIONEND_HOOKS_TIMEOUT_MS;
|
|
429191
429815
|
const parsed = raw ? parseInt(raw, 10) : NaN;
|
|
429192
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed :
|
|
429816
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : SESSION_END_HOOK_TIMEOUT_MS_DEFAULT2;
|
|
429193
429817
|
}
|
|
429194
429818
|
function executeInBackground({
|
|
429195
429819
|
processId,
|
|
@@ -430225,18 +430849,33 @@ async function* executeHooks({
|
|
|
430225
430849
|
if (jsonInputResult !== undefined) {
|
|
430226
430850
|
return jsonInputResult;
|
|
430227
430851
|
}
|
|
430228
|
-
|
|
430229
|
-
|
|
430230
|
-
} catch (error) {
|
|
430852
|
+
if (exceedsMaxNestingDepth(hookInput)) {
|
|
430853
|
+
const error = Error(`Hook input nesting depth exceeds MAX_HOOK_INPUT_NESTING_DEPTH (${MAX_HOOK_INPUT_NESTING_DEPTH}); refusing to serialize`);
|
|
430231
430854
|
logError3(Error(`Failed to stringify hook ${hookName} input`, { cause: error }));
|
|
430232
430855
|
return jsonInputResult = { ok: false, error };
|
|
430233
430856
|
}
|
|
430857
|
+
const serialized = stringifyWithGetterFallback(hookInput);
|
|
430858
|
+
if (serialized.ok !== true) {
|
|
430859
|
+
logError3(Error(`Failed to stringify hook ${hookName} input`, {
|
|
430860
|
+
cause: serialized.error
|
|
430861
|
+
}));
|
|
430862
|
+
return jsonInputResult = { ok: false, error: serialized.error };
|
|
430863
|
+
}
|
|
430864
|
+
if (serialized.droppedKeys.length > 0) {
|
|
430865
|
+
logForDebugging3(`Hooks: ${hookName}: dropped input keys with throwing getters: ${serialized.droppedKeys.join(", ")}`);
|
|
430866
|
+
}
|
|
430867
|
+
return jsonInputResult = { ok: true, value: serialized.value };
|
|
430234
430868
|
}
|
|
430235
430869
|
const hookPromises = matchingHooks.map(async function* ({ hook, pluginRoot, pluginId, skillRoot }, hookIndex) {
|
|
430870
|
+
if (isReentrantHook(hookEvent, hook, pluginRoot)) {
|
|
430871
|
+
logForDebugging3(`Hooks: ${hookName}: skipping re-entrant execution of ${getHookDisplayText(hook)}`);
|
|
430872
|
+
yield { outcome: "success", hook };
|
|
430873
|
+
return;
|
|
430874
|
+
}
|
|
430236
430875
|
if (hook.type === "callback") {
|
|
430237
430876
|
const callbackTimeoutMs = hook.timeout ? hook.timeout * 1000 : timeoutMs;
|
|
430238
430877
|
const { signal: abortSignal, cleanup } = createCombinedAbortSignal(signal, { timeoutMs: callbackTimeoutMs });
|
|
430239
|
-
yield executeHookCallback({
|
|
430878
|
+
yield runWithHookReentrancy(hookEvent, hook, pluginRoot, () => executeHookCallback({
|
|
430240
430879
|
toolUseID,
|
|
430241
430880
|
hook,
|
|
430242
430881
|
hookEvent,
|
|
@@ -430244,7 +430883,23 @@ async function* executeHooks({
|
|
|
430244
430883
|
signal: abortSignal,
|
|
430245
430884
|
hookIndex,
|
|
430246
430885
|
toolUseContext
|
|
430247
|
-
}).
|
|
430886
|
+
}).catch((error) => {
|
|
430887
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
430888
|
+
return {
|
|
430889
|
+
message: createAttachmentMessage({
|
|
430890
|
+
type: "hook_non_blocking_error",
|
|
430891
|
+
hookName: `${hookEvent}:Callback`,
|
|
430892
|
+
toolUseID,
|
|
430893
|
+
hookEvent,
|
|
430894
|
+
stderr: `Failed to run: ${errorMessage}`,
|
|
430895
|
+
stdout: "",
|
|
430896
|
+
exitCode: 1,
|
|
430897
|
+
command: "callback"
|
|
430898
|
+
}),
|
|
430899
|
+
outcome: "non_blocking_error",
|
|
430900
|
+
hook
|
|
430901
|
+
};
|
|
430902
|
+
}).finally(cleanup));
|
|
430248
430903
|
return;
|
|
430249
430904
|
}
|
|
430250
430905
|
if (hook.type === "function") {
|
|
@@ -430262,7 +430917,7 @@ async function* executeHooks({
|
|
|
430262
430917
|
};
|
|
430263
430918
|
return;
|
|
430264
430919
|
}
|
|
430265
|
-
yield executeFunctionHook({
|
|
430920
|
+
yield runWithHookReentrancy(hookEvent, hook, pluginRoot, () => executeFunctionHook({
|
|
430266
430921
|
hook,
|
|
430267
430922
|
messages,
|
|
430268
430923
|
hookName,
|
|
@@ -430270,7 +430925,7 @@ async function* executeHooks({
|
|
|
430270
430925
|
hookEvent,
|
|
430271
430926
|
timeoutMs,
|
|
430272
430927
|
signal
|
|
430273
|
-
});
|
|
430928
|
+
}));
|
|
430274
430929
|
return;
|
|
430275
430930
|
}
|
|
430276
430931
|
const commandTimeoutMs = hook.timeout ? hook.timeout * 1000 : timeoutMs;
|
|
@@ -430283,6 +430938,7 @@ async function* executeHooks({
|
|
|
430283
430938
|
try {
|
|
430284
430939
|
const jsonInputRes = getJsonInput();
|
|
430285
430940
|
if (!jsonInputRes.ok) {
|
|
430941
|
+
const failClosed = shouldFailClosePluginHook(hookEvent, pluginRoot);
|
|
430286
430942
|
yield {
|
|
430287
430943
|
message: createAttachmentMessage({
|
|
430288
430944
|
type: "hook_error_during_execution",
|
|
@@ -430293,7 +430949,13 @@ async function* executeHooks({
|
|
|
430293
430949
|
command: hookCommand,
|
|
430294
430950
|
durationMs: Date.now() - hookStartMs
|
|
430295
430951
|
}),
|
|
430296
|
-
|
|
430952
|
+
...failClosed ? {
|
|
430953
|
+
blockingError: {
|
|
430954
|
+
blockingError: `Plugin hook input could not be prepared; blocking gated action (fail-closed): ${errorMessage2(jsonInputRes.error)}`,
|
|
430955
|
+
command: hookCommand
|
|
430956
|
+
}
|
|
430957
|
+
} : {},
|
|
430958
|
+
outcome: failClosed ? "blocking" : "non_blocking_error",
|
|
430297
430959
|
hook
|
|
430298
430960
|
};
|
|
430299
430961
|
cleanup();
|
|
@@ -430304,7 +430966,7 @@ async function* executeHooks({
|
|
|
430304
430966
|
if (!toolUseContext) {
|
|
430305
430967
|
throw new Error("ToolUseContext is required for prompt hooks. This is a bug.");
|
|
430306
430968
|
}
|
|
430307
|
-
const promptResult = await execPromptHook(hook, hookName, hookEvent, jsonInput, abortSignal, toolUseContext, messages, toolUseID);
|
|
430969
|
+
const promptResult = await runWithHookReentrancy(hookEvent, hook, pluginRoot, () => execPromptHook(hook, hookName, hookEvent, jsonInput, abortSignal, toolUseContext, messages, toolUseID));
|
|
430308
430970
|
if (promptResult.message?.type === "attachment") {
|
|
430309
430971
|
const att = promptResult.message.attachment;
|
|
430310
430972
|
if (att.type === "hook_success" || att.type === "hook_non_blocking_error") {
|
|
@@ -430323,7 +430985,7 @@ async function* executeHooks({
|
|
|
430323
430985
|
if (!messages) {
|
|
430324
430986
|
throw new Error("Messages are required for agent hooks. This is a bug.");
|
|
430325
430987
|
}
|
|
430326
|
-
const agentResult = await execAgentHook(hook, hookName, hookEvent, jsonInput, abortSignal, toolUseContext, toolUseID, messages, "agent_type" in hookInput ? hookInput.agent_type : undefined);
|
|
430988
|
+
const agentResult = await runWithHookReentrancy(hookEvent, hook, pluginRoot, () => execAgentHook(hook, hookName, hookEvent, jsonInput, abortSignal, toolUseContext, toolUseID, messages, "agent_type" in hookInput ? hookInput.agent_type : undefined));
|
|
430327
430989
|
if (agentResult.message?.type === "attachment") {
|
|
430328
430990
|
const att = agentResult.message.attachment;
|
|
430329
430991
|
if (att.type === "hook_success" || att.type === "hook_non_blocking_error") {
|
|
@@ -430337,7 +430999,7 @@ async function* executeHooks({
|
|
|
430337
430999
|
}
|
|
430338
431000
|
if (hook.type === "http") {
|
|
430339
431001
|
emitHookStarted(hookId, hookName, hookEvent);
|
|
430340
|
-
const httpResult = await execHttpHook(hook, hookEvent, jsonInput, signal);
|
|
431002
|
+
const httpResult = await runWithHookReentrancy(hookEvent, hook, pluginRoot, () => execHttpHook(hook, hookEvent, jsonInput, signal));
|
|
430341
431003
|
cleanup?.();
|
|
430342
431004
|
if (httpResult.aborted) {
|
|
430343
431005
|
emitHookResponse({
|
|
@@ -430465,7 +431127,7 @@ async function* executeHooks({
|
|
|
430465
431127
|
return;
|
|
430466
431128
|
}
|
|
430467
431129
|
emitHookStarted(hookId, hookName, hookEvent);
|
|
430468
|
-
const result = await execCommandHook(hook, hookEvent, hookName, jsonInput, abortSignal, hookId, hookIndex, pluginRoot, pluginId, skillRoot, forceSyncExecution, boundRequestPrompt);
|
|
431130
|
+
const result = await runWithHookReentrancy(hookEvent, hook, pluginRoot, () => execCommandHook(hook, hookEvent, hookName, jsonInput, abortSignal, hookId, hookIndex, pluginRoot, pluginId, skillRoot, forceSyncExecution, boundRequestPrompt));
|
|
430469
431131
|
cleanup?.();
|
|
430470
431132
|
const durationMs = Date.now() - hookStartMs;
|
|
430471
431133
|
if (result.backgrounded) {
|
|
@@ -430711,7 +431373,7 @@ async function* executeHooks({
|
|
|
430711
431373
|
cancelled: 0
|
|
430712
431374
|
};
|
|
430713
431375
|
let permissionBehavior;
|
|
430714
|
-
for await (const result of all2(hookPromises)) {
|
|
431376
|
+
for await (const result of all2(hookPromises, MAX_HOOK_CONCURRENCY)) {
|
|
430715
431377
|
outcomes[result.outcome]++;
|
|
430716
431378
|
if (result.terminalSequence) {
|
|
430717
431379
|
try {
|
|
@@ -430901,20 +431563,46 @@ async function executeHooksOutsideREPL({
|
|
|
430901
431563
|
const pluginHookCounts = getPluginHookCounts(userHooks);
|
|
430902
431564
|
const hookTypeCounts = getHookTypeCounts(userHooks);
|
|
430903
431565
|
}
|
|
430904
|
-
|
|
430905
|
-
|
|
430906
|
-
|
|
430907
|
-
|
|
430908
|
-
|
|
430909
|
-
|
|
431566
|
+
if (exceedsMaxNestingDepth(hookInput)) {
|
|
431567
|
+
const message = `Hook input nesting depth exceeds MAX_HOOK_INPUT_NESTING_DEPTH (${MAX_HOOK_INPUT_NESTING_DEPTH}); refusing to run hooks`;
|
|
431568
|
+
logForDebugging3(`Hooks: ${hookName}: ${message}`);
|
|
431569
|
+
return matchingHooks.map(({ hook, pluginRoot }) => ({
|
|
431570
|
+
command: getHookDisplayText(hook),
|
|
431571
|
+
succeeded: false,
|
|
431572
|
+
output: message,
|
|
431573
|
+
blocked: shouldFailClosePluginHook(hookEvent, pluginRoot)
|
|
431574
|
+
}));
|
|
431575
|
+
}
|
|
431576
|
+
const serialized = stringifyWithGetterFallback(hookInput);
|
|
431577
|
+
if (serialized.ok !== true) {
|
|
431578
|
+
logError3(serialized.error);
|
|
431579
|
+
return matchingHooks.map(({ hook, pluginRoot }) => ({
|
|
431580
|
+
command: getHookDisplayText(hook),
|
|
431581
|
+
succeeded: false,
|
|
431582
|
+
output: `Failed to serialize hook input: ${errorMessage2(serialized.error)}`,
|
|
431583
|
+
blocked: shouldFailClosePluginHook(hookEvent, pluginRoot)
|
|
431584
|
+
}));
|
|
430910
431585
|
}
|
|
430911
|
-
|
|
431586
|
+
if (serialized.droppedKeys.length > 0) {
|
|
431587
|
+
logForDebugging3(`Hooks: ${hookName}: dropped input keys with throwing getters: ${serialized.droppedKeys.join(", ")}`);
|
|
431588
|
+
}
|
|
431589
|
+
const jsonInput = serialized.value;
|
|
431590
|
+
const hookTasks = matchingHooks.map(({ hook, pluginRoot, pluginId }, hookIndex) => async () => {
|
|
431591
|
+
if (isReentrantHook(hookEvent, hook, pluginRoot)) {
|
|
431592
|
+
logForDebugging3(`Hooks: ${hookName}: skipping re-entrant execution of ${getHookDisplayText(hook)}`);
|
|
431593
|
+
return {
|
|
431594
|
+
command: getHookDisplayText(hook),
|
|
431595
|
+
succeeded: true,
|
|
431596
|
+
output: "Skipped: re-entrant hook execution (already running in this call chain)",
|
|
431597
|
+
blocked: false
|
|
431598
|
+
};
|
|
431599
|
+
}
|
|
430912
431600
|
if (hook.type === "callback") {
|
|
430913
431601
|
const callbackTimeoutMs = hook.timeout ? hook.timeout * 1000 : timeoutMs;
|
|
430914
431602
|
const { signal: abortSignal, cleanup } = createCombinedAbortSignal(signal, { timeoutMs: callbackTimeoutMs });
|
|
430915
431603
|
try {
|
|
430916
431604
|
const toolUseID = randomUUID43();
|
|
430917
|
-
const json = await hook.callback(hookInput, toolUseID, abortSignal, hookIndex);
|
|
431605
|
+
const json = await runWithHookReentrancy(hookEvent, hook, pluginRoot, () => hook.callback(hookInput, toolUseID, abortSignal, hookIndex));
|
|
430918
431606
|
cleanup?.();
|
|
430919
431607
|
if (isAsyncHookJSONOutput(json)) {
|
|
430920
431608
|
logForDebugging3(`${hookName} [callback] returned async response, returning empty output`);
|
|
@@ -430973,7 +431661,7 @@ async function executeHooksOutsideREPL({
|
|
|
430973
431661
|
}
|
|
430974
431662
|
if (hook.type === "http") {
|
|
430975
431663
|
try {
|
|
430976
|
-
const httpResult = await execHttpHook(hook, hookEvent, jsonInput, signal);
|
|
431664
|
+
const httpResult = await runWithHookReentrancy(hookEvent, hook, pluginRoot, () => execHttpHook(hook, hookEvent, jsonInput, signal));
|
|
430977
431665
|
if (httpResult.aborted) {
|
|
430978
431666
|
logForDebugging3(`${hookName} [${hook.url}] cancelled`);
|
|
430979
431667
|
return {
|
|
@@ -431024,7 +431712,7 @@ async function executeHooksOutsideREPL({
|
|
|
431024
431712
|
const commandTimeoutMs = hook.timeout ? hook.timeout * 1000 : timeoutMs;
|
|
431025
431713
|
const { signal: abortSignal, cleanup } = createCombinedAbortSignal(signal, { timeoutMs: commandTimeoutMs });
|
|
431026
431714
|
try {
|
|
431027
|
-
const result = await execCommandHook(hook, hookEvent, hookName, jsonInput, abortSignal, randomUUID43(), hookIndex, pluginRoot, pluginId);
|
|
431715
|
+
const result = await runWithHookReentrancy(hookEvent, hook, pluginRoot, () => execCommandHook(hook, hookEvent, hookName, jsonInput, abortSignal, randomUUID43(), hookIndex, pluginRoot, pluginId));
|
|
431028
431716
|
cleanup?.();
|
|
431029
431717
|
if (result.aborted) {
|
|
431030
431718
|
logForDebugging3(`${hookName} [${hook.command}] cancelled`);
|
|
@@ -431068,7 +431756,7 @@ async function executeHooksOutsideREPL({
|
|
|
431068
431756
|
};
|
|
431069
431757
|
}
|
|
431070
431758
|
});
|
|
431071
|
-
return await
|
|
431759
|
+
return await runWithConcurrencyLimit(hookTasks, MAX_HOOK_CONCURRENCY);
|
|
431072
431760
|
}
|
|
431073
431761
|
async function* executePermissionDeniedHooks(toolName, toolUseID, toolInput, reason, toolUseContext, permissionMode, signal, timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS) {
|
|
431074
431762
|
const appState = toolUseContext.getAppState();
|
|
@@ -431868,7 +432556,7 @@ function getHookDefinitionsForTelemetry(matchedHooks) {
|
|
|
431868
432556
|
return { type: "unknown" };
|
|
431869
432557
|
});
|
|
431870
432558
|
}
|
|
431871
|
-
var TOOL_HOOK_EXECUTION_TIMEOUT_MS,
|
|
432559
|
+
var TOOL_HOOK_EXECUTION_TIMEOUT_MS, SESSION_END_HOOK_TIMEOUT_MS_DEFAULT2 = 1500;
|
|
431872
432560
|
var init_hooks7 = __esm(() => {
|
|
431873
432561
|
init_file();
|
|
431874
432562
|
init_ShellCommand2();
|
|
@@ -431901,12 +432589,16 @@ var init_hooks7 = __esm(() => {
|
|
|
431901
432589
|
init_permissionRuleParser2();
|
|
431902
432590
|
init_log5();
|
|
431903
432591
|
init_combinedAbortSignal();
|
|
432592
|
+
init_hookInputMaterialize();
|
|
432593
|
+
init_hookReentrancy();
|
|
432594
|
+
init_hookFailClosed();
|
|
431904
432595
|
init_AsyncHookRegistry();
|
|
431905
432596
|
init_messageQueueManager();
|
|
431906
432597
|
init_messages3();
|
|
431907
432598
|
init_hookEvents2();
|
|
431908
432599
|
init_attachments();
|
|
431909
432600
|
init_generators();
|
|
432601
|
+
init_engine();
|
|
431910
432602
|
init_Tool();
|
|
431911
432603
|
init_execPromptHook();
|
|
431912
432604
|
init_execAgentHook();
|
|
@@ -440987,7 +441679,21 @@ function getDestructiveCommandWarning2(command) {
|
|
|
440987
441679
|
}
|
|
440988
441680
|
return null;
|
|
440989
441681
|
}
|
|
440990
|
-
|
|
441682
|
+
function isStrictInlineShellRmPromptEnabled(env = process.env) {
|
|
441683
|
+
return env[STRICT_INLINE_SHELL_RM_PROMPT_ENV] === "1";
|
|
441684
|
+
}
|
|
441685
|
+
function getStrictInlineShellRmWarning(command) {
|
|
441686
|
+
if (STRICT_CONCAT_RM_RE.test(command)) {
|
|
441687
|
+
return STRICT_CONCAT_RM_WARNING;
|
|
441688
|
+
}
|
|
441689
|
+
for (const re of STRICT_SCRIPT_INVOCATION_RES) {
|
|
441690
|
+
if (re.test(command)) {
|
|
441691
|
+
return STRICT_SCRIPT_WARNING;
|
|
441692
|
+
}
|
|
441693
|
+
}
|
|
441694
|
+
return null;
|
|
441695
|
+
}
|
|
441696
|
+
var DESTRUCTIVE_PATTERNS, STRICT_INLINE_SHELL_RM_PROMPT_ENV = "ATLAS_STRICT_INLINE_SHELL_RM_PROMPT", STRICT_CONCAT_RM_RE, STRICT_SCRIPT_INVOCATION_RES, STRICT_CONCAT_RM_WARNING = "Note: may remove files via a non-literal rm invocation", STRICT_SCRIPT_WARNING = "Note: runs a shell script whose contents are not inspected";
|
|
440991
441697
|
var init_destructiveCommandWarning2 = __esm(() => {
|
|
440992
441698
|
DESTRUCTIVE_PATTERNS = [
|
|
440993
441699
|
{
|
|
@@ -441055,6 +441761,13 @@ var init_destructiveCommandWarning2 = __esm(() => {
|
|
|
441055
441761
|
warning: "Note: may destroy Terraform infrastructure"
|
|
441056
441762
|
}
|
|
441057
441763
|
];
|
|
441764
|
+
STRICT_CONCAT_RM_RE = /\brm\s+(?:-[a-zA-Z]*[rRf]|--recursive|--force)/;
|
|
441765
|
+
STRICT_SCRIPT_INVOCATION_RES = [
|
|
441766
|
+
/(^|[;&|\n]\s*)(?:[^\s;&|]*\/)?(?:bash|zsh|dash|ksh|sh)\b/,
|
|
441767
|
+
/(^|[;&|\n]\s*)source\s+\S/,
|
|
441768
|
+
/(^|[;&|\n]\s*)\.[ \t]*\S/,
|
|
441769
|
+
/(^|[;&|\n]\s*)\S+\.sh\b/
|
|
441770
|
+
];
|
|
441058
441771
|
});
|
|
441059
441772
|
|
|
441060
441773
|
// src/tui/utils/shell/specPrefix.ts
|
|
@@ -445115,7 +445828,7 @@ function BashPermissionRequestInner({
|
|
|
445115
445828
|
sandboxingEnabled: sandboxingEnabled_0,
|
|
445116
445829
|
isSandboxed: isSandboxed_0
|
|
445117
445830
|
} = import_react193.useMemo(() => {
|
|
445118
|
-
const destructiveWarning = getFeatureValue_CACHED_MAY_BE_STALE("atlas_destructive_command_warning", false) ? getDestructiveCommandWarning2(command) : null;
|
|
445831
|
+
const destructiveWarning = getFeatureValue_CACHED_MAY_BE_STALE("atlas_destructive_command_warning", false) ? getDestructiveCommandWarning2(command) ?? (isStrictInlineShellRmPromptEnabled() ? getStrictInlineShellRmWarning(command) : null) : null;
|
|
445119
445832
|
const sandboxingEnabled = getSandboxManager().isSandboxingEnabled();
|
|
445120
445833
|
const isSandboxed = sandboxingEnabled && shouldUseSandbox2(toolUseConfirm.input);
|
|
445121
445834
|
return {
|
|
@@ -470075,41 +470788,28 @@ async function processUserInput({
|
|
|
470075
470788
|
if (mode === "prompt" && inputString !== null && !isMeta) {
|
|
470076
470789
|
setUserInputOnProcessing?.(inputString);
|
|
470077
470790
|
}
|
|
470078
|
-
queryCheckpoint("query_process_user_input_base_start");
|
|
470079
470791
|
const appState = context.getAppState();
|
|
470080
|
-
const result = await processUserInputBase(input, mode, setToolJSX, context, pastedContents, ideSelection, messages, uuid, isAlreadyProcessing, querySource, canUseTool, appState.toolPermissionContext.mode, skipSlashCommands, bridgeOrigin, isMeta, skipAttachments, preExpansionInput);
|
|
470081
|
-
queryCheckpoint("query_process_user_input_base_end");
|
|
470082
|
-
if (!result.shouldQuery) {
|
|
470083
|
-
return result;
|
|
470084
|
-
}
|
|
470085
470792
|
queryCheckpoint("query_hooks_start");
|
|
470086
470793
|
const inputMessage = getContentText(input) || "";
|
|
470794
|
+
let hookBlockingMessage = null;
|
|
470795
|
+
let hookStopped = false;
|
|
470796
|
+
let hookStopReason;
|
|
470797
|
+
const hookMessages = [];
|
|
470087
470798
|
for await (const hookResult of executeUserPromptSubmitHooks(inputMessage, appState.toolPermissionContext.mode, context, context.requestPrompt)) {
|
|
470088
470799
|
if (hookResult.message?.type === "progress") {
|
|
470089
470800
|
continue;
|
|
470090
470801
|
}
|
|
470091
470802
|
if (hookResult.blockingError) {
|
|
470092
|
-
|
|
470093
|
-
|
|
470094
|
-
messages: [
|
|
470095
|
-
createSystemMessage(`${blockingMessage}
|
|
470096
|
-
|
|
470097
|
-
Original prompt: ${input}`, "warning")
|
|
470098
|
-
],
|
|
470099
|
-
shouldQuery: false,
|
|
470100
|
-
allowedTools: result.allowedTools
|
|
470101
|
-
};
|
|
470803
|
+
hookBlockingMessage = getUserPromptSubmitHookBlockingMessage(hookResult.blockingError);
|
|
470804
|
+
break;
|
|
470102
470805
|
}
|
|
470103
470806
|
if (hookResult.preventContinuation) {
|
|
470104
|
-
|
|
470105
|
-
|
|
470106
|
-
|
|
470107
|
-
}));
|
|
470108
|
-
result.shouldQuery = false;
|
|
470109
|
-
return result;
|
|
470807
|
+
hookStopped = true;
|
|
470808
|
+
hookStopReason = hookResult.stopReason;
|
|
470809
|
+
continue;
|
|
470110
470810
|
}
|
|
470111
470811
|
if (hookResult.additionalContexts && hookResult.additionalContexts.length > 0) {
|
|
470112
|
-
|
|
470812
|
+
hookMessages.push(createAttachmentMessage({
|
|
470113
470813
|
type: "hook_additional_context",
|
|
470114
470814
|
content: hookResult.additionalContexts.map(applyTruncation),
|
|
470115
470815
|
hookName: "UserPromptSubmit",
|
|
@@ -470123,7 +470823,7 @@ Original prompt: ${input}`, "warning")
|
|
|
470123
470823
|
if (!hookResult.message.attachment.content) {
|
|
470124
470824
|
break;
|
|
470125
470825
|
}
|
|
470126
|
-
|
|
470826
|
+
hookMessages.push({
|
|
470127
470827
|
...hookResult.message,
|
|
470128
470828
|
attachment: {
|
|
470129
470829
|
...hookResult.message.attachment,
|
|
@@ -470132,12 +470832,38 @@ Original prompt: ${input}`, "warning")
|
|
|
470132
470832
|
});
|
|
470133
470833
|
break;
|
|
470134
470834
|
default:
|
|
470135
|
-
|
|
470835
|
+
hookMessages.push(hookResult.message);
|
|
470136
470836
|
break;
|
|
470137
470837
|
}
|
|
470138
470838
|
}
|
|
470139
470839
|
}
|
|
470140
470840
|
queryCheckpoint("query_hooks_end");
|
|
470841
|
+
if (hookBlockingMessage !== null) {
|
|
470842
|
+
return {
|
|
470843
|
+
messages: [
|
|
470844
|
+
createSystemMessage(`${hookBlockingMessage}
|
|
470845
|
+
|
|
470846
|
+
Original prompt: ${input}`, "warning")
|
|
470847
|
+
],
|
|
470848
|
+
shouldQuery: false,
|
|
470849
|
+
allowedTools: []
|
|
470850
|
+
};
|
|
470851
|
+
}
|
|
470852
|
+
queryCheckpoint("query_process_user_input_base_start");
|
|
470853
|
+
const result = await processUserInputBase(input, mode, setToolJSX, context, pastedContents, ideSelection, messages, uuid, isAlreadyProcessing, querySource, canUseTool, appState.toolPermissionContext.mode, skipSlashCommands, bridgeOrigin, isMeta, skipAttachments, preExpansionInput);
|
|
470854
|
+
queryCheckpoint("query_process_user_input_base_end");
|
|
470855
|
+
if (hookStopped && result.shouldQuery) {
|
|
470856
|
+
const message = hookStopReason ? `Operation stopped by hook: ${hookStopReason}` : "Operation stopped by hook";
|
|
470857
|
+
result.messages.push(createUserMessage2({
|
|
470858
|
+
content: message
|
|
470859
|
+
}));
|
|
470860
|
+
result.shouldQuery = false;
|
|
470861
|
+
return result;
|
|
470862
|
+
}
|
|
470863
|
+
if (!result.shouldQuery) {
|
|
470864
|
+
return result;
|
|
470865
|
+
}
|
|
470866
|
+
result.messages.push(...hookMessages);
|
|
470141
470867
|
return result;
|
|
470142
470868
|
}
|
|
470143
470869
|
function applyTruncation(content) {
|