claude-home 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/index.html +61 -5
- package/server.js +26 -1
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -2766,13 +2766,42 @@
|
|
|
2766
2766
|
<div>
|
|
2767
2767
|
<div style="padding:8px 10px;border-bottom:1px solid var(--rule);display:flex;flex-direction:column;gap:6px">
|
|
2768
2768
|
<input class="search-input" type="text" placeholder="Buscar skills…" x-model="marketplaceSearch" style="width:100%;font-size:12px;padding:4px 8px">
|
|
2769
|
-
<
|
|
2770
|
-
<div style="display:flex;gap:4px;flex-wrap:wrap">
|
|
2771
|
-
<
|
|
2769
|
+
<div style="display:flex;align-items:center;gap:4px;flex-wrap:wrap">
|
|
2770
|
+
<div style="display:flex;gap:4px;flex-wrap:wrap;flex:1">
|
|
2771
|
+
<template x-if="marketplaceSources.length>1">
|
|
2772
|
+
<button class="tools-tab" :class="{active:marketplaceSourceFilter==='all'}" style="font-size:11px;padding:2px 8px" @click="marketplaceSourceFilter='all'">All</button>
|
|
2773
|
+
</template>
|
|
2772
2774
|
<template x-for="src in marketplaceSources" :key="src.id">
|
|
2773
|
-
<
|
|
2775
|
+
<span style="display:inline-flex;align-items:center;gap:2px">
|
|
2776
|
+
<button class="tools-tab" :class="{active:marketplaceSourceFilter===src.id||marketplaceSources.length===1}" style="font-size:11px;padding:2px 8px" @click="marketplaceSourceFilter=src.id" x-text="src.name"></button>
|
|
2777
|
+
<button style="font-size:10px;padding:1px 4px;border:none;background:none;color:var(--ink-3);cursor:pointer;line-height:1" title="Remove source" @click.stop="removeMarketplaceSource(src.id)">✕</button>
|
|
2778
|
+
</span>
|
|
2774
2779
|
</template>
|
|
2775
2780
|
</div>
|
|
2781
|
+
<button class="btn btn-outline btn-sm" style="font-size:11px;padding:2px 8px;flex-shrink:0" @click="marketplaceSourceForm.open=!marketplaceSourceForm.open;marketplaceSourceForm.msg=''">+ Add source</button>
|
|
2782
|
+
</div>
|
|
2783
|
+
<!-- Add source form -->
|
|
2784
|
+
<template x-if="marketplaceSourceForm.open">
|
|
2785
|
+
<div style="display:flex;flex-direction:column;gap:6px;padding:10px;border:1px solid var(--rule-2);border-radius:6px;background:var(--canvas)">
|
|
2786
|
+
<div style="font-size:11px;font-weight:600;color:var(--ink)">New source</div>
|
|
2787
|
+
<input type="text" x-model="marketplaceSourceForm.name" placeholder="Name (e.g. My Org Skills)" style="font-size:12px;padding:4px 8px;border:1px solid var(--rule-2);border-radius:4px;background:var(--white)">
|
|
2788
|
+
<div style="display:flex;gap:6px">
|
|
2789
|
+
<input type="text" x-model="marketplaceSourceForm.owner" placeholder="GitHub owner / org" style="font-size:12px;padding:4px 8px;border:1px solid var(--rule-2);border-radius:4px;background:var(--white);flex:1">
|
|
2790
|
+
<input type="text" x-model="marketplaceSourceForm.repo" placeholder="repo name" style="font-size:12px;padding:4px 8px;border:1px solid var(--rule-2);border-radius:4px;background:var(--white);flex:1">
|
|
2791
|
+
</div>
|
|
2792
|
+
<div style="display:flex;gap:6px">
|
|
2793
|
+
<input type="text" x-model="marketplaceSourceForm.branch" placeholder="branch (default: main)" style="font-size:12px;padding:4px 8px;border:1px solid var(--rule-2);border-radius:4px;background:var(--white);flex:1">
|
|
2794
|
+
<input type="text" x-model="marketplaceSourceForm.skillsPath" placeholder="skills path (leave empty for root)" style="font-size:12px;padding:4px 8px;border:1px solid var(--rule-2);border-radius:4px;background:var(--white);flex:1">
|
|
2795
|
+
</div>
|
|
2796
|
+
<input type="password" x-model="marketplaceSourceForm.token" placeholder="GitHub token (optional, for private repos)" style="font-size:12px;padding:4px 8px;border:1px solid var(--rule-2);border-radius:4px;background:var(--white)">
|
|
2797
|
+
<div style="display:flex;gap:6px;align-items:center">
|
|
2798
|
+
<button class="btn btn-primary btn-sm" :disabled="marketplaceSourceForm.saving||!marketplaceSourceForm.name||!marketplaceSourceForm.owner||!marketplaceSourceForm.repo" @click="addMarketplaceSource()">
|
|
2799
|
+
<span x-text="marketplaceSourceForm.saving ? 'Adding…' : 'Add'"></span>
|
|
2800
|
+
</button>
|
|
2801
|
+
<button class="btn btn-outline btn-sm" @click="marketplaceSourceForm.open=false">Cancel</button>
|
|
2802
|
+
<span x-show="marketplaceSourceForm.msg" :style="marketplaceSourceForm.msg.startsWith('Error')?'color:var(--red)':'color:var(--green)'" style="font-size:11px" x-text="marketplaceSourceForm.msg"></span>
|
|
2803
|
+
</div>
|
|
2804
|
+
</div>
|
|
2776
2805
|
</template>
|
|
2777
2806
|
</div>
|
|
2778
2807
|
<template x-for="s in filteredMarketplace()" :key="s.slug">
|
|
@@ -2781,7 +2810,7 @@
|
|
|
2781
2810
|
<div style="display:flex;align-items:center;gap:5px;flex-wrap:wrap">
|
|
2782
2811
|
<div class="tool-row-name" x-text="s.name"></div>
|
|
2783
2812
|
<template x-if="marketplaceInstalled[s.slug]"><span style="font-size:9px;padding:1px 5px;border-radius:3px;background:var(--green);color:#fff;font-weight:600">installed</span></template>
|
|
2784
|
-
<
|
|
2813
|
+
<span style="font-size:9px;padding:1px 5px;border-radius:3px;background:var(--canvas);border:1px solid var(--rule-2);color:var(--ink-3)" x-text="s._sourceName"></span>
|
|
2785
2814
|
</div>
|
|
2786
2815
|
<div class="tool-row-desc" x-text="s.description"></div>
|
|
2787
2816
|
<template x-if="s.tags?.length>0">
|
|
@@ -3829,6 +3858,7 @@
|
|
|
3829
3858
|
marketplace: [],
|
|
3830
3859
|
marketplaceSources: [],
|
|
3831
3860
|
marketplaceSourceFilter: 'all',
|
|
3861
|
+
marketplaceSourceForm: { open: false, name: '', owner: '', repo: '', branch: 'main', skillsPath: '', token: '', tokenEnv: '', saving: false, msg: '' },
|
|
3832
3862
|
marketplaceLoading: false,
|
|
3833
3863
|
marketplaceErrors: [],
|
|
3834
3864
|
marketplaceSearch: '',
|
|
@@ -4972,6 +5002,32 @@
|
|
|
4972
5002
|
);
|
|
4973
5003
|
},
|
|
4974
5004
|
|
|
5005
|
+
async addMarketplaceSource() {
|
|
5006
|
+
const f = this.marketplaceSourceForm;
|
|
5007
|
+
f.saving = true; f.msg = '';
|
|
5008
|
+
try {
|
|
5009
|
+
const r = await fetch('/api/marketplace/sources', {
|
|
5010
|
+
method: 'POST',
|
|
5011
|
+
headers: { 'Content-Type': 'application/json' },
|
|
5012
|
+
body: JSON.stringify({ name: f.name, owner: f.owner, repo: f.repo, branch: f.branch || 'main', skillsPath: f.skillsPath || '', token: f.token || '' }),
|
|
5013
|
+
});
|
|
5014
|
+
const data = await r.json();
|
|
5015
|
+
if (!r.ok) { f.msg = 'Error: ' + data.error; return; }
|
|
5016
|
+
f.msg = 'Source added!';
|
|
5017
|
+
f.open = false;
|
|
5018
|
+
Object.assign(f, { name: '', owner: '', repo: '', branch: 'main', skillsPath: '', token: '' });
|
|
5019
|
+
this.marketplace = [];
|
|
5020
|
+
await this.loadMarketplace();
|
|
5021
|
+
} catch (e) { f.msg = 'Error: ' + e.message; }
|
|
5022
|
+
finally { f.saving = false; }
|
|
5023
|
+
},
|
|
5024
|
+
|
|
5025
|
+
async removeMarketplaceSource(id) {
|
|
5026
|
+
await fetch(`/api/marketplace/sources/${encodeURIComponent(id)}`, { method: 'DELETE' });
|
|
5027
|
+
this.marketplace = [];
|
|
5028
|
+
await this.loadMarketplace();
|
|
5029
|
+
},
|
|
5030
|
+
|
|
4975
5031
|
async loadMarketplace() {
|
|
4976
5032
|
if (this.marketplace.length > 0) return;
|
|
4977
5033
|
this.marketplaceLoading = true;
|
package/server.js
CHANGED
|
@@ -1138,10 +1138,35 @@ app.get('/api/status', (req, res) => {
|
|
|
1138
1138
|
app.get('/api/marketplace/sources', (req, res) => {
|
|
1139
1139
|
const sources = getMarketplaceSources()
|
|
1140
1140
|
.filter(s => s.owner && s.repo)
|
|
1141
|
-
.map(({ id, name, owner, repo }) => ({ id, name, owner, repo }));
|
|
1141
|
+
.map(({ id, name, owner, repo, branch, skillsPath }) => ({ id, name, owner, repo, branch, skillsPath }));
|
|
1142
1142
|
res.json(sources);
|
|
1143
1143
|
});
|
|
1144
1144
|
|
|
1145
|
+
// POST /api/marketplace/sources — add a new source
|
|
1146
|
+
app.post('/api/marketplace/sources', (req, res) => {
|
|
1147
|
+
const { name, owner, repo, branch, skillsPath, token, tokenEnv } = req.body || {};
|
|
1148
|
+
if (!name || !owner || !repo) return res.status(400).json({ error: 'name, owner and repo are required' });
|
|
1149
|
+
const config = JSON.parse(fs.readFileSync(MARKETPLACE_CONFIG_PATH, 'utf8'));
|
|
1150
|
+
const id = owner.toLowerCase() + '-' + repo.toLowerCase().replace(/[^a-z0-9]/g, '-');
|
|
1151
|
+
if (config.sources.some(s => s.id === id)) return res.status(409).json({ error: 'Source already exists' });
|
|
1152
|
+
config.sources.push({ id, name, owner, repo, branch: branch || 'main', skillsPath: skillsPath || '', token: token || '', tokenEnv: tokenEnv || '' });
|
|
1153
|
+
fs.writeFileSync(MARKETPLACE_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
|
|
1154
|
+
sourceCache.delete(id);
|
|
1155
|
+
res.json({ id });
|
|
1156
|
+
});
|
|
1157
|
+
|
|
1158
|
+
// DELETE /api/marketplace/sources/:id — remove a source
|
|
1159
|
+
app.delete('/api/marketplace/sources/:id', (req, res) => {
|
|
1160
|
+
const { id } = req.params;
|
|
1161
|
+
const config = JSON.parse(fs.readFileSync(MARKETPLACE_CONFIG_PATH, 'utf8'));
|
|
1162
|
+
const idx = config.sources.findIndex(s => s.id === id);
|
|
1163
|
+
if (idx === -1) return res.status(404).json({ error: 'Source not found' });
|
|
1164
|
+
config.sources.splice(idx, 1);
|
|
1165
|
+
fs.writeFileSync(MARKETPLACE_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
|
|
1166
|
+
sourceCache.delete(id);
|
|
1167
|
+
res.json({ ok: true });
|
|
1168
|
+
});
|
|
1169
|
+
|
|
1145
1170
|
// GET /api/marketplace/registry — discovers skills from all configured sources
|
|
1146
1171
|
app.get('/api/marketplace/registry', async (req, res) => {
|
|
1147
1172
|
const sources = getMarketplaceSources().filter(s => s.owner && s.repo);
|