@kolisachint/hoocode-agent 0.4.129 → 0.4.130
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 +35 -0
- package/dist/cli/args.d.ts +7 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +18 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/extensions/plugins/authoring.d.ts +1 -2
- package/dist/core/extensions/plugins/authoring.d.ts.map +1 -1
- package/dist/core/extensions/plugins/authoring.js +5 -3
- package/dist/core/extensions/plugins/authoring.js.map +1 -1
- package/dist/core/extensions/plugins/formats/agents.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/agents.js +1 -0
- package/dist/core/extensions/plugins/formats/agents.js.map +1 -1
- package/dist/core/extensions/plugins/formats/claude.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/claude.js +1 -0
- package/dist/core/extensions/plugins/formats/claude.js.map +1 -1
- package/dist/core/extensions/plugins/formats/copilot.d.ts +24 -8
- package/dist/core/extensions/plugins/formats/copilot.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/copilot.js +85 -25
- package/dist/core/extensions/plugins/formats/copilot.js.map +1 -1
- package/dist/core/extensions/plugins/formats/index.d.ts +2 -1
- package/dist/core/extensions/plugins/formats/index.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/index.js +1 -0
- package/dist/core/extensions/plugins/formats/index.js.map +1 -1
- package/dist/core/extensions/plugins/formats/jsonManifest.d.ts +2 -0
- package/dist/core/extensions/plugins/formats/jsonManifest.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/jsonManifest.js +4 -2
- package/dist/core/extensions/plugins/formats/jsonManifest.js.map +1 -1
- package/dist/core/extensions/plugins/formats/platform-targets.d.ts +43 -0
- package/dist/core/extensions/plugins/formats/platform-targets.d.ts.map +1 -0
- package/dist/core/extensions/plugins/formats/platform-targets.js +74 -0
- package/dist/core/extensions/plugins/formats/platform-targets.js.map +1 -0
- package/dist/core/extensions/plugins/formats/shared.d.ts +13 -1
- package/dist/core/extensions/plugins/formats/shared.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/shared.js +36 -0
- package/dist/core/extensions/plugins/formats/shared.js.map +1 -1
- package/dist/core/extensions/plugins/formats/types.d.ts +17 -0
- package/dist/core/extensions/plugins/formats/types.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/types.js.map +1 -1
- package/dist/core/extensions/plugins/marketplace.d.ts.map +1 -1
- package/dist/core/extensions/plugins/marketplace.js +26 -9
- package/dist/core/extensions/plugins/marketplace.js.map +1 -1
- package/dist/core/settings-manager.d.ts +2 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +7 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/tools/propose-plugin.d.ts.map +1 -1
- package/dist/core/tools/propose-plugin.js +9 -4
- package/dist/core/tools/propose-plugin.js.map +1 -1
- package/dist/extensions/core/scaffold.d.ts +10 -2
- package/dist/extensions/core/scaffold.d.ts.map +1 -1
- package/dist/extensions/core/scaffold.js +111 -16
- package/dist/extensions/core/scaffold.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +25 -0
- package/dist/main.js.map +1 -1
- 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 +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"propose-plugin.js","sourceRoot":"","sources":["../../../src/core/tools/propose-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Capability authoring tools (spec §3). The two escalating-risk build paths are\n * kept as *separate tools* by design — not collapsed into one:\n *\n * ProposePlugin scaffold passive/low-risk capabilities — skills,\n * commands, and read-only subagents. Autonomous +\n * transparent (near-zero risk, reversible).\n * ProposeExecutablePlugin the risk-bearing path — hooks, MCP servers, and\n * mutating/high-privilege subagents. Draft → display\n * the code and the tool grant → human confirms →\n * activate. Bar >= install.\n *\n * Both author into `.agents/plugins/<id>/` in the requested vendor layouts\n * (Claude Code + GitHub Copilot by default) via the format registry, so results\n * are proper, publishable plugins that round-trip through parsePluginDir.\n *\n * Privilege-amplification guardrail: an authored subagent may never carry a\n * plugin-system (capability-acquisition) tool in its allowlist — enforced in\n * both tools — so a low-trust authored agent cannot bootstrap privilege.\n */\n\nimport { type Static, Type } from \"typebox\";\nimport {\n\tclassifyAllowlist,\n\tDEFAULT_AUTHORING_PLATFORMS,\n\tpluginExists,\n\twritePluginDraft,\n} from \"../extensions/plugins/authoring.js\";\nimport type { MarketplacePlatform, PluginDraft } from \"../extensions/plugins/formats/types.js\";\nimport type { ExtensionContext } from \"../extensions/types.js\";\nimport { defineTool, type ToolDefinition } from \"../extensions/types.js\";\nimport { PROPOSE_EXECUTABLE_PLUGIN_TOOL_NAME, PROPOSE_PLUGIN_TOOL_NAME } from \"./plugin-tool-names.js\";\n\nexport { PROPOSE_EXECUTABLE_PLUGIN_TOOL_NAME, PROPOSE_PLUGIN_TOOL_NAME } from \"./plugin-tool-names.js\";\n\nconst platformSchema = Type.Union([Type.Literal(\"claude\"), Type.Literal(\"github\"), Type.Literal(\"agents\")], {\n\tdescription: \"Target format: claude (Claude Code), github (GitHub Copilot), or agents (native).\",\n});\n\nconst skillSchema = Type.Object(\n\t{\n\t\tname: Type.String({ description: \"Skill name.\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"One-line trigger description (kept lazy in context).\" })),\n\t\tbody: Type.String({ description: \"SKILL.md instruction body (markdown).\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst commandSchema = Type.Object(\n\t{\n\t\tname: Type.String({ description: \"Command name (invoked as /name).\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"One-line description.\" })),\n\t\tbody: Type.String({ description: \"Prompt template body (markdown).\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst subagentSchema = Type.Object(\n\t{\n\t\tname: Type.String({ description: \"Subagent name.\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"When to dispatch this subagent.\" })),\n\t\ttools: Type.Optional(\n\t\t\tType.String({ description: \"Comma-separated allowed-tools, e.g. 'read, grep, glob'. Omit for none.\" }),\n\t\t),\n\t\tmodel: Type.Optional(Type.String({ description: \"Model override, or 'inherit'.\" })),\n\t\tbody: Type.String({ description: \"System-prompt / instruction body (markdown).\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst hookSchema = Type.Object(\n\t{\n\t\tevent: Type.String({ description: \"Event: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop, ...\" }),\n\t\tmatcher: Type.Optional(Type.String({ description: \"Regex matched against the tool name. Empty/'*' = all.\" })),\n\t\tcommand: Type.String({ description: \"Shell command to run on the event.\" }),\n\t\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds.\" })),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst mcpServerSchema = Type.Object(\n\t{\n\t\tname: Type.String({ description: \"MCP server name.\" }),\n\t\tcommand: Type.String({ description: \"Executable to launch the server.\" }),\n\t\targs: Type.Optional(Type.Array(Type.String(), { description: \"Command arguments.\" })),\n\t\tenv: Type.Optional(Type.Record(Type.String(), Type.String(), { description: \"Environment variables.\" })),\n\t},\n\t{ additionalProperties: false },\n);\n\nfunction resolvePlatforms(input: string[] | undefined): MarketplacePlatform[] {\n\treturn (input && input.length > 0 ? (input as MarketplacePlatform[]) : DEFAULT_AUTHORING_PLATFORMS).slice();\n}\n\nfunction summarizeWrite(id: string, platforms: MarketplacePlatform[], files: string[], dest: string): string {\n\treturn (\n\t\t`Authored plugin \"${id}\" (${platforms.join(\", \")}) with ${files.length} file(s) at ${dest}:\\n` +\n\t\tfiles.map((f) => ` ${f}`).join(\"\\n\") +\n\t\t`\\nRemove it with UninstallPlugin.`\n\t);\n}\n\n// ── ProposePlugin (scaffold path) ─────────────────────────────────────────────\n\nconst proposeParams = Type.Object(\n\t{\n\t\tid: Type.String({ description: \"Plugin id (directory + manifest name).\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"Plugin description.\" })),\n\t\tversion: Type.Optional(Type.String({ description: \"Plugin version, e.g. '0.1.0'.\" })),\n\t\tplatforms: Type.Optional(\n\t\t\tType.Array(platformSchema, { description: \"Formats to scaffold into. Default: claude + github.\" }),\n\t\t),\n\t\tskills: Type.Optional(Type.Array(skillSchema)),\n\t\tcommands: Type.Optional(Type.Array(commandSchema)),\n\t\tsubagents: Type.Optional(\n\t\t\tType.Array(subagentSchema, { description: \"Read-only subagents only (mutating grants are rejected here).\" }),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport interface ProposePluginDetails {\n\tid: string;\n\tauthored: boolean;\n}\n\nexport function createProposePluginToolDefinition(): ToolDefinition {\n\treturn defineTool<typeof proposeParams, ProposePluginDetails>({\n\t\tname: PROPOSE_PLUGIN_TOOL_NAME,\n\t\tlabel: PROPOSE_PLUGIN_TOOL_NAME,\n\t\tdescription:\n\t\t\t\"Author a new plugin from passive, low-risk capabilities — skills, slash commands, and READ-ONLY subagents — when no marketplace plugin fits a gap. Scaffolds a proper plugin (Claude Code + GitHub Copilot layouts by default). Autonomous and reversible. For hooks, MCP servers, or mutating/high-privilege subagents, use ProposeExecutablePlugin instead.\",\n\t\tpromptSnippet:\n\t\t\t\"Author a skill/command/read-only-subagent plugin to fill a capability gap (scaffold; reversible).\",\n\t\tpromptGuidelines: [\n\t\t\t\"Sense reusability proactively: when you complete a multi-step recipe you would plausibly repeat (or repeat the same pattern twice in one session) and SearchPlugins finds nothing that covers it, author it as a skill/command with ProposePlugin autonomously — announce what you created and why. It activates immediately and is reversible with UninstallPlugin.\",\n\t\t\t\"Use ProposePlugin only for passive capabilities: skills, commands, and subagents whose tools are read-only (read, grep, glob, webfetch).\",\n\t\t\t\"A subagent that needs Bash/Write/Edit/MCP or tools:* is mutating — author it with ProposeExecutablePlugin (human confirmation), not here.\",\n\t\t\t\"Never grant a subagent any plugin-system tool (InstallPlugin, ProposePlugin, ...); that is always rejected.\",\n\t\t],\n\t\tparameters: proposeParams,\n\t\tasync execute(_id, params: Static<typeof proposeParams>, _signal, _onUpdate, ctx: ExtensionContext) {\n\t\t\tconst platforms = resolvePlatforms(params.platforms);\n\n\t\t\t// Guardrail + risk gate on each subagent before writing anything.\n\t\t\tfor (const sa of params.subagents ?? []) {\n\t\t\t\tconst cls = classifyAllowlist(sa.tools);\n\t\t\t\tif (cls.pluginTools.length > 0) {\n\t\t\t\t\treturn reject(\n\t\t\t\t\t\t`Subagent \"${sa.name}\" requests plugin-system tools (${cls.pluginTools.join(\", \")}). ` +\n\t\t\t\t\t\t\t\"Authored subagents may never carry capability-acquisition tools.\",\n\t\t\t\t\t\tparams.id,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (cls.risk === \"mutating\") {\n\t\t\t\t\treturn reject(\n\t\t\t\t\t\t`Subagent \"${sa.name}\" has a mutating allowlist (${cls.reason}). ` +\n\t\t\t\t\t\t\t\"Use ProposeExecutablePlugin so the human can review and confirm the tool grant.\",\n\t\t\t\t\t\tparams.id,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pluginExists(ctx.cwd, params.id)) {\n\t\t\t\treturn reject(\n\t\t\t\t\t`A plugin named \"${params.id}\" already exists. Uninstall it first or pick another id.`,\n\t\t\t\t\tparams.id,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst draft: PluginDraft = {\n\t\t\t\tid: params.id,\n\t\t\t\tversion: params.version,\n\t\t\t\tdescription: params.description,\n\t\t\t\tsupportPlatform: platforms,\n\t\t\t\tskills: params.skills,\n\t\t\t\tcommands: params.commands,\n\t\t\t\tagents: params.subagents,\n\t\t\t};\n\t\t\tconst result = writePluginDraft(ctx.cwd, draft, platforms);\n\t\t\t// Passive capabilities activate live — the authored skill/command/subagent\n\t\t\t// is usable on the very next model request, in this same turn.\n\t\t\tconst activation = ctx.activatePlugin(result.dest);\n\t\t\tconst text = `${summarizeWrite(params.id, platforms, result.files, result.dest)}\\n${activation.message}`;\n\t\t\tctx.ui.notify(`Authored plugin \"${params.id}\" (${platforms.join(\", \")}).`, \"info\");\n\t\t\treturn { content: [{ type: \"text\" as const, text }], details: { id: params.id, authored: true } };\n\t\t},\n\t});\n}\n\n// ── ProposeExecutablePlugin (risk-bearing path) ───────────────────────────────\n\nconst proposeExecParams = Type.Object(\n\t{\n\t\tid: Type.String({ description: \"Plugin id (directory + manifest name).\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"Plugin description.\" })),\n\t\tversion: Type.Optional(Type.String({ description: \"Plugin version, e.g. '0.1.0'.\" })),\n\t\tplatforms: Type.Optional(\n\t\t\tType.Array(platformSchema, { description: \"Formats to scaffold into. Default: claude + github.\" }),\n\t\t),\n\t\thooks: Type.Optional(Type.Array(hookSchema)),\n\t\tmcpServers: Type.Optional(Type.Array(mcpServerSchema)),\n\t\tsubagents: Type.Optional(\n\t\t\tType.Array(subagentSchema, { description: \"Subagents with mutating/exec/network or tools:* allowlists.\" }),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport interface ProposeExecutablePluginDetails {\n\tid: string;\n\tauthored: boolean;\n\tconfirmed: boolean;\n}\n\n/** Build the human-facing review text: the executable code and every tool grant. */\nfunction buildReview(params: Static<typeof proposeExecParams>): string {\n\tconst lines: string[] = [`Plugin \"${params.id}\" wants to install executable capabilities:`];\n\tfor (const h of params.hooks ?? []) {\n\t\tlines.push(` hook [${h.event}${h.matcher ? ` matcher=${h.matcher}` : \"\"}]: ${h.command}`);\n\t}\n\tfor (const s of params.mcpServers ?? []) {\n\t\tlines.push(` mcp server \"${s.name}\": ${s.command}${s.args?.length ? ` ${s.args.join(\" \")}` : \"\"}`);\n\t}\n\tfor (const sa of params.subagents ?? []) {\n\t\tlines.push(` subagent \"${sa.name}\" tools: ${sa.tools ?? \"(none)\"}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function createProposeExecutablePluginToolDefinition(): ToolDefinition {\n\treturn defineTool<typeof proposeExecParams, ProposeExecutablePluginDetails>({\n\t\tname: PROPOSE_EXECUTABLE_PLUGIN_TOOL_NAME,\n\t\tlabel: PROPOSE_EXECUTABLE_PLUGIN_TOOL_NAME,\n\t\tdescription:\n\t\t\t\"Author a plugin that includes EXECUTABLE or high-privilege capabilities — hooks (run on tool events), MCP servers, or subagents with mutating/exec/network tool grants. The code and the exact tool grant are shown to the human, who must confirm before anything is activated. Use ProposePlugin for passive skills/commands/read-only subagents.\",\n\t\tpromptSnippet: \"Author a hook/MCP/high-privilege-subagent plugin (shows the code; requires human confirmation).\",\n\t\tpromptGuidelines: [\n\t\t\t\"ProposeExecutablePlugin always shows the code and tool grant and requires explicit human confirmation before activating.\",\n\t\t\t\"Never grant a subagent any plugin-system tool (InstallPlugin, ProposePlugin, ...); that is always rejected.\",\n\t\t\t\"Publishing a proven-useful plugin to a marketplace stays a human action — do not do it autonomously.\",\n\t\t],\n\t\tparameters: proposeExecParams,\n\t\tasync execute(_id, params: Static<typeof proposeExecParams>, _signal, _onUpdate, ctx: ExtensionContext) {\n\t\t\tconst platforms = resolvePlatforms(params.platforms);\n\n\t\t\t// Guardrail: authored subagents may never carry plugin-system tools.\n\t\t\tfor (const sa of params.subagents ?? []) {\n\t\t\t\tconst cls = classifyAllowlist(sa.tools);\n\t\t\t\tif (cls.pluginTools.length > 0) {\n\t\t\t\t\treturn rejectExec(\n\t\t\t\t\t\t`Subagent \"${sa.name}\" requests plugin-system tools (${cls.pluginTools.join(\", \")}). ` +\n\t\t\t\t\t\t\t\"Authored subagents may never carry capability-acquisition tools.\",\n\t\t\t\t\t\tparams.id,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst hasExecutable =\n\t\t\t\t(params.hooks?.length ?? 0) > 0 ||\n\t\t\t\t(params.mcpServers?.length ?? 0) > 0 ||\n\t\t\t\t(params.subagents?.length ?? 0) > 0;\n\t\t\tif (!hasExecutable) {\n\t\t\t\treturn rejectExec(\"Nothing to author. Provide hooks, mcpServers, or subagents.\", params.id);\n\t\t\t}\n\n\t\t\tif (pluginExists(ctx.cwd, params.id)) {\n\t\t\t\treturn rejectExec(\n\t\t\t\t\t`A plugin named \"${params.id}\" already exists. Uninstall it first or pick another id.`,\n\t\t\t\t\tparams.id,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Draft → display → confirm → activate. Fail closed without a UI to confirm on.\n\t\t\tconst review = buildReview(params);\n\t\t\tctx.ui.notify(review, \"warning\");\n\t\t\tif (!ctx.hasUI) {\n\t\t\t\treturn rejectExec(\n\t\t\t\t\t\"Authoring executable capabilities requires human confirmation, which is unavailable in this mode. \" +\n\t\t\t\t\t\t`Not activated.\\n${review}`,\n\t\t\t\t\tparams.id,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst confirmed = await ctx.ui.confirm(\n\t\t\t\t`Author executable plugin \"${params.id}\"?`,\n\t\t\t\t`${review}\\n\\nThis installs and can run the code above. Activate it?`,\n\t\t\t);\n\t\t\tif (!confirmed) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `Declined — plugin \"${params.id}\" was not authored.` }],\n\t\t\t\t\tdetails: { id: params.id, authored: false, confirmed: false },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst draft: PluginDraft = {\n\t\t\t\tid: params.id,\n\t\t\t\tversion: params.version,\n\t\t\t\tdescription: params.description,\n\t\t\t\tsupportPlatform: platforms,\n\t\t\t\thooks: params.hooks,\n\t\t\t\tmcpServers: params.mcpServers,\n\t\t\t\tagents: params.subagents,\n\t\t\t};\n\t\t\tconst result = writePluginDraft(ctx.cwd, draft, platforms);\n\t\t\t// Human confirmed above: activate now. Subagents go live immediately;\n\t\t\t// hooks/MCP servers activate via the automatic reload once the turn ends.\n\t\t\tconst activation = ctx.activatePlugin(result.dest);\n\t\t\tconst text = `${summarizeWrite(params.id, platforms, result.files, result.dest)}\\n${activation.message}`;\n\t\t\tctx.ui.notify(`Authored executable plugin \"${params.id}\" (${platforms.join(\", \")}).`, \"info\");\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: { id: params.id, authored: true, confirmed: true },\n\t\t\t};\n\t\t},\n\t});\n}\n\nfunction reject(\n\tmessage: string,\n\tid: string,\n): {\n\tcontent: { type: \"text\"; text: string }[];\n\tdetails: ProposePluginDetails;\n} {\n\treturn { content: [{ type: \"text\" as const, text: message }], details: { id, authored: false } };\n}\n\nfunction rejectExec(\n\tmessage: string,\n\tid: string,\n): {\n\tcontent: { type: \"text\"; text: string }[];\n\tdetails: ProposeExecutablePluginDetails;\n} {\n\treturn { content: [{ type: \"text\" as const, text: message }], details: { id, authored: false, confirmed: false } };\n}\n\n/** Both authoring tool definitions, for registration on the top-level agent. */\nexport function createProposePluginToolDefinitions(): ToolDefinition[] {\n\treturn [createProposePluginToolDefinition(), createProposeExecutablePluginToolDefinition()];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"propose-plugin.js","sourceRoot":"","sources":["../../../src/core/tools/propose-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Capability authoring tools (spec §3). The two escalating-risk build paths are\n * kept as *separate tools* by design — not collapsed into one:\n *\n * ProposePlugin scaffold passive/low-risk capabilities — skills,\n * commands, and read-only subagents. Autonomous +\n * transparent (near-zero risk, reversible).\n * ProposeExecutablePlugin the risk-bearing path — hooks, MCP servers, and\n * mutating/high-privilege subagents. Draft → display\n * the code and the tool grant → human confirms →\n * activate. Bar >= install.\n *\n * Both author into `.agents/plugins/<id>/` in the requested vendor layouts\n * (Claude Code + GitHub Copilot by default) via the format registry, so results\n * are proper, publishable plugins that round-trip through parsePluginDir.\n *\n * Privilege-amplification guardrail: an authored subagent may never carry a\n * plugin-system (capability-acquisition) tool in its allowlist — enforced in\n * both tools — so a low-trust authored agent cannot bootstrap privilege.\n */\n\nimport { type Static, Type } from \"typebox\";\nimport {\n\tclassifyAllowlist,\n\tpluginExists,\n\tresolveAuthoringPlatforms,\n\twritePluginDraft,\n} from \"../extensions/plugins/authoring.js\";\nimport type { MarketplacePlatform, PluginDraft } from \"../extensions/plugins/formats/types.js\";\nimport type { ExtensionContext } from \"../extensions/types.js\";\nimport { defineTool, type ToolDefinition } from \"../extensions/types.js\";\nimport { PROPOSE_EXECUTABLE_PLUGIN_TOOL_NAME, PROPOSE_PLUGIN_TOOL_NAME } from \"./plugin-tool-names.js\";\n\nexport { PROPOSE_EXECUTABLE_PLUGIN_TOOL_NAME, PROPOSE_PLUGIN_TOOL_NAME } from \"./plugin-tool-names.js\";\n\nconst platformSchema = Type.Union([Type.Literal(\"claude\"), Type.Literal(\"github\"), Type.Literal(\"agents\")], {\n\tdescription: \"Target format: claude (Claude Code), github (GitHub Copilot), or agents (native).\",\n});\n\nconst skillSchema = Type.Object(\n\t{\n\t\tname: Type.String({ description: \"Skill name.\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"One-line trigger description (kept lazy in context).\" })),\n\t\tbody: Type.String({ description: \"SKILL.md instruction body (markdown).\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst commandSchema = Type.Object(\n\t{\n\t\tname: Type.String({ description: \"Command name (invoked as /name).\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"One-line description.\" })),\n\t\tbody: Type.String({ description: \"Prompt template body (markdown).\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst subagentSchema = Type.Object(\n\t{\n\t\tname: Type.String({ description: \"Subagent name.\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"When to dispatch this subagent.\" })),\n\t\ttools: Type.Optional(\n\t\t\tType.String({ description: \"Comma-separated allowed-tools, e.g. 'read, grep, glob'. Omit for none.\" }),\n\t\t),\n\t\tmodel: Type.Optional(Type.String({ description: \"Model override, or 'inherit'.\" })),\n\t\tbody: Type.String({ description: \"System-prompt / instruction body (markdown).\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst hookSchema = Type.Object(\n\t{\n\t\tevent: Type.String({ description: \"Event: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop, ...\" }),\n\t\tmatcher: Type.Optional(Type.String({ description: \"Regex matched against the tool name. Empty/'*' = all.\" })),\n\t\tcommand: Type.String({ description: \"Shell command to run on the event.\" }),\n\t\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds.\" })),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst mcpServerSchema = Type.Object(\n\t{\n\t\tname: Type.String({ description: \"MCP server name.\" }),\n\t\tcommand: Type.String({ description: \"Executable to launch the server.\" }),\n\t\targs: Type.Optional(Type.Array(Type.String(), { description: \"Command arguments.\" })),\n\t\tenv: Type.Optional(Type.Record(Type.String(), Type.String(), { description: \"Environment variables.\" })),\n\t},\n\t{ additionalProperties: false },\n);\n\nfunction resolvePlatforms(input: string[] | undefined): MarketplacePlatform[] {\n\t// Explicit tool param → session --support-platform targets → claude + github.\n\treturn resolveAuthoringPlatforms(input as MarketplacePlatform[] | undefined);\n}\n\nfunction summarizeWrite(id: string, platforms: MarketplacePlatform[], files: string[], dest: string): string {\n\treturn (\n\t\t`Authored plugin \"${id}\" (${platforms.join(\", \")}) with ${files.length} file(s) at ${dest}:\\n` +\n\t\tfiles.map((f) => ` ${f}`).join(\"\\n\") +\n\t\t`\\nRemove it with UninstallPlugin.`\n\t);\n}\n\n// ── ProposePlugin (scaffold path) ─────────────────────────────────────────────\n\nconst proposeParams = Type.Object(\n\t{\n\t\tid: Type.String({ description: \"Plugin id (directory + manifest name).\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"Plugin description.\" })),\n\t\tversion: Type.Optional(Type.String({ description: \"Plugin version, e.g. '0.1.0'.\" })),\n\t\tplatforms: Type.Optional(\n\t\t\tType.Array(platformSchema, {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Formats to scaffold into. Default: the session's --support-platform targets, else claude + github.\",\n\t\t\t}),\n\t\t),\n\t\tskills: Type.Optional(Type.Array(skillSchema)),\n\t\tcommands: Type.Optional(Type.Array(commandSchema)),\n\t\tsubagents: Type.Optional(\n\t\t\tType.Array(subagentSchema, { description: \"Read-only subagents only (mutating grants are rejected here).\" }),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport interface ProposePluginDetails {\n\tid: string;\n\tauthored: boolean;\n}\n\nexport function createProposePluginToolDefinition(): ToolDefinition {\n\treturn defineTool<typeof proposeParams, ProposePluginDetails>({\n\t\tname: PROPOSE_PLUGIN_TOOL_NAME,\n\t\tlabel: PROPOSE_PLUGIN_TOOL_NAME,\n\t\tdescription:\n\t\t\t\"Author a new plugin from passive, low-risk capabilities — skills, slash commands, and READ-ONLY subagents — when no marketplace plugin fits a gap. Scaffolds a proper plugin (Claude Code + GitHub Copilot layouts by default). Autonomous and reversible. For hooks, MCP servers, or mutating/high-privilege subagents, use ProposeExecutablePlugin instead.\",\n\t\tpromptSnippet:\n\t\t\t\"Author a skill/command/read-only-subagent plugin to fill a capability gap (scaffold; reversible).\",\n\t\tpromptGuidelines: [\n\t\t\t\"Sense reusability proactively: when you complete a multi-step recipe you would plausibly repeat (or repeat the same pattern twice in one session) and SearchPlugins finds nothing that covers it, author it as a skill/command with ProposePlugin autonomously — announce what you created and why. It activates immediately and is reversible with UninstallPlugin.\",\n\t\t\t\"Use ProposePlugin only for passive capabilities: skills, commands, and subagents whose tools are read-only (read, grep, glob, webfetch).\",\n\t\t\t\"A subagent that needs Bash/Write/Edit/MCP or tools:* is mutating — author it with ProposeExecutablePlugin (human confirmation), not here.\",\n\t\t\t\"Never grant a subagent any plugin-system tool (InstallPlugin, ProposePlugin, ...); that is always rejected.\",\n\t\t],\n\t\tparameters: proposeParams,\n\t\tasync execute(_id, params: Static<typeof proposeParams>, _signal, _onUpdate, ctx: ExtensionContext) {\n\t\t\tconst platforms = resolvePlatforms(params.platforms);\n\n\t\t\t// Guardrail + risk gate on each subagent before writing anything.\n\t\t\tfor (const sa of params.subagents ?? []) {\n\t\t\t\tconst cls = classifyAllowlist(sa.tools);\n\t\t\t\tif (cls.pluginTools.length > 0) {\n\t\t\t\t\treturn reject(\n\t\t\t\t\t\t`Subagent \"${sa.name}\" requests plugin-system tools (${cls.pluginTools.join(\", \")}). ` +\n\t\t\t\t\t\t\t\"Authored subagents may never carry capability-acquisition tools.\",\n\t\t\t\t\t\tparams.id,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (cls.risk === \"mutating\") {\n\t\t\t\t\treturn reject(\n\t\t\t\t\t\t`Subagent \"${sa.name}\" has a mutating allowlist (${cls.reason}). ` +\n\t\t\t\t\t\t\t\"Use ProposeExecutablePlugin so the human can review and confirm the tool grant.\",\n\t\t\t\t\t\tparams.id,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pluginExists(ctx.cwd, params.id)) {\n\t\t\t\treturn reject(\n\t\t\t\t\t`A plugin named \"${params.id}\" already exists. Uninstall it first or pick another id.`,\n\t\t\t\t\tparams.id,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst draft: PluginDraft = {\n\t\t\t\tid: params.id,\n\t\t\t\tversion: params.version,\n\t\t\t\tdescription: params.description,\n\t\t\t\tsupportPlatform: platforms,\n\t\t\t\tskills: params.skills,\n\t\t\t\tcommands: params.commands,\n\t\t\t\tagents: params.subagents,\n\t\t\t};\n\t\t\tconst result = writePluginDraft(ctx.cwd, draft, platforms);\n\t\t\t// Passive capabilities activate live — the authored skill/command/subagent\n\t\t\t// is usable on the very next model request, in this same turn.\n\t\t\tconst activation = ctx.activatePlugin(result.dest);\n\t\t\tconst text = `${summarizeWrite(params.id, platforms, result.files, result.dest)}\\n${activation.message}`;\n\t\t\tctx.ui.notify(`Authored plugin \"${params.id}\" (${platforms.join(\", \")}).`, \"info\");\n\t\t\treturn { content: [{ type: \"text\" as const, text }], details: { id: params.id, authored: true } };\n\t\t},\n\t});\n}\n\n// ── ProposeExecutablePlugin (risk-bearing path) ───────────────────────────────\n\nconst proposeExecParams = Type.Object(\n\t{\n\t\tid: Type.String({ description: \"Plugin id (directory + manifest name).\" }),\n\t\tdescription: Type.Optional(Type.String({ description: \"Plugin description.\" })),\n\t\tversion: Type.Optional(Type.String({ description: \"Plugin version, e.g. '0.1.0'.\" })),\n\t\tplatforms: Type.Optional(\n\t\t\tType.Array(platformSchema, {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Formats to scaffold into. Default: the session's --support-platform targets, else claude + github.\",\n\t\t\t}),\n\t\t),\n\t\thooks: Type.Optional(Type.Array(hookSchema)),\n\t\tmcpServers: Type.Optional(Type.Array(mcpServerSchema)),\n\t\tsubagents: Type.Optional(\n\t\t\tType.Array(subagentSchema, { description: \"Subagents with mutating/exec/network or tools:* allowlists.\" }),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport interface ProposeExecutablePluginDetails {\n\tid: string;\n\tauthored: boolean;\n\tconfirmed: boolean;\n}\n\n/** Build the human-facing review text: the executable code and every tool grant. */\nfunction buildReview(params: Static<typeof proposeExecParams>): string {\n\tconst lines: string[] = [`Plugin \"${params.id}\" wants to install executable capabilities:`];\n\tfor (const h of params.hooks ?? []) {\n\t\tlines.push(` hook [${h.event}${h.matcher ? ` matcher=${h.matcher}` : \"\"}]: ${h.command}`);\n\t}\n\tfor (const s of params.mcpServers ?? []) {\n\t\tlines.push(` mcp server \"${s.name}\": ${s.command}${s.args?.length ? ` ${s.args.join(\" \")}` : \"\"}`);\n\t}\n\tfor (const sa of params.subagents ?? []) {\n\t\tlines.push(` subagent \"${sa.name}\" tools: ${sa.tools ?? \"(none)\"}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function createProposeExecutablePluginToolDefinition(): ToolDefinition {\n\treturn defineTool<typeof proposeExecParams, ProposeExecutablePluginDetails>({\n\t\tname: PROPOSE_EXECUTABLE_PLUGIN_TOOL_NAME,\n\t\tlabel: PROPOSE_EXECUTABLE_PLUGIN_TOOL_NAME,\n\t\tdescription:\n\t\t\t\"Author a plugin that includes EXECUTABLE or high-privilege capabilities — hooks (run on tool events), MCP servers, or subagents with mutating/exec/network tool grants. The code and the exact tool grant are shown to the human, who must confirm before anything is activated. Use ProposePlugin for passive skills/commands/read-only subagents.\",\n\t\tpromptSnippet: \"Author a hook/MCP/high-privilege-subagent plugin (shows the code; requires human confirmation).\",\n\t\tpromptGuidelines: [\n\t\t\t\"ProposeExecutablePlugin always shows the code and tool grant and requires explicit human confirmation before activating.\",\n\t\t\t\"Never grant a subagent any plugin-system tool (InstallPlugin, ProposePlugin, ...); that is always rejected.\",\n\t\t\t\"Publishing a proven-useful plugin to a marketplace stays a human action — do not do it autonomously.\",\n\t\t],\n\t\tparameters: proposeExecParams,\n\t\tasync execute(_id, params: Static<typeof proposeExecParams>, _signal, _onUpdate, ctx: ExtensionContext) {\n\t\t\tconst platforms = resolvePlatforms(params.platforms);\n\n\t\t\t// Guardrail: authored subagents may never carry plugin-system tools.\n\t\t\tfor (const sa of params.subagents ?? []) {\n\t\t\t\tconst cls = classifyAllowlist(sa.tools);\n\t\t\t\tif (cls.pluginTools.length > 0) {\n\t\t\t\t\treturn rejectExec(\n\t\t\t\t\t\t`Subagent \"${sa.name}\" requests plugin-system tools (${cls.pluginTools.join(\", \")}). ` +\n\t\t\t\t\t\t\t\"Authored subagents may never carry capability-acquisition tools.\",\n\t\t\t\t\t\tparams.id,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst hasExecutable =\n\t\t\t\t(params.hooks?.length ?? 0) > 0 ||\n\t\t\t\t(params.mcpServers?.length ?? 0) > 0 ||\n\t\t\t\t(params.subagents?.length ?? 0) > 0;\n\t\t\tif (!hasExecutable) {\n\t\t\t\treturn rejectExec(\"Nothing to author. Provide hooks, mcpServers, or subagents.\", params.id);\n\t\t\t}\n\n\t\t\tif (pluginExists(ctx.cwd, params.id)) {\n\t\t\t\treturn rejectExec(\n\t\t\t\t\t`A plugin named \"${params.id}\" already exists. Uninstall it first or pick another id.`,\n\t\t\t\t\tparams.id,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Draft → display → confirm → activate. Fail closed without a UI to confirm on.\n\t\t\tconst review = buildReview(params);\n\t\t\tctx.ui.notify(review, \"warning\");\n\t\t\tif (!ctx.hasUI) {\n\t\t\t\treturn rejectExec(\n\t\t\t\t\t\"Authoring executable capabilities requires human confirmation, which is unavailable in this mode. \" +\n\t\t\t\t\t\t`Not activated.\\n${review}`,\n\t\t\t\t\tparams.id,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst confirmed = await ctx.ui.confirm(\n\t\t\t\t`Author executable plugin \"${params.id}\"?`,\n\t\t\t\t`${review}\\n\\nThis installs and can run the code above. Activate it?`,\n\t\t\t);\n\t\t\tif (!confirmed) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `Declined — plugin \"${params.id}\" was not authored.` }],\n\t\t\t\t\tdetails: { id: params.id, authored: false, confirmed: false },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst draft: PluginDraft = {\n\t\t\t\tid: params.id,\n\t\t\t\tversion: params.version,\n\t\t\t\tdescription: params.description,\n\t\t\t\tsupportPlatform: platforms,\n\t\t\t\thooks: params.hooks,\n\t\t\t\tmcpServers: params.mcpServers,\n\t\t\t\tagents: params.subagents,\n\t\t\t};\n\t\t\tconst result = writePluginDraft(ctx.cwd, draft, platforms);\n\t\t\t// Human confirmed above: activate now. Subagents go live immediately;\n\t\t\t// hooks/MCP servers activate via the automatic reload once the turn ends.\n\t\t\tconst activation = ctx.activatePlugin(result.dest);\n\t\t\tconst text = `${summarizeWrite(params.id, platforms, result.files, result.dest)}\\n${activation.message}`;\n\t\t\tctx.ui.notify(`Authored executable plugin \"${params.id}\" (${platforms.join(\", \")}).`, \"info\");\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: { id: params.id, authored: true, confirmed: true },\n\t\t\t};\n\t\t},\n\t});\n}\n\nfunction reject(\n\tmessage: string,\n\tid: string,\n): {\n\tcontent: { type: \"text\"; text: string }[];\n\tdetails: ProposePluginDetails;\n} {\n\treturn { content: [{ type: \"text\" as const, text: message }], details: { id, authored: false } };\n}\n\nfunction rejectExec(\n\tmessage: string,\n\tid: string,\n): {\n\tcontent: { type: \"text\"; text: string }[];\n\tdetails: ProposeExecutablePluginDetails;\n} {\n\treturn { content: [{ type: \"text\" as const, text: message }], details: { id, authored: false, confirmed: false } };\n}\n\n/** Both authoring tool definitions, for registration on the top-level agent. */\nexport function createProposePluginToolDefinitions(): ToolDefinition[] {\n\treturn [createProposePluginToolDefinition(), createProposeExecutablePluginToolDefinition()];\n}\n"]}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scaffold commands — /new-skill, /new-agent, and /new-command.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Without `--support-platform`, each creates a ready-to-edit resource file
|
|
5
|
+
* under `.hoocode/` (hoocode's private surface), picked up on the next /reload.
|
|
6
|
+
*
|
|
7
|
+
* With `--support-platform` (or the `supportPlatform` setting), the scaffold
|
|
8
|
+
* instead lands in each target platform's *workspace* conventions via the
|
|
9
|
+
* format registry's per-adapter {@link WorkspaceLayout} — e.g.
|
|
10
|
+
* `--support-platform copilot` writes `.github/skills/<name>/SKILL.md`,
|
|
11
|
+
* `.github/agents/<name>.agent.md`, and `.github/prompts/<name>.prompt.md`,
|
|
12
|
+
* while `claude` writes `.claude/skills|agents|commands/`. hoocode reads all
|
|
13
|
+
* of these back, so the scaffold is live after /reload either way.
|
|
6
14
|
*/
|
|
7
15
|
import type { ExtensionAPI } from "../../core/extensions/types.js";
|
|
8
16
|
export declare function setupScaffold(pi: ExtensionAPI): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/extensions/core/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,gCAAgC,CAAC;AAW5F,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkKpD","sourcesContent":["/**\n * Scaffold commands — /new-skill, /new-agent, and /new-command.\n *\n * Each creates a ready-to-edit resource file under `.hoocode/` with valid\n * frontmatter, picked up on the next /reload.\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\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\nexport function setupScaffold(pi: ExtensionAPI): void {\n\t// ── /new-skill <name> ─────────────────────────────────────────────────────\n\t// Creates .hoocode/skills/<name>/SKILL.md with a valid Agent Skills frontmatter\n\t// template so the file is ready to edit and will be picked up on next reload.\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 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\t`# ${name}`,\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"TODO: write the skill instructions here.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"When relative paths appear below, they are resolved from this file's directory.\",\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`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 .hoocode/agents/<name>.md following the Claude Code subagent standard\n\t// (name, description, tools comma-string, model alias, optional background).\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 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 .hoocode/commands/<name>.md with a slash-command prompt-template\n\t// frontmatter (name, description, argument-hint) so it is ready to edit and\n\t// picked up on next reload. Body supports $1, $@, $ARGUMENTS placeholders.\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 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;;;;;;;;;;;;;GAaG;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 * Without `--support-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 `--support-platform` (or the `supportPlatform` 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 * `--support-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 { getSupportPlatforms } 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 `--support-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 --support-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 = getSupportPlatforms();\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 = getSupportPlatforms();\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 = getSupportPlatforms();\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,11 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scaffold commands — /new-skill, /new-agent, and /new-command.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Without `--support-platform`, each creates a ready-to-edit resource file
|
|
5
|
+
* under `.hoocode/` (hoocode's private surface), picked up on the next /reload.
|
|
6
|
+
*
|
|
7
|
+
* With `--support-platform` (or the `supportPlatform` setting), the scaffold
|
|
8
|
+
* instead lands in each target platform's *workspace* conventions via the
|
|
9
|
+
* format registry's per-adapter {@link WorkspaceLayout} — e.g.
|
|
10
|
+
* `--support-platform copilot` writes `.github/skills/<name>/SKILL.md`,
|
|
11
|
+
* `.github/agents/<name>.agent.md`, and `.github/prompts/<name>.prompt.md`,
|
|
12
|
+
* while `claude` writes `.claude/skills|agents|commands/`. hoocode reads all
|
|
13
|
+
* of these back, so the scaffold is live after /reload either way.
|
|
6
14
|
*/
|
|
7
15
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
8
|
-
import { join } from "node:path";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
import { getFormatByPlatform } from "../../core/extensions/plugins/formats/index.js";
|
|
18
|
+
import { getSupportPlatforms } from "../../core/extensions/plugins/formats/platform-targets.js";
|
|
9
19
|
/** Validates a resource name: lowercase a-z, 0-9, hyphens, no leading/trailing/double hyphens. */
|
|
10
20
|
function validateResourceName(name) {
|
|
11
21
|
if (!name)
|
|
@@ -18,10 +28,71 @@ function validateResourceName(name) {
|
|
|
18
28
|
return "name must not contain consecutive hyphens";
|
|
19
29
|
return null;
|
|
20
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Write one scaffolded artifact into every `--support-platform` target's
|
|
33
|
+
* workspace layout. Existing files are never clobbered — they are reported and
|
|
34
|
+
* skipped. Returns true when the platform-targeted path handled the command.
|
|
35
|
+
*/
|
|
36
|
+
function scaffoldForPlatforms(ctx, command, platforms, emit) {
|
|
37
|
+
const created = [];
|
|
38
|
+
const skipped = [];
|
|
39
|
+
for (const platform of platforms) {
|
|
40
|
+
const adapter = getFormatByPlatform(platform);
|
|
41
|
+
if (!adapter)
|
|
42
|
+
continue;
|
|
43
|
+
const file = emit(adapter.workspace);
|
|
44
|
+
const abs = join(ctx.cwd, file.path);
|
|
45
|
+
if (existsSync(abs)) {
|
|
46
|
+
skipped.push(file.path);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
50
|
+
writeFileSync(abs, file.content, "utf8");
|
|
51
|
+
created.push(file.path);
|
|
52
|
+
}
|
|
53
|
+
const lines = [];
|
|
54
|
+
if (created.length > 0) {
|
|
55
|
+
lines.push(`Created (${platforms.join(", ")}):`, ...created.map((f) => ` ${f}`));
|
|
56
|
+
lines.push("Edit the file(s), then run /reload to activate.");
|
|
57
|
+
}
|
|
58
|
+
if (skipped.length > 0) {
|
|
59
|
+
lines.push(`Skipped (already exist):`, ...skipped.map((f) => ` ${f}`));
|
|
60
|
+
}
|
|
61
|
+
if (lines.length === 0) {
|
|
62
|
+
lines.push(`/${command}: no writable platform targets resolved`);
|
|
63
|
+
}
|
|
64
|
+
ctx.ui.notify(lines.join("\n"), created.length > 0 ? "info" : "warning");
|
|
65
|
+
}
|
|
66
|
+
const SKILL_BODY_TEMPLATE = (name) => [
|
|
67
|
+
`# ${name}`,
|
|
68
|
+
"",
|
|
69
|
+
"TODO: write the skill instructions here.",
|
|
70
|
+
"",
|
|
71
|
+
"When relative paths appear below, they are resolved from this file's directory.",
|
|
72
|
+
"",
|
|
73
|
+
].join("\n");
|
|
74
|
+
const AGENT_BODY_TEMPLATE = (name) => [
|
|
75
|
+
`You are a ${name} subagent.`,
|
|
76
|
+
"You run in an isolated context and cannot see the parent conversation.",
|
|
77
|
+
"",
|
|
78
|
+
"TODO: write the system prompt here.",
|
|
79
|
+
"",
|
|
80
|
+
"Your final message must contain ONLY your answer — it is the only output",
|
|
81
|
+
"the caller receives. Do not include intermediate reasoning or tool logs.",
|
|
82
|
+
"",
|
|
83
|
+
].join("\n");
|
|
84
|
+
const COMMAND_BODY_TEMPLATE = (name) => [
|
|
85
|
+
`Run the /${name} command with arguments: **$ARGUMENTS**.`,
|
|
86
|
+
"",
|
|
87
|
+
"TODO: write the instructions here. Placeholders you can use:",
|
|
88
|
+
"- $1, $2, ... for positional arguments",
|
|
89
|
+
"- $@ or $ARGUMENTS for all arguments",
|
|
90
|
+
"",
|
|
91
|
+
].join("\n");
|
|
21
92
|
export function setupScaffold(pi) {
|
|
22
93
|
// ── /new-skill <name> ─────────────────────────────────────────────────────
|
|
23
|
-
// Creates
|
|
24
|
-
//
|
|
94
|
+
// Creates a SKILL.md with valid Agent Skills frontmatter — under .hoocode/ by
|
|
95
|
+
// default, or under each --support-platform target's skills directory.
|
|
25
96
|
pi.registerCommand("new-skill", {
|
|
26
97
|
description: "Scaffold a new skill. Usage: /new-skill <name>",
|
|
27
98
|
getArgumentCompletions: () => [],
|
|
@@ -32,6 +103,15 @@ export function setupScaffold(pi) {
|
|
|
32
103
|
ctx.ui.notify(`/new-skill: ${error}. Usage: /new-skill <name>`, "warning");
|
|
33
104
|
return;
|
|
34
105
|
}
|
|
106
|
+
const platforms = getSupportPlatforms();
|
|
107
|
+
if (platforms) {
|
|
108
|
+
scaffoldForPlatforms(ctx, "new-skill", platforms, (ws) => ws.emitSkill({
|
|
109
|
+
name,
|
|
110
|
+
description: "TODO: describe when to use this skill — the agent reads this to decide whether to load it.",
|
|
111
|
+
body: SKILL_BODY_TEMPLATE(name),
|
|
112
|
+
}));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
35
115
|
const skillDir = join(ctx.cwd, ".hoocode", "skills", name);
|
|
36
116
|
const skillFile = join(skillDir, "SKILL.md");
|
|
37
117
|
if (existsSync(skillFile)) {
|
|
@@ -48,19 +128,15 @@ export function setupScaffold(pi) {
|
|
|
48
128
|
"allowed-tools: read, bash",
|
|
49
129
|
"---",
|
|
50
130
|
"",
|
|
51
|
-
|
|
52
|
-
"",
|
|
53
|
-
"TODO: write the skill instructions here.",
|
|
54
|
-
"",
|
|
55
|
-
"When relative paths appear below, they are resolved from this file's directory.",
|
|
56
|
-
"",
|
|
131
|
+
SKILL_BODY_TEMPLATE(name),
|
|
57
132
|
].join("\n"), "utf8");
|
|
58
133
|
ctx.ui.notify(`Skill created: ${join(".hoocode", "skills", name, "SKILL.md")}\nEdit the file, then run /reload to activate it.`, "info");
|
|
59
134
|
},
|
|
60
135
|
});
|
|
61
136
|
// ── /new-agent <name> ─────────────────────────────────────────────────────
|
|
62
|
-
// Creates .hoocode/agents/<name>.md
|
|
63
|
-
//
|
|
137
|
+
// Creates a subagent definition — .hoocode/agents/<name>.md by default, or
|
|
138
|
+
// each platform's convention (.claude/agents/<name>.md,
|
|
139
|
+
// .github/agents/<name>.agent.md with a YAML-list tools grant, ...).
|
|
64
140
|
pi.registerCommand("new-agent", {
|
|
65
141
|
description: "Scaffold a new subagent. Usage: /new-agent <name>",
|
|
66
142
|
getArgumentCompletions: () => [],
|
|
@@ -71,6 +147,16 @@ export function setupScaffold(pi) {
|
|
|
71
147
|
ctx.ui.notify(`/new-agent: ${error}. Usage: /new-agent <name>`, "warning");
|
|
72
148
|
return;
|
|
73
149
|
}
|
|
150
|
+
const platforms = getSupportPlatforms();
|
|
151
|
+
if (platforms) {
|
|
152
|
+
scaffoldForPlatforms(ctx, "new-agent", platforms, (ws) => ws.emitAgent({
|
|
153
|
+
name,
|
|
154
|
+
description: "TODO: describe the task(s) to delegate to this agent.",
|
|
155
|
+
tools: "read, bash",
|
|
156
|
+
body: AGENT_BODY_TEMPLATE(name),
|
|
157
|
+
}));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
74
160
|
const agentsDir = join(ctx.cwd, ".hoocode", "agents");
|
|
75
161
|
const agentFile = join(agentsDir, `${name}.md`);
|
|
76
162
|
if (existsSync(agentFile)) {
|
|
@@ -103,9 +189,9 @@ export function setupScaffold(pi) {
|
|
|
103
189
|
},
|
|
104
190
|
});
|
|
105
191
|
// ── /new-command <name> ───────────────────────────────────────────────────
|
|
106
|
-
// Creates .hoocode/commands/<name>.md
|
|
107
|
-
//
|
|
108
|
-
//
|
|
192
|
+
// Creates a slash-command prompt template — .hoocode/commands/<name>.md by
|
|
193
|
+
// default, or each platform's convention (.claude/commands/<name>.md,
|
|
194
|
+
// .github/prompts/<name>.prompt.md, ...).
|
|
109
195
|
pi.registerCommand("new-command", {
|
|
110
196
|
description: "Scaffold a new slash command. Usage: /new-command <name>",
|
|
111
197
|
getArgumentCompletions: () => [],
|
|
@@ -116,6 +202,15 @@ export function setupScaffold(pi) {
|
|
|
116
202
|
ctx.ui.notify(`/new-command: ${error}. Usage: /new-command <name>`, "warning");
|
|
117
203
|
return;
|
|
118
204
|
}
|
|
205
|
+
const platforms = getSupportPlatforms();
|
|
206
|
+
if (platforms) {
|
|
207
|
+
scaffoldForPlatforms(ctx, "new-command", platforms, (ws) => ws.emitCommand({
|
|
208
|
+
name,
|
|
209
|
+
description: `TODO: describe what /${name} does and when to use it.`,
|
|
210
|
+
body: COMMAND_BODY_TEMPLATE(name),
|
|
211
|
+
}));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
119
214
|
const commandsDir = join(ctx.cwd, ".hoocode", "commands");
|
|
120
215
|
const commandFile = join(commandsDir, `${name}.md`);
|
|
121
216
|
if (existsSync(commandFile)) {
|
|
@@ -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 * Each creates a ready-to-edit resource file under `.hoocode/` with valid\n * frontmatter, picked up on the next /reload.\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\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\nexport function setupScaffold(pi: ExtensionAPI): void {\n\t// ── /new-skill <name> ─────────────────────────────────────────────────────\n\t// Creates .hoocode/skills/<name>/SKILL.md with a valid Agent Skills frontmatter\n\t// template so the file is ready to edit and will be picked up on next reload.\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 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\t`# ${name}`,\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"TODO: write the skill instructions here.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"When relative paths appear below, they are resolved from this file's directory.\",\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`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 .hoocode/agents/<name>.md following the Claude Code subagent standard\n\t// (name, description, tools comma-string, model alias, optional background).\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 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 .hoocode/commands/<name>.md with a slash-command prompt-template\n\t// frontmatter (name, description, argument-hint) so it is ready to edit and\n\t// picked up on next reload. Body supports $1, $@, $ARGUMENTS placeholders.\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 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 * Without `--support-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 `--support-platform` (or the `supportPlatform` 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 * `--support-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 { getSupportPlatforms } 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 `--support-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 --support-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 = getSupportPlatforms();\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 = getSupportPlatforms();\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 = getSupportPlatforms();\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"]}
|