@hiai-gg/hiai-opencode 0.1.5 → 0.1.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.
Files changed (180) hide show
  1. package/.env.example +21 -8
  2. package/AGENTS.md +60 -6
  3. package/ARCHITECTURE.md +6 -3
  4. package/LICENSE.md +0 -1
  5. package/README.md +113 -33
  6. package/assets/cli/hiai-opencode.mjs +668 -7
  7. package/assets/mcp/mempalace.mjs +159 -25
  8. package/config/hiai-opencode.schema.json +29 -3
  9. package/dist/agents/agent-skills.d.ts +7 -0
  10. package/dist/agents/bob/default.d.ts +1 -0
  11. package/dist/agents/bob/gemini.d.ts +1 -0
  12. package/dist/agents/bob/gpt-pro.d.ts +1 -0
  13. package/dist/agents/brainstormer.d.ts +7 -0
  14. package/dist/agents/coder/gpt-codex.d.ts +1 -1
  15. package/dist/agents/coder/gpt-pro.d.ts +1 -0
  16. package/dist/agents/coder/gpt.d.ts +2 -1
  17. package/dist/agents/designer.d.ts +7 -0
  18. package/dist/agents/dynamic-agent-core-sections.d.ts +4 -1
  19. package/dist/agents/dynamic-agent-prompt-builder.d.ts +1 -1
  20. package/dist/agents/strategist/gemini.d.ts +1 -0
  21. package/dist/agents/strategist/gpt.d.ts +1 -0
  22. package/dist/agents/types.d.ts +3 -1
  23. package/dist/config/index.d.ts +0 -1
  24. package/dist/config/platform-schema.d.ts +34 -6
  25. package/dist/config/schema/commands.d.ts +1 -0
  26. package/dist/config/schema/hooks.d.ts +0 -2
  27. package/dist/config/schema/index.d.ts +0 -2
  28. package/dist/config/schema/oh-my-opencode-config.d.ts +1 -9
  29. package/dist/config/types.d.ts +4 -4
  30. package/dist/create-hooks.d.ts +0 -2
  31. package/dist/features/builtin-commands/templates/doctor.d.ts +1 -0
  32. package/dist/features/builtin-commands/types.d.ts +1 -1
  33. package/dist/features/builtin-skills/skills/hiai-opencode-setup.d.ts +2 -0
  34. package/dist/features/builtin-skills/skills/index.d.ts +2 -0
  35. package/dist/features/builtin-skills/skills/website-copywriting.d.ts +2 -0
  36. package/dist/hooks/agent-usage-reminder/constants.d.ts +1 -1
  37. package/dist/hooks/index.d.ts +0 -2
  38. package/dist/hooks/keyword-detector/ultrawork/default.d.ts +1 -1
  39. package/dist/hooks/keyword-detector/ultrawork/gemini.d.ts +1 -1
  40. package/dist/hooks/keyword-detector/ultrawork/gpt.d.ts +1 -1
  41. package/dist/hooks/keyword-detector/ultrawork/planner.d.ts +1 -1
  42. package/dist/index.js +7719 -153698
  43. package/dist/mcp/index.d.ts +0 -1
  44. package/dist/mcp/registry.d.ts +1 -1
  45. package/dist/plugin/hooks/create-core-hooks.d.ts +0 -2
  46. package/dist/plugin/hooks/create-session-hooks.d.ts +1 -3
  47. package/dist/plugin/startup-diagnostics.d.ts +1 -0
  48. package/dist/shared/logger.d.ts +2 -0
  49. package/dist/shared/mcp-static-export.d.ts +22 -0
  50. package/dist/shared/mode-routing.d.ts +6 -0
  51. package/dist/tools/ast-grep/constants.d.ts +1 -1
  52. package/dist/tools/ast-grep/environment-check.d.ts +1 -5
  53. package/dist/tools/ast-grep/language-support.d.ts +0 -1
  54. package/dist/tools/ast-grep/types.d.ts +1 -2
  55. package/dist/tools/delegate-task/git-categories.d.ts +2 -0
  56. package/dist/tools/delegate-task/sub-agent.d.ts +2 -0
  57. package/dist/tools/skill-mcp/constants.d.ts +1 -1
  58. package/hiai-opencode.json +50 -19
  59. package/package.json +10 -5
  60. package/src/agents/agent-skills.ts +70 -0
  61. package/src/agents/bob/default.ts +7 -1
  62. package/src/agents/bob/gemini.ts +1 -0
  63. package/src/agents/bob/gpt-pro.ts +3 -1
  64. package/src/agents/bob.ts +3 -0
  65. package/src/agents/brainstormer.ts +72 -0
  66. package/src/agents/builtin-agents.ts +59 -3
  67. package/src/agents/coder/gpt-codex.ts +5 -3
  68. package/src/agents/coder/gpt-pro.ts +4 -2
  69. package/src/agents/coder/gpt.ts +3 -1
  70. package/src/agents/critic/agent.ts +1 -0
  71. package/src/agents/designer.ts +70 -0
  72. package/src/agents/dynamic-agent-category-skills-guide.ts +6 -0
  73. package/src/agents/dynamic-agent-core-sections.ts +36 -0
  74. package/src/agents/dynamic-agent-prompt-builder.ts +1 -0
  75. package/src/agents/guard/default.ts +1 -0
  76. package/src/agents/guard/gemini.ts +1 -0
  77. package/src/agents/guard/gpt.ts +1 -0
  78. package/src/agents/platform-manager.ts +17 -1
  79. package/src/agents/prompt-library/platform.ts +34 -0
  80. package/src/agents/researcher.ts +1 -0
  81. package/src/agents/strategist/gemini.ts +1 -0
  82. package/src/agents/strategist/gpt.ts +1 -0
  83. package/src/agents/types.ts +4 -1
  84. package/src/agents/ui.ts +1 -0
  85. package/src/config/defaults.ts +45 -13
  86. package/src/config/index.ts +0 -1
  87. package/src/config/model-slots-and-export.test.ts +73 -0
  88. package/src/config/platform-schema.ts +3 -3
  89. package/src/config/schema/commands.ts +1 -0
  90. package/src/config/schema/hooks.ts +0 -2
  91. package/src/config/schema/index.ts +0 -2
  92. package/src/config/schema/oh-my-opencode-config.ts +0 -5
  93. package/src/config/types.ts +4 -4
  94. package/src/features/builtin-commands/commands.ts +7 -0
  95. package/src/features/builtin-commands/templates/doctor.ts +43 -0
  96. package/src/features/builtin-commands/types.ts +1 -1
  97. package/src/features/builtin-skills/skills/hiai-opencode-setup.ts +69 -0
  98. package/src/features/builtin-skills/skills/index.ts +2 -0
  99. package/src/features/builtin-skills/skills/website-copywriting.ts +41 -0
  100. package/src/features/builtin-skills/skills.test.ts +8 -0
  101. package/src/features/builtin-skills/skills.ts +12 -1
  102. package/src/features/skill-mcp-manager/AGENTS.md +1 -1
  103. package/src/hooks/agent-usage-reminder/constants.ts +4 -4
  104. package/src/hooks/index.ts +0 -2
  105. package/src/hooks/keyword-detector/ultrawork/default.ts +18 -18
  106. package/src/hooks/keyword-detector/ultrawork/gemini.ts +21 -21
  107. package/src/hooks/keyword-detector/ultrawork/gpt.ts +6 -8
  108. package/src/hooks/keyword-detector/ultrawork/planner.ts +5 -5
  109. package/src/index.ts +8 -78
  110. package/src/internals/plugins/subtask2/commands/manifest.ts +2 -6
  111. package/src/internals/plugins/subtask2/hooks/command-hooks.ts +2 -2
  112. package/src/internals/plugins/subtask2/hooks/message-hooks.ts +1 -1
  113. package/src/internals/plugins/subtask2/parsing/parallel.ts +13 -10
  114. package/src/mcp/index.ts +0 -1
  115. package/src/mcp/registry.ts +27 -0
  116. package/src/plugin/chat-message.ts +0 -2
  117. package/src/plugin/hooks/create-session-hooks.ts +0 -17
  118. package/src/plugin/startup-diagnostics.ts +27 -0
  119. package/src/plugin-handlers/agent-config-handler.ts +3 -2
  120. package/src/plugin-handlers/mcp-config-handler.test.ts +63 -0
  121. package/src/plugin-handlers/mcp-config-handler.ts +29 -14
  122. package/src/plugin-handlers/strategist-agent-config-builder.ts +1 -1
  123. package/src/shared/agent-display-names.test.ts +9 -0
  124. package/src/shared/agent-display-names.ts +5 -0
  125. package/src/shared/log-legacy-plugin-startup-warning.ts +6 -8
  126. package/src/shared/logger.ts +8 -0
  127. package/src/shared/mcp-static-export.ts +119 -0
  128. package/src/shared/migration/agent-names.ts +8 -0
  129. package/src/shared/migration/hook-names.ts +1 -1
  130. package/src/shared/mode-routing.test.ts +88 -0
  131. package/src/shared/mode-routing.ts +30 -0
  132. package/src/shared/startup-diagnostics.ts +6 -7
  133. package/src/tools/ast-grep/constants.ts +1 -1
  134. package/src/tools/ast-grep/environment-check.ts +2 -32
  135. package/src/tools/ast-grep/language-support.ts +0 -3
  136. package/src/tools/ast-grep/types.ts +1 -2
  137. package/src/tools/call-omo-agent/tools.ts +11 -4
  138. package/src/tools/delegate-task/anthropic-categories.ts +3 -3
  139. package/src/tools/delegate-task/builtin-categories.ts +2 -0
  140. package/src/tools/delegate-task/categories.test.ts +87 -0
  141. package/src/tools/delegate-task/category-resolver.ts +8 -9
  142. package/src/tools/delegate-task/git-categories.ts +30 -0
  143. package/src/tools/delegate-task/model-string-parser.test.ts +90 -0
  144. package/src/tools/delegate-task/openai-categories.ts +26 -22
  145. package/src/tools/delegate-task/sub-agent.ts +10 -0
  146. package/src/tools/delegate-task/subagent-discovery.test.ts +123 -0
  147. package/src/tools/delegate-task/subagent-resolver.ts +18 -1
  148. package/src/tools/skill-mcp/constants.ts +1 -1
  149. package/src/tools/skill-mcp/tools.test.ts +44 -0
  150. package/dist/ast-grep-napi.win32-x64-msvc-67c0y8nc.node +0 -0
  151. package/dist/config/loader.test.d.ts +0 -1
  152. package/dist/config/models.d.ts +0 -13
  153. package/dist/config/schema/websearch.d.ts +0 -13
  154. package/dist/hooks/no-bob-gpt/hook.d.ts +0 -16
  155. package/dist/hooks/no-bob-gpt/index.d.ts +0 -1
  156. package/dist/hooks/no-coder-non-gpt/hook.d.ts +0 -20
  157. package/dist/hooks/no-coder-non-gpt/index.d.ts +0 -1
  158. package/dist/internals/plugins/websearch-cited/google.d.ts +0 -38
  159. package/dist/internals/plugins/websearch-cited/index.d.ts +0 -17
  160. package/dist/internals/plugins/websearch-cited/openai.d.ts +0 -9
  161. package/dist/internals/plugins/websearch-cited/openrouter.d.ts +0 -2
  162. package/dist/internals/plugins/websearch-cited/types.d.ts +0 -5
  163. package/dist/mcp/grep-app.d.ts +0 -6
  164. package/dist/mcp/omo-mcp-index.d.ts +0 -10
  165. package/dist/mcp/websearch.d.ts +0 -11
  166. package/src/config/schema/websearch.ts +0 -15
  167. package/src/hooks/no-bob-gpt/hook.ts +0 -56
  168. package/src/hooks/no-bob-gpt/index.ts +0 -1
  169. package/src/hooks/no-coder-non-gpt/hook.ts +0 -67
  170. package/src/hooks/no-coder-non-gpt/index.ts +0 -1
  171. package/src/internals/plugins/websearch-cited/LICENSE +0 -214
  172. package/src/internals/plugins/websearch-cited/codex_prompt.txt +0 -79
  173. package/src/internals/plugins/websearch-cited/google.ts +0 -749
  174. package/src/internals/plugins/websearch-cited/index.ts +0 -306
  175. package/src/internals/plugins/websearch-cited/openai.ts +0 -407
  176. package/src/internals/plugins/websearch-cited/openrouter.ts +0 -190
  177. package/src/internals/plugins/websearch-cited/types.ts +0 -7
  178. package/src/mcp/grep-app.ts +0 -6
  179. package/src/mcp/omo-mcp-index.ts +0 -30
  180. package/src/mcp/websearch.ts +0 -44
