llms-py 3.0.23__py3-none-any.whl → 3.0.24__py3-none-any.whl
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.
- llms/extensions/skills/README.md +13 -6
- llms/extensions/skills/__init__.py +21 -16
- llms/extensions/skills/ui/index.mjs +15 -8
- llms/main.py +1 -1
- llms/ui/ai.mjs +1 -1
- {llms_py-3.0.23.dist-info → llms_py-3.0.24.dist-info}/METADATA +1 -1
- {llms_py-3.0.23.dist-info → llms_py-3.0.24.dist-info}/RECORD +11 -11
- {llms_py-3.0.23.dist-info → llms_py-3.0.24.dist-info}/WHEEL +0 -0
- {llms_py-3.0.23.dist-info → llms_py-3.0.24.dist-info}/entry_points.txt +0 -0
- {llms_py-3.0.23.dist-info → llms_py-3.0.24.dist-info}/licenses/LICENSE +0 -0
- {llms_py-3.0.23.dist-info → llms_py-3.0.24.dist-info}/top_level.txt +0 -0
llms/extensions/skills/README.md
CHANGED
|
@@ -33,14 +33,21 @@ Access the skills panel by clicking the **Skills** icon in the top toolbar. The
|
|
|
33
33
|
|
|
34
34
|
### Skill Groups
|
|
35
35
|
|
|
36
|
-
Skills are organized into groups based on their source:
|
|
36
|
+
Skills are organized into groups based on their source location. Skills are discovered from these directories in order:
|
|
37
37
|
|
|
38
|
-
| Group | Description | Editable |
|
|
39
|
-
|
|
40
|
-
|
|
|
41
|
-
|
|
|
38
|
+
| Group | Location | Description | Editable |
|
|
39
|
+
|-------|----------|-------------|----------|
|
|
40
|
+
| Project (Agent) | `.agent/skills/` | Skills local to the current project | ✓ Yes |
|
|
41
|
+
| Project (Claude) | `.claude/skills/` | Claude-format skills in the current project | ✓ Yes |
|
|
42
|
+
| User (Agent) | `~/.llms/.agents/skills/` | Your personal skills collection | ✓ Yes |
|
|
43
|
+
| User (Claude) | `~/.claude/skills/` | Claude-format skills in your home directory | ✓ Yes |
|
|
44
|
+
| Built-in | Extension directory | Skills bundled with the extension | ✗ No |
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
**Project-level skills** (`.agent/` and `.claude/`) are specific to the workspace you're working in. They're ideal for project-specific workflows, coding standards, or team conventions.
|
|
47
|
+
|
|
48
|
+
**User-level skills** (`~/.llms/.agents/` and `~/.claude/`) are available across all projects. Use these for personal workflows and preferences.
|
|
49
|
+
|
|
50
|
+
Both `.agent` and `.claude` directory formats are supported for compatibility with different tooling conventions.
|
|
44
51
|
|
|
45
52
|
### Selecting Skills for a Conversation
|
|
46
53
|
|
|
@@ -21,6 +21,9 @@ g_home_skills = None
|
|
|
21
21
|
# }
|
|
22
22
|
g_available_skills = []
|
|
23
23
|
|
|
24
|
+
LLMS_HOME_SKILLS = "~/.llms/.agent/skills"
|
|
25
|
+
LLMS_LOCAL_SKILLS = ".agent/skills"
|
|
26
|
+
|
|
24
27
|
|
|
25
28
|
def is_safe_path(base_path: str, requested_path: str) -> bool:
|
|
26
29
|
"""Check if the requested path is safely within the base path."""
|
|
@@ -132,10 +135,12 @@ def install(ctx):
|
|
|
132
135
|
if os.path.exists(os.path.join(".claude", "skills")):
|
|
133
136
|
skill_roots[".claude/skills"] = os.path.join(".claude", "skills")
|
|
134
137
|
|
|
135
|
-
skill_roots[
|
|
138
|
+
skill_roots[LLMS_HOME_SKILLS] = home_skills
|
|
136
139
|
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
local_skills = os.path.join(".agent", "skills")
|
|
141
|
+
if os.path.exists(local_skills):
|
|
142
|
+
local_skills = str(Path(local_skills).resolve())
|
|
143
|
+
skill_roots[LLMS_LOCAL_SKILLS] = local_skills
|
|
139
144
|
|
|
140
145
|
g_skills = {}
|
|
141
146
|
for group, root in skill_roots.items():
|
|
@@ -237,7 +242,7 @@ def install(ctx):
|
|
|
237
242
|
skill_props = props.to_dict()
|
|
238
243
|
skill_props.update(
|
|
239
244
|
{
|
|
240
|
-
"group":
|
|
245
|
+
"group": LLMS_HOME_SKILLS,
|
|
241
246
|
"location": str(skill_dir),
|
|
242
247
|
"files": files,
|
|
243
248
|
}
|
|
@@ -303,9 +308,9 @@ def install(ctx):
|
|
|
303
308
|
|
|
304
309
|
location = skill_info.get("location")
|
|
305
310
|
|
|
306
|
-
# Only allow modifications to skills in home directory
|
|
307
|
-
if not is_safe_path(home_skills, location):
|
|
308
|
-
raise Exception("Cannot modify skills outside of
|
|
311
|
+
# Only allow modifications to skills in home or local .agent directory
|
|
312
|
+
if not is_safe_path(home_skills, location) and not (local_skills and is_safe_path(local_skills, location)):
|
|
313
|
+
raise Exception("Cannot modify skills outside of allowed directories")
|
|
309
314
|
|
|
310
315
|
full_path = os.path.join(location, file_path)
|
|
311
316
|
|
|
@@ -319,7 +324,7 @@ def install(ctx):
|
|
|
319
324
|
f.write(content)
|
|
320
325
|
|
|
321
326
|
# Reload skill metadata
|
|
322
|
-
group = skill_info.get("group",
|
|
327
|
+
group = skill_info.get("group", LLMS_HOME_SKILLS)
|
|
323
328
|
updated_skill = reload_skill(name, location, group)
|
|
324
329
|
|
|
325
330
|
return aiohttp.web.json_response({"path": file_path, "skill": updated_skill})
|
|
@@ -342,9 +347,9 @@ def install(ctx):
|
|
|
342
347
|
|
|
343
348
|
location = skill_info.get("location")
|
|
344
349
|
|
|
345
|
-
# Only allow modifications to skills in home directory
|
|
346
|
-
if not is_safe_path(home_skills, location):
|
|
347
|
-
raise Exception("Cannot modify skills outside of
|
|
350
|
+
# Only allow modifications to skills in home or local .agent directory
|
|
351
|
+
if not is_safe_path(home_skills, location) and not (local_skills and is_safe_path(local_skills, location)):
|
|
352
|
+
raise Exception("Cannot modify skills outside of allowed directories")
|
|
348
353
|
|
|
349
354
|
full_path = os.path.join(location, file_path)
|
|
350
355
|
|
|
@@ -371,7 +376,7 @@ def install(ctx):
|
|
|
371
376
|
break
|
|
372
377
|
|
|
373
378
|
# Reload skill metadata
|
|
374
|
-
group = skill_info.get("group",
|
|
379
|
+
group = skill_info.get("group", LLMS_HOME_SKILLS)
|
|
375
380
|
updated_skill = reload_skill(name, location, group)
|
|
376
381
|
|
|
377
382
|
return aiohttp.web.json_response({"path": file_path, "skill": updated_skill})
|
|
@@ -433,7 +438,7 @@ def install(ctx):
|
|
|
433
438
|
skill_props = props.to_dict()
|
|
434
439
|
skill_props.update(
|
|
435
440
|
{
|
|
436
|
-
"group":
|
|
441
|
+
"group": LLMS_HOME_SKILLS,
|
|
437
442
|
"location": str(skill_dir_path),
|
|
438
443
|
"files": files,
|
|
439
444
|
}
|
|
@@ -467,9 +472,9 @@ def install(ctx):
|
|
|
467
472
|
else:
|
|
468
473
|
raise Exception(f"Skill '{name}' not found")
|
|
469
474
|
|
|
470
|
-
# Only allow deletion of skills in home directory
|
|
471
|
-
if not is_safe_path(home_skills, location):
|
|
472
|
-
raise Exception("Cannot delete skills outside of
|
|
475
|
+
# Only allow deletion of skills in home or local .agent directory
|
|
476
|
+
if not is_safe_path(home_skills, location) and not (local_skills and is_safe_path(local_skills, location)):
|
|
477
|
+
raise Exception("Cannot delete skills outside of allowed directories")
|
|
473
478
|
|
|
474
479
|
try:
|
|
475
480
|
if os.path.exists(location):
|
|
@@ -3,6 +3,9 @@ import { leftPart } from "@servicestack/client"
|
|
|
3
3
|
|
|
4
4
|
let ext
|
|
5
5
|
|
|
6
|
+
const LLMS_HOME_SKILLS = "~/.llms/.agent/skills"
|
|
7
|
+
const LLMS_LOCAL_SKILLS = ".agent/skills"
|
|
8
|
+
|
|
6
9
|
const SkillSelector = {
|
|
7
10
|
template: `
|
|
8
11
|
<div class="px-4 py-4 bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 max-h-[80vh] overflow-y-auto">
|
|
@@ -119,10 +122,10 @@ const SkillSelector = {
|
|
|
119
122
|
skills
|
|
120
123
|
}))
|
|
121
124
|
|
|
122
|
-
// Sort groups: writable (~/.llms/.
|
|
125
|
+
// Sort groups: writable (~/.llms/.agent/skills,.agent/skills) first, then alphabetically
|
|
123
126
|
definedGroups.sort((a, b) => {
|
|
124
|
-
const aEditable = a.name ===
|
|
125
|
-
const bEditable = b.name ===
|
|
127
|
+
const aEditable = a.name === LLMS_HOME_SKILLS || a.name === LLMS_LOCAL_SKILLS
|
|
128
|
+
const bEditable = b.name === LLMS_HOME_SKILLS || b.name === LLMS_LOCAL_SKILLS
|
|
126
129
|
if (aEditable !== bEditable) return aEditable ? -1 : 1
|
|
127
130
|
return a.name.localeCompare(b.name)
|
|
128
131
|
})
|
|
@@ -158,6 +161,10 @@ const SkillSelector = {
|
|
|
158
161
|
onlySkills = onlySkills.filter(s => s !== name)
|
|
159
162
|
} else {
|
|
160
163
|
onlySkills = [...onlySkills, name]
|
|
164
|
+
// If has all skills set to 'All' (null)
|
|
165
|
+
if (onlySkills.length === availableSkills.value.length) {
|
|
166
|
+
onlySkills = null
|
|
167
|
+
}
|
|
161
168
|
}
|
|
162
169
|
}
|
|
163
170
|
|
|
@@ -395,8 +402,8 @@ const SkillPage = {
|
|
|
395
402
|
grouped[group].push(skill)
|
|
396
403
|
})
|
|
397
404
|
return Object.entries(grouped).sort((a, b) => {
|
|
398
|
-
const aEditable = a[0] ===
|
|
399
|
-
const bEditable = b[0] ===
|
|
405
|
+
const aEditable = a[0] === LLMS_HOME_SKILLS || a[0] === LLMS_LOCAL_SKILLS
|
|
406
|
+
const bEditable = b[0] === LLMS_HOME_SKILLS || b[0] === LLMS_LOCAL_SKILLS
|
|
400
407
|
if (aEditable !== bEditable) return aEditable ? -1 : 1
|
|
401
408
|
return a[0].localeCompare(b[0])
|
|
402
409
|
}).map(([name, skills]) => ({ name, skills: skills.sort((a, b) => a.name.localeCompare(b.name)) }))
|
|
@@ -419,8 +426,8 @@ const SkillPage = {
|
|
|
419
426
|
return tree.sort((a, b) => { if (a.isFile !== b.isFile) return a.isFile ? 1 : -1; return a.name.localeCompare(b.name) })
|
|
420
427
|
}
|
|
421
428
|
const hasUnsavedChanges = computed(() => isEditing.value && editContent.value !== fileContent.value)
|
|
422
|
-
function isGroupEditable(groupName) { return groupName ===
|
|
423
|
-
function isEditable(skill) { return skill?.group ===
|
|
429
|
+
function isGroupEditable(groupName) { return groupName === LLMS_HOME_SKILLS || groupName === LLMS_LOCAL_SKILLS }
|
|
430
|
+
function isEditable(skill) { return skill?.group === LLMS_HOME_SKILLS || skill?.group === LLMS_LOCAL_SKILLS }
|
|
424
431
|
function isSkillExpanded(name) { return !!expandedSkills.value[name] }
|
|
425
432
|
function toggleSkillExpand(skill) {
|
|
426
433
|
expandedSkills.value[skill.name] = !expandedSkills.value[skill.name]
|
|
@@ -579,7 +586,7 @@ const SkillStore = {
|
|
|
579
586
|
<div class="h-full flex flex-col">
|
|
580
587
|
<div class="px-4 py-3 bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between flex-shrink-0">
|
|
581
588
|
<div>
|
|
582
|
-
<h1 class="text-xl font-bold text-gray-900 dark:text-gray-100">
|
|
589
|
+
<h1 class="text-xl font-bold text-gray-900 dark:text-gray-100">Discover Skills</h1>
|
|
583
590
|
<p class="text-sm text-gray-500 dark:text-gray-400">{{ total.toLocaleString() }} skills available</p>
|
|
584
591
|
</div>
|
|
585
592
|
<div class="flex items-center gap-2">
|
llms/main.py
CHANGED
llms/ui/ai.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llms-py
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.24
|
|
4
4
|
Summary: A lightweight CLI tool and OpenAI-compatible server for querying multiple Large Language Model (LLM) providers
|
|
5
5
|
Home-page: https://github.com/ServiceStack/llms
|
|
6
6
|
Author: ServiceStack
|
|
@@ -3,7 +3,7 @@ llms/__main__.py,sha256=hrBulHIt3lmPm1BCyAEVtB6DQ0Hvc3gnIddhHCmJasg,151
|
|
|
3
3
|
llms/db.py,sha256=oozp5I5lECVO8oZEFwcZl3ES5mARqWeR1BkoqG5kSqM,11687
|
|
4
4
|
llms/index.html,sha256=nGk1Djtn9p7l6LuKp4Kg0JIB9fCzxtTWXFfmDb4ggpc,1658
|
|
5
5
|
llms/llms.json,sha256=xeIOuraZKs4CwSJ8R2aDAOClLqx6rdEN68O6s51_7cA,11824
|
|
6
|
-
llms/main.py,sha256=
|
|
6
|
+
llms/main.py,sha256=MBRi98pE7MZ70Iw45vMVEHqeRn6WH4oJFAY5gvjnhFM,184270
|
|
7
7
|
llms/providers-extra.json,sha256=_6DmGBiQY9LM6_Y0zOiObYn7ba4g3akSNQfmHcYlENc,11101
|
|
8
8
|
llms/providers.json,sha256=yls3OUqPIBLSf2rk0xgwUHKkvd-8drGq4JW7w49rEws,299324
|
|
9
9
|
llms/extensions/analytics/ui/index.mjs,sha256=m1XwaqYCLwK267JAUCAltkN_nOXep0GxfpvGNS5i4_w,69547
|
|
@@ -146,14 +146,14 @@ llms/extensions/providers/openai.py,sha256=n1jTXkWPrboTazCW0FX3zYYaOlsW44rQpIfgK
|
|
|
146
146
|
llms/extensions/providers/openrouter.py,sha256=9V1NSZJblku_lfsDY8Fantr5QFzkp3A0hXFDCYucShM,3344
|
|
147
147
|
llms/extensions/providers/zai.py,sha256=WPJlDxmnjuhxlgWhUXw2MYqgEKYfy14wVQbpQyMMlbU,7736
|
|
148
148
|
llms/extensions/skills/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
149
|
-
llms/extensions/skills/README.md,sha256=
|
|
150
|
-
llms/extensions/skills/__init__.py,sha256=
|
|
149
|
+
llms/extensions/skills/README.md,sha256=wawmpeyiJFw9G8qzCZ3CiKamt47k6fO680gFX9wuOGs,10471
|
|
150
|
+
llms/extensions/skills/__init__.py,sha256=DK4UECLKOmdL5_gz7NeKeZuuo7j5tpJzmGEcczkz3N4,17244
|
|
151
151
|
llms/extensions/skills/errors.py,sha256=V4DTFNtzVADDlZ0g7RmoxZRFeG01oaG3zzaPAVdtkfQ,572
|
|
152
152
|
llms/extensions/skills/installer.py,sha256=GfNYRK6LbYSZtIOesQ_fQvjtBsiZC9sTXLVuUbrrdLI,12751
|
|
153
153
|
llms/extensions/skills/models.py,sha256=xmRfz8BMeOdzZXhW6MYFjkOVHOKD6bMDynId8aysans,1461
|
|
154
154
|
llms/extensions/skills/parser.py,sha256=Mb4NOtoY3Ip4Nng8ixb26oE8U_Sp5CI3n3l_qxbg1UM,5500
|
|
155
155
|
llms/extensions/skills/validator.py,sha256=te49hTfIPJWcMcLLCApSJ2Ru3lrqVF8ayDXtPEZF9sU,5154
|
|
156
|
-
llms/extensions/skills/ui/index.mjs,sha256=
|
|
156
|
+
llms/extensions/skills/ui/index.mjs,sha256=U4oeqSGM2Q4hzIIK0sAFqi9AtZvmyUm5SdBYT2i-cMY,63499
|
|
157
157
|
llms/extensions/skills/ui/data/skills-top-5000.json,sha256=e8fUF_NQSUZRK0rGRUqBFecW5JEX6QO6H_P3WqTBBQ4,540056
|
|
158
158
|
llms/extensions/skills/ui/skills/create-plan/SKILL.md,sha256=ZAtiM2qPHcc8Z3Ongl1NgX5ythITPwyvcIqisgqWrGA,2493
|
|
159
159
|
llms/extensions/skills/ui/skills/skill-creator/LICENSE.txt,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
@@ -170,7 +170,7 @@ llms/extensions/system_prompts/ui/prompts.json,sha256=t5DD3bird-87wFa4OlW-bC2wdo
|
|
|
170
170
|
llms/extensions/tools/__init__.py,sha256=PRZe0QMfsOymJ3jTqO0VFppNEWI4f2bYSOImK_YrGQM,2036
|
|
171
171
|
llms/extensions/tools/ui/index.mjs,sha256=1TgCn74oX_rUAhxO8w54HlIgNkHnI5ma-GCqXp-qYVY,39434
|
|
172
172
|
llms/ui/App.mjs,sha256=CoUzO9mV__-jV19NKHYIbwHsjWMnO11jyNSbnJhe1gQ,7486
|
|
173
|
-
llms/ui/ai.mjs,sha256=
|
|
173
|
+
llms/ui/ai.mjs,sha256=SMAvpE5QzcoQvCNaoOptjZX8k8P3kH4L4yEkDTMfP-E,6541
|
|
174
174
|
llms/ui/app.css,sha256=SVVzmFhTd0chuGq5yhv3FjgNudgo6WXlM2fnb-csK4c,190220
|
|
175
175
|
llms/ui/ctx.mjs,sha256=4x-LTmofhf6OvLThSlDSTQOsLkzyBFOEMRGIOLHszqs,14974
|
|
176
176
|
llms/ui/fav.svg,sha256=_R6MFeXl6wBFT0lqcUxYQIDWgm246YH_3hSTW0oO8qw,734
|
|
@@ -196,9 +196,9 @@ llms/ui/modules/model-selector.mjs,sha256=6U4rAZ7vmQELFRQGWk4YEtq02v3lyHdMq6yUOp
|
|
|
196
196
|
llms/ui/modules/chat/ChatBody.mjs,sha256=jusiYUxz8NoN6iYCrEayYW5t2wdOx0So79aLxjk7J9c,58187
|
|
197
197
|
llms/ui/modules/chat/SettingsDialog.mjs,sha256=HMBJTwrapKrRIAstIIqp0QlJL5O-ho4hzgvfagPfsX8,19930
|
|
198
198
|
llms/ui/modules/chat/index.mjs,sha256=nS_L6G1RSuCybgnA6n-q8Sn3OeSbQWL2iW3-zCIFqJk,39548
|
|
199
|
-
llms_py-3.0.
|
|
200
|
-
llms_py-3.0.
|
|
201
|
-
llms_py-3.0.
|
|
202
|
-
llms_py-3.0.
|
|
203
|
-
llms_py-3.0.
|
|
204
|
-
llms_py-3.0.
|
|
199
|
+
llms_py-3.0.24.dist-info/licenses/LICENSE,sha256=bus9cuAOWeYqBk2OuhSABVV1P4z7hgrEFISpyda_H5w,1532
|
|
200
|
+
llms_py-3.0.24.dist-info/METADATA,sha256=DIZBWhv5icDwZzyHFqY9up_pq-9Om3JiNpW4GNYpjfA,2195
|
|
201
|
+
llms_py-3.0.24.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
202
|
+
llms_py-3.0.24.dist-info/entry_points.txt,sha256=WswyE7PfnkZMIxboC-MS6flBD6wm-CYU7JSUnMhqMfM,40
|
|
203
|
+
llms_py-3.0.24.dist-info/top_level.txt,sha256=gC7hk9BKSeog8gyg-EM_g2gxm1mKHwFRfK-10BxOsa4,5
|
|
204
|
+
llms_py-3.0.24.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|