@ddlqhd/agent-sdk 0.1.1 → 0.2.1

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 (40) hide show
  1. package/README.md +2 -1
  2. package/dist/{chunk-742JTNYI.js → chunk-D3UZNLZO.js} +570 -77
  3. package/dist/chunk-D3UZNLZO.js.map +1 -0
  4. package/dist/{chunk-AJD3DTL7.cjs → chunk-JXAJQGV5.cjs} +756 -107
  5. package/dist/chunk-JXAJQGV5.cjs.map +1 -0
  6. package/dist/{chunk-DQFTAD3I.cjs → chunk-NYZD3THB.cjs} +573 -76
  7. package/dist/chunk-NYZD3THB.cjs.map +1 -0
  8. package/dist/{chunk-Q3L4GIBG.cjs → chunk-P2X3AMDK.cjs} +115 -117
  9. package/dist/chunk-P2X3AMDK.cjs.map +1 -0
  10. package/dist/{chunk-THKEF32L.js → chunk-TKUPLTGJ.js} +110 -114
  11. package/dist/chunk-TKUPLTGJ.js.map +1 -0
  12. package/dist/{chunk-DXMVWGLJ.js → chunk-UHENMHUS.js} +744 -100
  13. package/dist/chunk-UHENMHUS.js.map +1 -0
  14. package/dist/cli/index.cjs +40 -31
  15. package/dist/cli/index.cjs.map +1 -1
  16. package/dist/cli/index.js +14 -5
  17. package/dist/cli/index.js.map +1 -1
  18. package/dist/{index-DGPDMbW5.d.cts → index-CnrY1ZA2.d.ts} +36 -14
  19. package/dist/{index-nEfayAzD.d.ts → index-DzBt4ewK.d.cts} +36 -14
  20. package/dist/index.cjs +128 -88
  21. package/dist/index.d.cts +42 -22
  22. package/dist/index.d.ts +42 -22
  23. package/dist/index.js +3 -3
  24. package/dist/models/index.cjs +14 -10
  25. package/dist/models/index.d.cts +7 -2
  26. package/dist/models/index.d.ts +7 -2
  27. package/dist/models/index.js +1 -1
  28. package/dist/tools/index.cjs +65 -57
  29. package/dist/tools/index.d.cts +3 -3
  30. package/dist/tools/index.d.ts +3 -3
  31. package/dist/tools/index.js +1 -1
  32. package/dist/{types-BLf9IqRs.d.cts → types-BUwjMwNH.d.cts} +279 -13
  33. package/dist/{types-BLf9IqRs.d.ts → types-BUwjMwNH.d.ts} +279 -13
  34. package/package.json +11 -11
  35. package/dist/chunk-742JTNYI.js.map +0 -1
  36. package/dist/chunk-AJD3DTL7.cjs.map +0 -1
  37. package/dist/chunk-DQFTAD3I.cjs.map +0 -1
  38. package/dist/chunk-DXMVWGLJ.js.map +0 -1
  39. package/dist/chunk-Q3L4GIBG.cjs.map +0 -1
  40. package/dist/chunk-THKEF32L.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var chunkDQFTAD3I_cjs = require('./chunk-DQFTAD3I.cjs');
5
- var chunkQ3L4GIBG_cjs = require('./chunk-Q3L4GIBG.cjs');
4
+ var chunkNYZD3THB_cjs = require('./chunk-NYZD3THB.cjs');
5
+ var chunkP2X3AMDK_cjs = require('./chunk-P2X3AMDK.cjs');
6
6
  var fs = require('fs');
7
7
  var path = require('path');
8
8
  var url = require('url');
@@ -16,9 +16,28 @@ var child_process = require('child_process');
16
16
  var util = require('util');
17
17
 
18
18
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
19
- var pkgDir = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-AJD3DTL7.cjs', document.baseURI).href))));
19
+ var pkgDir = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-JXAJQGV5.cjs', document.baseURI).href))));
20
20
  var pkgPath = path.join(pkgDir, "..", "package.json");
21
21
  var PACKAGE_VERSION = JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version;
