@charming_groot/core 0.1.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.
- package/dist/config.d.ts +669 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +99 -0
- package/dist/config.js.map +1 -0
- package/dist/errors/base-error.d.ts +29 -0
- package/dist/errors/base-error.d.ts.map +1 -0
- package/dist/errors/base-error.js +57 -0
- package/dist/errors/base-error.js.map +1 -0
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +2 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/event-bus.d.ts +14 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +64 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +33 -0
- package/dist/logger.js.map +1 -0
- package/dist/registry.d.ts +15 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +46 -0
- package/dist/registry.js.map +1 -0
- package/dist/run-context.d.ts +20 -0
- package/dist/run-context.d.ts.map +1 -0
- package/dist/run-context.js +39 -0
- package/dist/run-context.js.map +1 -0
- package/dist/types/auth.d.ts +56 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +2 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/types/common.d.ts +15 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +2 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/events.d.ts +77 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +2 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/provider.d.ts +42 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/provider.js +2 -0
- package/dist/types/provider.js.map +1 -0
- package/dist/types/sandbox.d.ts +27 -0
- package/dist/types/sandbox.d.ts.map +1 -0
- package/dist/types/sandbox.js +2 -0
- package/dist/types/sandbox.js.map +1 -0
- package/dist/types/tool.d.ts +43 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +8 -0
- package/dist/types/tool.js.map +1 -0
- package/package.json +34 -0
- package/src/config.ts +119 -0
- package/src/errors/base-error.ts +66 -0
- package/src/errors/index.ts +10 -0
- package/src/event-bus.ts +78 -0
- package/src/index.ts +74 -0
- package/src/logger.ts +43 -0
- package/src/registry.ts +62 -0
- package/src/run-context.ts +48 -0
- package/src/types/auth.ts +79 -0
- package/src/types/common.ts +22 -0
- package/src/types/events.ts +24 -0
- package/src/types/index.ts +54 -0
- package/src/types/provider.ts +50 -0
- package/src/types/sandbox.ts +29 -0
- package/src/types/tool.ts +37 -0
- package/tests/config.test.ts +98 -0
- package/tests/errors.test.ts +87 -0
- package/tests/event-bus.test.ts +89 -0
- package/tests/logger.test.ts +34 -0
- package/tests/registry.test.ts +90 -0
- package/tests/run-context.test.ts +80 -0
- package/tsconfig.json +9 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { EventBus } from '../src/event-bus.js';
|
|
3
|
+
|
|
4
|
+
describe('EventBus', () => {
|
|
5
|
+
let bus: EventBus;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
bus = new EventBus();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should emit and receive events', () => {
|
|
12
|
+
const handler = vi.fn();
|
|
13
|
+
bus.on('agent:start', handler);
|
|
14
|
+
bus.emit('agent:start', { runId: 'run-1' });
|
|
15
|
+
expect(handler).toHaveBeenCalledWith({ runId: 'run-1' });
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should support multiple listeners for same event', () => {
|
|
19
|
+
const handler1 = vi.fn();
|
|
20
|
+
const handler2 = vi.fn();
|
|
21
|
+
bus.on('agent:start', handler1);
|
|
22
|
+
bus.on('agent:start', handler2);
|
|
23
|
+
bus.emit('agent:start', { runId: 'run-1' });
|
|
24
|
+
expect(handler1).toHaveBeenCalledOnce();
|
|
25
|
+
expect(handler2).toHaveBeenCalledOnce();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should not fire handler after unsubscribe', () => {
|
|
29
|
+
const handler = vi.fn();
|
|
30
|
+
const unsub = bus.on('agent:start', handler);
|
|
31
|
+
unsub();
|
|
32
|
+
bus.emit('agent:start', { runId: 'run-1' });
|
|
33
|
+
expect(handler).not.toHaveBeenCalled();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should fire once listener only once', () => {
|
|
37
|
+
const handler = vi.fn();
|
|
38
|
+
bus.once('agent:start', handler);
|
|
39
|
+
bus.emit('agent:start', { runId: 'run-1' });
|
|
40
|
+
bus.emit('agent:start', { runId: 'run-2' });
|
|
41
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
42
|
+
expect(handler).toHaveBeenCalledWith({ runId: 'run-1' });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should remove all listeners for an event', () => {
|
|
46
|
+
const handler1 = vi.fn();
|
|
47
|
+
const handler2 = vi.fn();
|
|
48
|
+
bus.on('agent:start', handler1);
|
|
49
|
+
bus.on('agent:end', handler2);
|
|
50
|
+
bus.removeAllListeners('agent:start');
|
|
51
|
+
bus.emit('agent:start', { runId: 'run-1' });
|
|
52
|
+
bus.emit('agent:end', { runId: 'run-1', reason: 'done' });
|
|
53
|
+
expect(handler1).not.toHaveBeenCalled();
|
|
54
|
+
expect(handler2).toHaveBeenCalledOnce();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should remove all listeners when no event specified', () => {
|
|
58
|
+
const handler1 = vi.fn();
|
|
59
|
+
const handler2 = vi.fn();
|
|
60
|
+
bus.on('agent:start', handler1);
|
|
61
|
+
bus.on('agent:end', handler2);
|
|
62
|
+
bus.removeAllListeners();
|
|
63
|
+
bus.emit('agent:start', { runId: 'run-1' });
|
|
64
|
+
bus.emit('agent:end', { runId: 'run-1', reason: 'done' });
|
|
65
|
+
expect(handler1).not.toHaveBeenCalled();
|
|
66
|
+
expect(handler2).not.toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should report listener count', () => {
|
|
70
|
+
expect(bus.listenerCount('agent:start')).toBe(0);
|
|
71
|
+
const unsub = bus.on('agent:start', vi.fn());
|
|
72
|
+
bus.on('agent:start', vi.fn());
|
|
73
|
+
expect(bus.listenerCount('agent:start')).toBe(2);
|
|
74
|
+
unsub();
|
|
75
|
+
expect(bus.listenerCount('agent:start')).toBe(1);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should not throw when emitting with no listeners', () => {
|
|
79
|
+
expect(() => bus.emit('agent:start', { runId: 'run-1' })).not.toThrow();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should handle once unsubscribe before emit', () => {
|
|
83
|
+
const handler = vi.fn();
|
|
84
|
+
const unsub = bus.once('agent:start', handler);
|
|
85
|
+
unsub();
|
|
86
|
+
bus.emit('agent:start', { runId: 'run-1' });
|
|
87
|
+
expect(handler).not.toHaveBeenCalled();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { createLogger, createChildLogger, getRootLogger } from '../src/logger.js';
|
|
3
|
+
|
|
4
|
+
describe('Logger', () => {
|
|
5
|
+
it('should create a named logger', () => {
|
|
6
|
+
const logger = createLogger('test-module');
|
|
7
|
+
expect(logger).toBeDefined();
|
|
8
|
+
expect(typeof logger.info).toBe('function');
|
|
9
|
+
expect(typeof logger.error).toBe('function');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should create a logger with custom level', () => {
|
|
13
|
+
const logger = createLogger('debug-module', 'debug');
|
|
14
|
+
expect(logger.level).toBe('debug');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should return root logger', () => {
|
|
18
|
+
const root = getRootLogger();
|
|
19
|
+
expect(root).toBeDefined();
|
|
20
|
+
expect(typeof root.info).toBe('function');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should return same root logger instance', () => {
|
|
24
|
+
const root1 = getRootLogger();
|
|
25
|
+
const root2 = getRootLogger();
|
|
26
|
+
expect(root1).toBe(root2);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should create a child logger', () => {
|
|
30
|
+
const child = createChildLogger('child-module');
|
|
31
|
+
expect(child).toBeDefined();
|
|
32
|
+
expect(typeof child.info).toBe('function');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { Registry } from '../src/registry.js';
|
|
3
|
+
import { RegistryError } from '../src/errors/base-error.js';
|
|
4
|
+
|
|
5
|
+
describe('Registry', () => {
|
|
6
|
+
let registry: Registry<string>;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
registry = new Registry<string>('TestItem');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should register and retrieve an item', () => {
|
|
13
|
+
registry.register('foo', 'bar');
|
|
14
|
+
expect(registry.get('foo')).toBe('bar');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should throw on duplicate registration', () => {
|
|
18
|
+
registry.register('foo', 'bar');
|
|
19
|
+
expect(() => registry.register('foo', 'baz')).toThrow(RegistryError);
|
|
20
|
+
expect(() => registry.register('foo', 'baz')).toThrow(
|
|
21
|
+
"TestItem 'foo' is already registered"
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should throw on get for unregistered item', () => {
|
|
26
|
+
expect(() => registry.get('missing')).toThrow(RegistryError);
|
|
27
|
+
expect(() => registry.get('missing')).toThrow(
|
|
28
|
+
"TestItem 'missing' is not registered"
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should return undefined for tryGet on missing item', () => {
|
|
33
|
+
expect(registry.tryGet('missing')).toBeUndefined();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should report has correctly', () => {
|
|
37
|
+
registry.register('exists', 'value');
|
|
38
|
+
expect(registry.has('exists')).toBe(true);
|
|
39
|
+
expect(registry.has('nope')).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should return all items', () => {
|
|
43
|
+
registry.register('a', '1');
|
|
44
|
+
registry.register('b', '2');
|
|
45
|
+
const all = registry.getAll();
|
|
46
|
+
expect(all.size).toBe(2);
|
|
47
|
+
expect(all.get('a')).toBe('1');
|
|
48
|
+
expect(all.get('b')).toBe('2');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should return all names', () => {
|
|
52
|
+
registry.register('x', '1');
|
|
53
|
+
registry.register('y', '2');
|
|
54
|
+
expect(registry.getAllNames()).toEqual(['x', 'y']);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should unregister an item', () => {
|
|
58
|
+
registry.register('item', 'val');
|
|
59
|
+
expect(registry.unregister('item')).toBe(true);
|
|
60
|
+
expect(registry.has('item')).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should throw when unregistering non-existent item', () => {
|
|
64
|
+
expect(() => registry.unregister('ghost')).toThrow(RegistryError);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should clear all items', () => {
|
|
68
|
+
registry.register('a', '1');
|
|
69
|
+
registry.register('b', '2');
|
|
70
|
+
registry.clear();
|
|
71
|
+
expect(registry.size).toBe(0);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should track size correctly', () => {
|
|
75
|
+
expect(registry.size).toBe(0);
|
|
76
|
+
registry.register('a', '1');
|
|
77
|
+
expect(registry.size).toBe(1);
|
|
78
|
+
registry.register('b', '2');
|
|
79
|
+
expect(registry.size).toBe(2);
|
|
80
|
+
registry.unregister('a');
|
|
81
|
+
expect(registry.size).toBe(1);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should work with complex types', () => {
|
|
85
|
+
const objRegistry = new Registry<{ id: number; name: string }>('Object');
|
|
86
|
+
const item = { id: 1, name: 'test' };
|
|
87
|
+
objRegistry.register('obj', item);
|
|
88
|
+
expect(objRegistry.get('obj')).toBe(item);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { RunContext } from '../src/run-context.js';
|
|
3
|
+
import { EventBus } from '../src/event-bus.js';
|
|
4
|
+
import type { AgentConfig } from '../src/config.js';
|
|
5
|
+
|
|
6
|
+
const TEST_CONFIG: AgentConfig = {
|
|
7
|
+
provider: {
|
|
8
|
+
providerId: 'test',
|
|
9
|
+
model: 'test-model',
|
|
10
|
+
auth: { type: 'api-key' as const, apiKey: 'test-key' },
|
|
11
|
+
maxTokens: 4096,
|
|
12
|
+
temperature: 0.7,
|
|
13
|
+
},
|
|
14
|
+
maxIterations: 50,
|
|
15
|
+
workingDirectory: '/tmp/test',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe('RunContext', () => {
|
|
19
|
+
it('should generate a unique runId', () => {
|
|
20
|
+
const ctx1 = new RunContext(TEST_CONFIG);
|
|
21
|
+
const ctx2 = new RunContext(TEST_CONFIG);
|
|
22
|
+
expect(ctx1.runId).toBeTruthy();
|
|
23
|
+
expect(ctx2.runId).toBeTruthy();
|
|
24
|
+
expect(ctx1.runId).not.toBe(ctx2.runId);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should use provided EventBus', () => {
|
|
28
|
+
const bus = new EventBus();
|
|
29
|
+
const ctx = new RunContext(TEST_CONFIG, bus);
|
|
30
|
+
expect(ctx.eventBus).toBe(bus);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should create a default EventBus if none provided', () => {
|
|
34
|
+
const ctx = new RunContext(TEST_CONFIG);
|
|
35
|
+
expect(ctx.eventBus).toBeInstanceOf(EventBus);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should expose config and workingDirectory', () => {
|
|
39
|
+
const ctx = new RunContext(TEST_CONFIG);
|
|
40
|
+
expect(ctx.config).toBe(TEST_CONFIG);
|
|
41
|
+
expect(ctx.workingDirectory).toBe('/tmp/test');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should set and get metadata', () => {
|
|
45
|
+
const ctx = new RunContext(TEST_CONFIG);
|
|
46
|
+
ctx.setMetadata('key', 'value');
|
|
47
|
+
expect(ctx.getMetadata('key')).toBe('value');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should return undefined for missing metadata', () => {
|
|
51
|
+
const ctx = new RunContext(TEST_CONFIG);
|
|
52
|
+
expect(ctx.getMetadata('missing')).toBeUndefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should return all metadata', () => {
|
|
56
|
+
const ctx = new RunContext(TEST_CONFIG);
|
|
57
|
+
ctx.setMetadata('a', 1);
|
|
58
|
+
ctx.setMetadata('b', 'two');
|
|
59
|
+
const all = ctx.getAllMetadata();
|
|
60
|
+
expect(all.size).toBe(2);
|
|
61
|
+
expect(all.get('a')).toBe(1);
|
|
62
|
+
expect(all.get('b')).toBe('two');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should support abort', () => {
|
|
66
|
+
const ctx = new RunContext(TEST_CONFIG);
|
|
67
|
+
expect(ctx.isAborted).toBe(false);
|
|
68
|
+
ctx.abort('user cancelled');
|
|
69
|
+
expect(ctx.isAborted).toBe(true);
|
|
70
|
+
expect(ctx.signal.aborted).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should have a createdAt timestamp', () => {
|
|
74
|
+
const before = new Date();
|
|
75
|
+
const ctx = new RunContext(TEST_CONFIG);
|
|
76
|
+
const after = new Date();
|
|
77
|
+
expect(ctx.createdAt.getTime()).toBeGreaterThanOrEqual(before.getTime());
|
|
78
|
+
expect(ctx.createdAt.getTime()).toBeLessThanOrEqual(after.getTime());
|
|
79
|
+
});
|
|
80
|
+
});
|
package/tsconfig.json
ADDED