@goondocks/myco 0.14.4 → 0.15.1

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 (173) hide show
  1. package/dist/{agent-run-GZ5UVLDV.js → agent-run-T433ENJS.js} +6 -6
  2. package/dist/{agent-tasks-KKQ2GBBB.js → agent-tasks-TAIU3V5I.js} +6 -6
  3. package/dist/{chunk-X34OFKYU.js → chunk-23FJUKCN.js} +2 -2
  4. package/dist/{chunk-LD6U3L6O.js → chunk-2QMDRZPJ.js} +21 -17
  5. package/dist/chunk-2QMDRZPJ.js.map +1 -0
  6. package/dist/{chunk-KNTJOMWY.js → chunk-3MEOYXOW.js} +2 -2
  7. package/dist/{chunk-PSYLKCWQ.js → chunk-4BQ5QE76.js} +24 -5
  8. package/dist/chunk-4BQ5QE76.js.map +1 -0
  9. package/dist/{chunk-UZ5Y6XMP.js → chunk-4O3QNM5I.js} +2 -2
  10. package/dist/{chunk-JTYZRPX5.js → chunk-5ZT2Q6P5.js} +1 -1
  11. package/dist/{chunk-BCKYVLUZ.js → chunk-6GG2IVNV.js} +3 -3
  12. package/dist/{chunk-JJXVDCEX.js → chunk-75J2BR4P.js} +486 -488
  13. package/dist/chunk-75J2BR4P.js.map +1 -0
  14. package/dist/{chunk-TFBAV3PV.js → chunk-BFM6AM6R.js} +2 -2
  15. package/dist/{chunk-S6I62FAH.js → chunk-CUADDHHU.js} +4 -2
  16. package/dist/{chunk-S6I62FAH.js.map → chunk-CUADDHHU.js.map} +1 -1
  17. package/dist/{chunk-4VF6KQ2Z.js → chunk-DJQOYEK3.js} +87 -84
  18. package/dist/chunk-DJQOYEK3.js.map +1 -0
  19. package/dist/{chunk-OQVKLTQY.js → chunk-EYMKBNRP.js} +2 -2
  20. package/dist/{chunk-STBNNKL5.js → chunk-GCCBXCHF.js} +6 -6
  21. package/dist/{chunk-KH64DHOY.js → chunk-GDY63YAW.js} +279 -277
  22. package/dist/chunk-GDY63YAW.js.map +1 -0
  23. package/dist/{chunk-ZESTWGJT.js → chunk-GYIA6XLB.js} +2 -2
  24. package/dist/{chunk-S66YG6QK.js → chunk-LF5Z62X6.js} +46 -7
  25. package/dist/chunk-LF5Z62X6.js.map +1 -0
  26. package/dist/{chunk-PX5KIOKY.js → chunk-SPJGJEFV.js} +10 -2
  27. package/dist/{chunk-PX5KIOKY.js.map → chunk-SPJGJEFV.js.map} +1 -1
  28. package/dist/{chunk-QFMBZ72S.js → chunk-SV6UCB2Z.js} +2 -2
  29. package/dist/{chunk-GMTWRMLP.js → chunk-TQO4PF5K.js} +3 -3
  30. package/dist/{chunk-NVCGF2DS.js → chunk-X4XFJG6I.js} +10 -6
  31. package/dist/chunk-X4XFJG6I.js.map +1 -0
  32. package/dist/{chunk-TNCBMGWB.js → chunk-X5IXK5KO.js} +262 -226
  33. package/dist/chunk-X5IXK5KO.js.map +1 -0
  34. package/dist/{chunk-TVV6PZOC.js → chunk-Z7TZJ2SP.js} +2 -2
  35. package/dist/{cli-JLDCZ77U.js → cli-W37MRZHD.js} +45 -44
  36. package/dist/cli-W37MRZHD.js.map +1 -0
  37. package/dist/{client-LRQMMKLP.js → client-YNTTC75R.js} +4 -4
  38. package/dist/{config-H657SF6B.js → config-MOWCOJJ4.js} +4 -4
  39. package/dist/{detect-27DN6UTL.js → detect-GFYKKHLJ.js} +3 -3
  40. package/dist/{detect-providers-PAVE2X6O.js → detect-providers-EU35RUL3.js} +2 -2
  41. package/dist/{doctor-IG3CXMI7.js → doctor-PAAQU5AS.js} +38 -19
  42. package/dist/doctor-PAAQU5AS.js.map +1 -0
  43. package/dist/{executor-HKNINUWO.js → executor-4OXDK4ZA.js} +790 -312
  44. package/dist/executor-4OXDK4ZA.js.map +1 -0
  45. package/dist/{init-RHQUINC2.js → init-PHQAQANR.js} +41 -23
  46. package/dist/init-PHQAQANR.js.map +1 -0
  47. package/dist/{init-wizard-ZB3JRDLE.js → init-wizard-RFD46XAJ.js} +7 -7
  48. package/dist/{installer-25TSX4SR.js → installer-BTUNKWOU.js} +2 -2
  49. package/dist/{llm-T3QVHC3Y.js → llm-D4VWYUK7.js} +4 -4
  50. package/dist/{loader-WQKVWL5D.js → loader-WC4U5NM5.js} +4 -4
  51. package/dist/{loader-JQLO6K44.js → loader-WGDVRGLM.js} +6 -4
  52. package/dist/{logs-LXHPDKUA.js → logs-WFBX2I7C.js} +3 -3
  53. package/dist/{main-MVXPBP5Z.js → main-ADLCOYKM.js} +2351 -1914
  54. package/dist/main-ADLCOYKM.js.map +1 -0
  55. package/dist/{open-CVEMRH3Z.js → open-3VPUP3HD.js} +6 -6
  56. package/dist/{openai-embeddings-5T5ZP7LO.js → openai-embeddings-SEIV7AM3.js} +2 -2
  57. package/dist/{openrouter-RD2COFC7.js → openrouter-ELODIZRP.js} +2 -2
  58. package/dist/{post-compact-ALQ2UGZ7.js → post-compact-5NYLOC46.js} +9 -9
  59. package/dist/{post-tool-use-SPL7HIYU.js → post-tool-use-SNNXSZ5Y.js} +10 -10
  60. package/dist/{post-tool-use-failure-B3CUYBTR.js → post-tool-use-failure-POKVXQHY.js} +9 -9
  61. package/dist/{pre-compact-KPWC4V64.js → pre-compact-ZUICBJEX.js} +9 -9
  62. package/dist/{provider-check-QN7OGXZA.js → provider-check-B66E5PWS.js} +2 -2
  63. package/dist/{registry-2XQMCPA6.js → registry-DHWVHXWY.js} +5 -5
  64. package/dist/{remove-O2WCN6RC.js → remove-SVU2V4Q7.js} +52 -20
  65. package/dist/remove-SVU2V4Q7.js.map +1 -0
  66. package/dist/{resolution-events-5EVUEWHS.js → resolution-events-DBCRVZGU.js} +4 -4
  67. package/dist/{restart-S52VV3SP.js → restart-NBB5CXJ4.js} +7 -7
  68. package/dist/{search-IOJ5O37S.js → search-YUQZFRZX.js} +6 -6
  69. package/dist/{server-T4VPK6FU.js → server-NBRX56VL.js} +8 -8
  70. package/dist/{session-ID6BX72K.js → session-2QP4HMZ5.js} +8 -8
  71. package/dist/{session-end-I7ZABXRI.js → session-end-NNFBW7CQ.js} +10 -10
  72. package/dist/{session-start-VPOUY42U.js → session-start-NPNP4IXX.js} +15 -15
  73. package/dist/{setup-llm-G5UG5N3T.js → setup-llm-C3IGFLRN.js} +8 -8
  74. package/dist/src/agent/definitions/tasks/full-intelligence.yaml +8 -7
  75. package/dist/src/agent/definitions/tasks/skill-evolve.yaml +71 -144
  76. package/dist/src/agent/definitions/tasks/skill-generate.yaml +10 -62
  77. package/dist/src/agent/definitions/tasks/skill-survey.yaml +87 -53
  78. package/dist/src/agent/prompts/agent.md +1 -0
  79. package/dist/src/cli.js +1 -1
  80. package/dist/src/daemon/main.js +1 -1
  81. package/dist/src/hooks/post-tool-use.js +1 -1
  82. package/dist/src/hooks/session-end.js +1 -1
  83. package/dist/src/hooks/session-start.js +1 -1
  84. package/dist/src/hooks/stop.js +1 -1
  85. package/dist/src/hooks/user-prompt-submit.js +1 -1
  86. package/dist/src/mcp/server.js +1 -1
  87. package/dist/src/worker/src/schema.ts +14 -0
  88. package/dist/{stats-GRI4MTS2.js → stats-FEEXIRMS.js} +9 -9
  89. package/dist/{stop-UTZ2CXI2.js → stop-FGDGWXTK.js} +10 -10
  90. package/dist/{stop-failure-CECM5NB7.js → stop-failure-5YAGH2TQ.js} +9 -9
  91. package/dist/{subagent-start-SYZGJYUN.js → subagent-start-UCKVJDR4.js} +9 -9
  92. package/dist/{subagent-stop-7WWW7TGQ.js → subagent-stop-H25B3QEC.js} +9 -9
  93. package/dist/{task-completed-N7SIY6T6.js → task-completed-2JGZN2CF.js} +9 -9
  94. package/dist/{team-SJPDXELY.js → team-TG5WZXWO.js} +34 -26
  95. package/dist/team-TG5WZXWO.js.map +1 -0
  96. package/dist/ui/assets/index-7Vimyg7g.js +837 -0
  97. package/dist/ui/assets/{index-BmsHIwjl.css → index-DlEQ8A8Y.css} +1 -1
  98. package/dist/ui/index.html +2 -2
  99. package/dist/{update-DZZYQ4NJ.js → update-EG3N2EXI.js} +30 -14
  100. package/dist/update-EG3N2EXI.js.map +1 -0
  101. package/dist/{user-prompt-submit-UUNRRS5P.js → user-prompt-submit-7FFQ3ORA.js} +10 -10
  102. package/dist/{verify-JHIMXTY5.js → verify-2M3DYHEY.js} +6 -6
  103. package/dist/{version-VKNCAPZW.js → version-JUQU5W22.js} +2 -2
  104. package/package.json +3 -3
  105. package/dist/chunk-4VF6KQ2Z.js.map +0 -1
  106. package/dist/chunk-JJXVDCEX.js.map +0 -1
  107. package/dist/chunk-KH64DHOY.js.map +0 -1
  108. package/dist/chunk-LD6U3L6O.js.map +0 -1
  109. package/dist/chunk-NVCGF2DS.js.map +0 -1
  110. package/dist/chunk-PSYLKCWQ.js.map +0 -1
  111. package/dist/chunk-S66YG6QK.js.map +0 -1
  112. package/dist/chunk-TNCBMGWB.js.map +0 -1
  113. package/dist/cli-JLDCZ77U.js.map +0 -1
  114. package/dist/doctor-IG3CXMI7.js.map +0 -1
  115. package/dist/executor-HKNINUWO.js.map +0 -1
  116. package/dist/init-RHQUINC2.js.map +0 -1
  117. package/dist/main-MVXPBP5Z.js.map +0 -1
  118. package/dist/remove-O2WCN6RC.js.map +0 -1
  119. package/dist/resolve-3FEUV462.js +0 -9
  120. package/dist/team-SJPDXELY.js.map +0 -1
  121. package/dist/ui/assets/index-Cn6cQwJy.js +0 -842
  122. package/dist/update-DZZYQ4NJ.js.map +0 -1
  123. package/dist/version-VKNCAPZW.js.map +0 -1
  124. /package/dist/{agent-run-GZ5UVLDV.js.map → agent-run-T433ENJS.js.map} +0 -0
  125. /package/dist/{agent-tasks-KKQ2GBBB.js.map → agent-tasks-TAIU3V5I.js.map} +0 -0
  126. /package/dist/{chunk-X34OFKYU.js.map → chunk-23FJUKCN.js.map} +0 -0
  127. /package/dist/{chunk-KNTJOMWY.js.map → chunk-3MEOYXOW.js.map} +0 -0
  128. /package/dist/{chunk-UZ5Y6XMP.js.map → chunk-4O3QNM5I.js.map} +0 -0
  129. /package/dist/{chunk-JTYZRPX5.js.map → chunk-5ZT2Q6P5.js.map} +0 -0
  130. /package/dist/{chunk-BCKYVLUZ.js.map → chunk-6GG2IVNV.js.map} +0 -0
  131. /package/dist/{chunk-TFBAV3PV.js.map → chunk-BFM6AM6R.js.map} +0 -0
  132. /package/dist/{chunk-OQVKLTQY.js.map → chunk-EYMKBNRP.js.map} +0 -0
  133. /package/dist/{chunk-STBNNKL5.js.map → chunk-GCCBXCHF.js.map} +0 -0
  134. /package/dist/{chunk-ZESTWGJT.js.map → chunk-GYIA6XLB.js.map} +0 -0
  135. /package/dist/{chunk-QFMBZ72S.js.map → chunk-SV6UCB2Z.js.map} +0 -0
  136. /package/dist/{chunk-GMTWRMLP.js.map → chunk-TQO4PF5K.js.map} +0 -0
  137. /package/dist/{chunk-TVV6PZOC.js.map → chunk-Z7TZJ2SP.js.map} +0 -0
  138. /package/dist/{client-LRQMMKLP.js.map → client-YNTTC75R.js.map} +0 -0
  139. /package/dist/{config-H657SF6B.js.map → config-MOWCOJJ4.js.map} +0 -0
  140. /package/dist/{detect-27DN6UTL.js.map → detect-GFYKKHLJ.js.map} +0 -0
  141. /package/dist/{detect-providers-PAVE2X6O.js.map → detect-providers-EU35RUL3.js.map} +0 -0
  142. /package/dist/{init-wizard-ZB3JRDLE.js.map → init-wizard-RFD46XAJ.js.map} +0 -0
  143. /package/dist/{installer-25TSX4SR.js.map → installer-BTUNKWOU.js.map} +0 -0
  144. /package/dist/{llm-T3QVHC3Y.js.map → llm-D4VWYUK7.js.map} +0 -0
  145. /package/dist/{loader-JQLO6K44.js.map → loader-WC4U5NM5.js.map} +0 -0
  146. /package/dist/{loader-WQKVWL5D.js.map → loader-WGDVRGLM.js.map} +0 -0
  147. /package/dist/{logs-LXHPDKUA.js.map → logs-WFBX2I7C.js.map} +0 -0
  148. /package/dist/{open-CVEMRH3Z.js.map → open-3VPUP3HD.js.map} +0 -0
  149. /package/dist/{openai-embeddings-5T5ZP7LO.js.map → openai-embeddings-SEIV7AM3.js.map} +0 -0
  150. /package/dist/{openrouter-RD2COFC7.js.map → openrouter-ELODIZRP.js.map} +0 -0
  151. /package/dist/{post-compact-ALQ2UGZ7.js.map → post-compact-5NYLOC46.js.map} +0 -0
  152. /package/dist/{post-tool-use-SPL7HIYU.js.map → post-tool-use-SNNXSZ5Y.js.map} +0 -0
  153. /package/dist/{post-tool-use-failure-B3CUYBTR.js.map → post-tool-use-failure-POKVXQHY.js.map} +0 -0
  154. /package/dist/{pre-compact-KPWC4V64.js.map → pre-compact-ZUICBJEX.js.map} +0 -0
  155. /package/dist/{provider-check-QN7OGXZA.js.map → provider-check-B66E5PWS.js.map} +0 -0
  156. /package/dist/{registry-2XQMCPA6.js.map → registry-DHWVHXWY.js.map} +0 -0
  157. /package/dist/{resolution-events-5EVUEWHS.js.map → resolution-events-DBCRVZGU.js.map} +0 -0
  158. /package/dist/{restart-S52VV3SP.js.map → restart-NBB5CXJ4.js.map} +0 -0
  159. /package/dist/{search-IOJ5O37S.js.map → search-YUQZFRZX.js.map} +0 -0
  160. /package/dist/{server-T4VPK6FU.js.map → server-NBRX56VL.js.map} +0 -0
  161. /package/dist/{session-ID6BX72K.js.map → session-2QP4HMZ5.js.map} +0 -0
  162. /package/dist/{session-end-I7ZABXRI.js.map → session-end-NNFBW7CQ.js.map} +0 -0
  163. /package/dist/{session-start-VPOUY42U.js.map → session-start-NPNP4IXX.js.map} +0 -0
  164. /package/dist/{setup-llm-G5UG5N3T.js.map → setup-llm-C3IGFLRN.js.map} +0 -0
  165. /package/dist/{stats-GRI4MTS2.js.map → stats-FEEXIRMS.js.map} +0 -0
  166. /package/dist/{stop-UTZ2CXI2.js.map → stop-FGDGWXTK.js.map} +0 -0
  167. /package/dist/{stop-failure-CECM5NB7.js.map → stop-failure-5YAGH2TQ.js.map} +0 -0
  168. /package/dist/{subagent-start-SYZGJYUN.js.map → subagent-start-UCKVJDR4.js.map} +0 -0
  169. /package/dist/{subagent-stop-7WWW7TGQ.js.map → subagent-stop-H25B3QEC.js.map} +0 -0
  170. /package/dist/{task-completed-N7SIY6T6.js.map → task-completed-2JGZN2CF.js.map} +0 -0
  171. /package/dist/{user-prompt-submit-UUNRRS5P.js.map → user-prompt-submit-7FFQ3ORA.js.map} +0 -0
  172. /package/dist/{verify-JHIMXTY5.js.map → verify-2M3DYHEY.js.map} +0 -0
  173. /package/dist/{resolve-3FEUV462.js.map → version-JUQU5W22.js.map} +0 -0
