@nemus-cli/nemus 0.2.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/CHANGELOG.md +86 -0
- package/LICENSE +21 -0
- package/README.md +275 -0
- package/assets/README.md +53 -0
- package/assets/banner.png +0 -0
- package/assets/banner.svg +66 -0
- package/assets/favicon-32.png +0 -0
- package/assets/favicon-64.png +0 -0
- package/assets/icon-256.png +0 -0
- package/assets/icon.svg +23 -0
- package/assets/logo-256.png +0 -0
- package/assets/logo-512.png +0 -0
- package/assets/logo-wordmark.svg +35 -0
- package/assets/logo.svg +32 -0
- package/bin/workspace.js +130 -0
- package/dist/cli/ai-prompt.js +421 -0
- package/dist/cli/dashboard/AgentList.js +61 -0
- package/dist/cli/dashboard/DashboardSidebar.js +280 -0
- package/dist/cli/dashboard/HelpFooter.js +73 -0
- package/dist/cli/dashboard/StatusBadge.js +50 -0
- package/dist/cli/dashboard/index.js +11 -0
- package/dist/cli/dashboard/types.js +2 -0
- package/dist/cli/tui.js +48 -0
- package/dist/commands/ai-prompt.js +22 -0
- package/dist/commands/analyze-deps.js +138 -0
- package/dist/commands/archive.js +113 -0
- package/dist/commands/branch/create.js +119 -0
- package/dist/commands/branch/index.js +104 -0
- package/dist/commands/branch/merge.js +90 -0
- package/dist/commands/branch/rebase.js +84 -0
- package/dist/commands/branch/switch.js +165 -0
- package/dist/commands/cache/index.js +80 -0
- package/dist/commands/cache/manager.js +198 -0
- package/dist/commands/cleanup.js +153 -0
- package/dist/commands/configure-claude.js +55 -0
- package/dist/commands/configure.js +231 -0
- package/dist/commands/create.js +204 -0
- package/dist/commands/dashboard/hook-handler.js +162 -0
- package/dist/commands/dashboard/index.js +258 -0
- package/dist/commands/dashboard/launcher.js +40 -0
- package/dist/commands/dashboard/session-picker.js +106 -0
- package/dist/commands/dashboard/sidebar.js +39 -0
- package/dist/commands/dashboard/workspace-picker.js +95 -0
- package/dist/commands/delete.js +194 -0
- package/dist/commands/deprecated-aliases.js +44 -0
- package/dist/commands/diff.js +129 -0
- package/dist/commands/doctor.js +141 -0
- package/dist/commands/generate-docs.js +77 -0
- package/dist/commands/ghq-status.js +72 -0
- package/dist/commands/go.js +154 -0
- package/dist/commands/history.js +124 -0
- package/dist/commands/list.js +191 -0
- package/dist/commands/mcp/index.js +69 -0
- package/dist/commands/migrate.js +296 -0
- package/dist/commands/remove-repo.js +217 -0
- package/dist/commands/report-bug.js +112 -0
- package/dist/commands/run.js +147 -0
- package/dist/commands/save-context.js +171 -0
- package/dist/commands/sessions.js +129 -0
- package/dist/commands/status.js +138 -0
- package/dist/commands/suite/create.js +212 -0
- package/dist/commands/suite/delete.js +64 -0
- package/dist/commands/suite/export.js +126 -0
- package/dist/commands/suite/import.js +128 -0
- package/dist/commands/suite/index.js +94 -0
- package/dist/commands/suite/list.js +49 -0
- package/dist/commands/suite/use.js +227 -0
- package/dist/commands/sync.js +117 -0
- package/dist/commands/update.js +203 -0
- package/dist/mcp/install.js +550 -0
- package/dist/mcp/server.js +398 -0
- package/dist/mcp/tools.js +922 -0
- package/dist/pi-extensions/permission-sync.ts.template +41 -0
- package/dist/pi-extensions/permissions-gate.ts.template +69 -0
- package/dist/pi-extensions/pr-fix-trigger.ts.template +124 -0
- package/dist/pi-extensions/review-reminder.ts.template +58 -0
- package/dist/pi-extensions/workspace-input-status.ts.template +919 -0
- package/dist/program.js +136 -0
- package/dist/scripts/workspace-table.py +394 -0
- package/dist/types/dashboard.js +11 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/agent-config.js +263 -0
- package/dist/utils/agent-state.js +178 -0
- package/dist/utils/banner.js +24 -0
- package/dist/utils/branch-operations.js +232 -0
- package/dist/utils/bug-report.js +355 -0
- package/dist/utils/cache.js +168 -0
- package/dist/utils/claude-integration.js +617 -0
- package/dist/utils/claude-sessions.js +260 -0
- package/dist/utils/cleanup-operations.js +120 -0
- package/dist/utils/colors.js +26 -0
- package/dist/utils/command-helpers.js +44 -0
- package/dist/utils/config.js +150 -0
- package/dist/utils/context-file.js +33 -0
- package/dist/utils/dashboard-hooks.js +172 -0
- package/dist/utils/dependency-analyzer.js +234 -0
- package/dist/utils/diff-operations.js +80 -0
- package/dist/utils/doc-generator.js +184 -0
- package/dist/utils/ghq-integration.js +332 -0
- package/dist/utils/git-operations.js +237 -0
- package/dist/utils/git-status.js +187 -0
- package/dist/utils/github.js +68 -0
- package/dist/utils/health-checks.js +345 -0
- package/dist/utils/history.js +150 -0
- package/dist/utils/hooks.js +100 -0
- package/dist/utils/logger.js +40 -0
- package/dist/utils/permission-sync.js +681 -0
- package/dist/utils/pi-extensions.js +224 -0
- package/dist/utils/progress.js +92 -0
- package/dist/utils/prompts.js +279 -0
- package/dist/utils/repo-resolver.js +260 -0
- package/dist/utils/retry.js +65 -0
- package/dist/utils/run-operations.js +30 -0
- package/dist/utils/suite.js +159 -0
- package/dist/utils/sync-operations.js +107 -0
- package/dist/utils/tmux-dashboard.js +184 -0
- package/dist/utils/validation.js +153 -0
- package/dist/utils/version-check.js +121 -0
- package/dist/utils/workspace-meta.js +185 -0
- package/install-shell-integration.sh +532 -0
- package/install.sh +401 -0
- package/package.json +90 -0
- package/remove-shell-block.awk +44 -0
- package/scripts/postinstall.js +85 -0
- package/skills/analyze-deps.md +23 -0
- package/skills/archive-workspace.md +26 -0
- package/skills/branch-create.md +18 -0
- package/skills/create-workspace.md +39 -0
- package/skills/delete-workspace.md +37 -0
- package/skills/list-org-repos.md +26 -0
- package/skills/list-suites.md +24 -0
- package/skills/list-workspaces.md +27 -0
- package/skills/refresh-workspace-docs.md +89 -0
- package/skills/remove-repo.md +25 -0
- package/skills/run-command.md +23 -0
- package/skills/save-context.md +68 -0
- package/skills/search-repos.md +31 -0
- package/skills/snapshot-list.md +18 -0
- package/skills/snapshot-save.md +12 -0
- package/skills/switch-branch.md +18 -0
- package/skills/update-cache.md +21 -0
- package/skills/update-workspace.md +66 -0
- package/skills/workspace-cleanup.md +18 -0
- package/skills/workspace-diff.md +23 -0
- package/skills/workspace-doctor.md +23 -0
- package/skills/workspace-info.md +45 -0
- package/skills/workspace-manager/SKILL.md +201 -0
- package/skills/workspace-manager/references/ai-prompt.md +44 -0
- package/skills/workspace-manager/references/analyze-deps.md +45 -0
- package/skills/workspace-manager/references/archive-workspace.md +38 -0
- package/skills/workspace-manager/references/branch-create.md +31 -0
- package/skills/workspace-manager/references/branch-merge.md +22 -0
- package/skills/workspace-manager/references/branch-rebase.md +22 -0
- package/skills/workspace-manager/references/cache-clear.md +18 -0
- package/skills/workspace-manager/references/cache-info.md +22 -0
- package/skills/workspace-manager/references/configure-claude.md +31 -0
- package/skills/workspace-manager/references/configure.md +35 -0
- package/skills/workspace-manager/references/create-workspace.md +45 -0
- package/skills/workspace-manager/references/dashboard.md +61 -0
- package/skills/workspace-manager/references/delete-workspace.md +33 -0
- package/skills/workspace-manager/references/generate-docs.md +36 -0
- package/skills/workspace-manager/references/ghq-status.md +28 -0
- package/skills/workspace-manager/references/go.md +33 -0
- package/skills/workspace-manager/references/history.md +41 -0
- package/skills/workspace-manager/references/list-org-repos.md +26 -0
- package/skills/workspace-manager/references/list-suites.md +21 -0
- package/skills/workspace-manager/references/list-workspaces.md +27 -0
- package/skills/workspace-manager/references/mcp.md +49 -0
- package/skills/workspace-manager/references/remove-repo.md +26 -0
- package/skills/workspace-manager/references/run-command.md +44 -0
- package/skills/workspace-manager/references/search-repos.md +24 -0
- package/skills/workspace-manager/references/sessions.md +27 -0
- package/skills/workspace-manager/references/suite-create.md +22 -0
- package/skills/workspace-manager/references/suite-delete.md +21 -0
- package/skills/workspace-manager/references/suite-export.md +19 -0
- package/skills/workspace-manager/references/suite-import.md +19 -0
- package/skills/workspace-manager/references/suite-use.md +27 -0
- package/skills/workspace-manager/references/switch-branch.md +25 -0
- package/skills/workspace-manager/references/update-cache.md +22 -0
- package/skills/workspace-manager/references/update-workspace.md +50 -0
- package/skills/workspace-manager/references/workspace-cleanup.md +33 -0
- package/skills/workspace-manager/references/workspace-diff.md +27 -0
- package/skills/workspace-manager/references/workspace-doctor.md +27 -0
- package/skills/workspace-manager/references/workspace-info.md +33 -0
- package/skills/workspace-manager/references/workspace-status.md +43 -0
- package/skills/workspace-manager/references/workspace-sync.md +26 -0
- package/skills/workspace-status.md +26 -0
- package/skills/workspace-sync.md +23 -0
- package/src/cli/ai-prompt.test.ts +667 -0
- package/src/cli/ai-prompt.ts +421 -0
- package/src/cli/dashboard/AgentList.tsx +44 -0
- package/src/cli/dashboard/DashboardSidebar.tsx +291 -0
- package/src/cli/dashboard/HelpFooter.tsx +22 -0
- package/src/cli/dashboard/StatusBadge.tsx +23 -0
- package/src/cli/dashboard/index.ts +5 -0
- package/src/cli/dashboard/types.ts +16 -0
- package/src/cli/tui.tsx +51 -0
- package/src/cli/workspace-cli.test.ts +30 -0
- package/src/commands/ai-prompt.ts +21 -0
- package/src/commands/analyze-deps.ts +119 -0
- package/src/commands/archive.ts +114 -0
- package/src/commands/branch/create.ts +94 -0
- package/src/commands/branch/index.ts +74 -0
- package/src/commands/branch/merge.ts +61 -0
- package/src/commands/branch/rebase.ts +54 -0
- package/src/commands/branch/switch.ts +150 -0
- package/src/commands/cache/index.ts +51 -0
- package/src/commands/cache/manager.ts +168 -0
- package/src/commands/cleanup.ts +132 -0
- package/src/commands/configure-claude.ts +55 -0
- package/src/commands/configure.ts +204 -0
- package/src/commands/create.ts +196 -0
- package/src/commands/dashboard/hook-handler.ts +138 -0
- package/src/commands/dashboard/index.ts +248 -0
- package/src/commands/dashboard/launcher.ts +42 -0
- package/src/commands/dashboard/session-picker.ts +73 -0
- package/src/commands/dashboard/sidebar.js +39 -0
- package/src/commands/dashboard/workspace-picker.ts +62 -0
- package/src/commands/delete.test.ts +250 -0
- package/src/commands/delete.ts +171 -0
- package/src/commands/deprecated-aliases.ts +55 -0
- package/src/commands/diff.ts +106 -0
- package/src/commands/doctor.ts +110 -0
- package/src/commands/generate-docs.ts +45 -0
- package/src/commands/ghq-status.ts +70 -0
- package/src/commands/go.ts +125 -0
- package/src/commands/history.ts +136 -0
- package/src/commands/list.test.ts +219 -0
- package/src/commands/list.ts +176 -0
- package/src/commands/mcp/index.ts +39 -0
- package/src/commands/migrate.ts +277 -0
- package/src/commands/remove-repo.ts +194 -0
- package/src/commands/report-bug.ts +88 -0
- package/src/commands/run.ts +125 -0
- package/src/commands/save-context.test.ts +113 -0
- package/src/commands/save-context.ts +141 -0
- package/src/commands/sessions.ts +99 -0
- package/src/commands/status.ts +111 -0
- package/src/commands/suite/create.ts +240 -0
- package/src/commands/suite/delete.ts +65 -0
- package/src/commands/suite/export.ts +97 -0
- package/src/commands/suite/import.ts +100 -0
- package/src/commands/suite/index.ts +66 -0
- package/src/commands/suite/list.ts +54 -0
- package/src/commands/suite/use.ts +232 -0
- package/src/commands/sync.ts +97 -0
- package/src/commands/update.ts +197 -0
- package/src/mcp/install.ts +529 -0
- package/src/mcp/server.ts +579 -0
- package/src/mcp/tools.test.ts +545 -0
- package/src/mcp/tools.ts +1019 -0
- package/src/mcp/update-workspace.test.ts +220 -0
- package/src/pi-extensions/permission-sync.ts.template +41 -0
- package/src/pi-extensions/permissions-gate.ts.template +69 -0
- package/src/pi-extensions/pr-fix-trigger.ts.template +124 -0
- package/src/pi-extensions/review-reminder.ts.template +58 -0
- package/src/pi-extensions/workspace-input-status.ts.template +919 -0
- package/src/program.ts +112 -0
- package/src/scripts/workspace-table.py +394 -0
- package/src/types/dashboard.ts +29 -0
- package/src/types/index.ts +109 -0
- package/src/types/ink.d.ts +171 -0
- package/src/utils/agent-config.test.ts +303 -0
- package/src/utils/agent-config.ts +264 -0
- package/src/utils/agent-state.test.ts +166 -0
- package/src/utils/agent-state.ts +135 -0
- package/src/utils/banner.ts +24 -0
- package/src/utils/branch-operations.ts +237 -0
- package/src/utils/bug-report.test.ts +174 -0
- package/src/utils/bug-report.ts +355 -0
- package/src/utils/cache.ts +150 -0
- package/src/utils/claude-integration.test.ts +381 -0
- package/src/utils/claude-integration.ts +649 -0
- package/src/utils/claude-sessions.test.ts +262 -0
- package/src/utils/claude-sessions.ts +251 -0
- package/src/utils/cleanup-operations.ts +94 -0
- package/src/utils/colors.ts +25 -0
- package/src/utils/command-helpers.ts +46 -0
- package/src/utils/config.test.ts +203 -0
- package/src/utils/config.ts +133 -0
- package/src/utils/context-file.ts +36 -0
- package/src/utils/dashboard-hooks.test.ts +168 -0
- package/src/utils/dashboard-hooks.ts +163 -0
- package/src/utils/dependency-analyzer.ts +243 -0
- package/src/utils/diff-operations.ts +59 -0
- package/src/utils/doc-generator.ts +187 -0
- package/src/utils/ghq-integration.test.ts +195 -0
- package/src/utils/ghq-integration.ts +317 -0
- package/src/utils/git-operations.test.ts +265 -0
- package/src/utils/git-operations.ts +233 -0
- package/src/utils/git-status.ts +171 -0
- package/src/utils/github.ts +74 -0
- package/src/utils/health-checks.ts +359 -0
- package/src/utils/history.ts +140 -0
- package/src/utils/hooks.ts +92 -0
- package/src/utils/logger.ts +37 -0
- package/src/utils/permission-sync.test.ts +593 -0
- package/src/utils/permission-sync.ts +720 -0
- package/src/utils/pi-extensions.test.ts +182 -0
- package/src/utils/pi-extensions.ts +226 -0
- package/src/utils/progress.ts +73 -0
- package/src/utils/prompts.test.ts +169 -0
- package/src/utils/prompts.ts +296 -0
- package/src/utils/repo-resolver.test.ts +313 -0
- package/src/utils/repo-resolver.ts +294 -0
- package/src/utils/retry.test.ts +124 -0
- package/src/utils/retry.ts +85 -0
- package/src/utils/run-operations.ts +38 -0
- package/src/utils/suite.test.ts +256 -0
- package/src/utils/suite.ts +144 -0
- package/src/utils/sync-operations.ts +87 -0
- package/src/utils/tmux-dashboard.ts +193 -0
- package/src/utils/validation.test.ts +139 -0
- package/src/utils/validation.ts +128 -0
- package/src/utils/version-check.test.ts +108 -0
- package/src/utils/version-check.ts +96 -0
- package/src/utils/workspace-meta.ts +173 -0
- package/sync-permissions.sh +137 -0
- package/tsconfig.json +20 -0
- package/uninstall.sh +162 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.main = main;
|
|
41
|
+
const fs = __importStar(require("fs/promises"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const config_1 = require("../../utils/config");
|
|
44
|
+
const github_1 = require("../../utils/github");
|
|
45
|
+
const prompts_1 = require("../../utils/prompts");
|
|
46
|
+
const git_operations_1 = require("../../utils/git-operations");
|
|
47
|
+
const workspace_meta_1 = require("../../utils/workspace-meta");
|
|
48
|
+
const claude_integration_1 = require("../../utils/claude-integration");
|
|
49
|
+
const logger_1 = require("../../utils/logger");
|
|
50
|
+
const colors_1 = require("../../utils/colors");
|
|
51
|
+
const suite_1 = require("../../utils/suite");
|
|
52
|
+
const hooks_1 = require("../../utils/hooks");
|
|
53
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
54
|
+
const validation_1 = require("../../utils/validation");
|
|
55
|
+
async function main(opts) {
|
|
56
|
+
console.log('\n' + '='.repeat(60));
|
|
57
|
+
console.log((0, colors_1.colorize)('Create Workspace from Suite', 'bright'));
|
|
58
|
+
console.log('='.repeat(60) + '\n');
|
|
59
|
+
// Read from opts (Commander) or fall back to process.argv (legacy/direct)
|
|
60
|
+
const suiteFlag = opts?.suite;
|
|
61
|
+
const workspaceFlag = opts?.workspace;
|
|
62
|
+
const yes = opts?.yes ?? false;
|
|
63
|
+
const nonInteractive = !process.stdout.isTTY;
|
|
64
|
+
try {
|
|
65
|
+
// Step 1: Load suites
|
|
66
|
+
(0, logger_1.logStep)(1, 7, 'Loading suites...');
|
|
67
|
+
const suites = await (0, suite_1.listSuites)();
|
|
68
|
+
if (suites.length === 0) {
|
|
69
|
+
(0, logger_1.logError)('No suites found. Create one first with: workspace suite-create');
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
(0, logger_1.logSuccess)(`Found ${suites.length} suite(s)`);
|
|
73
|
+
// Step 2: Select suite
|
|
74
|
+
(0, logger_1.logStep)(2, 7, 'Select suite...');
|
|
75
|
+
if (!suiteFlag && nonInteractive) {
|
|
76
|
+
(0, logger_1.logError)("Missing required option: --suite");
|
|
77
|
+
(0, logger_1.logError)("Usage: w suite use --suite <name> --workspace <name>");
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
let selectedSuite;
|
|
81
|
+
if (suiteFlag) {
|
|
82
|
+
const found = suites.find(s => s.name === suiteFlag);
|
|
83
|
+
if (!found) {
|
|
84
|
+
(0, logger_1.logError)(`Suite not found: ${suiteFlag}`);
|
|
85
|
+
(0, logger_1.logError)(`Available suites: ${suites.map(s => s.name).join(', ')}`);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
selectedSuite = found;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const { suite } = await inquirer_1.default.prompt([
|
|
92
|
+
{
|
|
93
|
+
type: 'list',
|
|
94
|
+
name: 'suite',
|
|
95
|
+
message: 'Select a suite:',
|
|
96
|
+
choices: suites.map(s => ({
|
|
97
|
+
name: `${s.name} (${s.entries.length} repos)${s.description ? ` - ${s.description}` : ''}`,
|
|
98
|
+
value: s,
|
|
99
|
+
short: s.name,
|
|
100
|
+
})),
|
|
101
|
+
pageSize: 15,
|
|
102
|
+
},
|
|
103
|
+
]);
|
|
104
|
+
selectedSuite = suite;
|
|
105
|
+
}
|
|
106
|
+
console.log(`\n${(0, colors_1.colorize)('Suite repositories:', 'cyan')} ${selectedSuite.entries.length}`);
|
|
107
|
+
for (const entry of selectedSuite.entries) {
|
|
108
|
+
const alias = entry.directoryName !== entry.repoName ? ` (${entry.repoName})` : '';
|
|
109
|
+
console.log(` - ${entry.directoryName}${alias}`);
|
|
110
|
+
}
|
|
111
|
+
console.log('');
|
|
112
|
+
// Step 3: Verify gh CLI authentication
|
|
113
|
+
(0, logger_1.logStep)(3, 7, 'Verifying GitHub CLI authentication...');
|
|
114
|
+
const isAuthenticated = await (0, github_1.verifyGhAuth)();
|
|
115
|
+
if (!isAuthenticated) {
|
|
116
|
+
(0, logger_1.logError)('GitHub CLI is not authenticated');
|
|
117
|
+
(0, github_1.displayAuthInstructions)();
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
(0, logger_1.logSuccess)('GitHub CLI authenticated');
|
|
121
|
+
// Step 4: Fetch repos and resolve suite entries
|
|
122
|
+
(0, logger_1.logStep)(4, 7, 'Fetching repositories...');
|
|
123
|
+
const forceRefresh = opts?.forceRefresh ?? false;
|
|
124
|
+
const allRepos = await (0, github_1.fetchOrgRepos)({ forceRefresh });
|
|
125
|
+
const repoMap = new Map(allRepos.map(repo => [repo.name, repo]));
|
|
126
|
+
const resolvedEntries = [];
|
|
127
|
+
const missing = [];
|
|
128
|
+
for (const entry of selectedSuite.entries) {
|
|
129
|
+
const repo = repoMap.get(entry.repoName);
|
|
130
|
+
if (repo) {
|
|
131
|
+
resolvedEntries.push({ repo, directoryName: entry.directoryName });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
missing.push(entry.repoName);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (missing.length > 0) {
|
|
138
|
+
(0, logger_1.logInfo)(`${missing.length} repositories from suite not found or not accessible:`);
|
|
139
|
+
missing.forEach(name => console.log(` - ${(0, colors_1.colorize)(name, 'yellow')}`));
|
|
140
|
+
console.log('');
|
|
141
|
+
}
|
|
142
|
+
if (resolvedEntries.length === 0) {
|
|
143
|
+
(0, logger_1.logError)('No repositories from the suite are available');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
(0, logger_1.logInfo)(`${resolvedEntries.length} repositories will be cloned`);
|
|
147
|
+
// Step 5: Workspace name
|
|
148
|
+
(0, logger_1.logStep)(5, 7, 'Enter workspace name...');
|
|
149
|
+
if (!workspaceFlag && nonInteractive) {
|
|
150
|
+
(0, logger_1.logError)("Missing required option: --workspace");
|
|
151
|
+
(0, logger_1.logError)("Usage: w suite use --suite <name> --workspace <name>");
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
let workspaceName;
|
|
155
|
+
if (workspaceFlag) {
|
|
156
|
+
workspaceName = (0, validation_1.sanitizeWorkspaceName)(workspaceFlag);
|
|
157
|
+
const validation = (0, validation_1.validateWorkspaceName)(workspaceName);
|
|
158
|
+
if (validation !== true) {
|
|
159
|
+
(0, logger_1.logError)(typeof validation === 'string' ? validation : 'Invalid workspace name');
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
const exists = await (0, validation_1.checkWorkspaceExists)(workspaceName);
|
|
163
|
+
if (exists) {
|
|
164
|
+
const repoNames = selectedSuite.entries.map(e => e.repoName);
|
|
165
|
+
const resolved = await (0, validation_1.resolveWorkspaceNameConflict)(workspaceName, repoNames);
|
|
166
|
+
(0, logger_1.logInfo)(`Workspace "${workspaceName}" already exists — using "${(0, colors_1.colorize)(resolved, 'cyan')}" instead.`);
|
|
167
|
+
workspaceName = resolved;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
workspaceName = await (0, prompts_1.promptWorkspaceName)();
|
|
172
|
+
// Auto-resolve conflict in case the interactively chosen name already exists
|
|
173
|
+
const interactiveExists = await (0, validation_1.checkWorkspaceExists)(workspaceName);
|
|
174
|
+
if (interactiveExists) {
|
|
175
|
+
const repoNames = selectedSuite.entries.map(e => e.repoName);
|
|
176
|
+
const resolved = await (0, validation_1.resolveWorkspaceNameConflict)(workspaceName, repoNames);
|
|
177
|
+
(0, logger_1.logInfo)(`Workspace "${workspaceName}" already exists — using "${(0, colors_1.colorize)(resolved, 'cyan')}" instead.`);
|
|
178
|
+
workspaceName = resolved;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const workspacePath = path.join(config_1.WORKSPACES_DIR, workspaceName);
|
|
182
|
+
// Step 6: Confirm creation
|
|
183
|
+
(0, logger_1.logStep)(6, 7, 'Confirm workspace creation...');
|
|
184
|
+
if (!yes) {
|
|
185
|
+
const confirmed = await (0, prompts_1.confirmWorkspaceCreation)(workspaceName, resolvedEntries.length, workspacePath);
|
|
186
|
+
if (!confirmed) {
|
|
187
|
+
(0, logger_1.logInfo)('Workspace creation cancelled');
|
|
188
|
+
process.exit(0);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Step 7: Create workspace and clone repositories
|
|
192
|
+
(0, logger_1.logStep)(7, 7, 'Creating workspace from suite...');
|
|
193
|
+
await fs.mkdir(workspacePath, { recursive: true });
|
|
194
|
+
(0, logger_1.logSuccess)(`Created workspace directory: ${workspacePath}`);
|
|
195
|
+
const cloneResults = await (0, git_operations_1.cloneRepositories)(resolvedEntries, workspacePath);
|
|
196
|
+
const metadata = (0, workspace_meta_1.createMetadata)(workspaceName, cloneResults);
|
|
197
|
+
await (0, workspace_meta_1.saveMetadata)(workspacePath, metadata);
|
|
198
|
+
(0, git_operations_1.reportCloneResults)(cloneResults);
|
|
199
|
+
if (selectedSuite.postCloneHooks?.length) {
|
|
200
|
+
await (0, hooks_1.runPostCloneHooks)(workspacePath, metadata.repositories.filter(r => r.status === 'success'), selectedSuite.postCloneHooks);
|
|
201
|
+
}
|
|
202
|
+
const successfulRepos = cloneResults
|
|
203
|
+
.filter(r => r.status === 'success')
|
|
204
|
+
.map(r => r.repo);
|
|
205
|
+
if (successfulRepos.length > 0) {
|
|
206
|
+
(0, logger_1.logInfo)('Setting up Claude Code integration...');
|
|
207
|
+
await (0, claude_integration_1.generateClaudeContext)(workspacePath, workspaceName, successfulRepos, metadata);
|
|
208
|
+
}
|
|
209
|
+
const tempFile = path.join(process.env.HOME || '~', '.workspace-last-created');
|
|
210
|
+
try {
|
|
211
|
+
await fs.writeFile(tempFile, workspacePath, 'utf-8');
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
// Ignore errors writing temp file
|
|
215
|
+
}
|
|
216
|
+
(0, logger_1.logSuccess)('Workspace created from suite successfully!');
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
(0, logger_1.logError)('Failed to create workspace from suite');
|
|
220
|
+
if (error instanceof Error) {
|
|
221
|
+
(0, logger_1.logError)(error.message);
|
|
222
|
+
}
|
|
223
|
+
process.exit(1);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (require.main === module)
|
|
227
|
+
main();
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerSyncCommand = registerSyncCommand;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const config_1 = require("../utils/config");
|
|
39
|
+
const workspace_meta_1 = require("../utils/workspace-meta");
|
|
40
|
+
const logger_1 = require("../utils/logger");
|
|
41
|
+
const colors_1 = require("../utils/colors");
|
|
42
|
+
const progress_1 = require("../utils/progress");
|
|
43
|
+
const sync_operations_1 = require("../utils/sync-operations");
|
|
44
|
+
const command_helpers_1 = require("../utils/command-helpers");
|
|
45
|
+
function registerSyncCommand(parent) {
|
|
46
|
+
parent
|
|
47
|
+
.command('sync')
|
|
48
|
+
.alias('s')
|
|
49
|
+
.description('Git pull all repos in a workspace')
|
|
50
|
+
.argument('[workspace]', 'Workspace name')
|
|
51
|
+
.option('-w, --workspace <name>', 'Workspace name (alternative to positional)')
|
|
52
|
+
.action(async (workspaceArg, opts) => {
|
|
53
|
+
await handleSync(opts.workspace || workspaceArg);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async function handleSync(workspaceArg) {
|
|
57
|
+
console.log('\n' + '='.repeat(60));
|
|
58
|
+
console.log((0, colors_1.colorize)('Sync Workspace', 'bright'));
|
|
59
|
+
console.log('='.repeat(60) + '\n');
|
|
60
|
+
try {
|
|
61
|
+
const workspaceName = await (0, command_helpers_1.resolveWorkspace)(workspaceArg);
|
|
62
|
+
const workspacePath = path.join(config_1.WORKSPACES_DIR, workspaceName);
|
|
63
|
+
(0, logger_1.logInfo)(`Syncing workspace: ${(0, colors_1.colorize)(workspaceName, 'cyan')}`);
|
|
64
|
+
const metadata = await (0, workspace_meta_1.loadMetadata)(workspacePath);
|
|
65
|
+
if (!metadata) {
|
|
66
|
+
(0, logger_1.logError)('No metadata found for this workspace');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const repos = metadata.repositories.filter(r => r.status === 'success');
|
|
70
|
+
console.log(`\nFound ${repos.length} repositories to sync\n`);
|
|
71
|
+
const results = [];
|
|
72
|
+
const bar = (0, progress_1.createSimpleProgressBar)(repos.length, 'Syncing');
|
|
73
|
+
bar.start(repos.length, 0);
|
|
74
|
+
for (const repo of repos) {
|
|
75
|
+
const repoPath = path.join(workspacePath, repo.directoryName);
|
|
76
|
+
const displayName = repo.directoryName !== repo.name
|
|
77
|
+
? `${repo.directoryName} (${repo.name})`
|
|
78
|
+
: repo.name;
|
|
79
|
+
const result = await (0, sync_operations_1.syncRepository)(repoPath, displayName, true);
|
|
80
|
+
results.push(result);
|
|
81
|
+
bar.update(results.length);
|
|
82
|
+
}
|
|
83
|
+
bar.stop();
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log('\n' + '='.repeat(60));
|
|
86
|
+
console.log('Sync Results Summary');
|
|
87
|
+
console.log('='.repeat(60));
|
|
88
|
+
const successful = results.filter(r => r.status === 'success');
|
|
89
|
+
const failed = results.filter(r => r.status === 'failed');
|
|
90
|
+
const skipped = results.filter(r => r.status === 'skipped');
|
|
91
|
+
console.log(`${(0, colors_1.colorize)('✓', 'green')} Updated: ${successful.length}`);
|
|
92
|
+
console.log(`${(0, colors_1.colorize)('✗', 'red')} Failed: ${failed.length}`);
|
|
93
|
+
console.log(`${(0, colors_1.colorize)('○', 'yellow')} Skipped: ${skipped.length}`);
|
|
94
|
+
console.log('='.repeat(60));
|
|
95
|
+
if (failed.length > 0) {
|
|
96
|
+
console.log('\nFailed repositories:');
|
|
97
|
+
failed.forEach(result => {
|
|
98
|
+
console.log(` ${(0, colors_1.colorize)('✗', 'red')} ${result.repo}: ${result.message}`);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (skipped.length > 0) {
|
|
102
|
+
console.log('\nSkipped repositories:');
|
|
103
|
+
skipped.forEach(result => {
|
|
104
|
+
console.log(` ${(0, colors_1.colorize)('○', 'yellow')} ${result.repo}: ${result.message}`);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
console.log('');
|
|
108
|
+
(0, logger_1.logSuccess)('Workspace sync complete!');
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
(0, logger_1.logError)('Failed to sync workspace');
|
|
112
|
+
if (error instanceof Error) {
|
|
113
|
+
(0, logger_1.logError)(error.message);
|
|
114
|
+
}
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerUpdateCommand = registerUpdateCommand;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const config_1 = require("../utils/config");
|
|
39
|
+
const github_1 = require("../utils/github");
|
|
40
|
+
const prompts_1 = require("../utils/prompts");
|
|
41
|
+
const git_operations_1 = require("../utils/git-operations");
|
|
42
|
+
const ghq_integration_1 = require("../utils/ghq-integration");
|
|
43
|
+
const workspace_meta_1 = require("../utils/workspace-meta");
|
|
44
|
+
const claude_integration_1 = require("../utils/claude-integration");
|
|
45
|
+
const logger_1 = require("../utils/logger");
|
|
46
|
+
const colors_1 = require("../utils/colors");
|
|
47
|
+
const command_helpers_1 = require("../utils/command-helpers");
|
|
48
|
+
const repo_resolver_1 = require("../utils/repo-resolver");
|
|
49
|
+
function registerUpdateCommand(parent) {
|
|
50
|
+
parent
|
|
51
|
+
.command('update')
|
|
52
|
+
.alias('u')
|
|
53
|
+
.description('Add repositories to an existing workspace')
|
|
54
|
+
.option('-w, --workspace <name>', 'Workspace name')
|
|
55
|
+
.option('-r, --repos <repos>', 'Comma-separated repository names. Add a suffix to clone the same repo again under a separate folder, e.g. casper:cas-101 -> casper-cas-101')
|
|
56
|
+
.action(async (opts, cmd) => {
|
|
57
|
+
const globalOpts = (0, command_helpers_1.getGlobalOpts)(cmd);
|
|
58
|
+
await handleUpdate({ ...opts, ...globalOpts });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async function handleUpdate(opts) {
|
|
62
|
+
console.log('\n' + '='.repeat(60));
|
|
63
|
+
console.log((0, colors_1.colorize)('Update Workspace', 'bright'));
|
|
64
|
+
console.log('='.repeat(60) + '\n');
|
|
65
|
+
try {
|
|
66
|
+
// Step 1: Verify gh CLI authentication
|
|
67
|
+
(0, logger_1.logStep)(1, 5, 'Verifying GitHub CLI authentication...');
|
|
68
|
+
const isAuthenticated = await (0, github_1.verifyGhAuth)();
|
|
69
|
+
if (!isAuthenticated) {
|
|
70
|
+
(0, logger_1.logError)('GitHub CLI is not authenticated');
|
|
71
|
+
(0, github_1.displayAuthInstructions)();
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
(0, logger_1.logSuccess)('GitHub CLI authenticated');
|
|
75
|
+
// Step 2: List and select workspace
|
|
76
|
+
(0, logger_1.logStep)(2, 5, 'Select workspace to update...');
|
|
77
|
+
const workspaceName = await (0, command_helpers_1.resolveWorkspace)(opts.workspace);
|
|
78
|
+
const workspacePath = path.join(config_1.WORKSPACES_DIR, workspaceName);
|
|
79
|
+
(0, logger_1.logInfo)(`Selected workspace: ${(0, colors_1.colorize)(workspaceName, 'cyan')}`);
|
|
80
|
+
// Load existing metadata
|
|
81
|
+
const metadata = await (0, workspace_meta_1.loadMetadata)(workspacePath);
|
|
82
|
+
const existingDirectoryNames = metadata?.repositories.map(r => r.directoryName) || [];
|
|
83
|
+
// Duplicate detection is by directory name (the actual folder). The same
|
|
84
|
+
// repo CAN be added again under a different suffix (e.g. casper:cas-101 ->
|
|
85
|
+
// casper-cas-101), so we must NOT block on the canonical repo name.
|
|
86
|
+
const existingDirSet = new Set(existingDirectoryNames);
|
|
87
|
+
console.log(`\nCurrent repositories: ${existingDirectoryNames.length}`);
|
|
88
|
+
metadata?.repositories.forEach(r => {
|
|
89
|
+
const displayName = r.directoryName !== r.name
|
|
90
|
+
? `${r.directoryName} (${r.name})`
|
|
91
|
+
: r.name;
|
|
92
|
+
console.log(` - ${displayName}`);
|
|
93
|
+
});
|
|
94
|
+
console.log('');
|
|
95
|
+
// Step 3: Fetch all available repos
|
|
96
|
+
(0, logger_1.logStep)(3, 5, 'Fetching repositories...');
|
|
97
|
+
const allRepos = await (0, github_1.fetchOrgRepos)({ forceRefresh: opts.forceRefresh });
|
|
98
|
+
if (allRepos.length === 0) {
|
|
99
|
+
(0, logger_1.logError)('No repositories found');
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
// Step 4: Select new repositories to add
|
|
103
|
+
(0, logger_1.logStep)(4, 5, 'Select additional repositories to clone...');
|
|
104
|
+
let selectedEntries;
|
|
105
|
+
if (opts.repos) {
|
|
106
|
+
const repoSpecs = (0, command_helpers_1.parseList)(opts.repos);
|
|
107
|
+
const { resolved, notFound, invalidSuffix } = (0, repo_resolver_1.resolveRepoSpecs)(repoSpecs, allRepos);
|
|
108
|
+
if (invalidSuffix.length > 0) {
|
|
109
|
+
(0, logger_1.logError)(`Invalid instance suffix in: ${invalidSuffix.join(', ')}`);
|
|
110
|
+
(0, logger_1.logInfo)('Use repo:suffix (e.g. casper:cas-101). Suffix may contain letters, numbers, hyphens, underscores.');
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
// Warn about fuzzy-resolved names
|
|
114
|
+
for (const r of resolved) {
|
|
115
|
+
if (!r.exact)
|
|
116
|
+
(0, logger_1.logWarning)(`Repo "${r.input}" not found exactly — using "${r.repo.name}" (best match)`);
|
|
117
|
+
}
|
|
118
|
+
const duplicates = resolved.filter(r => existingDirSet.has(r.directoryName));
|
|
119
|
+
selectedEntries = resolved
|
|
120
|
+
.filter(r => !existingDirSet.has(r.directoryName))
|
|
121
|
+
.map(r => ({ repo: r.repo, directoryName: r.directoryName }));
|
|
122
|
+
if (duplicates.length > 0) {
|
|
123
|
+
(0, logger_1.logWarning)(`Skipping entries whose directory already exists: ${duplicates.map(r => r.directoryName).join(', ')}`);
|
|
124
|
+
}
|
|
125
|
+
if (notFound.length > 0) {
|
|
126
|
+
(0, logger_1.logError)(`Repositories not found: ${notFound.join(', ')}`);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log(`\n${allRepos.length} repositories available to add\n`);
|
|
132
|
+
selectedEntries = await (0, prompts_1.promptRepositorySelection)(allRepos, existingDirectoryNames);
|
|
133
|
+
}
|
|
134
|
+
if (selectedEntries.length === 0) {
|
|
135
|
+
(0, logger_1.logInfo)('No new repositories selected');
|
|
136
|
+
process.exit(0);
|
|
137
|
+
}
|
|
138
|
+
(0, logger_1.logInfo)(`Selected ${selectedEntries.length} new repositories to add`);
|
|
139
|
+
// Step 5: Clone new repositories
|
|
140
|
+
(0, logger_1.logStep)(5, 5, 'Cloning new repositories...');
|
|
141
|
+
await (0, ghq_integration_1.warnIfGhqMissing)();
|
|
142
|
+
const cloneResults = await (0, git_operations_1.cloneRepositories)(selectedEntries, workspacePath);
|
|
143
|
+
// Update metadata — create from scratch if the workspace had none
|
|
144
|
+
const newRepoMetadata = cloneResults.map(result => ({
|
|
145
|
+
name: result.repo.name,
|
|
146
|
+
directoryName: result.directoryName,
|
|
147
|
+
owner: result.repo.owner.login,
|
|
148
|
+
clonedAt: result.clonedAt || new Date().toISOString(),
|
|
149
|
+
cloneUrl: (0, config_1.getCloneUrl)(result.repo),
|
|
150
|
+
status: result.status,
|
|
151
|
+
error: result.error,
|
|
152
|
+
}));
|
|
153
|
+
let finalMetadata;
|
|
154
|
+
if (metadata) {
|
|
155
|
+
metadata.repositories.push(...newRepoMetadata);
|
|
156
|
+
metadata.lastModified = new Date().toISOString();
|
|
157
|
+
await (0, workspace_meta_1.saveMetadata)(workspacePath, metadata);
|
|
158
|
+
finalMetadata = metadata;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Workspace had no metadata file — create one now
|
|
162
|
+
const fresh = {
|
|
163
|
+
workspaceName,
|
|
164
|
+
createdAt: new Date().toISOString(),
|
|
165
|
+
lastModified: new Date().toISOString(),
|
|
166
|
+
repositories: newRepoMetadata,
|
|
167
|
+
};
|
|
168
|
+
await (0, workspace_meta_1.saveMetadata)(workspacePath, fresh);
|
|
169
|
+
finalMetadata = fresh;
|
|
170
|
+
}
|
|
171
|
+
// Regenerate the agent context (CLAUDE.md/AGENTS.md) + .mcp.json so the
|
|
172
|
+
// newly added repos actually surface — otherwise an investigate-first
|
|
173
|
+
// workspace keeps saying "0 repositories" and its context stays stale.
|
|
174
|
+
// Resolve the FULL remaining set (existing + new) to catalog objects so
|
|
175
|
+
// pre-existing repos keep their descriptions/URLs on regenerate (matches
|
|
176
|
+
// the remove-repo path). Best-effort: never fail the update over this.
|
|
177
|
+
const repoObjects = finalMetadata.repositories
|
|
178
|
+
.filter(r => r.status === 'success')
|
|
179
|
+
.map(r => allRepos.find(ar => ar.name === r.name))
|
|
180
|
+
.filter((r) => r != null);
|
|
181
|
+
// Only regenerate when this update actually added a repo — a failure-only
|
|
182
|
+
// update must not rewrite (and clobber) the existing context.
|
|
183
|
+
const addedNewRepo = cloneResults.some(r => r.status === 'success');
|
|
184
|
+
try {
|
|
185
|
+
if (addedNewRepo && repoObjects.length > 0) {
|
|
186
|
+
await (0, claude_integration_1.generateClaudeContext)(workspacePath, workspaceName, repoObjects, finalMetadata);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch { /* context regen is best-effort */ }
|
|
190
|
+
// Report results
|
|
191
|
+
(0, git_operations_1.reportCloneResults)(cloneResults);
|
|
192
|
+
const totalRepos = existingDirectoryNames.length + cloneResults.filter(r => r.status === 'success').length;
|
|
193
|
+
console.log(`Workspace now has ${(0, colors_1.colorize)(String(totalRepos), 'cyan')} repositories\n`);
|
|
194
|
+
(0, logger_1.logSuccess)('Workspace updated successfully!');
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
(0, logger_1.logError)('Failed to update workspace');
|
|
198
|
+
if (error instanceof Error) {
|
|
199
|
+
(0, logger_1.logError)(error.message);
|
|
200
|
+
}
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
}
|