@descix/cli 1.0.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 +95 -0
- package/SERVICE_README_sdk.md +399 -0
- package/agent-assets/guides/README.md +61 -0
- package/agent-assets/guides/dynamic-site-pattern.md +125 -0
- package/agent-assets/guides/knowledge-only-pattern.md +93 -0
- package/agent-assets/guides/microservice-pattern.md +152 -0
- package/agent-assets/guides/static-site-pattern.md +111 -0
- package/agent-assets/instructions/app-asset-validation.md +477 -0
- package/agent-assets/instructions/onboarding-flow.md +408 -0
- package/agent-assets/instructions/standard-folder-structure.md +125 -0
- package/agent-assets/reference/app-creation.md +381 -0
- package/agent-assets/reference/architecture.md +406 -0
- package/agent-assets/reference/local-dev.md +138 -0
- package/agent-assets/reference/mcp-integration.md +424 -0
- package/agent-assets/reference/workspace-config.md +415 -0
- package/agent-assets/rules/descix_mcp.template.mdc +243 -0
- package/bin/descix.js +3930 -0
- package/bin/mcp-server.js +382 -0
- package/descix-cli-1.0.0.tgz +0 -0
- package/lib/agent-files.js +162 -0
- package/lib/api-client.js +458 -0
- package/lib/auth-guard.js +67 -0
- package/lib/commands/app-wizard.js +627 -0
- package/lib/commands/auth.js +407 -0
- package/lib/commands/buy.js +207 -0
- package/lib/commands/clone.js +91 -0
- package/lib/commands/config.js +155 -0
- package/lib/commands/doctor.js +277 -0
- package/lib/commands/folder.js +291 -0
- package/lib/commands/init.js +257 -0
- package/lib/commands/kb.js +654 -0
- package/lib/commands/mcp.js +273 -0
- package/lib/commands/serve.js +12 -0
- package/lib/commands/status.js +239 -0
- package/lib/commands/update.js +653 -0
- package/lib/core/Chunker.js +610 -0
- package/lib/core/Hydrator.js +801 -0
- package/lib/core/PathContext.js +335 -0
- package/lib/core/Syncer.js +310 -0
- package/lib/core/index.js +32 -0
- package/lib/global-config.js +86 -0
- package/lib/google-storage-adc.js +511 -0
- package/lib/wallet-file.js +232 -0
- package/lib/wizard/setup.js +502 -0
- package/lib/workspace-config.js +712 -0
- package/lib/workspace-utils.js +126 -0
- package/package.json +41 -0
- package/templates/agent-claude.md +226 -0
- package/templates/agent-cline.md +133 -0
- package/templates/agent-copilot.md +133 -0
- package/templates/agent-cursor.md +133 -0
- package/templates/descix_mcp.mdc +122 -0
- package/templates/drive/README.md +42 -0
- package/templates/drive/app/assets/app_description.md +13 -0
- package/templates/drive/app/assets/icon.png +0 -0
- package/templates/drive/app/assets/system_instructions.md +17 -0
- package/templates/drive/app/kb/General/README.md +25 -0
- package/templates/drive/community/Apps/.gitkeep +4 -0
- package/templates/drive/community/community_assets/community_description.md +15 -0
- package/templates/drive/community/community_assets/icon.png +0 -0
- package/templates/drive_templates/README.md +104 -0
- package/templates/drive_templates/agent_app_template/assets/app_description.txt +13 -0
- package/templates/drive_templates/agent_app_template/assets/system_instructions.txt +17 -0
- package/templates/drive_templates/agent_app_template/kb/General/README.md +25 -0
- package/templates/drive_templates/agent_app_template/microservice/.gitkeep +10 -0
- package/templates/drive_templates/agent_app_template/site/.gitkeep +4 -0
- package/templates/drive_templates/community_template/Apps/.gitkeep +4 -0
- package/templates/drive_templates/community_template/community_assets/community_description.txt +15 -0
- package/templates/scaffolds/README.md +62 -0
- package/templates/scaffolds/microservice/Dockerfile +19 -0
- package/templates/scaffolds/microservice/SERVICE_README_sdk.md +399 -0
- package/templates/scaffolds/microservice/app.js +50 -0
- package/templates/scaffolds/microservice/app.yaml +8 -0
- package/templates/scaffolds/microservice/defaults-config.json +5 -0
- package/templates/scaffolds/microservice/dev-overrides.json.example +5 -0
- package/templates/scaffolds/microservice/manifest.json +49 -0
- package/templates/scaffolds/microservice/package-lock.json +2645 -0
- package/templates/scaffolds/microservice/package.json +29 -0
- package/templates/scaffolds/microservice/scripts/register.js +55 -0
- package/templates/scaffolds/microservice/services/apiFront.js +75 -0
- package/templates/scaffolds/microservice/services/commandHandlers/sampleCommands.js +57 -0
- package/templates/scaffolds/microservice/services/mcpClient.js +78 -0
- package/templates/scaffolds/microservice/services/utils.js +247 -0
- package/templates/scaffolds/microservice/setup-schema.json +18 -0
- package/templates/scaffolds/microservice/templates/SERVICE_README_TEMPLATE.md +143 -0
- package/templates/scaffolds/site/DeSciXAppSDK.js +62 -0
- package/templates/scaffolds/site/README.md +51 -0
- package/templates/scaffolds/site/app.js +22 -0
- package/templates/scaffolds/site/index.html +42 -0
- package/templates/scaffolds/site/styles.css +123 -0
- package/test-hydration.js +150 -0
- package/vendor/mcp/transports/http-sse-transport.js +196 -0
- package/vendor/mcp/transports/index.js +15 -0
- package/vendor/mcp/transports/stdio-transport.js +118 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Commands
|
|
3
|
+
*
|
|
4
|
+
* MCP server setup and configuration commands
|
|
5
|
+
* All operations use HTTP API client - no service imports
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import ora from 'ora';
|
|
10
|
+
import { DeSciXApiClient } from '../api-client.js';
|
|
11
|
+
import { requireAuth } from '../auth-guard.js';
|
|
12
|
+
import * as fs from 'fs/promises';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { dirname } from 'path';
|
|
16
|
+
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = dirname(__filename);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Load workspace config from JSON file
|
|
22
|
+
*/
|
|
23
|
+
async function loadWorkspaceConfig(workspaceRoot = process.cwd()) {
|
|
24
|
+
const configPath = path.join(workspaceRoot, '.descix', 'workspace.json');
|
|
25
|
+
try {
|
|
26
|
+
const data = await fs.readFile(configPath, 'utf-8');
|
|
27
|
+
return JSON.parse(data);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
// Return default config if file doesn't exist
|
|
30
|
+
return {
|
|
31
|
+
primaryCommunity: 'descix',
|
|
32
|
+
directoryMappings: {},
|
|
33
|
+
additionalContexts: [],
|
|
34
|
+
defaultContext: {
|
|
35
|
+
communityId: 'descix',
|
|
36
|
+
appId: 'agent',
|
|
37
|
+
kbId: 'General'
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Deploy descix_mcp.mdc rules file to .cursor/rules/
|
|
45
|
+
*/
|
|
46
|
+
async function deployRulesFile(workspaceRoot = process.cwd()) {
|
|
47
|
+
const rulesDir = path.join(workspaceRoot, '.cursor', 'rules');
|
|
48
|
+
await fs.mkdir(rulesDir, { recursive: true });
|
|
49
|
+
|
|
50
|
+
const templatePath = path.join(__dirname, '../../templates/descix_mcp.mdc');
|
|
51
|
+
const rulesPath = path.join(rulesDir, 'descix_mcp.mdc');
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
// Check if template exists
|
|
55
|
+
await fs.access(templatePath);
|
|
56
|
+
|
|
57
|
+
// Copy template to rules directory
|
|
58
|
+
const templateContent = await fs.readFile(templatePath, 'utf-8');
|
|
59
|
+
|
|
60
|
+
// Check if rules file already exists
|
|
61
|
+
let existingContent = '';
|
|
62
|
+
try {
|
|
63
|
+
existingContent = await fs.readFile(rulesPath, 'utf-8');
|
|
64
|
+
} catch {
|
|
65
|
+
// File doesn't exist, that's fine
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Only write if content is different (avoid unnecessary writes)
|
|
69
|
+
if (existingContent !== templateContent) {
|
|
70
|
+
await fs.writeFile(rulesPath, templateContent, 'utf-8');
|
|
71
|
+
return true; // File was deployed
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return false; // File already exists with same content
|
|
75
|
+
} catch (error) {
|
|
76
|
+
// Template might not exist in development, that's okay
|
|
77
|
+
console.error(chalk.yellow(`Warning: Could not deploy rules file: ${error.message}`));
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Initialize MCP server for workspace
|
|
84
|
+
*/
|
|
85
|
+
export async function init() {
|
|
86
|
+
const apiClient = new DeSciXApiClient();
|
|
87
|
+
await requireAuth(apiClient);
|
|
88
|
+
|
|
89
|
+
console.log(chalk.cyan('\n🚀 DeSciX MCP Workspace Setup\n'));
|
|
90
|
+
|
|
91
|
+
const spinner = ora('Initializing...').start();
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
spinner.text = 'Loading communities...';
|
|
95
|
+
|
|
96
|
+
// Query communities via HTTP
|
|
97
|
+
const response = await apiClient.invoke('find_communities', {}, { allowGuest: false });
|
|
98
|
+
const result = response.message || response;
|
|
99
|
+
const communities = result.communities || [];
|
|
100
|
+
spinner.succeed(`Found ${communities.length} communities`);
|
|
101
|
+
|
|
102
|
+
console.log(chalk.cyan('\nAvailable communities:'));
|
|
103
|
+
communities.forEach((c, idx) => {
|
|
104
|
+
console.log(chalk.gray(` ${idx + 1}. ${c.community_name} (${c.community_id})`));
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Use default community for now (can be enhanced with prompts)
|
|
108
|
+
const primaryCommunity = 'descix';
|
|
109
|
+
|
|
110
|
+
// Generate .descix/workspace.json
|
|
111
|
+
const workspaceRoot = process.cwd();
|
|
112
|
+
const config = {
|
|
113
|
+
primaryCommunity,
|
|
114
|
+
directoryMappings: {},
|
|
115
|
+
additionalContexts: [],
|
|
116
|
+
defaultContext: {
|
|
117
|
+
communityId: primaryCommunity,
|
|
118
|
+
appId: 'docs',
|
|
119
|
+
kbId: 'sdk'
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
spinner.start('Creating configuration files...');
|
|
124
|
+
|
|
125
|
+
const descixDir = path.join(workspaceRoot, '.descix');
|
|
126
|
+
await fs.mkdir(descixDir, { recursive: true });
|
|
127
|
+
const configPath = path.join(descixDir, 'workspace.json');
|
|
128
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
129
|
+
console.log(chalk.green('✅ Created .descix/workspace.json'));
|
|
130
|
+
|
|
131
|
+
// Create .cursor/mcp.json
|
|
132
|
+
const cursorDir = path.join(workspaceRoot, '.cursor');
|
|
133
|
+
await fs.mkdir(cursorDir, { recursive: true });
|
|
134
|
+
|
|
135
|
+
const cursorConfig = {
|
|
136
|
+
mcpServers: {
|
|
137
|
+
'descix-rag': {
|
|
138
|
+
command: 'node',
|
|
139
|
+
args: ['node_modules/@descix/cli/bin/mcp-server.js'],
|
|
140
|
+
cwd: '${workspaceFolder}'
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const cursorConfigPath = path.join(cursorDir, 'mcp.json');
|
|
146
|
+
await fs.writeFile(cursorConfigPath, JSON.stringify(cursorConfig, null, 2));
|
|
147
|
+
console.log(chalk.green('✅ Created .cursor/mcp.json'));
|
|
148
|
+
|
|
149
|
+
// Deploy rules file
|
|
150
|
+
spinner.text = 'Deploying agent rules file...';
|
|
151
|
+
const rulesDeployed = await deployRulesFile(workspaceRoot);
|
|
152
|
+
if (rulesDeployed) {
|
|
153
|
+
console.log(chalk.green('✅ Deployed .cursor/rules/descix_mcp.mdc'));
|
|
154
|
+
} else {
|
|
155
|
+
console.log(chalk.gray(' Rules file already exists'));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
spinner.succeed('Configuration complete!');
|
|
159
|
+
|
|
160
|
+
console.log(chalk.cyan('\n📋 Next Steps:\n'));
|
|
161
|
+
console.log(chalk.white('1. Restart Cursor (Cmd/Ctrl + Shift + P → "Reload Window")\n'));
|
|
162
|
+
console.log(chalk.white('2. MCP will automatically use your credentials!\n'));
|
|
163
|
+
console.log(chalk.gray('Test with: descix mcp test\n'));
|
|
164
|
+
|
|
165
|
+
} catch (error) {
|
|
166
|
+
spinner.fail('Setup failed');
|
|
167
|
+
console.error(chalk.red(error.message));
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Test MCP server via HTTP
|
|
174
|
+
*/
|
|
175
|
+
export async function test(options = {}) {
|
|
176
|
+
const apiClient = new DeSciXApiClient();
|
|
177
|
+
await requireAuth(apiClient);
|
|
178
|
+
|
|
179
|
+
const spinner = ora('Testing MCP server...').start();
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
const config = await loadWorkspaceConfig(process.cwd());
|
|
183
|
+
|
|
184
|
+
spinner.text = `Querying ${config.defaultContext.communityId}/${config.defaultContext.appId}/${config.defaultContext.kbId}...`;
|
|
185
|
+
|
|
186
|
+
// Get RAG status via HTTP
|
|
187
|
+
const statusResponse = await apiClient.invoke('get_kb_rag_status', {
|
|
188
|
+
app_id: config.defaultContext.appId,
|
|
189
|
+
kb_id: config.defaultContext.kbId
|
|
190
|
+
}, { allowGuest: false });
|
|
191
|
+
|
|
192
|
+
const status = statusResponse.message || statusResponse;
|
|
193
|
+
|
|
194
|
+
if (!status.enabled) {
|
|
195
|
+
spinner.warn(chalk.yellow('RAG not enabled for this knowledge base'));
|
|
196
|
+
console.log(chalk.gray('Enable RAG with: descix rag sync -c ' + config.defaultContext.communityId + ' -a ' + config.defaultContext.appId + ' -k ' + config.defaultContext.kbId));
|
|
197
|
+
throw new Error('RAG not enabled');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const query = options.query || 'What is this knowledge base about?';
|
|
201
|
+
const queryResponse = await apiClient.invoke('query_knowledge_base', {
|
|
202
|
+
app_id: config.defaultContext.appId,
|
|
203
|
+
kb_id: config.defaultContext.kbId,
|
|
204
|
+
query: query,
|
|
205
|
+
limit: 3
|
|
206
|
+
}, { allowGuest: false });
|
|
207
|
+
|
|
208
|
+
const result = queryResponse.message?.results || queryResponse.results || [];
|
|
209
|
+
|
|
210
|
+
spinner.succeed(chalk.green('MCP server working!'));
|
|
211
|
+
console.log(chalk.cyan(`\nQuery: "${query}"\n`));
|
|
212
|
+
console.log(chalk.white(`Found ${result.length} results\n`));
|
|
213
|
+
|
|
214
|
+
result.forEach((r, idx) => {
|
|
215
|
+
console.log(chalk.yellow(`${idx + 1}. ${r.fileName || r.file_path} (${((r.similarity || 0) * 100).toFixed(1)}% match)`));
|
|
216
|
+
console.log(chalk.gray(` ${(r.content || '').substring(0, 100)}...`));
|
|
217
|
+
console.log();
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
} catch (error) {
|
|
221
|
+
spinner.fail('Test failed');
|
|
222
|
+
console.error(chalk.red(error.message));
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Show MCP configuration
|
|
229
|
+
*/
|
|
230
|
+
export async function config() {
|
|
231
|
+
try {
|
|
232
|
+
const config = await loadWorkspaceConfig(process.cwd());
|
|
233
|
+
console.log(chalk.cyan('\nWorkspace Configuration:\n'));
|
|
234
|
+
console.log(JSON.stringify({
|
|
235
|
+
primaryCommunity: config.primaryCommunity,
|
|
236
|
+
directoryMappings: config.directoryMappings,
|
|
237
|
+
additionalContexts: config.additionalContexts,
|
|
238
|
+
defaultContext: config.defaultContext
|
|
239
|
+
}, null, 2));
|
|
240
|
+
console.log();
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.error(chalk.red('Error loading config:', error.message));
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Quickstart - one-command setup
|
|
249
|
+
*/
|
|
250
|
+
export async function quickstart(options = {}) {
|
|
251
|
+
const apiClient = new DeSciXApiClient();
|
|
252
|
+
|
|
253
|
+
console.log(chalk.cyan('\n🚀 DeSciX MCP Quick Start\n'));
|
|
254
|
+
|
|
255
|
+
// Check if authenticated
|
|
256
|
+
try {
|
|
257
|
+
await requireAuth(apiClient);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
console.log(chalk.yellow('⚠️ Authentication required first.\n'));
|
|
260
|
+
console.log(chalk.white('Run: descix login\n'));
|
|
261
|
+
throw new Error('Authentication required');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Run setup wizard
|
|
265
|
+
const { runSetupWizard } = await import('../wizard/setup.js');
|
|
266
|
+
await runSetupWizard();
|
|
267
|
+
|
|
268
|
+
// Deploy rules file after wizard completes
|
|
269
|
+
const workspaceRoot = process.cwd();
|
|
270
|
+
await deployRulesFile(workspaceRoot);
|
|
271
|
+
console.log(chalk.green('✅ Deployed .cursor/rules/descix_mcp.mdc'));
|
|
272
|
+
}
|
|
273
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* descix serve — thin CLI wrapper around @descix/app-sdk gateway.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { runGateway } from '@descix/app-sdk/dev';
|
|
6
|
+
|
|
7
|
+
export async function runServe(options = {}) {
|
|
8
|
+
await runGateway({
|
|
9
|
+
port: options.port || 5173,
|
|
10
|
+
workspaceRoot: options.workspaceRoot || process.cwd(),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Command
|
|
3
|
+
*
|
|
4
|
+
* Displays comprehensive status of the developer environment:
|
|
5
|
+
* - System info (CLI version, Node version, etc.)
|
|
6
|
+
* - Authentication status
|
|
7
|
+
* - Workspace context and mode
|
|
8
|
+
* - Configuration state
|
|
9
|
+
*
|
|
10
|
+
* Uses PathContext for workspace resolution - no scattered process.cwd() calls
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import chalk from 'chalk';
|
|
14
|
+
import os from 'os';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
import fs from 'fs/promises';
|
|
17
|
+
import { exec } from 'child_process';
|
|
18
|
+
import { promisify } from 'util';
|
|
19
|
+
import { DeSciXApiClient } from '../api-client.js';
|
|
20
|
+
import { GlobalConfig } from '../global-config.js';
|
|
21
|
+
import { PathContext } from '../core/PathContext.js';
|
|
22
|
+
import { detectWorkspaceMode } from '../workspace-utils.js';
|
|
23
|
+
import { isAuthenticated } from '../auth-guard.js';
|
|
24
|
+
|
|
25
|
+
const execAsync = promisify(exec);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get CLI version from package.json
|
|
29
|
+
*/
|
|
30
|
+
async function getCliVersion() {
|
|
31
|
+
try {
|
|
32
|
+
// Navigate up from lib/commands/status.js to package.json
|
|
33
|
+
const packageJsonPath = path.resolve(
|
|
34
|
+
path.dirname(new URL(import.meta.url).pathname),
|
|
35
|
+
'../../package.json'
|
|
36
|
+
);
|
|
37
|
+
const data = await fs.readFile(packageJsonPath, 'utf-8');
|
|
38
|
+
const pkg = JSON.parse(data);
|
|
39
|
+
return pkg.version;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return 'unknown';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if gcloud is installed
|
|
47
|
+
*/
|
|
48
|
+
async function checkGcloud() {
|
|
49
|
+
try {
|
|
50
|
+
const { stdout } = await execAsync('gcloud --version');
|
|
51
|
+
const version = stdout.split('\n')[0].trim();
|
|
52
|
+
return { installed: true, version };
|
|
53
|
+
} catch (error) {
|
|
54
|
+
return { installed: false };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Check ADC credentials
|
|
60
|
+
*/
|
|
61
|
+
async function checkAdc() {
|
|
62
|
+
// Simple check: see if GOOGLE_APPLICATION_CREDENTIALS is set
|
|
63
|
+
// or if default credentials file exists
|
|
64
|
+
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
65
|
+
return { configured: true, source: 'env_var' };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const defaultPath = path.join(os.homedir(), '.config', 'gcloud', 'application_default_credentials.json');
|
|
69
|
+
try {
|
|
70
|
+
await fs.access(defaultPath);
|
|
71
|
+
return { configured: true, source: 'default_file' };
|
|
72
|
+
} catch {
|
|
73
|
+
return { configured: false };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Run the status command
|
|
79
|
+
*/
|
|
80
|
+
export async function runStatus(options = {}) {
|
|
81
|
+
console.log(chalk.cyan('\nDeSciX CLI Status'));
|
|
82
|
+
console.log(chalk.cyan('=================\n'));
|
|
83
|
+
|
|
84
|
+
// 1. System Info
|
|
85
|
+
console.log(chalk.white('System'));
|
|
86
|
+
console.log(chalk.white('------'));
|
|
87
|
+
|
|
88
|
+
const cliVersion = await getCliVersion();
|
|
89
|
+
console.log(`CLI Version: ${chalk.green(cliVersion)}`);
|
|
90
|
+
console.log(`Node Version: ${chalk.green(process.version)}`);
|
|
91
|
+
console.log(`OS: ${os.type()} ${os.release()}`);
|
|
92
|
+
|
|
93
|
+
const globalConfig = await GlobalConfig.load();
|
|
94
|
+
console.log(`Environment: ${globalConfig.environment} (${globalConfig.api_url})`);
|
|
95
|
+
console.log();
|
|
96
|
+
|
|
97
|
+
// Try to load workspace context — WorkspaceConfig first (handles v2), fallback to PathContext
|
|
98
|
+
let ctx = null;
|
|
99
|
+
let workspaceRoot = null;
|
|
100
|
+
let workspaceConfig = null;
|
|
101
|
+
try {
|
|
102
|
+
const { WorkspaceConfig } = await import('../workspace-config.js');
|
|
103
|
+
const wsConfig = await WorkspaceConfig.load();
|
|
104
|
+
workspaceRoot = wsConfig.getWorkspaceRoot();
|
|
105
|
+
workspaceConfig = wsConfig;
|
|
106
|
+
} catch {
|
|
107
|
+
// Fallback to PathContext
|
|
108
|
+
ctx = await PathContext.tryLoad();
|
|
109
|
+
workspaceRoot = ctx?.getWorkspaceRoot();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 2. Authentication
|
|
113
|
+
console.log(chalk.white('Authentication'));
|
|
114
|
+
console.log(chalk.white('--------------'));
|
|
115
|
+
|
|
116
|
+
const apiClient = new DeSciXApiClient({ baseUrl: globalConfig.api_url });
|
|
117
|
+
const isAuth = await isAuthenticated(apiClient);
|
|
118
|
+
|
|
119
|
+
if (isAuth) {
|
|
120
|
+
console.log(`Status: ${chalk.green('Authenticated')}`);
|
|
121
|
+
|
|
122
|
+
// Try to get wallet address from stored credentials if available
|
|
123
|
+
if (workspaceRoot) {
|
|
124
|
+
try {
|
|
125
|
+
const { WalletFileManager } = await import('../wallet-file.js');
|
|
126
|
+
const walletData = await WalletFileManager.loadFromWorkspace(workspaceRoot);
|
|
127
|
+
if (walletData && walletData.walletAddress) {
|
|
128
|
+
console.log(`Wallet: ${chalk.green(walletData.walletAddress)}`);
|
|
129
|
+
}
|
|
130
|
+
} catch (e) {
|
|
131
|
+
// Ignore wallet load error
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
console.log(`Status: ${chalk.yellow('Not Authenticated')}`);
|
|
136
|
+
console.log(`Action: Run 'descix login' to authenticate`);
|
|
137
|
+
}
|
|
138
|
+
console.log();
|
|
139
|
+
|
|
140
|
+
// 3. Workspace Context
|
|
141
|
+
console.log(chalk.white('Workspace Context'));
|
|
142
|
+
console.log(chalk.white('-----------------'));
|
|
143
|
+
|
|
144
|
+
if (workspaceConfig || ctx) {
|
|
145
|
+
console.log(`Config File: ${path.join(workspaceRoot, '.descix', 'workspace.json')}`);
|
|
146
|
+
|
|
147
|
+
if (workspaceConfig) {
|
|
148
|
+
// V2 path — use WorkspaceConfig which handles env.platform/products format
|
|
149
|
+
try {
|
|
150
|
+
const defaultCtx = workspaceConfig.defaultContext;
|
|
151
|
+
if (defaultCtx) {
|
|
152
|
+
console.log(`Community: ${defaultCtx.communityId || 'unknown'}`);
|
|
153
|
+
console.log(`App: ${defaultCtx.appId || 'unknown'}`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// List all configured apps
|
|
157
|
+
const platform = workspaceConfig.env?.platform;
|
|
158
|
+
const products = workspaceConfig.env?.products || [];
|
|
159
|
+
const allApps = [platform?.appId, ...products.map(p => p.appId)].filter(Boolean);
|
|
160
|
+
if (allApps.length > 0) {
|
|
161
|
+
console.log(`Local Apps: ${allApps.join(', ')}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log(`API: ${workspaceConfig.apiUrl || 'unknown'}`);
|
|
165
|
+
console.log(`Local Root: ${workspaceRoot}`);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.log(`Mode: ${chalk.red('Unknown/Invalid')} (${error.message})`);
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
// Legacy PathContext path
|
|
171
|
+
const wsRawConfig = ctx.getWorkspaceConfig();
|
|
172
|
+
try {
|
|
173
|
+
const mode = detectWorkspaceMode(wsRawConfig);
|
|
174
|
+
console.log(`Mode: ${chalk.green(mode)}`);
|
|
175
|
+
|
|
176
|
+
if (wsRawConfig.communities) {
|
|
177
|
+
for (const [commId, comm] of Object.entries(wsRawConfig.communities)) {
|
|
178
|
+
const appCount = Object.keys(comm.apps || {}).length;
|
|
179
|
+
console.log(chalk.gray(` └─ ${commId}: ${appCount} app(s)`));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
console.log(`Local Root: ${workspaceRoot}`);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.log(`Mode: ${chalk.red('Unknown/Invalid')} (${error.message})`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
console.log(`Status: ${chalk.yellow('No workspace found')}`);
|
|
189
|
+
console.log(`Action: Run 'descix init -c <community> -a <app> -p .' to create a workspace`);
|
|
190
|
+
}
|
|
191
|
+
console.log();
|
|
192
|
+
|
|
193
|
+
// 4. Configuration & Tools
|
|
194
|
+
console.log(chalk.white('Configuration'));
|
|
195
|
+
console.log(chalk.white('-------------'));
|
|
196
|
+
|
|
197
|
+
if (globalConfig.hasBaseFolder()) {
|
|
198
|
+
console.log(`Base Drive Folder: ${chalk.green('Registered')} (ID: ${globalConfig.user_base_folder_id})`);
|
|
199
|
+
} else {
|
|
200
|
+
console.log(`Base Drive Folder: ${chalk.yellow('Not Registered')}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Check for service key (dev-overrides.json) - use workspace root if available
|
|
204
|
+
const checkDir = workspaceRoot || process.cwd();
|
|
205
|
+
const overridesPath = path.join(checkDir, 'dev-overrides.json');
|
|
206
|
+
try {
|
|
207
|
+
await fs.access(overridesPath);
|
|
208
|
+
console.log(`Service Key: ${chalk.green('Present')} (dev-overrides.json)`);
|
|
209
|
+
} catch {
|
|
210
|
+
console.log(`Service Key: ${chalk.gray('None')} (dev-overrides.json)`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Check for MCP rules
|
|
214
|
+
const rulesPath = path.join(checkDir, '.cursor', 'rules', 'descix_mcp.mdc');
|
|
215
|
+
try {
|
|
216
|
+
await fs.access(rulesPath);
|
|
217
|
+
console.log(`MCP Rules: ${chalk.green('Deployed')} (.cursor/rules/descix_mcp.mdc)`);
|
|
218
|
+
} catch {
|
|
219
|
+
console.log(`MCP Rules: ${chalk.gray('Not Deployed')}`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Check gcloud
|
|
223
|
+
const gcloudStatus = await checkGcloud();
|
|
224
|
+
if (gcloudStatus.installed) {
|
|
225
|
+
console.log(`gcloud SDK: ${chalk.green('Installed')} (${gcloudStatus.version})`);
|
|
226
|
+
} else {
|
|
227
|
+
console.log(`gcloud SDK: ${chalk.yellow('Not Installed')}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Check ADC
|
|
231
|
+
const adcStatus = await checkAdc();
|
|
232
|
+
if (adcStatus.configured) {
|
|
233
|
+
console.log(`ADC Credentials: ${chalk.green('Configured')} (${adcStatus.source})`);
|
|
234
|
+
} else {
|
|
235
|
+
console.log(`ADC Credentials: ${chalk.yellow('Not Configured')}`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
console.log();
|
|
239
|
+
}
|