pi-subagents 0.34.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +78 -9
  2. package/README.md +213 -32
  3. package/index.ts +1 -0
  4. package/install.mjs +1 -1
  5. package/package.json +23 -8
  6. package/prompts/review-loop.md +3 -1
  7. package/skills/pi-subagents/SKILL.md +87 -25
  8. package/src/agents/agent-management.ts +82 -15
  9. package/src/agents/agent-serializer.ts +19 -0
  10. package/src/agents/agents.ts +91 -49
  11. package/src/agents/frontmatter.ts +67 -13
  12. package/src/agents/skills.ts +25 -12
  13. package/src/api/background-work.ts +197 -0
  14. package/src/api/delegation.ts +158 -0
  15. package/src/extension/chain-validation.ts +165 -0
  16. package/src/extension/doctor.ts +15 -0
  17. package/src/extension/fanout-child.ts +3 -1
  18. package/src/extension/index.ts +65 -124
  19. package/src/extension/rpc.ts +10 -2
  20. package/src/extension/schemas.ts +18 -14
  21. package/src/extension/steering-notices.ts +35 -0
  22. package/src/extension/tool-description.ts +20 -9
  23. package/src/intercom/intercom-bridge.ts +3 -2
  24. package/src/intercom/native-supervisor-channel.ts +9 -1
  25. package/src/intercom/result-intercom.ts +4 -0
  26. package/src/runs/background/async-execution.ts +293 -44
  27. package/src/runs/background/async-job-tracker.ts +56 -9
  28. package/src/runs/background/async-resume.ts +159 -52
  29. package/src/runs/background/async-status.ts +25 -18
  30. package/src/runs/background/auto-drain.ts +67 -0
  31. package/src/runs/background/chain-root-attachment.ts +16 -8
  32. package/src/runs/background/control-channel.ts +260 -13
  33. package/src/runs/background/fleet-view.ts +23 -2
  34. package/src/runs/background/notify.ts +79 -10
  35. package/src/runs/background/result-watcher.ts +12 -9
  36. package/src/runs/background/run-id-resolver.ts +14 -2
  37. package/src/runs/background/run-status.ts +23 -15
  38. package/src/runs/background/scheduled-runs.ts +3 -0
  39. package/src/runs/background/stale-run-reconciler.ts +32 -10
  40. package/src/runs/background/steering.ts +237 -0
  41. package/src/runs/background/subagent-runner.ts +898 -236
  42. package/src/runs/background/subagent-wait.ts +484 -0
  43. package/src/runs/background/top-level-async.ts +2 -1
  44. package/src/runs/background/wait-config.ts +36 -0
  45. package/src/runs/background/wait-tool.ts +26 -0
  46. package/src/runs/foreground/async-steering-action.ts +230 -0
  47. package/src/runs/foreground/chain-clarify.ts +22 -6
  48. package/src/runs/foreground/chain-execution.ts +50 -32
  49. package/src/runs/foreground/execution.ts +308 -94
  50. package/src/runs/foreground/subagent-executor.ts +592 -268
  51. package/src/runs/shared/acceptance.ts +355 -97
  52. package/src/runs/shared/child-protocol.ts +121 -0
  53. package/src/runs/shared/completion-guard.ts +8 -127
  54. package/src/runs/shared/dynamic-fanout.ts +6 -4
  55. package/src/runs/shared/model-fallback.ts +36 -0
  56. package/src/runs/shared/nested-events.ts +9 -4
  57. package/src/runs/shared/nested-render.ts +4 -1
  58. package/src/runs/shared/parallel-utils.ts +7 -0
  59. package/src/runs/shared/pi-args.ts +34 -7
  60. package/src/runs/shared/pi-spawn.ts +18 -12
  61. package/src/runs/shared/session-lease.ts +279 -0
  62. package/src/runs/shared/single-output.ts +61 -6
  63. package/src/runs/shared/spawn-budget.ts +128 -0
  64. package/src/runs/shared/subagent-control.ts +10 -6
  65. package/src/runs/shared/subagent-prompt-runtime.ts +127 -26
  66. package/src/runs/shared/task-intent.ts +176 -0
  67. package/src/runs/shared/tool-availability.ts +65 -0
  68. package/src/runs/shared/turn-budget.ts +49 -4
  69. package/src/shared/atomic-json.ts +4 -1
  70. package/src/shared/fork-context.ts +28 -3
  71. package/src/shared/model-info.ts +7 -4
  72. package/src/shared/status-format.ts +7 -1
  73. package/src/shared/types.ts +203 -25
  74. package/src/shared/utils.ts +35 -7
  75. package/src/slash/delegation-adapters.ts +457 -0
  76. package/src/slash/delegation-request.ts +103 -0
  77. package/src/slash/prompt-template-bridge.ts +167 -344
  78. package/src/slash/slash-commands.ts +239 -6
  79. package/src/slash/subagents-admin.ts +428 -0
  80. package/src/slash/subagents-editor.ts +86 -0
  81. package/src/tui/fleet.ts +405 -0
  82. package/src/tui/render.ts +90 -16
  83. package/src/watchdog/change-signature.ts +127 -0
  84. package/src/watchdog/child-status.ts +205 -0
  85. package/src/watchdog/emission-guard.ts +123 -0
  86. package/src/watchdog/lsp-diagnostics.ts +532 -0
  87. package/src/watchdog/model-selection.ts +167 -0
  88. package/src/watchdog/register-child.ts +117 -0
  89. package/src/watchdog/register-main.ts +433 -0
  90. package/src/watchdog/render.ts +54 -0
  91. package/src/watchdog/review.ts +293 -0
  92. package/src/watchdog/runtime.ts +712 -0
  93. package/src/watchdog/settings.ts +528 -0
  94. package/src/watchdog/tool-actions.ts +155 -0
  95. package/src/watchdog/turn-delta.ts +161 -0
  96. package/src/watchdog/types.ts +188 -0
  97. package/src/watchdog/warning-format.ts +73 -0
  98. package/src/runs/background/wait.ts +0 -394
