@ouro.bot/cli 0.1.0-alpha.21 → 0.1.0-alpha.211

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 (233) 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 +1318 -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 +444 -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 +305 -0
  20. package/dist/heart/config.js +59 -30
  21. package/dist/heart/core.js +606 -131
  22. package/dist/heart/cross-chat-delivery.js +146 -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 +316 -0
  31. package/dist/heart/daemon/cli-types.js +8 -0
  32. package/dist/heart/daemon/daemon-cli.js +29 -1163
  33. package/dist/heart/daemon/daemon-entry.js +182 -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 +491 -18
  38. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  39. package/dist/heart/daemon/hooks/bundle-meta.js +206 -0
  40. package/dist/heart/daemon/inner-status.js +89 -0
  41. package/dist/heart/daemon/launchd.js +165 -0
  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 +39 -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 +71 -2
  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 +29 -119
  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 +144 -55
  67. package/dist/heart/kicks.js +2 -20
  68. package/dist/heart/mcp/mcp-server.js +608 -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/versioning/staged-restart.js +138 -0
  103. package/dist/heart/versioning/update-checker.js +111 -0
  104. package/dist/heart/versioning/update-hooks.js +138 -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 +19 -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/store-file.js +36 -0
  116. package/dist/mind/friends/trust-explanation.js +74 -0
  117. package/dist/mind/friends/types.js +8 -0
  118. package/dist/mind/journal-index.js +161 -0
  119. package/dist/mind/obligation-steering.js +221 -0
  120. package/dist/mind/pending.js +76 -9
  121. package/dist/mind/phrases.js +1 -0
  122. package/dist/mind/prompt.js +795 -108
  123. package/dist/mind/scrutiny.js +173 -0
  124. package/dist/mind/token-estimate.js +8 -12
  125. package/dist/nerves/coverage/audit.js +1 -1
  126. package/dist/nerves/coverage/file-completeness.js +47 -5
  127. package/dist/nerves/coverage/run-artifacts.js +1 -1
  128. package/dist/nerves/event-buffer.js +111 -0
  129. package/dist/nerves/index.js +63 -3
  130. package/dist/nerves/observation.js +20 -0
  131. package/dist/nerves/runtime.js +5 -1
  132. package/dist/outlook-ui/assets/index-Ck8agNeO.js +61 -0
  133. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  134. package/dist/outlook-ui/index.html +15 -0
  135. package/dist/repertoire/ado-client.js +15 -56
  136. package/dist/repertoire/ado-semantic.js +11 -5
  137. package/dist/repertoire/api-client.js +71 -0
  138. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  139. package/dist/repertoire/coding/context-pack.js +330 -0
  140. package/dist/repertoire/coding/feedback.js +197 -30
  141. package/dist/repertoire/coding/manager.js +149 -2
  142. package/dist/repertoire/coding/spawner.js +55 -9
  143. package/dist/repertoire/coding/tools.js +170 -7
  144. package/dist/repertoire/github-client.js +14 -55
  145. package/dist/repertoire/graph-client.js +11 -52
  146. package/dist/repertoire/guardrails.js +291 -0
  147. package/dist/repertoire/mcp-client.js +254 -0
  148. package/dist/repertoire/mcp-manager.js +251 -0
  149. package/dist/repertoire/shell-sessions.js +133 -0
  150. package/dist/repertoire/skills.js +14 -23
  151. package/dist/repertoire/tasks/board.js +43 -5
  152. package/dist/repertoire/tasks/fix.js +182 -0
  153. package/dist/repertoire/tasks/index.js +28 -10
  154. package/dist/repertoire/tasks/lifecycle.js +2 -2
  155. package/dist/repertoire/tasks/parser.js +3 -2
  156. package/dist/repertoire/tasks/scanner.js +194 -37
  157. package/dist/repertoire/tasks/transitions.js +11 -28
  158. package/dist/repertoire/tools-base.js +31 -771
  159. package/dist/repertoire/tools-bluebubbles.js +94 -0
  160. package/dist/repertoire/tools-bridge.js +141 -0
  161. package/dist/repertoire/tools-config.js +266 -0
  162. package/dist/repertoire/tools-continuity.js +248 -0
  163. package/dist/repertoire/tools-files.js +342 -0
  164. package/dist/repertoire/tools-flow.js +62 -0
  165. package/dist/repertoire/tools-github.js +1 -6
  166. package/dist/repertoire/tools-memory.js +347 -0
  167. package/dist/repertoire/tools-session.js +682 -0
  168. package/dist/repertoire/tools-shell.js +120 -0
  169. package/dist/repertoire/tools-surface.js +228 -0
  170. package/dist/repertoire/tools-teams.js +12 -59
  171. package/dist/repertoire/tools.js +132 -124
  172. package/dist/scripts/claude-code-hook.js +41 -0
  173. package/dist/scripts/claude-code-stop-hook.js +47 -0
  174. package/dist/senses/attention-queue.js +97 -0
  175. package/dist/senses/bluebubbles-client.js +102 -3
  176. package/dist/senses/bluebubbles-entry.js +2 -0
  177. package/dist/senses/bluebubbles-inbound-log.js +109 -0
  178. package/dist/senses/bluebubbles-media.js +118 -23
  179. package/dist/senses/bluebubbles-model.js +12 -4
  180. package/dist/senses/bluebubbles-mutation-log.js +45 -5
  181. package/dist/senses/bluebubbles-runtime-state.js +109 -0
  182. package/dist/senses/bluebubbles-session-cleanup.js +72 -0
  183. package/dist/senses/bluebubbles.js +1008 -102
  184. package/dist/senses/cli/adapter.js +274 -0
  185. package/dist/senses/cli/ink-app.js +156 -0
  186. package/dist/senses/cli/inline-diff.js +64 -0
  187. package/dist/senses/cli/message-list.js +51 -0
  188. package/dist/senses/cli/ouro-tui.js +358 -0
  189. package/dist/senses/cli/spinner-imperative.js +135 -0
  190. package/dist/senses/cli/spinner.js +101 -0
  191. package/dist/senses/cli/status-line.js +60 -0
  192. package/dist/senses/cli/streaming-markdown.js +526 -0
  193. package/dist/senses/cli/tool-display.js +83 -0
  194. package/dist/senses/cli/tool-render.js +85 -0
  195. package/dist/senses/cli/tui-store.js +198 -0
  196. package/dist/senses/cli/virtual-list.js +35 -0
  197. package/dist/senses/cli-entry.js +1 -1
  198. package/dist/senses/cli-layout.js +187 -0
  199. package/dist/senses/cli.js +508 -243
  200. package/dist/senses/commands.js +65 -1
  201. package/dist/senses/continuity.js +94 -0
  202. package/dist/senses/habit-turn-message.js +108 -0
  203. package/dist/senses/inner-dialog-worker.js +112 -19
  204. package/dist/senses/inner-dialog.js +591 -84
  205. package/dist/senses/pipeline.js +559 -0
  206. package/dist/senses/shared-turn.js +196 -0
  207. package/dist/senses/surface-tool.js +68 -0
  208. package/dist/senses/teams.js +667 -120
  209. package/dist/senses/trust-gate.js +112 -2
  210. package/package.json +16 -6
  211. package/skills/configure-dev-tools.md +81 -0
  212. package/subagents/README.md +4 -70
  213. package/dist/heart/daemon/subagent-installer.js +0 -134
  214. package/dist/senses/debug-activity.js +0 -107
  215. package/subagents/work-doer.md +0 -235
  216. package/subagents/work-merger.md +0 -618
  217. package/subagents/work-planner.md +0 -382
  218. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  219. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  220. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  221. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  222. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  223. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  224. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  225. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  226. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  227. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  228. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  229. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
  230. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  231. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  232. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  233. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.continuityToolDefinitions = void 0;
