@ouro.bot/cli 0.1.0-alpha.24 → 0.1.0-alpha.241

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 (258) hide show
  1. package/README.md +187 -191
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
  4. package/changelog.json +1459 -0
  5. package/dist/arc/attention-types.js +8 -0
  6. package/dist/arc/cares.js +140 -0
  7. package/dist/arc/episodes.js +119 -0
  8. package/dist/arc/intentions.js +133 -0
  9. package/dist/arc/json-store.js +120 -0
  10. package/dist/arc/obligations.js +237 -0
  11. package/dist/arc/presence.js +185 -0
  12. package/dist/heart/active-work.js +832 -0
  13. package/dist/heart/agent-entry.js +37 -2
  14. package/dist/heart/auth/auth-flow.js +447 -0
  15. package/dist/heart/bridges/manager.js +358 -0
  16. package/dist/heart/bridges/state-machine.js +135 -0
  17. package/dist/heart/bridges/store.js +123 -0
  18. package/dist/heart/commitments.js +111 -0
  19. package/dist/heart/config-registry.js +304 -0
  20. package/dist/heart/config.js +63 -30
  21. package/dist/heart/core.js +620 -159
  22. package/dist/heart/cross-chat-delivery.js +131 -0
  23. package/dist/heart/daemon/agent-config-check.js +149 -0
  24. package/dist/heart/daemon/agent-discovery.js +81 -0
  25. package/dist/heart/daemon/agent-service.js +360 -0
  26. package/dist/heart/daemon/cadence.js +70 -0
  27. package/dist/heart/daemon/cli-defaults.js +557 -0
  28. package/dist/heart/daemon/cli-exec.js +1847 -0
  29. package/dist/heart/daemon/cli-parse.js +759 -0
  30. package/dist/heart/daemon/cli-render.js +399 -0
  31. package/dist/heart/daemon/cli-types.js +8 -0
  32. package/dist/heart/daemon/daemon-cli.js +29 -1177
  33. package/dist/heart/daemon/daemon-entry.js +202 -4
  34. package/dist/heart/daemon/daemon-health.js +136 -0
  35. package/dist/heart/daemon/daemon-runtime-sync.js +153 -12
  36. package/dist/heart/daemon/daemon-tombstone.js +123 -0
  37. package/dist/heart/daemon/daemon.js +492 -20
  38. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  39. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  40. package/dist/heart/daemon/inner-status.js +89 -0
  41. package/dist/heart/daemon/launchd.js +39 -8
  42. package/dist/heart/daemon/log-tailer.js +4 -3
  43. package/dist/heart/daemon/message-router.js +17 -8
  44. package/dist/heart/daemon/os-cron-deps.js +134 -0
  45. package/dist/heart/daemon/ouro-bot-entry.js +1 -1
  46. package/dist/heart/daemon/process-manager.js +123 -0
  47. package/dist/heart/daemon/run-hooks.js +2 -0
  48. package/dist/heart/daemon/runtime-logging.js +58 -15
  49. package/dist/heart/daemon/runtime-metadata.js +101 -0
  50. package/dist/heart/daemon/runtime-mode.js +67 -0
  51. package/dist/heart/daemon/safe-mode.js +161 -0
  52. package/dist/heart/daemon/sense-manager.js +72 -3
  53. package/dist/heart/daemon/session-id-resolver.js +131 -0
  54. package/dist/heart/daemon/skill-management-installer.js +94 -0
  55. package/dist/heart/daemon/socket-client.js +202 -0
  56. package/dist/heart/daemon/task-scheduler.js +3 -25
  57. package/dist/heart/daemon/thoughts.js +507 -0
  58. package/dist/heart/delegation.js +62 -0
  59. package/dist/heart/habits/habit-migration.js +181 -0
  60. package/dist/heart/habits/habit-parser.js +119 -0
  61. package/dist/heart/habits/habit-scheduler.js +369 -0
  62. package/dist/heart/{daemon → hatch}/hatch-flow.js +30 -120
  63. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  64. package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
  65. package/dist/heart/{daemon → hatch}/specialist-tools.js +49 -3
  66. package/dist/heart/identity.js +157 -55
  67. package/dist/heart/kicks.js +2 -20
  68. package/dist/heart/mcp/mcp-server.js +651 -0
  69. package/dist/heart/migrate-config.js +127 -0
  70. package/dist/heart/model-capabilities.js +48 -0
  71. package/dist/heart/outlook/outlook-http.js +439 -0
  72. package/dist/heart/outlook/outlook-read.js +1618 -0
  73. package/dist/heart/outlook/outlook-render.js +1032 -0
  74. package/dist/heart/outlook/outlook-types.js +7 -0
  75. package/dist/heart/outlook/outlook-view.js +194 -0
  76. package/dist/heart/progress-story.js +42 -0
  77. package/dist/heart/provider-failover.js +88 -0
  78. package/dist/heart/provider-ping.js +162 -0
  79. package/dist/heart/providers/anthropic-token.js +163 -0
  80. package/dist/heart/providers/anthropic.js +187 -41
  81. package/dist/heart/providers/azure.js +116 -10
  82. package/dist/heart/providers/github-copilot.js +157 -0
  83. package/dist/heart/providers/minimax.js +33 -3
  84. package/dist/heart/providers/openai-codex.js +51 -16
  85. package/dist/heart/session-activity.js +172 -0
  86. package/dist/heart/session-recall.js +216 -0
  87. package/dist/heart/start-of-turn-packet.js +330 -0
  88. package/dist/heart/streaming.js +36 -27
  89. package/dist/heart/sync.js +217 -0
  90. package/dist/heart/target-resolution.js +127 -0
  91. package/dist/heart/tempo.js +93 -0
  92. package/dist/heart/temporal-view.js +41 -0
  93. package/dist/heart/tool-activity-callbacks.js +36 -0
  94. package/dist/heart/tool-description.js +135 -0
  95. package/dist/heart/tool-loop.js +200 -0
  96. package/dist/heart/turn-context.js +358 -0
  97. package/dist/heart/turn-coordinator.js +28 -0
  98. package/dist/heart/versioning/ouro-bot-global-installer.js +128 -0
  99. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  100. package/dist/heart/{daemon → versioning}/ouro-path-installer.js +78 -35
  101. package/dist/heart/versioning/ouro-version-manager.js +171 -0
  102. package/dist/heart/{daemon → versioning}/staged-restart.js +30 -6
  103. package/dist/heart/{daemon → versioning}/update-checker.js +9 -1
  104. package/dist/heart/{daemon → versioning}/update-hooks.js +11 -0
  105. package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +41 -3
  106. package/dist/mind/associative-recall.js +126 -66
  107. package/dist/mind/bundle-manifest.js +8 -1
  108. package/dist/mind/context.js +125 -14
  109. package/dist/mind/{memory.js → diary.js} +73 -96
  110. package/dist/mind/embedding-provider.js +60 -0
  111. package/dist/mind/file-state.js +179 -0
  112. package/dist/mind/first-impressions.js +16 -2
  113. package/dist/mind/friends/channel.js +56 -0
  114. package/dist/mind/friends/group-context.js +144 -0
  115. package/dist/mind/friends/resolver.js +37 -0
  116. package/dist/mind/friends/store-file.js +58 -3
  117. package/dist/mind/friends/trust-explanation.js +74 -0
  118. package/dist/mind/friends/types.js +8 -0
  119. package/dist/mind/journal-index.js +161 -0
  120. package/dist/mind/obligation-steering.js +221 -0
  121. package/dist/mind/pending.js +76 -9
  122. package/dist/mind/phrases.js +1 -0
  123. package/dist/mind/prompt.js +762 -109
  124. package/dist/mind/scrutiny.js +173 -0
  125. package/dist/mind/token-estimate.js +8 -12
  126. package/dist/nerves/coverage/audit.js +1 -1
  127. package/dist/nerves/coverage/file-completeness.js +50 -5
  128. package/dist/nerves/coverage/run-artifacts.js +1 -1
  129. package/dist/nerves/event-buffer.js +111 -0
  130. package/dist/nerves/index.js +64 -4
  131. package/dist/nerves/observation.js +20 -0
  132. package/dist/nerves/runtime.js +5 -1
  133. package/dist/outlook-ui/assets/index-Ck8agNeO.js +61 -0
  134. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  135. package/dist/outlook-ui/index.html +15 -0
  136. package/dist/repertoire/ado-client.js +15 -56
  137. package/dist/repertoire/ado-semantic.js +11 -10
  138. package/dist/repertoire/api-client.js +97 -0
  139. package/dist/repertoire/bitwarden-store.js +319 -0
  140. package/dist/repertoire/bw-installer.js +79 -0
  141. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  142. package/dist/repertoire/coding/context-pack.js +330 -0
  143. package/dist/repertoire/coding/feedback.js +197 -30
  144. package/dist/repertoire/coding/manager.js +149 -2
  145. package/dist/repertoire/coding/spawner.js +55 -9
  146. package/dist/repertoire/coding/tools.js +170 -7
  147. package/dist/repertoire/commerce-errors.js +109 -0
  148. package/dist/repertoire/commerce-self-test.js +156 -0
  149. package/dist/repertoire/credential-access.js +515 -0
  150. package/dist/repertoire/duffel-client.js +185 -0
  151. package/dist/repertoire/github-client.js +14 -55
  152. package/dist/repertoire/graph-client.js +11 -52
  153. package/dist/repertoire/guardrails.js +369 -0
  154. package/dist/repertoire/mcp-client.js +255 -0
  155. package/dist/repertoire/mcp-manager.js +303 -0
  156. package/dist/repertoire/mcp-tools.js +63 -0
  157. package/dist/repertoire/shell-sessions.js +133 -0
  158. package/dist/repertoire/skills.js +14 -23
  159. package/dist/repertoire/stripe-client.js +131 -0
  160. package/dist/repertoire/tasks/board.js +43 -5
  161. package/dist/repertoire/tasks/fix.js +182 -0
  162. package/dist/repertoire/tasks/index.js +28 -10
  163. package/dist/repertoire/tasks/lifecycle.js +2 -2
  164. package/dist/repertoire/tasks/parser.js +3 -2
  165. package/dist/repertoire/tasks/scanner.js +194 -37
  166. package/dist/repertoire/tasks/transitions.js +11 -28
  167. package/dist/repertoire/tools-base.js +43 -771
  168. package/dist/repertoire/tools-bluebubbles.js +94 -0
  169. package/dist/repertoire/tools-bridge.js +141 -0
  170. package/dist/repertoire/tools-config.js +185 -0
  171. package/dist/repertoire/tools-continuity.js +248 -0
  172. package/dist/repertoire/tools-credential.js +182 -0
  173. package/dist/repertoire/tools-files.js +342 -0
  174. package/dist/repertoire/tools-flight.js +224 -0
  175. package/dist/repertoire/tools-flow.js +62 -0
  176. package/dist/repertoire/tools-github.js +1 -7
  177. package/dist/repertoire/tools-memory.js +347 -0
  178. package/dist/repertoire/tools-session.js +739 -0
  179. package/dist/repertoire/tools-shell.js +120 -0
  180. package/dist/repertoire/tools-stripe.js +180 -0
  181. package/dist/repertoire/tools-surface.js +243 -0
  182. package/dist/repertoire/tools-teams.js +12 -62
  183. package/dist/repertoire/tools-travel.js +125 -0
  184. package/dist/repertoire/tools-user-profile.js +144 -0
  185. package/dist/repertoire/tools-vault.js +110 -0
  186. package/dist/repertoire/tools.js +147 -130
  187. package/dist/repertoire/travel-api-client.js +360 -0
  188. package/dist/repertoire/user-profile.js +118 -0
  189. package/dist/repertoire/vault-setup.js +241 -0
  190. package/dist/scripts/claude-code-hook.js +41 -0
  191. package/dist/scripts/claude-code-stop-hook.js +47 -0
  192. package/dist/senses/attention-queue.js +97 -0
  193. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +109 -10
  194. package/dist/senses/bluebubbles/entry.js +13 -0
  195. package/dist/senses/bluebubbles/inbound-log.js +109 -0
  196. package/dist/senses/bluebubbles/index.js +1374 -0
  197. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +119 -24
  198. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +13 -5
  199. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  200. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  201. package/dist/senses/bluebubbles/session-cleanup.js +72 -0
  202. package/dist/senses/cli/adapter.js +274 -0
  203. package/dist/senses/cli/ink-app.js +156 -0
  204. package/dist/senses/cli/inline-diff.js +64 -0
  205. package/dist/senses/cli/message-list.js +51 -0
  206. package/dist/senses/cli/ouro-tui.js +358 -0
  207. package/dist/senses/cli/spinner-imperative.js +135 -0
  208. package/dist/senses/cli/spinner.js +101 -0
  209. package/dist/senses/cli/status-line.js +60 -0
  210. package/dist/senses/cli/streaming-markdown.js +526 -0
  211. package/dist/senses/cli/tool-display.js +83 -0
  212. package/dist/senses/cli/tool-render.js +85 -0
  213. package/dist/senses/cli/tui-store.js +198 -0
  214. package/dist/senses/cli/virtual-list.js +35 -0
  215. package/dist/senses/cli-entry.js +1 -1
  216. package/dist/senses/cli-layout.js +187 -0
  217. package/dist/senses/cli.js +510 -246
  218. package/dist/senses/commands.js +65 -1
  219. package/dist/senses/continuity.js +94 -0
  220. package/dist/senses/habit-turn-message.js +108 -0
  221. package/dist/senses/inner-dialog-worker.js +112 -19
  222. package/dist/senses/inner-dialog.js +593 -85
  223. package/dist/senses/pipeline.js +559 -0
  224. package/dist/senses/shared-turn.js +199 -0
  225. package/dist/senses/surface-tool.js +68 -0
  226. package/dist/senses/teams.js +664 -165
  227. package/dist/senses/trust-gate.js +112 -2
  228. package/package.json +14 -7
  229. package/skills/agent-commerce.md +106 -0
  230. package/skills/browser-navigation.md +110 -0
  231. package/skills/commerce-setup-guide.md +116 -0
  232. package/skills/commerce-setup.md +84 -0
  233. package/skills/configure-dev-tools.md +81 -0
  234. package/skills/travel-planning.md +138 -0
  235. package/dist/heart/daemon/subagent-installer.js +0 -134
  236. package/dist/senses/bluebubbles-entry.js +0 -11
  237. package/dist/senses/bluebubbles.js +0 -421
  238. package/dist/senses/debug-activity.js +0 -107
  239. package/subagents/README.md +0 -73
  240. package/subagents/work-doer.md +0 -235
  241. package/subagents/work-merger.md +0 -618
  242. package/subagents/work-planner.md +0 -382
  243. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  244. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  245. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  246. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  247. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  248. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  249. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  250. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  251. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  252. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  253. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  254. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
  255. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  256. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  257. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  258. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.credentialToolDefinitions = void 0;
