skimpyclaw 0.3.14 โ 0.4.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/README.md +47 -37
- package/dist/__tests__/adapter-types.test.d.ts +4 -0
- package/dist/__tests__/adapter-types.test.js +63 -0
- package/dist/__tests__/anthropic-adapter.test.d.ts +4 -0
- package/dist/__tests__/anthropic-adapter.test.js +264 -0
- package/dist/__tests__/api.test.js +0 -1
- package/dist/__tests__/cli.integration.test.js +2 -4
- package/dist/__tests__/cli.test.js +0 -1
- package/dist/__tests__/code-agents-notifications.test.js +137 -0
- package/dist/__tests__/code-agents-parser.test.js +19 -1
- package/dist/__tests__/code-agents-preflight.test.js +3 -28
- package/dist/__tests__/code-agents-utils.test.js +34 -9
- package/dist/__tests__/code-agents-worktrees.test.js +116 -0
- package/dist/__tests__/codex-adapter.test.js +184 -0
- package/dist/__tests__/codex-auth.test.js +66 -0
- package/dist/__tests__/codex-provider-gating.test.js +35 -0
- package/dist/__tests__/codex-unified-loop.test.js +111 -0
- package/dist/__tests__/config-security.test.js +127 -0
- package/dist/__tests__/config.test.js +23 -0
- package/dist/__tests__/context-manager.test.js +243 -164
- package/dist/__tests__/cron-run.test.js +250 -0
- package/dist/__tests__/cron.test.js +12 -38
- package/dist/__tests__/digests.test.js +67 -0
- package/dist/__tests__/discord-attachments.test.js +211 -0
- package/dist/__tests__/discord-docs.test.d.ts +1 -0
- package/dist/__tests__/discord-docs.test.js +27 -0
- package/dist/__tests__/discord-thread-agents.test.d.ts +1 -0
- package/dist/__tests__/discord-thread-agents.test.js +115 -0
- package/dist/__tests__/discord-thread-context.test.d.ts +1 -0
- package/dist/__tests__/discord-thread-context.test.js +42 -0
- package/dist/__tests__/doctor.formatters.test.js +4 -4
- package/dist/__tests__/doctor.index.test.js +1 -1
- package/dist/__tests__/doctor.runner.test.js +3 -15
- package/dist/__tests__/env-sanitizer.test.d.ts +1 -0
- package/dist/__tests__/env-sanitizer.test.js +45 -0
- package/dist/__tests__/exec-approval.test.js +61 -0
- package/dist/__tests__/fetch-tool.test.d.ts +1 -0
- package/dist/__tests__/fetch-tool.test.js +85 -0
- package/dist/__tests__/gateway-status-auth.test.d.ts +1 -0
- package/dist/__tests__/gateway-status-auth.test.js +72 -0
- package/dist/__tests__/heartbeat.test.js +3 -3
- package/dist/__tests__/interactive-sessions.test.d.ts +1 -0
- package/dist/__tests__/interactive-sessions.test.js +96 -0
- package/dist/__tests__/langfuse.test.js +6 -18
- package/dist/__tests__/model-selection.test.js +3 -4
- package/dist/__tests__/providers-init.test.js +2 -8
- package/dist/__tests__/providers-routing.test.js +1 -1
- package/dist/__tests__/providers-utils.test.js +13 -3
- package/dist/__tests__/sessions.test.js +14 -10
- package/dist/__tests__/setup.test.js +12 -29
- package/dist/__tests__/skills.test.js +10 -7
- package/dist/__tests__/stream-formatter.test.d.ts +1 -0
- package/dist/__tests__/stream-formatter.test.js +114 -0
- package/dist/__tests__/token-efficiency.test.js +131 -15
- package/dist/__tests__/tool-loop.test.d.ts +4 -0
- package/dist/__tests__/tool-loop.test.js +505 -0
- package/dist/__tests__/tools.test.js +101 -276
- package/dist/__tests__/utils.test.d.ts +1 -0
- package/dist/__tests__/utils.test.js +14 -0
- package/dist/__tests__/voice.test.js +21 -0
- package/dist/agent.js +35 -4
- package/dist/api.js +113 -37
- package/dist/channels/discord/attachments.d.ts +50 -0
- package/dist/channels/discord/attachments.js +137 -0
- package/dist/channels/discord/delegation.d.ts +5 -0
- package/dist/channels/discord/delegation.js +136 -0
- package/dist/channels/discord/handlers.js +694 -7
- package/dist/channels/discord/index.d.ts +16 -1
- package/dist/channels/discord/index.js +64 -1
- package/dist/channels/discord/thread-agents.d.ts +54 -0
- package/dist/channels/discord/thread-agents.js +323 -0
- package/dist/channels/discord/threads.d.ts +58 -0
- package/dist/channels/discord/threads.js +192 -0
- package/dist/channels/discord/types.js +4 -2
- package/dist/channels/discord/utils.d.ts +16 -0
- package/dist/channels/discord/utils.js +86 -6
- package/dist/channels/telegram/index.d.ts +1 -1
- package/dist/channels/telegram/types.js +1 -1
- package/dist/channels/telegram/utils.js +9 -3
- package/dist/channels.d.ts +1 -1
- package/dist/cli.js +20 -400
- package/dist/code-agents/executor.d.ts +1 -1
- package/dist/code-agents/executor.js +101 -45
- package/dist/code-agents/index.d.ts +2 -7
- package/dist/code-agents/index.js +111 -80
- package/dist/code-agents/interactive-resume.d.ts +6 -0
- package/dist/code-agents/interactive-resume.js +98 -0
- package/dist/code-agents/interactive-sessions.d.ts +20 -0
- package/dist/code-agents/interactive-sessions.js +132 -0
- package/dist/code-agents/parser.js +5 -1
- package/dist/code-agents/registry.d.ts +7 -1
- package/dist/code-agents/registry.js +11 -23
- package/dist/code-agents/stream-formatter.d.ts +8 -0
- package/dist/code-agents/stream-formatter.js +92 -0
- package/dist/code-agents/types.d.ts +16 -24
- package/dist/code-agents/utils.d.ts +35 -11
- package/dist/code-agents/utils.js +349 -95
- package/dist/code-agents/worktrees.d.ts +37 -0
- package/dist/code-agents/worktrees.js +116 -0
- package/dist/config.d.ts +2 -4
- package/dist/config.js +123 -23
- package/dist/cron.d.ts +1 -6
- package/dist/cron.js +175 -82
- package/dist/dashboard/assets/index-B345aOO-.js +65 -0
- package/dist/dashboard/assets/index-ZWK4dalJ.css +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/digests.d.ts +1 -0
- package/dist/digests.js +132 -42
- package/dist/doctor/checks.d.ts +0 -3
- package/dist/doctor/checks.js +1 -108
- package/dist/doctor/runner.js +1 -4
- package/dist/env-sanitizer.d.ts +2 -0
- package/dist/env-sanitizer.js +61 -0
- package/dist/exec-approval.d.ts +11 -1
- package/dist/exec-approval.js +17 -4
- package/dist/gateway.d.ts +3 -1
- package/dist/gateway.js +17 -7
- package/dist/heartbeat.js +1 -6
- package/dist/langfuse.js +3 -29
- package/dist/model-selection.js +3 -1
- package/dist/providers/adapter.d.ts +118 -0
- package/dist/providers/adapter.js +6 -0
- package/dist/providers/adapters/anthropic-adapter.d.ts +22 -0
- package/dist/providers/adapters/anthropic-adapter.js +204 -0
- package/dist/providers/adapters/codex-adapter.d.ts +26 -0
- package/dist/providers/adapters/codex-adapter.js +203 -0
- package/dist/providers/anthropic.d.ts +1 -0
- package/dist/providers/anthropic.js +10 -272
- package/dist/providers/codex.d.ts +21 -0
- package/dist/providers/codex.js +149 -330
- package/dist/providers/content.d.ts +1 -1
- package/dist/providers/content.js +2 -2
- package/dist/providers/context-manager.d.ts +18 -6
- package/dist/providers/context-manager.js +199 -223
- package/dist/providers/index.d.ts +9 -1
- package/dist/providers/index.js +73 -64
- package/dist/providers/loop-utils.d.ts +20 -0
- package/dist/providers/loop-utils.js +30 -0
- package/dist/providers/tool-loop.d.ts +12 -0
- package/dist/providers/tool-loop.js +251 -0
- package/dist/providers/utils.d.ts +19 -3
- package/dist/providers/utils.js +100 -29
- package/dist/secure-store.d.ts +8 -0
- package/dist/secure-store.js +80 -0
- package/dist/service.js +3 -28
- package/dist/sessions.d.ts +3 -0
- package/dist/sessions.js +147 -18
- package/dist/setup-templates.js +13 -25
- package/dist/setup.d.ts +10 -6
- package/dist/setup.js +84 -292
- package/dist/skills.js +3 -11
- package/dist/tools/agent-delegation.d.ts +19 -0
- package/dist/tools/agent-delegation.js +49 -0
- package/dist/tools/bash-tool.js +89 -34
- package/dist/tools/definitions.d.ts +199 -302
- package/dist/tools/definitions.js +70 -123
- package/dist/tools/execute-context.d.ts +13 -4
- package/dist/tools/fetch-tool.js +109 -13
- package/dist/tools/file-tools.js +7 -1
- package/dist/tools.d.ts +7 -7
- package/dist/tools.js +133 -151
- package/dist/types.d.ts +37 -30
- package/dist/utils.js +4 -6
- package/dist/voice.d.ts +1 -1
- package/dist/voice.js +17 -4
- package/package.json +33 -23
- package/templates/TOOLS.md +0 -27
- package/dist/__tests__/audit.test.js +0 -122
- package/dist/__tests__/code-agents-orchestrator.test.js +0 -216
- package/dist/__tests__/code-agents-sandbox.test.js +0 -163
- package/dist/__tests__/orchestrator.test.js +0 -425
- package/dist/__tests__/sandbox-bridge.test.js +0 -116
- package/dist/__tests__/sandbox-manager.test.js +0 -144
- package/dist/__tests__/sandbox-mount-security.test.js +0 -139
- package/dist/__tests__/sandbox-runtime.test.js +0 -176
- package/dist/__tests__/subagent.test.js +0 -240
- package/dist/__tests__/telegram.test.js +0 -42
- package/dist/code-agents/orchestrator.d.ts +0 -29
- package/dist/code-agents/orchestrator.js +0 -694
- package/dist/code-agents/worktree.d.ts +0 -40
- package/dist/code-agents/worktree.js +0 -215
- package/dist/dashboard/assets/index-BoTHPby4.js +0 -65
- package/dist/dashboard/assets/index-D4mufvBg.css +0 -1
- package/dist/dashboard.d.ts +0 -8
- package/dist/dashboard.js +0 -4071
- package/dist/discord.d.ts +0 -8
- package/dist/discord.js +0 -792
- package/dist/mcp-context-a8c.d.ts +0 -13
- package/dist/mcp-context-a8c.js +0 -34
- package/dist/orchestrator.d.ts +0 -15
- package/dist/orchestrator.js +0 -676
- package/dist/providers/openai.d.ts +0 -10
- package/dist/providers/openai.js +0 -355
- package/dist/sandbox/bridge.d.ts +0 -5
- package/dist/sandbox/bridge.js +0 -63
- package/dist/sandbox/index.d.ts +0 -5
- package/dist/sandbox/index.js +0 -4
- package/dist/sandbox/manager.d.ts +0 -7
- package/dist/sandbox/manager.js +0 -100
- package/dist/sandbox/mount-security.d.ts +0 -12
- package/dist/sandbox/mount-security.js +0 -122
- package/dist/sandbox/runtime.d.ts +0 -39
- package/dist/sandbox/runtime.js +0 -192
- package/dist/sandbox-utils.d.ts +0 -6
- package/dist/sandbox-utils.js +0 -36
- package/dist/subagent.d.ts +0 -19
- package/dist/subagent.js +0 -407
- package/dist/telegram.d.ts +0 -2
- package/dist/telegram.js +0 -11
- package/dist/tools/browser-tool.d.ts +0 -3
- package/dist/tools/browser-tool.js +0 -266
- package/sandbox/Dockerfile +0 -40
- /package/dist/__tests__/{audit.test.d.ts โ code-agents-notifications.test.d.ts} +0 -0
- /package/dist/__tests__/{code-agents-orchestrator.test.d.ts โ code-agents-worktrees.test.d.ts} +0 -0
- /package/dist/__tests__/{code-agents-sandbox.test.d.ts โ codex-adapter.test.d.ts} +0 -0
- /package/dist/__tests__/{orchestrator.test.d.ts โ codex-auth.test.d.ts} +0 -0
- /package/dist/__tests__/{sandbox-bridge.test.d.ts โ codex-provider-gating.test.d.ts} +0 -0
- /package/dist/__tests__/{sandbox-manager.test.d.ts โ codex-unified-loop.test.d.ts} +0 -0
- /package/dist/__tests__/{sandbox-mount-security.test.d.ts โ config-security.test.d.ts} +0 -0
- /package/dist/__tests__/{sandbox-runtime.test.d.ts โ cron-run.test.d.ts} +0 -0
- /package/dist/__tests__/{subagent.test.d.ts โ digests.test.d.ts} +0 -0
- /package/dist/__tests__/{telegram.test.d.ts โ discord-attachments.test.d.ts} +0 -0
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
3
|
-
import { join } from 'path';
|
|
4
|
-
import { homedir } from 'os';
|
|
5
|
-
import { initSubagentSystem, dispatchSubagent, cancelTask, getActiveTasks, getRecentTasks, getTask, getPresetDescriptions, resetForTesting, ensureAgentSetup, } from '../subagent.js';
|
|
6
|
-
// Mock runAgentTurn
|
|
7
|
-
vi.mock('../agent.js', () => ({
|
|
8
|
-
runAgentTurn: vi.fn().mockResolvedValue('mock agent response'),
|
|
9
|
-
}));
|
|
10
|
-
// Mock getCurrentModel
|
|
11
|
-
vi.mock('../gateway.js', () => ({
|
|
12
|
-
getCurrentModel: vi.fn().mockReturnValue('anthropic/claude-sonnet-4-5'),
|
|
13
|
-
}));
|
|
14
|
-
// Mock fs operations for ensureAgentSetup tests
|
|
15
|
-
vi.mock('fs', async () => {
|
|
16
|
-
const actual = await vi.importActual('fs');
|
|
17
|
-
return {
|
|
18
|
-
...actual,
|
|
19
|
-
existsSync: vi.fn(actual.existsSync),
|
|
20
|
-
mkdirSync: vi.fn(),
|
|
21
|
-
writeFileSync: vi.fn(),
|
|
22
|
-
};
|
|
23
|
-
});
|
|
24
|
-
function createMockConfig() {
|
|
25
|
-
return {
|
|
26
|
-
gateway: { port: 18790, mode: 'local' },
|
|
27
|
-
agents: {
|
|
28
|
-
default: 'main',
|
|
29
|
-
list: {
|
|
30
|
-
main: {
|
|
31
|
-
identity: { name: 'Test', emoji: '๐ฆ' },
|
|
32
|
-
model: 'anthropic/claude-sonnet-4-5',
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
models: {
|
|
37
|
-
providers: {},
|
|
38
|
-
aliases: {
|
|
39
|
-
'claude-think': 'anthropic/claude-sonnet-4-5',
|
|
40
|
-
'claude-opus': 'anthropic/claude-opus-4-6',
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
channels: {
|
|
44
|
-
telegram: {
|
|
45
|
-
enabled: false,
|
|
46
|
-
token: '',
|
|
47
|
-
allowFrom: [],
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
cron: { jobs: [] },
|
|
51
|
-
heartbeat: {
|
|
52
|
-
intervalMs: 300000,
|
|
53
|
-
prompt: 'test',
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
describe('subagent', () => {
|
|
58
|
-
let deliveredMessages;
|
|
59
|
-
let mockConfig;
|
|
60
|
-
beforeEach(() => {
|
|
61
|
-
resetForTesting();
|
|
62
|
-
mockConfig = createMockConfig();
|
|
63
|
-
deliveredMessages = [];
|
|
64
|
-
initSubagentSystem(async (chatId, message) => {
|
|
65
|
-
deliveredMessages.push({ chatId, message });
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
describe('initSubagentSystem', () => {
|
|
69
|
-
it('initializes without error', () => {
|
|
70
|
-
expect(() => initSubagentSystem(async () => { })).not.toThrow();
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
describe('getPresetDescriptions', () => {
|
|
74
|
-
it('returns descriptions for all agent types', () => {
|
|
75
|
-
const desc = getPresetDescriptions();
|
|
76
|
-
expect(desc).toContain('coding');
|
|
77
|
-
expect(desc).toContain('research');
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
describe('dispatchSubagent', () => {
|
|
81
|
-
it('creates a task with correct fields', () => {
|
|
82
|
-
const task = dispatchSubagent('coding', 'list TODOs', 123, mockConfig);
|
|
83
|
-
expect(task.id).toBe('t1');
|
|
84
|
-
expect(task.type).toBe('coding');
|
|
85
|
-
expect(task.prompt).toBe('list TODOs');
|
|
86
|
-
expect(task.chatId).toBe(123);
|
|
87
|
-
expect(task.model).toBe('anthropic/claude-opus-4-6');
|
|
88
|
-
expect(task.createdAt).toBeInstanceOf(Date);
|
|
89
|
-
});
|
|
90
|
-
it('increments task IDs', () => {
|
|
91
|
-
const t1 = dispatchSubagent('coding', 'task 1', 123, mockConfig);
|
|
92
|
-
const t2 = dispatchSubagent('research', 'task 2', 123, mockConfig);
|
|
93
|
-
expect(t1.id).toBe('t1');
|
|
94
|
-
expect(t2.id).toBe('t2');
|
|
95
|
-
});
|
|
96
|
-
it('uses model override when provided', () => {
|
|
97
|
-
const task = dispatchSubagent('coding', 'test', 123, mockConfig, 'anthropic/claude-opus-4');
|
|
98
|
-
expect(task.model).toBe('anthropic/claude-opus-4-6');
|
|
99
|
-
});
|
|
100
|
-
it('resolves model override aliases to canonical model ids', () => {
|
|
101
|
-
const task = dispatchSubagent('coding', 'test', 123, mockConfig, 'claude-think');
|
|
102
|
-
expect(task.model).toBe('anthropic/claude-sonnet-4-5');
|
|
103
|
-
});
|
|
104
|
-
it('rejects when max concurrent reached', () => {
|
|
105
|
-
// Set max concurrent to 3 to test the limit
|
|
106
|
-
const configWithLimit = { ...mockConfig, subagents: { maxConcurrent: 3 } };
|
|
107
|
-
dispatchSubagent('coding', 'task 1', 123, configWithLimit);
|
|
108
|
-
dispatchSubagent('coding', 'task 2', 123, configWithLimit);
|
|
109
|
-
dispatchSubagent('coding', 'task 3', 123, configWithLimit);
|
|
110
|
-
expect(() => dispatchSubagent('coding', 'task 4', 123, configWithLimit)).toThrow('Max concurrent');
|
|
111
|
-
});
|
|
112
|
-
it('delivers result on completion', async () => {
|
|
113
|
-
dispatchSubagent('coding', 'test prompt', 456, mockConfig);
|
|
114
|
-
// Wait for async execution
|
|
115
|
-
await new Promise(r => setTimeout(r, 100));
|
|
116
|
-
expect(deliveredMessages.length).toBe(1);
|
|
117
|
-
expect(deliveredMessages[0].chatId).toBe(456);
|
|
118
|
-
expect(deliveredMessages[0].message).toContain('mock agent response');
|
|
119
|
-
expect(deliveredMessages[0].message).toContain('completed');
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
describe('cancelTask', () => {
|
|
123
|
-
it('cancels a running task', async () => {
|
|
124
|
-
const task = dispatchSubagent('coding', 'test', 123, mockConfig);
|
|
125
|
-
const result = cancelTask(task.id);
|
|
126
|
-
expect(result?.status).toBe('cancelled');
|
|
127
|
-
});
|
|
128
|
-
it('returns null for unknown task', () => {
|
|
129
|
-
expect(cancelTask('t999')).toBeNull();
|
|
130
|
-
});
|
|
131
|
-
it('returns task unchanged if already completed', async () => {
|
|
132
|
-
const task = dispatchSubagent('coding', 'test', 123, mockConfig);
|
|
133
|
-
await new Promise(r => setTimeout(r, 100));
|
|
134
|
-
const result = cancelTask(task.id);
|
|
135
|
-
expect(result?.status).toBe('completed');
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
describe('getActiveTasks', () => {
|
|
139
|
-
it('returns empty when no tasks', () => {
|
|
140
|
-
expect(getActiveTasks()).toHaveLength(0);
|
|
141
|
-
});
|
|
142
|
-
it('returns pending/running tasks', () => {
|
|
143
|
-
dispatchSubagent('coding', 'test', 123, mockConfig);
|
|
144
|
-
// Task starts as pending/running immediately
|
|
145
|
-
const active = getActiveTasks();
|
|
146
|
-
expect(active.length).toBeGreaterThanOrEqual(0); // may already be running
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
describe('getRecentTasks', () => {
|
|
150
|
-
it('returns tasks sorted newest first', async () => {
|
|
151
|
-
dispatchSubagent('coding', 'first', 123, mockConfig);
|
|
152
|
-
// Small delay to ensure different timestamps
|
|
153
|
-
await new Promise(r => setTimeout(r, 5));
|
|
154
|
-
dispatchSubagent('research', 'second', 123, mockConfig);
|
|
155
|
-
const recent = getRecentTasks(10);
|
|
156
|
-
expect(recent).toHaveLength(2);
|
|
157
|
-
expect(recent[0].prompt).toBe('second');
|
|
158
|
-
expect(recent[1].prompt).toBe('first');
|
|
159
|
-
});
|
|
160
|
-
it('limits results', () => {
|
|
161
|
-
dispatchSubagent('coding', 'a', 123, mockConfig);
|
|
162
|
-
dispatchSubagent('coding', 'b', 123, mockConfig);
|
|
163
|
-
dispatchSubagent('coding', 'c', 123, mockConfig);
|
|
164
|
-
const recent = getRecentTasks(2);
|
|
165
|
-
expect(recent).toHaveLength(2);
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
describe('getTask', () => {
|
|
169
|
-
it('returns task by id', () => {
|
|
170
|
-
const task = dispatchSubagent('coding', 'test', 123, mockConfig);
|
|
171
|
-
expect(getTask(task.id)).toBe(task);
|
|
172
|
-
});
|
|
173
|
-
it('returns null for unknown id', () => {
|
|
174
|
-
expect(getTask('t999')).toBeNull();
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
describe('ensureAgentSetup', () => {
|
|
178
|
-
const mockedExistsSync = vi.mocked(existsSync);
|
|
179
|
-
const mockedMkdirSync = vi.mocked(mkdirSync);
|
|
180
|
-
const mockedWriteFileSync = vi.mocked(writeFileSync);
|
|
181
|
-
beforeEach(() => {
|
|
182
|
-
mockedExistsSync.mockReset();
|
|
183
|
-
mockedMkdirSync.mockReset();
|
|
184
|
-
mockedWriteFileSync.mockReset();
|
|
185
|
-
});
|
|
186
|
-
it('creates agent dir and templates when dir does not exist', () => {
|
|
187
|
-
mockedExistsSync.mockReturnValue(false);
|
|
188
|
-
const config = createMockConfig();
|
|
189
|
-
ensureAgentSetup('coding', config);
|
|
190
|
-
const expectedDir = join(homedir(), '.skimpyclaw', 'agents', 'coding');
|
|
191
|
-
expect(mockedMkdirSync).toHaveBeenCalledWith(expectedDir, { recursive: true });
|
|
192
|
-
expect(mockedWriteFileSync).toHaveBeenCalledTimes(2);
|
|
193
|
-
// Check IDENTITY.md was written
|
|
194
|
-
const identityCall = mockedWriteFileSync.mock.calls.find((c) => String(c[0]).endsWith('IDENTITY.md'));
|
|
195
|
-
expect(identityCall).toBeTruthy();
|
|
196
|
-
expect(identityCall[1]).toContain('Coding Agent');
|
|
197
|
-
// Check TOOLS.md was written
|
|
198
|
-
const toolsCall = mockedWriteFileSync.mock.calls.find((c) => String(c[0]).endsWith('TOOLS.md'));
|
|
199
|
-
expect(toolsCall).toBeTruthy();
|
|
200
|
-
expect(toolsCall[1]).toContain('Act, Don\'t Narrate');
|
|
201
|
-
});
|
|
202
|
-
it('does not create dir when it already exists', () => {
|
|
203
|
-
mockedExistsSync.mockReturnValue(true);
|
|
204
|
-
const config = createMockConfig();
|
|
205
|
-
ensureAgentSetup('coding', config);
|
|
206
|
-
expect(mockedMkdirSync).not.toHaveBeenCalled();
|
|
207
|
-
expect(mockedWriteFileSync).not.toHaveBeenCalled();
|
|
208
|
-
});
|
|
209
|
-
it('registers agent in config.agents.list in-memory', () => {
|
|
210
|
-
mockedExistsSync.mockReturnValue(true);
|
|
211
|
-
const config = createMockConfig();
|
|
212
|
-
expect(config.agents.list['coding']).toBeUndefined();
|
|
213
|
-
ensureAgentSetup('coding', config);
|
|
214
|
-
expect(config.agents.list['coding']).toBeDefined();
|
|
215
|
-
expect(config.agents.list['coding'].identity.name).toBe('Coding Agent');
|
|
216
|
-
expect(config.agents.list['coding'].identity.emoji).toBe('๐ง');
|
|
217
|
-
expect(config.agents.list['coding'].thinking).toBe('medium');
|
|
218
|
-
});
|
|
219
|
-
it('does not overwrite existing agent registration', () => {
|
|
220
|
-
mockedExistsSync.mockReturnValue(true);
|
|
221
|
-
const config = createMockConfig();
|
|
222
|
-
config.agents.list['research'] = {
|
|
223
|
-
identity: { name: 'Custom Research', emoji: '๐งช' },
|
|
224
|
-
model: 'custom-model',
|
|
225
|
-
};
|
|
226
|
-
ensureAgentSetup('research', config);
|
|
227
|
-
// Should keep the existing registration
|
|
228
|
-
expect(config.agents.list['research'].identity.name).toBe('Custom Research');
|
|
229
|
-
expect(config.agents.list['research'].identity.emoji).toBe('๐งช');
|
|
230
|
-
});
|
|
231
|
-
it('creates correct templates for research type', () => {
|
|
232
|
-
mockedExistsSync.mockReturnValue(false);
|
|
233
|
-
const config = createMockConfig();
|
|
234
|
-
ensureAgentSetup('research', config);
|
|
235
|
-
const identityCall = mockedWriteFileSync.mock.calls.find((c) => String(c[0]).endsWith('IDENTITY.md'));
|
|
236
|
-
expect(identityCall[1]).toContain('Research Agent');
|
|
237
|
-
expect(identityCall[1]).toContain('research subagent dispatched');
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
});
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { mkdirSync, writeFileSync, rmSync } from 'fs';
|
|
3
|
-
import { join } from 'path';
|
|
4
|
-
import { tmpdir } from 'os';
|
|
5
|
-
import { getRecentMemoryFiles } from '../telegram.js';
|
|
6
|
-
const TEST_ROOT = join(tmpdir(), `skimpyclaw-telegram-test-${Date.now()}`);
|
|
7
|
-
function seedMemory(agentId, name, content) {
|
|
8
|
-
const dir = join(TEST_ROOT, 'agents', agentId, 'memory');
|
|
9
|
-
mkdirSync(dir, { recursive: true });
|
|
10
|
-
writeFileSync(join(dir, name), content, 'utf-8');
|
|
11
|
-
}
|
|
12
|
-
describe('getRecentMemoryFiles', () => {
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
mkdirSync(TEST_ROOT, { recursive: true });
|
|
15
|
-
});
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
rmSync(TEST_ROOT, { recursive: true, force: true });
|
|
18
|
-
});
|
|
19
|
-
it('returns files sorted newest first', () => {
|
|
20
|
-
seedMemory('main', '2026-02-05.md', 'older');
|
|
21
|
-
seedMemory('main', '2026-02-07.md', 'newer');
|
|
22
|
-
seedMemory('main', '2026-02-06.md', 'middle');
|
|
23
|
-
const files = getRecentMemoryFiles('main', 10, TEST_ROOT);
|
|
24
|
-
expect(files.map(f => f.name)).toEqual([
|
|
25
|
-
'2026-02-07.md',
|
|
26
|
-
'2026-02-06.md',
|
|
27
|
-
'2026-02-05.md',
|
|
28
|
-
]);
|
|
29
|
-
});
|
|
30
|
-
it('limits to requested count', () => {
|
|
31
|
-
seedMemory('main', '2026-02-01.md', '1');
|
|
32
|
-
seedMemory('main', '2026-02-02.md', '2');
|
|
33
|
-
seedMemory('main', '2026-02-03.md', '3');
|
|
34
|
-
const files = getRecentMemoryFiles('main', 2, TEST_ROOT);
|
|
35
|
-
expect(files).toHaveLength(2);
|
|
36
|
-
expect(files.map(f => f.name)).toEqual(['2026-02-03.md', '2026-02-02.md']);
|
|
37
|
-
});
|
|
38
|
-
it('returns empty for unknown agent memory dir', () => {
|
|
39
|
-
const files = getRecentMemoryFiles('does-not-exist', 5, TEST_ROOT);
|
|
40
|
-
expect(files).toEqual([]);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { Config } from '../types.js';
|
|
2
|
-
import type { ExecuteToolContext } from '../tools/execute-context.js';
|
|
3
|
-
import type { DecomposedSubtask, ChildResult } from './types.js';
|
|
4
|
-
/**
|
|
5
|
-
* Compute execution waves from dependency info.
|
|
6
|
-
* Returns an array of waves, where each wave is an array of subtask indices that can run in parallel.
|
|
7
|
-
* Throws if there's a cycle in the dependency graph.
|
|
8
|
-
*/
|
|
9
|
-
export declare function computeWaves(subtasks: DecomposedSubtask[]): number[][];
|
|
10
|
-
/**
|
|
11
|
-
* Gather lightweight codebase context to improve task decomposition.
|
|
12
|
-
* Returns a short summary of the project structure (file tree, package.json scripts).
|
|
13
|
-
* Capped at ~2000 chars to keep the decomposition prompt small.
|
|
14
|
-
*/
|
|
15
|
-
export declare function gatherCodebaseContext(workdir: string): string;
|
|
16
|
-
/**
|
|
17
|
-
* Use a quick model call to decompose a complex task into N subtasks with optional dependency info.
|
|
18
|
-
* Falls back to numbered subtask splitting on parse error.
|
|
19
|
-
* Falls back to all-independent if dependency info is missing or invalid.
|
|
20
|
-
*/
|
|
21
|
-
export declare function decomposeTask(task: string, teamSize: number, config: Config, workdir?: string): Promise<DecomposedSubtask[]>;
|
|
22
|
-
/**
|
|
23
|
-
* Use a quick model call to synthesize results from multiple subtask completions.
|
|
24
|
-
*/
|
|
25
|
-
export declare function synthesizeResults(originalTask: string, results: ChildResult[], config: Config, workdir?: string): Promise<string>;
|
|
26
|
-
/**
|
|
27
|
-
* Team orchestrator โ decomposes task, spawns parallel agents, monitors, synthesizes.
|
|
28
|
-
*/
|
|
29
|
-
export declare function runTeamOrchestrator(parentId: string, task: string, teamSize: number, workdir: string, validate: boolean, agent: string, model: string | undefined, startedAt: Date, context?: ExecuteToolContext): Promise<void>;
|