@ouro.bot/cli 0.1.0-alpha.723 → 0.1.0-alpha.725

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 (55) hide show
  1. package/changelog.json +295 -275
  2. package/dist/heart/active-work.js +10 -3
  3. package/dist/heart/core.js +343 -77
  4. package/dist/heart/daemon/cli-exec.js +132 -15
  5. package/dist/heart/daemon/cli-help.js +13 -2
  6. package/dist/heart/daemon/cli-parse.js +82 -1
  7. package/dist/heart/daemon/daemon.js +286 -33
  8. package/dist/heart/daemon/doctor.js +82 -6
  9. package/dist/heart/daemon/habit-private-wake.js +6 -1
  10. package/dist/heart/habits/habit-cancel.js +810 -0
  11. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  12. package/dist/heart/habits/habit-migration.js +28 -23
  13. package/dist/heart/habits/habit-parser.js +72 -8
  14. package/dist/heart/habits/habit-runtime-state.js +3 -24
  15. package/dist/heart/habits/habit-scheduler.js +268 -50
  16. package/dist/heart/habits/habit-session.js +16 -0
  17. package/dist/heart/hatch/hatch-flow.js +6 -4
  18. package/dist/heart/mailbox/readers/runtime-readers.js +26 -27
  19. package/dist/heart/orientation-frame.js +58 -1
  20. package/dist/heart/provider-attempt.js +4 -1
  21. package/dist/heart/providers/anthropic.js +23 -2
  22. package/dist/heart/start-of-turn-packet.js +14 -11
  23. package/dist/heart/streaming.js +565 -185
  24. package/dist/mind/obligation-steering.js +15 -9
  25. package/dist/mind/prompt.js +58 -26
  26. package/dist/nerves/coverage/run-artifacts.js +55 -35
  27. package/dist/nerves/review/cli.js +2 -2
  28. package/dist/nerves/review/core.js +14 -7
  29. package/dist/repertoire/tools-base.js +2 -0
  30. package/dist/repertoire/tools-habits.js +103 -0
  31. package/dist/repertoire/tools.js +18 -3
  32. package/dist/rsvp/cli.js +126 -20
  33. package/dist/rsvp/diagnostics.js +12 -2
  34. package/dist/rsvp/habit-policy.js +7 -0
  35. package/dist/rsvp/habit-stage.js +19 -4
  36. package/dist/rsvp/native-habit-runner.js +151 -11
  37. package/dist/rsvp/outbound-state.js +360 -0
  38. package/dist/senses/bluebubbles/client.js +90 -17
  39. package/dist/senses/bluebubbles/inbound-log.js +1 -0
  40. package/dist/senses/bluebubbles/index.js +662 -425
  41. package/dist/senses/bluebubbles/model.js +57 -13
  42. package/dist/senses/bluebubbles/mutation-log.js +21 -10
  43. package/dist/senses/bluebubbles/reaction-policy.js +55 -0
  44. package/dist/senses/bluebubbles/semantic-receipts.js +1818 -0
  45. package/dist/senses/cli/tui-store.js +1 -0
  46. package/dist/senses/cli.js +1 -0
  47. package/dist/senses/habit-lifecycle-guard.js +24 -0
  48. package/dist/senses/ingress-evidence.js +2 -0
  49. package/dist/senses/mail.js +129 -0
  50. package/dist/senses/pipeline.js +90 -24
  51. package/dist/senses/private-runtime-worker.js +21 -20
  52. package/dist/senses/private-runtime.js +79 -29
  53. package/dist/senses/shared-turn.js +1 -0
  54. package/dist/senses/teams.js +1 -0
  55. package/package.json +6 -1
