skyloom 1.12.0 → 1.13.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 (135) hide show
  1. package/.github/workflows/ci.yml +36 -36
  2. package/README.md +142 -46
  3. package/config/default.yaml +43 -47
  4. package/config/models.yaml +155 -155
  5. package/config/providers.yaml +39 -39
  6. package/config/skills/api_integrator/SKILL.md +15 -15
  7. package/config/skills/arch_designer/SKILL.md +13 -13
  8. package/config/skills/ci_cd_manager/SKILL.md +14 -14
  9. package/config/skills/code_analysis/SKILL.md +13 -13
  10. package/config/skills/code_generator/SKILL.md +12 -12
  11. package/config/skills/code_reviewer/SKILL.md +13 -13
  12. package/config/skills/content_writer/SKILL.md +14 -14
  13. package/config/skills/data_transformer/SKILL.md +15 -15
  14. package/config/skills/document_analysis/SKILL.md +13 -13
  15. package/config/skills/emotional_companion/SKILL.md +15 -15
  16. package/config/skills/performance_checker/SKILL.md +14 -14
  17. package/config/skills/security_auditor/SKILL.md +14 -14
  18. package/config/skills/self_evolve/SKILL.md +13 -13
  19. package/config/skills/sys_operator/SKILL.md +15 -15
  20. package/config/skills/task_planner/SKILL.md +14 -14
  21. package/config/skills/web_research/SKILL.md +14 -14
  22. package/config/skills/workflow_designer/SKILL.md +13 -13
  23. package/dist/agents/dew.js +52 -52
  24. package/dist/agents/fair.js +84 -84
  25. package/dist/agents/fog.js +30 -30
  26. package/dist/agents/frost.js +32 -32
  27. package/dist/agents/rain.js +32 -32
  28. package/dist/agents/snow.js +68 -68
  29. package/dist/cli/main.js +103 -51
  30. package/dist/cli/main.js.map +1 -1
  31. package/dist/cli/tui.d.ts.map +1 -1
  32. package/dist/cli/tui.js +8 -1
  33. package/dist/cli/tui.js.map +1 -1
  34. package/dist/core/agent/task.d.ts +58 -0
  35. package/dist/core/agent/task.d.ts.map +1 -0
  36. package/dist/core/agent/task.js +83 -0
  37. package/dist/core/agent/task.js.map +1 -0
  38. package/dist/core/agent.d.ts +2 -45
  39. package/dist/core/agent.d.ts.map +1 -1
  40. package/dist/core/agent.js +61 -145
  41. package/dist/core/agent.js.map +1 -1
  42. package/dist/core/agent_helpers.d.ts +10 -0
  43. package/dist/core/agent_helpers.d.ts.map +1 -1
  44. package/dist/core/agent_helpers.js +39 -0
  45. package/dist/core/agent_helpers.js.map +1 -1
  46. package/dist/core/catalog.d.ts +71 -0
  47. package/dist/core/catalog.d.ts.map +1 -0
  48. package/dist/core/catalog.js +176 -0
  49. package/dist/core/catalog.js.map +1 -0
  50. package/dist/core/config.d.ts +8 -0
  51. package/dist/core/config.d.ts.map +1 -1
  52. package/dist/core/config.js +12 -4
  53. package/dist/core/config.js.map +1 -1
  54. package/dist/core/factory.js +16 -16
  55. package/dist/core/llm.d.ts +7 -0
  56. package/dist/core/llm.d.ts.map +1 -1
  57. package/dist/core/llm.js +139 -7
  58. package/dist/core/llm.js.map +1 -1
  59. package/dist/core/longdoc.js +5 -5
  60. package/dist/core/memory.d.ts.map +1 -1
  61. package/dist/core/memory.js +69 -62
  62. package/dist/core/memory.js.map +1 -1
  63. package/dist/core/theme.d.ts +46 -0
  64. package/dist/core/theme.d.ts.map +1 -0
  65. package/dist/core/theme.js +42 -0
  66. package/dist/core/theme.js.map +1 -0
  67. package/dist/web/server.js +542 -519
  68. package/dist/web/server.js.map +1 -1
  69. package/docs/AESTHETIC_DESIGN.md +144 -0
  70. package/docs/OPTIMIZATION_PLAN.md +178 -0
  71. package/package.json +60 -60
  72. package/scripts/install.js +48 -48
  73. package/scripts/link.js +10 -10
  74. package/setup.bat +79 -79
  75. package/skill-test-ty2fOA/test.md +10 -10
  76. package/src/agents/dew.ts +70 -70
  77. package/src/agents/fair.ts +102 -102
  78. package/src/agents/fog.ts +48 -48
  79. package/src/agents/frost.ts +50 -50
  80. package/src/agents/rain.ts +50 -50
  81. package/src/agents/snow.ts +239 -239
  82. package/src/cli/main.ts +425 -372
  83. package/src/cli/mode.ts +58 -58
  84. package/src/cli/tui.ts +272 -269
  85. package/src/core/agent/task.ts +100 -0
  86. package/src/core/agent.ts +1446 -1549
  87. package/src/core/agent_helpers.ts +496 -461
  88. package/src/core/arbitrate.ts +162 -162
  89. package/src/core/catalog.ts +178 -0
  90. package/src/core/checkpoint.ts +94 -94
  91. package/src/core/config.ts +20 -4
  92. package/src/core/estimate.ts +104 -104
  93. package/src/core/evolve.ts +191 -191
  94. package/src/core/factory.ts +627 -627
  95. package/src/core/filter.ts +103 -103
  96. package/src/core/graph.ts +156 -156
  97. package/src/core/icons.ts +53 -53
  98. package/src/core/index.ts +37 -37
  99. package/src/core/learn.ts +146 -146
  100. package/src/core/llm.ts +108 -5
  101. package/src/core/longdoc.ts +155 -155
  102. package/src/core/mcp_server.ts +176 -176
  103. package/src/core/memory.ts +1178 -1171
  104. package/src/core/profile.ts +255 -255
  105. package/src/core/router.ts +124 -124
  106. package/src/core/sandbox.ts +142 -142
  107. package/src/core/security.ts +243 -243
  108. package/src/core/skill.ts +342 -342
  109. package/src/core/theme.ts +65 -0
  110. package/src/core/tool_router.ts +193 -193
  111. package/src/core/vector.ts +152 -152
  112. package/src/core/workspace.ts +150 -150
  113. package/src/plugins/loader.ts +66 -66
  114. package/src/skills/loader.ts +46 -46
  115. package/src/sql.js.d.ts +29 -29
  116. package/src/tools/builtin.ts +380 -380
  117. package/src/tools/computer.ts +269 -269
  118. package/src/tools/delegate.ts +49 -49
  119. package/src/web/server.ts +660 -634
  120. package/src/web/tts.ts +93 -93
  121. package/tests/agent_helpers.test.ts +48 -0
  122. package/tests/bus.test.ts +121 -121
  123. package/tests/catalog.test.ts +86 -0
  124. package/tests/config.test.ts +41 -0
  125. package/tests/icons.test.ts +45 -45
  126. package/tests/memory.test.ts +147 -0
  127. package/tests/router.test.ts +86 -86
  128. package/tests/schemas.test.ts +51 -51
  129. package/tests/semantic.test.ts +83 -83
  130. package/tests/setup.ts +10 -10
  131. package/tests/skill.test.ts +172 -172
  132. package/tests/task.test.ts +60 -0
  133. package/tests/tool.test.ts +108 -108
  134. package/tests/tool_router.test.ts +71 -71
  135. package/vitest.config.ts +17 -17
