@tyvm/knowhow 0.0.36 โ 0.0.38
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/package.json +1 -1
- package/src/agents/base/base.ts +8 -0
- package/src/agents/tools/aiClient.ts +36 -0
- package/src/agents/tools/lintFile.ts +1 -1
- package/src/agents/tools/list.ts +34 -0
- package/src/ai.ts +5 -4
- package/src/auth/browserLogin.ts +283 -0
- package/src/auth/errors.ts +6 -0
- package/src/auth/spinner.ts +23 -0
- package/src/chat/CliChatService.ts +25 -6
- package/src/chat/modules/AgentModule.ts +1 -2
- package/src/chat/modules/AskModule.ts +1 -2
- package/src/chat/types.ts +14 -4
- package/src/chat-old.ts +446 -0
- package/src/chat.ts +48 -433
- package/src/cli.ts +9 -14
- package/src/clients/index.ts +35 -2
- package/src/embeddings.ts +1 -1
- package/src/index.ts +1 -8
- package/src/login.ts +14 -1
- package/src/microphone.ts +0 -1
- package/src/plugins/downloader/downloader.ts +4 -2
- package/src/services/KnowhowClient.ts +1 -1
- package/src/services/index.ts +1 -2
- package/tests/manual/browser-login/README.md +189 -0
- package/tests/manual/browser-login/test_browser_login_basic.ts +115 -0
- package/tests/manual/browser-login/test_cli_integration.ts +169 -0
- package/tests/manual/browser-login/test_cross_platform_browser.ts +186 -0
- package/tests/manual/browser-login/test_error_scenarios.ts +223 -0
- package/tests/manual/cli/no-env.sh +267 -0
- package/ts_build/src/agents/base/base.js +4 -0
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/tools/aiClient.d.ts +2 -0
- package/ts_build/src/agents/tools/aiClient.js +21 -1
- package/ts_build/src/agents/tools/aiClient.js.map +1 -1
- package/ts_build/src/agents/tools/lintFile.js +1 -1
- package/ts_build/src/agents/tools/lintFile.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +32 -0
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/ai.d.ts +1 -1
- package/ts_build/src/ai.js +2 -1
- package/ts_build/src/ai.js.map +1 -1
- package/ts_build/src/auth/browserLogin.d.ts +11 -0
- package/ts_build/src/auth/browserLogin.js +197 -0
- package/ts_build/src/auth/browserLogin.js.map +1 -0
- package/ts_build/src/auth/errors.d.ts +4 -0
- package/ts_build/src/auth/errors.js +13 -0
- package/ts_build/src/auth/errors.js.map +1 -0
- package/ts_build/src/auth/spinner.d.ts +7 -0
- package/ts_build/src/auth/spinner.js +23 -0
- package/ts_build/src/auth/spinner.js.map +1 -0
- package/ts_build/src/chat/CliChatService.d.ts +4 -3
- package/ts_build/src/chat/CliChatService.js +18 -4
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +1 -1
- package/ts_build/src/chat/modules/AgentModule.js +1 -2
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/AskModule.js +1 -2
- package/ts_build/src/chat/modules/AskModule.js.map +1 -1
- package/ts_build/src/chat/types.d.ts +5 -3
- package/ts_build/src/chat-old.d.ts +13 -0
- package/ts_build/src/chat-old.js +340 -0
- package/ts_build/src/chat-old.js.map +1 -0
- package/ts_build/src/chat.d.ts +3 -13
- package/ts_build/src/chat.js +38 -331
- package/ts_build/src/chat.js.map +1 -1
- package/ts_build/src/chat2.d.ts +1 -1
- package/ts_build/src/chat2.js +2 -2
- package/ts_build/src/chat2.js.map +1 -1
- package/ts_build/src/cli.js +7 -11
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/index.d.ts +2 -2
- package/ts_build/src/clients/index.js +16 -1
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/embeddings.js.map +1 -1
- package/ts_build/src/index.d.ts +1 -2
- package/ts_build/src/index.js +2 -9
- package/ts_build/src/index.js.map +1 -1
- package/ts_build/src/login.d.ts +1 -1
- package/ts_build/src/login.js +14 -0
- package/ts_build/src/login.js.map +1 -1
- package/ts_build/src/microphone.js.map +1 -1
- package/ts_build/src/plugins/downloader/downloader.d.ts +1 -3
- package/ts_build/src/plugins/downloader/downloader.js +4 -4
- package/ts_build/src/plugins/downloader/downloader.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.js +1 -1
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/index.js +1 -2
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.d.ts +2 -0
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.js +108 -0
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.js.map +1 -0
- package/ts_build/tests/manual/browser-login/test_cli_integration.d.ts +2 -0
- package/ts_build/tests/manual/browser-login/test_cli_integration.js +153 -0
- package/ts_build/tests/manual/browser-login/test_cli_integration.js.map +1 -0
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.d.ts +2 -0
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js +159 -0
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js.map +1 -0
- package/ts_build/tests/manual/browser-login/test_error_scenarios.d.ts +2 -0
- package/ts_build/tests/manual/browser-login/test_error_scenarios.js +197 -0
- package/ts_build/tests/manual/browser-login/test_error_scenarios.js.map +1 -0
- package/src/agents/vim/vim.ts +0 -152
- package/src/chat2.ts +0 -62
package/src/login.ts
CHANGED
|
@@ -5,8 +5,9 @@ import { chmod } from "fs/promises";
|
|
|
5
5
|
import { ask } from "./utils";
|
|
6
6
|
import { getConfig, updateConfig } from "./config";
|
|
7
7
|
import { KNOWHOW_API_URL } from "./services/KnowhowClient";
|
|
8
|
+
import { BrowserLoginService } from "./auth/browserLogin";
|
|
8
9
|
|
|
9
|
-
export async function login(jwtFlag?:
|
|
10
|
+
export async function login(jwtFlag?: boolean): Promise<void> {
|
|
10
11
|
if (!KNOWHOW_API_URL) {
|
|
11
12
|
throw new Error("Error: KNOWHOW_API_URL environment variable not set.");
|
|
12
13
|
}
|
|
@@ -24,6 +25,18 @@ export async function login(jwtFlag?: string): Promise<void> {
|
|
|
24
25
|
fs.writeFileSync(jwtFile, jwt);
|
|
25
26
|
fs.chmodSync(jwtFile, 0o600);
|
|
26
27
|
console.log("JWT updated successfully.");
|
|
28
|
+
} else {
|
|
29
|
+
// Use browser login as default method
|
|
30
|
+
console.log("Starting browser-based authentication...");
|
|
31
|
+
try {
|
|
32
|
+
const browserLoginService = new BrowserLoginService();
|
|
33
|
+
await browserLoginService.login();
|
|
34
|
+
console.log("Successfully authenticated via browser!");
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error("Browser authentication failed:", error.message);
|
|
37
|
+
console.log("You can try manual JWT login with: knowhow login --jwt");
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
// Get current user/org information
|
package/src/microphone.ts
CHANGED
|
@@ -8,11 +8,12 @@ import { execAsync, fileExists, readFile, mkdir } from "../../utils";
|
|
|
8
8
|
import OpenAI from "openai";
|
|
9
9
|
import { Clients } from "../../clients";
|
|
10
10
|
import { Models } from "../../types";
|
|
11
|
+
import { openai } from "../../ai";
|
|
11
12
|
|
|
12
13
|
const logger = Logger();
|
|
13
14
|
|
|
14
15
|
export class DownloaderService {
|
|
15
|
-
constructor(private
|
|
16
|
+
constructor(private clients: typeof Clients) {}
|
|
16
17
|
|
|
17
18
|
async askGptVision(
|
|
18
19
|
imageUrl: string,
|
|
@@ -131,6 +132,7 @@ export class DownloaderService {
|
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
const allTranscripts = [];
|
|
135
|
+
const openAi = openai();
|
|
134
136
|
for (const file of files) {
|
|
135
137
|
const chunkName = path.parse(file).name;
|
|
136
138
|
const chunkTranscriptPath = path.join(
|
|
@@ -157,7 +159,7 @@ export class DownloaderService {
|
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
console.log("Transcribing", file);
|
|
160
|
-
const transcript = await
|
|
162
|
+
const transcript = await openAi.audio.transcriptions
|
|
161
163
|
.create({
|
|
162
164
|
file: fs.createReadStream(file),
|
|
163
165
|
model: "whisper-1",
|
package/src/services/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { openai } from "../ai";
|
|
2
1
|
import { DownloaderService } from "../plugins/downloader/downloader";
|
|
3
2
|
import { Clients } from "../clients";
|
|
4
3
|
import { Plugins } from "../plugins/plugins";
|
|
@@ -41,7 +40,7 @@ export const services = (): typeof Singletons => {
|
|
|
41
40
|
const Tools = new ToolsService();
|
|
42
41
|
const Events = new EventService();
|
|
43
42
|
const Agents = new AgentService(Tools, Events);
|
|
44
|
-
const Downloader = new DownloaderService(
|
|
43
|
+
const Downloader = new DownloaderService(Clients);
|
|
45
44
|
Singletons = {
|
|
46
45
|
Tools,
|
|
47
46
|
Events,
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Browser Login Manual Tests
|
|
2
|
+
|
|
3
|
+
This directory contains comprehensive manual tests for the browser-based login functionality in the Knowhow CLI.
|
|
4
|
+
|
|
5
|
+
## Test Overview
|
|
6
|
+
|
|
7
|
+
The browser login implementation includes the following key features:
|
|
8
|
+
- Browser-based authentication as the default login method
|
|
9
|
+
- Cross-platform browser opening (macOS, Windows, Linux)
|
|
10
|
+
- Polling mechanism with exponential backoff
|
|
11
|
+
- JWT token retrieval and secure storage
|
|
12
|
+
- Graceful error handling and user cancellation
|
|
13
|
+
- Backwards compatibility with `--jwt` flag
|
|
14
|
+
|
|
15
|
+
## Test Files
|
|
16
|
+
|
|
17
|
+
### 1. `test_browser_login_basic.ts`
|
|
18
|
+
**Purpose**: Tests the core browser login flow end-to-end
|
|
19
|
+
|
|
20
|
+
**What it tests**:
|
|
21
|
+
- Session creation with the API
|
|
22
|
+
- Browser opening for user authentication
|
|
23
|
+
- Authentication polling and completion
|
|
24
|
+
- JWT retrieval and secure storage
|
|
25
|
+
- File permissions (0o600)
|
|
26
|
+
- JWT format validation
|
|
27
|
+
|
|
28
|
+
**Prerequisites**:
|
|
29
|
+
- Valid `KNOWHOW_API_URL` environment variable
|
|
30
|
+
- Network connection to Knowhow API
|
|
31
|
+
- Default browser available
|
|
32
|
+
|
|
33
|
+
**Usage**:
|
|
34
|
+
```bash
|
|
35
|
+
npx tsx ./tests/manual/browser-login/test_browser_login_basic.ts
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Manual steps required**:
|
|
39
|
+
- Complete authentication in the opened browser window
|
|
40
|
+
- Verify browser opened to correct URL
|
|
41
|
+
|
|
42
|
+
### 2. `test_cli_integration.ts`
|
|
43
|
+
**Purpose**: Tests CLI command integration and backwards compatibility
|
|
44
|
+
|
|
45
|
+
**What it tests**:
|
|
46
|
+
- `knowhow login` uses browser login by default
|
|
47
|
+
- `knowhow login --jwt` prompts for manual JWT input
|
|
48
|
+
- Command help shows correct options
|
|
49
|
+
- JWT file creation through CLI
|
|
50
|
+
|
|
51
|
+
**Prerequisites**:
|
|
52
|
+
- Built CLI application (`npm run build`)
|
|
53
|
+
- Valid `KNOWHOW_API_URL` environment variable
|
|
54
|
+
|
|
55
|
+
**Usage**:
|
|
56
|
+
```bash
|
|
57
|
+
npx tsx ./tests/manual/browser-login/test_cli_integration.ts
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Manual steps required**:
|
|
61
|
+
- Complete browser authentication when prompted
|
|
62
|
+
- Verify help output is correct
|
|
63
|
+
|
|
64
|
+
### 3. `test_cross_platform_browser.ts`
|
|
65
|
+
**Purpose**: Tests browser opening across different operating systems
|
|
66
|
+
|
|
67
|
+
**What it tests**:
|
|
68
|
+
- Platform detection (macOS, Windows, Linux)
|
|
69
|
+
- Correct browser command selection (`open`, `start`, `xdg-open`)
|
|
70
|
+
- Browser command availability
|
|
71
|
+
- URL handling with special characters
|
|
72
|
+
- Graceful fallback when browser opening fails
|
|
73
|
+
|
|
74
|
+
**Prerequisites**:
|
|
75
|
+
- Default browser installed
|
|
76
|
+
- Platform-specific browser commands available
|
|
77
|
+
|
|
78
|
+
**Usage**:
|
|
79
|
+
```bash
|
|
80
|
+
npx tsx ./tests/manual/browser-login/test_cross_platform_browser.ts
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Manual steps required**:
|
|
84
|
+
- Verify browser opens to test URLs
|
|
85
|
+
- Confirm platform-specific behavior
|
|
86
|
+
|
|
87
|
+
### 4. `test_error_scenarios.ts`
|
|
88
|
+
**Purpose**: Tests error handling and edge cases
|
|
89
|
+
|
|
90
|
+
**What it tests**:
|
|
91
|
+
- Invalid API URL handling
|
|
92
|
+
- Missing API URL configuration
|
|
93
|
+
- JWT validation with various inputs
|
|
94
|
+
- File permission handling
|
|
95
|
+
- Error code propagation
|
|
96
|
+
- Graceful cancellation mechanisms
|
|
97
|
+
|
|
98
|
+
**Prerequisites**:
|
|
99
|
+
- Ability to modify environment variables temporarily
|
|
100
|
+
|
|
101
|
+
**Usage**:
|
|
102
|
+
```bash
|
|
103
|
+
npx tsx ./tests/manual/browser-login/test_error_scenarios.ts
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Manual steps required**:
|
|
107
|
+
- None (fully automated error scenario testing)
|
|
108
|
+
|
|
109
|
+
## Running All Tests
|
|
110
|
+
|
|
111
|
+
To run all tests in sequence:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Run individual tests
|
|
115
|
+
npx tsx ./tests/manual/browser-login/test_error_scenarios.ts
|
|
116
|
+
npx tsx ./tests/manual/browser-login/test_cross_platform_browser.ts
|
|
117
|
+
npx tsx ./tests/manual/browser-login/test_cli_integration.ts
|
|
118
|
+
npx tsx ./tests/manual/browser-login/test_browser_login_basic.ts
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Test Results Interpretation
|
|
122
|
+
|
|
123
|
+
### โ
PASSED
|
|
124
|
+
Test completed successfully with expected behavior.
|
|
125
|
+
|
|
126
|
+
### โ ๏ธ WARNING
|
|
127
|
+
Test completed but with minor issues or platform-specific concerns that don't prevent functionality.
|
|
128
|
+
|
|
129
|
+
### โ FAILED
|
|
130
|
+
Test failed due to errors or unexpected behavior that needs to be addressed.
|
|
131
|
+
|
|
132
|
+
### Manual Verification Required
|
|
133
|
+
Some tests require manual verification (e.g., confirming browser opened correctly) as they test user interaction flows.
|
|
134
|
+
|
|
135
|
+
## Common Issues and Troubleshooting
|
|
136
|
+
|
|
137
|
+
### Browser Not Opening
|
|
138
|
+
- **Symptoms**: Browser opening fails or command not found
|
|
139
|
+
- **Solutions**:
|
|
140
|
+
- Ensure default browser is installed
|
|
141
|
+
- Check platform-specific command availability (`open`, `start`, `xdg-open`)
|
|
142
|
+
- Verify display environment for Linux systems
|
|
143
|
+
|
|
144
|
+
### Network Errors
|
|
145
|
+
- **Symptoms**: API connection failures or timeouts
|
|
146
|
+
- **Solutions**:
|
|
147
|
+
- Verify `KNOWHOW_API_URL` is set correctly
|
|
148
|
+
- Check network connectivity
|
|
149
|
+
- Confirm API endpoints are accessible
|
|
150
|
+
|
|
151
|
+
### Permission Errors
|
|
152
|
+
- **Symptoms**: Cannot create or write JWT files
|
|
153
|
+
- **Solutions**:
|
|
154
|
+
- Check write permissions in project directory
|
|
155
|
+
- Verify `.knowhow` directory can be created
|
|
156
|
+
- Check for filesystem restrictions
|
|
157
|
+
|
|
158
|
+
### Authentication Timeout
|
|
159
|
+
- **Symptoms**: Polling times out before user completes authentication
|
|
160
|
+
- **Solutions**:
|
|
161
|
+
- Complete authentication more quickly
|
|
162
|
+
- Check if browser session is blocked by ad blockers
|
|
163
|
+
- Verify correct authentication URL
|
|
164
|
+
|
|
165
|
+
## Integration with CI/CD
|
|
166
|
+
|
|
167
|
+
These manual tests are designed for human verification and are not suitable for automated CI/CD pipelines. For automated testing, consider:
|
|
168
|
+
|
|
169
|
+
1. Mocking the browser opening functionality
|
|
170
|
+
2. Creating integration tests with test authentication endpoints
|
|
171
|
+
3. Unit testing individual components separately
|
|
172
|
+
|
|
173
|
+
## Security Considerations
|
|
174
|
+
|
|
175
|
+
When running these tests:
|
|
176
|
+
- JWT tokens are stored temporarily and cleaned up
|
|
177
|
+
- File permissions are tested to ensure secure storage (0o600)
|
|
178
|
+
- No sensitive data should be logged or persisted beyond test execution
|
|
179
|
+
- Tests clean up after themselves to avoid leaving test artifacts
|
|
180
|
+
|
|
181
|
+
## Contributing
|
|
182
|
+
|
|
183
|
+
When adding new tests:
|
|
184
|
+
1. Follow the existing test file naming pattern
|
|
185
|
+
2. Include comprehensive error handling
|
|
186
|
+
3. Provide clear manual steps in comments
|
|
187
|
+
4. Clean up any created files or state
|
|
188
|
+
5. Add appropriate timeout handling
|
|
189
|
+
6. Update this README with new test descriptions
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manual Test: Basic Browser Login Flow
|
|
5
|
+
*
|
|
6
|
+
* This test validates the complete browser-based authentication flow:
|
|
7
|
+
* 1. Creates a login session with the API
|
|
8
|
+
* 2. Opens browser for user authentication
|
|
9
|
+
* 3. Polls for authentication completion
|
|
10
|
+
* 4. Retrieves and stores JWT token
|
|
11
|
+
*
|
|
12
|
+
* Prerequisites:
|
|
13
|
+
* - Valid KNOWHOW_API_URL environment variable
|
|
14
|
+
* - Network connection to Knowhow API
|
|
15
|
+
* - Browser available on the system
|
|
16
|
+
*
|
|
17
|
+
* Usage: npx tsx ./tests/manual/browser-login/test_browser_login_basic.ts
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { BrowserLoginService } from '../../../src/auth/browserLogin';
|
|
21
|
+
import * as fs from 'fs';
|
|
22
|
+
import * as path from 'path';
|
|
23
|
+
|
|
24
|
+
async function testBasicBrowserLogin(): Promise<void> {
|
|
25
|
+
console.log('\n=== Basic Browser Login Test ===\n');
|
|
26
|
+
|
|
27
|
+
let success = false;
|
|
28
|
+
const configDir = path.join(process.cwd(), '.knowhow');
|
|
29
|
+
const jwtFile = path.join(configDir, '.jwt');
|
|
30
|
+
|
|
31
|
+
// Clean up any existing JWT file
|
|
32
|
+
if (fs.existsSync(jwtFile)) {
|
|
33
|
+
fs.unlinkSync(jwtFile);
|
|
34
|
+
console.log('๐งน Cleaned up existing JWT file');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
console.log('1. Initializing BrowserLoginService...');
|
|
39
|
+
const browserLogin = new BrowserLoginService();
|
|
40
|
+
|
|
41
|
+
console.log('2. Starting browser login flow...');
|
|
42
|
+
console.log(' Note: This will open your browser and require manual authentication');
|
|
43
|
+
console.log(' Please complete the authentication process in your browser');
|
|
44
|
+
|
|
45
|
+
await browserLogin.login();
|
|
46
|
+
|
|
47
|
+
console.log('3. Verifying JWT file was created...');
|
|
48
|
+
if (fs.existsSync(jwtFile)) {
|
|
49
|
+
const jwtContent = fs.readFileSync(jwtFile, 'utf8');
|
|
50
|
+
|
|
51
|
+
// Check file permissions
|
|
52
|
+
const stats = fs.statSync(jwtFile);
|
|
53
|
+
const permissions = stats.mode & parseInt('777', 8);
|
|
54
|
+
|
|
55
|
+
console.log(` โ
JWT file created: ${jwtFile}`);
|
|
56
|
+
console.log(` โ
JWT length: ${jwtContent.length} characters`);
|
|
57
|
+
console.log(` โ
File permissions: ${permissions.toString(8)} (should be 600)`);
|
|
58
|
+
|
|
59
|
+
// Basic JWT validation
|
|
60
|
+
const parts = jwtContent.split('.');
|
|
61
|
+
if (parts.length === 3) {
|
|
62
|
+
console.log(' โ
JWT has correct structure (3 parts)');
|
|
63
|
+
success = true;
|
|
64
|
+
} else {
|
|
65
|
+
console.log(' โ JWT has incorrect structure');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (permissions === parseInt('600', 8)) {
|
|
69
|
+
console.log(' โ
JWT file has correct permissions (600)');
|
|
70
|
+
} else {
|
|
71
|
+
console.log(` โ ๏ธ JWT file permissions may be incorrect: ${permissions.toString(8)}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
} else {
|
|
75
|
+
console.log(' โ JWT file was not created');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error('โ Test failed with error:', error.message);
|
|
80
|
+
|
|
81
|
+
if (error.code === 'USER_CANCELLED') {
|
|
82
|
+
console.log(' โน๏ธ Authentication was cancelled by user (this is expected for Ctrl+C)');
|
|
83
|
+
} else if (error.code === 'TIMEOUT') {
|
|
84
|
+
console.log(' โ ๏ธ Authentication timed out (user may not have completed authentication)');
|
|
85
|
+
} else if (error.code === 'NETWORK_ERROR') {
|
|
86
|
+
console.log(' โ Network error - check API connectivity');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log('\n=== Test Results ===');
|
|
91
|
+
if (success) {
|
|
92
|
+
console.log('โ
Browser login test PASSED');
|
|
93
|
+
console.log(' - Session created successfully');
|
|
94
|
+
console.log(' - Browser opened for authentication');
|
|
95
|
+
console.log(' - JWT retrieved and stored securely');
|
|
96
|
+
process.exit(0);
|
|
97
|
+
} else {
|
|
98
|
+
console.log('โ Browser login test FAILED');
|
|
99
|
+
console.log(' See error details above');
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Handle graceful shutdown
|
|
105
|
+
process.on('SIGINT', () => {
|
|
106
|
+
console.log('\n\n๐ Test interrupted by user (Ctrl+C)');
|
|
107
|
+
console.log(' This tests the graceful cancellation feature');
|
|
108
|
+
process.exit(0);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Run the test
|
|
112
|
+
testBasicBrowserLogin().catch((error) => {
|
|
113
|
+
console.error('Unhandled error:', error);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manual Test: CLI Integration Test
|
|
5
|
+
*
|
|
6
|
+
* This test validates the integration of browser login with the CLI command system:
|
|
7
|
+
* 1. Tests `knowhow login` (browser login as default)
|
|
8
|
+
* 2. Tests `knowhow login --jwt` (legacy JWT input)
|
|
9
|
+
* 3. Verifies backwards compatibility
|
|
10
|
+
* 4. Tests login status verification
|
|
11
|
+
*
|
|
12
|
+
* Prerequisites:
|
|
13
|
+
* - Built CLI application
|
|
14
|
+
* - Valid KNOWHOW_API_URL environment variable
|
|
15
|
+
* - Network connection to Knowhow API
|
|
16
|
+
*
|
|
17
|
+
* Usage: npx tsx ./tests/manual/browser-login/test_cli_integration.ts
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { exec } from 'child_process';
|
|
21
|
+
import { promisify } from 'util';
|
|
22
|
+
import * as fs from 'fs';
|
|
23
|
+
import * as path from 'path';
|
|
24
|
+
|
|
25
|
+
const execAsync = promisify(exec);
|
|
26
|
+
|
|
27
|
+
async function testCliIntegration(): Promise<void> {
|
|
28
|
+
console.log('\n=== CLI Integration Test ===\n');
|
|
29
|
+
|
|
30
|
+
const configDir = path.join(process.cwd(), '.knowhow');
|
|
31
|
+
const jwtFile = path.join(configDir, '.jwt');
|
|
32
|
+
let testResults: string[] = [];
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Clean up any existing JWT file
|
|
36
|
+
if (fs.existsSync(jwtFile)) {
|
|
37
|
+
fs.unlinkSync(jwtFile);
|
|
38
|
+
console.log('๐งน Cleaned up existing JWT file\n');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log('=== Test 1: Browser Login as Default ===');
|
|
42
|
+
console.log('Testing: knowhow login (should use browser login)');
|
|
43
|
+
console.log('Note: This will open your browser - please complete authentication\n');
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
// This should use browser login by default
|
|
47
|
+
const { stdout, stderr } = await execAsync('npm run build && node dist/cli.js login', {
|
|
48
|
+
timeout: 120000 // 2 minutes timeout
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log('Command output:', stdout);
|
|
52
|
+
if (stderr) console.log('Command stderr:', stderr);
|
|
53
|
+
|
|
54
|
+
// Check if JWT file was created
|
|
55
|
+
if (fs.existsSync(jwtFile)) {
|
|
56
|
+
const jwtContent = fs.readFileSync(jwtFile, 'utf8');
|
|
57
|
+
if (jwtContent.split('.').length === 3) {
|
|
58
|
+
console.log('โ
Test 1 PASSED: Browser login created valid JWT');
|
|
59
|
+
testResults.push('โ
Browser login as default: PASSED');
|
|
60
|
+
} else {
|
|
61
|
+
console.log('โ Test 1 FAILED: Invalid JWT created');
|
|
62
|
+
testResults.push('โ Browser login as default: FAILED (invalid JWT)');
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.log('โ Test 1 FAILED: No JWT file created');
|
|
66
|
+
testResults.push('โ Browser login as default: FAILED (no JWT file)');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (error.killed && error.signal === 'SIGTERM') {
|
|
71
|
+
console.log('โ ๏ธ Test 1 TIMEOUT: User may not have completed authentication');
|
|
72
|
+
testResults.push('โ ๏ธ Browser login as default: TIMEOUT');
|
|
73
|
+
} else {
|
|
74
|
+
console.log('โ Test 1 ERROR:', error.message);
|
|
75
|
+
testResults.push('โ Browser login as default: ERROR');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Clean up for next test
|
|
80
|
+
if (fs.existsSync(jwtFile)) {
|
|
81
|
+
fs.unlinkSync(jwtFile);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log('\n=== Test 2: Legacy JWT Input ===');
|
|
85
|
+
console.log('Testing: knowhow login --jwt (should prompt for manual JWT input)');
|
|
86
|
+
|
|
87
|
+
// Create a mock interaction that immediately exits
|
|
88
|
+
try {
|
|
89
|
+
const { stdout, stderr } = await execAsync('echo "" | npm run build && echo "" | node dist/cli.js login --jwt', {
|
|
90
|
+
timeout: 10000
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
console.log('Command output:', stdout);
|
|
94
|
+
if (stderr) console.log('Command stderr:', stderr);
|
|
95
|
+
|
|
96
|
+
// The command should have prompted for JWT input
|
|
97
|
+
if (stdout.includes('JWT') || stdout.includes('token') || stderr.includes('JWT') || stderr.includes('token')) {
|
|
98
|
+
console.log('โ
Test 2 PASSED: --jwt flag triggers manual JWT input');
|
|
99
|
+
testResults.push('โ
Legacy JWT input: PASSED');
|
|
100
|
+
} else {
|
|
101
|
+
console.log('โ Test 2 FAILED: --jwt flag not working correctly');
|
|
102
|
+
testResults.push('โ Legacy JWT input: FAILED');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
} catch (error) {
|
|
106
|
+
// This is expected since we're not providing valid JWT input
|
|
107
|
+
if (error.message.includes('JWT') || error.message.includes('token')) {
|
|
108
|
+
console.log('โ
Test 2 PASSED: --jwt flag triggered JWT input prompt');
|
|
109
|
+
testResults.push('โ
Legacy JWT input: PASSED');
|
|
110
|
+
} else {
|
|
111
|
+
console.log('โ Test 2 FAILED:', error.message);
|
|
112
|
+
testResults.push('โ Legacy JWT input: FAILED');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
console.log('\n=== Test 3: Command Help ===');
|
|
117
|
+
console.log('Testing: knowhow login --help');
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const { stdout, stderr } = await execAsync('npm run build && node dist/cli.js login --help');
|
|
121
|
+
|
|
122
|
+
console.log('Help output:', stdout);
|
|
123
|
+
|
|
124
|
+
if (stdout.includes('--jwt') && stdout.includes('browser')) {
|
|
125
|
+
console.log('โ
Test 3 PASSED: Help shows both browser and JWT options');
|
|
126
|
+
testResults.push('โ
Command help: PASSED');
|
|
127
|
+
} else {
|
|
128
|
+
console.log('โ Test 3 FAILED: Help missing expected options');
|
|
129
|
+
testResults.push('โ Command help: FAILED');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.log('โ Test 3 ERROR:', error.message);
|
|
134
|
+
testResults.push('โ Command help: ERROR');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('โ Test suite failed:', error.message);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Print summary
|
|
142
|
+
console.log('\n=== Test Summary ===');
|
|
143
|
+
testResults.forEach(result => console.log(result));
|
|
144
|
+
|
|
145
|
+
const passedTests = testResults.filter(r => r.includes('PASSED')).length;
|
|
146
|
+
const totalTests = testResults.length;
|
|
147
|
+
|
|
148
|
+
console.log(`\nResults: ${passedTests}/${totalTests} tests passed`);
|
|
149
|
+
|
|
150
|
+
if (passedTests === totalTests) {
|
|
151
|
+
console.log('๐ All CLI integration tests PASSED!');
|
|
152
|
+
process.exit(0);
|
|
153
|
+
} else {
|
|
154
|
+
console.log('โ Some CLI integration tests FAILED');
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Handle graceful shutdown
|
|
160
|
+
process.on('SIGINT', () => {
|
|
161
|
+
console.log('\n\n๐ Test interrupted by user (Ctrl+C)');
|
|
162
|
+
process.exit(0);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Run the test
|
|
166
|
+
testCliIntegration().catch((error) => {
|
|
167
|
+
console.error('Unhandled error:', error);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
});
|