@nookplot/runtime 0.5.99 → 0.5.105

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 (125) hide show
  1. package/dist/__tests__/autonomous.guardrails.test.d.ts +2 -0
  2. package/dist/__tests__/autonomous.guardrails.test.d.ts.map +1 -0
  3. package/dist/__tests__/autonomous.guardrails.test.js +215 -0
  4. package/dist/__tests__/autonomous.guardrails.test.js.map +1 -0
  5. package/dist/__tests__/autonomous.hooks.test.d.ts +2 -0
  6. package/dist/__tests__/autonomous.hooks.test.d.ts.map +1 -0
  7. package/dist/__tests__/autonomous.hooks.test.js +107 -0
  8. package/dist/__tests__/autonomous.hooks.test.js.map +1 -0
  9. package/dist/__tests__/chatEngine.episodicHook.test.d.ts +2 -0
  10. package/dist/__tests__/chatEngine.episodicHook.test.d.ts.map +1 -0
  11. package/dist/__tests__/chatEngine.episodicHook.test.js +160 -0
  12. package/dist/__tests__/chatEngine.episodicHook.test.js.map +1 -0
  13. package/dist/__tests__/chatEngine.test.d.ts +2 -0
  14. package/dist/__tests__/chatEngine.test.d.ts.map +1 -0
  15. package/dist/__tests__/chatEngine.test.js +482 -0
  16. package/dist/__tests__/chatEngine.test.js.map +1 -0
  17. package/dist/__tests__/conversation/compactionMemory.test.d.ts +2 -0
  18. package/dist/__tests__/conversation/compactionMemory.test.d.ts.map +1 -0
  19. package/dist/__tests__/conversation/compactionMemory.test.js +447 -0
  20. package/dist/__tests__/conversation/compactionMemory.test.js.map +1 -0
  21. package/dist/__tests__/conversation/modelThresholdsParity.test.d.ts +2 -0
  22. package/dist/__tests__/conversation/modelThresholdsParity.test.d.ts.map +1 -0
  23. package/dist/__tests__/conversation/modelThresholdsParity.test.js +79 -0
  24. package/dist/__tests__/conversation/modelThresholdsParity.test.js.map +1 -0
  25. package/dist/__tests__/guardrails.test.d.ts +2 -0
  26. package/dist/__tests__/guardrails.test.d.ts.map +1 -0
  27. package/dist/__tests__/guardrails.test.js +236 -0
  28. package/dist/__tests__/guardrails.test.js.map +1 -0
  29. package/dist/__tests__/hooks.test.d.ts +9 -0
  30. package/dist/__tests__/hooks.test.d.ts.map +1 -0
  31. package/dist/__tests__/hooks.test.js +188 -0
  32. package/dist/__tests__/hooks.test.js.map +1 -0
  33. package/dist/__tests__/querySegmentation.test.d.ts +2 -0
  34. package/dist/__tests__/querySegmentation.test.d.ts.map +1 -0
  35. package/dist/__tests__/querySegmentation.test.js +187 -0
  36. package/dist/__tests__/querySegmentation.test.js.map +1 -0
  37. package/dist/__tests__/sandbox.test.d.ts +13 -0
  38. package/dist/__tests__/sandbox.test.d.ts.map +1 -0
  39. package/dist/__tests__/sandbox.test.js +413 -0
  40. package/dist/__tests__/sandbox.test.js.map +1 -0
  41. package/dist/__tests__/wakeUpStack.test.d.ts +2 -0
  42. package/dist/__tests__/wakeUpStack.test.d.ts.map +1 -0
  43. package/dist/__tests__/wakeUpStack.test.js +239 -0
  44. package/dist/__tests__/wakeUpStack.test.js.map +1 -0
  45. package/dist/actionCatalog.generated.d.ts.map +1 -1
  46. package/dist/actionCatalog.generated.js +0 -5
  47. package/dist/actionCatalog.generated.js.map +1 -1
  48. package/dist/autonomous.d.ts +3 -0
  49. package/dist/autonomous.d.ts.map +1 -1
  50. package/dist/autonomous.js +108 -7
  51. package/dist/autonomous.js.map +1 -1
  52. package/dist/chat/chatEngine.d.ts +15 -0
  53. package/dist/chat/chatEngine.d.ts.map +1 -1
  54. package/dist/chat/chatEngine.js +59 -34
  55. package/dist/chat/chatEngine.js.map +1 -1
  56. package/dist/connection.d.ts.map +1 -1
  57. package/dist/connection.js +1 -0
  58. package/dist/connection.js.map +1 -1
  59. package/dist/conversation/compactionMemory.d.ts +124 -0
  60. package/dist/conversation/compactionMemory.d.ts.map +1 -0
  61. package/dist/conversation/compactionMemory.js +379 -0
  62. package/dist/conversation/compactionMemory.js.map +1 -0
  63. package/dist/conversation/conversationLogStore.d.ts +111 -0
  64. package/dist/conversation/conversationLogStore.d.ts.map +1 -0
  65. package/dist/conversation/conversationLogStore.js +248 -0
  66. package/dist/conversation/conversationLogStore.js.map +1 -0
  67. package/dist/conversation/conversationMemory.d.ts +59 -0
  68. package/dist/conversation/conversationMemory.d.ts.map +1 -0
  69. package/dist/conversation/conversationMemory.js +32 -0
  70. package/dist/conversation/conversationMemory.js.map +1 -0
  71. package/dist/conversation/index.d.ts +16 -0
  72. package/dist/conversation/index.d.ts.map +1 -0
  73. package/dist/conversation/index.js +5 -0
  74. package/dist/conversation/index.js.map +1 -0
  75. package/dist/conversation/modelLimits.d.ts +43 -0
  76. package/dist/conversation/modelLimits.d.ts.map +1 -0
  77. package/dist/conversation/modelLimits.js +67 -0
  78. package/dist/conversation/modelLimits.js.map +1 -0
  79. package/dist/defaultGuardrails.d.ts +21 -0
  80. package/dist/defaultGuardrails.d.ts.map +1 -0
  81. package/dist/defaultGuardrails.js +90 -0
  82. package/dist/defaultGuardrails.js.map +1 -0
  83. package/dist/episodicMemoryHook.d.ts +39 -0
  84. package/dist/episodicMemoryHook.d.ts.map +1 -0
  85. package/dist/episodicMemoryHook.js +58 -0
  86. package/dist/episodicMemoryHook.js.map +1 -0
  87. package/dist/guardrails.d.ts +182 -0
  88. package/dist/guardrails.d.ts.map +1 -0
  89. package/dist/guardrails.js +277 -0
  90. package/dist/guardrails.js.map +1 -0
  91. package/dist/hooks.d.ts +162 -0
  92. package/dist/hooks.d.ts.map +1 -0
  93. package/dist/hooks.js +91 -0
  94. package/dist/hooks.js.map +1 -0
  95. package/dist/index.d.ts +38 -3
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +51 -3
  98. package/dist/index.js.map +1 -1
  99. package/dist/knowledgeContext.d.ts +15 -1
  100. package/dist/knowledgeContext.d.ts.map +1 -1
  101. package/dist/knowledgeContext.js +26 -3
  102. package/dist/knowledgeContext.js.map +1 -1
  103. package/dist/memory.d.ts +15 -0
  104. package/dist/memory.d.ts.map +1 -1
  105. package/dist/memory.js +14 -0
  106. package/dist/memory.js.map +1 -1
  107. package/dist/querySegmentation.d.ts +54 -0
  108. package/dist/querySegmentation.d.ts.map +1 -0
  109. package/dist/querySegmentation.js +80 -0
  110. package/dist/querySegmentation.js.map +1 -0
  111. package/dist/sandbox.d.ts +156 -0
  112. package/dist/sandbox.d.ts.map +1 -0
  113. package/dist/sandbox.js +425 -0
  114. package/dist/sandbox.js.map +1 -0
  115. package/dist/signalActionMap.d.ts +19 -0
  116. package/dist/signalActionMap.d.ts.map +1 -1
  117. package/dist/signalActionMap.js +33 -0
  118. package/dist/signalActionMap.js.map +1 -1
  119. package/dist/types.d.ts +25 -1
  120. package/dist/types.d.ts.map +1 -1
  121. package/dist/wakeUpStack.d.ts +94 -0
  122. package/dist/wakeUpStack.d.ts.map +1 -0
  123. package/dist/wakeUpStack.js +215 -0
  124. package/dist/wakeUpStack.js.map +1 -0
  125. package/package.json +1 -1
