@ouro.bot/cli 0.1.0-alpha.27 → 0.1.0-alpha.271

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 (265) 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 +1637 -0
  5. package/dist/arc/attention-types.js +8 -0
  6. package/dist/arc/cares.js +140 -0
  7. package/dist/arc/episodes.js +117 -0
  8. package/dist/arc/intentions.js +133 -0
  9. package/dist/arc/json-store.js +117 -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 +644 -196
  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 +79 -3
  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 +1877 -0
  29. package/dist/heart/daemon/cli-parse.js +759 -0
  30. package/dist/heart/daemon/cli-render.js +503 -0
  31. package/dist/heart/daemon/cli-types.js +8 -0
  32. package/dist/heart/daemon/daemon-cli.js +29 -1155
  33. package/dist/heart/daemon/daemon-entry.js +214 -3
  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 +236 -0
  37. package/dist/heart/daemon/daemon.js +664 -57
  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 +307 -0
  56. package/dist/heart/daemon/task-scheduler.js +3 -25
  57. package/dist/heart/daemon/thoughts.js +510 -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 +371 -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 +160 -58
  67. package/dist/heart/kicks.js +2 -20
  68. package/dist/heart/mcp/mcp-server.js +653 -0
  69. package/dist/heart/migrate-config.js +127 -0
  70. package/dist/heart/model-capabilities.js +59 -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 +169 -46
  81. package/dist/heart/providers/azure.js +98 -11
  82. package/dist/heart/providers/error-classification.js +63 -0
  83. package/dist/heart/providers/github-copilot.js +136 -0
  84. package/dist/heart/providers/minimax-vlm.js +189 -0
  85. package/dist/heart/providers/minimax.js +23 -5
  86. package/dist/heart/providers/openai-codex.js +33 -22
  87. package/dist/heart/session-activity.js +172 -0
  88. package/dist/heart/session-recall.js +216 -0
  89. package/dist/heart/start-of-turn-packet.js +330 -0
  90. package/dist/heart/streaming.js +36 -27
  91. package/dist/heart/sync.js +277 -0
  92. package/dist/heart/target-resolution.js +127 -0
  93. package/dist/heart/tempo.js +93 -0
  94. package/dist/heart/temporal-view.js +41 -0
  95. package/dist/heart/tool-activity-callbacks.js +36 -0
  96. package/dist/heart/tool-description.js +135 -0
  97. package/dist/heart/tool-loop.js +200 -0
  98. package/dist/heart/turn-context.js +358 -0
  99. package/dist/heart/turn-coordinator.js +28 -0
  100. package/dist/heart/versioning/ouro-bot-global-installer.js +128 -0
  101. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  102. package/dist/heart/{daemon → versioning}/ouro-path-installer.js +78 -35
  103. package/dist/heart/versioning/ouro-version-manager.js +171 -0
  104. package/dist/heart/{daemon → versioning}/staged-restart.js +30 -6
  105. package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
  106. package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +41 -3
  107. package/dist/mind/associative-recall.js +126 -66
  108. package/dist/mind/bundle-manifest.js +8 -1
  109. package/dist/mind/context.js +125 -14
  110. package/dist/mind/{memory.js → diary.js} +68 -96
  111. package/dist/mind/embedding-provider.js +60 -0
  112. package/dist/mind/file-state.js +179 -0
  113. package/dist/mind/first-impressions.js +16 -2
  114. package/dist/mind/friends/channel.js +56 -0
  115. package/dist/mind/friends/group-context.js +144 -0
  116. package/dist/mind/friends/resolver.js +37 -0
  117. package/dist/mind/friends/store-file.js +58 -3
  118. package/dist/mind/friends/trust-explanation.js +74 -0
  119. package/dist/mind/friends/types.js +8 -0
  120. package/dist/mind/journal-index.js +161 -0
  121. package/dist/mind/obligation-steering.js +221 -0
  122. package/dist/mind/pending.js +76 -9
  123. package/dist/mind/prompt.js +777 -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 +305 -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 +201 -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 +155 -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/attachment-cache.js +53 -0
  194. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +145 -10
  195. package/dist/senses/bluebubbles/entry.js +13 -0
  196. package/dist/senses/bluebubbles/inbound-log.js +110 -0
  197. package/dist/senses/bluebubbles/index.js +1410 -0
  198. package/dist/senses/bluebubbles/media.js +455 -0
  199. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +20 -5
  200. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  201. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  202. package/dist/senses/bluebubbles/session-cleanup.js +72 -0
  203. package/dist/senses/cli/bracketed-paste.js +82 -0
  204. package/dist/senses/cli/image-paste.js +211 -0
  205. package/dist/senses/cli/image-ref-navigation.js +75 -0
  206. package/dist/senses/cli/ink-app.js +156 -0
  207. package/dist/senses/cli/inline-diff.js +64 -0
  208. package/dist/senses/cli/input-keys.js +174 -0
  209. package/dist/senses/cli/kill-ring.js +86 -0
  210. package/dist/senses/cli/message-list.js +51 -0
  211. package/dist/senses/cli/ouro-tui.js +578 -0
  212. package/dist/senses/cli/spinner-imperative.js +135 -0
  213. package/dist/senses/cli/spinner.js +101 -0
  214. package/dist/senses/cli/status-line.js +60 -0
  215. package/dist/senses/cli/streaming-markdown.js +526 -0
  216. package/dist/senses/cli/tool-display.js +83 -0
  217. package/dist/senses/cli/tool-render.js +85 -0
  218. package/dist/senses/cli/tui-store.js +240 -0
  219. package/dist/senses/cli/virtual-list.js +35 -0
  220. package/dist/senses/cli-entry.js +1 -1
  221. package/dist/senses/cli-layout.js +187 -0
  222. package/dist/senses/cli.js +569 -246
  223. package/dist/senses/commands.js +65 -1
  224. package/dist/senses/continuity.js +94 -0
  225. package/dist/senses/habit-turn-message.js +108 -0
  226. package/dist/senses/inner-dialog-worker.js +112 -19
  227. package/dist/senses/inner-dialog.js +593 -85
  228. package/dist/senses/pipeline.js +552 -0
  229. package/dist/senses/shared-turn.js +199 -0
  230. package/dist/senses/surface-tool.js +68 -0
  231. package/dist/senses/teams.js +664 -165
  232. package/dist/senses/trust-gate.js +112 -2
  233. package/package.json +14 -7
  234. package/skills/agent-commerce.md +106 -0
  235. package/skills/browser-navigation.md +110 -0
  236. package/skills/commerce-setup-guide.md +116 -0
  237. package/skills/commerce-setup.md +84 -0
  238. package/skills/configure-dev-tools.md +81 -0
  239. package/skills/travel-planning.md +138 -0
  240. package/dist/heart/daemon/subagent-installer.js +0 -134
  241. package/dist/senses/bluebubbles-entry.js +0 -11
  242. package/dist/senses/bluebubbles-media.js +0 -244
  243. package/dist/senses/bluebubbles.js +0 -421
  244. package/dist/senses/debug-activity.js +0 -108
  245. package/subagents/README.md +0 -73
  246. package/subagents/work-doer.md +0 -235
  247. package/subagents/work-merger.md +0 -618
  248. package/subagents/work-planner.md +0 -382
  249. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  250. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  251. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  252. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  253. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  254. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  255. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  256. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  257. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  258. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  259. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  260. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
  261. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  262. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  263. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  264. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  265. /package/dist/heart/{daemon → versioning}/update-hooks.js +0 -0
