@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
@@ -231,10 +231,12 @@ var ToolRegistry = class {
231
231
  outputHandler;
232
232
  hookManager = null;
233
233
  executionPolicy;
234
+ hookObserver;
234
235
  constructor(config) {
235
236
  const enableOutputHandler = config?.enableOutputHandler !== false;
236
237
  this.outputHandler = enableOutputHandler ? createOutputHandler(config?.userBasePath) : null;
237
238
  this.executionPolicy = config?.executionPolicy;
239
+ this.hookObserver = config?.hookObserver;
238
240
  }
239
241
  /**
240
242
  * 工具名是否在 {@link ToolExecutionPolicy.disallowedTools} 中(无策略时为 false)。
@@ -301,6 +303,14 @@ var ToolRegistry = class {
301
303
  ...extra
302
304
  };
303
305
  }
306
+ hookObserverCtx(eventType, name, options) {
307
+ return {
308
+ eventType,
309
+ toolName: name,
310
+ toolCallId: options?.toolCallId,
311
+ projectDir: options?.projectDir
312
+ };
313
+ }
304
314
  /**
305
315
  * 注册工具
306
316
  */
@@ -371,6 +381,11 @@ var ToolRegistry = class {
371
381
  }
372
382
  const tool = this.tools.get(name);
373
383
  if (!tool) {
384
+ if (hookMgr) {
385
+ this.hookObserver?.onHookStart?.(
386
+ this.hookObserverCtx("postToolUseFailure", name, options)
387
+ );
388
+ }
374
389
  const ctx = this.buildHookContext("postToolUseFailure", name, rawArgsObj, options, {
375
390
  errorMessage: `Tool "${name}" not found`,
376
391
  failureKind: "tool_error"
@@ -386,6 +401,11 @@ var ToolRegistry = class {
386
401
  const initial = tool.parameters.safeParse(args);
387
402
  if (!initial.success) {
388
403
  const msg = `Invalid arguments for tool "${name}": ${initial.error.issues.map((i) => i.message).join(", ")}`;
404
+ if (hookMgr) {
405
+ this.hookObserver?.onHookStart?.(
406
+ this.hookObserverCtx("postToolUseFailure", name, options)
407
+ );
408
+ }
389
409
  await hookMgr?.executePostToolUseFailure(
390
410
  this.buildHookContext("postToolUseFailure", name, rawArgsObj, options, {
391
411
  errorMessage: msg,
@@ -396,9 +416,17 @@ var ToolRegistry = class {
396
416
  }
397
417
  workingInput = initial.data;
398
418
  if (hookMgr) {
419
+ this.hookObserver?.onHookStart?.(
420
+ this.hookObserverCtx("preToolUse", name, options)
421
+ );
399
422
  const pre = await hookMgr.executePreToolUse(
400
423
  this.buildHookContext("preToolUse", name, workingInput, options)
401
424
  );
425
+ this.hookObserver?.onHookDecision?.({
426
+ ...this.hookObserverCtx("preToolUse", name, options),
427
+ allowed: pre.allowed,
428
+ reason: pre.reason
429
+ });
402
430
  if (!pre.allowed) {
403
431
  return {
404
432
  content: pre.reason ?? "Blocked by hook",
@@ -408,6 +436,9 @@ var ToolRegistry = class {
408
436
  const merged = tool.parameters.safeParse(pre.updatedInput ?? workingInput);
409
437
  if (!merged.success) {
410
438
  const msg = `Invalid arguments after hook merge for tool "${name}": ${merged.error.issues.map((i) => i.message).join(", ")}`;
439
+ this.hookObserver?.onHookStart?.(
440
+ this.hookObserverCtx("postToolUseFailure", name, options)
441
+ );
411
442
  await hookMgr.executePostToolUseFailure(
412
443
  this.buildHookContext("postToolUseFailure", name, workingInput, options, {
413
444
  errorMessage: msg,
@@ -427,6 +458,11 @@ var ToolRegistry = class {
427
458
  const result = await tool.handler(handlerArgs, executionContext);
428
459
  const toolResultRaw = result;
429
460
  if (result.isError) {
461
+ if (hookMgr) {
462
+ this.hookObserver?.onHookStart?.(
463
+ this.hookObserverCtx("postToolUseFailure", name, options)
464
+ );
465
+ }
430
466
  await hookMgr?.executePostToolUseFailure(
431
467
  this.buildHookContext("postToolUseFailure", name, workingInput, options, {
432
468
  errorMessage: result.content,
@@ -444,6 +480,11 @@ var ToolRegistry = class {
444
480
  { args: handlerArgs }
445
481
  );
446
482
  }
483
+ if (hookMgr) {
484
+ this.hookObserver?.onHookStart?.(
485
+ this.hookObserverCtx("postToolUse", name, options)
486
+ );
487
+ }
447
488
  await hookMgr?.executePostToolUse(
448
489
  this.buildHookContext("postToolUse", name, workingInput, options, {
449
490
  toolResultRaw,
@@ -453,6 +494,11 @@ var ToolRegistry = class {
453
494
  return finalResult;
454
495
  } catch (error) {
455
496
  const msg = `Error executing tool "${name}": ${error instanceof Error ? error.message : String(error)}`;
497
+ if (hookMgr) {
498
+ this.hookObserver?.onHookStart?.(
499
+ this.hookObserverCtx("postToolUseFailure", name, options)
500
+ );
501
+ }
456
502
  await hookMgr?.executePostToolUseFailure(
457
503
  this.buildHookContext("postToolUseFailure", name, workingInput, options, {
458
504
  errorMessage: msg,
@@ -2113,128 +2159,52 @@ var webSearchTool = createTool({
2113
2159
  function getWebTools() {
2114
2160
  return [webFetchTool, webSearchTool];
2115
2161
  }
2116
- var tasks = /* @__PURE__ */ new Map();
2117
- var nextId = 1;
2118
- var taskCreateTool = createTool({
2119
- name: "TaskCreate",
2162
+ var todoStatusEnum = z.enum(["pending", "in_progress", "completed"]);
2163
+ var todoWriteTool = createTool({
2164
+ name: "TodoWrite",
2120
2165
  category: "planning",
2121
- description: `Use this tool to create a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
2166
+ description: `MUST USE for multi-step tasks. Creates a structured task list to track progress. Call this tool FIRST before executing any complex task.
2122
2167
 
2123
- ## When to Use This Tool
2168
+ Any number of tasks may be "in_progress" when work runs in parallel. Zero in_progress is fine (e.g. all pending or all completed).
2124
2169
 
2125
- - Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
2126
- - Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
2127
- - User explicitly requests todo list - When the user directly asks you to use the task list
2128
- - User provides multiple tasks - When users provide a list of things to be done
2170
+ **Before you finish your assistant response for a multi-step request**, call \`TodoWrite\` again so **every** item in the list has status \`completed\`, unless you are explicitly pausing mid-work for a follow-up turn. Do not leave dangling \`pending\` or \`in_progress\` items when the work for this request is done.
2129
2171
 
2130
- ## When NOT to Use
2172
+ **Replanning:** If execution shows the earlier plan was wrong, incomplete, or no longer fits (wrong order, missing steps, obsolete items), call \`TodoWrite\` anytime with an updated full list\u2014add, remove, merge, or rewrite steps as needed.
2131
2173
 
2132
- - There is only a single, straightforward task
2133
- - The task is trivial and tracking it provides no organizational benefit
2134
- - The task can be completed in less than 3 trivial steps
2135
-
2136
- All tasks are created with status pending.`,
2174
+ Triggers: multi-step tasks, multiple files/components, user provides task list.
2175
+ Skip: single simple task, informational questions.`,
2137
2176
  parameters: z.object({
2138
- subject: z.string().describe("A brief title for the task"),
2139
- description: z.string().describe("What needs to be done"),
2140
- activeForm: z.string().optional().describe('Present continuous form shown in spinner when in_progress (e.g., "Running tests")')
2141
- }),
2142
- handler: async ({ subject, description, activeForm }) => {
2143
- const id = String(nextId++);
2144
- const task = {
2145
- id,
2146
- subject,
2147
- description,
2148
- status: "pending",
2149
- ...activeForm && { activeForm }
2150
- };
2151
- tasks.set(id, task);
2152
- return {
2153
- content: `Task created [${id}]: ${subject}`,
2154
- metadata: { task }
2155
- };
2156
- }
2157
- });
2158
- var taskUpdateTool = createTool({
2159
- name: "TaskUpdate",
2160
- category: "planning",
2161
- description: `Use this tool to update a task in the task list.
2162
-
2163
- ## When to Use This Tool
2164
-
2165
- **Mark tasks as completed:**
2166
- - When you have completed the work described in a task
2167
- - IMPORTANT: Always mark your assigned tasks as completed when you finish them
2168
-
2169
- **Delete tasks:**
2170
- - When a task is no longer relevant or was created in error
2171
-
2172
- ## Status Workflow
2173
-
2174
- Status progresses: pending \u2192 in_progress \u2192 completed`,
2175
- parameters: z.object({
2176
- taskId: z.string().describe("The ID of the task to update"),
2177
- status: z.enum(["pending", "in_progress", "completed", "deleted"]).optional().describe("New status for the task"),
2178
- subject: z.string().optional().describe("New subject for the task"),
2179
- description: z.string().optional().describe("New description for the task"),
2180
- activeForm: z.string().optional().describe("Present continuous form shown in spinner when in_progress")
2177
+ todos: z.array(
2178
+ z.object({
2179
+ content: z.string().describe('Brief description of the task in imperative form (e.g., "Run tests")'),
2180
+ activeForm: z.string().optional().describe(
2181
+ 'Optional present-continuous label for in-progress UI (e.g., "Running tests"). Omit if not needed.'
2182
+ ),
2183
+ status: todoStatusEnum.describe("Task status: pending, in_progress, or completed")
2184
+ })
2185
+ ).min(1).describe(
2186
+ "Full updated todo list. Refresh this whenever progress or the plan changes. When finishing the multi-step work, all entries should be completed."
2187
+ )
2181
2188
  }),
2182
- handler: async ({ taskId, status, subject, description, activeForm }) => {
2183
- const task = tasks.get(taskId);
2184
- if (!task) {
2185
- return {
2186
- content: `Task ${taskId} not found`,
2187
- isError: true
2188
- };
2189
- }
2190
- if (status === "deleted") {
2191
- tasks.delete(taskId);
2192
- return { content: `Task ${taskId} deleted` };
2193
- }
2194
- if (status) task.status = status;
2195
- if (subject) task.subject = subject;
2196
- if (description) task.description = description;
2197
- if (activeForm) task.activeForm = activeForm;
2198
- const icon = task.status === "completed" ? "x" : task.status === "in_progress" ? ">" : " ";
2199
- return {
2200
- content: `Task [${taskId}] updated: [${icon}] ${task.subject}`,
2201
- metadata: { task }
2202
- };
2203
- }
2204
- });
2205
- var taskListTool = createTool({
2206
- name: "TaskList",
2207
- category: "planning",
2208
- description: `Use this tool to list all tasks in the task list.
2209
-
2210
- ## Output
2211
-
2212
- Returns a summary of each task:
2213
- - id: Task identifier (use with TaskUpdate)
2214
- - subject: Brief description of the task
2215
- - status: pending, in_progress, or completed`,
2216
- parameters: z.object({}),
2217
- handler: async () => {
2218
- if (tasks.size === 0) {
2219
- return { content: "No tasks in the list." };
2220
- }
2189
+ handler: async ({ todos }) => {
2221
2190
  const lines = [];
2222
- for (const [, task] of tasks) {
2223
- const icon = task.status === "completed" ? "x" : task.status === "in_progress" ? ">" : " ";
2224
- lines.push(`[${icon}] [${task.id}] ${task.subject}`);
2191
+ for (const todo of todos) {
2192
+ const icon = todo.status === "completed" ? "x" : todo.status === "in_progress" ? ">" : " ";
2193
+ lines.push(`[${icon}] ${todo.content}`);
2225
2194
  }
2226
- const pending = [...tasks.values()].filter((t) => t.status === "pending").length;
2227
- const inProgress = [...tasks.values()].filter((t) => t.status === "in_progress").length;
2228
- const completed = [...tasks.values()].filter((t) => t.status === "completed").length;
2195
+ const pending = todos.filter((todo) => todo.status === "pending").length;
2196
+ const inProgress = todos.filter((todo) => todo.status === "in_progress").length;
2197
+ const completed = todos.filter((todo) => todo.status === "completed").length;
2229
2198
  return {
2230
- content: `Tasks (${completed} completed, ${inProgress} in progress, ${pending} pending):
2199
+ content: `Task list updated (${completed} completed, ${inProgress} in progress, ${pending} pending):
2231
2200
 
2232
- ${lines.join("\n")}`
2201
+ ${lines.join("\n")}`,
2202
+ metadata: { todos }
2233
2203
  };
2234
2204
  }
2235
2205
  });
2236
- function getTaskTools() {
2237
- return [taskCreateTool, taskUpdateTool, taskListTool];
2206
+ function getPlanningTools() {
2207
+ return [todoWriteTool];
2238
2208
  }
2239
2209
  var questionsSchema = z.object({
2240
2210
  questions: z.array(
@@ -2390,10 +2360,35 @@ ${availableList}`,
2390
2360
  function getSkillTools(skillRegistry) {
2391
2361
  return [createSkillTool(skillRegistry)];
2392
2362
  }
2363
+
2364
+ // src/tools/builtin/subagent-profiles.ts
2365
+ var SUBAGENT_TYPES = ["general-purpose", "explore"];
2366
+ var EXPLORE_SYSTEM_APPEND = `## Subagent role: explore
2367
+
2368
+ You are running as a read-focused subagent. Prefer **Read**, **Glob**, and **Grep** to locate and cite evidence; use **WebFetch** / **WebSearch** when external facts are needed. Summarize findings with file paths and short excerpts. If your tool list includes editing or shell (for example when the parent set \`allowed_tools\` explicitly), use those only when strictly necessary for the delegated task.`;
2369
+ var SUBAGENT_EXPLORE_DEFAULT_TOOL_NAMES = [
2370
+ "Read",
2371
+ "Glob",
2372
+ "Grep",
2373
+ "WebFetch",
2374
+ "WebSearch"
2375
+ ];
2376
+ function subagentExploreDefaultsUnavailableMessage() {
2377
+ const listed = SUBAGENT_EXPLORE_DEFAULT_TOOL_NAMES.join(", ");
2378
+ return `Explore subagent: none of the default tools (${listed}) are available from the parent agent. Register them on the parent, widen parent tools, or pass allowed_tools.`;
2379
+ }
2380
+ function resolveSubagentTypeAppend(type, subagent) {
2381
+ const custom = subagent?.subagentTypePrompts?.[type];
2382
+ if (custom !== void 0) {
2383
+ const trimmed = custom.trim();
2384
+ return trimmed === "" ? void 0 : custom;
2385
+ }
2386
+ return type === "explore" ? EXPLORE_SYSTEM_APPEND : void 0;
2387
+ }
2393
2388
  var subagentRequestSchema = z.object({
2394
2389
  prompt: z.string().min(1).describe("Task prompt for the subagent. Include all required context."),
2395
2390
  description: z.string().optional().describe("Short 3-5 words task label for logs and metadata."),
2396
- subagent_type: z.enum(["general-purpose", "explore"]).default("general-purpose").describe("Subagent profile/type to use."),
2391
+ subagent_type: z.enum(SUBAGENT_TYPES).default("general-purpose").describe("Subagent profile/type to use."),
2397
2392
  allowed_tools: z.array(z.string().min(1)).optional().describe("Optional allowlist of tool names for the subagent."),
2398
2393
  max_iterations: z.number().int().min(1).optional().describe("Maximum reasoning iterations for the subagent."),
2399
2394
  timeout_ms: z.number().int().min(1e3).optional().describe("Timeout for this subagent run in milliseconds."),
@@ -2419,7 +2414,8 @@ When NOT to use this tool:
2419
2414
 
2420
2415
  Usage notes:
2421
2416
  - Always pass a short description and a complete prompt with all required context
2422
- - Use subagent_type to select behavior; default is general-purpose
2417
+ - Use subagent_type: **general-purpose** (default) for balanced work, or **explore** for read-focused runs (SDK appends explore instructions; if you omit allowed_tools and subagent.defaultAllowedTools, tools default to Read/Glob/Grep/WebFetch/WebSearch)
2418
+ - Optional system_prompt is merged after the type-specific fragment; override per-type text via AgentConfig.subagent.subagentTypePrompts if needed
2423
2419
  - Subagents do not inherit parent conversation history, only the prompt you provide
2424
2420
  - Subagents cannot spawn other subagents (no nested Agent calls)`,
2425
2421
  parameters: subagentRequestSchema,
@@ -2445,7 +2441,7 @@ function getAllBuiltinTools(skillRegistry, interactionOptions) {
2445
2441
  ...getShellTools(),
2446
2442
  ...getGrepTools(),
2447
2443
  ...getWebTools(),
2448
- ...getTaskTools(),
2444
+ ...getPlanningTools(),
2449
2445
  ...getInteractionTools(interactionOptions),
2450
2446
  ...getSubagentTools(),
2451
2447
  ...getSkillTools(skillRegistry)
@@ -2856,6 +2852,6 @@ function createFunctionHook(config) {
2856
2852
  };
2857
2853
  }
2858
2854
 
2859
- export { DEFAULT_GREP_HEAD_LIMIT, FileStorageStrategy, HookManager, MAX_LINE_LENGTH2 as MAX_LINE_LENGTH, OUTPUT_CONFIG, OutputHandler, PaginationHintStrategy, SmartTruncateStrategy, ToolRegistry, agentTool, bashTool, buildHookEnv, createAgentTool, createAskUserQuestionTool, createFunctionHook, createOutputHandler, createSkillTool, createTool, editTool, formatAnswerSummary, formatAskUserQuestionPrompt, formatEnvironmentSection, getAllBuiltinTools, getEnvironmentInfo, getFileSystemTools, getGlobalRegistry, getGrepTools, getInteractionTools, getSafeBuiltinTools, getShellTools, getSkillTools, getSubagentTools, getTaskTools, getWebTools, globTool, grepTool, loadHooksSettingsFromProject, loadHooksSettingsFromUser, matchTool, mergeCommandHookLayers, parseHooksSettingsFile, questionTool, readFileTool, subagentRequestSchema, taskCreateTool, taskListTool, taskUpdateTool, truncateMatchLineForDisplay, webFetchTool, webSearchTool, writeFileTool };
2860
- //# sourceMappingURL=chunk-THKEF32L.js.map
2861
- //# sourceMappingURL=chunk-THKEF32L.js.map
2855
+ export { DEFAULT_GREP_HEAD_LIMIT, FileStorageStrategy, HookManager, MAX_LINE_LENGTH2 as MAX_LINE_LENGTH, OUTPUT_CONFIG, OutputHandler, PaginationHintStrategy, SUBAGENT_EXPLORE_DEFAULT_TOOL_NAMES, SUBAGENT_TYPES, SmartTruncateStrategy, ToolRegistry, agentTool, bashTool, buildHookEnv, createAgentTool, createAskUserQuestionTool, createFunctionHook, createOutputHandler, createSkillTool, createTool, editTool, formatAnswerSummary, formatAskUserQuestionPrompt, formatEnvironmentSection, getAllBuiltinTools, getEnvironmentInfo, getFileSystemTools, getGlobalRegistry, getGrepTools, getInteractionTools, getPlanningTools, getSafeBuiltinTools, getShellTools, getSkillTools, getSubagentTools, getWebTools, globTool, grepTool, loadHooksSettingsFromProject, loadHooksSettingsFromUser, matchTool, mergeCommandHookLayers, parseHooksSettingsFile, questionTool, readFileTool, resolveSubagentTypeAppend, subagentExploreDefaultsUnavailableMessage, subagentRequestSchema, todoWriteTool, truncateMatchLineForDisplay, webFetchTool, webSearchTool, writeFileTool };
2856
+ //# sourceMappingURL=chunk-TKUPLTGJ.js.map
2857
+ //# sourceMappingURL=chunk-TKUPLTGJ.js.map