@mystilleef/pi-subagent 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/package.json +8 -8
- package/src/agent/agents.ts +33 -8
- package/src/child/complete-extension.ts +36 -0
- package/src/child/complete-outcome.ts +35 -0
- package/src/child/model-resolution.ts +81 -0
- package/src/child/process-utils.ts +103 -0
- package/src/child/process.ts +125 -452
- package/src/child/prompt-contract.ts +14 -6
- package/src/child/prompt-setup.ts +36 -0
- package/src/child/result-builder.ts +142 -0
- package/src/child/sampling-extension.ts +49 -0
- package/src/child/streaming-progress.ts +138 -0
- package/src/orchestration/subagent-orchestrator.ts +20 -16
- package/src/output/normalize.ts +1 -1
- package/src/output/summary.ts +22 -6
- package/src/output/ui.ts +19 -21
- package/src/progress/progress-state.ts +10 -12
- package/src/progress/result-details.ts +54 -45
- package/src/shared/sampling.ts +56 -0
- package/src/shared/types.ts +1 -0
- package/src/shared/utils.ts +10 -0
|
@@ -79,6 +79,47 @@ function redactSensitiveDebugMessages(messages: unknown): unknown {
|
|
|
79
79
|
return messages.map(redactSensitiveDebugValue);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
function sanitizeProgressObject(
|
|
83
|
+
progress: SingleResult["progress"],
|
|
84
|
+
_includeDebugMessages: boolean,
|
|
85
|
+
): StreamingProgress | undefined {
|
|
86
|
+
if (!progress) return undefined;
|
|
87
|
+
const {
|
|
88
|
+
activityText,
|
|
89
|
+
activeToolActivity,
|
|
90
|
+
lastToolPreview,
|
|
91
|
+
toolResultCompleted,
|
|
92
|
+
...progBase
|
|
93
|
+
} = progress;
|
|
94
|
+
return {
|
|
95
|
+
toolCalls: progBase.toolCalls.map((tc) => ({
|
|
96
|
+
id: tc.id,
|
|
97
|
+
preview: tc.preview,
|
|
98
|
+
})),
|
|
99
|
+
...(activityText !== undefined && { activityText }),
|
|
100
|
+
...(activeToolActivity !== undefined && { activeToolActivity }),
|
|
101
|
+
...(lastToolPreview !== undefined && { lastToolPreview }),
|
|
102
|
+
...(toolResultCompleted !== undefined && { toolResultCompleted }),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function sanitizeTerminationObject(
|
|
107
|
+
termination: TerminationMetadata | undefined,
|
|
108
|
+
includeMessages: boolean,
|
|
109
|
+
includeDebugMessages: boolean,
|
|
110
|
+
): TerminationMetadata | undefined {
|
|
111
|
+
if (!includeMessages || !includeDebugMessages || !termination)
|
|
112
|
+
return undefined;
|
|
113
|
+
const { cancelReason, terminationSignal, fallbackCause, ...termBase } =
|
|
114
|
+
termination;
|
|
115
|
+
return {
|
|
116
|
+
...termBase,
|
|
117
|
+
...(cancelReason !== undefined && { cancelReason }),
|
|
118
|
+
...(terminationSignal !== undefined && { terminationSignal }),
|
|
119
|
+
...(fallbackCause !== undefined && { fallbackCause }),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
82
123
|
export function sanitizeResultDetails(
|
|
83
124
|
result: SingleResult,
|
|
84
125
|
includeDebugMessages: boolean,
|
|
@@ -88,37 +129,6 @@ export function sanitizeResultDetails(
|
|
|
88
129
|
includeDebugMessages && (options?.includeMessages ?? true);
|
|
89
130
|
const { messages, termination, progress, stderr, usage, ...core } = result;
|
|
90
131
|
const { contextWindowTokens, ...usageBase } = usage;
|
|
91
|
-
let progressValue: StreamingProgress | undefined;
|
|
92
|
-
if (progress) {
|
|
93
|
-
const {
|
|
94
|
-
activityText,
|
|
95
|
-
activeToolActivity,
|
|
96
|
-
lastToolPreview,
|
|
97
|
-
toolResultCompleted,
|
|
98
|
-
...progBase
|
|
99
|
-
} = progress;
|
|
100
|
-
progressValue = {
|
|
101
|
-
toolCalls: progBase.toolCalls.map((tc) => ({
|
|
102
|
-
id: tc.id,
|
|
103
|
-
preview: tc.preview,
|
|
104
|
-
})),
|
|
105
|
-
...(activityText !== undefined && { activityText }),
|
|
106
|
-
...(activeToolActivity !== undefined && { activeToolActivity }),
|
|
107
|
-
...(lastToolPreview !== undefined && { lastToolPreview }),
|
|
108
|
-
...(toolResultCompleted !== undefined && { toolResultCompleted }),
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
let terminationValue: TerminationMetadata | undefined;
|
|
112
|
-
if (includeMessages && includeDebugMessages && termination) {
|
|
113
|
-
const { cancelReason, terminationSignal, fallbackCause, ...termBase } =
|
|
114
|
-
termination;
|
|
115
|
-
terminationValue = {
|
|
116
|
-
...termBase,
|
|
117
|
-
...(cancelReason !== undefined && { cancelReason }),
|
|
118
|
-
...(terminationSignal !== undefined && { terminationSignal }),
|
|
119
|
-
...(fallbackCause !== undefined && { fallbackCause }),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
132
|
const sanitized: SingleResult = {
|
|
123
133
|
...core,
|
|
124
134
|
stderr: includeDebugMessages ? stderr : "",
|
|
@@ -127,6 +137,7 @@ export function sanitizeResultDetails(
|
|
|
127
137
|
...(contextWindowTokens !== undefined && { contextWindowTokens }),
|
|
128
138
|
},
|
|
129
139
|
};
|
|
140
|
+
const progressValue = sanitizeProgressObject(progress, includeDebugMessages);
|
|
130
141
|
if (progressValue !== undefined) sanitized.progress = progressValue;
|
|
131
142
|
if (includeMessages) {
|
|
132
143
|
sanitized.messages = options?.recentMessages
|
|
@@ -135,6 +146,11 @@ export function sanitizeResultDetails(
|
|
|
135
146
|
? [...messages]
|
|
136
147
|
: undefined;
|
|
137
148
|
}
|
|
149
|
+
const terminationValue = sanitizeTerminationObject(
|
|
150
|
+
termination,
|
|
151
|
+
includeMessages,
|
|
152
|
+
includeDebugMessages,
|
|
153
|
+
);
|
|
138
154
|
if (terminationValue !== undefined) sanitized.termination = terminationValue;
|
|
139
155
|
return sanitized;
|
|
140
156
|
}
|
|
@@ -224,19 +240,12 @@ export function patchProgressFromDetails(
|
|
|
224
240
|
patchProgressState(requestId, patch);
|
|
225
241
|
}
|
|
226
242
|
|
|
227
|
-
function getSubagentText(result: SubagentToolResult): string {
|
|
228
|
-
return (result.content[0] as { text?: string })?.text ?? "";
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
export function getResultDisplayText(result: SubagentToolResult): string {
|
|
232
|
-
return (
|
|
233
|
-
getLatestResult(result.details)?.finalOutput ?? getSubagentText(result)
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
243
|
export function getFeedbackSummaryText(result: SubagentToolResult): string {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
244
|
+
const latestResult = getLatestResult(result.details);
|
|
245
|
+
const rawFinalOutput = latestResult?.finalOutput ?? "";
|
|
246
|
+
const outcome = latestResult?.outcome;
|
|
247
|
+
if (!outcome?.trim() && !rawFinalOutput.trim()) {
|
|
248
|
+
return "(no output)";
|
|
249
|
+
}
|
|
250
|
+
return summarizeFeedbackUiFinalOutput(rawFinalOutput, outcome);
|
|
242
251
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export interface SamplingParams {
|
|
2
|
+
temperature?: number | undefined;
|
|
3
|
+
topP?: number | undefined;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function isValidSamplingValue(value: unknown): value is number {
|
|
7
|
+
return (
|
|
8
|
+
typeof value === "number" &&
|
|
9
|
+
Number.isFinite(value) &&
|
|
10
|
+
value >= 0.0 &&
|
|
11
|
+
value <= 1.0
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parses a JSON-encoded sampling parameters string.
|
|
17
|
+
* Returns undefined for missing, malformed, or wholly invalid values.
|
|
18
|
+
*/
|
|
19
|
+
export function parseSamplingParams(
|
|
20
|
+
envVal?: string,
|
|
21
|
+
): SamplingParams | undefined {
|
|
22
|
+
if (!envVal) return undefined;
|
|
23
|
+
try {
|
|
24
|
+
const parsed = JSON.parse(envVal);
|
|
25
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
26
|
+
return undefined;
|
|
27
|
+
const { temperature: rawTemperature, topP: rawTopP } = parsed as Record<
|
|
28
|
+
string,
|
|
29
|
+
unknown
|
|
30
|
+
>;
|
|
31
|
+
const result: SamplingParams = {};
|
|
32
|
+
if (isValidSamplingValue(rawTemperature))
|
|
33
|
+
result.temperature = rawTemperature;
|
|
34
|
+
if (isValidSamplingValue(rawTopP)) result.topP = rawTopP;
|
|
35
|
+
if (result.temperature !== undefined || result.topP !== undefined)
|
|
36
|
+
return result;
|
|
37
|
+
} catch {
|
|
38
|
+
/* malformed env value: run without sampling overrides */
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Serializes sampling parameters into a JSON string for environment passing.
|
|
45
|
+
* Returns undefined when no valid parameters are present.
|
|
46
|
+
*/
|
|
47
|
+
export function serializeSamplingParams(
|
|
48
|
+
params: SamplingParams,
|
|
49
|
+
): string | undefined {
|
|
50
|
+
if (params.temperature === undefined && params.topP === undefined)
|
|
51
|
+
return undefined;
|
|
52
|
+
const config: SamplingParams = {};
|
|
53
|
+
if (params.temperature !== undefined) config.temperature = params.temperature;
|
|
54
|
+
if (params.topP !== undefined) config.topP = params.topP;
|
|
55
|
+
return JSON.stringify(config);
|
|
56
|
+
}
|
package/src/shared/types.ts
CHANGED
package/src/shared/utils.ts
CHANGED
|
@@ -230,6 +230,15 @@ export function findLastAssistantTextMessage(messages: Message[]): number {
|
|
|
230
230
|
return -1;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
export function extractFinalOutputFromMessages(messages: Message[]): string {
|
|
234
|
+
const lastAsstIdx = findLastAssistantTextMessage(messages);
|
|
235
|
+
if (lastAsstIdx < 0) return "";
|
|
236
|
+
const content = messages[lastAsstIdx]?.content;
|
|
237
|
+
if (!Array.isArray(content)) return "";
|
|
238
|
+
const lastText = content.findLast((p) => p.type === "text");
|
|
239
|
+
return lastText?.type === "text" ? (lastText.text ?? "") : "";
|
|
240
|
+
}
|
|
241
|
+
|
|
233
242
|
export function detectMessageError(messages: Message[]): boolean {
|
|
234
243
|
const lastAssistantIdx = findLastAssistantTextMessage(messages);
|
|
235
244
|
const from = lastAssistantIdx >= 0 ? lastAssistantIdx + 1 : 0;
|
|
@@ -241,6 +250,7 @@ export function detectMessageError(messages: Message[]): boolean {
|
|
|
241
250
|
}
|
|
242
251
|
|
|
243
252
|
export function hasSubagentFailed(result: SingleResult): boolean {
|
|
253
|
+
if (result.outcome?.trim()) return false;
|
|
244
254
|
return (
|
|
245
255
|
result.exitCode !== 0 ||
|
|
246
256
|
result.stopReason === "error" ||
|