@@ -1,4 +1,5 @@
1
1
  /**
2
+ * PROMPT_VERSION: 2026-04-26
2
3
  * GPT-Pro optimized Coder prompt - entropy-reduced rewrite.
3
4
  *
4
5
  * Design principles (aligned with OpenAI GPT-Pro prompting guidance):
@@ -51,6 +52,7 @@ export function buildCoderPrompt(
51
52
  availableAgents,
52
53
  availableTools,
53
54
  availableSkills,
55
+ { includeIntegrationPrimer: true },
54
56
  );
55
57
  const researcherSection = buildResearcherSection(availableAgents);
56
58
  const categorySkillsGuide = buildCategorySkillsDelegationGuide(
@@ -72,7 +74,7 @@ You build context by examining the codebase first without assumptions. You think
72
74
 
73
75
  You are autonomous. When you see work to do, do it - run tests, fix issues, make decisions. Course-correct only on concrete failure. State assumptions in your final message, not as questions along the way. If you commit to doing something ("I'll fix X"), execute it before ending your turn. When a user's question implies action, answer briefly and do the implied work in the same turn. If you find something, act on it - do not explain findings without acting on them. Plans are starting lines, not finish lines - if you wrote a plan, execute it before ending your turn.
74
76
 
75
- When blocked: try a different approach, decompose the problem, challenge your assumptions, explore how others solved it. Asking the user is a last resort after exhausting creative alternatives. If you need context, fire explore/librarian agents in background immediately and continue only with non-overlapping work while they search. Continue only with non-overlapping work after launching background agents. If you notice a potential issue along the way, fix it or note it in your final message - do not ask for permission.
77
+ When blocked: try a different approach, decompose the problem, challenge your assumptions, explore how others solved it. Asking the user is a last resort after exhausting creative alternatives. If you need context, fire researcher agents in background immediately and continue only with non-overlapping work while they search. Continue only with non-overlapping work after launching background agents. If you notice a potential issue along the way, fix it or note it in your final message - do not ask for permission.
76
78
 
77
79
  You handle multi-step sub-tasks of a single goal. What you receive is one goal that may require multiple steps - this is your primary use case. Only flag when given genuinely independent goals in one request.
78
80
  </identity>`;
@@ -157,7 +159,7 @@ Prefer tools over guessing whenever you need specific data (files, configs, patt
157
159
  Parallelize aggressively - this is where you gain the most speed and accuracy. Every independent operation should run simultaneously, not sequentially:
158
160
  - Multiple file reads: read 5 files at once, not one by one
159
161
  - Grep + file reads: search and read in the same turn
160
- - Multiple explore/librarian agents: fire 3-5 agents in parallel for different angles on the same question
162
+ - Multiple researcher agents: fire 3-5 agents in parallel for different angles on the same question
161
163
  - Agent fires + direct tool calls: launch background agents AND do direct reads simultaneously
162
164
 
163
165
  Fire 2-5 researcher agents in parallel for any non-trivial codebase question. Researcher agents always run in background (\`run_in_background=true\`). Never use \`run_in_background=false\` for researcher. After launching, continue only with non-overlapping work. Continue only with non-overlapping work after launching background agents. If nothing independent remains, end your response and wait for the completion notification.
@@ -1,4 +1,5 @@
1
- /** Generic GPT Coder prompt - fallback for GPT models without a model-specific variant */
1
+ /** PROMPT_VERSION: 2026-04-26
2
+ * Generic GPT Coder prompt - fallback for GPT models without a model-specific variant */
2
3
 