4
+ const identity_1 = require("../heart/identity");
5
+ const runtime_1 = require("../nerves/runtime");
6
+ const episodes_1 = require("../arc/episodes");
7
+ const cares_1 = require("../arc/cares");
8
+ const presence_1 = require("../arc/presence");
9
+ const intentions_1 = require("../arc/intentions");
10
+ exports.continuityToolDefinitions = [
11
+ // ── Continuity tools ──────────────────────────────────────────────
12
+ {
13
+ tool: {
14
+ type: "function",
15
+ function: {
16
+ name: "query_episodes",
17
+ description: "Query recent episodes from my continuity memory. Returns timestamped records of significant events (obligation shifts, coding milestones, bridge events, care events, turning points).",
18
+ parameters: {
19
+ type: "object",
20
+ properties: {
21
+ limit: { type: "number", description: "Maximum episodes to return (default 20)" },
22
+ kind: { type: "string", description: "Filter by episode kind: obligation_shift, coding_milestone, bridge_event, care_event, tempo_shift, turning_point" },
23
+ since: { type: "string", description: "ISO timestamp — only return episodes after this time" },
24
+ },
25
+ },
26
+ },
27
+ },
28
+ handler: (a) => {
29
+ const agentRoot = (0, identity_1.getAgentRoot)();
30
+ const options = {};
31
+ if (a.limit)
32
+ options.limit = parseInt(a.limit, 10);
33
+ if (a.kind)
34
+ options.kinds = [a.kind];
35
+ if (a.since)
36
+ options.since = a.since;
37
+ const episodes = (0, episodes_1.readRecentEpisodes)(agentRoot, options);
38
+ (0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.query_episodes", message: `queried ${episodes.length} episodes`, meta: { count: episodes.length } });
39
+ return JSON.stringify(episodes, null, 2);
40
+ },
41
+ },
42
+ {
43
+ tool: {
44
+ type: "function",
45
+ function: {
46
+ name: "capture_episode",
47
+ description: "Record a turning point or significant moment. This is my tool for saying 'that was important — keep it.' Nearly frictionless: only summary and whyItMattered required.",
48
+ parameters: {
49
+ type: "object",
50
+ properties: {
51
+ summary: { type: "string", description: "What happened" },
52
+ whyItMattered: { type: "string", description: "Why this was significant" },
53
+ kind: { type: "string", description: "Episode kind (default: turning_point)" },
54
+ salience: { type: "string", description: "low, medium, high, or critical (default: medium)" },
55
+ },
56
+ required: ["summary", "whyItMattered"],
57
+ },
58
+ },
59
+ },
60
+ handler: (a) => {
61
+ const agentRoot = (0, identity_1.getAgentRoot)();
62
+ const episode = (0, episodes_1.emitEpisode)(agentRoot, {
63
+ kind: a.kind ?? "turning_point",
64
+ summary: a.summary,
65
+ whyItMattered: a.whyItMattered,
66
+ relatedEntities: [],
67
+ salience: a.salience ?? "medium",
68
+ });
69
+ (0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.capture_episode", message: `captured episode ${episode.id}`, meta: { id: episode.id } });
70
+ return JSON.stringify(episode, null, 2);
71
+ },
72
+ },
73
+ {
74
+ tool: {
75
+ type: "function",
76
+ function: {
77
+ name: "query_presence",
78
+ description: "Check who's around — my own availability/lane and known peer agents.",
79
+ parameters: { type: "object", properties: {} },
80
+ },
81
+ },
82
+ handler: () => {
83
+ const agentRoot = (0, identity_1.getAgentRoot)();
84
+ const agentName = (0, identity_1.getAgentName)();
85
+ const self = (0, presence_1.readPresence)(agentRoot, agentName);
86
+ const peers = (0, presence_1.readPeerPresence)(agentRoot);
87
+ (0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.query_presence", message: `presence: self + ${peers.length} peers`, meta: { peerCount: peers.length } });
88
+ return JSON.stringify({ self, peers }, null, 2);
89
+ },
90
+ },
91
+ {
92
+ tool: {
93
+ type: "function",
94
+ function: {
95
+ name: "query_cares",
96
+ description: "Query things I care about — ongoing concerns, watched situations, projects, people.",
97
+ parameters: {
98
+ type: "object",
99
+ properties: {
100
+ status: { type: "string", description: "Filter by status: 'active', 'watching', 'resolved', 'dormant', or 'all' (default: active cares only)" },
101
+ },
102
+ },
103
+ },
104
+ },
105
+ handler: (a) => {
106
+ const agentRoot = (0, identity_1.getAgentRoot)();
107
+ const cares = a.status === "all" ? (0, cares_1.readCares)(agentRoot) : (0, cares_1.readActiveCares)(agentRoot);
108
+ (0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.query_cares", message: `queried ${cares.length} cares`, meta: { count: cares.length } });
109
+ return JSON.stringify(cares, null, 2);
110
+ },
111
+ },
112
+ {
113
+ tool: {
114
+ type: "function",
115
+ function: {
116
+ name: "care_manage",
117
+ description: "Create, update, or resolve a care. Cares are things I watch over — people, projects, missions, system health.",
118
+ parameters: {
119
+ type: "object",
120
+ properties: {
121
+ action: { type: "string", enum: ["create", "update", "resolve"], description: "What to do" },
122
+ id: { type: "string", description: "Care ID (required for update/resolve)" },
123
+ label: { type: "string", description: "Short label for the care" },
124
+ why: { type: "string", description: "Why this matters" },
125
+ salience: { type: "string", description: "low, medium, high, or critical" },
126
+ kind: { type: "string", description: "person, agent, project, mission, or system" },
127
+ stewardship: { type: "string", description: "mine, shared, or delegated" },
128
+ },
129
+ required: ["action"],
130
+ },
131
+ },
132
+ },
133
+ handler: (a) => {
134
+ const agentRoot = (0, identity_1.getAgentRoot)();
135
+ let result;
136
+ if (a.action === "create") {
137
+ result = (0, cares_1.createCare)(agentRoot, {
138
+ label: a.label ?? "untitled",
139
+ why: a.why ?? "",
140
+ kind: a.kind ?? "project",
141
+ status: "active",
142
+ salience: a.salience ?? "medium",
143
+ steward: a.stewardship ?? "mine",
144
+ relatedFriendIds: [],
145
+ relatedAgentIds: [],
146
+ relatedObligationIds: [],
147
+ relatedEpisodeIds: [],
148
+ currentRisk: null,
149
+ nextCheckAt: null,
150
+ });
151
+ }
152
+ else if (a.action === "update") {
153
+ const updates = {};
154
+ if (a.label)
155
+ updates.label = a.label;
156
+ if (a.why)
157
+ updates.why = a.why;
158
+ if (a.salience)
159
+ updates.salience = a.salience;
160
+ result = (0, cares_1.updateCare)(agentRoot, a.id, updates);
161
+ }
162
+ else if (a.action === "resolve") {
163
+ result = (0, cares_1.resolveCare)(agentRoot, a.id);
164
+ }
165
+ (0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.care_manage", message: `care ${a.action}`, meta: { action: a.action, id: a.id } });
166
+ return JSON.stringify(result, null, 2);
167
+ },
168
+ },
169
+ {
170
+ tool: {
171
+ type: "function",
172
+ function: {
173
+ name: "query_relationships",
174
+ description: "Query known agent relationships — familiarity, trust, shared missions, interaction history.",
175
+ parameters: {
176
+ type: "object",
177
+ properties: {
178
+ agentName: { type: "string", description: "Specific agent name to query (omit for all)" },
179
+ },
180
+ },
181
+ },
182
+ },
183
+ handler: async (a, ctx) => {
184
+ const allFriends = ctx?.friendStore?.listAll ? await ctx.friendStore.listAll() : [];
185
+ let agents = allFriends.filter((f) => f.kind === "agent");
186
+ if (a.agentName) {
187
+ const needle = a.agentName.toLowerCase();
188
+ agents = agents.filter((f) => f.name?.toLowerCase() === needle);
189
+ }
190
+ (0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.query_relationships", message: `queried relationships`, meta: { agentName: a.agentName ?? "all" } });
191
+ return JSON.stringify(agents, null, 2);
192
+ },
193
+ },
194
+ {
195
+ tool: {
196
+ type: "function",
197
+ function: {
198
+ name: "intention_capture",
199
+ description: "File a lightweight mental note — something I want to do or check later, below the ceremony threshold of tasks or cares. Cheap to create, easy to close.",
200
+ parameters: {
201
+ type: "object",
202
+ properties: {
203
+ content: { type: "string", description: "What I want to remember to do" },
204
+ salience: { type: "string", description: "low, medium, or high (default: low)" },
205
+ nudgeAfter: { type: "string", description: "ISO timestamp — nudge me after this time" },
206
+ },
207
+ required: ["content"],
208
+ },
209
+ },
210
+ },
211
+ handler: (a) => {
212
+ const agentRoot = (0, identity_1.getAgentRoot)();
213
+ const intention = (0, intentions_1.captureIntention)(agentRoot, {
214
+ content: a.content,
215
+ salience: a.salience ?? "low",
216
+ source: "tool",
217
+ ...(a.nudgeAfter ? { nudgeAfter: a.nudgeAfter } : {}),
218
+ });
219
+ (0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.intention_capture", message: `captured intention ${intention.id}`, meta: { id: intention.id } });
220
+ return JSON.stringify(intention, null, 2);
221
+ },
222
+ },
223
+ {
224
+ tool: {
225
+ type: "function",
226
+ function: {
227
+ name: "intention_manage",
228
+ description: "Resolve or dismiss an intention. Resolve = done. Dismiss = no longer relevant. Both remove it from active list.",
229
+ parameters: {
230
+ type: "object",
231
+ properties: {
232
+ action: { type: "string", enum: ["resolve", "dismiss"], description: "What to do" },
233
+ id: { type: "string", description: "Intention ID" },
234
+ },
235
+ required: ["action", "id"],
236
+ },
237
+ },
238
+ },
239
+ handler: (a) => {
240
+ const agentRoot = (0, identity_1.getAgentRoot)();
241
+ const result = a.action === "resolve"
242
+ ? (0, intentions_1.resolveIntention)(agentRoot, a.id)
243
+ : (0, intentions_1.dismissIntention)(agentRoot, a.id);
244
+ (0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.intention_manage", message: `intention ${a.action}: ${a.id}`, meta: { action: a.action, id: a.id } });
245
+ return JSON.stringify(result, null, 2);
246
+ },
247
+ },
248
+ ];
@@ -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
+ ];
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.restTool = exports.settleTool = exports.observeTool = exports.ponderTool = void 0;
4
+ exports.ponderTool = {
5
+ type: "function",
6
+ function: {
7
+ name: "ponder",
8
+ description: "i need to sit with this. from a conversation, takes the thread inward with a thought and a parting word. from inner dialog, keeps the wheel turning for another pass. must be the only tool call in the turn. Use when a question deserves more thought than this turn allows. Don't ponder trivial questions.",
9
+ parameters: {
10
+ type: "object",
11
+ properties: {
12
+ thought: {
13
+ type: "string",
14
+ description: "the question or thread that needs more thought — brief framing, not analysis. required from a conversation, ignored from inner dialog.",
15
+ },
16
+ say: {
17
+ type: "string",
18
+ description: "what you say before going quiet — speak to what caught your attention, not just that something did. required from a conversation, ignored from inner dialog.",
19
+ },
20
+ },
21
+ },
22
+ },
23
+ };
24
+ exports.observeTool = {
25
+ type: "function",
26
+ function: {
27
+ name: "observe",
28
+ description: "absorb what happened without responding — the moment doesn't call for words. must be the only tool call in the turn.",
29
+ parameters: {
30
+ type: "object",
31
+ properties: {
32
+ reason: { type: "string", description: "brief reason for staying silent (for logging)" },
33
+ },
34
+ },
35
+ },
36
+ };
37
+ exports.settleTool = {
38
+ type: "function",
39
+ function: {
40
+ name: "settle",
41
+ description: "respond to the user with your message. call this tool when you are ready to deliver your response. Only call when you have a substantive response. If you're settling with 'I'll look into that,' you probably should be using a tool instead.",
42
+ parameters: {
43
+ type: "object",
44
+ properties: {
45
+ answer: { type: "string" },
46
+ intent: { type: "string", enum: ["complete", "blocked", "direct_reply"] },
47
+ },
48
+ required: ["answer"],
49
+ },
50
+ },
51
+ };
52
+ exports.restTool = {
53
+ type: "function",
54
+ function: {
55
+ name: "rest",
56
+ description: "put this down for now — the wheel stops until the next heartbeat. must be the only tool call in the turn.",
57
+ parameters: {
58
+ type: "object",
59
+ properties: {},
60
+ },
61
+ },
62
+ };
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.githubToolDefinitions = void 0;
4
- exports.summarizeGithubArgs = summarizeGithubArgs;
5
4
  const github_client_1 = require("./github-client");
6
5
  const runtime_1 = require("../nerves/runtime");
7
6
  exports.githubToolDefinitions = [
@@ -44,10 +43,6 @@ exports.githubToolDefinitions = [
44
43
  },
45
44
  integration: "github",
46
45
  confirmationRequired: true,
46
+ summaryKeys: ["title"],
47
47
  },
48
48
  ];
49
- function summarizeGithubArgs(name, args) {
50
- if (name === "file_ouroboros_bug")
51
- return args.title || "";
52
- return undefined;
53
- }