@codemieai/code 0.0.1
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/.claude/agents/README.md +298 -0
- package/.claude/agents/release-manager.md +857 -0
- package/CLAUDE.md +856 -0
- package/LICENSE +201 -0
- package/README.md +917 -0
- package/bin/codemie-code.js +23 -0
- package/bin/codemie.js +8 -0
- package/dist/agents/adapters/aider.d.ts +12 -0
- package/dist/agents/adapters/aider.d.ts.map +1 -0
- package/dist/agents/adapters/aider.js +80 -0
- package/dist/agents/adapters/aider.js.map +1 -0
- package/dist/agents/adapters/claude-code.d.ts +12 -0
- package/dist/agents/adapters/claude-code.d.ts.map +1 -0
- package/dist/agents/adapters/claude-code.js +98 -0
- package/dist/agents/adapters/claude-code.js.map +1 -0
- package/dist/agents/adapters/codemie-code.d.ts +12 -0
- package/dist/agents/adapters/codemie-code.d.ts.map +1 -0
- package/dist/agents/adapters/codemie-code.js +42 -0
- package/dist/agents/adapters/codemie-code.js.map +1 -0
- package/dist/agents/adapters/codex.d.ts +12 -0
- package/dist/agents/adapters/codex.d.ts.map +1 -0
- package/dist/agents/adapters/codex.js +80 -0
- package/dist/agents/adapters/codex.js.map +1 -0
- package/dist/agents/registry.d.ts +18 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +35 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/cli/cli.d.ts +4 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +107 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +128 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/install.d.ts +3 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +76 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/list.d.ts +3 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +50 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +3 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +459 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/run.d.ts +3 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +41 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +3 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +71 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/commands/version.d.ts +3 -0
- package/dist/cli/commands/version.d.ts.map +1 -0
- package/dist/cli/commands/version.js +28 -0
- package/dist/cli/commands/version.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +50 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/code/agent-events.d.ts +39 -0
- package/dist/code/agent-events.d.ts.map +1 -0
- package/dist/code/agent-events.js +4 -0
- package/dist/code/agent-events.js.map +1 -0
- package/dist/code/agent.d.ts +19 -0
- package/dist/code/agent.d.ts.map +1 -0
- package/dist/code/agent.js +144 -0
- package/dist/code/agent.js.map +1 -0
- package/dist/code/config.d.ts +13 -0
- package/dist/code/config.d.ts.map +1 -0
- package/dist/code/config.js +41 -0
- package/dist/code/config.js.map +1 -0
- package/dist/code/index.d.ts +19 -0
- package/dist/code/index.d.ts.map +1 -0
- package/dist/code/index.js +400 -0
- package/dist/code/index.js.map +1 -0
- package/dist/code/prompts.d.ts +2 -0
- package/dist/code/prompts.d.ts.map +1 -0
- package/dist/code/prompts.js +45 -0
- package/dist/code/prompts.js.map +1 -0
- package/dist/code/tools/command.d.ts +8 -0
- package/dist/code/tools/command.d.ts.map +1 -0
- package/dist/code/tools/command.js +83 -0
- package/dist/code/tools/command.js.map +1 -0
- package/dist/code/tools/diff-utils.d.ts +2 -0
- package/dist/code/tools/diff-utils.d.ts.map +1 -0
- package/dist/code/tools/diff-utils.js +45 -0
- package/dist/code/tools/diff-utils.js.map +1 -0
- package/dist/code/tools/filesystem.d.ts +11 -0
- package/dist/code/tools/filesystem.d.ts.map +1 -0
- package/dist/code/tools/filesystem.js +442 -0
- package/dist/code/tools/filesystem.js.map +1 -0
- package/dist/code/tools/git.d.ts +7 -0
- package/dist/code/tools/git.d.ts.map +1 -0
- package/dist/code/tools/git.js +111 -0
- package/dist/code/tools/git.js.map +1 -0
- package/dist/code/tools/mcp.d.ts +13 -0
- package/dist/code/tools/mcp.d.ts.map +1 -0
- package/dist/code/tools/mcp.js +230 -0
- package/dist/code/tools/mcp.js.map +1 -0
- package/dist/data/tips.json +118 -0
- package/dist/env/manager.d.ts +14 -0
- package/dist/env/manager.d.ts.map +1 -0
- package/dist/env/manager.js +99 -0
- package/dist/env/manager.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/terminal-ui.d.ts +73 -0
- package/dist/ui/terminal-ui.d.ts.map +1 -0
- package/dist/ui/terminal-ui.js +900 -0
- package/dist/ui/terminal-ui.js.map +1 -0
- package/dist/utils/async-tips.d.ts +64 -0
- package/dist/utils/async-tips.d.ts.map +1 -0
- package/dist/utils/async-tips.js +242 -0
- package/dist/utils/async-tips.js.map +1 -0
- package/dist/utils/env-mapper.d.ts +40 -0
- package/dist/utils/env-mapper.d.ts.map +1 -0
- package/dist/utils/env-mapper.js +122 -0
- package/dist/utils/env-mapper.js.map +1 -0
- package/dist/utils/errors.d.ts +25 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +58 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/exec.d.ts +12 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +49 -0
- package/dist/utils/exec.js.map +1 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +53 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/tips.d.ts +35 -0
- package/dist/utils/tips.d.ts.map +1 -0
- package/dist/utils/tips.js +132 -0
- package/dist/utils/tips.js.map +1 -0
- package/docs/USER_GUIDE.md +573 -0
- package/eslint.config.mjs +43 -0
- package/package.json +66 -0
- package/tests/agent-direct.test.mjs +45 -0
- package/tests/agent-output.test.mjs +64 -0
- package/tests/codemie-code.test.mjs +42 -0
- package/tests/context7-only.test.mjs +42 -0
- package/tests/conversation-flow.test.mjs +63 -0
- package/tests/interactive-simulation.test.mjs +60 -0
- package/tests/live-output.test.mjs +53 -0
- package/tests/mcp-context7.test.mjs +105 -0
- package/tests/mcp-e2e.test.mjs +109 -0
- package/tests/mcp-time-server.test.mjs +58 -0
- package/tests/streaming.test.mjs +57 -0
- package/tests/test-helpers.mjs +94 -0
- package/tests/text-wrapping.test.mjs +33 -0
- package/tests/tool-count.test.mjs +81 -0
- package/tests/ui-format.test.mjs +39 -0
- package/tests/ui-state.test.mjs +72 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Test: Streaming functionality
|
|
3
|
+
* Uses Node.js native test runner
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, before } from 'node:test';
|
|
7
|
+
import assert from 'node:assert';
|
|
8
|
+
import { CodeMieAgent } from '../dist/code/agent.js';
|
|
9
|
+
import { loadConfig } from '../dist/code/config.js';
|
|
10
|
+
import { FilesystemTools } from '../dist/code/tools/filesystem.js';
|
|
11
|
+
import { skipIfNoBaseUrl } from './test-helpers.mjs';
|
|
12
|
+
|
|
13
|
+
describe('Streaming', () => {
|
|
14
|
+
let agent;
|
|
15
|
+
|
|
16
|
+
before(() => {
|
|
17
|
+
if (skipIfNoBaseUrl()) return;
|
|
18
|
+
|
|
19
|
+
const config = loadConfig(process.cwd());
|
|
20
|
+
const filesystemTools = new FilesystemTools({
|
|
21
|
+
allowedDirectories: [process.cwd()]
|
|
22
|
+
});
|
|
23
|
+
const tools = filesystemTools.getTools();
|
|
24
|
+
agent = new CodeMieAgent(config, tools);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should stream tool calling events', async () => {
|
|
28
|
+
if (skipIfNoBaseUrl()) return;
|
|
29
|
+
|
|
30
|
+
const events = [];
|
|
31
|
+
|
|
32
|
+
await new Promise((resolve, reject) => {
|
|
33
|
+
agent.chatStream('list files in this directory', (event) => {
|
|
34
|
+
events.push(event.type);
|
|
35
|
+
|
|
36
|
+
switch(event.type) {
|
|
37
|
+
case 'complete':
|
|
38
|
+
try {
|
|
39
|
+
assert.ok(events.includes('thinking_start'), 'Should emit thinking_start');
|
|
40
|
+
assert.ok(events.includes('thinking_end'), 'Should emit thinking_end');
|
|
41
|
+
assert.ok(events.includes('tool_call_start'), 'Should emit tool_call_start');
|
|
42
|
+
assert.ok(events.includes('tool_call_result'), 'Should emit tool_call_result');
|
|
43
|
+
assert.ok(events.includes('content_chunk'), 'Should emit content_chunk');
|
|
44
|
+
assert.ok(events.includes('complete'), 'Should emit complete');
|
|
45
|
+
resolve();
|
|
46
|
+
} catch (error) {
|
|
47
|
+
reject(error);
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
case 'error':
|
|
51
|
+
reject(new Error(event.error));
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers and utilities
|
|
3
|
+
* Provides common functionality for test files
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check if base URL is configured for tests to run
|
|
8
|
+
* Tests that require LLM interaction need a valid base URL
|
|
9
|
+
*
|
|
10
|
+
* @returns {boolean} true if base URL is configured, false otherwise
|
|
11
|
+
*/
|
|
12
|
+
export function isBaseUrlConfigured() {
|
|
13
|
+
return !!(
|
|
14
|
+
process.env.CODEMIE_BASE_URL ||
|
|
15
|
+
process.env.ANTHROPIC_BASE_URL ||
|
|
16
|
+
process.env.OPENAI_BASE_URL
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Check if we should skip tests that require base URL
|
|
22
|
+
* Prints a warning message if base URL is not configured
|
|
23
|
+
*
|
|
24
|
+
* This function returns true if tests should be skipped. Tests should check
|
|
25
|
+
* the return value and return early if true.
|
|
26
|
+
*
|
|
27
|
+
* @param {string} [customMessage] - Optional custom message to display
|
|
28
|
+
* @returns {boolean} true if test should be skipped, false otherwise
|
|
29
|
+
*/
|
|
30
|
+
export function skipIfNoBaseUrl(customMessage) {
|
|
31
|
+
if (!isBaseUrlConfigured()) {
|
|
32
|
+
const message = customMessage ||
|
|
33
|
+
'Base URL not configured. Set CODEMIE_BASE_URL, ANTHROPIC_BASE_URL, or OPENAI_BASE_URL environment variable.';
|
|
34
|
+
|
|
35
|
+
console.warn(`⚠️ Skipping test: ${message}`);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get list of required environment variables that are missing
|
|
43
|
+
*
|
|
44
|
+
* @returns {string[]} Array of missing environment variable names
|
|
45
|
+
*/
|
|
46
|
+
export function getMissingEnvVars() {
|
|
47
|
+
const missing = [];
|
|
48
|
+
|
|
49
|
+
// Check base URL
|
|
50
|
+
if (!isBaseUrlConfigured()) {
|
|
51
|
+
missing.push('BASE_URL (CODEMIE_BASE_URL, ANTHROPIC_BASE_URL, or OPENAI_BASE_URL)');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check auth token
|
|
55
|
+
const hasAuthToken = !!(
|
|
56
|
+
process.env.CODEMIE_AUTH_TOKEN ||
|
|
57
|
+
process.env.CODEMIE_API_KEY ||
|
|
58
|
+
process.env.ANTHROPIC_AUTH_TOKEN ||
|
|
59
|
+
process.env.ANTHROPIC_API_KEY ||
|
|
60
|
+
process.env.OPENAI_AUTH_TOKEN ||
|
|
61
|
+
process.env.OPENAI_API_KEY
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (!hasAuthToken) {
|
|
65
|
+
missing.push('AUTH_TOKEN (CODEMIE_AUTH_TOKEN, ANTHROPIC_AUTH_TOKEN, or OPENAI_AUTH_TOKEN)');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return missing;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Check if all required environment variables are configured
|
|
73
|
+
*
|
|
74
|
+
* @returns {boolean} true if all required env vars are set
|
|
75
|
+
*/
|
|
76
|
+
export function isFullyConfigured() {
|
|
77
|
+
return getMissingEnvVars().length === 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Print configuration status for debugging
|
|
82
|
+
*/
|
|
83
|
+
export function printConfigStatus() {
|
|
84
|
+
console.log('\n=== Test Configuration Status ===');
|
|
85
|
+
console.log('Base URL configured:', isBaseUrlConfigured());
|
|
86
|
+
console.log('Fully configured:', isFullyConfigured());
|
|
87
|
+
|
|
88
|
+
const missing = getMissingEnvVars();
|
|
89
|
+
if (missing.length > 0) {
|
|
90
|
+
console.log('\nMissing configuration:');
|
|
91
|
+
missing.forEach(env => console.log(` - ${env}`));
|
|
92
|
+
}
|
|
93
|
+
console.log('=================================\n');
|
|
94
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Test: Text wrapping
|
|
3
|
+
* Uses Node.js native test runner
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it } from 'node:test';
|
|
7
|
+
import assert from 'node:assert';
|
|
8
|
+
|
|
9
|
+
describe('Text Wrapping', () => {
|
|
10
|
+
it('should split long text into lines', () => {
|
|
11
|
+
const longText = `I'll list the files in the current directory (\`/Users/Nikita_Levyankov/repos/EPMCDME/codemie-tools\`):
|
|
12
|
+
|
|
13
|
+
**Directories:**
|
|
14
|
+
- \`.claude\` - Claude configuration
|
|
15
|
+
- \`src\` - Source code
|
|
16
|
+
- \`dist\` - Distribution files`;
|
|
17
|
+
|
|
18
|
+
const lines = longText.split('\n');
|
|
19
|
+
|
|
20
|
+
assert.ok(lines.length > 1, 'Should have multiple lines');
|
|
21
|
+
assert.ok(lines[0].includes('list the files'), 'First line should contain intro');
|
|
22
|
+
assert.ok(lines.some(l => l.includes('Directories')), 'Should contain Directories header');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should preserve markdown formatting in lines', () => {
|
|
26
|
+
const text = '**Directories:**\n- `.claude` - Claude configuration';
|
|
27
|
+
const lines = text.split('\n');
|
|
28
|
+
|
|
29
|
+
assert.ok(lines[0].includes('**'), 'Should preserve bold markdown');
|
|
30
|
+
assert.ok(lines[1].includes('`'), 'Should preserve code markdown');
|
|
31
|
+
assert.ok(lines[1].startsWith('- '), 'Should preserve list formatting');
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Test: Verify MCP tools are loaded correctly
|
|
3
|
+
* Uses Node.js native test runner
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, before, after } from 'node:test';
|
|
7
|
+
import assert from 'node:assert';
|
|
8
|
+
import { CodeMieCode } from '../dist/code/index.js';
|
|
9
|
+
import { skipIfNoBaseUrl } from './test-helpers.mjs';
|
|
10
|
+
|
|
11
|
+
describe('Tool Loading', () => {
|
|
12
|
+
let assistant;
|
|
13
|
+
|
|
14
|
+
before(async () => {
|
|
15
|
+
if (skipIfNoBaseUrl()) return;
|
|
16
|
+
|
|
17
|
+
assistant = new CodeMieCode(process.cwd());
|
|
18
|
+
await assistant.initialize({ showTips: false });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
after(async () => {
|
|
22
|
+
if (assistant) {
|
|
23
|
+
await assistant.dispose();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should load all tools', () => {
|
|
28
|
+
if (skipIfNoBaseUrl()) return;
|
|
29
|
+
const agent = assistant.agent;
|
|
30
|
+
const tools = agent.tools;
|
|
31
|
+
|
|
32
|
+
assert.ok(tools, 'Tools should be defined');
|
|
33
|
+
assert.ok(tools.length > 0, 'Should have loaded tools');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should load tools by category', () => {
|
|
37
|
+
if (skipIfNoBaseUrl()) return;
|
|
38
|
+
const agent = assistant.agent;
|
|
39
|
+
const tools = agent.tools;
|
|
40
|
+
|
|
41
|
+
const toolTypes = {
|
|
42
|
+
filesystem: [],
|
|
43
|
+
command: [],
|
|
44
|
+
git: [],
|
|
45
|
+
mcp: [],
|
|
46
|
+
other: []
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
tools.forEach(tool => {
|
|
50
|
+
if (tool.name.startsWith('mcp_')) {
|
|
51
|
+
toolTypes.mcp.push(tool);
|
|
52
|
+
} else if (tool.name.includes('file') || tool.name.includes('directory') || tool.name.includes('read') || tool.name.includes('write')) {
|
|
53
|
+
toolTypes.filesystem.push(tool);
|
|
54
|
+
} else if (tool.name.includes('command') || tool.name.includes('execute')) {
|
|
55
|
+
toolTypes.command.push(tool);
|
|
56
|
+
} else if (tool.name.includes('git')) {
|
|
57
|
+
toolTypes.git.push(tool);
|
|
58
|
+
} else {
|
|
59
|
+
toolTypes.other.push(tool);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
assert.ok(toolTypes.filesystem.length >= 8, `Expected >= 8 filesystem tools, got ${toolTypes.filesystem.length}`);
|
|
64
|
+
assert.ok(toolTypes.command.length >= 2, `Expected >= 2 command tools, got ${toolTypes.command.length}`);
|
|
65
|
+
assert.ok(toolTypes.git.length >= 3, `Expected >= 3 git tools, got ${toolTypes.git.length}`);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should load MCP tools from context7', () => {
|
|
69
|
+
if (skipIfNoBaseUrl()) return;
|
|
70
|
+
const agent = assistant.agent;
|
|
71
|
+
const tools = agent.tools;
|
|
72
|
+
|
|
73
|
+
const mcpTools = tools.filter(tool => tool.name.startsWith('mcp_'));
|
|
74
|
+
|
|
75
|
+
assert.ok(mcpTools.length >= 2, `Expected >= 2 MCP tools, got ${mcpTools.length}`);
|
|
76
|
+
|
|
77
|
+
const toolNames = mcpTools.map(t => t.name);
|
|
78
|
+
assert.ok(toolNames.includes('mcp_resolve-library-id'), 'Should have mcp_resolve-library-id');
|
|
79
|
+
assert.ok(toolNames.includes('mcp_get-library-docs'), 'Should have mcp_get-library-docs');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Test: UI formatting
|
|
3
|
+
* Uses Node.js native test runner
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it } from 'node:test';
|
|
7
|
+
import assert from 'node:assert';
|
|
8
|
+
|
|
9
|
+
describe('UI Format', () => {
|
|
10
|
+
it('should format tool calls correctly', () => {
|
|
11
|
+
const toolName = 'Bash';
|
|
12
|
+
const toolArgs = { command: 'ls -la' };
|
|
13
|
+
const formatted = `⏺ ${toolName}(${JSON.stringify(toolArgs)})`;
|
|
14
|
+
|
|
15
|
+
assert.ok(formatted.includes('⏺'), 'Should include bullet point');
|
|
16
|
+
assert.ok(formatted.includes('Bash'), 'Should include tool name');
|
|
17
|
+
assert.ok(formatted.includes('ls -la'), 'Should include arguments');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should format tool results with indentation', () => {
|
|
21
|
+
const result = 'total 672\ndrwxr-xr-x@ 21 Nikita_Levyankov';
|
|
22
|
+
const lines = result.split('\n');
|
|
23
|
+
const formatted = ` ⎿ ${lines[0]}`;
|
|
24
|
+
|
|
25
|
+
assert.ok(formatted.includes('⎿'), 'Should include corner symbol');
|
|
26
|
+
assert.ok(formatted.startsWith(' '), 'Should be indented');
|
|
27
|
+
assert.ok(formatted.includes('total 672'), 'Should include result content');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should truncate long multi-line results', () => {
|
|
31
|
+
const result = Array(20).fill('line').join('\n');
|
|
32
|
+
const lines = result.split('\n');
|
|
33
|
+
const displayLines = lines.slice(0, 3);
|
|
34
|
+
const hiddenLines = Math.max(0, lines.length - 3);
|
|
35
|
+
|
|
36
|
+
assert.strictEqual(displayLines.length, 3, 'Should show only 3 lines');
|
|
37
|
+
assert.strictEqual(hiddenLines, 17, 'Should hide 17 lines');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Test: UI state management
|
|
3
|
+
* Uses Node.js native test runner
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, before, after } from 'node:test';
|
|
7
|
+
import assert from 'node:assert';
|
|
8
|
+
import { CodeMieCode } from '../dist/code/index.js';
|
|
9
|
+
import { skipIfNoBaseUrl } from './test-helpers.mjs';
|
|
10
|
+
|
|
11
|
+
describe('UI State Management', () => {
|
|
12
|
+
let assistant;
|
|
13
|
+
|
|
14
|
+
before(async () => {
|
|
15
|
+
if (skipIfNoBaseUrl()) return;
|
|
16
|
+
|
|
17
|
+
assistant = new CodeMieCode(process.cwd());
|
|
18
|
+
await assistant.initialize({ showTips: false });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
after(async () => {
|
|
22
|
+
if (assistant) {
|
|
23
|
+
await assistant.dispose();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should handle consecutive messages without blocking', async () => {
|
|
28
|
+
if (skipIfNoBaseUrl()) return;
|
|
29
|
+
const mockUIState = {
|
|
30
|
+
isProcessing: false,
|
|
31
|
+
inputEnabled: true
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const questions = [
|
|
35
|
+
'What is 2+2?',
|
|
36
|
+
'What is the capital of France?',
|
|
37
|
+
'List files in current directory'
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
let messageCount = 0;
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < questions.length; i++) {
|
|
43
|
+
const question = questions[i];
|
|
44
|
+
|
|
45
|
+
// Check if processing (simulating UI check)
|
|
46
|
+
assert.strictEqual(mockUIState.isProcessing, false, `Should not be processing before question ${i + 1}`);
|
|
47
|
+
|
|
48
|
+
// Set processing flag (like the UI does)
|
|
49
|
+
mockUIState.isProcessing = true;
|
|
50
|
+
mockUIState.inputEnabled = false;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// Call the agent
|
|
54
|
+
await assistant.agent.chatStream(question, (event) => {
|
|
55
|
+
// Track events silently
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
messageCount++;
|
|
59
|
+
} finally {
|
|
60
|
+
// Reset state (like the UI does)
|
|
61
|
+
mockUIState.isProcessing = false;
|
|
62
|
+
mockUIState.inputEnabled = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Verify state is properly reset
|
|
66
|
+
assert.strictEqual(mockUIState.isProcessing, false, `isProcessing should be reset after question ${i + 1}`);
|
|
67
|
+
assert.strictEqual(mockUIState.inputEnabled, true, `inputEnabled should be reset after question ${i + 1}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
assert.strictEqual(messageCount, 3, 'Should have processed all 3 messages');
|
|
71
|
+
});
|
|
72
|
+
});
|