22
+
23
+ // src/core/types.ts
24
+ var MODEL_STREAM_EVENT_TYPES = [
25
+ "text_start",
26
+ "text_delta",
27
+ "text_end",
28
+ "tool_call_start",
29
+ "tool_call_delta",
30
+ "tool_call",
31
+ "tool_call_end",
32
+ "thinking_start",
33
+ "thinking",
34
+ "thinking_end",
35
+ "model_usage"
36
+ ];
37
+ var MODEL_STREAM_EVENT_TYPE_SET = new Set(MODEL_STREAM_EVENT_TYPES);
38
+ function isModelStreamEventType(type) {
39
+ return MODEL_STREAM_EVENT_TYPE_SET.has(type);
40
+ }
22
41
  var JsonlStorage = class {
23
42
  basePath;
24
43
  constructor(config = {}) {
@@ -421,6 +440,7 @@ When to use tools:
421
440
  - **Glob** to find paths by pattern \u2014 not \`find\` or \`ls\` for discovery
422
441
  - **Grep** to search file contents \u2014 not \`grep\` or \`rg\` in the shell (built-in line-by-line regex search; correct integration)
423
442
  - **WebFetch** / **WebSearch** when the task needs HTTP or web search (when configured)
443
+ - **TodoWrite** for structured multi-step task lists (see **Task Management with Todo List** below)
424
444
 
425
445
  Reserve **Bash** for real shell needs: \`git\`, package managers, build commands, compilers, and other operations that require a shell or are not covered above.
426
446
 
@@ -441,7 +461,7 @@ Skills are instruction guides for specialized tasks. When activated, you receive
441
461
 
442
462
  ## Task Execution Principles
443
463
 
444
- 1. **Plan First for Complex Tasks**: For multi-step tasks, you MUST call \`TaskCreate\` BEFORE any other tool. Do NOT skip this step.
464
+ 1. **Plan First for Complex Tasks**: For multi-step tasks, you MUST call \`TodoWrite\` BEFORE any other tool. Do NOT skip this step.
445
465
  2. **Be Direct**: Go straight to the point. Try the simplest approach first.
446
466
  3. **Be Concise**: If you can say it in one sentence, don't use three.
447
467
  4. **Read Before Modify**: Always understand existing code before changing it.
@@ -451,17 +471,17 @@ Skills are instruction guides for specialized tasks. When activated, you receive
451
471
 
452
472
  ## Task Management with Todo List
453
473
 
454
- **MANDATORY**: For multi-step tasks, call \`TaskCreate\` FIRST.
474
+ **MANDATORY**: For multi-step tasks, call \`TodoWrite\` FIRST.
455
475
 
456
476
  **Workflow:**
457
- 1. Receive complex task -> call \`TaskCreate\` immediately
458
- 2. Start first task (in_progress) -> complete -> mark completed
459
- 3. Move to next task -> repeat
460
- 4. Cancel tasks that become irrelevant
477
+ 1. Receive complex task -> call \`TodoWrite\` immediately
478
+ 2. Mark tasks \`in_progress\` / \`completed\` as you work; several items may be \`in_progress\` at once when work is parallel
479
+ 3. **Replan freely:** if the plan was wrong or incomplete, call \`TodoWrite\` again with a revised full list (add, remove, reorder, or rewrite steps)
480
+ 4. **Before you finish your response** for a multi-step request, ensure **every** todo is \`completed\` via \`TodoWrite\` (unless you intentionally pause for a follow-up turn). Do not leave \`pending\` / \`in_progress\` items when the work is done
461
481
 
462
482
  **Example:**
463
483
  User: "Open Google, search X, summarize results, open first link, extract info"
464
- -> Multi-step task detected -> call \`TaskCreate\` FIRST, then execute.
484
+ -> Multi-step task detected -> call \`TodoWrite\` FIRST, then execute.
465
485
 
466
486
  ## Output Format
467
487
 
@@ -562,8 +582,16 @@ ${combinedContent}
562
582
  };
563
583
  }
564
584
  };
565
- function isStdioConfig(config) {
566
- return "command" in config;
585
+
586
+ // src/mcp/mcp-tool-name.ts
587
+ function formatMcpToolName(serverName, toolName) {
588
+ return `mcp__${serverName}__${toolName}`;
589
+ }
590
+ function isMcpPrefixedToolName(name) {
591
+ if (!name.startsWith("mcp__")) {
592
+ return false;
593
+ }
594
+ return name.slice("mcp__".length).includes("__");
567
595
  }
568
596
  var MCPClient = class {
569
597
  client;
@@ -578,13 +606,21 @@ var MCPClient = class {
578
606
  { name: "agent-sdk-client", version: PACKAGE_VERSION },
579
607
  { capabilities: {} }
580
608
  );
581
- if (isStdioConfig(config)) {
609
+ if (config.transport === "stdio") {
610
+ if (!config.command) {
611
+ throw new Error(`MCP server "${config.name}": stdio transport requires command`);
612
+ }
613
+ const cwd = (config.cwd ?? "").trim();
582
614
  this.transport = new stdio_js.StdioClientTransport({
583
615
  command: config.command,
584
616
  args: config.args,
585
- env: config.env
617
+ env: config.env,
618
+ ...cwd !== "" ? { cwd } : {}
586
619
  });
587
620
  } else {
621
+ if (!config.url) {
622
+ throw new Error(`MCP server "${config.name}": http transport requires url`);
623
+ }
588
624
  this.transport = new streamableHttp_js.StreamableHTTPClientTransport(
589
625
  new URL(config.url),
590
626
  { requestInit: { headers: config.headers } }
@@ -693,7 +729,7 @@ var MCPClient = class {
693
729
  }
694
730
  toToolDefinitions() {
695
731
  return this._tools.map((tool) => ({
696
- name: `mcp_${this._name}__${tool.name}`,
732
+ name: formatMcpToolName(this._name, tool.name),
697
733
  description: tool.description || `MCP tool: ${tool.name}`,
698
734
  parameters: this.convertSchema(tool.inputSchema),
699
735
  handler: async (args) => this.callTool(tool.name, args),
@@ -768,7 +804,7 @@ var MCPAdapter = class {
768
804
  await client.connect();
769
805
  this.clients.set(config.name, client);
770
806
  for (const tool of client.tools) {
771
- const fullName = `mcp_${config.name}__${tool.name}`;
807
+ const fullName = formatMcpToolName(config.name, tool.name);
772
808
  this.toolMap.set(fullName, { client, toolName: tool.name });
773
809
  }
774
810
  }
@@ -1320,9 +1356,12 @@ var StreamChunkProcessor = class {
1320
1356
  currentToolCall = null;
1321
1357
  lastUsage;
1322
1358
  inTextBlock = false;
1359
+ inThinkingBlock = false;
1323
1360
  emitTextBoundaries;
1361
+ emitThinkingBoundaries;
1324
1362
  constructor(options) {
1325
1363
  this.emitTextBoundaries = options?.emitTextBoundaries ?? true;
1364
+ this.emitThinkingBoundaries = options?.emitThinkingBoundaries ?? true;
1326
1365
  }
1327
1366
  processChunk(chunk) {
1328
1367
  const events = [];
@@ -1332,8 +1371,15 @@ var StreamChunkProcessor = class {
1332
1371
  this.inTextBlock = false;
1333
1372
  }
1334
1373
  };
1374
+ const endThinkingBlockIfNeeded = () => {
1375
+ if (this.emitThinkingBoundaries && this.inThinkingBlock) {
1376
+ events.push({ type: "thinking_end" });
1377
+ this.inThinkingBlock = false;
1378
+ }
1379
+ };
1335
1380
  switch (chunk.type) {
1336
1381
  case "text":
1382
+ endThinkingBlockIfNeeded();
1337
1383
  if (chunk.content) {
1338
1384
  if (this.emitTextBoundaries && !this.inTextBlock) {
1339
1385
  events.push({ type: "text_start" });
@@ -1343,6 +1389,7 @@ var StreamChunkProcessor = class {
1343
1389
  }
1344
1390
  break;
1345
1391
  case "tool_call_start":
1392
+ endThinkingBlockIfNeeded();
1346
1393
  endTextBlockIfNeeded();
1347
1394
  if (this.currentToolCall) {
1348
1395
  events.push(...this.finalizeStreamingToolCall());
@@ -1388,6 +1435,7 @@ var StreamChunkProcessor = class {
1388
1435
  }
1389
1436
  break;
1390
1437
  case "tool_call": {
1438
+ endThinkingBlockIfNeeded();
1391
1439
  endTextBlockIfNeeded();
1392
1440
  if (!chunk.toolCall) break;
1393
1441
  const tc = chunk.toolCall;
@@ -1406,6 +1454,7 @@ var StreamChunkProcessor = class {
1406
1454
  break;
1407
1455
  }
1408
1456
  case "tool_call_end":
1457
+ endThinkingBlockIfNeeded();
1409
1458
  endTextBlockIfNeeded();
1410
1459
  if (this.currentToolCall) {
1411
1460
  events.push(...this.finalizeStreamingToolCall());
@@ -1413,6 +1462,16 @@ var StreamChunkProcessor = class {
1413
1462
  break;
1414
1463
  case "thinking":
1415
1464
  endTextBlockIfNeeded();
1465
+ if (this.emitThinkingBoundaries) {
1466
+ const opensBlock = !this.inThinkingBlock && (chunk.content !== void 0 || chunk.signature !== void 0);
1467
+ if (opensBlock) {
1468
+ events.push({
1469
+ type: "thinking_start",
1470
+ ...chunk.signature !== void 0 ? { signature: chunk.signature } : {}
1471
+ });
1472
+ this.inThinkingBlock = true;
1473
+ }
1474
+ }
1416
1475
  if (chunk.content !== void 0) {
1417
1476
  events.push({
1418
1477
  type: "thinking",
@@ -1421,7 +1480,12 @@ var StreamChunkProcessor = class {
1421
1480
  });
1422
1481
  }
1423
1482
  break;
1483
+ case "thinking_block_end":
1484
+ endThinkingBlockIfNeeded();
1485
+ endTextBlockIfNeeded();
1486
+ break;
1424
1487
  case "error":
1488
+ endThinkingBlockIfNeeded();
1425
1489
  endTextBlockIfNeeded();
1426
1490
  if (chunk.error) {
1427
1491
  events.push({
@@ -1449,6 +1513,10 @@ var StreamChunkProcessor = class {
1449
1513
  /** End open text block and finalize any in-progress streamed tool call. */
1450
1514
  flush() {
1451
1515
  const events = [];
1516
+ if (this.emitThinkingBoundaries && this.inThinkingBlock) {
1517
+ events.push({ type: "thinking_end" });
1518
+ this.inThinkingBlock = false;
1519
+ }
1452
1520
  if (this.emitTextBoundaries && this.inTextBlock) {
1453
1521
  events.push({ type: "text_end" });
1454
1522
  this.inTextBlock = false;
@@ -1593,11 +1661,52 @@ var SummarizationCompressor = class {
1593
1661
  this.options = options;
1594
1662
  }
1595
1663
  name = "summarization";
1664
+ getSessionId() {
1665
+ return this.options.sessionIdProvider?.() ?? this.options.sessionId;
1666
+ }
1596
1667
  async compress(messages, targetTokens) {
1668
+ const startedAt = Date.now();
1597
1669
  const preserveRecent = this.options.preserveRecent ?? 6;
1670
+ const sessionId = this.getSessionId();
1671
+ chunkNYZD3THB_cjs.emitSDKLog({
1672
+ logger: this.options.logger,
1673
+ logLevel: this.options.logLevel,
1674
+ level: "info",
1675
+ event: {
1676
+ component: "memory",
1677
+ event: "context.compress.start",
1678
+ message: "Starting context compression",
1679
+ operation: "compress",
1680
+ sessionId,
1681
+ metadata: {
1682
+ compressor: this.name,
1683
+ messageCount: messages.length,
1684
+ targetTokens,
1685
+ preserveRecent
1686
+ }
1687
+ }
1688
+ });
1598
1689
  const systemMessages = messages.filter((m) => m.role === "system");
1599
1690
  const nonSystemMessages = messages.filter((m) => m.role !== "system");
1600
1691
  if (nonSystemMessages.length <= preserveRecent) {
1692
+ chunkNYZD3THB_cjs.emitSDKLog({
1693
+ logger: this.options.logger,
1694
+ logLevel: this.options.logLevel,
1695
+ level: "debug",
1696
+ event: {
1697
+ component: "memory",
1698
+ event: "context.compress.skipped",
1699
+ message: "Skipped compression because there are not enough messages",
1700
+ operation: "compress",
1701
+ sessionId,
1702
+ durationMs: Date.now() - startedAt,
1703
+ metadata: {
1704
+ compressor: this.name,
1705
+ messageCount: messages.length,
1706
+ preserveRecent
1707
+ }
1708
+ }
1709
+ });
1601
1710
  return messages;
1602
1711
  }
1603
1712
  const recentMessages = nonSystemMessages.slice(-preserveRecent);
@@ -1607,21 +1716,68 @@ var SummarizationCompressor = class {
1607
1716
  this.options.maxSummaryTokens ?? 4e3,
1608
1717
  Math.floor(targetTokens * 0.3)
1609
1718
  );
1610
- const summaryResponse = await this.model.complete({
1611
- messages: [
1612
- { role: "system", content: summaryPrompt },
1613
- ...messagesToSummarize
1614
- ],
1615
- maxTokens
1616
- });
1617
- return [
1618
- ...systemMessages,
1619
- {
1620
- role: "system",
1621
- content: this.wrapSummary(summaryResponse.content)
1622
- },
1623
- ...recentMessages
1624
- ];
1719
+ try {
1720
+ const summaryResponse = await this.model.complete({
1721
+ messages: [
1722
+ { role: "system", content: summaryPrompt },
1723
+ ...messagesToSummarize
1724
+ ],
1725
+ maxTokens,
1726
+ logger: this.options.logger,
1727
+ logLevel: this.options.logLevel,
1728
+ redaction: this.options.redaction,
1729
+ sessionId
1730
+ });
1731
+ const compressedMessages = [
1732
+ ...systemMessages,
1733
+ {
1734
+ role: "system",
1735
+ content: this.wrapSummary(summaryResponse.content)
1736
+ },
1737
+ ...recentMessages
1738
+ ];
1739
+ chunkNYZD3THB_cjs.emitSDKLog({
1740
+ logger: this.options.logger,
1741
+ logLevel: this.options.logLevel,
1742
+ level: "info",
1743
+ event: {
1744
+ component: "memory",
1745
+ event: "context.compress.end",
1746
+ message: "Context compression completed",
1747
+ operation: "compress",
1748
+ sessionId,
1749
+ durationMs: Date.now() - startedAt,
1750
+ metadata: {
1751
+ compressor: this.name,
1752
+ originalMessageCount: messages.length,
1753
+ compressedMessageCount: compressedMessages.length
1754
+ }
1755
+ }
1756
+ });
1757
+ return compressedMessages;
1758
+ } catch (error) {
1759
+ const err = error instanceof Error ? error : new Error(String(error));
1760
+ chunkNYZD3THB_cjs.emitSDKLog({
1761
+ logger: this.options.logger,
1762
+ logLevel: this.options.logLevel,
1763
+ level: "error",
1764
+ event: {
1765
+ component: "memory",
1766
+ event: "context.compress.error",
1767
+ message: "Context compression failed",
1768
+ operation: "compress",
1769
+ sessionId,
1770
+ durationMs: Date.now() - startedAt,
1771
+ errorName: err.name,
1772
+ errorMessage: err.message,
1773
+ metadata: {
1774
+ compressor: this.name,
1775
+ messageCount: messages.length
1776
+ }
1777
+ }
1778
+ });
1779
+ throw err;
1780
+ }
1625
1781
  }
1626
1782
  /**
1627
1783
  * 构建默认摘要提示 (借鉴 Opencode 模板)
@@ -1807,21 +1963,7 @@ var ContextManager = class {
1807
1963
  };
1808
1964
 
1809
1965
  // src/core/agent.ts
1810
- function toMCPClientConfig(config, agentEnv) {
1811
- if (config.transport === "http") {
1812
- return {
1813
- name: config.name,
1814
- url: config.url,
1815
- headers: config.headers
1816
- };
1817
- }
1818
- return {
1819
- name: config.name,
1820
- command: config.command,
1821
- args: config.args,
1822
- env: chunkDQFTAD3I_cjs.mergeMcpStdioEnv(agentEnv, config.env)
1823
- };
1824
- }
1966
+ var DEFAULT_MAX_ITERATIONS = 400;
1825
1967
  var Agent = class _Agent {
1826
1968
  config;
1827
1969
  toolRegistry;
@@ -1847,29 +1989,31 @@ var Agent = class _Agent {
1847
1989
  return config.model;
1848
1990
  }
1849
1991
  if (config.modelConfig) {
1850
- return chunkDQFTAD3I_cjs.createModel(config.modelConfig, config.env);
1992
+ return chunkNYZD3THB_cjs.createModel(config.modelConfig, config.env);
1851
1993
  }
1852
1994
  throw new Error("AgentConfig: `model` or `modelConfig` is required");
1853
1995
  }
1854
1996
  constructor(config) {
1855
1997
  const resolvedModel = _Agent.resolveModel(config);
1856
1998
  this.config = {
1857
- maxIterations: 200,
1999
+ maxIterations: DEFAULT_MAX_ITERATIONS,
1858
2000
  streaming: true,
1859
2001
  ...config,
1860
2002
  model: resolvedModel,
1861
2003
  modelConfig: void 0
1862
2004
  };
2005
+ this.config.maxIterations = this.config.maxIterations ?? DEFAULT_MAX_ITERATIONS;
1863
2006
  this.skillRegistry = createSkillRegistry({
1864
2007
  cwd: this.config.cwd,
1865
2008
  userBasePath: this.config.userBasePath
1866
2009
  });
1867
- this.toolRegistry = new chunkQ3L4GIBG_cjs.ToolRegistry({
2010
+ this.toolRegistry = new chunkP2X3AMDK_cjs.ToolRegistry({
1868
2011
  executionPolicy: {
1869
2012
  disallowedTools: this.config.disallowedTools,
1870
2013
  allowedTools: this.config.allowedTools,
1871
2014
  canUseTool: this.config.canUseTool
1872
- }
2015
+ },
2016
+ hookObserver: this.config.callbacks?.lifecycle?.hooks
1873
2017
  });
1874
2018
  this.registerInitialTools();
1875
2019
  const subagentEnabled = this.config.subagent?.enabled !== false;
@@ -1877,7 +2021,7 @@ var Agent = class _Agent {
1877
2021
  if (this.toolRegistry.has("Agent")) {
1878
2022
  this.toolRegistry.unregister("Agent");
1879
2023
  }
1880
- this.toolRegistry.register(chunkQ3L4GIBG_cjs.createAgentTool({
2024
+ this.toolRegistry.register(chunkP2X3AMDK_cjs.createAgentTool({
1881
2025
  runner: (request, context) => this.runSubagent(request, context)
1882
2026
  }));
1883
2027
  } else if (this.toolRegistry.has("Agent")) {
@@ -1886,7 +2030,7 @@ var Agent = class _Agent {
1886
2030
  if (this.config.hookManager) {
1887
2031
  this.toolRegistry.setHookManager(this.config.hookManager);
1888
2032
  } else if (this.config.hookConfigDir !== void 0) {
1889
- const hm = chunkQ3L4GIBG_cjs.HookManager.create();
2033
+ const hm = chunkP2X3AMDK_cjs.HookManager.create();
1890
2034
  this.toolRegistry.setHookManager(hm);
1891
2035
  this.hookDiscoverPromise = hm.discoverAndLoad(this.config.hookConfigDir);
1892
2036
  }
@@ -1896,10 +2040,27 @@ var Agent = class _Agent {
1896
2040
  });
1897
2041
  if (this.config.contextManagement !== false) {
1898
2042
  const cmConfig = this.config.contextManagement === true ? {} : this.config.contextManagement ?? {};
1899
- this.contextManager = new ContextManager(this.config.model, cmConfig);
2043
+ const compressor = cmConfig.compressor ?? new SummarizationCompressor(this.config.model, {
2044
+ logger: this.config.logger,
2045
+ logLevel: this.config.logLevel,
2046
+ redaction: this.config.redaction,
2047
+ sessionIdProvider: () => this.sessionManager.sessionId ?? void 0
2048
+ });
2049
+ this.contextManager = new ContextManager(this.config.model, {
2050
+ ...cmConfig,
2051
+ compressor
2052
+ });
1900
2053
  }
1901
2054
  this.initPromise = this.initializeAsync();
1902
2055
  }
2056
+ log(level, event) {
2057
+ chunkNYZD3THB_cjs.emitSDKLog({
2058
+ logger: this.config.logger,
2059
+ logLevel: this.config.logLevel,
2060
+ level,
2061
+ event
2062
+ });
2063
+ }
1903
2064
  /**
1904
2065
  * 注册内置 + 自定义工具,或仅 {@link AgentConfig.exclusiveTools}。
1905
2066
  */
@@ -1913,7 +2074,7 @@ var Agent = class _Agent {
1913
2074
  }
1914
2075
  return;
1915
2076
  }
1916
- const builtins = chunkQ3L4GIBG_cjs.getAllBuiltinTools(this.skillRegistry, {
2077
+ const builtins = chunkP2X3AMDK_cjs.getAllBuiltinTools(this.skillRegistry, {
1917
2078
  resolve: this.config.askUserQuestion
1918
2079
  }).filter((t) => !this.toolRegistry.isDisallowed(t.name));
1919
2080
  this.toolRegistry.registerMany(builtins);
@@ -1944,7 +2105,14 @@ var Agent = class _Agent {
1944
2105
  await this.initializeMCP(this.config.mcpServers);
1945
2106
  }
1946
2107
  } catch (err) {
1947
- console.error("Failed to initialize:", err);
2108
+ const error = err instanceof Error ? err : new Error(String(err));
2109
+ this.log("error", {
2110
+ component: "agent",
2111
+ event: "agent.initialize.error",
2112
+ message: "Failed to initialize agent resources",
2113
+ errorName: error.name,
2114
+ errorMessage: error.message
2115
+ });
1948
2116
  }
1949
2117
  }
1950
2118
  /**
@@ -1963,7 +2131,17 @@ var Agent = class _Agent {
1963
2131
  try {
1964
2132
  await this.connectMCP(serverConfig);
1965
2133
  } catch (err) {
1966
- console.error(`Failed to connect MCP server "${serverConfig.name}":`, err);
2134
+ const error = err instanceof Error ? err : new Error(String(err));
2135
+ this.log("error", {
2136
+ component: "tooling",
2137
+ event: "mcp.connect.error",
2138
+ message: `Failed to connect MCP server "${serverConfig.name}"`,
2139
+ errorName: error.name,
2140
+ errorMessage: error.message,
2141
+ metadata: {
2142
+ serverName: serverConfig.name
2143
+ }
2144
+ });
1967
2145
  }
1968
2146
  }
1969
2147
  }
@@ -1975,6 +2153,74 @@ var Agent = class _Agent {
1975
2153
  sessionId: this.sessionManager.sessionId ?? void 0
1976
2154
  };
1977
2155
  }
2156
+ baseRunContext() {
2157
+ return {
2158
+ sessionId: this.sessionManager.sessionId ?? void 0,
2159
+ cwd: this.config.cwd
2160
+ };
2161
+ }
2162
+ /**
2163
+ * 分发流式事件到 `callbacks.onEvent` 与 `lifecycle.onModelEvent` / `onModelUsage`。
2164
+ */
2165
+ emitStreamEvent(event) {
2166
+ try {
2167
+ this.config.callbacks?.onEvent?.(event);
2168
+ const lifecycle = this.config.callbacks?.lifecycle;
2169
+ if (lifecycle?.onModelEvent && isModelStreamEventType(event.type)) {
2170
+ lifecycle.onModelEvent(event);
2171
+ }
2172
+ if (event.type === "model_usage" && lifecycle?.onModelUsage) {
2173
+ lifecycle.onModelUsage({
2174
+ ...this.baseRunContext(),
2175
+ usage: event.usage,
2176
+ iteration: event.iteration,
2177
+ phase: event.phase
2178
+ });
2179
+ }
2180
+ } catch (err) {
2181
+ const e = err instanceof Error ? err : new Error(String(err));
2182
+ this.emitAgentError(e, { phase: "lifecycle_callback" });
2183
+ }
2184
+ }
2185
+ /** 标注、触发观察回调并返回供 `yield` 的事件 */
2186
+ streamOut(event, iteration) {
2187
+ const out = iteration !== void 0 ? this.annotateStreamEvent(event, iteration) : this.annotateStreamEvent(event);
2188
+ this.emitStreamEvent(out);
2189
+ return out;
2190
+ }
2191
+ emitAgentError(error, ctx) {
2192
+ try {
2193
+ this.config.callbacks?.lifecycle?.onAgentError?.(error, ctx);
2194
+ this.config.callbacks?.onError?.(error, ctx);
2195
+ } catch (err) {
2196
+ this.log("error", {
2197
+ component: "agent",
2198
+ event: "agent.callback.error",
2199
+ message: "Agent error callback threw",
2200
+ errorName: err instanceof Error ? err.name : "Error",
2201
+ errorMessage: err instanceof Error ? err.message : String(err)
2202
+ });
2203
+ }
2204
+ }
2205
+ safeLifecycleVoid(fn) {
2206
+ try {
2207
+ fn();
2208
+ } catch (err) {
2209
+ const e = err instanceof Error ? err : new Error(String(err));
2210
+ this.emitAgentError(e, { phase: "lifecycle_callback" });
2211
+ }
2212
+ }
2213
+ emitRunEnd(args) {
2214
+ this.safeLifecycleVoid(() => {
2215
+ this.config.callbacks?.lifecycle?.onRunEnd?.({
2216
+ ...this.baseRunContext(),
2217
+ reason: args.reason,
2218
+ iterations: args.iterations,
2219
+ usage: args.usage,
2220
+ error: args.error
2221
+ });
2222
+ });
2223
+ }
1978
2224
  static createEmptySessionUsage() {
1979
2225
  return {
1980
2226
  contextTokens: 0,
@@ -1998,8 +2244,8 @@ var Agent = class _Agent {
1998
2244
  let envSection = "";
1999
2245
  if (shouldIncludeEnv) {
2000
2246
  const cwd = this.config.cwd || process.cwd();
2001
- const envInfo = chunkQ3L4GIBG_cjs.getEnvironmentInfo(cwd);
2002
- envSection = chunkQ3L4GIBG_cjs.formatEnvironmentSection(envInfo);
2247
+ const envInfo = chunkP2X3AMDK_cjs.getEnvironmentInfo(cwd);
2248
+ envSection = chunkP2X3AMDK_cjs.formatEnvironmentSection(envInfo);
2003
2249
  }
2004
2250
  if (!customPrompt) {
2005
2251
  let basePrompt = DEFAULT_SYSTEM_PROMPT;
@@ -2036,20 +2282,45 @@ ${content}`;
2036
2282
  }
2037
2283
  try {
2038
2284
  this.messages = await this.sessionManager.resumeSession(options.sessionId);
2285
+ this.safeLifecycleVoid(() => {
2286
+ this.config.callbacks?.lifecycle?.onSessionResume?.({
2287
+ sessionId: options.sessionId,
2288
+ messageCount: this.messages.length
2289
+ });
2290
+ });
2039
2291
  } catch {
2040
2292
  this.sessionManager.createSession(options.sessionId);
2293
+ this.safeLifecycleVoid(() => {
2294
+ this.config.callbacks?.lifecycle?.onSessionCreate?.({
2295
+ sessionId: this.sessionManager.sessionId ?? void 0
2296
+ });
2297
+ });
2041
2298
  }
2042
2299
  } else if (!this.sessionManager.sessionId) {
2043
2300
  this.resetSessionState();
2044
2301
  this.sessionManager.createSession();
2302
+ this.safeLifecycleVoid(() => {
2303
+ this.config.callbacks?.lifecycle?.onSessionCreate?.({
2304
+ sessionId: this.sessionManager.sessionId ?? void 0
2305
+ });
2306
+ });
2045
2307
  }