@@ -1,421 +0,0 @@
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.handleBlueBubblesEvent = handleBlueBubblesEvent;
37
- exports.createBlueBubblesWebhookHandler = createBlueBubblesWebhookHandler;
38
- exports.startBlueBubblesApp = startBlueBubblesApp;
39
- const http = __importStar(require("node:http"));
40
- const path = __importStar(require("node:path"));
41
- const core_1 = require("../heart/core");
42
- const config_1 = require("../heart/config");
43
- const identity_1 = require("../heart/identity");
44
- const context_1 = require("../mind/context");
45
- const tokens_1 = require("../mind/friends/tokens");
46
- const resolver_1 = require("../mind/friends/resolver");
47
- const store_file_1 = require("../mind/friends/store-file");
48
- const prompt_1 = require("../mind/prompt");
49
- const phrases_1 = require("../mind/phrases");
50
- const runtime_1 = require("../nerves/runtime");
51
- const bluebubbles_model_1 = require("./bluebubbles-model");
52
- const bluebubbles_client_1 = require("./bluebubbles-client");
53
- const bluebubbles_mutation_log_1 = require("./bluebubbles-mutation-log");
54
- const debug_activity_1 = require("./debug-activity");
55
- const defaultDeps = {
56
- getAgentName: identity_1.getAgentName,
57
- buildSystem: prompt_1.buildSystem,
58
- runAgent: core_1.runAgent,
59
- loadSession: context_1.loadSession,
60
- postTurn: context_1.postTurn,
61
- sessionPath: config_1.sessionPath,
62
- accumulateFriendTokens: tokens_1.accumulateFriendTokens,
63
- createClient: () => (0, bluebubbles_client_1.createBlueBubblesClient)(),
64
- recordMutation: bluebubbles_mutation_log_1.recordBlueBubblesMutation,
65
- createFriendStore: () => new store_file_1.FileFriendStore(path.join((0, identity_1.getAgentRoot)(), "friends")),
66
- createFriendResolver: (store, params) => new resolver_1.FriendResolver(store, params),
67
- createServer: http.createServer,
68
- };
69
- function resolveFriendParams(event) {
70
- if (event.chat.isGroup) {
71
- const groupKey = event.chat.chatGuid ?? event.chat.chatIdentifier ?? event.sender.externalId;
72
- return {
73
- provider: "imessage-handle",
74
- externalId: `group:${groupKey}`,
75
- displayName: event.chat.displayName ?? "Unknown Group",
76
- channel: "bluebubbles",
77
- };
78
- }
79
- return {
80
- provider: "imessage-handle",
81
- externalId: event.sender.externalId || event.sender.rawId,
82
- displayName: event.sender.displayName || "Unknown",
83
- channel: "bluebubbles",
84
- };
85
- }
86
- function buildInboundText(event) {
87
- const baseText = event.repairNotice?.trim()
88
- ? `${event.textForAgent}\n[${event.repairNotice.trim()}]`
89
- : event.textForAgent;
90
- if (!event.chat.isGroup)
91
- return baseText;
92
- if (event.kind === "mutation") {
93
- return `${event.sender.displayName} ${baseText}`;
94
- }
95
- return `${event.sender.displayName}: ${baseText}`;
96
- }
97
- function buildInboundContent(event) {
98
- const text = buildInboundText(event);
99
- if (event.kind !== "message" || !event.inputPartsForAgent || event.inputPartsForAgent.length === 0) {
100
- return text;
101
- }
102
- return [
103
- { type: "text", text },
104
- ...event.inputPartsForAgent,
105
- ];
106
- }
107
- function createBlueBubblesCallbacks(client, chat, replyToMessageGuid) {
108
- let textBuffer = "";
109
- const phrases = (0, phrases_1.getPhrases)();
110
- const activity = (0, debug_activity_1.createDebugActivityController)({
111
- thinkingPhrases: phrases.thinking,
112
- followupPhrases: phrases.followup,
113
- transport: {
114
- sendStatus: async (text) => {
115
- const sent = await client.sendText({
116
- chat,
117
- text,
118
- replyToMessageGuid,
119
- });
120
- return sent.messageGuid;
121
- },
122
- editStatus: async (_messageGuid, text) => {
123
- await client.sendText({
124
- chat,
125
- text,
126
- replyToMessageGuid,
127
- });
128
- },
129
- setTyping: async (active) => {
130
- await client.setTyping(chat, active);
131
- },
132
- },
133
- onTransportError: (operation, error) => {
134
- (0, runtime_1.emitNervesEvent)({
135
- level: "warn",
136
- component: "senses",
137
- event: "senses.bluebubbles_activity_error",
138
- message: "bluebubbles activity transport failed",
139
- meta: {
140
- operation,
141
- reason: error instanceof Error ? error.message : String(error),
142
- },
143
- });
144
- },
145
- });
146
- return {
147
- onModelStart() {
148
- activity.onModelStart();
149
- (0, runtime_1.emitNervesEvent)({
150
- component: "senses",
151
- event: "senses.bluebubbles_turn_start",
152
- message: "bluebubbles turn started",
153
- meta: { chatGuid: chat.chatGuid ?? null },
154
- });
155
- },
156
- onModelStreamStart() {
157
- (0, runtime_1.emitNervesEvent)({
158
- component: "senses",
159
- event: "senses.bluebubbles_stream_start",
160
- message: "bluebubbles non-streaming response started",
161
- meta: {},
162
- });
163
- },
164
- onTextChunk(text) {
165
- activity.onTextChunk(text);
166
- textBuffer += text;
167
- },
168
- onReasoningChunk(_text) { },
169
- onToolStart(name, _args) {
170
- activity.onToolStart(name, _args);
171
- (0, runtime_1.emitNervesEvent)({
172
- component: "senses",
173
- event: "senses.bluebubbles_tool_start",
174
- message: "bluebubbles tool execution started",
175
- meta: { name },
176
- });
177
- },
178
- onToolEnd(name, summary, success) {
179
- activity.onToolEnd(name, summary, success);
180
- (0, runtime_1.emitNervesEvent)({
181
- component: "senses",
182
- event: "senses.bluebubbles_tool_end",
183
- message: "bluebubbles tool execution completed",
184
- meta: { name, success, summary },
185
- });
186
- },
187
- onError(error, severity) {
188
- activity.onError(error);
189
- (0, runtime_1.emitNervesEvent)({
190
- level: severity === "terminal" ? "error" : "warn",
191
- component: "senses",
192
- event: "senses.bluebubbles_turn_error",
193
- message: "bluebubbles turn callback error",
194
- meta: { severity, reason: error.message },
195
- });
196
- },
197
- onClearText() {
198
- textBuffer = "";
199
- },
200
- async flush() {
201
- await activity.drain();
202
- const trimmed = textBuffer.trim();
203
- if (!trimmed) {
204
- await activity.finish();
205
- return;
206
- }
207
- textBuffer = "";
208
- await activity.finish();
209
- await client.sendText({
210
- chat,
211
- text: trimmed,
212
- replyToMessageGuid,
213
- });
214
- },
215
- async finish() {
216
- await activity.finish();
217
- },
218
- };
219
- }
220
- async function readRequestBody(req) {
221
- let body = "";
222
- for await (const chunk of req) {
223
- body += chunk.toString();
224
- }
225
- return body;
226
- }
227
- function writeJson(res, statusCode, payload) {
228
- res.statusCode = statusCode;
229
- res.setHeader("Content-Type", "application/json; charset=utf-8");
230
- res.end(JSON.stringify(payload));
231
- }
232
- function isWebhookPasswordValid(url, expectedPassword) {
233
- const provided = url.searchParams.get("password");
234
- return !provided || provided === expectedPassword;
235
- }
236
- async function handleBlueBubblesEvent(payload, deps = {}) {
237
- const resolvedDeps = { ...defaultDeps, ...deps };
238
- const client = resolvedDeps.createClient();
239
- const event = await client.repairEvent((0, bluebubbles_model_1.normalizeBlueBubblesEvent)(payload));
240
- if (event.fromMe) {
241
- (0, runtime_1.emitNervesEvent)({
242
- component: "senses",
243
- event: "senses.bluebubbles_from_me_ignored",
244
- message: "ignored from-me bluebubbles event",
245
- meta: {
246
- messageGuid: event.messageGuid,
247
- kind: event.kind,
248
- },
249
- });
250
- return { handled: true, notifiedAgent: false, kind: event.kind, reason: "from_me" };
251
- }
252
- if (event.kind === "mutation") {
253
- try {
254
- resolvedDeps.recordMutation(resolvedDeps.getAgentName(), event);
255
- }
256
- catch (error) {
257
- (0, runtime_1.emitNervesEvent)({
258
- level: "error",
259
- component: "senses",
260
- event: "senses.bluebubbles_mutation_log_error",
261
- message: "failed recording bluebubbles mutation sidecar",
262
- meta: {
263
- messageGuid: event.messageGuid,
264
- mutationType: event.mutationType,
265
- reason: error instanceof Error ? error.message : String(error),
266
- },
267
- });
268
- }
269
- }
270
- if (event.kind === "mutation" && !event.shouldNotifyAgent) {
271
- (0, runtime_1.emitNervesEvent)({
272
- component: "senses",
273
- event: "senses.bluebubbles_state_mutation_recorded",
274
- message: "recorded non-notify bluebubbles mutation",
275
- meta: {
276
- messageGuid: event.messageGuid,
277
- mutationType: event.mutationType,
278
- },
279
- });
280
- return { handled: true, notifiedAgent: false, kind: event.kind, reason: "mutation_state_only" };
281
- }
282
- const store = resolvedDeps.createFriendStore();
283
- const resolver = resolvedDeps.createFriendResolver(store, resolveFriendParams(event));
284
- const context = await resolver.resolve();
285
- const toolContext = {
286
- signin: async () => undefined,
287
- friendStore: store,
288
- summarize: (0, core_1.createSummarize)(),
289
- context,
290
- codingFeedback: {
291
- send: async (message) => {
292
- await client.sendText({
293
- chat: event.chat,
294
- text: message,
295
- replyToMessageGuid: event.kind === "message" ? event.messageGuid : undefined,
296
- });
297
- },
298
- },
299
- };
300
- const friendId = context.friend.id;
301
- const sessPath = resolvedDeps.sessionPath(friendId, "bluebubbles", event.chat.sessionKey);
302
- const existing = resolvedDeps.loadSession(sessPath);
303
- const messages = existing?.messages && existing.messages.length > 0
304
- ? existing.messages
305
- : [{ role: "system", content: await resolvedDeps.buildSystem("bluebubbles", undefined, context) }];
306
- messages.push({ role: "user", content: buildInboundContent(event) });
307
- const callbacks = createBlueBubblesCallbacks(client, event.chat, event.kind === "message" ? event.messageGuid : undefined);
308
- const controller = new AbortController();
309
- const agentOptions = {
310
- toolContext,
311
- };
312
- try {
313
- const result = await resolvedDeps.runAgent(messages, callbacks, "bluebubbles", controller.signal, agentOptions);
314
- await callbacks.flush();
315
- resolvedDeps.postTurn(messages, sessPath, result.usage);
316
- await resolvedDeps.accumulateFriendTokens(store, friendId, result.usage);
317
- try {
318
- await client.markChatRead(event.chat);
319
- }
320
- catch (error) {
321
- (0, runtime_1.emitNervesEvent)({
322
- level: "warn",
323
- component: "senses",
324
- event: "senses.bluebubbles_mark_read_error",
325
- message: "failed to mark bluebubbles chat as read",
326
- meta: {
327
- chatGuid: event.chat.chatGuid ?? null,
328
- reason: error instanceof Error ? error.message : String(error),
329
- },
330
- });
331
- }
332
- (0, runtime_1.emitNervesEvent)({
333
- component: "senses",
334
- event: "senses.bluebubbles_turn_end",
335
- message: "bluebubbles event handled",
336
- meta: {
337
- messageGuid: event.messageGuid,
338
- kind: event.kind,
339
- sessionKey: event.chat.sessionKey,
340
- },
341
- });
342
- return {
343
- handled: true,
344
- notifiedAgent: true,
345
- kind: event.kind,
346
- };
347
- }
348
- finally {
349
- await callbacks.finish();
350
- }
351
- }
352
- function createBlueBubblesWebhookHandler(deps = {}) {
353
- return async (req, res) => {
354
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
355
- const channelConfig = (0, config_1.getBlueBubblesChannelConfig)();
356
- const runtimeConfig = (0, config_1.getBlueBubblesConfig)();
357
- if (url.pathname !== channelConfig.webhookPath) {
358
- writeJson(res, 404, { error: "Not found" });
359
- return;
360
- }
361
- if (req.method !== "POST") {
362
- writeJson(res, 405, { error: "Method not allowed" });
363
- return;
364
- }
365
- if (!isWebhookPasswordValid(url, runtimeConfig.password)) {
366
- writeJson(res, 401, { error: "Unauthorized" });
367
- return;
368
- }
369
- let payload;
370
- try {
371
- const rawBody = await readRequestBody(req);
372
- payload = JSON.parse(rawBody);
373
- }
374
- catch (error) {
375
- (0, runtime_1.emitNervesEvent)({
376
- level: "warn",
377
- component: "senses",
378
- event: "senses.bluebubbles_webhook_bad_json",
379
- message: "failed to parse bluebubbles webhook body",
380
- meta: {
381
- reason: error instanceof Error ? error.message : String(error),
382
- },
383
- });
384
- writeJson(res, 400, { error: "Invalid JSON body" });
385
- return;
386
- }
387
- try {
388
- const result = await handleBlueBubblesEvent(payload, deps);
389
- writeJson(res, 200, result);
390
- }
391
- catch (error) {
392
- (0, runtime_1.emitNervesEvent)({
393
- level: "error",
394
- component: "senses",
395
- event: "senses.bluebubbles_webhook_error",
396
- message: "bluebubbles webhook handling failed",
397
- meta: {
398
- reason: error instanceof Error ? error.message : String(error),
399
- },
400
- });
401
- writeJson(res, 500, {
402
- error: error instanceof Error ? error.message : String(error),
403
- });
404
- }
405
- };
406
- }
407
- function startBlueBubblesApp(deps = {}) {
408
- const resolvedDeps = { ...defaultDeps, ...deps };
409
- resolvedDeps.createClient();
410
- const channelConfig = (0, config_1.getBlueBubblesChannelConfig)();
411
- const server = resolvedDeps.createServer(createBlueBubblesWebhookHandler(deps));
412
- server.listen(channelConfig.port, () => {
413
- (0, runtime_1.emitNervesEvent)({
414
- component: "channels",
415
- event: "channel.app_started",
416
- message: "BlueBubbles sense started",
417
- meta: { port: channelConfig.port, webhookPath: channelConfig.webhookPath },
418
- });
419
- });
420
- return server;
421
- }
@@ -1,108 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createDebugActivityController = createDebugActivityController;
4
- const format_1 = require("../mind/format");
5
- const phrases_1 = require("../mind/phrases");
6
- const runtime_1 = require("../nerves/runtime");
7
- function createDebugActivityController(options) {
8
- let queue = Promise.resolve();
9
- let statusMessageGuid;
10
- let typingActive = false;
11
- let hadToolRun = false;
12
- let followupShown = false;
13
- let lastPhrase = "";
14
- function reportTransportError(operation, error) {
15
- (0, runtime_1.emitNervesEvent)({
16
- level: "warn",
17
- component: "senses",
18
- event: "senses.debug_activity_transport_error",
19
- message: "debug activity transport failed",
20
- meta: {
21
- operation,
22
- reason: error instanceof Error ? error.message : String(error),
23
- },
24
- });
25
- options.onTransportError?.(operation, error);
26
- }
27
- function enqueue(operation, task) {
28
- queue = queue
29
- .then(task)
30
- .catch((error) => {
31
- reportTransportError(operation, error);
32
- });
33
- }
34
- function nextPhrase(pool) {
35
- const phrase = (0, phrases_1.pickPhrase)(pool, lastPhrase);
36
- lastPhrase = phrase;
37
- return phrase;
38
- }
39
- function setStatus(text) {
40
- (0, runtime_1.emitNervesEvent)({
41
- component: "senses",
42
- event: "senses.debug_activity_update",
43
- message: "debug activity status updated",
44
- meta: {
45
- hasStatusGuid: Boolean(statusMessageGuid),
46
- textLength: text.length,
47
- },
48
- });
49
- const shouldStartTyping = !typingActive;
50
- if (shouldStartTyping) {
51
- typingActive = true;
52
- }
53
- enqueue("status_update", async () => {
54
- if (statusMessageGuid) {
55
- await options.transport.editStatus(statusMessageGuid, text);
56
- }
57
- else {
58
- statusMessageGuid = await options.transport.sendStatus(text);
59
- }
60
- if (shouldStartTyping) {
61
- await options.transport.setTyping(true);
62
- }
63
- });
64
- }
65
- return {
66
- onModelStart() {
67
- const pool = hadToolRun ? options.followupPhrases : options.thinkingPhrases;
68
- setStatus(`${nextPhrase(pool)}...`);
69
- },
70
- onToolStart(name, args) {
71
- hadToolRun = true;
72
- followupShown = false;
73
- const argSummary = Object.values(args).join(", ");
74
- const detail = argSummary ? ` (${argSummary})` : "";
75
- setStatus(`running ${name}${detail}...`);
76
- },
77
- onToolEnd(name, summary, success) {
78
- hadToolRun = true;
79
- followupShown = false;
80
- setStatus((0, format_1.formatToolResult)(name, summary, success));
81
- },
82
- onTextChunk(text) {
83
- if (!text || !hadToolRun || followupShown) {
84
- return;
85
- }
86
- followupShown = true;
87
- setStatus(`${nextPhrase(options.followupPhrases)}...`);
88
- },
89
- onError(error) {
90
- setStatus((0, format_1.formatError)(error));
91
- this.finish();
92
- },
93
- async drain() {
94
- await queue;
95
- },
96
- async finish() {
97
- if (!typingActive) {
98
- await queue;
99
- return;
100
- }
101
- typingActive = false;
102
- enqueue("typing_stop", async () => {
103
- await options.transport.setTyping(false);
104
- });
105
- await queue;
106
- },
107
- };
108
- }
@@ -1,73 +0,0 @@
1
- # Sub-agents
2
-
3
- These are source-of-truth workflow definitions (`work-planner`, `work-doer`, `work-merger`) for planning, execution, and merge. They can be consumed either as Claude sub-agents (`.md` files with YAML frontmatter) or as Codex-style skills (`SKILL.md`).
4
-
5
- ## Installation
6
-
7
- ### Claude Code (sub-agents)
8
-
9
- Copy or symlink these files into Claude's sub-agent directory:
10
-
11
- ```bash
12
- # Claude Code
13
- cp subagents/*.md ~/.claude/agents/
14
- # or
15
- ln -s "$(pwd)"/subagents/*.md ~/.claude/agents/
16
- ```
17
-
18
- ### Codex / skill-based harnesses
19
-
20
- For tools that support skills but not Claude sub-agents, install these as skills:
21
-
22
- ```bash
23
- mkdir -p ~/.codex/skills/work-planner ~/.codex/skills/work-doer ~/.codex/skills/work-merger
24
-
25
- # Hard-link to keep one source of truth
26
- ln -f "$(pwd)/subagents/work-planner.md" ~/.codex/skills/work-planner/SKILL.md
27
- ln -f "$(pwd)/subagents/work-doer.md" ~/.codex/skills/work-doer/SKILL.md
28
- ln -f "$(pwd)/subagents/work-merger.md" ~/.codex/skills/work-merger/SKILL.md
29
- ```
30
-
31
- **Important:** Hard-links break when editors save by replacing the file (new inode). After editing any `subagents/*.md` file, re-run the `ln -f` command for that file to restore the link. You can verify with `stat -f '%i'` — both files should share the same inode.
32
-
33
- Optional UI metadata:
34
-
35
- ```bash
36
- mkdir -p ~/.codex/skills/work-planner/agents ~/.codex/skills/work-doer/agents ~/.codex/skills/work-merger/agents
37
- cat > ~/.codex/skills/work-planner/agents/openai.yaml << 'EOF'
38
- interface:
39
- display_name: "Work Planner"
40
- short_description: "Create and gate planning/doing task docs"
41
- default_prompt: "Use $work-planner to create or update a planning doc, then stop at NEEDS_REVIEW."
42
- EOF
43
- cat > ~/.codex/skills/work-doer/agents/openai.yaml << 'EOF'
44
- interface:
45
- display_name: "Work Doer"
46
- short_description: "Execute approved doing docs with strict TDD"
47
- default_prompt: "Use $work-doer to execute an approved doing doc unit by unit."
48
- EOF
49
- cat > ~/.codex/skills/work-merger/agents/openai.yaml << 'EOF'
50
- interface:
51
- display_name: "Work Merger"
52
- short_description: "Merge feature branch into main via PR after work-doer completes"
53
- default_prompt: "Use $work-merger to merge the current feature branch into main."
54
- EOF
55
- ```
56
-
57
- Restart the harness after install so new skills are discovered.
58
-
59
- ## Available sub-agents
60
-
61
- | File | Purpose |
62
- |------|---------|
63
- | `work-planner.md` | Interactive task planner. Generates planning docs through conversation, then converts to doing docs after human approval. |
64
- | `work-doer.md` | Task executor. Reads a doing doc and works through each unit sequentially with strict TDD. |
65
- | `work-merger.md` | Sync-and-merge agent. Merges feature branch into main via PR after work-doer completes. Handles conflicts, CI failures, and race conditions. |
66
-
67
- ## Workflow
68
-
69
- 1. Human describes a task
70
- 2. Agent invokes **work-planner** to create a planning doc → human approves → planner converts to doing doc
71
- 3. Agent invokes **work-doer** to execute the doing doc unit by unit
72
- 4. Each unit is committed independently with progress tracked in the doing doc
73
- 5. Agent invokes **work-merger** to merge the feature branch into main via PR (fetch, merge, resolve conflicts, CI gate, merge PR, cleanup)