opencode-ultra 0.7.2 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +159 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14541,7 +14541,7 @@ function detectConfigFile(basePath) {
14541
14541
  return null;
14542
14542
  }
14543
14543
  function loadConfig(projectDir) {
14544
- const userPath = detectConfigFile(path.join(getConfigDir(), "oh-my-opencode"));
14544
+ const userPath = detectConfigFile(path.join(getConfigDir(), "opencode-ultra"));
14545
14545
  let config2 = {};
14546
14546
  if (userPath) {
14547
14547
  try {
@@ -14552,7 +14552,7 @@ function loadConfig(projectDir) {
14552
14552
  log(`Error loading user config: ${err}`);
14553
14553
  }
14554
14554
  }
14555
- const projectPath = detectConfigFile(path.join(projectDir, ".opencode", "oh-my-opencode"));
14555
+ const projectPath = detectConfigFile(path.join(projectDir, ".opencode", "opencode-ultra"));
14556
14556
  if (projectPath) {
14557
14557
  try {
14558
14558
  const content = fs.readFileSync(projectPath, "utf-8");
@@ -28600,6 +28600,160 @@ function formatResult(result) {
28600
28600
  `);
28601
28601
  }
28602
28602
 
28603
+ // src/tools/evolve-filter.ts
28604
+ var PRIORITY_WEIGHT = {
28605
+ P0: 10,
28606
+ P1: 5,
28607
+ P2: 1
28608
+ };
28609
+ var EFFORT_WEIGHT = {
28610
+ Low: 3,
28611
+ Medium: 2,
28612
+ High: 1
28613
+ };
28614
+ var DEFAULT_MIN_SCORE = 5;
28615
+ var DEFAULT_MAX_PROPOSALS = 3;
28616
+ function scoreProposal(p) {
28617
+ const pw = PRIORITY_WEIGHT[p.priority] ?? 1;
28618
+ const ew = EFFORT_WEIGHT[p.effort] ?? 1;
28619
+ return pw * ew;
28620
+ }
28621
+ function filterProposals(proposals, config3) {
28622
+ const minScore = config3?.minScore ?? DEFAULT_MIN_SCORE;
28623
+ const maxProposals = config3?.maxProposals ?? DEFAULT_MAX_PROPOSALS;
28624
+ const scored = proposals.map((p) => {
28625
+ const score = scoreProposal(p);
28626
+ const accepted2 = score >= minScore;
28627
+ return {
28628
+ ...p,
28629
+ score,
28630
+ accepted: accepted2,
28631
+ reason: accepted2 ? undefined : `Score ${score} below threshold ${minScore}`
28632
+ };
28633
+ });
28634
+ const accepted = scored.filter((p) => p.accepted).sort((a, b) => b.score - a.score).slice(0, maxProposals);
28635
+ const rejected = scored.filter((p) => !p.accepted);
28636
+ const acceptedSet = new Set(accepted);
28637
+ const overflow = scored.filter((p) => p.accepted && !acceptedSet.has(p)).map((p) => ({ ...p, accepted: false, reason: `Exceeded maxProposals (${maxProposals})` }));
28638
+ return [...accepted, ...overflow, ...rejected];
28639
+ }
28640
+ function parseProposalsFromMarkdown(markdown) {
28641
+ const proposals = [];
28642
+ const sections = markdown.split(/^##\s+Improvement:\s*/m);
28643
+ for (let i = 1;i < sections.length; i++) {
28644
+ const section = sections[i];
28645
+ const lines = section.trim();
28646
+ const titleMatch = lines.match(/^(.+?)(?:\n|$)/);
28647
+ const title = titleMatch?.[1]?.trim() ?? "Untitled";
28648
+ const priority = extractField(lines, "Priority");
28649
+ const effort = extractField(lines, "Effort");
28650
+ const description = extractField(lines, "Why") || extractField(lines, "How") || "";
28651
+ const currentState = extractField(lines, "Current state") || undefined;
28652
+ const inspiration = extractField(lines, "Inspiration") || undefined;
28653
+ const normalizedPriority = normalizePriority(priority);
28654
+ const normalizedEffort = normalizeEffort(effort);
28655
+ if (normalizedPriority && normalizedEffort) {
28656
+ proposals.push({
28657
+ title,
28658
+ priority: normalizedPriority,
28659
+ effort: normalizedEffort,
28660
+ description,
28661
+ currentState,
28662
+ inspiration
28663
+ });
28664
+ }
28665
+ }
28666
+ return proposals;
28667
+ }
28668
+ function extractField(text, fieldName) {
28669
+ const pattern = new RegExp(`\\*\\*${fieldName}\\*\\*\\s*:\\s*(.+?)(?:\\n|$)`, "i");
28670
+ const match = text.match(pattern);
28671
+ return match?.[1]?.trim() ?? "";
28672
+ }
28673
+ function normalizePriority(raw) {
28674
+ const upper = raw.toUpperCase().trim();
28675
+ if (upper.startsWith("P0"))
28676
+ return "P0";
28677
+ if (upper.startsWith("P1"))
28678
+ return "P1";
28679
+ if (upper.startsWith("P2"))
28680
+ return "P2";
28681
+ return null;
28682
+ }
28683
+ function normalizeEffort(raw) {
28684
+ const lower = raw.toLowerCase().trim();
28685
+ if (lower.startsWith("low"))
28686
+ return "Low";
28687
+ if (lower.startsWith("medium") || lower.startsWith("med"))
28688
+ return "Medium";
28689
+ if (lower.startsWith("high"))
28690
+ return "High";
28691
+ return null;
28692
+ }
28693
+ function createEvolveScoreTool() {
28694
+ return tool({
28695
+ description: `Score and rank evolve improvement proposals.
28696
+
28697
+ Takes the markdown output from an evolve scan (Phase 3 proposals) and returns scored, filtered results.
28698
+
28699
+ Scoring: priority_weight \xD7 effort_weight
28700
+ P0=10, P1=5, P2=1 | Low=3, Medium=2, High=1
28701
+ Best: P0+Low=30 | Worst: P2+High=1
28702
+
28703
+ Input must contain proposals in this format:
28704
+ ## Improvement: [Title]
28705
+ **Priority**: P0 / P1 / P2
28706
+ **Effort**: Low / Medium / High
28707
+ **Why**: [reason]
28708
+
28709
+ Example:
28710
+ evolve_score({ markdown: "## Improvement: Rate Limiting\\n**Priority**: P0\\n**Effort**: Low\\n**Why**: Prevents API overload" })`,
28711
+ args: {
28712
+ markdown: tool.schema.string().describe("Markdown containing evolve proposals (## Improvement: format)"),
28713
+ minScore: tool.schema.number().optional().describe("Minimum score to accept (default: 5)"),
28714
+ maxProposals: tool.schema.number().optional().describe("Max proposals to accept (default: 3)")
28715
+ },
28716
+ execute: async (args) => {
28717
+ const parsed = parseProposalsFromMarkdown(args.markdown);
28718
+ if (parsed.length === 0) {
28719
+ return `No proposals found. Ensure proposals use the format:
28720
+ ## Improvement: [Title]
28721
+ **Priority**: P0/P1/P2
28722
+ **Effort**: Low/Medium/High`;
28723
+ }
28724
+ const filtered = filterProposals(parsed, {
28725
+ minScore: args.minScore,
28726
+ maxProposals: args.maxProposals
28727
+ });
28728
+ const accepted = filtered.filter((p) => p.accepted);
28729
+ const rejected = filtered.filter((p) => !p.accepted);
28730
+ const lines = [];
28731
+ lines.push(`## Evolve Score Results (${parsed.length} parsed, ${accepted.length} accepted)`);
28732
+ lines.push("");
28733
+ if (accepted.length > 0) {
28734
+ lines.push("### Accepted (by score descending)");
28735
+ for (const p of accepted) {
28736
+ lines.push(`- **${p.title}** \u2014 score=${p.score} [${p.priority}/${p.effort}]`);
28737
+ if (p.description)
28738
+ lines.push(` ${p.description}`);
28739
+ }
28740
+ lines.push("");
28741
+ }
28742
+ if (rejected.length > 0) {
28743
+ lines.push("### Rejected");
28744
+ for (const p of rejected) {
28745
+ lines.push(`- **${p.title}** \u2014 score=${p.score} [${p.priority}/${p.effort}] \u2014 ${p.reason}`);
28746
+ }
28747
+ lines.push("");
28748
+ }
28749
+ lines.push("### Score Reference");
28750
+ lines.push("P0+Low=30 | P0+Med=20 | P0+High=10 | P1+Low=15 | P1+Med=10 | P1+High=5 | P2+Low=3 | P2+Med=2 | P2+High=1");
28751
+ return lines.join(`
28752
+ `);
28753
+ }
28754
+ });
28755
+ }
28756
+
28603
28757
  // src/hooks/todo-enforcer.ts
28604
28758
  var DEFAULT_MAX_ENFORCEMENTS = 5;
28605
28759
  var sessionState = new Map;
@@ -29135,6 +29289,9 @@ var OpenCodeUltra = async (ctx) => {
29135
29289
  if (!disabledTools.has("evolve_apply")) {
29136
29290
  toolRegistry.evolve_apply = evolveApply;
29137
29291
  }
29292
+ if (!disabledTools.has("evolve_score")) {
29293
+ toolRegistry.evolve_score = createEvolveScoreTool();
29294
+ }
29138
29295
  return {
29139
29296
  tool: toolRegistry,
29140
29297
  config: async (config3) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-ultra",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "Lightweight OpenCode 1.2.x plugin — ultrawork mode, multi-agent orchestration, rules injection",
5
5
  "keywords": [
6
6
  "opencode",