opencode-enhancer-plugin 1.0.1 → 1.5.0

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.js CHANGED
@@ -1,29 +1,325 @@
1
+ import { TodoParser } from "./utils/todoParser.js";
2
+ import { todoStore } from "./utils/sessionStore.js";
3
+ // === TODO ENFORCER CONSTANTS ===
4
+ const TODO_ENFORCER_AGENTS = ['ultraplan', 'strategos'];
5
+ const TODO_MARKER_START = '<!-- TODOS-START -->';
6
+ const TODO_MARKER_END = '<!-- TODOS-END -->';
7
+ // === STRATEGOS MODE CONSTANTS ===
8
+ const STRATEGOS_KEYWORDS = [
9
+ 'strategos',
10
+ 'strategy',
11
+ 'strat',
12
+ 'interview mode',
13
+ 'strategic plan',
14
+ 'complex plan',
15
+ 'architecture decision',
16
+ 'design review',
17
+ 'comprehensive plan',
18
+ 'šŸŽÆ',
19
+ ];
20
+ // Validation Constants
21
+ const VALID_MODEL_PATTERNS = [
22
+ /^opencode\//,
23
+ /^anthropic\//,
24
+ /^openai\//,
25
+ /^google\//,
26
+ /^mistral\//,
27
+ /^cohere\//,
28
+ /^ollama\//,
29
+ /^zai-coding-plan\//,
30
+ /^kimi-for-coding\//
31
+ ];
32
+ const DEFAULT_MODEL = "opencode/kimi-k2.5-free";
33
+ // Model Validation Function
34
+ function validateModel(model, agentName, client) {
35
+ if (!model || typeof model !== 'string') {
36
+ client.app.log({
37
+ service: "enhancer",
38
+ level: "warn",
39
+ message: `Invalid model for ${agentName}, using default`
40
+ }).catch(() => { });
41
+ return DEFAULT_MODEL;
42
+ }
43
+ const isValid = VALID_MODEL_PATTERNS.some(pattern => pattern.test(model));
44
+ if (!isValid) {
45
+ client.app.log({
46
+ service: "enhancer",
47
+ level: "warn",
48
+ message: `Unknown model provider for ${agentName}: ${model}, using default`
49
+ }).catch(() => { });
50
+ return DEFAULT_MODEL;
51
+ }
52
+ return model;
53
+ }
54
+ // Model Resolver with Hierarchical Configuration
55
+ function resolveModel(agentName, agentType, existingConfig, client) {
56
+ let model;
57
+ // 1. Check existing OpenCode Config (highest priority)
58
+ if (existingConfig?.model) {
59
+ return validateModel(existingConfig.model, agentName, client);
60
+ }
61
+ // 2. Specific environment variable (e.g., ENHANCER_MODEL_REVIEW_PLAN)
62
+ const specificVar = `ENHANCER_MODEL_${agentName.toUpperCase().replace(/-/g, '_')}`;
63
+ model = process.env[specificVar];
64
+ if (model) {
65
+ client.app.log({
66
+ service: "enhancer",
67
+ level: "info",
68
+ message: `Using specific env var ${specificVar} for ${agentName}`
69
+ }).catch(() => { });
70
+ return validateModel(model, agentName, client);
71
+ }
72
+ // 3. Grouped environment variable (ENHANCER_MODEL_SUBAGENT or ENHANCER_MODEL_PRIMARY)
73
+ const groupVar = `ENHANCER_MODEL_${agentType.toUpperCase()}`;
74
+ model = process.env[groupVar];
75
+ if (model) {
76
+ client.app.log({
77
+ service: "enhancer",
78
+ level: "info",
79
+ message: `Using group env var ${groupVar} for ${agentName}`
80
+ }).catch(() => { });
81
+ return validateModel(model, agentName, client);
82
+ }
83
+ // 4. Default
84
+ return DEFAULT_MODEL;
85
+ }
1
86
  export const EnhancerPlugin = async ({ client }) => {
2
87
  client.app.log({
3
88
  service: "enhancer",
4
89
  level: "info",
5
- message: "Enhancer plugin initialized"
90
+ message: "šŸ”„ Enhancer plugin v1.5.0 initialized with 5 Specialized Subagents"
6
91
  }).catch(() => { });
7
92
  return {
8
93
  config: async (input) => {
9
94
  if (!input.agent) {
10
95
  input.agent = {};
11
96
  }
12
- input.agent["explore-context"] = {
13
- mode: "subagent",
14
- hidden: true,
15
- model: "opencode/kimi-k2.5-free",
16
- prompt: `You are the UNIVERSAL CONTEXT DETECTIVE. Map the codebase and extract technical context.`,
97
+ // Helper function to configure agent with merging logic
98
+ const configureAgent = (name, type, defaultConfig) => {
99
+ const existing = input.agent[name] || {};
100
+ const resolvedModel = resolveModel(name, type, existing, client);
101
+ // Merge: Default → User Config → Resolved Model → Fixed Props
102
+ input.agent[name] = {
103
+ ...defaultConfig,
104
+ ...existing,
105
+ model: resolvedModel,
106
+ mode: type === 'subagent' ? 'subagent' : 'primary',
107
+ ...(type === 'subagent' ? { hidden: true } : {})
108
+ };
109
+ };
110
+ // === SUBAGENTS (4 spezialisierte Experten) ===
111
+ // 1. LIBRARIAN - Dokumentation & Recherche
112
+ configureAgent('librarian', 'subagent', {
113
+ prompt: `You are LIBRARIAN - a documentation and codebase research specialist.
114
+
115
+ YOUR EXPERTISE:
116
+ - Find official documentation (Context7)
117
+ - Search GitHub for implementation examples (codesearch)
118
+ - Map project structure and entry points
119
+ - Identify tech stack and frameworks
120
+
121
+ WORKFLOW:
122
+ 1. ALWAYS check context7 first for detected libraries
123
+ 2. Use codesearch for real-world usage patterns
124
+ 3. List project structure with glob
125
+ 4. Return structured findings
126
+
127
+ OUTPUT FORMAT:
128
+ # šŸ“š Librarian Report
129
+
130
+ ## Tech Stack Detected
131
+ - **Framework**: [Name + Version]
132
+ - **Language**: [TypeScript/Python/etc.]
133
+ - **Key Libraries**: [List with Context7 links]
134
+
135
+ ## Project Structure
136
+ - **Entry Point**: [Main file]
137
+ - **Core Directories**: [src/, lib/, etc.]
138
+ - **Config Files**: [package.json, tsconfig.json, etc.]
139
+
140
+ ## Documentation Resources
141
+ - Context7 Libraries: [List of libraries with docs available]
142
+ - GitHub Examples: [Patterns found via codesearch]
143
+
144
+ ## Recommendations
145
+ - [What should the primary agent know?]
146
+ - [Any missing dependencies?]`,
17
147
  tools: {
18
148
  list: true,
19
149
  read: true,
20
150
  grep: true,
21
- bash: true
151
+ context7_resolve_library_id: true,
152
+ context7_query_docs: true,
153
+ codesearch: true
22
154
  }
23
- };
24
- input.agent.enhancer = {
25
- mode: "primary",
26
- model: "opencode/kimi-k2.5-free",
155
+ });
156
+ // 2. ORACLE - Debugging & Code Analysis
157
+ configureAgent('oracle', 'subagent', {
158
+ prompt: `You are ORACLE - a debugging and code architecture specialist.
159
+
160
+ YOUR EXPERTISE:
161
+ - Deep code analysis and understanding
162
+ - Error pattern recognition
163
+ - Architecture evaluation
164
+ - Root cause analysis (not symptoms!)
165
+
166
+ WORKFLOW:
167
+ 1. Read relevant source files thoroughly
168
+ 2. Analyze patterns and relationships
169
+ 3. Identify issues or architectural concerns
170
+ 4. Provide specific, actionable insights
171
+
172
+ OUTPUT FORMAT:
173
+ # šŸ”® Oracle Analysis
174
+
175
+ ## Code Understanding
176
+ - **File**: [path/to/file.ts]
177
+ - **Purpose**: [What does this code do?]
178
+ - **Key Functions**: [List important functions/classes]
179
+
180
+ ## Issues Found
181
+ - **[SEVERITY: Critical/Warning/Info]** [Issue description]
182
+ - Location: [File:Line]
183
+ - Impact: [What could go wrong]
184
+ - Fix: [Specific recommendation]
185
+
186
+ ## Architecture Assessment
187
+ - **Patterns Used**: [Singleton, Factory, etc.]
188
+ - **Coupling**: [High/Medium/Low]
189
+ - **Recommendations**: [Improvements]`,
190
+ tools: {
191
+ read: true,
192
+ grep: true
193
+ }
194
+ });
195
+ // 3. ARCHITECT - Dependencies & System Design
196
+ configureAgent('architect', 'subagent', {
197
+ prompt: `You are ARCHITECT - a dependency and system design specialist.
198
+
199
+ YOUR EXPERTISE:
200
+ - Dependency analysis and conflicts
201
+ - Import patterns and module relationships
202
+ - System architecture evaluation
203
+ - Integration complexity assessment
204
+
205
+ WORKFLOW:
206
+ 1. Analyze package.json / requirements / dependencies
207
+ 2. Map import patterns across codebase
208
+ 3. Check for version conflicts or deprecated packages
209
+ 4. Assess system boundaries
210
+
211
+ OUTPUT FORMAT:
212
+ # šŸ—ļø Architecture Report
213
+
214
+ ## Dependencies Analysis
215
+ - **Core Libraries**: [List with versions]
216
+ - **Dev Dependencies**: [Testing, build tools]
217
+ - **Peer Dependencies**: [Compatibility requirements]
218
+
219
+ ## Import Patterns
220
+ - **Common Imports**: [Most used modules]
221
+ - **Circular Dependencies**: [If any found]
222
+ - **Unused Dependencies**: [Potential cleanup]
223
+
224
+ ## System Boundaries
225
+ - **External APIs**: [Services integrated]
226
+ - **Database/Storage**: [Data layer]
227
+ - **Authentication**: [Auth mechanism]
228
+
229
+ ## Risk Assessment
230
+ - **Version Conflicts**: [Issues]
231
+ - **Deprecated Packages**: [Needs update]
232
+ - **Security Concerns**: [Vulnerabilities]`,
233
+ tools: {
234
+ read: true,
235
+ grep: true,
236
+ glob: true
237
+ }
238
+ });
239
+ // 4. REVIEWER - Plan Validation
240
+ configureAgent('reviewer', 'subagent', {
241
+ prompt: `You are REVIEWER - a critical plan validation specialist.
242
+
243
+ YOUR EXPERTISE:
244
+ - Spot missing steps in plans
245
+ - Identify technical risks early
246
+ - Validate file paths and assumptions
247
+ - Ensure test coverage
248
+
249
+ WORKFLOW:
250
+ 1. Analyze the proposed plan
251
+ 2. Check for completeness gaps
252
+ 3. Verify technical feasibility
253
+ 4. Provide critical feedback
254
+
255
+ OUTPUT FORMAT:
256
+ # āœ… Plan Review
257
+
258
+ ## Summary
259
+ - **Status**: [APPROVED / NEEDS_REVISION]
260
+ - **Completeness**: [X%]
261
+ - **Risk Level**: [Low/Medium/High]
262
+
263
+ ## Critical Issues
264
+ 1. [Issue] → [Fix]
265
+
266
+ ## Warnings
267
+ 1. [Concern] → [Mitigation]
268
+
269
+ ## Missing Elements
270
+ - [What was forgotten?]
271
+
272
+ ## Final Verdict
273
+ [One paragraph assessment]`,
274
+ tools: {
275
+ read: true,
276
+ task: true
277
+ }
278
+ });
279
+ // 5. INTERVIEWER (nur für strategos)
280
+ configureAgent('interviewer', 'subagent', {
281
+ prompt: `You are INTERVIEWER - a requirements clarification specialist.
282
+
283
+ YOUR EXPERTISE:
284
+ - Ask the right questions
285
+ - Uncover hidden assumptions
286
+ - Define clear scope and success criteria
287
+ - Identify stakeholders and constraints
288
+
289
+ RULES:
290
+ - Ask 3-5 questions maximum
291
+ - Focus on "Must Have" vs "Nice to Have"
292
+ - Clarify technical constraints
293
+ - Define "Done"
294
+
295
+ OUTPUT FORMAT:
296
+ # šŸŽ¤ Interview Report
297
+
298
+ ## Clarification Questions
299
+
300
+ ### Q1: [Question]
301
+ **Why**: [Context]
302
+
303
+ ### Q2: [Question]
304
+ **Why**: [Context]
305
+
306
+ ### Q3: [Question]
307
+ **Why**: [Context]
308
+
309
+ ## Anticipated Complexity
310
+ - **Level**: [Low/Medium/High]
311
+ - **Estimated Effort**: [X hours/days]
312
+ - **Main Risks**: [List]
313
+
314
+ ## Next Steps
315
+ [What to do after getting answers]`,
316
+ tools: {
317
+ read: true
318
+ }
319
+ });
320
+ // Configure Primary Agents
321
+ // enhancer - Prompt Enhancement
322
+ configureAgent('enhancer', 'primary', {
27
323
  description: "Universal Technical Architect & Prompt Enhancer",
28
324
  color: "#9C27B0",
29
325
  steps: 15,
@@ -34,36 +330,478 @@ export const EnhancerPlugin = async ({ client }) => {
34
330
  edit: false,
35
331
  write: false
36
332
  },
37
- prompt: `You are the CHIEF ARCHITECT (Enhancer). Translate user wishes into precise engineering specifications.`
38
- };
333
+ permission: {
334
+ edit: "deny",
335
+ bash: "deny"
336
+ },
337
+ prompt: `You are ENHANCER - generate enhanced, executable prompts.
338
+
339
+ WORKFLOW:
340
+ 1. Classify intent: FIX/FEAT/REFACTOR/TEST/EXPLAIN
341
+ 2. Call subagents IN PARALLEL:
342
+ - FIX/FEAT: librarian + oracle + architect
343
+ - REFACTOR: librarian + oracle + reviewer
344
+ - TEST: librarian + oracle + architect + reviewer
345
+ - EXPLAIN: librarian + oracle
346
+ 3. Synthesize results
347
+ 4. Generate markdown prompt
348
+
349
+ OUTPUT FORMAT:
350
+ # Task: [Title]
351
+
352
+ ## Context
353
+ [Tech stack and key files]
354
+
355
+ ## Instructions
356
+ 1. [Specific step]
357
+ 2. [Specific step]
358
+
359
+ ## Technical Constraints
360
+ - [Constraint 1]
361
+ - [Constraint 2]
362
+
363
+ ---
364
+ **Run in Build mode to execute**
365
+
366
+ === RULES ===
367
+ - ALL paths from subagents
368
+ - Be specific, never vague`
369
+ });
370
+ // ultraplan - Vereinfacht & Fokussiert
371
+ configureAgent('ultraplan', 'primary', {
372
+ description: "Planning Agent with Parallel Discovery šŸ”",
373
+ color: "#FF5722",
374
+ steps: 20,
375
+ tools: {
376
+ task: true,
377
+ read: true,
378
+ bash: false,
379
+ edit: false,
380
+ write: false,
381
+ todowrite: true // ⭐ Todo-Integration
382
+ },
383
+ permission: {
384
+ edit: "deny",
385
+ bash: "deny"
386
+ },
387
+ prompt: `You are ULTRAPLAN - create implementation plans through parallel discovery.
388
+
389
+ === WORKFLOW (STRICT) ===
390
+
391
+ **STEP 1: PARALLEL DISCOVERY** ⚔
392
+ Call ALL subagents IN PARALLEL:
393
+ - librarian: Map project structure & docs
394
+ - oracle: Analyze relevant code
395
+ - architect: Check dependencies & system design
396
+
397
+ WAIT for all results. Do NOT proceed before all return.
398
+
399
+ **STEP 2: CREATE TODOS** šŸ”’
400
+ MUST use todowrite tool:
401
+ \`\`\`
402
+ todowrite({
403
+ todos: [
404
+ { id: "1", content: "Step 1: [Specific task]", status: "pending", priority: "high" },
405
+ { id: "2", content: "Step 2: [Specific task]", status: "pending", priority: "high" },
406
+ // 3-8 todos depending on complexity
407
+ ]
408
+ })
409
+ \`\`\`
410
+
411
+ **STEP 3: CREATE PLAN**
412
+ Generate markdown plan with:
413
+ - File paths from discovery (NEVER invent!)
414
+ - Specific implementation steps
415
+ - Error handling strategy
416
+
417
+ **STEP 4: REQUEST REVIEW** (optional for complex tasks)
418
+ Call reviewer subagent if plan is high-risk.
419
+
420
+ === RULES ===
421
+ - ALL file paths must come from librarian/oracle/architect
422
+ - ALWAYS create todos via todowrite tool
423
+ - NEVER enable write/edit tools
424
+ - End with: "Copy this plan and run in **Build** mode"
425
+
426
+ === WHEN TO USE ===
427
+ - Simple bugfixes
428
+ - Small features (1-3 files)
429
+ - Documentation
430
+ - Adding tests
431
+
432
+ === WHEN TO USE STRATEGOS ===
433
+ - New features (>3 files)
434
+ - Architecture changes
435
+ - Integrations (APIs, DBs)
436
+ - Performance/Security work`
437
+ });
438
+ // ask - Question Answering
439
+ configureAgent('ask', 'primary', {
440
+ description: "Context-Aware Question Answering",
441
+ color: "#2196F3",
442
+ steps: 15,
443
+ tools: {
444
+ task: true,
445
+ read: true,
446
+ bash: false,
447
+ edit: false,
448
+ write: false
449
+ },
450
+ permission: {
451
+ edit: "deny",
452
+ bash: "deny"
453
+ },
454
+ prompt: `You are ASK - a context-aware research assistant.
455
+
456
+ === WORKFLOW ===
457
+
458
+ **STEP 1: CLASSIFY QUESTION**
459
+ - CODE: "How does X work?", "Explain this function"
460
+ - ARCHITECTURE: "How is this project structured?"
461
+ - DEBUG: "Why is this not working?"
462
+ - GENERAL: "What is this project about?"
463
+
464
+ **STEP 2: PARALLEL SUBAGENTS**
465
+ Call based on type:
466
+
467
+ | Type | Subagents |
468
+ |------|-----------|
469
+ | CODE | librarian + oracle + architect |
470
+ | ARCHITECTURE | librarian + oracle |
471
+ | DEBUG | librarian + oracle + architect + reviewer |
472
+ | GENERAL | librarian |
473
+
474
+ **STEP 3: SYNTHESIZE**
475
+ - Wait for ALL results
476
+ - Combine findings
477
+ - Resolve conflicts
478
+
479
+ **STEP 4: ANSWER FORMAT**
480
+
481
+ ## Answer
482
+ [2-4 sentences]
483
+
484
+ ## Details
485
+
486
+ ### Relevant Files
487
+ - \`path/to/file.ts\` - [Why it matters]
488
+
489
+ ### Key Code
490
+ \`\`\`typescript
491
+ // From: path/to/file.ts
492
+ [Snippet]
493
+ \`\`\`
494
+
495
+ ### Context
496
+ - **Tech Stack**: [Technologies]
497
+ - **Pattern**: [Design patterns]
498
+
499
+ ## Explore Further
500
+ - [Suggestion 1]
501
+ - [Suggestion 2]
502
+
503
+ === RULES ===
504
+ - ALL paths from subagents (never invent)
505
+ - Cite sources (which subagent found what)
506
+ - Be concise but thorough`
507
+ });
508
+ // strategos - Strategic Planning
509
+ configureAgent('strategos', 'primary', {
510
+ description: "šŸŽÆ Strategic Planner with Interview Mode",
511
+ color: "#FF6F00",
512
+ steps: 30,
513
+ tools: {
514
+ task: true,
515
+ read: true,
516
+ bash: false,
517
+ edit: false,
518
+ write: false,
519
+ todowrite: true
520
+ },
521
+ permission: {
522
+ edit: "deny",
523
+ bash: "deny",
524
+ },
525
+ prompt: `You are STRATEGOS - the Strategic General.
526
+
527
+ === STRATEGOS WORKFLOW ===
528
+
529
+ **PHASE 1: INTERVIEW (If needed)**
530
+ When requirements are unclear:
531
+ 1. Call interviewer subagent
532
+ 2. Present questions to user
533
+ 3. Wait for answers
534
+ 4. Analyze and confirm understanding
535
+
536
+ **PHASE 2: DISCOVERY**
537
+ Call ALL in PARALLEL:
538
+ - librarian: Project & docs
539
+ - oracle: Code analysis
540
+ - architect: Dependencies & system
541
+
542
+ **PHASE 3: STRATEGIC PLANNING**
543
+
544
+ Create structured plan:
545
+
546
+ # šŸŽÆ Strategos Strategic Plan
547
+
548
+ ## Mission Statement
549
+ [1-2 sentences]
550
+
551
+ ## Requirements Analysis
552
+ ### Must Have
553
+ - [ ]
554
+ ### Should Have
555
+ - [ ]
556
+ ### Could Have
557
+ - [ ]
558
+
559
+ ## Architecture Decisions
560
+ | Decision | Rationale | Trade-offs |
561
+ |----------|-----------|------------|
562
+ | [Decision] | [Why] | [Pros/Cons] |
563
+
564
+ ## Implementation Roadmap
565
+
566
+ ### Phase 1: Foundation
567
+ **Goal**: [What to achieve]
568
+ **Deliverables**:
569
+ - [ ] [Specific deliverable]
570
+ **Files**:
571
+ - \`path/to/file.ts\` - [Why?]
572
+ **Steps**:
573
+ 1. [Concrete step]
574
+
575
+ ### Phase 2: Core Implementation
576
+ ...
577
+
578
+ ### Phase 3: Integration & Testing
579
+ ...
580
+
581
+ ## Risk Assessment
582
+ | Risk | Probability | Impact | Mitigation |
583
+ |------|------------|--------|------------|
584
+ | [Risk] | High/Med/Low | High/Med/Low | [Strategy] |
585
+
586
+ ## āœ… Quality Gates
587
+ - [ ] Gate 1: [Criterion]
588
+ - [ ] Gate 2: [Criterion]
589
+
590
+ ## 🧪 Validation Plan
591
+ [How to test success]
592
+
593
+ **NEXT STEP**: Run in **Build** mode.
594
+
595
+ === TODO CREATION ===
596
+ MUST create todos via todowrite:
597
+ - Phase 1: [Description]
598
+ - Phase 2: [Description]
599
+ - Phase 3: [Description]
600
+
601
+ āš ļø You cannot stop until all todos are completed!
602
+
603
+ === WHEN TO USE STRATEGOS ===
604
+ - New features (>3 files)
605
+ - Architecture changes
606
+ - Integrations (APIs, DBs)
607
+ - Performance/Security work
608
+ - Complex refactoring
609
+
610
+ === WHEN TO USE ULTRAPLAN ===
611
+ - Simple tasks (<3 files)
612
+ - Bugfixes
613
+ - Documentation`,
614
+ });
615
+ // Log configured agent models
616
+ const configuredAgents = [
617
+ 'librarian', 'oracle', 'architect', 'reviewer', 'interviewer',
618
+ 'enhancer', 'ultraplan', 'ask', 'strategos'
619
+ ];
620
+ const modelSummary = configuredAgents
621
+ .map(name => `${name}=${input.agent[name]?.model || 'default'}`)
622
+ .join(', ');
623
+ client.app.log({
624
+ service: "enhancer",
625
+ level: "info",
626
+ message: `šŸ”„ Registered ${Object.keys(input.agent).length} agents: ${Object.keys(input.agent).join(", ")}`
627
+ }).catch(() => { });
628
+ client.app.log({
629
+ service: "enhancer",
630
+ level: "debug",
631
+ message: `Agent models configured: ${modelSummary}`
632
+ }).catch(() => { });
39
633
  },
40
634
  "tool.execute.before": async (input, output) => {
41
635
  if (input.tool === "task") {
42
636
  const args = output.args;
43
- if (args?.subagent_type === "explore-context") {
637
+ const validSubagents = [
638
+ "librarian", "oracle", "architect", "reviewer", "interviewer"
639
+ ];
640
+ if (args?.subagent_type && validSubagents.includes(args.subagent_type)) {
44
641
  client.app.log({
45
642
  service: "enhancer",
46
643
  level: "debug",
47
- message: "Calling explore-context subagent"
644
+ message: `Calling ${args.subagent_type} subagent`
48
645
  }).catch(() => { });
49
646
  }
50
647
  }
51
648
  },
52
649
  "message.updated": async (input, output) => {
53
- if (input.session?.agent?.name !== "enhancer") {
650
+ const agentName = input.session?.agent?.name;
651
+ if (!["enhancer", "ultraplan", "ask", "strategos"].includes(agentName)) {
54
652
  return;
55
653
  }
56
654
  const content = input.message?.content || "";
57
655
  if (content.includes("Build mode") || content.includes("Build Mode")) {
58
656
  return;
59
657
  }
60
- if (content.includes("```markdown") || content.includes("# Task:")) {
658
+ if (content.includes("\`\`\`markdown") || content.includes("# Task:")) {
61
659
  const hint = "\n\n---\n**Next Step**: Copy this entire block and run it in **Build** mode to execute the plan.";
62
660
  if (output && typeof output === "object") {
63
661
  output.content = content + hint;
64
662
  }
65
663
  }
66
- }
664
+ },
665
+ // === TODO ENFORCER: Message Completed Hook ===
666
+ // Extracts todos from agent responses and stores them
667
+ "message.completed": async (input, output) => {
668
+ const agentName = input.session?.agent?.name;
669
+ const sessionId = input.session?.id || input.sessionId || 'default';
670
+ // Only for Todo-enforced agents
671
+ if (!TODO_ENFORCER_AGENTS.includes(agentName)) {
672
+ return;
673
+ }
674
+ try {
675
+ const content = input.message?.content || output?.content || "";
676
+ // Extract todos
677
+ const result = TodoParser.extractTodos(content);
678
+ if (result.hasTodos) {
679
+ // Store todos
680
+ todoStore.set(sessionId, result.todos, agentName);
681
+ // Log for debugging
682
+ await client.app.log({
683
+ service: "enhancer",
684
+ level: "info",
685
+ message: `šŸ“ Todos detected in ${agentName}: ${result.completedCount}/${result.todos.length} completed`
686
+ }).catch(() => { });
687
+ // Add visual todo block if pending todos exist
688
+ if (result.pendingCount > 0) {
689
+ const todoBlock = `\n\n${TODO_MARKER_START}\n## šŸ“‹ Open Todos (${result.pendingCount}/${result.todos.length})\n\n${TodoParser.formatTodoList(result.todos, true)}\n\nāš ļø **Note**: You cannot stop until all Todos are completed!\n${TODO_MARKER_END}`;
690
+ if (output && typeof output === "object") {
691
+ output.content = content + todoBlock;
692
+ }
693
+ }
694
+ }
695
+ }
696
+ catch (error) {
697
+ await client.app.log({
698
+ service: "enhancer",
699
+ level: "warn",
700
+ message: `Error in todo extraction: ${error}`
701
+ }).catch(() => { });
702
+ }
703
+ },
704
+ // === TODO ENFORCER: Stop Requested Hook ===
705
+ // Prevents stop when todos are open
706
+ "stop.requested": async (input, output) => {
707
+ const agentName = input.session?.agent?.name;
708
+ const sessionId = input.session?.id || input.sessionId || 'default';
709
+ // Only for Todo-enforced agents
710
+ if (!TODO_ENFORCER_AGENTS.includes(agentName)) {
711
+ return;
712
+ }
713
+ try {
714
+ const unfinishedCount = todoStore.countUnfinished(sessionId);
715
+ if (unfinishedCount > 0) {
716
+ const pendingTodos = todoStore.getAllPending(sessionId);
717
+ // DENY STOP
718
+ output.continue = true;
719
+ output.reason = `šŸ›‘ **STOP DENIED** - ${unfinishedCount} TODO(S) STILL OPEN!\n\nYou cannot end the session until all tasks are completed. Please work on the remaining todos:\n\n${pendingTodos.map((t, i) => `${i + 1}. [ ] ${t.description}`).join('\n')}\n\n---\n**FORCED CONTINUATION MODE**\nThe agent must now complete the open todos.`;
720
+ await client.app.log({
721
+ service: "enhancer",
722
+ level: "warn",
723
+ message: `šŸ›‘ Stop blocked for ${agentName}: ${unfinishedCount} todos open`
724
+ }).catch(() => { });
725
+ }
726
+ else {
727
+ // All todos completed - clean up store
728
+ if (todoStore.has(sessionId)) {
729
+ todoStore.delete(sessionId);
730
+ await client.app.log({
731
+ service: "enhancer",
732
+ level: "info",
733
+ message: `āœ… All todos completed in ${agentName} - Store cleaned`
734
+ }).catch(() => { });
735
+ }
736
+ }
737
+ }
738
+ catch (error) {
739
+ await client.app.log({
740
+ service: "enhancer",
741
+ level: "error",
742
+ message: `Error in stop.requested hook: ${error}`
743
+ }).catch(() => { });
744
+ }
745
+ },
746
+ // === TODO ENFORCER: Session Start Hook ===
747
+ // Cleans old todos on new session
748
+ "session.start": async (input, output) => {
749
+ const agentName = input.agent?.name;
750
+ if (TODO_ENFORCER_AGENTS.includes(agentName)) {
751
+ // Cleanup old sessions
752
+ todoStore.cleanup();
753
+ await client.app.log({
754
+ service: "enhancer",
755
+ level: "debug",
756
+ message: `šŸ”„ New ${agentName} session started - Todo Store cleaned`
757
+ }).catch(() => { });
758
+ }
759
+ },
760
+ // === TODO ENFORCER: Session End Hook ===
761
+ "session.end": async (input, output) => {
762
+ const agentName = input.agent?.name;
763
+ const sessionId = input.session?.id || input.sessionId || 'default';
764
+ if (TODO_ENFORCER_AGENTS.includes(agentName)) {
765
+ // Check if open todos exist
766
+ if (todoStore.has(sessionId)) {
767
+ const stats = todoStore.get(sessionId);
768
+ const unfinished = stats?.todos.filter(t => t.status !== 'completed').length || 0;
769
+ if (unfinished > 0) {
770
+ await client.app.log({
771
+ service: "enhancer",
772
+ level: "warn",
773
+ message: `āš ļø Session ended with ${unfinished} open todos`
774
+ }).catch(() => { });
775
+ }
776
+ // Clean up
777
+ todoStore.delete(sessionId);
778
+ }
779
+ }
780
+ },
781
+ // === STRATEGOS MODE ACTIVATION ===
782
+ // Auto-switch to strategos on keywords
783
+ "user.prompt.submitted": async (input, output) => {
784
+ const prompt = input.prompt || "";
785
+ const currentAgent = input.agent?.name;
786
+ const lowerPrompt = prompt.toLowerCase();
787
+ // Check for Strategos keywords
788
+ const detectedKeyword = STRATEGOS_KEYWORDS.find(kw => lowerPrompt.includes(kw.toLowerCase()));
789
+ if (detectedKeyword && currentAgent !== 'strategos') {
790
+ // Switch to strategos Agent
791
+ output.agent = 'strategos';
792
+ // Add hint
793
+ output.hint = `šŸŽÆ **Strategos Mode activated** (Keyword: "${detectedKeyword}")\n\nI will interview you first to clarify requirements, then create a strategic plan.`;
794
+ await client.app.log({
795
+ service: "enhancer",
796
+ level: "info",
797
+ message: `šŸŽÆ Strategos Mode activated by keyword: "${detectedKeyword}"`
798
+ }).catch(() => { });
799
+ }
800
+ // Alternative: Interview Mode hint for ultraplan
801
+ if (lowerPrompt.includes('interview me') && currentAgent === 'ultraplan') {
802
+ output.hint = `šŸ’” **Tip**: For complex tasks with interview, use the **strategos** Agent (Tab → strategos)`;
803
+ }
804
+ },
67
805
  };
68
806
  };
69
807
  export default EnhancerPlugin;