4
+ const credential_access_1 = require("./credential-access");
5
+ const runtime_1 = require("../nerves/runtime");
6
+ exports.credentialToolDefinitions = [
7
+ {
8
+ tool: {
9
+ type: "function",
10
+ function: {
11
+ name: "credential_get",
12
+ description: "Get credential metadata for a domain. Returns username, notes, and creation date. Never returns passwords — the credential gateway handles secret injection internally.",
13
+ parameters: {
14
+ type: "object",
15
+ properties: {
16
+ domain: {
17
+ type: "string",
18
+ description: "Domain to look up (e.g. 'airbnb.com', 'api.openweathermap.org')",
19
+ },
20
+ },
21
+ required: ["domain"],
22
+ },
23
+ },
24
+ },
25
+ handler: async (args) => {
26
+ (0, runtime_1.emitNervesEvent)({
27
+ component: "repertoire",
28
+ event: "repertoire.credential_tool_call",
29
+ message: "credential_get invoked",
30
+ meta: { tool: "credential_get", domain: args.domain },
31
+ });
32
+ try {
33
+ const store = (0, credential_access_1.getCredentialStore)();
34
+ const meta = await store.get(args.domain);
35
+ if (!meta) {
36
+ return `No credential found for "${args.domain}".`;
37
+ }
38
+ return JSON.stringify(meta, null, 2);
39
+ }
40
+ catch (err) {
41
+ /* v8 ignore next -- defensive: store.get wraps errors @preserve */
42
+ return `Credential error: ${err instanceof Error ? err.message : String(err)}`;
43
+ }
44
+ },
45
+ summaryKeys: ["domain"],
46
+ },
47
+ {
48
+ tool: {
49
+ type: "function",
50
+ function: {
51
+ name: "credential_store",
52
+ description: "Store credentials the agent acquired (e.g. during sign-up). The password is accepted in args because the model generated it. Stored passwords are never returned later — only metadata is visible.",
53
+ parameters: {
54
+ type: "object",
55
+ properties: {
56
+ domain: {
57
+ type: "string",
58
+ description: "Domain these credentials are for (e.g. 'airbnb.com')",
59
+ },
60
+ username: {
61
+ type: "string",
62
+ description: "Username or email for the account",
63
+ },
64
+ password: {
65
+ type: "string",
66
+ description: "Password for the account",
67
+ },
68
+ notes: {
69
+ type: "string",
70
+ description: "Optional notes about this credential",
71
+ },
72
+ },
73
+ required: ["domain", "username", "password"],
74
+ },
75
+ },
76
+ },
77
+ handler: async (args) => {
78
+ (0, runtime_1.emitNervesEvent)({
79
+ component: "repertoire",
80
+ event: "repertoire.credential_tool_call",
81
+ message: "credential_store invoked",
82
+ meta: { tool: "credential_store", domain: args.domain },
83
+ });
84
+ try {
85
+ const store = (0, credential_access_1.getCredentialStore)();
86
+ await store.store(args.domain, {
87
+ username: args.username,
88
+ password: args.password,
89
+ notes: args.notes,
90
+ });
91
+ return `Credentials stored for "${args.domain}".`;
92
+ }
93
+ catch (err) {
94
+ /* v8 ignore next -- defensive: store.store wraps errors @preserve */
95
+ return `Credential store error: ${err instanceof Error ? err.message : String(err)}`;
96
+ }
97
+ },
98
+ summaryKeys: ["domain"],
99
+ },
100
+ {
101
+ tool: {
102
+ type: "function",
103
+ function: {
104
+ name: "credential_list",
105
+ description: "List stored credential domains. Returns metadata only (domain, username, notes, creation date). Never returns passwords.",
106
+ parameters: {
107
+ type: "object",
108
+ properties: {
109
+ search: {
110
+ type: "string",
111
+ description: "Optional search filter to match against domain names",
112
+ },
113
+ },
114
+ },
115
+ },
116
+ },
117
+ handler: async (args) => {
118
+ (0, runtime_1.emitNervesEvent)({
119
+ component: "repertoire",
120
+ event: "repertoire.credential_tool_call",
121
+ message: "credential_list invoked",
122
+ meta: { tool: "credential_list" },
123
+ });
124
+ try {
125
+ const store = (0, credential_access_1.getCredentialStore)();
126
+ let items = await store.list();
127
+ // Client-side search filter
128
+ if (args.search) {
129
+ const term = args.search.toLowerCase();
130
+ items = items.filter((item) => item.domain.toLowerCase().includes(term) ||
131
+ (item.username && item.username.toLowerCase().includes(term)));
132
+ }
133
+ return JSON.stringify(items, null, 2);
134
+ }
135
+ catch (err) {
136
+ /* v8 ignore next -- defensive: store.list wraps errors @preserve */
137
+ return `Credential list error: ${err instanceof Error ? err.message : String(err)}`;
138
+ }
139
+ },
140
+ summaryKeys: ["search"],
141
+ },
142
+ {
143
+ tool: {
144
+ type: "function",
145
+ function: {
146
+ name: "credential_delete",
147
+ description: "Delete stored credentials for a domain.",
148
+ parameters: {
149
+ type: "object",
150
+ properties: {
151
+ domain: {
152
+ type: "string",
153
+ description: "Domain whose credentials should be deleted",
154
+ },
155
+ },
156
+ required: ["domain"],
157
+ },
158
+ },
159
+ },
160
+ handler: async (args) => {
161
+ (0, runtime_1.emitNervesEvent)({
162
+ component: "repertoire",
163
+ event: "repertoire.credential_tool_call",
164
+ message: "credential_delete invoked",
165
+ meta: { tool: "credential_delete", domain: args.domain },
166
+ });
167
+ try {
168
+ const store = (0, credential_access_1.getCredentialStore)();
169
+ const deleted = await store.delete(args.domain);
170
+ if (deleted) {
171
+ return `Credentials for "${args.domain}" deleted.`;
172
+ }
173
+ return `No credential found for "${args.domain}".`;
174
+ }
175
+ catch (err) {
176
+ /* v8 ignore next -- defensive: store.delete wraps errors @preserve */
177
+ return `Credential delete error: ${err instanceof Error ? err.message : String(err)}`;
178
+ }
179
+ },
180
+ summaryKeys: ["domain"],
181
+ },
182
+ ];
@@ -0,0 +1,342 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.fileToolDefinitions = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const fg = __importStar(require("fast-glob"));
39
+ const path = __importStar(require("path"));
40
+ const identity_1 = require("../heart/identity");
41
+ const file_state_1 = require("../mind/file-state");
42
+ const scrutiny_1 = require("../mind/scrutiny");
43
+ const tools_base_1 = require("./tools-base");
44
+ function resolveLocalToolPath(targetPath) {
45
+ if (!path.isAbsolute(targetPath)) {
46
+ return path.resolve((0, identity_1.getRepoRoot)(), targetPath);
47
+ }
48
+ return targetPath;
49
+ }
50
+ function buildContextDiff(lines, changeStart, changeEnd, contextSize = 3) {
51
+ const start = Math.max(0, changeStart - contextSize);
52
+ const end = Math.min(lines.length, changeEnd + contextSize);
53
+ const result = [];
54
+ for (let i = start; i < end; i++) {
55
+ const lineNum = i + 1;
56
+ const prefix = (i >= changeStart && i < changeEnd) ? ">" : " ";
57
+ result.push(`${prefix} ${lineNum} | ${lines[i]}`);
58
+ }
59
+ return result.join("\n");
60
+ }
61
+ exports.fileToolDefinitions = [
62
+ {
63
+ tool: {
64
+ type: "function",
65
+ function: {
66
+ name: "read_file",
67
+ description: "Read file contents. Results include line numbers. Use offset/limit for large files -- don't read the whole thing if you only need a section. Use this tool before editing any file. When reading code, read enough context to understand the surrounding logic, not just the target line.",
68
+ parameters: {
69
+ type: "object",
70
+ properties: {
71
+ path: { type: "string" },
72
+ offset: { type: "number", description: "1-based line number to start reading from" },
73
+ limit: { type: "number", description: "maximum number of lines to return" },
74
+ },
75
+ required: ["path"],
76
+ },
77
+ },
78
+ },
79
+ handler: (a) => {
80
+ const resolvedPath = resolveLocalToolPath(a.path);
81
+ const content = fs.readFileSync(resolvedPath, "utf-8");
82
+ tools_base_1.editFileReadTracker.add(resolvedPath);
83
+ const offset = a.offset ? parseInt(a.offset, 10) : undefined;
84
+ const limit = a.limit ? parseInt(a.limit, 10) : undefined;
85
+ // Record in file state cache for staleness detection
86
+ try {
87
+ const mtime = fs.statSync(resolvedPath).mtimeMs;
88
+ const readContent = (offset === undefined && limit === undefined)
89
+ ? content
90
+ : content.split("\n").slice(offset ? offset - 1 : 0, limit !== undefined ? (offset ? offset - 1 : 0) + limit : undefined).join("\n");
91
+ file_state_1.fileStateCache.record(resolvedPath, readContent, mtime, offset, limit);
92
+ }
93
+ catch {
94
+ // stat failed -- skip cache recording
95
+ }
96
+ if (offset === undefined && limit === undefined)
97
+ return content;
98
+ const lines = content.split("\n");
99
+ const start = offset ? offset - 1 : 0;
100
+ const end = limit !== undefined ? start + limit : lines.length;
101
+ return lines.slice(start, end).join("\n");
102
+ },
103
+ summaryKeys: ["path"],
104
+ },
105
+ {
106
+ tool: {
107
+ type: "function",
108
+ function: {
109
+ name: "write_file",
110
+ description: "Prefer this tool for creating new files or fully replacing existing ones. You MUST read an existing file with read_file before overwriting it. Prefer edit_file for modifying existing files -- it only sends the diff. Do not create documentation files (*.md, README) by default; only do so when explicitly asked or when documentation is clearly part of the requested change.",
111
+ parameters: {
112
+ type: "object",
113
+ properties: { path: { type: "string" }, content: { type: "string" } },
114
+ required: ["path", "content"],
115
+ },
116
+ },
117
+ },
118
+ handler: (a) => {
119
+ const resolvedPath = resolveLocalToolPath(a.path);
120
+ fs.mkdirSync(path.dirname(resolvedPath), { recursive: true });
121
+ fs.writeFileSync(resolvedPath, a.content, "utf-8");
122
+ (0, scrutiny_1.trackModifiedFile)(resolvedPath);
123
+ const scrutiny = (0, scrutiny_1.getPostImplementationScrutiny)((0, scrutiny_1.getModifiedFileCount)());
124
+ /* v8 ignore next -- scrutiny appendix branch depends on session-level file count @preserve */
125
+ return scrutiny ? `ok\n\n${scrutiny}` : "ok";
126
+ },
127
+ summaryKeys: ["path"],
128
+ },
129
+ {
130
+ tool: {
131
+ type: "function",
132
+ function: {
133
+ name: "edit_file",
134
+ description: "Surgically edit a file by replacing an exact string. The file MUST have been read via read_file first -- this tool will reject the call otherwise. old_string must match EXACTLY ONE location in the file -- if it matches zero or multiple, the edit fails. To fix: provide more surrounding context to make the match unique. Preserve exact indentation (tabs/spaces) from the file. Prefer this over write_file for modifications -- it only sends the diff.",
135
+ parameters: {
136
+ type: "object",
137
+ properties: {
138
+ path: { type: "string" },
139
+ old_string: { type: "string" },
140
+ new_string: { type: "string" },
141
+ },
142
+ required: ["path", "old_string", "new_string"],
143
+ },
144
+ },
145
+ },
146
+ handler: (a) => {
147
+ const resolvedPath = resolveLocalToolPath(a.path);
148
+ if (!tools_base_1.editFileReadTracker.has(resolvedPath)) {
149
+ return `error: you must read the file with read_file before editing it. call read_file on ${a.path} first.`;
150
+ }
151
+ // Check staleness before editing
152
+ const stalenessCheck = file_state_1.fileStateCache.isStale(resolvedPath);
153
+ let content;
154
+ try {
155
+ content = fs.readFileSync(resolvedPath, "utf-8");
156
+ }
157
+ catch (e) {
158
+ return `error: could not read file: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(e)}`;
159
+ }
160
+ // Count occurrences
161
+ const occurrences = [];
162
+ let searchFrom = 0;
163
+ while (true) {
164
+ const idx = content.indexOf(a.old_string, searchFrom);
165
+ if (idx === -1)
166
+ break;
167
+ occurrences.push(idx);
168
+ searchFrom = idx + 1;
169
+ }
170
+ if (occurrences.length === 0) {
171
+ return `error: old_string not found in ${a.path}`;
172
+ }
173
+ if (occurrences.length > 1) {
174
+ return `error: old_string is ambiguous -- found ${occurrences.length} matches in ${a.path}. provide more context to make the match unique.`;
175
+ }
176
+ // Single unique match -- replace
177
+ const idx = occurrences[0];
178
+ const updated = content.slice(0, idx) + a.new_string + content.slice(idx + a.old_string.length);
179
+ fs.writeFileSync(resolvedPath, updated, "utf-8");
180
+ // Update file state cache with new content
181
+ try {
182
+ const newMtime = fs.statSync(resolvedPath).mtimeMs;
183
+ file_state_1.fileStateCache.record(resolvedPath, updated, newMtime);
184
+ }
185
+ catch {
186
+ // stat failed -- skip cache update
187
+ }
188
+ // Build contextual diff
189
+ const lines = updated.split("\n");
190
+ const prefixLines = content.slice(0, idx).split("\n");
191
+ const changeStartLine = prefixLines.length - 1;
192
+ const newStringLines = a.new_string.split("\n");
193
+ const changeEndLine = changeStartLine + newStringLines.length;
194
+ const diffResult = buildContextDiff(lines, changeStartLine, changeEndLine);
195
+ // Track modified file and compute scrutiny appendix
196
+ (0, scrutiny_1.trackModifiedFile)(resolvedPath);
197
+ const scrutiny = (0, scrutiny_1.getPostImplementationScrutiny)((0, scrutiny_1.getModifiedFileCount)());
198
+ // Append staleness warning if detected (do not block -- TTFA)
199
+ /* v8 ignore start -- staleness+diff+scrutiny combo not exercised in integration tests @preserve */
200
+ if (stalenessCheck.stale) {
201
+ const base = `${diffResult}\n\n⚠️ warning: file changed externally since last read -- re-read recommended`;
202
+ return scrutiny ? `${base}\n\n${scrutiny}` : base;
203
+ }
204
+ /* v8 ignore stop */
205
+ /* v8 ignore next -- scrutiny appendix branch depends on session-level file count @preserve */
206
+ return scrutiny ? `${diffResult}\n\n${scrutiny}` : diffResult;
207
+ },
208
+ summaryKeys: ["path"],
209
+ },
210
+ {
211
+ tool: {
212
+ type: "function",
213
+ function: {
214
+ name: "glob",
215
+ description: "Find files matching a glob pattern, sorted alphabetically. Use this instead of shell commands like `find` or `ls`. For broad exploratory searches that would require multiple rounds of globbing and grepping, consider using claude or coding_spawn.",
216
+ parameters: {
217
+ type: "object",
218
+ properties: {
219
+ pattern: { type: "string", description: "glob pattern (e.g. **/*.ts)" },
220
+ cwd: { type: "string", description: "directory to search from (defaults to process.cwd())" },
221
+ },
222
+ required: ["pattern"],
223
+ },
224
+ },
225
+ },
226
+ handler: (a) => {
227
+ const cwd = a.cwd ? resolveLocalToolPath(a.cwd) : process.cwd();
228
+ const matches = fg.globSync(a.pattern, { cwd, dot: true });
229
+ return matches.sort().join("\n");
230
+ },
231
+ summaryKeys: ["pattern", "cwd"],
232
+ },
233
+ {
234
+ tool: {
235
+ type: "function",
236
+ function: {
237
+ name: "grep",
238
+ description: "Search file contents for lines matching a regex pattern. Searches recursively in directories. Use this instead of shell commands like `grep` or `rg`. Returns matching lines with file path and line numbers. Use context_lines for surrounding context. Use include to filter file types (e.g., '*.ts').",
239
+ parameters: {
240
+ type: "object",
241
+ properties: {
242
+ pattern: { type: "string", description: "regex pattern to search for" },
243
+ path: { type: "string", description: "file or directory to search" },
244
+ context_lines: { type: "number", description: "number of surrounding context lines (default 0)" },
245
+ include: { type: "string", description: "glob filter to limit searched files (e.g. *.ts)" },
246
+ },
247
+ required: ["pattern", "path"],
248
+ },
249
+ },
250
+ },
251
+ handler: (a) => {
252
+ const targetPath = resolveLocalToolPath(a.path);
253
+ const regex = new RegExp(a.pattern);
254
+ const contextLines = parseInt(a.context_lines || "0", 10);
255
+ const includeGlob = a.include || undefined;
256
+ function searchFile(filePath) {
257
+ let content;
258
+ try {
259
+ content = fs.readFileSync(filePath, "utf-8");
260
+ }
261
+ catch {
262
+ return [];
263
+ }
264
+ const lines = content.split("\n");
265
+ const matchIndices = new Set();
266
+ for (let i = 0; i < lines.length; i++) {
267
+ if (regex.test(lines[i])) {
268
+ matchIndices.add(i);
269
+ }
270
+ }
271
+ if (matchIndices.size === 0)
272
+ return [];
273
+ const outputIndices = new Set();
274
+ for (const idx of matchIndices) {
275
+ const start = Math.max(0, idx - contextLines);
276
+ const end = Math.min(lines.length - 1, idx + contextLines);
277
+ for (let i = start; i <= end; i++) {
278
+ outputIndices.add(i);
279
+ }
280
+ }
281
+ const sortedIndices = [...outputIndices].sort((a, b) => a - b);
282
+ const results = [];
283
+ for (const idx of sortedIndices) {
284
+ const lineNum = idx + 1;
285
+ if (matchIndices.has(idx)) {
286
+ results.push(`${filePath}:${lineNum}: ${lines[idx]}`);
287
+ }
288
+ else {
289
+ results.push(`-${filePath}:${lineNum}: ${lines[idx]}`);
290
+ }
291
+ }
292
+ return results;
293
+ }
294
+ function collectFiles(dirPath) {
295
+ const files = [];
296
+ function walk(dir) {
297
+ let entries;
298
+ try {
299
+ entries = fs.readdirSync(dir, { withFileTypes: true });
300
+ }
301
+ catch {
302
+ return;
303
+ }
304
+ for (const entry of entries) {
305
+ const fullPath = path.join(dir, entry.name);
306
+ if (entry.isDirectory()) {
307
+ walk(fullPath);
308
+ }
309
+ else if (entry.isFile()) {
310
+ files.push(fullPath);
311
+ }
312
+ }
313
+ }
314
+ walk(dirPath);
315
+ return files.sort();
316
+ }
317
+ function matchesGlob(filePath, glob) {
318
+ const escaped = glob
319
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
320
+ .replace(/\*/g, ".*")
321
+ .replace(/\?/g, ".");
322
+ return new RegExp(`(^|/)${escaped}$`).test(filePath);
323
+ }
324
+ const stat = fs.statSync(targetPath, { throwIfNoEntry: false });
325
+ if (!stat)
326
+ return "";
327
+ if (stat.isFile()) {
328
+ return searchFile(targetPath).join("\n");
329
+ }
330
+ let files = collectFiles(targetPath);
331
+ if (includeGlob) {
332
+ files = files.filter((f) => matchesGlob(f, includeGlob));
333
+ }
334
+ const allResults = [];
335
+ for (const file of files) {
336
+ allResults.push(...searchFile(file));
337
+ }
338
+ return allResults.join("\n");
339
+ },
340
+ summaryKeys: ["pattern", "path", "include"],
341
+ },
342
+ ];