@kolisachint/hoocode-agent 0.3.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cli/args.d.ts +1 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +5 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/extensions/loader.d.ts.map +1 -1
  7. package/dist/core/extensions/loader.js +9 -1
  8. package/dist/core/extensions/loader.js.map +1 -1
  9. package/dist/core/resource-loader.d.ts.map +1 -1
  10. package/dist/core/resource-loader.js +12 -2
  11. package/dist/core/resource-loader.js.map +1 -1
  12. package/dist/core/settings-manager.d.ts +3 -0
  13. package/dist/core/settings-manager.d.ts.map +1 -1
  14. package/dist/core/settings-manager.js +8 -0
  15. package/dist/core/settings-manager.js.map +1 -1
  16. package/dist/core/subagent.d.ts +46 -0
  17. package/dist/core/subagent.d.ts.map +1 -0
  18. package/dist/core/subagent.js +139 -0
  19. package/dist/core/subagent.js.map +1 -0
  20. package/dist/core/task-store.d.ts +37 -0
  21. package/dist/core/task-store.d.ts.map +1 -0
  22. package/dist/core/task-store.js +57 -0
  23. package/dist/core/task-store.js.map +1 -0
  24. package/dist/core/tools/subagent.d.ts +18 -0
  25. package/dist/core/tools/subagent.d.ts.map +1 -0
  26. package/dist/core/tools/subagent.js +99 -0
  27. package/dist/core/tools/subagent.js.map +1 -0
  28. package/dist/init-templates.generated.d.ts +1 -0
  29. package/dist/init-templates.generated.d.ts.map +1 -1
  30. package/dist/init-templates.generated.js +12 -5
  31. package/dist/init-templates.generated.js.map +1 -1
  32. package/dist/main.d.ts.map +1 -1
  33. package/dist/main.js +6 -0
  34. package/dist/main.js.map +1 -1
  35. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  36. package/dist/modes/interactive/components/footer.js +41 -0
  37. package/dist/modes/interactive/components/footer.js.map +1 -1
  38. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  39. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  40. package/dist/modes/interactive/interactive-mode.js +8 -0
  41. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  42. package/examples/README.md +1 -1
  43. package/examples/extensions/README.md +0 -1
  44. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  45. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  46. package/examples/extensions/sandbox/package.json +1 -1
  47. package/examples/extensions/with-deps/package.json +1 -1
  48. package/package.json +6 -5
  49. package/templates/subagent/edit.md +17 -0
  50. package/templates/subagent/explore.md +16 -0
  51. package/templates/subagent/fix.md +17 -0
  52. package/templates/subagent/review.md +16 -0
  53. package/templates/subagent/test.md +15 -0
  54. package/examples/extensions/subagent/README.md +0 -172
  55. package/examples/extensions/subagent/agents/planner.md +0 -37
  56. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  57. package/examples/extensions/subagent/agents/scout.md +0 -50
  58. package/examples/extensions/subagent/agents/worker.md +0 -24
  59. package/examples/extensions/subagent/agents.ts +0 -126
  60. package/examples/extensions/subagent/index.ts +0 -987
  61. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  62. package/examples/extensions/subagent/prompts/implement.md +0 -10
  63. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../src/core/subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAoB,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAGvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE1E,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAAiD,CAAC;AAWpG,MAAM,WAAW,kBAAkB;IAClC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,IAAI,EAAE,YAAY,CAAC;IACnB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,8DAA8D;IAC9D,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mEAAmE;AACnE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAMlE;AA2DD;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA4DtF","sourcesContent":["/**\n * Subagent core: spawn a fresh, isolated agent loop for one delegated task.\n *\n * Each invocation creates a brand-new in-process AgentSession with:\n * - a clean, minimal system prompt (the mode template, no parent history),\n * - an in-memory session (nothing persisted to disk),\n * - a tool allowlist scoped to the mode.\n *\n * The subagent runs to completion and returns ONLY its final answer string;\n * intermediate reasoning, tool calls, and tool output are discarded.\n */\n\nimport type { AssistantMessage, Model } from \"@kolisachint/hoocode-ai\";\nimport { EMBEDDED_SUBAGENT_PROMPTS } from \"../init-templates.generated.js\";\nimport { createExtensionRuntime, type LoadExtensionsResult } from \"./extensions/index.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { ResourceExtensionPaths, ResourceLoader } from \"./resource-loader.js\";\nimport { createAgentSession } from \"./sdk.js\";\nimport { SessionManager } from \"./session-manager.js\";\n\nexport type SubagentMode = \"explore\" | \"edit\" | \"test\" | \"fix\" | \"review\";\n\nexport const SUBAGENT_MODES: readonly SubagentMode[] = [\"explore\", \"edit\", \"test\", \"fix\", \"review\"];\n\n/** Tool allowlist per mode. Read-only modes deliberately omit edit/write. */\nconst MODE_TOOLS: Record<SubagentMode, string[]> = {\n\texplore: [\"read\", \"grep\", \"find\", \"ls\", \"bash\"],\n\tedit: [\"read\", \"edit\", \"write\", \"grep\", \"find\", \"ls\", \"bash\"],\n\ttest: [\"read\", \"bash\", \"grep\", \"find\", \"ls\"],\n\tfix: [\"read\", \"edit\", \"write\", \"bash\", \"grep\", \"find\", \"ls\"],\n\treview: [\"read\", \"grep\", \"find\", \"ls\", \"bash\"],\n};\n\nexport interface RunSubagentOptions {\n\t/** The task to delegate. */\n\ttask: string;\n\t/** Optional context distilled from the parent conversation. */\n\tcontext?: string;\n\t/** Which subagent mode to run. */\n\tmode: SubagentMode;\n\t/** Working directory for the subagent. */\n\tcwd: string;\n\t/** Model to use. When omitted the subagent picks the configured default. */\n\tmodel?: Model<any>;\n\t/** Model registry to reuse (shares the parent's auth). */\n\tmodelRegistry?: ModelRegistry;\n\t/** Abort signal from the parent; aborts the subagent loop. */\n\tsignal?: AbortSignal;\n}\n\nexport interface SubagentResult {\n\tmode: SubagentMode;\n\t/** The subagent's final answer (its last assistant text), or \"\" on failure. */\n\tanswer: string;\n\tok: boolean;\n\t/** Populated when ok is false. */\n\terror?: string;\n}\n\n/** Return the clean, minimal system prompt for a subagent mode. */\nexport function getSubagentSystemPrompt(mode: SubagentMode): string {\n\tconst prompt = EMBEDDED_SUBAGENT_PROMPTS[mode];\n\tif (!prompt) {\n\t\tthrow new Error(`No system prompt template for subagent mode \"${mode}\"`);\n\t}\n\treturn prompt;\n}\n\n/**\n * Resource loader that gives the subagent a clean context: just the mode's\n * system prompt, with no project context files, skills, prompts, or extensions.\n */\nclass MinimalResourceLoader implements ResourceLoader {\n\tprivate readonly extensionsResult: LoadExtensionsResult;\n\n\tconstructor(private readonly systemPrompt: string) {\n\t\tthis.extensionsResult = { extensions: [], errors: [], runtime: createExtensionRuntime() };\n\t}\n\n\tgetExtensions(): LoadExtensionsResult {\n\t\treturn this.extensionsResult;\n\t}\n\n\tgetSkills() {\n\t\treturn { skills: [], diagnostics: [] };\n\t}\n\n\tgetPrompts() {\n\t\treturn { prompts: [], diagnostics: [] };\n\t}\n\n\tgetThemes() {\n\t\treturn { themes: [], diagnostics: [] };\n\t}\n\n\tgetAgentsFiles() {\n\t\treturn { agentsFiles: [], warnings: [] };\n\t}\n\n\tgetSystemPrompt(): string | undefined {\n\t\treturn this.systemPrompt;\n\t}\n\n\tgetAppendSystemPrompt(): string[] {\n\t\treturn [];\n\t}\n\n\textendResources(_paths: ResourceExtensionPaths): void {\n\t\t// Subagents do not accept additional resource paths.\n\t}\n\n\tasync reload(): Promise<void> {\n\t\t// Nothing to reload: the context is fixed at construction.\n\t}\n}\n\nfunction composePrompt(task: string, context: string | undefined): string {\n\tconst trimmedContext = context?.trim();\n\tconst trimmedTask = task.trim();\n\tif (trimmedContext) {\n\t\treturn `Context from the calling agent:\\n\\n${trimmedContext}\\n\\nTask: ${trimmedTask}`;\n\t}\n\treturn `Task: ${trimmedTask}`;\n}\n\n/**\n * Run one subagent task to completion and return only its final answer.\n */\nexport async function runSubagent(options: RunSubagentOptions): Promise<SubagentResult> {\n\tconst { task, context, mode, cwd, model, modelRegistry, signal } = options;\n\n\tif (signal?.aborted) {\n\t\treturn { mode, answer: \"\", ok: false, error: \"Subagent aborted before starting.\" };\n\t}\n\n\tconst systemPrompt = getSubagentSystemPrompt(mode);\n\tconst { session } = await createAgentSession({\n\t\tcwd,\n\t\tmodel,\n\t\tmodelRegistry,\n\t\ttools: MODE_TOOLS[mode],\n\t\tresourceLoader: new MinimalResourceLoader(systemPrompt),\n\t\tsessionManager: SessionManager.inMemory(cwd),\n\t});\n\n\tconst onAbort = () => {\n\t\tvoid session.abort();\n\t};\n\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\ttry {\n\t\tif (!session.model) {\n\t\t\treturn { mode, answer: \"\", ok: false, error: \"No model available for the subagent.\" };\n\t\t}\n\n\t\tawait session.bindExtensions({ onError: () => {} });\n\t\tawait session.prompt(composePrompt(task, context), {\n\t\t\texpandPromptTemplates: false,\n\t\t\tsource: \"extension\",\n\t\t});\n\n\t\tconst messages = session.messages;\n\t\tconst last = messages[messages.length - 1];\n\t\tif (last?.role === \"assistant\") {\n\t\t\tconst assistant = last as AssistantMessage;\n\t\t\tif (assistant.stopReason === \"error\" || assistant.stopReason === \"aborted\") {\n\t\t\t\treturn {\n\t\t\t\t\tmode,\n\t\t\t\t\tanswer: \"\",\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: assistant.errorMessage || `Subagent ${assistant.stopReason}.`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tconst answer = session.getLastAssistantText() ?? \"\";\n\t\treturn { mode, answer, ok: true };\n\t} catch (error) {\n\t\treturn {\n\t\t\tmode,\n\t\t\tanswer: \"\",\n\t\t\tok: false,\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t} finally {\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\tsession.dispose();\n\t}\n}\n"]}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Subagent core: spawn a fresh, isolated agent loop for one delegated task.
