@hiai-gg/hiai-opencode 0.1.6 → 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 (140) hide show
  1. package/.env.example +7 -0
  2. package/AGENTS.md +46 -1
  3. package/ARCHITECTURE.md +6 -3
  4. package/README.md +71 -10
  5. package/assets/cli/hiai-opencode.mjs +78 -0
  6. package/config/hiai-opencode.schema.json +16 -1
  7. package/dist/agents/agent-skills.d.ts +7 -0
  8. package/dist/agents/bob/default.d.ts +1 -0
  9. package/dist/agents/bob/gemini.d.ts +1 -0
  10. package/dist/agents/bob/gpt-pro.d.ts +1 -0
  11. package/dist/agents/brainstormer.d.ts +7 -0
  12. package/dist/agents/coder/gpt-codex.d.ts +1 -1
  13. package/dist/agents/coder/gpt-pro.d.ts +1 -0
  14. package/dist/agents/coder/gpt.d.ts +2 -1
  15. package/dist/agents/designer.d.ts +7 -0
  16. package/dist/agents/strategist/gemini.d.ts +1 -0
  17. package/dist/agents/strategist/gpt.d.ts +1 -0
  18. package/dist/agents/types.d.ts +3 -1
  19. package/dist/config/index.d.ts +0 -1
  20. package/dist/config/platform-schema.d.ts +32 -0
  21. package/dist/config/schema/hooks.d.ts +0 -2
  22. package/dist/config/schema/index.d.ts +0 -2
  23. package/dist/config/schema/oh-my-opencode-config.d.ts +0 -6
  24. package/dist/config/types.d.ts +3 -1
  25. package/dist/create-hooks.d.ts +0 -2
  26. package/dist/features/builtin-skills/skills/index.d.ts +1 -0
  27. package/dist/features/builtin-skills/skills/website-copywriting.d.ts +2 -0
  28. package/dist/hooks/agent-usage-reminder/constants.d.ts +1 -1
  29. package/dist/hooks/index.d.ts +0 -2
  30. package/dist/hooks/keyword-detector/ultrawork/default.d.ts +1 -1
  31. package/dist/hooks/keyword-detector/ultrawork/gemini.d.ts +1 -1
  32. package/dist/hooks/keyword-detector/ultrawork/gpt.d.ts +1 -1
  33. package/dist/hooks/keyword-detector/ultrawork/planner.d.ts +1 -1
  34. package/dist/index.js +8963 -153866
  35. package/dist/mcp/index.d.ts +0 -1
  36. package/dist/mcp/registry.d.ts +1 -1
  37. package/dist/plugin/hooks/create-core-hooks.d.ts +0 -2
  38. package/dist/plugin/hooks/create-session-hooks.d.ts +1 -3
  39. package/dist/plugin/startup-diagnostics.d.ts +1 -0
  40. package/dist/shared/logger.d.ts +2 -0
  41. package/dist/shared/mode-routing.d.ts +6 -0
  42. package/dist/tools/delegate-task/git-categories.d.ts +2 -0
  43. package/dist/tools/delegate-task/sub-agent.d.ts +2 -0
  44. package/dist/tools/skill-mcp/constants.d.ts +1 -1
  45. package/hiai-opencode.json +48 -19
  46. package/package.json +6 -3
  47. package/src/agents/agent-skills.ts +70 -0
  48. package/src/agents/bob/default.ts +1 -0
  49. package/src/agents/bob/gemini.ts +1 -0
  50. package/src/agents/bob/gpt-pro.ts +2 -1
  51. package/src/agents/bob.ts +2 -0
  52. package/src/agents/brainstormer.ts +72 -0
  53. package/src/agents/builtin-agents.ts +59 -3
  54. package/src/agents/coder/gpt-codex.ts +4 -3
  55. package/src/agents/coder/gpt-pro.ts +3 -2
  56. package/src/agents/coder/gpt.ts +2 -1
  57. package/src/agents/critic/agent.ts +1 -0
  58. package/src/agents/designer.ts +70 -0
  59. package/src/agents/dynamic-agent-category-skills-guide.ts +6 -0
  60. package/src/agents/guard/default.ts +1 -0
  61. package/src/agents/guard/gemini.ts +1 -0
  62. package/src/agents/guard/gpt.ts +1 -0
  63. package/src/agents/platform-manager.ts +17 -1
  64. package/src/agents/prompt-library/platform.ts +34 -0
  65. package/src/agents/researcher.ts +1 -0
  66. package/src/agents/strategist/gemini.ts +1 -0
  67. package/src/agents/strategist/gpt.ts +1 -0
  68. package/src/agents/types.ts +4 -1
  69. package/src/agents/ui.ts +1 -0
  70. package/src/config/defaults.ts +31 -12
  71. package/src/config/index.ts +0 -1
  72. package/src/config/model-slots-and-export.test.ts +22 -4
  73. package/src/config/platform-schema.ts +2 -0
  74. package/src/config/schema/hooks.ts +0 -2
  75. package/src/config/schema/index.ts +0 -2
  76. package/src/config/schema/oh-my-opencode-config.ts +0 -2
  77. package/src/config/types.ts +3 -1
  78. package/src/features/builtin-skills/skills/index.ts +1 -0
  79. package/src/features/builtin-skills/skills/website-copywriting.ts +41 -0
  80. package/src/features/builtin-skills/skills.test.ts +8 -0
  81. package/src/features/builtin-skills/skills.ts +2 -0
  82. package/src/features/skill-mcp-manager/AGENTS.md +1 -1
  83. package/src/hooks/agent-usage-reminder/constants.ts +4 -4
  84. package/src/hooks/index.ts +0 -2
  85. package/src/hooks/keyword-detector/ultrawork/default.ts +18 -18
  86. package/src/hooks/keyword-detector/ultrawork/gemini.ts +21 -21
  87. package/src/hooks/keyword-detector/ultrawork/gpt.ts +6 -8
  88. package/src/hooks/keyword-detector/ultrawork/planner.ts +5 -5
  89. package/src/index.ts +5 -3
  90. package/src/internals/plugins/subtask2/commands/manifest.ts +2 -6
  91. package/src/internals/plugins/subtask2/hooks/command-hooks.ts +2 -2
  92. package/src/internals/plugins/subtask2/hooks/message-hooks.ts +1 -1
  93. package/src/internals/plugins/subtask2/parsing/parallel.ts +13 -10
  94. package/src/mcp/index.ts +0 -1
  95. package/src/mcp/registry.ts +27 -0
  96. package/src/plugin/chat-message.ts +0 -2
  97. package/src/plugin/hooks/create-session-hooks.ts +0 -17
  98. package/src/plugin/startup-diagnostics.ts +27 -0
  99. package/src/plugin-handlers/agent-config-handler.ts +3 -2
  100. package/src/plugin-handlers/mcp-config-handler.test.ts +63 -0
  101. package/src/plugin-handlers/mcp-config-handler.ts +29 -14
  102. package/src/plugin-handlers/strategist-agent-config-builder.ts +1 -1
  103. package/src/shared/agent-display-names.test.ts +9 -0
  104. package/src/shared/agent-display-names.ts +5 -0
  105. package/src/shared/log-legacy-plugin-startup-warning.ts +6 -8
  106. package/src/shared/logger.ts +8 -0
  107. package/src/shared/mcp-static-export.ts +4 -6
  108. package/src/shared/migration/agent-names.ts +8 -0
  109. package/src/shared/migration/hook-names.ts +1 -1
  110. package/src/shared/mode-routing.test.ts +88 -0
  111. package/src/shared/mode-routing.ts +30 -0
  112. package/src/shared/startup-diagnostics.ts +6 -7
  113. package/src/tools/call-omo-agent/tools.ts +11 -4
  114. package/src/tools/delegate-task/anthropic-categories.ts +3 -3
  115. package/src/tools/delegate-task/builtin-categories.ts +2 -0
  116. package/src/tools/delegate-task/categories.test.ts +87 -0
  117. package/src/tools/delegate-task/category-resolver.ts +8 -9
  118. package/src/tools/delegate-task/git-categories.ts +30 -0
  119. package/src/tools/delegate-task/model-string-parser.test.ts +90 -0
  120. package/src/tools/delegate-task/openai-categories.ts +26 -22
  121. package/src/tools/delegate-task/sub-agent.ts +10 -0
  122. package/src/tools/delegate-task/subagent-discovery.test.ts +123 -0
  123. package/src/tools/delegate-task/subagent-resolver.ts +18 -1
  124. package/src/tools/skill-mcp/constants.ts +1 -1
  125. package/dist/config/schema/websearch.d.ts +0 -13
  126. package/dist/hooks/no-bob-gpt/hook.d.ts +0 -16
  127. package/dist/hooks/no-bob-gpt/index.d.ts +0 -1
  128. package/dist/hooks/no-coder-non-gpt/hook.d.ts +0 -20
  129. package/dist/hooks/no-coder-non-gpt/index.d.ts +0 -1
  130. package/dist/mcp/grep-app.d.ts +0 -6
  131. package/dist/mcp/omo-mcp-index.d.ts +0 -10
  132. package/dist/mcp/websearch.d.ts +0 -11
  133. package/src/config/schema/websearch.ts +0 -15
  134. package/src/hooks/no-bob-gpt/hook.ts +0 -56
  135. package/src/hooks/no-bob-gpt/index.ts +0 -1
  136. package/src/hooks/no-coder-non-gpt/hook.ts +0 -67
  137. package/src/hooks/no-coder-non-gpt/index.ts +0 -1
  138. package/src/mcp/grep-app.ts +0 -6
  139. package/src/mcp/omo-mcp-index.ts +0 -30
  140. package/src/mcp/websearch.ts +0 -44
