@animalabs/agent-framework 0.1.0 → 0.2.0

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 (84) hide show
  1. package/dist/src/framework.d.ts +5 -0
  2. package/dist/src/framework.d.ts.map +1 -1
  3. package/dist/src/framework.js +91 -8
  4. package/dist/src/framework.js.map +1 -1
  5. package/dist/src/gate/event-gate.d.ts +5 -0
  6. package/dist/src/gate/event-gate.d.ts.map +1 -1
  7. package/dist/src/gate/event-gate.js +104 -6
  8. package/dist/src/gate/event-gate.js.map +1 -1
  9. package/dist/src/gate/types.d.ts +31 -0
  10. package/dist/src/gate/types.d.ts.map +1 -1
  11. package/dist/src/index.d.ts +2 -0
  12. package/dist/src/index.d.ts.map +1 -1
  13. package/dist/src/index.js +2 -0
  14. package/dist/src/index.js.map +1 -1
  15. package/dist/src/mcpl/channel-registry.d.ts +11 -0
  16. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  17. package/dist/src/mcpl/channel-registry.js +40 -1
  18. package/dist/src/mcpl/channel-registry.js.map +1 -1
  19. package/dist/src/mcpl/push-handler.js +1 -1
  20. package/dist/src/mcpl/push-handler.js.map +1 -1
  21. package/dist/src/mcpl/types.d.ts +15 -0
  22. package/dist/src/mcpl/types.d.ts.map +1 -1
  23. package/dist/src/mcpl/types.js.map +1 -1
  24. package/dist/src/modules/workspace/index.d.ts +36 -1
  25. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  26. package/dist/src/modules/workspace/index.js +210 -32
  27. package/dist/src/modules/workspace/index.js.map +1 -1
  28. package/dist/src/modules/workspace/sync.d.ts +7 -2
  29. package/dist/src/modules/workspace/sync.d.ts.map +1 -1
  30. package/dist/src/modules/workspace/sync.js +2 -2
  31. package/dist/src/modules/workspace/sync.js.map +1 -1
  32. package/dist/src/modules/workspace/types.d.ts +44 -3
  33. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  34. package/dist/src/modules/workspace/types.js +8 -1
  35. package/dist/src/modules/workspace/types.js.map +1 -1
  36. package/dist/src/modules/workspace/watcher.d.ts +28 -3
  37. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  38. package/dist/src/modules/workspace/watcher.js +53 -12
  39. package/dist/src/modules/workspace/watcher.js.map +1 -1
  40. package/dist/src/types/trace.d.ts +16 -0
  41. package/dist/src/types/trace.d.ts.map +1 -1
  42. package/dist/src/usage/index.d.ts +3 -0
  43. package/dist/src/usage/index.d.ts.map +1 -0
  44. package/dist/src/usage/index.js +2 -0
  45. package/dist/src/usage/index.js.map +1 -0
  46. package/dist/src/usage/types.d.ts +28 -0
  47. package/dist/src/usage/types.d.ts.map +1 -0
  48. package/dist/src/usage/types.js +2 -0
  49. package/dist/src/usage/types.js.map +1 -0
  50. package/dist/src/usage/usage-tracker.d.ts +33 -0
  51. package/dist/src/usage/usage-tracker.d.ts.map +1 -0
  52. package/dist/src/usage/usage-tracker.js +115 -0
  53. package/dist/src/usage/usage-tracker.js.map +1 -0
  54. package/dist/test/event-gate.test.js +135 -16
  55. package/dist/test/event-gate.test.js.map +1 -1
  56. package/dist/test/mcpl-gate-roundtrip.test.d.ts +2 -0
  57. package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +1 -0
  58. package/dist/test/mcpl-gate-roundtrip.test.js +140 -0
  59. package/dist/test/mcpl-gate-roundtrip.test.js.map +1 -0
  60. package/dist/test/usage-tracker.test.d.ts +2 -0
  61. package/dist/test/usage-tracker.test.d.ts.map +1 -0
  62. package/dist/test/usage-tracker.test.js +129 -0
  63. package/dist/test/usage-tracker.test.js.map +1 -0
  64. package/dist/test/workspace-watcher.test.d.ts +2 -0
  65. package/dist/test/workspace-watcher.test.d.ts.map +1 -0
  66. package/dist/test/workspace-watcher.test.js +90 -0
  67. package/dist/test/workspace-watcher.test.js.map +1 -0
  68. package/dist/tsconfig.tsbuildinfo +1 -1
  69. package/package.json +3 -3
  70. package/src/framework.ts +104 -8
  71. package/src/gate/event-gate.ts +106 -6
  72. package/src/gate/types.ts +28 -0
  73. package/src/index.ts +4 -0
  74. package/src/mcpl/channel-registry.ts +45 -1
  75. package/src/mcpl/push-handler.ts +1 -1
  76. package/src/mcpl/types.ts +16 -0
  77. package/src/modules/workspace/index.ts +228 -37
  78. package/src/modules/workspace/sync.ts +11 -4
  79. package/src/modules/workspace/types.ts +59 -3
  80. package/src/modules/workspace/watcher.ts +64 -15
  81. package/src/types/trace.ts +19 -1
  82. package/src/usage/index.ts +2 -0
  83. package/src/usage/types.ts +27 -0
  84. package/src/usage/usage-tracker.ts +141 -0