@@ -43,6 +43,9 @@ import { prepareSignRelay } from "./signing.js";
43
43
  import { wrapUntrusted, sanitizeForPrompt, UNTRUSTED_CONTENT_INSTRUCTION } from "./contentSafety.js";
44
44
  import { getAvailableActionsFromMap } from "./signalActionMap.js";
45
45
  import { getCategoryListing, getToolsInCategory } from "./actionCatalog.js";
46
+ import { WakeUpStack } from "./wakeUpStack.js";
47
+ import { hooks as defaultHooks } from "./hooks.js";
48
+ import { guardrails as defaultGuardrails, GuardrailTripped, InputGuardrailTripped, } from "./guardrails.js";
46
49
  // ----------------------------------------------------------------
47
50
  // AutonomousAgent
48
51
  // ----------------------------------------------------------------
@@ -144,6 +147,8 @@ export class AutonomousAgent {
144
147
  processedSignals = new Map();
145
148
  /** Dynamic tool browsing: categories loaded via browse_tools. */
146
149
  loadedCategories = new Set();
150
+ /** Tiered knowledge context: L0 identity + L1 essentials (session-cached) + L2 on-demand. */
151
+ wakeUpStack;
147
152
  constructor(runtime, options = {}) {
148
153
  this.runtime = runtime;
149
154
  this.verbose = options.verbose ?? true;
@@ -152,6 +157,7 @@ export class AutonomousAgent {
152
157
  this.actionHandler = options.onAction;
153
158
  this.approvalHandler = options.onApproval;
154
159
  this.cooldownSec = options.responseCooldown ?? 120;
160
+ this.wakeUpStack = new WakeUpStack(runtime);
155
161
  }
156
162
  /** Start listening for proactive signals and action requests. */
157
163
  start() {
@@ -361,6 +367,8 @@ export class AutonomousAgent {
361
367
  if (this.verbose) {
362
368
  console.log(`[autonomous] Signal: ${signalType}${data.channelName ? ` in #${data.channelName}` : ""}`);
363
369
  }
370
+ const signalHooks = this.runtime.hooks ?? defaultHooks;
371
+ signalHooks.emitFireAndForget("signal_received", data);
364
372
  // Raw handler takes priority — full manual control
365
373
  if (this.signalHandler) {
366
374
  await this.signalHandler(data, this.runtime);
@@ -725,11 +733,25 @@ export class AutonomousAgent {
725
733
  }
726
734
  }
727
735
  catch { /* non-fatal */ }
736
+ // Tiered knowledge context (L0+L1 cached, L2 on-demand) — non-fatal.
737
+ // Pass signalType so the L2 search picks the right MAD selection mode
738
+ // (e.g. "aggressive" for channel_mention/reply_to_own_post, "moderate"
739
+ // for general channel_message). See SPEC_latent-briefing-inspired-upgrades.md.
740
+ let knowledgeContext = "";
741
+ try {
742
+ const wakeUp = await this.wakeUpStack.getContext(preview || channelName, data.signalType);
743
+ if (wakeUp.markdown) {
744
+ knowledgeContext = "\n\n" + wakeUp.markdown + "\n";
745
+ }
746
+ }
747
+ catch { /* non-fatal */ }
728
748
  // Build prompt for the agent's LLM
729
749
  let prompt = `${UNTRUSTED_CONTENT_INSTRUCTION}\n\n`;
730
750
  prompt += `You are participating in a Nookplot channel called "${channelName}". `;
731
751
  prompt += "Read the conversation and respond naturally. Be helpful and concise. ";
732
752
  prompt += "If there's nothing meaningful to add, respond with exactly: [SKIP]\n\n";
753
+ if (knowledgeContext)
754
+ prompt += knowledgeContext + "\n";
733
755
  if (historyText)
734
756
  prompt += `Recent messages:\n${historyText}\n\n`;
735
757
  if (bundleContext)
@@ -758,10 +780,24 @@ export class AutonomousAgent {
758
780
  return;
759
781
  try {
760
782
  const preview = data.messagePreview ?? "";
761
- const prompt = `${UNTRUSTED_CONTENT_INSTRUCTION}\n\n` +
762
- "You received a direct message on Nookplot from another agent.\n" +
763
- "Reply naturally and helpfully. If nothing to say, respond with: [SKIP]\n\n" +
764
- `Message from ${senderAddress.slice(0, 12)}...:\n${wrapUntrusted(preview, "DM")}\n\nYour reply (under 500 chars):`;
783
+ // Tiered knowledge context for focused 1:1 reply (Change 1: wire DM
784
+ // handler into WakeUpStack). "dm_received" maps to "aggressive" in
785
+ // SIGNAL_SELECTION_MODE so L2 pulls 2-3 tight matches instead of a
786
+ // scattershot pooled-vector top-k.
787
+ let knowledgeContext = "";
788
+ try {
789
+ const wakeUp = await this.wakeUpStack.getContext(preview, "dm_received");
790
+ if (wakeUp.markdown) {
791
+ knowledgeContext = "\n\n" + wakeUp.markdown + "\n";
792
+ }
793
+ }
794
+ catch { /* non-fatal */ }
795
+ let prompt = `${UNTRUSTED_CONTENT_INSTRUCTION}\n\n`;
796
+ prompt += "You received a direct message on Nookplot from another agent.\n";
797
+ prompt += "Reply naturally and helpfully. If nothing to say, respond with: [SKIP]\n\n";
798
+ if (knowledgeContext)
799
+ prompt += knowledgeContext + "\n";
800
+ prompt += `Message from ${senderAddress.slice(0, 12)}...:\n${wrapUntrusted(preview, "DM")}\n\nYour reply (under 500 chars):`;
765
801
  const response = await this.generateResponse(prompt);
766
802
  const content = response?.trim() ?? "";
767
803
  if (content && content !== "[SKIP]") {
@@ -2593,15 +2629,22 @@ export class AutonomousAgent {
2593
2629
  return;
2594
2630
  }
2595
2631
  const { actionType, actionId, suggestedContent, payload } = event;
2632
+ let args = (payload ?? {});
2633
+ const hooks = this.runtime.hooks ?? defaultHooks;
2634
+ const guardrails = this.runtime.guardrails ?? defaultGuardrails;
2635
+ const agentAddress = this.runtime.connection?.address;
2596
2636
  if (this.verbose) {
2597
2637
  console.log(`[autonomous] Action request: ${actionType}${actionId ? ` (${actionId})` : ""}`);
2598
2638
  }
2599
2639
  // Approval gate: on-chain actions require approval when handler is set
2600
2640
  if (this.approvalHandler && ON_CHAIN_ACTIONS.has(actionType)) {
2601
- const approved = await this.approvalHandler(actionType, (payload ?? {}));
2641
+ const approved = await this.approvalHandler(actionType, args);
2602
2642
  if (!approved) {
2603
2643
  if (this.verbose)
2604
2644
  console.log(`[autonomous] Action rejected by approval handler: ${actionType}`);
2645
+ hooks.emitFireAndForget("action_rejected", {
2646
+ actionType, args, reason: "Rejected by approval handler", actionId,
2647
+ });
2605
2648
  if (actionId) {
2606
2649
  try {
2607
2650
  await this.runtime.proactive.rejectDelegatedAction(actionId, "Rejected by approval handler");
@@ -2611,17 +2654,52 @@ export class AutonomousAgent {
2611
2654
  return;
2612
2655
  }
2613
2656
  }
2657
+ const startTime = Date.now();
2658
+ hooks.emitFireAndForget("action_start", { actionType, args, actionId, agentAddress });
2659
+ // ── Input guardrails (Phase 3) ──
2660
+ // Run BEFORE the action body so a tripped guardrail prevents dispatch.
2661
+ // `tool_input` fires regardless so observability sees the call attempt;
2662
+ // a tripped guardrail then routes to `action_error`, NOT `action_end`.
2663
+ hooks.emitFireAndForget("tool_input", { toolName: actionType, args });
2664
+ try {
2665
+ args = await guardrails.runInput(actionType, args);
2666
+ }
2667
+ catch (err) {
2668
+ const guardrailErr = err instanceof GuardrailTripped
2669
+ ? err
2670
+ : new InputGuardrailTripped(`Input guardrail for "${actionType}" failed: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
2671
+ if (this.verbose)
2672
+ console.error(`[autonomous] ✗ guardrail blocked ${actionType}: ${guardrailErr.message}`);
2673
+ hooks.emitFireAndForget("action_error", {
2674
+ actionType, args, error: guardrailErr,
2675
+ durationMs: Date.now() - startTime, actionId,
2676
+ });
2677
+ if (actionId) {
2678
+ try {
2679
+ await this.runtime.proactive.rejectDelegatedAction(actionId, guardrailErr.message);
2680
+ }
2681
+ catch { /* best-effort */ }
2682
+ }
2683
+ return;
2684
+ }
2614
2685
  try {
2615
2686
  let txHash;
2616
2687
  let result;
2617
2688
  // ── Intercept browse_tools (client-side, no gateway call needed) ──
2618
2689
  if (actionType === "browse_tools") {
2619
- const category = payload?.category;
2690
+ // Read from the (possibly guardrail-mutated) args, not raw payload.
2691
+ const category = args?.category;
2620
2692
  if (!category) {
2621
2693
  const listing = getCategoryListing();
2622
2694
  if (this.verbose) {
2623
2695
  console.log(`[autonomous] browse_tools — ${listing.length} categories: ${listing.map((c) => `${c.name} (${c.count})`).join(", ")}`);
2624
2696
  }
2697
+ let browseResult = { categories: listing };
2698
+ browseResult = await guardrails.runOutput(actionType, browseResult);
2699
+ hooks.emitFireAndForget("tool_output", { toolName: actionType, args, result: browseResult });
2700
+ hooks.emitFireAndForget("action_end", {
2701
+ actionType, args, result: browseResult, durationMs: Date.now() - startTime, actionId,
2702
+ });
2625
2703
  return;
2626
2704
  }
2627
2705
  this.loadedCategories.add(category);
@@ -2629,14 +2707,24 @@ export class AutonomousAgent {
2629
2707
  if (this.verbose) {
2630
2708
  console.log(`[autonomous] browse_tools — loaded ${tools.length} tools from "${category}"`);
2631
2709
  }
2710
+ let browseResult = { category, count: tools.length };
2711
+ browseResult = await guardrails.runOutput(actionType, browseResult);
2712
+ hooks.emitFireAndForget("tool_output", { toolName: actionType, args, result: browseResult });
2713
+ hooks.emitFireAndForget("action_end", {
2714
+ actionType, args, result: browseResult, durationMs: Date.now() - startTime, actionId,
2715
+ });
2632
2716
  return;
2633
2717
  }
2634
2718
  // ── Unified dispatch via POST /v1/actions/execute ──
2635
2719
  // The gateway's ToolDispatcher routes the call to the correct internal
2636
2720
  // endpoint, replacing the 2000+ line switch statement that was here before.
2721
+ // NOTE: build the dispatch body from the GUARDRAIL-MUTATED `args`, not
2722
+ // the original `payload` — otherwise input-guardrail mutations
2723
+ // (lowercase normalization, content sanitization, etc.) silently get
2724
+ // dropped on the way to the gateway.
2637
2725
  const toolName = `nookplot_${actionType}`;
2638
2726
  const dispatchPayload = {
2639
- ...(payload ?? {}),
2727
+ ...args,
2640
2728
  ...(suggestedContent ? { suggestedContent } : {}),
2641
2729
  };
2642
2730
  const dispatchResult = await this.runtime.connection.request("POST", "/v1/actions/execute", { toolName, payload: dispatchPayload });
@@ -2700,15 +2788,28 @@ export class AutonomousAgent {
2700
2788
  }
2701
2789
  }
2702
2790
  // ── END unified dispatch ──
2791
+ // ── Output guardrails (Phase 3) ──
2792
+ // Run AFTER the body, BEFORE we mark the action complete on the
2793
+ // gateway. A tripped output guardrail throws -> caught by the outer
2794
+ // catch -> action_error fires (NOT action_end).
2795
+ result = await guardrails.runOutput(actionType, result ?? {});
2796
+ hooks.emitFireAndForget("tool_output", { toolName: actionType, args, result });
2703
2797
  if (actionId)
2704
2798
  await this.runtime.proactive.completeAction(actionId, txHash, result);
2705
2799
  if (this.verbose)
2706
2800
  console.log(`[autonomous] ✓ ${actionType}${txHash ? ` tx=${txHash}` : ""}`);
2801
+ hooks.emitFireAndForget("action_end", {
2802
+ actionType, args, result, durationMs: Date.now() - startTime, actionId, txHash,
2803
+ });
2707
2804
  }
2708
2805
  catch (error) {
2709
2806
  const msg = error instanceof Error ? error.message : String(error);
2710
2807
  if (this.verbose)
2711
2808
  console.error(`[autonomous] ✗ ${actionType}: ${msg}`);
2809
+ hooks.emitFireAndForget("action_error", {
2810
+ actionType, args, error: error instanceof Error ? error : new Error(msg),
2811
+ durationMs: Date.now() - startTime, actionId,
2812
+ });
2712
2813
  if (actionId) {
2713
2814
  try {
2714
2815
  await this.runtime.proactive.rejectDelegatedAction(actionId, msg);