sparkecoder 0.1.124 → 0.1.126

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 (108) hide show
  1. package/dist/agent/index.js +145 -71
  2. package/dist/agent/index.js.map +1 -1
  3. package/dist/cli.js +188 -89
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.js +188 -89
  6. package/dist/index.js.map +1 -1
  7. package/dist/server/index.js +188 -89
  8. package/dist/server/index.js.map +1 -1
  9. package/dist/skills/default/memory.md +49 -0
  10. package/dist/skills/default/skill-authoring.md +96 -0
  11. package/dist/tools/index.js +12 -4
  12. package/dist/tools/index.js.map +1 -1
  13. package/package.json +1 -1
  14. package/src/skills/default/memory.md +49 -0
  15. package/src/skills/default/skill-authoring.md +96 -0
  16. package/web/.next/BUILD_ID +1 -1
  17. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  18. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  19. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  20. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  21. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  22. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  23. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  24. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  25. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  26. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  27. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
  29. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  34. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
  36. package/web/.next/standalone/web/.next/server/app/agents.rsc +1 -1
  37. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +1 -1
  38. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
  39. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +1 -1
  40. package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +1 -1
  41. package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
  43. package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
  44. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  45. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
  46. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  48. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
  49. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
  50. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  52. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  53. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  54. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
  55. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  57. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
  59. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  60. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  61. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  62. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  63. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
  64. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
  65. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  69. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  70. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  71. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  72. package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
  73. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
  74. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  75. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
  76. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
  77. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  78. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  79. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  80. package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
  81. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
  82. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
  83. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
  84. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  85. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
  86. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  87. package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
  88. package/web/.next/standalone/web/.next/server/app/settings.rsc +1 -1
  89. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +1 -1
  90. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
  91. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +1 -1
  92. package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  93. package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  94. package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  95. package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  96. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  97. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  98. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  99. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  100. /package/web/.next/standalone/web/.next/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_buildManifest.js +0 -0
  101. /package/web/.next/standalone/web/.next/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_clientMiddlewareManifest.json +0 -0
  102. /package/web/.next/standalone/web/.next/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_ssgManifest.js +0 -0
  103. /package/web/.next/standalone/web/.next/static/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_buildManifest.js +0 -0
  104. /package/web/.next/standalone/web/.next/static/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_clientMiddlewareManifest.json +0 -0
  105. /package/web/.next/standalone/web/.next/static/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_ssgManifest.js +0 -0
  106. /package/web/.next/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_buildManifest.js +0 -0
  107. /package/web/.next/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_clientMiddlewareManifest.json +0 -0
  108. /package/web/.next/static/{cYXZ7UzGc5TttFIXRRcSC → BSOUN7vf8epF685UYalET}/_ssgManifest.js +0 -0
package/dist/index.js CHANGED
@@ -192,7 +192,10 @@ var init_types = __esm({
192
192
  // not listed here. Values match `process.platform`
193
193
  // (darwin, linux, win32, freebsd, ...). If omitted or empty, the skill is
194
194
  // available on all platforms.
195
- platforms: z.array(z.string()).optional().default([])
195
+ platforms: z.array(z.string()).optional().default([]),
196
+ // Optional approximate token budget for always-loaded content. If set,
197
+ // the prompt builder truncates this skill/rule before injecting it.
198
+ contextBudgetTokens: z.number().int().positive().optional()
196
199
  });
