@kolisachint/hoocode-agent 0.5.30 → 0.5.32
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/CHANGELOG.md +234 -0
- package/dist/core/agent-selection-eval.d.ts +91 -0
- package/dist/core/agent-selection-eval.d.ts.map +1 -0
- package/dist/core/agent-selection-eval.js +186 -0
- package/dist/core/agent-selection-eval.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts +28 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +61 -2
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/builtin-skills.d.ts +61 -0
- package/dist/core/builtin-skills.d.ts.map +1 -0
- package/dist/core/builtin-skills.js +106 -0
- package/dist/core/builtin-skills.js.map +1 -0
- package/dist/core/extensions/plugins/default-marketplace/.agents-plugin/marketplace.json +5 -1
- package/dist/core/extensions/plugins/trigger-judge.d.ts +42 -0
- package/dist/core/extensions/plugins/trigger-judge.d.ts.map +1 -0
- package/dist/core/extensions/plugins/trigger-judge.js +121 -0
- package/dist/core/extensions/plugins/trigger-judge.js.map +1 -0
- package/dist/core/external-tools.d.ts +67 -0
- package/dist/core/external-tools.d.ts.map +1 -0
- package/dist/core/external-tools.js +120 -0
- package/dist/core/external-tools.js.map +1 -0
- package/dist/core/keybindings.d.ts +102 -30
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +123 -29
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/mode-prompts.d.ts +15 -3
- package/dist/core/mode-prompts.d.ts.map +1 -1
- package/dist/core/mode-prompts.js +17 -29
- package/dist/core/mode-prompts.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +1 -1
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +1 -1
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +19 -8
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +5 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tool-output-view.d.ts +33 -0
- package/dist/core/tool-output-view.d.ts.map +1 -0
- package/dist/core/tool-output-view.js +31 -0
- package/dist/core/tool-output-view.js.map +1 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +4 -0
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/propose-plugin.d.ts.map +1 -1
- package/dist/core/tools/propose-plugin.js +7 -7
- package/dist/core/tools/propose-plugin.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +7 -1
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +12 -24
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/extensions/core/modes.d.ts.map +1 -1
- package/dist/extensions/core/modes.js +21 -23
- package/dist/extensions/core/modes.js.map +1 -1
- package/dist/extensions/core/scaffold.d.ts.map +1 -1
- package/dist/extensions/core/scaffold.js +28 -24
- package/dist/extensions/core/scaffold.js.map +1 -1
- package/dist/init-templates.generated.d.ts +3 -0
- package/dist/init-templates.generated.d.ts.map +1 -1
- package/dist/init-templates.generated.js +12 -0
- package/dist/init-templates.generated.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +14 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/command-executor.d.ts +20 -0
- package/dist/modes/interactive/command-executor.d.ts.map +1 -1
- package/dist/modes/interactive/command-executor.js +138 -9
- package/dist/modes/interactive/command-executor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +4 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +31 -2
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +2 -2
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +2 -2
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +10 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +165 -23
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-chain-summary.d.ts +65 -0
- package/dist/modes/interactive/components/tool-chain-summary.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-chain-summary.js +216 -0
- package/dist/modes/interactive/components/tool-chain-summary.js.map +1 -0
- package/dist/modes/interactive/components/tool-chain.d.ts +61 -0
- package/dist/modes/interactive/components/tool-chain.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-chain.js +156 -0
- package/dist/modes/interactive/components/tool-chain.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +55 -9
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +173 -33
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-signal.d.ts +50 -0
- package/dist/modes/interactive/components/tool-signal.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-signal.js +151 -0
- package/dist/modes/interactive/components/tool-signal.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +50 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +244 -29
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/resource-display.d.ts +9 -0
- package/dist/modes/interactive/resource-display.d.ts.map +1 -1
- package/dist/modes/interactive/resource-display.js +13 -0
- package/dist/modes/interactive/resource-display.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +30 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +35 -0
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/modes.md +4 -0
- package/docs/plugins.md +10 -0
- package/docs/settings.md +42 -0
- package/docs/skills.md +30 -0
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +5 -4
- package/templates/prompts/grill-bridge.md +1 -0
- package/templates/prompts/grill-me.md +7 -0
- package/templates/prompts/grill-plan.md +9 -0
- package/templates/prompts/task-background-agents.md +2 -0
- package/templates/prompts/task-background-none.md +1 -0
- package/templates/prompts/task-main.md +19 -0
- package/templates/skills/plugin-authoring/SKILL.md +81 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modes.js","sourceRoot":"","sources":["../../../src/extensions/core/modes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mode system — resolves the active mode (ask/plan/build/debug), loads the\n * mode's system prompt, filters active tools, and exposes the /mode, /plan,\n * /grill, /goal, and /approve commands.\n *\n * Mode prompt search order (first hit wins):\n * - `./.hoocode/modes/{mode}/system.md`\n * - `~/.hoocode/modes/{mode}/system.md`\n * - each configured/contributed external dir in declared order\n * - built-in MODE_DEFAULTS for the four known modes\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { getHooCodeDir } from \"../../config.js\";\nimport type {\n\tBeforeAgentStartEvent,\n\tBeforeAgentStartEventResult,\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tSessionStartEvent,\n} from \"../../core/extensions/types.js\";\nimport { isLightModeEnv } from \"../../core/light.js\";\nimport { DEFAULT_MODE, DEFAULT_MODE_PROMPTS as MODE_DEFAULTS } from \"../../core/mode-prompts.js\";\nimport { mergeSearchPaths, readConfig, readMergedConfig, writeConfig } from \"./config.js\";\nimport { AUTO_LOOP_DONE_TOKEN, LOOP_AUTO_CHANGED, LOOP_AUTO_START, type LoopAutoStartPayload } from \"./loop.js\";\n\nconst HOOCODE_DIR = getHooCodeDir();\n\n/**\n * Per-session plan file path. Keying on sessionId lets concurrent or resumed\n * plan sessions keep distinct plans instead of clobbering each other.\n */\nfunction getPlanPath(cwd: string, sessionId: string): string {\n\treturn join(cwd, \".hoocode\", \"plans\", `${sessionId}.md`);\n}\n\n/** Legacy single-file plan location, retained as a read-only fallback for /approve. */\nfunction getLegacyPlanPath(cwd: string): string {\n\treturn join(cwd, \".hoocode\", \"plan.md\");\n}\n\nfunction tryReadFile(path: string): string | undefined {\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst text = readFileSync(path, \"utf8\").trim();\n\t\treturn text || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Outcome of reading the first usable plan file out of a candidate list. */\ntype PlanLoadResult =\n\t| { status: \"loaded\"; sections: PlanSections }\n\t| { status: \"missing\" }\n\t| { status: \"error\"; path: string };\n\n/**\n * Reads the first candidate plan file that exists and is non-empty, parsed into\n * sections. Missing and blank files fall through to the next candidate; an\n * unreadable one stops the walk so the caller can report the specific path.\n */\nfunction loadPlanSections(candidatePaths: string[]): PlanLoadResult {\n\tfor (const planPath of candidatePaths) {\n\t\tif (!existsSync(planPath)) continue;\n\t\ttry {\n\t\t\tconst raw = readFileSync(planPath, \"utf8\").trim();\n\t\t\tif (raw) return { status: \"loaded\", sections: parsePlanSections(raw) };\n\t\t} catch {\n\t\t\treturn { status: \"error\", path: planPath };\n\t\t}\n\t}\n\treturn { status: \"missing\" };\n}\n\n/**\n * Walks search dirs in precedence order and returns the first existing\n * `modes/{name}/system.md` content. Order: project → user → externalDirs.\n */\nfunction resolveModeFile(name: string, cwd: string, externalDirs: string[]): string | undefined {\n\tconst candidates: string[] = [\n\t\tjoin(cwd, \".hoocode\", \"modes\", name, \"system.md\"),\n\t\tjoin(HOOCODE_DIR, \"modes\", name, \"system.md\"),\n\t\t...externalDirs.map((dir) => join(dir, name, \"system.md\")),\n\t];\n\tfor (const candidate of candidates) {\n\t\tconst content = tryReadFile(candidate);\n\t\tif (content !== undefined) return content;\n\t}\n\treturn undefined;\n}\n\n/**\n * Returns the system prompt for the active mode.\n *\n * Search order (first hit wins):\n * - `./.hoocode/modes/{mode}/system.md`\n * - `~/.hoocode/modes/{mode}/system.md`\n * - each of `externalDirs` in declared order (config + CLI + extension contributions)\n * - built-in MODE_DEFAULTS for the four known modes\n */\nexport function buildSystemPrompt(mode: string, cwd: string, options?: { modePaths?: string[] }): string | undefined {\n\tconst modePaths = options?.modePaths ?? [];\n\treturn resolveModeFile(mode, cwd, modePaths) ?? MODE_DEFAULTS[mode];\n}\n\n// ============================================================================\n// Plan file: section parsing and step-by-step execution message\n// ============================================================================\n\nexport interface PlanSections {\n\tgoal?: string;\n\tfilesToModify?: string;\n\tnewFiles?: string;\n\ttests?: string;\n\tverification?: string;\n\t/** Original full text, used as fallback if no sections parsed */\n\traw: string;\n}\n\n/**\n * Parses `.hoocode/plan.md` into named sections.\n *\n * Recognises both ATX headings (`## Goal`) and bold labels (`**Goal**`).\n * Section names matched (case-insensitive): Goal, Files to modify, New files,\n * Tests, Verification.\n */\nexport function parsePlanSections(planContent: string): PlanSections {\n\tconst result: PlanSections = { raw: planContent };\n\n\t// Match `## Heading text` or `**Heading text**` followed by content until\n\t// the next heading of the same style.\n\tconst sectionPattern =\n\t\t/^(?:#{1,3}\\s+(.+?)|(?:\\*\\*(.+?)\\*\\*))\\s*\\n([\\s\\S]*?)(?=(?:^#{1,3}\\s+|\\*\\*[^*\\n]+\\*\\*\\s*\\n)|$)/gm;\n\n\tfor (const match of planContent.matchAll(sectionPattern)) {\n\t\tconst heading = (match[1] ?? match[2] ?? \"\").toLowerCase().trim();\n\t\tconst content = match[3].trim();\n\t\tif (!content) continue;\n\n\t\tif (/^goal/.test(heading)) {\n\t\t\tresult.goal = content;\n\t\t} else if (/files?\\s+to\\s+modif|^modif/.test(heading)) {\n\t\t\tresult.filesToModify = content;\n\t\t} else if (/new\\s+files?/.test(heading)) {\n\t\t\tresult.newFiles = content;\n\t\t} else if (/^tests?/.test(heading)) {\n\t\t\tresult.tests = content;\n\t\t} else if (/^verif/.test(heading)) {\n\t\t\tresult.verification = content;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Builds the user message sent to the agent when `/approve` is run.\n *\n * If the plan has recognisable sections, each is presented as a numbered step\n * so the agent works through them sequentially. Otherwise the raw plan is used.\n *\n * Execution order:\n * 1. Modify existing files\n * 2. Create new files\n * 3. Update / add tests\n * 4. Run verification commands\n */\nexport function buildApproveMessage(sections: PlanSections): string {\n\tconst steps: string[] = [];\n\n\tif (sections.goal) {\n\t\tsteps.push(`**Goal:** ${sections.goal}`);\n\t}\n\tif (sections.filesToModify) {\n\t\tsteps.push(`**Step 1 — Modify existing files:**\\n${sections.filesToModify}`);\n\t}\n\tif (sections.newFiles) {\n\t\tsteps.push(`**Step 2 — Create new files:**\\n${sections.newFiles}`);\n\t}\n\tif (sections.tests) {\n\t\tsteps.push(`**Step 3 — Update tests:**\\n${sections.tests}`);\n\t}\n\tif (sections.verification) {\n\t\tsteps.push(`**Step 4 — Verify:**\\n${sections.verification}`);\n\t}\n\n\tif (steps.length === 0) {\n\t\treturn `Execute the following plan:\\n\\n${sections.raw}`;\n\t}\n\n\treturn `Execute this plan step by step. Complete each step fully before moving to the next.\\n\\n${steps.join(\"\\n\\n\")}`;\n}\n\n// ============================================================================\n// Grill: plan interrogation\n// ============================================================================\n\n/** Which half (or both) of the grill flow to run. */\nexport type GrillTarget = \"both\" | \"me\" | \"plan\";\n\n/**\n * Parses the `/grill` argument into a target.\n *\n * Bare `/grill` runs both phases, `/grill me` only questions the user, and\n * `/grill plan` only critiques the plan. Anything else returns undefined so the\n * caller shows usage rather than guessing at intent.\n */\nexport function parseGrillTarget(args: string): GrillTarget | undefined {\n\tconst arg = args.trim().toLowerCase();\n\tif (!arg) return \"both\";\n\tif (arg === \"me\" || arg === \"plan\") return arg;\n\treturn undefined;\n}\n\n/**\n * Renders the parsed plan back into the message so the agent reviews a concrete\n * artifact rather than whatever it remembers writing. Falls back to the raw plan\n * text when no sections were recognised.\n */\nfunction renderPlanForReview(sections: PlanSections): string {\n\tconst parts: string[] = [];\n\tif (sections.goal) parts.push(`**Goal**\\n${sections.goal}`);\n\tif (sections.filesToModify) parts.push(`**Files to modify**\\n${sections.filesToModify}`);\n\tif (sections.newFiles) parts.push(`**New files**\\n${sections.newFiles}`);\n\tif (sections.tests) parts.push(`**Tests**\\n${sections.tests}`);\n\tif (sections.verification) parts.push(`**Verification**\\n${sections.verification}`);\n\treturn parts.length > 0 ? parts.join(\"\\n\\n\") : sections.raw;\n}\n\n/** Phase 1 — interrogate the request, surfacing unknowns as ask_options questions. */\nconst GRILL_ME_PROMPT = `You are interrogating the *request*, not writing code.\n\nRe-read the plan below and find where it rests on assumptions nobody confirmed: ambiguous requirements, unstated constraints, decisions you made silently because the request did not specify them, and places where a different reasonable reading of the request would produce a materially different plan.\n\nPut the most consequential of those to the user with the ask_options tool. Ask only what would actually change the plan — settle anything you can from the codebase or from convention yourself. Prefer two to four sharp questions over an exhaustive list, and mark a recommended option wherever you have a genuine preference.\n\nDo not edit files and do not revise the plan yet.`;\n\n/** Phase 2 — adversarial self-critique of the plan file. */\nconst GRILL_PLAN_PROMPT = `You are attacking the plan below, not executing it.\n\nReview it as a skeptical reviewer would:\n- Which steps rest on assumptions you have not verified in the codebase? Read the relevant files and verify them now.\n- Where could this fail silently — wrong-but-plausible behaviour rather than a loud error?\n- What does the goal require that the plan does not cover? What does the plan cover that the goal does not need?\n- Does the verification section prove the goal is met, or only that the code runs?\n\nReport what you find. Where a weakness is real, revise the plan file and state what changed. Where the plan holds up, say so plainly rather than inventing criticism. Do not implement anything.`;\n\n/**\n * Builds the follow-up message injected by `/grill`.\n *\n * The two phases are ordered rather than alternative: underspecification sits\n * upstream of plan weakness, so critiquing a plan built on a misread request\n * produces a well-reviewed plan for the wrong job. Bare `/grill` therefore asks\n * first and folds the answers into the critique.\n */\nexport function buildGrillMessage(sections: PlanSections, target: GrillTarget): string {\n\tconst plan = renderPlanForReview(sections);\n\tif (target === \"me\") return `${GRILL_ME_PROMPT}\\n\\n---\\n\\n${plan}`;\n\tif (target === \"plan\") return `${GRILL_PLAN_PROMPT}\\n\\n---\\n\\n${plan}`;\n\treturn (\n\t\t`${GRILL_ME_PROMPT}\\n\\n` +\n\t\t`Once the user has answered, fold their answers into the plan and immediately continue with this review:\\n\\n` +\n\t\t`${GRILL_PLAN_PROMPT}\\n\\n---\\n\\n${plan}`\n\t);\n}\n\n// ============================================================================\n// Goal: autonomous execution toward a completion condition\n// ============================================================================\n\n/** A parsed `/goal` invocation. */\nexport interface GoalInvocation {\n\t/** Explicit objective; falls back to the plan's Goal section when absent. */\n\tobjective?: string;\n\t/** Turn budget passed through to the autonomous loop. */\n\tmaxTurns?: number;\n}\n\n/**\n * Parses `/goal [--max-turns N] [objective]`.\n *\n * Returns undefined when `--max-turns` is present but not followed by a\n * non-negative integer, so the caller shows usage instead of silently running\n * with the default budget.\n */\nexport function parseGoalArgs(args: string): GoalInvocation | undefined {\n\tlet rest = args.trim();\n\tlet maxTurns: number | undefined;\n\n\tconst flag = /^--max-turns(?:\\s+(\\S+))?([\\s\\S]*)$/.exec(rest);\n\tif (flag) {\n\t\tconst raw = flag[1];\n\t\tif (!raw || !/^\\d+$/.test(raw)) return undefined;\n\t\tmaxTurns = Number(raw);\n\t\trest = flag[2].trim();\n\t}\n\n\treturn { objective: rest || undefined, maxTurns };\n}\n\n/** The two messages `/goal` hands to the autonomous loop. */\nexport interface GoalMessages {\n\t/** Delivered once, to start the run. */\n\ttask: string;\n\t/** Re-sent on each continuation to keep the target in view. */\n\tcontinuePrompt: string;\n}\n\n/**\n * Builds the messages for a `/goal` run.\n *\n * When the plan carries a Verification section it becomes the completion\n * condition, which is the difference between a loop that stops when it feels\n * finished and one that stops when something it can run says so. Both messages\n * restate the objective, because the loop's continuation prompt is all that\n * holds the target in place as the transcript grows.\n */\nexport function buildGoalMessages(objective: string, verification?: string): GoalMessages {\n\tconst condition = verification\n\t\t? `\\n\\nThe goal counts as complete only once this verification passes. Run it, and if it fails, fix what it reports and run it again:\\n\\n${verification}`\n\t\t: \"\";\n\n\treturn {\n\t\ttask: `Work autonomously toward this goal:\\n\\n${objective}${condition}`,\n\t\tcontinuePrompt:\n\t\t\t`Keep working toward the goal:\\n\\n${objective}${condition}\\n\\n` +\n\t\t\t`Reply with ${AUTO_LOOP_DONE_TOKEN} only when it is genuinely complete — not when it is merely close.`,\n\t};\n}\n\n// ============================================================================\n// setupMode\n// ============================================================================\n\nexport function setupMode(pi: ExtensionAPI): void {\n\tlet cachedMode = DEFAULT_MODE;\n\tlet cachedSystemPrompt: string | undefined;\n\tlet cachedPlanPath: string | undefined;\n\n\t// `/grill me` asks the user a question via ask_options, which an unattended\n\t// `/loop auto` run has nobody to answer. Track the loop's broadcast state so\n\t// the command can drop its interrogation phase instead of stalling the run.\n\tlet autoLoopActive = false;\n\tpi.events.on(LOOP_AUTO_CHANGED, (data) => {\n\t\tautoLoopActive = (data as { active?: boolean } | undefined)?.active === true;\n\t});\n\n\t// ── session_start ─────────────────────────────────────────────────────────\n\t// Config resolution order:\n\t// 1. Read global config (~/.hoocode/hoo-config.json)\n\t// 2. Read project config (./.hoocode/hoo-config.json) if present\n\t// 3. Merge — project scalars win; arrays are unioned\n\t// 4. Re-resolve active_mode from the merged result\n\n\tpi.on(\"session_start\", (_event: SessionStartEvent, ctx: ExtensionContext) => {\n\t\t// Light mode strips every fixed prompt appendix. Leaving\n\t\t// cachedSystemPrompt unset makes before_agent_start a no-op, so no\n\t\t// `<!-- hoo-core: mode= -->` block is appended.\n\t\tif (isLightModeEnv()) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Steps 1–3: merge global + project configs\n\t\tconst config = readMergedConfig(ctx.cwd);\n\n\t\t// Step 4: resolve mode from the merged config\n\t\tcachedMode = config.active_mode ?? DEFAULT_MODE;\n\t\t// External search dirs come from two channels:\n\t\t// - HooConfig.mode_paths (config-declared)\n\t\t// - pi.addModeSearchPath (CLI flags + extension contributions)\n\t\tconst modePaths = mergeSearchPaths(config.mode_paths, pi.getModeSearchPaths());\n\t\tconst rawSystemPrompt = buildSystemPrompt(cachedMode, ctx.cwd, { modePaths });\n\n\t\t// Per-session plan path so concurrent sessions don't overwrite each other.\n\t\t// The `{{PLAN_PATH}}` token in plan-mode templates is substituted here.\n\t\tcachedPlanPath = getPlanPath(ctx.cwd, ctx.sessionManager.getSessionId());\n\t\tconst relPlanPath = relative(ctx.cwd, cachedPlanPath) || cachedPlanPath;\n\t\tcachedSystemPrompt = rawSystemPrompt?.replace(/\\{\\{PLAN_PATH\\}\\}/g, relPlanPath);\n\n\t\t// Update footer with active mode\n\t\tif (ctx.hasUI) {\n\t\t\tctx.ui.setMode(cachedMode);\n\t\t}\n\n\t\t// Apply tool filter from mode enabled_tools\n\t\tconst modeCfg = config.modes?.[cachedMode];\n\t\tif (modeCfg?.enabled_tools && modeCfg.enabled_tools.length > 0) {\n\t\t\tpi.setActiveTools(modeCfg.enabled_tools);\n\t\t}\n\t});\n\n\t// ── before_agent_start ────────────────────────────────────────────────────\n\n\tpi.on(\"before_agent_start\", (event: BeforeAgentStartEvent): BeforeAgentStartEventResult | undefined => {\n\t\tif (!cachedSystemPrompt) return;\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n\\n<!-- hoo-core: mode=${cachedMode} -->\\n${cachedSystemPrompt}`,\n\t\t};\n\t});\n\n\t// ── /mode command ─────────────────────────────────────────────────────────\n\n\tconst KNOWN_MODES = [\"ask\", \"plan\", \"build\", \"debug\"];\n\n\tpi.registerCommand(\"mode\", {\n\t\tdescription: \"Switch active mode. Usage: /mode <ask|plan|build|debug>\",\n\t\tgetArgumentCompletions: (prefix: string) =>\n\t\t\tKNOWN_MODES.filter((m) => m.startsWith(prefix)).map((m) => ({ value: m, label: m })),\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tif (!name) {\n\t\t\t\tctx.ui.notify(`Active mode: ${cachedMode}`, \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst config = readConfig();\n\t\t\tconfig.active_mode = name === DEFAULT_MODE ? undefined : name;\n\t\t\twriteConfig(config);\n\t\t\tctx.ui.notify(`Mode set to \"${name}\" — reloading…`, \"info\");\n\t\t\tawait ctx.reload();\n\t\t},\n\t});\n\n\t// ── /plan command (shorthand for /mode plan) ──────────────────────────────\n\n\tpi.registerCommand(\"plan\", {\n\t\tdescription: \"Switch to plan mode. Shorthand for /mode plan.\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (_args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst config = readConfig();\n\t\t\tconfig.active_mode = \"plan\";\n\t\t\twriteConfig(config);\n\t\t\tctx.ui.notify(`Mode set to \"plan\" — reloading…`, \"info\");\n\t\t\tawait ctx.reload();\n\t\t},\n\t});\n\n\t// ── /grill command ────────────────────────────────────────────────────────\n\t// Stress-tests the current plan in two phases: `me` surfaces the request's\n\t// unconfirmed assumptions as ask_options questions, `plan` critiques the plan\n\t// file itself. Unlike /approve this only injects a follow-up message — no\n\t// session switch, no mode change, no config write.\n\n\tpi.registerCommand(\"grill\", {\n\t\tdescription: \"Stress-test the current plan. Usage: /grill [me|plan]\",\n\t\tgetArgumentCompletions: (prefix: string) =>\n\t\t\t[\"me\", \"plan\"].filter((s) => s.startsWith(prefix)).map((s) => ({ value: s, label: s })),\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst requested = parseGrillTarget(args);\n\t\t\tif (!requested) {\n\t\t\t\tctx.ui.notify(\"Usage: /grill [me|plan]\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Same lookup as /approve: per-session plan first, legacy file second.\n\t\t\tconst sessionPlanPath = cachedPlanPath ?? getPlanPath(ctx.cwd, ctx.sessionManager.getSessionId());\n\t\t\tconst loaded = loadPlanSections([sessionPlanPath, getLegacyPlanPath(ctx.cwd)]);\n\t\t\tif (loaded.status === \"error\") {\n\t\t\t\tctx.ui.notify(`Could not read ${relative(ctx.cwd, loaded.path) || loaded.path}`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (loaded.status === \"missing\") {\n\t\t\t\tconst relPlan = relative(ctx.cwd, sessionPlanPath) || sessionPlanPath;\n\t\t\t\tctx.ui.notify(`No plan to grill — ${relPlan} not found. Run /plan first.`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Nobody is present to answer during an autonomous loop, so keep the\n\t\t\t// half of the flow that still works rather than blocking on a question.\n\t\t\tlet target = requested;\n\t\t\tif (autoLoopActive && target !== \"plan\") {\n\t\t\t\ttarget = \"plan\";\n\t\t\t\tctx.ui.notify(\"Autonomous loop active — grilling the plan only, skipping questions.\", \"info\");\n\t\t\t}\n\n\t\t\tpi.sendUserMessage(buildGrillMessage(loaded.sections, target), { deliverAs: \"followUp\" });\n\t\t},\n\t});\n\n\t// ── /goal command ─────────────────────────────────────────────────────────\n\t// Works autonomously toward a completion condition by driving the loop in\n\t// loop.ts over the LOOP_AUTO_START channel. Linear by design: a single thread\n\t// of execution that iterates until it reports done or exhausts its budget —\n\t// there is no task graph here, and no subtask fan-out.\n\t//\n\t// The run inherits whatever the active mode already permits (enabled_tools,\n\t// allowed_bash_commands, allowed_write_paths, auto_allow), so how much rope\n\t// an unattended goal gets is a mode-config decision, not one made here.\n\n\tpi.registerCommand(\"goal\", {\n\t\tdescription: \"Work autonomously toward a goal. Usage: /goal [--max-turns N] [objective]\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst parsed = parseGoalArgs(args);\n\t\t\tif (!parsed) {\n\t\t\t\tctx.ui.notify(\"Usage: /goal [--max-turns N] [objective]\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// The plan supplies the objective when none was typed, and its\n\t\t\t// verification section becomes the completion condition either way.\n\t\t\tconst sessionPlanPath = cachedPlanPath ?? getPlanPath(ctx.cwd, ctx.sessionManager.getSessionId());\n\t\t\tconst loaded = loadPlanSections([sessionPlanPath, getLegacyPlanPath(ctx.cwd)]);\n\t\t\tif (loaded.status === \"error\") {\n\t\t\t\tctx.ui.notify(`Could not read ${relative(ctx.cwd, loaded.path) || loaded.path}`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst sections = loaded.status === \"loaded\" ? loaded.sections : undefined;\n\n\t\t\tconst objective = parsed.objective ?? sections?.goal;\n\t\t\tif (!objective) {\n\t\t\t\tconst relPlan = relative(ctx.cwd, sessionPlanPath) || sessionPlanPath;\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`No objective — pass one as /goal <objective>, or write a Goal section in ${relPlan}.`,\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst { task, continuePrompt } = buildGoalMessages(objective, sections?.verification);\n\t\t\t// The loop announces itself on start, so nothing to notify here.\n\t\t\tpi.events.emit(LOOP_AUTO_START, {\n\t\t\t\ttask,\n\t\t\t\tmaxTurns: parsed.maxTurns,\n\t\t\t\tcontinuePrompt,\n\t\t\t} satisfies LoopAutoStartPayload);\n\t\t},\n\t});\n\n\t// ── /approve command ──────────────────────────────────────────────────────\n\t// Reads .hoocode/plan.md, parses it into named sections (Goal, Files to\n\t// modify, New files, Tests, Verification), switches to build mode, then\n\t// injects a step-by-step execution message into the new session.\n\n\tpi.registerCommand(\"approve\", {\n\t\tdescription: \"Approve the current plan and switch to build mode to execute it.\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (_args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tif (cachedMode !== \"plan\") {\n\t\t\t\tctx.ui.notify(`/approve is only available in plan mode (current mode: \"${cachedMode}\")`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prefer the per-session plan file, fall back to the legacy single file.\n\t\t\tconst sessionPlanPath = cachedPlanPath ?? getPlanPath(ctx.cwd, ctx.sessionManager.getSessionId());\n\t\t\tconst loaded = loadPlanSections([sessionPlanPath, getLegacyPlanPath(ctx.cwd)]);\n\t\t\tif (loaded.status === \"error\") {\n\t\t\t\tctx.ui.notify(`Could not read ${relative(ctx.cwd, loaded.path) || loaded.path}`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst approveMessage = loaded.status === \"loaded\" ? buildApproveMessage(loaded.sections) : undefined;\n\n\t\t\t// Switch global config to build mode\n\t\t\tconst config = readConfig();\n\t\t\tconfig.active_mode = \"build\";\n\t\t\twriteConfig(config);\n\n\t\t\tif (approveMessage) {\n\t\t\t\t// Open a new build-mode session and deliver the parsed plan as the\n\t\t\t\t// first user message so the agent starts executing immediately\n\t\t\t\tawait ctx.newSession({\n\t\t\t\t\twithSession: async (replacedCtx) => {\n\t\t\t\t\t\tawait replacedCtx.sendUserMessage(approveMessage!, { deliverAs: \"followUp\" });\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst relPlan = relative(ctx.cwd, sessionPlanPath) || sessionPlanPath;\n\t\t\t\tctx.ui.notify(`Switched to build mode. No ${relPlan} found — describe what to build.`, \"info\");\n\t\t\t\tawait ctx.reload();\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"modes.js","sourceRoot":"","sources":["../../../src/extensions/core/modes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mode system — resolves the active mode (ask/plan/build/debug), loads the\n * mode's system prompt, filters active tools, and exposes the /mode, /plan,\n * /grill, /goal, and /approve commands.\n *\n * Mode prompt search order (first hit wins):\n * - `./.hoocode/modes/{mode}/system.md`\n * - `~/.hoocode/modes/{mode}/system.md`\n * - each configured/contributed external dir in declared order\n * - built-in MODE_DEFAULTS for the four known modes\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { getHooCodeDir } from \"../../config.js\";\nimport type {\n\tBeforeAgentStartEvent,\n\tBeforeAgentStartEventResult,\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tSessionStartEvent,\n} from \"../../core/extensions/types.js\";\nimport { isLightModeEnv } from \"../../core/light.js\";\nimport { DEFAULT_MODE, DEFAULT_MODE_PROMPTS as MODE_DEFAULTS } from \"../../core/mode-prompts.js\";\nimport { EMBEDDED_PROMPTS } from \"../../init-templates.generated.js\";\nimport { mergeSearchPaths, readConfig, readMergedConfig, writeConfig } from \"./config.js\";\nimport { AUTO_LOOP_DONE_TOKEN, LOOP_AUTO_CHANGED, LOOP_AUTO_START, type LoopAutoStartPayload } from \"./loop.js\";\n\nconst HOOCODE_DIR = getHooCodeDir();\n\n/**\n * Per-session plan file path. Keying on sessionId lets concurrent or resumed\n * plan sessions keep distinct plans instead of clobbering each other.\n */\nfunction getPlanPath(cwd: string, sessionId: string): string {\n\treturn join(cwd, \".hoocode\", \"plans\", `${sessionId}.md`);\n}\n\n/** Legacy single-file plan location, retained as a read-only fallback for /approve. */\nfunction getLegacyPlanPath(cwd: string): string {\n\treturn join(cwd, \".hoocode\", \"plan.md\");\n}\n\nfunction tryReadFile(path: string): string | undefined {\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst text = readFileSync(path, \"utf8\").trim();\n\t\treturn text || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Outcome of reading the first usable plan file out of a candidate list. */\ntype PlanLoadResult =\n\t| { status: \"loaded\"; sections: PlanSections }\n\t| { status: \"missing\" }\n\t| { status: \"error\"; path: string };\n\n/**\n * Reads the first candidate plan file that exists and is non-empty, parsed into\n * sections. Missing and blank files fall through to the next candidate; an\n * unreadable one stops the walk so the caller can report the specific path.\n */\nfunction loadPlanSections(candidatePaths: string[]): PlanLoadResult {\n\tfor (const planPath of candidatePaths) {\n\t\tif (!existsSync(planPath)) continue;\n\t\ttry {\n\t\t\tconst raw = readFileSync(planPath, \"utf8\").trim();\n\t\t\tif (raw) return { status: \"loaded\", sections: parsePlanSections(raw) };\n\t\t} catch {\n\t\t\treturn { status: \"error\", path: planPath };\n\t\t}\n\t}\n\treturn { status: \"missing\" };\n}\n\n/**\n * Walks search dirs in precedence order and returns the first existing\n * `modes/{name}/system.md` content. Order: project → user → externalDirs.\n */\nfunction resolveModeFile(name: string, cwd: string, externalDirs: string[]): string | undefined {\n\tconst candidates: string[] = [\n\t\tjoin(cwd, \".hoocode\", \"modes\", name, \"system.md\"),\n\t\tjoin(HOOCODE_DIR, \"modes\", name, \"system.md\"),\n\t\t...externalDirs.map((dir) => join(dir, name, \"system.md\")),\n\t];\n\tfor (const candidate of candidates) {\n\t\tconst content = tryReadFile(candidate);\n\t\tif (content !== undefined) return content;\n\t}\n\treturn undefined;\n}\n\n/**\n * Returns the system prompt for the active mode.\n *\n * Search order (first hit wins):\n * - `./.hoocode/modes/{mode}/system.md`\n * - `~/.hoocode/modes/{mode}/system.md`\n * - each of `externalDirs` in declared order (config + CLI + extension contributions)\n * - built-in MODE_DEFAULTS for the four known modes\n */\nexport function buildSystemPrompt(mode: string, cwd: string, options?: { modePaths?: string[] }): string | undefined {\n\tconst modePaths = options?.modePaths ?? [];\n\treturn resolveModeFile(mode, cwd, modePaths) ?? MODE_DEFAULTS[mode];\n}\n\n// ============================================================================\n// Plan file: section parsing and step-by-step execution message\n// ============================================================================\n\nexport interface PlanSections {\n\tgoal?: string;\n\tfilesToModify?: string;\n\tnewFiles?: string;\n\ttests?: string;\n\tverification?: string;\n\t/** Original full text, used as fallback if no sections parsed */\n\traw: string;\n}\n\n/**\n * Parses `.hoocode/plan.md` into named sections.\n *\n * Recognises both ATX headings (`## Goal`) and bold labels (`**Goal**`).\n * Section names matched (case-insensitive): Goal, Files to modify, New files,\n * Tests, Verification.\n */\nexport function parsePlanSections(planContent: string): PlanSections {\n\tconst result: PlanSections = { raw: planContent };\n\n\t// Match `## Heading text` or `**Heading text**` followed by content until\n\t// the next heading of the same style.\n\tconst sectionPattern =\n\t\t/^(?:#{1,3}\\s+(.+?)|(?:\\*\\*(.+?)\\*\\*))\\s*\\n([\\s\\S]*?)(?=(?:^#{1,3}\\s+|\\*\\*[^*\\n]+\\*\\*\\s*\\n)|$)/gm;\n\n\tfor (const match of planContent.matchAll(sectionPattern)) {\n\t\tconst heading = (match[1] ?? match[2] ?? \"\").toLowerCase().trim();\n\t\tconst content = match[3].trim();\n\t\tif (!content) continue;\n\n\t\tif (/^goal/.test(heading)) {\n\t\t\tresult.goal = content;\n\t\t} else if (/files?\\s+to\\s+modif|^modif/.test(heading)) {\n\t\t\tresult.filesToModify = content;\n\t\t} else if (/new\\s+files?/.test(heading)) {\n\t\t\tresult.newFiles = content;\n\t\t} else if (/^tests?/.test(heading)) {\n\t\t\tresult.tests = content;\n\t\t} else if (/^verif/.test(heading)) {\n\t\t\tresult.verification = content;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Builds the user message sent to the agent when `/approve` is run.\n *\n * If the plan has recognisable sections, each is presented as a numbered step\n * so the agent works through them sequentially. Otherwise the raw plan is used.\n *\n * Execution order:\n * 1. Modify existing files\n * 2. Create new files\n * 3. Update / add tests\n * 4. Run verification commands\n */\nexport function buildApproveMessage(sections: PlanSections): string {\n\tconst steps: string[] = [];\n\n\tif (sections.goal) {\n\t\tsteps.push(`**Goal:** ${sections.goal}`);\n\t}\n\tif (sections.filesToModify) {\n\t\tsteps.push(`**Step 1 — Modify existing files:**\\n${sections.filesToModify}`);\n\t}\n\tif (sections.newFiles) {\n\t\tsteps.push(`**Step 2 — Create new files:**\\n${sections.newFiles}`);\n\t}\n\tif (sections.tests) {\n\t\tsteps.push(`**Step 3 — Update tests:**\\n${sections.tests}`);\n\t}\n\tif (sections.verification) {\n\t\tsteps.push(`**Step 4 — Verify:**\\n${sections.verification}`);\n\t}\n\n\tif (steps.length === 0) {\n\t\treturn `Execute the following plan:\\n\\n${sections.raw}`;\n\t}\n\n\treturn `Execute this plan step by step. Complete each step fully before moving to the next.\\n\\n${steps.join(\"\\n\\n\")}`;\n}\n\n// ============================================================================\n// Grill: plan interrogation\n// ============================================================================\n\n/** Which half (or both) of the grill flow to run. */\nexport type GrillTarget = \"both\" | \"me\" | \"plan\";\n\n/**\n * Parses the `/grill` argument into a target.\n *\n * Bare `/grill` runs both phases, `/grill me` only questions the user, and\n * `/grill plan` only critiques the plan. Anything else returns undefined so the\n * caller shows usage rather than guessing at intent.\n */\nexport function parseGrillTarget(args: string): GrillTarget | undefined {\n\tconst arg = args.trim().toLowerCase();\n\tif (!arg) return \"both\";\n\tif (arg === \"me\" || arg === \"plan\") return arg;\n\treturn undefined;\n}\n\n/**\n * Renders the parsed plan back into the message so the agent reviews a concrete\n * artifact rather than whatever it remembers writing. Falls back to the raw plan\n * text when no sections were recognised.\n */\nfunction renderPlanForReview(sections: PlanSections): string {\n\tconst parts: string[] = [];\n\tif (sections.goal) parts.push(`**Goal**\\n${sections.goal}`);\n\tif (sections.filesToModify) parts.push(`**Files to modify**\\n${sections.filesToModify}`);\n\tif (sections.newFiles) parts.push(`**New files**\\n${sections.newFiles}`);\n\tif (sections.tests) parts.push(`**Tests**\\n${sections.tests}`);\n\tif (sections.verification) parts.push(`**Verification**\\n${sections.verification}`);\n\treturn parts.length > 0 ? parts.join(\"\\n\\n\") : sections.raw;\n}\n\n/**\n * The `/grill` phases, read from the shipped prompt templates.\n *\n * These were two ~200-word string constants in this file. They are prose the\n * runtime injects verbatim - no interpolation, no branching, nothing a compiler\n * checks - so a `.md` under `templates/prompts/` is their right home, and the\n * existing build-time embed carries them in. Editing a prompt is now editing\n * prose rather than editing TypeScript that happens to contain prose.\n *\n * Each is trimmed: the files end with a newline and the phases are joined with\n * explicit separators below.\n */\nfunction grillPrompt(name: \"grill-me\" | \"grill-plan\" | \"grill-bridge\"): string {\n\treturn (EMBEDDED_PROMPTS[name] ?? \"\").trim();\n}\n\n/**\n * Builds the follow-up message injected by `/grill`.\n *\n * The two phases are ordered rather than alternative: underspecification sits\n * upstream of plan weakness, so critiquing a plan built on a misread request\n * produces a well-reviewed plan for the wrong job. Bare `/grill` therefore asks\n * first and folds the answers into the critique.\n */\nexport function buildGrillMessage(sections: PlanSections, target: GrillTarget): string {\n\tconst plan = renderPlanForReview(sections);\n\tconst me = grillPrompt(\"grill-me\");\n\tconst critique = grillPrompt(\"grill-plan\");\n\tif (target === \"me\") return `${me}\\n\\n---\\n\\n${plan}`;\n\tif (target === \"plan\") return `${critique}\\n\\n---\\n\\n${plan}`;\n\treturn `${me}\\n\\n${grillPrompt(\"grill-bridge\")}\\n\\n${critique}\\n\\n---\\n\\n${plan}`;\n}\n\n// ============================================================================\n// Goal: autonomous execution toward a completion condition\n// ============================================================================\n\n/** A parsed `/goal` invocation. */\nexport interface GoalInvocation {\n\t/** Explicit objective; falls back to the plan's Goal section when absent. */\n\tobjective?: string;\n\t/** Turn budget passed through to the autonomous loop. */\n\tmaxTurns?: number;\n}\n\n/**\n * Parses `/goal [--max-turns N] [objective]`.\n *\n * Returns undefined when `--max-turns` is present but not followed by a\n * non-negative integer, so the caller shows usage instead of silently running\n * with the default budget.\n */\nexport function parseGoalArgs(args: string): GoalInvocation | undefined {\n\tlet rest = args.trim();\n\tlet maxTurns: number | undefined;\n\n\tconst flag = /^--max-turns(?:\\s+(\\S+))?([\\s\\S]*)$/.exec(rest);\n\tif (flag) {\n\t\tconst raw = flag[1];\n\t\tif (!raw || !/^\\d+$/.test(raw)) return undefined;\n\t\tmaxTurns = Number(raw);\n\t\trest = flag[2].trim();\n\t}\n\n\treturn { objective: rest || undefined, maxTurns };\n}\n\n/** The two messages `/goal` hands to the autonomous loop. */\nexport interface GoalMessages {\n\t/** Delivered once, to start the run. */\n\ttask: string;\n\t/** Re-sent on each continuation to keep the target in view. */\n\tcontinuePrompt: string;\n}\n\n/**\n * Builds the messages for a `/goal` run.\n *\n * When the plan carries a Verification section it becomes the completion\n * condition, which is the difference between a loop that stops when it feels\n * finished and one that stops when something it can run says so. Both messages\n * restate the objective, because the loop's continuation prompt is all that\n * holds the target in place as the transcript grows.\n */\nexport function buildGoalMessages(objective: string, verification?: string): GoalMessages {\n\tconst condition = verification\n\t\t? `\\n\\nThe goal counts as complete only once this verification passes. Run it, and if it fails, fix what it reports and run it again:\\n\\n${verification}`\n\t\t: \"\";\n\n\treturn {\n\t\ttask: `Work autonomously toward this goal:\\n\\n${objective}${condition}`,\n\t\tcontinuePrompt:\n\t\t\t`Keep working toward the goal:\\n\\n${objective}${condition}\\n\\n` +\n\t\t\t`Reply with ${AUTO_LOOP_DONE_TOKEN} only when it is genuinely complete — not when it is merely close.`,\n\t};\n}\n\n// ============================================================================\n// setupMode\n// ============================================================================\n\nexport function setupMode(pi: ExtensionAPI): void {\n\tlet cachedMode = DEFAULT_MODE;\n\tlet cachedSystemPrompt: string | undefined;\n\tlet cachedPlanPath: string | undefined;\n\n\t// `/grill me` asks the user a question via ask_options, which an unattended\n\t// `/loop auto` run has nobody to answer. Track the loop's broadcast state so\n\t// the command can drop its interrogation phase instead of stalling the run.\n\tlet autoLoopActive = false;\n\tpi.events.on(LOOP_AUTO_CHANGED, (data) => {\n\t\tautoLoopActive = (data as { active?: boolean } | undefined)?.active === true;\n\t});\n\n\t// ── session_start ─────────────────────────────────────────────────────────\n\t// Config resolution order:\n\t// 1. Read global config (~/.hoocode/hoo-config.json)\n\t// 2. Read project config (./.hoocode/hoo-config.json) if present\n\t// 3. Merge — project scalars win; arrays are unioned\n\t// 4. Re-resolve active_mode from the merged result\n\n\tpi.on(\"session_start\", (_event: SessionStartEvent, ctx: ExtensionContext) => {\n\t\t// Light mode strips every fixed prompt appendix. Leaving\n\t\t// cachedSystemPrompt unset makes before_agent_start a no-op, so no\n\t\t// `<!-- hoo-core: mode= -->` block is appended.\n\t\tif (isLightModeEnv()) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Steps 1–3: merge global + project configs\n\t\tconst config = readMergedConfig(ctx.cwd);\n\n\t\t// Step 4: resolve mode from the merged config\n\t\tcachedMode = config.active_mode ?? DEFAULT_MODE;\n\t\t// External search dirs come from two channels:\n\t\t// - HooConfig.mode_paths (config-declared)\n\t\t// - pi.addModeSearchPath (CLI flags + extension contributions)\n\t\tconst modePaths = mergeSearchPaths(config.mode_paths, pi.getModeSearchPaths());\n\t\tconst rawSystemPrompt = buildSystemPrompt(cachedMode, ctx.cwd, { modePaths });\n\n\t\t// Per-session plan path so concurrent sessions don't overwrite each other.\n\t\t// The `{{PLAN_PATH}}` token in plan-mode templates is substituted here.\n\t\tcachedPlanPath = getPlanPath(ctx.cwd, ctx.sessionManager.getSessionId());\n\t\tconst relPlanPath = relative(ctx.cwd, cachedPlanPath) || cachedPlanPath;\n\t\tcachedSystemPrompt = rawSystemPrompt?.replace(/\\{\\{PLAN_PATH\\}\\}/g, relPlanPath);\n\n\t\t// Update footer with active mode\n\t\tif (ctx.hasUI) {\n\t\t\tctx.ui.setMode(cachedMode);\n\t\t}\n\n\t\t// Apply tool filter from mode enabled_tools\n\t\tconst modeCfg = config.modes?.[cachedMode];\n\t\tif (modeCfg?.enabled_tools && modeCfg.enabled_tools.length > 0) {\n\t\t\tpi.setActiveTools(modeCfg.enabled_tools);\n\t\t}\n\t});\n\n\t// ── before_agent_start ────────────────────────────────────────────────────\n\n\tpi.on(\"before_agent_start\", (event: BeforeAgentStartEvent): BeforeAgentStartEventResult | undefined => {\n\t\tif (!cachedSystemPrompt) return;\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n\\n<!-- hoo-core: mode=${cachedMode} -->\\n${cachedSystemPrompt}`,\n\t\t};\n\t});\n\n\t// ── /mode command ─────────────────────────────────────────────────────────\n\n\tconst KNOWN_MODES = [\"ask\", \"plan\", \"build\", \"debug\"];\n\n\tpi.registerCommand(\"mode\", {\n\t\tdescription: \"Switch active mode. Usage: /mode <ask|plan|build|debug>\",\n\t\tgetArgumentCompletions: (prefix: string) =>\n\t\t\tKNOWN_MODES.filter((m) => m.startsWith(prefix)).map((m) => ({ value: m, label: m })),\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tif (!name) {\n\t\t\t\tctx.ui.notify(`Active mode: ${cachedMode}`, \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst config = readConfig();\n\t\t\tconfig.active_mode = name === DEFAULT_MODE ? undefined : name;\n\t\t\twriteConfig(config);\n\t\t\tctx.ui.notify(`Mode set to \"${name}\" — reloading…`, \"info\");\n\t\t\tawait ctx.reload();\n\t\t},\n\t});\n\n\t// ── /plan command (shorthand for /mode plan) ──────────────────────────────\n\n\tpi.registerCommand(\"plan\", {\n\t\tdescription: \"Switch to plan mode. Shorthand for /mode plan.\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (_args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst config = readConfig();\n\t\t\tconfig.active_mode = \"plan\";\n\t\t\twriteConfig(config);\n\t\t\tctx.ui.notify(`Mode set to \"plan\" — reloading…`, \"info\");\n\t\t\tawait ctx.reload();\n\t\t},\n\t});\n\n\t// ── /grill command ────────────────────────────────────────────────────────\n\t// Stress-tests the current plan in two phases: `me` surfaces the request's\n\t// unconfirmed assumptions as ask_options questions, `plan` critiques the plan\n\t// file itself. Unlike /approve this only injects a follow-up message — no\n\t// session switch, no mode change, no config write.\n\n\tpi.registerCommand(\"grill\", {\n\t\tdescription: \"Stress-test the current plan. Usage: /grill [me|plan]\",\n\t\tgetArgumentCompletions: (prefix: string) =>\n\t\t\t[\"me\", \"plan\"].filter((s) => s.startsWith(prefix)).map((s) => ({ value: s, label: s })),\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst requested = parseGrillTarget(args);\n\t\t\tif (!requested) {\n\t\t\t\tctx.ui.notify(\"Usage: /grill [me|plan]\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Same lookup as /approve: per-session plan first, legacy file second.\n\t\t\tconst sessionPlanPath = cachedPlanPath ?? getPlanPath(ctx.cwd, ctx.sessionManager.getSessionId());\n\t\t\tconst loaded = loadPlanSections([sessionPlanPath, getLegacyPlanPath(ctx.cwd)]);\n\t\t\tif (loaded.status === \"error\") {\n\t\t\t\tctx.ui.notify(`Could not read ${relative(ctx.cwd, loaded.path) || loaded.path}`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (loaded.status === \"missing\") {\n\t\t\t\tconst relPlan = relative(ctx.cwd, sessionPlanPath) || sessionPlanPath;\n\t\t\t\tctx.ui.notify(`No plan to grill — ${relPlan} not found. Run /plan first.`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Nobody is present to answer during an autonomous loop, so keep the\n\t\t\t// half of the flow that still works rather than blocking on a question.\n\t\t\tlet target = requested;\n\t\t\tif (autoLoopActive && target !== \"plan\") {\n\t\t\t\ttarget = \"plan\";\n\t\t\t\tctx.ui.notify(\"Autonomous loop active — grilling the plan only, skipping questions.\", \"info\");\n\t\t\t}\n\n\t\t\tpi.sendUserMessage(buildGrillMessage(loaded.sections, target), { deliverAs: \"followUp\" });\n\t\t},\n\t});\n\n\t// ── /goal command ─────────────────────────────────────────────────────────\n\t// Works autonomously toward a completion condition by driving the loop in\n\t// loop.ts over the LOOP_AUTO_START channel. Linear by design: a single thread\n\t// of execution that iterates until it reports done or exhausts its budget —\n\t// there is no task graph here, and no subtask fan-out.\n\t//\n\t// The run inherits whatever the active mode already permits (enabled_tools,\n\t// allowed_bash_commands, allowed_write_paths, auto_allow), so how much rope\n\t// an unattended goal gets is a mode-config decision, not one made here.\n\n\tpi.registerCommand(\"goal\", {\n\t\tdescription: \"Work autonomously toward a goal. Usage: /goal [--max-turns N] [objective]\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst parsed = parseGoalArgs(args);\n\t\t\tif (!parsed) {\n\t\t\t\tctx.ui.notify(\"Usage: /goal [--max-turns N] [objective]\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// The plan supplies the objective when none was typed, and its\n\t\t\t// verification section becomes the completion condition either way.\n\t\t\tconst sessionPlanPath = cachedPlanPath ?? getPlanPath(ctx.cwd, ctx.sessionManager.getSessionId());\n\t\t\tconst loaded = loadPlanSections([sessionPlanPath, getLegacyPlanPath(ctx.cwd)]);\n\t\t\tif (loaded.status === \"error\") {\n\t\t\t\tctx.ui.notify(`Could not read ${relative(ctx.cwd, loaded.path) || loaded.path}`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst sections = loaded.status === \"loaded\" ? loaded.sections : undefined;\n\n\t\t\tconst objective = parsed.objective ?? sections?.goal;\n\t\t\tif (!objective) {\n\t\t\t\tconst relPlan = relative(ctx.cwd, sessionPlanPath) || sessionPlanPath;\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`No objective — pass one as /goal <objective>, or write a Goal section in ${relPlan}.`,\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst { task, continuePrompt } = buildGoalMessages(objective, sections?.verification);\n\t\t\t// The loop announces itself on start, so nothing to notify here.\n\t\t\tpi.events.emit(LOOP_AUTO_START, {\n\t\t\t\ttask,\n\t\t\t\tmaxTurns: parsed.maxTurns,\n\t\t\t\tcontinuePrompt,\n\t\t\t} satisfies LoopAutoStartPayload);\n\t\t},\n\t});\n\n\t// ── /approve command ──────────────────────────────────────────────────────\n\t// Reads .hoocode/plan.md, parses it into named sections (Goal, Files to\n\t// modify, New files, Tests, Verification), switches to build mode, then\n\t// injects a step-by-step execution message into the new session.\n\n\tpi.registerCommand(\"approve\", {\n\t\tdescription: \"Approve the current plan and switch to build mode to execute it.\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (_args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tif (cachedMode !== \"plan\") {\n\t\t\t\tctx.ui.notify(`/approve is only available in plan mode (current mode: \"${cachedMode}\")`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prefer the per-session plan file, fall back to the legacy single file.\n\t\t\tconst sessionPlanPath = cachedPlanPath ?? getPlanPath(ctx.cwd, ctx.sessionManager.getSessionId());\n\t\t\tconst loaded = loadPlanSections([sessionPlanPath, getLegacyPlanPath(ctx.cwd)]);\n\t\t\tif (loaded.status === \"error\") {\n\t\t\t\tctx.ui.notify(`Could not read ${relative(ctx.cwd, loaded.path) || loaded.path}`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst approveMessage = loaded.status === \"loaded\" ? buildApproveMessage(loaded.sections) : undefined;\n\n\t\t\t// Switch global config to build mode\n\t\t\tconst config = readConfig();\n\t\t\tconfig.active_mode = \"build\";\n\t\t\twriteConfig(config);\n\n\t\t\tif (approveMessage) {\n\t\t\t\t// Open a new build-mode session and deliver the parsed plan as the\n\t\t\t\t// first user message so the agent starts executing immediately\n\t\t\t\tawait ctx.newSession({\n\t\t\t\t\twithSession: async (replacedCtx) => {\n\t\t\t\t\t\tawait replacedCtx.sendUserMessage(approveMessage!, { deliverAs: \"followUp\" });\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst relPlan = relative(ctx.cwd, sessionPlanPath) || sessionPlanPath;\n\t\t\t\tctx.ui.notify(`Switched to build mode. No ${relPlan} found — describe what to build.`, \"info\");\n\t\t\t\tawait ctx.reload();\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/extensions/core/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,gCAAgC,CAAC;AAoF5F,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAoMpD","sourcesContent":["/**\n * Scaffold commands — /new-skill, /new-agent, and /new-command.\n *\n * `/new-canvas` was their fourth sibling and is not here any more. It stopped\n * being a file-writing command when it grew Copilot's `/create-canvas` shape:\n * it opens what it writes and hands the agent a brief to build it, so it needs\n * the canvas session and the agent loop, neither of which belongs in a scaffold.\n * It lives in `extensions/core/canvas.ts` over `core/canvas/scaffold.ts`.\n *\n * Without `--platform`, each creates a ready-to-edit resource file\n * under `.hoocode/` (hoocode's private surface), picked up on the next /reload.\n *\n * With `--platform` (or the `platform` setting), the scaffold\n * instead lands in each target platform's *workspace* conventions via the\n * format registry's per-adapter {@link WorkspaceLayout} — e.g.\n * `--platform copilot` writes `.github/skills/<name>/SKILL.md`,\n * `.github/agents/<name>.agent.md`, and `.github/prompts/<name>.prompt.md`,\n * while `claude` writes `.claude/skills|agents|commands/`. hoocode reads all\n * of these back, so the scaffold is live after /reload either way.\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getFormatByPlatform } from \"../../core/extensions/plugins/formats/index.js\";\nimport { getWorkspacePlatforms } from \"../../core/extensions/plugins/formats/platform-targets.js\";\nimport type { EmittedFile, MarketplacePlatform, WorkspaceLayout } from \"../../core/extensions/plugins/formats/types.js\";\nimport type { ExtensionAPI, ExtensionCommandContext } from \"../../core/extensions/types.js\";\n\n/** Validates a resource name: lowercase a-z, 0-9, hyphens, no leading/trailing/double hyphens. */\nfunction validateResourceName(name: string): string | null {\n\tif (!name) return \"name is required\";\n\tif (!/^[a-z0-9-]+$/.test(name)) return \"name must be lowercase a-z, 0-9, and hyphens only\";\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) return \"name must not start or end with a hyphen\";\n\tif (name.includes(\"--\")) return \"name must not contain consecutive hyphens\";\n\treturn null;\n}\n\n/**\n * Write one scaffolded artifact into every `--platform` target's\n * workspace layout. Existing files are never clobbered — they are reported and\n * skipped. Returns true when the platform-targeted path handled the command.\n */\nfunction scaffoldForPlatforms(\n\tctx: ExtensionCommandContext,\n\tcommand: string,\n\tplatforms: MarketplacePlatform[],\n\temit: (workspace: WorkspaceLayout) => EmittedFile,\n): void {\n\tconst created: string[] = [];\n\tconst skipped: string[] = [];\n\tfor (const platform of platforms) {\n\t\tconst adapter = getFormatByPlatform(platform);\n\t\tif (!adapter) continue;\n\t\tconst file = emit(adapter.workspace);\n\t\tconst abs = join(ctx.cwd, file.path);\n\t\tif (existsSync(abs)) {\n\t\t\tskipped.push(file.path);\n\t\t\tcontinue;\n\t\t}\n\t\tmkdirSync(dirname(abs), { recursive: true });\n\t\twriteFileSync(abs, file.content, \"utf8\");\n\t\tcreated.push(file.path);\n\t}\n\n\tconst lines: string[] = [];\n\tif (created.length > 0) {\n\t\tlines.push(`Created (${platforms.join(\", \")}):`, ...created.map((f) => ` ${f}`));\n\t\tlines.push(\"Edit the file(s), then run /reload to activate.\");\n\t}\n\tif (skipped.length > 0) {\n\t\tlines.push(`Skipped (already exist):`, ...skipped.map((f) => ` ${f}`));\n\t}\n\tif (lines.length === 0) {\n\t\tlines.push(`/${command}: no writable platform targets resolved`);\n\t}\n\tctx.ui.notify(lines.join(\"\\n\"), created.length > 0 ? \"info\" : \"warning\");\n}\n\nconst SKILL_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`# ${name}`,\n\t\t\"\",\n\t\t\"TODO: write the skill instructions here.\",\n\t\t\"\",\n\t\t\"When relative paths appear below, they are resolved from this file's directory.\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst AGENT_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`You are a ${name} subagent.`,\n\t\t\"You run in an isolated context and cannot see the parent conversation.\",\n\t\t\"\",\n\t\t\"TODO: write the system prompt here.\",\n\t\t\"\",\n\t\t\"Your final message must contain ONLY your answer — it is the only output\",\n\t\t\"the caller receives. Do not include intermediate reasoning or tool logs.\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst COMMAND_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`Run the /${name} command with arguments: **$ARGUMENTS**.`,\n\t\t\"\",\n\t\t\"TODO: write the instructions here. Placeholders you can use:\",\n\t\t\"- $1, $2, ... for positional arguments\",\n\t\t\"- $@ or $ARGUMENTS for all arguments\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nexport function setupScaffold(pi: ExtensionAPI): void {\n\t// ── /new-skill <name> ─────────────────────────────────────────────────────\n\t// Creates a SKILL.md with valid Agent Skills frontmatter — under .hoocode/ by\n\t// default, or under each --platform target's skills directory.\n\n\tpi.registerCommand(\"new-skill\", {\n\t\tdescription: \"Scaffold a new skill. Usage: /new-skill <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-skill: ${error}. Usage: /new-skill <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-skill\", platforms, (ws) =>\n\t\t\t\t\tws.emitSkill({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"TODO: describe when to use this skill — the agent reads this to decide whether to load it.\",\n\t\t\t\t\t\tbody: SKILL_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst skillDir = join(ctx.cwd, \".hoocode\", \"skills\", name);\n\t\t\tconst skillFile = join(skillDir, \"SKILL.md\");\n\n\t\t\tif (existsSync(skillFile)) {\n\t\t\t\tctx.ui.notify(`/new-skill: ${skillFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(skillDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tskillFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t\" TODO: describe when to use this skill — one clear sentence per bullet.\",\n\t\t\t\t\t\" The model reads this to decide whether to load the skill.\",\n\t\t\t\t\t\"allowed-tools: read, bash\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\t\"\",\n\t\t\t\t\tSKILL_BODY_TEMPLATE(name),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Skill created: ${join(\".hoocode\", \"skills\", name, \"SKILL.md\")}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n\n\t// ── /new-agent <name> ─────────────────────────────────────────────────────\n\t// Creates a subagent definition — .hoocode/agents/<name>.md by default, or\n\t// each platform's convention (.claude/agents/<name>.md,\n\t// .github/agents/<name>.agent.md with a YAML-list tools grant, ...).\n\n\tpi.registerCommand(\"new-agent\", {\n\t\tdescription: \"Scaffold a new subagent. Usage: /new-agent <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-agent: ${error}. Usage: /new-agent <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-agent\", platforms, (ws) =>\n\t\t\t\t\tws.emitAgent({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: \"TODO: describe the task(s) to delegate to this agent.\",\n\t\t\t\t\t\ttools: \"read, bash\",\n\t\t\t\t\t\tbody: AGENT_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst agentsDir = join(ctx.cwd, \".hoocode\", \"agents\");\n\t\t\tconst agentFile = join(agentsDir, `${name}.md`);\n\n\t\t\tif (existsSync(agentFile)) {\n\t\t\t\tctx.ui.notify(`/new-agent: ${agentFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(agentsDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tagentFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t\" Use this subagent ONLY when:\",\n\t\t\t\t\t\" - TODO: describe the task(s) to delegate here\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\" DO NOT use for:\",\n\t\t\t\t\t\" - TODO: describe what this agent should NOT handle\",\n\t\t\t\t\t\"tools: read, bash\",\n\t\t\t\t\t\"model: sonnet\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`You are a ${name} subagent running inside hoocode.`,\n\t\t\t\t\t\"You run in an isolated context and cannot see the parent conversation.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"TODO: write the system prompt here.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Your final message must contain ONLY your answer — it is the only output\",\n\t\t\t\t\t\"the caller receives. Do not include intermediate reasoning or tool logs.\",\n\t\t\t\t\t\"\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Agent created: ${join(\".hoocode\", \"agents\", `${name}.md`)}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n\n\t// ── /new-command <name> ───────────────────────────────────────────────────\n\t// Creates a slash-command prompt template — .hoocode/commands/<name>.md by\n\t// default, or each platform's convention (.claude/commands/<name>.md,\n\t// .github/prompts/<name>.prompt.md, ...).\n\n\tpi.registerCommand(\"new-command\", {\n\t\tdescription: \"Scaffold a new slash command. Usage: /new-command <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-command: ${error}. Usage: /new-command <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-command\", platforms, (ws) =>\n\t\t\t\t\tws.emitCommand({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: `TODO: describe what /${name} does and when to use it.`,\n\t\t\t\t\t\tbody: COMMAND_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst commandsDir = join(ctx.cwd, \".hoocode\", \"commands\");\n\t\t\tconst commandFile = join(commandsDir, `${name}.md`);\n\n\t\t\tif (existsSync(commandFile)) {\n\t\t\t\tctx.ui.notify(`/new-command: ${commandFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(commandsDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tcommandFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t` TODO: describe what /${name} does and when to use it.`,\n\t\t\t\t\t` Usage: /${name} <args>`,\n\t\t\t\t\t\"argument-hint: <args>\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`Run the /${name} command with arguments: **$ARGUMENTS**.`,\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"TODO: write the instructions here. Placeholders you can use:\",\n\t\t\t\t\t\"- $1, $2, ... for positional arguments\",\n\t\t\t\t\t\"- $@ or $ARGUMENTS for all arguments\",\n\t\t\t\t\t`- $${\"{\"}@:N} / $${\"{\"}@:N:L} for bash-style slices`,\n\t\t\t\t\t\"\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Command created: ${join(\".hoocode\", \"commands\", `${name}.md`)}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/extensions/core/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,gCAAgC,CAAC;AA2G5F,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAoLpD","sourcesContent":["/**\n * Scaffold commands — /new-skill, /new-agent, and /new-command.\n *\n * `/new-canvas` was their fourth sibling and is not here any more. It stopped\n * being a file-writing command when it grew Copilot's `/create-canvas` shape:\n * it opens what it writes and hands the agent a brief to build it, so it needs\n * the canvas session and the agent loop, neither of which belongs in a scaffold.\n * It lives in `extensions/core/canvas.ts` over `core/canvas/scaffold.ts`.\n *\n * Without `--platform`, each creates a ready-to-edit resource file\n * under `.hoocode/` (hoocode's private surface), picked up on the next /reload.\n *\n * With `--platform` (or the `platform` setting), the scaffold\n * instead lands in each target platform's *workspace* conventions via the\n * format registry's per-adapter {@link WorkspaceLayout} — e.g.\n * `--platform copilot` writes `.github/skills/<name>/SKILL.md`,\n * `.github/agents/<name>.agent.md`, and `.github/prompts/<name>.prompt.md`,\n * while `claude` writes `.claude/skills|agents|commands/`. hoocode reads all\n * of these back, so the scaffold is live after /reload either way.\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getFormatByPlatform } from \"../../core/extensions/plugins/formats/index.js\";\nimport { getWorkspacePlatforms } from \"../../core/extensions/plugins/formats/platform-targets.js\";\nimport type { EmittedFile, MarketplacePlatform, WorkspaceLayout } from \"../../core/extensions/plugins/formats/types.js\";\nimport type { ExtensionAPI, ExtensionCommandContext } from \"../../core/extensions/types.js\";\n\n/** Validates a resource name: lowercase a-z, 0-9, hyphens, no leading/trailing/double hyphens. */\nfunction validateResourceName(name: string): string | null {\n\tif (!name) return \"name is required\";\n\tif (!/^[a-z0-9-]+$/.test(name)) return \"name must be lowercase a-z, 0-9, and hyphens only\";\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) return \"name must not start or end with a hyphen\";\n\tif (name.includes(\"--\")) return \"name must not contain consecutive hyphens\";\n\treturn null;\n}\n\n/**\n * Write one scaffolded artifact into every `--platform` target's\n * workspace layout. Existing files are never clobbered — they are reported and\n * skipped. Returns true when the platform-targeted path handled the command.\n */\nfunction scaffoldForPlatforms(\n\tctx: ExtensionCommandContext,\n\tcommand: string,\n\tplatforms: MarketplacePlatform[],\n\temit: (workspace: WorkspaceLayout) => EmittedFile,\n): void {\n\tconst created: string[] = [];\n\tconst skipped: string[] = [];\n\tfor (const platform of platforms) {\n\t\tconst adapter = getFormatByPlatform(platform);\n\t\tif (!adapter) continue;\n\t\tconst file = emit(adapter.workspace);\n\t\tconst abs = join(ctx.cwd, file.path);\n\t\tif (existsSync(abs)) {\n\t\t\tskipped.push(file.path);\n\t\t\tcontinue;\n\t\t}\n\t\tmkdirSync(dirname(abs), { recursive: true });\n\t\twriteFileSync(abs, file.content, \"utf8\");\n\t\tcreated.push(file.path);\n\t}\n\n\tconst lines: string[] = [];\n\tif (created.length > 0) {\n\t\tlines.push(`Created (${platforms.join(\", \")}):`, ...created.map((f) => ` ${f}`));\n\t\tlines.push(\"Edit the file(s), then run /reload to activate.\");\n\t}\n\tif (skipped.length > 0) {\n\t\tlines.push(`Skipped (already exist):`, ...skipped.map((f) => ` ${f}`));\n\t}\n\tif (lines.length === 0) {\n\t\tlines.push(`/${command}: no writable platform targets resolved`);\n\t}\n\tctx.ui.notify(lines.join(\"\\n\"), created.length > 0 ? \"info\" : \"warning\");\n}\n\n/**\n * The scaffold bodies and descriptions, each defined once.\n *\n * Every command here has two paths — the `--platform` emitters and the plain\n * `.hoocode/` writer — and each path used to carry its own copy of the text.\n * They had drifted in both directions: the `.hoocode/` agent body said \"running\n * inside hoocode\" where the platform one did not, and the `.hoocode/` command\n * body documented the bash-style slice placeholders that the platform one\n * silently omitted, so what `/new-command` taught you depended on whether\n * `--platform` was set. Both paths read these now.\n *\n * These stay as functions rather than moving to `templates/`: unlike the mode\n * and `/grill` prompts they interpolate throughout and feed a structured\n * emitter, so a flat markdown file would be the worse home.\n */\nconst SKILL_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`# ${name}`,\n\t\t\"\",\n\t\t\"TODO: write the skill instructions here.\",\n\t\t\"\",\n\t\t\"When relative paths appear below, they are resolved from this file's directory.\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst SKILL_DESCRIPTION_TEMPLATE =\n\t\"TODO: describe when to use this skill — the agent reads this to decide whether to load it.\";\n\nconst AGENT_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`You are a ${name} subagent running inside hoocode.`,\n\t\t\"You run in an isolated context and cannot see the parent conversation.\",\n\t\t\"\",\n\t\t\"TODO: write the system prompt here.\",\n\t\t\"\",\n\t\t\"Your final message must contain ONLY your answer — it is the only output\",\n\t\t\"the caller receives. Do not include intermediate reasoning or tool logs.\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst AGENT_DESCRIPTION_TEMPLATE = \"TODO: describe the task(s) to delegate to this agent.\";\n\nconst COMMAND_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`Run the /${name} command with arguments: **$ARGUMENTS**.`,\n\t\t\"\",\n\t\t\"TODO: write the instructions here. Placeholders you can use:\",\n\t\t\"- $1, $2, ... for positional arguments\",\n\t\t\"- $@ or $ARGUMENTS for all arguments\",\n\t\t`- $${\"{\"}@:N} / $${\"{\"}@:N:L} for bash-style slices`,\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst COMMAND_DESCRIPTION_TEMPLATE = (name: string) => `TODO: describe what /${name} does and when to use it.`;\n\nexport function setupScaffold(pi: ExtensionAPI): void {\n\t// ── /new-skill <name> ─────────────────────────────────────────────────────\n\t// Creates a SKILL.md with valid Agent Skills frontmatter — under .hoocode/ by\n\t// default, or under each --platform target's skills directory.\n\n\tpi.registerCommand(\"new-skill\", {\n\t\tdescription: \"Scaffold a new skill. Usage: /new-skill <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-skill: ${error}. Usage: /new-skill <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-skill\", platforms, (ws) =>\n\t\t\t\t\tws.emitSkill({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: SKILL_DESCRIPTION_TEMPLATE,\n\t\t\t\t\t\tbody: SKILL_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst skillDir = join(ctx.cwd, \".hoocode\", \"skills\", name);\n\t\t\tconst skillFile = join(skillDir, \"SKILL.md\");\n\n\t\t\tif (existsSync(skillFile)) {\n\t\t\t\tctx.ui.notify(`/new-skill: ${skillFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(skillDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tskillFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t`description: ${SKILL_DESCRIPTION_TEMPLATE}`,\n\t\t\t\t\t\"allowed-tools: read, bash\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\t\"\",\n\t\t\t\t\tSKILL_BODY_TEMPLATE(name),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Skill created: ${join(\".hoocode\", \"skills\", name, \"SKILL.md\")}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n\n\t// ── /new-agent <name> ─────────────────────────────────────────────────────\n\t// Creates a subagent definition — .hoocode/agents/<name>.md by default, or\n\t// each platform's convention (.claude/agents/<name>.md,\n\t// .github/agents/<name>.agent.md with a YAML-list tools grant, ...).\n\n\tpi.registerCommand(\"new-agent\", {\n\t\tdescription: \"Scaffold a new subagent. Usage: /new-agent <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-agent: ${error}. Usage: /new-agent <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-agent\", platforms, (ws) =>\n\t\t\t\t\tws.emitAgent({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: AGENT_DESCRIPTION_TEMPLATE,\n\t\t\t\t\t\ttools: \"read, bash\",\n\t\t\t\t\t\tbody: AGENT_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst agentsDir = join(ctx.cwd, \".hoocode\", \"agents\");\n\t\t\tconst agentFile = join(agentsDir, `${name}.md`);\n\n\t\t\tif (existsSync(agentFile)) {\n\t\t\t\tctx.ui.notify(`/new-agent: ${agentFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(agentsDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tagentFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t\" Use this subagent ONLY when:\",\n\t\t\t\t\t` - ${AGENT_DESCRIPTION_TEMPLATE}`,\n\t\t\t\t\t\"\",\n\t\t\t\t\t\" DO NOT use for:\",\n\t\t\t\t\t\" - TODO: describe what this agent should NOT handle\",\n\t\t\t\t\t\"tools: read, bash\",\n\t\t\t\t\t\"model: sonnet\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\tAGENT_BODY_TEMPLATE(name),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Agent created: ${join(\".hoocode\", \"agents\", `${name}.md`)}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n\n\t// ── /new-command <name> ───────────────────────────────────────────────────\n\t// Creates a slash-command prompt template — .hoocode/commands/<name>.md by\n\t// default, or each platform's convention (.claude/commands/<name>.md,\n\t// .github/prompts/<name>.prompt.md, ...).\n\n\tpi.registerCommand(\"new-command\", {\n\t\tdescription: \"Scaffold a new slash command. Usage: /new-command <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-command: ${error}. Usage: /new-command <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-command\", platforms, (ws) =>\n\t\t\t\t\tws.emitCommand({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: COMMAND_DESCRIPTION_TEMPLATE(name),\n\t\t\t\t\t\tbody: COMMAND_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst commandsDir = join(ctx.cwd, \".hoocode\", \"commands\");\n\t\t\tconst commandFile = join(commandsDir, `${name}.md`);\n\n\t\t\tif (existsSync(commandFile)) {\n\t\t\t\tctx.ui.notify(`/new-command: ${commandFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(commandsDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tcommandFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t` ${COMMAND_DESCRIPTION_TEMPLATE(name)}`,\n\t\t\t\t\t` Usage: /${name} <args>`,\n\t\t\t\t\t\"argument-hint: <args>\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\tCOMMAND_BODY_TEMPLATE(name),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Command created: ${join(\".hoocode\", \"commands\", `${name}.md`)}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
|
|
@@ -69,6 +69,21 @@ function scaffoldForPlatforms(ctx, command, platforms, emit) {
|
|
|
69
69
|
}
|
|
70
70
|
ctx.ui.notify(lines.join("\n"), created.length > 0 ? "info" : "warning");
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* The scaffold bodies and descriptions, each defined once.
|
|
74
|
+
*
|
|
75
|
+
* Every command here has two paths — the `--platform` emitters and the plain
|
|
76
|
+
* `.hoocode/` writer — and each path used to carry its own copy of the text.
|
|
77
|
+
* They had drifted in both directions: the `.hoocode/` agent body said "running
|
|
78
|
+
* inside hoocode" where the platform one did not, and the `.hoocode/` command
|
|
79
|
+
* body documented the bash-style slice placeholders that the platform one
|
|
80
|
+
* silently omitted, so what `/new-command` taught you depended on whether
|
|
81
|
+
* `--platform` was set. Both paths read these now.
|
|
82
|
+
*
|
|
83
|
+
* These stay as functions rather than moving to `templates/`: unlike the mode
|
|
84
|
+
* and `/grill` prompts they interpolate throughout and feed a structured
|
|
85
|
+
* emitter, so a flat markdown file would be the worse home.
|
|
86
|
+
*/
|
|
72
87
|
const SKILL_BODY_TEMPLATE = (name) => [
|
|
73
88
|
`# ${name}`,
|
|
74
89
|
"",
|
|
@@ -77,8 +92,9 @@ const SKILL_BODY_TEMPLATE = (name) => [
|
|
|
77
92
|
"When relative paths appear below, they are resolved from this file's directory.",
|
|
78
93
|
"",
|
|
79
94
|
].join("\n");
|
|
95
|
+
const SKILL_DESCRIPTION_TEMPLATE = "TODO: describe when to use this skill — the agent reads this to decide whether to load it.";
|
|
80
96
|
const AGENT_BODY_TEMPLATE = (name) => [
|
|
81
|
-
`You are a ${name} subagent.`,
|
|
97
|
+
`You are a ${name} subagent running inside hoocode.`,
|
|
82
98
|
"You run in an isolated context and cannot see the parent conversation.",
|
|
83
99
|
"",
|
|
84
100
|
"TODO: write the system prompt here.",
|
|
@@ -87,14 +103,17 @@ const AGENT_BODY_TEMPLATE = (name) => [
|
|
|
87
103
|
"the caller receives. Do not include intermediate reasoning or tool logs.",
|
|
88
104
|
"",
|
|
89
105
|
].join("\n");
|
|
106
|
+
const AGENT_DESCRIPTION_TEMPLATE = "TODO: describe the task(s) to delegate to this agent.";
|
|
90
107
|
const COMMAND_BODY_TEMPLATE = (name) => [
|
|
91
108
|
`Run the /${name} command with arguments: **$ARGUMENTS**.`,
|
|
92
109
|
"",
|
|
93
110
|
"TODO: write the instructions here. Placeholders you can use:",
|
|
94
111
|
"- $1, $2, ... for positional arguments",
|
|
95
112
|
"- $@ or $ARGUMENTS for all arguments",
|
|
113
|
+
`- $${"{"}@:N} / $${"{"}@:N:L} for bash-style slices`,
|
|
96
114
|
"",
|
|
97
115
|
].join("\n");
|
|
116
|
+
const COMMAND_DESCRIPTION_TEMPLATE = (name) => `TODO: describe what /${name} does and when to use it.`;
|
|
98
117
|
export function setupScaffold(pi) {
|
|
99
118
|
// ── /new-skill <name> ─────────────────────────────────────────────────────
|
|
100
119
|
// Creates a SKILL.md with valid Agent Skills frontmatter — under .hoocode/ by
|
|
@@ -113,7 +132,7 @@ export function setupScaffold(pi) {
|
|
|
113
132
|
if (platforms) {
|
|
114
133
|
scaffoldForPlatforms(ctx, "new-skill", platforms, (ws) => ws.emitSkill({
|
|
115
134
|
name,
|
|
116
|
-
description:
|
|
135
|
+
description: SKILL_DESCRIPTION_TEMPLATE,
|
|
117
136
|
body: SKILL_BODY_TEMPLATE(name),
|
|
118
137
|
}));
|
|
119
138
|
return;
|
|
@@ -128,9 +147,7 @@ export function setupScaffold(pi) {
|
|
|
128
147
|
writeFileSync(skillFile, [
|
|
129
148
|
"---",
|
|
130
149
|
`name: ${name}`,
|
|
131
|
-
|
|
132
|
-
" TODO: describe when to use this skill — one clear sentence per bullet.",
|
|
133
|
-
" The model reads this to decide whether to load the skill.",
|
|
150
|
+
`description: ${SKILL_DESCRIPTION_TEMPLATE}`,
|
|
134
151
|
"allowed-tools: read, bash",
|
|
135
152
|
"---",
|
|
136
153
|
"",
|
|
@@ -157,7 +174,7 @@ export function setupScaffold(pi) {
|
|
|
157
174
|
if (platforms) {
|
|
158
175
|
scaffoldForPlatforms(ctx, "new-agent", platforms, (ws) => ws.emitAgent({
|
|
159
176
|
name,
|
|
160
|
-
description:
|
|
177
|
+
description: AGENT_DESCRIPTION_TEMPLATE,
|
|
161
178
|
tools: "read, bash",
|
|
162
179
|
body: AGENT_BODY_TEMPLATE(name),
|
|
163
180
|
}));
|
|
@@ -175,21 +192,14 @@ export function setupScaffold(pi) {
|
|
|
175
192
|
`name: ${name}`,
|
|
176
193
|
"description: |",
|
|
177
194
|
" Use this subagent ONLY when:",
|
|
178
|
-
|
|
195
|
+
` - ${AGENT_DESCRIPTION_TEMPLATE}`,
|
|
179
196
|
"",
|
|
180
197
|
" DO NOT use for:",
|
|
181
198
|
" - TODO: describe what this agent should NOT handle",
|
|
182
199
|
"tools: read, bash",
|
|
183
200
|
"model: sonnet",
|
|
184
201
|
"---",
|
|
185
|
-
|
|
186
|
-
"You run in an isolated context and cannot see the parent conversation.",
|
|
187
|
-
"",
|
|
188
|
-
"TODO: write the system prompt here.",
|
|
189
|
-
"",
|
|
190
|
-
"Your final message must contain ONLY your answer — it is the only output",
|
|
191
|
-
"the caller receives. Do not include intermediate reasoning or tool logs.",
|
|
192
|
-
"",
|
|
202
|
+
AGENT_BODY_TEMPLATE(name),
|
|
193
203
|
].join("\n"), "utf8");
|
|
194
204
|
ctx.ui.notify(`Agent created: ${join(".hoocode", "agents", `${name}.md`)}\nEdit the file, then run /reload to activate it.`, "info");
|
|
195
205
|
},
|
|
@@ -212,7 +222,7 @@ export function setupScaffold(pi) {
|
|
|
212
222
|
if (platforms) {
|
|
213
223
|
scaffoldForPlatforms(ctx, "new-command", platforms, (ws) => ws.emitCommand({
|
|
214
224
|
name,
|
|
215
|
-
description:
|
|
225
|
+
description: COMMAND_DESCRIPTION_TEMPLATE(name),
|
|
216
226
|
body: COMMAND_BODY_TEMPLATE(name),
|
|
217
227
|
}));
|
|
218
228
|
return;
|
|
@@ -228,17 +238,11 @@ export function setupScaffold(pi) {
|
|
|
228
238
|
"---",
|
|
229
239
|
`name: ${name}`,
|
|
230
240
|
"description: |",
|
|
231
|
-
`
|
|
241
|
+
` ${COMMAND_DESCRIPTION_TEMPLATE(name)}`,
|
|
232
242
|
` Usage: /${name} <args>`,
|
|
233
243
|
"argument-hint: <args>",
|
|
234
244
|
"---",
|
|
235
|
-
|
|
236
|
-
"",
|
|
237
|
-
"TODO: write the instructions here. Placeholders you can use:",
|
|
238
|
-
"- $1, $2, ... for positional arguments",
|
|
239
|
-
"- $@ or $ARGUMENTS for all arguments",
|
|
240
|
-
`- $${"{"}@:N} / $${"{"}@:N:L} for bash-style slices`,
|
|
241
|
-
"",
|
|
245
|
+
COMMAND_BODY_TEMPLATE(name),
|
|
242
246
|
].join("\n"), "utf8");
|
|
243
247
|
ctx.ui.notify(`Command created: ${join(".hoocode", "commands", `${name}.md`)}\nEdit the file, then run /reload to activate it.`, "info");
|
|
244
248
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/extensions/core/scaffold.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scaffold commands — /new-skill, /new-agent, and /new-command.\n *\n * `/new-canvas` was their fourth sibling and is not here any more. It stopped\n * being a file-writing command when it grew Copilot's `/create-canvas` shape:\n * it opens what it writes and hands the agent a brief to build it, so it needs\n * the canvas session and the agent loop, neither of which belongs in a scaffold.\n * It lives in `extensions/core/canvas.ts` over `core/canvas/scaffold.ts`.\n *\n * Without `--platform`, each creates a ready-to-edit resource file\n * under `.hoocode/` (hoocode's private surface), picked up on the next /reload.\n *\n * With `--platform` (or the `platform` setting), the scaffold\n * instead lands in each target platform's *workspace* conventions via the\n * format registry's per-adapter {@link WorkspaceLayout} — e.g.\n * `--platform copilot` writes `.github/skills/<name>/SKILL.md`,\n * `.github/agents/<name>.agent.md`, and `.github/prompts/<name>.prompt.md`,\n * while `claude` writes `.claude/skills|agents|commands/`. hoocode reads all\n * of these back, so the scaffold is live after /reload either way.\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getFormatByPlatform } from \"../../core/extensions/plugins/formats/index.js\";\nimport { getWorkspacePlatforms } from \"../../core/extensions/plugins/formats/platform-targets.js\";\nimport type { EmittedFile, MarketplacePlatform, WorkspaceLayout } from \"../../core/extensions/plugins/formats/types.js\";\nimport type { ExtensionAPI, ExtensionCommandContext } from \"../../core/extensions/types.js\";\n\n/** Validates a resource name: lowercase a-z, 0-9, hyphens, no leading/trailing/double hyphens. */\nfunction validateResourceName(name: string): string | null {\n\tif (!name) return \"name is required\";\n\tif (!/^[a-z0-9-]+$/.test(name)) return \"name must be lowercase a-z, 0-9, and hyphens only\";\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) return \"name must not start or end with a hyphen\";\n\tif (name.includes(\"--\")) return \"name must not contain consecutive hyphens\";\n\treturn null;\n}\n\n/**\n * Write one scaffolded artifact into every `--platform` target's\n * workspace layout. Existing files are never clobbered — they are reported and\n * skipped. Returns true when the platform-targeted path handled the command.\n */\nfunction scaffoldForPlatforms(\n\tctx: ExtensionCommandContext,\n\tcommand: string,\n\tplatforms: MarketplacePlatform[],\n\temit: (workspace: WorkspaceLayout) => EmittedFile,\n): void {\n\tconst created: string[] = [];\n\tconst skipped: string[] = [];\n\tfor (const platform of platforms) {\n\t\tconst adapter = getFormatByPlatform(platform);\n\t\tif (!adapter) continue;\n\t\tconst file = emit(adapter.workspace);\n\t\tconst abs = join(ctx.cwd, file.path);\n\t\tif (existsSync(abs)) {\n\t\t\tskipped.push(file.path);\n\t\t\tcontinue;\n\t\t}\n\t\tmkdirSync(dirname(abs), { recursive: true });\n\t\twriteFileSync(abs, file.content, \"utf8\");\n\t\tcreated.push(file.path);\n\t}\n\n\tconst lines: string[] = [];\n\tif (created.length > 0) {\n\t\tlines.push(`Created (${platforms.join(\", \")}):`, ...created.map((f) => ` ${f}`));\n\t\tlines.push(\"Edit the file(s), then run /reload to activate.\");\n\t}\n\tif (skipped.length > 0) {\n\t\tlines.push(`Skipped (already exist):`, ...skipped.map((f) => ` ${f}`));\n\t}\n\tif (lines.length === 0) {\n\t\tlines.push(`/${command}: no writable platform targets resolved`);\n\t}\n\tctx.ui.notify(lines.join(\"\\n\"), created.length > 0 ? \"info\" : \"warning\");\n}\n\nconst SKILL_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`# ${name}`,\n\t\t\"\",\n\t\t\"TODO: write the skill instructions here.\",\n\t\t\"\",\n\t\t\"When relative paths appear below, they are resolved from this file's directory.\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst AGENT_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`You are a ${name} subagent.`,\n\t\t\"You run in an isolated context and cannot see the parent conversation.\",\n\t\t\"\",\n\t\t\"TODO: write the system prompt here.\",\n\t\t\"\",\n\t\t\"Your final message must contain ONLY your answer — it is the only output\",\n\t\t\"the caller receives. Do not include intermediate reasoning or tool logs.\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst COMMAND_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`Run the /${name} command with arguments: **$ARGUMENTS**.`,\n\t\t\"\",\n\t\t\"TODO: write the instructions here. Placeholders you can use:\",\n\t\t\"- $1, $2, ... for positional arguments\",\n\t\t\"- $@ or $ARGUMENTS for all arguments\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nexport function setupScaffold(pi: ExtensionAPI): void {\n\t// ── /new-skill <name> ─────────────────────────────────────────────────────\n\t// Creates a SKILL.md with valid Agent Skills frontmatter — under .hoocode/ by\n\t// default, or under each --platform target's skills directory.\n\n\tpi.registerCommand(\"new-skill\", {\n\t\tdescription: \"Scaffold a new skill. Usage: /new-skill <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-skill: ${error}. Usage: /new-skill <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-skill\", platforms, (ws) =>\n\t\t\t\t\tws.emitSkill({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"TODO: describe when to use this skill — the agent reads this to decide whether to load it.\",\n\t\t\t\t\t\tbody: SKILL_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst skillDir = join(ctx.cwd, \".hoocode\", \"skills\", name);\n\t\t\tconst skillFile = join(skillDir, \"SKILL.md\");\n\n\t\t\tif (existsSync(skillFile)) {\n\t\t\t\tctx.ui.notify(`/new-skill: ${skillFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(skillDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tskillFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t\" TODO: describe when to use this skill — one clear sentence per bullet.\",\n\t\t\t\t\t\" The model reads this to decide whether to load the skill.\",\n\t\t\t\t\t\"allowed-tools: read, bash\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\t\"\",\n\t\t\t\t\tSKILL_BODY_TEMPLATE(name),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Skill created: ${join(\".hoocode\", \"skills\", name, \"SKILL.md\")}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n\n\t// ── /new-agent <name> ─────────────────────────────────────────────────────\n\t// Creates a subagent definition — .hoocode/agents/<name>.md by default, or\n\t// each platform's convention (.claude/agents/<name>.md,\n\t// .github/agents/<name>.agent.md with a YAML-list tools grant, ...).\n\n\tpi.registerCommand(\"new-agent\", {\n\t\tdescription: \"Scaffold a new subagent. Usage: /new-agent <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-agent: ${error}. Usage: /new-agent <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-agent\", platforms, (ws) =>\n\t\t\t\t\tws.emitAgent({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: \"TODO: describe the task(s) to delegate to this agent.\",\n\t\t\t\t\t\ttools: \"read, bash\",\n\t\t\t\t\t\tbody: AGENT_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst agentsDir = join(ctx.cwd, \".hoocode\", \"agents\");\n\t\t\tconst agentFile = join(agentsDir, `${name}.md`);\n\n\t\t\tif (existsSync(agentFile)) {\n\t\t\t\tctx.ui.notify(`/new-agent: ${agentFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(agentsDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tagentFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t\" Use this subagent ONLY when:\",\n\t\t\t\t\t\" - TODO: describe the task(s) to delegate here\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\" DO NOT use for:\",\n\t\t\t\t\t\" - TODO: describe what this agent should NOT handle\",\n\t\t\t\t\t\"tools: read, bash\",\n\t\t\t\t\t\"model: sonnet\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`You are a ${name} subagent running inside hoocode.`,\n\t\t\t\t\t\"You run in an isolated context and cannot see the parent conversation.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"TODO: write the system prompt here.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Your final message must contain ONLY your answer — it is the only output\",\n\t\t\t\t\t\"the caller receives. Do not include intermediate reasoning or tool logs.\",\n\t\t\t\t\t\"\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Agent created: ${join(\".hoocode\", \"agents\", `${name}.md`)}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n\n\t// ── /new-command <name> ───────────────────────────────────────────────────\n\t// Creates a slash-command prompt template — .hoocode/commands/<name>.md by\n\t// default, or each platform's convention (.claude/commands/<name>.md,\n\t// .github/prompts/<name>.prompt.md, ...).\n\n\tpi.registerCommand(\"new-command\", {\n\t\tdescription: \"Scaffold a new slash command. Usage: /new-command <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-command: ${error}. Usage: /new-command <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-command\", platforms, (ws) =>\n\t\t\t\t\tws.emitCommand({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: `TODO: describe what /${name} does and when to use it.`,\n\t\t\t\t\t\tbody: COMMAND_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst commandsDir = join(ctx.cwd, \".hoocode\", \"commands\");\n\t\t\tconst commandFile = join(commandsDir, `${name}.md`);\n\n\t\t\tif (existsSync(commandFile)) {\n\t\t\t\tctx.ui.notify(`/new-command: ${commandFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(commandsDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tcommandFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t` TODO: describe what /${name} does and when to use it.`,\n\t\t\t\t\t` Usage: /${name} <args>`,\n\t\t\t\t\t\"argument-hint: <args>\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`Run the /${name} command with arguments: **$ARGUMENTS**.`,\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"TODO: write the instructions here. Placeholders you can use:\",\n\t\t\t\t\t\"- $1, $2, ... for positional arguments\",\n\t\t\t\t\t\"- $@ or $ARGUMENTS for all arguments\",\n\t\t\t\t\t`- $${\"{\"}@:N} / $${\"{\"}@:N:L} for bash-style slices`,\n\t\t\t\t\t\"\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Command created: ${join(\".hoocode\", \"commands\", `${name}.md`)}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/extensions/core/scaffold.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scaffold commands — /new-skill, /new-agent, and /new-command.\n *\n * `/new-canvas` was their fourth sibling and is not here any more. It stopped\n * being a file-writing command when it grew Copilot's `/create-canvas` shape:\n * it opens what it writes and hands the agent a brief to build it, so it needs\n * the canvas session and the agent loop, neither of which belongs in a scaffold.\n * It lives in `extensions/core/canvas.ts` over `core/canvas/scaffold.ts`.\n *\n * Without `--platform`, each creates a ready-to-edit resource file\n * under `.hoocode/` (hoocode's private surface), picked up on the next /reload.\n *\n * With `--platform` (or the `platform` setting), the scaffold\n * instead lands in each target platform's *workspace* conventions via the\n * format registry's per-adapter {@link WorkspaceLayout} — e.g.\n * `--platform copilot` writes `.github/skills/<name>/SKILL.md`,\n * `.github/agents/<name>.agent.md`, and `.github/prompts/<name>.prompt.md`,\n * while `claude` writes `.claude/skills|agents|commands/`. hoocode reads all\n * of these back, so the scaffold is live after /reload either way.\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getFormatByPlatform } from \"../../core/extensions/plugins/formats/index.js\";\nimport { getWorkspacePlatforms } from \"../../core/extensions/plugins/formats/platform-targets.js\";\nimport type { EmittedFile, MarketplacePlatform, WorkspaceLayout } from \"../../core/extensions/plugins/formats/types.js\";\nimport type { ExtensionAPI, ExtensionCommandContext } from \"../../core/extensions/types.js\";\n\n/** Validates a resource name: lowercase a-z, 0-9, hyphens, no leading/trailing/double hyphens. */\nfunction validateResourceName(name: string): string | null {\n\tif (!name) return \"name is required\";\n\tif (!/^[a-z0-9-]+$/.test(name)) return \"name must be lowercase a-z, 0-9, and hyphens only\";\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) return \"name must not start or end with a hyphen\";\n\tif (name.includes(\"--\")) return \"name must not contain consecutive hyphens\";\n\treturn null;\n}\n\n/**\n * Write one scaffolded artifact into every `--platform` target's\n * workspace layout. Existing files are never clobbered — they are reported and\n * skipped. Returns true when the platform-targeted path handled the command.\n */\nfunction scaffoldForPlatforms(\n\tctx: ExtensionCommandContext,\n\tcommand: string,\n\tplatforms: MarketplacePlatform[],\n\temit: (workspace: WorkspaceLayout) => EmittedFile,\n): void {\n\tconst created: string[] = [];\n\tconst skipped: string[] = [];\n\tfor (const platform of platforms) {\n\t\tconst adapter = getFormatByPlatform(platform);\n\t\tif (!adapter) continue;\n\t\tconst file = emit(adapter.workspace);\n\t\tconst abs = join(ctx.cwd, file.path);\n\t\tif (existsSync(abs)) {\n\t\t\tskipped.push(file.path);\n\t\t\tcontinue;\n\t\t}\n\t\tmkdirSync(dirname(abs), { recursive: true });\n\t\twriteFileSync(abs, file.content, \"utf8\");\n\t\tcreated.push(file.path);\n\t}\n\n\tconst lines: string[] = [];\n\tif (created.length > 0) {\n\t\tlines.push(`Created (${platforms.join(\", \")}):`, ...created.map((f) => ` ${f}`));\n\t\tlines.push(\"Edit the file(s), then run /reload to activate.\");\n\t}\n\tif (skipped.length > 0) {\n\t\tlines.push(`Skipped (already exist):`, ...skipped.map((f) => ` ${f}`));\n\t}\n\tif (lines.length === 0) {\n\t\tlines.push(`/${command}: no writable platform targets resolved`);\n\t}\n\tctx.ui.notify(lines.join(\"\\n\"), created.length > 0 ? \"info\" : \"warning\");\n}\n\n/**\n * The scaffold bodies and descriptions, each defined once.\n *\n * Every command here has two paths — the `--platform` emitters and the plain\n * `.hoocode/` writer — and each path used to carry its own copy of the text.\n * They had drifted in both directions: the `.hoocode/` agent body said \"running\n * inside hoocode\" where the platform one did not, and the `.hoocode/` command\n * body documented the bash-style slice placeholders that the platform one\n * silently omitted, so what `/new-command` taught you depended on whether\n * `--platform` was set. Both paths read these now.\n *\n * These stay as functions rather than moving to `templates/`: unlike the mode\n * and `/grill` prompts they interpolate throughout and feed a structured\n * emitter, so a flat markdown file would be the worse home.\n */\nconst SKILL_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`# ${name}`,\n\t\t\"\",\n\t\t\"TODO: write the skill instructions here.\",\n\t\t\"\",\n\t\t\"When relative paths appear below, they are resolved from this file's directory.\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst SKILL_DESCRIPTION_TEMPLATE =\n\t\"TODO: describe when to use this skill — the agent reads this to decide whether to load it.\";\n\nconst AGENT_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`You are a ${name} subagent running inside hoocode.`,\n\t\t\"You run in an isolated context and cannot see the parent conversation.\",\n\t\t\"\",\n\t\t\"TODO: write the system prompt here.\",\n\t\t\"\",\n\t\t\"Your final message must contain ONLY your answer — it is the only output\",\n\t\t\"the caller receives. Do not include intermediate reasoning or tool logs.\",\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst AGENT_DESCRIPTION_TEMPLATE = \"TODO: describe the task(s) to delegate to this agent.\";\n\nconst COMMAND_BODY_TEMPLATE = (name: string) =>\n\t[\n\t\t`Run the /${name} command with arguments: **$ARGUMENTS**.`,\n\t\t\"\",\n\t\t\"TODO: write the instructions here. Placeholders you can use:\",\n\t\t\"- $1, $2, ... for positional arguments\",\n\t\t\"- $@ or $ARGUMENTS for all arguments\",\n\t\t`- $${\"{\"}@:N} / $${\"{\"}@:N:L} for bash-style slices`,\n\t\t\"\",\n\t].join(\"\\n\");\n\nconst COMMAND_DESCRIPTION_TEMPLATE = (name: string) => `TODO: describe what /${name} does and when to use it.`;\n\nexport function setupScaffold(pi: ExtensionAPI): void {\n\t// ── /new-skill <name> ─────────────────────────────────────────────────────\n\t// Creates a SKILL.md with valid Agent Skills frontmatter — under .hoocode/ by\n\t// default, or under each --platform target's skills directory.\n\n\tpi.registerCommand(\"new-skill\", {\n\t\tdescription: \"Scaffold a new skill. Usage: /new-skill <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-skill: ${error}. Usage: /new-skill <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-skill\", platforms, (ws) =>\n\t\t\t\t\tws.emitSkill({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: SKILL_DESCRIPTION_TEMPLATE,\n\t\t\t\t\t\tbody: SKILL_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst skillDir = join(ctx.cwd, \".hoocode\", \"skills\", name);\n\t\t\tconst skillFile = join(skillDir, \"SKILL.md\");\n\n\t\t\tif (existsSync(skillFile)) {\n\t\t\t\tctx.ui.notify(`/new-skill: ${skillFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(skillDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tskillFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t`description: ${SKILL_DESCRIPTION_TEMPLATE}`,\n\t\t\t\t\t\"allowed-tools: read, bash\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\t\"\",\n\t\t\t\t\tSKILL_BODY_TEMPLATE(name),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Skill created: ${join(\".hoocode\", \"skills\", name, \"SKILL.md\")}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n\n\t// ── /new-agent <name> ─────────────────────────────────────────────────────\n\t// Creates a subagent definition — .hoocode/agents/<name>.md by default, or\n\t// each platform's convention (.claude/agents/<name>.md,\n\t// .github/agents/<name>.agent.md with a YAML-list tools grant, ...).\n\n\tpi.registerCommand(\"new-agent\", {\n\t\tdescription: \"Scaffold a new subagent. Usage: /new-agent <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-agent: ${error}. Usage: /new-agent <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-agent\", platforms, (ws) =>\n\t\t\t\t\tws.emitAgent({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: AGENT_DESCRIPTION_TEMPLATE,\n\t\t\t\t\t\ttools: \"read, bash\",\n\t\t\t\t\t\tbody: AGENT_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst agentsDir = join(ctx.cwd, \".hoocode\", \"agents\");\n\t\t\tconst agentFile = join(agentsDir, `${name}.md`);\n\n\t\t\tif (existsSync(agentFile)) {\n\t\t\t\tctx.ui.notify(`/new-agent: ${agentFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(agentsDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tagentFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t\" Use this subagent ONLY when:\",\n\t\t\t\t\t` - ${AGENT_DESCRIPTION_TEMPLATE}`,\n\t\t\t\t\t\"\",\n\t\t\t\t\t\" DO NOT use for:\",\n\t\t\t\t\t\" - TODO: describe what this agent should NOT handle\",\n\t\t\t\t\t\"tools: read, bash\",\n\t\t\t\t\t\"model: sonnet\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\tAGENT_BODY_TEMPLATE(name),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Agent created: ${join(\".hoocode\", \"agents\", `${name}.md`)}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n\n\t// ── /new-command <name> ───────────────────────────────────────────────────\n\t// Creates a slash-command prompt template — .hoocode/commands/<name>.md by\n\t// default, or each platform's convention (.claude/commands/<name>.md,\n\t// .github/prompts/<name>.prompt.md, ...).\n\n\tpi.registerCommand(\"new-command\", {\n\t\tdescription: \"Scaffold a new slash command. Usage: /new-command <name>\",\n\t\tgetArgumentCompletions: () => [],\n\t\thandler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {\n\t\t\tconst name = args.trim();\n\t\t\tconst error = validateResourceName(name);\n\t\t\tif (error) {\n\t\t\t\tctx.ui.notify(`/new-command: ${error}. Usage: /new-command <name>`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst platforms = getWorkspacePlatforms();\n\t\t\tif (platforms) {\n\t\t\t\tscaffoldForPlatforms(ctx, \"new-command\", platforms, (ws) =>\n\t\t\t\t\tws.emitCommand({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: COMMAND_DESCRIPTION_TEMPLATE(name),\n\t\t\t\t\t\tbody: COMMAND_BODY_TEMPLATE(name),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst commandsDir = join(ctx.cwd, \".hoocode\", \"commands\");\n\t\t\tconst commandFile = join(commandsDir, `${name}.md`);\n\n\t\t\tif (existsSync(commandFile)) {\n\t\t\t\tctx.ui.notify(`/new-command: ${commandFile} already exists`, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmkdirSync(commandsDir, { recursive: true });\n\t\t\twriteFileSync(\n\t\t\t\tcommandFile,\n\t\t\t\t[\n\t\t\t\t\t\"---\",\n\t\t\t\t\t`name: ${name}`,\n\t\t\t\t\t\"description: |\",\n\t\t\t\t\t` ${COMMAND_DESCRIPTION_TEMPLATE(name)}`,\n\t\t\t\t\t` Usage: /${name} <args>`,\n\t\t\t\t\t\"argument-hint: <args>\",\n\t\t\t\t\t\"---\",\n\t\t\t\t\tCOMMAND_BODY_TEMPLATE(name),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"utf8\",\n\t\t\t);\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Command created: ${join(\".hoocode\", \"commands\", `${name}.md`)}\\nEdit the file, then run /reload to activate it.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
|
|
@@ -2,4 +2,7 @@ export declare const EMBEDDED_DEFAULT_CONFIG: string;
|
|
|
2
2
|
export declare const EMBEDDED_MODES: Record<string, string>;
|
|
3
3
|
export declare const EMBEDDED_PROFILES: Record<string, string>;
|
|
4
4
|
export declare const EMBEDDED_AGENT_PROMPTS: Record<string, string>;
|
|
5
|
+
export declare const EMBEDDED_PROMPTS: Record<string, string>;
|
|
6
|
+
/** Built-in skills, keyed by path relative to templates/skills (POSIX separators). */
|
|
7
|
+
export declare const EMBEDDED_SKILLS: Record<string, string>;
|
|
5
8
|
//# sourceMappingURL=init-templates.generated.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-templates.generated.d.ts","sourceRoot":"","sources":["../src/init-templates.generated.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB,EAAE,MAC+Z,CAAC;AAEtc,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKjD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,CAAC;AAE5D,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMzD,CAAC","sourcesContent":["// AUTO-GENERATED by scripts/embed-templates.mjs — do not edit.\n// Source of truth: packages/coding-agent/templates/**\n// Regenerated on every `npm run build`.\n\nexport const EMBEDDED_DEFAULT_CONFIG: string =\n\t'{\\n \"version\": \"1.0\",\\n \"active_mode\": \"build\",\\n \"llm\": {\\n \"default_provider\": \"anthropic\",\\n \"providers\": {\\n \"anthropic\": { \"api_key_env\": \"ANTHROPIC_API_KEY\" },\\n \"openai\": { \"api_key_env\": \"OPENAI_API_KEY\" }\\n }\\n },\\n \"modes\": {\\n \"ask\": { \"auto_allow\": [\"read\"] },\\n \"plan\": { \"auto_allow\": [\"read\", \"write\"] },\\n \"build\": { \"auto_allow\": [\"read\"] },\\n \"debug\": { \"auto_allow\": [\"read\", \"bash\"] }\\n }\\n}\\n';\n\nexport const EMBEDDED_MODES: Record<string, string> = {\n\task: \"You are in **ask mode** — read-only Q&A.\\n\\nPermitted: read files, run grep/find, explain code, trace logic, compare approaches, debug conceptually.\\nForbidden: edit files, write files, run commands that modify state.\\n\\nWhen answering:\\n- Cite file paths and line numbers.\\n- Prefer precise over verbose.\\n- If a question requires a code change to answer properly, describe the change; do not apply it.\\n- If the user asks you to edit something, decline and suggest switching to build mode with `/mode build`.\\n\",\n\tbuild: \"You are in **build mode** — implement carefully, one step at a time.\\n\\nRules:\\n- **One tool per turn.** Plan the action, call the tool, wait for the result before proceeding.\\n- **Read before editing.** Never write to a file you have not read in this session.\\n- **Show diffs** before applying non-trivial edits; wait for implicit acceptance.\\n- **Dangerous ops** (delete, force-push, drop table, rm -rf): state what you are about to do and wait for explicit confirmation.\\n- **Match existing style** — indentation, naming, import order.\\n- **Run tests** after every logical unit of change. Fix failures before continuing.\\n\",\n\tdebug: \"You are in **debug mode** — root-cause analysis only, no file modifications.\\n\\nProcess:\\n1. **Gather evidence** — read logs, error traces, and relevant source. Run safe diagnostic commands (grep, find, read, non-mutating shell commands).\\n2. **Reproduce** — identify the minimal condition that triggers the bug.\\n3. **Trace** — follow the full call path from entry point to failure site, citing file and line at each step.\\n4. **State the root cause** in one clear sentence.\\n5. **Describe the fix** — files, lines, and what to change — but do not apply it.\\n\\nForbidden: edit or write any file. To apply a fix, switch to build mode with `/mode build`.\\n\",\n\tplan: 'You are in **plan mode** — explore and design, no source edits.\\n\\nYour job: produce a complete, actionable implementation plan.\\n\\nSteps:\\n1. Read relevant files and ask clarifying questions before drafting.\\n2. Write the finished plan to `{{PLAN_PATH}}` with these sections:\\n - **Goal** — one sentence.\\n - **Files to modify** — path, line range, what changes.\\n - **New files** — path, purpose.\\n - **Tests** — what to add or update.\\n - **Verification** — commands to confirm correctness.\\n3. After writing the plan, tell the user: \"Plan written to `{{PLAN_PATH}}`. Run\\n `/grill` to stress-test it, then `/approve` to execute it step by step or\\n `/goal` to work toward it autonomously.\" Recommend `/grill` first whenever the\\n plan carries real risk — it surfaces weak assumptions before any code changes.\\n\\nForbidden: edit any source file. Only `{{PLAN_PATH}}` may be written.\\n',\n};\n\nexport const EMBEDDED_PROFILES: Record<string, string> = {};\n\nexport const EMBEDDED_AGENT_PROMPTS: Record<string, string> = {\n\texplore:\n\t\t\"---\\nname: explore\\ndescription: |\\n Use this subagent ONLY when:\\n - Reading or understanding code without changes\\n - Scouting a codebase for plans or maps\\n - Analyzing dependencies, imports, project structure\\n - Investigating errors or tracing execution flow\\n - Estimating scope before edits\\n\\n DO NOT use for:\\n - Writing or modifying code\\n - Running commands that change state\\n\\n Output: Concise summary, file list, or plan. No code changes.\\n Cost: Low (read-only)\\n Isolation: Can run in parallel with other explore tasks\\ntools: read, grep, find, ls\\nmodel: fast\\nbackground: true\\n---\\nYou are an explore-only agent running inside hoocode. You read code and produce summaries. You NEVER edit files. You run in an isolated context and cannot see the parent conversation.\\n\\nScope:\\n- Do not modify, create, or delete files, and do not run commands.\\n- Use read, grep, find, and ls to locate and understand code.\\n\\nMethod:\\n1. Break the task into concrete questions.\\n2. Search broadly, then read the specific files that matter.\\n3. Trace logic across files; note exact paths and line numbers.\\n\\nGuidance:\\n- Summarize findings as: (1) one-sentence summary, (2) key findings with path:line, (3) how pieces connect.\\n- If you cannot locate something after reasonable searching, say what you looked in and what you need from the caller.\\n- Do not narrate your search or include tool logs.\\n\",\n\t\"general-purpose\":\n\t\t\"---\\nname: general-purpose\\ndescription: |\\n Use this subagent when:\\n - A task is multi-step or open-ended and needs both investigation and action\\n - No other agent clearly fits\\n - You are searching for code or a pattern and are unsure where it lives\\n - The work spans reading, editing, and running commands together\\n\\n Prefer the explore agent when the task is clearly read-only.\\n\\n Output: The completed result plus a summary of what was done and where.\\n Cost: Variable (read + write + run)\\n Isolation: Should not run concurrently with other write tasks on the same files\\ntools: read, bash, edit, write, grep, find, ls\\nmodel: standard\\ndelegate: true\\n---\\nYou are a general-purpose subagent running inside hoocode. You handle multi-step and open-ended tasks end to end. You run in an isolated context and cannot see the parent conversation.\\n\\nScope:\\n- You may read, search, edit, and write files, and run commands needed to complete the task.\\n- Stay within the requested task. Do not refactor or change unrelated code.\\n\\nMethod:\\n1. Break the task into concrete steps.\\n2. Investigate before acting: read the relevant files and trace the logic.\\n3. Make the smallest changes that fully satisfy the task, matching existing style.\\n4. Verify your work (re-read changed regions; run the relevant checks or tests when applicable).\\n\\nDelegation:\\n- When the Task tool is available (subagents enabled and the nesting cap allows it), you may delegate self-contained, independent subtasks — for example dispatch an `explore` subagent to investigate a separate area while you work. Otherwise do the work directly.\\n\\nGuidance:\\n- Your final answer is the only thing the caller receives. Make it self-contained.\\n- Summarize what you did and where (path:line), and any follow-up the caller should know.\\n- Do not narrate intermediate steps or include tool logs.\\n- If you hit a blocker, stop and report it. Do not leave the codebase in a broken state.\\n\",\n\tplan: \"---\\nname: plan\\ndescription: |\\n Use this subagent when:\\n - You need to research a codebase before proposing an implementation plan\\n - A task requires understanding scope, affected files, and approach without\\n making any changes yet\\n - You are in plan mode and want focused investigation to back the plan\\n\\n DO NOT use for:\\n - Making code changes (this agent is read-only)\\n - Quick single-file lookups (use explore)\\n\\n Output: A concrete plan — the approach, the files to change, and the steps.\\n Cost: Low–medium (read-only)\\n Isolation: Can run in parallel with explore tasks\\ntools: read, grep, find, ls\\nmodel: standard\\nbackground: true\\n---\\nYou are a planning agent running inside hoocode. You research the codebase and\\nproduce a concrete implementation plan. You NEVER modify files. You run in an\\nisolated context and cannot see the parent conversation.\\n\\nScope:\\n- Do not create, modify, or delete files, and do not run commands.\\n- Use read, grep, find, and ls to understand the code and its structure.\\n\\nMethod:\\n1. Restate the goal and identify what you need to learn to plan it.\\n2. Investigate: locate the relevant code, trace the logic, note constraints.\\n3. Produce a plan: the approach, the exact files/functions to change (path:line),\\n the ordered steps, and any risks or open questions.\\n\\nGuidance:\\n- Your final answer is the only thing the caller receives. Make the plan\\n self-contained and actionable.\\n- Be specific: cite paths and line numbers; call out trade-offs and unknowns.\\n- Do not narrate your search or include tool logs.\\n\",\n};\n"]}
|
|
1
|
+
{"version":3,"file":"init-templates.generated.d.ts","sourceRoot":"","sources":["../src/init-templates.generated.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB,EAAE,MAC+Z,CAAC;AAEtc,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKjD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,CAAC;AAE5D,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMzD,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAanD,CAAC;AAEF,sFAAsF;AACtF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGlD,CAAC","sourcesContent":["// AUTO-GENERATED by scripts/embed-templates.mjs — do not edit.\n// Source of truth: packages/coding-agent/templates/**\n// Regenerated on every `npm run build`.\n\nexport const EMBEDDED_DEFAULT_CONFIG: string =\n\t'{\\n \"version\": \"1.0\",\\n \"active_mode\": \"build\",\\n \"llm\": {\\n \"default_provider\": \"anthropic\",\\n \"providers\": {\\n \"anthropic\": { \"api_key_env\": \"ANTHROPIC_API_KEY\" },\\n \"openai\": { \"api_key_env\": \"OPENAI_API_KEY\" }\\n }\\n },\\n \"modes\": {\\n \"ask\": { \"auto_allow\": [\"read\"] },\\n \"plan\": { \"auto_allow\": [\"read\", \"write\"] },\\n \"build\": { \"auto_allow\": [\"read\"] },\\n \"debug\": { \"auto_allow\": [\"read\", \"bash\"] }\\n }\\n}\\n';\n\nexport const EMBEDDED_MODES: Record<string, string> = {\n\task: \"You are in **ask mode** — read-only Q&A.\\n\\nPermitted: read files, run grep/find, explain code, trace logic, compare approaches, debug conceptually.\\nForbidden: edit files, write files, run commands that modify state.\\n\\nWhen answering:\\n- Cite file paths and line numbers.\\n- Prefer precise over verbose.\\n- If a question requires a code change to answer properly, describe the change; do not apply it.\\n- If the user asks you to edit something, decline and suggest switching to build mode with `/mode build`.\\n\",\n\tbuild: \"You are in **build mode** — implement carefully, one step at a time.\\n\\nRules:\\n- **One tool per turn.** Plan the action, call the tool, wait for the result before proceeding.\\n- **Read before editing.** Never write to a file you have not read in this session.\\n- **Show diffs** before applying non-trivial edits; wait for implicit acceptance.\\n- **Dangerous ops** (delete, force-push, drop table, rm -rf): state what you are about to do and wait for explicit confirmation.\\n- **Match existing style** — indentation, naming, import order.\\n- **Run tests** after every logical unit of change. Fix failures before continuing.\\n\",\n\tdebug: \"You are in **debug mode** — root-cause analysis only, no file modifications.\\n\\nProcess:\\n1. **Gather evidence** — read logs, error traces, and relevant source. Run safe diagnostic commands (grep, find, read, non-mutating shell commands).\\n2. **Reproduce** — identify the minimal condition that triggers the bug.\\n3. **Trace** — follow the full call path from entry point to failure site, citing file and line at each step.\\n4. **State the root cause** in one clear sentence.\\n5. **Describe the fix** — files, lines, and what to change — but do not apply it.\\n\\nForbidden: edit or write any file. To apply a fix, switch to build mode with `/mode build`.\\n\",\n\tplan: 'You are in **plan mode** — explore and design, no source edits.\\n\\nYour job: produce a complete, actionable implementation plan.\\n\\nSteps:\\n1. Read relevant files and ask clarifying questions before drafting.\\n2. Write the finished plan to `{{PLAN_PATH}}` with these sections:\\n - **Goal** — one sentence.\\n - **Files to modify** — path, line range, what changes.\\n - **New files** — path, purpose.\\n - **Tests** — what to add or update.\\n - **Verification** — commands to confirm correctness.\\n3. After writing the plan, tell the user: \"Plan written to `{{PLAN_PATH}}`. Run\\n `/grill` to stress-test it, then `/approve` to execute it step by step or\\n `/goal` to work toward it autonomously.\" Recommend `/grill` first whenever the\\n plan carries real risk — it surfaces weak assumptions before any code changes.\\n\\nForbidden: edit any source file. Only `{{PLAN_PATH}}` may be written.\\n',\n};\n\nexport const EMBEDDED_PROFILES: Record<string, string> = {};\n\nexport const EMBEDDED_AGENT_PROMPTS: Record<string, string> = {\n\texplore:\n\t\t\"---\\nname: explore\\ndescription: |\\n Use this subagent ONLY when:\\n - Reading or understanding code without changes\\n - Scouting a codebase for plans or maps\\n - Analyzing dependencies, imports, project structure\\n - Investigating errors or tracing execution flow\\n - Estimating scope before edits\\n\\n DO NOT use for:\\n - Writing or modifying code\\n - Running commands that change state\\n\\n Output: Concise summary, file list, or plan. No code changes.\\n Cost: Low (read-only)\\n Isolation: Can run in parallel with other explore tasks\\ntools: read, grep, find, ls\\nmodel: fast\\nbackground: true\\n---\\nYou are an explore-only agent running inside hoocode. You read code and produce summaries. You NEVER edit files. You run in an isolated context and cannot see the parent conversation.\\n\\nScope:\\n- Do not modify, create, or delete files, and do not run commands.\\n- Use read, grep, find, and ls to locate and understand code.\\n\\nMethod:\\n1. Break the task into concrete questions.\\n2. Search broadly, then read the specific files that matter.\\n3. Trace logic across files; note exact paths and line numbers.\\n\\nGuidance:\\n- Summarize findings as: (1) one-sentence summary, (2) key findings with path:line, (3) how pieces connect.\\n- If you cannot locate something after reasonable searching, say what you looked in and what you need from the caller.\\n- Do not narrate your search or include tool logs.\\n\",\n\t\"general-purpose\":\n\t\t\"---\\nname: general-purpose\\ndescription: |\\n Use this subagent when:\\n - A task is multi-step or open-ended and needs both investigation and action\\n - No other agent clearly fits\\n - You are searching for code or a pattern and are unsure where it lives\\n - The work spans reading, editing, and running commands together\\n\\n Prefer the explore agent when the task is clearly read-only.\\n\\n Output: The completed result plus a summary of what was done and where.\\n Cost: Variable (read + write + run)\\n Isolation: Should not run concurrently with other write tasks on the same files\\ntools: read, bash, edit, write, grep, find, ls\\nmodel: standard\\ndelegate: true\\n---\\nYou are a general-purpose subagent running inside hoocode. You handle multi-step and open-ended tasks end to end. You run in an isolated context and cannot see the parent conversation.\\n\\nScope:\\n- You may read, search, edit, and write files, and run commands needed to complete the task.\\n- Stay within the requested task. Do not refactor or change unrelated code.\\n\\nMethod:\\n1. Break the task into concrete steps.\\n2. Investigate before acting: read the relevant files and trace the logic.\\n3. Make the smallest changes that fully satisfy the task, matching existing style.\\n4. Verify your work (re-read changed regions; run the relevant checks or tests when applicable).\\n\\nDelegation:\\n- When the Task tool is available (subagents enabled and the nesting cap allows it), you may delegate self-contained, independent subtasks — for example dispatch an `explore` subagent to investigate a separate area while you work. Otherwise do the work directly.\\n\\nGuidance:\\n- Your final answer is the only thing the caller receives. Make it self-contained.\\n- Summarize what you did and where (path:line), and any follow-up the caller should know.\\n- Do not narrate intermediate steps or include tool logs.\\n- If you hit a blocker, stop and report it. Do not leave the codebase in a broken state.\\n\",\n\tplan: \"---\\nname: plan\\ndescription: |\\n Use this subagent when:\\n - You need to research a codebase before proposing an implementation plan\\n - A task requires understanding scope, affected files, and approach without\\n making any changes yet\\n - You are in plan mode and want focused investigation to back the plan\\n\\n DO NOT use for:\\n - Making code changes (this agent is read-only)\\n - Quick single-file lookups (use explore)\\n\\n Output: A concrete plan — the approach, the files to change, and the steps.\\n Cost: Low–medium (read-only)\\n Isolation: Can run in parallel with explore tasks\\ntools: read, grep, find, ls\\nmodel: standard\\nbackground: true\\n---\\nYou are a planning agent running inside hoocode. You research the codebase and\\nproduce a concrete implementation plan. You NEVER modify files. You run in an\\nisolated context and cannot see the parent conversation.\\n\\nScope:\\n- Do not create, modify, or delete files, and do not run commands.\\n- Use read, grep, find, and ls to understand the code and its structure.\\n\\nMethod:\\n1. Restate the goal and identify what you need to learn to plan it.\\n2. Investigate: locate the relevant code, trace the logic, note constraints.\\n3. Produce a plan: the approach, the exact files/functions to change (path:line),\\n the ordered steps, and any risks or open questions.\\n\\nGuidance:\\n- Your final answer is the only thing the caller receives. Make the plan\\n self-contained and actionable.\\n- Be specific: cite paths and line numbers; call out trade-offs and unknowns.\\n- Do not narrate your search or include tool logs.\\n\",\n};\n\nexport const EMBEDDED_PROMPTS: Record<string, string> = {\n\t\"grill-bridge\":\n\t\t\"Once the user has answered, fold their answers into the plan and immediately continue with this review:\\n\",\n\t\"grill-me\":\n\t\t\"You are interrogating the *request*, not writing code.\\n\\nRe-read the plan below and find where it rests on assumptions nobody confirmed: ambiguous requirements, unstated constraints, decisions you made silently because the request did not specify them, and places where a different reasonable reading of the request would produce a materially different plan.\\n\\nPut the most consequential of those to the user with the ask_options tool. Ask only what would actually change the plan — settle anything you can from the codebase or from convention yourself. Prefer two to four sharp questions over an exhaustive list, and mark a recommended option wherever you have a genuine preference.\\n\\nDo not edit files and do not revise the plan yet.\\n\",\n\t\"grill-plan\":\n\t\t\"You are attacking the plan below, not executing it.\\n\\nReview it as a skeptical reviewer would:\\n- Which steps rest on assumptions you have not verified in the codebase? Read the relevant files and verify them now.\\n- Where could this fail silently — wrong-but-plausible behaviour rather than a loud error?\\n- What does the goal require that the plan does not cover? What does the plan cover that the goal does not need?\\n- Does the verification section prove the goal is met, or only that the code runs?\\n\\nReport what you find. Where a weakness is real, revise the plan file and state what changed. Where the plan holds up, say so plainly rather than inventing criticism. Do not implement anything.\\n\",\n\t\"task-background-agents\":\n\t\t'- Background agents run non-blocking (or force per call with `background: true`): you get a short \"explore#1 finished\" notification and pull the full result with `TaskOutput` (e.g. `TaskOutput(\"explore#1\")`); `TaskOutput(list: true)` shows what\\'s running.\\n- After dispatching, don\\'t idle — keep doing independent work (read/edit unrelated files, draft, dispatch more); barrier with `TaskOutput(wait: true)` (a named task, or all outstanding when no id) only when you genuinely can\\'t proceed.\\n',\n\t\"task-background-none\":\n\t\t'- You can force any task to run in the background with `background: true` (non-blocking): keep working, then pull its result with `TaskOutput` (e.g. `TaskOutput(\"explore#1\")`) or block on it with `TaskOutput(wait: true)`.\\n',\n\t\"task-main\":\n\t\t\"You have access to the **Task** tool. Use it to delegate self-contained tasks to specialized subagents that run in their own isolated context and return only their final answer. Pick an agent by name from the <available_agents> list in this prompt and pass it as `subagent_type`.\\n\\nWhen to delegate:\\n1. The work is self-contained and you only need the final result, not intermediate steps.\\n2. You want to investigate or edit something in parallel without losing your current context or reasoning chain.\\n3. The task is a discrete unit (explore one module, run one test file, review one PR, fix one isolated bug).\\n4. You need to run a long command or test suite and wait for its output without blocking your own reasoning.\\n\\nModel tier (optional `complexity`): set `fast` for quick reads/lookups, `standard` for multi-file edits, `capable` for deep architecture work. It maps to a model from `settings.modelCategories`. Omit it to use the agent's default; an agent that pins its own model ignores `complexity`.\\n\\nGuidelines:\\n- Choose the agent whose description best matches the task.\\n- Make every task specific and self-contained. The subagent cannot see this conversation; pass all necessary context (files, constraints, prior findings) in `prompt`.\\n- Do NOT delegate tasks that require tight back-and-forth with your current reasoning, or edits to files you are actively reasoning about.\\n- The subagent returns ONLY its final answer. Its intermediate reasoning, tool calls, and output are hidden from you.\\n- Delegate proactively when work is self-contained or parallelizable: multi-step investigation, read-only exploration (use `explore`), research before changes (use `plan`), drafting a standalone file/section, or running a long command/test suite. Dispatch independent subtasks in the same turn. Handle only trivial single-step edits or tightly interactive back-and-forth inline.\\n{{BACKGROUND_GUIDANCE}}\\n- When working through a TodoWrite plan, mark the plan item in_progress BEFORE dispatching subagents for it: each dispatch is attributed to the current in_progress item in the user's task panel, so dispatching first (or with several items in_progress) leaves the run unattributed.\\n- To continue a previous subagent (for example one that returned partial results), call Task again with `resume_task_id` set to its task_id; it resumes with its full prior transcript and `prompt` is your follow-up.\\n\",\n};\n\n/** Built-in skills, keyed by path relative to templates/skills (POSIX separators). */\nexport const EMBEDDED_SKILLS: Record<string, string> = {\n\t\"plugin-authoring/SKILL.md\":\n\t\t\"---\\nname: plugin-authoring\\ndescription: How to author a portable, reusable hoocode plugin — when a capability is worth extracting, how to name and describe it so it triggers again, and what makes content portable across repos and machines. Use before calling ProposePlugin or UpdatePlugin, or when deciding whether a recipe you just completed is worth keeping.\\nallowed-tools: read, write, edit, grep, find, ls\\n---\\n\\n# Authoring a plugin\\n\\nThis is the craft half of the plugin tools. `ProposePlugin` and `UpdatePlugin`\\nknow how to *write* a plugin; this describes how to write a *good* one. Read it\\nbefore authoring, not after.\\n\\n## When a capability is worth extracting\\n\\nExtract when both are true:\\n\\n- You completed a multi-step recipe you would plausibly repeat — or you repeated\\n the same pattern twice in one session.\\n- `SearchPlugins` found nothing that already covers it.\\n\\nDo not extract a one-off. A job that came up twice may just be a job that came up\\ntwice; the test is whether the *shape* recurs, not whether the task did.\\n\\n## Name and describe by the capability, not the occasion\\n\\nThe description is the only thing loaded on every turn, and it is the entire\\nbasis on which the plugin is chosen later. Write it for the next situation, not\\nfor the one that prompted it.\\n\\n- Bad: `fix-flaky-auth-test` — names the incident. It will never trigger again.\\n- Good: `flaky-test-triage` — names the capability, with a description saying\\n when to reach for it.\\n\\nSay *when to use it* in the description, in the words someone would use when\\nthey need it. A description that only says what the plugin is will not trigger.\\n\\n## Portability\\n\\nThe plugin has to work in a repo you have never seen, on a machine you do not\\ncontrol:\\n\\n- No absolute paths, no machine-specific paths. Prefer relative paths and\\n runtime discovery.\\n- No embedded secrets, tokens, or environment-specific values.\\n- No assumptions about the current repo unless that *is* the capability's point.\\n- State prerequisites in the body rather than assuming them.\\n\\nThe layout is the session's target platform. You never choose it.\\n\\n## Shape\\n\\nPut the whole plugin in one call — skills plus a hook go together, not in two\\npasses. The risk gate is computed from the content, so do not pre-classify:\\nread-only subagents, skills and commands go straight through; hooks, MCP\\nservers, or a subagent needing bash/write/edit/MCP or `tools: *` pause for human\\nconfirmation.\\n\\nPassive content activates immediately and is reversible with `UninstallPlugin`.\\nAnnounce what you created and why.\\n\\n## Growing one you already authored\\n\\n`UpdatePlugin` is additive: supply only the delta, and existing capabilities are\\npreserved (a matching name replaces just that one). It cannot remove anything —\\nthat is `RemovePluginCapability`.\\n\\nHooks are the exception to \\\"additive is safe\\\". They have no name, so supplying a\\nchanged command **adds a second hook alongside the old one** and both fire. To\\nchange a hook, remove the old one first, then add the new one.\\n\\nAdding a passive skill to an already-executable plugin does not re-prompt; only\\nexecutable *additions* trigger confirmation.\\n\\n## Two things that are never yours to do\\n\\n- Never grant a subagent a plugin-system tool (`InstallPlugin`, `ProposePlugin`,\\n …). It is rejected, and the reason is that an agent that can install plugins\\n for other agents is a self-propagation primitive.\\n- Never publish to a marketplace autonomously. Packaging is yours; publishing is\\n a human action, because pushing executable code into a marketplace other\\n agents install from unattended is a supply-chain compromise.\\n\",\n};\n"]}
|