pulse-coder-engine 0.0.1-alpha.4 → 0.0.1-alpha.7
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/LICENSE +21 -0
- package/dist/built-in/index.cjs +477 -50
- 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 +459 -34
- package/dist/built-in/index.js.map +1 -1
- package/dist/index-Dh5B8P2t.d.cts +277 -0
- package/dist/index-Dh5B8P2t.d.ts +277 -0
- package/dist/index.cjs +559 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -96
- package/dist/index.d.ts +16 -96
- package/dist/index.js +535 -51
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/dist/index-DDqISE31.d.cts +0 -120
- package/dist/index-DDqISE31.d.ts +0 -120
package/dist/built-in/index.js
CHANGED
|
@@ -233,10 +233,417 @@ var builtInSkillsPlugin = {
|
|
|
233
233
|
}
|
|
234
234
|
};
|
|
235
235
|
|
|
236
|
+
// src/built-in/plan-mode-plugin/index.ts
|
|
237
|
+
var PLANNING_POLICY = {
|
|
238
|
+
mode: "planning",
|
|
239
|
+
allowedCategories: ["read", "search", "other"],
|
|
240
|
+
disallowedCategories: ["write", "execute"],
|
|
241
|
+
notes: "Planning mode is prompt-constrained only. Disallowed tool attempts are observed and logged, not hard-blocked."
|
|
242
|
+
};
|
|
243
|
+
var EXECUTING_POLICY = {
|
|
244
|
+
mode: "executing",
|
|
245
|
+
allowedCategories: ["read", "search", "write", "execute", "other"],
|
|
246
|
+
disallowedCategories: []
|
|
247
|
+
};
|
|
248
|
+
var EXECUTE_PATTERNS = [
|
|
249
|
+
/开始执行/i,
|
|
250
|
+
/按这个计划做/i,
|
|
251
|
+
/可以改代码了/i,
|
|
252
|
+
/直接实现/i,
|
|
253
|
+
/go\s+ahead/i,
|
|
254
|
+
/proceed/i,
|
|
255
|
+
/implement\s+it/i,
|
|
256
|
+
/start\s+implement/i,
|
|
257
|
+
/start\s+coding/i
|
|
258
|
+
];
|
|
259
|
+
var NEGATIVE_PATTERNS = [
|
|
260
|
+
/先不(要)?执行/i,
|
|
261
|
+
/先别执行/i,
|
|
262
|
+
/不要执行/i,
|
|
263
|
+
/暂时不要执行/i,
|
|
264
|
+
/先别改代码/i,
|
|
265
|
+
/先不要改代码/i,
|
|
266
|
+
/先不要实现/i,
|
|
267
|
+
/not\s+now/i,
|
|
268
|
+
/hold\s+off/i,
|
|
269
|
+
/do\s+not\s+(start|execute|implement|proceed)/i,
|
|
270
|
+
/don't\s+(start|execute|implement|proceed)/i
|
|
271
|
+
];
|
|
272
|
+
var PLAN_PATTERNS = [/先计划/i, /先分析/i, /先出方案/i, /plan\s+first/i, /analysis\s+first/i];
|
|
273
|
+
function appendSystemPrompt(base, append) {
|
|
274
|
+
if (!append.trim()) {
|
|
275
|
+
return base ?? { append: "" };
|
|
276
|
+
}
|
|
277
|
+
if (!base) {
|
|
278
|
+
return { append };
|
|
279
|
+
}
|
|
280
|
+
if (typeof base === "string") {
|
|
281
|
+
return `${base}
|
|
282
|
+
|
|
283
|
+
${append}`;
|
|
284
|
+
}
|
|
285
|
+
if (typeof base === "function") {
|
|
286
|
+
return () => `${base()}
|
|
287
|
+
|
|
288
|
+
${append}`;
|
|
289
|
+
}
|
|
290
|
+
const currentAppend = base.append.trim();
|
|
291
|
+
return {
|
|
292
|
+
append: currentAppend ? `${currentAppend}
|
|
293
|
+
|
|
294
|
+
${append}` : append
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
var KNOWN_TOOL_META = {
|
|
298
|
+
read: {
|
|
299
|
+
category: "read",
|
|
300
|
+
risk: "low",
|
|
301
|
+
description: "Read file contents from the workspace."
|
|
302
|
+
},
|
|
303
|
+
ls: {
|
|
304
|
+
category: "read",
|
|
305
|
+
risk: "low",
|
|
306
|
+
description: "List files and directories."
|
|
307
|
+
},
|
|
308
|
+
grep: {
|
|
309
|
+
category: "search",
|
|
310
|
+
risk: "low",
|
|
311
|
+
description: "Search text content across files."
|
|
312
|
+
},
|
|
313
|
+
tavily: {
|
|
314
|
+
category: "search",
|
|
315
|
+
risk: "low",
|
|
316
|
+
description: "Search web results from external sources."
|
|
317
|
+
},
|
|
318
|
+
skill: {
|
|
319
|
+
category: "search",
|
|
320
|
+
risk: "low",
|
|
321
|
+
description: "Load procedural guidance from installed skills."
|
|
322
|
+
},
|
|
323
|
+
write: {
|
|
324
|
+
category: "write",
|
|
325
|
+
risk: "high",
|
|
326
|
+
description: "Create or overwrite file content."
|
|
327
|
+
},
|
|
328
|
+
edit: {
|
|
329
|
+
category: "write",
|
|
330
|
+
risk: "high",
|
|
331
|
+
description: "Modify existing files using exact replacements."
|
|
332
|
+
},
|
|
333
|
+
bash: {
|
|
334
|
+
category: "execute",
|
|
335
|
+
risk: "high",
|
|
336
|
+
description: "Execute shell commands."
|
|
337
|
+
},
|
|
338
|
+
clarify: {
|
|
339
|
+
category: "other",
|
|
340
|
+
risk: "low",
|
|
341
|
+
description: "Ask the user a targeted clarification question."
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
var BuiltInPlanModeService = class {
|
|
345
|
+
constructor(logger, eventEmitter, initialMode = "executing") {
|
|
346
|
+
this.logger = logger;
|
|
347
|
+
this.eventEmitter = eventEmitter;
|
|
348
|
+
this.mode = initialMode;
|
|
349
|
+
this.emitEvent("mode_entered", { reason: "initialize" });
|
|
350
|
+
}
|
|
351
|
+
mode;
|
|
352
|
+
events = [];
|
|
353
|
+
getMode() {
|
|
354
|
+
return this.mode;
|
|
355
|
+
}
|
|
356
|
+
setMode(mode, reason = "manual") {
|
|
357
|
+
if (this.mode === mode) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
this.mode = mode;
|
|
361
|
+
this.emitEvent("mode_entered", { reason });
|
|
362
|
+
}
|
|
363
|
+
detectIntent(input) {
|
|
364
|
+
const text = input.trim();
|
|
365
|
+
if (!text) {
|
|
366
|
+
return "UNCLEAR";
|
|
367
|
+
}
|
|
368
|
+
if (NEGATIVE_PATTERNS.some((pattern) => pattern.test(text))) {
|
|
369
|
+
return "PLAN_ONLY";
|
|
370
|
+
}
|
|
371
|
+
if (EXECUTE_PATTERNS.some((pattern) => pattern.test(text))) {
|
|
372
|
+
return "EXECUTE_NOW";
|
|
373
|
+
}
|
|
374
|
+
if (PLAN_PATTERNS.some((pattern) => pattern.test(text))) {
|
|
375
|
+
return "PLAN_ONLY";
|
|
376
|
+
}
|
|
377
|
+
return "UNCLEAR";
|
|
378
|
+
}
|
|
379
|
+
processContextMessages(messages) {
|
|
380
|
+
const userInput = this.getLatestUserText(messages);
|
|
381
|
+
const modeBefore = this.mode;
|
|
382
|
+
if (!userInput) {
|
|
383
|
+
return {
|
|
384
|
+
modeBefore,
|
|
385
|
+
modeAfter: this.mode,
|
|
386
|
+
switched: false,
|
|
387
|
+
intent: "UNCLEAR",
|
|
388
|
+
userInput: ""
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const intent = this.detectIntent(userInput);
|
|
392
|
+
if (intent === "EXECUTE_NOW") {
|
|
393
|
+
this.emitEvent("execution_intent_detected", { intent, userInput });
|
|
394
|
+
if (this.mode === "planning") {
|
|
395
|
+
this.mode = "executing";
|
|
396
|
+
this.emitEvent("mode_switched_by_intent", {
|
|
397
|
+
from: "planning",
|
|
398
|
+
to: "executing",
|
|
399
|
+
userInput
|
|
400
|
+
});
|
|
401
|
+
this.emitEvent("mode_entered", {
|
|
402
|
+
reason: "intent",
|
|
403
|
+
from: "planning"
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
modeBefore,
|
|
409
|
+
modeAfter: this.mode,
|
|
410
|
+
switched: modeBefore !== this.mode,
|
|
411
|
+
intent,
|
|
412
|
+
userInput
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
getModePolicy(mode = this.mode) {
|
|
416
|
+
return mode === "planning" ? PLANNING_POLICY : EXECUTING_POLICY;
|
|
417
|
+
}
|
|
418
|
+
getToolMetadata(toolNames) {
|
|
419
|
+
return Array.from(new Set(toolNames)).sort().map((name) => this.inferToolMeta(name));
|
|
420
|
+
}
|
|
421
|
+
buildPromptAppend(toolNames, transition) {
|
|
422
|
+
const mode = this.mode;
|
|
423
|
+
const policy = this.getModePolicy(mode);
|
|
424
|
+
const toolMeta = this.getToolMetadata(toolNames);
|
|
425
|
+
const shownTools = toolMeta.slice(0, 40);
|
|
426
|
+
const omittedCount = toolMeta.length - shownTools.length;
|
|
427
|
+
const lines = [
|
|
428
|
+
"## Plan Mode Policy (Built-in Plugin)",
|
|
429
|
+
`Current mode: ${mode.toUpperCase()}`,
|
|
430
|
+
`Allowed tool categories: ${policy.allowedCategories.join(", ")}`,
|
|
431
|
+
`Disallowed tool categories: ${policy.disallowedCategories.join(", ") || "none"}`,
|
|
432
|
+
policy.notes ? `Policy notes: ${policy.notes}` : ""
|
|
433
|
+
].filter(Boolean);
|
|
434
|
+
if (mode === "planning") {
|
|
435
|
+
lines.push(
|
|
436
|
+
"Planning objective: prioritize reading, analysis, and plan generation.",
|
|
437
|
+
"In planning mode, do not intentionally perform write/edit/execute actions.",
|
|
438
|
+
"If implementation is requested but intent is not explicit, ask for execution authorization.",
|
|
439
|
+
"Before each tool call in planning mode, self-check category compliance.",
|
|
440
|
+
"Plan format must include: goals, assumptions, steps, risks, validation approach."
|
|
441
|
+
);
|
|
442
|
+
} else {
|
|
443
|
+
lines.push(
|
|
444
|
+
"Executing objective: follow the agreed plan before broad exploration.",
|
|
445
|
+
"Make targeted edits and keep changes scoped.",
|
|
446
|
+
"Report what changed and how it was validated."
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
if (transition?.switched && transition.modeAfter === "executing") {
|
|
450
|
+
lines.push(
|
|
451
|
+
"Mode transition: the latest user message explicitly authorized execution.",
|
|
452
|
+
"In your next reply, acknowledge switching to EXECUTING mode before implementation details."
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
lines.push("Tool metadata (prompt-level policy reference):");
|
|
456
|
+
for (const meta of shownTools) {
|
|
457
|
+
lines.push(`- ${meta.name}: category=${meta.category}, risk=${meta.risk}, ${meta.description}`);
|
|
458
|
+
}
|
|
459
|
+
if (omittedCount > 0) {
|
|
460
|
+
lines.push(`- ... ${omittedCount} additional tool(s) omitted for brevity.`);
|
|
461
|
+
}
|
|
462
|
+
return lines.join("\n");
|
|
463
|
+
}
|
|
464
|
+
applyHooks(baseHooks) {
|
|
465
|
+
return {
|
|
466
|
+
onBeforeToolCall: async (name, input) => {
|
|
467
|
+
this.observePotentialPolicyViolation(name, input);
|
|
468
|
+
if (baseHooks?.onBeforeToolCall) {
|
|
469
|
+
const nextInput = await baseHooks.onBeforeToolCall(name, input);
|
|
470
|
+
return nextInput ?? input;
|
|
471
|
+
}
|
|
472
|
+
return input;
|
|
473
|
+
},
|
|
474
|
+
onAfterToolCall: async (name, input, output) => {
|
|
475
|
+
if (baseHooks?.onAfterToolCall) {
|
|
476
|
+
const nextOutput = await baseHooks.onAfterToolCall(name, input, output);
|
|
477
|
+
return nextOutput ?? output;
|
|
478
|
+
}
|
|
479
|
+
return output;
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
getEvents(limit = 50) {
|
|
484
|
+
return this.events.slice(-Math.max(0, limit));
|
|
485
|
+
}
|
|
486
|
+
observePotentialPolicyViolation(toolName, input) {
|
|
487
|
+
if (this.mode !== "planning") {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
const meta = this.inferToolMeta(toolName);
|
|
491
|
+
const policy = this.getModePolicy("planning");
|
|
492
|
+
if (!policy.disallowedCategories.includes(meta.category)) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
this.emitEvent("disallowed_tool_attempt_in_planning", {
|
|
496
|
+
toolName,
|
|
497
|
+
category: meta.category,
|
|
498
|
+
risk: meta.risk,
|
|
499
|
+
input
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
inferToolMeta(name) {
|
|
503
|
+
const knownMeta = KNOWN_TOOL_META[name];
|
|
504
|
+
if (knownMeta) {
|
|
505
|
+
return {
|
|
506
|
+
name,
|
|
507
|
+
...knownMeta
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
if (name.startsWith("mcp_")) {
|
|
511
|
+
return {
|
|
512
|
+
name,
|
|
513
|
+
category: "execute",
|
|
514
|
+
risk: "medium",
|
|
515
|
+
description: "MCP external tool invocation."
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
if (name.endsWith("_agent")) {
|
|
519
|
+
return {
|
|
520
|
+
name,
|
|
521
|
+
category: "execute",
|
|
522
|
+
risk: "high",
|
|
523
|
+
description: "Sub-agent task execution tool."
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
if (/read|list|cat/i.test(name)) {
|
|
527
|
+
return {
|
|
528
|
+
name,
|
|
529
|
+
category: "read",
|
|
530
|
+
risk: "low",
|
|
531
|
+
description: "Likely a read-only inspection tool inferred by name."
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (/search|find|query|grep/i.test(name)) {
|
|
535
|
+
return {
|
|
536
|
+
name,
|
|
537
|
+
category: "search",
|
|
538
|
+
risk: "low",
|
|
539
|
+
description: "Likely a search tool inferred by name."
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
if (/write|edit|patch|update|create|delete|remove/i.test(name)) {
|
|
543
|
+
return {
|
|
544
|
+
name,
|
|
545
|
+
category: "write",
|
|
546
|
+
risk: "high",
|
|
547
|
+
description: "Likely a file-modifying tool inferred by name."
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
if (/bash|exec|run|shell|deploy|build|test/i.test(name)) {
|
|
551
|
+
return {
|
|
552
|
+
name,
|
|
553
|
+
category: "execute",
|
|
554
|
+
risk: "high",
|
|
555
|
+
description: "Likely a command execution tool inferred by name."
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
return {
|
|
559
|
+
name,
|
|
560
|
+
category: "other",
|
|
561
|
+
risk: "low",
|
|
562
|
+
description: "Tool category could not be inferred with high confidence."
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
getLatestUserText(messages) {
|
|
566
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
567
|
+
const message = messages[i];
|
|
568
|
+
if (message.role !== "user") {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
return this.messageContentToText(message.content);
|
|
572
|
+
}
|
|
573
|
+
return "";
|
|
574
|
+
}
|
|
575
|
+
messageContentToText(content) {
|
|
576
|
+
if (typeof content === "string") {
|
|
577
|
+
return content;
|
|
578
|
+
}
|
|
579
|
+
if (!Array.isArray(content)) {
|
|
580
|
+
return "";
|
|
581
|
+
}
|
|
582
|
+
const textParts = [];
|
|
583
|
+
for (const part of content) {
|
|
584
|
+
if (typeof part === "string") {
|
|
585
|
+
textParts.push(part);
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
if (part && typeof part === "object" && "text" in part && typeof part.text === "string") {
|
|
589
|
+
textParts.push(part.text);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return textParts.join("\n");
|
|
593
|
+
}
|
|
594
|
+
emitEvent(name, payload) {
|
|
595
|
+
const event = {
|
|
596
|
+
name,
|
|
597
|
+
mode: this.mode,
|
|
598
|
+
timestamp: Date.now(),
|
|
599
|
+
payload
|
|
600
|
+
};
|
|
601
|
+
this.events.push(event);
|
|
602
|
+
if (this.events.length > 500) {
|
|
603
|
+
this.events.shift();
|
|
604
|
+
}
|
|
605
|
+
this.eventEmitter.emit(name, event);
|
|
606
|
+
this.eventEmitter.emit("plan_mode_event", event);
|
|
607
|
+
if (name === "disallowed_tool_attempt_in_planning") {
|
|
608
|
+
this.logger.warn("[PlanMode] Soft violation detected in planning mode", payload);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
this.logger.info(`[PlanMode] ${name}`, payload);
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
var builtInPlanModePlugin = {
|
|
615
|
+
name: "pulse-coder-engine/built-in-plan-mode",
|
|
616
|
+
version: "1.0.0",
|
|
617
|
+
async initialize(context) {
|
|
618
|
+
const service = new BuiltInPlanModeService(context.logger, context.events, "executing");
|
|
619
|
+
context.registerRunHook("plan-mode", ({ context: runContext, tools, systemPrompt, hooks }) => {
|
|
620
|
+
const mode = service.getMode();
|
|
621
|
+
if (mode === "executing") {
|
|
622
|
+
return {
|
|
623
|
+
systemPrompt,
|
|
624
|
+
hooks
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
const transition = service.processContextMessages(runContext.messages);
|
|
628
|
+
const append = service.buildPromptAppend(Object.keys(tools), transition);
|
|
629
|
+
const finalSystemPrompt = appendSystemPrompt(systemPrompt, append);
|
|
630
|
+
return {
|
|
631
|
+
systemPrompt: finalSystemPrompt,
|
|
632
|
+
hooks: service.applyHooks(hooks)
|
|
633
|
+
};
|
|
634
|
+
});
|
|
635
|
+
context.registerService("planMode", service);
|
|
636
|
+
context.registerService("planModeService", service);
|
|
637
|
+
context.logger.info("[PlanMode] Built-in plan mode plugin initialized", {
|
|
638
|
+
mode: service.getMode()
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
|
|
236
643
|
// src/built-in/sub-agent-plugin/index.ts
|
|
237
644
|
import { z as z10 } from "zod";
|
|
238
|
-
import { promises as
|
|
239
|
-
import
|
|
645
|
+
import { promises as fs2 } from "fs";
|
|
646
|
+
import path3 from "path";
|
|
240
647
|
|
|
241
648
|
// src/ai/index.ts
|
|
242
649
|
import { generateText, streamText } from "ai";
|
|
@@ -268,8 +675,9 @@ var CLARIFICATION_TIMEOUT = Number(process.env.CLARIFICATION_TIMEOUT ?? 3e5);
|
|
|
268
675
|
var CLARIFICATION_ENABLED = process.env.CLARIFICATION_ENABLED !== "false";
|
|
269
676
|
|
|
270
677
|
// src/prompt/system.ts
|
|
271
|
-
|
|
272
|
-
|
|
678
|
+
import fs from "fs";
|
|
679
|
+
import path2 from "path";
|
|
680
|
+
var DEFAULT_PROMPT = `
|
|
273
681
|
You are Pulse Coder, the best coding agent on the planet.
|
|
274
682
|
|
|
275
683
|
You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
|
|
@@ -349,7 +757,7 @@ Use the 'clarify' tool when you genuinely need information from the user to proc
|
|
|
349
757
|
- Explain briefly what would change based on the answer
|
|
350
758
|
|
|
351
759
|
Example usage: Call clarify with a question, optional context, and optional default answer. The tool will pause and wait for the user's response.
|
|
352
|
-
- For substantial work, summarize clearly; follow final
|
|
760
|
+
- For substantial work, summarize clearly; follow final-answer formatting.
|
|
353
761
|
- Skip heavy formatting for simple confirmations.
|
|
354
762
|
- Don't dump large files you've written; reference paths only.
|
|
355
763
|
- No "save/copy this file" - User is on the same machine.
|
|
@@ -363,19 +771,19 @@ Example usage: Call clarify with a question, optional context, and optional defa
|
|
|
363
771
|
## Final answer structure and style guidelines
|
|
364
772
|
|
|
365
773
|
- Plain text; CLI handles styling. Use structure only when it helps scanability.
|
|
366
|
-
- Headers: optional; short Title Case (1-3 words) wrapped in
|
|
367
|
-
- Bullets: use - ; merge related points; keep to one line when possible; 4
|
|
774
|
+
- Headers: optional; short Title Case (1-3 words) wrapped in **...**; no blank line before the first bullet; add only if they truly help.
|
|
775
|
+
- Bullets: use - ; merge related points; keep to one line when possible; 4-6 per list ordered by importance; keep phrasing consistent.
|
|
368
776
|
- Monospace: backticks for commands/paths/env vars/code ids and inline examples; use for literal keyword bullets; never combine with **.
|
|
369
777
|
- Code samples or multi-line snippets should be wrapped in fenced code blocks; include an info string as often as possible.
|
|
370
|
-
- Structure: group related bullets; order sections general
|
|
371
|
-
- Tone: collaborative, concise, factual; present tense, active voice; self
|
|
372
|
-
- Don'ts: no nested bullets/hierarchies; no ANSI codes; don't cram unrelated keywords; keep keyword lists short
|
|
373
|
-
- Adaptation: code explanations
|
|
778
|
+
- Structure: group related bullets; order sections general -> specific -> supporting; for subsections, start with a bolded keyword bullet, then items; match complexity to the task.
|
|
779
|
+
- Tone: collaborative, concise, factual; present tense, active voice; self-contained; no "above/below"; parallel wording.
|
|
780
|
+
- Don'ts: no nested bullets/hierarchies; no ANSI codes; don't cram unrelated keywords; keep keyword lists short-wrap/reformat if long; avoid naming formatting styles in answers.
|
|
781
|
+
- Adaptation: code explanations -> precise, structured with code refs; simple tasks -> lead with outcome; big changes -> logical walkthrough + rationale + next actions; casual one-offs -> plain sentences, no headers/bullets.
|
|
374
782
|
- File References: When referencing files in your response follow the below rules:
|
|
375
783
|
* Use inline code to make file paths clickable.
|
|
376
784
|
* Each reference should have a stand alone path. Even if it's the same file.
|
|
377
|
-
* Accepted: absolute, workspace
|
|
378
|
-
* Optionally include line/column (1
|
|
785
|
+
* Accepted: absolute, workspace-relative, a/ or b/ diff prefixes, or bare filename/suffix.
|
|
786
|
+
* Optionally include line/column (1-based): :line[:column] or #Lline[Ccolumn] (column defaults to 1).
|
|
379
787
|
* Do not use URIs like file://, vscode://, or https://.
|
|
380
788
|
* Do not provide range of lines
|
|
381
789
|
* Examples: src/app.ts, src/app.ts:42, b/server/index.js#L10, C:\repoprojectmain.rs:12:5
|
|
@@ -389,7 +797,24 @@ Here is some useful information about the environment you are running in:
|
|
|
389
797
|
<files>
|
|
390
798
|
|
|
391
799
|
</files>`;
|
|
392
|
-
|
|
800
|
+
var AGENTS_FILE_REGEX = /^agents\.md$/i;
|
|
801
|
+
var loadAgentsPrompt = () => {
|
|
802
|
+
try {
|
|
803
|
+
const cwd = process.cwd();
|
|
804
|
+
const entries = fs.readdirSync(cwd, { withFileTypes: true });
|
|
805
|
+
const target = entries.find((entry) => entry.isFile() && AGENTS_FILE_REGEX.test(entry.name));
|
|
806
|
+
if (!target) {
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
const filePath = path2.join(cwd, target.name);
|
|
810
|
+
const content = fs.readFileSync(filePath, "utf8").trim();
|
|
811
|
+
return content.length > 0 ? content : null;
|
|
812
|
+
} catch {
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
var generateSystemPrompt = () => {
|
|
817
|
+
return loadAgentsPrompt() ?? DEFAULT_PROMPT;
|
|
393
818
|
};
|
|
394
819
|
|
|
395
820
|
// src/ai/index.ts
|
|
@@ -419,9 +844,10 @@ var streamTextAI = (messages, tools, options) => {
|
|
|
419
844
|
const provider = options?.provider ?? CoderAI;
|
|
420
845
|
const model = options?.model ?? DEFAULT_MODEL;
|
|
421
846
|
const wrappedTools = options?.toolExecutionContext ? wrapToolsWithContext(tools, options.toolExecutionContext) : tools;
|
|
847
|
+
const finalSystemPrompt = resolveSystemPrompt(options?.systemPrompt);
|
|
422
848
|
return streamText({
|
|
423
849
|
model: provider(model),
|
|
424
|
-
system:
|
|
850
|
+
system: finalSystemPrompt,
|
|
425
851
|
messages,
|
|
426
852
|
tools: wrappedTools,
|
|
427
853
|
providerOptions,
|
|
@@ -864,7 +1290,7 @@ var GrepTool = {
|
|
|
864
1290
|
}),
|
|
865
1291
|
execute: async ({
|
|
866
1292
|
pattern,
|
|
867
|
-
path:
|
|
1293
|
+
path: path4 = ".",
|
|
868
1294
|
glob,
|
|
869
1295
|
type,
|
|
870
1296
|
outputMode = "files_with_matches",
|
|
@@ -899,11 +1325,11 @@ var GrepTool = {
|
|
|
899
1325
|
if (type) {
|
|
900
1326
|
args.push("--type", type);
|
|
901
1327
|
}
|
|
902
|
-
if (
|
|
903
|
-
if (!existsSync5(
|
|
904
|
-
throw new Error(`Path does not exist: ${
|
|
1328
|
+
if (path4 && path4 !== ".") {
|
|
1329
|
+
if (!existsSync5(path4)) {
|
|
1330
|
+
throw new Error(`Path does not exist: ${path4}`);
|
|
905
1331
|
}
|
|
906
|
-
args.push(
|
|
1332
|
+
args.push(path4);
|
|
907
1333
|
}
|
|
908
1334
|
let command = args.map((arg) => {
|
|
909
1335
|
if (arg.includes(" ") || arg.includes("$") || arg.includes("*")) {
|
|
@@ -958,8 +1384,8 @@ var LsTool = {
|
|
|
958
1384
|
inputSchema: z6.object({
|
|
959
1385
|
path: z6.string().optional().describe("The path to list files from (defaults to current directory)")
|
|
960
1386
|
}),
|
|
961
|
-
execute: async ({ path:
|
|
962
|
-
const files = readdirSync(
|
|
1387
|
+
execute: async ({ path: path4 = "." }) => {
|
|
1388
|
+
const files = readdirSync(path4);
|
|
963
1389
|
return { files };
|
|
964
1390
|
}
|
|
965
1391
|
};
|
|
@@ -1130,8 +1556,8 @@ var ConfigLoader = class {
|
|
|
1130
1556
|
const fileInfos = [];
|
|
1131
1557
|
for (let configDir of configDirs) {
|
|
1132
1558
|
try {
|
|
1133
|
-
await
|
|
1134
|
-
const files = await
|
|
1559
|
+
await fs2.access(configDir);
|
|
1560
|
+
const files = await fs2.readdir(configDir);
|
|
1135
1561
|
fileInfos.push({ files, configDir });
|
|
1136
1562
|
} catch {
|
|
1137
1563
|
continue;
|
|
@@ -1148,7 +1574,7 @@ var ConfigLoader = class {
|
|
|
1148
1574
|
const files = fileInfo.files;
|
|
1149
1575
|
for (const file of files) {
|
|
1150
1576
|
if (file.endsWith(".md")) {
|
|
1151
|
-
const config = await this.parseConfig(
|
|
1577
|
+
const config = await this.parseConfig(path3.join(fileInfo.configDir, file));
|
|
1152
1578
|
if (config) configs.push(config);
|
|
1153
1579
|
}
|
|
1154
1580
|
}
|
|
@@ -1160,7 +1586,7 @@ var ConfigLoader = class {
|
|
|
1160
1586
|
}
|
|
1161
1587
|
async parseConfig(filePath) {
|
|
1162
1588
|
try {
|
|
1163
|
-
const content = await
|
|
1589
|
+
const content = await fs2.readFile(filePath, "utf-8");
|
|
1164
1590
|
const lines = content.split("\n");
|
|
1165
1591
|
let name = "";
|
|
1166
1592
|
let description = "";
|
|
@@ -1189,7 +1615,7 @@ var ConfigLoader = class {
|
|
|
1189
1615
|
}
|
|
1190
1616
|
}
|
|
1191
1617
|
if (!name) {
|
|
1192
|
-
name =
|
|
1618
|
+
name = path3.basename(filePath, ".md");
|
|
1193
1619
|
}
|
|
1194
1620
|
return {
|
|
1195
1621
|
name: name.trim(),
|
|
@@ -1228,20 +1654,15 @@ var SubAgentPlugin = class {
|
|
|
1228
1654
|
async initialize(context) {
|
|
1229
1655
|
try {
|
|
1230
1656
|
const configs = await this.configLoader.loadAgentConfigs();
|
|
1231
|
-
const tools = this.getAvailableTools(context);
|
|
1232
1657
|
for (const config of configs) {
|
|
1233
|
-
this.registerAgentTool(context, config
|
|
1658
|
+
this.registerAgentTool(context, config);
|
|
1234
1659
|
}
|
|
1235
1660
|
context.logger.info(`SubAgentPlugin loaded ${configs.length} agents.`);
|
|
1236
1661
|
} catch (error) {
|
|
1237
1662
|
context.logger.error("Failed to initialize SubAgentPlugin", error);
|
|
1238
1663
|
}
|
|
1239
1664
|
}
|
|
1240
|
-
|
|
1241
|
-
const allTools = {};
|
|
1242
|
-
return BuiltinToolsMap;
|
|
1243
|
-
}
|
|
1244
|
-
registerAgentTool(context, config, tools) {
|
|
1665
|
+
registerAgentTool(context, config) {
|
|
1245
1666
|
const toolName = `${config.name}_agent`;
|
|
1246
1667
|
const tool2 = {
|
|
1247
1668
|
description: config.description,
|
|
@@ -1250,6 +1671,7 @@ var SubAgentPlugin = class {
|
|
|
1250
1671
|
context: z10.any().optional().describe("\u4EFB\u52A1\u4E0A\u4E0B\u6587\u4FE1\u606F")
|
|
1251
1672
|
}),
|
|
1252
1673
|
execute: async ({ task, context: taskContext }) => {
|
|
1674
|
+
const tools = { ...BuiltinToolsMap, ...context.getTools() };
|
|
1253
1675
|
try {
|
|
1254
1676
|
context.logger.info(`Running agent ${config.name}: ${task}`);
|
|
1255
1677
|
const result = await this.agentRunner.runAgent(config, task, taskContext, tools);
|
|
@@ -1272,13 +1694,16 @@ var SubAgentPlugin = class {
|
|
|
1272
1694
|
var builtInPlugins = [
|
|
1273
1695
|
builtInMCPPlugin,
|
|
1274
1696
|
builtInSkillsPlugin,
|
|
1697
|
+
builtInPlanModePlugin,
|
|
1275
1698
|
new SubAgentPlugin()
|
|
1276
1699
|
];
|
|
1277
1700
|
var built_in_default = builtInPlugins;
|
|
1278
1701
|
export {
|
|
1702
|
+
BuiltInPlanModeService,
|
|
1279
1703
|
BuiltInSkillRegistry,
|
|
1280
1704
|
SubAgentPlugin,
|
|
1281
1705
|
builtInMCPPlugin,
|
|
1706
|
+
builtInPlanModePlugin,
|
|
1282
1707
|
builtInPlugins,
|
|
1283
1708
|
builtInSkillsPlugin,
|
|
1284
1709
|
built_in_default as default
|