micode 0.4.1 → 0.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
@@ -16,14 +16,12 @@ var brainstormerAgent = {
16
16
  mode: "primary",
17
17
  model: "anthropic/claude-opus-4-5",
18
18
  temperature: 0.7,
19
- tools: { ask: true },
20
19
  prompt: `<purpose>
21
20
  Turn ideas into fully formed designs through natural collaborative dialogue.
22
21
  This is DESIGN ONLY. The planner agent handles detailed implementation plans.
23
22
  </purpose>
24
23
 
25
24
  <critical-rules>
26
- <rule>ASK TOOL: Use the ask tool for EVERY question to the user. Never ask in plain text.</rule>
27
25
  <rule>NO CODE: Never write code. Never provide code examples. Design only.</rule>
28
26
  <rule>SUBAGENTS: Spawn multiple in parallel for codebase analysis.</rule>
29
27
  <rule>TOOLS (grep, read, etc.): Do NOT use directly - use subagents instead.</rule>
@@ -54,8 +52,6 @@ This is DESIGN ONLY. The planner agent handles detailed implementation plans.
54
52
  - codebase-analyzer: "Analyze existing [related feature]"
55
53
  - pattern-finder: "Find patterns for [similar functionality]"
56
54
  </spawn-example>
57
- <rule>Use the ask tool for EVERY question - never plain text</rule>
58
- <rule>Always provide MULTIPLE CHOICE options in the ask tool</rule>
59
55
  <focus>purpose, constraints, success criteria</focus>
60
56
  </phase>
61
57
 
@@ -91,9 +87,7 @@ This is DESIGN ONLY. The planner agent handles detailed implementation plans.
91
87
  <principle name="design-only">NO CODE. Describe components, not implementations. Planner writes code.</principle>
92
88
  <principle name="subagents-first">ALWAYS use subagents for code analysis, NEVER tools directly</principle>
93
89
  <principle name="parallel-spawn">Spawn multiple subagents in a SINGLE message</principle>
94
- <principle name="ask-tool-always">ALWAYS use the ask tool for questions - never plain text</principle>
95
- <principle name="one-question">Ask ONE question at a time via ask tool. Wait for answer.</principle>
96
- <principle name="multiple-choice">Present 3-5 options in ask tool questions</principle>
90
+ <principle name="one-question">Ask ONE question at a time. Wait for answer.</principle>
97
91
  <principle name="yagni">Remove unnecessary features from ALL designs</principle>
98
92
  <principle name="explore-alternatives">ALWAYS propose 2-3 approaches before settling</principle>
99
93
  <principle name="incremental-validation">Present in sections, validate each before proceeding</principle>
@@ -865,10 +859,6 @@ If you want exception to ANY rule, STOP and get explicit permission first.
865
859
  Breaking the letter or spirit of the rules is failure.
866
860
  </rule>
867
861
 
868
- <rule priority="critical">
869
- ALWAYS use the ask tool when you need user input. Never ask questions in plain text.
870
- </rule>
871
-
872
862
  <values>
873
863
  <value>Honesty. If you lie, you'll be replaced.</value>
874
864
  <value>Do it right, not fast. Never skip steps or take shortcuts.</value>
@@ -884,8 +874,6 @@ ALWAYS use the ask tool when you need user input. Never ask questions in plain t
884
874
  <rule>If uncomfortable pushing back, say "Strange things are afoot at the Circle K"</rule>
885
875
  <rule>STOP and ask for clarification rather than making assumptions</rule>
886
876
  <rule>STOP and ask for help when human input would be valuable</rule>
887
- <rule>ALWAYS use the ask tool when asking questions - never plain text</rule>
888
- <rule>Provide multiple-choice options in the ask tool whenever possible</rule>
889
877
  </relationship>
890
878
 
891
879
  <proactiveness>
@@ -967,8 +955,7 @@ var primaryAgent = {
967
955
  budgetTokens: 32000
968
956
  },
969
957
  maxTokens: 64000,
970
- prompt: PROMPT,
971
- tools: { ask: true }
958
+ prompt: PROMPT
972
959
  };
973
960
  var PRIMARY_AGENT_NAME = process.env.OPENCODE_AGENT_NAME || "commander";
974
961
 
@@ -13838,6 +13825,69 @@ ${output}`;
13838
13825
  }
13839
13826
  });
13840
13827
 