3
+ *
4
+ * Each invocation creates a brand-new in-process AgentSession with:
5
+ * - a clean, minimal system prompt (the mode template, no parent history),
6
+ * - an in-memory session (nothing persisted to disk),
7
+ * - a tool allowlist scoped to the mode.
8
+ *
9
+ * The subagent runs to completion and returns ONLY its final answer string;
10
+ * intermediate reasoning, tool calls, and tool output are discarded.
11
+ */
12
+ import { EMBEDDED_SUBAGENT_PROMPTS } from "../init-templates.generated.js";
13
+ import { createExtensionRuntime } from "./extensions/index.js";
14
+ import { createAgentSession } from "./sdk.js";
15
+ import { SessionManager } from "./session-manager.js";
16
+ export const SUBAGENT_MODES = ["explore", "edit", "test", "fix", "review"];
17
+ /** Tool allowlist per mode. Read-only modes deliberately omit edit/write. */
18
+ const MODE_TOOLS = {
19
+ explore: ["read", "grep", "find", "ls", "bash"],
20
+ edit: ["read", "edit", "write", "grep", "find", "ls", "bash"],
21
+ test: ["read", "bash", "grep", "find", "ls"],
22
+ fix: ["read", "edit", "write", "bash", "grep", "find", "ls"],
23
+ review: ["read", "grep", "find", "ls", "bash"],
24
+ };
25
+ /** Return the clean, minimal system prompt for a subagent mode. */
26
+ export function getSubagentSystemPrompt(mode) {
27
+ const prompt = EMBEDDED_SUBAGENT_PROMPTS[mode];
28
+ if (!prompt) {
29
+ throw new Error(`No system prompt template for subagent mode "${mode}"`);
30
+ }
31
+ return prompt;
32
+ }
33
+ /**
34
+ * Resource loader that gives the subagent a clean context: just the mode's
35
+ * system prompt, with no project context files, skills, prompts, or extensions.
36
+ */
37
+ class MinimalResourceLoader {
38
+ systemPrompt;
39
+ extensionsResult;
40
+ constructor(systemPrompt) {
41
+ this.systemPrompt = systemPrompt;
42
+ this.extensionsResult = { extensions: [], errors: [], runtime: createExtensionRuntime() };
43
+ }
44
+ getExtensions() {
45
+ return this.extensionsResult;
46
+ }
47
+ getSkills() {
48
+ return { skills: [], diagnostics: [] };
49
+ }
50
+ getPrompts() {
51
+ return { prompts: [], diagnostics: [] };
52
+ }
53
+ getThemes() {
54
+ return { themes: [], diagnostics: [] };
55
+ }
56
+ getAgentsFiles() {
57
+ return { agentsFiles: [], warnings: [] };
58
+ }
59
+ getSystemPrompt() {
60
+ return this.systemPrompt;
61
+ }
62
+ getAppendSystemPrompt() {
63
+ return [];
64
+ }
65
+ extendResources(_paths) {
66
+ // Subagents do not accept additional resource paths.
67
+ }
68
+ async reload() {
69
+ // Nothing to reload: the context is fixed at construction.
70
+ }
71
+ }
72
+ function composePrompt(task, context) {
73
+ const trimmedContext = context?.trim();
74
+ const trimmedTask = task.trim();
75
+ if (trimmedContext) {
76
+ return `Context from the calling agent:\n\n${trimmedContext}\n\nTask: ${trimmedTask}`;
77
+ }
78
+ return `Task: ${trimmedTask}`;
79
+ }
80
+ /**
81
+ * Run one subagent task to completion and return only its final answer.
82
+ */
83
+ export async function runSubagent(options) {
84
+ const { task, context, mode, cwd, model, modelRegistry, signal } = options;
85
+ if (signal?.aborted) {
86
+ return { mode, answer: "", ok: false, error: "Subagent aborted before starting." };
87
+ }
88
+ const systemPrompt = getSubagentSystemPrompt(mode);
89
+ const { session } = await createAgentSession({
90
+ cwd,
91
+ model,
92
+ modelRegistry,
93
+ tools: MODE_TOOLS[mode],
94
+ resourceLoader: new MinimalResourceLoader(systemPrompt),
95
+ sessionManager: SessionManager.inMemory(cwd),
96
+ });
97
+ const onAbort = () => {
98
+ void session.abort();
99
+ };
100
+ signal?.addEventListener("abort", onAbort, { once: true });
101
+ try {
102
+ if (!session.model) {
103
+ return { mode, answer: "", ok: false, error: "No model available for the subagent." };
104
+ }
105
+ await session.bindExtensions({ onError: () => { } });
106
+ await session.prompt(composePrompt(task, context), {
107
+ expandPromptTemplates: false,
108
+ source: "extension",
109
+ });
110
+ const messages = session.messages;
111
+ const last = messages[messages.length - 1];
112
+ if (last?.role === "assistant") {
113
+ const assistant = last;
114
+ if (assistant.stopReason === "error" || assistant.stopReason === "aborted") {
115
+ return {
116
+ mode,
117
+ answer: "",
118
+ ok: false,
119
+ error: assistant.errorMessage || `Subagent ${assistant.stopReason}.`,
120
+ };
121
+ }
122
+ }
123
+ const answer = session.getLastAssistantText() ?? "";
124
+ return { mode, answer, ok: true };
125
+ }
126
+ catch (error) {
127
+ return {
128
+ mode,
129
+ answer: "",
130
+ ok: false,
131
+ error: error instanceof Error ? error.message : String(error),
132
+ };
133
+ }
134
+ finally {
135
+ signal?.removeEventListener("abort", onAbort);
136
+ session.dispose();
137
+ }
138
+ }
139
+ //# sourceMappingURL=subagent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent.js","sourceRoot":"","sources":["../../src/core/subagent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Subagent core: spawn a fresh, isolated agent loop for one delegated task.\n *\n * Each invocation creates a brand-new in-process AgentSession with:\n * - a clean, minimal system prompt (the mode template, no parent history),\n * - an in-memory session (nothing persisted to disk),\n * - a tool allowlist scoped to the mode.\n *\n * The subagent runs to completion and returns ONLY its final answer string;\n * intermediate reasoning, tool calls, and tool output are discarded.\n */\n\nimport type { AssistantMessage, Model } from \"@kolisachint/hoocode-ai\";\nimport { EMBEDDED_SUBAGENT_PROMPTS } from \"../init-templates.generated.js\";\nimport { createExtensionRuntime, type LoadExtensionsResult } from \"./extensions/index.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { ResourceExtensionPaths, ResourceLoader } from \"./resource-loader.js\";\nimport { createAgentSession } from \"./sdk.js\";\nimport { SessionManager } from \"./session-manager.js\";\n\nexport type SubagentMode = \"explore\" | \"edit\" | \"test\" | \"fix\" | \"review\";\n\nexport const SUBAGENT_MODES: readonly SubagentMode[] = [\"explore\", \"edit\", \"test\", \"fix\", \"review\"];\n\n/** Tool allowlist per mode. Read-only modes deliberately omit edit/write. */\nconst MODE_TOOLS: Record<SubagentMode, string[]> = {\n\texplore: [\"read\", \"grep\", \"find\", \"ls\", \"bash\"],\n\tedit: [\"read\", \"edit\", \"write\", \"grep\", \"find\", \"ls\", \"bash\"],\n\ttest: [\"read\", \"bash\", \"grep\", \"find\", \"ls\"],\n\tfix: [\"read\", \"edit\", \"write\", \"bash\", \"grep\", \"find\", \"ls\"],\n\treview: [\"read\", \"grep\", \"find\", \"ls\", \"bash\"],\n};\n\nexport interface RunSubagentOptions {\n\t/** The task to delegate. */\n\ttask: string;\n\t/** Optional context distilled from the parent conversation. */\n\tcontext?: string;\n\t/** Which subagent mode to run. */\n\tmode: SubagentMode;\n\t/** Working directory for the subagent. */\n\tcwd: string;\n\t/** Model to use. When omitted the subagent picks the configured default. */\n\tmodel?: Model<any>;\n\t/** Model registry to reuse (shares the parent's auth). */\n\tmodelRegistry?: ModelRegistry;\n\t/** Abort signal from the parent; aborts the subagent loop. */\n\tsignal?: AbortSignal;\n}\n\nexport interface SubagentResult {\n\tmode: SubagentMode;\n\t/** The subagent's final answer (its last assistant text), or \"\" on failure. */\n\tanswer: string;\n\tok: boolean;\n\t/** Populated when ok is false. */\n\terror?: string;\n}\n\n/** Return the clean, minimal system prompt for a subagent mode. */\nexport function getSubagentSystemPrompt(mode: SubagentMode): string {\n\tconst prompt = EMBEDDED_SUBAGENT_PROMPTS[mode];\n\tif (!prompt) {\n\t\tthrow new Error(`No system prompt template for subagent mode \"${mode}\"`);\n\t}\n\treturn prompt;\n}\n\n/**\n * Resource loader that gives the subagent a clean context: just the mode's\n * system prompt, with no project context files, skills, prompts, or extensions.\n */\nclass MinimalResourceLoader implements ResourceLoader {\n\tprivate readonly extensionsResult: LoadExtensionsResult;\n\n\tconstructor(private readonly systemPrompt: string) {\n\t\tthis.extensionsResult = { extensions: [], errors: [], runtime: createExtensionRuntime() };\n\t}\n\n\tgetExtensions(): LoadExtensionsResult {\n\t\treturn this.extensionsResult;\n\t}\n\n\tgetSkills() {\n\t\treturn { skills: [], diagnostics: [] };\n\t}\n\n\tgetPrompts() {\n\t\treturn { prompts: [], diagnostics: [] };\n\t}\n\n\tgetThemes() {\n\t\treturn { themes: [], diagnostics: [] };\n\t}\n\n\tgetAgentsFiles() {\n\t\treturn { agentsFiles: [], warnings: [] };\n\t}\n\n\tgetSystemPrompt(): string | undefined {\n\t\treturn this.systemPrompt;\n\t}\n\n\tgetAppendSystemPrompt(): string[] {\n\t\treturn [];\n\t}\n\n\textendResources(_paths: ResourceExtensionPaths): void {\n\t\t// Subagents do not accept additional resource paths.\n\t}\n\n\tasync reload(): Promise<void> {\n\t\t// Nothing to reload: the context is fixed at construction.\n\t}\n}\n\nfunction composePrompt(task: string, context: string | undefined): string {\n\tconst trimmedContext = context?.trim();\n\tconst trimmedTask = task.trim();\n\tif (trimmedContext) {\n\t\treturn `Context from the calling agent:\\n\\n${trimmedContext}\\n\\nTask: ${trimmedTask}`;\n\t}\n\treturn `Task: ${trimmedTask}`;\n}\n\n/**\n * Run one subagent task to completion and return only its final answer.\n */\nexport async function runSubagent(options: RunSubagentOptions): Promise<SubagentResult> {\n\tconst { task, context, mode, cwd, model, modelRegistry, signal } = options;\n\n\tif (signal?.aborted) {\n\t\treturn { mode, answer: \"\", ok: false, error: \"Subagent aborted before starting.\" };\n\t}\n\n\tconst systemPrompt = getSubagentSystemPrompt(mode);\n\tconst { session } = await createAgentSession({\n\t\tcwd,\n\t\tmodel,\n\t\tmodelRegistry,\n\t\ttools: MODE_TOOLS[mode],\n\t\tresourceLoader: new MinimalResourceLoader(systemPrompt),\n\t\tsessionManager: SessionManager.inMemory(cwd),\n\t});\n\n\tconst onAbort = () => {\n\t\tvoid session.abort();\n\t};\n\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\ttry {\n\t\tif (!session.model) {\n\t\t\treturn { mode, answer: \"\", ok: false, error: \"No model available for the subagent.\" };\n\t\t}\n\n\t\tawait session.bindExtensions({ onError: () => {} });\n\t\tawait session.prompt(composePrompt(task, context), {\n\t\t\texpandPromptTemplates: false,\n\t\t\tsource: \"extension\",\n\t\t});\n\n\t\tconst messages = session.messages;\n\t\tconst last = messages[messages.length - 1];\n\t\tif (last?.role === \"assistant\") {\n\t\t\tconst assistant = last as AssistantMessage;\n\t\t\tif (assistant.stopReason === \"error\" || assistant.stopReason === \"aborted\") {\n\t\t\t\treturn {\n\t\t\t\t\tmode,\n\t\t\t\t\tanswer: \"\",\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: assistant.errorMessage || `Subagent ${assistant.stopReason}.`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tconst answer = session.getLastAssistantText() ?? \"\";\n\t\treturn { mode, answer, ok: true };\n\t} catch (error) {\n\t\treturn {\n\t\t\tmode,\n\t\t\tanswer: \"\",\n\t\t\tok: false,\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t} finally {\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\tsession.dispose();\n\t}\n}\n"]}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Minimal in-process task store.
3
+ *
4
+ * Tracks short-lived tasks (e.g. subagent delegations) so the TUI footer can
5
+ * display active work. It is a process-level singleton because the tool that
6
+ * creates tasks and the footer that renders them live in the same process and
7
+ * there is no cross-process boundary to cross.
8
+ */
9
+ export type TaskStatus = "pending" | "in_progress" | "done" | "failed";
10
+ export interface Task {
11
+ readonly id: number;
12
+ title: string;
13
+ status: TaskStatus;
14
+ /** Subagent mode when this task is owned by a subagent (e.g. "explore"). */
15
+ subagentMode?: string;
16
+ readonly createdAt: number;
17
+ updatedAt: number;
18
+ }
19
+ export interface CreateTaskOptions {
20
+ subagentMode?: string;
21
+ }
22
+ export type TaskPatch = Partial<Pick<Task, "title" | "status" | "subagentMode">>;
23
+ type Listener = () => void;
24
+ declare class TaskStore {
25
+ private tasks;
26
+ private nextId;
27
+ private readonly listeners;
28
+ create(title: string, options?: CreateTaskOptions): Task;
29
+ update(id: number, patch: TaskPatch): void;
30
+ list(): readonly Task[];
31
+ subscribe(listener: Listener): () => void;
32
+ private emit;
33
+ }
34
+ /** Shared, process-wide task store. */
35
+ export declare const taskStore: TaskStore;
36
+ export {};
37
+ //# sourceMappingURL=task-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../src/core/task-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvE,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC;AAEjF,KAAK,QAAQ,GAAG,MAAM,IAAI,CAAC;AAE3B,cAAM,SAAS;IACd,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuB;IAEjD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,IAAI,CAa3D;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAQzC;IAED,IAAI,IAAI,SAAS,IAAI,EAAE,CAEtB;IAED,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,IAAI,CAKxC;IAED,OAAO,CAAC,IAAI;CAKZ;AAED,uCAAuC;AACvC,eAAO,MAAM,SAAS,WAAkB,CAAC","sourcesContent":["/**\n * Minimal in-process task store.\n *\n * Tracks short-lived tasks (e.g. subagent delegations) so the TUI footer can\n * display active work. It is a process-level singleton because the tool that\n * creates tasks and the footer that renders them live in the same process and\n * there is no cross-process boundary to cross.\n */\n\nexport type TaskStatus = \"pending\" | \"in_progress\" | \"done\" | \"failed\";\n\nexport interface Task {\n\treadonly id: number;\n\ttitle: string;\n\tstatus: TaskStatus;\n\t/** Subagent mode when this task is owned by a subagent (e.g. \"explore\"). */\n\tsubagentMode?: string;\n\treadonly createdAt: number;\n\tupdatedAt: number;\n}\n\nexport interface CreateTaskOptions {\n\tsubagentMode?: string;\n}\n\nexport type TaskPatch = Partial<Pick<Task, \"title\" | \"status\" | \"subagentMode\">>;\n\ntype Listener = () => void;\n\nclass TaskStore {\n\tprivate tasks: Task[] = [];\n\tprivate nextId = 1;\n\tprivate readonly listeners = new Set<Listener>();\n\n\tcreate(title: string, options: CreateTaskOptions = {}): Task {\n\t\tconst now = Date.now();\n\t\tconst task: Task = {\n\t\t\tid: this.nextId++,\n\t\t\ttitle: title.trim() || \"(untitled task)\",\n\t\t\tstatus: \"pending\",\n\t\t\tsubagentMode: options.subagentMode,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t};\n\t\tthis.tasks.push(task);\n\t\tthis.emit();\n\t\treturn task;\n\t}\n\n\tupdate(id: number, patch: TaskPatch): void {\n\t\tconst task = this.tasks.find((t) => t.id === id);\n\t\tif (!task) return;\n\t\tif (patch.title !== undefined) task.title = patch.title;\n\t\tif (patch.status !== undefined) task.status = patch.status;\n\t\tif (patch.subagentMode !== undefined) task.subagentMode = patch.subagentMode;\n\t\ttask.updatedAt = Date.now();\n\t\tthis.emit();\n\t}\n\n\tlist(): readonly Task[] {\n\t\treturn this.tasks;\n\t}\n\n\tsubscribe(listener: Listener): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\n\tprivate emit(): void {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n}\n\n/** Shared, process-wide task store. */\nexport const taskStore = new TaskStore();\n"]}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Minimal in-process task store.
3
+ *
4
+ * Tracks short-lived tasks (e.g. subagent delegations) so the TUI footer can
5
+ * display active work. It is a process-level singleton because the tool that
6
+ * creates tasks and the footer that renders them live in the same process and
7
+ * there is no cross-process boundary to cross.
8
+ */
9
+ class TaskStore {
10
+ tasks = [];
11
+ nextId = 1;
12
+ listeners = new Set();
13
+ create(title, options = {}) {
14
+ const now = Date.now();
15
+ const task = {
16
+ id: this.nextId++,
17
+ title: title.trim() || "(untitled task)",
18
+ status: "pending",
19
+ subagentMode: options.subagentMode,
20
+ createdAt: now,
21
+ updatedAt: now,
22
+ };
23
+ this.tasks.push(task);
24
+ this.emit();
25
+ return task;
26
+ }
27
+ update(id, patch) {
28
+ const task = this.tasks.find((t) => t.id === id);
29
+ if (!task)
30
+ return;
31
+ if (patch.title !== undefined)
32
+ task.title = patch.title;
33
+ if (patch.status !== undefined)
34
+ task.status = patch.status;
35
+ if (patch.subagentMode !== undefined)
36
+ task.subagentMode = patch.subagentMode;
37
+ task.updatedAt = Date.now();
38
+ this.emit();
39
+ }
40
+ list() {
41
+ return this.tasks;
42
+ }
43
+ subscribe(listener) {
44
+ this.listeners.add(listener);
45
+ return () => {
46
+ this.listeners.delete(listener);
47
+ };
48
+ }
49
+ emit() {
50
+ for (const listener of this.listeners) {
51
+ listener();
52
+ }
53
+ }
54
+ }
55
+ /** Shared, process-wide task store. */
56
+ export const taskStore = new TaskStore();
57
+ //# sourceMappingURL=task-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-store.js","sourceRoot":"","sources":["../../src/core/task-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsBH,MAAM,SAAS;IACN,KAAK,GAAW,EAAE,CAAC;IACnB,MAAM,GAAG,CAAC,CAAC;IACF,SAAS,GAAG,IAAI,GAAG,EAAY,CAAC;IAEjD,MAAM,CAAC,KAAa,EAAE,OAAO,GAAsB,EAAE,EAAQ;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,GAAS;YAClB,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE;YACjB,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,iBAAiB;YACxC,MAAM,EAAE,SAAS;YACjB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;SACd,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IAAA,CACZ;IAED,MAAM,CAAC,EAAU,EAAE,KAAgB,EAAQ;QAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACxD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3D,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS;YAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QAC7E,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;IAAA,CACZ;IAED,IAAI,GAAoB;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC;IAAA,CAClB;IAED,SAAS,CAAC,QAAkB,EAAc;QACzC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC;YACZ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAAA,CAChC,CAAC;IAAA,CACF;IAEO,IAAI,GAAS;QACpB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACvC,QAAQ,EAAE,CAAC;QACZ,CAAC;IAAA,CACD;CACD;AAED,uCAAuC;AACvC,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC","sourcesContent":["/**\n * Minimal in-process task store.\n *\n * Tracks short-lived tasks (e.g. subagent delegations) so the TUI footer can\n * display active work. It is a process-level singleton because the tool that\n * creates tasks and the footer that renders them live in the same process and\n * there is no cross-process boundary to cross.\n */\n\nexport type TaskStatus = \"pending\" | \"in_progress\" | \"done\" | \"failed\";\n\nexport interface Task {\n\treadonly id: number;\n\ttitle: string;\n\tstatus: TaskStatus;\n\t/** Subagent mode when this task is owned by a subagent (e.g. \"explore\"). */\n\tsubagentMode?: string;\n\treadonly createdAt: number;\n\tupdatedAt: number;\n}\n\nexport interface CreateTaskOptions {\n\tsubagentMode?: string;\n}\n\nexport type TaskPatch = Partial<Pick<Task, \"title\" | \"status\" | \"subagentMode\">>;\n\ntype Listener = () => void;\n\nclass TaskStore {\n\tprivate tasks: Task[] = [];\n\tprivate nextId = 1;\n\tprivate readonly listeners = new Set<Listener>();\n\n\tcreate(title: string, options: CreateTaskOptions = {}): Task {\n\t\tconst now = Date.now();\n\t\tconst task: Task = {\n\t\t\tid: this.nextId++,\n\t\t\ttitle: title.trim() || \"(untitled task)\",\n\t\t\tstatus: \"pending\",\n\t\t\tsubagentMode: options.subagentMode,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t};\n\t\tthis.tasks.push(task);\n\t\tthis.emit();\n\t\treturn task;\n\t}\n\n\tupdate(id: number, patch: TaskPatch): void {\n\t\tconst task = this.tasks.find((t) => t.id === id);\n\t\tif (!task) return;\n\t\tif (patch.title !== undefined) task.title = patch.title;\n\t\tif (patch.status !== undefined) task.status = patch.status;\n\t\tif (patch.subagentMode !== undefined) task.subagentMode = patch.subagentMode;\n\t\ttask.updatedAt = Date.now();\n\t\tthis.emit();\n\t}\n\n\tlist(): readonly Task[] {\n\t\treturn this.tasks;\n\t}\n\n\tsubscribe(listener: Listener): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\n\tprivate emit(): void {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n}\n\n/** Shared, process-wide task store. */\nexport const taskStore = new TaskStore();\n"]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Subagent tool: delegate a focused task to a fresh, isolated agent loop.
3
+ *
4
+ * The tool registers a task in the shared task store (visible in the footer),
5
+ * runs the subagent to completion, and returns ONLY the subagent's final
6
+ * answer. It is an optional, opt-in tool (enabled via --subagent or the
7
+ * `enableSubagent` setting); see buildSessionOptions in main.ts.
8
+ */
9
+ import type { ToolDefinition } from "../extensions/types.js";
10
+ import { type SubagentMode } from "../subagent.js";
11
+ export interface SubagentToolDetails {
12
+ mode: SubagentMode;
13
+ ok: boolean;
14
+ error?: string;
15
+ }
16
+ /** Create the subagent tool definition. Registered as a customTool when enabled. */
17
+ export declare function createSubagentToolDefinition(): ToolDefinition;
18
+ //# sourceMappingURL=subagent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../../src/core/tools/subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA6BhE,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,YAAY,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAQD,oFAAoF;AACpF,wBAAgB,4BAA4B,IAAI,cAAc,CAkE7D","sourcesContent":["/**\n * Subagent tool: delegate a focused task to a fresh, isolated agent loop.\n *\n * The tool registers a task in the shared task store (visible in the footer),\n * runs the subagent to completion, and returns ONLY the subagent's final\n * answer. It is an optional, opt-in tool (enabled via --subagent or the\n * `enableSubagent` setting); see buildSessionOptions in main.ts.\n */\n\nimport { Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { defineTool } from \"../extensions/types.js\";\nimport { runSubagent, type SubagentMode } from \"../subagent.js\";\nimport { taskStore } from \"../task-store.js\";\n\nconst subagentParams = Type.Object({\n\ttask: Type.String({\n\t\tdescription:\n\t\t\t\"The task to delegate. Make it specific and self-contained; the subagent cannot see this conversation.\",\n\t}),\n\tcontext: Type.String({\n\t\tdescription:\n\t\t\t'Context distilled from the conversation the subagent needs (files, constraints, prior findings). Pass \"\" if none.',\n\t}),\n\tmode: Type.Union(\n\t\t[\n\t\t\tType.Literal(\"explore\"),\n\t\t\tType.Literal(\"edit\"),\n\t\t\tType.Literal(\"test\"),\n\t\t\tType.Literal(\"fix\"),\n\t\t\tType.Literal(\"review\"),\n\t\t],\n\t\t{\n\t\t\tdescription:\n\t\t\t\t\"explore: read-only investigation. edit: make a focused code change. test: run tests and report. fix: diagnose and fix a failure. review: read-only code review.\",\n\t\t},\n\t),\n});\n\ntype SubagentParams = Static<typeof subagentParams>;\n\nexport interface SubagentToolDetails {\n\tmode: SubagentMode;\n\tok: boolean;\n\terror?: string;\n}\n\n/** First line of the task, trimmed to a short summary for the task list/footer. */\nfunction summarize(task: string): string {\n\tconst firstLine = task.trim().split(\"\\n\")[0] ?? \"\";\n\treturn firstLine.length > 60 ? `${firstLine.slice(0, 57)}...` : firstLine || \"(task)\";\n}\n\n/** Create the subagent tool definition. Registered as a customTool when enabled. */\nexport function createSubagentToolDefinition(): ToolDefinition {\n\treturn defineTool<typeof subagentParams, SubagentToolDetails>({\n\t\tname: \"subagent\",\n\t\tlabel: \"Subagent\",\n\t\tdescription: [\n\t\t\t\"Delegate a focused task to a subagent that runs in a fresh, isolated context (it cannot see this conversation).\",\n\t\t\t\"Pass everything it needs via `context`. The subagent returns only its final answer.\",\n\t\t\t\"Modes: explore, edit, test, fix, review.\",\n\t\t\t\"Use it to parallelize investigation or contain a self-contained chunk of work without polluting your own context.\",\n\t\t].join(\" \"),\n\t\tpromptSnippet: \"delegate a self-contained task to an isolated subagent (modes: explore/edit/test/fix/review)\",\n\t\tparameters: subagentParams,\n\n\t\tasync execute(_toolCallId, params: SubagentParams, signal, _onUpdate, ctx) {\n\t\t\tconst mode = params.mode as SubagentMode;\n\t\t\tconst summary = summarize(params.task);\n\n\t\t\tconst task = taskStore.create(summary, { subagentMode: mode });\n\t\t\ttaskStore.update(task.id, { status: \"in_progress\" });\n\t\t\tif (ctx.hasUI) {\n\t\t\t\tctx.ui.setStatus(\"subagent\", `subagent:${mode} ${summary}`);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await runSubagent({\n\t\t\t\t\ttask: params.task,\n\t\t\t\t\tcontext: params.context,\n\t\t\t\t\tmode,\n\t\t\t\t\tcwd: ctx.cwd,\n\t\t\t\t\tmodel: ctx.model,\n\t\t\t\t\tmodelRegistry: ctx.modelRegistry,\n\t\t\t\t\tsignal: signal ?? ctx.signal,\n\t\t\t\t});\n\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\t// Signal failure by throwing: the agent loop derives a tool's error\n\t\t\t\t\t// state from a thrown error, not from a returned flag.\n\t\t\t\t\ttaskStore.update(task.id, { status: \"failed\" });\n\t\t\t\t\tthrow new Error(`Subagent (${mode}) failed: ${result.error ?? \"unknown error\"}`);\n\t\t\t\t}\n\n\t\t\t\ttaskStore.update(task.id, { status: \"done\" });\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: result.answer || \"(subagent returned no output)\" }],\n\t\t\t\t\tdetails: { mode, ok: true },\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\ttaskStore.update(task.id, { status: \"failed\" });\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tctx.ui.setStatus(\"subagent\", undefined);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\trenderCall(args, theme) {\n\t\t\tconst mode = args.mode ?? \"explore\";\n\t\t\tconst preview = summarize(args.task ?? \"\");\n\t\t\tconst text =\n\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(\"subagent \")) +\n\t\t\t\ttheme.fg(\"accent\", `[${mode}]`) +\n\t\t\t\ttheme.fg(\"dim\", ` ${preview}`);\n\t\t\treturn new Text(text, 0, 0);\n\t\t},\n\t});\n}\n"]}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Subagent tool: delegate a focused task to a fresh, isolated agent loop.
3
+ *
4
+ * The tool registers a task in the shared task store (visible in the footer),
5
+ * runs the subagent to completion, and returns ONLY the subagent's final
6
+ * answer. It is an optional, opt-in tool (enabled via --subagent or the
7
+ * `enableSubagent` setting); see buildSessionOptions in main.ts.
8
+ */
9
+ import { Text } from "@kolisachint/hoocode-tui";
10
+ import { Type } from "typebox";
11
+ import { defineTool } from "../extensions/types.js";
12
+ import { runSubagent } from "../subagent.js";
13
+ import { taskStore } from "../task-store.js";
14
+ const subagentParams = Type.Object({
15
+ task: Type.String({
16
+ description: "The task to delegate. Make it specific and self-contained; the subagent cannot see this conversation.",
17
+ }),
18
+ context: Type.String({
19
+ description: 'Context distilled from the conversation the subagent needs (files, constraints, prior findings). Pass "" if none.',
20
+ }),
21
+ mode: Type.Union([
22
+ Type.Literal("explore"),
23
+ Type.Literal("edit"),
24
+ Type.Literal("test"),
25
+ Type.Literal("fix"),
26
+ Type.Literal("review"),
27
+ ], {
28
+ description: "explore: read-only investigation. edit: make a focused code change. test: run tests and report. fix: diagnose and fix a failure. review: read-only code review.",
29
+ }),
30
+ });
31
+ /** First line of the task, trimmed to a short summary for the task list/footer. */
32
+ function summarize(task) {
33
+ const firstLine = task.trim().split("\n")[0] ?? "";
34
+ return firstLine.length > 60 ? `${firstLine.slice(0, 57)}...` : firstLine || "(task)";
35
+ }
36
+ /** Create the subagent tool definition. Registered as a customTool when enabled. */
37
+ export function createSubagentToolDefinition() {
38
+ return defineTool({
39
+ name: "subagent",
40
+ label: "Subagent",
41
+ description: [
42
+ "Delegate a focused task to a subagent that runs in a fresh, isolated context (it cannot see this conversation).",
43
+ "Pass everything it needs via `context`. The subagent returns only its final answer.",
44
+ "Modes: explore, edit, test, fix, review.",
45
+ "Use it to parallelize investigation or contain a self-contained chunk of work without polluting your own context.",
46
+ ].join(" "),
47
+ promptSnippet: "delegate a self-contained task to an isolated subagent (modes: explore/edit/test/fix/review)",
48
+ parameters: subagentParams,
49
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
50
+ const mode = params.mode;
51
+ const summary = summarize(params.task);
52
+ const task = taskStore.create(summary, { subagentMode: mode });
53
+ taskStore.update(task.id, { status: "in_progress" });
54
+ if (ctx.hasUI) {
55
+ ctx.ui.setStatus("subagent", `subagent:${mode} ${summary}`);
56
+ }
57
+ try {
58
+ const result = await runSubagent({
59
+ task: params.task,
60
+ context: params.context,
61
+ mode,
62
+ cwd: ctx.cwd,
63
+ model: ctx.model,
64
+ modelRegistry: ctx.modelRegistry,
65
+ signal: signal ?? ctx.signal,
66
+ });
67
+ if (!result.ok) {
68
+ // Signal failure by throwing: the agent loop derives a tool's error
69
+ // state from a thrown error, not from a returned flag.
70
+ taskStore.update(task.id, { status: "failed" });
71
+ throw new Error(`Subagent (${mode}) failed: ${result.error ?? "unknown error"}`);
72
+ }
73
+ taskStore.update(task.id, { status: "done" });
74
+ return {
75
+ content: [{ type: "text", text: result.answer || "(subagent returned no output)" }],
76
+ details: { mode, ok: true },
77
+ };
78
+ }
79
+ catch (error) {
80
+ taskStore.update(task.id, { status: "failed" });
81
+ throw error;
82
+ }
83
+ finally {
84
+ if (ctx.hasUI) {
85
+ ctx.ui.setStatus("subagent", undefined);
86
+ }
87
+ }
88
+ },
89
+ renderCall(args, theme) {
90
+ const mode = args.mode ?? "explore";
91
+ const preview = summarize(args.task ?? "");
92
+ const text = theme.fg("toolTitle", theme.bold("subagent ")) +
93
+ theme.fg("accent", `[${mode}]`) +
94
+ theme.fg("dim", ` ${preview}`);
95
+ return new Text(text, 0, 0);
96
+ },
97
+ });
98
+ }
99
+ //# sourceMappingURL=subagent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent.js","sourceRoot":"","sources":["../../../src/core/tools/subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAqB,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;QACjB,WAAW,EACV,uGAAuG;KACxG,CAAC;IACF,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC;QACpB,WAAW,EACV,mHAAmH;KACpH,CAAC;IACF,IAAI,EAAE,IAAI,CAAC,KAAK,CACf;QACC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;QACvB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;KACtB,EACD;QACC,WAAW,EACV,iKAAiK;KAClK,CACD;CACD,CAAC,CAAC;AAUH,mFAAmF;AACnF,SAAS,SAAS,CAAC,IAAY,EAAU;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,OAAO,SAAS,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC;AAAA,CACtF;AAED,oFAAoF;AACpF,MAAM,UAAU,4BAA4B,GAAmB;IAC9D,OAAO,UAAU,CAA6C;QAC7D,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE;YACZ,iHAAiH;YACjH,qFAAqF;YACrF,0CAA0C;YAC1C,mHAAmH;SACnH,CAAC,IAAI,CAAC,GAAG,CAAC;QACX,aAAa,EAAE,8FAA8F;QAC7G,UAAU,EAAE,cAAc;QAE1B,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAsB,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE;YAC1E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAoB,CAAC;YACzC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAEvC,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/D,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;YACrD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,YAAY,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;YAC7D,CAAC;YAED,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;oBAChC,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,IAAI;oBACJ,GAAG,EAAE,GAAG,CAAC,GAAG;oBACZ,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,aAAa,EAAE,GAAG,CAAC,aAAa;oBAChC,MAAM,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM;iBAC5B,CAAC,CAAC;gBAEH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBAChB,oEAAoE;oBACpE,uDAAuD;oBACvD,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;oBAChD,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,aAAa,MAAM,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAC;gBAClF,CAAC;gBAED,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC9C,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,IAAI,+BAA+B,EAAE,CAAC;oBACnF,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE;iBAC3B,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAChD,MAAM,KAAK,CAAC;YACb,CAAC;oBAAS,CAAC;gBACV,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;oBACf,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;gBACzC,CAAC;YACF,CAAC;QAAA,CACD;QAED,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE;YACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC;YACpC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,IAAI,GACT,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC9C,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,IAAI,GAAG,CAAC;gBAC/B,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,OAAO,EAAE,CAAC,CAAC;YAChC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAAA,CAC5B;KACD,CAAC,CAAC;AAAA,CACH","sourcesContent":["/**\n * Subagent tool: delegate a focused task to a fresh, isolated agent loop.\n *\n * The tool registers a task in the shared task store (visible in the footer),\n * runs the subagent to completion, and returns ONLY the subagent's final\n * answer. It is an optional, opt-in tool (enabled via --subagent or the\n * `enableSubagent` setting); see buildSessionOptions in main.ts.\n */\n\nimport { Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { defineTool } from \"../extensions/types.js\";\nimport { runSubagent, type SubagentMode } from \"../subagent.js\";\nimport { taskStore } from \"../task-store.js\";\n\nconst subagentParams = Type.Object({\n\ttask: Type.String({\n\t\tdescription:\n\t\t\t\"The task to delegate. Make it specific and self-contained; the subagent cannot see this conversation.\",\n\t}),\n\tcontext: Type.String({\n\t\tdescription:\n\t\t\t'Context distilled from the conversation the subagent needs (files, constraints, prior findings). Pass \"\" if none.',\n\t}),\n\tmode: Type.Union(\n\t\t[\n\t\t\tType.Literal(\"explore\"),\n\t\t\tType.Literal(\"edit\"),\n\t\t\tType.Literal(\"test\"),\n\t\t\tType.Literal(\"fix\"),\n\t\t\tType.Literal(\"review\"),\n\t\t],\n\t\t{\n\t\t\tdescription:\n\t\t\t\t\"explore: read-only investigation. edit: make a focused code change. test: run tests and report. fix: diagnose and fix a failure. review: read-only code review.\",\n\t\t},\n\t),\n});\n\ntype SubagentParams = Static<typeof subagentParams>;\n\nexport interface SubagentToolDetails {\n\tmode: SubagentMode;\n\tok: boolean;\n\terror?: string;\n}\n\n/** First line of the task, trimmed to a short summary for the task list/footer. */\nfunction summarize(task: string): string {\n\tconst firstLine = task.trim().split(\"\\n\")[0] ?? \"\";\n\treturn firstLine.length > 60 ? `${firstLine.slice(0, 57)}...` : firstLine || \"(task)\";\n}\n\n/** Create the subagent tool definition. Registered as a customTool when enabled. */\nexport function createSubagentToolDefinition(): ToolDefinition {\n\treturn defineTool<typeof subagentParams, SubagentToolDetails>({\n\t\tname: \"subagent\",\n\t\tlabel: \"Subagent\",\n\t\tdescription: [\n\t\t\t\"Delegate a focused task to a subagent that runs in a fresh, isolated context (it cannot see this conversation).\",\n\t\t\t\"Pass everything it needs via `context`. The subagent returns only its final answer.\",\n\t\t\t\"Modes: explore, edit, test, fix, review.\",\n\t\t\t\"Use it to parallelize investigation or contain a self-contained chunk of work without polluting your own context.\",\n\t\t].join(\" \"),\n\t\tpromptSnippet: \"delegate a self-contained task to an isolated subagent (modes: explore/edit/test/fix/review)\",\n\t\tparameters: subagentParams,\n\n\t\tasync execute(_toolCallId, params: SubagentParams, signal, _onUpdate, ctx) {\n\t\t\tconst mode = params.mode as SubagentMode;\n\t\t\tconst summary = summarize(params.task);\n\n\t\t\tconst task = taskStore.create(summary, { subagentMode: mode });\n\t\t\ttaskStore.update(task.id, { status: \"in_progress\" });\n\t\t\tif (ctx.hasUI) {\n\t\t\t\tctx.ui.setStatus(\"subagent\", `subagent:${mode} ${summary}`);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await runSubagent({\n\t\t\t\t\ttask: params.task,\n\t\t\t\t\tcontext: params.context,\n\t\t\t\t\tmode,\n\t\t\t\t\tcwd: ctx.cwd,\n\t\t\t\t\tmodel: ctx.model,\n\t\t\t\t\tmodelRegistry: ctx.modelRegistry,\n\t\t\t\t\tsignal: signal ?? ctx.signal,\n\t\t\t\t});\n\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\t// Signal failure by throwing: the agent loop derives a tool's error\n\t\t\t\t\t// state from a thrown error, not from a returned flag.\n\t\t\t\t\ttaskStore.update(task.id, { status: \"failed\" });\n\t\t\t\t\tthrow new Error(`Subagent (${mode}) failed: ${result.error ?? \"unknown error\"}`);\n\t\t\t\t}\n\n\t\t\t\ttaskStore.update(task.id, { status: \"done\" });\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: result.answer || \"(subagent returned no output)\" }],\n\t\t\t\t\tdetails: { mode, ok: true },\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\ttaskStore.update(task.id, { status: \"failed\" });\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tctx.ui.setStatus(\"subagent\", undefined);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\trenderCall(args, theme) {\n\t\t\tconst mode = args.mode ?? \"explore\";\n\t\t\tconst preview = summarize(args.task ?? \"\");\n\t\t\tconst text =\n\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(\"subagent \")) +\n\t\t\t\ttheme.fg(\"accent\", `[${mode}]`) +\n\t\t\t\ttheme.fg(\"dim\", ` ${preview}`);\n\t\t\treturn new Text(text, 0, 0);\n\t\t},\n\t});\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  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
+ export declare const EMBEDDED_SUBAGENT_PROMPTS: Record<string, string>;
4
5
  //# 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,MAAugB,CAAC;AAE9iB,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKjD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEpD,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 \\\"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\t\"ask\": \"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\t\"build\": \"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\t\"debug\": \"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\t\"plan\": \"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 `/approve` to begin execution.\\\"\\n\\nForbidden: edit any source file. Only `{{PLAN_PATH}}` may be written.\\n\",\n};\n\nexport const EMBEDDED_PROFILES: Record<string, string> = {\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,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQ5D,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 `/approve` to begin execution.\"\\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_SUBAGENT_PROMPTS: Record<string, string> = {\n\tedit: \"You are an edit subagent running inside hoocode. You implement one focused code change. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- You may read, edit, and write files, and run commands needed to make the change.\\n- Stay strictly within the requested task. Do not refactor unrelated code.\\n\\nMethod:\\n1. Read the relevant files before changing them.\\n2. Match the existing style: indentation, naming, import order.\\n3. Make the smallest change that fully satisfies the task.\\n4. Verify your edits by re-reading the changed regions.\\n\\nOutput:\\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\\n- Summarize what you changed 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 could not complete the change, say what blocked you.\\n\",\n\texplore:\n\t\t\"You are an exploration subagent running inside hoocode. You investigate a codebase and report findings. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- READ ONLY. Do not modify, create, or delete files. Do not run state-changing commands.\\n- Use read, grep, find, and ls (and read-only shell commands) 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\\nOutput:\\n- Your final message must contain ONLY your findings — it is the only thing the caller receives.\\n- Be concise and concrete: what you found, where (path:line), and how the pieces connect.\\n- Do not narrate your search or include tool logs or step-by-step reasoning.\\n- If something could not be determined, say so plainly.\\n\",\n\tfix: \"You are a fix subagent running inside hoocode. You diagnose a failure and apply a fix. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- You may read, edit, write, and run commands.\\n- Fix only the reported problem; avoid unrelated changes.\\n\\nMethod:\\n1. Reproduce or locate the failure; gather evidence (logs, traces, code).\\n2. Identify the root cause and state it in one sentence.\\n3. Apply the minimal correct fix, matching existing style.\\n4. Verify: re-run the relevant test or command to confirm the fix.\\n\\nOutput:\\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\\n- Give the root cause, the fix (files and path:line), and the verification result.\\n- Do not narrate intermediate steps or include full tool logs.\\n- If you could not fix it, state the root cause and what you tried.\\n\",\n\treview:\n\t\t\"You are a review subagent running inside hoocode. You review code and report issues. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- READ ONLY. Do not modify files.\\n- Review the code or change named in the task for correctness, clarity, and risk.\\n\\nMethod:\\n1. Read the relevant code (and any diff or context provided).\\n2. Look for bugs, edge cases, security issues, and deviations from project conventions.\\n3. Prioritize correctness over style nits.\\n\\nOutput:\\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\\n- List findings ordered by severity, each with path:line and a concrete suggestion.\\n- If the code looks correct, say so and note any minor optional improvements.\\n- Do not narrate your reading process or include tool logs.\\n\",\n\ttest: \"You are a test subagent running inside hoocode. You run tests and report the result. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- You may read files and run commands (test runners, build, lint). Do not modify source files.\\n- Run the tests the task names; if unspecified, find and run the most relevant suite.\\n\\nMethod:\\n1. Locate the test command from package.json, config, or the task instructions.\\n2. Run it. Capture pass/fail counts and the first meaningful failures.\\n3. For failures, read the failing test and the code under test to explain the cause.\\n\\nOutput:\\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\\n- State the command you ran, the result (pass/fail with counts), and for failures the path:line and likely cause.\\n- Do not paste full raw logs or narrate your process.\\n\",\n};\n"]}