@@ -1,108 +1,108 @@
1
- /**
2
- * Tests for tool system.
3
- */
4
- import { describe, it, expect, vi } from 'vitest';
5
- import { ToolRegistry, type ToolDefinition } from '../src/core/tool';
6
-
7
- function makeTool(overrides: Partial<ToolDefinition> & { name: string }): ToolDefinition {
8
- return {
9
- name: overrides.name,
10
- description: overrides.description ?? 'Test tool',
11
- parameters: overrides.parameters ?? [],
12
- handler: overrides.handler ?? vi.fn().mockResolvedValue('ok'),
13
- dangerous: overrides.dangerous,
14
- cacheable: overrides.cacheable,
15
- maxRetries: overrides.maxRetries,
16
- retryDelay: overrides.retryDelay,
17
- timeout: overrides.timeout,
18
- };
19
- }
20
-
21
- describe('ToolRegistry', () => {
22
- let registry: ToolRegistry;
23
-
24
- beforeEach(() => {
25
- registry = new ToolRegistry();
26
- });
27
-
28
- it('register and get tool', () => {
29
- const tool = makeTool({ name: 'test_tool' });
30
- registry.register(tool);
31
- expect(registry.get('test_tool')).toBe(tool);
32
- expect(registry.get('nonexistent')).toBeUndefined();
33
- });
34
-
35
- it('list returns all tools', () => {
36
- registry.register(makeTool({ name: 'a', description: 'A' }));
37
- registry.register(makeTool({ name: 'b', description: 'B' }));
38
- expect(registry.list()).toHaveLength(2);
39
- });
40
-
41
- it('listNames returns all names', () => {
42
- registry.register(makeTool({ name: 'alpha', description: 'Alpha' }));
43
- registry.register(makeTool({ name: 'beta', description: 'Beta' }));
44
- const names = registry.listNames();
45
- expect(names).toContain('alpha');
46
- expect(names).toContain('beta');
47
- });
48
-
49
- it('getTools returns all tools', () => {
50
- registry.register(makeTool({ name: 'x', description: 'X' }));
51
- expect(registry.getTools()).toHaveLength(1);
52
- });
53
-
54
- it('reregister overrides existing', () => {
55
- const t1 = makeTool({ name: 't', description: 'v1' });
56
- const t2 = makeTool({ name: 't', description: 'v2' });
57
- registry.register(t1);
58
- registry.register(t2);
59
- expect(registry.get('t')?.description).toBe('v2');
60
- });
61
-
62
- it('unregister removes tool', () => {
63
- registry.register(makeTool({ name: 'temp', description: 'Temp' }));
64
- expect(registry.get('temp')).toBeDefined();
65
- registry.unregister('temp');
66
- expect(registry.get('temp')).toBeUndefined();
67
- });
68
-
69
- it('has checks existence', () => {
70
- registry.register(makeTool({ name: 'exists' }));
71
- expect(registry.has('exists')).toBe(true);
72
- expect(registry.has('missing')).toBe(false);
73
- });
74
-
75
- it('merge copies tools', () => {
76
- const r2 = new ToolRegistry();
77
- r2.register(makeTool({ name: 't2', description: 'T2' }));
78
- registry.merge(r2);
79
- expect(registry.get('t2')).toBeDefined();
80
- });
81
-
82
- it('execute returns result from handler', async () => {
83
- const handler = vi.fn().mockResolvedValue('hello world');
84
- registry.register(makeTool({ name: 'greet', handler }));
85
- const result = await registry.execute('greet', { name: 'world' });
86
- expect(result.success).toBe(true);
87
- expect(result.result).toBe('hello world');
88
- });
89
-
90
- it('execute returns error for unknown tool', async () => {
91
- const result = await registry.execute('unknown', {});
92
- expect(result.success).toBe(false);
93
- expect(result.error).toContain('not found');
94
- });
95
-
96
- it('execute validates required parameters', async () => {
97
- const handler = vi.fn().mockResolvedValue('ok');
98
- registry.register(makeTool({
99
- name: 'needs_path',
100
- parameters: [{ name: 'path', type: 'string', description: 'File path', required: true }],
101
- handler,
102
- }));
103
- const result = await registry.execute('needs_path', {});
104
- expect(result.success).toBe(false);
105
- expect(result.error).toContain('required');
106
- expect(handler).not.toHaveBeenCalled();
107
- });
108
- });
1
+ /**
2
+ * Tests for tool system.
3
+ */
4
+ import { describe, it, expect, vi } from 'vitest';
5
+ import { ToolRegistry, type ToolDefinition } from '../src/core/tool';
6
+
7
+ function makeTool(overrides: Partial<ToolDefinition> & { name: string }): ToolDefinition {
8
+ return {
9
+ name: overrides.name,
10
+ description: overrides.description ?? 'Test tool',
11
+ parameters: overrides.parameters ?? [],
12
+ handler: overrides.handler ?? vi.fn().mockResolvedValue('ok'),
13
+ dangerous: overrides.dangerous,
14
+ cacheable: overrides.cacheable,
15
+ maxRetries: overrides.maxRetries,
16
+ retryDelay: overrides.retryDelay,
17
+ timeout: overrides.timeout,
18
+ };
19
+ }
20
+
21
+ describe('ToolRegistry', () => {
22
+ let registry: ToolRegistry;
23
+
24
+ beforeEach(() => {
25
+ registry = new ToolRegistry();
26
+ });
27
+
28
+ it('register and get tool', () => {
29
+ const tool = makeTool({ name: 'test_tool' });
30
+ registry.register(tool);
31
+ expect(registry.get('test_tool')).toBe(tool);
32
+ expect(registry.get('nonexistent')).toBeUndefined();
33
+ });
34
+
35
+ it('list returns all tools', () => {
36
+ registry.register(makeTool({ name: 'a', description: 'A' }));
37
+ registry.register(makeTool({ name: 'b', description: 'B' }));
38
+ expect(registry.list()).toHaveLength(2);
39
+ });
40
+
41
+ it('listNames returns all names', () => {
42
+ registry.register(makeTool({ name: 'alpha', description: 'Alpha' }));
43
+ registry.register(makeTool({ name: 'beta', description: 'Beta' }));
44
+ const names = registry.listNames();
45
+ expect(names).toContain('alpha');
46
+ expect(names).toContain('beta');
47
+ });
48
+
49
+ it('getTools returns all tools', () => {
50
+ registry.register(makeTool({ name: 'x', description: 'X' }));
51
+ expect(registry.getTools()).toHaveLength(1);
52
+ });
53
+
54
+ it('reregister overrides existing', () => {
55
+ const t1 = makeTool({ name: 't', description: 'v1' });
56
+ const t2 = makeTool({ name: 't', description: 'v2' });
57
+ registry.register(t1);
58
+ registry.register(t2);
59
+ expect(registry.get('t')?.description).toBe('v2');
60
+ });
61
+
62
+ it('unregister removes tool', () => {
63
+ registry.register(makeTool({ name: 'temp', description: 'Temp' }));
64
+ expect(registry.get('temp')).toBeDefined();
65
+ registry.unregister('temp');
66
+ expect(registry.get('temp')).toBeUndefined();
67
+ });
68
+
69
+ it('has checks existence', () => {
70
+ registry.register(makeTool({ name: 'exists' }));
71
+ expect(registry.has('exists')).toBe(true);
72
+ expect(registry.has('missing')).toBe(false);
73
+ });
74
+
75
+ it('merge copies tools', () => {
76
+ const r2 = new ToolRegistry();
77
+ r2.register(makeTool({ name: 't2', description: 'T2' }));
78
+ registry.merge(r2);
79
+ expect(registry.get('t2')).toBeDefined();
80
+ });
81
+
82
+ it('execute returns result from handler', async () => {
83
+ const handler = vi.fn().mockResolvedValue('hello world');
84
+ registry.register(makeTool({ name: 'greet', handler }));
85
+ const result = await registry.execute('greet', { name: 'world' });
86
+ expect(result.success).toBe(true);
87
+ expect(result.result).toBe('hello world');
88
+ });
89
+
90
+ it('execute returns error for unknown tool', async () => {
91
+ const result = await registry.execute('unknown', {});
92
+ expect(result.success).toBe(false);
93
+ expect(result.error).toContain('not found');
94
+ });
95
+
96
+ it('execute validates required parameters', async () => {
97
+ const handler = vi.fn().mockResolvedValue('ok');
98
+ registry.register(makeTool({
99
+ name: 'needs_path',
100
+ parameters: [{ name: 'path', type: 'string', description: 'File path', required: true }],
101
+ handler,
102
+ }));
103
+ const result = await registry.execute('needs_path', {});
104
+ expect(result.success).toBe(false);
105
+ expect(result.error).toContain('required');
106
+ expect(handler).not.toHaveBeenCalled();
107
+ });
108
+ });
@@ -1,71 +1,71 @@
1
- /**
2
- * Tests for tool subset routing.
3
- */
4
- import { describe, it, expect } from 'vitest';
5
- import { selectRelevantTools } from '../src/core/tool_router';
6
- import { ToolRegistry } from '../src/core/tool';
7
-
8
- function makeRegistry(toolSpecs: Array<[string, string]>): ToolRegistry {
9
- const r = new ToolRegistry();
10
- for (const [name, desc] of toolSpecs) {
11
- r.register({
12
- name,
13
- description: desc,
14
- parameters: [{ name: 'x', type: 'string', description: 'x' }],
15
- handler: async () => 'ok',
16
- });
17
- }
18
- return r;
19
- }
20
-
21
- describe('selectRelevantTools', () => {
22
- it('short query returns full set', () => {
23
- const r = makeRegistry(Array.from({ length: 20 }, (_, i) => [`tool_${i}`, `desc ${i}`]));
24
- const names = r.listNames();
25
- const selected = selectRelevantTools(r, names, 'ok', { topK: 5 });
26
- expect(new Set(selected)).toEqual(new Set(names));
27
- });
28
-
29
- it('small catalog returns full set', () => {
30
- const r = makeRegistry([['a', 'alpha'], ['b', 'beta']]);
31
- const names = r.listNames();
32
- const selected = selectRelevantTools(r, names, 'anything goes here', { topK: 12 });
33
- expect(new Set(selected)).toEqual(new Set(names));
34
- });
35
-
36
- it('caps at topK for large catalog', () => {
37
- const r = makeRegistry(Array.from({ length: 50 }, (_, i) => [`tool_${i}`, `desc ${i}`]));
38
- const names = r.listNames();
39
- const selected = selectRelevantTools(r, names, 'find weather data', { topK: 10 });
40
- expect(selected.length).toBeLessThanOrEqual(10);
41
- });
42
-
43
- it('relevant tools score higher', () => {
44
- const r = makeRegistry([
45
- ['read_file', 'read a file from disk'],
46
- ['write_file', 'write content to a file'],
47
- ['send_email', 'send an email message'],
48
- ['fetch_url', 'fetch a web URL'],
49
- ['query_db', 'query the database'],
50
- ]);
51
- const names = r.listNames();
52
- const selected = selectRelevantTools(r, names, 'read this config file', { topK: 3 });
53
- expect(selected).toContain('read_file');
54
- });
55
-
56
- it('mustInclude always present', () => {
57
- const r = makeRegistry(Array.from({ length: 20 }, (_, i) => [`random_${i}`, `unrelated tool ${i}`]));
58
- r.register({
59
- name: 'critical_tool',
60
- description: 'must always be available',
61
- parameters: [{ name: 'x', type: 'string', description: 'x' }],
62
- handler: async () => 'ok',
63
- });
64
- const names = r.listNames();
65
- const selected = selectRelevantTools(r, names, 'totally unrelated query', {
66
- topK: 3,
67
- mustInclude: new Set(['critical_tool']),
68
- });
69
- expect(selected).toContain('critical_tool');
70
- });
71
- });
1
+ /**
2
+ * Tests for tool subset routing.
3
+ */
4
+ import { describe, it, expect } from 'vitest';
5
+ import { selectRelevantTools } from '../src/core/tool_router';
6
+ import { ToolRegistry } from '../src/core/tool';
7
+
8
+ function makeRegistry(toolSpecs: Array<[string, string]>): ToolRegistry {
9
+ const r = new ToolRegistry();
10
+ for (const [name, desc] of toolSpecs) {
11
+ r.register({
12
+ name,
13
+ description: desc,
14
+ parameters: [{ name: 'x', type: 'string', description: 'x' }],
15
+ handler: async () => 'ok',
16
+ });
17
+ }
18
+ return r;
19
+ }
20
+
21
+ describe('selectRelevantTools', () => {
22
+ it('short query returns full set', () => {
23
+ const r = makeRegistry(Array.from({ length: 20 }, (_, i) => [`tool_${i}`, `desc ${i}`]));
24
+ const names = r.listNames();
25
+ const selected = selectRelevantTools(r, names, 'ok', { topK: 5 });
26
+ expect(new Set(selected)).toEqual(new Set(names));
27
+ });
28
+
29
+ it('small catalog returns full set', () => {
30
+ const r = makeRegistry([['a', 'alpha'], ['b', 'beta']]);
31
+ const names = r.listNames();
32
+ const selected = selectRelevantTools(r, names, 'anything goes here', { topK: 12 });
33
+ expect(new Set(selected)).toEqual(new Set(names));
34
+ });
35
+
36
+ it('caps at topK for large catalog', () => {
37
+ const r = makeRegistry(Array.from({ length: 50 }, (_, i) => [`tool_${i}`, `desc ${i}`]));
38
+ const names = r.listNames();
39
+ const selected = selectRelevantTools(r, names, 'find weather data', { topK: 10 });
40
+ expect(selected.length).toBeLessThanOrEqual(10);
41
+ });
42
+
43
+ it('relevant tools score higher', () => {
44
+ const r = makeRegistry([
45
+ ['read_file', 'read a file from disk'],
46
+ ['write_file', 'write content to a file'],
47
+ ['send_email', 'send an email message'],
48
+ ['fetch_url', 'fetch a web URL'],
49
+ ['query_db', 'query the database'],
50
+ ]);
51
+ const names = r.listNames();
52
+ const selected = selectRelevantTools(r, names, 'read this config file', { topK: 3 });
53
+ expect(selected).toContain('read_file');
54
+ });
55
+
56
+ it('mustInclude always present', () => {
57
+ const r = makeRegistry(Array.from({ length: 20 }, (_, i) => [`random_${i}`, `unrelated tool ${i}`]));
58
+ r.register({
59
+ name: 'critical_tool',
60
+ description: 'must always be available',
61
+ parameters: [{ name: 'x', type: 'string', description: 'x' }],
62
+ handler: async () => 'ok',
63
+ });
64
+ const names = r.listNames();
65
+ const selected = selectRelevantTools(r, names, 'totally unrelated query', {
66
+ topK: 3,
67
+ mustInclude: new Set(['critical_tool']),
68
+ });
69
+ expect(selected).toContain('critical_tool');
70
+ });
71
+ });
package/vitest.config.ts CHANGED
@@ -1,17 +1,17 @@
1
- import { defineConfig } from 'vitest/config';
2
- import path from 'path';
3
-
4
- export default defineConfig({
5
- test: {
6
- globals: true,
7
- environment: 'node',
8
- include: ['tests/**/*.test.ts'],
9
- setupFiles: ['tests/setup.ts'],
10
- },
11
- resolve: {
12
- alias: {
13
- '@skyloom': path.resolve(__dirname, 'src'),
14
- '@': path.resolve(__dirname, 'src'),
15
- },
16
- },
17
- });
1
+ import { defineConfig } from 'vitest/config';
2
+ import path from 'path';
3
+
4
+ export default defineConfig({
5
+ test: {
6
+ globals: true,
7
+ environment: 'node',
8
+ include: ['tests/**/*.test.ts'],
9
+ setupFiles: ['tests/setup.ts'],
10
+ },
11
+ resolve: {
12
+ alias: {
13
+ '@skyloom': path.resolve(__dirname, 'src'),
14
+ '@': path.resolve(__dirname, 'src'),
15
+ },
16
+ },
17
+ });