itismyskillmarket 1.3.27 → 1.3.30

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # SkillMarket
2
2
 
3
- Cross-platform skill manager for AI coding tools (Cursor, VSCode, Codex, OpenCode, Claude Code, Antigravity, OpenClaw, Hermes Agent).
3
+ > **v1.3.29** — Cross-platform skill manager for AI coding tools (Cursor, VSCode, Codex, OpenCode, Claude Code, Antigravity, OpenClaw, Hermes Agent).
4
4
 
5
5
  ## Installation
6
6
 
@@ -14,6 +14,25 @@ Or use directly:
14
14
  npx itismyskillmarket --help
15
15
  ```
16
16
 
17
+ ## Download Standalone .exe (Windows)
18
+
19
+ Download the **standalone Windows executable** (~86 MB) — no Node.js installation required:
20
+
21
+ ```bash
22
+ # Download from GitHub Releases
23
+ # https://github.com/wxc2004/market/releases/download/v1.3.29/skillmarket.exe
24
+
25
+ # Double-click the exe to start GUI + open browser automatically
26
+ # Or run from terminal:
27
+ .\skillmarket.exe # Start GUI (same as double-click)
28
+ .\skillmarket.exe --help # Show CLI help
29
+ .\skillmarket.exe ls # List available skills
30
+ ```
31
+
32
+ > **双击体验**: 直接双击 `skillmarket.exe` 会自动启动 Web GUI 界面并打开浏览器,无需打开终端输入命令。带参数运行则进入命令行模式。
33
+
34
+ All CLI commands work identically to the npm version. Built with Node.js SEA (Single Executable Applications).
35
+
17
36
  ## Usage
18
37
 
19
38
  ```bash
@@ -160,6 +179,14 @@ skm admin owner rm my-skill old-maintainer
160
179
  skm admin access my-skill restricted
161
180
  ```
162
181
 
182
+ ### GUI Upload Skill
183
+
184
+ The `skm gui` web interface includes an **Upload** view for publishing or installing skills from a `.zip` archive:
185
+
186
+ 1. Drag & drop or select a skill zip file
187
+ 2. Click "Upload & Parse" to extract and validate
188
+ 3. Choose action: **Publish to npm**, **Install Locally**, or **Both**
189
+
163
190
  ### GUI Admin Dashboard
164
191
 
165
192
  The `skm gui` web interface includes an **Admin** view with:
@@ -265,6 +292,11 @@ npm run build
265
292
 
266
293
  # Link for local testing
267
294
  npm link
295
+
296
+ # Build standalone .exe (Windows)
297
+ # Requires: Node.js 20+, esbuild, postject
298
+ node scripts/build-exe.mjs
299
+ # Output: dist/skillmarket.exe (~86 MB)
268
300
  ```
269
301
 
270
302
  ## Architecture
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { Command } from "commander";
5
5
  import { readFileSync as readFileSync3 } from "fs";
6
6
  import { fileURLToPath as fileURLToPath4 } from "url";
7
7
  import { dirname as dirname2, resolve } from "path";
8
+ import { execSync as execSync3 } from "child_process";
8
9
 
9
10
  // src/commands/registry.ts
10
11
  import fs2 from "fs-extra";
@@ -1171,11 +1172,11 @@ Uninstalling all skills...
1171
1172
  import fs12 from "fs-extra";
1172
1173
  import path11 from "path";
