@animalabs/agent-framework 0.5.4 → 0.5.7

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 (101) hide show
  1. package/dist/src/agent.d.ts +20 -4
  2. package/dist/src/agent.d.ts.map +1 -1
  3. package/dist/src/agent.js +45 -14
  4. package/dist/src/agent.js.map +1 -1
  5. package/dist/src/framework.d.ts +153 -5
  6. package/dist/src/framework.d.ts.map +1 -1
  7. package/dist/src/framework.js +1046 -56
  8. package/dist/src/framework.js.map +1 -1
  9. package/dist/src/gate/event-gate.d.ts +27 -0
  10. package/dist/src/gate/event-gate.d.ts.map +1 -1
  11. package/dist/src/gate/event-gate.js +140 -1
  12. package/dist/src/gate/event-gate.js.map +1 -1
  13. package/dist/src/gate/types.d.ts +17 -0
  14. package/dist/src/gate/types.d.ts.map +1 -1
  15. package/dist/src/index.d.ts +2 -0
  16. package/dist/src/index.d.ts.map +1 -1
  17. package/dist/src/index.js +2 -0
  18. package/dist/src/index.js.map +1 -1
  19. package/dist/src/mcpl/channel-registry.d.ts +50 -0
  20. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  21. package/dist/src/mcpl/channel-registry.js +180 -0
  22. package/dist/src/mcpl/channel-registry.js.map +1 -1
  23. package/dist/src/mcpl/conversation-router.d.ts +161 -0
  24. package/dist/src/mcpl/conversation-router.d.ts.map +1 -0
  25. package/dist/src/mcpl/conversation-router.js +179 -0
  26. package/dist/src/mcpl/conversation-router.js.map +1 -0
  27. package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
  28. package/dist/src/mcpl/feature-set-manager.js +10 -1
  29. package/dist/src/mcpl/feature-set-manager.js.map +1 -1
  30. package/dist/src/mcpl/index.d.ts +2 -0
  31. package/dist/src/mcpl/index.d.ts.map +1 -1
  32. package/dist/src/mcpl/index.js +2 -0
  33. package/dist/src/mcpl/index.js.map +1 -1
  34. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  35. package/dist/src/mcpl/server-connection.js +4 -0
  36. package/dist/src/mcpl/server-connection.js.map +1 -1
  37. package/dist/src/module-registry.d.ts +3 -1
  38. package/dist/src/module-registry.d.ts.map +1 -1
  39. package/dist/src/module-registry.js +9 -2
  40. package/dist/src/module-registry.js.map +1 -1
  41. package/dist/src/modules/discord/index.d.ts +10 -0
  42. package/dist/src/modules/discord/index.d.ts.map +1 -1
  43. package/dist/src/modules/discord/index.js +83 -0
  44. package/dist/src/modules/discord/index.js.map +1 -1
  45. package/dist/src/tool-result-history.d.ts +17 -0
  46. package/dist/src/tool-result-history.d.ts.map +1 -0
  47. package/dist/src/tool-result-history.js +60 -0
  48. package/dist/src/tool-result-history.js.map +1 -0
  49. package/dist/src/types/agent.d.ts +11 -0
  50. package/dist/src/types/agent.d.ts.map +1 -1
  51. package/dist/src/types/framework.d.ts +8 -0
  52. package/dist/src/types/framework.d.ts.map +1 -1
  53. package/dist/src/types/module.d.ts +15 -0
  54. package/dist/src/types/module.d.ts.map +1 -1
  55. package/dist/src/types/trace.d.ts +48 -0
  56. package/dist/src/types/trace.d.ts.map +1 -1
  57. package/dist/test/channel-registry-routing.test.d.ts +2 -0
  58. package/dist/test/channel-registry-routing.test.d.ts.map +1 -0
  59. package/dist/test/channel-registry-routing.test.js +75 -0
  60. package/dist/test/channel-registry-routing.test.js.map +1 -0
  61. package/dist/test/conversation-router.test.d.ts +2 -0
  62. package/dist/test/conversation-router.test.d.ts.map +1 -0
  63. package/dist/test/conversation-router.test.js +160 -0
  64. package/dist/test/conversation-router.test.js.map +1 -0
  65. package/dist/test/conversation-routing.test.d.ts +7 -0
  66. package/dist/test/conversation-routing.test.d.ts.map +1 -0
  67. package/dist/test/conversation-routing.test.js +203 -0
  68. package/dist/test/conversation-routing.test.js.map +1 -0
  69. package/dist/test/framework.test.js +120 -2
  70. package/dist/test/framework.test.js.map +1 -1
  71. package/dist/test/helpers/mock-membrane.d.ts +41 -0
  72. package/dist/test/helpers/mock-membrane.d.ts.map +1 -0
  73. package/dist/test/helpers/mock-membrane.js +161 -0
  74. package/dist/test/helpers/mock-membrane.js.map +1 -0
  75. package/dist/test/inference-failure-observability.test.d.ts +2 -0
  76. package/dist/test/inference-failure-observability.test.d.ts.map +1 -0
  77. package/dist/test/inference-failure-observability.test.js +75 -0
  78. package/dist/test/inference-failure-observability.test.js.map +1 -0
  79. package/dist/test/tool-result-history.test.d.ts +7 -0
  80. package/dist/test/tool-result-history.test.d.ts.map +1 -0
  81. package/dist/test/tool-result-history.test.js +77 -0
  82. package/dist/test/tool-result-history.test.js.map +1 -0
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/package.json +6 -2
  85. package/src/agent.ts +53 -18
  86. package/src/framework.ts +1202 -59
  87. package/src/gate/event-gate.ts +144 -1
  88. package/src/gate/types.ts +17 -0
  89. package/src/index.ts +12 -0
  90. package/src/mcpl/channel-registry.ts +221 -0
  91. package/src/mcpl/conversation-router.ts +284 -0
  92. package/src/mcpl/feature-set-manager.ts +14 -1
  93. package/src/mcpl/index.ts +12 -0
  94. package/src/mcpl/server-connection.ts +4 -0
  95. package/src/module-registry.ts +14 -2
  96. package/src/modules/discord/index.ts +93 -0
  97. package/src/tool-result-history.ts +57 -0
  98. package/src/types/agent.ts +11 -0
  99. package/src/types/framework.ts +9 -0
  100. package/src/types/module.ts +16 -0
  101. package/src/types/trace.ts +57 -0
