skills-manager-cli 2026.8.26-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/LICENSE +21 -0
- package/README.md +103 -0
- package/README.zh-CN.md +103 -0
- package/dist/cli/main.js +261 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/catalog/agent-catalog.json +1134 -0
- package/dist/core/catalog/evaluate-detection.js +41 -0
- package/dist/core/catalog/evaluate-detection.js.map +1 -0
- package/dist/core/catalog/extract.js +388 -0
- package/dist/core/catalog/extract.js.map +1 -0
- package/dist/core/catalog/resolve-path.js +29 -0
- package/dist/core/catalog/resolve-path.js.map +1 -0
- package/dist/core/catalog/validate-snapshot.js +117 -0
- package/dist/core/catalog/validate-snapshot.js.map +1 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/model/catalog.js +7 -0
- package/dist/core/model/catalog.js.map +1 -0
- package/dist/core/model/index.js +7 -0
- package/dist/core/model/index.js.map +1 -0
- package/dist/core/ports/filesystem.js +2 -0
- package/dist/core/ports/filesystem.js.map +1 -0
- package/dist/core/ports/git.js +2 -0
- package/dist/core/ports/git.js.map +1 -0
- package/dist/core/ports/process-runner.js +2 -0
- package/dist/core/ports/process-runner.js.map +1 -0
- package/dist/core/services/activity-service.js +36 -0
- package/dist/core/services/activity-service.js.map +1 -0
- package/dist/core/services/adopt-service.js +7 -0
- package/dist/core/services/adopt-service.js.map +1 -0
- package/dist/core/services/archive-service.js +35 -0
- package/dist/core/services/archive-service.js.map +1 -0
- package/dist/core/services/backup-service.js +94 -0
- package/dist/core/services/backup-service.js.map +1 -0
- package/dist/core/services/catalog-service.js +123 -0
- package/dist/core/services/catalog-service.js.map +1 -0
- package/dist/core/services/distribute-service.js +474 -0
- package/dist/core/services/distribute-service.js.map +1 -0
- package/dist/core/services/doctor-service.js +75 -0
- package/dist/core/services/doctor-service.js.map +1 -0
- package/dist/core/services/index.js +54 -0
- package/dist/core/services/index.js.map +1 -0
- package/dist/core/services/init-service.js +234 -0
- package/dist/core/services/init-service.js.map +1 -0
- package/dist/core/services/install-service.js +73 -0
- package/dist/core/services/install-service.js.map +1 -0
- package/dist/core/services/migration-service.js +102 -0
- package/dist/core/services/migration-service.js.map +1 -0
- package/dist/core/services/package-service.js +33 -0
- package/dist/core/services/package-service.js.map +1 -0
- package/dist/core/services/registry-service.js +133 -0
- package/dist/core/services/registry-service.js.map +1 -0
- package/dist/core/services/skill-home-resolver.js +33 -0
- package/dist/core/services/skill-home-resolver.js.map +1 -0
- package/dist/core/services/skill-home-service.js +35 -0
- package/dist/core/services/skill-home-service.js.map +1 -0
- package/dist/core/services/source-service.js +109 -0
- package/dist/core/services/source-service.js.map +1 -0
- package/dist/core/services/update-service.js +93 -0
- package/dist/core/services/update-service.js.map +1 -0
- package/dist/core/services/view-service.js +45 -0
- package/dist/core/services/view-service.js.map +1 -0
- package/dist/dashboard/server/main.js +427 -0
- package/dist/dashboard/server/main.js.map +1 -0
- package/dist/dashboard/server/render-markdown.js +75 -0
- package/dist/dashboard/server/render-markdown.js.map +1 -0
- package/dist/dashboard/server/skill-file.js +129 -0
- package/dist/dashboard/server/skill-file.js.map +1 -0
- package/dist/dashboard-web/assets/index-B43GPIpA.js +13 -0
- package/dist/dashboard-web/assets/index-CzbkHV2A.css +1 -0
- package/dist/dashboard-web/index.html +13 -0
- package/dist/infra/fs-skill-home.js +87 -0
- package/dist/infra/fs-skill-home.js.map +1 -0
- package/dist/infra/git-cli.js +36 -0
- package/dist/infra/git-cli.js.map +1 -0
- package/dist/infra/index.js +5 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/infra/runtime.js +23 -0
- package/dist/infra/runtime.js.map +1 -0
- package/dist/infra/shell-runner.js +18 -0
- package/dist/infra/shell-runner.js.map +1 -0
- package/dist/shared/errors.js +17 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/result.js +17 -0
- package/dist/shared/result.js.map +1 -0
- package/dist/shared/validation.js +92 -0
- package/dist/shared/validation.js.map +1 -0
- package/docs/CLI.md +75 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.recent-paths[data-v-269197d9]{border-bottom:1px solid var(--line2);padding:.75rem 1rem}.recent-label[data-v-269197d9]{color:var(--fg3);text-transform:uppercase;letter-spacing:.08em;margin-bottom:.5rem;font-size:.75rem;font-weight:600}.recent-list[data-v-269197d9]{flex-wrap:wrap;gap:.5rem;display:flex;overflow:auto hidden}.recent-item[data-v-269197d9]{background:var(--line2);border:1px solid var(--line);color:var(--fg2);cursor:pointer;white-space:nowrap;border-radius:4px;padding:.4rem .75rem;font-size:.8rem;transition:background-color .2s}.recent-item[data-v-269197d9]:hover{background:var(--line)}.browser-loading[data-v-269197d9],.browser-error[data-v-269197d9]{text-align:center;color:var(--fg3);justify-content:center;align-items:center;min-height:200px;padding:1rem;display:flex}.browser-error[data-v-269197d9]{color:var(--danger)}.browser-content[data-v-269197d9]{flex-direction:column;gap:1rem;min-height:300px;max-height:60vh;padding:1rem;display:flex}.breadcrumb-row[data-v-269197d9]{flex-wrap:wrap;align-items:center;gap:.5rem;display:flex}.breadcrumb-btn[data-v-269197d9]{background:var(--line2);border:1px solid var(--line);cursor:pointer;color:var(--fg2);border-radius:4px;padding:.4rem .8rem;font-size:.875rem}.breadcrumb-btn[data-v-269197d9]:hover{background:var(--line)}.breadcrumb-path[data-v-269197d9]{word-break:break-all;flex:1;align-items:center;font-size:.875rem;display:flex;overflow-x:auto}.breadcrumb-part[data-v-269197d9]{align-items:center;display:flex}.breadcrumb-sep[data-v-269197d9]{color:var(--fg3);margin:0 .25rem}.breadcrumb-text[data-v-269197d9]{color:var(--accent);cursor:pointer;font:inherit;background:0 0;border:none;padding:0}.breadcrumb-text[data-v-269197d9]:hover{text-decoration:underline}.directory-list[data-v-269197d9]{flex-direction:column;flex:1;gap:.5rem;display:flex;overflow-y:auto}.dir-entry[data-v-269197d9],.empty-hint[data-v-269197d9]{border:1px solid var(--line2);cursor:pointer;text-align:left;color:var(--fg);background:0 0;border-radius:4px;align-items:center;gap:.5rem;padding:.5rem .75rem;font-size:.875rem;transition:background-color .2s;display:flex}.dir-entry[data-v-269197d9]:hover{background:var(--line2)}.empty-hint[data-v-269197d9]{cursor:default;color:var(--fg3)}.dir-icon[data-v-269197d9]{flex-shrink:0}.dir-name[data-v-269197d9]{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.sheet-foot[data-v-269197d9]{border-top:1px solid var(--line);justify-content:flex-end;gap:.5rem;padding:1rem;display:flex}.project-dropdown[data-v-9756024d]{width:100%;position:relative}.dropdown-input[data-v-9756024d]{border:1px solid var(--line);background:var(--bg);width:100%;color:var(--fg);border-radius:4px;outline:none;padding:.5rem .75rem;font-size:.875rem;transition:border-color .2s}.dropdown-input[data-v-9756024d]:focus{border-color:var(--accent)}.dropdown-overlay[data-v-9756024d]{z-index:98;position:fixed;inset:0}.dropdown-menu[data-v-9756024d]{background:var(--bg);border:1px solid var(--line);z-index:99;border-radius:4px;flex-direction:column;max-height:300px;margin-top:.25rem;display:flex;position:absolute;top:100%;left:0;right:0;overflow-y:auto;box-shadow:0 4px 12px #00000026}.dropdown-browse[data-v-9756024d]{background:var(--line2);border:none;border-bottom:1px solid var(--line);cursor:pointer;color:var(--fg);align-items:center;gap:.5rem;padding:.75rem 1rem;font-size:.875rem;transition:background-color .2s;display:flex}.dropdown-browse[data-v-9756024d]:hover{background:var(--line)}.dropdown-items[data-v-9756024d]{flex-direction:column;display:flex}.dropdown-section[data-v-9756024d]{border-bottom:1px solid var(--line2)}.dropdown-section[data-v-9756024d]:last-child{border-bottom:none}.section-header[data-v-9756024d]{color:var(--fg3);text-transform:uppercase;letter-spacing:.08em;background:var(--bg);padding:.5rem 1rem;font-size:.7rem;font-weight:600}.dropdown-item[data-v-9756024d]{cursor:pointer;text-align:left;color:var(--fg);background:0 0;border:none;align-items:center;gap:.75rem;padding:.75rem 1rem;font-size:.875rem;transition:background-color .15s;display:flex}.dropdown-item[data-v-9756024d]:hover,.dropdown-item.selected[data-v-9756024d]{background:var(--line2)}.item-icon[data-v-9756024d]{flex-shrink:0;font-size:1rem}.item-label[data-v-9756024d]{text-overflow:ellipsis;white-space:nowrap;flex-shrink:0;min-width:120px;font-weight:500;overflow:hidden}.item-path[data-v-9756024d]{color:var(--fg3);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:.75rem;overflow:hidden}.dropdown-empty[data-v-9756024d]{text-align:center;color:var(--fg3);padding:1rem;font-size:.875rem}.project-input-row[data-v-f4078e0b]{padding:0 0 1rem}.init-choice[data-v-c0fd2434]{text-overflow:ellipsis;vertical-align:bottom;max-width:22rem;margin-left:.5rem;overflow:hidden}:root{--bg:#fafafa;--fg:#18181b;--fg2:#71717a;--fg3:#a1a1aa;--line:#e4e4e7;--line2:#f4f4f5;--accent:#2563eb;--warn:#d97706;--danger:#dc2626;--ok:#16a34a;font-size:15px}:root[data-theme=dark]{--bg:#101013;--fg:#ededef;--fg2:#9d9da7;--fg3:#63636e;--line:#26262c;--line2:#1d1d22;--accent:#3b82f6;--warn:#f59e0b;--danger:#ef4444;--ok:#22c55e}*{box-sizing:border-box;margin:0;padding:0}html{scrollbar-gutter:stable}body{background:var(--bg);color:var(--fg);font-family:-apple-system,PingFang SC,Segoe UI,sans-serif}button{font:inherit;cursor:pointer;color:inherit;background:0 0;border:none}input{font:inherit;color:inherit}.mono{font-family:ui-monospace,SF Mono,Menlo,monospace}.page{max-width:720px;margin:0 auto;padding:56px 24px 80px}.head{align-items:baseline;gap:12px;margin-bottom:6px;display:flex}.head h1{letter-spacing:-.01em;font-size:22px;font-weight:700}.head .links{color:var(--fg2);gap:16px;margin-left:auto;font-size:13.5px;display:flex}.head .links button:hover{color:var(--fg)}.sub{color:var(--fg3);margin-bottom:18px;font-size:13px}.search-line{border-bottom:1px solid var(--line);margin-bottom:8px}.search-line input{background:0 0;border:none;outline:none;width:100%;padding:8px 2px;font-size:14.5px}.search-line input::placeholder{color:var(--fg3)}.update-line{color:var(--fg2);padding:10px 2px;font-size:14px}.update-line b{color:var(--fg);font-weight:600}.update-line button{color:var(--accent);margin-left:12px;font-weight:600}.update-line button:disabled{opacity:.6;cursor:default}.item{border-bottom:1px solid var(--line2);align-items:baseline;gap:10px;padding:13px 2px;display:flex}.item .cb{flex:none;align-self:center;width:22px}.item .cb input{width:15px;height:15px;accent-color:var(--accent);cursor:pointer;opacity:0;transition:opacity .12s}.item:hover .cb input,body.selecting .item .cb input{opacity:1}.item .main{flex:1;min-width:0}.item .l1{align-items:baseline;gap:10px;display:flex}.item .name{font-size:15px;font-weight:600}.item .meta{color:var(--fg3);white-space:nowrap;margin-left:auto;font-size:12.5px}.item .meta.updatable{color:var(--accent);font-weight:600}.item .meta.warning{color:var(--warn)}.item .desc{color:var(--fg2);white-space:nowrap;text-overflow:ellipsis;margin-top:3px;font-size:13.5px;overflow:hidden}.item .hover-acts{color:var(--fg2);align-self:center;gap:12px;font-size:13px;display:none}.item:hover .hover-acts,.item.menu-open .hover-acts{display:flex}.item:hover .meta{display:none}.hover-acts button:hover{color:var(--fg)}.hover-acts .upd{color:var(--accent);font-weight:600}.empty,.error{color:var(--fg2);padding:48px 2px}.empty .title,.error .title{color:var(--fg);margin-bottom:6px;font-size:16px;font-weight:600}.empty .hint{color:var(--fg3);font-size:13.5px}.error .retry{color:var(--accent);margin-top:10px;font-size:13.5px;font-weight:600}.sheet-overlay{background:color-mix(in srgb, var(--bg) 55%, transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:500;justify-content:center;align-items:flex-start;padding:8vh 24px 24px;display:flex;position:fixed;inset:0;overflow-y:auto}.sheet{background:var(--bg);border:1px solid var(--line);border-radius:12px;width:640px;max-width:100%;padding:20px 22px 18px;box-shadow:0 18px 48px #00000024}.sheet-head{align-items:baseline;margin-bottom:12px;display:flex}.sheet-head h2{font-size:17px;font-weight:650}.sheet-close{color:var(--fg3);margin-left:auto;font-size:13px}.sheet-close:hover{color:var(--fg)}.sheet-foot{border-top:1px solid var(--line2);align-items:center;gap:14px;margin-top:16px;padding-top:12px;display:flex}.sheet-foot .picker-count{color:var(--fg3);margin-right:auto;font-size:13px}.text-btn{color:var(--fg2);font-size:13.5px}.text-btn:hover{color:var(--fg)}.primary-btn{background:var(--accent);color:#fff;border-radius:8px;padding:7px 16px;font-size:13.5px;font-weight:600}.primary-btn:disabled{opacity:.45;cursor:default}.primary-btn.danger{background:var(--danger)}.confirm-body{color:var(--fg2);font-size:14px;line-height:1.6}.confirm-skills{color:var(--fg3);margin-top:8px;font-size:13px}.scope-row{gap:18px;margin-bottom:10px;font-size:14px;display:flex}.scope-row button{color:var(--fg2);border-bottom:2px solid #0000;padding-bottom:3px}.scope-row button.on{color:var(--fg);border-bottom-color:var(--accent);font-weight:600}.field-line input{border:none;border-bottom:1px solid var(--line);background:0 0;outline:none;width:100%;margin-bottom:10px;padding:7px 2px;font-size:14px}.field-line input::placeholder{color:var(--fg3)}.agent-list{max-height:46vh;margin:6px 0 4px;overflow-y:auto}.agent-list h3{color:var(--fg3);text-transform:uppercase;letter-spacing:.08em;margin:12px 0 6px;font-size:12px;font-weight:600}.agent-row{cursor:pointer;align-items:baseline;gap:10px;padding:5px 2px;font-size:13.5px;display:flex}.agent-row input{accent-color:var(--accent);align-self:center}.agent-row .agent-id{min-width:130px}.agent-row .agent-label{color:var(--fg2);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.agent-row.invalid{color:var(--fg3);cursor:default}.agent-row.invalid .agent-label{color:var(--fg3);font-style:italic}.quick-row{gap:14px;margin:-4px 0 6px;display:flex}.quick-row .text-btn{color:var(--fg3);padding:0;font-size:12.5px}.quick-row .text-btn:hover{color:var(--accent)}.family{margin-bottom:4px}.family-all{color:var(--fg3);padding:2px 0;font-size:12.5px}.family-all:hover{color:var(--accent)}.picker-hint,.picker-error{color:var(--fg3);margin:8px 0;font-size:13px}.picker-error{color:var(--danger)}.mode-row{align-items:baseline;gap:14px;margin-top:10px;font-size:13.5px;display:flex}.mode-row .mode-label{color:var(--fg3)}.mode-row button{color:var(--fg2);border-bottom:2px solid #0000;padding-bottom:2px}.mode-row button.on{color:var(--fg);border-bottom-color:var(--accent);font-weight:600}.row-menu{position:relative}.row-menu .more{color:var(--fg3);padding:0 4px}.row-menu .more:hover{color:var(--fg)}.menu-backdrop{z-index:600;position:fixed;inset:0}.menu{z-index:601;background:var(--bg);border:1px solid var(--line);border-radius:10px;flex-direction:column;min-width:180px;padding:6px;display:flex;position:absolute;top:100%;right:0;box-shadow:0 10px 28px #00000024}.menu button{text-align:left;color:var(--fg);border-radius:6px;padding:7px 12px;font-size:13.5px}.menu button:hover{background:var(--line2)}.notice{margin:0 0 6px;font-size:13.5px}.notice.ok{color:var(--ok)}.notice.error{color:var(--danger)}.selection-bar{background:var(--fg);color:var(--bg);z-index:400;border-radius:12px;align-items:center;gap:14px;padding:10px 16px;font-size:14px;display:flex;position:fixed;bottom:24px;left:50%;transform:translate(-50%);box-shadow:0 12px 32px #00000040}.selection-bar .count{font-weight:600}.selection-bar .act{border-radius:7px;padding:5px 12px}.selection-bar .act:hover:not(:disabled){background:#80808040}.selection-bar .act:disabled{opacity:.5;cursor:default}.selection-bar .act.remove{color:#fca5a5}.selection-bar .esc{opacity:.6;font-size:12px}.existing-mark{color:var(--warn);margin-left:6px;font-size:12px;font-style:normal}.overwrite-ask{border:1px solid var(--line);color:var(--fg2);border-radius:10px;margin-top:12px;padding:12px;font-size:13.5px}.overwrite-ask .overwrite-actions{justify-content:flex-end;gap:14px;margin-top:10px;display:flex}.drawer-overlay{background:color-mix(in srgb, var(--bg) 45%, transparent);z-index:450;position:fixed;inset:0}.log-drawer{background:var(--bg);border-left:1px solid var(--line);z-index:451;width:min(420px,92vw);padding:20px 22px;position:fixed;top:0;bottom:0;right:0;overflow-y:auto;box-shadow:-12px 0 32px #0000001f}.log-drawer .sheet-head{margin-bottom:10px}.log-line{border-bottom:1px solid var(--line2);align-items:baseline;gap:10px;padding:8px 0;font-size:13px;display:flex}.log-time{color:var(--fg3);white-space:nowrap;font-variant-numeric:tabular-nums}.log-action{color:var(--fg2);white-space:nowrap}.log-summary{color:var(--fg2);text-overflow:ellipsis;overflow:hidden}.sheet.wide{flex-direction:column;width:min(92vw,1080px);height:calc(92vh - 24px);display:flex}.sheet.wide .sheet-head{flex:none}.sheet-head .preview-desc{color:var(--fg3);text-overflow:ellipsis;white-space:nowrap;margin-left:12px;margin-right:auto;font-size:13px;overflow:hidden}.preview-body{flex:1;min-height:0;display:flex}.preview-tree{border-right:1px solid var(--line2);flex:none;width:240px;padding:6px 0 16px;overflow-y:auto}.preview-tree-row{text-align:left;width:100%;color:var(--fg2);white-space:nowrap;text-overflow:ellipsis;padding:3px 10px;font-size:12.5px;display:block;overflow:hidden}.preview-tree-row.dir{color:var(--fg3);cursor:default;font-weight:600}.preview-tree-row:not(.dir):hover{color:var(--fg)}.preview-tree-row.on{color:var(--accent);background:var(--line2)}.preview-content{flex:1;min-width:0;padding:0 20px;overflow-y:auto}.item .name.preview-link:hover{text-decoration:underline}.preview-md{max-width:78ch;color:var(--fg);padding:6px 2px 28px;font-size:14.5px;line-height:1.75}.preview-md h1,.preview-md h2,.preview-md h3,.preview-md h4{margin:1.5em 0 .5em;line-height:1.3}.preview-md h1{font-size:1.5em}.preview-md h2{font-size:1.28em}.preview-md h3{font-size:1.12em}.preview-md h4{font-size:1em}.preview-md h1:first-child,.preview-md h2:first-child,.preview-md h3:first-child{margin-top:.2em}.preview-md p{margin:.6em 0}.preview-md a{color:var(--accent)}.preview-md code{background:var(--line2);border-radius:5px;padding:1.5px 5px;font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:.88em}.preview-md pre{margin:.9em 0;overflow-x:auto}.preview-md pre code{background:0 0;padding:0;font-size:13px;line-height:1.65}.preview-md ul,.preview-md ol{margin:.6em 0;padding-left:1.5em}.preview-md li{margin:.25em 0}.preview-md blockquote{border-left:3px solid var(--line);color:var(--fg2);margin:.9em 0;padding:.1em 0 .1em 14px}.preview-md hr{border:none;border-top:1px solid var(--line);margin:1.6em 0}.preview-md table{border-collapse:collapse;margin:.9em 0;font-size:.95em}.preview-md th,.preview-md td{border:1px solid var(--line);text-align:left;padding:5px 10px}.preview-md img{max-width:100%}.preview-md .shiki,.preview-md .shiki span,.preview-code .shiki,.preview-code .shiki span{color:var(--shiki-light);background-color:var(--shiki-light-bg)}[data-theme=dark] .preview-md .shiki,[data-theme=dark] .preview-md .shiki span,[data-theme=dark] .preview-code .shiki,[data-theme=dark] .preview-code .shiki span{color:var(--shiki-dark);background-color:var(--shiki-dark-bg)}.preview-md .shiki,.preview-code .shiki{border-radius:8px;padding:12px 14px;font-size:13px;line-height:1.65}.preview-code{padding:8px 0 28px}.preview-source{color:var(--fg2);white-space:pre-wrap;word-break:break-word;padding:6px 2px 28px;font-size:13px;line-height:1.65}.preview-hint{color:var(--fg3);font-size:13px}.preview-truncated{color:var(--warn)}.preview-error{color:var(--danger);font-size:13.5px}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>技能库 · Skills Manager</title>
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-B43GPIpA.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CzbkHV2A.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="app"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync, appendFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export class NodeFileSystem {
|
|
4
|
+
exists(filePath) {
|
|
5
|
+
return existsSync(filePath);
|
|
6
|
+
}
|
|
7
|
+
readText(filePath) {
|
|
8
|
+
return readFileSync(filePath, 'utf8');
|
|
9
|
+
}
|
|
10
|
+
writeText(filePath, contents) {
|
|
11
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
12
|
+
writeFileSync(filePath, contents);
|
|
13
|
+
}
|
|
14
|
+
appendText(filePath, contents) {
|
|
15
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
16
|
+
appendFileSync(filePath, contents);
|
|
17
|
+
}
|
|
18
|
+
readDirectory(dirPath) {
|
|
19
|
+
return readdirSync(dirPath, { withFileTypes: true }).map((entry) => ({ name: entry.name, kind: this.direntKind(entry) }));
|
|
20
|
+
}
|
|
21
|
+
kind(filePath) {
|
|
22
|
+
try {
|
|
23
|
+
const st = lstatSync(filePath);
|
|
24
|
+
if (st.isSymbolicLink())
|
|
25
|
+
return 'symlink';
|
|
26
|
+
if (st.isDirectory())
|
|
27
|
+
return 'directory';
|
|
28
|
+
if (st.isFile())
|
|
29
|
+
return 'file';
|
|
30
|
+
return 'other';
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return 'missing';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
targetKind(filePath) {
|
|
37
|
+
try {
|
|
38
|
+
const st = statSync(filePath);
|
|
39
|
+
if (st.isDirectory())
|
|
40
|
+
return 'directory';
|
|
41
|
+
if (st.isFile())
|
|
42
|
+
return 'file';
|
|
43
|
+
return 'other';
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return 'missing';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
makeDirectory(dirPath) {
|
|
50
|
+
mkdirSync(dirPath, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
removeFileOrSymlink(filePath) {
|
|
53
|
+
rmSync(filePath, { force: true });
|
|
54
|
+
}
|
|
55
|
+
removeTree(filePath) {
|
|
56
|
+
rmSync(filePath, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
copyDirectoryContents(sourceDir, destinationDir) {
|
|
59
|
+
mkdirSync(destinationDir, { recursive: true });
|
|
60
|
+
rmSync(destinationDir, { recursive: true, force: true });
|
|
61
|
+
mkdirSync(destinationDir, { recursive: true });
|
|
62
|
+
cpSync(sourceDir, destinationDir, { recursive: true, dereference: false, force: true, verbatimSymlinks: true });
|
|
63
|
+
}
|
|
64
|
+
move(source, destination) {
|
|
65
|
+
mkdirSync(path.dirname(destination), { recursive: true });
|
|
66
|
+
renameSync(source, destination);
|
|
67
|
+
}
|
|
68
|
+
symlink(target, filePath) {
|
|
69
|
+
symlinkSync(target, filePath);
|
|
70
|
+
}
|
|
71
|
+
readlink(filePath) {
|
|
72
|
+
return readlinkSync(filePath);
|
|
73
|
+
}
|
|
74
|
+
direntKind(entry) {
|
|
75
|
+
if (entry.isSymbolicLink())
|
|
76
|
+
return 'symlink';
|
|
77
|
+
if (entry.isDirectory())
|
|
78
|
+
return 'directory';
|
|
79
|
+
if (entry.isFile())
|
|
80
|
+
return 'file';
|
|
81
|
+
return 'other';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export function createNodeFileSystem() {
|
|
85
|
+
return new NodeFileSystem();
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=fs-skill-home.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-skill-home.js","sourceRoot":"","sources":["../../src/infra/fs-skill-home.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACtL,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,OAAO,cAAc;IACzB,MAAM,CAAC,QAAgB;QACrB,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED,QAAQ,CAAC,QAAgB;QACvB,OAAO,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,SAAS,CAAC,QAAgB,EAAE,QAAgB;QAC1C,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,UAAU,CAAC,QAAgB,EAAE,QAAgB;QAC3C,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,aAAa,CAAC,OAAe;QAC3B,OAAO,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5H,CAAC;IAED,IAAI,CAAC,QAAgB;QACnB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC/B,IAAI,EAAE,CAAC,cAAc,EAAE;gBAAE,OAAO,SAAS,CAAC;YAC1C,IAAI,EAAE,CAAC,WAAW,EAAE;gBAAE,OAAO,WAAW,CAAC;YACzC,IAAI,EAAE,CAAC,MAAM,EAAE;gBAAE,OAAO,MAAM,CAAC;YAC/B,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,UAAU,CAAC,QAAgB;QACzB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,EAAE,CAAC,WAAW,EAAE;gBAAE,OAAO,WAAW,CAAC;YACzC,IAAI,EAAE,CAAC,MAAM,EAAE;gBAAE,OAAO,MAAM,CAAC;YAC/B,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,aAAa,CAAC,OAAe;QAC3B,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,mBAAmB,CAAC,QAAgB;QAClC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,UAAU,CAAC,QAAgB;QACzB,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,qBAAqB,CAAC,SAAiB,EAAE,cAAsB;QAC7D,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;IAClH,CAAC;IAED,IAAI,CAAC,MAAc,EAAE,WAAmB;QACtC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,CAAC,MAAc,EAAE,QAAgB;QACtC,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,QAAQ,CAAC,QAAgB;QACvB,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAEO,UAAU,CAAC,KAA+B;QAChD,IAAI,KAAK,CAAC,cAAc,EAAE;YAAE,OAAO,SAAS,CAAC;QAC7C,IAAI,KAAK,CAAC,WAAW,EAAE;YAAE,OAAO,WAAW,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM,EAAE;YAAE,OAAO,MAAM,CAAC;QAClC,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,cAAc,EAAE,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ShellRunner } from './shell-runner.js';
|
|
2
|
+
export class GitCli {
|
|
3
|
+
runner;
|
|
4
|
+
constructor(runner = new ShellRunner()) {
|
|
5
|
+
this.runner = runner;
|
|
6
|
+
}
|
|
7
|
+
clone(repoUrl, destination) {
|
|
8
|
+
this.runner.runOrThrow('git', ['clone', repoUrl, destination]);
|
|
9
|
+
}
|
|
10
|
+
checkout(repoDir, ref) {
|
|
11
|
+
this.runner.runOrThrow('git', ['-C', repoDir, 'checkout', ref]);
|
|
12
|
+
}
|
|
13
|
+
revParseHead(repoDir) {
|
|
14
|
+
return this.runner.runOrThrow('git', ['-C', repoDir, 'rev-parse', 'HEAD']);
|
|
15
|
+
}
|
|
16
|
+
listRemoteHeads(repoUrl) {
|
|
17
|
+
const output = this.runner.runOrThrow('git', ['ls-remote', '--heads', repoUrl]);
|
|
18
|
+
return output.split('\n')
|
|
19
|
+
.map((line) => line.match(/refs\/heads\/(.+)$/)?.[1])
|
|
20
|
+
.filter((value) => Boolean(value));
|
|
21
|
+
}
|
|
22
|
+
statusShort(cwd) {
|
|
23
|
+
const result = this.runner.run('git', ['-C', cwd, 'status', '--short']);
|
|
24
|
+
return result.status === 0 ? result.stdout.trim() : '';
|
|
25
|
+
}
|
|
26
|
+
log(cwd, maxCount) {
|
|
27
|
+
const result = this.runner.run('git', ['-C', cwd, 'log', `--max-count=${maxCount}`, '--date=iso-strict', '--pretty=format:%H%x09%cI%x09%s']);
|
|
28
|
+
if (result.status !== 0)
|
|
29
|
+
return [];
|
|
30
|
+
return result.stdout.split('\n').filter(Boolean).map((line) => {
|
|
31
|
+
const [hash, timestamp, ...subject] = line.split('\t');
|
|
32
|
+
return { hash, timestamp, subject: subject.join('\t') };
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=git-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-cli.js","sourceRoot":"","sources":["../../src/infra/git-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,OAAO,MAAM;IACY,MAAM;IAAnC,YAA6B,MAAM,GAAG,IAAI,WAAW,EAAE;sBAA1B,MAAM;IAAuB,CAAC;IAE3D,KAAK,CAAC,OAAe,EAAE,WAAmB;QACxC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,QAAQ,CAAC,OAAe,EAAE,GAAW;QACnC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,YAAY,CAAC,OAAe;QAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,eAAe,CAAC,OAAe;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAChF,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;aACtB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;aACpD,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,WAAW,CAAC,GAAW;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;QACxE,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,QAAgB;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe,QAAQ,EAAE,EAAE,mBAAmB,EAAE,iCAAiC,CAAC,CAAC,CAAC;QAC7I,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAC5D,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { NodeFileSystem, createNodeFileSystem } from './fs-skill-home.js';
|
|
2
|
+
export { GitCli } from './git-cli.js';
|
|
3
|
+
export { ShellRunner } from './shell-runner.js';
|
|
4
|
+
export { createRuntimeServices, projectRootFromImportMeta } from './runtime.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/infra/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { createCoreServices } from '../core/index.js';
|
|
4
|
+
import { SkillHomeResolver } from '../core/services/skill-home-resolver.js';
|
|
5
|
+
import { NodeFileSystem } from './fs-skill-home.js';
|
|
6
|
+
import { GitCli } from './git-cli.js';
|
|
7
|
+
import { ShellRunner } from './shell-runner.js';
|
|
8
|
+
export function projectRootFromImportMeta(metaUrl) {
|
|
9
|
+
return path.resolve(path.dirname(fileURLToPath(metaUrl)), '..', '..');
|
|
10
|
+
}
|
|
11
|
+
export function createRuntimeServices(options = {}, projectRoot = process.cwd()) {
|
|
12
|
+
const fs = new NodeFileSystem();
|
|
13
|
+
const resolver = new SkillHomeResolver(fs);
|
|
14
|
+
const resolution = resolver.resolve({ explicitHome: options.home, cwd: options.cwd || process.cwd(), env: options.env || process.env });
|
|
15
|
+
const git = new GitCli();
|
|
16
|
+
const processRunner = new ShellRunner();
|
|
17
|
+
const env = options.env || process.env;
|
|
18
|
+
const userHome = options.userHome || env.SKILLS_MANAGER_USER_HOME;
|
|
19
|
+
const services = createCoreServices({ skillHomeRoot: resolution.root, projectRoot, fs, git, processRunner, userHome, env: options.env, catalogSnapshot: options.catalogSnapshot });
|
|
20
|
+
services.skillHome.ensure();
|
|
21
|
+
return { ...services, resolution };
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/infra/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAA4B,MAAM,yCAAyC,CAAC;AAEtG,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAUhD,MAAM,UAAU,yBAAyB,CAAC,OAAe;IACvD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,OAAO,GAAmB,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7F,MAAM,EAAE,GAAG,IAAI,cAAc,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxI,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAC;IACzB,MAAM,aAAa,GAAG,IAAI,WAAW,EAAE,CAAC;IACxC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,GAAG,CAAC,wBAAwB,CAAC;IAClE,MAAM,QAAQ,GAAG,kBAAkB,CAAC,EAAE,aAAa,EAAE,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACnL,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAwF,CAAC;AAC3H,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
export class ShellRunner {
|
|
3
|
+
run(command, args, options = {}) {
|
|
4
|
+
const result = spawnSync(command, args, { cwd: options.cwd, encoding: 'utf8', stdio: 'pipe' });
|
|
5
|
+
return {
|
|
6
|
+
status: result.status,
|
|
7
|
+
stdout: result.stdout || '',
|
|
8
|
+
stderr: result.stderr || '',
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
runOrThrow(command, args, options = {}) {
|
|
12
|
+
const result = this.run(command, args, options);
|
|
13
|
+
if (result.status !== 0)
|
|
14
|
+
throw new Error(`Command failed: ${command} ${args.join(' ')}\n${result.stderr || result.stdout}`);
|
|
15
|
+
return result.stdout.trim();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=shell-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-runner.js","sourceRoot":"","sources":["../../src/infra/shell-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,MAAM,OAAO,WAAW;IACtB,GAAG,CAAC,OAAe,EAAE,IAAc,EAAE,OAAO,GAAqB,EAAE;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/F,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;YAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;SAC5B,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,OAAe,EAAE,IAAc,EAAE,OAAO,GAAqB,EAAE;QACxE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAChD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5H,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class SkillsManagerError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
details;
|
|
4
|
+
constructor(code, message, details) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'SkillsManagerError';
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.details = details;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function errorCode(error) {
|
|
12
|
+
return error instanceof SkillsManagerError ? error.code : 'unexpected_error';
|
|
13
|
+
}
|
|
14
|
+
export function errorMessage(error) {
|
|
15
|
+
return error instanceof Error ? error.message : String(error);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,CAAS;IACb,OAAO,CAAW;IAE3B,YAAY,IAAY,EAAE,OAAe,EAAE,OAAiB;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,KAAK,YAAY,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { errorCode, errorMessage } from './errors.js';
|
|
2
|
+
export function ok(data) {
|
|
3
|
+
return { ok: true, data };
|
|
4
|
+
}
|
|
5
|
+
export function err(code, message, details) {
|
|
6
|
+
return { ok: false, error: { code, message, details } };
|
|
7
|
+
}
|
|
8
|
+
export function fromThrowable(fn) {
|
|
9
|
+
try {
|
|
10
|
+
return ok(fn());
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
const details = error instanceof Error && 'details' in error ? error.details : undefined;
|
|
14
|
+
return err(errorCode(error), errorMessage(error), details);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/shared/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMtD,MAAM,UAAU,EAAE,CAAI,IAAO;IAC3B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,OAAiB;IAClE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,aAAa,CAAI,EAAW;IAC1C,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,IAAI,SAAS,IAAI,KAAK,CAAC,CAAC,CAAE,KAA+B,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACpH,OAAO,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import YAML from 'yaml';
|
|
3
|
+
import { SkillsManagerError } from './errors.js';
|
|
4
|
+
import { LEGACY_CONSUMERS } from '../core/model/index.js';
|
|
5
|
+
export function assertSafeSkillName(name) {
|
|
6
|
+
if (!name || name === '.' || name === '..')
|
|
7
|
+
throw new SkillsManagerError('invalid_skill_name', `Invalid skill name: ${name}`);
|
|
8
|
+
if (name.includes('/') || name.includes('\\'))
|
|
9
|
+
throw new SkillsManagerError('invalid_skill_name', `Skill name must not contain path separators: ${name}`);
|
|
10
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(name)) {
|
|
11
|
+
throw new SkillsManagerError('invalid_skill_name', `Invalid skill name: ${name}. Use letters, numbers, dot, underscore, or dash, and start with a letter or number.`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function assertPathInside(child, parent) {
|
|
15
|
+
const resolvedChild = path.resolve(child);
|
|
16
|
+
const resolvedParent = path.resolve(parent);
|
|
17
|
+
if (resolvedChild !== resolvedParent && !resolvedChild.startsWith(resolvedParent + path.sep)) {
|
|
18
|
+
throw new SkillsManagerError('path_escape', `Path escape blocked: ${resolvedChild} is not inside ${resolvedParent}`, { child: resolvedChild, parent: resolvedParent });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Whether a value is one of the legacy consumer words (agents/claude) — the migration bridge's recognition test. */
|
|
22
|
+
export function isLegacyConsumer(value) {
|
|
23
|
+
return LEGACY_CONSUMERS.includes(value);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parse desired/default agent tags. Catalog membership is NOT checked here —
|
|
27
|
+
* callers at the catalog boundary (API endpoints) validate ids against the
|
|
28
|
+
* snapshot; legacy words always fail there, with migrate-consumers as the
|
|
29
|
+
* only path for old values.
|
|
30
|
+
*/
|
|
31
|
+
export function parseAgentTags(values, fallback, options = {}) {
|
|
32
|
+
const raw = values !== undefined ? values : fallback;
|
|
33
|
+
if (!raw || raw.length === 0) {
|
|
34
|
+
if (options.allowEmpty)
|
|
35
|
+
return [];
|
|
36
|
+
throw new SkillsManagerError('missing_agents', 'At least one agent id is required.');
|
|
37
|
+
}
|
|
38
|
+
const invalid = raw.map(String).filter((value) => !/^[a-z0-9][a-z0-9-]*$/.test(value) || isLegacyConsumer(value));
|
|
39
|
+
if (invalid.length > 0) {
|
|
40
|
+
throw new SkillsManagerError('invalid_agent', `Invalid agent id(s): ${invalid.join(', ')}. Agent ids come from the catalog (kebab-case, e.g. claude-code). Legacy values (agents/claude) must go through \`skills-manager migrate-consumers\`.`);
|
|
41
|
+
}
|
|
42
|
+
return [...new Set(raw.map(String))].sort();
|
|
43
|
+
}
|
|
44
|
+
export function normalizeTags(value) {
|
|
45
|
+
if (!Array.isArray(value))
|
|
46
|
+
return [];
|
|
47
|
+
return [...new Set(value.map((item) => String(item).trim()).filter(Boolean))].sort();
|
|
48
|
+
}
|
|
49
|
+
export function parseSkillMarkdownMetadata(text) {
|
|
50
|
+
const match = text.match(/^---\s*\n([\s\S]*?)\n---\s*\n?/);
|
|
51
|
+
if (!match)
|
|
52
|
+
return {};
|
|
53
|
+
const parsed = YAML.parse(match[1]);
|
|
54
|
+
if (!parsed || typeof parsed !== 'object')
|
|
55
|
+
return {};
|
|
56
|
+
const metadata = {};
|
|
57
|
+
if (typeof parsed.name === 'string') {
|
|
58
|
+
const name = parsed.name.trim();
|
|
59
|
+
assertSafeSkillName(name);
|
|
60
|
+
metadata.name = name;
|
|
61
|
+
}
|
|
62
|
+
if (typeof parsed.title === 'string')
|
|
63
|
+
metadata.title = parsed.title.trim();
|
|
64
|
+
if (typeof parsed.description === 'string')
|
|
65
|
+
metadata.description = parsed.description.trim();
|
|
66
|
+
return metadata;
|
|
67
|
+
}
|
|
68
|
+
export function validateRegistrySafePatch(patch) {
|
|
69
|
+
const next = {};
|
|
70
|
+
if ('title' in patch && patch.title !== undefined)
|
|
71
|
+
next.title = String(patch.title).trim();
|
|
72
|
+
if ('category' in patch && patch.category !== undefined)
|
|
73
|
+
next.category = String(patch.category).trim() || 'experimental';
|
|
74
|
+
if ('tags' in patch && patch.tags !== undefined)
|
|
75
|
+
next.tags = normalizeTags(patch.tags);
|
|
76
|
+
if ('consumers' in patch && patch.consumers !== undefined)
|
|
77
|
+
next.consumers = parseAgentTags(patch.consumers, undefined, { allowEmpty: true });
|
|
78
|
+
if ('description' in patch && patch.description !== undefined)
|
|
79
|
+
next.description = String(patch.description).trim();
|
|
80
|
+
if ('source' in patch && patch.source !== undefined) {
|
|
81
|
+
const source = patch.source || {};
|
|
82
|
+
next.source = {
|
|
83
|
+
...source,
|
|
84
|
+
url: source.url === undefined ? undefined : source.url ? String(source.url) : null,
|
|
85
|
+
subpath: source.subpath === undefined ? undefined : source.subpath ? String(source.subpath) : null,
|
|
86
|
+
ref: source.ref === undefined ? undefined : source.ref ? String(source.ref) : null,
|
|
87
|
+
upstream_commit: source.upstream_commit === undefined ? undefined : source.upstream_commit ? String(source.upstream_commit) : null,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return next;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/shared/validation.ts"],"names":[],"mappings":"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"}
|
package/docs/CLI.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Skills Manager CLI
|
|
2
|
+
|
|
3
|
+
**English** | [简体中文](CLI.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
`skills-manager-cli` provides the `skills-manager` executable for a local-first skill home.
|
|
6
|
+
|
|
7
|
+
## Skill home resolution
|
|
8
|
+
|
|
9
|
+
Priority:
|
|
10
|
+
|
|
11
|
+
1. `--home <path>`
|
|
12
|
+
2. `SKILL_HOME`
|
|
13
|
+
3. the current working directory when it already contains `skills/`, `views/`, `collections/`, and `registry.yaml`
|
|
14
|
+
4. `~/.skills-manager`, which is initialized automatically
|
|
15
|
+
|
|
16
|
+
Initialization creates `skills/`, `views/`, `collections/`, `registry.yaml`, and the parent directory for `.skills/activity.jsonl`.
|
|
17
|
+
|
|
18
|
+
## Commands
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
skills-manager web --home ./my-skill-home
|
|
22
|
+
skills-manager doctor --home ./my-skill-home
|
|
23
|
+
skills-manager catalog info --home ./my-skill-home
|
|
24
|
+
skills-manager catalog refresh --home ./my-skill-home
|
|
25
|
+
skills-manager list --home ./my-skill-home
|
|
26
|
+
skills-manager add <source> --all --yes
|
|
27
|
+
skills-manager update --plan
|
|
28
|
+
skills-manager update --skill my-skill
|
|
29
|
+
skills-manager update --source '<source-key>'
|
|
30
|
+
skills-manager distribute --to user --skill my-skill --agent claude-code --agent zed
|
|
31
|
+
skills-manager distribute --to project --project ./repo --skill my-skill --agent cursor --mode copy
|
|
32
|
+
skills-manager undistribute --to user --skill my-skill --agent claude-code
|
|
33
|
+
skills-manager redistribute --outdated
|
|
34
|
+
skills-manager init --dry-run
|
|
35
|
+
skills-manager init --agent claude-code --agent cursor
|
|
36
|
+
skills-manager init --resolve my-skill=cursor --resolve other-skill=hub
|
|
37
|
+
skills-manager backup list
|
|
38
|
+
skills-manager backup restore my-skill
|
|
39
|
+
skills-manager edit my-skill --source-url https://github.com/owner/repo
|
|
40
|
+
skills-manager archive old-skill
|
|
41
|
+
skills-manager rebuild-collections
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Distribute targets any catalog agent id (`--agent`, repeatable). Omitting `--agent` applies to the detected set on this machine. User scope defaults to `--mode symlink`, project scope to `--mode copy`; one mode per apply.
|
|
45
|
+
|
|
46
|
+
### init (reverse import)
|
|
47
|
+
|
|
48
|
+
`init` is the reverse of distribute: it scans the **global runtime directories of detected catalog agents** (`~/.claude/skills`, `~/.cursor/skills`, …), imports discovered skills into the hub, and turns each origin into a managed symlink back to `skills/<name>/` (the original is moved to `<home>/.backups/` first; backups expire after 30 days). Imported entries are stamped `imported: true` with no source — Skills Manager never guesses provenance. The CLI is non-interactive: clashing skills (same name in several runtimes, or in both hub and runtime) are skipped and reported with a suggested `--resolve <skill>=<agent-id|hub>` re-run; the winning copy enters the hub and **all** clashing origins symlink to it. `doctor` lists imported skills without a managed source; `edit <skill> --source-url <url>` supplies the upstream and enables normal update management. See [ADR-0006](adr/0006-init-reverse-import-symlinks.md).
|
|
49
|
+
|
|
50
|
+
## Agent catalog snapshot
|
|
51
|
+
|
|
52
|
+
The agent table (ids, runtime paths, detection rules) ships as a bundled snapshot extracted from [vercel-labs/skills](https://github.com/vercel-labs/skills) (MIT; attribution inside the file). `skills-manager catalog info` shows the snapshot stamp (upstream commit, date, age) and the detected agent set — the same determination `npx skills` makes with no `-a`. `skills-manager catalog refresh` re-downloads upstream, re-extracts, and stores the newer snapshot as a hub-local override at `<home>/.skills/agent-catalog.json`; doctor warns when the effective snapshot is older than 90 days.
|
|
53
|
+
|
|
54
|
+
To regenerate the checked-in snapshot during development: `pnpm run catalog:extract` (downloads `src/agents.ts` + `src/detect-agent.ts`, extracts, writes `src/core/catalog/agent-catalog.json`).
|
|
55
|
+
|
|
56
|
+
`<source>` can be a GitHub shorthand (`owner/repo`), Git URL, GitHub tree URL, or local path.
|
|
57
|
+
|
|
58
|
+
## Dashboard
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
skills-manager web --home ~/.skills-manager
|
|
62
|
+
skills-manager web --no-open
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The dashboard serves a local Vue/Vite UI backed by Fastify routes. Mutating dashboard operations write activity records to `.skills/activity.jsonl` and leave disk changes visible for `git diff`.
|
|
66
|
+
|
|
67
|
+
## Development
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
pnpm install
|
|
71
|
+
pnpm run build
|
|
72
|
+
pnpm test
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The test suite includes compiled-artifact coverage: `tests/cli/cli-bin.test.ts` boots `dist/cli.js` as a real subprocess (home resolution, help, migrate-views), and `tests/package/package-smoke.test.ts` packs the tarball, installs it into a temp dir, and drives the installed bin plus the dashboard API.
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "skills-manager-cli",
|
|
3
|
+
"version": "2026.8.26-1",
|
|
4
|
+
"packageManager": "pnpm@10.33.0",
|
|
5
|
+
"description": "Local-first CLI and dashboard for managing agent, Claude, and Codex skills",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/shenysun/skills-manager.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/shenysun/skills-manager#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/shenysun/skills-manager/issues"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"skills-manager": "tsx src/cli.ts",
|
|
16
|
+
"build": "pnpm run clean && tsc -p tsconfig.json && node scripts/copy-catalog-snapshot.mjs && vite build --config dashboard-web/vite.config.ts",
|
|
17
|
+
"build:cli": "pnpm run clean && tsc -p tsconfig.json && node scripts/copy-catalog-snapshot.mjs",
|
|
18
|
+
"build:web": "vite build --config dashboard-web/vite.config.ts",
|
|
19
|
+
"dev:web": "vite --config dashboard-web/vite.config.ts",
|
|
20
|
+
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"catalog:extract": "tsx scripts/extract-agent-catalog.ts",
|
|
24
|
+
"release": "node scripts/release.mjs"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"skills",
|
|
28
|
+
"agent",
|
|
29
|
+
"agents",
|
|
30
|
+
"claude",
|
|
31
|
+
"claude-code",
|
|
32
|
+
"codex",
|
|
33
|
+
"cursor",
|
|
34
|
+
"cli",
|
|
35
|
+
"dashboard"
|
|
36
|
+
],
|
|
37
|
+
"author": "shenysun <shenysun@163.com>",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"type": "module",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@fastify/static": "^10.1.2",
|
|
42
|
+
"commander": "^15.0.0",
|
|
43
|
+
"fastify": "^5.11.2",
|
|
44
|
+
"isomorphic-dompurify": "^3.23.0",
|
|
45
|
+
"markdown-it": "^15.0.0",
|
|
46
|
+
"shiki": "^4.4.3",
|
|
47
|
+
"vue": "^3.5.41",
|
|
48
|
+
"vue-i18n": "^11.4.8",
|
|
49
|
+
"yaml": "^2.9.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/markdown-it": "^14.2.0",
|
|
53
|
+
"@types/node": "^26.1.2",
|
|
54
|
+
"@vitejs/plugin-vue": "^6.0.8",
|
|
55
|
+
"tsx": "^4.23.7",
|
|
56
|
+
"typescript": "^7.0.2",
|
|
57
|
+
"vite": "^8.2.0",
|
|
58
|
+
"vitest": "^4.1.11"
|
|
59
|
+
},
|
|
60
|
+
"private": false,
|
|
61
|
+
"bin": {
|
|
62
|
+
"skills-manager": "./dist/cli.js"
|
|
63
|
+
},
|
|
64
|
+
"files": [
|
|
65
|
+
"dist",
|
|
66
|
+
"README.md",
|
|
67
|
+
"docs/CLI.md",
|
|
68
|
+
"LICENSE"
|
|
69
|
+
],
|
|
70
|
+
"engines": {
|
|
71
|
+
"node": ">=20"
|
|
72
|
+
}
|
|
73
|
+
}
|