1173
1174
  var GITHUB_URL_PATTERNS = [
1174
- /^https?:\/\/github\.com\/([^/]+)\/([^/]+)(?:\/tree\/([^/]+)(?:\/(.+))?)?$/,
1175
- /^([^/]+)\/([^/]+)(?:#(.+))?$/,
1175
+ /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\/tree\/([^/]+)(?:\/(.+))?)?$/,
1176
+ /^([^/]+)\/([^/@]+)@(.+)$/,
1177
+ // owner/repo@commit (must come before # pattern)
1178
+ /^([^/]+)\/([^/#]+)(?:#(.+))?$/
1176
1179
  // owner/repo#branch
1177
- /^([^/]+)\/([^/]+)@(.+)$/
1178
- // owner/repo@commit
1179
1180
  ];
1180
1181
  function parseGitHubUrl(input) {
1181
1182
  input = input.replace(/\/$/, "");
@@ -1186,7 +1187,7 @@ function parseGitHubUrl(input) {
1186
1187
  const repo = match[2].replace(/\.git$/, "");
1187
1188
  const branch = match[3] || "main";
1188
1189
  const commitOrPath = match[4] || match[3];
1189
- const path14 = match[5] || void 0;
1190
+ const path14 = match[4] || void 0;
1190
1191
  return {
1191
1192
  owner,
1192
1193
  repo,
@@ -1437,7 +1438,7 @@ import { join as join2 } from "path";
1437
1438
  import { fileURLToPath } from "url";
1438
1439
  async function publishSkill(skillName, options) {
1439
1440
  const __dirname4 = fileURLToPath(new URL(".", import.meta.url));
1440
- const projectRoot = join2(__dirname4, "..", "..");
1441
+ const projectRoot = join2(__dirname4, "..");
1441
1442
  const skillDir = join2(projectRoot, "skills", skillName);
1442
1443
  console.log(`Publishing ${skillName}...`);
1443
1444
  if (!existsSync2(skillDir)) {
@@ -3288,4 +3289,16 @@ admin.command("access <skill> <level>").description("Set package access (public|
3288
3289
  process.exit(1);
3289
3290
  }
3290
3291
  });
3291
- program.parse();
3292
+ var hasArgs = process.argv.slice(2).length > 0;
3293
+ if (!hasArgs) {
3294
+ const port = 18770;
3295
+ setTimeout(() => {
3296
+ try {
3297
+ execSync3(`start http://localhost:${port}`, { timeout: 5e3 });
3298
+ } catch {
3299
+ }
3300
+ }, 1500);
3301
+ startGuiServer(port);
3302
+ } else {
3303
+ program.parse();
3304
+ }
package/gui/app.js CHANGED
@@ -601,6 +601,31 @@ function applyI18nToStaticElements() {
601
601
  if (refreshAdmin) refreshAdmin.innerHTML = `🔄 ${t('btn.refresh')}`;
602
602
  if (updateAll) updateAll.innerHTML = `🔄 ${t('btn.updateAll')}`;
603
603
  if (backBtn) backBtn.innerHTML = `← ${t('nav.back')}`;
604
+
605
+ // Upload 视图静态文本
606
+ const uploadDropzoneText = document.getElementById('upload-dropzone-text');
607
+ const uploadDropzoneHint = document.getElementById('upload-dropzone-hint');
608
+ const uploadSelectBtn = document.getElementById('upload-select-btn');
609
+ const uploadSkillNameLabel = document.getElementById('upload-skill-name-label');
610
+ const uploadSkillNameInput = document.getElementById('upload-skill-name');
611
+ const uploadSubmitBtn = document.getElementById('upload-submit-btn');
612
+ const uploadActionPublish = document.getElementById('upload-action-publish');
613
+ const uploadActionInstall = document.getElementById('upload-action-install');
614
+ const uploadActionBoth = document.getElementById('upload-action-both');
615
+ const uploadActionDiscard = document.getElementById('upload-action-discard');
616
+ const uploadProgressText = document.getElementById('upload-progress-text');
617
+
618
+ if (uploadDropzoneText) uploadDropzoneText.textContent = t('upload.dropzoneText');
619
+ if (uploadDropzoneHint) uploadDropzoneHint.textContent = t('upload.dropzoneHint');
620
+ if (uploadSelectBtn) uploadSelectBtn.textContent = t('upload.chooseFile');
621
+ if (uploadSkillNameLabel) uploadSkillNameLabel.textContent = t('upload.skillNameLabel');
622
+ if (uploadSkillNameInput) uploadSkillNameInput.placeholder = t('upload.skillNamePlaceholder');
623
+ if (uploadSubmitBtn) uploadSubmitBtn.innerHTML = t('upload.uploadParse');
624
+ if (uploadActionPublish) uploadActionPublish.innerHTML = t('upload.actionPublish');
625
+ if (uploadActionInstall) uploadActionInstall.innerHTML = t('upload.actionInstall');
626
+ if (uploadActionBoth) uploadActionBoth.innerHTML = t('upload.actionBoth');
627
+ if (uploadActionDiscard) uploadActionDiscard.innerHTML = t('upload.actionDiscard');
628
+ if (uploadProgressText) uploadProgressText.textContent = t('upload.processing');
604
629
  }
605
630
 
606
631
  // -----------------------------------------------------------------------------
package/gui/index.html CHANGED
@@ -104,13 +104,13 @@
104
104
  <div id="upload-phase1" class="upload-phase">
105
105
  <div class="upload-dropzone" id="upload-dropzone">
106
106
  <div class="upload-dropzone-icon">📦</div>
107
- <p class="upload-dropzone-text">Drop a skill .zip file here, or click to select</p>
108
- <p class="upload-dropzone-hint">The zip should contain SKILL.md and optionally package.json</p>
107
+ <p class="upload-dropzone-text" id="upload-dropzone-text">Drop a skill .zip file here, or click to select</p>
108
+ <p class="upload-dropzone-hint" id="upload-dropzone-hint">The zip should contain SKILL.md and optionally package.json</p>
109
109
  <input type="file" id="upload-file-input" accept=".zip" style="display:none">
110
110
  <button id="upload-select-btn" class="btn btn-primary" style="margin-top:12px;">Choose File</button>
111
111
  </div>
112
112
  <div class="upload-skill-name-input">
113
- <label for="upload-skill-name">Skill Name</label>
113
+ <label for="upload-skill-name" id="upload-skill-name-label">Skill Name</label>
114
114
  <input type="text" id="upload-skill-name" placeholder="Auto-detected from zip, or override here">
115
115
  </div>
116
116
  <button id="upload-submit-btn" class="btn btn-success" disabled style="align-self:center;margin-top:8px;">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itismyskillmarket",
3
- "version": "1.3.27",
3
+ "version": "1.3.30",
4
4
  "description": "Cross-platform skill manager for AI coding tools",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,7 +9,8 @@
9
9
  "scripts": {
10
10
  "build": "tsup",
11
11
  "dev": "tsup --watch",
12
- "test": "vitest"
12
+ "test": "vitest",
13
+ "build:exe": "node scripts/build-exe.mjs"
13
14
  },
14
15
  "dependencies": {
15
16
  "adm-zip": "^0.5.17",
@@ -18,6 +19,8 @@
18
19
  },
19
20
  "devDependencies": {
20
21
  "@types/fs-extra": "^11.0.4",
22
+ "@yao-pkg/pkg": "^6.19.0",
23
+ "postject": "^1.0.0-alpha.6",
21
24
  "tsup": "^8.0.0",
22
25
  "typescript": "^5.3.0",
23
26
  "vitest": "^1.2.0"