@@ -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.`
@@ -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"] {
@@ -145,6 +151,19 @@ function deriveMcp(config: HiaiOpencodeConfig): HiaiOpencodeConfig["mcp"] {
145
151
  }
146
152
  }
147
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
+
148
167
  // Internal launcher hint; do not leak unknown keys into final OpenCode MCP server config.
149
168
  delete merged.pythonPath
150
169
 
@@ -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";
@@ -17,6 +17,7 @@ const baseConfig: HiaiOpencodeConfig = {
17
17
  manager: { model: "openrouter/test/manager", recommended: "fast" },
18
18
  brainstormer: { model: "openrouter/test/brainstormer", recommended: "writing" },
19
19
  vision: { model: "openrouter/test/vision", recommended: "vision" },
20
+ sub: { model: "openrouter/test/sub", recommended: "fast" },
20
21
  },
21
22
  mcp: {
22
23
  mempalace: { enabled: true, pythonPath: "/opt/venv/bin/python" },
@@ -28,10 +29,13 @@ test("model slots derive canonical agents and categories", () => {
28
29
  expect(resolved.agents?.bob?.model).toBe("openrouter/test/bob")
29
30
  expect(resolved.agents?.coder?.model).toBe("openrouter/test/coder")
30
31
  expect(resolved.agents?.["platform-manager"]?.model).toBe("openrouter/test/manager")
31
- expect(resolved.agents?.sub?.model).toBe("openrouter/test/coder")
32
- expect(resolved.categories?.artistry?.model).toBe("openrouter/test/designer")
33
- expect(resolved.categories?.ultrabrain?.model).toBe("openrouter/test/strategist")
34
- expect(resolved.categories?.writing?.model).toBe("openrouter/test/brainstormer")
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()
35
39
  })
36
40
 
37
41
  test("compact MCP mempalace pythonPath is materialized into environment", () => {
@@ -47,6 +51,20 @@ test("static MCP export includes marker metadata and servers", () => {
47
51
  expect(exported._meta?.version).toBe(1)
48
52
  expect(exported.mcpServers.playwright).toBeDefined()
49
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}")
50
68
  })
51
69
 
52
70
  test("integration primer does not request model provider API keys", () => {
@@ -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,6 +72,7 @@ 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(),
@@ -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,7 +23,6 @@ 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
28
  stitch: z.string().optional(),
@@ -78,7 +77,6 @@ export const HiaiOpenCodeConfigSchema = z.object({
78
77
  git_env_prefix: "GIT_MASTER=1",
79
78
  }),
80
79
  browser_automation_engine: BrowserAutomationConfigSchema.optional(),
81
- websearch: WebsearchConfigSchema.optional(),
82
80
  tmux: TmuxConfigSchema.optional(),
83
81
  "bob": BobConfigSchema.optional(),
84
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,6 +146,7 @@ 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[];
@@ -6,3 +6,4 @@ export { devBrowserSkill } from "./dev-browser"
6
6
  export { reviewWorkSkill } from "./review-work"
7
7
  export { aiSlopRemoverSkill } from "./ai-slop-remover"
8
8
  export { hiaiOpencodeSetupSkill } from "./hiai-opencode-setup"
9
+ export { websiteCopywritingSkill } from "./website-copywriting"
@@ -0,0 +1,41 @@
1
+ import type { BuiltinSkill } from "../types"
2
+
3
+ export const websiteCopywritingSkill: BuiltinSkill = {
4
+ name: "website-copywriting",
5
+ description:
6
+ "Writes sharp website/product copy: landing pages, hero sections, CTAs, feature blocks, positioning, naming, and tone of voice.",
7
+ template: `# Website Copywriting
8
+
9
+ Use this skill for public-facing product and website text.
10
+
11
+ ## Inputs To Clarify
12
+
13
+ - Audience: who reads this and what do they already know?
14
+ - Goal: sign up, book demo, understand feature, trust product, recover from error, continue onboarding.
15
+ - Tone: precise, playful, premium, technical, calm, bold, founder-led, enterprise, developer-first.
16
+ - Proof: real features, constraints, metrics, customer pain, differentiators. Do not invent proof.
17
+
18
+ ## Output Shape
19
+
20
+ Prefer copy that can be pasted into UI:
21
+
22
+ - Hero: headline, subheadline, primary CTA, secondary CTA.
23
+ - Feature block: title, one-sentence value, 2-4 proof bullets.
24
+ - Section copy: heading, short intro, card titles, card bodies.
25
+ - Microcopy: button labels, empty states, errors, onboarding hints.
26
+ - Alternatives: 3-5 variants when tone or positioning is undecided.
27
+
28
+ ## Writing Rules
29
+
30
+ - Specific beats clever. Concrete verbs beat vague hype.
31
+ - Avoid generic AI language: seamless, unlock, supercharge, leverage, robust, cutting-edge, revolutionize, next-generation.
32
+ - Keep claims tied to actual capabilities.
33
+ - Use short lines for UI. Long paragraphs are usually wrong for websites.
34
+ - Preserve product vocabulary from the codebase/docs when available.
35
+ - If visual direction matters, pair with \`frontend-ui-ux\` or delegate visual work to Designer.
36
+
37
+ ## Delegation Hint
38
+
39
+ Use \`task(subagent_type="brainstormer", load_skills=["website-copywriting"], ...)\` for copy-only work.
40
+ Use \`category="writing"\` when a category is required. Writer/copywriter aliases map to Brainstormer.`,
41
+ }
@@ -0,0 +1,8 @@
1
+ import { expect, test } from "bun:test"
2
+
3
+ import { createBuiltinSkills } from "./skills"
4
+
5
+ test("website-copywriting is available as a builtin skill", () => {
6
+ const skills = createBuiltinSkills()
7
+ expect(skills.some((skill) => skill.name === "website-copywriting")).toBe(true)
8
+ })
@@ -11,6 +11,7 @@ import {
11
11
  reviewWorkSkill,
12
12
  aiSlopRemoverSkill,
13
13
  hiaiOpencodeSetupSkill,
14
+ websiteCopywritingSkill,
14
15
  } from "./skills/index"
