pulse-coder-engine 0.0.1-alpha.11 → 0.0.1-alpha.13
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/built-in/index.cjs +550 -97
- package/dist/built-in/index.cjs.map +1 -1
- package/dist/built-in/index.d.cts +1 -1
- package/dist/built-in/index.d.ts +1 -1
- package/dist/built-in/index.js +537 -86
- package/dist/built-in/index.js.map +1 -1
- package/dist/{index-BeWyLfso.d.cts → index-CPgs_IXY.d.cts} +84 -2
- package/dist/{index-BeWyLfso.d.ts → index-CPgs_IXY.d.ts} +84 -2
- package/dist/index.cjs +479 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +477 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/built-in/index.cjs
CHANGED
|
@@ -33,10 +33,12 @@ __export(built_in_exports, {
|
|
|
33
33
|
BuiltInPlanModeService: () => BuiltInPlanModeService,
|
|
34
34
|
BuiltInSkillRegistry: () => BuiltInSkillRegistry,
|
|
35
35
|
SubAgentPlugin: () => SubAgentPlugin,
|
|
36
|
+
TaskListService: () => TaskListService,
|
|
36
37
|
builtInMCPPlugin: () => builtInMCPPlugin,
|
|
37
38
|
builtInPlanModePlugin: () => builtInPlanModePlugin,
|
|
38
39
|
builtInPlugins: () => builtInPlugins,
|
|
39
40
|
builtInSkillsPlugin: () => builtInSkillsPlugin,
|
|
41
|
+
builtInTaskTrackingPlugin: () => builtInTaskTrackingPlugin,
|
|
40
42
|
default: () => built_in_default
|
|
41
43
|
});
|
|
42
44
|
module.exports = __toCommonJS(built_in_exports);
|
|
@@ -202,16 +204,44 @@ var BuiltInSkillRegistry = class {
|
|
|
202
204
|
return Array.from(this.skills.values());
|
|
203
205
|
}
|
|
204
206
|
/**
|
|
205
|
-
*
|
|
207
|
+
* 注册或更新一个技能(支持插件在运行期追加技能)
|
|
208
|
+
*/
|
|
209
|
+
registerSkill(skill) {
|
|
210
|
+
const name = skill.name?.trim();
|
|
211
|
+
if (!name) {
|
|
212
|
+
throw new Error("Skill name is required");
|
|
213
|
+
}
|
|
214
|
+
const existingKey = Array.from(this.skills.keys()).find((key) => key.toLowerCase() === name.toLowerCase());
|
|
215
|
+
const replaced = existingKey !== void 0;
|
|
216
|
+
if (existingKey && existingKey !== name) {
|
|
217
|
+
this.skills.delete(existingKey);
|
|
218
|
+
}
|
|
219
|
+
this.skills.set(name, {
|
|
220
|
+
...skill,
|
|
221
|
+
name
|
|
222
|
+
});
|
|
223
|
+
return {
|
|
224
|
+
skillName: name,
|
|
225
|
+
replaced,
|
|
226
|
+
total: this.skills.size
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* 根据名称获取技能(大小写不敏感)
|
|
206
231
|
*/
|
|
207
232
|
get(name) {
|
|
208
|
-
|
|
233
|
+
const exact = this.skills.get(name);
|
|
234
|
+
if (exact) {
|
|
235
|
+
return exact;
|
|
236
|
+
}
|
|
237
|
+
const target = name.toLowerCase();
|
|
238
|
+
return this.getAll().find((skill) => skill.name.toLowerCase() === target);
|
|
209
239
|
}
|
|
210
240
|
/**
|
|
211
241
|
* 检查技能是否存在
|
|
212
242
|
*/
|
|
213
243
|
has(name) {
|
|
214
|
-
return this.
|
|
244
|
+
return !!this.get(name);
|
|
215
245
|
}
|
|
216
246
|
/**
|
|
217
247
|
* 搜索技能(模糊匹配)
|
|
@@ -226,7 +256,7 @@ var BuiltInSkillRegistry = class {
|
|
|
226
256
|
var skillToolSchema = import_zod.z.object({
|
|
227
257
|
name: import_zod.z.string().describe("The name of the skill to execute")
|
|
228
258
|
});
|
|
229
|
-
function generateSkillTool(
|
|
259
|
+
function generateSkillTool(registry) {
|
|
230
260
|
const getSkillsPrompt = (availableSkills) => {
|
|
231
261
|
return [
|
|
232
262
|
"If query matches an available skill's description or instruction [use skill], use the skill tool to get detailed instructions.",
|
|
@@ -247,10 +277,10 @@ function generateSkillTool(skills) {
|
|
|
247
277
|
};
|
|
248
278
|
return {
|
|
249
279
|
name: "skill",
|
|
250
|
-
description: getSkillsPrompt(
|
|
280
|
+
description: getSkillsPrompt(registry.getAll()),
|
|
251
281
|
inputSchema: skillToolSchema,
|
|
252
282
|
execute: async ({ name }) => {
|
|
253
|
-
const skill =
|
|
283
|
+
const skill = registry.get(name);
|
|
254
284
|
if (!skill) {
|
|
255
285
|
throw new Error(`Skill ${name} not found`);
|
|
256
286
|
}
|
|
@@ -264,14 +294,21 @@ var builtInSkillsPlugin = {
|
|
|
264
294
|
async initialize(context) {
|
|
265
295
|
const registry = new BuiltInSkillRegistry();
|
|
266
296
|
await registry.initialize(process.cwd());
|
|
297
|
+
context.registerService("skillRegistry", registry);
|
|
298
|
+
context.registerTool("skill", generateSkillTool(registry));
|
|
299
|
+
context.registerHook("beforeRun", ({ tools }) => {
|
|
300
|
+
return {
|
|
301
|
+
tools: {
|
|
302
|
+
...tools,
|
|
303
|
+
skill: generateSkillTool(registry)
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
});
|
|
267
307
|
const skills = registry.getAll();
|
|
268
308
|
if (skills.length === 0) {
|
|
269
309
|
console.log("[Skills] No skills found");
|
|
270
310
|
return;
|
|
271
311
|
}
|
|
272
|
-
const skillTool = generateSkillTool(skills);
|
|
273
|
-
context.registerTool("skill", skillTool);
|
|
274
|
-
context.registerService("skillRegistry", registry);
|
|
275
312
|
console.log(`[Skills] Registered ${skills.length} skill(s)`);
|
|
276
313
|
}
|
|
277
314
|
};
|
|
@@ -382,6 +419,26 @@ var KNOWN_TOOL_META = {
|
|
|
382
419
|
category: "other",
|
|
383
420
|
risk: "low",
|
|
384
421
|
description: "Ask the user a targeted clarification question."
|
|
422
|
+
},
|
|
423
|
+
task_create: {
|
|
424
|
+
category: "other",
|
|
425
|
+
risk: "low",
|
|
426
|
+
description: "Create tracked task entries for planning and execution visibility."
|
|
427
|
+
},
|
|
428
|
+
task_get: {
|
|
429
|
+
category: "other",
|
|
430
|
+
risk: "low",
|
|
431
|
+
description: "Inspect a task entry by ID."
|
|
432
|
+
},
|
|
433
|
+
task_list: {
|
|
434
|
+
category: "other",
|
|
435
|
+
risk: "low",
|
|
436
|
+
description: "List task tracking entries and status summary."
|
|
437
|
+
},
|
|
438
|
+
task_update: {
|
|
439
|
+
category: "other",
|
|
440
|
+
risk: "low",
|
|
441
|
+
description: "Update task tracking fields and status."
|
|
385
442
|
}
|
|
386
443
|
};
|
|
387
444
|
var BuiltInPlanModeService = class {
|
|
@@ -661,10 +718,397 @@ var builtInPlanModePlugin = {
|
|
|
661
718
|
}
|
|
662
719
|
};
|
|
663
720
|
|
|
721
|
+
// src/built-in/task-tracking-plugin/index.ts
|
|
722
|
+
var import_fs3 = require("fs");
|
|
723
|
+
var import_path = __toESM(require("path"), 1);
|
|
724
|
+
var import_os2 = require("os");
|
|
725
|
+
var import_crypto = require("crypto");
|
|
726
|
+
var import_zod2 = require("zod");
|
|
727
|
+
var TASK_STATUSES = ["pending", "in_progress", "completed", "blocked"];
|
|
728
|
+
var CREATE_TASK_ITEM_SCHEMA = import_zod2.z.object({
|
|
729
|
+
title: import_zod2.z.string().min(1).describe("Task title"),
|
|
730
|
+
details: import_zod2.z.string().optional().describe("Task details / acceptance notes"),
|
|
731
|
+
status: import_zod2.z.enum(TASK_STATUSES).optional().describe("Initial status; defaults to pending"),
|
|
732
|
+
dependencies: import_zod2.z.array(import_zod2.z.string()).optional().describe("Task IDs that must be completed first"),
|
|
733
|
+
blockedReason: import_zod2.z.string().optional().describe("Reason when status is blocked"),
|
|
734
|
+
metadata: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.any()).optional().describe("Additional machine-readable metadata")
|
|
735
|
+
});
|
|
736
|
+
var TASK_CREATE_INPUT_SCHEMA = import_zod2.z.object({
|
|
737
|
+
title: import_zod2.z.string().min(1).optional().describe("Task title (single-task mode)"),
|
|
738
|
+
details: import_zod2.z.string().optional().describe("Task details (single-task mode)"),
|
|
739
|
+
status: import_zod2.z.enum(TASK_STATUSES).optional().describe("Initial status (single-task mode)"),
|
|
740
|
+
dependencies: import_zod2.z.array(import_zod2.z.string()).optional().describe("Dependencies (single-task mode)"),
|
|
741
|
+
blockedReason: import_zod2.z.string().optional().describe("Blocked reason (single-task mode)"),
|
|
742
|
+
metadata: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.any()).optional().describe("Metadata (single-task mode)"),
|
|
743
|
+
tasks: import_zod2.z.array(CREATE_TASK_ITEM_SCHEMA).min(1).optional().describe("Batch create mode")
|
|
744
|
+
}).refine((value) => !!value.tasks?.length || !!value.title, {
|
|
745
|
+
message: "Either provide `tasks` or `title` for single-task mode."
|
|
746
|
+
});
|
|
747
|
+
var TASK_GET_INPUT_SCHEMA = import_zod2.z.object({
|
|
748
|
+
id: import_zod2.z.string().min(1).describe("Task ID to retrieve")
|
|
749
|
+
});
|
|
750
|
+
var TASK_LIST_INPUT_SCHEMA = import_zod2.z.object({
|
|
751
|
+
statuses: import_zod2.z.array(import_zod2.z.enum(TASK_STATUSES)).optional().describe("Filter by statuses"),
|
|
752
|
+
includeCompleted: import_zod2.z.boolean().optional().describe("Set false to hide completed tasks"),
|
|
753
|
+
limit: import_zod2.z.number().int().positive().max(500).optional().describe("Maximum tasks to return")
|
|
754
|
+
});
|
|
755
|
+
var TASK_TRACKING_SKILL = {
|
|
756
|
+
name: "task-tracking-workflow",
|
|
757
|
+
description: "Track complex execution with task tools and proceed directly without confirmation unless the user explicitly asks for confirmation.",
|
|
758
|
+
location: "pulse-coder-engine/built-in/task-tracking-plugin",
|
|
759
|
+
content: `# Task Tracking Workflow
|
|
760
|
+
|
|
761
|
+
## When to use
|
|
762
|
+
- The request has multiple phases or deliverables.
|
|
763
|
+
- Work may span multiple tool calls or sessions.
|
|
764
|
+
- You need explicit progress visibility and blocker management.
|
|
765
|
+
|
|
766
|
+
## Execution autonomy
|
|
767
|
+
- Default behavior: execute directly and call tools without asking for confirmation.
|
|
768
|
+
- Only ask for confirmation when the user explicitly requires confirmation.
|
|
769
|
+
- If critical information is missing, ask only the minimum clarifying question needed to continue.
|
|
770
|
+
|
|
771
|
+
## Required flow
|
|
772
|
+
1. Start by reviewing existing tasks with \`task_list\`.
|
|
773
|
+
2. If no suitable tasks exist, create focused tasks with \`task_create\` (prefer batch mode).
|
|
774
|
+
3. Keep exactly one primary task in \`in_progress\` where possible.
|
|
775
|
+
4. Update status with \`task_update\` after meaningful progress.
|
|
776
|
+
5. Mark blockers with \`status=blocked\` and a concrete \`blockedReason\`.
|
|
777
|
+
6. Mark done tasks as \`completed\` and move to the next actionable item.
|
|
778
|
+
|
|
779
|
+
## Quality rules
|
|
780
|
+
- Keep tasks atomic and verifiable.
|
|
781
|
+
- Avoid single oversized umbrella tasks.
|
|
782
|
+
- Reuse existing in-progress tasks instead of duplicating.
|
|
783
|
+
- Keep dependency links explicit when order matters.`
|
|
784
|
+
};
|
|
785
|
+
var TASK_UPDATE_INPUT_SCHEMA = import_zod2.z.object({
|
|
786
|
+
id: import_zod2.z.string().min(1).describe("Task ID to update"),
|
|
787
|
+
title: import_zod2.z.string().min(1).optional().describe("New title"),
|
|
788
|
+
details: import_zod2.z.string().optional().describe("New details"),
|
|
789
|
+
status: import_zod2.z.enum(TASK_STATUSES).optional().describe("New status"),
|
|
790
|
+
dependencies: import_zod2.z.array(import_zod2.z.string()).optional().describe("Replace dependencies with this list"),
|
|
791
|
+
blockedReason: import_zod2.z.string().optional().describe("Blocked reason, used with status=blocked"),
|
|
792
|
+
metadata: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.any()).optional().describe("Replace metadata object"),
|
|
793
|
+
delete: import_zod2.z.boolean().optional().describe("Delete this task")
|
|
794
|
+
});
|
|
795
|
+
function normalizeTaskListId(raw) {
|
|
796
|
+
const trimmed = raw.trim();
|
|
797
|
+
if (!trimmed) {
|
|
798
|
+
return "default";
|
|
799
|
+
}
|
|
800
|
+
return trimmed.replace(/[^a-zA-Z0-9._-]/g, "-").slice(0, 120) || "default";
|
|
801
|
+
}
|
|
802
|
+
function now() {
|
|
803
|
+
return Date.now();
|
|
804
|
+
}
|
|
805
|
+
function dedupeStrings(values) {
|
|
806
|
+
if (!values?.length) {
|
|
807
|
+
return [];
|
|
808
|
+
}
|
|
809
|
+
return Array.from(new Set(values.map((value) => String(value).trim()).filter(Boolean)));
|
|
810
|
+
}
|
|
811
|
+
var TaskListService = class _TaskListService {
|
|
812
|
+
taskListId;
|
|
813
|
+
storagePath;
|
|
814
|
+
storageDir;
|
|
815
|
+
initialized = false;
|
|
816
|
+
createdAt = now();
|
|
817
|
+
updatedAt = now();
|
|
818
|
+
tasks = /* @__PURE__ */ new Map();
|
|
819
|
+
constructor(taskListId = _TaskListService.resolveTaskListId(), storageDir = _TaskListService.resolveStorageDir()) {
|
|
820
|
+
const normalized = normalizeTaskListId(taskListId);
|
|
821
|
+
this.storageDir = storageDir;
|
|
822
|
+
this.taskListId = normalized;
|
|
823
|
+
this.storagePath = import_path.default.join(this.storageDir, `${normalized}.json`);
|
|
824
|
+
}
|
|
825
|
+
static resolveTaskListId() {
|
|
826
|
+
return process.env.PULSE_CODER_TASK_LIST_ID || process.env.CLAUDE_CODE_TASK_LIST_ID || "default";
|
|
827
|
+
}
|
|
828
|
+
static resolveStorageDir() {
|
|
829
|
+
return process.env.PULSE_CODER_TASKS_DIR || import_path.default.join((0, import_os2.homedir)(), ".pulse-coder", "tasks");
|
|
830
|
+
}
|
|
831
|
+
async initialize() {
|
|
832
|
+
if (this.initialized) {
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
await this.loadTaskList(this.taskListId);
|
|
836
|
+
}
|
|
837
|
+
async setTaskListId(taskListId) {
|
|
838
|
+
await this.initialize();
|
|
839
|
+
const normalized = normalizeTaskListId(taskListId);
|
|
840
|
+
if (normalized === this.taskListId) {
|
|
841
|
+
return {
|
|
842
|
+
switched: false,
|
|
843
|
+
taskListId: this.taskListId,
|
|
844
|
+
storagePath: this.storagePath
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
await this.loadTaskList(normalized);
|
|
848
|
+
return {
|
|
849
|
+
switched: true,
|
|
850
|
+
taskListId: this.taskListId,
|
|
851
|
+
storagePath: this.storagePath
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
async createTask(input) {
|
|
855
|
+
await this.initialize();
|
|
856
|
+
const timestamp = now();
|
|
857
|
+
const status = input.status ?? "pending";
|
|
858
|
+
const task = {
|
|
859
|
+
id: (0, import_crypto.randomUUID)(),
|
|
860
|
+
title: input.title.trim(),
|
|
861
|
+
details: input.details,
|
|
862
|
+
status,
|
|
863
|
+
dependencies: dedupeStrings(input.dependencies),
|
|
864
|
+
blockedReason: status === "blocked" ? input.blockedReason ?? "Blocked without reason" : void 0,
|
|
865
|
+
metadata: input.metadata,
|
|
866
|
+
createdAt: timestamp,
|
|
867
|
+
updatedAt: timestamp,
|
|
868
|
+
completedAt: status === "completed" ? timestamp : void 0
|
|
869
|
+
};
|
|
870
|
+
this.tasks.set(task.id, task);
|
|
871
|
+
this.updatedAt = timestamp;
|
|
872
|
+
await this.persist();
|
|
873
|
+
return task;
|
|
874
|
+
}
|
|
875
|
+
async createTasks(inputs) {
|
|
876
|
+
const created = [];
|
|
877
|
+
for (const input of inputs) {
|
|
878
|
+
created.push(await this.createTask(input));
|
|
879
|
+
}
|
|
880
|
+
return created;
|
|
881
|
+
}
|
|
882
|
+
async listTasks(options) {
|
|
883
|
+
await this.initialize();
|
|
884
|
+
const statuses = options?.statuses?.length ? new Set(options.statuses) : null;
|
|
885
|
+
const includeCompleted = options?.includeCompleted ?? true;
|
|
886
|
+
let tasks = Array.from(this.tasks.values()).filter((task) => {
|
|
887
|
+
if (!includeCompleted && task.status === "completed") {
|
|
888
|
+
return false;
|
|
889
|
+
}
|
|
890
|
+
if (statuses && !statuses.has(task.status)) {
|
|
891
|
+
return false;
|
|
892
|
+
}
|
|
893
|
+
return true;
|
|
894
|
+
});
|
|
895
|
+
tasks = tasks.sort((a, b) => a.createdAt - b.createdAt);
|
|
896
|
+
if (options?.limit && options.limit > 0) {
|
|
897
|
+
tasks = tasks.slice(0, options.limit);
|
|
898
|
+
}
|
|
899
|
+
return tasks;
|
|
900
|
+
}
|
|
901
|
+
async getTask(id) {
|
|
902
|
+
await this.initialize();
|
|
903
|
+
return this.tasks.get(id) ?? null;
|
|
904
|
+
}
|
|
905
|
+
async updateTask(input) {
|
|
906
|
+
await this.initialize();
|
|
907
|
+
if (input.delete) {
|
|
908
|
+
const deleted = this.tasks.delete(input.id);
|
|
909
|
+
if (!deleted) {
|
|
910
|
+
return null;
|
|
911
|
+
}
|
|
912
|
+
this.updatedAt = now();
|
|
913
|
+
await this.persist();
|
|
914
|
+
return null;
|
|
915
|
+
}
|
|
916
|
+
const existing = this.tasks.get(input.id);
|
|
917
|
+
if (!existing) {
|
|
918
|
+
return null;
|
|
919
|
+
}
|
|
920
|
+
const timestamp = now();
|
|
921
|
+
const nextStatus = input.status ?? existing.status;
|
|
922
|
+
const next = {
|
|
923
|
+
...existing,
|
|
924
|
+
title: input.title !== void 0 ? input.title : existing.title,
|
|
925
|
+
details: input.details !== void 0 ? input.details : existing.details,
|
|
926
|
+
status: nextStatus,
|
|
927
|
+
dependencies: input.dependencies !== void 0 ? dedupeStrings(input.dependencies) : existing.dependencies,
|
|
928
|
+
metadata: input.metadata !== void 0 ? input.metadata : existing.metadata,
|
|
929
|
+
blockedReason: this.resolveBlockedReason(nextStatus, input.blockedReason, existing.blockedReason),
|
|
930
|
+
updatedAt: timestamp,
|
|
931
|
+
completedAt: nextStatus === "completed" ? existing.completedAt ?? timestamp : void 0
|
|
932
|
+
};
|
|
933
|
+
this.tasks.set(input.id, next);
|
|
934
|
+
this.updatedAt = timestamp;
|
|
935
|
+
await this.persist();
|
|
936
|
+
return next;
|
|
937
|
+
}
|
|
938
|
+
async snapshot(options) {
|
|
939
|
+
const tasks = await this.listTasks(options);
|
|
940
|
+
return {
|
|
941
|
+
taskListId: this.taskListId,
|
|
942
|
+
storagePath: this.storagePath,
|
|
943
|
+
createdAt: this.createdAt,
|
|
944
|
+
updatedAt: this.updatedAt,
|
|
945
|
+
total: tasks.length,
|
|
946
|
+
tasks
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
resolveBlockedReason(status, blockedReasonInput, previous) {
|
|
950
|
+
if (status !== "blocked") {
|
|
951
|
+
return void 0;
|
|
952
|
+
}
|
|
953
|
+
if (blockedReasonInput !== void 0) {
|
|
954
|
+
return blockedReasonInput || "Blocked without reason";
|
|
955
|
+
}
|
|
956
|
+
return previous ?? "Blocked without reason";
|
|
957
|
+
}
|
|
958
|
+
async loadTaskList(taskListId) {
|
|
959
|
+
const normalized = normalizeTaskListId(taskListId);
|
|
960
|
+
this.taskListId = normalized;
|
|
961
|
+
this.storagePath = import_path.default.join(this.storageDir, `${normalized}.json`);
|
|
962
|
+
await import_fs3.promises.mkdir(this.storageDir, { recursive: true });
|
|
963
|
+
try {
|
|
964
|
+
const raw = await import_fs3.promises.readFile(this.storagePath, "utf-8");
|
|
965
|
+
const parsed = JSON.parse(raw);
|
|
966
|
+
const parsedTasks = Array.isArray(parsed.tasks) ? parsed.tasks : [];
|
|
967
|
+
this.tasks = new Map(parsedTasks.filter((task) => !!task?.id).map((task) => [task.id, task]));
|
|
968
|
+
this.createdAt = typeof parsed.createdAt === "number" ? parsed.createdAt : now();
|
|
969
|
+
this.updatedAt = typeof parsed.updatedAt === "number" ? parsed.updatedAt : now();
|
|
970
|
+
} catch (error) {
|
|
971
|
+
if (error?.code !== "ENOENT") {
|
|
972
|
+
throw error;
|
|
973
|
+
}
|
|
974
|
+
const timestamp = now();
|
|
975
|
+
this.tasks = /* @__PURE__ */ new Map();
|
|
976
|
+
this.createdAt = timestamp;
|
|
977
|
+
this.updatedAt = timestamp;
|
|
978
|
+
await this.persist();
|
|
979
|
+
}
|
|
980
|
+
this.initialized = true;
|
|
981
|
+
}
|
|
982
|
+
async persist() {
|
|
983
|
+
const payload = {
|
|
984
|
+
taskListId: this.taskListId,
|
|
985
|
+
createdAt: this.createdAt,
|
|
986
|
+
updatedAt: this.updatedAt,
|
|
987
|
+
tasks: Array.from(this.tasks.values()).sort((a, b) => a.createdAt - b.createdAt)
|
|
988
|
+
};
|
|
989
|
+
await import_fs3.promises.writeFile(this.storagePath, JSON.stringify(payload, null, 2), "utf-8");
|
|
990
|
+
}
|
|
991
|
+
};
|
|
992
|
+
function buildTaskCreateTool(service) {
|
|
993
|
+
return {
|
|
994
|
+
name: "task_create",
|
|
995
|
+
description: "Create one or more tracked tasks for complex work. Use this when work has multiple steps, dependencies, or blockers.",
|
|
996
|
+
inputSchema: TASK_CREATE_INPUT_SCHEMA,
|
|
997
|
+
execute: async ({ tasks, title, details, status, dependencies, blockedReason, metadata }) => {
|
|
998
|
+
const items = tasks?.length ? tasks : [{ title, details, status, dependencies, blockedReason, metadata }];
|
|
999
|
+
const created = await service.createTasks(items);
|
|
1000
|
+
return {
|
|
1001
|
+
taskListId: service.taskListId,
|
|
1002
|
+
storagePath: service.storagePath,
|
|
1003
|
+
createdCount: created.length,
|
|
1004
|
+
tasks: created
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
function buildTaskGetTool(service) {
|
|
1010
|
+
return {
|
|
1011
|
+
name: "task_get",
|
|
1012
|
+
description: "Get full details for a single task by task ID.",
|
|
1013
|
+
inputSchema: TASK_GET_INPUT_SCHEMA,
|
|
1014
|
+
execute: async ({ id }) => {
|
|
1015
|
+
const task = await service.getTask(id);
|
|
1016
|
+
if (!task) {
|
|
1017
|
+
throw new Error(`Task not found: ${id}`);
|
|
1018
|
+
}
|
|
1019
|
+
return {
|
|
1020
|
+
taskListId: service.taskListId,
|
|
1021
|
+
storagePath: service.storagePath,
|
|
1022
|
+
task
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
function buildTaskListTool(service) {
|
|
1028
|
+
return {
|
|
1029
|
+
name: "task_list",
|
|
1030
|
+
description: "List tasks and their current status. Use this to check progress before and after major changes.",
|
|
1031
|
+
inputSchema: TASK_LIST_INPUT_SCHEMA,
|
|
1032
|
+
execute: async ({ statuses, includeCompleted, limit }) => {
|
|
1033
|
+
const snapshot = await service.snapshot({ statuses, includeCompleted, limit });
|
|
1034
|
+
const completed = snapshot.tasks.filter((task) => task.status === "completed").length;
|
|
1035
|
+
const inProgress = snapshot.tasks.filter((task) => task.status === "in_progress").length;
|
|
1036
|
+
const pending = snapshot.tasks.filter((task) => task.status === "pending").length;
|
|
1037
|
+
const blocked = snapshot.tasks.filter((task) => task.status === "blocked").length;
|
|
1038
|
+
return {
|
|
1039
|
+
...snapshot,
|
|
1040
|
+
summary: {
|
|
1041
|
+
total: snapshot.total,
|
|
1042
|
+
completed,
|
|
1043
|
+
inProgress,
|
|
1044
|
+
pending,
|
|
1045
|
+
blocked
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
function buildTaskUpdateTool(service) {
|
|
1052
|
+
return {
|
|
1053
|
+
name: "task_update",
|
|
1054
|
+
description: "Update task fields, move status (pending/in_progress/completed/blocked), or delete tasks.",
|
|
1055
|
+
inputSchema: TASK_UPDATE_INPUT_SCHEMA,
|
|
1056
|
+
execute: async (input) => {
|
|
1057
|
+
const task = await service.updateTask(input);
|
|
1058
|
+
if (input.delete) {
|
|
1059
|
+
return {
|
|
1060
|
+
taskListId: service.taskListId,
|
|
1061
|
+
storagePath: service.storagePath,
|
|
1062
|
+
deleted: true,
|
|
1063
|
+
id: input.id
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
if (!task) {
|
|
1067
|
+
throw new Error(`Task not found: ${input.id}`);
|
|
1068
|
+
}
|
|
1069
|
+
return {
|
|
1070
|
+
taskListId: service.taskListId,
|
|
1071
|
+
storagePath: service.storagePath,
|
|
1072
|
+
deleted: false,
|
|
1073
|
+
task
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
var builtInTaskTrackingPlugin = {
|
|
1079
|
+
name: "pulse-coder-engine/built-in-task-tracking",
|
|
1080
|
+
version: "1.0.0",
|
|
1081
|
+
dependencies: ["pulse-coder-engine/built-in-skills"],
|
|
1082
|
+
async initialize(context) {
|
|
1083
|
+
const service = new TaskListService();
|
|
1084
|
+
await service.initialize();
|
|
1085
|
+
context.registerService("taskListService", service);
|
|
1086
|
+
context.registerService("taskTracking", service);
|
|
1087
|
+
const skillRegistry = context.getService("skillRegistry");
|
|
1088
|
+
if (skillRegistry) {
|
|
1089
|
+
const registration = skillRegistry.registerSkill(TASK_TRACKING_SKILL);
|
|
1090
|
+
context.logger.info("[TaskTracking] Registered built-in task tracking skill", registration);
|
|
1091
|
+
} else {
|
|
1092
|
+
context.logger.warn("[TaskTracking] skillRegistry service unavailable; skipped task tracking skill registration");
|
|
1093
|
+
}
|
|
1094
|
+
context.registerTools({
|
|
1095
|
+
task_create: buildTaskCreateTool(service),
|
|
1096
|
+
task_get: buildTaskGetTool(service),
|
|
1097
|
+
task_list: buildTaskListTool(service),
|
|
1098
|
+
task_update: buildTaskUpdateTool(service)
|
|
1099
|
+
});
|
|
1100
|
+
context.logger.info("[TaskTracking] Registered task tools", {
|
|
1101
|
+
taskListId: service.taskListId,
|
|
1102
|
+
storagePath: service.storagePath,
|
|
1103
|
+
skillRegistryAvailable: !!skillRegistry
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
};
|
|
1107
|
+
|
|
664
1108
|
// src/built-in/sub-agent-plugin/index.ts
|
|
665
|
-
var
|
|
666
|
-
var
|
|
667
|
-
var
|
|
1109
|
+
var import_zod11 = require("zod");
|
|
1110
|
+
var import_fs10 = require("fs");
|
|
1111
|
+
var import_path4 = __toESM(require("path"), 1);
|
|
668
1112
|
|
|
669
1113
|
// src/ai/index.ts
|
|
670
1114
|
var import_ai = require("ai");
|
|
@@ -696,8 +1140,8 @@ var CLARIFICATION_TIMEOUT = Number(process.env.CLARIFICATION_TIMEOUT ?? 3e5);
|
|
|
696
1140
|
var CLARIFICATION_ENABLED = process.env.CLARIFICATION_ENABLED !== "false";
|
|
697
1141
|
|
|
698
1142
|
// src/prompt/system.ts
|
|
699
|
-
var
|
|
700
|
-
var
|
|
1143
|
+
var import_fs4 = __toESM(require("fs"), 1);
|
|
1144
|
+
var import_path2 = __toESM(require("path"), 1);
|
|
701
1145
|
var DEFAULT_PROMPT = `
|
|
702
1146
|
You are Pulse Coder, the best coding agent on the planet.
|
|
703
1147
|
|
|
@@ -833,13 +1277,13 @@ var AGENTS_FILE_REGEX = /^agents\.md$/i;
|
|
|
833
1277
|
var loadAgentsPrompt = () => {
|
|
834
1278
|
try {
|
|
835
1279
|
const cwd = process.cwd();
|
|
836
|
-
const entries =
|
|
1280
|
+
const entries = import_fs4.default.readdirSync(cwd, { withFileTypes: true });
|
|
837
1281
|
const target = entries.find((entry) => entry.isFile() && AGENTS_FILE_REGEX.test(entry.name));
|
|
838
1282
|
if (!target) {
|
|
839
1283
|
return null;
|
|
840
1284
|
}
|
|
841
|
-
const filePath =
|
|
842
|
-
const content =
|
|
1285
|
+
const filePath = import_path2.default.join(cwd, target.name);
|
|
1286
|
+
const content = import_fs4.default.readFileSync(filePath, "utf8").trim();
|
|
843
1287
|
return content.length > 0 ? content : null;
|
|
844
1288
|
} catch {
|
|
845
1289
|
return null;
|
|
@@ -1135,6 +1579,9 @@ async function loop(context, options) {
|
|
|
1135
1579
|
}
|
|
1136
1580
|
}
|
|
1137
1581
|
if (finishReason === "stop") {
|
|
1582
|
+
if (!text) {
|
|
1583
|
+
continue;
|
|
1584
|
+
}
|
|
1138
1585
|
return text || "Task completed.";
|
|
1139
1586
|
}
|
|
1140
1587
|
if (finishReason === "length") {
|
|
@@ -1166,6 +1613,9 @@ async function loop(context, options) {
|
|
|
1166
1613
|
}
|
|
1167
1614
|
continue;
|
|
1168
1615
|
}
|
|
1616
|
+
if (!text) {
|
|
1617
|
+
continue;
|
|
1618
|
+
}
|
|
1169
1619
|
return text || "Task completed.";
|
|
1170
1620
|
} catch (error) {
|
|
1171
1621
|
if (options?.abortSignal?.aborted || error?.name === "AbortError") {
|
|
@@ -1193,8 +1643,8 @@ function sleep(ms) {
|
|
|
1193
1643
|
}
|
|
1194
1644
|
|
|
1195
1645
|
// src/tools/read.ts
|
|
1196
|
-
var
|
|
1197
|
-
var
|
|
1646
|
+
var import_zod3 = __toESM(require("zod"), 1);
|
|
1647
|
+
var import_fs5 = require("fs");
|
|
1198
1648
|
|
|
1199
1649
|
// src/tools/utils.ts
|
|
1200
1650
|
var truncateOutput = (output) => {
|
|
@@ -1214,20 +1664,20 @@ var truncateOutput = (output) => {
|
|
|
1214
1664
|
var ReadTool = {
|
|
1215
1665
|
name: "read",
|
|
1216
1666
|
description: "Read the contents of a file. Supports reading specific line ranges with offset and limit.",
|
|
1217
|
-
inputSchema:
|
|
1218
|
-
filePath:
|
|
1219
|
-
offset:
|
|
1220
|
-
limit:
|
|
1667
|
+
inputSchema: import_zod3.default.object({
|
|
1668
|
+
filePath: import_zod3.default.string().describe("The absolute path to the file to read"),
|
|
1669
|
+
offset: import_zod3.default.number().optional().describe("The line number to start reading from (0-based). Only provide if the file is too large to read at once."),
|
|
1670
|
+
limit: import_zod3.default.number().optional().describe("The number of lines to read. Only provide if the file is too large to read at once.")
|
|
1221
1671
|
}),
|
|
1222
1672
|
execute: async ({ filePath, offset, limit }) => {
|
|
1223
|
-
if (!(0,
|
|
1673
|
+
if (!(0, import_fs5.existsSync)(filePath)) {
|
|
1224
1674
|
throw new Error(`File does not exist: ${filePath}`);
|
|
1225
1675
|
}
|
|
1226
|
-
const stats = (0,
|
|
1676
|
+
const stats = (0, import_fs5.statSync)(filePath);
|
|
1227
1677
|
if (stats.isDirectory()) {
|
|
1228
1678
|
throw new Error(`Cannot read directory: ${filePath}. Use 'ls' tool to list directory contents.`);
|
|
1229
1679
|
}
|
|
1230
|
-
const content = (0,
|
|
1680
|
+
const content = (0, import_fs5.readFileSync)(filePath, "utf-8");
|
|
1231
1681
|
const lines = content.split("\n");
|
|
1232
1682
|
const totalLines = lines.length;
|
|
1233
1683
|
if (offset === void 0 && limit === void 0) {
|
|
@@ -1254,23 +1704,23 @@ var ReadTool = {
|
|
|
1254
1704
|
};
|
|
1255
1705
|
|
|
1256
1706
|
// src/tools/write.ts
|
|
1257
|
-
var
|
|
1258
|
-
var
|
|
1259
|
-
var
|
|
1707
|
+
var import_zod4 = __toESM(require("zod"), 1);
|
|
1708
|
+
var import_fs6 = require("fs");
|
|
1709
|
+
var import_path3 = require("path");
|
|
1260
1710
|
var WriteTool = {
|
|
1261
1711
|
name: "write",
|
|
1262
1712
|
description: "Write contents to a file. Automatically creates parent directories if they do not exist. Will overwrite existing files.",
|
|
1263
|
-
inputSchema:
|
|
1264
|
-
filePath:
|
|
1265
|
-
content:
|
|
1713
|
+
inputSchema: import_zod4.default.object({
|
|
1714
|
+
filePath: import_zod4.default.string().describe("The absolute path to the file to write (must be absolute, not relative)"),
|
|
1715
|
+
content: import_zod4.default.string().describe("The content to write to the file")
|
|
1266
1716
|
}),
|
|
1267
1717
|
execute: async ({ filePath, content }) => {
|
|
1268
|
-
const fileExists = (0,
|
|
1269
|
-
const dir = (0,
|
|
1270
|
-
if (!(0,
|
|
1271
|
-
(0,
|
|
1718
|
+
const fileExists = (0, import_fs6.existsSync)(filePath);
|
|
1719
|
+
const dir = (0, import_path3.dirname)(filePath);
|
|
1720
|
+
if (!(0, import_fs6.existsSync)(dir)) {
|
|
1721
|
+
(0, import_fs6.mkdirSync)(dir, { recursive: true });
|
|
1272
1722
|
}
|
|
1273
|
-
(0,
|
|
1723
|
+
(0, import_fs6.writeFileSync)(filePath, content, "utf-8");
|
|
1274
1724
|
const bytes = Buffer.byteLength(content, "utf-8");
|
|
1275
1725
|
return {
|
|
1276
1726
|
success: true,
|
|
@@ -1281,22 +1731,22 @@ var WriteTool = {
|
|
|
1281
1731
|
};
|
|
1282
1732
|
|
|
1283
1733
|
// src/tools/edit.ts
|
|
1284
|
-
var
|
|
1285
|
-
var
|
|
1734
|
+
var import_zod5 = __toESM(require("zod"), 1);
|
|
1735
|
+
var import_fs7 = require("fs");
|
|
1286
1736
|
var EditTool = {
|
|
1287
1737
|
name: "edit",
|
|
1288
1738
|
description: "Performs exact string replacements in files. Use this to edit existing files by replacing old_string with new_string.",
|
|
1289
|
-
inputSchema:
|
|
1290
|
-
filePath:
|
|
1291
|
-
oldString:
|
|
1292
|
-
newString:
|
|
1293
|
-
replaceAll:
|
|
1739
|
+
inputSchema: import_zod5.default.object({
|
|
1740
|
+
filePath: import_zod5.default.string().describe("The absolute path to the file to modify"),
|
|
1741
|
+
oldString: import_zod5.default.string().describe("The exact text to replace (must match exactly)"),
|
|
1742
|
+
newString: import_zod5.default.string().describe("The text to replace it with (must be different from old_string)"),
|
|
1743
|
+
replaceAll: import_zod5.default.boolean().optional().default(false).describe("Replace all occurrences of old_string (default false)")
|
|
1294
1744
|
}),
|
|
1295
1745
|
execute: async ({ filePath, oldString, newString, replaceAll = false }) => {
|
|
1296
1746
|
if (oldString === newString) {
|
|
1297
1747
|
throw new Error("old_string and new_string must be different");
|
|
1298
1748
|
}
|
|
1299
|
-
const content = (0,
|
|
1749
|
+
const content = (0, import_fs7.readFileSync)(filePath, "utf-8");
|
|
1300
1750
|
if (!content.includes(oldString)) {
|
|
1301
1751
|
throw new Error(`old_string not found in file: ${filePath}`);
|
|
1302
1752
|
}
|
|
@@ -1320,7 +1770,7 @@ var EditTool = {
|
|
|
1320
1770
|
newContent = content.slice(0, index) + newString + content.slice(index + oldString.length);
|
|
1321
1771
|
replacements = 1;
|
|
1322
1772
|
}
|
|
1323
|
-
(0,
|
|
1773
|
+
(0, import_fs7.writeFileSync)(filePath, newContent, "utf-8");
|
|
1324
1774
|
const changedIndex = newContent.indexOf(newString);
|
|
1325
1775
|
const contextLength = 200;
|
|
1326
1776
|
const start = Math.max(0, changedIndex - contextLength);
|
|
@@ -1337,27 +1787,27 @@ var EditTool = {
|
|
|
1337
1787
|
};
|
|
1338
1788
|
|
|
1339
1789
|
// src/tools/grep.ts
|
|
1340
|
-
var
|
|
1790
|
+
var import_zod6 = __toESM(require("zod"), 1);
|
|
1341
1791
|
var import_child_process = require("child_process");
|
|
1342
|
-
var
|
|
1792
|
+
var import_fs8 = require("fs");
|
|
1343
1793
|
var GrepTool = {
|
|
1344
1794
|
name: "grep",
|
|
1345
1795
|
description: "A powerful search tool built on ripgrep. Supports regex patterns, file filtering, and multiple output modes.",
|
|
1346
|
-
inputSchema:
|
|
1347
|
-
pattern:
|
|
1348
|
-
path:
|
|
1349
|
-
glob:
|
|
1350
|
-
type:
|
|
1351
|
-
outputMode:
|
|
1352
|
-
context:
|
|
1353
|
-
caseInsensitive:
|
|
1354
|
-
headLimit:
|
|
1355
|
-
offset:
|
|
1356
|
-
multiline:
|
|
1796
|
+
inputSchema: import_zod6.default.object({
|
|
1797
|
+
pattern: import_zod6.default.string().describe("The regular expression pattern to search for in file contents"),
|
|
1798
|
+
path: import_zod6.default.string().optional().describe("File or directory to search in. Defaults to current working directory."),
|
|
1799
|
+
glob: import_zod6.default.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}")'),
|
|
1800
|
+
type: import_zod6.default.string().optional().describe("File type to search (e.g., js, py, rust, go, java, ts, tsx, json, md)"),
|
|
1801
|
+
outputMode: import_zod6.default.enum(["content", "files_with_matches", "count"]).optional().default("files_with_matches").describe('Output mode: "content" shows matching lines, "files_with_matches" shows file paths, "count" shows match counts'),
|
|
1802
|
+
context: import_zod6.default.number().optional().describe('Number of lines to show before and after each match (only with output_mode: "content")'),
|
|
1803
|
+
caseInsensitive: import_zod6.default.boolean().optional().default(false).describe("Case insensitive search"),
|
|
1804
|
+
headLimit: import_zod6.default.number().optional().default(0).describe("Limit output to first N lines/entries. 0 means unlimited."),
|
|
1805
|
+
offset: import_zod6.default.number().optional().default(0).describe("Skip first N lines/entries before applying head_limit"),
|
|
1806
|
+
multiline: import_zod6.default.boolean().optional().default(false).describe("Enable multiline mode where patterns can span lines")
|
|
1357
1807
|
}),
|
|
1358
1808
|
execute: async ({
|
|
1359
1809
|
pattern,
|
|
1360
|
-
path:
|
|
1810
|
+
path: path5 = ".",
|
|
1361
1811
|
glob,
|
|
1362
1812
|
type,
|
|
1363
1813
|
outputMode = "files_with_matches",
|
|
@@ -1392,11 +1842,11 @@ var GrepTool = {
|
|
|
1392
1842
|
if (type) {
|
|
1393
1843
|
args.push("--type", type);
|
|
1394
1844
|
}
|
|
1395
|
-
if (
|
|
1396
|
-
if (!(0,
|
|
1397
|
-
throw new Error(`Path does not exist: ${
|
|
1845
|
+
if (path5 && path5 !== ".") {
|
|
1846
|
+
if (!(0, import_fs8.existsSync)(path5)) {
|
|
1847
|
+
throw new Error(`Path does not exist: ${path5}`);
|
|
1398
1848
|
}
|
|
1399
|
-
args.push(
|
|
1849
|
+
args.push(path5);
|
|
1400
1850
|
}
|
|
1401
1851
|
let command = args.map((arg) => {
|
|
1402
1852
|
if (arg.includes(" ") || arg.includes("$") || arg.includes("*")) {
|
|
@@ -1443,31 +1893,31 @@ Command: ${command}`
|
|
|
1443
1893
|
};
|
|
1444
1894
|
|
|
1445
1895
|
// src/tools/ls.ts
|
|
1446
|
-
var
|
|
1447
|
-
var
|
|
1896
|
+
var import_zod7 = __toESM(require("zod"), 1);
|
|
1897
|
+
var import_fs9 = require("fs");
|
|
1448
1898
|
var LsTool = {
|
|
1449
1899
|
name: "ls",
|
|
1450
1900
|
description: "List files and directories in a given path",
|
|
1451
|
-
inputSchema:
|
|
1452
|
-
path:
|
|
1901
|
+
inputSchema: import_zod7.default.object({
|
|
1902
|
+
path: import_zod7.default.string().optional().describe("The path to list files from (defaults to current directory)")
|
|
1453
1903
|
}),
|
|
1454
|
-
execute: async ({ path:
|
|
1455
|
-
const files = (0,
|
|
1904
|
+
execute: async ({ path: path5 = "." }) => {
|
|
1905
|
+
const files = (0, import_fs9.readdirSync)(path5);
|
|
1456
1906
|
return { files };
|
|
1457
1907
|
}
|
|
1458
1908
|
};
|
|
1459
1909
|
|
|
1460
1910
|
// src/tools/bash.ts
|
|
1461
|
-
var
|
|
1911
|
+
var import_zod8 = __toESM(require("zod"), 1);
|
|
1462
1912
|
var import_child_process2 = require("child_process");
|
|
1463
1913
|
var BashTool = {
|
|
1464
1914
|
name: "bash",
|
|
1465
1915
|
description: "Execute a bash command and return the output. Supports timeout and working directory configuration.",
|
|
1466
|
-
inputSchema:
|
|
1467
|
-
command:
|
|
1468
|
-
timeout:
|
|
1469
|
-
cwd:
|
|
1470
|
-
description:
|
|
1916
|
+
inputSchema: import_zod8.default.object({
|
|
1917
|
+
command: import_zod8.default.string().describe("The bash command to execute"),
|
|
1918
|
+
timeout: import_zod8.default.number().optional().describe("Optional timeout in milliseconds (max 600000ms / 10 minutes). Defaults to 120000ms (2 minutes)."),
|
|
1919
|
+
cwd: import_zod8.default.string().optional().describe("Optional working directory for command execution. Defaults to current directory."),
|
|
1920
|
+
description: import_zod8.default.string().optional().describe("Optional description of what this command does (for logging/debugging)")
|
|
1471
1921
|
}),
|
|
1472
1922
|
execute: async ({ command, timeout = 12e4, cwd, description }) => {
|
|
1473
1923
|
if (timeout && (timeout < 0 || timeout > 6e5)) {
|
|
@@ -1508,13 +1958,13 @@ ${stderr}`),
|
|
|
1508
1958
|
};
|
|
1509
1959
|
|
|
1510
1960
|
// src/tools/tavily.ts
|
|
1511
|
-
var
|
|
1961
|
+
var import_zod9 = __toESM(require("zod"), 1);
|
|
1512
1962
|
var TavilyTool = {
|
|
1513
1963
|
name: "tavily",
|
|
1514
1964
|
description: "Search the web using Tavily API",
|
|
1515
|
-
inputSchema:
|
|
1516
|
-
query:
|
|
1517
|
-
maxResults:
|
|
1965
|
+
inputSchema: import_zod9.default.object({
|
|
1966
|
+
query: import_zod9.default.string().describe("The search query"),
|
|
1967
|
+
maxResults: import_zod9.default.number().optional().default(5).describe("Maximum number of results to return")
|
|
1518
1968
|
}),
|
|
1519
1969
|
execute: async ({ query, maxResults = 5 }) => {
|
|
1520
1970
|
const apiKey = process.env.TAVILY_API_KEY;
|
|
@@ -1552,23 +2002,23 @@ var TavilyTool = {
|
|
|
1552
2002
|
};
|
|
1553
2003
|
|
|
1554
2004
|
// src/tools/clarify.ts
|
|
1555
|
-
var
|
|
1556
|
-
var
|
|
2005
|
+
var import_zod10 = __toESM(require("zod"), 1);
|
|
2006
|
+
var import_crypto2 = require("crypto");
|
|
1557
2007
|
var ClarifyTool = {
|
|
1558
2008
|
name: "clarify",
|
|
1559
2009
|
description: "Ask the user a clarifying question and wait for their response. Use this when you need information from the user to proceed with the task.",
|
|
1560
|
-
inputSchema:
|
|
1561
|
-
question:
|
|
1562
|
-
context:
|
|
1563
|
-
defaultAnswer:
|
|
1564
|
-
timeout:
|
|
2010
|
+
inputSchema: import_zod10.default.object({
|
|
2011
|
+
question: import_zod10.default.string().describe("The question to ask the user"),
|
|
2012
|
+
context: import_zod10.default.string().optional().describe("Additional context to help the user answer"),
|
|
2013
|
+
defaultAnswer: import_zod10.default.string().optional().describe("Default answer if user does not respond within timeout"),
|
|
2014
|
+
timeout: import_zod10.default.number().optional().describe("Timeout in milliseconds (default: 5 minutes)")
|
|
1565
2015
|
}),
|
|
1566
2016
|
execute: async (input, toolContext) => {
|
|
1567
2017
|
if (!toolContext?.onClarificationRequest) {
|
|
1568
2018
|
throw new Error("Clarification is not supported in this context. The clarify tool requires a CLI interface with user interaction.");
|
|
1569
2019
|
}
|
|
1570
2020
|
const timeout = input.timeout ?? CLARIFICATION_TIMEOUT;
|
|
1571
|
-
const requestId = (0,
|
|
2021
|
+
const requestId = (0, import_crypto2.randomUUID)();
|
|
1572
2022
|
try {
|
|
1573
2023
|
const timeoutPromise = new Promise((_, reject) => {
|
|
1574
2024
|
setTimeout(() => {
|
|
@@ -1623,8 +2073,8 @@ var ConfigLoader = class {
|
|
|
1623
2073
|
const fileInfos = [];
|
|
1624
2074
|
for (let configDir of configDirs) {
|
|
1625
2075
|
try {
|
|
1626
|
-
await
|
|
1627
|
-
const files = await
|
|
2076
|
+
await import_fs10.promises.access(configDir);
|
|
2077
|
+
const files = await import_fs10.promises.readdir(configDir);
|
|
1628
2078
|
fileInfos.push({ files, configDir });
|
|
1629
2079
|
} catch {
|
|
1630
2080
|
continue;
|
|
@@ -1641,7 +2091,7 @@ var ConfigLoader = class {
|
|
|
1641
2091
|
const files = fileInfo.files;
|
|
1642
2092
|
for (const file of files) {
|
|
1643
2093
|
if (file.endsWith(".md")) {
|
|
1644
|
-
const config = await this.parseConfig(
|
|
2094
|
+
const config = await this.parseConfig(import_path4.default.join(fileInfo.configDir, file));
|
|
1645
2095
|
if (config) configs.push(config);
|
|
1646
2096
|
}
|
|
1647
2097
|
}
|
|
@@ -1653,7 +2103,7 @@ var ConfigLoader = class {
|
|
|
1653
2103
|
}
|
|
1654
2104
|
async parseConfig(filePath) {
|
|
1655
2105
|
try {
|
|
1656
|
-
const content = await
|
|
2106
|
+
const content = await import_fs10.promises.readFile(filePath, "utf-8");
|
|
1657
2107
|
const lines = content.split("\n");
|
|
1658
2108
|
let name = "";
|
|
1659
2109
|
let description = "";
|
|
@@ -1682,7 +2132,7 @@ var ConfigLoader = class {
|
|
|
1682
2132
|
}
|
|
1683
2133
|
}
|
|
1684
2134
|
if (!name) {
|
|
1685
|
-
name =
|
|
2135
|
+
name = import_path4.default.basename(filePath, ".md");
|
|
1686
2136
|
}
|
|
1687
2137
|
return {
|
|
1688
2138
|
name: name.trim(),
|
|
@@ -1733,9 +2183,9 @@ var SubAgentPlugin = class {
|
|
|
1733
2183
|
const toolName = `${config.name}_agent`;
|
|
1734
2184
|
const tool2 = {
|
|
1735
2185
|
description: config.description,
|
|
1736
|
-
inputSchema:
|
|
1737
|
-
task:
|
|
1738
|
-
context:
|
|
2186
|
+
inputSchema: import_zod11.z.object({
|
|
2187
|
+
task: import_zod11.z.string().describe("\u8981\u6267\u884C\u7684\u4EFB\u52A1\u63CF\u8FF0"),
|
|
2188
|
+
context: import_zod11.z.any().optional().describe("\u4EFB\u52A1\u4E0A\u4E0B\u6587\u4FE1\u606F")
|
|
1739
2189
|
}),
|
|
1740
2190
|
execute: async ({ task, context: taskContext }) => {
|
|
1741
2191
|
const tools = { ...BuiltinToolsMap, ...context.getTools() };
|
|
@@ -1762,6 +2212,7 @@ var builtInPlugins = [
|
|
|
1762
2212
|
builtInMCPPlugin,
|
|
1763
2213
|
builtInSkillsPlugin,
|
|
1764
2214
|
builtInPlanModePlugin,
|
|
2215
|
+
builtInTaskTrackingPlugin,
|
|
1765
2216
|
new SubAgentPlugin()
|
|
1766
2217
|
];
|
|
1767
2218
|
var built_in_default = builtInPlugins;
|
|
@@ -1770,9 +2221,11 @@ var built_in_default = builtInPlugins;
|
|
|
1770
2221
|
BuiltInPlanModeService,
|
|
1771
2222
|
BuiltInSkillRegistry,
|
|
1772
2223
|
SubAgentPlugin,
|
|
2224
|
+
TaskListService,
|
|
1773
2225
|
builtInMCPPlugin,
|
|
1774
2226
|
builtInPlanModePlugin,
|
|
1775
2227
|
builtInPlugins,
|
|
1776
|
-
builtInSkillsPlugin
|
|
2228
|
+
builtInSkillsPlugin,
|
|
2229
|
+
builtInTaskTrackingPlugin
|
|
1777
2230
|
});
|
|
1778
2231
|
//# sourceMappingURL=index.cjs.map
|