package/src/agent.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Membrane, NormalizedMessage, NormalizedRequest, ContentBlock, YieldingStream } from '@animalabs/membrane';
2
2
  import { isAbortedResponse } from '@animalabs/membrane';
3
+ import { toolResultDataToHistoryString } from './tool-result-history.js';
3
4
 
4
5
  export interface StartStreamResult {
5
6
  stream: YieldingStream;
@@ -42,13 +43,17 @@ export class Agent {
42
43
  * request native thinking from the provider. Signatures on response thinking
43
44
  * blocks are preserved through Chronicle.
44
45
  */
45
- readonly thinking: { enabled: boolean; budgetTokens?: number } | undefined;
46
+ readonly thinking: AgentConfig['thinking'];
46
47
 
47
48
  private _state: AgentState = { status: 'idle' };
48
49
  private _inferenceStartedAt = 0;
49
50
  private _streamId = 0;
50
51
  lastStreamInputTokens = 0;
51
52
  maxStreamTokens: number;
53
+ /** Per-agent context compile budget (input tokens). When unset, the
54
+ * ContextManager's built-in default applies. reserveForResponse uses
55
+ * this agent's maxTokens. */
56
+ contextBudgetTokens?: number;
52
57
  private contextManager: ContextManager;
53
58
  private membrane: Membrane;
54
59
 
@@ -66,6 +71,7 @@ export class Agent {
66
71
  this.temperature = config.temperature;
67
72
  this.thinking = config.thinking;
68
73
  this.maxStreamTokens = config.maxStreamTokens ?? 150_000;
74
+ this.contextBudgetTokens = config.contextBudgetTokens;
69
75
  this.contextManager = contextManager;
70
76
  this.membrane = membrane;
71
77
  }
@@ -125,8 +131,16 @@ export class Agent {
125
131
  * Step 1 of the inference pipeline — callers can inspect/modify the result
126
132
  * before building a request.
127
133
  */
134
+ /** Resolve the compile budget: explicit arg wins, else the per-agent
135
+ * configured context budget (if any), else the ContextManager default. */
136
+ private resolveBudget(budget?: TokenBudget): TokenBudget | undefined {
137
+ if (budget) return budget;
138
+ if (this.contextBudgetTokens === undefined) return undefined;
139
+ return { maxTokens: this.contextBudgetTokens, reserveForResponse: this.maxTokens };
140
+ }
141
+
128
142
  async compileContext(budget?: TokenBudget): Promise<CompileResult> {
129
- return this.contextManager.compile(budget);
143
+ return this.contextManager.compile(this.resolveBudget(budget));
130
144
  }
131
145
 
132
146
  /**
@@ -138,7 +152,7 @@ export class Agent {
138
152
  budget?: TokenBudget,
139
153
  injections?: ContextInjection[]
140
154
  ): Promise<CompileResult> {
141
- return this.contextManager.compile(budget, injections);
155
+ return this.contextManager.compile(this.resolveBudget(budget), injections);
142
156
  }
143
157
 
144
158
  // ==========================================================================
@@ -290,22 +304,21 @@ export class Agent {
290
304
  }
291
305
 
292
306
  /**
293
- * Start a yielding stream with context injections.
294
- * Same as startStream but passes injections through to compile.
307
+ * Build the membrane-normalized request that WOULD be emitted for this
308
+ * agent's next activation, given the supplied tools and injections.
309
+ *
310
+ * This is the single source of truth for request assembly, shared by the
311
+ * real activation path (`startStreamWithInjections`) and debug/preview
312
+ * tooling (`Framework.previewActivation`). It is pure and non-mutating:
313
+ * it does not touch agent state and does not call the membrane, and
314
+ * `ContextManager.compile` is itself side-effect-free (compression runs in
315
+ * the background). Safe to call regardless of the agent's current status.
295
316
  */
296
- async startStreamWithInjections(
317
+ async buildActivationRequest(
297
318
  availableTools: ToolDefinition[],
298
319
  injections?: ContextInjection[],
299
320
  budget?: TokenBudget
300
- ): Promise<StartStreamResult> {
301
- if (this._state.status !== 'idle') {
302
- throw new Error(`Agent ${this.name} cannot start stream in state ${this._state.status}`);
303
- }
304
-
305
- this._streamId++;
306
- this._inferenceStartedAt = Date.now();
307
- this.lastStreamInputTokens = 0;
308
-
321
+ ): Promise<NormalizedRequest> {
309
322
  let { messages, systemInjections } = await this.compileWithInjections(budget, injections);
310
323
 
311
324
  // Safety: ensure messages don't end with an assistant message.
@@ -318,7 +331,7 @@ export class Agent {
318
331
  }];
319
332
  }
320
333
 
321
- const request: NormalizedRequest = {
334
+ return {
322
335
  messages,
323
336
  system: this.buildSystemPrompt(systemInjections),
324
337
  config: {
@@ -331,6 +344,26 @@ export class Agent {
331
344
  promptCaching: true,
332
345
  assistantParticipant: this.name,
333
346
  };
347
+ }
348
+
349
+ /**
350
+ * Start a yielding stream with context injections.
351
+ * Same as startStream but passes injections through to compile.
352
+ */
353
+ async startStreamWithInjections(
354
+ availableTools: ToolDefinition[],
355
+ injections?: ContextInjection[],
356
+ budget?: TokenBudget
357
+ ): Promise<StartStreamResult> {
358
+ if (this._state.status !== 'idle') {
359
+ throw new Error(`Agent ${this.name} cannot start stream in state ${this._state.status}`);
360
+ }
361
+
362
+ this._streamId++;
363
+ this._inferenceStartedAt = Date.now();
364
+ this.lastStreamInputTokens = 0;
365
+
366
+ const request = await this.buildActivationRequest(availableTools, injections, budget);
334
367
 
335
368
  const stream = this.membrane.streamYielding(request, {
336
369
  emitTokens: true,
@@ -509,13 +542,15 @@ export class Agent {
509
542
  }
510
543
 
511
544
  private buildToolResultMessages(results: CompletedToolCall[]): NormalizedMessage[] {
512
- // Tool results go as a user message with tool_result blocks
545
+ // Tool results go as a user message with tool_result blocks. The history
546
+ // serializer turns MCP image blocks into `[image: type, size]` so the
547
+ // persisted transcript stays small and survives truncation.
513
548
  const content = results.map((r) => ({
514
549
  type: 'tool_result' as const,
515
550
  toolUseId: r.id,
516
551
  content: r.result.isError
517
552
  ? r.result.error ?? 'Unknown error'
518
- : JSON.stringify(r.result.data),
553
+ : toolResultDataToHistoryString(r.result.data),
519
554
  isError: r.result.isError,
520
555
  }));
521
556