agentdev 0.1.9 → 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 (42) hide show
  1. package/dist/BasicAgent-7TNMYC3X.js +13 -0
  2. package/dist/ExplorerAgent-L3ZTVQGM.js +13 -0
  3. package/dist/{chunk-QFHPUAUQ.js → chunk-35LBACUK.js} +8 -8
  4. package/dist/{chunk-QFHPUAUQ.js.map → chunk-35LBACUK.js.map} +1 -1
  5. package/dist/{chunk-NORTAQIL.js → chunk-4WK7UENZ.js} +1011 -11
  6. package/dist/chunk-4WK7UENZ.js.map +1 -0
  7. package/dist/{chunk-BAP2GCYH.js → chunk-7GTVQ55R.js} +1 -1
  8. package/dist/chunk-7GTVQ55R.js.map +1 -0
  9. package/dist/{chunk-G5ECPY4K.js → chunk-EK6KGS2M.js} +87 -8
  10. package/dist/{chunk-G5ECPY4K.js.map → chunk-EK6KGS2M.js.map} +1 -1
  11. package/dist/{chunk-5T4C2XRT.js → chunk-KE3KYZVJ.js} +21 -8
  12. package/dist/chunk-KE3KYZVJ.js.map +1 -0
  13. package/dist/{chunk-EECW6PYP.js → chunk-UL2ZBPBL.js} +60 -4
  14. package/dist/chunk-UL2ZBPBL.js.map +1 -0
  15. package/dist/{chunk-A354ZCZF.js → chunk-XRB6MD2J.js} +5593 -982
  16. package/dist/chunk-XRB6MD2J.js.map +1 -0
  17. package/dist/cli/server.js +2 -2
  18. package/dist/cli/viewer.js +2 -2
  19. package/dist/create-feature-cli.js +26 -7
  20. package/dist/features/mcp/templates/mcp-tool.render.js +14 -1
  21. package/dist/features/mcp/templates/mcp-tool.render.js.map +1 -1
  22. package/dist/features/shell/templates/bash.render.d.ts +1 -1
  23. package/dist/features/websearch/templates/web-fetch.render.d.ts +1 -1
  24. package/dist/index.d.ts +778 -21
  25. package/dist/index.js +17 -7
  26. package/dist/index.js.map +1 -1
  27. package/dist/{notification-NWVOS2WR.js → notification-QPH37BHW.js} +29 -6
  28. package/dist/notification-QPH37BHW.js.map +1 -0
  29. package/dist/{tools-LDR3LIJP.js → tools-OKH7SPMP.js} +2 -2
  30. package/dist/{types-CF5UsxD9.d.ts → types-NVwNUVFR.d.ts} +180 -14
  31. package/package.json +7 -14
  32. package/dist/BasicAgent-UWXLSZP2.js +0 -13
  33. package/dist/ExplorerAgent-LCM3JQS4.js +0 -13
  34. package/dist/chunk-5T4C2XRT.js.map +0 -1
  35. package/dist/chunk-A354ZCZF.js.map +0 -1
  36. package/dist/chunk-BAP2GCYH.js.map +0 -1
  37. package/dist/chunk-EECW6PYP.js.map +0 -1
  38. package/dist/chunk-NORTAQIL.js.map +0 -1
  39. package/dist/notification-NWVOS2WR.js.map +0 -1
  40. /package/dist/{BasicAgent-UWXLSZP2.js.map → BasicAgent-7TNMYC3X.js.map} +0 -0
  41. /package/dist/{ExplorerAgent-LCM3JQS4.js.map → ExplorerAgent-L3ZTVQGM.js.map} +0 -0
  42. /package/dist/{tools-LDR3LIJP.js.map → tools-OKH7SPMP.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  BasicAgent
3
- } from "./chunk-5T4C2XRT.js";
3
+ } from "./chunk-KE3KYZVJ.js";
4
4
  import {
5
5
  ExplorerAgent
6
- } from "./chunk-QFHPUAUQ.js";
6
+ } from "./chunk-35LBACUK.js";
7
7
  import {
8
8
  AgentBase,
9
9
  AgentPool,
@@ -16,7 +16,9 @@ import {
16
16
  DataSourceRegistry,
17
17
  Decision,
18
18
  ExampleFeature,
19
+ FileHistoryFeature,
19
20
  FileSessionStore,
21
+ LspFeature,
20
22
  MCPClient,
21
23
  MCPConnectionManager,
22
24
  MCPConnectionState,
@@ -24,6 +26,7 @@ import {
24
26
  MCPToolAdapter,
25
27
  MemoryFeature,
26
28
  OpenAILLM,
29
+ OpenAIResponsesLLM,
27
30
  OpencodeBasicFeature,
28
31
  PluginCompatFeature,
29
32
  QQBotFeature,
@@ -43,6 +46,7 @@ import {
43
46
  WebSearchFeature,
44
47
  assistant,
45
48
  compileContextForAnthropic,
49
+ compileContextForOpenAIResponses,
46
50
  createAnthropicLLM,
47
51
  createDefaultMCPToolName,
48
52
  createLLM,
@@ -54,6 +58,7 @@ import {
54
58
  createManagedMCPToolsFromClient,
55
59
  createMessage,
56
60
  createOpenAILLM,
61
+ createOpenAIResponsesLLM,
57
62
  discover,
58
63
  discoverMCPTools,
59
64
  discoverManagedMCPTools,
@@ -71,7 +76,7 @@ import {
71
76
  system,
72
77
  toolResult,
73
78
  user
74
- } from "./chunk-A354ZCZF.js";
79
+ } from "./chunk-XRB6MD2J.js";
75
80
  import {
76
81
  PlaceholderResolver
77
82
  } from "./chunk-BVF7RUXV.js";
@@ -80,17 +85,17 @@ import {
80
85
  getClawRuntimeUrl,
81
86
  getDebugCapabilities,
82
87
  resolveDebugTransportMode
83
- } from "./chunk-EECW6PYP.js";
88
+ } from "./chunk-UL2ZBPBL.js";
84
89
  import {
85
90
  ToolRegistry,
86
91
  createTool
87
- } from "./chunk-G5ECPY4K.js";
92
+ } from "./chunk-EK6KGS2M.js";
88
93
  import {
89
94
  ViewerWorker
90
- } from "./chunk-NORTAQIL.js";
95
+ } from "./chunk-4WK7UENZ.js";
91
96
  import {
92
97
  getDefaultUDSPath
93
- } from "./chunk-BAP2GCYH.js";
98
+ } from "./chunk-7GTVQ55R.js";
94
99
  import "./chunk-BDS2QGZ5.js";
95
100
 
96
101
  // src/template/types.ts