@@ -290,6 +290,7 @@ async function streamAnthropicMessages(client, model, request) {
290
290
  const thinkingBlocks = new Map();
291
291
  const redactedBlocks = new Map();
292
292
  const answerStreamer = new streaming_1.SettleStreamer(request.callbacks, request.eagerSettleStreaming);
293
+ const textOutput = new streaming_1.ProviderTextOutput(request.callbacks);
293
294
  try {
294
295
  for await (const event of response) {
295
296
  if (request.signal?.aborted)
@@ -319,6 +320,7 @@ async function streamAnthropicMessages(client, model, request) {
319
320
  /* v8 ignore next -- settle streaming activation, tested via SettleStreamer unit tests @preserve */
320
321
  if (name === "settle" && toolCalls.size === 1) {
321
322
  answerStreamer.activate();
323
+ textOutput.suppress();
322
324
  }
323
325
  }
324
326
  continue;
@@ -333,7 +335,7 @@ async function streamAnthropicMessages(client, model, request) {
333
335
  }
334
336
  const text = String(delta?.text ?? "");
335
337
  content += text;
336
- request.callbacks.onTextChunk(text);
338
+ textOutput.emit(text);
337
339
  continue;
338
340
  }
339
341
  if (deltaType === "thinking_delta") {
@@ -387,8 +389,26 @@ async function streamAnthropicMessages(client, model, request) {
387
389
  }
388
390
  }
389
391
  catch (error) {
392
+ textOutput.discard();
393
+ answerStreamer.cancel();
390
394
  throw error instanceof Error ? error : /* v8 ignore next -- defensive: stream errors are always Error @preserve */ new Error(String(error));
391
395
  }
396
+ const completedToolCalls = [...toolCalls.values()];
397
+ let settleFinalization;
398
+ if (request.signal?.aborted) {
399
+ textOutput.discard();
400
+ answerStreamer.cancel();
401
+ }
402
+ else if (completedToolCalls.length === 1
403
+ && completedToolCalls[0].name === "settle"
404
+ && answerStreamer.detected) {
405
+ textOutput.discard();
406
+ settleFinalization = (0, streaming_1.finalizeSettleStream)(answerStreamer, completedToolCalls[0].arguments);
407
+ }
408
+ else {
409
+ answerStreamer.cancel();
410
+ textOutput.flush();
411
+ }
392
412
  // Collect all thinking blocks (regular + redacted) sorted by index to preserve ordering
393
413
  const allThinkingIndices = [...thinkingBlocks.keys(), ...redactedBlocks.keys()].sort((a, b) => a - b);
394
414
  const outputItems = allThinkingIndices.map((idx) => {
@@ -399,10 +419,11 @@ async function streamAnthropicMessages(client, model, request) {
399
419
  });
400
420
  return {
401
421
  content,
402
- toolCalls: [...toolCalls.values()],
422
+ toolCalls: completedToolCalls,
403
423
  outputItems,
404
424
  usage,
405
425
  settleStreamed: answerStreamer.streamed,
426
+ ...(settleFinalization ? { settleFinalization } : {}),
406
427
  };
407
428
  }
408
429
  function createAnthropicProviderRuntime(model, anthropicConfig = (0, config_1.getAnthropicConfig)()) {
@@ -44,6 +44,7 @@ const bundle_state_1 = require("./bundle-state");
44
44
  const tempo_1 = require("./tempo");
45
45
  const flight_recorder_1 = require("../arc/flight-recorder");
46
46
  const context_loss_sentinel_1 = require("./context-loss-sentinel");
47
+ const orientation_frame_1 = require("./orientation-frame");
47
48
  function estimateTokens(text) {
48
49
  return Math.ceil(text.length / 4);
49
50
  }
@@ -224,8 +225,9 @@ function buildStartOfTurnPacket(view, opts) {
224
225
  * So presence is truncated first, then plotLine, then cares, then obligations.
225
226
  * resumeHint is never truncated.
226
227
  */
227
- function renderStartOfTurnPacket(packet) {
228
+ function renderStartOfTurnPacket(packet, options = {}) {
228
229
  const budget = packet.tokenBudget;
230
+ const resumePriorWork = options.resumePriorWork === true;
229
231
  // Assemble sections in priority order (highest priority first for budget allocation)
230
232
  // Each section is { label, content, priority } where lower priority number = truncated first
231
233
  const sections = [
@@ -257,7 +259,7 @@ function renderStartOfTurnPacket(packet) {
257
259
  return "";
258
260
  }
259
261
  // Build the rendered output, truncating lower-priority sections first
260
- let rendered = formatSections(sections);
262
+ let rendered = formatSections(sections, resumePriorWork);
261
263
  let tokens = estimateTokens(rendered);
262
264
  // Truncate sections from lowest priority until we fit budget
263
265
  const sortedByPriority = [...sections].sort((a, b) => a.priority - b.priority);
@@ -270,7 +272,7 @@ function renderStartOfTurnPacket(packet) {
270
272
  // Remove this section entirely
271
273
  const idx = sections.findIndex((s) => s.label === section.label);
272
274
  sections.splice(idx, 1);
273
- rendered = formatSections(sections);
275
+ rendered = formatSections(sections, resumePriorWork);
274
276
  tokens = estimateTokens(rendered);
275
277
  }
276
278
  // If still over budget after removing all non-protected sections, trim what's left
@@ -286,18 +288,18 @@ function renderStartOfTurnPacket(packet) {
286
288
  });
287
289
  return rendered;
288
290
  }
289
- function formatSections(sections) {
291
+ function formatSections(sections, resumePriorWork) {
290
292
  const parts = [];
291
293
  for (const section of sections) {
292
294
  switch (section.label) {
293
295
  case "resume":
294
- parts.push(`**Next:** ${section.content}`);
296
+ parts.push((0, orientation_frame_1.labelPriorWorkSurface)(`**Next:**\n${section.content}`, resumePriorWork));
295
297
  break;
296
298
  case "arc":
297
- parts.push(`**Arc:**\n${section.content}`);
299
+ parts.push((0, orientation_frame_1.labelPriorWorkSurface)(`**Arc:**\n${section.content}`, resumePriorWork));
298
300
  break;
299
301
  case "recoverySentinel":
300
- parts.push(`**Recovery Sentinel:**\n${section.content}`);
302
+ parts.push((0, orientation_frame_1.labelPriorWorkSurface)(`**Recovery Sentinel:**\n${section.content}`, resumePriorWork));
301
303
  break;
302
304
  case "sessionTiming":
303
305
  parts.push(`**Thread timing:** ${section.content}`);
@@ -306,7 +308,7 @@ function formatSections(sections) {
306
308
  parts.push(`**Recent contact:** ${section.content}`);
307
309
  break;
308
310
  case "obligations":
309
- parts.push(`**Owed:**\n${section.content}`);
311
+ parts.push((0, orientation_frame_1.labelPriorWorkSurface)(`**Owed:**\n${section.content}`, resumePriorWork));
310
312
  break;
311
313
  case "cares":
312
314
  parts.push(`**Cares:**\n${section.content}`);
@@ -337,15 +339,16 @@ function formatSections(sections) {
337
339
  * Ultra-compact version for coding context (max 200 tokens).
338
340
  * Just resumeHint + top obligation + top care, single-line bullets.
339
341
  */
340
- function renderCompactStartOfTurnPacket(packet) {
342
+ function renderCompactStartOfTurnPacket(packet, options = {}) {
341
343
  const parts = [];
344
+ const instruction = (0, orientation_frame_1.priorWorkInstruction)(options.resumePriorWork === true);
342
345
  if (packet.resumeHint) {
343
- parts.push(`next: ${packet.resumeHint}`);
346
+ parts.push(`next:\n${instruction}\n${packet.resumeHint}`);
344
347
  }
345
348
  if (packet.obligations) {
346
349
  // Just first line of obligations
347
350
  const firstOb = packet.obligations.split("\n")[0];
348
- parts.push(`owed: ${firstOb.replace(/^- /, "")}`);
351
+ parts.push(`owed:\n${instruction}\n${firstOb.replace(/^- /, "")}`);
349
352
  }
350
353
  if (packet.cares) {
351
354
  const firstCare = packet.cares.split("\n")[0];