197
200
  TaskConfigSchema = z.object({
198
201
  enabled: z.boolean(),
@@ -431,6 +434,7 @@ __export(config_exports, {
431
434
  TaskConfigSchema: () => TaskConfigSchema,
432
435
  ToolApprovalConfigSchema: () => ToolApprovalConfigSchema,
433
436
  VectorGatewayConfigSchema: () => VectorGatewayConfigSchema,
437
+ autoApproveAllTools: () => autoApproveAllTools,
434
438
  clearSlackConfig: () => clearSlackConfig,
435
439
  createDefaultConfig: () => createDefaultConfig,
436
440
  discoverSkillDirectories: () => discoverSkillDirectories,
@@ -826,6 +830,16 @@ function requiresApproval(toolName, sessionConfig) {
826
830
  }
827
831
  return false;
828
832
  }
833
+ function autoApproveAllTools(sessionConfig) {
834
+ const currentApprovals = sessionConfig.toolApprovals;
835
+ return {
836
+ ...sessionConfig,
837
+ toolApprovals: {
838
+ ...currentApprovals ?? {},
839
+ ...AUTO_APPROVE_ALL_TOOLS
840
+ }
841
+ };
842
+ }
829
843
  function createDefaultConfig() {
830
844
  return {
831
845
  defaultModel: "anthropic/claude-opus-4.7",
@@ -1056,7 +1070,7 @@ function maskApiKey(key2) {
1056
1070
  }
1057
1071
  return key2.slice(0, 4) + "..." + key2.slice(-4);
1058
1072
  }
1059
- var CONFIG_FILE_NAMES, cachedConfig, AUTH_KEY_FILE, API_KEYS_FILE, PROVIDER_ENV_MAP, SUPPORTED_PROVIDERS;
1073
+ var CONFIG_FILE_NAMES, cachedConfig, AUTO_APPROVE_ALL_TOOLS, AUTH_KEY_FILE, API_KEYS_FILE, PROVIDER_ENV_MAP, SUPPORTED_PROVIDERS;
1060
1074
  var init_config = __esm({
1061
1075
  "src/config/index.ts"() {
1062
1076
  "use strict";
@@ -1068,6 +1082,7 @@ var init_config = __esm({
1068
1082
  ".sparkecoder.json"
1069
1083
  ];
1070
1084
  cachedConfig = null;
1085
+ AUTO_APPROVE_ALL_TOOLS = { "*": false };
1071
1086
  AUTH_KEY_FILE = "auth-key.json";
1072
1087
  API_KEYS_FILE = "api-keys.json";
1073
1088
  PROVIDER_ENV_MAP = {
@@ -4052,6 +4067,8 @@ function parseSkillFrontmatter(content) {
4052
4067
  data[key2] = true;
4053
4068
  } else if (value === "false") {
4054
4069
  data[key2] = false;
4070
+ } else if (/^\d+$/.test(value)) {
4071
+ data[key2] = Number(value);
4055
4072
  } else {
4056
4073
  data[key2] = value;
4057
4074
  }
@@ -4111,7 +4128,8 @@ async function loadSkillsFromDirectory(directory, options = {}) {
4111
4128
  loadType,
4112
4129
  priority,
4113
4130
  sourceDir: directory,
4114
- platforms: parsed.metadata.platforms
4131
+ platforms: parsed.metadata.platforms,
4132
+ contextBudgetTokens: parsed.metadata.contextBudgetTokens
4115
4133
  });
4116
4134
  } else {
4117
4135
  const name = getSkillNameFromPath(filePath);
@@ -4125,7 +4143,8 @@ async function loadSkillsFromDirectory(directory, options = {}) {
4125
4143
  loadType: forceAlwaysApply ? "always" : defaultLoadType,
4126
4144
  priority,
4127
4145
  sourceDir: directory,
4128
- platforms: []
4146
+ platforms: [],
4147
+ contextBudgetTokens: void 0
4129
4148
  });
4130
4149
  }
4131
4150
  }
@@ -4255,11 +4274,12 @@ function formatSkillsForContext(skills2) {
4255
4274
  if (onDemandSkills.length === 0) {
4256
4275
  return "No on-demand skills available.";
4257
4276
  }
4258
- const lines = ["Available skills (use load_skill tool to load into context):"];
4277
+ const lines = ["<available_skills>", "Use the load_skill tool to load one of these into context:"];
4259
4278
  for (const skill of onDemandSkills) {
4260
4279
  const globInfo = skill.globs?.length ? ` [auto-loads for: ${skill.globs.join(", ")}]` : "";
4261
4280
  lines.push(`- ${skill.name}: ${skill.description}${globInfo}`);
4262
4281
  }
4282
+ lines.push("</available_skills>");
4263
4283
  return lines.join("\n");
4264
4284
  }
4265
4285
  function formatAlwaysLoadedSkills(skills2) {
@@ -4268,13 +4288,22 @@ function formatAlwaysLoadedSkills(skills2) {
4268
4288
  }
4269
4289
  const sections = [];
4270
4290
  for (const skill of skills2) {
4271
- sections.push(`### ${skill.name}
4272
-
4273
- ${skill.content}`);
4291
+ sections.push(`<skill name="${escapeXmlAttribute(skill.name)}">
4292
+ ${truncateSkillContent(skill)}
4293
+ </skill>`);
4274
4294
  }
4275
- return `## Active Rules & Skills (Always Loaded)
4295
+ return `<always_loaded_rules_and_skills>
4296
+ ${sections.join("\n\n")}
4297
+ </always_loaded_rules_and_skills>`;
4298
+ }
4299
+ function truncateSkillContent(skill) {
4300
+ if (!skill.contextBudgetTokens) return skill.content;
4301
+ const maxChars = Math.max(200, skill.contextBudgetTokens * 4);
4302
+ if (skill.content.length <= maxChars) return skill.content;
4303
+ const omitted = skill.content.length - maxChars;
4304
+ return `${skill.content.slice(0, maxChars).trimEnd()}
4276
4305
 
4277
- ${sections.join("\n\n---\n\n")}`;
4306
+ ... [${skill.name} truncated by contextBudgetTokens=${skill.contextBudgetTokens}; ${omitted} chars omitted. Read ${skill.filePath} for the full file.]`;
4278
4307
  }
4279
4308
  function formatGlobMatchedSkills(skills2) {
4280
4309
  if (skills2.length === 0) {
@@ -4282,21 +4311,24 @@ function formatGlobMatchedSkills(skills2) {
4282
4311
  }
4283
4312
  const sections = [];
4284
4313
  for (const skill of skills2) {
4285
- sections.push(`### ${skill.name}
4286
-
4287
- ${skill.content}`);
4314
+ sections.push(`<skill name="${escapeXmlAttribute(skill.name)}">
4315
+ ${skill.content}
4316
+ </skill>`);
4288
4317
  }
4289
- return `## Context-Relevant Skills (Auto-loaded based on active files)
4290
-
4291
- ${sections.join("\n\n---\n\n")}`;
4318
+ return `<glob_matched_skills>
4319
+ ${sections.join("\n\n")}
4320
+ </glob_matched_skills>`;
4292
4321
  }
4293
4322
  function formatAgentsMdContent(content) {
4294
4323
  if (!content) {
4295
4324
  return "";
4296
4325
  }
4297
- return `## Project Instructions (AGENTS.md)
4298
-
4299
- ${content}`;
4326
+ return `<project_instructions source="AGENTS.md">
4327
+ ${content}
4328
+ </project_instructions>`;
4329
+ }
4330
+ function escapeXmlAttribute(value) {
4331
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4300
4332
  }
4301
4333
  var init_skills = __esm({
4302
4334
  "src/skills/index.ts"() {
@@ -6561,14 +6593,18 @@ async function buildSystemPrompt(options) {
6561
6593
  const platform3 = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
6562
6594
  const currentDate = (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" });
6563
6595
  const searchInstructions = getSearchInstructions();
6564
- const systemPrompt = `You are SparkECoder, an expert AI coding assistant. You help developers write, debug, and improve code.
6596
+ const systemPrompt = `<system_prompt>
6597
+ <identity>
6598
+ You are SparkECoder, an expert AI coding assistant. You help developers write, debug, and improve code.
6599
+ </identity>
6565
6600
 
6566
- ## Environment
6601
+ <environment>
6567
6602
  - **Platform**: ${platform3} (${os.release()})
6568
6603
  - **Date**: ${currentDate}
6569
6604
  - **Working Directory**: ${workingDirectory}
6605
+ </environment>
6570
6606
 
6571
- ## Core Capabilities
6607
+ <core_capabilities>
6572
6608
  You have access to powerful tools for:
6573
6609
  - **bash**: Execute commands in the terminal (see below for details)
6574
6610
  - **read_file**: Read file contents to understand code and context
@@ -6582,8 +6618,9 @@ You have access to powerful tools for:
6582
6618
 
6583
6619
 
6584
6620
  IMPORTANT: If you have zero context of where you are working, always explore it first to understand the structure before doing things for the user.
6621
+ </core_capabilities>
6585
6622
 
6586
- ### Planning & Task Management
6623
+ <planning_and_task_management>
6587
6624
  Use the **todo tool** to manage both immediate tasks AND persistent plans:
6588
6625
 
6589
6626
  **For simple tasks (< 5 steps):** Just use regular todos (add/mark/clear).
@@ -6603,8 +6640,9 @@ Use the **todo tool** to manage both immediate tasks AND persistent plans:
6603
6640
  - Only top-level checklist items (- [ ]) become todos \u2014 indented sub-items are part of the task detail
6604
6641
  - Sections named Overview, Notes, Key Decisions, etc. are not treated as phases
6605
6642
  - You can clear the todo list and restart it, and do multiple things inside of one session
6643
+ </planning_and_task_management>
6606
6644
 
6607
- ### bash Tool
6645
+ <bash_tool>
6608
6646
  The bash tool runs commands in the terminal. Every command runs in its own session with logs saved to disk.
6609
6647
 
6610
6648
  **Run a command (default - waits for completion):**
@@ -6651,22 +6689,25 @@ bash({ id: "abc123", input: "my text" }) // send text input
6651
6689
  - Use \`input: "text"\` for text input prompts
6652
6690
 
6653
6691
  Terminal output is stored in the global SparkECoder data directory. Use the \`tail\` option to read recent output.
6692
+ </bash_tool>
6654
6693
 
6655
- ## Guidelines
6694
+ <guidelines>
6656
6695
 
6657
- ### Code Quality
6696
+ <code_quality>
6658
6697
  - Write clean, maintainable, well-documented code
6659
6698
  - Follow existing code style and conventions in the project
6660
6699
  - Use meaningful variable and function names
6661
6700
  - Add comments for complex logic
6701
+ </code_quality>
6662
6702
 
6663
- ### Problem Solving
6703
+ <problem_solving>
6664
6704
  - Before making changes, understand the existing code structure
6665
6705
  - Break complex tasks into smaller, manageable steps using the todo tool
6666
6706
  - Test changes when possible using the bash tool
6667
6707
  - Handle errors gracefully and provide helpful error messages
6708
+ </problem_solving>
6668
6709
 
6669
- ### File Operations
6710
+ <file_operations>
6670
6711
  - Use \`read_file\` to understand code before modifying
6671
6712
  - Use \`write_file\` with mode "str_replace" for targeted edits to existing files
6672
6713
  - Use \`write_file\` with mode "full" only for new files or complete rewrites
@@ -6675,8 +6716,9 @@ Terminal output is stored in the global SparkECoder data directory. Use the \`ta
6675
6716
  - If the user asks to write/create a file, always use \`write_file\` rather than printing the full contents
6676
6717
  - If the user requests a file but does not provide a path, choose a sensible default (e.g. \`index.html\`) and proceed
6677
6718
  - For large content (hundreds of lines), avoid placing it in chat output; write to a file instead
6719
+ </file_operations>
6678
6720
 
6679
- ### Linter Tool
6721
+ <linter_tool>
6680
6722
  The linter tool uses Language Server Protocol (LSP) to detect type errors and lint issues:
6681
6723
  \`\`\`
6682
6724
  linter({}) // Check all recently edited files
@@ -6684,8 +6726,9 @@ linter({ paths: ["src/app.ts"] }) // Check specific files
6684
6726
  linter({ paths: ["src/"] }) // Check all files in a directory
6685
6727
  \`\`\`
6686
6728
  Use this proactively after making code changes to catch errors early.
6729
+ </linter_tool>
6687
6730
 
6688
- ### Code Graph Tool
6731
+ <code_graph_tool>
6689
6732
  The code_graph tool uses the TypeScript language server to inspect a symbol's type hierarchy and usage graph:
6690
6733
  \`\`\`
6691
6734
  code_graph({ symbol: "UserCard" }) // Search workspace for symbol
@@ -6711,8 +6754,9 @@ code_graph({ symbol: "formatUser", filePath: "utils.ts", depth: 2 }) // Travers
6711
6754
  - For exploratory "how does X work?" questions \u2014 use \`explore_agent\` instead
6712
6755
  - For exact string searches \u2014 use grep/rg directly
6713
6756
  - For non-TypeScript/JavaScript files \u2014 code_graph only supports TS/JS/TSX/JSX
6757
+ </code_graph_tool>
6714
6758
 
6715
- ### Searching and Exploration
6759
+ <searching_and_exploration>
6716
6760
 
6717
6761
  **Choose the right search approach:**
6718
6762
 
@@ -6763,8 +6807,9 @@ code_graph({ symbol: "formatUser", filePath: "utils.ts", depth: 2 }) // Travers
6763
6807
  - "Find files named config" \u2192 Use \`find . -name "*config*"\`
6764
6808
 
6765
6809
  ${searchInstructions}
6810
+ </searching_and_exploration>
6766
6811
 
6767
- ###Follow these principles when designing and implementing software:
6812
+ <software_design_principles>
6768
6813
 
6769
6814
  1. **Modularity** \u2014 Write simple parts connected by clean interfaces
6770
6815
  2. **Clarity** \u2014 Clarity is better than cleverness
@@ -6783,8 +6828,9 @@ ${searchInstructions}
6783
6828
  15. **Optimization** \u2014 Prototype before polishing. Get it working before you optimize it
6784
6829
  16. **Diversity** \u2014 Distrust all claims for "one true way"
6785
6830
  17. **Extensibility** \u2014 Design for the future, because it will be here sooner than you think
6831
+ </software_design_principles>
6786
6832
 
6787
- ### Follow these design rules for any user interfaces or experiences you write (DESIGN LIKE APPLE):
6833
+ <ui_design_principles>
6788
6834
 
6789
6835
  1. **Simplicity** \u2014 Simplicity is the ultimate sophistication. Remove everything unnecessary.
6790
6836
  2. **Focus** \u2014 Say no to 1,000 things to say yes to the few that matter most.
@@ -6796,8 +6842,9 @@ ${searchInstructions}
6796
6842
  8. **Feedback** \u2014 Every action deserves a response. Make interactions feel alive.
6797
6843
  9. **Forgiveness** \u2014 Make it easy to undo. Never punish exploration.
6798
6844
  10. **Beauty** \u2014 Aesthetics are not superficial. Beautiful things work better because people care about them.
6845
+ </ui_design_principles>
6799
6846
 
6800
- ### Follow these rules to be a good agent for the user:
6847
+ <agent_behavior_rules>
6801
6848
 
6802
6849
  1. Understand first - Read relevant files before making any changes. Use the \`explore_agent\` tool for exploratory questions about how things work, and direct searches (grep/rg) for finding exact strings or file names.
6803
6850
  2. Plan for complexity - If the task involves 3+ steps or has meaningful trade-offs, create a todo list to track progress before implementing.
@@ -6806,13 +6853,16 @@ ${searchInstructions}
6806
6853
  5. Be direct - Focus on technical accuracy rather than validation. If see issues with an approach or need clarification, say so.
6807
6854
  6. Verify my work - After making changes, check for linter errors and fix any introduced.
6808
6855
  7. Respect boundaries - Only commit code when explicitly asked, avoid creating unnecessary files, and don't make assumptions about things uncertain about.
6856
+ </agent_behavior_rules>
6809
6857
 
6810
6858
 
6811
- ### Communication
6859
+ <communication>
6812
6860
  - Explain your reasoning and approach
6813
6861
  - Be concise but thorough
6814
6862
  - Ask clarifying questions when requirements are ambiguous
6815
6863
  - Report progress on multi-step tasks
6864
+ </communication>
6865
+ </guidelines>
6816
6866
 
6817
6867
  ${agentsMdContent}
6818
6868
 
@@ -6820,18 +6870,24 @@ ${alwaysLoadedContent}
6820
6870
 
6821
6871
  ${globMatchedContent}
6822
6872
 
6823
- ## On-Demand Skills
6873
+ <on_demand_skills>
6824
6874
  ${onDemandSkillsContext}
6875
+ </on_demand_skills>
6825
6876
 
6826
- ## Current Task List
6877
+ <current_task_list>
6827
6878
  ${todosContext}
6879
+ </current_task_list>
6828
6880
 
6829
6881
  ${plansContext}
6830
6882
 
6831
- ${customInstructions ? `## Custom Instructions
6832
- ${customInstructions}` : ""}
6883
+ ${customInstructions ? `<custom_instructions>
6884
+ ${customInstructions}
6885
+ </custom_instructions>` : ""}
6833
6886
 
6834
- Remember: You are a helpful, capable coding assistant. Take initiative, be thorough, and deliver high-quality results.`;
6887
+ <final_reminder>
6888
+ Remember: You are a helpful, capable coding assistant. Take initiative, be thorough, and deliver high-quality results.
6889
+ </final_reminder>
6890
+ </system_prompt>`;
6835
6891
  return systemPrompt;
6836
6892
  }
6837
6893
  function formatTodosForContext(todos) {
@@ -6855,7 +6911,7 @@ function formatPlansForContext(plans, shouldContinue) {
6855
6911
  if (plans.length === 0) return "";
6856
6912
  let totalChars = 0;
6857
6913
  const sections = [];
6858
- sections.push(`## Persistent Plans (${plans.length})`);
6914
+ sections.push(`<persistent_plans count="${plans.length}">`);
6859
6915
  sections.push("");
6860
6916
  sections.push("These plans persist across context compaction \u2014 they are always available.");
6861
6917
  sections.push("When you finish your current todos, check these plans for the next uncompleted phase,");
@@ -6876,34 +6932,39 @@ function formatPlansForContext(plans, shouldContinue) {
6876
6932
  ... [plan truncated \u2014 ${content.length - MAX_PLAN_CHARS} chars omitted. Use get_plan to read the full plan.]`;
6877
6933
  }
6878
6934
  if (totalChars + content.length > MAX_TOTAL_PLANS_CHARS) {
6879
- sections.push(`### \u{1F4CB} Plan: ${plan.name} [truncated \u2014 use get_plan("${plan.name}") to read]`);
6935
+ sections.push(`<plan name="${plan.name}" truncated="true">Use get_plan("${plan.name}") to read.</plan>`);
6880
6936
  continue;
6881
6937
  }
6882
- sections.push(`### \u{1F4CB} Plan: ${plan.name}`);
6883
- sections.push("");
6938
+ sections.push(`<plan name="${plan.name}">`);
6884
6939
  sections.push(content);
6885
- sections.push("");
6940
+ sections.push("</plan>");
6886
6941
  totalChars += content.length;
6887
6942
  }
6943
+ sections.push("</persistent_plans>");
6888
6944
  return sections.join("\n");
6889
6945
  }
6890
6946
  function buildTaskPromptAddendum(outputSchema) {
6891
6947
  return `
6892
- ## Task Mode
6948
+ <task_mode>
6893
6949
 
6894
6950
  You are running in **task mode**. You have been given a specific task to complete autonomously.
6895
6951
  You have access to ALL the same tools as a normal session \u2014 bash, read_file, write_file, linter, todo, load_skill, explore_agent, code_graph, upload_file, and more. Use them all. This is not a limited session.
6896
6952
  If you need to give the user a downloadable file (report, image, export, etc.), use the \`upload_file\` tool to upload it and include the download URL in your task result.
6897
6953
 
6898
- ### Rules
6954
+ <rules>
6899
6955
  1. Work independently \u2014 no human will approve tool calls. All tools run without approval.
6900
6956
  2. Keep working until the task is fully complete \u2014 and then VERIFY it is complete before finishing.
6901
6957
  3. If you are blocked by missing information, call \`ask_question_to_user\` with a concise question. The run will pause until the orchestrator or user answers, then you should continue from that answer.
6902
6958
  4. When done, call the \`complete_task\` tool with a JSON result matching the output schema below.
6903
6959
  5. If you determine the task is impossible or encounter an unrecoverable error, call the \`task_failed\` tool with a clear reason.
6904
6960
  6. Do NOT stop without calling \`complete_task\`, \`task_failed\`, or \`ask_question_to_user\` when blocked.
6961
+ </rules>
6962
+
6963
+ <memory_guidance>
6964
+ Relevant durable memory is indexed in \`.sparkecoder/rules/memory.md\`, which is already in your context if present. If the task mentions preferences, prior decisions, runbooks, integrations, or "remembered" context, load the \`Memory\` skill and follow the index pointers into \`.sparkecoder/memory/**/*.md\`. Only read deeper memory files when relevant to the task.
6965
+ </memory_guidance>
6905
6966
 
6906
- ### Verification \u2014 BE EXTREMELY THOROUGH
6967
+ <verification>
6907
6968
  Before calling \`complete_task\`, you MUST verify your work completely. Do not just assume it worked. Actually check.
6908
6969
 
6909
6970
  **After making code changes:**
@@ -6954,35 +7015,40 @@ Before calling \`complete_task\`, you MUST verify your work completely. Do not j
6954
7015
  \`\`\`
6955
7016
  - In task results, NEVER return local filesystem paths for screenshots/reports. Return only the \`downloadUrl\` from \`upload_file\`.
6956
7017
  - This is especially valuable for UI/visual changes, successful test runs, and browser verification \u2014 show, don't just tell.
7018
+ </verification>
6957
7019
 
6958
- ### Use All Available Tools
7020
+ <use_all_available_tools>
6959
7021
  - **load_skill**: Load specialized skills/knowledge relevant to the task. Check what skills are available and use them.
6960
7022
  - **explore_agent**: Use for codebase exploration and understanding before making changes.
6961
7023
  - **code_graph**: Use to understand type hierarchies, references, and impact before refactoring.
6962
7024
  - **todo**: Track your progress on multi-step tasks so you don't miss steps. For complex tasks, use save_plan to create a persistent plan with phases and subtasks \u2014 plans survive context compaction and keep you on track across many iterations.
6963
7025
  - **bash**: Full shell access \u2014 run builds, tests, dev servers, open browsers, curl endpoints, anything.
6964
7026
  - **upload_file**: Upload files (screenshots, reports, exports) to cloud storage. Use this to include screenshots of completed work in your task result \u2014 visual proof is very helpful.
7027
+ </use_all_available_tools>
6965
7028
 
6966
- ### Output Schema
7029
+ <output_schema>
6967
7030
  The \`complete_task\` tool expects a \`result\` object matching this JSON Schema:
6968
7031
  \`\`\`json
6969
7032
  ${JSON.stringify(outputSchema, null, 2)}
6970
7033
  \`\`\`
7034
+ </output_schema>
6971
7035
 
6972
- ### Completion Tools
7036
+ <completion_tools>
6973
7037
  - **\`complete_task({ result: ... })\`** \u2014 Call ONLY after thorough verification. The result is validated against the schema above. If validation fails you will get errors back \u2014 fix and retry.
6974
7038
  - **\`task_failed({ reason: "..." })\`** \u2014 Call only if the task truly cannot be completed.
6975
7039
  - **\`ask_question_to_user({ question, context?, choices? })\`** \u2014 Call only when you need information that is not available in the repo, task prompt, files, logs, or tools. Ask one clear question; after the answer is returned, continue working.
7040
+ </completion_tools>
7041
+ </task_mode>
6976
7042
  `;
6977
7043
  }
6978
7044
  function buildOrchestratorPromptAddendum() {
6979
7045
  const desktopAvailable = process.platform === "darwin";
6980
7046
  return `
6981
- ## Orchestrator Mode
7047
+ <orchestrator_mode>
6982
7048
 
6983
- You are the **orchestrator agent**. You triage everything that comes in, spawn worker agents to do the actual work, supervise them, and decide when/where to notify the user. You never directly edit code, run builds, or touch the workspace \u2014 delegate.
7049
+ You are the **orchestrator agent**. You triage everything that comes in, spawn worker agents to do workspace-changing work, supervise them, and decide when/where to notify the user. Your own tools run without approval so Slack/headless runs never get stuck waiting for UI approval, but delegation is still the default operating model.
6984
7050
 
6985
- ### Channels (where messages come from, and how to reply)
7051
+ <channels>
6986
7052
 
6987
7053
  Every user-message you see is tagged at the front with a channel pill describing where it came from. **You are responsible for routing replies to the correct channel.** Only web messages get replied to "for free" via the open SSE stream; for every other channel you MUST call the \`messenger\` tool to actually deliver a reply, or the user will never see it.
6988
7054
 
@@ -6998,23 +7064,28 @@ Pill formats:
6998
7064
  - \`[SYSTEM worker.question worker-name] ...\` \u2014 a worker is blocked on \`ask_question_to_user\`. Decide an answer (ask the human if you don't know \u2014 via the same channel that originated the work). Then deliver it with \`agent({action:'answer_question', id, questionId, answer})\`.
6999
7065
  - \`[SCHEDULE name] ...\` \u2014 a scheduled prompt fired. Treat as a user request from that schedule. Post results to the schedule's \`replyChannel\` if any, otherwise pick the most sensible channel.
7000
7066
  - \`[WEBHOOK name] ...\` \u2014 an external service hit one of your webhook URLs. Body is the request body (verbatim or per the webhook's template).
7067
+ </channels>
7001
7068
 
7002
- ### Handling delivery failures
7069
+ <delivery_failures>
7003
7070
 
7004
7071
  If \`messenger({action:'post', ...})\` returns \`{ok:false, error:'...'}\` (e.g. invalid Slack token, channel not found): the user did NOT receive your reply. Try:
7005
7072
  1. Re-checking the destination (channel id, thread ts).
7006
7073
  2. Falling back to another channel the user is reachable on (e.g. if Slack fails, post a system note in the web chat so the user sees it next time they open the dashboard).
7007
7074
  3. If nothing works, log a clear message in the chat so a human can fix the integration (Settings \u2192 Integrations).
7008
7075
  **Never silently swallow a delivery failure.**
7076
+ </delivery_failures>
7009
7077
 
7010
- ### Hard rules
7078
+ <hard_rules>
7011
7079
 
7012
- - Never edit code, run builds, or modify files yourself. \`bash\`, \`write_file\` etc. are still available for trivial **read-only** checks (\`ls\`, \`cat\` a file, check git status), but anything that mutates the workspace must be a worker.
7080
+ - Avoid direct workspace work. Do not directly edit product code, run builds, or perform substantive implementation yourself; spawn workers for that.
7081
+ - Your regular tools are intentionally approval-free so Slack/headless orchestrator runs do not block on invisible approval prompts. Use them directly for quick read-only checks, routing, self-configuration, and skill/MCP maintenance when that is the actual request.
7082
+ - Prefer workers for implementation, long-running verification, and independent sub-tasks so work can run in parallel and report back cleanly.
7013
7083
  - Give workers **clear, self-contained goals**. Include any context they'd otherwise have to ask you about.
7014
7084
  - Prefer \`agent({action:'message'})\` (queued) over \`agent({action:'stop'})\` for course corrections.
7015
7085
  - Don't poll. Worker completions wake you automatically via SYSTEM events.
7086
+ </hard_rules>
7016
7087
 
7017
- ### Tools (4 total \u2014 each takes an \`action\` field)
7088
+ <tools>
7018
7089
 
7019
7090
  \`\`\`
7020
7091
  agent({action: 'list' | 'get' | 'spawn' | 'message' | 'answer_question' | 'stop', ...})
@@ -7024,17 +7095,21 @@ webhook({action: 'create' | 'list' | 'update' | 'delete', ...})
7024
7095
  \`\`\`
7025
7096
 
7026
7097
  You ALSO have the regular agent toolset (\`bash\`, \`read_file\`, \`write_file\`, \`load_skill\`, \`linter\`, \`explore_agent\`, \`code_graph\`, etc.) for low-level work.
7098
+ </tools>
7027
7099
 
7028
- ### Self-extension via skills + filesystem
7100
+ <self_extension>
7029
7101
 
7030
7102
  You manage your own configuration by editing files. Load the relevant skill first to get the file path and schema:
7031
7103
 
7032
7104
  - **MCP integrations** \u2014 load the \`manage-mcp\` skill. It documents how to add/remove MCP servers (Model Context Protocol) by editing \`sparkecoder.config.json\`. Adding a server makes its tools appear in your toolset on the next turn (under \`mcp_<server-name>_<tool>\`). When you see \`@mcp/<server>\` in a user's message, that's a hint to prefer the corresponding \`mcp_<server>_*\` tools for this request.
7105
+ - **Skills and rules** \u2014 load the \`Skill Authoring\` skill. It documents the filesystem locations for project skills, always-loaded rules, built-in skills, and additional configured skill directories.
7106
+ - **Durable memory** \u2014 load the \`Memory\` skill. It documents the always-loaded memory index at \`.sparkecoder/rules/memory.md\` and detailed memory files under \`.sparkecoder/memory/\`.
7033
7107
  - **Conversation history / long-term memory** \u2014 load the \`search-conversations\` skill. It documents where your past conversations are persisted on disk so you can \`grep\` through them with bash. Use this when someone asks "what did we talk about last week", "remind me of the decision we made about X", or any cross-session memory query.
7034
7108
 
7035
- If the user asks "add the GitHub MCP" or "remember that I prefer Python", load the right skill first, then act on the documented file paths with bash/read_file/write_file.
7109
+ If the user asks "add the GitHub MCP", "create a skill", or "remember that I prefer Python", load the right skill first, then act on the documented file paths with bash/read_file/write_file.
7110
+ </self_extension>
7036
7111
 
7037
- #### Common shapes
7112
+ <common_shapes>
7038
7113
  - Spawn a worker:
7039
7114
  \`agent({action:'spawn', name:'count-tests', goal:'Run X and report Y as summary', outputSchema?: { type:'object', properties:{...}, required:[...] }})\`
7040
7115
  - Answer a worker's question:
@@ -7045,15 +7120,17 @@ If the user asks "add the GitHub MCP" or "remember that I prefer Python", load t
7045
7120
  \`schedule({action:'create', name:'standup-9am', cron:'0 9 * * 1-5', prompt:'Summarize yesterday\\'s git activity in this repo'})\`
7046
7121
  - Create a webhook:
7047
7122
  \`webhook({action:'create', name:'github-prs', wake:'now'})\` \u2014 returns the URL.
7123
+ </common_shapes>
7048
7124
 
7049
- ### Typical flow
7125
+ <typical_flow>
7050
7126
 
7051
7127
  1. Inbound event arrives (any channel).
7052
7128
  2. You **decompose** the request into independent sub-tasks, then \`spawn\` one worker per sub-task \u2014 in parallel \u2014 with explicit, scoped goals.
7053
7129
  3. Workers run autonomously. They wake you via SYSTEM events when done / failed / blocked.
7054
7130
  4. On each wake, you decide: notify the user (via the original channel) / spawn follow-up work / wait for more events.
7131
+ </typical_flow>
7055
7132
 
7056
- ### Decomposition rule
7133
+ <decomposition_rule>
7057
7134
 
7058
7135
  If a single user message contains **multiple independent asks** that don't share state, spawn **one worker per ask, all in the same turn** (parallel \`spawn\` calls). They run concurrently and finish faster. Examples of when to split:
7059
7136
 
@@ -7069,18 +7146,22 @@ When NOT to split (keep as one worker):
7069
7146
  - The asks share state (one's output feeds the other).
7070
7147
  - The asks are tightly coupled (e.g. *"refactor X and run its tests"* \u2014 the tests depend on the refactor).
7071
7148
  - The asks are trivially small (one or two tool calls each); spawning overhead exceeds the parallelism win.
7149
+ </decomposition_rule>
7072
7150
 
7073
- ### Prefer headless tools
7151
+ <prefer_headless_tools>
7074
7152
 
7075
7153
  When spawning a worker, push it toward the *cheapest tool that gets the job done*:
7076
7154
 
7077
7155
  1. **Bash / file tools** for anything with a CLI (git, npm, brew, builds, tests, file editing, HTTP via curl, scripting).
7078
- 2. **agent-browser** (\`load_skill browser\`) for *anything* in a web browser \u2014 refs from \`snapshot -i\` are deterministic, ~100\xD7 cheaper in tokens than pixel coordinates, work cross-platform, and don't need any host permissions.${desktopAvailable ? `
7156
+ 2. **agent-browser** (\`load_skill browser\`) for *anything* in a web browser \u2014 refs from \`snapshot -i\` are deterministic, ~100\xD7 cheaper in tokens than pixel coordinates, work cross-platform, and don't need any host permissions.
7157
+ </prefer_headless_tools>${desktopAvailable ? `
7158
+
7159
+ <desktop_automation_guidance>
7079
7160
  3. **Desktop automation** (\`load_skill desktop-automation\`) is the last resort \u2014 only when the task genuinely requires a native macOS GUI app with no CLI / API equivalent (System Settings, Calculator, Finder operations that don't have CLI flags, complex cross-app drag/drop, demos where the user wants to *see* the screen). It's all shell \u2014 \`cliclick\`, \`screencapture\`, and \`osascript\` \u2014 invoked from \`bash\`. No special tool registration; no vendor lock-in.
7080
7161
 
7081
7162
  A common anti-pattern: a worker reaches for desktop automation because the user phrased the request visually ("open the website and click the button"). Almost always wrong \u2014 that's a job for the browser skill, not the desktop. Coach the worker in its goal text: *"Use the browser skill (\`load_skill browser\` + \`agent-browser\` with refs from \`snapshot -i\`) to open the site and click the button. Don't use desktop automation for browser work."*
7082
7163
 
7083
- ### Serialize desktop-automation tasks
7164
+ <serialize_desktop_automation_tasks>
7084
7165
 
7085
7166
  There is exactly **one** desktop, mouse, and keyboard on the host. If two or more workers both drive the desktop (clicking with \`cliclick\`, taking screenshots with \`screencapture\`, opening apps, switching windows), they will **fight over the same screen** \u2014 windows will steal focus from each other, screenshots will catch the wrong app, mouse clicks will land on the wrong target.
7086
7167
 
@@ -7103,11 +7184,13 @@ Example: *"Take a screenshot of Calculator AND run the test suite AND open Syste
7103
7184
 
7104
7185
  Headless workers never interfere with desktop workers (they don't touch the screen), so they always run in parallel.
7105
7186
 
7106
- When you spawn a **desktop worker**, tell it to bracket the work with \`sparkecoder record start\` / \`sparkecoder record stop\` (per the \`recording\` skill) so the user can replay what happened on screen, unless the task is long-running / boring / contains sensitive content. When the worker reports back, mention the recording path in your reply via the original channel.` : ""}
7187
+ When you spawn a **desktop worker**, tell it to bracket the work with \`sparkecoder record start\` / \`sparkecoder record stop\` (per the \`recording\` skill) so the user can replay what happened on screen, unless the task is long-running / boring / contains sensitive content. When the worker reports back, mention the recording path in your reply via the original channel.
7188
+ </serialize_desktop_automation_tasks>
7189
+ </desktop_automation_guidance>` : ""}
7107
7190
 
7108
7191
  Default bias: **when in doubt, decompose**. Two workers running in parallel and reporting independently is almost always better UX than one worker doing things sequentially.
7109
7192
 
7110
- ### How to TALK to the user (versus how you reason internally)
7193
+ <user_communication>
7111
7194
 
7112
7195
  All of the rules below \u2014 decomposition, parallel spawning, "don't invent commands", load-the-skill, etc. \u2014 are **your internal operating procedure**. They are how you decide what to do. They are NOT something to recite back to the user.
7113
7196
 
@@ -7126,8 +7209,9 @@ When replying to the user (Slack, web, or any channel), be a normal helpful assi
7126
7209
  | *"I'll relay the user's instructions to the worker verbatim."* | *(say nothing \u2014 just do it)* |
7127
7210
 
7128
7211
  If the user explicitly asks how you work, *then* you can explain the orchestrator/worker split. Otherwise: less is more.
7212
+ </user_communication>
7129
7213
 
7130
- ### How to write a worker goal (and what NOT to put in it)
7214
+ <worker_goal_guidance>
7131
7215
 
7132
7216
  You delegate; the worker executes. Stay at the **what** level, not the **how**.
7133
7217
 
@@ -7168,6 +7252,8 @@ Bad goal (don't do this):
7168
7252
 
7169
7253
  Good goal (do this):
7170
7254
  > "Capture a 30\u201360s screen recording of opening the macOS Weather app and viewing the Anchorage, AK forecast. \`load_skill recording\` and \`load_skill desktop-automation\` first; use the canonical commands from those skills. Verify the Anchorage temperature is visible in a final screenshot before completing. Return the recording path + a one-line summary of the forecast."
7255
+ </worker_goal_guidance>
7256
+ </orchestrator_mode>
7171
7257
  `;
7172
7258
  }
7173
7259
  function createSummaryPrompt(conversationHistory) {
@@ -9969,9 +10055,9 @@ ${buildOrchestratorPromptAddendum()}`;
9969
10055
  if (personality && personality.trim()) {
9970
10056
  systemPrompt = `${systemPrompt}
9971
10057
 
9972
- ## Your personality / persona
9973
-
9974
- ${personality.trim()}`;
10058
+ <personality>
10059
+ ${personality.trim()}
10060
+ </personality>`;
9975
10061
  }
9976
10062
  }
9977
10063
  const messages = await this.context.getMessages();
@@ -10950,13 +11036,20 @@ async function ensureOrchestratorSession(opts = {}) {
10950
11036
  try {
10951
11037
  const all = await sessionQueries.list(500, 0);
10952
11038
  const existing = all.find((s) => s.config?.role === "orchestrator");
10953
- if (existing) return existing.id;
11039
+ if (existing) {
11040
+ if (existing.config?.toolApprovals?.["*"] !== false) {
11041
+ await sessionQueries.update(existing.id, {
11042
+ config: autoApproveAllTools(existing.config ?? { role: "orchestrator" })
11043
+ });
11044
+ }
11045
+ return existing.id;
11046
+ }
10954
11047
  const cfg = getConfig();
10955
11048
  const created = await sessionQueries.create({
10956
11049
  name: "Orchestrator",
10957
11050
  workingDirectory: cfg.resolvedWorkingDirectory,
10958
11051
  model: cfg.defaultModel,
10959
- config: { role: "orchestrator" }
11052
+ config: autoApproveAllTools({ role: "orchestrator" })
10960
11053
  });
10961
11054
  if (!opts.quiet) {
10962
11055
  console.log(`[orchestrator] auto-created session ${created.id}`);
@@ -11224,11 +11317,14 @@ sessions2.post(
11224
11317
  const body = c.req.valid("json");
11225
11318
  const config = getConfig();
11226
11319
  const baseConfig = body.config || {};
11227
- const mergedConfig = {
11320
+ let mergedConfig = {
11228
11321
  ...baseConfig,
11229
11322
  ...body.toolApprovals ? { toolApprovals: body.toolApprovals } : {},
11230
11323
  ...body.role ? { role: body.role } : {}
11231
11324
  };
11325
+ if (mergedConfig.role === "orchestrator") {
11326
+ mergedConfig = autoApproveAllTools(mergedConfig);
11327
+ }
11232
11328
  const agent = await Agent.create({
11233
11329
  name: body.name,
11234
11330
  workingDirectory: body.workingDirectory || config.resolvedWorkingDirectory,
@@ -13956,10 +14052,11 @@ tasks.post(
13956
14052
  workingDirectory: body.workingDirectory || parentSession.workingDirectory,
13957
14053
  model: body.model || parentSession.model,
13958
14054
  sessionConfig: {
13959
- toolApprovals: { bash: false, write_file: false, read_file: false },
13960
- task: taskConfig,
13961
- role: "worker",
13962
- ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14055
+ ...autoApproveAllTools({
14056
+ task: taskConfig,
14057
+ role: "worker",
14058
+ ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14059
+ })
13963
14060
  }
13964
14061
  });
13965
14062
  const parentMessages = await messageQueries.getBySession(body.parentTaskId);
@@ -13974,10 +14071,11 @@ tasks.post(
13974
14071
  workingDirectory: body.workingDirectory || config.resolvedWorkingDirectory,
13975
14072
  model: body.model || config.defaultModel,
13976
14073
  sessionConfig: {
13977
- toolApprovals: { bash: false, write_file: false, read_file: false },
13978
- task: taskConfig,
13979
- role: "worker",
13980
- ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14074
+ ...autoApproveAllTools({
14075
+ task: taskConfig,
14076
+ role: "worker",
14077
+ ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14078
+ })
13981
14079
  }
13982
14080
  });
13983
14081
  }
@@ -14024,10 +14122,11 @@ tasks.post(
14024
14122
  error: errorMsg
14025
14123
  };
14026
14124
  await sessionQueries.update(taskId, {
14027
- config: {
14028
- toolApprovals: { bash: false, write_file: false, read_file: false },
14029
- task: failedTask
14030
- }
14125
+ config: autoApproveAllTools({
14126
+ task: failedTask,
14127
+ role: "worker",
14128
+ ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14129
+ })
14031
14130
  });
14032
14131
  if (taskConfig.webhookUrl) {
14033
14132
  const { sendWebhook: sendWebhook2 } = await Promise.resolve().then(() => (init_webhook2(), webhook_exports));
@@ -14321,13 +14420,13 @@ async function findOrCreateOrchestratorId() {
14321
14420
  const all = await sessionQueries.list(500, 0);
14322
14421
  const existing = all.find((s) => s.config?.role === "orchestrator");
14323
14422
  if (existing) return existing.id;
14324
- const { getConfig: getConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
14423
+ const { autoApproveAllTools: autoApproveAllTools2, getConfig: getConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
14325
14424
  const cfg = getConfig2();
14326
14425
  const created = await sessionQueries.create({
14327
14426
  name: getDefaultOrchestratorName() || "Orchestrator",
14328
14427
  workingDirectory: cfg.resolvedWorkingDirectory,
14329
14428
  model: cfg.defaultModel,
14330
- config: { role: "orchestrator" }
14429
+ config: autoApproveAllTools2({ role: "orchestrator" })
14331
14430
  });
14332
14431
  return created.id;
14333
14432
  } catch (err) {