@@ -0,0 +1,161 @@
1
+ import { SUBAGENT_WATCHDOG_WARNING_TYPE } from "./types.ts";
2
+
3
+ type MessageLike = {
4
+ role?: string;
5
+ content?: unknown;
6
+ customType?: string;
7
+ toolName?: string;
8
+ name?: string;
9
+ input?: unknown;
10
+ args?: unknown;
11
+ arguments?: unknown;
12
+ error?: unknown;
13
+ isError?: boolean;
14
+ details?: unknown;
15
+ stopReason?: string;
16
+ };
17
+
18
+ export interface WatchdogTurnDeltaInput {
19
+ userPrompt?: string;
20
+ includeUserPrompt?: boolean;
21
+ messages?: unknown[];
22
+ events?: unknown[];
23
+ finalAssistantStop?: boolean;
24
+ }
25
+
26
+ function textFromContent(content: unknown): string {
27
+ if (typeof content === "string") return content;
28
+ if (Array.isArray(content)) {
29
+ return content.map((block) => {
30
+ if (typeof block === "string") return block;
31
+ if (block && typeof block === "object") {
32
+ const item = block as { type?: string; text?: unknown; thinking?: unknown; content?: unknown; name?: unknown; input?: unknown; args?: unknown; arguments?: unknown };
33
+ if (item.type === "text" && typeof item.text === "string") return item.text;
34
+ if (item.type === "thinking" && typeof item.thinking === "string") return ["Thinking:", item.thinking].join("\n");
35
+ if (item.type === "toolCall") return formatToolCall(item.name, item.input ?? item.args ?? item.arguments);
36
+ if (typeof item.content === "string") return item.content;
37
+ }
38
+ return "";
39
+ }).filter(Boolean).join("\n");
40
+ }
41
+ if (content === undefined || content === null) return "";
42
+ return formatValue(content);
43
+ }
44
+
45
+ function formatValue(value: unknown, indent = ""): string {
46
+ if (typeof value === "string") return value;
47
+ if (value === undefined) return "undefined";
48
+ if (value === null || typeof value === "number" || typeof value === "boolean") return JSON.stringify(value);
49
+ if (Array.isArray(value)) {
50
+ return value.map((item, index) => `${indent}- ${formatValue(item, `${indent} `)}`).join("\n");
51
+ }
52
+ if (typeof value === "object") {
53
+ const lines: string[] = [];
54
+ for (const [key, item] of Object.entries(value as Record<string, unknown>)) {
55
+ if (typeof item === "string" && item.includes("\n")) lines.push(`${indent}${key}:\n${item}`);
56
+ else lines.push(`${indent}${key}: ${formatValue(item, `${indent} `)}`);
57
+ }
58
+ return lines.join("\n");
59
+ }
60
+ return String(value);
61
+ }
62
+
63
+ function redactEditWriteInput(input: unknown): unknown {
64
+ if (Array.isArray(input)) return input.map(redactEditWriteInput);
65
+ if (!input || typeof input !== "object") return input;
66
+ const sanitized: Record<string, unknown> = {};
67
+ for (const [key, value] of Object.entries(input as Record<string, unknown>)) {
68
+ sanitized[key] = ["oldText", "newText", "content"].includes(key) && typeof value === "string"
69
+ ? `[omitted ${value.length} chars; use tool result diff]`
70
+ : redactEditWriteInput(value);
71
+ }
72
+ return sanitized;
73
+ }
74
+
75
+ function formatToolArguments(name: string, input: unknown): string {
76
+ if (name === "edit" || name === "write") return formatValue(redactEditWriteInput(input));
77
+ return formatValue(input);
78
+ }
79
+
80
+ function formatToolCall(name: unknown, input: unknown): string {
81
+ const toolName = typeof name === "string" && name ? name : "tool";
82
+ return [`Tool call: ${toolName}`, "Arguments:", formatToolArguments(toolName, input ?? {})].join("\n");
83
+ }
84
+
85
+ function formatToolResult(name: string, content: unknown, details: unknown, error: unknown, isError: boolean | undefined): string {
86
+ const failed = isError === true || Boolean(error);
87
+ const lines = [`Tool result: ${name}`];
88
+ if (failed) lines.push(`Error: ${error ? (typeof error === "string" ? error : formatValue(error)) : "tool reported an error"}`);
89
+ if (!failed && details && typeof details === "object" && "diff" in details && typeof (details as { diff?: unknown }).diff === "string") {
90
+ lines.push("Diff:", (details as { diff: string }).diff);
91
+ } else {
92
+ const body = textFromContent(content);
93
+ if (body) lines.push(failed ? "Output:" : "Result:", body);
94
+ }
95
+ return lines.join("\n");
96
+ }
97
+
98
+ function messagesFromEvent(event: unknown): unknown[] {
99
+ if (!event || typeof event !== "object") return [];
100
+ const input = event as Record<string, unknown>;
101
+ if (input.type === "turn_end" || input.event === "turn_end") {
102
+ return [input.message, ...(Array.isArray(input.toolResults) ? input.toolResults : [])].filter(Boolean);
103
+ }
104
+ if (input.message) return [input.message];
105
+ if (input.type === "tool_execution_start" || input.event === "tool_execution_start") {
106
+ return [{ role: "toolCall", name: input.toolName ?? input.name, input: input.args ?? input.input }];
107
+ }
108
+ if (input.type === "tool_execution_end" || input.event === "tool_execution_end") {
109
+ const result = input.result && typeof input.result === "object" && !Array.isArray(input.result) ? input.result as Record<string, unknown> : undefined;
110
+ return [{
111
+ role: "toolResult",
112
+ toolName: input.toolName ?? input.name,
113
+ content: result?.content ?? input.content ?? input.result,
114
+ details: result?.details ?? input.details,
115
+ error: input.error,
116
+ isError: input.isError,
117
+ }];
118
+ }
119
+ if (input.type === "tool_result" || input.event === "tool_result") {
120
+ return [{ role: "toolResult", toolName: input.toolName ?? input.name, content: input.content, details: input.details, error: input.error, isError: input.isError }];
121
+ }
122
+ return [];
123
+ }
124
+
125
+ export function formatWatchdogReviewMessage(message: unknown): string | undefined {
126
+ if (!message || typeof message !== "object") return undefined;
127
+ const input = message as MessageLike;
128
+ if (input.role === "custom" && input.customType === SUBAGENT_WATCHDOG_WARNING_TYPE) return undefined;
129
+ if (input.role === "assistant") {
130
+ const text = textFromContent(input.content);
131
+ const lines = text ? ["Assistant:", text] : ["Assistant: (no text)"];
132
+ if (input.stopReason === "stop") lines.push("Assistant stop: stop");
133
+ return lines.join("\n");
134
+ }
135
+ if (input.role === "toolCall") return formatToolCall(input.name ?? input.toolName, input.input ?? input.args ?? input.arguments);
136
+ if (input.role === "toolResult" || input.role === "tool") {
137
+ return formatToolResult(input.toolName ?? input.name ?? "tool", input.content, input.details, input.error, input.isError);
138
+ }
139
+ if (input.role === "user") {
140
+ const text = textFromContent(input.content);
141
+ return text ? ["User:", text].join("\n") : undefined;
142
+ }
143
+ return undefined;
144
+ }
145
+
146
+ export function formatWatchdogTurnDelta(input: WatchdogTurnDeltaInput): string {
147
+ const sections: string[] = [];
148
+ if (input.includeUserPrompt && input.userPrompt?.trim()) sections.push(["User prompt:", input.userPrompt].join("\n"));
149
+ for (const message of input.messages ?? []) {
150
+ const section = formatWatchdogReviewMessage(message);
151
+ if (section) sections.push(section);
152
+ }
153
+ for (const event of input.events ?? []) {
154
+ for (const message of messagesFromEvent(event)) {
155
+ const section = formatWatchdogReviewMessage(message);
156
+ if (section) sections.push(section);
157
+ }
158
+ }
159
+ if (input.finalAssistantStop) sections.push("Final assistant stop: stop without tool call");
160
+ return sections.join("\n\n---\n\n");
161
+ }
@@ -0,0 +1,188 @@
1
+ export const SUBAGENT_WATCHDOG_WARNING_TYPE = "subagent_watchdog_warning";
2
+
3
+ export const WATCHDOG_WARNING_SEVERITIES = ["concern", "blocker"] as const;
4
+ export type WatchdogSeverity = typeof WATCHDOG_WARNING_SEVERITIES[number];
5
+
6
+ export const WATCHDOG_WARNING_CATEGORIES = [
7
+ "correctness",
8
+ "missed-constraint",
9
+ "test-gap",
10
+ "unsafe-change",
11
+ "scope-drift",
12
+ "stale-fact",
13
+ "loop-risk",
14
+ "other",
15
+ ] as const;
16
+ export type WatchdogCategory = typeof WATCHDOG_WARNING_CATEGORIES[number];
17
+
18
+ export const WATCHDOG_WARNING_CONFIDENCES = ["medium", "high"] as const;
19
+ export type WatchdogConfidence = typeof WATCHDOG_WARNING_CONFIDENCES[number];
20
+
21
+ export const WATCHDOG_WARNING_SOURCES = ["main", "child", "async-completion", "lsp"] as const;
22
+ export type WatchdogWarningSource = typeof WATCHDOG_WARNING_SOURCES[number];
23
+
24
+ export const WATCHDOG_LSP_DIAGNOSTIC_SEVERITIES = ["error", "warning", "info", "hint"] as const;
25
+ export type WatchdogLspDiagnosticSeverity = typeof WATCHDOG_LSP_DIAGNOSTIC_SEVERITIES[number];
26
+
27
+ export const WATCHDOG_LSP_STATUSES = ["disabled", "ok", "skipped", "unavailable", "timeout", "failed"] as const;
28
+ export type WatchdogLspStatus = typeof WATCHDOG_LSP_STATUSES[number];
29
+
30
+ export const WATCHDOG_RUNTIME_STATUSES = ["idle", "queued", "reviewing", "waiting-at-agent-end", "stale", "failed"] as const;
31
+ export type WatchdogRuntimeStatus = typeof WATCHDOG_RUNTIME_STATUSES[number];
32
+
33
+ export const WATCHDOG_WARNING_STATES = [
34
+ "candidate",
35
+ "confirmed",
36
+ "displayed",
37
+ "stale",
38
+ "failed",
39
+ "resolved",
40
+ "stalemate",
41
+ "suppressed",
42
+ ] as const;
43
+ export type WatchdogWarningState = typeof WATCHDOG_WARNING_STATES[number];
44
+
45
+ export const WATCHDOG_LATE_WARNING_POLICIES = ["show-stale-no-autofollow"] as const;
46
+ export type WatchdogLateWarningPolicy = typeof WATCHDOG_LATE_WARNING_POLICIES[number];
47
+
48
+ export const WATCHDOG_DELIVERY_MODES = ["held"] as const;
49
+ export type WatchdogDeliveryMode = typeof WATCHDOG_DELIVERY_MODES[number];
50
+
51
+ export type WatchdogSyncBacklog = "off" | number;
52
+
53
+ export interface WatchdogWarning {
54
+ severity: WatchdogSeverity;
55
+ summary: string;
56
+ evidence: string;
57
+ recommendedAction: string;
58
+ category?: WatchdogCategory;
59
+ confidence?: WatchdogConfidence;
60
+ source?: WatchdogWarningSource;
61
+ agent?: string;
62
+ runId?: string;
63
+ stale?: boolean;
64
+ autoFollowAttempt?: number;
65
+ state?: WatchdogWarningState;
66
+ }
67
+
68
+ export interface WatchdogWarningDetails extends WatchdogWarning {
69
+ category: WatchdogCategory;
70
+ source: WatchdogWarningSource;
71
+ identity?: string;
72
+ displayedAt?: string;
73
+ error?: string;
74
+ stalemateRepeats?: number;
75
+ }
76
+
77
+ export interface WatchdogWarningMessage {
78
+ customType: typeof SUBAGENT_WATCHDOG_WARNING_TYPE;
79
+ content: string;
80
+ display: boolean;
81
+ details: WatchdogWarningDetails;
82
+ }
83
+
84
+ export interface WatchdogAutoFollowConfig {
85
+ blockers: boolean;
86
+ maxAttempts: number | null;
87
+ stalemateRepeats: number;
88
+ }
89
+
90
+ export interface WatchdogGuidanceConfig {
91
+ watchdogMd: boolean;
92
+ systemPromptPath: string | null;
93
+ }
94
+
95
+ export interface WatchdogEndpointConfig {
96
+ enabled: boolean;
97
+ model?: string;
98
+ thinking?: string | false;
99
+ }
100
+
101
+ export interface WatchdogChildOverrideConfig {
102
+ enabled?: boolean;
103
+ model?: string;
104
+ thinking?: string | false;
105
+ }
106
+
107
+ export interface WatchdogChildrenConfig extends WatchdogEndpointConfig {
108
+ watchdogTailTimeoutMs: number;
109
+ autoFollow: WatchdogAutoFollowConfig;
110
+ overrides: Record<string, WatchdogChildOverrideConfig>;
111
+ }
112
+
113
+ export interface WatchdogAsyncCompletionConfig {
114
+ enabled: boolean;
115
+ autoFollowBlockers: boolean;
116
+ }
117
+
118
+ export interface WatchdogLspConfig {
119
+ enabled: boolean;
120
+ timeoutMs: number;
121
+ maxFiles: number;
122
+ maxDiagnostics: number;
123
+ }
124
+
125
+ export interface WatchdogLspDiagnostic {
126
+ path: string;
127
+ line: number;
128
+ column: number;
129
+ severity: WatchdogLspDiagnosticSeverity;
130
+ source: string;
131
+ code?: string;
132
+ message: string;
133
+ }
134
+
135
+ export interface WatchdogLspResult {
136
+ status: WatchdogLspStatus;
137
+ provider?: string;
138
+ checkedPaths: string[];
139
+ skippedPaths: string[];
140
+ diagnostics: WatchdogLspDiagnostic[];
141
+ message?: string;
142
+ }
143
+
144
+ export interface WatchdogLspRuntimeSnapshot extends WatchdogLspResult {
145
+ enabled: boolean;
146
+ diagnosticCount: number;
147
+ freshDiagnosticCount: number;
148
+ updatedAt?: string;
149
+ }
150
+
151
+ export interface ResolvedWatchdogConfig {
152
+ enabled: boolean;
153
+ delivery: WatchdogDeliveryMode;
154
+ showDuringRun: boolean;
155
+ syncBacklog: WatchdogSyncBacklog;
156
+ agentEndTimeoutMs: number;
157
+ lateWarningPolicy: WatchdogLateWarningPolicy;
158
+ severityThreshold: WatchdogSeverity;
159
+ maxWarnings: number | null;
160
+ guidance: WatchdogGuidanceConfig;
161
+ autoFollow: WatchdogAutoFollowConfig;
162
+ main: WatchdogEndpointConfig;
163
+ children: WatchdogChildrenConfig;
164
+ asyncCompletion: WatchdogAsyncCompletionConfig;
165
+ lsp: WatchdogLspConfig;
166
+ compactAtPercent: number;
167
+ reviewRetryDelayMs: number;
168
+ maxReviewFailures: number;
169
+ }
170
+
171
+ export interface WatchdogSettingsError {
172
+ scope: "user" | "project" | "session";
173
+ path?: string;
174
+ message: string;
175
+ }
176
+
177
+ export interface WatchdogSettingsSource {
178
+ scope: "user" | "project" | "session";
179
+ path?: string;
180
+ exists: boolean;
181
+ }
182
+
183
+ export interface WatchdogSettingsResult {
184
+ ok: boolean;
185
+ config: ResolvedWatchdogConfig;
186
+ errors: WatchdogSettingsError[];
187
+ sources: WatchdogSettingsSource[];
188
+ }
@@ -0,0 +1,73 @@
1
+ import {
2
+ SUBAGENT_WATCHDOG_WARNING_TYPE,
3
+ type WatchdogWarning,
4
+ type WatchdogWarningDetails,
5
+ type WatchdogWarningMessage,
6
+ } from "./types.ts";
7
+
8
+ function escapeXmlText(value: string): string {
9
+ return value
10
+ .replace(/&/g, "&amp;")
11
+ .replace(/</g, "&lt;")
12
+ .replace(/>/g, "&gt;");
13
+ }
14
+
15
+ function escapeXmlAttribute(value: string): string {
16
+ return escapeXmlText(value).replace(/"/g, "&quot;");
17
+ }
18
+
19
+ function tag(name: string, value: string | number | boolean | undefined): string | undefined {
20
+ if (value === undefined) return undefined;
21
+ return `<${name}>${escapeXmlText(String(value))}</${name}>`;
22
+ }
23
+
24
+ export function normalizeWatchdogWarningDetails(warning: WatchdogWarning, extras: Partial<WatchdogWarningDetails> = {}): WatchdogWarningDetails {
25
+ return {
26
+ ...warning,
27
+ category: warning.category ?? extras.category ?? "other",
28
+ source: warning.source ?? extras.source ?? "main",
29
+ ...extras,
30
+ };
31
+ }
32
+
33
+ export function formatWatchdogWarningContent(warning: WatchdogWarning): string {
34
+ const details = normalizeWatchdogWarningDetails(warning);
35
+ const attrs = [
36
+ `severity="${escapeXmlAttribute(details.severity)}"`,
37
+ `category="${escapeXmlAttribute(details.category)}"`,
38
+ `source="${escapeXmlAttribute(details.source)}"`,
39
+ `guidance="weigh, don't blindly obey"`,
40
+ ];
41
+ const optionalTags = [
42
+ tag("confidence", details.confidence),
43
+ tag("agent", details.agent),
44
+ tag("run_id", details.runId),
45
+ tag("state", details.state),
46
+ tag("stale", details.stale),
47
+ tag("auto_follow_attempt", details.autoFollowAttempt),
48
+ ];
49
+ return [
50
+ `<subagent_watchdog ${attrs.join(" ")}>`,
51
+ `<summary>${escapeXmlText(details.summary)}</summary>`,
52
+ `<evidence>${escapeXmlText(details.evidence)}</evidence>`,
53
+ `<recommended_action>${escapeXmlText(details.recommendedAction)}</recommended_action>`,
54
+ ...optionalTags.filter((line): line is string => Boolean(line)),
55
+ details.severity === "blocker"
56
+ ? "<blocker_guidance>If this warning changes the outcome, produce a new self-contained final answer after addressing it.</blocker_guidance>"
57
+ : undefined,
58
+ "</subagent_watchdog>",
59
+ ].filter((line): line is string => Boolean(line)).join("\n");
60
+ }
61
+
62
+ export function createWatchdogWarningMessage(
63
+ warning: WatchdogWarning,
64
+ options: { display?: boolean; details?: Partial<WatchdogWarningDetails> } = {},
65
+ ): WatchdogWarningMessage {
66
+ const details = normalizeWatchdogWarningDetails(warning, options.details);
67
+ return {
68
+ customType: SUBAGENT_WATCHDOG_WARNING_TYPE,
69
+ content: formatWatchdogWarningContent(details),
70
+ display: options.display ?? true,
71
+ details,
72
+ };
73
+ }