@@ -1,12 +1,19 @@
1
1
  // AUTO-GENERATED by scripts/embed-templates.mjs — do not edit.
2
2
  // Source of truth: packages/coding-agent/templates/**
3
3
  // Regenerated on every `npm run build`.
4
- export const EMBEDDED_DEFAULT_CONFIG = "{\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";
4
+ export const EMBEDDED_DEFAULT_CONFIG = '{\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';
5
5
  export const EMBEDDED_MODES = {
6
- "ask": "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",
7
- "build": "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",
8
- "debug": "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",
9
- "plan": "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 `/approve` to begin execution.\"\n\nForbidden: edit any source file. Only `{{PLAN_PATH}}` may be written.\n",
6
+ ask: "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",
7
+ build: "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",
8
+ debug: "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",
9
+ plan: '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 `/approve` to begin execution."\n\nForbidden: edit any source file. Only `{{PLAN_PATH}}` may be written.\n',
10
10
  };
11
11
  export const EMBEDDED_PROFILES = {};
12
+ export const EMBEDDED_SUBAGENT_PROMPTS = {
13
+ edit: "You are an edit subagent running inside hoocode. You implement one focused code change. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\n\nScope:\n- You may read, edit, and write files, and run commands needed to make the change.\n- Stay strictly within the requested task. Do not refactor unrelated code.\n\nMethod:\n1. Read the relevant files before changing them.\n2. Match the existing style: indentation, naming, import order.\n3. Make the smallest change that fully satisfies the task.\n4. Verify your edits by re-reading the changed regions.\n\nOutput:\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\n- Summarize what you changed 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 could not complete the change, say what blocked you.\n",
14
+ explore: "You are an exploration subagent running inside hoocode. You investigate a codebase and report findings. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\n\nScope:\n- READ ONLY. Do not modify, create, or delete files. Do not run state-changing commands.\n- Use read, grep, find, and ls (and read-only shell commands) 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\nOutput:\n- Your final message must contain ONLY your findings — it is the only thing the caller receives.\n- Be concise and concrete: what you found, where (path:line), and how the pieces connect.\n- Do not narrate your search or include tool logs or step-by-step reasoning.\n- If something could not be determined, say so plainly.\n",
15
+ fix: "You are a fix subagent running inside hoocode. You diagnose a failure and apply a fix. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\n\nScope:\n- You may read, edit, write, and run commands.\n- Fix only the reported problem; avoid unrelated changes.\n\nMethod:\n1. Reproduce or locate the failure; gather evidence (logs, traces, code).\n2. Identify the root cause and state it in one sentence.\n3. Apply the minimal correct fix, matching existing style.\n4. Verify: re-run the relevant test or command to confirm the fix.\n\nOutput:\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\n- Give the root cause, the fix (files and path:line), and the verification result.\n- Do not narrate intermediate steps or include full tool logs.\n- If you could not fix it, state the root cause and what you tried.\n",
16
+ review: "You are a review subagent running inside hoocode. You review code and report issues. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\n\nScope:\n- READ ONLY. Do not modify files.\n- Review the code or change named in the task for correctness, clarity, and risk.\n\nMethod:\n1. Read the relevant code (and any diff or context provided).\n2. Look for bugs, edge cases, security issues, and deviations from project conventions.\n3. Prioritize correctness over style nits.\n\nOutput:\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\n- List findings ordered by severity, each with path:line and a concrete suggestion.\n- If the code looks correct, say so and note any minor optional improvements.\n- Do not narrate your reading process or include tool logs.\n",
17
+ test: "You are a test subagent running inside hoocode. You run tests and report the result. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\n\nScope:\n- You may read files and run commands (test runners, build, lint). Do not modify source files.\n- Run the tests the task names; if unspecified, find and run the most relevant suite.\n\nMethod:\n1. Locate the test command from package.json, config, or the task instructions.\n2. Run it. Capture pass/fail counts and the first meaningful failures.\n3. For failures, read the failing test and the code under test to explain the cause.\n\nOutput:\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\n- State the command you ran, the result (pass/fail with counts), and for failures the path:line and likely cause.\n- Do not paste full raw logs or narrate your process.\n",
18
+ };
12
19
  //# sourceMappingURL=init-templates.generated.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init-templates.generated.js","sourceRoot":"","sources":["../src/init-templates.generated.ts"],"names":[],"mappings":"AAAA,iEAA+D;AAC/D,sDAAsD;AACtD,wCAAwC;AAExC,MAAM,CAAC,MAAM,uBAAuB,GAAW,8fAA8f,CAAC;AAE9iB,MAAM,CAAC,MAAM,cAAc,GAA2B;IACrD,KAAK,EAAE,ogBAAkgB;IACzgB,OAAO,EAAE,unBAAmnB;IAC5nB,OAAO,EAAE,6pBAAipB;IAC1pB,MAAM,EAAE,msBAAurB;CAC/rB,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAA2B,EAExD,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 \\\"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\t\"ask\": \"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\t\"build\": \"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\t\"debug\": \"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\t\"plan\": \"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 `/approve` to begin execution.\\\"\\n\\nForbidden: edit any source file. Only `{{PLAN_PATH}}` may be written.\\n\",\n};\n\nexport const EMBEDDED_PROFILES: Record<string, string> = {\n\n};\n"]}
