@iqai/adk 0.2.4 → 0.3.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/dist/index.mjs CHANGED
@@ -30,98 +30,269 @@ import chalk from "chalk";
30
30
  function isDebugEnabled() {
31
31
  return process.env.NODE_ENV === "development" || process.env.ADK_DEBUG === "true";
32
32
  }
33
- var Logger;
33
+ var LOG_LEVELS, Logger;
34
34
  var init_logger = __esm({
35
35
  "src/logger/index.ts"() {
36
+ LOG_LEVELS = {
37
+ debug: { icon: "\u{1F41B}", color: chalk.blue, method: console.log },
38
+ info: { icon: "\u2139\uFE0F", color: chalk.cyan, method: console.debug },
39
+ warn: { icon: "\u{1F6A7}", color: chalk.yellow, method: console.warn },
40
+ error: { icon: "\u274C", color: chalk.red, method: console.error }
41
+ };
36
42
  Logger = class {
37
43
  name;
38
44
  isDebugEnabled = isDebugEnabled();
39
45
  constructor({ name }) {
40
46
  this.name = name;
41
47
  }
42
- colorize(message) {
43
- return chalk.blue(message);
44
- }
45
48
  debug(message, ...args) {
46
49
  if (this.isDebugEnabled) {
47
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
48
- console.log(
49
- this.colorize(`[${time}] \u{1F41B} [${this.name}] ${message}`),
50
- ...args
51
- );
50
+ this.log("debug", message, ...args);
52
51
  }
53
52
  }
54
53
  info(message, ...args) {
55
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
56
- console.debug(
57
- this.colorize(`[${time}] \u2139\uFE0F [${this.name}] ${message}`),
58
- ...args
59
- );
54
+ this.log("info", message, ...args);
60
55
  }
61
56
  warn(message, ...args) {
62
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
63
- console.warn(
64
- this.colorize(`[${time}] \u{1F6A7} [${this.name}] ${message}`),
65
- ...args
66
- );
57
+ this.log("warn", message, ...args);
67
58
  }
68
59
  error(message, ...args) {
60
+ this.log("error", message, ...args);
61
+ }
62
+ log(level, message, ...args) {
63
+ const { icon, color, method } = LOG_LEVELS[level];
69
64
  const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
70
- console.error(
71
- this.colorize(`[${time}] \u274C [${this.name}] ${message}`),
72
- ...args
65
+ const isProd = process.env.NODE_ENV === "production";
66
+ const forceBoxes = process.env.ADK_FORCE_BOXES === "true";
67
+ const { meta, otherArgs } = this.extractMeta(args);
68
+ const lines = this.formatArgs(otherArgs, level === "error");
69
+ if (meta.suggestion) lines.unshift(`\u2022 Suggestion: ${meta.suggestion}`);
70
+ if (meta.context && Object.keys(meta.context).length) {
71
+ const contextStr = Object.entries(meta.context).map(([k, v]) => `${k}=${this.stringify(v)}`).join(" ");
72
+ lines.unshift(`\u2022 Context: ${contextStr}`);
73
+ }
74
+ if (isProd && !forceBoxes) {
75
+ const header = `[${time}] ${icon} [${this.name}] ${message}`;
76
+ const output = lines.length ? [header, ...lines].join("\n") : header;
77
+ method(color(output));
78
+ return;
79
+ }
80
+ if (level === "warn" || level === "error") {
81
+ const box = this.formatBox({
82
+ title: `${icon} ${this.capitalize(level)} @ ${time} (${this.name})`,
83
+ description: message,
84
+ lines,
85
+ color
86
+ });
87
+ method(box);
88
+ } else {
89
+ const header = `[${time}] ${icon} [${this.name}] ${message}`;
90
+ const output = lines.length ? [header, ...lines].join("\n") : header;
91
+ method(color(output));
92
+ }
93
+ }
94
+ extractMeta(args) {
95
+ const meta = {};
96
+ const otherArgs = [];
97
+ let metaFound = false;
98
+ for (const arg of args) {
99
+ if (!arg) continue;
100
+ if (!metaFound && typeof arg === "object" && !(arg instanceof Error) && ("suggestion" in arg || "context" in arg)) {
101
+ meta.suggestion = arg.suggestion;
102
+ meta.context = arg.context;
103
+ metaFound = true;
104
+ } else {
105
+ otherArgs.push(arg);
106
+ }
107
+ }
108
+ return { meta, otherArgs };
109
+ }
110
+ formatArgs(args, includeStack = false) {
111
+ const lines = [];
112
+ const maxFrames = Number(process.env.ADK_ERROR_STACK_FRAMES || 8);
113
+ for (const arg of args) {
114
+ if (!arg) continue;
115
+ if (arg instanceof Error) {
116
+ lines.push(`\u2022 ${arg.name}: ${arg.message}`);
117
+ if (includeStack && arg.stack) {
118
+ const frames = this.parseStackFrames(arg.stack, maxFrames);
119
+ if (frames.length) {
120
+ lines.push("\u2022 Stack:", ...frames);
121
+ }
122
+ }
123
+ } else {
124
+ lines.push(`\u2022 ${this.stringify(arg)}`);
125
+ }
126
+ }
127
+ return lines;
128
+ }
129
+ parseStackFrames(stack, maxFrames) {
130
+ const frames = stack.split(/\n/).slice(1).map((f) => f.trim()).filter(Boolean).slice(0, maxFrames);
131
+ const result = frames.map((frame) => {
132
+ const cleaned = frame.replace(/^at\s+/, "").replace(process.cwd(), ".");
133
+ return ` \u21B3 ${cleaned}`;
134
+ });
135
+ const totalFrames = stack.split(/\n/).length - 1;
136
+ if (totalFrames > maxFrames) {
137
+ result.push(` \u21B3 \u2026 ${totalFrames - maxFrames} more frames`);
138
+ }
139
+ return result;
140
+ }
141
+ stringify(value) {
142
+ if (typeof value === "string") return value;
143
+ if (typeof value === "number" || typeof value === "boolean")
144
+ return String(value);
145
+ if (value === null || value === void 0) return String(value);
146
+ try {
147
+ return JSON.stringify(value);
148
+ } catch {
149
+ return String(value);
150
+ }
151
+ }
152
+ capitalize(str) {
153
+ return str.charAt(0).toUpperCase() + str.slice(1);
154
+ }
155
+ formatBox(params) {
156
+ const {
157
+ title,
158
+ description,
159
+ lines = [],
160
+ width = 60,
161
+ maxWidthPct = 0.9,
162
+ color = chalk.yellow,
163
+ pad = 1,
164
+ borderChar = "\u2500"
165
+ } = params;
166
+ const isProd = process.env.NODE_ENV === "production";
167
+ const forceBoxes = process.env.ADK_FORCE_BOXES === "true";
168
+ if (isProd && !forceBoxes) {
169
+ return [`${title}: ${description}`, ...lines].join("\n");
170
+ }
171
+ const termWidth = process.stdout.columns || 80;
172
+ const maxWidth = Math.floor(termWidth * maxWidthPct);
173
+ const contentWidth = Math.max(
174
+ width,
175
+ title.length + 2,
176
+ description.length,
177
+ ...lines.map((l) => l.length)
73
178
  );
179
+ const innerWidth = Math.min(contentWidth + pad * 2, maxWidth - 2);
180
+ const horizontal = borderChar.repeat(innerWidth + 2);
181
+ const top = `\u250C${horizontal}\u2510`;
182
+ const separator = `\u251C${horizontal}\u2524`;
183
+ const bottom = `\u2514${horizontal}\u2518`;
184
+ const padLine = (text) => {
185
+ const maxContent = innerWidth - pad * 2;
186
+ const truncated = text.length > maxContent ? `${text.slice(0, maxContent - 1)}\u2026` : text;
187
+ const padded = " ".repeat(pad) + truncated;
188
+ return padded + " ".repeat(innerWidth - padded.length);
189
+ };
190
+ const content = [
191
+ top,
192
+ `\u2502 ${padLine(title)} \u2502`,
193
+ separator,
194
+ `\u2502 ${padLine(description)} \u2502`,
195
+ ...lines.map((line) => `\u2502 ${padLine(line)} \u2502`),
196
+ bottom
197
+ ];
198
+ return `
199
+ ${content.map((line) => color(line)).join("\n")}`;
74
200
  }
75
201
  /**
76
- * Logs structured data in a visually appealing table format.
77
- * Uses vertical layout for better readability and respects debug settings.
202
+ * Structured warning with code, suggestion, context.
78
203
  */
204
+ warnStructured(warning, opts = {}) {
205
+ const format = opts.format || process.env.ADK_WARN_FORMAT || "pretty";
206
+ const verbose = opts.verbose || process.env.ADK_AGENT_BUILDER_WARN === "verbose";
207
+ const timestamp = warning.timestamp || (/* @__PURE__ */ new Date()).toISOString();
208
+ const severity = warning.severity || "warn";
209
+ if (format === "json") {
210
+ this.warn(
211
+ JSON.stringify({
212
+ level: severity,
213
+ source: this.name,
214
+ timestamp,
215
+ ...warning
216
+ })
217
+ );
218
+ return;
219
+ }
220
+ const { icon } = LOG_LEVELS[severity] || LOG_LEVELS.warn;
221
+ const base = `${icon} ${warning.code} ${warning.message}`;
222
+ const parts = [base];
223
+ if (warning.suggestion) {
224
+ parts.push(` \u2022 Suggestion: ${warning.suggestion}`);
225
+ }
226
+ if (verbose && warning.context && Object.keys(warning.context).length) {
227
+ const contextStr = Object.entries(warning.context).map(([k, v]) => `${k}=${this.stringify(v)}`).join(" ");
228
+ parts.push(` \u2022 Context: ${contextStr}`);
229
+ }
230
+ if (format === "pretty") {
231
+ this.warn(parts.join("\n"));
232
+ } else {
233
+ const textParts = [`[${warning.code}] ${warning.message}`];
234
+ if (warning.suggestion) textParts.push(` -> ${warning.suggestion}`);
235
+ if (verbose && warning.context && Object.keys(warning.context).length) {
236
+ const contextStr = Object.entries(warning.context).map(([k, v]) => `${k}=${this.stringify(v)}`).join(" ");
237
+ textParts.push(` \u2022 Context: ${contextStr}`);
238
+ }
239
+ this.warn(textParts.join("\n"));
240
+ }
241
+ }
79
242
  debugStructured(title, data) {
80
243
  if (!this.isDebugEnabled) return;
81
- const terminalWidth = process.stdout.columns || 60;
82
- const width = Math.min(terminalWidth, 100);
83
- const contentWidth = width - 4;
84
- const topBorder = `\u250C${"\u2500".repeat(width - 2)}\u2510`;
85
- const bottomBorder = `\u2514${"\u2500".repeat(width - 2)}\u2518`;
86
- const middleBorder = `\u251C${"\u2500".repeat(width - 2)}\u2524`;
87
- console.log(this.colorize(topBorder));
88
- console.log(this.colorize(`\u2502 ${title.padEnd(contentWidth)} \u2502`));
89
- console.log(this.colorize(middleBorder));
90
- Object.entries(data).forEach(([key, value]) => {
91
- const formattedKey = key.padEnd(20);
92
- const formattedValue = String(value);
93
- const availableValueSpace = contentWidth - 20 - 2;
94
- const truncatedValue = formattedValue.length > availableValueSpace ? `${formattedValue.substring(0, availableValueSpace - 3)}...` : formattedValue;
95
- const content = `${formattedKey}: ${truncatedValue}`;
96
- const paddedContent = content.padEnd(contentWidth);
97
- console.log(this.colorize(`\u2502 ${paddedContent} \u2502`));
244
+ const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
245
+ const lines = this.objectToLines(data);
246
+ const box = this.formatBox({
247
+ title: `\u{1F41B} Debug @ ${time} (${this.name})`,
248
+ description: title,
249
+ lines,
250
+ color: chalk.blue
98
251
  });
99
- console.log(this.colorize(bottomBorder));
252
+ console.log(box);
100
253
  }
101
- /**
102
- * Logs array data in a compact, readable format.
103
- */
104
254
  debugArray(title, items) {
105
255
  if (!this.isDebugEnabled) return;
106
- const terminalWidth = process.stdout.columns || 78;
107
- const width = Math.min(terminalWidth, 120);
108
- const contentWidth = width - 4;
109
- const topBorder = `\u250C${"\u2500".repeat(width - 2)}\u2510`;
110
- const bottomBorder = `\u2514${"\u2500".repeat(width - 2)}\u2518`;
111
- const middleBorder = `\u251C${"\u2500".repeat(width - 2)}\u2524`;
112
- console.log(this.colorize(topBorder));
113
- console.log(this.colorize(`\u2502 ${title.padEnd(contentWidth)} \u2502`));
114
- console.log(this.colorize(middleBorder));
115
- items.forEach((item, index) => {
116
- const itemStr = Object.entries(item).map(([k, v]) => `${k}: ${v}`).join(" \u2022 ");
117
- const indexPart = `[${index + 1}] `;
118
- const availableSpace = contentWidth - indexPart.length;
119
- const truncatedItem = itemStr.length > availableSpace ? `${itemStr.substring(0, availableSpace - 3)}...` : itemStr;
120
- const content = `${indexPart}${truncatedItem}`;
121
- const paddedContent = content.padEnd(contentWidth);
122
- console.log(this.colorize(`\u2502 ${paddedContent} \u2502`));
256
+ const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
257
+ const lines = this.arrayToLines(items);
258
+ const box = this.formatBox({
259
+ title: `\u{1F41B} Debug List @ ${time} (${this.name})`,
260
+ description: title,
261
+ lines,
262
+ color: chalk.blue,
263
+ width: 78,
264
+ maxWidthPct: 0.95
265
+ });
266
+ console.log(box);
267
+ }
268
+ objectToLines(obj) {
269
+ const entries = Object.entries(obj || {});
270
+ if (!entries.length) return ["(empty)"];
271
+ const keyWidth = Math.min(
272
+ 30,
273
+ Math.max(6, ...entries.map(([k]) => k.length))
274
+ );
275
+ return entries.slice(0, 200).map(([k, v]) => {
276
+ const value = this.stringify(v);
277
+ const truncated = value.length > 140 ? `${value.slice(0, 139)}\u2026` : value;
278
+ return `${k.padEnd(keyWidth)}: ${truncated}`;
279
+ });
280
+ }
281
+ arrayToLines(items) {
282
+ if (!items.length) return ["(empty list)"];
283
+ const maxItems = 50;
284
+ const lines = items.slice(0, maxItems).map((obj, i) => {
285
+ const props = Object.entries(obj).map(([k, v]) => {
286
+ const value = this.stringify(v);
287
+ const truncated = value.length > 160 ? `${value.slice(0, 159)}\u2026` : value;
288
+ return `${k}=${truncated}`;
289
+ }).join(" \u2022 ");
290
+ return `[${i + 1}] ${props}`;
123
291
  });
124
- console.log(this.colorize(bottomBorder));
292
+ if (items.length > maxItems) {
293
+ lines.push(`\u2026 ${items.length - maxItems} more items omitted`);
294
+ }
295
+ return lines;
125
296
  }
126
297
  };
127
298
  }
@@ -7111,6 +7282,7 @@ var AuthLlmRequestProcessor = class extends BaseLlmRequestProcessor {
7111
7282
  var requestProcessor = new AuthLlmRequestProcessor();
7112
7283
 
7113
7284
  // src/flows/llm-flows/basic.ts
7285
+ init_logger();
7114
7286
  var BasicLlmRequestProcessor = class extends BaseLlmRequestProcessor {
7115
7287
  async *runAsync(invocationContext, llmRequest) {
7116
7288
  const agent = invocationContext.agent;
@@ -7126,7 +7298,21 @@ var BasicLlmRequestProcessor = class extends BaseLlmRequestProcessor {
7126
7298
  llmRequest.config = {};
7127
7299
  }
7128
7300
  if (agent.outputSchema) {
7129
- llmRequest.setOutputSchema(agent.outputSchema);
7301
+ const hasTools = (await agent.canonicalTools?.(invocationContext))?.length > 0;
7302
+ const hasTransfers = !!("subAgents" in agent && agent.subAgents && agent.subAgents.length > 0 && !(agent.disallowTransferToParent && agent.disallowTransferToPeers));
7303
+ if (!hasTools && !hasTransfers) {
7304
+ llmRequest.setOutputSchema(agent.outputSchema);
7305
+ } else {
7306
+ (() => {
7307
+ try {
7308
+ const logger = new Logger({ name: "BasicLlmRequestProcessor" });
7309
+ logger.debug(
7310
+ `Skipping request-level output schema for agent ${agent.name} because tools/transfers are present. Schema will be validated during response processing.`
7311
+ );
7312
+ } catch (e) {
7313
+ }
7314
+ })();
7315
+ }
7130
7316
  }
7131
7317
  const runConfig = invocationContext.runConfig;
7132
7318
  if (!llmRequest.liveConnectConfig) {
@@ -8278,10 +8464,11 @@ var InstructionsLlmRequestProcessor = class extends BaseLlmRequestProcessor {
8278
8464
  });
8279
8465
  const { $schema, ...json } = raw || {};
8280
8466
  llmRequest.appendInstructions([
8281
- "You must respond with application/json that validates against this JSON Schema:",
8282
- "```json",
8283
- JSON.stringify(json, null, 2),
8284
- "```"
8467
+ "You must respond with application/json that validates against this JSON Schema (do NOT wrap the output in markdown or code fences):",
8468
+ JSON.stringify(json, null, 2)
8469
+ ]);
8470
+ llmRequest.appendInstructions([
8471
+ 'IMPORTANT: After any tool calls, function calls, or agent transfers have completed, produce ONE final assistant message whose entire content is ONLY the JSON object that conforms to the schema provided above. Do NOT include any explanatory text, markdown, or additional messages. Do NOT wrap the JSON in code fences (for example, do NOT use ```json or ```). If you cannot produce valid JSON that matches the schema, return a JSON object with an "error" field describing the problem.'
8285
8472
  ]);
8286
8473
  } catch {
8287
8474
  }
@@ -8578,6 +8765,7 @@ var requestProcessor7 = new NlPlanningRequestProcessor();
8578
8765
  var responseProcessor2 = new NlPlanningResponseProcessor();
8579
8766
 
8580
8767
  // src/flows/llm-flows/output-schema.ts
8768
+ import { jsonrepair } from "jsonrepair";
8581
8769
  init_logger();
8582
8770
  var OutputSchemaResponseProcessor = class extends BaseLlmResponseProcessor {
8583
8771
  logger = new Logger({ name: "OutputSchemaResponseProcessor" });
@@ -8599,7 +8787,8 @@ var OutputSchemaResponseProcessor = class extends BaseLlmResponseProcessor {
8599
8787
  return;
8600
8788
  }
8601
8789
  try {
8602
- const parsed = JSON.parse(textContent);
8790
+ const candidate = this.stripCodeFences(textContent);
8791
+ const parsed = this.tryParseJson(candidate, agent.name);
8603
8792
  const validated = agent.outputSchema.parse(parsed);
8604
8793
  textContent = JSON.stringify(validated, null, 2);
8605
8794
  llmResponse.content.parts = llmResponse.content.parts.map((part) => {
@@ -8647,6 +8836,38 @@ var OutputSchemaResponseProcessor = class extends BaseLlmResponseProcessor {
8647
8836
  yield errorEvent;
8648
8837
  }
8649
8838
  }
8839
+ // Strip common code fences and surrounding explanatory text from LLM output.
8840
+ stripCodeFences(raw) {
8841
+ const fencePattern = /```(?:json)?\s*([\s\S]*?)```/i;
8842
+ const fenceMatch = raw.match(fencePattern);
8843
+ if (fenceMatch?.[1]) {
8844
+ return fenceMatch[1].trim();
8845
+ }
8846
+ const lines = raw.split(/\r?\n/).map((l) => l.trim());
8847
+ const startIdx = lines.findIndex(
8848
+ (l) => l.startsWith("{") || l.startsWith("[")
8849
+ );
8850
+ if (startIdx >= 0) {
8851
+ return lines.slice(startIdx).join("\n").trim();
8852
+ }
8853
+ return raw.trim();
8854
+ }
8855
+ // Try parsing JSON; if parse fails, attempt to repair using jsonrepair and parse again.
8856
+ tryParseJson(candidate, agentName) {
8857
+ try {
8858
+ return JSON.parse(candidate);
8859
+ } catch (err) {
8860
+ this.logger.debug("Initial JSON.parse failed, attempting jsonrepair", {
8861
+ agent: agentName
8862
+ });
8863
+ try {
8864
+ const repaired = jsonrepair(candidate);
8865
+ return JSON.parse(repaired);
8866
+ } catch (repairErr) {
8867
+ throw err;
8868
+ }
8869
+ }
8870
+ }
8650
8871
  };
8651
8872
  var responseProcessor3 = new OutputSchemaResponseProcessor();
8652
8873
 
@@ -9069,19 +9290,17 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
9069
9290
  }
9070
9291
  if (!this.disallowTransferToParent || !this.disallowTransferToPeers) {
9071
9292
  this.logger.warn(
9072
- `Invalid config for agent ${this.name}: output_schema cannot co-exist with agent transfer configurations. Setting disallow_transfer_to_parent=true, disallow_transfer_to_peers=true`
9293
+ `Agent ${this.name}: outputSchema is set while transfer flags allow transfers. The output schema will be applied in response post-processing to preserve tool-calling and transfer behavior.`
9073
9294
  );
9074
- this.disallowTransferToParent = true;
9075
- this.disallowTransferToPeers = true;
9076
9295
  }
9077
9296
  if (this.subAgents && this.subAgents.length > 0) {
9078
- throw new Error(
9079
- `Invalid config for agent ${this.name}: if output_schema is set, sub_agents must be empty to disable agent transfer.`
9297
+ this.logger.warn(
9298
+ `Agent ${this.name}: outputSchema is set and subAgents are present. Agent transfers to sub-agents will remain enabled; the schema will be validated after transfers/tools complete.`
9080
9299
  );
9081
9300
  }
9082
9301
  if (this.tools && this.tools.length > 0) {
9083
- throw new Error(
9084
- `Invalid config for agent ${this.name}: if output_schema is set, tools must be empty`
9302
+ this.logger.warn(
9303
+ `Agent ${this.name}: outputSchema is set and tools are configured. Tools will be callable; the output schema will be applied during response post-processing.`
9085
9304
  );
9086
9305
  }
9087
9306
  }
@@ -9243,37 +9462,29 @@ async function* mergeAgentRun(agentRuns) {
9243
9462
  if (agentRuns.length === 0) {
9244
9463
  return;
9245
9464
  }
9246
- const promises = agentRuns.map(async (generator, index) => {
9247
- try {
9248
- const result = await generator.next();
9249
- return { index, result };
9250
- } catch (error) {
9251
- return { index, result: { done: true, value: void 0 }, error };
9465
+ const nextFor = (gen, index) => gen.next().then((result) => ({ index, result })).catch((error) => ({
9466
+ index,
9467
+ result: { done: true, value: void 0 },
9468
+ error
9469
+ }));
9470
+ const entries = agentRuns.map((gen, i) => ({ index: i, promise: nextFor(gen, i) }));
9471
+ const activePromises = () => entries.filter((e) => !!e).map((e) => e.promise);
9472
+ while (true) {
9473
+ const currentActivePromises = activePromises();
9474
+ if (currentActivePromises.length === 0) {
9475
+ break;
9252
9476
  }
9253
- });
9254
- let pendingPromises = [...promises];
9255
- while (pendingPromises.length > 0) {
9256
- const { index, result, error } = await Promise.race(pendingPromises);
9257
- pendingPromises = pendingPromises.filter((_, i) => i !== index);
9477
+ const { index, result, error } = await Promise.race(currentActivePromises);
9258
9478
  if (error) {
9259
9479
  console.error(`Error in parallel agent ${index}:`, error);
9480
+ entries[index] = void 0;
9260
9481
  continue;
9261
9482
  }
9262
9483
  if (!result.done) {
9263
9484
  yield result.value;
9264
- const nextPromise = (async () => {
9265
- try {
9266
- const nextResult = await agentRuns[index].next();
9267
- return { index, result: nextResult };
9268
- } catch (nextError) {
9269
- return {
9270
- index,
9271
- result: { done: true, value: void 0 },
9272
- error: nextError
9273
- };
9274
- }
9275
- })();
9276
- pendingPromises.push(nextPromise);
9485
+ entries[index] = { index, promise: nextFor(agentRuns[index], index) };
9486
+ } else {
9487
+ entries[index] = void 0;
9277
9488
  }
9278
9489
  }
9279
9490
  }
@@ -10432,8 +10643,20 @@ var AgentBuilder = class _AgentBuilder {
10432
10643
  // If provided, reuse directly
10433
10644
  definitionLocked = false;
10434
10645
  // Lock further definition mutation after withAgent
10435
- warnedMethods = /* @__PURE__ */ new Set();
10436
10646
  logger = new Logger({ name: "AgentBuilder" });
10647
+ /**
10648
+ * Warn (once per method) if the definition has been locked by withAgent().
10649
+ */
10650
+ warnIfLocked(method) {
10651
+ if (!this.definitionLocked) return;
10652
+ this.logger.warn(
10653
+ `AgentBuilder: ${method}() ignored because builder is locked by withAgent()`,
10654
+ {
10655
+ suggestion: "Configure model/tools/etc. before calling withAgent(), or avoid withAgent() if you intend to mutate afterwards.",
10656
+ context: { method, agentName: this.config.name }
10657
+ }
10658
+ );
10659
+ }
10437
10660
  /**
10438
10661
  * Private constructor - use static create() method
10439
10662
  */
@@ -10493,6 +10716,16 @@ var AgentBuilder = class _AgentBuilder {
10493
10716
  }
10494
10717
  withOutputSchema(schema) {
10495
10718
  this.warnIfLocked("withOutputSchema");
10719
+ if (this.agentType === "sequential" || this.agentType === "parallel") {
10720
+ const msg = "Output schemas cannot be applied to sequential or parallel agents. Define output schemas on each sub-agent instead.";
10721
+ this.logger.error(msg, {
10722
+ suggestion: "Apply outputSchema to each sub-agent individually.",
10723
+ context: {
10724
+ agentType: this.agentType
10725
+ }
10726
+ });
10727
+ throw new Error(msg);
10728
+ }
10496
10729
  this.config.outputSchema = schema;
10497
10730
  return this;
10498
10731
  }
@@ -10533,6 +10766,16 @@ var AgentBuilder = class _AgentBuilder {
10533
10766
  */
10534
10767
  withOutputKey(outputKey) {
10535
10768
  this.warnIfLocked("withOutputKey");
10769
+ if (this.agentType === "sequential" || this.agentType === "parallel") {
10770
+ this.logger.warn(
10771
+ "AgentBuilder: outputKey ignored for sequential/parallel aggregator",
10772
+ {
10773
+ suggestion: "Set outputKey on each sub-agent instead.",
10774
+ context: { attemptedOutputKey: outputKey, agentType: this.agentType }
10775
+ }
10776
+ );
10777
+ return this;
10778
+ }
10536
10779
  this.config.outputKey = outputKey;
10537
10780
  return this;
10538
10781
  }
@@ -10584,9 +10827,37 @@ var AgentBuilder = class _AgentBuilder {
10584
10827
  * @returns This builder instance for chaining
10585
10828
  */
10586
10829
  asSequential(subAgents) {
10587
- this.warnIfLocked("asSequential");
10830
+ if (this.definitionLocked) {
10831
+ this.logger.warn(
10832
+ "AgentBuilder: asSequential() ignored; builder locked by withAgent()",
10833
+ {
10834
+ suggestion: "Call asSequential() before withAgent().",
10835
+ context: { agentName: this.config.name }
10836
+ }
10837
+ );
10838
+ return this;
10839
+ }
10588
10840
  this.agentType = "sequential";
10589
10841
  this.config.subAgents = subAgents;
10842
+ if (this.config.outputKey) {
10843
+ this.logger.warn(
10844
+ "AgentBuilder: outputKey ignored for sequential agent aggregator; removed",
10845
+ {
10846
+ suggestion: "Assign outputKey on individual sub-agents if needed.",
10847
+ context: { previousValue: this.config.outputKey }
10848
+ }
10849
+ );
10850
+ this.config.outputKey = void 0;
10851
+ }
10852
+ if (this.config.outputSchema) {
10853
+ this.logger.warn(
10854
+ "AgentBuilder: outputSchema cannot be applied to sequential aggregator; removed",
10855
+ {
10856
+ suggestion: "Apply schemas to sub-agents individually."
10857
+ }
10858
+ );
10859
+ this.config.outputSchema = void 0;
10860
+ }
10590
10861
  return this;
10591
10862
  }
10592
10863
  /**
@@ -10595,9 +10866,37 @@ var AgentBuilder = class _AgentBuilder {
10595
10866
  * @returns This builder instance for chaining
10596
10867
  */
10597
10868
  asParallel(subAgents) {
10598
- this.warnIfLocked("asParallel");
10869
+ if (this.definitionLocked) {
10870
+ this.logger.warn(
10871
+ "AgentBuilder: asParallel() ignored; builder locked by withAgent()",
10872
+ {
10873
+ suggestion: "Call asParallel() before withAgent().",
10874
+ context: { agentName: this.config.name }
10875
+ }
10876
+ );
10877
+ return this;
10878
+ }
10599
10879
  this.agentType = "parallel";
10600
10880
  this.config.subAgents = subAgents;
10881
+ if (this.config.outputKey) {
10882
+ this.logger.warn(
10883
+ "AgentBuilder: outputKey ignored for parallel agent aggregator; removed",
10884
+ {
10885
+ suggestion: "Assign outputKey on individual sub-agents if needed.",
10886
+ context: { previousValue: this.config.outputKey }
10887
+ }
10888
+ );
10889
+ this.config.outputKey = void 0;
10890
+ }
10891
+ if (this.config.outputSchema) {
10892
+ this.logger.warn(
10893
+ "AgentBuilder: outputSchema cannot be applied to parallel aggregator; removed",
10894
+ {
10895
+ suggestion: "Apply schemas to sub-agents individually."
10896
+ }
10897
+ );
10898
+ this.config.outputSchema = void 0;
10899
+ }
10601
10900
  return this;
10602
10901
  }
10603
10902
  /**
@@ -10650,9 +10949,11 @@ var AgentBuilder = class _AgentBuilder {
10650
10949
  */
10651
10950
  withSession(session) {
10652
10951
  if (!this.sessionService) {
10653
- throw new Error(
10654
- "Session service must be configured before using withSession(). Call withSessionService() first, or use withQuickSession() for in-memory sessions."
10655
- );
10952
+ const msg = "Session service must be configured before using withSession(). Call withSessionService() first, or use withQuickSession() for in-memory sessions.";
10953
+ this.logger.error(msg, {
10954
+ suggestion: "Invoke withSessionService() prior to withSession()."
10955
+ });
10956
+ throw new Error(msg);
10656
10957
  }
10657
10958
  this.sessionOptions = {
10658
10959
  ...this.sessionOptions,
@@ -10723,7 +11024,12 @@ var AgentBuilder = class _AgentBuilder {
10723
11024
  const baseRunner = new Runner(runnerConfig);
10724
11025
  runner = this.createEnhancedRunner(baseRunner, session);
10725
11026
  }
10726
- return { agent, runner, session };
11027
+ return {
11028
+ agent,
11029
+ runner,
11030
+ session,
11031
+ sessionService: this.sessionService
11032
+ };
10727
11033
  }
10728
11034
  /**
10729
11035
  * Type-safe build method for agents with output schemas
@@ -10751,7 +11057,11 @@ var AgentBuilder = class _AgentBuilder {
10751
11057
  switch (this.agentType) {
10752
11058
  case "llm": {
10753
11059
  if (!this.config.model) {
10754
- throw new Error("Model is required for LLM agent");
11060
+ const msg = "Model is required for LLM agent";
11061
+ this.logger.error(msg, {
11062
+ suggestion: "Call withModel() before build()."
11063
+ });
11064
+ throw new Error(msg);
10755
11065
  }
10756
11066
  const model = this.config.model;
10757
11067
  return new LlmAgent({
@@ -10775,7 +11085,11 @@ var AgentBuilder = class _AgentBuilder {
10775
11085
  }
10776
11086
  case "sequential":
10777
11087
  if (!this.config.subAgents || !Array.isArray(this.config.subAgents) || this.config.subAgents.length === 0) {
10778
- throw new Error("Sub-agents required for sequential agent");
11088
+ const msg = "Sub-agents required for sequential agent";
11089
+ this.logger.error(msg, {
11090
+ suggestion: "Provide at least one sub-agent."
11091
+ });
11092
+ throw new Error(msg);
10779
11093
  }
10780
11094
  return new SequentialAgent({
10781
11095
  name: this.config.name,
@@ -10784,7 +11098,11 @@ var AgentBuilder = class _AgentBuilder {
10784
11098
  });
10785
11099
  case "parallel":
10786
11100
  if (!this.config.subAgents || !Array.isArray(this.config.subAgents) || this.config.subAgents.length === 0) {
10787
- throw new Error("Sub-agents required for parallel agent");
11101
+ const msg = "Sub-agents required for parallel agent";
11102
+ this.logger.error(msg, {
11103
+ suggestion: "Provide at least one sub-agent."
11104
+ });
11105
+ throw new Error(msg);
10788
11106
  }
10789
11107
  return new ParallelAgent({
10790
11108
  name: this.config.name,
@@ -10793,7 +11111,11 @@ var AgentBuilder = class _AgentBuilder {
10793
11111
  });
10794
11112
  case "loop":
10795
11113
  if (!this.config.subAgents || !Array.isArray(this.config.subAgents) || this.config.subAgents.length === 0) {
10796
- throw new Error("Sub-agents required for loop agent");
11114
+ const msg = "Sub-agents required for loop agent";
11115
+ this.logger.error(msg, {
11116
+ suggestion: "Provide at least one sub-agent."
11117
+ });
11118
+ throw new Error(msg);
10797
11119
  }
10798
11120
  return new LoopAgent({
10799
11121
  name: this.config.name,
@@ -10803,7 +11125,11 @@ var AgentBuilder = class _AgentBuilder {
10803
11125
  });
10804
11126
  case "langgraph":
10805
11127
  if (!this.config.nodes || !Array.isArray(this.config.nodes) || this.config.nodes.length === 0 || !this.config.rootNode || typeof this.config.rootNode !== "string") {
10806
- throw new Error("Nodes and root node required for LangGraph agent");
11128
+ const msg = "Nodes and root node required for LangGraph agent";
11129
+ this.logger.error(msg, {
11130
+ suggestion: "Provide nodes[] and a valid rootNode string."
11131
+ });
11132
+ throw new Error(msg);
10807
11133
  }
10808
11134
  return new LangGraphAgent({
10809
11135
  name: this.config.name,
@@ -10837,11 +11163,16 @@ var AgentBuilder = class _AgentBuilder {
10837
11163
  createEnhancedRunner(baseRunner, session) {
10838
11164
  const sessionOptions = this.sessionOptions;
10839
11165
  const outputSchema = this.config.outputSchema;
11166
+ const agentType = this.agentType;
11167
+ const isMulti = agentType === "parallel" || agentType === "sequential";
11168
+ const subAgentNames = this.config.subAgents?.map((a) => a.name) || [];
10840
11169
  return {
10841
11170
  __outputSchema: outputSchema,
10842
11171
  async ask(message) {
10843
11172
  const newMessage = typeof message === "string" ? { parts: [{ text: message }] } : typeof message === "object" && "contents" in message ? { parts: message.contents[message.contents.length - 1].parts } : message;
10844
- let response = "";
11173
+ let combinedResponse = "";
11174
+ const perAgentBuffers = {};
11175
+ const authors = /* @__PURE__ */ new Set();
10845
11176
  if (!sessionOptions?.userId) {
10846
11177
  throw new Error("Session configuration is required");
10847
11178
  }
@@ -10855,45 +11186,45 @@ var AgentBuilder = class _AgentBuilder {
10855
11186
  (part) => (part && typeof part === "object" && "text" in part ? part.text : "") || ""
10856
11187
  ).join("");
10857
11188
  if (content) {
10858
- response += content;
11189
+ combinedResponse += content;
11190
+ const author = event.author || "";
11191
+ if (author && author !== "user") {
11192
+ authors.add(author);
11193
+ perAgentBuffers[author] = (perAgentBuffers[author] || "") + content;
11194
+ }
10859
11195
  }
10860
11196
  }
10861
11197
  }
11198
+ if (isMulti) {
11199
+ return subAgentNames.map((name) => ({
11200
+ agent: name,
11201
+ response: (perAgentBuffers[name] || "").trim()
11202
+ }));
11203
+ }
10862
11204
  if (outputSchema) {
10863
11205
  try {
10864
- const parsed = JSON.parse(response);
11206
+ const parsed = JSON.parse(combinedResponse);
10865
11207
  return outputSchema.parse(parsed);
10866
11208
  } catch (parseError) {
10867
11209
  try {
10868
- return outputSchema.parse(response);
11210
+ return outputSchema.parse(combinedResponse);
10869
11211
  } catch (validationError) {
10870
- return response.trim();
11212
+ throw new Error(
11213
+ `Failed to parse and validate LLM output against the schema.
11214
+ JSON parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}
11215
+ Zod validation error: ${validationError instanceof Error ? validationError.message : String(validationError)}
11216
+ Raw output: "${combinedResponse}"`
11217
+ );
10871
11218
  }
10872
11219
  }
10873
11220
  }
10874
- return response.trim();
11221
+ return combinedResponse.trim();
10875
11222
  },
10876
11223
  runAsync(params) {
10877
11224
  return baseRunner.runAsync(params);
10878
11225
  }
10879
11226
  };
10880
11227
  }
10881
- /**
10882
- * Warn (once per method) if the definition has been locked by withAgent().
10883
- */
10884
- warnIfLocked(method) {
10885
- if (!this.definitionLocked) return;
10886
- if (this.warnedMethods.has(method)) return;
10887
- this.warnedMethods.add(method);
10888
- if (process.env.NODE_ENV !== "production") {
10889
- const msg = `AgentBuilder: attempted to call ${method} after withAgent(); ignoring. (Wrap the agent first OR configure before withAgent).`;
10890
- if (this.logger && typeof this.logger.warn === "function") {
10891
- this.logger.warn(msg);
10892
- } else {
10893
- console.warn(msg);
10894
- }
10895
- }
10896
- }
10897
11228
  };
10898
11229
 
10899
11230
  // src/memory/index.ts