opencode-ultra 0.7.2 → 0.7.3

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 +157 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -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.3",
4
4
  "description": "Lightweight OpenCode 1.2.x plugin — ultrawork mode, multi-agent orchestration, rules injection",
5
5
  "keywords": [
6
6
  "opencode",