edsger 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/app-store.d.ts +76 -0
- package/dist/api/app-store.js +148 -0
- package/dist/api/github.js +16 -23
- package/dist/api/mcp-client.js +5 -10
- package/dist/auth/auth-store.d.ts +13 -0
- package/dist/auth/auth-store.js +38 -1
- package/dist/auth/login.js +18 -18
- package/dist/commands/agent-workflow/index.js +6 -6
- package/dist/commands/agent-workflow/processor.d.ts +1 -1
- package/dist/commands/agent-workflow/processor.js +34 -6
- package/dist/commands/analyze-logs/index.d.ts +7 -0
- package/dist/commands/analyze-logs/index.js +34 -0
- package/dist/commands/app-store/index.d.ts +12 -0
- package/dist/commands/app-store/index.js +60 -0
- package/dist/commands/code-review/reviewer.js +14 -13
- package/dist/commands/growth-analysis/index.js +14 -1
- package/dist/commands/init/index.js +4 -4
- package/dist/commands/refactor/refactor.js +4 -4
- package/dist/commands/workflow/core/__tests__/feature-filter.test.d.ts +5 -0
- package/dist/commands/workflow/core/__tests__/feature-filter.test.js +325 -0
- package/dist/commands/workflow/core/__tests__/pipeline-evaluator.test.d.ts +4 -0
- package/dist/commands/workflow/core/__tests__/pipeline-evaluator.test.js +406 -0
- package/dist/commands/workflow/core/__tests__/state-manager.test.d.ts +4 -0
- package/dist/commands/workflow/core/__tests__/state-manager.test.js +384 -0
- package/dist/commands/workflow/core/workflow-logger.js +6 -6
- package/dist/commands/workflow/executors/phase-executor.js +19 -18
- package/dist/config/__tests__/config.test.d.ts +4 -0
- package/dist/config/__tests__/config.test.js +286 -0
- package/dist/config.js +12 -0
- package/dist/errors/__tests__/index.test.d.ts +4 -0
- package/dist/errors/__tests__/index.test.js +349 -0
- package/dist/errors/index.d.ts +62 -0
- package/dist/errors/index.js +116 -0
- package/dist/index.js +48 -0
- package/dist/phases/analyze-logs/agent.d.ts +11 -0
- package/dist/phases/analyze-logs/agent.js +63 -0
- package/dist/phases/analyze-logs/index.d.ts +23 -0
- package/dist/phases/analyze-logs/index.js +131 -0
- package/dist/phases/analyze-logs/prompts.d.ts +3 -0
- package/dist/phases/analyze-logs/prompts.js +59 -0
- package/dist/phases/app-store-generation/__tests__/agent.test.d.ts +5 -0
- package/dist/phases/app-store-generation/__tests__/agent.test.js +144 -0
- package/dist/phases/app-store-generation/__tests__/context.test.d.ts +4 -0
- package/dist/phases/app-store-generation/__tests__/context.test.js +280 -0
- package/dist/phases/app-store-generation/__tests__/prompts.test.d.ts +4 -0
- package/dist/phases/app-store-generation/__tests__/prompts.test.js +165 -0
- package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.d.ts +5 -0
- package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.js +407 -0
- package/dist/phases/app-store-generation/agent.d.ts +2 -0
- package/dist/phases/app-store-generation/agent.js +97 -0
- package/dist/phases/app-store-generation/context.d.ts +21 -0
- package/dist/phases/app-store-generation/context.js +77 -0
- package/dist/phases/app-store-generation/index.d.ts +19 -0
- package/dist/phases/app-store-generation/index.js +119 -0
- package/dist/phases/app-store-generation/prompts.d.ts +43 -0
- package/dist/phases/app-store-generation/prompts.js +134 -0
- package/dist/phases/app-store-generation/screenshot-composer.d.ts +42 -0
- package/dist/phases/app-store-generation/screenshot-composer.js +319 -0
- package/dist/phases/app-store-generation/uploader.d.ts +18 -0
- package/dist/phases/app-store-generation/uploader.js +119 -0
- package/dist/phases/autonomous/index.js +3 -7
- package/dist/phases/branch-planning/index.js +3 -7
- package/dist/phases/bug-fixing/analyzer.js +3 -7
- package/dist/phases/bug-fixing/mcp-server.js +2 -1
- package/dist/phases/chat-processor/index.js +5 -13
- package/dist/phases/code-implementation/index.d.ts +2 -2
- package/dist/phases/code-implementation/index.js +63 -86
- package/dist/phases/code-implementation-verification/agent.js +3 -7
- package/dist/phases/code-refine/context.js +24 -56
- package/dist/phases/code-refine/index.js +3 -7
- package/dist/phases/code-refine/retry-handler.js +9 -15
- package/dist/phases/code-review/context.js +21 -49
- package/dist/phases/code-review/index.js +2 -4
- package/dist/phases/code-testing/analyzer.js +7 -11
- package/dist/phases/feature-analysis/agent.js +3 -7
- package/dist/phases/feature-analysis-verification/agent.js +2 -4
- package/dist/phases/functional-testing/analyzer.js +6 -9
- package/dist/phases/functional-testing/http-fallback.js +5 -4
- package/dist/phases/functional-testing/mcp-server.js +3 -2
- package/dist/phases/functional-testing/test-report-creator.js +7 -6
- package/dist/phases/functional-testing/test-retry-handler.js +8 -15
- package/dist/phases/growth-analysis/agent.js +3 -7
- package/dist/phases/growth-analysis/index.d.ts +6 -0
- package/dist/phases/growth-analysis/index.js +142 -2
- package/dist/phases/growth-analysis/prompts.js +70 -3
- package/dist/phases/pr-execution/index.js +3 -7
- package/dist/phases/pr-splitting/index.js +3 -7
- package/dist/phases/pull-request/creator.js +23 -66
- package/dist/phases/pull-request/handler.js +13 -32
- package/dist/phases/task/agent.js +3 -7
- package/dist/phases/technical-design/index.d.ts +4 -4
- package/dist/phases/technical-design/index.js +3 -7
- package/dist/phases/technical-design-verification/agent.js +2 -4
- package/dist/phases/test-cases-analysis/agent.js +3 -7
- package/dist/phases/user-stories-analysis/agent.js +3 -7
- package/dist/services/branches.js +12 -11
- package/dist/services/checklist.js +18 -17
- package/dist/services/feedbacks.js +16 -14
- package/dist/services/product-logs.d.ts +31 -0
- package/dist/services/product-logs.js +33 -0
- package/dist/services/pull-requests.js +10 -9
- package/dist/services/video/__tests__/video-pipeline.test.d.ts +6 -0
- package/dist/services/video/__tests__/video-pipeline.test.js +231 -0
- package/dist/services/video/device-frames.d.ts +30 -0
- package/dist/services/video/device-frames.js +422 -0
- package/dist/services/video/index.d.ts +66 -0
- package/dist/services/video/index.js +226 -0
- package/dist/services/video/retry.d.ts +20 -0
- package/dist/services/video/retry.js +73 -0
- package/dist/services/video/screenshot-generator.d.ts +67 -0
- package/dist/services/video/screenshot-generator.js +254 -0
- package/dist/services/video/tts-generator.d.ts +40 -0
- package/dist/services/video/tts-generator.js +121 -0
- package/dist/services/video/video-assembler.d.ts +45 -0
- package/dist/services/video/video-assembler.js +308 -0
- package/dist/services/video/video-uploader.d.ts +28 -0
- package/dist/services/video/video-uploader.js +105 -0
- package/dist/types/features.d.ts +2 -2
- package/dist/types/index.d.ts +48 -28
- package/dist/types/llm-responses.d.ts +127 -0
- package/dist/types/llm-responses.js +9 -0
- package/dist/types/pipeline.d.ts +1 -1
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.js +11 -0
- package/dist/utils/pipeline-logger.js +11 -8
- package/dist/utils/validation.js +5 -4
- package/dist/utils/workflow-utils.js +3 -2
- package/package.json +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export interface AppStoreConfig {
|
|
2
|
+
id: string;
|
|
3
|
+
product_id: string;
|
|
4
|
+
store_type: 'apple_app_store' | 'google_play';
|
|
5
|
+
credentials: Record<string, unknown>;
|
|
6
|
+
app_identifier: string | null;
|
|
7
|
+
listings: Record<string, AppStoreListing>;
|
|
8
|
+
screenshots: AppStoreScreenshot[];
|
|
9
|
+
current_version: string | null;
|
|
10
|
+
submission_status: string;
|
|
11
|
+
submitted_at: string | null;
|
|
12
|
+
released_at: string | null;
|
|
13
|
+
rejection_reason: string | null;
|
|
14
|
+
is_active: boolean;
|
|
15
|
+
created_by: string;
|
|
16
|
+
created_at: string;
|
|
17
|
+
updated_at: string;
|
|
18
|
+
}
|
|
19
|
+
export interface AppStoreListing {
|
|
20
|
+
app_name: string;
|
|
21
|
+
subtitle?: string;
|
|
22
|
+
short_description?: string;
|
|
23
|
+
description: string;
|
|
24
|
+
keywords?: string;
|
|
25
|
+
whats_new?: string;
|
|
26
|
+
privacy_policy_url?: string;
|
|
27
|
+
support_url?: string;
|
|
28
|
+
marketing_url?: string;
|
|
29
|
+
primary_category?: string;
|
|
30
|
+
secondary_category?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface AppStoreScreenshot {
|
|
33
|
+
device_type: string;
|
|
34
|
+
display_order: number;
|
|
35
|
+
storage_url: string;
|
|
36
|
+
storage_path: string;
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
caption: string;
|
|
40
|
+
background_gradient: string;
|
|
41
|
+
device_frame: string;
|
|
42
|
+
locale: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get app store configs for a product via MCP
|
|
46
|
+
*/
|
|
47
|
+
export declare function getAppStoreConfigs(productId: string, verbose?: boolean): Promise<AppStoreConfig[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Get a single app store config via MCP
|
|
50
|
+
*/
|
|
51
|
+
export declare function getAppStoreConfig(configId: string, verbose?: boolean): Promise<AppStoreConfig | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Create or update an app store config via MCP
|
|
54
|
+
*/
|
|
55
|
+
export declare function upsertAppStoreConfig(params: {
|
|
56
|
+
product_id: string;
|
|
57
|
+
store_type: string;
|
|
58
|
+
credentials?: Record<string, unknown>;
|
|
59
|
+
app_identifier?: string;
|
|
60
|
+
}, verbose?: boolean): Promise<AppStoreConfig | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Save listings to an app store config via MCP
|
|
63
|
+
*/
|
|
64
|
+
export declare function saveAppStoreListings(configId: string, listings: Record<string, AppStoreListing>, verbose?: boolean): Promise<AppStoreConfig | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Save screenshots to an app store config via MCP
|
|
67
|
+
*/
|
|
68
|
+
export declare function saveAppStoreScreenshots(configId: string, screenshots: AppStoreScreenshot[], verbose?: boolean): Promise<AppStoreConfig | null>;
|
|
69
|
+
/**
|
|
70
|
+
* Update submission status via MCP
|
|
71
|
+
*/
|
|
72
|
+
export declare function updateAppStoreStatus(configId: string, updates: {
|
|
73
|
+
submission_status?: string;
|
|
74
|
+
current_version?: string;
|
|
75
|
+
rejection_reason?: string;
|
|
76
|
+
}, verbose?: boolean): Promise<AppStoreConfig | null>;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { logInfo, logError } from '../utils/logger.js';
|
|
2
|
+
import { callMcpEndpoint } from './mcp-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get app store configs for a product via MCP
|
|
5
|
+
*/
|
|
6
|
+
export async function getAppStoreConfigs(productId, verbose) {
|
|
7
|
+
if (verbose) {
|
|
8
|
+
logInfo(`Fetching app store configs for product: ${productId}`);
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const result = (await callMcpEndpoint('app_store/configs/list', {
|
|
12
|
+
product_id: productId,
|
|
13
|
+
}));
|
|
14
|
+
const text = result.content?.[0]?.text || '[]';
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(text);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (verbose) {
|
|
24
|
+
logError(`Failed to fetch app store configs: ${error instanceof Error ? error.message : String(error)}`);
|
|
25
|
+
}
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get a single app store config via MCP
|
|
31
|
+
*/
|
|
32
|
+
export async function getAppStoreConfig(configId, verbose) {
|
|
33
|
+
try {
|
|
34
|
+
const result = (await callMcpEndpoint('app_store/configs/get', {
|
|
35
|
+
config_id: configId,
|
|
36
|
+
}));
|
|
37
|
+
const text = result.content?.[0]?.text || 'null';
|
|
38
|
+
try {
|
|
39
|
+
return JSON.parse(text);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (verbose) {
|
|
47
|
+
logError(`Failed to fetch app store config: ${error instanceof Error ? error.message : String(error)}`);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create or update an app store config via MCP
|
|
54
|
+
*/
|
|
55
|
+
export async function upsertAppStoreConfig(params, verbose) {
|
|
56
|
+
if (verbose) {
|
|
57
|
+
logInfo(`Upserting app store config for ${params.store_type}`);
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const result = (await callMcpEndpoint('app_store/configs/upsert', params));
|
|
61
|
+
const text = result.content?.[0]?.text || 'null';
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(text);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
logError(`Failed to upsert app store config: ${error instanceof Error ? error.message : String(error)}`);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Save listings to an app store config via MCP
|
|
76
|
+
*/
|
|
77
|
+
export async function saveAppStoreListings(configId, listings, verbose) {
|
|
78
|
+
if (verbose) {
|
|
79
|
+
logInfo(`Saving listings for config: ${configId}`);
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const result = (await callMcpEndpoint('app_store/configs/save_listings', {
|
|
83
|
+
config_id: configId,
|
|
84
|
+
listings,
|
|
85
|
+
}));
|
|
86
|
+
const text = result.content?.[0]?.text || 'null';
|
|
87
|
+
try {
|
|
88
|
+
return JSON.parse(text);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
logError(`Failed to save listings: ${error instanceof Error ? error.message : String(error)}`);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Save screenshots to an app store config via MCP
|
|
101
|
+
*/
|
|
102
|
+
export async function saveAppStoreScreenshots(configId, screenshots, verbose) {
|
|
103
|
+
if (verbose) {
|
|
104
|
+
logInfo(`Saving ${screenshots.length} screenshots for config: ${configId}`);
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const result = (await callMcpEndpoint('app_store/configs/save_screenshots', {
|
|
108
|
+
config_id: configId,
|
|
109
|
+
screenshots,
|
|
110
|
+
}));
|
|
111
|
+
const text = result.content?.[0]?.text || 'null';
|
|
112
|
+
try {
|
|
113
|
+
return JSON.parse(text);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
logError(`Failed to save screenshots: ${error instanceof Error ? error.message : String(error)}`);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Update submission status via MCP
|
|
126
|
+
*/
|
|
127
|
+
export async function updateAppStoreStatus(configId, updates, verbose) {
|
|
128
|
+
if (verbose) {
|
|
129
|
+
logInfo(`Updating status for config: ${configId}`);
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
const result = (await callMcpEndpoint('app_store/configs/update_status', {
|
|
133
|
+
config_id: configId,
|
|
134
|
+
...updates,
|
|
135
|
+
}));
|
|
136
|
+
const text = result.content?.[0]?.text || 'null';
|
|
137
|
+
try {
|
|
138
|
+
return JSON.parse(text);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
logError(`Failed to update status: ${error instanceof Error ? error.message : String(error)}`);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
package/dist/api/github.js
CHANGED
|
@@ -3,31 +3,30 @@
|
|
|
3
3
|
* Uses product developer configuration from the database
|
|
4
4
|
*/
|
|
5
5
|
import { callMcpEndpoint } from './mcp-client.js';
|
|
6
|
+
import { logDebug, logSuccess, logWarning, logError } from '../utils/logger.js';
|
|
6
7
|
/**
|
|
7
8
|
* Get GitHub developer configuration for a feature
|
|
8
9
|
* Returns installation_id, repository info from product_developers
|
|
9
10
|
*/
|
|
10
11
|
export async function getGitHubDeveloperConfig(featureId, verbose) {
|
|
11
|
-
|
|
12
|
-
console.log(`🔍 Fetching GitHub developer config for feature: ${featureId}`);
|
|
13
|
-
}
|
|
12
|
+
logDebug(`Fetching GitHub developer config for feature: ${featureId}`, verbose);
|
|
14
13
|
try {
|
|
15
14
|
const result = (await callMcpEndpoint('github/developer_config', {
|
|
16
15
|
feature_id: featureId,
|
|
17
16
|
}));
|
|
18
17
|
if (verbose) {
|
|
19
18
|
if (result.configured) {
|
|
20
|
-
|
|
19
|
+
logSuccess(`GitHub configured: ${result.repository_full_name}`);
|
|
21
20
|
}
|
|
22
21
|
else {
|
|
23
|
-
|
|
22
|
+
logWarning(`GitHub not configured: ${result.message}`);
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
25
|
return result;
|
|
27
26
|
}
|
|
28
27
|
catch (error) {
|
|
29
28
|
if (verbose) {
|
|
30
|
-
|
|
29
|
+
logError(`Failed to get GitHub developer config: ${error instanceof Error ? error.message : String(error)}`);
|
|
31
30
|
}
|
|
32
31
|
return {
|
|
33
32
|
configured: false,
|
|
@@ -39,22 +38,20 @@ export async function getGitHubDeveloperConfig(featureId, verbose) {
|
|
|
39
38
|
* Get installation access token for GitHub API operations
|
|
40
39
|
*/
|
|
41
40
|
export async function getGitHubInstallationToken(installationId, featureId, verbose) {
|
|
42
|
-
|
|
43
|
-
console.log(`🔑 Fetching GitHub installation token for: ${installationId}`);
|
|
44
|
-
}
|
|
41
|
+
logDebug(`Fetching GitHub installation token for: ${installationId}`, verbose);
|
|
45
42
|
try {
|
|
46
43
|
const result = (await callMcpEndpoint('github/installation_token', {
|
|
47
44
|
installation_id: installationId,
|
|
48
45
|
feature_id: featureId,
|
|
49
46
|
}));
|
|
50
47
|
if (verbose) {
|
|
51
|
-
|
|
48
|
+
logSuccess(`GitHub token obtained, expires: ${result.expires_at}`);
|
|
52
49
|
}
|
|
53
50
|
return result;
|
|
54
51
|
}
|
|
55
52
|
catch (error) {
|
|
56
53
|
if (verbose) {
|
|
57
|
-
|
|
54
|
+
logError(`Failed to get GitHub installation token: ${error instanceof Error ? error.message : String(error)}`);
|
|
58
55
|
}
|
|
59
56
|
return null;
|
|
60
57
|
}
|
|
@@ -64,19 +61,17 @@ export async function getGitHubInstallationToken(installationId, featureId, verb
|
|
|
64
61
|
* Used for product-level operations like growth analysis.
|
|
65
62
|
*/
|
|
66
63
|
export async function getGitHubConfigByProduct(productId, verbose) {
|
|
67
|
-
|
|
68
|
-
console.log(`🔍 Fetching GitHub config for product: ${productId}`);
|
|
69
|
-
}
|
|
64
|
+
logDebug(`Fetching GitHub config for product: ${productId}`, verbose);
|
|
70
65
|
try {
|
|
71
66
|
const result = (await callMcpEndpoint('github/config_and_token_by_product', {
|
|
72
67
|
product_id: productId,
|
|
73
68
|
}));
|
|
74
69
|
if (verbose) {
|
|
75
70
|
if (result.configured) {
|
|
76
|
-
|
|
71
|
+
logSuccess(`GitHub ready: ${result.repository_full_name}`);
|
|
77
72
|
}
|
|
78
73
|
else {
|
|
79
|
-
|
|
74
|
+
logWarning(`GitHub not configured: ${result.message}`);
|
|
80
75
|
}
|
|
81
76
|
}
|
|
82
77
|
if (result.configured && result.token && result.owner && result.repo) {
|
|
@@ -95,7 +90,7 @@ export async function getGitHubConfigByProduct(productId, verbose) {
|
|
|
95
90
|
}
|
|
96
91
|
catch (error) {
|
|
97
92
|
if (verbose) {
|
|
98
|
-
|
|
93
|
+
logError(`Failed to get GitHub config for product: ${error instanceof Error ? error.message : String(error)}`);
|
|
99
94
|
}
|
|
100
95
|
return {
|
|
101
96
|
configured: false,
|
|
@@ -108,19 +103,17 @@ export async function getGitHubConfigByProduct(productId, verbose) {
|
|
|
108
103
|
* This is the main entry point for getting GitHub config
|
|
109
104
|
*/
|
|
110
105
|
export async function getGitHubConfig(featureId, verbose) {
|
|
111
|
-
|
|
112
|
-
console.log(`🔍 Fetching GitHub config for feature: ${featureId}`);
|
|
113
|
-
}
|
|
106
|
+
logDebug(`Fetching GitHub config for feature: ${featureId}`, verbose);
|
|
114
107
|
try {
|
|
115
108
|
const result = (await callMcpEndpoint('github/config_and_token', {
|
|
116
109
|
feature_id: featureId,
|
|
117
110
|
}));
|
|
118
111
|
if (verbose) {
|
|
119
112
|
if (result.configured) {
|
|
120
|
-
|
|
113
|
+
logSuccess(`GitHub ready: ${result.repository_full_name}`);
|
|
121
114
|
}
|
|
122
115
|
else {
|
|
123
|
-
|
|
116
|
+
logWarning(`GitHub not configured: ${result.message}`);
|
|
124
117
|
}
|
|
125
118
|
}
|
|
126
119
|
if (result.configured && result.token && result.owner && result.repo) {
|
|
@@ -139,7 +132,7 @@ export async function getGitHubConfig(featureId, verbose) {
|
|
|
139
132
|
}
|
|
140
133
|
catch (error) {
|
|
141
134
|
if (verbose) {
|
|
142
|
-
|
|
135
|
+
logError(`Failed to get GitHub config: ${error instanceof Error ? error.message : String(error)}`);
|
|
143
136
|
}
|
|
144
137
|
return {
|
|
145
138
|
configured: false,
|
package/dist/api/mcp-client.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Environment variables take precedence over stored auth.
|
|
8
8
|
*/
|
|
9
9
|
import { getMcpServerUrl, getMcpToken } from '../auth/auth-store.js';
|
|
10
|
+
import { logDebug, logError } from '../utils/logger.js';
|
|
10
11
|
/**
|
|
11
12
|
* Helper function to make HTTP requests to the MCP server
|
|
12
13
|
* Uses stored auth from `edsger login` or environment variables
|
|
@@ -44,7 +45,7 @@ export async function callMcpEndpoint(method, params) {
|
|
|
44
45
|
return data.result;
|
|
45
46
|
}
|
|
46
47
|
catch (error) {
|
|
47
|
-
|
|
48
|
+
logError(`MCP call failed for ${method}: ${error instanceof Error ? error.message : String(error)}`);
|
|
48
49
|
throw error;
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -53,21 +54,15 @@ export async function callMcpEndpoint(method, params) {
|
|
|
53
54
|
*/
|
|
54
55
|
export async function makeMcpRequest(options) {
|
|
55
56
|
const { method, params, verbose } = options;
|
|
56
|
-
|
|
57
|
-
console.log(`Making MCP request: ${method}`);
|
|
58
|
-
}
|
|
57
|
+
logDebug(`Making MCP request: ${method}`, verbose);
|
|
59
58
|
try {
|
|
60
59
|
const result = await callMcpEndpoint(method, params);
|
|
61
|
-
|
|
62
|
-
console.log(`MCP request successful: ${method}`);
|
|
63
|
-
}
|
|
60
|
+
logDebug(`MCP request successful: ${method}`, verbose);
|
|
64
61
|
return result;
|
|
65
62
|
}
|
|
66
63
|
catch (error) {
|
|
67
64
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
68
|
-
|
|
69
|
-
console.error(`MCP request failed: ${method} - ${errorMessage}`);
|
|
70
|
-
}
|
|
65
|
+
logDebug(`MCP request failed: ${method} - ${errorMessage}`, verbose);
|
|
71
66
|
throw error;
|
|
72
67
|
}
|
|
73
68
|
}
|
|
@@ -50,3 +50,16 @@ export declare function getEdsgerBaseUrl(): string;
|
|
|
50
50
|
* Get the auth file path (for display purposes)
|
|
51
51
|
*/
|
|
52
52
|
export declare function getAuthFilePath(): string;
|
|
53
|
+
/**
|
|
54
|
+
* Watch the auth file for external changes (e.g., from Edsger Desktop app).
|
|
55
|
+
* When the file changes, the in-memory cache is invalidated so the CLI
|
|
56
|
+
* picks up new auth credentials automatically.
|
|
57
|
+
*
|
|
58
|
+
* @param onChange - Optional callback invoked when auth config changes
|
|
59
|
+
* @returns A function to stop watching
|
|
60
|
+
*/
|
|
61
|
+
export declare function watchAuthFile(onChange?: (config: AuthConfig | null) => void): () => void;
|
|
62
|
+
/**
|
|
63
|
+
* Stop watching the auth file
|
|
64
|
+
*/
|
|
65
|
+
export declare function stopWatchingAuthFile(): void;
|
package/dist/auth/auth-store.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Stores auth credentials in ~/.edsger/auth.json
|
|
5
5
|
* Provides read/write/clear operations for auth tokens
|
|
6
6
|
*/
|
|
7
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, chmodSync } from 'fs';
|
|
7
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, chmodSync, watch } from 'fs';
|
|
8
8
|
import { join } from 'path';
|
|
9
9
|
import { homedir } from 'os';
|
|
10
10
|
const EDSGER_DIR = join(homedir(), '.edsger');
|
|
@@ -115,3 +115,40 @@ export function getEdsgerBaseUrl() {
|
|
|
115
115
|
export function getAuthFilePath() {
|
|
116
116
|
return AUTH_FILE;
|
|
117
117
|
}
|
|
118
|
+
/** Active file watcher for auth file changes */
|
|
119
|
+
let _authWatcher = null;
|
|
120
|
+
/**
|
|
121
|
+
* Watch the auth file for external changes (e.g., from Edsger Desktop app).
|
|
122
|
+
* When the file changes, the in-memory cache is invalidated so the CLI
|
|
123
|
+
* picks up new auth credentials automatically.
|
|
124
|
+
*
|
|
125
|
+
* @param onChange - Optional callback invoked when auth config changes
|
|
126
|
+
* @returns A function to stop watching
|
|
127
|
+
*/
|
|
128
|
+
export function watchAuthFile(onChange) {
|
|
129
|
+
// Stop any existing watcher
|
|
130
|
+
stopWatchingAuthFile();
|
|
131
|
+
ensureEdsgerDir();
|
|
132
|
+
_authWatcher = watch(EDSGER_DIR, (eventType, filename) => {
|
|
133
|
+
if (filename !== 'auth.json')
|
|
134
|
+
return;
|
|
135
|
+
// Invalidate cache so next loadAuth() reads from disk
|
|
136
|
+
_authCache = undefined;
|
|
137
|
+
const config = loadAuth();
|
|
138
|
+
if (onChange) {
|
|
139
|
+
onChange(config);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
// Don't keep the process alive just for the watcher
|
|
143
|
+
_authWatcher.unref();
|
|
144
|
+
return () => stopWatchingAuthFile();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Stop watching the auth file
|
|
148
|
+
*/
|
|
149
|
+
export function stopWatchingAuthFile() {
|
|
150
|
+
if (_authWatcher) {
|
|
151
|
+
_authWatcher.close();
|
|
152
|
+
_authWatcher = null;
|
|
153
|
+
}
|
|
154
|
+
}
|
package/dist/auth/login.js
CHANGED
|
@@ -8,7 +8,7 @@ import { createInterface } from 'readline';
|
|
|
8
8
|
import { execSync } from 'child_process';
|
|
9
9
|
import { platform } from 'os';
|
|
10
10
|
import { saveAuth, loadAuth, clearAuth, getEdsgerBaseUrl, getAuthFilePath } from './auth-store.js';
|
|
11
|
-
import { logInfo, logSuccess, logError, logWarning } from '../utils/logger.js';
|
|
11
|
+
import { logInfo, logSuccess, logError, logWarning, logRaw } from '../utils/logger.js';
|
|
12
12
|
/**
|
|
13
13
|
* Open a URL in the user's default browser
|
|
14
14
|
*/
|
|
@@ -65,7 +65,7 @@ export async function runLogin() {
|
|
|
65
65
|
const baseUrl = getEdsgerBaseUrl();
|
|
66
66
|
const authUrl = `${baseUrl}/cli/auth`;
|
|
67
67
|
logInfo('Starting Edsger CLI login...');
|
|
68
|
-
|
|
68
|
+
logRaw('');
|
|
69
69
|
// Check if already logged in
|
|
70
70
|
const existingAuth = loadAuth();
|
|
71
71
|
if (existingAuth) {
|
|
@@ -77,19 +77,19 @@ export async function runLogin() {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
// Open browser
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
logInfo(`Opening browser to: ${authUrl}`);
|
|
81
|
+
logRaw('');
|
|
82
82
|
const opened = openBrowser(authUrl);
|
|
83
83
|
if (!opened) {
|
|
84
84
|
logWarning(`Could not open browser automatically.`);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
logInfo('Please open this URL manually:');
|
|
86
|
+
logRaw(` ${authUrl}`);
|
|
87
|
+
logRaw('');
|
|
88
88
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
logInfo('1. Sign in to edsger.ai (if not already signed in)');
|
|
90
|
+
logInfo('2. Click "Generate CLI Token" on the page');
|
|
91
|
+
logInfo('3. Copy the CLI Token and paste it below');
|
|
92
|
+
logRaw('');
|
|
93
93
|
const mcpServerUrl = process.env.EDSGER_MCP_SERVER_URL || MCP_SERVER_URL;
|
|
94
94
|
// Read token
|
|
95
95
|
const mcpToken = await readLine('CLI Token: ');
|
|
@@ -130,19 +130,19 @@ export async function runLogin() {
|
|
|
130
130
|
loggedInAt: new Date().toISOString(),
|
|
131
131
|
edsgerBaseUrl: baseUrl,
|
|
132
132
|
});
|
|
133
|
-
|
|
133
|
+
logRaw('');
|
|
134
134
|
logSuccess('Login successful!');
|
|
135
135
|
logInfo(`Credentials saved to ${getAuthFilePath()}`);
|
|
136
136
|
// Show available products
|
|
137
137
|
const products = data.result?.products || [];
|
|
138
138
|
if (products.length > 0) {
|
|
139
|
-
|
|
139
|
+
logRaw('');
|
|
140
140
|
logInfo(`You have access to ${products.length} product(s):`);
|
|
141
141
|
products.forEach((p, i) => {
|
|
142
|
-
|
|
142
|
+
logRaw(` ${i + 1}. ${p.name} (${p.id})`);
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
|
|
145
|
+
logRaw('');
|
|
146
146
|
logInfo('You can now run `edsger` to start processing features.');
|
|
147
147
|
}
|
|
148
148
|
catch (error) {
|
|
@@ -173,7 +173,7 @@ export async function runStatus() {
|
|
|
173
173
|
return;
|
|
174
174
|
}
|
|
175
175
|
logInfo('Login status:');
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
logRaw(` Server: ${auth.mcpServerUrl}`);
|
|
177
|
+
logRaw(` Logged in at: ${auth.loggedInAt}`);
|
|
178
|
+
logRaw(` Token: ${auth.mcpToken.substring(0, 8)}...${auth.mcpToken.substring(auth.mcpToken.length - 4)}`);
|
|
179
179
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* 6. Responds to web dashboard commands (pause/resume/stop)
|
|
11
11
|
*/
|
|
12
12
|
import { AgentWorkflowProcessor, MAX_CONCURRENCY } from './processor.js';
|
|
13
|
-
import { logInfo, logError, logSuccess, logWarning } from '../../utils/logger.js';
|
|
13
|
+
import { logInfo, logError, logSuccess, logWarning, logRaw } from '../../utils/logger.js';
|
|
14
14
|
import { isLoggedIn } from '../../auth/auth-store.js';
|
|
15
15
|
import { startAutoUpdateChecker, stopAutoUpdateChecker } from '../../updater/auto-updater.js';
|
|
16
16
|
import { startSleepPrevention, stopSleepPrevention } from '../../system/sleep-prevention.js';
|
|
@@ -27,10 +27,10 @@ export async function runAgentWorkflow(options) {
|
|
|
27
27
|
}
|
|
28
28
|
const config = validateConfiguration(options);
|
|
29
29
|
const version = getVersion();
|
|
30
|
-
|
|
30
|
+
logRaw('');
|
|
31
31
|
logInfo(`Edsger Agent v${version}`);
|
|
32
32
|
logInfo('Cross-product workflow mode');
|
|
33
|
-
|
|
33
|
+
logRaw('');
|
|
34
34
|
// Set up workspace directory
|
|
35
35
|
const workspaceRoot = ensureWorkspaceDir();
|
|
36
36
|
logInfo(`Workspace: ${workspaceRoot}`);
|
|
@@ -44,9 +44,9 @@ export async function runAgentWorkflow(options) {
|
|
|
44
44
|
startSleepMonitor();
|
|
45
45
|
// Start heartbeat
|
|
46
46
|
startHeartbeat();
|
|
47
|
-
|
|
47
|
+
logRaw('');
|
|
48
48
|
logSuccess('Agent started. Watching for features...');
|
|
49
|
-
|
|
49
|
+
logRaw('');
|
|
50
50
|
// Create and start the processor
|
|
51
51
|
let maxConcurrent = 3;
|
|
52
52
|
if (options.concurrency && options.concurrency > 0) {
|
|
@@ -71,7 +71,7 @@ export async function runAgentWorkflow(options) {
|
|
|
71
71
|
processor.stop();
|
|
72
72
|
// Show stats
|
|
73
73
|
const stats = processor.getStats();
|
|
74
|
-
|
|
74
|
+
logRaw('');
|
|
75
75
|
logInfo('Session Statistics:');
|
|
76
76
|
logInfo(` Total processed: ${stats.totalProcessed}`);
|
|
77
77
|
logInfo(` Completed: ${stats.completed}`);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { EdsgerConfig } from '../../types/index.js';
|
|
11
11
|
import { type WorkflowStats } from '../workflow/core/state-manager.js';
|
|
12
12
|
/**
|
|
13
|
-
* Maximum allowed concurrency.
|
|
13
|
+
* Maximum allowed concurrency (hard cap).
|
|
14
14
|
* Limits are due to:
|
|
15
15
|
* - MCP API rate limits (per-minute/per-hour per token)
|
|
16
16
|
* - AI API rate limits (Claude/OpenAI RPM/TPM)
|