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
@@ -705,7 +705,10 @@ var init_types = __esm({
705
705
  // not listed here. Values match `process.platform`
706
706
  // (darwin, linux, win32, freebsd, ...). If omitted or empty, the skill is
707
707
  // available on all platforms.
708
- platforms: z.array(z.string()).optional().default([])
708
+ platforms: z.array(z.string()).optional().default([]),
709
+ // Optional approximate token budget for always-loaded content. If set,
710
+ // the prompt builder truncates this skill/rule before injecting it.
711
+ contextBudgetTokens: z.number().int().positive().optional()
709
712
  });
710
713
  TaskConfigSchema = z.object({
711
714
  enabled: z.boolean(),
@@ -944,6 +947,7 @@ __export(config_exports, {
944
947
  TaskConfigSchema: () => TaskConfigSchema,
945
948
  ToolApprovalConfigSchema: () => ToolApprovalConfigSchema,
946
949
  VectorGatewayConfigSchema: () => VectorGatewayConfigSchema,
950
+ autoApproveAllTools: () => autoApproveAllTools,
947
951
  clearSlackConfig: () => clearSlackConfig,
948
952
  createDefaultConfig: () => createDefaultConfig,
949
953
  discoverSkillDirectories: () => discoverSkillDirectories,
@@ -1339,6 +1343,16 @@ function requiresApproval(toolName, sessionConfig) {
1339
1343
  }
1340
1344
  return false;
1341
1345
  }
1346
+ function autoApproveAllTools(sessionConfig) {
1347
+ const currentApprovals = sessionConfig.toolApprovals;
1348
+ return {
1349
+ ...sessionConfig,
1350
+ toolApprovals: {
1351
+ ...currentApprovals ?? {},
1352
+ ...AUTO_APPROVE_ALL_TOOLS
1353
+ }
1354
+ };
1355
+ }
1342
1356
  function createDefaultConfig() {
1343
1357
  return {
1344
1358
  defaultModel: "anthropic/claude-opus-4.7",
@@ -1569,7 +1583,7 @@ function maskApiKey(key2) {
1569
1583
  }
1570
1584
  return key2.slice(0, 4) + "..." + key2.slice(-4);
1571
1585
  }
1572
- var CONFIG_FILE_NAMES, cachedConfig, AUTH_KEY_FILE, API_KEYS_FILE, PROVIDER_ENV_MAP, SUPPORTED_PROVIDERS;
1586
+ var CONFIG_FILE_NAMES, cachedConfig, AUTO_APPROVE_ALL_TOOLS, AUTH_KEY_FILE, API_KEYS_FILE, PROVIDER_ENV_MAP, SUPPORTED_PROVIDERS;
1573
1587
  var init_config = __esm({
1574
1588
  "src/config/index.ts"() {
1575
1589
  "use strict";
@@ -1581,6 +1595,7 @@ var init_config = __esm({
1581
1595
  ".sparkecoder.json"
1582
1596
  ];
1583
1597
  cachedConfig = null;
1598
+ AUTO_APPROVE_ALL_TOOLS = { "*": false };
1584
1599
  AUTH_KEY_FILE = "auth-key.json";
1585
1600
  API_KEYS_FILE = "api-keys.json";
1586
1601
  PROVIDER_ENV_MAP = {
@@ -4035,6 +4050,8 @@ function parseSkillFrontmatter(content) {
4035
4050
  data[key2] = true;
4036
4051
  } else if (value === "false") {
4037
4052
  data[key2] = false;
4053
+ } else if (/^\d+$/.test(value)) {
4054
+ data[key2] = Number(value);
4038
4055
  } else {
4039
4056
  data[key2] = value;
4040
4057
  }
@@ -4094,7 +4111,8 @@ async function loadSkillsFromDirectory(directory, options = {}) {
4094
4111
  loadType,
4095
4112
  priority,
4096
4113
  sourceDir: directory,
4097
- platforms: parsed.metadata.platforms
4114
+ platforms: parsed.metadata.platforms,
4115
+ contextBudgetTokens: parsed.metadata.contextBudgetTokens
4098
4116
  });
4099
4117
  } else {
4100
4118
  const name = getSkillNameFromPath(filePath);
@@ -4108,7 +4126,8 @@ async function loadSkillsFromDirectory(directory, options = {}) {
4108
4126
  loadType: forceAlwaysApply ? "always" : defaultLoadType,
4109
4127
  priority,
4110
4128
  sourceDir: directory,
4111
- platforms: []
4129
+ platforms: [],
4130
+ contextBudgetTokens: void 0
4112
4131
  });
4113
4132
  }
4114
4133
  }
@@ -4238,11 +4257,12 @@ function formatSkillsForContext(skills2) {
4238
4257
  if (onDemandSkills.length === 0) {
4239
4258
  return "No on-demand skills available.";
4240
4259
  }
4241
- const lines = ["Available skills (use load_skill tool to load into context):"];
4260
+ const lines = ["<available_skills>", "Use the load_skill tool to load one of these into context:"];
4242
4261
  for (const skill of onDemandSkills) {
4243
4262
  const globInfo = skill.globs?.length ? ` [auto-loads for: ${skill.globs.join(", ")}]` : "";
4244
4263
  lines.push(`- ${skill.name}: ${skill.description}${globInfo}`);
4245
4264
  }
4265
+ lines.push("</available_skills>");
4246
4266
  return lines.join("\n");
4247
4267
  }
4248
4268
  function formatAlwaysLoadedSkills(skills2) {
@@ -4251,13 +4271,22 @@ function formatAlwaysLoadedSkills(skills2) {
4251
4271
  }
4252
4272
  const sections = [];
4253
4273
  for (const skill of skills2) {
4254
- sections.push(`### ${skill.name}
4255
-
4256
- ${skill.content}`);
4274
+ sections.push(`<skill name="${escapeXmlAttribute(skill.name)}">
4275
+ ${truncateSkillContent(skill)}
4276
+ </skill>`);
4257
4277
  }
4258
- return `## Active Rules & Skills (Always Loaded)
4278
+ return `<always_loaded_rules_and_skills>
4279
+ ${sections.join("\n\n")}
4280
+ </always_loaded_rules_and_skills>`;
4281
+ }
4282
+ function truncateSkillContent(skill) {
4283
+ if (!skill.contextBudgetTokens) return skill.content;
4284
+ const maxChars = Math.max(200, skill.contextBudgetTokens * 4);
4285
+ if (skill.content.length <= maxChars) return skill.content;
4286
+ const omitted = skill.content.length - maxChars;
4287
+ return `${skill.content.slice(0, maxChars).trimEnd()}
4259
4288
 
4260
- ${sections.join("\n\n---\n\n")}`;
4289
+ ... [${skill.name} truncated by contextBudgetTokens=${skill.contextBudgetTokens}; ${omitted} chars omitted. Read ${skill.filePath} for the full file.]`;
4261
4290
  }
4262
4291
  function formatGlobMatchedSkills(skills2) {
4263
4292
  if (skills2.length === 0) {
@@ -4265,21 +4294,24 @@ function formatGlobMatchedSkills(skills2) {
4265
4294
  }
4266
4295
  const sections = [];
4267
4296
  for (const skill of skills2) {
4268
- sections.push(`### ${skill.name}
4269
-
4270
- ${skill.content}`);
4297
+ sections.push(`<skill name="${escapeXmlAttribute(skill.name)}">
4298
+ ${skill.content}
4299
+ </skill>`);
4271
4300
  }
4272
- return `## Context-Relevant Skills (Auto-loaded based on active files)
4273
-
4274
- ${sections.join("\n\n---\n\n")}`;
4301
+ return `<glob_matched_skills>
4302
+ ${sections.join("\n\n")}
4303
+ </glob_matched_skills>`;
4275
4304
  }
4276
4305
  function formatAgentsMdContent(content) {
4277
4306
  if (!content) {
4278
4307
  return "";
4279
4308
  }
4280
- return `## Project Instructions (AGENTS.md)
4281
-
4282
- ${content}`;
4309
+ return `<project_instructions source="AGENTS.md">
4310
+ ${content}
4311
+ </project_instructions>`;
4312
+ }
4313
+ function escapeXmlAttribute(value) {
4314
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4283
4315
  }
4284
4316
  var init_skills = __esm({
4285
4317
  "src/skills/index.ts"() {
@@ -6544,14 +6576,18 @@ async function buildSystemPrompt(options) {
6544
6576
  const platform3 = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
6545
6577
  const currentDate = (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" });
6546
6578
  const searchInstructions = getSearchInstructions();
6547
- const systemPrompt = `You are SparkECoder, an expert AI coding assistant. You help developers write, debug, and improve code.
6579
+ const systemPrompt = `<system_prompt>
6580
+ <identity>
6581
+ You are SparkECoder, an expert AI coding assistant. You help developers write, debug, and improve code.
6582
+ </identity>
6548
6583
 
6549
- ## Environment
6584
+ <environment>
6550
6585
  - **Platform**: ${platform3} (${os.release()})
6551
6586
  - **Date**: ${currentDate}
6552
6587
  - **Working Directory**: ${workingDirectory}
6588
+ </environment>
6553
6589
 
6554
- ## Core Capabilities
6590
+ <core_capabilities>
6555
6591
  You have access to powerful tools for:
6556
6592
  - **bash**: Execute commands in the terminal (see below for details)
6557
6593
  - **read_file**: Read file contents to understand code and context
@@ -6565,8 +6601,9 @@ You have access to powerful tools for:
6565
6601
 
6566
6602
 
6567
6603
  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.
6604
+ </core_capabilities>
6568
6605
 
6569
- ### Planning & Task Management
6606
+ <planning_and_task_management>
6570
6607
  Use the **todo tool** to manage both immediate tasks AND persistent plans:
6571
6608
 
6572
6609
  **For simple tasks (< 5 steps):** Just use regular todos (add/mark/clear).
@@ -6586,8 +6623,9 @@ Use the **todo tool** to manage both immediate tasks AND persistent plans:
6586
6623
  - Only top-level checklist items (- [ ]) become todos \u2014 indented sub-items are part of the task detail
6587
6624
  - Sections named Overview, Notes, Key Decisions, etc. are not treated as phases
6588
6625
  - You can clear the todo list and restart it, and do multiple things inside of one session
6626
+ </planning_and_task_management>
6589
6627
 
6590
- ### bash Tool
6628
+ <bash_tool>
6591
6629
  The bash tool runs commands in the terminal. Every command runs in its own session with logs saved to disk.
6592
6630
 
6593
6631
  **Run a command (default - waits for completion):**
@@ -6634,22 +6672,25 @@ bash({ id: "abc123", input: "my text" }) // send text input
6634
6672
  - Use \`input: "text"\` for text input prompts
6635
6673
 
6636
6674
  Terminal output is stored in the global SparkECoder data directory. Use the \`tail\` option to read recent output.
6675
+ </bash_tool>
6637
6676
 
6638
- ## Guidelines
6677
+ <guidelines>
6639
6678
 
6640
- ### Code Quality
6679
+ <code_quality>
6641
6680
  - Write clean, maintainable, well-documented code
6642
6681
  - Follow existing code style and conventions in the project
6643
6682
  - Use meaningful variable and function names
6644
6683
  - Add comments for complex logic
6684
+ </code_quality>
6645
6685
 
6646
- ### Problem Solving
6686
+ <problem_solving>
6647
6687
  - Before making changes, understand the existing code structure
6648
6688
  - Break complex tasks into smaller, manageable steps using the todo tool
6649
6689
  - Test changes when possible using the bash tool
6650
6690
  - Handle errors gracefully and provide helpful error messages
6691
+ </problem_solving>
6651
6692
 
6652
- ### File Operations
6693
+ <file_operations>
6653
6694
  - Use \`read_file\` to understand code before modifying
6654
6695
  - Use \`write_file\` with mode "str_replace" for targeted edits to existing files
6655
6696
  - Use \`write_file\` with mode "full" only for new files or complete rewrites
@@ -6658,8 +6699,9 @@ Terminal output is stored in the global SparkECoder data directory. Use the \`ta
6658
6699
  - If the user asks to write/create a file, always use \`write_file\` rather than printing the full contents
6659
6700
  - If the user requests a file but does not provide a path, choose a sensible default (e.g. \`index.html\`) and proceed
6660
6701
  - For large content (hundreds of lines), avoid placing it in chat output; write to a file instead
6702
+ </file_operations>
6661
6703
 
6662
- ### Linter Tool
6704
+ <linter_tool>
6663
6705
  The linter tool uses Language Server Protocol (LSP) to detect type errors and lint issues:
6664
6706
  \`\`\`
6665
6707
  linter({}) // Check all recently edited files
@@ -6667,8 +6709,9 @@ linter({ paths: ["src/app.ts"] }) // Check specific files
6667
6709
  linter({ paths: ["src/"] }) // Check all files in a directory
6668
6710
  \`\`\`
6669
6711
  Use this proactively after making code changes to catch errors early.
6712
+ </linter_tool>
6670
6713
 
6671
- ### Code Graph Tool
6714
+ <code_graph_tool>
6672
6715
  The code_graph tool uses the TypeScript language server to inspect a symbol's type hierarchy and usage graph:
6673
6716
  \`\`\`
6674
6717
  code_graph({ symbol: "UserCard" }) // Search workspace for symbol
@@ -6694,8 +6737,9 @@ code_graph({ symbol: "formatUser", filePath: "utils.ts", depth: 2 }) // Travers
6694
6737
  - For exploratory "how does X work?" questions \u2014 use \`explore_agent\` instead
6695
6738
  - For exact string searches \u2014 use grep/rg directly
6696
6739
  - For non-TypeScript/JavaScript files \u2014 code_graph only supports TS/JS/TSX/JSX
6740
+ </code_graph_tool>
6697
6741
 
6698
- ### Searching and Exploration
6742
+ <searching_and_exploration>
6699
6743
 
6700
6744
  **Choose the right search approach:**
6701
6745
 
@@ -6746,8 +6790,9 @@ code_graph({ symbol: "formatUser", filePath: "utils.ts", depth: 2 }) // Travers
6746
6790
  - "Find files named config" \u2192 Use \`find . -name "*config*"\`
6747
6791
 
6748
6792
  ${searchInstructions}
6793
+ </searching_and_exploration>
6749
6794
 
6750
- ###Follow these principles when designing and implementing software:
6795
+ <software_design_principles>
6751
6796
 
6752
6797
  1. **Modularity** \u2014 Write simple parts connected by clean interfaces
6753
6798
  2. **Clarity** \u2014 Clarity is better than cleverness
@@ -6766,8 +6811,9 @@ ${searchInstructions}
6766
6811
  15. **Optimization** \u2014 Prototype before polishing. Get it working before you optimize it
6767
6812
  16. **Diversity** \u2014 Distrust all claims for "one true way"
6768
6813
  17. **Extensibility** \u2014 Design for the future, because it will be here sooner than you think
6814
+ </software_design_principles>
6769
6815
 
6770
- ### Follow these design rules for any user interfaces or experiences you write (DESIGN LIKE APPLE):
6816
+ <ui_design_principles>
6771
6817
 
6772
6818
  1. **Simplicity** \u2014 Simplicity is the ultimate sophistication. Remove everything unnecessary.
6773
6819
  2. **Focus** \u2014 Say no to 1,000 things to say yes to the few that matter most.
@@ -6779,8 +6825,9 @@ ${searchInstructions}
6779
6825
  8. **Feedback** \u2014 Every action deserves a response. Make interactions feel alive.
6780
6826
  9. **Forgiveness** \u2014 Make it easy to undo. Never punish exploration.
6781
6827
  10. **Beauty** \u2014 Aesthetics are not superficial. Beautiful things work better because people care about them.
6828
+ </ui_design_principles>
6782
6829
 
6783
- ### Follow these rules to be a good agent for the user:
6830
+ <agent_behavior_rules>
6784
6831
 
6785
6832
  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.
6786
6833
  2. Plan for complexity - If the task involves 3+ steps or has meaningful trade-offs, create a todo list to track progress before implementing.
@@ -6789,13 +6836,16 @@ ${searchInstructions}
6789
6836
  5. Be direct - Focus on technical accuracy rather than validation. If see issues with an approach or need clarification, say so.
6790
6837
  6. Verify my work - After making changes, check for linter errors and fix any introduced.
6791
6838
  7. Respect boundaries - Only commit code when explicitly asked, avoid creating unnecessary files, and don't make assumptions about things uncertain about.
6839
+ </agent_behavior_rules>
6792
6840
 
6793
6841
 
6794
- ### Communication
6842
+ <communication>
6795
6843
  - Explain your reasoning and approach
6796
6844
  - Be concise but thorough
6797
6845
  - Ask clarifying questions when requirements are ambiguous
6798
6846
  - Report progress on multi-step tasks
6847
+ </communication>
6848
+ </guidelines>
6799
6849
 
6800
6850
  ${agentsMdContent}
6801
6851
 
@@ -6803,18 +6853,24 @@ ${alwaysLoadedContent}
6803
6853
 
6804
6854
  ${globMatchedContent}
6805
6855
 
6806
- ## On-Demand Skills
6856
+ <on_demand_skills>
6807
6857
  ${onDemandSkillsContext}
6858
+ </on_demand_skills>
6808
6859
 
6809
- ## Current Task List
6860
+ <current_task_list>
6810
6861
  ${todosContext}
6862
+ </current_task_list>
6811
6863
 
6812
6864
  ${plansContext}
6813
6865
 
6814
- ${customInstructions ? `## Custom Instructions
6815
- ${customInstructions}` : ""}
6866
+ ${customInstructions ? `<custom_instructions>
6867
+ ${customInstructions}
6868
+ </custom_instructions>` : ""}
6816
6869
 
6817
- Remember: You are a helpful, capable coding assistant. Take initiative, be thorough, and deliver high-quality results.`;
6870
+ <final_reminder>
6871
+ Remember: You are a helpful, capable coding assistant. Take initiative, be thorough, and deliver high-quality results.
6872
+ </final_reminder>
6873
+ </system_prompt>`;
6818
6874
  return systemPrompt;
6819
6875
  }
6820
6876
  function formatTodosForContext(todos) {
@@ -6838,7 +6894,7 @@ function formatPlansForContext(plans, shouldContinue) {
6838
6894
  if (plans.length === 0) return "";
6839
6895
  let totalChars = 0;
6840
6896
  const sections = [];
6841
- sections.push(`## Persistent Plans (${plans.length})`);
6897
+ sections.push(`<persistent_plans count="${plans.length}">`);
6842
6898
  sections.push("");
6843
6899
  sections.push("These plans persist across context compaction \u2014 they are always available.");
6844
6900
  sections.push("When you finish your current todos, check these plans for the next uncompleted phase,");
@@ -6859,34 +6915,39 @@ function formatPlansForContext(plans, shouldContinue) {
6859
6915
  ... [plan truncated \u2014 ${content.length - MAX_PLAN_CHARS} chars omitted. Use get_plan to read the full plan.]`;
6860
6916
  }
6861
6917
  if (totalChars + content.length > MAX_TOTAL_PLANS_CHARS) {
6862
- sections.push(`### \u{1F4CB} Plan: ${plan.name} [truncated \u2014 use get_plan("${plan.name}") to read]`);
6918
+ sections.push(`<plan name="${plan.name}" truncated="true">Use get_plan("${plan.name}") to read.</plan>`);
6863
6919
  continue;
6864
6920
  }
6865
- sections.push(`### \u{1F4CB} Plan: ${plan.name}`);
6866
- sections.push("");
6921
+ sections.push(`<plan name="${plan.name}">`);
6867
6922
  sections.push(content);
6868
- sections.push("");
6923
+ sections.push("</plan>");
6869
6924
  totalChars += content.length;
6870
6925
  }
6926
+ sections.push("</persistent_plans>");
6871
6927
  return sections.join("\n");
6872
6928
  }
6873
6929
  function buildTaskPromptAddendum(outputSchema) {
6874
6930
  return `
6875
- ## Task Mode
6931
+ <task_mode>
6876
6932
 
6877
6933
  You are running in **task mode**. You have been given a specific task to complete autonomously.
6878
6934
  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.
6879
6935
  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.
6880
6936
 
6881
- ### Rules
6937
+ <rules>
6882
6938
  1. Work independently \u2014 no human will approve tool calls. All tools run without approval.
6883
6939
  2. Keep working until the task is fully complete \u2014 and then VERIFY it is complete before finishing.
6884
6940
  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.
6885
6941
  4. When done, call the \`complete_task\` tool with a JSON result matching the output schema below.
6886
6942
  5. If you determine the task is impossible or encounter an unrecoverable error, call the \`task_failed\` tool with a clear reason.
6887
6943
  6. Do NOT stop without calling \`complete_task\`, \`task_failed\`, or \`ask_question_to_user\` when blocked.
6944
+ </rules>
6945
+
6946
+ <memory_guidance>
6947
+ 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.
6948
+ </memory_guidance>
6888
6949
 
6889
- ### Verification \u2014 BE EXTREMELY THOROUGH
6950
+ <verification>
6890
6951
  Before calling \`complete_task\`, you MUST verify your work completely. Do not just assume it worked. Actually check.
6891
6952
 
6892
6953
  **After making code changes:**
@@ -6937,35 +6998,40 @@ Before calling \`complete_task\`, you MUST verify your work completely. Do not j
6937
6998
  \`\`\`
6938
6999
  - In task results, NEVER return local filesystem paths for screenshots/reports. Return only the \`downloadUrl\` from \`upload_file\`.
6939
7000
  - This is especially valuable for UI/visual changes, successful test runs, and browser verification \u2014 show, don't just tell.
7001
+ </verification>
6940
7002
 
6941
- ### Use All Available Tools
7003
+ <use_all_available_tools>
6942
7004
  - **load_skill**: Load specialized skills/knowledge relevant to the task. Check what skills are available and use them.
6943
7005
  - **explore_agent**: Use for codebase exploration and understanding before making changes.
6944
7006
  - **code_graph**: Use to understand type hierarchies, references, and impact before refactoring.
6945
7007
  - **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.
6946
7008
  - **bash**: Full shell access \u2014 run builds, tests, dev servers, open browsers, curl endpoints, anything.
6947
7009
  - **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.
7010
+ </use_all_available_tools>
6948
7011
 
6949
- ### Output Schema
7012
+ <output_schema>
6950
7013
  The \`complete_task\` tool expects a \`result\` object matching this JSON Schema:
6951
7014
  \`\`\`json
6952
7015
  ${JSON.stringify(outputSchema, null, 2)}
6953
7016
  \`\`\`
7017
+ </output_schema>
6954
7018
 
6955
- ### Completion Tools
7019
+ <completion_tools>
6956
7020
  - **\`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.
6957
7021
  - **\`task_failed({ reason: "..." })\`** \u2014 Call only if the task truly cannot be completed.
6958
7022
  - **\`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.
7023
+ </completion_tools>
7024
+ </task_mode>
6959
7025
  `;
6960
7026
  }
6961
7027
  function buildOrchestratorPromptAddendum() {
6962
7028
  const desktopAvailable = process.platform === "darwin";
6963
7029
  return `
6964
- ## Orchestrator Mode
7030
+ <orchestrator_mode>
6965
7031
 
6966
- 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.
7032
+ 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.
6967
7033
 
6968
- ### Channels (where messages come from, and how to reply)
7034
+ <channels>
6969
7035
 
6970
7036
  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.
6971
7037
 
@@ -6981,23 +7047,28 @@ Pill formats:
6981
7047
  - \`[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})\`.
6982
7048
  - \`[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.
6983
7049
  - \`[WEBHOOK name] ...\` \u2014 an external service hit one of your webhook URLs. Body is the request body (verbatim or per the webhook's template).
7050
+ </channels>
6984
7051
 
6985
- ### Handling delivery failures
7052
+ <delivery_failures>
6986
7053
 
6987
7054
  If \`messenger({action:'post', ...})\` returns \`{ok:false, error:'...'}\` (e.g. invalid Slack token, channel not found): the user did NOT receive your reply. Try:
6988
7055
  1. Re-checking the destination (channel id, thread ts).
6989
7056
  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).
6990
7057
  3. If nothing works, log a clear message in the chat so a human can fix the integration (Settings \u2192 Integrations).
6991
7058
  **Never silently swallow a delivery failure.**
7059
+ </delivery_failures>
6992
7060
 
6993
- ### Hard rules
7061
+ <hard_rules>
6994
7062
 
6995
- - 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.
7063
+ - Avoid direct workspace work. Do not directly edit product code, run builds, or perform substantive implementation yourself; spawn workers for that.
7064
+ - 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.
7065
+ - Prefer workers for implementation, long-running verification, and independent sub-tasks so work can run in parallel and report back cleanly.
6996
7066
  - Give workers **clear, self-contained goals**. Include any context they'd otherwise have to ask you about.
6997
7067
  - Prefer \`agent({action:'message'})\` (queued) over \`agent({action:'stop'})\` for course corrections.
6998
7068
  - Don't poll. Worker completions wake you automatically via SYSTEM events.
7069
+ </hard_rules>
6999
7070
 
7000
- ### Tools (4 total \u2014 each takes an \`action\` field)
7071
+ <tools>
7001
7072
 
7002
7073
  \`\`\`
7003
7074
  agent({action: 'list' | 'get' | 'spawn' | 'message' | 'answer_question' | 'stop', ...})
@@ -7007,17 +7078,21 @@ webhook({action: 'create' | 'list' | 'update' | 'delete', ...})
7007
7078
  \`\`\`
7008
7079
 
7009
7080
  You ALSO have the regular agent toolset (\`bash\`, \`read_file\`, \`write_file\`, \`load_skill\`, \`linter\`, \`explore_agent\`, \`code_graph\`, etc.) for low-level work.
7081
+ </tools>
7010
7082
 
7011
- ### Self-extension via skills + filesystem
7083
+ <self_extension>
7012
7084
 
7013
7085
  You manage your own configuration by editing files. Load the relevant skill first to get the file path and schema:
7014
7086
 
7015
7087
  - **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.
7088
+ - **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.
7089
+ - **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/\`.
7016
7090
  - **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.
7017
7091
 
7018
- 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.
7092
+ 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.
7093
+ </self_extension>
7019
7094
 
7020
- #### Common shapes
7095
+ <common_shapes>
7021
7096
  - Spawn a worker:
7022
7097
  \`agent({action:'spawn', name:'count-tests', goal:'Run X and report Y as summary', outputSchema?: { type:'object', properties:{...}, required:[...] }})\`
7023
7098
  - Answer a worker's question:
@@ -7028,15 +7103,17 @@ If the user asks "add the GitHub MCP" or "remember that I prefer Python", load t
7028
7103
  \`schedule({action:'create', name:'standup-9am', cron:'0 9 * * 1-5', prompt:'Summarize yesterday\\'s git activity in this repo'})\`
7029
7104
  - Create a webhook:
7030
7105
  \`webhook({action:'create', name:'github-prs', wake:'now'})\` \u2014 returns the URL.
7106
+ </common_shapes>
7031
7107
 
7032
- ### Typical flow
7108
+ <typical_flow>
7033
7109
 
7034
7110
  1. Inbound event arrives (any channel).
7035
7111
  2. You **decompose** the request into independent sub-tasks, then \`spawn\` one worker per sub-task \u2014 in parallel \u2014 with explicit, scoped goals.
7036
7112
  3. Workers run autonomously. They wake you via SYSTEM events when done / failed / blocked.
7037
7113
  4. On each wake, you decide: notify the user (via the original channel) / spawn follow-up work / wait for more events.
7114
+ </typical_flow>
7038
7115
 
7039
- ### Decomposition rule
7116
+ <decomposition_rule>
7040
7117
 
7041
7118
  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:
7042
7119
 
@@ -7052,18 +7129,22 @@ When NOT to split (keep as one worker):
7052
7129
  - The asks share state (one's output feeds the other).
7053
7130
  - The asks are tightly coupled (e.g. *"refactor X and run its tests"* \u2014 the tests depend on the refactor).
7054
7131
  - The asks are trivially small (one or two tool calls each); spawning overhead exceeds the parallelism win.
7132
+ </decomposition_rule>
7055
7133
 
7056
- ### Prefer headless tools
7134
+ <prefer_headless_tools>
7057
7135
 
7058
7136
  When spawning a worker, push it toward the *cheapest tool that gets the job done*:
7059
7137
 
7060
7138
  1. **Bash / file tools** for anything with a CLI (git, npm, brew, builds, tests, file editing, HTTP via curl, scripting).
7061
- 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 ? `
7139
+ 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.
7140
+ </prefer_headless_tools>${desktopAvailable ? `
7141
+
7142
+ <desktop_automation_guidance>
7062
7143
  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.
7063
7144
 
7064
7145
  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."*
7065
7146
 
7066
- ### Serialize desktop-automation tasks
7147
+ <serialize_desktop_automation_tasks>
7067
7148
 
7068
7149
  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.
7069
7150
 
@@ -7086,11 +7167,13 @@ Example: *"Take a screenshot of Calculator AND run the test suite AND open Syste
7086
7167
 
7087
7168
  Headless workers never interfere with desktop workers (they don't touch the screen), so they always run in parallel.
7088
7169
 
7089
- 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.` : ""}
7170
+ 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.
7171
+ </serialize_desktop_automation_tasks>
7172
+ </desktop_automation_guidance>` : ""}
7090
7173
 
7091
7174
  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.
7092
7175
 
7093
- ### How to TALK to the user (versus how you reason internally)
7176
+ <user_communication>
7094
7177
 
7095
7178
  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.
7096
7179
 
@@ -7109,8 +7192,9 @@ When replying to the user (Slack, web, or any channel), be a normal helpful assi
7109
7192
  | *"I'll relay the user's instructions to the worker verbatim."* | *(say nothing \u2014 just do it)* |
7110
7193
 
7111
7194
  If the user explicitly asks how you work, *then* you can explain the orchestrator/worker split. Otherwise: less is more.
7195
+ </user_communication>
7112
7196
 
7113
- ### How to write a worker goal (and what NOT to put in it)
7197
+ <worker_goal_guidance>
7114
7198
 
7115
7199
  You delegate; the worker executes. Stay at the **what** level, not the **how**.
7116
7200
 
@@ -7151,6 +7235,8 @@ Bad goal (don't do this):
7151
7235
 
7152
7236
  Good goal (do this):
7153
7237
  > "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."
7238
+ </worker_goal_guidance>
7239
+ </orchestrator_mode>
7154
7240
  `;
7155
7241
  }
7156
7242
  function createSummaryPrompt(conversationHistory) {
@@ -9952,9 +10038,9 @@ ${buildOrchestratorPromptAddendum()}`;
9952
10038
  if (personality && personality.trim()) {
9953
10039
  systemPrompt = `${systemPrompt}
9954
10040
 
9955
- ## Your personality / persona
9956
-
9957
- ${personality.trim()}`;
10041
+ <personality>
10042
+ ${personality.trim()}
10043
+ </personality>`;
9958
10044
  }
9959
10045
  }
9960
10046
  const messages = await this.context.getMessages();
@@ -10933,13 +11019,20 @@ async function ensureOrchestratorSession(opts = {}) {
10933
11019
  try {
10934
11020
  const all = await sessionQueries.list(500, 0);
10935
11021
  const existing = all.find((s) => s.config?.role === "orchestrator");
10936
- if (existing) return existing.id;
11022
+ if (existing) {
11023
+ if (existing.config?.toolApprovals?.["*"] !== false) {
11024
+ await sessionQueries.update(existing.id, {
11025
+ config: autoApproveAllTools(existing.config ?? { role: "orchestrator" })
11026
+ });
11027
+ }
11028
+ return existing.id;
11029
+ }
10937
11030
  const cfg = getConfig();
10938
11031
  const created = await sessionQueries.create({
10939
11032
  name: "Orchestrator",
10940
11033
  workingDirectory: cfg.resolvedWorkingDirectory,
10941
11034
  model: cfg.defaultModel,
10942
- config: { role: "orchestrator" }
11035
+ config: autoApproveAllTools({ role: "orchestrator" })
10943
11036
  });
10944
11037
  if (!opts.quiet) {
10945
11038
  console.log(`[orchestrator] auto-created session ${created.id}`);
@@ -11204,11 +11297,14 @@ sessions2.post(
11204
11297
  const body = c.req.valid("json");
11205
11298
  const config = getConfig();
11206
11299
  const baseConfig = body.config || {};
11207
- const mergedConfig = {
11300
+ let mergedConfig = {
11208
11301
  ...baseConfig,
11209
11302
  ...body.toolApprovals ? { toolApprovals: body.toolApprovals } : {},
11210
11303
  ...body.role ? { role: body.role } : {}
11211
11304
  };
11305
+ if (mergedConfig.role === "orchestrator") {
11306
+ mergedConfig = autoApproveAllTools(mergedConfig);
11307
+ }
11212
11308
  const agent = await Agent.create({
11213
11309
  name: body.name,
11214
11310
  workingDirectory: body.workingDirectory || config.resolvedWorkingDirectory,
@@ -13936,10 +14032,11 @@ tasks.post(
13936
14032
  workingDirectory: body.workingDirectory || parentSession.workingDirectory,
13937
14033
  model: body.model || parentSession.model,
13938
14034
  sessionConfig: {
13939
- toolApprovals: { bash: false, write_file: false, read_file: false },
13940
- task: taskConfig,
13941
- role: "worker",
13942
- ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14035
+ ...autoApproveAllTools({
14036
+ task: taskConfig,
14037
+ role: "worker",
14038
+ ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14039
+ })
13943
14040
  }
13944
14041
  });
13945
14042
  const parentMessages = await messageQueries.getBySession(body.parentTaskId);
@@ -13954,10 +14051,11 @@ tasks.post(
13954
14051
  workingDirectory: body.workingDirectory || config.resolvedWorkingDirectory,
13955
14052
  model: body.model || config.defaultModel,
13956
14053
  sessionConfig: {
13957
- toolApprovals: { bash: false, write_file: false, read_file: false },
13958
- task: taskConfig,
13959
- role: "worker",
13960
- ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14054
+ ...autoApproveAllTools({
14055
+ task: taskConfig,
14056
+ role: "worker",
14057
+ ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14058
+ })
13961
14059
  }
13962
14060
  });
13963
14061
  }
@@ -14004,10 +14102,11 @@ tasks.post(
14004
14102
  error: errorMsg
14005
14103
  };
14006
14104
  await sessionQueries.update(taskId, {
14007
- config: {
14008
- toolApprovals: { bash: false, write_file: false, read_file: false },
14009
- task: failedTask
14010
- }
14105
+ config: autoApproveAllTools({
14106
+ task: failedTask,
14107
+ role: "worker",
14108
+ ...body.orchestratorSessionId ? { orchestratorSessionId: body.orchestratorSessionId } : {}
14109
+ })
14011
14110
  });
14012
14111
  if (taskConfig.webhookUrl) {
14013
14112
  const { sendWebhook: sendWebhook2 } = await Promise.resolve().then(() => (init_webhook2(), webhook_exports));
@@ -14301,13 +14400,13 @@ async function findOrCreateOrchestratorId() {
14301
14400
  const all = await sessionQueries.list(500, 0);
14302
14401
  const existing = all.find((s) => s.config?.role === "orchestrator");
14303
14402
  if (existing) return existing.id;
14304
- const { getConfig: getConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
14403
+ const { autoApproveAllTools: autoApproveAllTools2, getConfig: getConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
14305
14404
  const cfg = getConfig2();
14306
14405
  const created = await sessionQueries.create({
14307
14406
  name: getDefaultOrchestratorName() || "Orchestrator",
14308
14407
  workingDirectory: cfg.resolvedWorkingDirectory,
14309
14408
  model: cfg.defaultModel,
14310
- config: { role: "orchestrator" }
14409
+ config: autoApproveAllTools2({ role: "orchestrator" })
14311
14410
  });
14312
14411
  return created.id;
14313
14412
  } catch (err) {