@@ -30,13 +30,13 @@ import {
30
30
  updateRunStatus,
31
31
  updateSkillRecord,
32
32
  upsertDigestExtract
33
- } from "./chunk-JJXVDCEX.js";
33
+ } from "./chunk-75J2BR4P.js";
34
34
  import {
35
35
  fullTextSearch
36
36
  } from "./chunk-DTE3SHYK.js";
37
37
  import {
38
38
  loadAllTasks
39
- } from "./chunk-KNTJOMWY.js";
39
+ } from "./chunk-3MEOYXOW.js";
40
40
  import {
41
41
  getAgent,
42
42
  getDefaultTask,
@@ -45,31 +45,31 @@ import {
45
45
  loadSystemPrompt,
46
46
  resolveDefinitionsDir,
47
47
  resolveEffectiveConfig
48
- } from "./chunk-NVCGF2DS.js";
48
+ } from "./chunk-X4XFJG6I.js";
49
49
  import {
50
50
  insertTurn
51
51
  } from "./chunk-QLCD77AN.js";
52
52
  import {
53
53
  insertResolutionEvent
54
- } from "./chunk-TVV6PZOC.js";
54
+ } from "./chunk-Z7TZJ2SP.js";
55
55
  import "./chunk-IB76KGBY.js";
56
56
  import {
57
57
  DEFAULT_IMPORTANCE,
58
58
  insertSpore,
59
59
  listSpores,
60
60
  updateSporeStatus
61
- } from "./chunk-PX5KIOKY.js";
61
+ } from "./chunk-SPJGJEFV.js";
62
62
  import {
63
63
  listSessions,
64
64
  updateSession
65
- } from "./chunk-X34OFKYU.js";
66
- import "./chunk-S66YG6QK.js";
65
+ } from "./chunk-23FJUKCN.js";
66
+ import "./chunk-LF5Z62X6.js";
67
67
  import {
68
68
  createSchema
69
- } from "./chunk-4VF6KQ2Z.js";
69
+ } from "./chunk-DJQOYEK3.js";
70
70
  import {
71
71
  loadConfig
72
- } from "./chunk-PSYLKCWQ.js";
72
+ } from "./chunk-4BQ5QE76.js";
73
73
  import {
74
74
  getDatabase,
75
75
  initDatabase,
@@ -77,7 +77,7 @@ import {
77
77
  } from "./chunk-MYX5NCRH.js";
78
78
  import {
79
79
  getPluginVersion
80
- } from "./chunk-TFBAV3PV.js";
80
+ } from "./chunk-BFM6AM6R.js";
81
81
  import {
82
82
  findPackageRoot
83
83
  } from "./chunk-LPUQPDC2.js";
@@ -90,23 +90,23 @@ import {
90
90
  TEAM_SOURCE_PREFIX,
91
91
  epochSeconds
92
92
  } from "./chunk-TRA3R4EC.js";
93
- import "./chunk-S6I62FAH.js";
93
+ import "./chunk-CUADDHHU.js";
94
94
  import "./chunk-D7TYRPRM.js";
95
95
  import "./chunk-E4VLWIJC.js";
96
96
  import {
97
97
  external_exports
98
- } from "./chunk-KH64DHOY.js";
98
+ } from "./chunk-GDY63YAW.js";
99
99
  import "./chunk-PZUWP5VK.js";
100
100
 
101
101
  // src/agent/executor.ts
102
- import crypto2 from "crypto";
102
+ import crypto4 from "crypto";
103
103
  import { resolve as resolve2 } from "path";
104
104
 
105
105
  // src/agent/tools.ts
