@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,172 @@
|
|
|
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.installDashboardHooks = installDashboardHooks;
|
|
37
|
+
exports.areDashboardHooksInstalled = areDashboardHooksInstalled;
|
|
38
|
+
exports.uninstallDashboardHooks = uninstallDashboardHooks;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
const dashboard_1 = require("../types/dashboard");
|
|
43
|
+
const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), '.claude', 'settings.json');
|
|
44
|
+
/** Events we register hooks for */
|
|
45
|
+
const HOOK_EVENTS = ['SessionStart', 'PreToolUse', 'PostToolUse', 'UserPromptSubmit', 'Notification', 'Stop', 'SessionEnd'];
|
|
46
|
+
/**
|
|
47
|
+
* Resolve path to the compiled hook-handler.js.
|
|
48
|
+
* This file (dashboard-hooks.ts) compiles to dist/utils/dashboard-hooks.js,
|
|
49
|
+
* so hook-handler.js is at ../commands/dashboard/hook-handler.js relative to dist/utils/.
|
|
50
|
+
*/
|
|
51
|
+
function getHookHandlerPath() {
|
|
52
|
+
return path.join(__dirname, '..', 'commands', 'dashboard', 'hook-handler.js');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build the hook command string for a given event.
|
|
56
|
+
*/
|
|
57
|
+
function buildHookCommand(event) {
|
|
58
|
+
const handlerPath = getHookHandlerPath();
|
|
59
|
+
return `node "${handlerPath}" --event ${event} --marker ${dashboard_1.HOOK_MARKER}`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Read Claude settings from disk. Returns empty settings if file doesn't exist.
|
|
63
|
+
*/
|
|
64
|
+
function readClaudeSettings() {
|
|
65
|
+
try {
|
|
66
|
+
const content = fs.readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8');
|
|
67
|
+
return JSON.parse(content);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Write Claude settings to disk atomically (write to .tmp, then rename).
|
|
75
|
+
* Prevents corruption if the process is interrupted mid-write.
|
|
76
|
+
*/
|
|
77
|
+
function writeClaudeSettings(settings) {
|
|
78
|
+
const dir = path.dirname(CLAUDE_SETTINGS_PATH);
|
|
79
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
80
|
+
const tmp = CLAUDE_SETTINGS_PATH + '.tmp';
|
|
81
|
+
try {
|
|
82
|
+
fs.writeFileSync(tmp, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
|
|
83
|
+
fs.renameSync(tmp, CLAUDE_SETTINGS_PATH);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
try {
|
|
87
|
+
fs.unlinkSync(tmp);
|
|
88
|
+
}
|
|
89
|
+
catch { /* ignore */ }
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if a hook group contains our dashboard hook marker.
|
|
95
|
+
*/
|
|
96
|
+
function groupContainsMarker(group) {
|
|
97
|
+
return group.hooks.some(h => h.command && h.command.includes(dashboard_1.HOOK_MARKER));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Install dashboard hooks into Claude settings.
|
|
101
|
+
* Appends new hook groups — never modifies existing hooks.
|
|
102
|
+
* Idempotent: skips events that already have the marker.
|
|
103
|
+
*/
|
|
104
|
+
function installDashboardHooks() {
|
|
105
|
+
const settings = readClaudeSettings();
|
|
106
|
+
if (!settings.hooks) {
|
|
107
|
+
settings.hooks = {};
|
|
108
|
+
}
|
|
109
|
+
for (const event of HOOK_EVENTS) {
|
|
110
|
+
if (!settings.hooks[event]) {
|
|
111
|
+
settings.hooks[event] = [];
|
|
112
|
+
}
|
|
113
|
+
// Check if already installed
|
|
114
|
+
const alreadyInstalled = settings.hooks[event].some(groupContainsMarker);
|
|
115
|
+
if (alreadyInstalled) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Append a new hook group
|
|
119
|
+
const hookGroup = {
|
|
120
|
+
hooks: [
|
|
121
|
+
{
|
|
122
|
+
type: 'command',
|
|
123
|
+
command: buildHookCommand(event),
|
|
124
|
+
timeout: 5,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
};
|
|
128
|
+
// PreToolUse and PostToolUse hooks use a matcher — use empty string to match all tools
|
|
129
|
+
if (event === 'PreToolUse' || event === 'PostToolUse') {
|
|
130
|
+
hookGroup.matcher = '';
|
|
131
|
+
}
|
|
132
|
+
settings.hooks[event].push(hookGroup);
|
|
133
|
+
}
|
|
134
|
+
writeClaudeSettings(settings);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if all dashboard hooks are installed.
|
|
138
|
+
*/
|
|
139
|
+
function areDashboardHooksInstalled() {
|
|
140
|
+
const settings = readClaudeSettings();
|
|
141
|
+
if (!settings.hooks)
|
|
142
|
+
return false;
|
|
143
|
+
return HOOK_EVENTS.every(event => {
|
|
144
|
+
const groups = settings.hooks?.[event];
|
|
145
|
+
if (!groups || !Array.isArray(groups))
|
|
146
|
+
return false;
|
|
147
|
+
return groups.some(groupContainsMarker);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Remove all dashboard hooks from Claude settings.
|
|
152
|
+
* Only removes hook groups containing the HOOK_MARKER — leaves everything else untouched.
|
|
153
|
+
*/
|
|
154
|
+
function uninstallDashboardHooks() {
|
|
155
|
+
const settings = readClaudeSettings();
|
|
156
|
+
if (!settings.hooks)
|
|
157
|
+
return;
|
|
158
|
+
for (const event of HOOK_EVENTS) {
|
|
159
|
+
if (!settings.hooks[event])
|
|
160
|
+
continue;
|
|
161
|
+
settings.hooks[event] = settings.hooks[event].filter(g => !groupContainsMarker(g));
|
|
162
|
+
// Clean up empty arrays
|
|
163
|
+
if (settings.hooks[event].length === 0) {
|
|
164
|
+
delete settings.hooks[event];
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Clean up empty hooks object
|
|
168
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
169
|
+
delete settings.hooks;
|
|
170
|
+
}
|
|
171
|
+
writeClaudeSettings(settings);
|
|
172
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
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.updateWorkspaceMetadata = exports.generateMermaidDiagram = exports.detectCircularDependencies = exports.analyzeDependencies = exports.analyzeDockerCompose = exports.analyzeDockerfile = exports.analyzeImports = exports.analyzePackageJson = void 0;
|
|
37
|
+
const fs = __importStar(require("fs/promises"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const config_1 = require("./config");
|
|
40
|
+
const analyzePackageJson = async (repoPath) => {
|
|
41
|
+
try {
|
|
42
|
+
const packageJsonPath = path.join(repoPath, 'package.json');
|
|
43
|
+
const content = await fs.readFile(packageJsonPath, 'utf-8');
|
|
44
|
+
const packageJson = JSON.parse(content);
|
|
45
|
+
const dependencies = [];
|
|
46
|
+
// Check dependencies and devDependencies
|
|
47
|
+
const allDeps = {
|
|
48
|
+
...packageJson.dependencies,
|
|
49
|
+
...packageJson.devDependencies,
|
|
50
|
+
};
|
|
51
|
+
const { githubOrg } = (0, config_1.getUserConfig)();
|
|
52
|
+
const scopePrefix = githubOrg ? `@${githubOrg}/` : '';
|
|
53
|
+
for (const dep of Object.keys(allDeps)) {
|
|
54
|
+
// Match packages under the configured org scope (e.g. @your-org/*), or any
|
|
55
|
+
// scoped package as a fallback so cross-repo links are still detected.
|
|
56
|
+
if (dep.startsWith('@')) {
|
|
57
|
+
dependencies.push(scopePrefix && dep.startsWith(scopePrefix)
|
|
58
|
+
? dep.slice(scopePrefix.length)
|
|
59
|
+
: dep.replace(/^@[^/]+\//, '').replace('@', ''));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return dependencies;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
exports.analyzePackageJson = analyzePackageJson;
|
|
69
|
+
const analyzeImports = async (repoPath) => {
|
|
70
|
+
try {
|
|
71
|
+
const dependencies = new Set();
|
|
72
|
+
// Scan source files for relative imports that might indicate dependencies
|
|
73
|
+
const scanDirs = ['src', 'lib', 'app'];
|
|
74
|
+
for (const dir of scanDirs) {
|
|
75
|
+
const dirPath = path.join(repoPath, dir);
|
|
76
|
+
try {
|
|
77
|
+
await fs.access(dirPath);
|
|
78
|
+
// For simplicity, we're not doing deep file scanning here
|
|
79
|
+
// In a real implementation, you'd recursively read .ts, .js, .tsx files
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return Array.from(dependencies);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
exports.analyzeImports = analyzeImports;
|
|
92
|
+
const analyzeDockerfile = async (repoPath) => {
|
|
93
|
+
try {
|
|
94
|
+
const dockerfilePath = path.join(repoPath, 'Dockerfile');
|
|
95
|
+
const content = await fs.readFile(dockerfilePath, 'utf-8');
|
|
96
|
+
const dependencies = [];
|
|
97
|
+
const fromRegex = /FROM\s+([^\s]+)/g;
|
|
98
|
+
let match;
|
|
99
|
+
while ((match = fromRegex.exec(content)) !== null) {
|
|
100
|
+
const image = match[1];
|
|
101
|
+
// Extract potential dependency references to other org images. When an org
|
|
102
|
+
// is configured, treat images named after it (e.g. `your-org-foo`) as deps.
|
|
103
|
+
const { githubOrg } = (0, config_1.getUserConfig)();
|
|
104
|
+
if (githubOrg && image.includes(githubOrg)) {
|
|
105
|
+
dependencies.push(image.split(':')[0].replace(`${githubOrg}-`, ''));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return dependencies;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
exports.analyzeDockerfile = analyzeDockerfile;
|
|
115
|
+
const analyzeDockerCompose = async (repoPath) => {
|
|
116
|
+
try {
|
|
117
|
+
const composePath = path.join(repoPath, 'docker-compose.yml');
|
|
118
|
+
const content = await fs.readFile(composePath, 'utf-8');
|
|
119
|
+
const dependencies = [];
|
|
120
|
+
// Simple pattern matching for service references
|
|
121
|
+
const serviceRegex = /depends_on:\s*\n((?:\s+-\s+\w+\n)+)/g;
|
|
122
|
+
let match;
|
|
123
|
+
while ((match = serviceRegex.exec(content)) !== null) {
|
|
124
|
+
const services = match[1].match(/\w+/g);
|
|
125
|
+
if (services) {
|
|
126
|
+
dependencies.push(...services);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return dependencies;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
exports.analyzeDockerCompose = analyzeDockerCompose;
|
|
136
|
+
const analyzeDependencies = async (workspacePath, repoNames) => {
|
|
137
|
+
const analyses = new Map();
|
|
138
|
+
for (const repoName of repoNames) {
|
|
139
|
+
const repoPath = path.join(workspacePath, repoName);
|
|
140
|
+
const [packageDeps, dockerDeps, composeDeps] = await Promise.all([
|
|
141
|
+
(0, exports.analyzePackageJson)(repoPath),
|
|
142
|
+
(0, exports.analyzeDockerfile)(repoPath),
|
|
143
|
+
(0, exports.analyzeDockerCompose)(repoPath),
|
|
144
|
+
]);
|
|
145
|
+
const allDeps = [...new Set([...packageDeps, ...dockerDeps, ...composeDeps])];
|
|
146
|
+
// Filter to only dependencies that are in the workspace
|
|
147
|
+
const validDeps = allDeps.filter(dep => repoNames.includes(dep));
|
|
148
|
+
// Find missing dependencies (referenced but not in workspace)
|
|
149
|
+
const missingDeps = allDeps.filter(dep => !repoNames.includes(dep));
|
|
150
|
+
analyses.set(repoName, {
|
|
151
|
+
repoName,
|
|
152
|
+
dependencies: validDeps,
|
|
153
|
+
dependents: [], // Will be filled in next pass
|
|
154
|
+
missingDependencies: missingDeps,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
// Build dependents lists
|
|
158
|
+
for (const [repoName, analysis] of analyses) {
|
|
159
|
+
for (const dep of analysis.dependencies) {
|
|
160
|
+
const depAnalysis = analyses.get(dep);
|
|
161
|
+
if (depAnalysis && !depAnalysis.dependents.includes(repoName)) {
|
|
162
|
+
depAnalysis.dependents.push(repoName);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return analyses;
|
|
167
|
+
};
|
|
168
|
+
exports.analyzeDependencies = analyzeDependencies;
|
|
169
|
+
const detectCircularDependencies = (analyses) => {
|
|
170
|
+
const visited = new Set();
|
|
171
|
+
const recursionStack = new Set();
|
|
172
|
+
const cycles = [];
|
|
173
|
+
const dfs = (repo, path) => {
|
|
174
|
+
visited.add(repo);
|
|
175
|
+
recursionStack.add(repo);
|
|
176
|
+
path.push(repo);
|
|
177
|
+
const analysis = analyses.get(repo);
|
|
178
|
+
if (analysis) {
|
|
179
|
+
for (const dep of analysis.dependencies) {
|
|
180
|
+
if (!visited.has(dep)) {
|
|
181
|
+
dfs(dep, [...path]);
|
|
182
|
+
}
|
|
183
|
+
else if (recursionStack.has(dep)) {
|
|
184
|
+
// Found a cycle
|
|
185
|
+
const cycleStart = path.indexOf(dep);
|
|
186
|
+
const cycle = path.slice(cycleStart);
|
|
187
|
+
cycle.push(dep);
|
|
188
|
+
cycles.push(cycle);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
recursionStack.delete(repo);
|
|
193
|
+
};
|
|
194
|
+
for (const repoName of analyses.keys()) {
|
|
195
|
+
if (!visited.has(repoName)) {
|
|
196
|
+
dfs(repoName, []);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return cycles;
|
|
200
|
+
};
|
|
201
|
+
exports.detectCircularDependencies = detectCircularDependencies;
|
|
202
|
+
const generateMermaidDiagram = (analyses) => {
|
|
203
|
+
const lines = ['```mermaid', 'graph TD'];
|
|
204
|
+
for (const [repoName, analysis] of analyses) {
|
|
205
|
+
const nodeId = repoName.replace(/[^a-zA-Z0-9]/g, '_');
|
|
206
|
+
for (const dep of analysis.dependencies) {
|
|
207
|
+
const depId = dep.replace(/[^a-zA-Z0-9]/g, '_');
|
|
208
|
+
lines.push(` ${nodeId}[${repoName}] --> ${depId}[${dep}]`);
|
|
209
|
+
}
|
|
210
|
+
// Add standalone nodes (no dependencies)
|
|
211
|
+
if (analysis.dependencies.length === 0 && analysis.dependents.length === 0) {
|
|
212
|
+
lines.push(` ${nodeId}[${repoName}]`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
lines.push('```');
|
|
216
|
+
return lines.join('\n');
|
|
217
|
+
};
|
|
218
|
+
exports.generateMermaidDiagram = generateMermaidDiagram;
|
|
219
|
+
const updateWorkspaceMetadata = (metadata, analyses) => {
|
|
220
|
+
const dependencies = {};
|
|
221
|
+
for (const [repoName, analysis] of analyses) {
|
|
222
|
+
dependencies[repoName] = {
|
|
223
|
+
dependsOn: analysis.dependencies,
|
|
224
|
+
dependedBy: analysis.dependents,
|
|
225
|
+
lastAnalyzed: new Date().toISOString(),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
...metadata,
|
|
230
|
+
dependencies,
|
|
231
|
+
lastModified: new Date().toISOString(),
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
exports.updateWorkspaceMetadata = updateWorkspaceMetadata;
|
|
@@ -0,0 +1,80 @@
|
|
|
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.parseDiffStat = parseDiffStat;
|
|
37
|
+
exports.getRepoDiff = getRepoDiff;
|
|
38
|
+
const child_process_1 = require("child_process");
|
|
39
|
+
const util_1 = require("util");
|
|
40
|
+
const fs = __importStar(require("fs/promises"));
|
|
41
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
42
|
+
function parseDiffStat(output) {
|
|
43
|
+
const match = output.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/);
|
|
44
|
+
if (!match) {
|
|
45
|
+
return { files: 0, insertions: 0, deletions: 0 };
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
files: parseInt(match[1], 10) || 0,
|
|
49
|
+
insertions: parseInt(match[2], 10) || 0,
|
|
50
|
+
deletions: parseInt(match[3], 10) || 0,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async function getRepoDiff(repoPath, repoName) {
|
|
54
|
+
try {
|
|
55
|
+
await fs.access(repoPath);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return { repo: repoName, staged: { files: 0, insertions: 0, deletions: 0 }, unstaged: { files: 0, insertions: 0, deletions: 0 }, error: 'Directory not found' };
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const [unstagedResult, stagedResult] = await Promise.all([
|
|
62
|
+
execAsync('git diff --stat', { cwd: repoPath }).catch(() => ({ stdout: '' })),
|
|
63
|
+
execAsync('git diff --cached --stat', { cwd: repoPath }).catch(() => ({ stdout: '' })),
|
|
64
|
+
]);
|
|
65
|
+
return {
|
|
66
|
+
repo: repoName,
|
|
67
|
+
unstaged: parseDiffStat(unstagedResult.stdout),
|
|
68
|
+
staged: parseDiffStat(stagedResult.stdout),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
73
|
+
return {
|
|
74
|
+
repo: repoName,
|
|
75
|
+
staged: { files: 0, insertions: 0, deletions: 0 },
|
|
76
|
+
unstaged: { files: 0, insertions: 0, deletions: 0 },
|
|
77
|
+
error: errorMessage,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
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.writeDocs = exports.generateRepositoryIndex = exports.generateDependencyGraph = exports.generateWorkspaceReadme = void 0;
|
|
37
|
+
const fs = __importStar(require("fs/promises"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const dependency_analyzer_1 = require("./dependency-analyzer");
|
|
40
|
+
const generateWorkspaceReadme = async (metadata, workspacePath) => {
|
|
41
|
+
const lines = [];
|
|
42
|
+
lines.push(`# ${metadata.workspaceName}`);
|
|
43
|
+
lines.push('');
|
|
44
|
+
if (metadata.description) {
|
|
45
|
+
lines.push(metadata.description);
|
|
46
|
+
lines.push('');
|
|
47
|
+
}
|
|
48
|
+
lines.push('## Overview');
|
|
49
|
+
lines.push('');
|
|
50
|
+
lines.push(`- **Created:** ${new Date(metadata.createdAt).toLocaleString()}`);
|
|
51
|
+
if (metadata.lastModified) {
|
|
52
|
+
lines.push(`- **Last Modified:** ${new Date(metadata.lastModified).toLocaleString()}`);
|
|
53
|
+
}
|
|
54
|
+
lines.push(`- **Repositories:** ${metadata.repositories.length}`);
|
|
55
|
+
lines.push('');
|
|
56
|
+
lines.push('## Repositories');
|
|
57
|
+
lines.push('');
|
|
58
|
+
const tableData = [
|
|
59
|
+
['Repository', 'Owner', 'Cloned At', 'Status'],
|
|
60
|
+
];
|
|
61
|
+
for (const repo of metadata.repositories) {
|
|
62
|
+
tableData.push([
|
|
63
|
+
repo.name,
|
|
64
|
+
repo.owner,
|
|
65
|
+
new Date(repo.clonedAt).toLocaleDateString(),
|
|
66
|
+
repo.status === 'success' ? '✓' : '✗',
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
// Simple table generation without markdown-table for now
|
|
70
|
+
for (const row of tableData) {
|
|
71
|
+
lines.push('| ' + row.join(' | ') + ' |');
|
|
72
|
+
if (tableData.indexOf(row) === 0) {
|
|
73
|
+
lines.push('| ' + row.map(() => '---').join(' | ') + ' |');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
lines.push('');
|
|
77
|
+
lines.push('## Quick Start');
|
|
78
|
+
lines.push('');
|
|
79
|
+
lines.push('```bash');
|
|
80
|
+
lines.push(`# Navigate to workspace`);
|
|
81
|
+
lines.push(`wgo ${metadata.workspaceName}`);
|
|
82
|
+
lines.push('');
|
|
83
|
+
lines.push('# Check status');
|
|
84
|
+
lines.push(`workspace status ${metadata.workspaceName}`);
|
|
85
|
+
lines.push('');
|
|
86
|
+
lines.push('# Sync all repositories');
|
|
87
|
+
lines.push(`workspace sync ${metadata.workspaceName}`);
|
|
88
|
+
lines.push('```');
|
|
89
|
+
lines.push('');
|
|
90
|
+
lines.push('## Commands');
|
|
91
|
+
lines.push('');
|
|
92
|
+
lines.push('- `workspace status` - Check git status across all repos');
|
|
93
|
+
lines.push('- `workspace doctor` - Run health checks');
|
|
94
|
+
lines.push('- `workspace sync` - Pull latest changes');
|
|
95
|
+
lines.push('- `workspace switch-branch` - Switch all repos to a branch');
|
|
96
|
+
lines.push('- `workspace analyze-deps` - Analyze dependencies');
|
|
97
|
+
lines.push('');
|
|
98
|
+
return lines.join('\n');
|
|
99
|
+
};
|
|
100
|
+
exports.generateWorkspaceReadme = generateWorkspaceReadme;
|
|
101
|
+
const generateDependencyGraph = (metadata) => {
|
|
102
|
+
const lines = [];
|
|
103
|
+
lines.push('# Dependency Graph');
|
|
104
|
+
lines.push('');
|
|
105
|
+
if (metadata.dependencies) {
|
|
106
|
+
const analyses = new Map();
|
|
107
|
+
for (const [repoName, depInfo] of Object.entries(metadata.dependencies)) {
|
|
108
|
+
analyses.set(repoName, {
|
|
109
|
+
repoName,
|
|
110
|
+
dependencies: depInfo.dependsOn,
|
|
111
|
+
dependents: depInfo.dependedBy,
|
|
112
|
+
missingDependencies: [],
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const diagram = (0, dependency_analyzer_1.generateMermaidDiagram)(analyses);
|
|
116
|
+
lines.push(diagram);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
lines.push('No dependency analysis available. Run `workspace analyze-deps` to generate.');
|
|
120
|
+
}
|
|
121
|
+
lines.push('');
|
|
122
|
+
lines.push('## Dependency Details');
|
|
123
|
+
lines.push('');
|
|
124
|
+
if (metadata.dependencies) {
|
|
125
|
+
for (const [repoName, depInfo] of Object.entries(metadata.dependencies)) {
|
|
126
|
+
lines.push(`### ${repoName}`);
|
|
127
|
+
lines.push('');
|
|
128
|
+
if (depInfo.dependsOn.length > 0) {
|
|
129
|
+
lines.push(`**Depends on:** ${depInfo.dependsOn.join(', ')}`);
|
|
130
|
+
lines.push('');
|
|
131
|
+
}
|
|
132
|
+
if (depInfo.dependedBy.length > 0) {
|
|
133
|
+
lines.push(`**Depended by:** ${depInfo.dependedBy.join(', ')}`);
|
|
134
|
+
lines.push('');
|
|
135
|
+
}
|
|
136
|
+
if (depInfo.dependsOn.length === 0 && depInfo.dependedBy.length === 0) {
|
|
137
|
+
lines.push('No dependencies');
|
|
138
|
+
lines.push('');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return lines.join('\n');
|
|
143
|
+
};
|
|
144
|
+
exports.generateDependencyGraph = generateDependencyGraph;
|
|
145
|
+
const generateRepositoryIndex = async (metadata, workspacePath) => {
|
|
146
|
+
const lines = [];
|
|
147
|
+
lines.push('# Repository Index');
|
|
148
|
+
lines.push('');
|
|
149
|
+
for (const repo of metadata.repositories) {
|
|
150
|
+
const repoPath = path.join(workspacePath, repo.name);
|
|
151
|
+
lines.push(`## ${repo.name}`);
|
|
152
|
+
lines.push('');
|
|
153
|
+
lines.push(`- **Owner:** ${repo.owner}`);
|
|
154
|
+
lines.push(`- **Clone URL:** ${repo.cloneUrl}`);
|
|
155
|
+
lines.push(`- **Cloned At:** ${new Date(repo.clonedAt).toLocaleString()}`);
|
|
156
|
+
// Try to read package.json for tech stack info
|
|
157
|
+
try {
|
|
158
|
+
const packageJsonPath = path.join(repoPath, 'package.json');
|
|
159
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
|
|
160
|
+
if (packageJson.description) {
|
|
161
|
+
lines.push(`- **Description:** ${packageJson.description}`);
|
|
162
|
+
}
|
|
163
|
+
if (packageJson.scripts) {
|
|
164
|
+
const scripts = Object.keys(packageJson.scripts).slice(0, 5);
|
|
165
|
+
lines.push(`- **Scripts:** ${scripts.join(', ')}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// No package.json or can't read
|
|
170
|
+
}
|
|
171
|
+
lines.push('');
|
|
172
|
+
}
|
|
173
|
+
return lines.join('\n');
|
|
174
|
+
};
|
|
175
|
+
exports.generateRepositoryIndex = generateRepositoryIndex;
|
|
176
|
+
const writeDocs = async (workspacePath, metadata) => {
|
|
177
|
+
const readme = await (0, exports.generateWorkspaceReadme)(metadata, workspacePath);
|
|
178
|
+
await fs.writeFile(path.join(workspacePath, 'WORKSPACE-README.md'), readme, 'utf-8');
|
|
179
|
+
const depGraph = (0, exports.generateDependencyGraph)(metadata);
|
|
180
|
+
await fs.writeFile(path.join(workspacePath, 'DEPENDENCY-GRAPH.md'), depGraph, 'utf-8');
|
|
181
|
+
const repoIndex = await (0, exports.generateRepositoryIndex)(metadata, workspacePath);
|
|
182
|
+
await fs.writeFile(path.join(workspacePath, 'REPOSITORY-INDEX.md'), repoIndex, 'utf-8');
|
|
183
|
+
};
|
|
184
|
+
exports.writeDocs = writeDocs;
|