@@ -239,7 +244,9 @@ export {
239
244
  Decision,
240
245
  ExampleFeature,
241
246
  ExplorerAgent,
247
+ FileHistoryFeature,
242
248
  FileSessionStore,
249
+ LspFeature,
243
250
  MCPClient,
244
251
  MCPConnectionManager,
245
252
  MCPConnectionState,
@@ -248,6 +255,7 @@ export {
248
255
  MCP_RENDER_TEMPLATES,
249
256
  MemoryFeature,
250
257
  OpenAILLM,
258
+ OpenAIResponsesLLM,
251
259
  OpencodeBasicFeature,
252
260
  PlaceholderResolver,
253
261
  PluginCompatFeature,
@@ -271,6 +279,7 @@ export {
271
279
  WebSearchFeature,
272
280
  assistant,
273
281
  compileContextForAnthropic,
282
+ compileContextForOpenAIResponses,
274
283
  createAnthropicLLM,
275
284
  createDefaultMCPToolName,
276
285
  createLLM,
@@ -282,6 +291,7 @@ export {
282
291
  createManagedMCPToolsFromClient,
283
292
  createMessage,
284
293
  createOpenAILLM,
294
+ createOpenAIResponsesLLM,
285
295
  createTool,
286
296
  discover,
287
297
  discoverMCPTools,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/template/types.ts","../src/mcp/render.ts"],"sourcesContent":["/**\n * 提示词模板系统 - 核心类型定义\n */\n\n/**\n * 模板源\n * - string: 硬编码字符串\n * - { file: string }: 文件路径\n * - [dataSourceName: string]: 数据源名称(如 skills, tasks 等)\n * - TemplateComposer: 组合模板\n *\n * @example\n * ```typescript\n * // 静态字符串\n * 'Hello {{name}}'\n *\n * // 文件\n * { file: 'prompts/system.md' }\n *\n * // 数据源(列表渲染)\n * { skills: '- **{{name}}**: {{description}}' }\n * { tasks: '- [{{title}}](#{{id}}) ({{priority}})' }\n *\n * // 条件渲染\n * { conditional: { part: { file: 'advanced.md' }, condition: (ctx) => ctx.advanced } }\n * ```\n */\nexport type TemplateSource =\n | string\n | { file: string }\n | { conditional: ConditionalSource }\n | { [dataSourceName: string]: string } // 数据源 -> 模板\n | import('./composer.js').TemplateComposer;\n\n/**\n * 条件源配置\n */\nexport interface ConditionalSource {\n /** 条件模板源 */\n part: TemplateSource;\n /** 条件函数(true 时渲染) */\n condition: (context: PlaceholderContext) => boolean;\n}\n\n/**\n * 占位符上下文 - 变量替换的键值对\n * 支持原始类型和复杂对象(用于数据源渲染)\n */\nexport type PlaceholderContext = Record<string, string | number | boolean | undefined | object>;\n\n/**\n * 模板渲染结果\n */\nexport interface TemplateResult {\n /** 渲染后的内容 */\n content: string;\n /** 使用的源文件列表(用于调试) */\n sources: string[];\n}\n\n/**\n * 模板加载器配置\n */\nexport interface TemplateLoaderOptions {\n /** 缓存启用状态,默认 true */\n cacheEnabled?: boolean;\n /** 模板搜索目录(相对于项目根目录) */\n searchDirs?: string[];\n /** 项目根目录(自动检测) */\n projectRoot?: string;\n}\n\n/**\n * 缓存统计\n */\nexport interface CacheStats {\n size: number; // 缓存条目数\n hits: number; // 命中次数\n misses: number; // 未命中次数\n hitRate: number; // 命中率\n}\n\n/**\n * 模板相关错误\n */\nexport class TemplateError extends Error {\n constructor(\n message: string,\n public code:\n | 'FILE_NOT_FOUND'\n | 'INVALID_PATH'\n | 'READ_ERROR'\n | 'UNSUPPORTED_FORMAT',\n public path?: string\n ) {\n super(message);\n this.name = 'TemplateError';\n }\n}\n","/**\n * MCP 工具渲染模板\n *\n * 定义 MCP 工具在 DebugHub 中的显示样式\n */\n\n/**\n * 转义 HTML\n */\nfunction escapeHtml(text: any): string {\n const str = String(text);\n const map: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n };\n return str.replace(/[&<>\"']/g, m => map[m]);\n}\n\n/**\n * MCP 工具渲染模板\n */\nexport const MCP_RENDER_TEMPLATES = {\n /**\n * MCP 工具调用显示\n */\n 'mcp-tool': {\n call: (args: any) => {\n const server = args._server || 'unknown';\n const name = args._name || 'unknown';\n return `\n <div class=\"bash-command\" style=\"\n border-left: 3px solid #ff6b6b;\n padding-left: 8px;\n margin: 4px 0;\n \">\n <span style=\"\n color: #ff6b6b;\n font-weight: bold;\n font-size: 11px;\n text-transform: uppercase;\n \">MCP</span>\n <span class=\"file-path\" style=\"color: #c068ff;\">${escapeHtml(server)}</span>\n <span style=\"color: #888;\">::</span>\n <span style=\"color: #fff;\">${escapeHtml(name)}</span>\n </div>\n `.trim();\n },\n result: (data: any, success = true) => {\n if (!success || data.error) {\n return `\n <div class=\"bash-output\" style=\"\n border-left: 3px solid #ff4444;\n padding-left: 8px;\n color: #ff6b6b;\n \">\n <div style=\"font-weight: bold; margin-bottom: 4px;\">MCP Error</div>\n <pre style=\"margin: 0; white-space: pre-wrap;\">${escapeHtml(data.error || 'Unknown error')}</pre>\n </div>\n `.trim();\n }\n\n let content = '';\n\n // 文本内容\n if (data.content) {\n content += `<pre class=\"bash-output\" style=\"max-height: 400px; overflow: auto;\">${escapeHtml(data.content)}</pre>`;\n }\n\n // 结构化数据\n if (data.structuredContent) {\n content += `<details style=\"margin-top: 8px;\">\n <summary style=\"cursor: pointer; color: var(--accent-color);\">Structured Data</summary>\n <pre style=\"margin: 4px 0; padding: 8px; background: var(--bg-secondary);\">${escapeHtml(JSON.stringify(data.structuredContent, null, 2))}</pre>\n </details>`;\n }\n\n // 图像\n if (data.images && data.images.length > 0) {\n content += `<div style=\"margin-top: 8px;\">`;\n data.images.forEach((img: any) => {\n content += `<img src=\"data:${img.mimeType};base64,${img.data}\" style=\"max-width: 100%; border-radius: 4px;\" />`;\n });\n content += `</div>`;\n }\n\n // 资源\n if (data.resources && data.resources.length > 0) {\n content += `<div style=\"margin-top: 8px;\">\n <div style=\"font-weight: bold; margin-bottom: 4px;\">Resources:</div>`;\n data.resources.forEach((res: any) => {\n content += `<div style=\"padding: 4px; background: var(--bg-secondary); margin: 4px 0;\">\n <div style=\"font-size: 11px; color: var(--text-secondary);\">${escapeHtml(res.uri)}</div>\n ${res.text ? `<pre style=\"margin: 4px 0 0 0;\">${escapeHtml(res.text)}</pre>` : ''}\n </div>`;\n });\n content += `</div>`;\n }\n\n // 元数据\n const meta = `\n <div style=\"\n font-size: 11px;\n opacity: 0.6;\n margin-top: 8px;\n display: flex;\n gap: 12px;\n \">\n <span>Server: ${escapeHtml(data.server)}</span>\n <span>Duration: ${data.duration}ms</span>\n </div>\n `;\n\n return content + meta;\n },\n },\n\n /**\n * MCP 结果 (简化版)\n */\n 'mcp-result': {\n call: () => '<div class=\"bash-command\">MCP Tool Call</div>',\n result: (data: any, success = true) => {\n return MCP_RENDER_TEMPLATES['mcp-tool'].result(data, success);\n },\n },\n} as const;\n\n/**\n * 获取 MCP 渲染模板\n */\nexport function getMCPRenderTemplate(toolName: string): string {\n return 'mcp-tool';\n}\n\n/**\n * 渲染 MCP 工具调用\n */\nexport function renderMCPToolCall(\n serverName: string,\n toolName: string,\n args: Record<string, any>\n): string {\n const template = MCP_RENDER_TEMPLATES['mcp-tool'].call;\n if (typeof template === 'function') {\n return template({ _server: serverName, _name: toolName, ...args });\n }\n return template;\n}\n\n/**\n * 渲染 MCP 工具结果\n */\nexport function renderMCPToolResult(\n result: any,\n success = true\n): string {\n const template = MCP_RENDER_TEMPLATES['mcp-tool'].result;\n if (typeof template === 'function') {\n return template(result, success);\n }\n return template;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/template/types.ts","../src/mcp/render.ts"],"sourcesContent":["/**\n * 提示词模板系统 - 核心类型定义\n */\n\n/**\n * 模板源\n * - string: 硬编码字符串\n * - { file: string }: 文件路径\n * - [dataSourceName: string]: 数据源名称(如 skills, tasks 等)\n * - TemplateComposer: 组合模板\n *\n * @example\n * ```typescript\n * // 静态字符串\n * 'Hello {{name}}'\n *\n * // 文件\n * { file: 'prompts/system.md' }\n *\n * // 数据源(列表渲染)\n * { skills: '- **{{name}}**: {{description}}' }\n * { tasks: '- [{{title}}](#{{id}}) ({{priority}})' }\n *\n * // 条件渲染\n * { conditional: { part: { file: 'advanced.md' }, condition: (ctx) => ctx.advanced } }\n * ```\n */\nexport type TemplateSource =\n | string\n | { file: string }\n | { conditional: ConditionalSource }\n | { [dataSourceName: string]: string } // 数据源 -> 模板\n | import('./composer.js').TemplateComposer;\n\n/**\n * 条件源配置\n */\nexport interface ConditionalSource {\n /** 条件模板源 */\n part: TemplateSource;\n /** 条件函数(true 时渲染) */\n condition: (context: PlaceholderContext) => boolean;\n}\n\n/**\n * 占位符上下文 - 变量替换的键值对\n * 支持原始类型和复杂对象(用于数据源渲染)\n */\nexport type PlaceholderContext = Record<string, string | number | boolean | undefined | object>;\n\n/**\n * 模板渲染结果\n */\nexport interface TemplateResult {\n /** 渲染后的内容 */\n content: string;\n /** 使用的源文件列表(用于调试) */\n sources: string[];\n}\n\n/**\n * 模板加载器配置\n */\nexport interface TemplateLoaderOptions {\n /** 缓存启用状态,默认 true */\n cacheEnabled?: boolean;\n /** 模板搜索目录(相对于项目根目录) */\n searchDirs?: string[];\n /** 项目根目录(自动检测) */\n projectRoot?: string;\n}\n\n/**\n * 缓存统计\n */\nexport interface CacheStats {\n size: number; // 缓存条目数\n hits: number; // 命中次数\n misses: number; // 未命中次数\n hitRate: number; // 命中率\n}\n\n/**\n * 模板相关错误\n */\nexport class TemplateError extends Error {\n constructor(\n message: string,\n public code:\n | 'FILE_NOT_FOUND'\n | 'INVALID_PATH'\n | 'READ_ERROR'\n | 'UNSUPPORTED_FORMAT',\n public path?: string\n ) {\n super(message);\n this.name = 'TemplateError';\n }\n}\n","/**\n * MCP 工具渲染模板\n *\n * 定义 MCP 工具在 DebugHub 中的显示样式\n */\n\n/**\n * 转义 HTML\n */\nfunction escapeHtml(text: any): string {\n const str = String(text);\n const map: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n };\n return str.replace(/[&<>\"']/g, m => map[m]);\n}\n\n/**\n * MCP 工具渲染模板\n */\nexport const MCP_RENDER_TEMPLATES = {\n /**\n * MCP 工具调用显示\n */\n 'mcp-tool': {\n call: (args: any) => {\n const server = args._server || 'unknown';\n const name = args._name || 'unknown';\n return `\n <div class=\"bash-command\" style=\"\n border-left: 3px solid #ff6b6b;\n padding-left: 8px;\n margin: 4px 0;\n \">\n <span style=\"\n color: #ff6b6b;\n font-weight: bold;\n font-size: 11px;\n text-transform: uppercase;\n \">MCP</span>\n <span class=\"file-path\" style=\"color: #c068ff;\">${escapeHtml(server)}</span>\n <span style=\"color: #888;\">::</span>\n <span style=\"color: #fff;\">${escapeHtml(name)}</span>\n </div>\n `.trim();\n },\n result: (data: any, success = true) => {\n if (!success || data.error) {\n return `\n <div class=\"bash-output\" style=\"\n border-left: 3px solid #ff4444;\n padding-left: 8px;\n color: #ff6b6b;\n \">\n <div style=\"font-weight: bold; margin-bottom: 4px;\">MCP Error</div>\n <pre style=\"margin: 0; white-space: pre-wrap;\">${escapeHtml(data.error || 'Unknown error')}</pre>\n </div>\n `.trim();\n }\n\n let content = '';\n\n // 文本内容\n if (data.content) {\n content += `<pre class=\"bash-output\" style=\"max-height: 400px; overflow: auto;\">${escapeHtml(data.content)}</pre>`;\n }\n\n // 结构化数据\n if (data.structuredContent) {\n content += `<details style=\"margin-top: 8px;\">\n <summary style=\"cursor: pointer; color: var(--accent-color);\">Structured Data</summary>\n <pre style=\"margin: 4px 0; padding: 8px; background: var(--bg-secondary);\">${escapeHtml(JSON.stringify(data.structuredContent, null, 2))}</pre>\n </details>`;\n }\n\n // 图像\n if (data.images && data.images.length > 0) {\n content += `<div style=\"margin-top: 8px;\">`;\n data.images.forEach((img: any) => {\n content += `<img src=\"data:${img.mimeType};base64,${img.data}\" style=\"max-width: 100%; border-radius: 4px;\" />`;\n });\n content += `</div>`;\n }\n\n // 资源\n if (data.resources && data.resources.length > 0) {\n content += `<div style=\"margin-top: 8px;\">\n <div style=\"font-weight: bold; margin-bottom: 4px;\">Resources:</div>`;\n data.resources.forEach((res: any) => {\n content += `<div style=\"padding: 4px; background: var(--bg-secondary); margin: 4px 0;\">\n <div style=\"font-size: 11px; color: var(--text-secondary);\">${escapeHtml(res.uri)}</div>\n ${res.text ? `<pre style=\"margin: 4px 0 0 0;\">${escapeHtml(res.text)}</pre>` : ''}\n </div>`;\n });\n content += `</div>`;\n }\n\n // 元数据\n const meta = `\n <div style=\"\n font-size: 11px;\n opacity: 0.6;\n margin-top: 8px;\n display: flex;\n gap: 12px;\n \">\n <span>Server: ${escapeHtml(data.server)}</span>\n <span>Duration: ${data.duration}ms</span>\n </div>\n `;\n\n return content + meta;\n },\n },\n\n /**\n * MCP 结果 (简化版)\n */\n 'mcp-result': {\n call: () => '<div class=\"bash-command\">MCP Tool Call</div>',\n result: (data: any, success = true) => {\n return MCP_RENDER_TEMPLATES['mcp-tool'].result(data, success);\n },\n },\n} as const;\n\n/**\n * 获取 MCP 渲染模板\n */\nexport function getMCPRenderTemplate(toolName: string): string {\n return 'mcp-tool';\n}\n\n/**\n * 渲染 MCP 工具调用\n */\nexport function renderMCPToolCall(\n serverName: string,\n toolName: string,\n args: Record<string, any>\n): string {\n const template = MCP_RENDER_TEMPLATES['mcp-tool'].call;\n if (typeof template === 'function') {\n return template({ _server: serverName, _name: toolName, ...args });\n }\n return template;\n}\n\n/**\n * 渲染 MCP 工具结果\n */\nexport function renderMCPToolResult(\n result: any,\n success = true\n): string {\n const template = MCP_RENDER_TEMPLATES['mcp-tool'].result;\n if (typeof template === 'function') {\n return template(result, success);\n }\n return template;\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DebugHub
3
- } from "./chunk-EECW6PYP.js";
4
- import "./chunk-BAP2GCYH.js";
3
+ } from "./chunk-UL2ZBPBL.js";
4
+ import "./chunk-7GTVQ55R.js";
5
5
  import "./chunk-BDS2QGZ5.js";
6
6
 
7
7
  // src/core/notification.ts
@@ -23,7 +23,9 @@ function emitNotification(notification) {
23
23
  return;
24
24
  }
25
25
  const now = Date.now();
26
- if (notification.category === "state") {
26
+ const notificationType = String(notification.type || "");
27
+ const bypassThrottle = notificationType === "call.start" || notificationType === "call.finish" || notificationType === "llm.complete";
28
+ if (notification.category === "state" && !bypassThrottle) {
27
29
  const timeSinceLast = now - lastNotificationTime;
28
30
  if (timeSinceLast < THROTTLE_INTERVAL) {
29
31
  return;
@@ -33,14 +35,17 @@ function emitNotification(notification) {
33
35
  const debugHub = DebugHub.getInstance();
34
36
  debugHub.pushNotification(currentAgentId, notification);
35
37
  }
36
- function createLLMCharCount(charCount, phase) {
38
+ function createLLMCharCount(charCount, phase, extras) {
37
39
  return {
38
40
  type: "llm.char_count",
39
41
  category: "state",
40
42
  timestamp: Date.now(),
41
43
  data: {
42
44
  charCount,
43
- phase
45
+ phase,
46
+ ...typeof extras?.thinkingChars === "number" ? { thinkingChars: extras.thinkingChars } : {},
47
+ ...typeof extras?.contentChars === "number" ? { contentChars: extras.contentChars } : {},
48
+ ...typeof extras?.toolCallCount === "number" ? { toolCallCount: extras.toolCallCount } : {}
44
49
  }
45
50
  };
46
51
  }
@@ -76,14 +81,32 @@ function createToolComplete(toolName, success, duration) {
76
81
  }
77
82
  };
78
83
  }
84
+ function createCallStart() {
85
+ return {
86
+ type: "call.start",
87
+ category: "state",
88
+ timestamp: Date.now(),
89
+ data: {}
90
+ };
91
+ }
92
+ function createCallFinish(completed, finishReason) {
93
+ return {
94
+ type: "call.finish",
95
+ category: "state",
96
+ timestamp: Date.now(),
97
+ data: { completed, ...finishReason ? { finishReason } : {} }
98
+ };
99
+ }
79
100
  export {
80
101
  _clearNotificationAgent,
81
102
  _getCurrentNotificationAgent,
82
103
  _setNotificationAgent,
104
+ createCallFinish,
105
+ createCallStart,
83
106
  createLLMCharCount,
84
107
  createLLMComplete,
85
108
  createToolComplete,
86
109
  createToolStart,
87
110
  emitNotification
88
111
  };
89
- //# sourceMappingURL=notification-NWVOS2WR.js.map
112
+ //# sourceMappingURL=notification-QPH37BHW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/notification.ts"],"sourcesContent":["/**\n * Notification System - 核心通知系统\n *\n * 职责:\n * - 定义通知类型和分类\n * - 提供通知发送接口\n * - 管理通知上下文(当前 Agent ID)\n * - 节流高频通知\n */\n\nimport type { Notification, NotificationCategory, LLMPhase } from './types.js';\nimport { DebugHub } from './debug-hub.js';\n\n// ========== 模块级状态 ==========\n\n/**\n * 当前通知上下文的 Agent ID\n */\nlet currentAgentId: string | null = null;\n\n/**\n * 节流控制:上次发送通知的时间戳\n */\nlet lastNotificationTime: number = 0;\n\n/**\n * 节流间隔(毫秒)\n */\nconst THROTTLE_INTERVAL = 100;\n\n// ========== 公开 API ==========\n\n/**\n * 设置通知上下文\n * @param agentId Agent ID\n */\nexport function _setNotificationAgent(agentId: string): void {\n currentAgentId = agentId;\n}\n\n/**\n * 清除通知上下文\n */\nexport function _clearNotificationAgent(): void {\n currentAgentId = null;\n // 重置节流状态\n lastNotificationTime = 0;\n}\n\n/**\n * 获取当前通知上下文的 Agent ID\n */\nexport function _getCurrentNotificationAgent(): string | null {\n return currentAgentId;\n}\n\n/**\n * 发送通知到 DebugHub\n * @param notification 通知对象\n */\nexport function emitNotification(notification: Notification): void {\n if (!currentAgentId) {\n // 没有通知上下文,静默忽略\n return;\n }\n\n const now = Date.now();\n const notificationType = String(notification.type || '');\n const bypassThrottle = notificationType === 'call.start'\n || notificationType === 'call.finish'\n || notificationType === 'llm.complete';\n\n // 节流:状态类通知需要节流,事件类通知不需要\n if (notification.category === 'state' && !bypassThrottle) {\n const timeSinceLast = now - lastNotificationTime;\n if (timeSinceLast < THROTTLE_INTERVAL) {\n // 跳过此次通知\n return;\n }\n lastNotificationTime = now;\n }\n\n // 推送到 DebugHub\n const debugHub = DebugHub.getInstance();\n debugHub.pushNotification(currentAgentId, notification);\n}\n\n// ========== 通知构造函数 ==========\n\n/**\n * 创建 LLM 字符计数通知\n * @param charCount 当前累积字符数\n * @param phase LLM 生成阶段\n */\nexport function createLLMCharCount(\n charCount: number,\n phase: LLMPhase,\n extras?: {\n thinkingChars?: number;\n contentChars?: number;\n toolCallCount?: number;\n },\n): Notification {\n return {\n type: 'llm.char_count',\n category: 'state',\n timestamp: Date.now(),\n data: {\n charCount,\n phase,\n ...(typeof extras?.thinkingChars === 'number' ? { thinkingChars: extras.thinkingChars } : {}),\n ...(typeof extras?.contentChars === 'number' ? { contentChars: extras.contentChars } : {}),\n ...(typeof extras?.toolCallCount === 'number' ? { toolCallCount: extras.toolCallCount } : {}),\n },\n };\n}\n\n/**\n * 创建 LLM 完成通知\n * @param totalChars 总字符数\n */\nexport function createLLMComplete(totalChars: number): Notification {\n return {\n type: 'llm.complete',\n category: 'state',\n timestamp: Date.now(),\n data: {\n totalChars,\n },\n };\n}\n\n/**\n * 创建工具开始通知\n * @param toolName 工具名称\n */\nexport function createToolStart(toolName: string): Notification {\n return {\n type: 'tool.start',\n category: 'event',\n timestamp: Date.now(),\n data: {\n toolName,\n },\n };\n}\n\n/**\n * 创建工具完成通知\n * @param toolName 工具名称\n * @param success 是否成功\n * @param duration 耗时(毫秒)\n */\nexport function createToolComplete(\n toolName: string,\n success: boolean,\n duration: number\n): Notification {\n return {\n type: 'tool.complete',\n category: 'event',\n timestamp: Date.now(),\n data: {\n toolName,\n success,\n duration,\n },\n };\n}\n\n/**\n * 创建 Call 开始通知\n */\nexport function createCallStart(): Notification {\n return {\n type: 'call.start',\n category: 'state',\n timestamp: Date.now(),\n data: {},\n };\n}\n\n/**\n * 创建 Call 结束通知\n * @param completed 是否正常完成(false 表示被中断或出错)\n */\nexport function createCallFinish(completed: boolean, finishReason?: string): Notification {\n return {\n type: 'call.finish',\n category: 'state',\n timestamp: Date.now(),\n data: { completed, ...(finishReason ? { finishReason } : {}) },\n };\n}\n"],"mappings":";;;;;;;AAkBA,IAAI,iBAAgC;AAKpC,IAAI,uBAA+B;AAKnC,IAAM,oBAAoB;AAQnB,SAAS,sBAAsB,SAAuB;AAC3D,mBAAiB;AACnB;AAKO,SAAS,0BAAgC;AAC9C,mBAAiB;AAEjB,yBAAuB;AACzB;AAKO,SAAS,+BAA8C;AAC5D,SAAO;AACT;AAMO,SAAS,iBAAiB,cAAkC;AACjE,MAAI,CAAC,gBAAgB;AAEnB;AAAA,EACF;AAEA,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,mBAAmB,OAAO,aAAa,QAAQ,EAAE;AACvD,QAAM,iBAAiB,qBAAqB,gBACvC,qBAAqB,iBACrB,qBAAqB;AAG1B,MAAI,aAAa,aAAa,WAAW,CAAC,gBAAgB;AACxD,UAAM,gBAAgB,MAAM;AAC5B,QAAI,gBAAgB,mBAAmB;AAErC;AAAA,IACF;AACA,2BAAuB;AAAA,EACzB;AAGA,QAAM,WAAW,SAAS,YAAY;AACtC,WAAS,iBAAiB,gBAAgB,YAAY;AACxD;AASO,SAAS,mBACd,WACA,OACA,QAKc;AACd,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW,KAAK,IAAI;AAAA,IACpB,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,GAAI,OAAO,QAAQ,kBAAkB,WAAW,EAAE,eAAe,OAAO,cAAc,IAAI,CAAC;AAAA,MAC3F,GAAI,OAAO,QAAQ,iBAAiB,WAAW,EAAE,cAAc,OAAO,aAAa,IAAI,CAAC;AAAA,MACxF,GAAI,OAAO,QAAQ,kBAAkB,WAAW,EAAE,eAAe,OAAO,cAAc,IAAI,CAAC;AAAA,IAC7F;AAAA,EACF;AACF;AAMO,SAAS,kBAAkB,YAAkC;AAClE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW,KAAK,IAAI;AAAA,IACpB,MAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAMO,SAAS,gBAAgB,UAAgC;AAC9D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW,KAAK,IAAI;AAAA,IACpB,MAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAQO,SAAS,mBACd,UACA,SACA,UACc;AACd,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW,KAAK,IAAI;AAAA,IACpB,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,kBAAgC;AAC9C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW,KAAK,IAAI;AAAA,IACpB,MAAM,CAAC;AAAA,EACT;AACF;AAMO,SAAS,iBAAiB,WAAoB,cAAqC;AACxF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW,KAAK,IAAI;AAAA,IACpB,MAAM,EAAE,WAAW,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC,EAAG;AAAA,EAC/D;AACF;","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  createCaptureAndUnderstandAdvancedTool,
4
4
  createCaptureAndUnderstandTool,
5
5
  understandImage
6
- } from "./chunk-G5ECPY4K.js";
6
+ } from "./chunk-EK6KGS2M.js";
7
7
  import "./chunk-BDS2QGZ5.js";
8
8
  export {
9
9
  captureWindow,
@@ -11,4 +11,4 @@ export {
11
11
  createCaptureAndUnderstandTool,
12
12
  understandImage
13
13
  };
14
- //# sourceMappingURL=tools-LDR3LIJP.js.map
14
+ //# sourceMappingURL=tools-OKH7SPMP.js.map
@@ -265,6 +265,8 @@ interface UsageStatsSnapshot {
265
265
  totalRequests: number;
266
266
  /** 命中缓存的请求数(request-level) */
267
267
  totalCacheHitRequests: number;
268
+ /** 最后一次请求的用量(用于显示当前上下文占用) */
269
+ lastRequestUsage?: UsageInfo$1;
268
270
  }
269
271
  /**
270
272
  * 用量统计类
@@ -280,6 +282,8 @@ declare class UsageStats {
280
282
  private totalCacheHitRequests;
281
283
  /** 当前 Call 的 Step 记录(临时,用于聚合) */
282
284
  private currentStepRecords;
285
+ /** 最后一次 LLM 调用的用量(用于显示当前上下文占用) */
286
+ private lastRequestUsage;
283
287
  /**
284
288
  * 记录一次 LLM 调用的用量
285
289
  * @param callIndex Call 序号
@@ -310,6 +314,10 @@ declare class UsageStats {
310
314
  */
311
315
  getTotalRequests(): number;
312
316
  getTotalCacheHitRequests(): number;
317
+ /**
318
+ * 获取最后一次请求的用量(用于显示当前上下文占用)
319
+ */
320
+ getLastRequestUsage(): UsageInfo$1 | null;
313
321
  /**
314
322
  * 获取格式化的用量报告
315
323
  */
@@ -381,6 +389,65 @@ interface DebugLogEntry {
381
389
  data?: unknown;
382
390
  delivery: DebugLogDelivery;
383
391
  }
392
+ type RuntimeStage = 'idle' | 'llm_thinking' | 'llm_content' | 'llm_tool_call_building' | 'awaiting_runtime' | 'tool_executing' | 'retry_waiting' | 'retry_requesting' | 'completed' | 'failed';
393
+ interface AgentRuntimeSnapshot {
394
+ stage: RuntimeStage;
395
+ callActive: boolean;
396
+ charCount: number;
397
+ thinkingChars: number;
398
+ contentChars: number;
399
+ toolCallCount: number;
400
+ activeToolNames: string[];
401
+ activeToolCount: number;
402
+ callStartedAt?: number;
403
+ stageStartedAt?: number;
404
+ retryAttempt?: number;
405
+ maxRetries?: number;
406
+ nextRetryDelayMs?: number;
407
+ lastErrorType?: string | null;
408
+ lastErrorMessage?: string | null;
409
+ updatedAt: number;
410
+ }
411
+ /**
412
+ * 工具定义
413
+ */
414
+ interface Tool {
415
+ name: string;
416
+ description: string;
417
+ parameters?: Record<string, any>;
418
+ /**
419
+ * 执行工具
420
+ *
421
+ * @param args 工具参数
422
+ * @param context 执行上下文,可能包含:
423
+ * - signal?: AbortSignal - 用于中断工具执行
424
+ * - ...其他上下文信息
425
+ */
426
+ execute: (args: any, context?: any) => Promise<any>;
427
+ /** 可选:渲染配置 */
428
+ render?: ToolRenderConfig;
429
+ /**
430
+ * 工具执行模式
431
+ * - 'normal'(默认):普通工具,可与其他工具在同一次 assistant turn 中并行调用
432
+ * - 'exclusive':独占工具,必须是 assistant turn 中唯一的工具调用
433
+ *
434
+ * exclusive 工具适用于控制流工具(如 checkpoint、rollback),
435
+ * 它们不应与其他工具产生副作用交织。
436
+ */
437
+ executionMode?: 'normal' | 'exclusive';
438
+ /**
439
+ * 工具是否可并行执行。
440
+ *
441
+ * - true: 该工具可以与同批次中其他 parallelizable 工具并发执行
442
+ * - false/undefined: 串行执行(默认,向后兼容)
443
+ *
444
+ * 约束:
445
+ * - exclusive 工具忽略此属性(exclusive 总是独占批次)
446
+ * - 标记为 parallelizable 的工具应是无副作用的只读操作,
447
+ * 或其副作用不会与同批次其他工具冲突
448
+ */
449
+ parallelizable?: boolean;
450
+ }
384
451
  type MessageRole = 'system' | 'user' | 'assistant' | 'tool' | string;
385
452
  interface Message {
386
453
  role: MessageRole;
@@ -390,6 +457,23 @@ interface Message {
390
457
  toolCalls?: ToolCall[];
391
458
  reasoning?: string;
392
459
  thinkingBlocks?: ThinkingBlock[];
460
+ /**
461
+ * LLM 用量信息(仅 assistant 消息有值)。
462
+ *
463
+ * 由 LLM provider 在生成响应时返回,表示生成此消息时的上下文 token 开销。
464
+ * inputTokens 是发送给 LLM 的完整上下文大小(包含所有历史消息),
465
+ * 不是单条消息的 token 数。
466
+ */
467
+ usage?: MessageUsage;
468
+ }
469
+ /**
470
+ * 消息级用量记录(盖戳在 assistant 消息上)
471
+ */
472
+ interface MessageUsage {
473
+ /** 生成此消息时,发送给 LLM 的总输入 token(即当时的完整上下文大小) */
474
+ inputTokens: number;
475
+ /** LLM 生成的输出 token */
476
+ outputTokens: number;
393
477
  }
394
478
  interface ThinkingBlock {
395
479
  signature: string;
@@ -426,6 +510,8 @@ interface LLMResponse {
426
510
  thinkingBlocks?: ThinkingBlock[];
427
511
  /** 用量统计(可选) */
428
512
  usage?: UsageInfo;
513
+ /** 停止原因,由 LLM API 返回(如 end_turn, tool_use, stop 等) */
514
+ stopReason?: string | null;
429
515
  }
430
516
  /**
431
517
  * 渲染模板项
@@ -450,16 +536,14 @@ interface ToolRenderConfig {
450
536
  /** 结果时的渲染模板(字符串引用或内联模板) */
451
537
  result?: string | InlineRenderTemplate;
452
538
  }
453
- interface Tool {
454
- name: string;
455
- description: string;
456
- parameters?: Record<string, any>;
457
- execute: (args: any, context?: any) => Promise<any>;
458
- /** 可选:渲染配置 */
459
- render?: ToolRenderConfig;
460
- }
461
539
  interface LLMClient {
462
- chat(messages: Message[], tools: Tool[]): Promise<LLMResponse>;
540
+ chat(messages: Message[], tools: Tool[], options?: LLMChatOptions): Promise<LLMResponse>;
541
+ /** 可选:返回当前 LLM 实例使用的模型名(用于调试显示) */
542
+ readonly modelName?: string;
543
+ }
544
+ interface LLMChatOptions {
545
+ /** 允许中断正在进行的 LLM 调用 */
546
+ signal?: AbortSignal;
463
547
  }
464
548
 
465
549
  interface AgentConfig {
@@ -528,7 +612,7 @@ interface HookLifecycleSnapshot {
528
612
  interface FeatureInspectorSnapshot {
529
613
  name: string;
530
614
  enabled: boolean;
531
- status: 'enabled' | 'disabled' | 'partial';
615
+ status: 'enabled' | 'disabled' | 'removed' | 'partial';
532
616
  hookCount: number;
533
617
  toolCount: number;
534
618
  enabledToolCount: number;
@@ -537,7 +621,8 @@ interface FeatureInspectorSnapshot {
537
621
  tools: Array<{
538
622
  name: string;
539
623
  description: string;
540
- enabled: boolean;
624
+ state: 'enabled' | 'disabled' | 'removed' | 'superseded';
625
+ enabled?: boolean;
541
626
  renderCall?: string;
542
627
  renderResult?: string;
543
628
  }>;
@@ -546,6 +631,15 @@ interface HookInspectorSnapshot {
546
631
  lifecycleOrder: string[];
547
632
  features: FeatureInspectorSnapshot[];
548
633
  hooks: HookLifecycleSnapshot[];
634
+ standaloneTools?: Array<{
635
+ name: string;
636
+ description: string;
637
+ state: 'enabled' | 'disabled' | 'removed' | 'superseded';
638
+ enabled?: boolean;
639
+ source?: string;
640
+ renderCall?: string;
641
+ renderResult?: string;
642
+ }>;
549
643
  }
550
644
  interface AgentContextMetrics {
551
645
  messageCount: number;
@@ -557,6 +651,9 @@ interface AgentOverviewSnapshot {
557
651
  updatedAt: number;
558
652
  context: AgentContextMetrics;
559
653
  usageStats: UsageStatsSnapshot;
654
+ runtime?: AgentRuntimeSnapshot;
655
+ /** 可选:当前使用的模型名(由 agent 实例注入) */
656
+ modelName?: string;
560
657
  }
561
658
  /**
562
659
  * Agent 会话数据(Worker 端)
@@ -570,6 +667,8 @@ interface AgentSession {
570
667
  lastActive: number;
571
668
  projectRoot?: string;
572
669
  currentState: Notification | null;
670
+ callActive?: boolean;
671
+ runtimeState?: AgentRuntimeSnapshot;
573
672
  events: Notification[];
574
673
  lastEventCount: number;
575
674
  logs: DebugLogEntry[];
@@ -577,12 +676,21 @@ interface AgentSession {
577
676
  _lastMessageSig?: string;
578
677
  hookInspector?: HookInspectorSnapshot;
579
678
  overview?: AgentOverviewSnapshot;
679
+ queuedInputs: QueuedInput[];
680
+ }
681
+ /**
682
+ * 排队的用户输入
683
+ */
684
+ interface QueuedInput {
685
+ id: string;
686
+ text: string;
687
+ timestamp: number;
580
688
  }
581
689
  /**
582
690
  * DebugHub IPC 消息类型(主进程 → Worker)
583
691
  * 使用 discriminated union 确保类型安全
584
692
  */
585
- type DebugHubIPCMessage = RegisterAgentMsg | UpdateAgentInspectorMsg | UpdateAgentOverviewMsg | PushMessagesMsg | RegisterToolsMsg | SetCurrentAgentMsg | UnregisterAgentMsg | PushNotificationMsg | RequestInputMsg | StopMsg;
693
+ type DebugHubIPCMessage = RegisterAgentMsg | UpdateAgentInspectorMsg | UpdateAgentOverviewMsg | PushMessagesMsg | RegisterToolsMsg | SetCurrentAgentMsg | UnregisterAgentMsg | PushNotificationMsg | RequestInputMsg | QueueInputMsg | ConsumeQueuedInputMsg | InterruptAgentMsg | StopMsg;
586
694
  /**
587
695
  * 注册新 Agent
588
696
  */
@@ -674,6 +782,32 @@ interface RequestInputMsg {
674
782
  placeholder?: string;
675
783
  initialValue?: string;
676
784
  actions?: UserInputAction[];
785
+ mode?: UserInputRequestMode;
786
+ questions?: UserInputQuestion[];
787
+ }
788
+ /**
789
+ * 排队用户输入(运行期间提交的消息)
790
+ */
791
+ interface QueueInputMsg {
792
+ type: 'queue-input';
793
+ agentId: string;
794
+ input: QueuedInput;
795
+ }
796
+ /**
797
+ * 通知 Worker 移除一条已被运行时接管/开始处理的排队输入
798
+ */
799
+ interface ConsumeQueuedInputMsg {
800
+ type: 'consume-queued-input';
801
+ agentId: string;
802
+ inputId: string;
803
+ }
804
+ /**
805
+ * 中断正在运行的 Agent
806
+ */
807
+ interface InterruptAgentMsg {
808
+ type: 'interrupt-agent';
809
+ agentId: string;
810
+ clearQueue?: boolean;
677
811
  }
678
812
  interface UserInputAction {
679
813
  id: string;
@@ -682,16 +816,48 @@ interface UserInputAction {
682
816
  variant?: 'primary' | 'secondary' | 'danger';
683
817
  payload?: Record<string, unknown>;
684
818
  }
819
+ type UserInputRequestMode = 'text' | 'choices';
820
+ interface UserInputOption {
821
+ id: string;
822
+ label: string;
823
+ description?: string;
824
+ /** Whether this option allows supplementary free-text input */
825
+ allowSupplement?: boolean;
826
+ /** Whether the supplement text is required (only meaningful when allowSupplement is true) */
827
+ supplementRequired?: boolean;
828
+ /** Label shown above the supplement textarea */
829
+ supplementLabel?: string;
830
+ /** Placeholder for the supplement textarea */
831
+ supplementPlaceholder?: string;
832
+ }
833
+ interface UserInputQuestion {
834
+ id: string;
835
+ question: string;
836
+ options: UserInputOption[];
837
+ allowCustom?: boolean;
838
+ customLabel?: string;
839
+ customPlaceholder?: string;
840
+ }
685
841
  interface UserInputRequest {
686
842
  prompt: string;
687
843
  placeholder?: string;
688
844
  initialValue?: string;
689
845
  actions?: UserInputAction[];
846
+ mode?: UserInputRequestMode;
847
+ questions?: UserInputQuestion[];
848
+ }
849
+ interface UserInputChoiceAnswer {
850
+ questionId: string;
851
+ optionId?: string;
852
+ customText?: string;
853
+ /** Supplementary free-text provided alongside the selected option */
854
+ supplementText?: string;
690
855
  }
691
856
  interface UserInputResponse {
692
- kind: 'text' | 'action';
857
+ kind: 'text' | 'action' | 'choices';
693
858
  text?: string;
694
859
  actionId?: string;
860
+ choices?: UserInputChoiceAnswer[];
695
861
  payload?: Record<string, unknown>;
696
862
  }
697
863
  /**
@@ -745,4 +911,4 @@ interface EnrichedMessage extends Message {
745
911
  */
746
912
  declare function getDefaultUDSPath(): string;
747
913
 
748
- export { type AgentConfig as A, type CacheStats as C, type DebugHubIPCMessage as D, type EnrichedMessage as E, type HookInspectorSnapshot as H, type InlineRenderTemplate as I, type LLMResponse as L, type MessageTag as M, type Notification as N, type PlaceholderContext as P, type ToolCall as T, type UserInputRequest as U, type Message as a, type Tool as b, type LogContextRef as c, type ToolRenderConfig as d, type AgentOverviewSnapshot as e, type AgentInfo as f, type UserInputResponse as g, type UsageStatsSnapshot as h, type TemplateSource as i, TemplateLoader as j, UsageStats as k, type UsageInfo as l, type UserInputAction as m, type LLMClient as n, type MessageRole as o, type AgentSession as p, type ContextMiddleware as q, TemplateComposer as r, TemplateError as s, type TemplateLoaderOptions as t, type TemplateResult as u, type ToolMetadata as v, getDefaultUDSPath as w };
914
+ export { type AgentConfig as A, type CacheStats as C, type DebugHubIPCMessage as D, type EnrichedMessage as E, type HookInspectorSnapshot as H, type InlineRenderTemplate as I, type LLMResponse as L, type MessageTag as M, type Notification as N, type PlaceholderContext as P, type ToolCall as T, type UserInputRequest as U, type Message as a, type Tool as b, type LogContextRef as c, type ToolRenderConfig as d, type AgentOverviewSnapshot as e, type AgentInfo as f, type UserInputResponse as g, type UsageStatsSnapshot as h, type TemplateSource as i, TemplateLoader as j, UsageStats as k, type UsageInfo as l, type UserInputAction as m, type UserInputQuestion as n, type UserInputChoiceAnswer as o, type LLMClient as p, type MessageRole as q, type AgentSession as r, type ContextMiddleware as s, type MessageUsage as t, TemplateComposer as u, TemplateError as v, type TemplateLoaderOptions as w, type TemplateResult as x, type ToolMetadata as y, getDefaultUDSPath as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentdev",
3
- "version": "0.1.9",
3
+ "version": "0.2.1",
4
4
  "description": "A lightweight, decoupled AI agent framework with built-in debugger",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -19,25 +19,15 @@
19
19
  "@sliverp/qqbot"
20
20
  ],
21
21
  "scripts": {
22
- "build": "tsup && node scripts/generate-bin-cmds.mjs",
22
+ "build": "tsup && node scripts/copy-feature-skills.mjs && node scripts/generate-bin-cmds.mjs",
23
23
  "dev": "tsup --watch",
24
+ "test": "tsx src/test/test-runner.ts",
25
+ "test:openai-responses": "tsx src/test/openai-responses.test.ts",
24
26
  "prepublishOnly": "npm run build",
25
27
  "create-feature": "node dist/create-feature-cli.js",
26
28
  "copy-example": "node scripts/copy-example-feature.mjs",
27
29
  "server": "node dist/cli/server.js"
28
30
  },
29
- "tsup": {
30
- "entry": [
31
- "src/index.ts",
32
- "src/cli/viewer.ts",
33
- "src/cli/server.ts",
34
- "src/features/*/templates/*.render.ts"
35
- ],
36
- "format": "esm",
37
- "dts": true,
38
- "clean": true,
39
- "sourcemap": true
40
- },
41
31
  "dependencies": {
42
32
  "@modelcontextprotocol/sdk": "^1.26.0",
43
33
  "@openai/agents": "^0.4.6",
@@ -50,6 +40,9 @@
50
40
  "openai": "^4.73.0",
51
41
  "sharp": "^0.33.5",
52
42
  "sound-play": "^1.1.0",
43
+ "undici": "^7.25.0",
44
+ "vscode-jsonrpc": "^8.2.1",
45
+ "vscode-languageserver-types": "^3.18.0",
53
46
  "zod": "^4.1.5"
54
47
  },
55
48
  "devDependencies": {
@@ -1,13 +0,0 @@
1
- import {
2
- BasicAgent
3
- } from "./chunk-5T4C2XRT.js";
4
- import "./chunk-A354ZCZF.js";
5
- import "./chunk-BVF7RUXV.js";
6
- import "./chunk-EECW6PYP.js";
7
- import "./chunk-G5ECPY4K.js";
8
- import "./chunk-BAP2GCYH.js";
9
- import "./chunk-BDS2QGZ5.js";
10
- export {
11
- BasicAgent
12
- };
13
- //# sourceMappingURL=BasicAgent-UWXLSZP2.js.map
@@ -1,13 +0,0 @@
1
- import {
2
- ExplorerAgent
3
- } from "./chunk-QFHPUAUQ.js";
4
- import "./chunk-A354ZCZF.js";
5
- import "./chunk-BVF7RUXV.js";
6
- import "./chunk-EECW6PYP.js";
7
- import "./chunk-G5ECPY4K.js";
8
- import "./chunk-BAP2GCYH.js";
9
- import "./chunk-BDS2QGZ5.js";
10
- export {
11
- ExplorerAgent
12
- };
13
- //# sourceMappingURL=ExplorerAgent-LCM3JQS4.js.map