1
+ {"version":3,"file":"init-templates.generated.js","sourceRoot":"","sources":["../src/init-templates.generated.ts"],"names":[],"mappings":"AAAA,iEAA+D;AAC/D,sDAAsD;AACtD,wCAAwC;AAExC,MAAM,CAAC,MAAM,uBAAuB,GACnC,ocAAoc,CAAC;AAEtc,MAAM,CAAC,MAAM,cAAc,GAA2B;IACrD,GAAG,EAAE,ogBAAkgB;IACvgB,KAAK,EAAE,unBAAmnB;IAC1nB,KAAK,EAAE,6pBAAipB;IACxpB,IAAI,EAAE,isBAAqrB;CAC3rB,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAA2B,EAAE,CAAC;AAE5D,MAAM,CAAC,MAAM,yBAAyB,GAA2B;IAChE,IAAI,EAAE,w7BAAs7B;IAC57B,OAAO,EACN,86BAA46B;IAC76B,GAAG,EAAE,+5BAA65B;IACl6B,MAAM,EACL,+2BAA62B;IAC92B,IAAI,EAAE,o6BAAk6B;CACx6B,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 `/approve` to begin execution.\"\\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_SUBAGENT_PROMPTS: Record<string, string> = {\n\tedit: \"You are an edit subagent running inside hoocode. You implement one focused code change. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- You may read, edit, and write files, and run commands needed to make the change.\\n- Stay strictly within the requested task. Do not refactor unrelated code.\\n\\nMethod:\\n1. Read the relevant files before changing them.\\n2. Match the existing style: indentation, naming, import order.\\n3. Make the smallest change that fully satisfies the task.\\n4. Verify your edits by re-reading the changed regions.\\n\\nOutput:\\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\\n- Summarize what you changed 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 could not complete the change, say what blocked you.\\n\",\n\texplore:\n\t\t\"You are an exploration subagent running inside hoocode. You investigate a codebase and report findings. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- READ ONLY. Do not modify, create, or delete files. Do not run state-changing commands.\\n- Use read, grep, find, and ls (and read-only shell commands) 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\\nOutput:\\n- Your final message must contain ONLY your findings — it is the only thing the caller receives.\\n- Be concise and concrete: what you found, where (path:line), and how the pieces connect.\\n- Do not narrate your search or include tool logs or step-by-step reasoning.\\n- If something could not be determined, say so plainly.\\n\",\n\tfix: \"You are a fix subagent running inside hoocode. You diagnose a failure and apply a fix. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- You may read, edit, write, and run commands.\\n- Fix only the reported problem; avoid unrelated changes.\\n\\nMethod:\\n1. Reproduce or locate the failure; gather evidence (logs, traces, code).\\n2. Identify the root cause and state it in one sentence.\\n3. Apply the minimal correct fix, matching existing style.\\n4. Verify: re-run the relevant test or command to confirm the fix.\\n\\nOutput:\\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\\n- Give the root cause, the fix (files and path:line), and the verification result.\\n- Do not narrate intermediate steps or include full tool logs.\\n- If you could not fix it, state the root cause and what you tried.\\n\",\n\treview:\n\t\t\"You are a review subagent running inside hoocode. You review code and report issues. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- READ ONLY. Do not modify files.\\n- Review the code or change named in the task for correctness, clarity, and risk.\\n\\nMethod:\\n1. Read the relevant code (and any diff or context provided).\\n2. Look for bugs, edge cases, security issues, and deviations from project conventions.\\n3. Prioritize correctness over style nits.\\n\\nOutput:\\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\\n- List findings ordered by severity, each with path:line and a concrete suggestion.\\n- If the code looks correct, say so and note any minor optional improvements.\\n- Do not narrate your reading process or include tool logs.\\n\",\n\ttest: \"You are a test subagent running inside hoocode. You run tests and report the result. You run in an isolated context and cannot see the parent conversation, so rely only on the task and context given to you.\\n\\nScope:\\n- You may read files and run commands (test runners, build, lint). Do not modify source files.\\n- Run the tests the task names; if unspecified, find and run the most relevant suite.\\n\\nMethod:\\n1. Locate the test command from package.json, config, or the task instructions.\\n2. Run it. Capture pass/fail counts and the first meaningful failures.\\n3. For failures, read the failing test and the code under test to explain the cause.\\n\\nOutput:\\n- Your final message must contain ONLY your answer — it is the only thing the caller receives.\\n- State the command you ran, the result (pass/fail with counts), and for failures the path:line and likely cause.\\n- Do not paste full raw logs or narrate your process.\\n\",\n};\n"]}