13828
+ // src/tools/btca/index.ts
13829
+ var {spawn: spawn2, which: which2 } = globalThis.Bun;
13830
+ async function checkBtcaAvailable() {
13831
+ const btcaPath = which2("btca");
13832
+ if (btcaPath) {
13833
+ return { available: true };
13834
+ }
13835
+ return {
13836
+ available: false,
13837
+ message: `btca CLI not found. Library source code search will not work.
13838
+ ` + `Install from: https://github.com/anthropics/btca
13839
+ ` + " cargo install btca"
13840
+ };
13841
+ }
13842
+ var BTCA_TIMEOUT_MS = 120000;
13843
+ async function runBtca(args) {
13844
+ try {
13845
+ const proc = spawn2(["btca", ...args], {
13846
+ stdout: "pipe",
13847
+ stderr: "pipe"
13848
+ });
13849
+ const timeoutPromise = new Promise((_, reject) => {
13850
+ setTimeout(() => {
13851
+ proc.kill();
13852
+ reject(new Error("btca command timed out after 2 minutes"));
13853
+ }, BTCA_TIMEOUT_MS);
13854
+ });
13855
+ const [stdout, stderr, exitCode] = await Promise.race([
13856
+ Promise.all([new Response(proc.stdout).text(), new Response(proc.stderr).text(), proc.exited]),
13857
+ timeoutPromise
13858
+ ]);
13859
+ if (exitCode !== 0) {
13860
+ const errorMsg = stderr.trim() || `Exit code ${exitCode}`;
13861
+ return { output: "", error: errorMsg };
13862
+ }
13863
+ return { output: stdout.trim() };
13864
+ } catch (e) {
13865
+ const err = e;
13866
+ if (err.message?.includes("ENOENT")) {
13867
+ return {
13868
+ output: "",
13869
+ error: `btca CLI not found. Install from: https://github.com/anthropics/btca
13870
+ ` + " cargo install btca"
13871
+ };
13872
+ }
13873
+ return { output: "", error: err.message };
13874
+ }
13875
+ }
13876
+ var btca_ask = tool({
13877
+ description: "Ask questions about library/framework source code using btca. " + "Clones repos locally and searches source code to answer questions. " + "Use for understanding library internals, finding implementation details, or debugging.",
13878
+ args: {
13879
+ tech: tool.schema.string().describe("Resource name configured in btca (e.g., 'react', 'express')"),
13880
+ question: tool.schema.string().describe("Question to ask about the library source code")
13881
+ },
13882
+ execute: async (args) => {
13883
+ const result = await runBtca(["ask", "-t", args.tech, "-q", args.question]);
13884
+ if (result.error) {
13885
+ return `Error: ${result.error}`;
13886
+ }
13887
+ return result.output || "No answer found";
13888
+ }
13889
+ });
13890
+
13841
13891
  // src/tools/look-at.ts
13842
13892
  import { readFileSync, statSync } from "fs";
13843
13893
  import { extname, basename } from "path";
@@ -14862,20 +14912,22 @@ function createTokenAwareTruncationHook(ctx) {
14862
14912
  };
14863
14913
  }
14864
14914
 
14865
- // src/hooks/context-window-monitor.ts
14866
- var WARNING_THRESHOLD = 0.7;
14867
- var CRITICAL_THRESHOLD = 0.85;
14868
- var DEFAULT_CONTEXT_LIMIT2 = 200000;
14915
+ // src/utils/model-limits.ts
14869
14916
  var MODEL_CONTEXT_LIMITS = {
14870
14917
  "claude-opus": 200000,
14871
14918
  "claude-sonnet": 200000,
14872
14919
  "claude-haiku": 200000,
14920
+ "claude-3": 200000,
14921
+ "claude-4": 200000,
14922
+ "gpt-4o": 128000,
14923
+ "gpt-4-turbo": 128000,
14873
14924
  "gpt-4": 128000,
14874
14925
  "gpt-5": 200000,
14875
14926
  o1: 200000,
14876
14927
  o3: 200000,
14877
14928
  gemini: 1e6
14878
14929
  };