106
- import crypto from "crypto";
107
- import { writeFileSync, mkdirSync, rmSync } from "fs";
108
- import { resolve } from "path";
109
- import { tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
106
+ import { createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
107
+
108
+ // src/agent/tools/read-tools.ts
109
+ import { tool } from "@anthropic-ai/claude-agent-sdk";
110
110
 
111
111
  // src/db/queries/agent-state.ts
112
112
  var STATE_COLUMNS = [
@@ -148,77 +148,20 @@ function getStatesForAgent(agentId) {
148
148
  return rows.map(toAgentStateRow);
149
149
  }
150
150
 
151
- // src/agent/tools.ts
151
+ // src/agent/tools/types.ts
152
+ function textResult(data) {
153
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
154
+ }
155
+
156
+ // src/agent/tools/read-tools.ts
152
157
  var DEFAULT_UNPROCESSED_LIMIT = 50;
153
158
  var DEFAULT_SPORES_LIMIT = 50;
154
159
  var DEFAULT_SESSIONS_LIMIT = 20;
155
160
  var DEFAULT_SEARCH_LIMIT = 10;
156
161
  var DEFAULT_ENTITIES_LIMIT = 50;
157
162
  var DEFAULT_EDGES_LIMIT = 50;
158
- function textResult(data) {
159
- return { content: [{ type: "text", text: JSON.stringify(data) }] };
160
- }
161
- var MAX_SKILL_LINES = 500;
162
- var REQUIRED_FRONTMATTER_FIELDS = ["name", "description", "managed_by", "user-invocable", "allowed-tools"];
163
- function validateSkillContent(content, dirName) {
164
- const issues = [];
165
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
166
- if (!fmMatch) {
167
- issues.push("Missing YAML frontmatter (must start with --- and end with ---)");
168
- return issues;
169
- }
170
- const frontmatter = fmMatch[1];
171
- for (const field of REQUIRED_FRONTMATTER_FIELDS) {
172
- if (!frontmatter.includes(`${field}:`)) {
173
- issues.push(`Missing required frontmatter field: ${field}`);
174
- }
175
- }
176
- const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
177
- if (nameMatch && !nameMatch[1].trim().startsWith("myco:")) {
178
- issues.push(`Skill name must start with "myco:" prefix. Got: "${nameMatch[1].trim()}"`);
179
- }
180
- const managedMatch = frontmatter.match(/^managed_by:\s*(.+)$/m);
181
- if (managedMatch && managedMatch[1].trim() !== "myco") {
182
- issues.push(`managed_by must be "myco". Got: "${managedMatch[1].trim()}"`);
183
- }
184
- const allowedToolsMatch = frontmatter.match(/^allowed-tools:\s*(.+)$/m);
185
- if (allowedToolsMatch) {
186
- const toolsValue = allowedToolsMatch[1].trim();
187
- if (toolsValue.includes("vault_")) {
188
- issues.push(
189
- "allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions \u2014 use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
190
- );
191
- }
192
- }
193
- const listToolLines = frontmatter.match(/^\s+-\s+vault_\w+/gm);
194
- if (listToolLines) {
195
- issues.push(
196
- "allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions \u2014 use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
197
- );
198
- }
199
- const lineCount = content.split("\n").length;
200
- if (lineCount > MAX_SKILL_LINES) {
201
- issues.push(`Skill is ${lineCount} lines (max ${MAX_SKILL_LINES})`);
202
- }
203
- return issues;
204
- }
205
- function createVaultTools(agentId, runId, options) {
206
- const { turnOffset = 0, embeddingManager, teamClient, machineId, projectRoot, vaultDir } = options ?? {};
207
- let turnCounter = turnOffset;
208
- function recordTurn(toolName, toolInput) {
209
- turnCounter++;
210
- try {
211
- insertTurn({
212
- run_id: runId,
213
- agent_id: agentId,
214
- turn_number: turnCounter,
215
- tool_name: toolName,
216
- tool_input: JSON.stringify(toolInput),
217
- started_at: epochSeconds()
218
- });
219
- } catch {
220
- }
221
- }
163
+ function createReadTools(deps) {
164
+ const { agentId, embeddingManager, teamClient, machineId, recordTurn } = deps;
222
165
  const vaultUnprocessed = tool(
223
166
  "vault_unprocessed",
224
167
  "Get unprocessed prompt batches, ordered by id ASC. Supports cursor-based pagination.",
@@ -337,7 +280,7 @@ function createVaultTools(agentId, runId, options) {
337
280
  return textResult({ results: [], message: "Semantic search unavailable" });
338
281
  }
339
282
  },
340
- { annotations: { readOnlyHint: true } }
283
+ { annotations: { readOnlyHint: true, openWorldHint: true } }
341
284
  );
342
285
  const vaultState = tool(
343
286
  "vault_state",
@@ -392,7 +335,24 @@ function createVaultTools(agentId, runId, options) {
392
335
  },
393
336
  { annotations: { readOnlyHint: true } }
394
337
  );
395
- const vaultCreateSpore = tool(
338
+ return [
339
+ vaultUnprocessed,
340
+ vaultSpores,
341
+ vaultSessions,
342
+ vaultSearchFts,
343
+ vaultSearchSemantic,
344
+ vaultState,
345
+ vaultEntities,
346
+ vaultEdges
347
+ ];
348
+ }
349
+
350
+ // src/agent/tools/write-tools.ts
351
+ import crypto from "crypto";
352
+ import { tool as tool2 } from "@anthropic-ai/claude-agent-sdk";
353
+ function createWriteTools(deps) {
354
+ const { agentId, embeddingManager, machineId, recordTurn } = deps;
355
+ const vaultCreateSpore = tool2(
396
356
  "vault_create_spore",
397
357
  "Create a new spore (observation) in the vault. The agent_id is set automatically.",
398
358
  {
@@ -436,9 +396,10 @@ function createVaultTools(agentId, runId, options) {
436
396
  });
437
397
  recordTurn("vault_create_spore", args);
438
398
  return textResult(spore);
439
- }
399
+ },
400
+ { annotations: { openWorldHint: true } }
440
401
  );
441
- const vaultCreateEntity = tool(
402
+ const vaultCreateEntity = tool2(
442
403
  "vault_create_entity",
443
404
  "Create or update an entity in the knowledge graph. Uses UPSERT on (agent_id, type, name).",
444
405
  {
@@ -462,9 +423,10 @@ function createVaultTools(agentId, runId, options) {
462
423
  });
463
424
  recordTurn("vault_create_entity", args);
464
425
  return textResult(entity);
465
- }
426
+ },
427
+ { annotations: { idempotentHint: true } }
466
428
  );
467
- const vaultCreateEdge = tool(
429
+ const vaultCreateEdge = tool2(
468
430
  "vault_create_edge",
469
431
  "Create a semantic edge in the knowledge graph. Lineage edges (FROM_SESSION, EXTRACTED_FROM, HAS_BATCH, DERIVED_FROM) are created automatically \u2014 do NOT create those.",
470
432
  {
@@ -495,9 +457,10 @@ function createVaultTools(agentId, runId, options) {
495
457
  });
496
458
  recordTurn("vault_create_edge", args);
497
459
  return textResult(edge);
498
- }
460
+ },
461
+ { annotations: { idempotentHint: true } }
499
462
  );
500
- const vaultResolveSpore = tool(
463
+ const vaultResolveSpore = tool2(
501
464
  "vault_resolve_spore",
502
465
  "Resolve a spore by updating its status and recording a resolution event.",
503
466
  {
@@ -538,9 +501,10 @@ function createVaultTools(agentId, runId, options) {
538
501
  }
539
502
  recordTurn("vault_resolve_spore", args);
540
503
  return textResult({ spore: updatedSpore, resolution_event_id: eventId });
541
- }
504
+ },
505
+ { annotations: { destructiveHint: true } }
542
506
  );
543
- const vaultUpdateSession = tool(
507
+ const vaultUpdateSession = tool2(
544
508
  "vault_update_session",
545
509
  "Update a session title and/or summary. When generating for the first time, provide BOTH title and summary. Title should be under 80 characters and reflect the full session scope.",
546
510
  {
@@ -559,9 +523,10 @@ function createVaultTools(agentId, runId, options) {
559
523
  }
560
524
  recordTurn("vault_update_session", args);
561
525
  return textResult(session);
562
- }
526
+ },
527
+ { annotations: { idempotentHint: true } }
563
528
  );
564
- const vaultSetState = tool(
529
+ const vaultSetState = tool2(
565
530
  "vault_set_state",
566
531
  "Set a key-value state pair for the current agent. Used for bookmarks, cursors, and preferences.",
567
532
  {
@@ -573,9 +538,10 @@ function createVaultTools(agentId, runId, options) {
573
538
  const state = setState(agentId, args.key, args.value, now);
574
539
  recordTurn("vault_set_state", args);
575
540
  return textResult(state);
576
- }
541
+ },
542
+ { annotations: { idempotentHint: true } }
577
543
  );
578
- const vaultReadDigest = tool(
544
+ const vaultReadDigest = tool2(
579
545
  "vault_read_digest",
580
546
  "Read current digest extracts. Without a tier parameter, returns a summary of all tiers (content length, generation time). With a tier parameter, returns the full content for that specific tier.",
581
547
  {
@@ -597,7 +563,7 @@ function createVaultTools(agentId, runId, options) {
597
563
  },
598
564
  { annotations: { readOnlyHint: true } }
599
565
  );
600
- const vaultWriteDigest = tool(
566
+ const vaultWriteDigest = tool2(
601
567
  "vault_write_digest",
602
568
  "Write or update a digest extract at a specific token tier. Uses UPSERT on (agent_id, tier).",
603
569
  {
@@ -614,9 +580,10 @@ function createVaultTools(agentId, runId, options) {
614
580
  });
615
581
  recordTurn("vault_write_digest", args);
616
582
  return textResult(extract);
617
- }
583
+ },
584
+ { annotations: { idempotentHint: true } }
618
585
  );
619
- const vaultMarkProcessed = tool(
586
+ const vaultMarkProcessed = tool2(
620
587
  "vault_mark_processed",
621
588
  "Mark a prompt batch as processed so it is not returned by vault_unprocessed.",
622
589
  {
@@ -626,9 +593,27 @@ function createVaultTools(agentId, runId, options) {
626
593
  const batch = markBatchProcessed(args.batch_id);
627
594
  recordTurn("vault_mark_processed", args);
628
595
  return textResult(batch);
629
- }
596
+ },
597
+ { annotations: { destructiveHint: true } }
630
598
  );
631
- const vaultReport = tool(
599
+ return [
600
+ vaultCreateSpore,
601
+ vaultCreateEntity,
602
+ vaultCreateEdge,
603
+ vaultResolveSpore,
604
+ vaultUpdateSession,
605
+ vaultSetState,
606
+ vaultReadDigest,
607
+ vaultWriteDigest,
608
+ vaultMarkProcessed
609
+ ];
610
+ }
611
+
612
+ // src/agent/tools/observability-tools.ts
613
+ import { tool as tool3 } from "@anthropic-ai/claude-agent-sdk";
614
+ function createObservabilityTools(deps) {
615
+ const { runId, agentId, recordTurn } = deps;
616
+ const vaultReport = tool3(
632
617
  "vault_report",
633
618
  'Record an observability report for the current run. Use action "skip" when skipping expected operations (e.g., not updating a session summary) with reasoning in the summary field.',
634
619
  {
@@ -648,9 +633,210 @@ function createVaultTools(agentId, runId, options) {
648
633
  created_at: now
649
634
  });
650
635
  return textResult(report);
651
- }
636
+ },
637
+ { annotations: {} }
638
+ );
639
+ return [vaultReport];
640
+ }
641
+
642
+ // src/agent/tools/skill-tools.ts
643
+ import crypto2 from "crypto";
644
+ import { readFileSync, writeFileSync, mkdirSync, rmSync, existsSync } from "fs";
645
+ import { resolve } from "path";
646
+ import { tool as tool4 } from "@anthropic-ai/claude-agent-sdk";
647
+
648
+ // src/agent/tools/skill-validator.ts
649
+ var MAX_SKILL_LINES = 500;
650
+ var REQUIRED_FRONTMATTER_FIELDS = ["name", "description", "managed_by", "user-invocable", "allowed-tools"];
651
+ var PROTECTED_FRONTMATTER_FIELDS = ["user-invocable", "allowed-tools"];
652
+ var ALLOWED_CLAUDE_CODE_TOOLS = /* @__PURE__ */ new Set([
653
+ "Read",
654
+ "Edit",
655
+ "Write",
656
+ "MultiEdit",
657
+ "Bash",
658
+ "Grep",
659
+ "Glob",
660
+ "NotebookRead",
661
+ "NotebookEdit",
662
+ "WebFetch",
663
+ "WebSearch",
664
+ "Task",
665
+ "TodoWrite"
666
+ ]);
667
+ function extractFrontmatterField(content, field) {
668
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
669
+ if (!fmMatch) return void 0;
670
+ const match = fmMatch[1].match(new RegExp(`^${field}:\\s*(.+)$`, "m"));
671
+ return match?.[1].trim();
672
+ }
673
+ function parseAllowedTools(rawValue) {
674
+ if (!rawValue) return null;
675
+ let stripped = rawValue.trim();
676
+ if (stripped.length === 0) return null;
677
+ if (stripped.startsWith("[") && stripped.endsWith("]")) {
678
+ stripped = stripped.slice(1, -1).trim();
679
+ }
680
+ if (stripped.length === 0) return null;
681
+ const parts = stripped.split(",").map((s) => s.trim().replace(/^['"]|['"]$/g, "")).filter((s) => s.length > 0);
682
+ if (parts.length === 0) return null;
683
+ const sentinels = /* @__PURE__ */ new Set(["None", "none", "null", "Null", "~"]);
684
+ if (parts.some((p) => sentinels.has(p))) return null;
685
+ return parts;
686
+ }
687
+ function tokenSet(text) {
688
+ const stopwords = /* @__PURE__ */ new Set([
689
+ "the",
690
+ "a",
691
+ "an",
692
+ "and",
693
+ "or",
694
+ "but",
695
+ "is",
696
+ "are",
697
+ "was",
698
+ "were",
699
+ "be",
700
+ "been",
701
+ "being",
702
+ "have",
703
+ "has",
704
+ "had",
705
+ "do",
706
+ "does",
707
+ "did",
708
+ "will",
709
+ "would",
710
+ "should",
711
+ "could",
712
+ "may",
713
+ "might",
714
+ "must",
715
+ "can",
716
+ "this",
717
+ "that",
718
+ "these",
719
+ "those",
720
+ "with",
721
+ "from",
722
+ "into",
723
+ "onto",
724
+ "for",
725
+ "when",
726
+ "where",
727
+ "which",
728
+ "what",
729
+ "who",
730
+ "how",
731
+ "why",
732
+ "use",
733
+ "uses",
734
+ "used",
735
+ "using",
736
+ "not",
737
+ "also",
738
+ "than",
739
+ "then",
740
+ "ensure",
741
+ "ensures",
742
+ "make",
743
+ "makes"
744
+ ]);
745
+ return new Set(
746
+ text.toLowerCase().replace(/[^a-z0-9_\s]/g, " ").split(/\s+/).filter((w) => w.length >= 4 && !stopwords.has(w))
652
747
  );
653
- const vaultSkillCandidates = tool(
748
+ }
749
+ function descriptionSimilarity(a, b) {
750
+ const aTokens = tokenSet(a);
751
+ const bTokens = tokenSet(b);
752
+ if (aTokens.size === 0 || bTokens.size === 0) return 0;
753
+ let intersection = 0;
754
+ for (const token of aTokens) {
755
+ if (bTokens.has(token)) intersection++;
756
+ }
757
+ const union = aTokens.size + bTokens.size - intersection;
758
+ return union === 0 ? 0 : intersection / union;
759
+ }
760
+ var DESCRIPTION_DUPLICATE_THRESHOLD = 0.4;
761
+ function checkFrontmatterPreservation(existing, incoming) {
762
+ const violations = [];
763
+ for (const field of PROTECTED_FRONTMATTER_FIELDS) {
764
+ const oldValue = extractFrontmatterField(existing, field);
765
+ const newValue = extractFrontmatterField(incoming, field);
766
+ if (oldValue !== void 0 && newValue !== void 0 && oldValue !== newValue) {
767
+ violations.push(`${field}: was "${oldValue}", changed to "${newValue}"`);
768
+ }
769
+ }
770
+ const oldDesc = extractFrontmatterField(existing, "description");
771
+ const newDesc = extractFrontmatterField(incoming, "description");
772
+ if (oldDesc && newDesc && newDesc.length < oldDesc.length * 0.9) {
773
+ violations.push(
774
+ `description shortened from ${oldDesc.length} to ${newDesc.length} chars (${Math.round((1 - newDesc.length / oldDesc.length) * 100)}% reduction). Descriptions are the primary triggering mechanism \u2014 do not shorten them.`
775
+ );
776
+ }
777
+ return violations;
778
+ }
779
+ function validateSkillContent(content, dirName) {
780
+ const issues = [];
781
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
782
+ if (!fmMatch) {
783
+ issues.push("Missing YAML frontmatter (must start with --- and end with ---)");
784
+ return issues;
785
+ }
786
+ const frontmatter = fmMatch[1];
787
+ for (const field of REQUIRED_FRONTMATTER_FIELDS) {
788
+ if (!frontmatter.includes(`${field}:`)) {
789
+ issues.push(`Missing required frontmatter field: ${field}`);
790
+ }
791
+ }
792
+ const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
793
+ if (nameMatch && !nameMatch[1].trim().startsWith("myco:")) {
794
+ issues.push(`Skill name must start with "myco:" prefix. Got: "${nameMatch[1].trim()}"`);
795
+ }
796
+ const managedMatch = frontmatter.match(/^managed_by:\s*(.+)$/m);
797
+ if (managedMatch && managedMatch[1].trim() !== "myco") {
798
+ issues.push(`managed_by must be "myco". Got: "${managedMatch[1].trim()}"`);
799
+ }
800
+ const allowedToolsMatch = frontmatter.match(/^allowed-tools:\s*(.+)$/m);
801
+ if (allowedToolsMatch) {
802
+ const rawValue = allowedToolsMatch[1].trim();
803
+ if (rawValue.includes("vault_")) {
804
+ issues.push(
805
+ "allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions -- use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
806
+ );
807
+ } else {
808
+ const parsed = parseAllowedTools(rawValue);
809
+ if (parsed === null) {
810
+ issues.push(
811
+ `allowed-tools value is malformed or empty: "${rawValue}". Provide a comma-separated list of Claude Code tools, e.g. "Read, Edit, Write, Bash, Grep, Glob". Use the narrowest set the skill actually needs.`
812
+ );
813
+ } else {
814
+ const unknown = parsed.filter((t) => !ALLOWED_CLAUDE_CODE_TOOLS.has(t));
815
+ if (unknown.length > 0) {
816
+ issues.push(
817
+ `allowed-tools contains unknown tool name(s): ${unknown.join(", ")}. Valid Claude Code tools: ${[...ALLOWED_CLAUDE_CODE_TOOLS].join(", ")}.`
818
+ );
819
+ }
820
+ }
821
+ }
822
+ }
823
+ const listToolLines = frontmatter.match(/^\s+-\s+vault_\w+/gm);
824
+ if (listToolLines) {
825
+ issues.push(
826
+ "allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions -- use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
827
+ );
828
+ }
829
+ const lineCount = content.split("\n").length;
830
+ if (lineCount > MAX_SKILL_LINES) {
831
+ issues.push(`Skill is ${lineCount} lines (max ${MAX_SKILL_LINES})`);
832
+ }
833
+ return issues;
834
+ }
835
+
836
+ // src/agent/tools/skill-tools.ts
837
+ function createSkillTools(deps) {
838
+ const { agentId, machineId, projectRoot, vaultDir, recordTurn } = deps;
839
+ const vaultSkillCandidates = tool4(
654
840
  "vault_skill_candidates",
655
841
  "Manage skill candidates (identified topics that may become skills). Supports list, get, create, and update actions.",
656
842
  {
@@ -685,9 +871,22 @@ function createVaultTools(agentId, runId, options) {
685
871
  if (!args.topic || !args.rationale) {
686
872
  return textResult({ error: "topic and rationale are required for create action" });
687
873
  }
874
+ const activeSkills = listSkillRecords({ agent_id: agentId, status: "active", limit: 100 });
875
+ const topicLower = args.topic.toLowerCase();
876
+ const overlapping = activeSkills.filter((s) => {
877
+ const nameWords = s.name.split("-").filter((w) => w.length > 2);
878
+ if (nameWords.length < 2) return false;
879
+ return nameWords.every((w) => topicLower.includes(w));
880
+ });
881
+ if (overlapping.length > 0) {
882
+ return textResult({
883
+ error: "Candidate rejected: active skill(s) already cover this topic. Update the existing skill via vault_skill_records instead.",
884
+ overlapping_skills: overlapping.map((s) => ({ name: s.name, display_name: s.display_name, description: s.description }))
885
+ });
886
+ }
688
887
  const now = epochSeconds();
689
888
  const candidate = insertCandidate({
690
- id: crypto.randomUUID(),
889
+ id: crypto2.randomUUID(),
691
890
  agent_id: agentId,
692
891
  machine_id: machineId,
693
892
  topic: args.topic,
@@ -732,9 +931,10 @@ function createVaultTools(agentId, runId, options) {
732
931
  default:
733
932
  return textResult({ error: `Unknown action: ${args.action}` });
734
933
  }
735
- }
934
+ },
935
+ { annotations: {} }
736
936
  );
737
- const vaultSkillRecords = tool(
937
+ const vaultSkillRecords = tool4(
738
938
  "vault_skill_records",
739
939
  "Read, update, and delete skill records (materialized skills on disk). Supports list, get, update, and delete actions.",
740
940
  {
@@ -791,7 +991,7 @@ function createVaultTools(agentId, runId, options) {
791
991
  console.warn("[vault_skill_records] Failed to remove skill directory:", err instanceof Error ? err.message : err);
792
992
  }
793
993
  try {
794
- const { syncSkillSymlinks } = await import("./installer-25TSX4SR.js");
994
+ const { syncSkillSymlinks } = await import("./installer-BTUNKWOU.js");
795
995
  syncSkillSymlinks(root, result.name, { remove: true });
796
996
  } catch (err) {
797
997
  console.warn("[vault_skill_records] Failed to remove symlinks:", err instanceof Error ? err.message : err);
@@ -802,9 +1002,10 @@ function createVaultTools(agentId, runId, options) {
802
1002
  default:
803
1003
  return textResult({ error: `Unknown action: ${args.action}` });
804
1004
  }
805
- }
1005
+ },
1006
+ { annotations: {} }
806
1007
  );
807
- const vaultWriteSkill = tool(
1008
+ const vaultWriteSkill = tool4(
808
1009
  "vault_write_skill",
809
1010
  "Write a SKILL.md file to disk and create or update the corresponding skill record and lineage entry.",
810
1011
  {
@@ -831,9 +1032,71 @@ function createVaultTools(agentId, runId, options) {
831
1032
  error: 'Invalid skill name: must be a simple directory name without path separators or ".."'
832
1033
  });
833
1034
  }
1035
+ const existingSameName = getSkillRecordByName(args.name);
1036
+ if (!existingSameName) {
1037
+ if (args.candidate_id) {
1038
+ const candidate = getCandidate(args.candidate_id);
1039
+ if (candidate?.skill_id) {
1040
+ const linkedSkill = getSkillRecord(candidate.skill_id);
1041
+ if (linkedSkill && linkedSkill.name !== args.name) {
1042
+ recordTurn("vault_write_skill", args);
1043
+ return textResult({
1044
+ error: `Candidate ${args.candidate_id} is already fulfilled by skill "${linkedSkill.name}". Do not create a sibling skill. If the existing skill needs changes, write to the same name to evolve it (this bumps its generation), or mark it stale via vault_skill_records before replacing.`,
1045
+ existing_skill: {
1046
+ id: linkedSkill.id,
1047
+ name: linkedSkill.name,
1048
+ description: linkedSkill.description,
1049
+ path: linkedSkill.path
1050
+ }
1051
+ });
1052
+ }
1053
+ }
1054
+ }
1055
+ const activeSkills = listSkillRecords({ agent_id: agentId, status: "active", limit: 200 });
1056
+ let bestMatch = null;
1057
+ for (const skill of activeSkills) {
1058
+ const score = descriptionSimilarity(args.description, skill.description);
1059
+ if (score >= DESCRIPTION_DUPLICATE_THRESHOLD && (!bestMatch || score > bestMatch.score)) {
1060
+ bestMatch = { skill, score };
1061
+ }
1062
+ }
1063
+ if (bestMatch) {
1064
+ recordTurn("vault_write_skill", args);
1065
+ return textResult({
1066
+ error: `Description overlaps with existing active skill "${bestMatch.skill.name}" (Jaccard ${bestMatch.score.toFixed(2)}, threshold ${DESCRIPTION_DUPLICATE_THRESHOLD}). Do not create a duplicate. Either evolve the existing skill by writing to its name ("${bestMatch.skill.name}"), or reframe this skill so its description describes a distinct procedure.`,
1067
+ overlapping_skill: {
1068
+ id: bestMatch.skill.id,
1069
+ name: bestMatch.skill.name,
1070
+ description: bestMatch.skill.description,
1071
+ path: bestMatch.skill.path
1072
+ },
1073
+ similarity: bestMatch.score
1074
+ });
1075
+ }
1076
+ }
834
1077
  const root = projectRoot ?? process.cwd();
835
1078
  const skillDir = resolve(root, ".agents", "skills", args.name);
836
1079
  const skillPath = resolve(skillDir, "SKILL.md");
1080
+ if (existsSync(skillPath)) {
1081
+ const existingContent = readFileSync(skillPath, "utf-8");
1082
+ const violations = checkFrontmatterPreservation(existingContent, args.content);
1083
+ if (violations.length > 0) {
1084
+ recordTurn("vault_write_skill", args);
1085
+ return textResult({
1086
+ error: "Skill update rejected: protected frontmatter fields were changed. Read the existing skill and preserve these values exactly.",
1087
+ violations
1088
+ });
1089
+ }
1090
+ }
1091
+ const skillDirPreexisted = existsSync(skillDir);
1092
+ let priorSkillContent = null;
1093
+ if (existsSync(skillPath)) {
1094
+ try {
1095
+ priorSkillContent = readFileSync(skillPath, "utf-8");
1096
+ } catch {
1097
+ priorSkillContent = null;
1098
+ }
1099
+ }
837
1100
  try {
838
1101
  mkdirSync(skillDir, { recursive: true });
839
1102
  writeFileSync(skillPath, args.content, "utf-8");
@@ -841,7 +1104,7 @@ function createVaultTools(agentId, runId, options) {
841
1104
  return textResult({ error: `Failed to write skill file: ${err instanceof Error ? err.message : String(err)}` });
842
1105
  }
843
1106
  try {
844
- const { syncSkillSymlinks } = await import("./installer-25TSX4SR.js");
1107
+ const { syncSkillSymlinks } = await import("./installer-BTUNKWOU.js");
845
1108
  syncSkillSymlinks(root, args.name);
846
1109
  } catch (err) {
847
1110
  console.warn("[vault_write_skill] syncSkillSymlinks failed:", err instanceof Error ? err.message : err);
@@ -852,77 +1115,98 @@ function createVaultTools(agentId, runId, options) {
852
1115
  let recordId = "";
853
1116
  let generation = 0;
854
1117
  const txDb = getDatabase();
855
- txDb.transaction(() => {
856
- if (existing) {
857
- generation = existing.generation + 1;
858
- recordId = existing.id;
859
- updateSkillRecord(existing.id, {
860
- display_name: args.display_name,
861
- description: args.description,
862
- generation,
863
- ...args.source_ids !== void 0 ? { source_ids: args.source_ids } : {},
864
- path: relativePath,
865
- updated_at: now
866
- });
867
- insertLineage({
868
- id: crypto.randomUUID(),
869
- skill_id: existing.id,
870
- generation,
871
- action: "updated",
872
- rationale: args.rationale ?? "Skill content updated",
873
- source_ids_added: args.source_ids,
874
- content_snapshot: args.content,
875
- created_at: now
876
- });
877
- } else {
878
- recordId = crypto.randomUUID();
879
- generation = 1;
880
- insertSkillRecord({
881
- id: recordId,
882
- agent_id: agentId,
883
- machine_id: machineId,
884
- name: args.name,
885
- display_name: args.display_name,
886
- description: args.description,
887
- candidate_id: args.candidate_id ?? null,
888
- source_ids: args.source_ids,
889
- path: relativePath,
890
- created_at: now,
891
- updated_at: now
892
- });
893
- insertLineage({
894
- id: crypto.randomUUID(),
895
- skill_id: recordId,
896
- generation,
897
- action: "created",
898
- rationale: args.rationale ?? "Initial skill creation",
899
- source_ids_added: args.source_ids,
900
- content_snapshot: args.content,
901
- created_at: now
902
- });
903
- const approvedCandidates = listCandidates({ status: "approved", limit: 10 });
904
- let linkedCandidate = false;
905
- if (args.candidate_id && !linkedCandidate) {
906
- const exact = updateCandidate(args.candidate_id, {
907
- status: "generated",
908
- skill_id: recordId,
1118
+ try {
1119
+ txDb.transaction(() => {
1120
+ if (existing) {
1121
+ generation = existing.generation + 1;
1122
+ recordId = existing.id;
1123
+ updateSkillRecord(existing.id, {
1124
+ display_name: args.display_name,
1125
+ description: args.description,
1126
+ generation,
1127
+ ...args.source_ids !== void 0 ? { source_ids: args.source_ids } : {},
1128
+ path: relativePath,
909
1129
  updated_at: now
910
1130
  });
911
- if (exact) linkedCandidate = true;
912
- }
913
- if (args.candidate_id && !linkedCandidate) {
914
- const prefixMatch = approvedCandidates.find((c) => c.id.startsWith(args.candidate_id));
915
- if (prefixMatch) {
916
- updateCandidate(prefixMatch.id, {
1131
+ insertLineage({
1132
+ id: crypto2.randomUUID(),
1133
+ skill_id: existing.id,
1134
+ generation,
1135
+ action: "updated",
1136
+ rationale: args.rationale ?? "Skill content updated",
1137
+ source_ids_added: args.source_ids,
1138
+ content_snapshot: args.content,
1139
+ created_at: now
1140
+ });
1141
+ } else {
1142
+ recordId = crypto2.randomUUID();
1143
+ generation = 1;
1144
+ insertSkillRecord({
1145
+ id: recordId,
1146
+ agent_id: agentId,
1147
+ machine_id: machineId,
1148
+ name: args.name,
1149
+ display_name: args.display_name,
1150
+ description: args.description,
1151
+ candidate_id: args.candidate_id ?? null,
1152
+ source_ids: args.source_ids,
1153
+ path: relativePath,
1154
+ created_at: now,
1155
+ updated_at: now
1156
+ });
1157
+ insertLineage({
1158
+ id: crypto2.randomUUID(),
1159
+ skill_id: recordId,
1160
+ generation,
1161
+ action: "created",
1162
+ rationale: args.rationale ?? "Initial skill creation",
1163
+ source_ids_added: args.source_ids,
1164
+ content_snapshot: args.content,
1165
+ created_at: now
1166
+ });
1167
+ const approvedCandidates = listCandidates({ status: "approved", limit: 10 });
1168
+ let linkedCandidate = false;
1169
+ if (args.candidate_id && !linkedCandidate) {
1170
+ const exact = updateCandidate(args.candidate_id, {
917
1171
  status: "generated",
918
1172
  skill_id: recordId,
919
1173
  updated_at: now
920
1174
  });
921
- linkedCandidate = true;
1175
+ if (exact) linkedCandidate = true;
922
1176
  }
1177
+ if (args.candidate_id && !linkedCandidate) {
1178
+ const prefixMatch = approvedCandidates.find((c) => c.id.startsWith(args.candidate_id));
1179
+ if (prefixMatch) {
1180
+ updateCandidate(prefixMatch.id, {
1181
+ status: "generated",
1182
+ skill_id: recordId,
1183
+ updated_at: now
1184
+ });
1185
+ linkedCandidate = true;
1186
+ }
1187
+ }
1188
+ }
1189
+ })();
1190
+ } catch (err) {
1191
+ try {
1192
+ if (priorSkillContent !== null) {
1193
+ writeFileSync(skillPath, priorSkillContent, "utf-8");
1194
+ } else if (!skillDirPreexisted) {
1195
+ rmSync(skillDir, { recursive: true, force: true });
1196
+ } else {
1197
+ rmSync(skillPath, { force: true });
923
1198
  }
1199
+ } catch (rollbackErr) {
1200
+ console.warn(
1201
+ "[vault_write_skill] file rollback after DB failure also failed:",
1202
+ rollbackErr instanceof Error ? rollbackErr.message : rollbackErr
1203
+ );
924
1204
  }
925
- })();
1205
+ recordTurn("vault_write_skill", args);
1206
+ return textResult({
1207
+ error: `Skill write aborted: database transaction failed and on-disk state was rolled back. ${err instanceof Error ? err.message : String(err)}`
1208
+ });
1209
+ }
926
1210
  const isNew = generation === 1;
927
1211
  notify(vaultDir, {
928
1212
  domain: "skills",
@@ -939,32 +1223,85 @@ function createVaultTools(agentId, runId, options) {
939
1223
  path: relativePath,
940
1224
  generation
941
1225
  });
942
- }
1226
+ },
1227
+ { annotations: { openWorldHint: true } }
943
1228
  );
944
1229
  return [
945
- vaultUnprocessed,
946
- vaultSpores,
947
- vaultSessions,
948
- vaultSearchFts,
949
- vaultSearchSemantic,
950
- vaultState,
951
- vaultEntities,
952
- vaultEdges,
953
- vaultCreateSpore,
954
- vaultCreateEntity,
955
- vaultCreateEdge,
956
- vaultResolveSpore,
957
- vaultUpdateSession,
958
- vaultSetState,
959
- vaultReadDigest,
960
- vaultWriteDigest,
961
- vaultMarkProcessed,
962
- vaultReport,
963
1230
  vaultSkillCandidates,
964
1231
  vaultSkillRecords,
965
1232
  vaultWriteSkill
966
1233
  ];
967
1234
  }
1235
+
1236
+ // src/agent/tools.ts
1237
+ var READ_TOOL_NAMES = /* @__PURE__ */ new Set([
1238
+ "vault_unprocessed",
1239
+ "vault_spores",
1240
+ "vault_sessions",
1241
+ "vault_search_fts",
1242
+ "vault_search_semantic",
1243
+ "vault_state",
1244
+ "vault_entities",
1245
+ "vault_edges"
1246
+ ]);
1247
+ var WRITE_TOOL_NAMES = /* @__PURE__ */ new Set([
1248
+ "vault_create_spore",
1249
+ "vault_create_entity",
1250
+ "vault_create_edge",
1251
+ "vault_resolve_spore",
1252
+ "vault_update_session",
1253
+ "vault_set_state",
1254
+ "vault_read_digest",
1255
+ "vault_write_digest",
1256
+ "vault_mark_processed"
1257
+ ]);
1258
+ var OBSERVABILITY_TOOL_NAMES = /* @__PURE__ */ new Set(["vault_report"]);
1259
+ var SKILL_TOOL_NAMES = /* @__PURE__ */ new Set([
1260
+ "vault_skill_candidates",
1261
+ "vault_skill_records",
1262
+ "vault_write_skill"
1263
+ ]);
1264
+ function setsOverlap(a, b) {
1265
+ for (const item of a) {
1266
+ if (b.has(item)) return true;
1267
+ }
1268
+ return false;
1269
+ }
1270
+ function createVaultTools(agentId, runId, options) {
1271
+ const { turnOffset = 0, embeddingManager, teamClient, machineId, projectRoot, vaultDir, onlyNames } = options ?? {};
1272
+ let turnCounter = turnOffset;
1273
+ function recordTurn(toolName, toolInput) {
1274
+ turnCounter++;
1275
+ try {
1276
+ insertTurn({
1277
+ run_id: runId,
1278
+ agent_id: agentId,
1279
+ turn_number: turnCounter,
1280
+ tool_name: toolName,
1281
+ tool_input: JSON.stringify(toolInput),
1282
+ started_at: epochSeconds()
1283
+ });
1284
+ } catch {
1285
+ }
1286
+ }
1287
+ const deps = {
1288
+ agentId,
1289
+ runId,
1290
+ embeddingManager,
1291
+ teamClient,
1292
+ machineId,
1293
+ projectRoot,
1294
+ vaultDir,
1295
+ recordTurn
1296
+ };
1297
+ const needsAll = !onlyNames;
1298
+ return [
1299
+ ...needsAll || setsOverlap(onlyNames, READ_TOOL_NAMES) ? createReadTools(deps) : [],
1300
+ ...needsAll || setsOverlap(onlyNames, WRITE_TOOL_NAMES) ? createWriteTools(deps) : [],
1301
+ ...needsAll || setsOverlap(onlyNames, OBSERVABILITY_TOOL_NAMES) ? createObservabilityTools(deps) : [],
1302
+ ...needsAll || setsOverlap(onlyNames, SKILL_TOOL_NAMES) ? createSkillTools(deps) : []
1303
+ ];
1304
+ }
968
1305
  function createVaultToolServer(agentId, runId, options) {
969
1306
  const tools = createVaultTools(agentId, runId, options);
970
1307
  return createSdkMcpServer({
@@ -974,9 +1311,10 @@ function createVaultToolServer(agentId, runId, options) {
974
1311
  });
975
1312
  }
976
1313
  function createScopedVaultToolServer(agentId, runId, toolNames, options) {
977
- const allTools = createVaultTools(agentId, runId, options);
978
1314
  const nameSet = new Set(toolNames);
979
- const scopedTools = allTools.filter((t) => nameSet.has(t.name));
1315
+ const allTools = createVaultTools(agentId, runId, { ...options, onlyNames: nameSet });
1316
+ const eligible = options?.readOnly ? allTools.filter((t) => t.annotations?.readOnlyHint === true) : allTools;
1317
+ const scopedTools = eligible.filter((t) => nameSet.has(t.name));
980
1318
  return createSdkMcpServer({
981
1319
  name: "myco-vault",
982
1320
  version: getPluginVersion(),
@@ -1251,13 +1589,13 @@ var KNOWN_CONTEXT_QUERY_TOOLS = /* @__PURE__ */ new Set([
1251
1589
  "vault_sessions",
1252
1590
  "vault_state"
1253
1591
  ]);
1254
- function validateTool(tool2) {
1255
- if (!KNOWN_CONTEXT_QUERY_TOOLS.has(tool2)) {
1256
- throw new Error(`Unknown context query tool: "${tool2}"`);
1592
+ function validateTool(tool5) {
1593
+ if (!KNOWN_CONTEXT_QUERY_TOOLS.has(tool5)) {
1594
+ throw new Error(`Unknown context query tool: "${tool5}"`);
1257
1595
  }
1258
1596
  }
1259
- async function executeQuery(agentId, tool2, limit) {
1260
- switch (tool2) {
1597
+ async function executeQuery(agentId, tool5, limit) {
1598
+ switch (tool5) {
1261
1599
  case "vault_unprocessed":
1262
1600
  return getUnprocessedBatches({ limit });
1263
1601
  case "vault_spores":
@@ -1267,7 +1605,7 @@ async function executeQuery(agentId, tool2, limit) {
1267
1605
  case "vault_state":
1268
1606
  return getStatesForAgent(agentId);
1269
1607
  default:
1270
- throw new Error(`Unknown context query tool: "${tool2}"`);
1608
+ throw new Error(`Unknown context query tool: "${tool5}"`);
1271
1609
  }
1272
1610
  }
1273
1611
 
@@ -1306,62 +1644,87 @@ function getProviderEnvVars(provider) {
1306
1644
  }
1307
1645
  }
1308
1646
 
1309
- // src/agent/executor.ts
1310
- var STATUS_SKIPPED = "skipped";
1311
- var SKIP_REASON_ALREADY_RUNNING = "already_running";
1312
- var PROMPT_SECTION_TASK = "## Task: ";
1313
- var PROMPT_SECTION_INSTRUCTION = "## User Instruction";
1314
- var PROMPT_SECTION_SEPARATOR = "\n\n";
1315
- var MCP_SERVER_NAME = "myco-vault";
1316
- var PERSIST_SESSION = true;
1317
- var PROMPT_SECTION_PRIOR_PHASES = "## Prior Phase Results";
1318
- var PROMPT_SECTION_CURRENT_PHASE = "## Current Phase: ";
1319
- function composeTaskPrompt(vaultContext, taskDisplayName, taskPrompt, instruction) {
1320
- const sessionIdMatch = instruction?.match(/\b([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\b/i);
1321
- const sessionId = sessionIdMatch?.[1] ?? "";
1322
- let resolvedPrompt = taskPrompt;
1323
- resolvedPrompt = resolvedPrompt.replace(/\{\{session_id\}\}/g, sessionId);
1324
- resolvedPrompt = resolvedPrompt.replace(/\{\{instruction\}\}/g, instruction ?? "");
1325
- const parts = [
1326
- vaultContext,
1327
- `${PROMPT_SECTION_TASK}${taskDisplayName}
1328
- ${resolvedPrompt}`
1329
- ];
1330
- if (instruction) {
1331
- parts.push(`${PROMPT_SECTION_INSTRUCTION}
1332
- ${instruction}`);
1333
- }
1334
- return parts.join(PROMPT_SECTION_SEPARATOR);
1647
+ // src/agent/config-resolver.ts
1648
+ function toProviderConfig(p) {
1649
+ return {
1650
+ type: p.type,
1651
+ baseUrl: p.base_url,
1652
+ model: p.model,
1653
+ contextLength: p.context_length
1654
+ };
1335
1655
  }
1336
- function composePhasePrompt(vaultContext, taskDisplayName, taskOverview, phase, priorPhaseResults, instruction) {
1337
- const parts = [
1338
- vaultContext,
1339
- `${PROMPT_SECTION_TASK}${taskDisplayName}
1340
- ${taskOverview}`
1341
- ];
1342
- if (instruction) {
1343
- parts.push(`${PROMPT_SECTION_INSTRUCTION}
1344
- ${instruction}`);
1345
- }
1346
- if (priorPhaseResults.length > 0 && !phase.skipPriorContext) {
1347
- const summaries = priorPhaseResults.map((pr) => {
1348
- const truncated = pr.summary.length > PHASE_SUMMARY_MAX_CHARS ? pr.summary.slice(0, PHASE_SUMMARY_MAX_CHARS) + "..." : pr.summary;
1349
- return `### ${pr.name} (${pr.status})
1350
- ${truncated}`;
1351
- });
1352
- parts.push(`${PROMPT_SECTION_PRIOR_PHASES}
1353
- ${summaries.join("\n\n")}`);
1656
+ function resolveRunConfig(agentId, requestedTask, vaultDir) {
1657
+ const definitionsDir = resolveDefinitionsDir();
1658
+ const definition = loadAgentDefinition(definitionsDir);
1659
+ const agentRow = getAgent(agentId);
1660
+ const taskRow = requestedTask ? getTask(requestedTask) : getDefaultTask(agentId);
1661
+ const allTasks = loadAllTasks(definitionsDir, vaultDir);
1662
+ const taskName = taskRow?.id ?? requestedTask;
1663
+ const yamlTask = taskName ? allTasks.get(taskName) : void 0;
1664
+ const taskOverrides = taskRow ? {
1665
+ name: taskRow.id,
1666
+ displayName: taskRow.display_name ?? taskRow.id,
1667
+ description: taskRow.description ?? "",
1668
+ agent: taskRow.agent_id,
1669
+ prompt: taskRow.prompt,
1670
+ isDefault: taskRow.is_default === 1,
1671
+ ...taskRow.tool_overrides ? { toolOverrides: JSON.parse(taskRow.tool_overrides) } : {},
1672
+ // Scalar config from YAML (model, turns, timeout) — DB doesn't store these
1673
+ ...yamlTask?.model ? { model: yamlTask.model } : {},
1674
+ ...yamlTask?.maxTurns ? { maxTurns: yamlTask.maxTurns } : {},
1675
+ ...yamlTask?.timeoutSeconds ? { timeoutSeconds: yamlTask.timeoutSeconds } : {},
1676
+ // Structural config from YAML
1677
+ ...yamlTask?.phases ? { phases: yamlTask.phases } : {},
1678
+ ...yamlTask?.execution ? { execution: yamlTask.execution } : {},
1679
+ ...yamlTask?.contextQueries ? { contextQueries: yamlTask.contextQueries } : {},
1680
+ ...yamlTask?.orchestrator ? { orchestrator: yamlTask.orchestrator } : {}
1681
+ } : void 0;
1682
+ const config = resolveEffectiveConfig(definition, agentRow, taskOverrides);
1683
+ let taskProviderOverride;
1684
+ let phaseProviderOverrides = {};
1685
+ let taskParams;
1686
+ try {
1687
+ const mycoConfig = loadConfig(vaultDir);
1688
+ const taskConfig = taskName ? mycoConfig.agent.tasks?.[taskName] : void 0;
1689
+ const globalProvider = mycoConfig.agent.provider;
1690
+ if (taskConfig?.provider) {
1691
+ taskProviderOverride = toProviderConfig(taskConfig.provider);
1692
+ } else if (globalProvider) {
1693
+ taskProviderOverride = toProviderConfig(globalProvider);
1694
+ }
1695
+ if (taskConfig?.phases) {
1696
+ for (const [phaseName, phaseConfig] of Object.entries(taskConfig.phases)) {
1697
+ phaseProviderOverrides[phaseName] = {
1698
+ ...phaseConfig.provider ? { provider: toProviderConfig(phaseConfig.provider) } : {},
1699
+ ...phaseConfig.maxTurns != null ? { maxTurns: phaseConfig.maxTurns } : {}
1700
+ };
1701
+ }
1702
+ }
1703
+ const yamlParams = yamlTask?.params;
1704
+ const configParams = taskConfig?.params;
1705
+ if (yamlParams || configParams) {
1706
+ taskParams = { ...yamlParams, ...configParams };
1707
+ }
1708
+ } catch {
1354
1709
  }
1355
- parts.push(`${PROMPT_SECTION_CURRENT_PHASE}${phase.name}
1356
- ${phase.prompt}`);
1357
- return parts.join(PROMPT_SECTION_SEPARATOR);
1710
+ return {
1711
+ config,
1712
+ definitionsDir,
1713
+ taskProviderOverride,
1714
+ phaseProviderOverrides,
1715
+ taskName,
1716
+ taskParams
1717
+ };
1358
1718
  }
1719
+
1720
+ // src/agent/ollama-context.ts
1721
+ import { execFileSync } from "child_process";
1722
+ import { writeFileSync as writeFileSync2, unlinkSync } from "fs";
1723
+ import { tmpdir } from "os";
1724
+ import { join } from "path";
1359
1725
  var OLLAMA_PRELOAD_TIMEOUT_MS = 3e4;
1726
+ var DEFAULT_OLLAMA_CONTEXT_LENGTH = 32768;
1360
1727
  async function ensureOllamaContextVariant(model, contextLength) {
1361
- const { execFileSync } = await import("child_process");
1362
- const { writeFileSync: writeFileSync2, unlinkSync } = await import("fs");
1363
- const { tmpdir } = await import("os");
1364
- const { join } = await import("path");
1365
1728
  const baseName = model.replace(/:latest$/, "");
1366
1729
  const variantName = `${baseName}-ctx${contextLength}`;
1367
1730
  try {
@@ -1387,6 +1750,63 @@ PARAMETER num_ctx ${contextLength}
1387
1750
  return model;
1388
1751
  }
1389
1752
  }
1753
+ async function resolveOllamaContextVariants(taskProvider, phaseOverrides, createVariant = ensureOllamaContextVariant) {
1754
+ const seen = /* @__PURE__ */ new Map();
1755
+ const recordOllama = (p) => {
1756
+ if (p?.type !== "ollama" || !p.model) return;
1757
+ const ctx = p.contextLength ?? DEFAULT_OLLAMA_CONTEXT_LENGTH;
1758
+ const set = seen.get(p.model) ?? /* @__PURE__ */ new Set();
1759
+ set.add(ctx);
1760
+ seen.set(p.model, set);
1761
+ };
1762
+ recordOllama(taskProvider);
1763
+ for (const override of Object.values(phaseOverrides)) {
1764
+ recordOllama(override.provider);
1765
+ }
1766
+ if (seen.size === 0) {
1767
+ return { taskProvider, phaseOverrides, conflicts: [] };
1768
+ }
1769
+ const resolvedContext = /* @__PURE__ */ new Map();
1770
+ const conflicts = [];
1771
+ for (const [model, values] of seen) {
1772
+ const sorted = [...values].sort((a, b) => a - b);
1773
+ const max = sorted[sorted.length - 1];
1774
+ resolvedContext.set(model, max);
1775
+ if (sorted.length > 1) {
1776
+ conflicts.push({ model, values: sorted, resolved: max });
1777
+ }
1778
+ }
1779
+ const variantEntries = await Promise.all(
1780
+ [...resolvedContext.entries()].map(async ([model, ctx]) => {
1781
+ const variant = await createVariant(model, ctx);
1782
+ return [model, variant];
1783
+ })
1784
+ );
1785
+ const variantByModel = new Map(variantEntries);
1786
+ const rewriteProvider = (p) => {
1787
+ if (!p) return p;
1788
+ if (p.type !== "ollama" || !p.model) return p;
1789
+ const variant = variantByModel.get(p.model);
1790
+ const resolvedCtx = resolvedContext.get(p.model);
1791
+ if (!variant) return p;
1792
+ return { ...p, model: variant, contextLength: resolvedCtx };
1793
+ };
1794
+ const rewrittenPhaseOverrides = {};
1795
+ for (const [name, override] of Object.entries(phaseOverrides)) {
1796
+ rewrittenPhaseOverrides[name] = {
1797
+ ...override,
1798
+ ...override.provider ? { provider: rewriteProvider(override.provider) } : {}
1799
+ };
1800
+ }
1801
+ return {
1802
+ taskProvider: rewriteProvider(taskProvider),
1803
+ phaseOverrides: rewrittenPhaseOverrides,
1804
+ conflicts
1805
+ };
1806
+ }
1807
+
1808
+ // src/agent/wave-computation.ts
1809
+ import crypto3 from "crypto";
1390
1810
  function computeWaves(phases) {
1391
1811
  const nameToPhase = new Map(phases.map((p) => [p.name, p]));
1392
1812
  const inDegree = /* @__PURE__ */ new Map();
@@ -1428,7 +1848,7 @@ function computeWaves(phases) {
1428
1848
  return waves;
1429
1849
  }
1430
1850
  function phaseSessionId(runId, phaseName) {
1431
- const hash = crypto2.createHash("sha256").update(`${runId}-${phaseName}`).digest("hex");
1851
+ const hash = crypto3.createHash("sha256").update(`${runId}-${phaseName}`).digest("hex");
1432
1852
  return [
1433
1853
  hash.slice(0, 8),
1434
1854
  hash.slice(8, 12),
@@ -1437,10 +1857,94 @@ function phaseSessionId(runId, phaseName) {
1437
1857
  hash.slice(20, 32)
1438
1858
  ].join("-");
1439
1859
  }
1860
+
1861
+ // src/agent/executor.ts
1862
+ var STATUS_SKIPPED = "skipped";
1863
+ var SKIP_REASON_ALREADY_RUNNING = "already_running";
1864
+ var PROMPT_SECTION_TASK = "## Task: ";
1865
+ var PROMPT_SECTION_INSTRUCTION = "## User Instruction";
1866
+ var PROMPT_SECTION_SEPARATOR = "\n\n";
1867
+ var MCP_SERVER_NAME = "myco-vault";
1868
+ var PERSIST_SESSION = true;
1869
+ var PROMPT_SECTION_PRIOR_PHASES = "## Prior Phase Results";
1870
+ var PROMPT_SECTION_CURRENT_PHASE = "## Current Phase: ";
1871
+ var DEBUG_TOOL_CALLS = process.env.MYCO_AGENT_DEBUG === "1";
1872
+ var TOOL_DEBUG_PREVIEW_CHARS = 240;
1873
+ function previewPayload(value) {
1874
+ const str = typeof value === "string" ? value : JSON.stringify(value);
1875
+ if (str === void 0) return "";
1876
+ return str.length > TOOL_DEBUG_PREVIEW_CHARS ? `${str.slice(0, TOOL_DEBUG_PREVIEW_CHARS)}\u2026(${str.length - TOOL_DEBUG_PREVIEW_CHARS} more chars)` : str;
1877
+ }
1878
+ function logToolUseBlocks(phaseName, message) {
1879
+ if (!DEBUG_TOOL_CALLS) return;
1880
+ const blocks = message.message?.content;
1881
+ if (!Array.isArray(blocks)) return;
1882
+ for (const block of blocks) {
1883
+ if (block.type === "tool_use") {
1884
+ console.log(
1885
+ `[agent:debug] ${phaseName} tool_use: ${block.name ?? "unknown"} input=${previewPayload(block.input)}`
1886
+ );
1887
+ }
1888
+ }
1889
+ }
1890
+ function logToolResultBlocks(phaseName, message) {
1891
+ if (!DEBUG_TOOL_CALLS) return;
1892
+ const blocks = message.message?.content;
1893
+ if (!Array.isArray(blocks)) return;
1894
+ for (const block of blocks) {
1895
+ if (block.type === "tool_result") {
1896
+ const flag = block.is_error ? " [ERROR]" : "";
1897
+ console.log(
1898
+ `[agent:debug] ${phaseName} tool_result${flag}: ${previewPayload(block.content)}`
1899
+ );
1900
+ }
1901
+ }
1902
+ }
1903
+ function composeTaskPrompt(vaultContext, taskDisplayName, taskPrompt, instruction) {
1904
+ const sessionIdMatch = instruction?.match(/\b([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\b/i);
1905
+ const sessionId = sessionIdMatch?.[1] ?? "";
1906
+ let resolvedPrompt = taskPrompt;
1907
+ resolvedPrompt = resolvedPrompt.replace(/\{\{session_id\}\}/g, sessionId);
1908
+ resolvedPrompt = resolvedPrompt.replace(/\{\{instruction\}\}/g, instruction ?? "");
1909
+ const parts = [
1910
+ vaultContext,
1911
+ `${PROMPT_SECTION_TASK}${taskDisplayName}
1912
+ ${resolvedPrompt}`
1913
+ ];
1914
+ if (instruction) {
1915
+ parts.push(`${PROMPT_SECTION_INSTRUCTION}
1916
+ ${instruction}`);
1917
+ }
1918
+ return parts.join(PROMPT_SECTION_SEPARATOR);
1919
+ }
1920
+ function composePhasePrompt(vaultContext, taskDisplayName, taskOverview, phase, priorPhaseResults, instruction) {
1921
+ const parts = [
1922
+ vaultContext,
1923
+ `${PROMPT_SECTION_TASK}${taskDisplayName}
1924
+ ${taskOverview}`
1925
+ ];
1926
+ if (instruction) {
1927
+ parts.push(`${PROMPT_SECTION_INSTRUCTION}
1928
+ ${instruction}`);
1929
+ }
1930
+ if (priorPhaseResults.length > 0 && !phase.skipPriorContext) {
1931
+ const summaries = priorPhaseResults.map((pr) => {
1932
+ const truncated = pr.summary.length > PHASE_SUMMARY_MAX_CHARS ? pr.summary.slice(0, PHASE_SUMMARY_MAX_CHARS) + "..." : pr.summary;
1933
+ return `### ${pr.name} (${pr.status})
1934
+ ${truncated}`;
1935
+ });
1936
+ parts.push(`${PROMPT_SECTION_PRIOR_PHASES}
1937
+ ${summaries.join("\n\n")}`);
1938
+ }
1939
+ parts.push(`${PROMPT_SECTION_CURRENT_PHASE}${phase.name}
1940
+ ${phase.prompt}`);
1941
+ return parts.join(PROMPT_SECTION_SEPARATOR);
1942
+ }
1440
1943
  async function executePhase(query, phasePrompt, phaseModel, systemPrompt, toolServer, phase, env, sessionId, abortController) {
1441
1944
  let phaseCost = 0;
1442
1945
  let phaseTokens = 0;
1443
1946
  let phaseTurns = 0;
1947
+ let agenticTurns = 0;
1444
1948
  let phaseSummary = "";
1445
1949
  try {
1446
1950
  for await (const message of query({
@@ -1460,6 +1964,13 @@ async function executePhase(query, phasePrompt, phaseModel, systemPrompt, toolSe
1460
1964
  ...abortController ? { abortController } : {}
1461
1965
  }
1462
1966
  })) {
1967
+ if (message.type === "assistant") {
1968
+ agenticTurns++;
1969
+ logToolUseBlocks(phase.name, message);
1970
+ }
1971
+ if (message.type === "user") {
1972
+ logToolResultBlocks(phase.name, message);
1973
+ }
1463
1974
  if (message.type === "result") {
1464
1975
  phaseCost = message.total_cost_usd ?? 0;
1465
1976
  phaseTokens = (message.usage.input_tokens ?? 0) + (message.usage.output_tokens ?? 0);
@@ -1469,6 +1980,11 @@ async function executePhase(query, phasePrompt, phaseModel, systemPrompt, toolSe
1469
1980
  }
1470
1981
  }
1471
1982
  }
1983
+ if (phase.maxTurns) {
1984
+ console.log(
1985
+ `[agent] Phase "${phase.name}": num_turns=${phaseTurns}, assistant_msgs=${agenticTurns}, budget=${phase.maxTurns}`
1986
+ );
1987
+ }
1472
1988
  if (phase.required && phaseTurns === 0) {
1473
1989
  console.warn(`[agent] Required phase "${phase.name}" produced 0 turns`);
1474
1990
  }
@@ -1581,7 +2097,8 @@ async function executePhasedQuery(config, systemPrompt, vaultContext, agentId, r
1581
2097
  turnOffset: runningTurnCount + indexInWave * effectiveMaxTurns,
1582
2098
  embeddingManager,
1583
2099
  projectRoot,
1584
- vaultDir
2100
+ vaultDir,
2101
+ readOnly: phase.readOnly
1585
2102
  }
1586
2103
  );
1587
2104
  const phaseProvider = phase.provider ?? phaseOverride?.provider ?? taskProviderOverride ?? config.execution?.provider;
@@ -1644,60 +2161,15 @@ async function runAgent(vaultDir, options) {
1644
2161
  }
1645
2162
  }
1646
2163
  }
1647
- const definitionsDir = resolveDefinitionsDir();
1648
- const definition = loadAgentDefinition(definitionsDir);
1649
- const agentRow = getAgent(agentId);
1650
- const taskRow = options?.task ? getTask(options.task) : getDefaultTask(agentId);
1651
- const allTasks = loadAllTasks(definitionsDir, vaultDir);
1652
- const taskName = taskRow?.id ?? options?.task;
1653
- const yamlTask = taskName ? allTasks.get(taskName) : void 0;
1654
- const taskOverrides = taskRow ? {
1655
- name: taskRow.id,
1656
- displayName: taskRow.display_name ?? taskRow.id,
1657
- description: taskRow.description ?? "",
1658
- agent: taskRow.agent_id,
1659
- prompt: taskRow.prompt,
1660
- isDefault: taskRow.is_default === 1,
1661
- ...taskRow.tool_overrides ? { toolOverrides: JSON.parse(taskRow.tool_overrides) } : {},
1662
- // Scalar config from YAML (model, turns, timeout) — DB doesn't store these
1663
- ...yamlTask?.model ? { model: yamlTask.model } : {},
1664
- ...yamlTask?.maxTurns ? { maxTurns: yamlTask.maxTurns } : {},
1665
- ...yamlTask?.timeoutSeconds ? { timeoutSeconds: yamlTask.timeoutSeconds } : {},
1666
- // Structural config from YAML
1667
- ...yamlTask?.phases ? { phases: yamlTask.phases } : {},
1668
- ...yamlTask?.execution ? { execution: yamlTask.execution } : {},
1669
- ...yamlTask?.contextQueries ? { contextQueries: yamlTask.contextQueries } : {},
1670
- ...yamlTask?.orchestrator ? { orchestrator: yamlTask.orchestrator } : {}
1671
- } : void 0;
1672
- const config = resolveEffectiveConfig(definition, agentRow, taskOverrides);
1673
- let taskProviderOverride;
1674
- let phaseProviderOverrides = {};
1675
- try {
1676
- const mycoConfig = loadConfig(vaultDir);
1677
- const toProviderConfig = (p) => ({
1678
- type: p.type,
1679
- baseUrl: p.base_url,
1680
- model: p.model,
1681
- contextLength: p.context_length
1682
- });
1683
- const taskConfig = taskName ? mycoConfig.agent.tasks?.[taskName] : void 0;
1684
- const globalProvider = mycoConfig.agent.provider;
1685
- if (taskConfig?.provider) {
1686
- taskProviderOverride = toProviderConfig(taskConfig.provider);
1687
- } else if (globalProvider) {
1688
- taskProviderOverride = toProviderConfig(globalProvider);
1689
- }
1690
- if (taskConfig?.phases) {
1691
- for (const [phaseName, phaseConfig] of Object.entries(taskConfig.phases)) {
1692
- phaseProviderOverrides[phaseName] = {
1693
- ...phaseConfig.provider ? { provider: toProviderConfig(phaseConfig.provider) } : {},
1694
- ...phaseConfig.maxTurns != null ? { maxTurns: phaseConfig.maxTurns } : {}
1695
- };
1696
- }
1697
- }
1698
- } catch {
1699
- }
1700
- const runId = options?.resumeRunId ?? crypto2.randomUUID();
2164
+ const {
2165
+ config,
2166
+ definitionsDir,
2167
+ taskProviderOverride: resolvedTaskProvider,
2168
+ phaseProviderOverrides: resolvedPhaseOverrides
2169
+ } = resolveRunConfig(agentId, requestedTask, vaultDir);
2170
+ let taskProviderOverride = resolvedTaskProvider;
2171
+ let phaseProviderOverrides = resolvedPhaseOverrides;
2172
+ const runId = options?.resumeRunId ?? crypto4.randomUUID();
1701
2173
  const now = epochSeconds();
1702
2174
  if (!options?.resumeRunId) {
1703
2175
  insertRun({
@@ -1718,12 +2190,18 @@ async function runAgent(vaultDir, options) {
1718
2190
  provider: effectiveProvider?.type ?? "cloud",
1719
2191
  ...effectiveProvider?.baseUrl ? { baseUrl: effectiveProvider.baseUrl } : {}
1720
2192
  };
1721
- if (effectiveProvider?.type === "ollama" && effectiveProvider.contextLength && effectiveProvider.model) {
1722
- const variantModel = await ensureOllamaContextVariant(
1723
- effectiveProvider.model,
1724
- effectiveProvider.contextLength
2193
+ {
2194
+ const resolved = await resolveOllamaContextVariants(
2195
+ taskProviderOverride,
2196
+ phaseProviderOverrides
1725
2197
  );
1726
- taskProviderOverride = { ...taskProviderOverride, model: variantModel };
2198
+ taskProviderOverride = resolved.taskProvider;
2199
+ phaseProviderOverrides = resolved.phaseOverrides;
2200
+ for (const conflict of resolved.conflicts) {
2201
+ console.warn(
2202
+ `[agent] Ollama model "${conflict.model}" referenced with conflicting context_length values [${conflict.values.join(", ")}] \u2014 reconciled to ${conflict.resolved} to avoid loading multiple variants. Configure one value per model to silence this warning.`
2203
+ );
2204
+ }
1727
2205
  }
1728
2206
  const taskAbortController = new AbortController();
1729
2207
  const timeoutMs = config.timeoutSeconds * MS_PER_SECOND;
@@ -1834,4 +2312,4 @@ export {
1834
2312
  computeWaves,
1835
2313
  runAgent
1836
2314
  };
1837
- //# sourceMappingURL=executor-HKNINUWO.js.map
2315
+ //# sourceMappingURL=executor-4OXDK4ZA.js.map