pulse-coder-engine 0.0.1-alpha.11 → 0.0.1-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -43,12 +43,14 @@ __export(src_exports, {
43
43
  PluginManager: () => PluginManager,
44
44
  PulseAgent: () => Engine,
45
45
  ReadTool: () => ReadTool,
46
+ TaskListService: () => TaskListService,
46
47
  TavilyTool: () => TavilyTool,
47
48
  WriteTool: () => WriteTool,
48
49
  builtInMCPPlugin: () => builtInMCPPlugin,
49
50
  builtInPlanModePlugin: () => builtInPlanModePlugin,
50
51
  builtInPlugins: () => builtInPlugins,
51
52
  builtInSkillsPlugin: () => builtInSkillsPlugin,
53
+ builtInTaskTrackingPlugin: () => builtInTaskTrackingPlugin,
52
54
  getFinalToolsMap: () => getFinalToolsMap,
53
55
  loop: () => loop,
54
56
  maybeCompactContext: () => maybeCompactContext,
@@ -747,7 +749,7 @@ var GrepTool = {
747
749
  }),
748
750
  execute: async ({
749
751
  pattern,
750
- path: path5 = ".",
752
+ path: path6 = ".",
751
753
  glob: glob2,
752
754
  type,
753
755
  outputMode = "files_with_matches",
@@ -782,11 +784,11 @@ var GrepTool = {
782
784
  if (type) {
783
785
  args.push("--type", type);
784
786
  }
785
- if (path5 && path5 !== ".") {
786
- if (!(0, import_fs5.existsSync)(path5)) {
787
- throw new Error(`Path does not exist: ${path5}`);
787
+ if (path6 && path6 !== ".") {
788
+ if (!(0, import_fs5.existsSync)(path6)) {
789
+ throw new Error(`Path does not exist: ${path6}`);
788
790
  }
789
- args.push(path5);
791
+ args.push(path6);
790
792
  }
791
793
  let command = args.map((arg) => {
792
794
  if (arg.includes(" ") || arg.includes("$") || arg.includes("*")) {
@@ -841,8 +843,8 @@ var LsTool = {
841
843
  inputSchema: import_zod5.default.object({
842
844
  path: import_zod5.default.string().optional().describe("The path to list files from (defaults to current directory)")
843
845
  }),
844
- execute: async ({ path: path5 = "." }) => {
845
- const files = (0, import_fs6.readdirSync)(path5);
846
+ execute: async ({ path: path6 = "." }) => {
847
+ const files = (0, import_fs6.readdirSync)(path6);
846
848
  return { files };
847
849
  }
848
850
  };
@@ -1614,16 +1616,44 @@ var BuiltInSkillRegistry = class {
1614
1616
  return Array.from(this.skills.values());
1615
1617
  }
1616
1618
  /**
1617
- * 根据名称获取技能
1619
+ * 注册或更新一个技能(支持插件在运行期追加技能)
1620
+ */
1621
+ registerSkill(skill) {
1622
+ const name = skill.name?.trim();
1623
+ if (!name) {
1624
+ throw new Error("Skill name is required");
1625
+ }
1626
+ const existingKey = Array.from(this.skills.keys()).find((key) => key.toLowerCase() === name.toLowerCase());
1627
+ const replaced = existingKey !== void 0;
1628
+ if (existingKey && existingKey !== name) {
1629
+ this.skills.delete(existingKey);
1630
+ }
1631
+ this.skills.set(name, {
1632
+ ...skill,
1633
+ name
1634
+ });
1635
+ return {
1636
+ skillName: name,
1637
+ replaced,
1638
+ total: this.skills.size
1639
+ };
1640
+ }
1641
+ /**
1642
+ * 根据名称获取技能(大小写不敏感)
1618
1643
  */
1619
1644
  get(name) {
1620
- return this.skills.get(name);
1645
+ const exact = this.skills.get(name);
1646
+ if (exact) {
1647
+ return exact;
1648
+ }
1649
+ const target = name.toLowerCase();
1650
+ return this.getAll().find((skill) => skill.name.toLowerCase() === target);
1621
1651
  }
1622
1652
  /**
1623
1653
  * 检查技能是否存在
1624
1654
  */
1625
1655
  has(name) {
1626
- return this.skills.has(name);
1656
+ return !!this.get(name);
1627
1657
  }
1628
1658
  /**
1629
1659
  * 搜索技能(模糊匹配)
@@ -1638,7 +1668,7 @@ var BuiltInSkillRegistry = class {
1638
1668
  var skillToolSchema = import_zod10.z.object({
1639
1669
  name: import_zod10.z.string().describe("The name of the skill to execute")
1640
1670
  });
1641
- function generateSkillTool(skills) {
1671
+ function generateSkillTool(registry) {
1642
1672
  const getSkillsPrompt = (availableSkills) => {
1643
1673
  return [
1644
1674
  "If query matches an available skill's description or instruction [use skill], use the skill tool to get detailed instructions.",
@@ -1659,10 +1689,10 @@ function generateSkillTool(skills) {
1659
1689
  };
1660
1690
  return {
1661
1691
  name: "skill",
1662
- description: getSkillsPrompt(skills),
1692
+ description: getSkillsPrompt(registry.getAll()),
1663
1693
  inputSchema: skillToolSchema,
1664
1694
  execute: async ({ name }) => {
1665
- const skill = skills.find((skill2) => skill2.name === name);
1695
+ const skill = registry.get(name);
1666
1696
  if (!skill) {
1667
1697
  throw new Error(`Skill ${name} not found`);
1668
1698
  }
@@ -1676,14 +1706,21 @@ var builtInSkillsPlugin = {
1676
1706
  async initialize(context) {
1677
1707
  const registry = new BuiltInSkillRegistry();
1678
1708
  await registry.initialize(process.cwd());
1709
+ context.registerService("skillRegistry", registry);
1710
+ context.registerTool("skill", generateSkillTool(registry));
1711
+ context.registerHook("beforeRun", ({ tools }) => {
1712
+ return {
1713
+ tools: {
1714
+ ...tools,
1715
+ skill: generateSkillTool(registry)
1716
+ }
1717
+ };
1718
+ });
1679
1719
  const skills = registry.getAll();
1680
1720
  if (skills.length === 0) {
1681
1721
  console.log("[Skills] No skills found");
1682
1722
  return;
1683
1723
  }
1684
- const skillTool = generateSkillTool(skills);
1685
- context.registerTool("skill", skillTool);
1686
- context.registerService("skillRegistry", registry);
1687
1724
  console.log(`[Skills] Registered ${skills.length} skill(s)`);
1688
1725
  }
1689
1726
  };
@@ -1794,6 +1831,26 @@ var KNOWN_TOOL_META = {
1794
1831
  category: "other",
1795
1832
  risk: "low",
1796
1833
  description: "Ask the user a targeted clarification question."
1834
+ },
1835
+ task_create: {
1836
+ category: "other",
1837
+ risk: "low",
1838
+ description: "Create tracked task entries for planning and execution visibility."
1839
+ },
1840
+ task_get: {
1841
+ category: "other",
1842
+ risk: "low",
1843
+ description: "Inspect a task entry by ID."
1844
+ },
1845
+ task_list: {
1846
+ category: "other",
1847
+ risk: "low",
1848
+ description: "List task tracking entries and status summary."
1849
+ },
1850
+ task_update: {
1851
+ category: "other",
1852
+ risk: "low",
1853
+ description: "Update task tracking fields and status."
1797
1854
  }
1798
1855
  };
1799
1856
  var BuiltInPlanModeService = class {
@@ -2073,17 +2130,404 @@ var builtInPlanModePlugin = {
2073
2130
  }
2074
2131
  };
2075
2132
 
2076
- // src/built-in/sub-agent-plugin/index.ts
2077
- var import_zod11 = require("zod");
2133
+ // src/built-in/task-tracking-plugin/index.ts
2078
2134
  var import_fs10 = require("fs");
2079
2135
  var import_path4 = __toESM(require("path"), 1);
2136
+ var import_os2 = require("os");
2137
+ var import_crypto2 = require("crypto");
2138
+ var import_zod11 = require("zod");
2139
+ var TASK_STATUSES = ["pending", "in_progress", "completed", "blocked"];
2140
+ var CREATE_TASK_ITEM_SCHEMA = import_zod11.z.object({
2141
+ title: import_zod11.z.string().min(1).describe("Task title"),
2142
+ details: import_zod11.z.string().optional().describe("Task details / acceptance notes"),
2143
+ status: import_zod11.z.enum(TASK_STATUSES).optional().describe("Initial status; defaults to pending"),
2144
+ dependencies: import_zod11.z.array(import_zod11.z.string()).optional().describe("Task IDs that must be completed first"),
2145
+ blockedReason: import_zod11.z.string().optional().describe("Reason when status is blocked"),
2146
+ metadata: import_zod11.z.record(import_zod11.z.string(), import_zod11.z.any()).optional().describe("Additional machine-readable metadata")
2147
+ });
2148
+ var TASK_CREATE_INPUT_SCHEMA = import_zod11.z.object({
2149
+ title: import_zod11.z.string().min(1).optional().describe("Task title (single-task mode)"),
2150
+ details: import_zod11.z.string().optional().describe("Task details (single-task mode)"),
2151
+ status: import_zod11.z.enum(TASK_STATUSES).optional().describe("Initial status (single-task mode)"),
2152
+ dependencies: import_zod11.z.array(import_zod11.z.string()).optional().describe("Dependencies (single-task mode)"),
2153
+ blockedReason: import_zod11.z.string().optional().describe("Blocked reason (single-task mode)"),
2154
+ metadata: import_zod11.z.record(import_zod11.z.string(), import_zod11.z.any()).optional().describe("Metadata (single-task mode)"),
2155
+ tasks: import_zod11.z.array(CREATE_TASK_ITEM_SCHEMA).min(1).optional().describe("Batch create mode")
2156
+ }).refine((value) => !!value.tasks?.length || !!value.title, {
2157
+ message: "Either provide `tasks` or `title` for single-task mode."
2158
+ });
2159
+ var TASK_GET_INPUT_SCHEMA = import_zod11.z.object({
2160
+ id: import_zod11.z.string().min(1).describe("Task ID to retrieve")
2161
+ });
2162
+ var TASK_LIST_INPUT_SCHEMA = import_zod11.z.object({
2163
+ statuses: import_zod11.z.array(import_zod11.z.enum(TASK_STATUSES)).optional().describe("Filter by statuses"),
2164
+ includeCompleted: import_zod11.z.boolean().optional().describe("Set false to hide completed tasks"),
2165
+ limit: import_zod11.z.number().int().positive().max(500).optional().describe("Maximum tasks to return")
2166
+ });
2167
+ var TASK_TRACKING_SKILL = {
2168
+ name: "task-tracking-workflow",
2169
+ description: "Track complex execution with task tools and proceed directly without confirmation unless the user explicitly asks for confirmation.",
2170
+ location: "pulse-coder-engine/built-in/task-tracking-plugin",
2171
+ content: `# Task Tracking Workflow
2172
+
2173
+ ## When to use
2174
+ - The request has multiple phases or deliverables.
2175
+ - Work may span multiple tool calls or sessions.
2176
+ - You need explicit progress visibility and blocker management.
2177
+
2178
+ ## Execution autonomy
2179
+ - Default behavior: execute directly and call tools without asking for confirmation.
2180
+ - Only ask for confirmation when the user explicitly requires confirmation.
2181
+ - If critical information is missing, ask only the minimum clarifying question needed to continue.
2182
+
2183
+ ## Required flow
2184
+ 1. Start by reviewing existing tasks with \`task_list\`.
2185
+ 2. If no suitable tasks exist, create focused tasks with \`task_create\` (prefer batch mode).
2186
+ 3. Keep exactly one primary task in \`in_progress\` where possible.
2187
+ 4. Update status with \`task_update\` after meaningful progress.
2188
+ 5. Mark blockers with \`status=blocked\` and a concrete \`blockedReason\`.
2189
+ 6. Mark done tasks as \`completed\` and move to the next actionable item.
2190
+
2191
+ ## Quality rules
2192
+ - Keep tasks atomic and verifiable.
2193
+ - Avoid single oversized umbrella tasks.
2194
+ - Reuse existing in-progress tasks instead of duplicating.
2195
+ - Keep dependency links explicit when order matters.`
2196
+ };
2197
+ var TASK_UPDATE_INPUT_SCHEMA = import_zod11.z.object({
2198
+ id: import_zod11.z.string().min(1).describe("Task ID to update"),
2199
+ title: import_zod11.z.string().min(1).optional().describe("New title"),
2200
+ details: import_zod11.z.string().optional().describe("New details"),
2201
+ status: import_zod11.z.enum(TASK_STATUSES).optional().describe("New status"),
2202
+ dependencies: import_zod11.z.array(import_zod11.z.string()).optional().describe("Replace dependencies with this list"),
2203
+ blockedReason: import_zod11.z.string().optional().describe("Blocked reason, used with status=blocked"),
2204
+ metadata: import_zod11.z.record(import_zod11.z.string(), import_zod11.z.any()).optional().describe("Replace metadata object"),
2205
+ delete: import_zod11.z.boolean().optional().describe("Delete this task")
2206
+ });
2207
+ function normalizeTaskListId(raw) {
2208
+ const trimmed = raw.trim();
2209
+ if (!trimmed) {
2210
+ return "default";
2211
+ }
2212
+ return trimmed.replace(/[^a-zA-Z0-9._-]/g, "-").slice(0, 120) || "default";
2213
+ }
2214
+ function now() {
2215
+ return Date.now();
2216
+ }
2217
+ function dedupeStrings(values) {
2218
+ if (!values?.length) {
2219
+ return [];
2220
+ }
2221
+ return Array.from(new Set(values.map((value) => String(value).trim()).filter(Boolean)));
2222
+ }
2223
+ var TaskListService = class _TaskListService {
2224
+ taskListId;
2225
+ storagePath;
2226
+ storageDir;
2227
+ initialized = false;
2228
+ createdAt = now();
2229
+ updatedAt = now();
2230
+ tasks = /* @__PURE__ */ new Map();
2231
+ constructor(taskListId = _TaskListService.resolveTaskListId(), storageDir = _TaskListService.resolveStorageDir()) {
2232
+ const normalized = normalizeTaskListId(taskListId);
2233
+ this.storageDir = storageDir;
2234
+ this.taskListId = normalized;
2235
+ this.storagePath = import_path4.default.join(this.storageDir, `${normalized}.json`);
2236
+ }
2237
+ static resolveTaskListId() {
2238
+ return process.env.PULSE_CODER_TASK_LIST_ID || process.env.CLAUDE_CODE_TASK_LIST_ID || "default";
2239
+ }
2240
+ static resolveStorageDir() {
2241
+ return process.env.PULSE_CODER_TASKS_DIR || import_path4.default.join((0, import_os2.homedir)(), ".pulse-coder", "tasks");
2242
+ }
2243
+ async initialize() {
2244
+ if (this.initialized) {
2245
+ return;
2246
+ }
2247
+ await this.loadTaskList(this.taskListId);
2248
+ }
2249
+ async setTaskListId(taskListId) {
2250
+ await this.initialize();
2251
+ const normalized = normalizeTaskListId(taskListId);
2252
+ if (normalized === this.taskListId) {
2253
+ return {
2254
+ switched: false,
2255
+ taskListId: this.taskListId,
2256
+ storagePath: this.storagePath
2257
+ };
2258
+ }
2259
+ await this.loadTaskList(normalized);
2260
+ return {
2261
+ switched: true,
2262
+ taskListId: this.taskListId,
2263
+ storagePath: this.storagePath
2264
+ };
2265
+ }
2266
+ async createTask(input) {
2267
+ await this.initialize();
2268
+ const timestamp = now();
2269
+ const status = input.status ?? "pending";
2270
+ const task = {
2271
+ id: (0, import_crypto2.randomUUID)(),
2272
+ title: input.title.trim(),
2273
+ details: input.details,
2274
+ status,
2275
+ dependencies: dedupeStrings(input.dependencies),
2276
+ blockedReason: status === "blocked" ? input.blockedReason ?? "Blocked without reason" : void 0,
2277
+ metadata: input.metadata,
2278
+ createdAt: timestamp,
2279
+ updatedAt: timestamp,
2280
+ completedAt: status === "completed" ? timestamp : void 0
2281
+ };
2282
+ this.tasks.set(task.id, task);
2283
+ this.updatedAt = timestamp;
2284
+ await this.persist();
2285
+ return task;
2286
+ }
2287
+ async createTasks(inputs) {
2288
+ const created = [];
2289
+ for (const input of inputs) {
2290
+ created.push(await this.createTask(input));
2291
+ }
2292
+ return created;
2293
+ }
2294
+ async listTasks(options) {
2295
+ await this.initialize();
2296
+ const statuses = options?.statuses?.length ? new Set(options.statuses) : null;
2297
+ const includeCompleted = options?.includeCompleted ?? true;
2298
+ let tasks = Array.from(this.tasks.values()).filter((task) => {
2299
+ if (!includeCompleted && task.status === "completed") {
2300
+ return false;
2301
+ }
2302
+ if (statuses && !statuses.has(task.status)) {
2303
+ return false;
2304
+ }
2305
+ return true;
2306
+ });
2307
+ tasks = tasks.sort((a, b) => a.createdAt - b.createdAt);
2308
+ if (options?.limit && options.limit > 0) {
2309
+ tasks = tasks.slice(0, options.limit);
2310
+ }
2311
+ return tasks;
2312
+ }
2313
+ async getTask(id) {
2314
+ await this.initialize();
2315
+ return this.tasks.get(id) ?? null;
2316
+ }
2317
+ async updateTask(input) {
2318
+ await this.initialize();
2319
+ if (input.delete) {
2320
+ const deleted = this.tasks.delete(input.id);
2321
+ if (!deleted) {
2322
+ return null;
2323
+ }
2324
+ this.updatedAt = now();
2325
+ await this.persist();
2326
+ return null;
2327
+ }
2328
+ const existing = this.tasks.get(input.id);
2329
+ if (!existing) {
2330
+ return null;
2331
+ }
2332
+ const timestamp = now();
2333
+ const nextStatus = input.status ?? existing.status;
2334
+ const next = {
2335
+ ...existing,
2336
+ title: input.title !== void 0 ? input.title : existing.title,
2337
+ details: input.details !== void 0 ? input.details : existing.details,
2338
+ status: nextStatus,
2339
+ dependencies: input.dependencies !== void 0 ? dedupeStrings(input.dependencies) : existing.dependencies,
2340
+ metadata: input.metadata !== void 0 ? input.metadata : existing.metadata,
2341
+ blockedReason: this.resolveBlockedReason(nextStatus, input.blockedReason, existing.blockedReason),
2342
+ updatedAt: timestamp,
2343
+ completedAt: nextStatus === "completed" ? existing.completedAt ?? timestamp : void 0
2344
+ };
2345
+ this.tasks.set(input.id, next);
2346
+ this.updatedAt = timestamp;
2347
+ await this.persist();
2348
+ return next;
2349
+ }
2350
+ async snapshot(options) {
2351
+ const tasks = await this.listTasks(options);
2352
+ return {
2353
+ taskListId: this.taskListId,
2354
+ storagePath: this.storagePath,
2355
+ createdAt: this.createdAt,
2356
+ updatedAt: this.updatedAt,
2357
+ total: tasks.length,
2358
+ tasks
2359
+ };
2360
+ }
2361
+ resolveBlockedReason(status, blockedReasonInput, previous) {
2362
+ if (status !== "blocked") {
2363
+ return void 0;
2364
+ }
2365
+ if (blockedReasonInput !== void 0) {
2366
+ return blockedReasonInput || "Blocked without reason";
2367
+ }
2368
+ return previous ?? "Blocked without reason";
2369
+ }
2370
+ async loadTaskList(taskListId) {
2371
+ const normalized = normalizeTaskListId(taskListId);
2372
+ this.taskListId = normalized;
2373
+ this.storagePath = import_path4.default.join(this.storageDir, `${normalized}.json`);
2374
+ await import_fs10.promises.mkdir(this.storageDir, { recursive: true });
2375
+ try {
2376
+ const raw = await import_fs10.promises.readFile(this.storagePath, "utf-8");
2377
+ const parsed = JSON.parse(raw);
2378
+ const parsedTasks = Array.isArray(parsed.tasks) ? parsed.tasks : [];
2379
+ this.tasks = new Map(parsedTasks.filter((task) => !!task?.id).map((task) => [task.id, task]));
2380
+ this.createdAt = typeof parsed.createdAt === "number" ? parsed.createdAt : now();
2381
+ this.updatedAt = typeof parsed.updatedAt === "number" ? parsed.updatedAt : now();
2382
+ } catch (error) {
2383
+ if (error?.code !== "ENOENT") {
2384
+ throw error;
2385
+ }
2386
+ const timestamp = now();
2387
+ this.tasks = /* @__PURE__ */ new Map();
2388
+ this.createdAt = timestamp;
2389
+ this.updatedAt = timestamp;
2390
+ await this.persist();
2391
+ }
2392
+ this.initialized = true;
2393
+ }
2394
+ async persist() {
2395
+ const payload = {
2396
+ taskListId: this.taskListId,
2397
+ createdAt: this.createdAt,
2398
+ updatedAt: this.updatedAt,
2399
+ tasks: Array.from(this.tasks.values()).sort((a, b) => a.createdAt - b.createdAt)
2400
+ };
2401
+ await import_fs10.promises.writeFile(this.storagePath, JSON.stringify(payload, null, 2), "utf-8");
2402
+ }
2403
+ };
2404
+ function buildTaskCreateTool(service) {
2405
+ return {
2406
+ name: "task_create",
2407
+ description: "Create one or more tracked tasks for complex work. Use this when work has multiple steps, dependencies, or blockers.",
2408
+ inputSchema: TASK_CREATE_INPUT_SCHEMA,
2409
+ execute: async ({ tasks, title, details, status, dependencies, blockedReason, metadata }) => {
2410
+ const items = tasks?.length ? tasks : [{ title, details, status, dependencies, blockedReason, metadata }];
2411
+ const created = await service.createTasks(items);
2412
+ return {
2413
+ taskListId: service.taskListId,
2414
+ storagePath: service.storagePath,
2415
+ createdCount: created.length,
2416
+ tasks: created
2417
+ };
2418
+ }
2419
+ };
2420
+ }
2421
+ function buildTaskGetTool(service) {
2422
+ return {
2423
+ name: "task_get",
2424
+ description: "Get full details for a single task by task ID.",
2425
+ inputSchema: TASK_GET_INPUT_SCHEMA,
2426
+ execute: async ({ id }) => {
2427
+ const task = await service.getTask(id);
2428
+ if (!task) {
2429
+ throw new Error(`Task not found: ${id}`);
2430
+ }
2431
+ return {
2432
+ taskListId: service.taskListId,
2433
+ storagePath: service.storagePath,
2434
+ task
2435
+ };
2436
+ }
2437
+ };
2438
+ }
2439
+ function buildTaskListTool(service) {
2440
+ return {
2441
+ name: "task_list",
2442
+ description: "List tasks and their current status. Use this to check progress before and after major changes.",
2443
+ inputSchema: TASK_LIST_INPUT_SCHEMA,
2444
+ execute: async ({ statuses, includeCompleted, limit }) => {
2445
+ const snapshot = await service.snapshot({ statuses, includeCompleted, limit });
2446
+ const completed = snapshot.tasks.filter((task) => task.status === "completed").length;
2447
+ const inProgress = snapshot.tasks.filter((task) => task.status === "in_progress").length;
2448
+ const pending = snapshot.tasks.filter((task) => task.status === "pending").length;
2449
+ const blocked = snapshot.tasks.filter((task) => task.status === "blocked").length;
2450
+ return {
2451
+ ...snapshot,
2452
+ summary: {
2453
+ total: snapshot.total,
2454
+ completed,
2455
+ inProgress,
2456
+ pending,
2457
+ blocked
2458
+ }
2459
+ };
2460
+ }
2461
+ };
2462
+ }
2463
+ function buildTaskUpdateTool(service) {
2464
+ return {
2465
+ name: "task_update",
2466
+ description: "Update task fields, move status (pending/in_progress/completed/blocked), or delete tasks.",
2467
+ inputSchema: TASK_UPDATE_INPUT_SCHEMA,
2468
+ execute: async (input) => {
2469
+ const task = await service.updateTask(input);
2470
+ if (input.delete) {
2471
+ return {
2472
+ taskListId: service.taskListId,
2473
+ storagePath: service.storagePath,
2474
+ deleted: true,
2475
+ id: input.id
2476
+ };
2477
+ }
2478
+ if (!task) {
2479
+ throw new Error(`Task not found: ${input.id}`);
2480
+ }
2481
+ return {
2482
+ taskListId: service.taskListId,
2483
+ storagePath: service.storagePath,
2484
+ deleted: false,
2485
+ task
2486
+ };
2487
+ }
2488
+ };
2489
+ }
2490
+ var builtInTaskTrackingPlugin = {
2491
+ name: "pulse-coder-engine/built-in-task-tracking",
2492
+ version: "1.0.0",
2493
+ dependencies: ["pulse-coder-engine/built-in-skills"],
2494
+ async initialize(context) {
2495
+ const service = new TaskListService();
2496
+ await service.initialize();
2497
+ context.registerService("taskListService", service);
2498
+ context.registerService("taskTracking", service);
2499
+ const skillRegistry = context.getService("skillRegistry");
2500
+ if (skillRegistry) {
2501
+ const registration = skillRegistry.registerSkill(TASK_TRACKING_SKILL);
2502
+ context.logger.info("[TaskTracking] Registered built-in task tracking skill", registration);
2503
+ } else {
2504
+ context.logger.warn("[TaskTracking] skillRegistry service unavailable; skipped task tracking skill registration");
2505
+ }
2506
+ context.registerTools({
2507
+ task_create: buildTaskCreateTool(service),
2508
+ task_get: buildTaskGetTool(service),
2509
+ task_list: buildTaskListTool(service),
2510
+ task_update: buildTaskUpdateTool(service)
2511
+ });
2512
+ context.logger.info("[TaskTracking] Registered task tools", {
2513
+ taskListId: service.taskListId,
2514
+ storagePath: service.storagePath,
2515
+ skillRegistryAvailable: !!skillRegistry
2516
+ });
2517
+ }
2518
+ };
2519
+
2520
+ // src/built-in/sub-agent-plugin/index.ts
2521
+ var import_zod12 = require("zod");
2522
+ var import_fs11 = require("fs");
2523
+ var import_path5 = __toESM(require("path"), 1);
2080
2524
  var ConfigLoader = class {
2081
2525
  async getAgentFilesInfo(configDirs) {
2082
2526
  const fileInfos = [];
2083
2527
  for (let configDir of configDirs) {
2084
2528
  try {
2085
- await import_fs10.promises.access(configDir);
2086
- const files = await import_fs10.promises.readdir(configDir);
2529
+ await import_fs11.promises.access(configDir);
2530
+ const files = await import_fs11.promises.readdir(configDir);
2087
2531
  fileInfos.push({ files, configDir });
2088
2532
  } catch {
2089
2533
  continue;
@@ -2100,7 +2544,7 @@ var ConfigLoader = class {
2100
2544
  const files = fileInfo.files;
2101
2545
  for (const file of files) {
2102
2546
  if (file.endsWith(".md")) {
2103
- const config = await this.parseConfig(import_path4.default.join(fileInfo.configDir, file));
2547
+ const config = await this.parseConfig(import_path5.default.join(fileInfo.configDir, file));
2104
2548
  if (config) configs.push(config);
2105
2549
  }
2106
2550
  }
@@ -2112,7 +2556,7 @@ var ConfigLoader = class {
2112
2556
  }
2113
2557
  async parseConfig(filePath) {
2114
2558
  try {
2115
- const content = await import_fs10.promises.readFile(filePath, "utf-8");
2559
+ const content = await import_fs11.promises.readFile(filePath, "utf-8");
2116
2560
  const lines = content.split("\n");
2117
2561
  let name = "";
2118
2562
  let description = "";
@@ -2141,7 +2585,7 @@ var ConfigLoader = class {
2141
2585
  }
2142
2586
  }
2143
2587
  if (!name) {
2144
- name = import_path4.default.basename(filePath, ".md");
2588
+ name = import_path5.default.basename(filePath, ".md");
2145
2589
  }
2146
2590
  return {
2147
2591
  name: name.trim(),
@@ -2192,9 +2636,9 @@ var SubAgentPlugin = class {
2192
2636
  const toolName = `${config.name}_agent`;
2193
2637
  const tool2 = {
2194
2638
  description: config.description,
2195
- inputSchema: import_zod11.z.object({
2196
- task: import_zod11.z.string().describe("\u8981\u6267\u884C\u7684\u4EFB\u52A1\u63CF\u8FF0"),
2197
- context: import_zod11.z.any().optional().describe("\u4EFB\u52A1\u4E0A\u4E0B\u6587\u4FE1\u606F")
2639
+ inputSchema: import_zod12.z.object({
2640
+ task: import_zod12.z.string().describe("\u8981\u6267\u884C\u7684\u4EFB\u52A1\u63CF\u8FF0"),
2641
+ context: import_zod12.z.any().optional().describe("\u4EFB\u52A1\u4E0A\u4E0B\u6587\u4FE1\u606F")
2198
2642
  }),
2199
2643
  execute: async ({ task, context: taskContext }) => {
2200
2644
  const tools = { ...BuiltinToolsMap, ...context.getTools() };
@@ -2221,6 +2665,7 @@ var builtInPlugins = [
2221
2665
  builtInMCPPlugin,
2222
2666
  builtInSkillsPlugin,
2223
2667
  builtInPlanModePlugin,
2668
+ builtInTaskTrackingPlugin,
2224
2669
  new SubAgentPlugin()
2225
2670
  ];
2226
2671
 
@@ -2408,12 +2853,14 @@ var Engine = class {
2408
2853
  PluginManager,
2409
2854
  PulseAgent,
2410
2855
  ReadTool,
2856
+ TaskListService,
2411
2857
  TavilyTool,
2412
2858
  WriteTool,
2413
2859
  builtInMCPPlugin,
2414
2860
  builtInPlanModePlugin,
2415
2861
  builtInPlugins,
2416
2862
  builtInSkillsPlugin,
2863
+ builtInTaskTrackingPlugin,
2417
2864
  getFinalToolsMap,
2418
2865
  loop,
2419
2866
  maybeCompactContext,