15
16
 
16
17
  export interface CreateBuiltinSkillsOptions {
@@ -38,6 +39,7 @@ export function createBuiltinSkills(options: CreateBuiltinSkillsOptions = {}): B
38
39
  devBrowserSkill,
39
40
  reviewWorkSkill,
40
41
  aiSlopRemoverSkill,
42
+ websiteCopywritingSkill,
41
43
  ]
42
44
 
43
45
  if (!disabledSkills) {
@@ -10,7 +10,7 @@
10
10
 
11
11
  | Tier | Manager | Scope |
12
12
  |------|---------|-------|
13
- | 1. Built-in | `createBuiltinMcps()` (src/mcp/) | Global, 3 remote HTTP |
13
+ | 1. Platform defaults | `HIAI_MCP_REGISTRY` (src/mcp/registry.ts) | Global MCP defaults materialized from hiai-opencode.json |
14
14
  | 2. Claude Code | `claude-code-mcp-loader` (src/features/) | From `.mcp.json` |
15
15
  | 3. **Skill-embedded** | **`SkillMcpManager` (this module)** | **Per-session, from SKILL.md YAML** |
16
16
 
@@ -30,13 +30,13 @@ export const REMINDER_MESSAGE = `
30
30
 
31
31
  You called a search/fetch tool directly without leveraging specialized agents.
32
32
 
33
- RECOMMENDED: Use task with explore/librarian agents for better results:
33
+ RECOMMENDED: Use task with researcher agents for better results:
34
34
 
35
35
  \`\`\`
36
36
  // Parallel exploration - fire multiple agents simultaneously
37
- task(subagent_type="explore", load_skills=[], prompt="Find all files matching pattern X")
38
- task(subagent_type="explore", load_skills=[], prompt="Search for implementation of Y")
39
- task(subagent_type="librarian", load_skills=[], prompt="Lookup documentation for Z")
37
+ task(subagent_type="researcher", load_skills=[], prompt="Find all files matching pattern X")
38
+ task(subagent_type="researcher", load_skills=[], prompt="Search for implementation of Y")
39
+ task(subagent_type="researcher", load_skills=[], prompt="Lookup documentation for Z")
40
40
 
41
41
  // Then continue your work while they run in background
42
42
  // System will notify you when each completes
@@ -28,8 +28,6 @@ export { createThinkingBlockValidatorHook } from "./thinking-block-validator";
28
28
  export { createToolPairValidatorHook } from "./tool-pair-validator";
29
29
  export { createCategorySkillReminderHook } from "./category-skill-reminder";
30
30
  export { createRalphLoopHook, type RalphLoopHook } from "./ralph-loop";
31
- export { createNoBobGptHook } from "./no-bob-gpt";
32
- export { createNoCoderNonGptHook } from "./no-coder-non-gpt";
33
31
  export { createAutoSlashCommandHook } from "./auto-slash-command";
34
32
  export { createEditErrorRecoveryHook } from "./edit-error-recovery";
35
33
 
@@ -95,50 +95,50 @@ TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
95
95
 
96
96
  ## MANDATORY: PLAN AGENT INVOCATION (NON-NEGOTIABLE)
97
97
 
98
- **YOU MUST ALWAYS INVOKE THE PLAN AGENT FOR ANY NON-TRIVIAL TASK.**
98
+ **YOU MUST ALWAYS INVOKE THE STRATEGIST AGENT FOR ANY NON-TRIVIAL TASK.**
99
99
 
100
100
  | Condition | Action |
101
101
  |-----------|--------|
102
- | Task has 2+ steps | MUST call plan agent |
103
- | Task scope unclear | MUST call plan agent |
104
- | Implementation required | MUST call plan agent |
105
- | Architecture decision needed | MUST call plan agent |
102
+ | Task has 2+ steps | MUST call strategist agent |
103
+ | Task scope unclear | MUST call strategist agent |
104
+ | Implementation required | MUST call strategist agent |
105
+ | Architecture decision needed | MUST call strategist agent |
106
106
 
107
107
  \`\`\`
108
- task(subagent_type="plan", load_skills=[], run_in_background=false, prompt="<gathered context + user request>")
108
+ task(subagent_type="strategist", load_skills=[], run_in_background=false, prompt="<gathered context + user request>")
109
109
  \`\`\`
110
110
 
111
- **WHY PLAN AGENT IS MANDATORY:**
112
- - Plan agent analyzes dependencies and parallel execution opportunities
113
- - Plan agent outputs a **parallel task graph** with waves and dependencies
114
- - Plan agent provides structured TODO list with category + skills per task
111
+ **WHY STRATEGIST AGENT IS MANDATORY:**
112
+ - Strategist analyzes dependencies and parallel execution opportunities
113
+ - Strategist outputs a **parallel task graph** with waves and dependencies
114
+ - Strategist provides structured TODO list with category + skills per task
115
115
  - YOU are an orchestrator, NOT an implementer
116
116
 
117
- ### SESSION CONTINUITY WITH PLAN AGENT (CRITICAL)
117
+ ### SESSION CONTINUITY WITH STRATEGIST AGENT (CRITICAL)
118
118
 
119
- **Plan agent returns a session_id. USE IT for follow-up interactions.**
119
+ **Strategist agent returns a session_id. USE IT for follow-up interactions.**
120
120
 
121
121
  | Scenario | Action |
122
122
  |----------|--------|
123
- | Plan agent asks clarifying questions | \`task(session_id="{returned_session_id}", load_skills=[], run_in_background=false, prompt="<your answer>")\` |
123
+ | Strategist asks clarifying questions | \`task(session_id="{returned_session_id}", load_skills=[], run_in_background=false, prompt="<your answer>")\` |
124
124
  | Need to refine the plan | \`task(session_id="{returned_session_id}", load_skills=[], run_in_background=false, prompt="Please adjust: <feedback>")\` |
125
- | Plan needs more detail | \`task(session_id="{returned_session_id}", load_skills=[], run_in_background=false, prompt="Add more detail to Task N")\` |
125
+ | Strategist needs more detail | \`task(session_id="{returned_session_id}", load_skills=[], run_in_background=false, prompt="Add more detail to Task N")\` |
126
126
 
127
127
  **WHY SESSION_ID IS CRITICAL:**
128
- - Plan agent retains FULL conversation context
128
+ - Strategist retains FULL conversation context
129
129
  - No repeated exploration or context gathering
130
130
  - Saves 70%+ tokens on follow-ups
131
131
  - Maintains interview continuity until plan is finalized
132
132
 
133
133
  \`\`\`
134
134
  // WRONG: Starting fresh loses all context
135
- task(subagent_type="plan", load_skills=[], run_in_background=false, prompt="Here's more info...")
135
+ task(subagent_type="strategist", load_skills=[], run_in_background=false, prompt="Here's more info...")
136
136
 
137
137
  // CORRECT: Resume preserves everything
138
138
  task(session_id="ses_abc123", load_skills=[], run_in_background=false, prompt="Here's my answer to your question: ...")
139
139
  \`\`\`
140
140
 
141
- **FAILURE TO CALL PLAN AGENT = INCOMPLETE WORK.**
141
+ **FAILURE TO CALL STRATEGIST AGENT = INCOMPLETE WORK.**
142
142
 
143
143
  ---
144
144
 
@@ -150,7 +150,7 @@ task(session_id="ses_abc123", load_skills=[], run_in_background=false, prompt="H
150
150
  |-----------|--------|-----|
151
151
  | Codebase exploration | task(subagent_type="researcher", load_skills=[], run_in_background=true) | Parallel, context-efficient |
152
152
  | Documentation lookup | task(subagent_type="researcher", load_skills=[], run_in_background=true) | Specialized knowledge |
153
- | Planning | task(subagent_type="plan", load_skills=[], run_in_background=false) | Parallel task graph + structured TODO list |
153
+ | Planning | task(subagent_type="strategist", load_skills=[], run_in_background=false) | Parallel task graph + structured TODO list |
154
154
  | Hard problem (conventional) | task(subagent_type="strategist", load_skills=[], run_in_background=false) | Architecture, planning, complex logic |
155
155
  | Hard problem (review/debugging) | task(subagent_type="critic", load_skills=[], run_in_background=false) | Verification, debugging, high-risk review |
156
156
  | Hard problem (non-conventional) | task(category="artistry", load_skills=[...], run_in_background=true) | Different approach needed |