2046
2308
  if (this.messages.length === 0) {
2309
+ const usedRuntimePrompt = options?.systemPrompt !== void 0;
2047
2310
  const systemPrompt = this.buildSystemPrompt(
2048
2311
  options?.systemPrompt || this.config.systemPrompt
2049
2312
  );
2050
- this.messages.push({
2313
+ const sysMsg = {
2051
2314
  role: "system",
2052
2315
  content: systemPrompt
2316
+ };
2317
+ this.messages.push(sysMsg);
2318
+ this.safeLifecycleVoid(() => {
2319
+ this.config.callbacks?.lifecycle?.onSystemMessage?.(
2320
+ sysMsg,
2321
+ usedRuntimePrompt ? "runtime_prompt" : "default_prompt",
2322
+ this.baseRunContext()
2323
+ );
2053
2324
  });
2054
2325
  }
2055
2326
  if (this.config.memory !== false) {
@@ -2058,9 +2329,13 @@ ${content}`;
2058
2329
  const memoryManager = new MemoryManager(this.config.cwd, this.config.memoryConfig, this.config.userBasePath);
2059
2330
  const memoryContent = memoryManager.loadMemory();
2060
2331
  if (memoryContent) {
2061
- this.messages.push({
2332
+ const memMsg = {
2062
2333
  role: "system",
2063
2334
  content: memoryContent
2335
+ };
2336
+ this.messages.push(memMsg);
2337
+ this.safeLifecycleVoid(() => {
2338
+ this.config.callbacks?.lifecycle?.onSystemMessage?.(memMsg, "memory", this.baseRunContext());
2064
2339
  });
2065
2340
  }
2066
2341
  }
@@ -2070,21 +2345,60 @@ ${content}`;
2070
2345
  if (processed.invoked) {
2071
2346
  processedInput = processed.prompt;
2072
2347
  }
2073
- this.messages.push({
2348
+ const userMsg = {
2074
2349
  role: "user",
2075
2350
  content: processedInput
2351
+ };
2352
+ this.messages.push(userMsg);
2353
+ this.safeLifecycleVoid(() => {
2354
+ this.config.callbacks?.lifecycle?.onUserMessage?.(
2355
+ userMsg,
2356
+ processed.invoked ? "processed_input" : "raw_input",
2357
+ this.baseRunContext()
2358
+ );
2359
+ });
2360
+ this.log("info", {
2361
+ component: "agent",
2362
+ event: "agent.run.start",
2363
+ message: "Starting agent turn",
2364
+ sessionId: this.sessionManager.sessionId ?? void 0,
2365
+ metadata: {
2366
+ inputLength: input.length,
2367
+ processedInputLength: processedInput.length,
2368
+ includeRawStreamEvents: options?.includeRawStreamEvents === true
2369
+ }
2370
+ });
2371
+ this.safeLifecycleVoid(() => {
2372
+ this.config.callbacks?.lifecycle?.onRunStart?.({
2373
+ ...this.baseRunContext(),
2374
+ inputLength: input.length,
2375
+ processedInputLength: processedInput.length,
2376
+ resumeSessionId: options?.sessionId
2377
+ });
2076
2378
  });
2077
- yield this.annotateStreamEvent({ type: "start", timestamp: Date.now() });
2379
+ yield this.streamOut({ type: "start", timestamp: Date.now() });
2078
2380
  try {
2079
- const maxIterations = this.config.maxIterations || 10;
2381
+ const maxIterations = Math.max(1, this.config.maxIterations ?? DEFAULT_MAX_ITERATIONS);
2080
2382
  let totalUsage = {
2081
2383
  promptTokens: 0,
2082
2384
  completionTokens: 0,
2083
2385
  totalTokens: 0
2084
2386
  };
2085
- for (let iteration = 0; iteration < maxIterations; iteration++) {
2387
+ let iteration = 0;
2388
+ for (; iteration < maxIterations; iteration++) {
2086
2389
  if (signal?.aborted) {
2087
- yield this.annotateStreamEvent(
2390
+ this.log("info", {
2391
+ component: "agent",
2392
+ event: "agent.run.aborted",
2393
+ message: "Agent turn aborted before model request",
2394
+ sessionId: this.sessionManager.sessionId ?? void 0,
2395
+ iteration
2396
+ });
2397
+ this.emitRunEnd({ reason: "aborted", iterations: iteration, usage: totalUsage });
2398
+ this.safeLifecycleVoid(() => {
2399
+ this.config.callbacks?.lifecycle?.onRunAbort?.({ ...this.baseRunContext(), iteration });
2400
+ });
2401
+ yield this.streamOut(
2088
2402
  {
2089
2403
  type: "end",
2090
2404
  usage: totalUsage,
@@ -2095,10 +2409,49 @@ ${content}`;
2095
2409
  );
2096
2410
  return;
2097
2411
  }
2412
+ this.log("debug", {
2413
+ component: "agent",
2414
+ event: "agent.iteration.start",
2415
+ message: "Starting agent iteration",
2416
+ sessionId: this.sessionManager.sessionId ?? void 0,
2417
+ iteration,
2418
+ metadata: {
2419
+ messageCount: this.messages.length,
2420
+ toolCount: this.toolRegistry.getAll().length
2421
+ }
2422
+ });
2423
+ this.safeLifecycleVoid(() => {
2424
+ this.config.callbacks?.lifecycle?.onIterationStart?.({
2425
+ ...this.baseRunContext(),
2426
+ iteration,
2427
+ messageCount: this.messages.length,
2428
+ toolCount: this.toolRegistry.getAll().length
2429
+ });
2430
+ });
2098
2431
  const contextEvents = await this.checkContextCompression();
2099
2432
  for (const event of contextEvents) {
2100
- yield this.annotateStreamEvent(event, iteration);
2433
+ if (event.type === "context_compressed") {
2434
+ this.safeLifecycleVoid(() => {
2435
+ this.config.callbacks?.lifecycle?.onContextCompressed?.({
2436
+ ...this.baseRunContext(),
2437
+ iteration,
2438
+ stats: event.stats
2439
+ });
2440
+ });
2441
+ }
2442
+ yield this.streamOut(event, iteration);
2101
2443
  }
2444
+ this.safeLifecycleVoid(() => {
2445
+ this.config.callbacks?.lifecycle?.onModelRequestStart?.({
2446
+ ...this.baseRunContext(),
2447
+ iteration,
2448
+ messageCount: this.messages.length,
2449
+ toolCount: this.toolRegistry.getAll().length,
2450
+ temperature: this.config.temperature,
2451
+ maxTokens: this.config.maxTokens,
2452
+ includeRawStreamEvents: options?.includeRawStreamEvents
2453
+ });
2454
+ });
2102
2455
  const modelParams = {
2103
2456
  messages: this.messages,
2104
2457
  tools: this.toolRegistry.getAll(),
@@ -2106,7 +2459,10 @@ ${content}`;
2106
2459
  maxTokens: this.config.maxTokens,
2107
2460
  signal,
2108
2461
  includeRawStreamEvents: options?.includeRawStreamEvents,
2109
- sessionId: this.sessionManager.sessionId ?? void 0
2462
+ sessionId: this.sessionManager.sessionId ?? void 0,
2463
+ logger: this.config.logger,
2464
+ logLevel: this.config.logLevel,
2465
+ redaction: this.config.redaction
2110
2466
  };
2111
2467
  const stream = this.config.model.stream(modelParams);
2112
2468
  let hasToolCalls = false;
@@ -2149,7 +2505,7 @@ ${content}`;
2149
2505
  for await (const chunk of stream) {
2150
2506
  if (signal?.aborted) {
2151
2507
  for (const event of chunkProcessor.flush()) {
2152
- const out = this.annotateStreamEvent(event, iteration);
2508
+ const out = this.streamOut(event, iteration);
2153
2509
  yield out;
2154
2510
  applyStreamOut(out);
2155
2511
  }
@@ -2165,13 +2521,37 @@ ${content}`;
2165
2521
  ];
2166
2522
  }
2167
2523
  this.messages.push(assistantMessage2);
2524
+ this.safeLifecycleVoid(() => {
2525
+ this.config.callbacks?.lifecycle?.onAssistantMessage?.(assistantMessage2, {
2526
+ ...this.baseRunContext(),
2527
+ iteration
2528
+ });
2529
+ });
2168
2530
  }
2169
- this.messages.push({
2531
+ const interruptMsg = {
2170
2532
  role: "user",
2171
2533
  content: "[User interrupted the response]"
2534
+ };
2535
+ this.messages.push(interruptMsg);
2536
+ this.safeLifecycleVoid(() => {
2537
+ this.config.callbacks?.lifecycle?.onUserMessage?.(
2538
+ interruptMsg,
2539
+ "interruption_marker",
2540
+ this.baseRunContext()
2541
+ );
2172
2542
  });
2173
2543
  await this.sessionManager.saveMessages(this.messages);
2174
- yield this.annotateStreamEvent(
2544
+ this.safeLifecycleVoid(() => {
2545
+ this.config.callbacks?.lifecycle?.onMessagePersist?.({
2546
+ ...this.baseRunContext(),
2547
+ messageCount: this.messages.length
2548
+ });
2549
+ });
2550
+ this.emitRunEnd({ reason: "aborted", iterations: iteration + 1, usage: totalUsage });
2551
+ this.safeLifecycleVoid(() => {
2552
+ this.config.callbacks?.lifecycle?.onRunAbort?.({ ...this.baseRunContext(), iteration });
2553
+ });
2554
+ yield this.streamOut(
2175
2555
  {
2176
2556
  type: "end",
2177
2557
  usage: totalUsage,
@@ -2185,9 +2565,18 @@ ${content}`;
2185
2565
  }
2186
2566
  const events = chunkProcessor.processChunk(chunk);
2187
2567
  for (const event of events) {
2188
- const out = this.annotateStreamEvent(event, iteration);
2568
+ const out = this.streamOut(event, iteration);
2189
2569
  yield out;
2190
2570
  applyStreamOut(out);
2571
+ if (out.type === "end" && out.reason === "error" && out.error) {
2572
+ this.emitAgentError(out.error, { phase: "model", iteration });
2573
+ this.safeLifecycleVoid(() => {
2574
+ this.config.callbacks?.lifecycle?.onModelRequestError?.(out.error, {
2575
+ phase: "model",
2576
+ iteration
2577
+ });
2578
+ });
2579
+ }
2191
2580
  if (out.type === "end" && out.reason === "error") {
2192
2581
  fatalModelError = true;
2193
2582
  break;
@@ -2201,10 +2590,13 @@ ${content}`;
2201
2590
  return;
2202
2591
  }
2203
2592
  for (const event of chunkProcessor.flush()) {
2204
- const out = this.annotateStreamEvent(event, iteration);
2593
+ const out = this.streamOut(event, iteration);
2205
2594
  yield out;
2206
2595
  applyStreamOut(out);
2207
2596
  }
2597
+ this.safeLifecycleVoid(() => {
2598
+ this.config.callbacks?.lifecycle?.onModelRequestEnd?.({ ...this.baseRunContext(), iteration });
2599
+ });
2208
2600
  const assistantMessage = {
2209
2601
  role: "assistant",
2210
2602
  content: assistantContent
@@ -2226,13 +2618,36 @@ ${content}`;
2226
2618
  assistantMessage.toolCalls = toolCalls;
2227
2619
  }
2228
2620
  this.messages.push(assistantMessage);
2621
+ this.safeLifecycleVoid(() => {
2622
+ this.config.callbacks?.lifecycle?.onAssistantMessage?.(assistantMessage, {
2623
+ ...this.baseRunContext(),
2624
+ iteration
2625
+ });
2626
+ });
2229
2627
  if (!hasToolCalls) {
2628
+ this.log("debug", {
2629
+ component: "agent",
2630
+ event: "agent.iteration.end",
2631
+ message: "Iteration completed without tool calls",
2632
+ sessionId: this.sessionManager.sessionId ?? void 0,
2633
+ iteration,
2634
+ metadata: {
2635
+ assistantContentLength: assistantContent.length
2636
+ }
2637
+ });
2638
+ this.safeLifecycleVoid(() => {
2639
+ this.config.callbacks?.lifecycle?.onIterationEnd?.({
2640
+ ...this.baseRunContext(),
2641
+ iteration,
2642
+ hadToolCalls: false
2643
+ });
2644
+ });
2230
2645
  break;
2231
2646
  }
2232
- const toolResults = await this.executeTools(toolCalls);
2647
+ const toolResults = await this.executeTools(toolCalls, iteration);
2233
2648
  for (const result of toolResults) {
2234
2649
  if (result.isError && result.error) {
2235
- yield this.annotateStreamEvent(
2650
+ yield this.streamOut(
2236
2651
  {
2237
2652
  type: "tool_error",
2238
2653
  toolCallId: result.toolCallId,
@@ -2241,7 +2656,7 @@ ${content}`;
2241
2656
  iteration
2242
2657
  );
2243
2658
  }
2244
- yield this.annotateStreamEvent(
2659
+ yield this.streamOut(
2245
2660
  {
2246
2661
  type: "tool_result",
2247
2662
  toolCallId: result.toolCallId,
@@ -2249,38 +2664,110 @@ ${content}`;
2249
2664
  },
2250
2665
  iteration
2251
2666
  );
2252
- this.messages.push({
2667
+ const toolMsg = {
2253
2668
  role: "tool",
2254
2669
  toolCallId: result.toolCallId,
2255
2670
  content: result.content
2671
+ };
2672
+ this.messages.push(toolMsg);
2673
+ this.safeLifecycleVoid(() => {
2674
+ this.config.callbacks?.lifecycle?.onToolMessage?.(toolMsg, {
2675
+ ...this.baseRunContext(),
2676
+ iteration,
2677
+ toolCallId: result.toolCallId
2678
+ });
2256
2679
  });
2257
2680
  }
2681
+ this.log("debug", {
2682
+ component: "agent",
2683
+ event: "agent.iteration.end",
2684
+ message: "Iteration completed with tool calls",
2685
+ sessionId: this.sessionManager.sessionId ?? void 0,
2686
+ iteration,
2687
+ metadata: {
2688
+ toolCallCount: toolCalls.length,
2689
+ toolResultCount: toolResults.length
2690
+ }
2691
+ });
2692
+ this.safeLifecycleVoid(() => {
2693
+ this.config.callbacks?.lifecycle?.onIterationEnd?.({
2694
+ ...this.baseRunContext(),
2695
+ iteration,
2696
+ hadToolCalls: true
2697
+ });
2698
+ });
2258
2699
  }
2259
2700
  await this.sessionManager.saveMessages(this.messages);
2260
- yield this.annotateStreamEvent({
2701
+ this.safeLifecycleVoid(() => {
2702
+ this.config.callbacks?.lifecycle?.onMessagePersist?.({
2703
+ ...this.baseRunContext(),
2704
+ messageCount: this.messages.length
2705
+ });
2706
+ });
2707
+ const finishedByIterationCap = iteration >= maxIterations;
2708
+ const sessionIterations = finishedByIterationCap ? maxIterations : iteration + 1;
2709
+ yield this.streamOut({
2261
2710
  type: "session_summary",
2262
2711
  usage: totalUsage,
2263
- iterations: Math.min(maxIterations, this.messages.length)
2712
+ iterations: sessionIterations
2713
+ });
2714
+ this.emitRunEnd({
2715
+ reason: finishedByIterationCap ? "max_iterations" : "complete",
2716
+ iterations: sessionIterations,
2717
+ usage: totalUsage
2264
2718
  });
2265
- yield this.annotateStreamEvent({
2719
+ yield this.streamOut({
2266
2720
  type: "end",
2267
2721
  timestamp: Date.now(),
2268
- reason: "complete"
2722
+ reason: finishedByIterationCap ? "max_iterations" : "complete"
2723
+ });
2724
+ this.log("info", {
2725
+ component: "agent",
2726
+ event: "agent.run.end",
2727
+ message: finishedByIterationCap ? "Agent turn stopped at max iterations" : "Agent turn completed",
2728
+ sessionId: this.sessionManager.sessionId ?? void 0,
2729
+ metadata: {
2730
+ iterations: sessionIterations,
2731
+ promptTokens: totalUsage.promptTokens,
2732
+ completionTokens: totalUsage.completionTokens,
2733
+ totalTokens: totalUsage.totalTokens
2734
+ }
2269
2735
  });
2270
2736
  } catch (error) {
2271
2737
  if (error.name === "AbortError") {
2272
- yield this.annotateStreamEvent({
2738
+ this.log("info", {
2739
+ component: "agent",
2740
+ event: "agent.run.aborted",
2741
+ message: "Agent turn aborted",
2742
+ sessionId: this.sessionManager.sessionId ?? void 0
2743
+ });
2744
+ this.emitRunEnd({ reason: "aborted", iterations: 0 });
2745
+ this.safeLifecycleVoid(() => {
2746
+ this.config.callbacks?.lifecycle?.onRunAbort?.({ ...this.baseRunContext() });
2747
+ });
2748
+ yield this.streamOut({
2273
2749
  type: "end",
2274
2750
  timestamp: Date.now(),
2275
2751
  reason: "aborted"
2276
2752
  });
2277
2753
  return;
2278
2754
  }
2279
- yield this.annotateStreamEvent({
2755
+ const err = error instanceof Error ? error : new Error(String(error));
2756
+ this.log("error", {
2757
+ component: "agent",
2758
+ event: "agent.run.error",
2759
+ message: "Agent turn failed",
2760
+ sessionId: this.sessionManager.sessionId ?? void 0,
2761
+ errorName: err.name,
2762
+ errorMessage: err.message
2763
+ });
2764
+ this.emitAgentError(err, { phase: "run" });
2765
+ this.emitRunEnd({ reason: "error", iterations: 0, error: err });
2766
+ yield this.streamOut({
2280
2767
  type: "end",
2281
2768
  timestamp: Date.now(),
2282
2769
  reason: "error",
2283
- error
2770
+ error: err
2284
2771
  });
2285
2772
  }
2286
2773
  }
@@ -2463,10 +2950,16 @@ ARGUMENTS: ${args}`;
2463
2950
  if (!this.mcpAdapter) {
2464
2951
  this.mcpAdapter = new MCPAdapter();
2465
2952
  }
2466
- await this.mcpAdapter.addServer(toMCPClientConfig(config, this.config.env));
2953
+ const resolved = config.transport === "stdio" ? {
2954
+ ...config,
2955
+ env: chunkNYZD3THB_cjs.mergeMcpStdioEnv(this.config.env, config.env),
2956
+ cwd: (config.cwd ?? "").trim() || (this.config.cwd || process.cwd())
2957
+ } : config;
2958
+ await this.mcpAdapter.addServer(resolved);
2467
2959
  const mcpTools = this.mcpAdapter.getToolDefinitions();
2960
+ const serverPrefix = formatMcpToolName(config.name, "");
2468
2961
  for (const tool of mcpTools) {
2469
- if (!tool.name.startsWith(`mcp_${config.name}__`)) {
2962
+ if (!tool.name.startsWith(serverPrefix)) {
2470
2963
  continue;
2471
2964
  }
2472
2965
  if (this.toolRegistry.isDisallowed(tool.name)) {
@@ -2482,7 +2975,7 @@ ARGUMENTS: ${args}`;
2482
2975
  if (!this.mcpAdapter) return;
2483
2976
  const tools = this.toolRegistry.getAll();
2484
2977
  for (const tool of tools) {
2485
- if (tool.name.startsWith(`mcp_${name}__`)) {
2978
+ if (tool.name.startsWith(formatMcpToolName(name, ""))) {
2486
2979
  this.toolRegistry.unregister(tool.name);
2487
2980
  }
2488
2981
  }
@@ -2495,7 +2988,7 @@ ARGUMENTS: ${args}`;
2495
2988
  if (!this.mcpAdapter) return;
2496
2989
  const tools = this.toolRegistry.getAll();
2497
2990
  for (const tool of tools) {
2498
- if (tool.name.startsWith("mcp_") && tool.name.includes("__")) {
2991
+ if (isMcpPrefixedToolName(tool.name)) {
2499
2992
  this.toolRegistry.unregister(tool.name);
2500
2993
  }
2501
2994
  }
@@ -2631,12 +3124,20 @@ ${additionalContent}`;
2631
3124
  defaultAllowedTools: this.config.subagent?.defaultAllowedTools
2632
3125
  };
2633
3126
  }
2634
- resolveSubagentTools(request) {
3127
+ resolveSubagentTools(request, subagentType) {
2635
3128
  const subagentConfig = this.getSubagentConfig();
2636
3129
  const parentTools = this.toolRegistry.getAll();
2637
3130
  const byName = new Map(parentTools.map((tool) => [tool.name, tool]));
2638
- const requestedNames = request.allowed_tools ?? subagentConfig.defaultAllowedTools;
3131
+ let requestedNames = request.allowed_tools ?? subagentConfig.defaultAllowedTools;
3132
+ let usedExploreDefaultNames = false;
3133
+ if (requestedNames === void 0 && subagentType === "explore") {
3134
+ requestedNames = [...chunkP2X3AMDK_cjs.SUBAGENT_EXPLORE_DEFAULT_TOOL_NAMES];
3135
+ usedExploreDefaultNames = true;
3136
+ }
2639
3137
  let selected = requestedNames ? requestedNames.map((name) => byName.get(name)).filter((tool) => tool !== void 0) : parentTools.filter((tool) => !tool.isDangerous);
3138
+ if (usedExploreDefaultNames && selected.length === 0) {
3139
+ return { error: chunkP2X3AMDK_cjs.subagentExploreDefaultsUnavailableMessage() };
3140
+ }
2640
3141
  selected = selected.filter((tool) => tool.name !== "Agent");
2641
3142
  selected = selected.filter((tool) => tool.name !== "AskUserQuestion");
2642
3143
  if (!subagentConfig.allowDangerousTools) {
@@ -2668,8 +3169,11 @@ ${additionalContent}`;
2668
3169
  const normalizedType = request.subagent_type ?? "general-purpose";
2669
3170
  const requestedTimeout = request.timeout_ms ?? subagentConfig.timeoutMs;
2670
3171
  const timeoutMs = Math.min(requestedTimeout, subagentConfig.timeoutMs);
2671
- const maxIterations = Math.max(1, request.max_iterations ?? this.config.maxIterations ?? 50);
2672
- const resolved = this.resolveSubagentTools(request);
3172
+ const maxIterations = Math.max(
3173
+ 1,
3174
+ request.max_iterations ?? this.config.maxIterations ?? DEFAULT_MAX_ITERATIONS
3175
+ );
3176
+ const resolved = this.resolveSubagentTools(request, normalizedType);
2673
3177
  if (!resolved.tools) {
2674
3178
  return {
2675
3179
  content: resolved.error ?? "Unable to resolve subagent tools",
@@ -2693,8 +3197,10 @@ ${additionalContent}`;
2693
3197
  this.activeSubagentRuns += 1;
2694
3198
  try {
2695
3199
  await child.waitForInit();
3200
+ const typeAppend = chunkP2X3AMDK_cjs.resolveSubagentTypeAppend(normalizedType, this.config.subagent);
3201
+ const mergedSystem = [typeAppend, request.system_prompt].filter((s) => typeof s === "string" && s.trim().length > 0).join("\n\n");
2696
3202
  const runPromise = child.run(request.prompt, {
2697
- systemPrompt: request.system_prompt
3203
+ systemPrompt: mergedSystem || void 0
2698
3204
  });
2699
3205
  const timeoutPromise = new Promise((_, reject) => {
2700
3206
  const timer = setTimeout(() => {
@@ -2740,21 +3246,158 @@ ${additionalContent}`;
2740
3246
  /**
2741
3247
  * 执行工具调用
2742
3248
  */
2743
- async executeTools(toolCalls) {
3249
+ async executeTools(toolCalls, iteration) {
2744
3250
  const results = await Promise.all(
2745
3251
  toolCalls.map(async (tc) => {
2746
- const result = await this.toolRegistry.execute(tc.name, tc.arguments, {
2747
- toolCallId: tc.id,
2748
- projectDir: this.config.cwd || process.cwd(),
2749
- agentDepth: this.agentDepth
3252
+ this.safeLifecycleVoid(() => {
3253
+ this.config.callbacks?.lifecycle?.onToolCallPlanned?.(tc, {
3254
+ ...this.baseRunContext(),
3255
+ iteration
3256
+ });
2750
3257
  });
2751
- const isError = Boolean(result.isError);
2752
- return {
2753
- toolCallId: tc.id,
2754
- content: isError ? `Error: ${result.content}` : result.content,
2755
- isError,
2756
- error: isError ? new Error(result.content) : void 0
2757
- };
3258
+ const startedAt = Date.now();
3259
+ this.safeLifecycleVoid(() => {
3260
+ this.config.callbacks?.lifecycle?.onToolExecutionStart?.({
3261
+ ...this.baseRunContext(),
3262
+ iteration,
3263
+ toolCallId: tc.id,
3264
+ toolName: tc.name,
3265
+ arguments: tc.arguments,
3266
+ projectDir: this.config.cwd || process.cwd(),
3267
+ agentDepth: this.agentDepth
3268
+ });
3269
+ });
3270
+ this.log("info", {
3271
+ component: "tooling",
3272
+ event: "tool.call.start",
3273
+ message: "Executing tool call",
3274
+ sessionId: this.sessionManager.sessionId ?? void 0,
3275
+ toolName: tc.name,
3276
+ toolCallId: tc.id
3277
+ });
3278
+ try {
3279
+ const result = await this.toolRegistry.execute(tc.name, tc.arguments, {
3280
+ toolCallId: tc.id,
3281
+ projectDir: this.config.cwd || process.cwd(),
3282
+ agentDepth: this.agentDepth
3283
+ });
3284
+ const durationMs = Date.now() - startedAt;
3285
+ const isError = Boolean(result.isError);
3286
+ const error = isError ? new Error(result.content) : void 0;
3287
+ this.safeLifecycleVoid(() => {
3288
+ this.config.callbacks?.lifecycle?.onToolExecutionEnd?.({
3289
+ ...this.baseRunContext(),
3290
+ iteration,
3291
+ toolCallId: tc.id,
3292
+ toolName: tc.name,
3293
+ arguments: tc.arguments,
3294
+ projectDir: this.config.cwd || process.cwd(),
3295
+ agentDepth: this.agentDepth,
3296
+ durationMs,
3297
+ isError,
3298
+ executionError: void 0
3299
+ });
3300
+ });
3301
+ this.safeLifecycleVoid(() => {
3302
+ this.config.callbacks?.lifecycle?.onToolResult?.({
3303
+ ...this.baseRunContext(),
3304
+ iteration,
3305
+ toolCallId: tc.id,
3306
+ toolName: tc.name,
3307
+ arguments: tc.arguments,
3308
+ projectDir: this.config.cwd || process.cwd(),
3309
+ agentDepth: this.agentDepth,
3310
+ durationMs,
3311
+ isError,
3312
+ result
3313
+ });
3314
+ });
3315
+ this.log(isError ? "warn" : "info", {
3316
+ component: "tooling",
3317
+ event: isError ? "tool.call.error" : "tool.call.end",
3318
+ message: isError ? "Tool call returned an error" : "Tool call completed",
3319
+ sessionId: this.sessionManager.sessionId ?? void 0,
3320
+ toolName: tc.name,
3321
+ toolCallId: tc.id,
3322
+ durationMs,
3323
+ ...error ? {
3324
+ errorName: error.name,
3325
+ errorMessage: error.message
3326
+ } : {},
3327
+ metadata: {
3328
+ resultLength: result.content.length
3329
+ }
3330
+ });
3331
+ return {
3332
+ toolCallId: tc.id,
3333
+ content: isError ? `Error: ${result.content}` : result.content,
3334
+ isError,
3335
+ error
3336
+ };
3337
+ } catch (error) {
3338
+ const err = error instanceof Error ? error : new Error(String(error));
3339
+ const durationMs = Date.now() - startedAt;
3340
+ const synthetic = { content: err.message, isError: true };
3341
+ this.emitAgentError(err, {
3342
+ phase: "tool",
3343
+ toolName: tc.name,
3344
+ toolCallId: tc.id,
3345
+ iteration
3346
+ });
3347
+ this.safeLifecycleVoid(() => {
3348
+ this.config.callbacks?.lifecycle?.onToolExecutionError?.(err, {
3349
+ phase: "tool",
3350
+ toolName: tc.name,
3351
+ toolCallId: tc.id,
3352
+ iteration
3353
+ });
3354
+ });
3355
+ this.safeLifecycleVoid(() => {
3356
+ this.config.callbacks?.lifecycle?.onToolExecutionEnd?.({
3357
+ ...this.baseRunContext(),
3358
+ iteration,
3359
+ toolCallId: tc.id,
3360
+ toolName: tc.name,
3361
+ arguments: tc.arguments,
3362
+ projectDir: this.config.cwd || process.cwd(),
3363
+ agentDepth: this.agentDepth,
3364
+ durationMs,
3365
+ isError: true,
3366
+ executionError: err
3367
+ });
3368
+ });
3369
+ this.safeLifecycleVoid(() => {
3370
+ this.config.callbacks?.lifecycle?.onToolResult?.({
3371
+ ...this.baseRunContext(),
3372
+ iteration,
3373
+ toolCallId: tc.id,
3374
+ toolName: tc.name,
3375
+ arguments: tc.arguments,
3376
+ projectDir: this.config.cwd || process.cwd(),
3377
+ agentDepth: this.agentDepth,
3378
+ durationMs,
3379
+ isError: true,
3380
+ result: synthetic
3381
+ });
3382
+ });
3383
+ this.log("error", {
3384
+ component: "tooling",
3385
+ event: "tool.call.error",
3386
+ message: "Tool call threw an exception",
3387
+ sessionId: this.sessionManager.sessionId ?? void 0,
3388
+ toolName: tc.name,
3389
+ toolCallId: tc.id,
3390
+ durationMs,
3391
+ errorName: err.name,
3392
+ errorMessage: err.message
3393
+ });
3394
+ return {
3395
+ toolCallId: tc.id,
3396
+ content: `Error: ${err.message}`,
3397
+ isError: true,
3398
+ error: err
3399
+ };
3400
+ }
2758
3401
  })
2759
3402
  );
2760
3403
  return results;
@@ -2798,7 +3441,8 @@ function transformConfig(config) {
2798
3441
  ...transport === "stdio" ? {
2799
3442
  command: serverConfig.command,
2800
3443
  args: serverConfig.args,
2801
- env: serverConfig.env
3444
+ env: serverConfig.env,
3445
+ cwd: serverConfig.cwd
2802
3446
  } : {
2803
3447
  url: serverConfig.url,
2804
3448
  headers: serverConfig.headers
@@ -2880,10 +3524,12 @@ function validateMCPConfig(config) {
2880
3524
  }
2881
3525
 
2882
3526
  exports.Agent = Agent;
3527
+ exports.DEFAULT_MAX_ITERATIONS = DEFAULT_MAX_ITERATIONS;
2883
3528
  exports.DEFAULT_SYSTEM_PROMPT = DEFAULT_SYSTEM_PROMPT;
2884
3529
  exports.JsonlStorage = JsonlStorage;
2885
3530
  exports.MCPAdapter = MCPAdapter;
2886
3531
  exports.MCPClient = MCPClient;
3532
+ exports.MODEL_STREAM_EVENT_TYPES = MODEL_STREAM_EVENT_TYPES;
2887
3533
  exports.MemoryManager = MemoryManager;
2888
3534
  exports.MemoryStorage = MemoryStorage;
2889
3535
  exports.PACKAGE_VERSION = PACKAGE_VERSION;
@@ -2900,10 +3546,13 @@ exports.createSessionManager = createSessionManager;
2900
3546
  exports.createSkillLoader = createSkillLoader;
2901
3547
  exports.createSkillRegistry = createSkillRegistry;
2902
3548
  exports.createStorage = createStorage;
3549
+ exports.formatMcpToolName = formatMcpToolName;
2903
3550
  exports.getLatestSessionId = getLatestSessionId;
2904
3551
  exports.getSessionStoragePath = getSessionStoragePath;
3552
+ exports.isMcpPrefixedToolName = isMcpPrefixedToolName;
3553
+ exports.isModelStreamEventType = isModelStreamEventType;
2905
3554
  exports.loadMCPConfig = loadMCPConfig;
2906
3555
  exports.parseSkillMd = parseSkillMd;
2907
3556
  exports.validateMCPConfig = validateMCPConfig;
2908
- //# sourceMappingURL=chunk-AJD3DTL7.cjs.map
2909
- //# sourceMappingURL=chunk-AJD3DTL7.cjs.map
3557
+ //# sourceMappingURL=chunk-JXAJQGV5.cjs.map
3558
+ //# sourceMappingURL=chunk-JXAJQGV5.cjs.map