3
4
  import { GPT_APPLY_PATCH_GUIDANCE } from "../gpt-apply-patch-guard"
4
5
  import type {
@@ -32,6 +33,7 @@ export function buildCoderPrompt(
32
33
  availableAgents,
33
34
  availableTools,
34
35
  availableSkills,
36
+ { includeIntegrationPrimer: true },
35
37
  );
36
38
  const researcherSection = buildResearcherSection(availableAgents);
37
39
  const categorySkillsGuide = buildCategorySkillsDelegationGuide(
@@ -1,3 +1,4 @@
1
+ // PROMPT_VERSION: 2026-04-26
1
2
  import type { AgentConfig } from "@opencode-ai/sdk";
2
3
  import type { AgentMode, AgentPromptMetadata } from "../types";
3
4
 
@@ -0,0 +1,70 @@
1
+ // PROMPT_VERSION: 2026-04-26
2
+ import type { AgentConfig } from "@opencode-ai/sdk";
3
+ import type { AgentMode, AgentPromptMetadata } from "./types";
4
+ import { createAgentToolRestrictions } from "../shared/permission-compat";
5
+
6
+ const MODE: AgentMode = "subagent";
7
+
8
+ const DESIGNER_PROMPT = `
9
+ <identity>
10
+ You are Designer, the visual and UX specialist for HiaiOpenCode.
11
+ Your goal is crafting stunning UI/UX, design systems, and visual direction.
12
+ </identity>
13
+
14
+ <responsibilities>
15
+ - Visual direction: concept, art direction, layout, branding, design-system guidance
16
+ - UI feel: interaction patterns, hierarchy, visual coherence, polish beyond functional implementation
17
+ - Design-system work: tokens, typography, color, spacing, component patterns
18
+ - Frontend aesthetics review: taste, hierarchy, visual coherence
19
+ </responsibilities>
20
+
21
+ <instructions>
22
+ - Ask about target audience, product context, desired emotional tone when missing.
23
+ - Generate multiple visual directions with tradeoffs, then recommend one.
24
+ - Consider accessibility, brand consistency, and technical feasibility.
25
+ - When reviewing UI, focus on what makes it feel premium vs generic.
26
+ </instructions>
27
+ `;
28
+
29
+ export function createDesignerAgent(model: string): AgentConfig {
30
+ const restrictions = createAgentToolRestrictions([
31
+ "apply_patch",
32
+ "task",
33
+ ]);
34
+
35
+ return {
36
+ description: "Visual direction, UI/UX design, design systems, and frontend aesthetics. (Designer - HiaiOpenCode)",
37
+ mode: MODE,
38
+ model,
39
+ temperature: 0.7,
40
+ ...restrictions,
41
+ prompt: DESIGNER_PROMPT,
42
+ } as AgentConfig;
43
+ }
44
+ createDesignerAgent.mode = MODE;
45
+
46
+ export const designerPromptMetadata: AgentPromptMetadata = {
47
+ category: "specialist",
48
+ cost: "EXPENSIVE",
49
+ promptAlias: "Designer",
50
+ keyTrigger: "Visual direction, product UI feel, layout, branding, or design-system work → use designer/visual-engineering.",
51
+ triggers: [
52
+ {
53
+ domain: "Visual direction",
54
+ trigger: "Need UI concept, art direction, layout, branding, or design-system guidance",
55
+ },
56
+ {
57
+ domain: "Frontend aesthetics",
58
+ trigger: "Need polished interface design beyond functional implementation",
59
+ },
60
+ ],
61
+ useWhen: [
62
+ "Defining visual direction, layout, interaction feel, or design-system choices",
63
+ "Reviewing UI for taste, hierarchy, and visual coherence",
64
+ ],
65
+ avoidWhen: [
66
+ "Website copy or wording only (use Brainstormer/Writer)",
67
+ "Backend or infrastructure implementation",
68
+ "Pure file/media extraction (use Vision)",
69
+ ],
70
+ };
@@ -18,6 +18,8 @@ function buildSkillsSection(skills: AvailableSkill[]): string {
18
18
  if (customSkills.length > 0 && builtinSkills.length > 0) {
19
19
  return `#### Available Skills (via \`skill\` tool)
20
20
 
21
+ Skills are instruction packs, not agents. Do not look for \`strategist\`, \`critic\`, \`manager\`, or \`researcher\` here; call agents with \`task(subagent_type="...")\`.
22
+
21
23
  **Built-in**: ${builtinNames}
22
24
  **⚡ YOUR SKILLS (PRIORITY)**: ${customNames}
23
25
 
@@ -28,6 +30,8 @@ function buildSkillsSection(skills: AvailableSkill[]): string {
28
30
  if (customSkills.length > 0) {
29
31
  return `#### Available Skills (via \`skill\` tool)
30
32
 
33
+ Skills are instruction packs, not agents. Do not look for \`strategist\`, \`critic\`, \`manager\`, or \`researcher\` here; call agents with \`task(subagent_type="...")\`.
34
+
31
35
  **⚡ YOUR SKILLS (PRIORITY)**: ${customNames}
32
36
 
33
37
  > User-installed skills OVERRIDE built-in defaults. ALWAYS prefer YOUR SKILLS when domain matches.
@@ -37,6 +41,8 @@ function buildSkillsSection(skills: AvailableSkill[]): string {
37
41
  if (builtinSkills.length > 0) {
38
42
  return `#### Available Skills (via \`skill\` tool)
39
43
 
44
+ Skills are instruction packs, not agents. Do not look for \`strategist\`, \`critic\`, \`manager\`, or \`researcher\` here; call agents with \`task(subagent_type="...")\`.
45
+
40
46
  **Built-in**: ${builtinNames}
41
47
 
42
48
  > Full skill descriptions → use the \`skill\` tool to check before EVERY delegation.`
@@ -45,6 +45,7 @@ export function buildToolSelectionTable(
45
45
  agents: AvailableAgent[],
46
46
  tools: AvailableTool[] = [],
47
47
  _skills: AvailableSkill[] = [],
48
+ options: { includeIntegrationPrimer?: boolean } = {},
48
49
  ): string {
49
50
  const rows: string[] = ["### Tool & Agent Selection:", ""]
50
51
 
@@ -72,10 +73,45 @@ export function buildToolSelectionTable(
72
73
  rows.push(
73
74
  "**Default flow**: researcher (background) + tools → strategist (if required) → critic (high-risk gate)",
74
75
  )
76
+ if (options.includeIntegrationPrimer) {
77
+ rows.push("")
78
+ rows.push(buildHiaiIntegrationPrimerSection())
79
+ }
75
80
 
76
81
  return rows.join("\n")
77
82
  }
78
83
 
84
+ export function buildHiaiIntegrationPrimerSection(): string {
85
+ return `<hiai-opencode-integration-primer>
86
+ ## hiai-opencode Architecture And Integration Rules
87
+
88
+ This workspace may use hiai-opencode, an OpenCode plugin that wires agents, skills, MCP launchers, LSP, diagnostics, and compatibility helpers around external upstream tools.
89
+
90
+ Core rules:
91
+ - OpenCode plugins are not MCP servers. Keep \`@hiai-gg/hiai-opencode\` and optional \`@tarquinen/opencode-dcp\` in the OpenCode plugin list; never add MCP packages such as \`firecrawl-mcp\`, \`@playwright/mcp\`, or \`@modelcontextprotocol/server-sequential-thinking\` to the plugin list.
92
+ - User-facing config lives in \`hiai-opencode.json\` or \`.opencode/hiai-opencode.json\`: 10 model slots, MCP enable flags, LSP enable flags, service auth placeholders, and skill discovery switches.
93
+ - Model provider credentials are configured through OpenCode Connect. Do not ask for \`OPENROUTER_API_KEY\`, \`OPENAI_API_KEY\`, or \`ANTHROPIC_API_KEY\` for normal model usage.
94
+ - Service keys are separate: \`FIRECRAWL_API_KEY\`, \`STITCH_AI_API_KEY\`, \`CONTEXT7_API_KEY\`, and \`OPENCODE_RAG_URL\` when those services are enabled.
95
+
96
+ MCP usage:
97
+ - Run \`hiai-opencode doctor\` or \`hiai-opencode mcp-status\` for effective runtime MCP status.
98
+ - \`opencode mcp list\` often reads only static \`.mcp.json\`; plugin runtime MCP may work even when that list is empty.
99
+ - The plugin auto-exports \`.mcp.json\` when missing. Run \`hiai-opencode export-mcp .mcp.json\` to refresh static visibility.
100
+ - \`skill_mcp\` can call skill-embedded MCP and enabled hiai-opencode MCP. If an MCP is "not found", check whether the skill was loaded, whether \`hiai-opencode.json\` enables it, and whether static export is needed.
101
+
102
+ Memory and retrieval:
103
+ - MemPalace MCP is external. If enabled, use \`mempalace_status\` first, search before answering about remembered people/projects/past decisions, and write diary entries when appropriate. Never invent memories.
104
+ - RAG MCP is external/local. Use it for project knowledge search when \`OPENCODE_RAG_URL\` is configured or the default \`http://localhost:9002/tools/search\` is reachable.
105
+ - Sequential Thinking MCP is for complex planning/revision/branching, not for trivial edits.
106
+ - Firecrawl/Stitch/Context7 are external web/docs/research services; missing service keys should be reported by env var name only.
107
+
108
+ Installation/debugging:
109
+ - Use \`/doctor\` or \`hiai-opencode doctor\` before changing config.
110
+ - Prefer user-level or project-local installs. Do not use sudo/admin rights unless explicitly requested.
111
+ - If DCP is requested, install it separately with \`opencode plugin @tarquinen/opencode-dcp@latest --global\`.
112
+ </hiai-opencode-integration-primer>`
113
+ }
114
+
79
115
  export function buildResearcherSection(agents: AvailableAgent[]): string {
80
116
  const researcherAgent = agents.find((agent) => agent.name === "researcher")
81
117
  if (!researcherAgent) {
@@ -13,6 +13,7 @@ export {
13
13
  buildToolSelectionTable,
14
14
  buildResearcherSection,
15
15
  buildDelegationTable,
16
+ buildHiaiIntegrationPrimerSection,
16
17
  buildStrategistAndCriticSection,
17
18
  buildNonClaudePlannerSection,
18
19
  buildParallelDelegationSection,
@@ -1,3 +1,4 @@
1
+ // PROMPT_VERSION: 2026-04-26
1
2
  import { buildGuardPrompt } from "./shared-prompt"
2
3
  import {
3
4
  DEFAULT_ATLAS_INTRO,
@@ -1,3 +1,4 @@
1
+ // PROMPT_VERSION: 2026-04-26
1
2
  import { buildGuardPrompt } from "./shared-prompt"
2
3
  import {
3
4
  GEMINI_ATLAS_INTRO,
@@ -1,3 +1,4 @@
1
+ // PROMPT_VERSION: 2026-04-26
1
2
  import { buildGuardPrompt } from "./shared-prompt"
2
3
  import {
3
4
  GPT_ATLAS_INTRO,
@@ -1,3 +1,4 @@
1
+ // PROMPT_VERSION: 2026-04-26
1
2
  import type { AgentConfig } from "@opencode-ai/sdk";
2
3
  import type { AgentMode, AgentPromptMetadata } from "./types";
3
4
  import { createAgentToolRestrictions } from "../shared/permission-compat";
@@ -15,7 +16,7 @@ export function createPlatformManagerAgent(model: string): AgentConfig {
15
16
 
16
17
  return {
17
18
  description:
18
- "Unified platform management agent for session continuity, project initialization, and mindmodel orchestration. (Manager - HiaiOpenCode)",
19
+ "Project memory steward for MemPalace, RAG handoff notes, TODO hygiene, session continuity, project initialization, and mindmodel orchestration. (Manager - HiaiOpenCode)",
19
20
  mode: MODE,
20
21
  model,
21
22
  temperature: 0.2,
@@ -31,6 +32,18 @@ export const platformManagerPromptMetadata: AgentPromptMetadata = {
31
32
  cost: "CHEAP",
32
33
  promptAlias: "Manager",
33
34
  triggers: [
35
+ {
36
+ domain: "Memory maintenance",
37
+ trigger: "Need to write durable decisions to MemPalace, avoid duplicates, or update project memory",
38
+ },
39
+ {
40
+ domain: "Architecture knowledge sync",
41
+ trigger: "Architecture decisions changed and MemPalace/RAG state should be updated",
42
+ },
43
+ {
44
+ domain: "TODO hygiene",
45
+ trigger: "Need completed items marked, stale tasks collapsed, or handoff state cleaned",
46
+ },
34
47
  {
35
48
  domain: "Session management",
36
49
  trigger: "Need to preserve session state or create continuity ledgers",
@@ -47,6 +60,9 @@ export const platformManagerPromptMetadata: AgentPromptMetadata = {
47
60
  useWhen: [
48
61
  "At beginning of session for project initialization",
49
62
  "At end of session for ledger creation",
63
+ "After durable architecture, product, or workflow decisions",
64
+ "When TODO/task lists need cleanup or completion status reconciliation",
65
+ "When MemPalace or RAG state must be checked or refreshed",
50
66
  "When mindmodel update is requested",
51
67
  "For rapid codebase discovery during bootstrapping",
52
68
  ],
@@ -13,6 +13,40 @@ You are the Unified Platform Manager, responsible for orchestration, session con
13
13
  You consolidate the capabilities of the Ledger Creator, Bootstrapper, Project Initializer, and Mindmodel Orchestrator.
14
14
  </Platform_Manager_Identity>
15
15
 
16
+ <Memory_And_Knowledge_Stewardship>
17
+ ## Mode: Memory, RAG, and Task Hygiene
18
+
19
+ You are the durable project memory steward. Your job is to keep only decision-grade knowledge current, not to dump transcripts.
20
+
21
+ ### MemPalace protocol
22
+ - Start memory work with \`mempalace_status\` when the MemPalace MCP is available.
23
+ - Search before writing: use \`mempalace_search\` or related read tools to avoid duplicates.
24
+ - Write only durable facts: architectural decisions, accepted tradeoffs, project conventions, long-lived TODO ownership, release decisions, and important user preferences.
25
+ - Do not write noise: transient debugging attempts, failed commands without lasting lesson, repeated summaries, raw chat logs, or obvious file diffs.
26
+ - When facts change, invalidate or update old knowledge instead of appending conflicting facts.
27
+ - Prefer AAAK-style concise entries: actor, artifact, action, knowledge, timestamp/context.
28
+ - Use diary entries for session summaries only when they contain decisions or handoff-relevant state.
29
+
30
+ ### RAG protocol
31
+ - Treat the bundled RAG MCP as retrieval-first unless its configured endpoint exposes write/upsert tools.
32
+ - When architecture decisions change, first store the durable decision in MemPalace.
33
+ - If a RAG write/upsert capability is available, sync the same decision-level summary there.
34
+ - If RAG is search-only, report "RAG sync pending/search-only" rather than pretending it was updated.
35
+
36
+ ### TODO and task hygiene
37
+ - Verify active TODO/task lists before closure.
38
+ - Mark completed items as completed; do not leave finished work as pending.
39
+ - Preserve unfinished work with owner, next action, and blocker.
40
+ - Remove or collapse stale duplicate TODOs.
41
+ - Before final response, provide a short ledger: memory updated, RAG updated or pending, TODO state clean or remaining.
42
+
43
+ ### When to run Manager
44
+ - Session start: load current memory and identify stale/important project state.
45
+ - After architecture/design decisions: update MemPalace and, when possible, RAG.
46
+ - Before handoff/final closure: clean TODO state and write a concise memory checkpoint.
47
+ - During long work: periodically consolidate only durable decisions.
48
+ </Memory_And_Knowledge_Stewardship>
49
+
16
50
  <Capability_Ledger>
17
51
  ## Mode: Session Continuity (Ledger)
18
52
  ${ledger}
@@ -1,3 +1,4 @@
1
+ // PROMPT_VERSION: 2026-04-26
1
2
  import type { AgentConfig } from "@opencode-ai/sdk";
2
3
  import type { AgentMode, AgentPromptMetadata } from "./types";
3
4
  import { createAgentToolRestrictions } from "../shared/permission-compat";
@@ -1,4 +1,5 @@
1
1
  /**
2
+ * PROMPT_VERSION: 2026-04-26
2
3
  * Gemini-optimized Strategist System Prompt
3
4
  *
4
5
  * Key differences from Claude/GPT variants:
@@ -1,4 +1,5 @@
1
1
  /**
2
+ * PROMPT_VERSION: 2026-04-26
2
3
  * GPT-5.4 Optimized Strategist System Prompt
3
4
  *
4
5
  * Tuned for GPT-5.4 system prompt design principles:
@@ -66,8 +66,11 @@ export interface AgentPromptMetadata {
66
66
  /** Nickname/alias used in prompt (e.g., "Logician" instead of "logician") */
67
67
  promptAlias?: string;
68
68
 
69
- /** Key triggers that should appear in Phase 0 (e.g., "External library mentioned → fire librarian") */
69
+ /** Key triggers that should appear in Phase 0 (e.g., "External library mentioned → fire researcher") */
70
70
  keyTrigger?: string;
71
+
72
+ /** Prompt version for snapshot tracking (format: YYYY-MM-DD) */
73
+ promptVersion?: string;
71
74
  }
72
75
 
73
76
  function extractModelName(model: string): string {
package/src/agents/ui.ts CHANGED
@@ -1,3 +1,4 @@
1
+ // PROMPT_VERSION: 2026-04-26
1
2
  import type { AgentConfig } from "@opencode-ai/sdk"
2
3
  import type { AgentMode, AgentPromptMetadata } from "./types"
3
4
  import { createAgentToolAllowlist } from "../shared/permission-compat"
@@ -20,6 +20,7 @@ const REQUIRED_MODEL_SLOTS = [
20
20
  "manager",
21
21
  "brainstormer",
22
22
  "vision",
23
+ "sub",
23
24
  ] as const
24
25
 
25
26
  type ModelSlot = (typeof REQUIRED_MODEL_SLOTS)[number]
@@ -109,24 +110,29 @@ function deriveAgents(models: Record<ModelSlot, string>): HiaiOpencodeConfig["ag
109
110
  "platform-manager": { model: models.manager },
110
111
  brainstormer: { model: models.brainstormer },
111
112
  multimodal: { model: models.vision },
112
- sub: { model: models.coder },
113
+ sub: { model: models.sub },
113
114
  "quality-guardian": { model: models.critic },
114
115
  "agent-skills": { model: models.manager },
115
116
  }
116
117
  }
117
118
 
118
- function deriveCategories(models: Record<ModelSlot, string>): HiaiOpencodeConfig["categories"] {
119
- return {
120
- "visual-engineering": { model: models.designer, variant: "high" },
121
- artistry: { model: models.designer, variant: "high" },
122
- ultrabrain: { model: models.strategist, variant: "xhigh" },
123
- deep: { model: models.coder, variant: "medium" },
124
- quick: { model: models.researcher },
125
- writing: { model: models.brainstormer },
126
- git: { model: models.manager },
127
- "unspecified-low": { model: models.coder },
128
- "unspecified-high": { model: models.bob, variant: "max" },
119
+ function deriveCategories(models: Record<ModelSlot, string>): Record<string, import("./types").CategoryConfig> {
120
+ const categories: Record<string, import("./types").CategoryConfig> = {}
121
+ const entries: [string, Record<string, unknown>][] = [
122
+ ["visual-engineering", { variant: "high" }],
123
+ ["artistry", { variant: "high" }],
124
+ ["ultrabrain", { variant: "xhigh" }],
125
+ ["deep", { variant: "medium" }],
126
+ ["quick", {}],
127
+ ["writing", {}],
128
+ ["git", {}],
129
+ ["unspecified-low", {}],
130
+ ["unspecified-high", { variant: "max" }],
131
+ ]
132
+ for (const [name, cfg] of entries) {
133
+ categories[name] = cfg as import("./types").CategoryConfig
129
134
  }
135
+ return categories
130
136
  }
131
137
 
132
138
  function deriveMcp(config: HiaiOpencodeConfig): HiaiOpencodeConfig["mcp"] {
@@ -135,7 +141,33 @@ function deriveMcp(config: HiaiOpencodeConfig): HiaiOpencodeConfig["mcp"] {
135
141
  return Object.fromEntries(
136
142
  Object.entries(defaults).map(([name, entry]) => {
137
143
  const override = userMcp[name] ?? {}
138
- return [name, { ...entry, ...override }]
144
+ const merged = { ...entry, ...override }
145
+
146
+ if (name === "mempalace" && typeof merged.pythonPath === "string" && merged.pythonPath.trim()) {
147
+ merged.environment = {
148
+ ...(entry.environment ?? {}),
149
+ ...(merged.environment ?? {}),
150
+ MEMPALACE_PYTHON: merged.pythonPath.trim(),
151
+ }
152
+ }
153
+
154
+ if (name === "websearch") {
155
+ const provider = merged.provider === "tavily" ? "tavily" : "exa"
156
+ merged.provider = provider
157
+ merged.type = "remote"
158
+ if (provider === "tavily") {
159
+ merged.url = "https://mcp.tavily.com/mcp/"
160
+ merged.headers = { Authorization: "Bearer {env:TAVILY_API_KEY}" }
161
+ } else {
162
+ merged.url = "https://mcp.exa.ai/mcp?tools=web_search_exa"
163
+ merged.headers = { "x-api-key": "{env:EXA_API_KEY}" }
164
+ }
165
+ }
166
+
167
+ // Internal launcher hint; do not leak unknown keys into final OpenCode MCP server config.
168
+ delete merged.pythonPath
169
+
170
+ return [name, merged]
139
171
  }),
140
172
  )
141
173
  }
@@ -62,5 +62,4 @@ export type { RalphLoopConfig } from "./schema/ralph-loop.js";
62
62
  export type { DynamicContextPruningConfig } from "./schema/dynamic-context-pruning.js";
63
63
  export type { GitMasterConfig } from "./schema/git-master.js";
64
64
  export type { ModelCapabilitiesConfig } from "./schema/model-capabilities.js";
65
- export type { WebsearchConfig, WebsearchProvider } from "./schema/websearch.js";
66
65
  export type { FastApplyConfig } from "./schema/fast-apply.js";
@@ -0,0 +1,73 @@
1
+ import { expect, test } from "bun:test"
2
+
3
+ import { applyModelSlots } from "./defaults"
4
+ import type { HiaiOpencodeConfig } from "./types"
5
+ import { buildStaticMcpJson, MCP_EXPORT_MARKER } from "../shared/mcp-static-export"
6
+ import { buildHiaiIntegrationPrimerSection } from "../agents/dynamic-agent-core-sections"
7
+
8
+ const baseConfig: HiaiOpencodeConfig = {
9
+ models: {
10
+ bob: { model: "openrouter/test/bob", recommended: "xhigh" },
11
+ coder: { model: "openrouter/test/coder", recommended: "high" },
12
+ strategist: { model: "openrouter/test/strategist", recommended: "high" },
13
+ guard: { model: "openrouter/test/guard", recommended: "middle" },
14
+ critic: { model: "openrouter/test/critic", recommended: "high" },
15
+ designer: { model: "openrouter/test/designer", recommended: "design" },
16
+ researcher: { model: "openrouter/test/researcher", recommended: "fast" },
17
+ manager: { model: "openrouter/test/manager", recommended: "fast" },
18
+ brainstormer: { model: "openrouter/test/brainstormer", recommended: "writing" },
19
+ vision: { model: "openrouter/test/vision", recommended: "vision" },
20
+ sub: { model: "openrouter/test/sub", recommended: "fast" },
21
+ },
22
+ mcp: {
23
+ mempalace: { enabled: true, pythonPath: "/opt/venv/bin/python" },
24
+ },
25
+ }
26
+
27
+ test("model slots derive canonical agents and categories", () => {
28
+ const resolved = applyModelSlots(baseConfig)
29
+ expect(resolved.agents?.bob?.model).toBe("openrouter/test/bob")
30
+ expect(resolved.agents?.coder?.model).toBe("openrouter/test/coder")
31
+ expect(resolved.agents?.["platform-manager"]?.model).toBe("openrouter/test/manager")
32
+ expect(resolved.agents?.sub?.model).toBe("openrouter/test/sub")
33
+ expect(resolved.categories?.artistry?.variant).toBe("high")
34
+ expect(resolved.categories?.ultrabrain?.variant).toBe("xhigh")
35
+ expect(resolved.categories?.deep?.variant).toBe("medium")
36
+ expect(resolved.categories?.quick).toBeDefined()
37
+ expect(resolved.categories?.writing).toBeDefined()
38
+ expect(resolved.categories?.git).toBeDefined()
39
+ })
40
+
41
+ test("compact MCP mempalace pythonPath is materialized into environment", () => {
42
+ const resolved = applyModelSlots(baseConfig)
43
+ expect(resolved.mcp?.mempalace?.environment?.MEMPALACE_PYTHON).toBe("/opt/venv/bin/python")
44
+ })
45
+
46
+ test("static MCP export includes marker metadata and servers", () => {
47
+ const resolved = applyModelSlots(baseConfig)
48
+ const exported = buildStaticMcpJson(resolved)
49
+
50
+ expect(exported._meta?.generatedBy).toBe(MCP_EXPORT_MARKER)
51
+ expect(exported._meta?.version).toBe(1)
52
+ expect(exported.mcpServers.playwright).toBeDefined()
53
+ expect(exported.mcpServers.mempalace).toBeDefined()
54
+ expect(exported.mcpServers.websearch).toBeDefined()
55
+ expect(exported.mcpServers.grep_app).toBeDefined()
56
+ })
57
+
58
+ test("websearch MCP provider is selected from the MCP switchboard", () => {
59
+ const resolved = applyModelSlots({
60
+ ...baseConfig,
61
+ mcp: {
62
+ websearch: { enabled: true, provider: "tavily" },
63
+ },
64
+ })
65
+
66
+ expect(resolved.mcp?.websearch?.url).toBe("https://mcp.tavily.com/mcp/")
67
+ expect(resolved.mcp?.websearch?.headers?.Authorization).toBe("Bearer {env:TAVILY_API_KEY}")
68
+ })
69
+
70
+ test("integration primer does not request model provider API keys", () => {
71
+ const primer = buildHiaiIntegrationPrimerSection()
72
+ expect(primer).toContain("Do not ask for `OPENROUTER_API_KEY`, `OPENAI_API_KEY`, or `ANTHROPIC_API_KEY`")
73
+ })
@@ -37,6 +37,7 @@ export const ModelSlotsConfigSchema = z.object({
37
37
  manager: ModelSlotConfigSchema.optional(),
38
38
  brainstormer: ModelSlotConfigSchema.optional(),
39
39
  vision: ModelSlotConfigSchema.optional(),
40
+ sub: ModelSlotConfigSchema.optional(),
40
41
  });
41
42
 
42
43
  export const FallbackEntrySchema = z.object({
@@ -71,11 +72,13 @@ export const CategoryConfigSchema = z.object({
71
72
  export const McpServerConfigSchema = z.object({
72
73
  enabled: z.boolean().default(true),
73
74
  type: z.enum(["remote", "local"]).optional(),
75
+ provider: z.enum(["exa", "tavily"]).optional(),
74
76
  url: z.string().optional(),
75
77
  headers: z.record(z.string(), z.string()).optional(),
76
78
  command: z.array(z.string()).optional(),
77
79
  timeout: z.number().optional(),
78
80
  environment: z.record(z.string(), z.string()).optional(),
81
+ pythonPath: z.string().optional(),
79
82
  });
80
83
 
81
84
  export const LspServerConfigSchema = z.object({
@@ -129,9 +132,6 @@ export const PermissionsConfigSchema = z.object({
129
132
  });
130
133
 
131
134
  export const AuthKeysSchema = z.object({
132
- googleSearch: z.string().optional(),
133
- openai: z.string().optional(),
134
- openrouter: z.string().optional(),
135
135
  stitch: z.string().optional(),
136
136
  firecrawl: z.string().optional(),
137
137
  context7: z.string().optional(),
@@ -10,6 +10,7 @@ export const BuiltinCommandNameSchema = z.enum([
10
10
  "stop-continuation",
11
11
  "remove-ai-slops",
12
12
  "mcp-status",
13
+ "doctor",
13
14
  ])
14
15
 
15
16
  export type BuiltinCommandName = z.infer<typeof BuiltinCommandNameSchema>
@@ -38,8 +38,6 @@ export const HookNameSchema = z.enum([
38
38
  "delegate-task-retry",
39
39
  "strategist-md-only",
40
40
  "sub-notepad",
41
- "no-bob-gpt",
42
- "no-coder-non-gpt",
43
41
  "start-work",
44
42
  "guard",
45
43
  "unstable-agent-babysitter",
@@ -50,5 +50,3 @@ export { StartWorkConfigSchema } from "./start-work"
50
50
  export type { StartWorkConfig } from "./start-work"
51
51
  export { TmuxConfigSchema, TmuxLayoutSchema, TmuxIsolationSchema } from "./tmux"
52
52
  export type { TmuxConfig, TmuxLayout, TmuxIsolation } from "./tmux"
53
- export { WebsearchConfigSchema } from "./websearch"
54
- export type { WebsearchConfig, WebsearchProvider } from "./websearch"
@@ -23,12 +23,8 @@ import { BobAgentConfigSchema } from "./bob-agent"
23
23
  import { TmuxConfigSchema } from "./tmux"
24
24
  import { StartWorkConfigSchema } from "./start-work"
25
25
  import { FastApplyConfigSchema } from "./fast-apply"
26
- import { WebsearchConfigSchema } from "./websearch"
27
26
 
28
27
  const AuthConfigSchema = z.object({
29
- googleSearch: z.string().optional(),
30
- openai: z.string().optional(),
31
- openrouter: z.string().optional(),
32
28
  stitch: z.string().optional(),
33
29
  firecrawl: z.string().optional(),
34
30
  context7: z.string().optional(),
@@ -81,7 +77,6 @@ export const HiaiOpenCodeConfigSchema = z.object({
81
77
  git_env_prefix: "GIT_MASTER=1",
82
78
  }),
83
79
  browser_automation_engine: BrowserAutomationConfigSchema.optional(),
84
- websearch: WebsearchConfigSchema.optional(),
85
80
  tmux: TmuxConfigSchema.optional(),
86
81
  "bob": BobConfigSchema.optional(),
87
82
  start_work: StartWorkConfigSchema.optional(),
@@ -34,6 +34,7 @@ export interface ModelSlotsConfig {
34
34
  manager?: ModelSlotConfig;
35
35
  brainstormer?: ModelSlotConfig;
36
36
  vision?: ModelSlotConfig;
37
+ sub?: ModelSlotConfig;
37
38
  }
38
39
 
39
40
  // Canonical 12-agent model exposed by schema/default config.
@@ -136,7 +137,7 @@ export interface HeuristicModelFamilyDefinition {
136
137
  }
137
138
 
138
139
  export interface CategoryConfig {
139
- model: string;
140
+ model?: string;
140
141
  variant?: string;
141
142
  description?: string;
142
143
  fallbackChain?: FallbackEntry[];
@@ -145,11 +146,13 @@ export interface CategoryConfig {
145
146
  export interface McpServerConfig {
146
147
  enabled: boolean;
147
148
  type?: "remote" | "local";
149
+ provider?: "exa" | "tavily";
148
150
  url?: string;
149
151
  headers?: Record<string, string>;
150
152
  command?: string[];
151
153
  timeout?: number;
152
154
  environment?: Record<string, string>;
155
+ pythonPath?: string;
153
156
  }
154
157
 
155
158
  export interface LspServerConfig {
@@ -187,9 +190,6 @@ export interface PermissionsConfig {
187
190
  }
188
191
 
189
192
  export interface AuthKeys {
190
- googleSearch?: string;
191
- openai?: string;
192
- openrouter?: string;
193
193
  stitch?: string;
194
194
  firecrawl?: string;
195
195
  context7?: string;