14930
+ var DEFAULT_CONTEXT_LIMIT2 = 200000;
14879
14931
  function getContextLimit(modelID) {
14880
14932
  const modelLower = modelID.toLowerCase();
14881
14933
  for (const [pattern, limit] of Object.entries(MODEL_CONTEXT_LIMITS)) {
@@ -14885,6 +14937,10 @@ function getContextLimit(modelID) {
14885
14937
  }
14886
14938
  return DEFAULT_CONTEXT_LIMIT2;
14887
14939
  }
14940
+
14941
+ // src/hooks/context-window-monitor.ts
14942
+ var WARNING_THRESHOLD = 0.7;
14943
+ var CRITICAL_THRESHOLD = 0.85;
14888
14944
  var WARNING_COOLDOWN_MS = 120000;
14889
14945
  function createContextWindowMonitorHook(ctx) {
14890
14946
  const state = {
@@ -15163,33 +15219,9 @@ function createFileOpsTrackerHook(_ctx) {
15163
15219
  }
15164
15220
 
15165
15221
  // src/hooks/auto-clear-ledger.ts
15166
- var MODEL_CONTEXT_LIMITS2 = {
15167
- "claude-opus": 200000,
15168
- "claude-sonnet": 200000,
15169
- "claude-haiku": 200000,
15170
- "claude-3": 200000,
15171
- "claude-4": 200000,
15172
- "gpt-4o": 128000,
15173
- "gpt-4-turbo": 128000,
15174
- "gpt-4": 128000,
15175
- "gpt-5": 200000,
15176
- o1: 200000,
15177
- o3: 200000,
15178
- gemini: 1e6
15179
- };
15180
- var DEFAULT_CONTEXT_LIMIT3 = 200000;
15181
15222
  var DEFAULT_THRESHOLD = 0.8;
15182
15223
  var MIN_TOKENS_FOR_CLEAR = 50000;
15183
15224
  var CLEAR_COOLDOWN_MS = 60000;
15184
- function getContextLimit2(modelID) {
15185
- const modelLower = modelID.toLowerCase();
15186
- for (const [pattern, limit] of Object.entries(MODEL_CONTEXT_LIMITS2)) {
15187
- if (modelLower.includes(pattern)) {
15188
- return limit;
15189
- }
15190
- }
15191
- return DEFAULT_CONTEXT_LIMIT3;
15192
- }
15193
15225
  function createAutoClearLedgerHook(ctx) {
15194
15226
  const state = {
15195
15227
  lastClearTime: new Map,
@@ -15224,7 +15256,7 @@ function createAutoClearLedgerHook(ctx) {
15224
15256
  if (totalUsed < MIN_TOKENS_FOR_CLEAR)
15225
15257
  return;
15226
15258
  const model = modelID || info?.modelID || "";
15227
- const contextLimit = getContextLimit2(model);
15259
+ const contextLimit = getContextLimit(model);
15228
15260
  const usageRatio = totalUsed / contextLimit;
15229
15261
  if (usageRatio < DEFAULT_THRESHOLD)
15230
15262
  return;
@@ -15923,6 +15955,10 @@ var OpenCodeConfigPlugin = async (ctx) => {
15923
15955
  if (!astGrepStatus.available) {
15924
15956
  console.warn(`[micode] ${astGrepStatus.message}`);
15925
15957
  }
15958
+ const btcaStatus = await checkBtcaAvailable();
15959
+ if (!btcaStatus.available) {
15960
+ console.warn(`[micode] ${btcaStatus.message}`);
15961
+ }
15926
15962
  const userConfig = await loadMicodeConfig();
15927
15963
  if (userConfig?.agents) {
15928
15964
  console.log(`[micode] Loaded model overrides for: ${Object.keys(userConfig.agents).join(", ")}`);
@@ -15944,6 +15980,7 @@ var OpenCodeConfigPlugin = async (ctx) => {
15944
15980
  tool: {
15945
15981
  ast_grep_search,
15946
15982
  ast_grep_replace,
15983
+ btca_ask,
15947
15984
  look_at,
15948
15985
  artifact_search,
15949
15986
  ...backgroundTaskTools
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Check if btca CLI is available on the system.
3
+ * Returns installation instructions if not found.
4
+ */
5
+ export declare function checkBtcaAvailable(): Promise<{
6
+ available: boolean;
7
+ message?: string;
8
+ }>;
9
+ export declare const btca_ask: {
10
+ description: string;
11
+ args: {
12
+ tech: import("zod").ZodString;
13
+ question: import("zod").ZodString;
14
+ };
15
+ execute(args: {
16
+ tech: string;
17
+ question: string;
18
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
19
+ };
@@ -0,0 +1,7 @@
1
+ export declare const MODEL_CONTEXT_LIMITS: Record<string, number>;
2
+ export declare const DEFAULT_CONTEXT_LIMIT = 200000;
3
+ /**
4
+ * Get the context window limit for a given model ID.
5
+ * Matches against known patterns and falls back to default.
6
+ */
7
+ export declare function getContextLimit(modelID: string): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "micode",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "OpenCode plugin with Brainstorm-Research-Plan-Implement workflow",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",