@@ -0,0 +1,27 @@
1
+ export interface SessionUsage {
2
+ inputTokens: number;
3
+ outputTokens: number;
4
+ cacheCreationTokens: number;
5
+ cacheReadTokens: number;
6
+ estimatedCost?: { total: number; currency: string };
7
+ }
8
+
9
+ export interface AgentUsage {
10
+ agentName: string;
11
+ usage: SessionUsage;
12
+ inferenceCount: number;
13
+ }
14
+
15
+ export interface SessionUsageSnapshot {
16
+ totals: SessionUsage;
17
+ byAgent: AgentUsage[];
18
+ inferenceCount: number;
19
+ }
20
+
21
+ /** Trace event emitted by UsageTracker after each inference completion. */
22
+ export interface UsageUpdatedEvent {
23
+ type: 'usage:updated';
24
+ totals: SessionUsage;
25
+ agentName: string;
26
+ inferenceCount: number;
27
+ }
@@ -0,0 +1,141 @@
1
+ import type { SessionUsage, SessionUsageSnapshot, UsageUpdatedEvent } from './types.js';
2
+
3
+ function snapshotUsage(usage: SessionUsage): SessionUsage {
4
+ return {
5
+ ...usage,
6
+ estimatedCost: usage.estimatedCost ? { ...usage.estimatedCost } : undefined,
7
+ };
8
+ }
9
+
10
+ function accumulateUsage(
11
+ target: SessionUsage,
12
+ tokens: { inputTokens: number; outputTokens: number; cacheCreationTokens: number; cacheReadTokens: number },
13
+ estimatedCost?: { total: number; currency: string }
14
+ ): void {
15
+ target.inputTokens += tokens.inputTokens;
16
+ target.outputTokens += tokens.outputTokens;
17
+ target.cacheCreationTokens += tokens.cacheCreationTokens;
18
+ target.cacheReadTokens += tokens.cacheReadTokens;
19
+ if (estimatedCost) {
20
+ if (!target.estimatedCost) {
21
+ target.estimatedCost = { total: 0, currency: estimatedCost.currency };
22
+ } else if (target.estimatedCost.currency !== estimatedCost.currency) {
23
+ // Mixed currencies — drop cost tracking rather than produce garbage
24
+ target.estimatedCost = undefined;
25
+ return;
26
+ }
27
+ target.estimatedCost.total += estimatedCost.total;
28
+ }
29
+ }
30
+
31
+ function parseUsage(raw: unknown): SessionUsage | null {
32
+ if (!raw || typeof raw !== 'object') return null;
33
+ const o = raw as Record<string, unknown>;
34
+ if (typeof o.inputTokens !== 'number' || typeof o.outputTokens !== 'number') return null;
35
+ return {
36
+ inputTokens: o.inputTokens,
37
+ outputTokens: o.outputTokens as number,
38
+ cacheCreationTokens: typeof o.cacheCreationTokens === 'number' ? o.cacheCreationTokens : 0,
39
+ cacheReadTokens: typeof o.cacheReadTokens === 'number' ? o.cacheReadTokens : 0,
40
+ estimatedCost: o.estimatedCost && typeof o.estimatedCost === 'object'
41
+ ? { total: (o.estimatedCost as any).total, currency: (o.estimatedCost as any).currency }
42
+ : undefined,
43
+ };
44
+ }
45
+
46
+ export interface PersistedUsageState {
47
+ totals: SessionUsage;
48
+ byAgent: Array<{ agentName: string; usage: SessionUsage; inferenceCount: number }>;
49
+ inferenceCount: number;
50
+ }
51
+
52
+ export class UsageTracker {
53
+ private totals: SessionUsage = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
54
+ private byAgent: Map<string, { usage: SessionUsage; inferenceCount: number }> = new Map();
55
+ private inferenceCount = 0;
56
+ private emitTrace: (event: UsageUpdatedEvent) => void;
57
+
58
+ constructor(opts: {
59
+ emitTrace: (event: UsageUpdatedEvent) => void;
60
+ restored?: PersistedUsageState;
61
+ }) {
62
+ this.emitTrace = opts.emitTrace;
63
+ if (opts.restored) {
64
+ this.restoreFrom(opts.restored);
65
+ }
66
+ }
67
+
68
+ private restoreFrom(state: PersistedUsageState): void {
69
+ const totals = parseUsage(state.totals);
70
+ if (!totals) return;
71
+ this.totals = totals;
72
+ this.inferenceCount = typeof state.inferenceCount === 'number' ? state.inferenceCount : 0;
73
+ if (Array.isArray(state.byAgent)) {
74
+ for (const entry of state.byAgent) {
75
+ const usage = parseUsage(entry.usage);
76
+ if (usage && typeof entry.agentName === 'string') {
77
+ this.byAgent.set(entry.agentName, {
78
+ usage,
79
+ inferenceCount: typeof entry.inferenceCount === 'number' ? entry.inferenceCount : 0,
80
+ });
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ toJSON(): PersistedUsageState {
87
+ return {
88
+ totals: snapshotUsage(this.totals),
89
+ byAgent: [...this.byAgent.entries()].map(([name, data]) => ({
90
+ agentName: name,
91
+ usage: snapshotUsage(data.usage),
92
+ inferenceCount: data.inferenceCount,
93
+ })),
94
+ inferenceCount: this.inferenceCount,
95
+ };
96
+ }
97
+
98
+ onInferenceCompleted(agentName: string, usage: {
99
+ inputTokens: number;
100
+ outputTokens: number;
101
+ cacheCreationTokens?: number;
102
+ cacheReadTokens?: number;
103
+ }, estimatedCost?: { total: number; currency: string }): void {
104
+ const tokens = {
105
+ inputTokens: usage.inputTokens,
106
+ outputTokens: usage.outputTokens,
107
+ cacheCreationTokens: usage.cacheCreationTokens ?? 0,
108
+ cacheReadTokens: usage.cacheReadTokens ?? 0,
109
+ };
110
+
111
+ accumulateUsage(this.totals, tokens, estimatedCost);
112
+ this.inferenceCount++;
113
+
114
+ let agent = this.byAgent.get(agentName);
115
+ if (!agent) {
116
+ agent = { usage: { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 }, inferenceCount: 0 };
117
+ this.byAgent.set(agentName, agent);
118
+ }
119
+ accumulateUsage(agent.usage, tokens, estimatedCost);
120
+ agent.inferenceCount++;
121
+
122
+ this.emitTrace({
123
+ type: 'usage:updated',
124
+ totals: snapshotUsage(this.totals),
125
+ agentName,
126
+ inferenceCount: this.inferenceCount,
127
+ });
128
+ }
129
+
130
+ getSnapshot(): SessionUsageSnapshot {
131
+ return {
132
+ totals: snapshotUsage(this.totals),
133
+ byAgent: [...this.byAgent.entries()].map(([name, data]) => ({
134
+ agentName: name,
135
+ usage: snapshotUsage(data.usage),
136
+ inferenceCount: data.inferenceCount,
137
+ })),
138
+ inferenceCount: this.inferenceCount,
139
+ };
140
+ }
141
+ }