@cnwenf/occ 2.1.314 → 2.1.315
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 +338 -133
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
globalThis.MACRO={"VERSION":"2.1.
|
|
2
|
+
globalThis.MACRO={"VERSION":"2.1.315","BINARY_NAME":"occ","BUILD_TIME":"2026-08-28T20:42:08.546Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
|
|
3
3
|
// @bun
|
|
4
4
|
var __create = Object.create;
|
|
5
5
|
var __getProtoOf = Object.getPrototypeOf;
|
|
@@ -231222,6 +231222,7 @@ async function loadAgentFromFile(filePath, pluginName, namespace, sourceName, pl
|
|
|
231222
231222
|
}
|
|
231223
231223
|
const isolationRaw = frontmatter.isolation;
|
|
231224
231224
|
const isolation = isolationRaw === "worktree" ? "worktree" : undefined;
|
|
231225
|
+
const cacheTtl = extractAgentCacheTtl(frontmatter);
|
|
231225
231226
|
const effortRaw = frontmatter.effort;
|
|
231226
231227
|
const effort = effortRaw !== undefined ? parseEffortValue(effortRaw) : undefined;
|
|
231227
231228
|
if (effortRaw !== undefined && effort === undefined) {
|
|
@@ -231274,7 +231275,8 @@ async function loadAgentFromFile(filePath, pluginName, namespace, sourceName, pl
|
|
|
231274
231275
|
...memory ? { memory } : {},
|
|
231275
231276
|
...isolation ? { isolation } : {},
|
|
231276
231277
|
...effort !== undefined ? { effort } : {},
|
|
231277
|
-
...maxTurns !== undefined ? { maxTurns } : {}
|
|
231278
|
+
...maxTurns !== undefined ? { maxTurns } : {},
|
|
231279
|
+
...cacheTtl !== undefined ? { cacheTtl } : {}
|
|
231278
231280
|
};
|
|
231279
231281
|
} catch (error52) {
|
|
231280
231282
|
logForDebugging(`Failed to load agent from ${filePath}: ${error52}`, {
|
|
@@ -231291,6 +231293,7 @@ var init_loadPluginAgents = __esm(() => {
|
|
|
231291
231293
|
init_memoize();
|
|
231292
231294
|
init_paths();
|
|
231293
231295
|
init_agentMemory();
|
|
231296
|
+
init_loadAgentsDir();
|
|
231294
231297
|
init_prompt3();
|
|
231295
231298
|
init_prompt4();
|
|
231296
231299
|
init_debug();
|
|
@@ -232235,6 +232238,7 @@ __export(exports_loadAgentsDir, {
|
|
|
232235
232238
|
getAgentDefinitionsWithOverrides: () => getAgentDefinitionsWithOverrides,
|
|
232236
232239
|
getActiveAgentsFromList: () => getActiveAgentsFromList,
|
|
232237
232240
|
filterAgentsByMcpRequirements: () => filterAgentsByMcpRequirements,
|
|
232241
|
+
extractAgentCacheTtl: () => extractAgentCacheTtl,
|
|
232238
232242
|
clearAgentDefinitionsCache: () => clearAgentDefinitionsCache
|
|
232239
232243
|
});
|
|
232240
232244
|
import { basename as basename12, dirname as dirname26, resolve as resolve23, join as join51 } from "path";
|
|
@@ -232438,6 +232442,14 @@ function parseAgentsFromJson(agentsJson, source = "flagSettings") {
|
|
|
232438
232442
|
return [];
|
|
232439
232443
|
}
|
|
232440
232444
|
}
|
|
232445
|
+
function extractAgentCacheTtl(frontmatter) {
|
|
232446
|
+
const experimental = frontmatter.experimental;
|
|
232447
|
+
if (typeof experimental !== "object" || experimental === null) {
|
|
232448
|
+
return;
|
|
232449
|
+
}
|
|
232450
|
+
const raw = Object.entries(experimental).find(([key2]) => key2.toLowerCase() === "cachettl")?.[1];
|
|
232451
|
+
return raw === "5m" || raw === "1h" ? raw : undefined;
|
|
232452
|
+
}
|
|
232441
232453
|
function parseAgentFromMarkdown(filePath, baseDir, frontmatter, content, source) {
|
|
232442
232454
|
try {
|
|
232443
232455
|
const agentType = frontmatter["name"];
|
|
@@ -232487,6 +232499,7 @@ function parseAgentFromMarkdown(filePath, baseDir, frontmatter, content, source)
|
|
|
232487
232499
|
logForDebugging(`Agent file ${filePath} has invalid isolation value '${isolationRaw}'. Valid options: ${VALID_ISOLATION_MODES.join(", ")}`);
|
|
232488
232500
|
}
|
|
232489
232501
|
}
|
|
232502
|
+
const cacheTtl = extractAgentCacheTtl(frontmatter);
|
|
232490
232503
|
const effortRaw = frontmatter["effort"];
|
|
232491
232504
|
const parsedEffort = effortRaw !== undefined ? parseEffortValue(effortRaw) : undefined;
|
|
232492
232505
|
if (effortRaw !== undefined && parsedEffort === undefined) {
|
|
@@ -232564,7 +232577,8 @@ function parseAgentFromMarkdown(filePath, baseDir, frontmatter, content, source)
|
|
|
232564
232577
|
...maxTurns !== undefined ? { maxTurns } : {},
|
|
232565
232578
|
...background ? { background } : {},
|
|
232566
232579
|
...memory ? { memory } : {},
|
|
232567
|
-
...isolation ? { isolation } : {}
|
|
232580
|
+
...isolation ? { isolation } : {},
|
|
232581
|
+
...cacheTtl !== undefined ? { cacheTtl } : {}
|
|
232568
232582
|
};
|
|
232569
232583
|
return agentDef;
|
|
232570
232584
|
} catch (error52) {
|
|
@@ -472395,7 +472409,8 @@ async function* runAgent({
|
|
|
472395
472409
|
userContext: resolvedUserContext,
|
|
472396
472410
|
systemContext: resolvedSystemContext,
|
|
472397
472411
|
toolUseContext: agentToolUseContext,
|
|
472398
|
-
forkContextMessages: initialMessages
|
|
472412
|
+
forkContextMessages: initialMessages,
|
|
472413
|
+
...agentDefinition.cacheTtl !== undefined ? { agentCacheTtlOverride: agentDefinition.cacheTtl } : {}
|
|
472399
472414
|
});
|
|
472400
472415
|
}
|
|
472401
472416
|
recordSidechainTranscript(initialMessages, agentId).catch((_err) => logForDebugging(`Failed to record sidechain transcript: ${_err}`));
|
|
@@ -472422,7 +472437,8 @@ async function* runAgent({
|
|
|
472422
472437
|
canUseTool,
|
|
472423
472438
|
toolUseContext: agentToolUseContext,
|
|
472424
472439
|
querySource,
|
|
472425
|
-
maxTurns: maxTurns ?? agentDefinition.maxTurns
|
|
472440
|
+
maxTurns: maxTurns ?? agentDefinition.maxTurns,
|
|
472441
|
+
agentCacheTtlOverride: agentDefinition.cacheTtl
|
|
472426
472442
|
})) {
|
|
472427
472443
|
onQueryProgress?.();
|
|
472428
472444
|
if (message.type === "stream_event" && message.event.type === "message_start" && message.ttftMs != null) {
|
|
@@ -597567,7 +597583,8 @@ async function* queryLoop(params, consumedCommandUuids) {
|
|
|
597567
597583
|
fallbackModel,
|
|
597568
597584
|
querySource,
|
|
597569
597585
|
maxTurns,
|
|
597570
|
-
skipCacheWrite
|
|
597586
|
+
skipCacheWrite,
|
|
597587
|
+
agentCacheTtlOverride
|
|
597571
597588
|
} = params;
|
|
597572
597589
|
const deps = params.deps ?? productionDeps();
|
|
597573
597590
|
let state3 = {
|
|
@@ -597780,6 +597797,7 @@ async function* queryLoop(params, consumedCommandUuids) {
|
|
|
597780
597797
|
effortValue: appState.effortValue,
|
|
597781
597798
|
advisorModel: appState.advisorModel,
|
|
597782
597799
|
skipCacheWrite,
|
|
597800
|
+
agentCacheTtlOverride,
|
|
597783
597801
|
agentId: toolUseContext.agentId,
|
|
597784
597802
|
addNotification: toolUseContext.addNotification,
|
|
597785
597803
|
...params.taskBudget && {
|
|
@@ -599250,7 +599268,8 @@ async function runForkedAgent({
|
|
|
599250
599268
|
userContext,
|
|
599251
599269
|
systemContext,
|
|
599252
599270
|
toolUseContext,
|
|
599253
|
-
forkContextMessages
|
|
599271
|
+
forkContextMessages,
|
|
599272
|
+
agentCacheTtlOverride
|
|
599254
599273
|
} = cacheSafeParams;
|
|
599255
599274
|
const isolatedToolUseContext = createSubagentContext(toolUseContext, overrides);
|
|
599256
599275
|
const initialMessages = [...forkContextMessages, ...promptMessages];
|
|
@@ -599271,7 +599290,8 @@ async function runForkedAgent({
|
|
|
599271
599290
|
querySource,
|
|
599272
599291
|
maxOutputTokensOverride: maxOutputTokens,
|
|
599273
599292
|
maxTurns,
|
|
599274
|
-
skipCacheWrite
|
|
599293
|
+
skipCacheWrite,
|
|
599294
|
+
agentCacheTtlOverride
|
|
599275
599295
|
})) {
|
|
599276
599296
|
if (message.type === "stream_event") {
|
|
599277
599297
|
if ("event" in message && message.event?.type === "message_delta" && message.event.usage) {
|
|
@@ -631305,11 +631325,12 @@ function getPromptCachingEnabled(model) {
|
|
|
631305
631325
|
}
|
|
631306
631326
|
function getCacheControl({
|
|
631307
631327
|
scope,
|
|
631308
|
-
querySource
|
|
631328
|
+
querySource,
|
|
631329
|
+
agentCacheTtlOverride
|
|
631309
631330
|
} = {}) {
|
|
631310
631331
|
return {
|
|
631311
631332
|
type: "ephemeral",
|
|
631312
|
-
...should1hCacheTTL(querySource) && { ttl: "1h" },
|
|
631333
|
+
...should1hCacheTTL(querySource, agentCacheTtlOverride) && { ttl: "1h" },
|
|
631313
631334
|
...scope === "global" && { scope }
|
|
631314
631335
|
};
|
|
631315
631336
|
}
|
|
@@ -631322,7 +631343,7 @@ function isMainThreadQuerySource(querySource) {
|
|
|
631322
631343
|
function parsePromptCacheTtlEnv(value) {
|
|
631323
631344
|
return value === "5m" || value === "1h" ? value : undefined;
|
|
631324
631345
|
}
|
|
631325
|
-
function resolvePromptCacheTtlOverride(querySource) {
|
|
631346
|
+
function resolvePromptCacheTtlOverride(querySource, agentCacheTtlOverride, isUsingOverage = false) {
|
|
631326
631347
|
if (isEnvTruthy(process.env.FORCE_PROMPT_CACHING_5M)) {
|
|
631327
631348
|
return { ttl: "5m", reason: "force_5m_env" };
|
|
631328
631349
|
}
|
|
@@ -631334,16 +631355,21 @@ function resolvePromptCacheTtlOverride(querySource) {
|
|
|
631334
631355
|
const settingTtl = isMainThread ? settings.promptCacheTtl : settings.subagentPromptCacheTtl;
|
|
631335
631356
|
if (settingTtl !== undefined)
|
|
631336
631357
|
return { ttl: settingTtl, reason: "setting" };
|
|
631358
|
+
if (agentCacheTtlOverride !== undefined && !(agentCacheTtlOverride === "1h" && isUsingOverage)) {
|
|
631359
|
+
return { ttl: agentCacheTtlOverride, reason: "agent_frontmatter" };
|
|
631360
|
+
}
|
|
631337
631361
|
if (isEnvTruthy(process.env.ENABLE_PROMPT_CACHING_1H) || getAPIProvider() === "bedrock" && isEnvTruthy(process.env.ENABLE_PROMPT_CACHING_1H_BEDROCK)) {
|
|
631338
631362
|
return { ttl: "1h", reason: "enable_1h_env" };
|
|
631339
631363
|
}
|
|
631340
631364
|
return;
|
|
631341
631365
|
}
|
|
631342
|
-
function resolvePromptCacheTtl(querySource) {
|
|
631343
|
-
const
|
|
631366
|
+
function resolvePromptCacheTtl(querySource, options) {
|
|
631367
|
+
const isSubscriber2 = isClaudeAISubscriber();
|
|
631368
|
+
const isOverage = isSubscriber2 && options?.ignoreOverage !== true && currentLimits.isUsingOverage === true;
|
|
631369
|
+
const override = resolvePromptCacheTtlOverride(querySource, options?.agentCacheTtlOverride, isOverage);
|
|
631344
631370
|
if (override !== undefined)
|
|
631345
631371
|
return override;
|
|
631346
|
-
if (!
|
|
631372
|
+
if (!isSubscriber2 || isOverage) {
|
|
631347
631373
|
return { ttl: "5m", reason: "default" };
|
|
631348
631374
|
}
|
|
631349
631375
|
let allowlist = getPromptCache1hAllowlist();
|
|
@@ -631356,8 +631382,8 @@ function resolvePromptCacheTtl(querySource) {
|
|
|
631356
631382
|
}
|
|
631357
631383
|
return querySourceMatchesPatterns(querySource, allowlist) ? { ttl: "1h", reason: "subscriber" } : { ttl: "5m", reason: "default" };
|
|
631358
631384
|
}
|
|
631359
|
-
function should1hCacheTTL(querySource) {
|
|
631360
|
-
return resolvePromptCacheTtl(querySource).ttl === "1h";
|
|
631385
|
+
function should1hCacheTTL(querySource, agentCacheTtlOverride) {
|
|
631386
|
+
return resolvePromptCacheTtl(querySource, { agentCacheTtlOverride }).ttl === "1h";
|
|
631361
631387
|
}
|
|
631362
631388
|
function configureEffortParams(effortValue, outputConfig, extraBodyParams, betas, model) {
|
|
631363
631389
|
if (!modelSupportsEffort(model) || "effort" in outputConfig) {
|
|
@@ -631448,7 +631474,7 @@ async function verifyApiKey(apiKey, isNonInteractiveSession) {
|
|
|
631448
631474
|
throw error52;
|
|
631449
631475
|
}
|
|
631450
631476
|
}
|
|
631451
|
-
function userMessageToMessageParam(message, addCache = false, enablePromptCaching, querySource) {
|
|
631477
|
+
function userMessageToMessageParam(message, addCache = false, enablePromptCaching, querySource, agentCacheTtlOverride) {
|
|
631452
631478
|
if (addCache) {
|
|
631453
631479
|
if (typeof message.message.content === "string") {
|
|
631454
631480
|
return {
|
|
@@ -631458,7 +631484,10 @@ function userMessageToMessageParam(message, addCache = false, enablePromptCachin
|
|
|
631458
631484
|
type: "text",
|
|
631459
631485
|
text: message.message.content,
|
|
631460
631486
|
...enablePromptCaching && {
|
|
631461
|
-
cache_control: getCacheControl({
|
|
631487
|
+
cache_control: getCacheControl({
|
|
631488
|
+
querySource,
|
|
631489
|
+
agentCacheTtlOverride
|
|
631490
|
+
})
|
|
631462
631491
|
}
|
|
631463
631492
|
}
|
|
631464
631493
|
]
|
|
@@ -631468,7 +631497,12 @@ function userMessageToMessageParam(message, addCache = false, enablePromptCachin
|
|
|
631468
631497
|
role: "user",
|
|
631469
631498
|
content: message.message.content.map((_4, i6) => ({
|
|
631470
631499
|
..._4,
|
|
631471
|
-
...i6 === message.message.content.length - 1 ? enablePromptCaching ? {
|
|
631500
|
+
...i6 === message.message.content.length - 1 ? enablePromptCaching ? {
|
|
631501
|
+
cache_control: getCacheControl({
|
|
631502
|
+
querySource,
|
|
631503
|
+
agentCacheTtlOverride
|
|
631504
|
+
})
|
|
631505
|
+
} : {} : {}
|
|
631472
631506
|
}))
|
|
631473
631507
|
};
|
|
631474
631508
|
}
|
|
@@ -631478,7 +631512,7 @@ function userMessageToMessageParam(message, addCache = false, enablePromptCachin
|
|
|
631478
631512
|
content: Array.isArray(message.message.content) ? [...message.message.content] : message.message.content
|
|
631479
631513
|
};
|
|
631480
631514
|
}
|
|
631481
|
-
function assistantMessageToMessageParam(message, addCache = false, enablePromptCaching, querySource) {
|
|
631515
|
+
function assistantMessageToMessageParam(message, addCache = false, enablePromptCaching, querySource, agentCacheTtlOverride) {
|
|
631482
631516
|
if (addCache) {
|
|
631483
631517
|
if (typeof message.message.content === "string") {
|
|
631484
631518
|
return {
|
|
@@ -631488,7 +631522,10 @@ function assistantMessageToMessageParam(message, addCache = false, enablePromptC
|
|
|
631488
631522
|
type: "text",
|
|
631489
631523
|
text: message.message.content,
|
|
631490
631524
|
...enablePromptCaching && {
|
|
631491
|
-
cache_control: getCacheControl({
|
|
631525
|
+
cache_control: getCacheControl({
|
|
631526
|
+
querySource,
|
|
631527
|
+
agentCacheTtlOverride
|
|
631528
|
+
})
|
|
631492
631529
|
}
|
|
631493
631530
|
}
|
|
631494
631531
|
]
|
|
@@ -631498,7 +631535,12 @@ function assistantMessageToMessageParam(message, addCache = false, enablePromptC
|
|
|
631498
631535
|
role: "assistant",
|
|
631499
631536
|
content: message.message.content.map((_4, i6) => ({
|
|
631500
631537
|
..._4,
|
|
631501
|
-
...i6 === message.message.content.length - 1 && _4.type !== "thinking" && _4.type !== "redacted_thinking" && (feature("CONNECTOR_TEXT") ? !isConnectorTextBlock(_4) : true) ? enablePromptCaching ? {
|
|
631538
|
+
...i6 === message.message.content.length - 1 && _4.type !== "thinking" && _4.type !== "redacted_thinking" && (feature("CONNECTOR_TEXT") ? !isConnectorTextBlock(_4) : true) ? enablePromptCaching ? {
|
|
631539
|
+
cache_control: getCacheControl({
|
|
631540
|
+
querySource,
|
|
631541
|
+
agentCacheTtlOverride
|
|
631542
|
+
})
|
|
631543
|
+
} : {} : {}
|
|
631502
631544
|
}))
|
|
631503
631545
|
};
|
|
631504
631546
|
}
|
|
@@ -631720,7 +631762,7 @@ async function* queryModel(messages, systemPrompt, thinkingConfig, tools, signal
|
|
|
631720
631762
|
queryCheckpoint("query_tool_schema_build_start");
|
|
631721
631763
|
const isAgenticQuery = options.querySource.startsWith("repl_main_thread") || options.querySource.startsWith("agent:") || options.querySource === "sdk" || options.querySource === "hook_agent" || options.querySource === "verification_agent";
|
|
631722
631764
|
const betas = getMergedBetas(options.model, { isAgenticQuery });
|
|
631723
|
-
if (should1hCacheTTL(options.querySource) && shouldSendExtendedCacheTtlBeta() && !betas.includes(EXTENDED_CACHE_TTL_BETA_HEADER)) {
|
|
631765
|
+
if (should1hCacheTTL(options.querySource, options.agentCacheTtlOverride) && shouldSendExtendedCacheTtlBeta() && !betas.includes(EXTENDED_CACHE_TTL_BETA_HEADER)) {
|
|
631724
631766
|
betas.push(EXTENDED_CACHE_TTL_BETA_HEADER);
|
|
631725
631767
|
}
|
|
631726
631768
|
if (isAdvisorEnabled()) {
|
|
@@ -631872,7 +631914,8 @@ ${deferredToolList}
|
|
|
631872
631914
|
const enablePromptCaching = options.enablePromptCaching ?? getPromptCachingEnabled(options.model);
|
|
631873
631915
|
const system = buildSystemPromptBlocks(systemPrompt, enablePromptCaching, {
|
|
631874
631916
|
skipGlobalCacheForSystemPrompt: needsToolBasedCacheMarker,
|
|
631875
|
-
querySource: options.querySource
|
|
631917
|
+
querySource: options.querySource,
|
|
631918
|
+
agentCacheTtlOverride: options.agentCacheTtlOverride
|
|
631876
631919
|
});
|
|
631877
631920
|
const useBetas = betas.length > 0;
|
|
631878
631921
|
const extraToolSchemas = [...options.extraToolSchemas ?? []];
|
|
@@ -632027,7 +632070,7 @@ ${deferredToolList}
|
|
|
632027
632070
|
lastRequestBetas = betasParams;
|
|
632028
632071
|
return {
|
|
632029
632072
|
model: normalizeModelStringForAPI(options.model),
|
|
632030
|
-
messages: addCacheBreakpoints(messagesForAPI, enablePromptCaching2, options.querySource, useCachedMC, consumedCacheEdits, consumedPinnedEdits, options.skipCacheWrite),
|
|
632073
|
+
messages: addCacheBreakpoints(messagesForAPI, enablePromptCaching2, options.querySource, useCachedMC, consumedCacheEdits, consumedPinnedEdits, options.skipCacheWrite, options.agentCacheTtlOverride),
|
|
632031
632074
|
system,
|
|
632032
632075
|
tools: allTools,
|
|
632033
632076
|
tool_choice: options.toolChoice,
|
|
@@ -632881,7 +632924,7 @@ function accumulateUsage(totalUsage, messageUsage) {
|
|
|
632881
632924
|
function isToolResultBlock2(block) {
|
|
632882
632925
|
return block !== null && typeof block === "object" && "type" in block && block.type === "tool_result" && "tool_use_id" in block;
|
|
632883
632926
|
}
|
|
632884
|
-
function addCacheBreakpoints(messages, enablePromptCaching, querySource, useCachedMC = false, newCacheEdits, pinnedEdits, skipCacheWrite = false) {
|
|
632927
|
+
function addCacheBreakpoints(messages, enablePromptCaching, querySource, useCachedMC = false, newCacheEdits, pinnedEdits, skipCacheWrite = false, agentCacheTtlOverride) {
|
|
632885
632928
|
logEvent2("tengu_api_cache_breakpoints", {
|
|
632886
632929
|
totalMessageCount: messages.length,
|
|
632887
632930
|
cachingEnabled: enablePromptCaching,
|
|
@@ -632891,9 +632934,9 @@ function addCacheBreakpoints(messages, enablePromptCaching, querySource, useCach
|
|
|
632891
632934
|
const result = messages.map((msg, index2) => {
|
|
632892
632935
|
const addCache = index2 === markerIndex;
|
|
632893
632936
|
if (msg.type === "user") {
|
|
632894
|
-
return userMessageToMessageParam(msg, addCache, enablePromptCaching, querySource);
|
|
632937
|
+
return userMessageToMessageParam(msg, addCache, enablePromptCaching, querySource, agentCacheTtlOverride);
|
|
632895
632938
|
}
|
|
632896
|
-
return assistantMessageToMessageParam(msg, addCache, enablePromptCaching, querySource);
|
|
632939
|
+
return assistantMessageToMessageParam(msg, addCache, enablePromptCaching, querySource, agentCacheTtlOverride);
|
|
632897
632940
|
});
|
|
632898
632941
|
if (!useCachedMC) {
|
|
632899
632942
|
return result;
|
|
@@ -632984,7 +633027,8 @@ function buildSystemPromptBlocks(systemPrompt, enablePromptCaching, options) {
|
|
|
632984
633027
|
...enablePromptCaching && block.cacheScope !== null && {
|
|
632985
633028
|
cache_control: getCacheControl({
|
|
632986
633029
|
scope: block.cacheScope,
|
|
632987
|
-
querySource: options?.querySource
|
|
633030
|
+
querySource: options?.querySource,
|
|
633031
|
+
agentCacheTtlOverride: options?.agentCacheTtlOverride
|
|
632988
633032
|
})
|
|
632989
633033
|
}
|
|
632990
633034
|
};
|
|
@@ -727155,21 +727199,6 @@ var init_execPromptHook = __esm(() => {
|
|
|
727155
727199
|
init_hookHelpers();
|
|
727156
727200
|
});
|
|
727157
727201
|
|
|
727158
|
-
// src/utils/hooks/hookExit2Block.ts
|
|
727159
|
-
function exit2BlockReason(params) {
|
|
727160
|
-
const { status: status2, validationError, hasJson, stderr, command: command11 } = params;
|
|
727161
|
-
if (status2 !== 2) {
|
|
727162
|
-
return null;
|
|
727163
|
-
}
|
|
727164
|
-
if (hasJson && !validationError) {
|
|
727165
|
-
return null;
|
|
727166
|
-
}
|
|
727167
|
-
return {
|
|
727168
|
-
blockingError: `[${command11}]: ${stderr || "No stderr output"}`,
|
|
727169
|
-
command: command11
|
|
727170
|
-
};
|
|
727171
|
-
}
|
|
727172
|
-
|
|
727173
727202
|
// src/utils/hooks/execAgentHook.ts
|
|
727174
727203
|
import { randomUUID as randomUUID40 } from "crypto";
|
|
727175
727204
|
async function execAgentHook(hook, hookName, hookEvent, jsonInput, signal, toolUseContext, toolUseID, _messages, agentName) {
|
|
@@ -727774,10 +727803,16 @@ var init_execMcpToolHook = __esm(() => {
|
|
|
727774
727803
|
// src/utils/hooks.ts
|
|
727775
727804
|
var exports_hooks2 = {};
|
|
727776
727805
|
__export(exports_hooks2, {
|
|
727806
|
+
wrapHookErrorWithStderr: () => wrapHookErrorWithStderr,
|
|
727777
727807
|
skipFrontmatterHooksForUntrustedOrigin: () => skipFrontmatterHooksForUntrustedOrigin,
|
|
727778
727808
|
shouldSkipHookDueToTrust: () => shouldSkipHookDueToTrust,
|
|
727779
727809
|
processHookJSONOutput: () => processHookJSONOutput,
|
|
727810
|
+
parseHookOutput: () => parseHookOutput,
|
|
727811
|
+
looksLikeMissingHookScript: () => looksLikeMissingHookScript,
|
|
727780
727812
|
isPerHookCallbackTimeout: () => isPerHookCallbackTimeout,
|
|
727813
|
+
isMultipleJsonDocuments: () => isMultipleJsonDocuments,
|
|
727814
|
+
isAsyncHookAnnouncement: () => isAsyncHookAnnouncement,
|
|
727815
|
+
hookOutputSchemaHint: () => hookOutputSchemaHint,
|
|
727781
727816
|
hookCallbackTimeoutMessage: () => hookCallbackTimeoutMessage,
|
|
727782
727817
|
hasWorktreeCreateHook: () => hasWorktreeCreateHook,
|
|
727783
727818
|
hasInstructionsLoadedHook: () => hasInstructionsLoadedHook,
|
|
@@ -727790,6 +727825,7 @@ __export(exports_hooks2, {
|
|
|
727790
727825
|
getSessionEndHookTimeoutMs: () => getSessionEndHookTimeoutMs,
|
|
727791
727826
|
getPreToolHookBlockingMessage: () => getPreToolHookBlockingMessage,
|
|
727792
727827
|
getMatchingHooks: () => getMatchingHooks,
|
|
727828
|
+
formatHookJsonValidationError: () => formatHookJsonValidationError,
|
|
727793
727829
|
executeWorktreeRemoveHook: () => executeWorktreeRemoveHook,
|
|
727794
727830
|
executeWorktreeCreateHook: () => executeWorktreeCreateHook,
|
|
727795
727831
|
executeUserPromptSubmitHooks: () => executeUserPromptSubmitHooks,
|
|
@@ -727993,6 +728029,109 @@ function getSessionCronsForHookInput() {
|
|
|
727993
728029
|
prompt: capHookString(task.prompt ?? "", HOOK_STRING_CAP)
|
|
727994
728030
|
}));
|
|
727995
728031
|
}
|
|
728032
|
+
function isHookJsonPlainObject(value) {
|
|
728033
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
728034
|
+
}
|
|
728035
|
+
function isHookJsonDiscriminatorIssue(issue2) {
|
|
728036
|
+
const last3 = issue2.path.at(-1);
|
|
728037
|
+
return issue2.code === "invalid_value" && typeof last3 === "string" && HOOK_JSON_DISCRIMINATOR_KEYS.has(last3);
|
|
728038
|
+
}
|
|
728039
|
+
function formatHookJsonIssue(issue2, parentPath) {
|
|
728040
|
+
const path39 = [...parentPath, ...issue2.path];
|
|
728041
|
+
if (issue2.code !== "invalid_union" || (issue2.errors?.length ?? 0) === 0) {
|
|
728042
|
+
return { path: path39, message: issue2.message.replace(/^Invalid input: /, "") };
|
|
728043
|
+
}
|
|
728044
|
+
const errors8 = issue2.errors;
|
|
728045
|
+
const relevant = errors8.find((branch2) => branch2.length > 0 && !branch2.some(isHookJsonDiscriminatorIssue))?.[0];
|
|
728046
|
+
if (relevant) {
|
|
728047
|
+
return formatHookJsonIssue(relevant, path39);
|
|
728048
|
+
}
|
|
728049
|
+
const discriminatorIssues = errors8.flat().filter(isHookJsonDiscriminatorIssue);
|
|
728050
|
+
const first2 = discriminatorIssues[0];
|
|
728051
|
+
if (first2?.code !== "invalid_value") {
|
|
728052
|
+
return { path: path39, message: issue2.message };
|
|
728053
|
+
}
|
|
728054
|
+
const values3 = [
|
|
728055
|
+
...new Set(discriminatorIssues.flatMap((discriminator) => discriminator.code === "invalid_value" ? (discriminator.values ?? []).map((value) => jsonStringify(value)) : []))
|
|
728056
|
+
];
|
|
728057
|
+
const preview = values3.slice(0, 6).join(" | ");
|
|
728058
|
+
return {
|
|
728059
|
+
path: [...path39, ...first2.path],
|
|
728060
|
+
message: `expected one of ${preview}${values3.length > 6 ? " | \u2026" : ""}`
|
|
728061
|
+
};
|
|
728062
|
+
}
|
|
728063
|
+
function formatHookJsonPath(path39) {
|
|
728064
|
+
return path39.map(String).join(".") || "(root)";
|
|
728065
|
+
}
|
|
728066
|
+
function formatHookJsonValidationError(parsed, issues) {
|
|
728067
|
+
const hookSpecificOutput = isHookJsonPlainObject(parsed) ? parsed.hookSpecificOutput : undefined;
|
|
728068
|
+
const formatted = issues.map((issue2) => formatHookJsonIssue(issue2, []));
|
|
728069
|
+
const first2 = formatted[0];
|
|
728070
|
+
let primary = first2 ? `${formatHookJsonPath(first2.path)}: ${first2.message}` : "unknown error";
|
|
728071
|
+
if (isHookJsonPlainObject(hookSpecificOutput) && !("hookEventName" in hookSpecificOutput)) {
|
|
728072
|
+
primary = 'hookSpecificOutput is missing required field "hookEventName"';
|
|
728073
|
+
} else if (isHookJsonPlainObject(hookSpecificOutput) && hookSpecificOutput.hookEventName === "PermissionRequest" && !isHookJsonPlainObject(hookSpecificOutput.decision) && first2?.path[0] === "hookSpecificOutput" && first2.path[1] === "decision") {
|
|
728074
|
+
primary += ' (PermissionRequest decision must be {"behavior": "allow"} or {"behavior": "deny", "message": "..."})';
|
|
728075
|
+
} else if (isHookJsonPlainObject(parsed) && first2?.path.length === 1 && first2.path[0] === "decision" && (parsed.decision === "allow" || parsed.decision === "deny" || parsed.decision === "ask")) {
|
|
728076
|
+
primary += parsed.decision === "ask" ? ' (top-level decision is the legacy approve|block field; for "ask" use hookSpecificOutput.permissionDecision in a PreToolUse hook)' : ` (top-level decision is the legacy approve|block field; for "${parsed.decision}" use hookSpecificOutput.permissionDecision in a PreToolUse hook, or hookSpecificOutput.decision: {"behavior": "${parsed.decision}"} in a PermissionRequest hook)`;
|
|
728077
|
+
}
|
|
728078
|
+
const rest = formatted.slice(1).map((entry) => ` - ${formatHookJsonPath(entry.path)}: ${entry.message}`).join(`
|
|
728079
|
+
`);
|
|
728080
|
+
return `${HOOK_JSON_VALIDATION_ERROR_PREFIX}${primary}${rest ? `
|
|
728081
|
+
${rest}` : ""}
|
|
728082
|
+
|
|
728083
|
+
The hook's output was: ${jsonStringify(parsed, null, 2)}`;
|
|
728084
|
+
}
|
|
728085
|
+
function hookOutputSchemaHint() {
|
|
728086
|
+
return jsonStringify({
|
|
728087
|
+
continue: "boolean (optional)",
|
|
728088
|
+
suppressOutput: "boolean (optional)",
|
|
728089
|
+
stopReason: "string (optional)",
|
|
728090
|
+
decision: '"approve" | "block" (optional)',
|
|
728091
|
+
reason: "string (optional)",
|
|
728092
|
+
systemMessage: "string (optional)",
|
|
728093
|
+
terminalSequence: "string (optional)",
|
|
728094
|
+
hookSpecificOutput: {
|
|
728095
|
+
"for PreToolUse": {
|
|
728096
|
+
hookEventName: '"PreToolUse"',
|
|
728097
|
+
permissionDecision: '"allow" | "deny" | "ask" | "defer" (optional)',
|
|
728098
|
+
permissionDecisionReason: "string (optional)",
|
|
728099
|
+
updatedInput: "object (optional) - Modified tool input to use"
|
|
728100
|
+
},
|
|
728101
|
+
"for PermissionRequest": {
|
|
728102
|
+
hookEventName: '"PermissionRequest"',
|
|
728103
|
+
decision: {
|
|
728104
|
+
"to allow": {
|
|
728105
|
+
behavior: '"allow"',
|
|
728106
|
+
updatedInput: "object (optional) - Modified tool input to use",
|
|
728107
|
+
updatedPermissions: "array (optional) - Permission updates"
|
|
728108
|
+
},
|
|
728109
|
+
"to deny": {
|
|
728110
|
+
behavior: '"deny"',
|
|
728111
|
+
message: "string (optional)",
|
|
728112
|
+
interrupt: "boolean (optional)"
|
|
728113
|
+
}
|
|
728114
|
+
}
|
|
728115
|
+
},
|
|
728116
|
+
"for UserPromptSubmit": {
|
|
728117
|
+
hookEventName: '"UserPromptSubmit"',
|
|
728118
|
+
additionalContext: "string (optional)"
|
|
728119
|
+
},
|
|
728120
|
+
"for PostToolUse": {
|
|
728121
|
+
hookEventName: '"PostToolUse"',
|
|
728122
|
+
additionalContext: "string (optional)"
|
|
728123
|
+
},
|
|
728124
|
+
"for PostToolBatch": {
|
|
728125
|
+
hookEventName: '"PostToolBatch"',
|
|
728126
|
+
additionalContext: "string (optional)"
|
|
728127
|
+
},
|
|
728128
|
+
"for Stop / SubagentStop": {
|
|
728129
|
+
hookEventName: '"Stop" | "SubagentStop"',
|
|
728130
|
+
additionalContext: "string (optional) - Feedback for the model; the conversation continues so the model can act on it"
|
|
728131
|
+
}
|
|
728132
|
+
}
|
|
728133
|
+
}, null, 2);
|
|
728134
|
+
}
|
|
727996
728135
|
function validateHookJson(jsonString) {
|
|
727997
728136
|
const parsed = jsonParse(jsonString);
|
|
727998
728137
|
const validation2 = hookJSONOutputSchema().safeParse(parsed);
|
|
@@ -728000,21 +728139,57 @@ function validateHookJson(jsonString) {
|
|
|
728000
728139
|
logForDebugging("Successfully parsed and validated hook JSON output");
|
|
728001
728140
|
return { json: validation2.data };
|
|
728002
728141
|
}
|
|
728003
|
-
const errors8 = validation2.error.issues.map((err2) => ` - ${err2.path.join(".")}: ${err2.message}`).join(`
|
|
728004
|
-
`);
|
|
728005
728142
|
return {
|
|
728006
|
-
validationError:
|
|
728007
|
-
${errors8}
|
|
728008
|
-
|
|
728009
|
-
The hook's output was: ${jsonStringify(parsed, null, 2)}`
|
|
728143
|
+
validationError: formatHookJsonValidationError(parsed, validation2.error.issues)
|
|
728010
728144
|
};
|
|
728011
728145
|
}
|
|
728146
|
+
function isAsyncHookAnnouncement(stdout) {
|
|
728147
|
+
const firstLine = firstLineOf(stdout).trim();
|
|
728148
|
+
if (!firstLine.startsWith("{")) {
|
|
728149
|
+
return false;
|
|
728150
|
+
}
|
|
728151
|
+
try {
|
|
728152
|
+
const parsed = jsonParse(firstLine);
|
|
728153
|
+
return typeof parsed === "object" && parsed !== null && "async" in parsed && parsed.async === true;
|
|
728154
|
+
} catch {
|
|
728155
|
+
return false;
|
|
728156
|
+
}
|
|
728157
|
+
}
|
|
728158
|
+
function isMultipleJsonDocuments(output2) {
|
|
728159
|
+
const lines2 = output2.split(`
|
|
728160
|
+
`).filter((line) => line.trim() !== "");
|
|
728161
|
+
if (lines2.length < 2) {
|
|
728162
|
+
return false;
|
|
728163
|
+
}
|
|
728164
|
+
return lines2.every((line) => {
|
|
728165
|
+
try {
|
|
728166
|
+
const validation2 = hookJSONOutputSchema().safeParse(jsonParse(line.trim()));
|
|
728167
|
+
return !validation2.success || Object.keys(validation2.data).length === 0;
|
|
728168
|
+
} catch {
|
|
728169
|
+
return false;
|
|
728170
|
+
}
|
|
728171
|
+
});
|
|
728172
|
+
}
|
|
728173
|
+
function wrapHookErrorWithStderr(validationError, exitCode, stderr) {
|
|
728174
|
+
const trimmedStderr = stderr.trim();
|
|
728175
|
+
return exitCode !== 0 && trimmedStderr ? `${validationError}
|
|
728176
|
+
|
|
728177
|
+
Hook exited ${exitCode} with stderr:
|
|
728178
|
+
${trimmedStderr}` : validationError;
|
|
728179
|
+
}
|
|
728180
|
+
function looksLikeMissingHookScript(params) {
|
|
728181
|
+
const { hookEvent, stdout, stderr, pluginId } = params;
|
|
728182
|
+
return (MISSING_SCRIPT_HOOK_EVENTS.has(hookEvent) || Boolean(pluginId) && hookEvent === "UserPromptSubmit") && !stdout.trim() && /no such file|can't open/i.test(stderr);
|
|
728183
|
+
}
|
|
728012
728184
|
function parseHookOutput(stdout) {
|
|
728013
728185
|
const trimmed = stdout.trim();
|
|
728014
728186
|
if (!trimmed.startsWith("{")) {
|
|
728015
728187
|
logForDebugging("Hook output does not start with {, treating as plain text");
|
|
728016
728188
|
return { plainText: stdout };
|
|
728017
728189
|
}
|
|
728190
|
+
if (isAsyncHookAnnouncement(stdout)) {
|
|
728191
|
+
return { json: { async: true } };
|
|
728192
|
+
}
|
|
728018
728193
|
try {
|
|
728019
728194
|
const result = validateHookJson(trimmed);
|
|
728020
728195
|
if ("json" in result) {
|
|
@@ -728023,37 +728198,22 @@ function parseHookOutput(stdout) {
|
|
|
728023
728198
|
const errorMessage3 = `${result.validationError}
|
|
728024
728199
|
|
|
728025
728200
|
Expected schema:
|
|
728026
|
-
${
|
|
728027
|
-
continue: "boolean (optional)",
|
|
728028
|
-
suppressOutput: "boolean (optional)",
|
|
728029
|
-
stopReason: "string (optional)",
|
|
728030
|
-
decision: '"approve" | "block" (optional)',
|
|
728031
|
-
reason: "string (optional)",
|
|
728032
|
-
systemMessage: "string (optional)",
|
|
728033
|
-
permissionDecision: '"allow" | "deny" | "ask" (optional)',
|
|
728034
|
-
hookSpecificOutput: {
|
|
728035
|
-
"for PreToolUse": {
|
|
728036
|
-
hookEventName: '"PreToolUse"',
|
|
728037
|
-
permissionDecision: '"allow" | "deny" | "ask" (optional)',
|
|
728038
|
-
permissionDecisionReason: "string (optional)",
|
|
728039
|
-
updatedInput: "object (optional) - Modified tool input to use"
|
|
728040
|
-
},
|
|
728041
|
-
"for UserPromptSubmit": {
|
|
728042
|
-
hookEventName: '"UserPromptSubmit"',
|
|
728043
|
-
additionalContext: "string (required)",
|
|
728044
|
-
sessionTitle: "string (optional) - Set the session title (same effect as /rename)"
|
|
728045
|
-
},
|
|
728046
|
-
"for PostToolUse": {
|
|
728047
|
-
hookEventName: '"PostToolUse"',
|
|
728048
|
-
additionalContext: "string (optional)"
|
|
728049
|
-
}
|
|
728050
|
-
}
|
|
728051
|
-
}, null, 2)}`;
|
|
728201
|
+
${hookOutputSchemaHint()}`;
|
|
728052
728202
|
logForDebugging(errorMessage3);
|
|
728053
728203
|
return { plainText: stdout, validationError: errorMessage3 };
|
|
728054
728204
|
} catch (e4) {
|
|
728055
|
-
|
|
728056
|
-
|
|
728205
|
+
const parseError = e4 instanceof Error ? e4.message : String(e4);
|
|
728206
|
+
if (!trimmed.endsWith("}")) {
|
|
728207
|
+
logForDebugging(`Hook output starts with { but is not a JSON object, treating as plain text: ${parseError}`);
|
|
728208
|
+
return { plainText: stdout };
|
|
728209
|
+
}
|
|
728210
|
+
if (isMultipleJsonDocuments(trimmed)) {
|
|
728211
|
+
logForDebugging("Hook output is several JSON documents, treating as plain text");
|
|
728212
|
+
return { plainText: stdout };
|
|
728213
|
+
}
|
|
728214
|
+
const errorMessage3 = `Hook output looks like a JSON object but is not valid JSON \u2014 ${parseError}. Emit the payload with a JSON encoder (jq, ConvertTo-Json, json.dumps) rather than string concatenation so backslashes and quotes inside strings are escaped.`;
|
|
728215
|
+
logForDebugging(errorMessage3);
|
|
728216
|
+
return { plainText: stdout, validationError: errorMessage3 };
|
|
728057
728217
|
}
|
|
728058
728218
|
}
|
|
728059
728219
|
function parseHttpHookOutput(body) {
|
|
@@ -729212,7 +729372,7 @@ async function* executeHooks({
|
|
|
729212
729372
|
hookEvent,
|
|
729213
729373
|
output: httpResult.body,
|
|
729214
729374
|
stdout: httpResult.body,
|
|
729215
|
-
stderr:
|
|
729375
|
+
stderr: httpValidationError,
|
|
729216
729376
|
exitCode: httpResult.statusCode,
|
|
729217
729377
|
outcome: "error"
|
|
729218
729378
|
});
|
|
@@ -729222,7 +729382,7 @@ async function* executeHooks({
|
|
|
729222
729382
|
hookName,
|
|
729223
729383
|
toolUseID,
|
|
729224
729384
|
hookEvent,
|
|
729225
|
-
stderr:
|
|
729385
|
+
stderr: httpValidationError,
|
|
729226
729386
|
stdout: httpResult.body,
|
|
729227
729387
|
exitCode: httpResult.statusCode ?? 0,
|
|
729228
729388
|
command: hook.url,
|
|
@@ -729353,43 +729513,16 @@ async function* executeHooks({
|
|
|
729353
729513
|
return;
|
|
729354
729514
|
}
|
|
729355
729515
|
const { json: json2, plainText, validationError } = parseHookOutput(result.stdout);
|
|
729356
|
-
if (validationError) {
|
|
729357
|
-
const
|
|
729358
|
-
status: result.status,
|
|
729359
|
-
validationError,
|
|
729360
|
-
hasJson: !!json2,
|
|
729361
|
-
stderr: result.stderr,
|
|
729362
|
-
command: hookCommand
|
|
729363
|
-
});
|
|
729364
|
-
if (exit2Block) {
|
|
729365
|
-
emitHookResponse({
|
|
729366
|
-
hookId,
|
|
729367
|
-
hookName,
|
|
729368
|
-
hookEvent,
|
|
729369
|
-
output: result.output,
|
|
729370
|
-
stdout: result.stdout,
|
|
729371
|
-
stderr: result.stderr,
|
|
729372
|
-
exitCode: result.status,
|
|
729373
|
-
outcome: "error"
|
|
729374
|
-
});
|
|
729375
|
-
yield {
|
|
729376
|
-
blockingError: {
|
|
729377
|
-
blockingError: exit2Block.blockingError,
|
|
729378
|
-
command: exit2Block.command
|
|
729379
|
-
},
|
|
729380
|
-
outcome: "blocking",
|
|
729381
|
-
hook
|
|
729382
|
-
};
|
|
729383
|
-
return;
|
|
729384
|
-
}
|
|
729516
|
+
if (validationError && result.status !== 2) {
|
|
729517
|
+
const stderr = wrapHookErrorWithStderr(validationError, result.status, result.stderr);
|
|
729385
729518
|
emitHookResponse({
|
|
729386
729519
|
hookId,
|
|
729387
729520
|
hookName,
|
|
729388
729521
|
hookEvent,
|
|
729389
729522
|
output: result.output,
|
|
729390
729523
|
stdout: result.stdout,
|
|
729391
|
-
stderr
|
|
729392
|
-
exitCode:
|
|
729524
|
+
stderr,
|
|
729525
|
+
exitCode: result.status,
|
|
729393
729526
|
outcome: "error"
|
|
729394
729527
|
});
|
|
729395
729528
|
yield {
|
|
@@ -729398,9 +729531,9 @@ async function* executeHooks({
|
|
|
729398
729531
|
hookName,
|
|
729399
729532
|
toolUseID,
|
|
729400
729533
|
hookEvent,
|
|
729401
|
-
stderr
|
|
729534
|
+
stderr,
|
|
729402
729535
|
stdout: result.stdout,
|
|
729403
|
-
exitCode:
|
|
729536
|
+
exitCode: result.status,
|
|
729404
729537
|
command: hookCommand,
|
|
729405
729538
|
durationMs
|
|
729406
729539
|
}),
|
|
@@ -729411,6 +729544,55 @@ async function* executeHooks({
|
|
|
729411
729544
|
}
|
|
729412
729545
|
if (json2) {
|
|
729413
729546
|
if (isAsyncHookJSONOutput(json2)) {
|
|
729547
|
+
if (result.status === 2) {
|
|
729548
|
+
emitHookResponse({
|
|
729549
|
+
hookId,
|
|
729550
|
+
hookName,
|
|
729551
|
+
hookEvent,
|
|
729552
|
+
output: result.output,
|
|
729553
|
+
stdout: result.stdout,
|
|
729554
|
+
stderr: result.stderr,
|
|
729555
|
+
exitCode: result.status,
|
|
729556
|
+
outcome: "error"
|
|
729557
|
+
});
|
|
729558
|
+
yield {
|
|
729559
|
+
blockingError: {
|
|
729560
|
+
blockingError: `[${hook.command}]: ${result.stderr || "No stderr output"}`,
|
|
729561
|
+
command: hook.command
|
|
729562
|
+
},
|
|
729563
|
+
outcome: "blocking",
|
|
729564
|
+
hook
|
|
729565
|
+
};
|
|
729566
|
+
return;
|
|
729567
|
+
}
|
|
729568
|
+
if (result.status !== 0) {
|
|
729569
|
+
emitHookResponse({
|
|
729570
|
+
hookId,
|
|
729571
|
+
hookName,
|
|
729572
|
+
hookEvent,
|
|
729573
|
+
output: result.output,
|
|
729574
|
+
stdout: result.stdout,
|
|
729575
|
+
stderr: result.stderr,
|
|
729576
|
+
exitCode: result.status,
|
|
729577
|
+
outcome: "error"
|
|
729578
|
+
});
|
|
729579
|
+
yield {
|
|
729580
|
+
message: createAttachmentMessage({
|
|
729581
|
+
type: "hook_non_blocking_error",
|
|
729582
|
+
hookName,
|
|
729583
|
+
toolUseID,
|
|
729584
|
+
hookEvent,
|
|
729585
|
+
stderr: `Announced async, then failed with status code ${result.status}: ${result.stderr.trim() || "No stderr output"}`,
|
|
729586
|
+
stdout: result.stdout,
|
|
729587
|
+
exitCode: result.status,
|
|
729588
|
+
command: hookCommand,
|
|
729589
|
+
durationMs
|
|
729590
|
+
}),
|
|
729591
|
+
outcome: "non_blocking_error",
|
|
729592
|
+
hook
|
|
729593
|
+
};
|
|
729594
|
+
return;
|
|
729595
|
+
}
|
|
729414
729596
|
yield {
|
|
729415
729597
|
outcome: "success",
|
|
729416
729598
|
hook
|
|
@@ -729513,6 +729695,39 @@ async function* executeHooks({
|
|
|
729513
729695
|
};
|
|
729514
729696
|
return;
|
|
729515
729697
|
}
|
|
729698
|
+
if (result.status === 2 && looksLikeMissingHookScript({
|
|
729699
|
+
hookEvent,
|
|
729700
|
+
stdout: result.stdout,
|
|
729701
|
+
stderr: result.stderr,
|
|
729702
|
+
pluginId
|
|
729703
|
+
})) {
|
|
729704
|
+
emitHookResponse({
|
|
729705
|
+
hookId,
|
|
729706
|
+
hookName,
|
|
729707
|
+
hookEvent,
|
|
729708
|
+
output: result.output,
|
|
729709
|
+
stdout: result.stdout,
|
|
729710
|
+
stderr: result.stderr,
|
|
729711
|
+
exitCode: result.status,
|
|
729712
|
+
outcome: "error"
|
|
729713
|
+
});
|
|
729714
|
+
yield {
|
|
729715
|
+
message: createAttachmentMessage({
|
|
729716
|
+
type: "hook_non_blocking_error",
|
|
729717
|
+
hookName,
|
|
729718
|
+
toolUseID,
|
|
729719
|
+
hookEvent,
|
|
729720
|
+
stderr: `Hook script appears to be missing \u2014 "${hookCommand}" exited 2 with: ${result.stderr.trim()}. Treating as non-blocking. ${pluginId ? `Run \`/plugin\` to reinstall '${pluginId}' or remove it from settings.` : "If this is a plugin hook, check the plugin install (run /plugin)."}`,
|
|
729721
|
+
stdout: result.stdout,
|
|
729722
|
+
exitCode: result.status,
|
|
729723
|
+
command: hookCommand,
|
|
729724
|
+
durationMs
|
|
729725
|
+
}),
|
|
729726
|
+
outcome: "non_blocking_error",
|
|
729727
|
+
hook
|
|
729728
|
+
};
|
|
729729
|
+
return;
|
|
729730
|
+
}
|
|
729516
729731
|
if (result.status === 2) {
|
|
729517
729732
|
emitHookResponse({
|
|
729518
729733
|
hookId,
|
|
@@ -729960,25 +730175,8 @@ async function executeHooksOutsideREPL({
|
|
|
729960
730175
|
}
|
|
729961
730176
|
logForDebugging(`${hookName} [${hook.command}] completed with status ${result.status}`);
|
|
729962
730177
|
const { json: json2, validationError } = parseHookOutput(result.stdout);
|
|
729963
|
-
if (validationError) {
|
|
729964
|
-
|
|
729965
|
-
status: result.status,
|
|
729966
|
-
validationError,
|
|
729967
|
-
hasJson: !!json2,
|
|
729968
|
-
stderr: result.stderr,
|
|
729969
|
-
command: hook.command
|
|
729970
|
-
});
|
|
729971
|
-
if (exit2Block) {
|
|
729972
|
-
return {
|
|
729973
|
-
command: hook.command,
|
|
729974
|
-
succeeded: false,
|
|
729975
|
-
output: result.stderr || "",
|
|
729976
|
-
blocked: true,
|
|
729977
|
-
watchPaths: undefined,
|
|
729978
|
-
systemMessage: undefined
|
|
729979
|
-
};
|
|
729980
|
-
}
|
|
729981
|
-
throw new Error(validationError);
|
|
730178
|
+
if (validationError && result.status !== 2) {
|
|
730179
|
+
throw new Error(wrapHookErrorWithStderr(validationError, result.status, result.stderr));
|
|
729982
730180
|
}
|
|
729983
730181
|
if (json2 && !isAsyncHookJSONOutput(json2)) {
|
|
729984
730182
|
logForDebugging(`Parsed JSON output from hook: ${jsonStringify(json2)}`, { level: "verbose" });
|
|
@@ -731008,7 +731206,7 @@ async function* executeMessageDisplayHooks(display, getAppState, agentId, signal
|
|
|
731008
731206
|
timeoutMs
|
|
731009
731207
|
});
|
|
731010
731208
|
}
|
|
731011
|
-
var TOOL_HOOK_EXECUTION_TIMEOUT_MS, PRE_TOOL_USE_HOOK_TIMEOUT_MESSAGE = "PreToolUse hook did not respond before its timeout (host client may be unreachable). The tool call was not executed; other configured hooks may not have completed.", SESSION_END_HOOK_TIMEOUT_MS_DEFAULT = 1500, BACKGROUND_TASK_TYPE_LABELS, HOOK_STRING_CAP = 1000, MATCHER_COMMA_HYPHEN_EVENTS;
|
|
731209
|
+
var TOOL_HOOK_EXECUTION_TIMEOUT_MS, PRE_TOOL_USE_HOOK_TIMEOUT_MESSAGE = "PreToolUse hook did not respond before its timeout (host client may be unreachable). The tool call was not executed; other configured hooks may not have completed.", SESSION_END_HOOK_TIMEOUT_MS_DEFAULT = 1500, BACKGROUND_TASK_TYPE_LABELS, HOOK_STRING_CAP = 1000, HOOK_JSON_VALIDATION_ERROR_PREFIX = "Hook JSON output validation failed \u2014 ", HOOK_JSON_DISCRIMINATOR_KEYS, MISSING_SCRIPT_HOOK_EVENTS, MATCHER_COMMA_HYPHEN_EVENTS;
|
|
731012
731210
|
var init_hooks5 = __esm(() => {
|
|
731013
731211
|
init_file();
|
|
731014
731212
|
init_envValidation();
|
|
@@ -731071,6 +731269,13 @@ var init_hooks5 = __esm(() => {
|
|
|
731071
731269
|
dream: "dream",
|
|
731072
731270
|
remote_agent: "cloud session"
|
|
731073
731271
|
};
|
|
731272
|
+
HOOK_JSON_DISCRIMINATOR_KEYS = new Set(["async", "hookEventName", "behavior"]);
|
|
731273
|
+
MISSING_SCRIPT_HOOK_EVENTS = new Set([
|
|
731274
|
+
"Stop",
|
|
731275
|
+
"SubagentStop",
|
|
731276
|
+
"TaskCompleted",
|
|
731277
|
+
"TeammateIdle"
|
|
731278
|
+
]);
|
|
731074
731279
|
MATCHER_COMMA_HYPHEN_EVENTS = new Set([
|
|
731075
731280
|
"PreToolUse",
|
|
731076
731281
|
"PostToolUse",
|