wave-agent-sdk 0.19.4 → 0.19.5
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/managers/aiManager.d.ts +1 -0
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +57 -0
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +6 -0
- package/dist/tools/grepTool.d.ts.map +1 -1
- package/dist/tools/grepTool.js +23 -1
- package/dist/types/hooks.d.ts +19 -0
- package/dist/types/hooks.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/managers/aiManager.ts +69 -0
- package/src/services/hook.ts +7 -0
- package/src/tools/grepTool.ts +25 -1
- package/src/types/hooks.ts +29 -0
|
@@ -96,6 +96,7 @@ export declare class AIManager {
|
|
|
96
96
|
getIsCompacting(): boolean;
|
|
97
97
|
setIsCompacting(isCompacting: boolean): void;
|
|
98
98
|
private get subagentManager();
|
|
99
|
+
private get cronManager();
|
|
99
100
|
private get skillManager();
|
|
100
101
|
sendAIMessage(options?: {
|
|
101
102
|
recursionDepth?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiManager.d.ts","sourceRoot":"","sources":["../../src/managers/aiManager.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,KAAK,EAGN,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"aiManager.d.ts","sourceRoot":"","sources":["../../src/managers/aiManager.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,KAAK,EAGN,MAAM,mBAAmB,CAAC;AAoB3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAwDlD,MAAM,WAAW,kBAAkB;IACjC,uBAAuB,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,SAAS;IA2BlB,OAAO,CAAC,SAAS;IA1BZ,SAAS,EAAE,OAAO,CAAS;IAClC,OAAO,CAAC,eAAe,CAAgC;IACvD,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,OAAO,CAAC,mBAAmB,CAAgC;IAC3D,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,YAAY,CAAC,CAA2B;IAChD,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,6BAA6B,CAAa;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,gFAAgF;IAChF,OAAO,CAAC,aAAa,CAGjB;IACJ,4EAA4E;IACrE,kBAAkB,CAAC,EACtB,MAAM,GACN,MAAM,GACN,UAAU,GACV;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;gBAI3C,SAAS,EAAE,SAAS,EAC5B,OAAO,EAAE,gBAAgB;IAY3B,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,aAAa,GAIxB;IAED,OAAO,KAAK,WAAW,GAItB;IAED,OAAO,KAAK,qBAAqB,GAEhC;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,gBAAgB,GAM3B;IAED,OAAO,KAAK,iBAAiB,GAE5B;IAED,OAAO,KAAK,WAAW,GAMtB;IAED,OAAO,KAAK,oBAAoB,GAE/B;IAGM,gBAAgB,IAAI,aAAa;IAIjC,cAAc,IAAI,WAAW;IA6B7B,iBAAiB,IAAI,MAAM;IAI3B,WAAW,IAAI,MAAM,GAAG,SAAS;IAIjC,oBAAoB,IAAI,OAAO;IAI/B,UAAU,IAAI,MAAM;IAIpB,kBAAkB,IAAI,MAAM;IAInC;;;OAGG;IACI,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAKpC,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAI/D,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,SAAS,CAAqB;IAEtC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;YA+CjB,wBAAwB;IAsB/B,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAUtC,cAAc,IAAI,IAAI;IAuB7B,OAAO,CAAC,qBAAqB;YAuBf,6BAA6B;IAsC3C;;;OAGG;IACU,mBAAmB,CAC9B,OAAO,GAAE;QACP,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,WAAW,CAAC,EAAE,WAAW,CAAC;KACtB,GACL,OAAO,CAAC,IAAI,CAAC;IA0KhB;;;OAGG;YACW,uBAAuB;IAwH9B,eAAe,IAAI,OAAO;IAI1B,eAAe,CAAC,YAAY,EAAE,OAAO,GAAG,IAAI;IAOnD,OAAO,KAAK,eAAe,GAE1B;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,YAAY,GAEvB;IAEY,aAAa,CACxB,OAAO,GAAE;QACP,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,oEAAoE;QACpE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;KACf,GACL,OAAO,CAAC,IAAI,CAAC;IAqqBhB;;;;OAIG;YACW,gBAAgB;IAwG9B;;;OAGG;YACW,eAAe;IAqM7B;;;OAGG;YACW,sBAAsB;IAsEpC;;OAEG;YACW,uBAAuB;CA2DtC"}
|
|
@@ -12,6 +12,42 @@ import { recoverTruncatedJson } from "../utils/stringUtils.js";
|
|
|
12
12
|
import { logger } from "../utils/globalLogger.js";
|
|
13
13
|
import { startInteractionSpan, endInteractionSpan, startLLMRequestSpan, endLLMRequestSpan, resetTracingState, } from "../telemetry/sessionTracing.js";
|
|
14
14
|
import { logOTelEvent } from "../telemetry/events.js";
|
|
15
|
+
// Truncate text to `max` chars and append a "… [+N chars]" marker when exceeded.
|
|
16
|
+
// Used for background_tasks description/command fields (≤1000 chars per spec FR-063).
|
|
17
|
+
function truncateWithMarker(text, max) {
|
|
18
|
+
if (text.length <= max)
|
|
19
|
+
return text;
|
|
20
|
+
return text.slice(0, max) + `… [+${text.length - max} chars]`;
|
|
21
|
+
}
|
|
22
|
+
// Map a BackgroundTask (from BackgroundTaskManager) to the Stop hook's
|
|
23
|
+
// background_tasks array element shape (aligned with Claude Code v2.1.145+).
|
|
24
|
+
// Conditional fields are populated based on task type:
|
|
25
|
+
// - shell: `command`
|
|
26
|
+
// - subagent: `agent_type` (looked up via SubagentManager by subagentId)
|
|
27
|
+
// - workflow: `name` (extracted from "Workflow: <name>" description)
|
|
28
|
+
function mapBackgroundTask(task, subagentManager) {
|
|
29
|
+
const base = {
|
|
30
|
+
id: task.id,
|
|
31
|
+
type: task.type,
|
|
32
|
+
status: task.status,
|
|
33
|
+
description: truncateWithMarker(task.description ?? "", 1000),
|
|
34
|
+
};
|
|
35
|
+
if (task.type === "shell") {
|
|
36
|
+
return { ...base, command: truncateWithMarker(task.command ?? "", 1000) };
|
|
37
|
+
}
|
|
38
|
+
if (task.type === "subagent") {
|
|
39
|
+
const instance = subagentManager
|
|
40
|
+
?.getActiveInstances()
|
|
41
|
+
.find((i) => i.subagentId === task.subagentId);
|
|
42
|
+
return { ...base, agent_type: instance?.subagentType ?? "" };
|
|
43
|
+
}
|
|
44
|
+
// workflow
|
|
45
|
+
const prefix = "Workflow: ";
|
|
46
|
+
const name = task.description?.startsWith(prefix)
|
|
47
|
+
? task.description.slice(prefix.length)
|
|
48
|
+
: (task.description ?? "");
|
|
49
|
+
return { ...base, name };
|
|
50
|
+
}
|
|
15
51
|
export class AIManager {
|
|
16
52
|
// Service overrides
|
|
17
53
|
constructor(container, options) {
|
|
@@ -499,6 +535,9 @@ export class AIManager {
|
|
|
499
535
|
get subagentManager() {
|
|
500
536
|
return this.container.get("SubagentManager");
|
|
501
537
|
}
|
|
538
|
+
get cronManager() {
|
|
539
|
+
return this.container.get("CronManager");
|
|
540
|
+
}
|
|
502
541
|
get skillManager() {
|
|
503
542
|
return this.container.get("SkillManager");
|
|
504
543
|
}
|
|
@@ -1033,6 +1072,22 @@ export class AIManager {
|
|
|
1033
1072
|
try {
|
|
1034
1073
|
// Use "SubagentStop" hook name when triggered by a subagent, otherwise use "Stop"
|
|
1035
1074
|
const hookName = this.subagentType ? "SubagentStop" : "Stop";
|
|
1075
|
+
// For main-agent Stop events, snapshot running background tasks and
|
|
1076
|
+
// session cron jobs so the hook can decide whether to block stopping.
|
|
1077
|
+
// SubagentStop does not include these fields (per spec FR-065).
|
|
1078
|
+
const backgroundTasks = hookName === "Stop"
|
|
1079
|
+
? (this.backgroundTaskManager?.getAllTasks() ?? [])
|
|
1080
|
+
.filter((t) => t.status === "running")
|
|
1081
|
+
.map((t) => mapBackgroundTask(t, this.subagentManager))
|
|
1082
|
+
: undefined;
|
|
1083
|
+
const sessionCrons = hookName === "Stop"
|
|
1084
|
+
? (this.cronManager?.listJobs() ?? []).map((j) => ({
|
|
1085
|
+
id: j.id,
|
|
1086
|
+
schedule: j.cron,
|
|
1087
|
+
recurring: j.recurring,
|
|
1088
|
+
prompt: j.prompt,
|
|
1089
|
+
}))
|
|
1090
|
+
: undefined;
|
|
1036
1091
|
const context = {
|
|
1037
1092
|
event: hookName,
|
|
1038
1093
|
projectDir: this.getWorkdir(),
|
|
@@ -1041,6 +1096,8 @@ export class AIManager {
|
|
|
1041
1096
|
transcriptPath: this.messageManager.getTranscriptPath(),
|
|
1042
1097
|
cwd: this.getWorkdir(),
|
|
1043
1098
|
subagentType: this.subagentType, // Include subagent type in hook context
|
|
1099
|
+
backgroundTasks, // Stop-only: running background tasks snapshot
|
|
1100
|
+
sessionCrons, // Stop-only: session cron jobs snapshot
|
|
1044
1101
|
// Stop hooks don't need toolName, toolInput, toolResponse, or userPrompt
|
|
1045
1102
|
env: Object.fromEntries(Object.entries(process.env).filter((e) => e[1] !== undefined)), // Include environment variables
|
|
1046
1103
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/services/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAElC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/services/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAElC,MAAM,mBAAmB,CAAC;AA8G3B;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA6I9B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAchC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAMhC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBtD"}
|
package/dist/services/hook.js
CHANGED
|
@@ -83,6 +83,12 @@ async function buildHookJsonInput(context) {
|
|
|
83
83
|
jsonInput.end_source = context.endSource;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
+
// Add background_tasks and session_crons for Stop events only (not SubagentStop).
|
|
87
|
+
// Fields are always present for Stop (empty arrays when nothing in flight).
|
|
88
|
+
if (context.event === "Stop") {
|
|
89
|
+
jsonInput.background_tasks = context.backgroundTasks ?? [];
|
|
90
|
+
jsonInput.session_crons = context.sessionCrons ?? [];
|
|
91
|
+
}
|
|
86
92
|
return jsonInput;
|
|
87
93
|
}
|
|
88
94
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grepTool.d.ts","sourceRoot":"","sources":["../../src/tools/grepTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"grepTool.d.ts","sourceRoot":"","sources":["../../src/tools/grepTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAsBtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA0TtB,CAAC"}
|
package/dist/tools/grepTool.js
CHANGED
|
@@ -2,6 +2,17 @@ import { spawn } from "child_process";
|
|
|
2
2
|
import { rgPath } from "../utils/ripgrep.js";
|
|
3
3
|
import { getDisplayPath } from "../utils/path.js";
|
|
4
4
|
import { GREP_TOOL_NAME, BASH_TOOL_NAME, AGENT_TOOL_NAME, } from "../constants/tools.js";
|
|
5
|
+
// Version control system directories to exclude from searches.
|
|
6
|
+
// These are excluded automatically because they create noise in search results.
|
|
7
|
+
// Mirrors Claude Code's VCS_DIRECTORIES_TO_EXCLUDE.
|
|
8
|
+
const VCS_DIRECTORIES_TO_EXCLUDE = [
|
|
9
|
+
".git",
|
|
10
|
+
".svn",
|
|
11
|
+
".hg",
|
|
12
|
+
".bzr",
|
|
13
|
+
".jj",
|
|
14
|
+
".sl",
|
|
15
|
+
];
|
|
5
16
|
/**
|
|
6
17
|
* Grep tool plugin - powerful search tool based on ripgrep
|
|
7
18
|
*/
|
|
@@ -119,7 +130,18 @@ export const grepTool = {
|
|
|
119
130
|
}
|
|
120
131
|
try {
|
|
121
132
|
const workdir = context.workdir;
|
|
122
|
-
const rgArgs = [
|
|
133
|
+
const rgArgs = [
|
|
134
|
+
"--color=never",
|
|
135
|
+
"--max-columns=500",
|
|
136
|
+
// Search hidden files/directories by default (aligns with Claude Code).
|
|
137
|
+
// --hidden does NOT disable .gitignore; only --no-ignore would.
|
|
138
|
+
"--hidden",
|
|
139
|
+
];
|
|
140
|
+
// Exclude VCS directories to avoid noise from version control metadata.
|
|
141
|
+
// --hidden above would otherwise traverse .git/.svn/etc.
|
|
142
|
+
for (const dir of VCS_DIRECTORIES_TO_EXCLUDE) {
|
|
143
|
+
rgArgs.push("--glob", `!${dir}`);
|
|
144
|
+
}
|
|
123
145
|
// Set output mode
|
|
124
146
|
if (outputMode === "files_with_matches") {
|
|
125
147
|
rgArgs.push("-l");
|
package/dist/types/hooks.d.ts
CHANGED
|
@@ -79,6 +79,23 @@ export interface HookJsonInput {
|
|
|
79
79
|
end_source?: SessionEndSource;
|
|
80
80
|
compact_instructions?: string;
|
|
81
81
|
compact_summary?: string;
|
|
82
|
+
background_tasks?: BackgroundTaskInfo[];
|
|
83
|
+
session_crons?: SessionCronInfo[];
|
|
84
|
+
}
|
|
85
|
+
export interface BackgroundTaskInfo {
|
|
86
|
+
id: string;
|
|
87
|
+
type: "shell" | "subagent" | "workflow";
|
|
88
|
+
status: string;
|
|
89
|
+
description: string;
|
|
90
|
+
command?: string;
|
|
91
|
+
agent_type?: string;
|
|
92
|
+
name?: string;
|
|
93
|
+
}
|
|
94
|
+
export interface SessionCronInfo {
|
|
95
|
+
id: string;
|
|
96
|
+
schedule: string;
|
|
97
|
+
recurring: boolean;
|
|
98
|
+
prompt: string;
|
|
82
99
|
}
|
|
83
100
|
export interface ExtendedHookExecutionContext extends HookExecutionContext {
|
|
84
101
|
sessionId?: string;
|
|
@@ -97,6 +114,8 @@ export interface ExtendedHookExecutionContext extends HookExecutionContext {
|
|
|
97
114
|
endSource?: SessionEndSource;
|
|
98
115
|
compactInstructions?: string;
|
|
99
116
|
compactSummary?: string;
|
|
117
|
+
backgroundTasks?: BackgroundTaskInfo[];
|
|
118
|
+
sessionCrons?: SessionCronInfo[];
|
|
100
119
|
}
|
|
101
120
|
export interface HookEnvironment {
|
|
102
121
|
WAVE_PROJECT_DIR: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -26,8 +26,10 @@ import { ChatCompletionMessageFunctionToolCall } from "openai/resources.js";
|
|
|
26
26
|
|
|
27
27
|
import type { HookManager } from "./hookManager.js";
|
|
28
28
|
import type { ExtendedHookExecutionContext } from "../types/hooks.js";
|
|
29
|
+
import type { BackgroundTaskInfo, SessionCronInfo } from "../types/hooks.js";
|
|
29
30
|
import type { PermissionManager } from "./permissionManager.js";
|
|
30
31
|
import type { SubagentManager } from "./subagentManager.js";
|
|
32
|
+
import type { CronManager } from "./cronManager.js";
|
|
31
33
|
import type { SkillManager } from "./skillManager.js";
|
|
32
34
|
import { buildSystemPrompt } from "../prompts/index.js";
|
|
33
35
|
import {
|
|
@@ -49,6 +51,47 @@ import {
|
|
|
49
51
|
resetTracingState,
|
|
50
52
|
} from "../telemetry/sessionTracing.js";
|
|
51
53
|
import { logOTelEvent } from "../telemetry/events.js";
|
|
54
|
+
import type { BackgroundTask } from "../types/processes.js";
|
|
55
|
+
|
|
56
|
+
// Truncate text to `max` chars and append a "… [+N chars]" marker when exceeded.
|
|
57
|
+
// Used for background_tasks description/command fields (≤1000 chars per spec FR-063).
|
|
58
|
+
function truncateWithMarker(text: string, max: number): string {
|
|
59
|
+
if (text.length <= max) return text;
|
|
60
|
+
return text.slice(0, max) + `… [+${text.length - max} chars]`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Map a BackgroundTask (from BackgroundTaskManager) to the Stop hook's
|
|
64
|
+
// background_tasks array element shape (aligned with Claude Code v2.1.145+).
|
|
65
|
+
// Conditional fields are populated based on task type:
|
|
66
|
+
// - shell: `command`
|
|
67
|
+
// - subagent: `agent_type` (looked up via SubagentManager by subagentId)
|
|
68
|
+
// - workflow: `name` (extracted from "Workflow: <name>" description)
|
|
69
|
+
function mapBackgroundTask(
|
|
70
|
+
task: BackgroundTask,
|
|
71
|
+
subagentManager: SubagentManager | undefined,
|
|
72
|
+
): BackgroundTaskInfo {
|
|
73
|
+
const base: BackgroundTaskInfo = {
|
|
74
|
+
id: task.id,
|
|
75
|
+
type: task.type,
|
|
76
|
+
status: task.status,
|
|
77
|
+
description: truncateWithMarker(task.description ?? "", 1000),
|
|
78
|
+
};
|
|
79
|
+
if (task.type === "shell") {
|
|
80
|
+
return { ...base, command: truncateWithMarker(task.command ?? "", 1000) };
|
|
81
|
+
}
|
|
82
|
+
if (task.type === "subagent") {
|
|
83
|
+
const instance = subagentManager
|
|
84
|
+
?.getActiveInstances()
|
|
85
|
+
.find((i) => i.subagentId === task.subagentId);
|
|
86
|
+
return { ...base, agent_type: instance?.subagentType ?? "" };
|
|
87
|
+
}
|
|
88
|
+
// workflow
|
|
89
|
+
const prefix = "Workflow: ";
|
|
90
|
+
const name = task.description?.startsWith(prefix)
|
|
91
|
+
? task.description.slice(prefix.length)
|
|
92
|
+
: (task.description ?? "");
|
|
93
|
+
return { ...base, name };
|
|
94
|
+
}
|
|
52
95
|
|
|
53
96
|
export interface AIManagerCallbacks {
|
|
54
97
|
onCompactionStateChange?: (isCompacting: boolean) => void;
|
|
@@ -734,6 +777,10 @@ export class AIManager {
|
|
|
734
777
|
return this.container.get<SubagentManager>("SubagentManager");
|
|
735
778
|
}
|
|
736
779
|
|
|
780
|
+
private get cronManager(): CronManager | undefined {
|
|
781
|
+
return this.container.get<CronManager>("CronManager");
|
|
782
|
+
}
|
|
783
|
+
|
|
737
784
|
private get skillManager(): SkillManager | undefined {
|
|
738
785
|
return this.container.get<SkillManager>("SkillManager");
|
|
739
786
|
}
|
|
@@ -1435,6 +1482,26 @@ export class AIManager {
|
|
|
1435
1482
|
// Use "SubagentStop" hook name when triggered by a subagent, otherwise use "Stop"
|
|
1436
1483
|
const hookName = this.subagentType ? "SubagentStop" : "Stop";
|
|
1437
1484
|
|
|
1485
|
+
// For main-agent Stop events, snapshot running background tasks and
|
|
1486
|
+
// session cron jobs so the hook can decide whether to block stopping.
|
|
1487
|
+
// SubagentStop does not include these fields (per spec FR-065).
|
|
1488
|
+
const backgroundTasks: BackgroundTaskInfo[] | undefined =
|
|
1489
|
+
hookName === "Stop"
|
|
1490
|
+
? (this.backgroundTaskManager?.getAllTasks() ?? [])
|
|
1491
|
+
.filter((t) => t.status === "running")
|
|
1492
|
+
.map((t) => mapBackgroundTask(t, this.subagentManager))
|
|
1493
|
+
: undefined;
|
|
1494
|
+
|
|
1495
|
+
const sessionCrons: SessionCronInfo[] | undefined =
|
|
1496
|
+
hookName === "Stop"
|
|
1497
|
+
? (this.cronManager?.listJobs() ?? []).map((j) => ({
|
|
1498
|
+
id: j.id,
|
|
1499
|
+
schedule: j.cron,
|
|
1500
|
+
recurring: j.recurring,
|
|
1501
|
+
prompt: j.prompt,
|
|
1502
|
+
}))
|
|
1503
|
+
: undefined;
|
|
1504
|
+
|
|
1438
1505
|
const context: ExtendedHookExecutionContext = {
|
|
1439
1506
|
event: hookName,
|
|
1440
1507
|
projectDir: this.getWorkdir(),
|
|
@@ -1443,6 +1510,8 @@ export class AIManager {
|
|
|
1443
1510
|
transcriptPath: this.messageManager.getTranscriptPath(),
|
|
1444
1511
|
cwd: this.getWorkdir(),
|
|
1445
1512
|
subagentType: this.subagentType, // Include subagent type in hook context
|
|
1513
|
+
backgroundTasks, // Stop-only: running background tasks snapshot
|
|
1514
|
+
sessionCrons, // Stop-only: session cron jobs snapshot
|
|
1446
1515
|
// Stop hooks don't need toolName, toolInput, toolResponse, or userPrompt
|
|
1447
1516
|
env: Object.fromEntries(
|
|
1448
1517
|
Object.entries(process.env).filter((e) => e[1] !== undefined),
|
package/src/services/hook.ts
CHANGED
|
@@ -113,6 +113,13 @@ async function buildHookJsonInput(
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
// Add background_tasks and session_crons for Stop events only (not SubagentStop).
|
|
117
|
+
// Fields are always present for Stop (empty arrays when nothing in flight).
|
|
118
|
+
if (context.event === "Stop") {
|
|
119
|
+
jsonInput.background_tasks = context.backgroundTasks ?? [];
|
|
120
|
+
jsonInput.session_crons = context.sessionCrons ?? [];
|
|
121
|
+
}
|
|
122
|
+
|
|
116
123
|
return jsonInput;
|
|
117
124
|
}
|
|
118
125
|
|
package/src/tools/grepTool.ts
CHANGED
|
@@ -8,6 +8,18 @@ import {
|
|
|
8
8
|
AGENT_TOOL_NAME,
|
|
9
9
|
} from "../constants/tools.js";
|
|
10
10
|
|
|
11
|
+
// Version control system directories to exclude from searches.
|
|
12
|
+
// These are excluded automatically because they create noise in search results.
|
|
13
|
+
// Mirrors Claude Code's VCS_DIRECTORIES_TO_EXCLUDE.
|
|
14
|
+
const VCS_DIRECTORIES_TO_EXCLUDE = [
|
|
15
|
+
".git",
|
|
16
|
+
".svn",
|
|
17
|
+
".hg",
|
|
18
|
+
".bzr",
|
|
19
|
+
".jj",
|
|
20
|
+
".sl",
|
|
21
|
+
] as const;
|
|
22
|
+
|
|
11
23
|
/**
|
|
12
24
|
* Grep tool plugin - powerful search tool based on ripgrep
|
|
13
25
|
*/
|
|
@@ -144,7 +156,19 @@ export const grepTool: ToolPlugin = {
|
|
|
144
156
|
|
|
145
157
|
try {
|
|
146
158
|
const workdir = context.workdir;
|
|
147
|
-
const rgArgs: string[] = [
|
|
159
|
+
const rgArgs: string[] = [
|
|
160
|
+
"--color=never",
|
|
161
|
+
"--max-columns=500",
|
|
162
|
+
// Search hidden files/directories by default (aligns with Claude Code).
|
|
163
|
+
// --hidden does NOT disable .gitignore; only --no-ignore would.
|
|
164
|
+
"--hidden",
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
// Exclude VCS directories to avoid noise from version control metadata.
|
|
168
|
+
// --hidden above would otherwise traverse .git/.svn/etc.
|
|
169
|
+
for (const dir of VCS_DIRECTORIES_TO_EXCLUDE) {
|
|
170
|
+
rgArgs.push("--glob", `!${dir}`);
|
|
171
|
+
}
|
|
148
172
|
|
|
149
173
|
// Set output mode
|
|
150
174
|
if (outputMode === "files_with_matches") {
|
package/src/types/hooks.ts
CHANGED
|
@@ -196,6 +196,33 @@ export interface HookJsonInput {
|
|
|
196
196
|
end_source?: SessionEndSource; // Present for SessionEnd events
|
|
197
197
|
compact_instructions?: string; // Present for PreCompact events
|
|
198
198
|
compact_summary?: string; // Present for PostCompact events
|
|
199
|
+
background_tasks?: BackgroundTaskInfo[]; // Present for Stop events: running background tasks snapshot
|
|
200
|
+
session_crons?: SessionCronInfo[]; // Present for Stop events: session-scoped cron jobs snapshot
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Describes one in-flight background task in the Stop hook input.
|
|
204
|
+
// Aligned with Claude Code (v2.1.145+) background_tasks array element schema.
|
|
205
|
+
// Conditional fields are populated based on `type`:
|
|
206
|
+
// - "shell": `command` is set
|
|
207
|
+
// - "subagent": `agent_type` is set
|
|
208
|
+
// - "workflow": `name` is set
|
|
209
|
+
export interface BackgroundTaskInfo {
|
|
210
|
+
id: string;
|
|
211
|
+
type: "shell" | "subagent" | "workflow";
|
|
212
|
+
status: string;
|
|
213
|
+
description: string; // Capped at 1000 chars with "… [+N chars]" marker
|
|
214
|
+
command?: string; // Present only for shell tasks (≤1000 chars)
|
|
215
|
+
agent_type?: string; // Present only for subagent tasks
|
|
216
|
+
name?: string; // Present only for workflow tasks
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Describes one session-scoped cron job in the Stop hook input.
|
|
220
|
+
// Aligned with Claude Code (v2.1.145+) session_crons array element schema.
|
|
221
|
+
export interface SessionCronInfo {
|
|
222
|
+
id: string;
|
|
223
|
+
schedule: string; // Cron expression
|
|
224
|
+
recurring: boolean;
|
|
225
|
+
prompt: string;
|
|
199
226
|
}
|
|
200
227
|
|
|
201
228
|
// Extended context interface for passing additional data to hook executor
|
|
@@ -216,6 +243,8 @@ export interface ExtendedHookExecutionContext extends HookExecutionContext {
|
|
|
216
243
|
endSource?: SessionEndSource; // Session end source (SessionEnd only)
|
|
217
244
|
compactInstructions?: string; // Custom instructions for PreCompact
|
|
218
245
|
compactSummary?: string; // Summary text for PostCompact
|
|
246
|
+
backgroundTasks?: BackgroundTaskInfo[]; // Running background tasks snapshot (Stop only)
|
|
247
|
+
sessionCrons?: SessionCronInfo[]; // Session-scoped cron jobs snapshot (Stop only)
|
|
219
248
|
}
|
|
220
249
|
|
|
221
250
|
// Environment variables injected into hook processes
|