herm-tui 1.9.0-dev.8 → 1.9.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/README.md +55 -10
- package/assets/eikons/nous/manifest.json +123 -0
- package/assets/eikons/nous/nous.eikon +0 -0
- package/assets/plugins/eikon/__init__.py +34 -11
- package/assets/plugins/eikon/plugin.yaml +6 -1
- package/assets/plugins/eikon/schemas.py +70 -2
- package/assets/plugins/eikon/tools.py +77 -21
- package/assets/skills/eikon/SKILL.md +92 -19
- package/assets/skills/eikon-create/SKILL.md +106 -69
- package/db.worker.js +8 -5
- package/index.js +182 -147
- package/package.json +1 -1
- package/assets/eikons/ares/ares.eikon +0 -367
- package/assets/eikons/ares/manifest.json +0 -28
- package/assets/eikons/default/default.eikon +0 -398
- package/assets/eikons/default/manifest.json +0 -28
- package/assets/eikons/mono/manifest.json +0 -28
- package/assets/eikons/mono/mono.eikon +0 -395
package/README.md
CHANGED
|
@@ -93,16 +93,61 @@ See [`.env.example`](./.env.example) for rarely-needed overrides.
|
|
|
93
93
|
|
|
94
94
|
### Share and install eikons
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
Eikons are 48×24 terminal avatars. The shipped lifecycle is deterministic:
|
|
97
|
+
discover, inspect, install, use, update, and remove.
|
|
98
|
+
|
|
99
|
+
In Herm:
|
|
100
|
+
|
|
101
|
+
- Open Eikon → Catalog, or run `/catalog`, to browse shared catalog
|
|
102
|
+
entries.
|
|
103
|
+
- Preview rows before installing. Trust is shown as `Verified`, `Unverified`,
|
|
104
|
+
or `Mismatch` beside source and compatibility state.
|
|
105
|
+
- Install adds the eikon to your local library without activating it.
|
|
106
|
+
- Use selects an installed eikon as the active avatar.
|
|
107
|
+
- Installing over the currently active eikon name also requires confirmation or
|
|
108
|
+
`--active-ok` because it replaces the active avatar's backing package.
|
|
109
|
+
- Update or remove an active eikon only after confirming that the active
|
|
110
|
+
avatar's backing package will change or be cleared.
|
|
111
|
+
|
|
112
|
+
From the shell:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
herm eikon search [query] [--json]
|
|
116
|
+
herm eikon browse [query] [--json]
|
|
117
|
+
herm eikon inspect <name|url|dir> [--json]
|
|
118
|
+
herm eikon install <name|url|dir> [--name N] [--no-source] [--active-ok] [--json]
|
|
119
|
+
herm eikon list [--json]
|
|
120
|
+
herm eikon use <name> [--json]
|
|
121
|
+
herm eikon info <name> [--json]
|
|
122
|
+
herm eikon update <name> [--active-ok] [--json]
|
|
123
|
+
herm eikon remove <name> [--active-ok] [--json]
|
|
124
|
+
herm eikon delist <name|id> [--json]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`install` never activates. `use` is the activation action. JSON output is
|
|
128
|
+
available for automation with `--json`.
|
|
129
|
+
|
|
130
|
+
Default Catalog installs fetch built package artifacts referenced by the
|
|
131
|
+
catalog, not creator repositories. Direct GitHub installs are for sharing
|
|
132
|
+
outside the default catalog and support both single-package repos and
|
|
133
|
+
multi-eikon catalog repos addressed as `github.com/user/repo/eikon-name`.
|
|
134
|
+
Private GitHub repos use normal git authentication.
|
|
135
|
+
|
|
136
|
+
Creators can share Eikons through normal GitHub repositories. For official
|
|
137
|
+
registry listing, press `u` in Studio or use Library's Share to catalog action
|
|
138
|
+
after baking. Herm previews metadata, the prepared public bundle, and the GitHub
|
|
139
|
+
PR target; with local `gh` auth it creates the PR, otherwise it shows manual PR
|
|
140
|
+
steps with the prepared bundle path and compare URL. Direct-install repos can
|
|
141
|
+
still be prepared with upstream `eikon pack`, `eikon index`, and
|
|
142
|
+
`eikon manifest`.
|
|
143
|
+
`eikon publish` remains the lower-level GitHub PR contribution helper for the
|
|
144
|
+
configured/default catalog repo; it is not a hosted marketplace account, upload,
|
|
145
|
+
dashboard, or moderation flow.
|
|
146
|
+
|
|
147
|
+
Use `eikon.liftaris.dev` as a discovery gallery only; it previews catalog
|
|
148
|
+
entries and gives copyable Herm install instructions.
|
|
149
|
+
|
|
150
|
+
Herm owns native Catalog behavior. The eikon repo owns the registry,
|
|
106
151
|
browser mirror, shared catalog/player exports, install resolver, and publish
|
|
107
152
|
preflight. Herm imports public eikon package exports rather than browser mirror
|
|
108
153
|
internals or unexported source paths.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "eikon.package",
|
|
3
|
+
"schemaVersion": "1.0",
|
|
4
|
+
"id": "liftaris/nous",
|
|
5
|
+
"name": "nous",
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"display": {
|
|
8
|
+
"title": "nous",
|
|
9
|
+
"author": "kaio",
|
|
10
|
+
"glyph": "⬡"
|
|
11
|
+
},
|
|
12
|
+
"compatibility": {
|
|
13
|
+
"eikon": ">=1 <2"
|
|
14
|
+
},
|
|
15
|
+
"legacy": {
|
|
16
|
+
"sourceFormat": "pre-launch .eikon draft",
|
|
17
|
+
"migration": "converted",
|
|
18
|
+
"notes": [
|
|
19
|
+
"moved legacy metadata: author, created, source_url"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"source": {
|
|
23
|
+
"base": "blobs/sha256/8c4dc411ca159253cc90fa31f5263799054592e6eaeb4e5c99881c8cac29e67b",
|
|
24
|
+
"states": {
|
|
25
|
+
"idle": {
|
|
26
|
+
"file": "blobs/sha256/481c010826d7cacb9c419455bd0f73d020f66492a1236b37e4e53353b7965902"
|
|
27
|
+
},
|
|
28
|
+
"listening": {
|
|
29
|
+
"file": "blobs/sha256/94f0f4f710c708f516128125142d5dce701f83558e9fad444c1bb376ee3c1fea"
|
|
30
|
+
},
|
|
31
|
+
"thinking": {
|
|
32
|
+
"file": "blobs/sha256/5ae0eb2e1889c72bed69144998acc6f80b9d11b67beffccd972842a9d6ed0f24"
|
|
33
|
+
},
|
|
34
|
+
"speaking": {
|
|
35
|
+
"file": "blobs/sha256/5c15fd3db3fba93b378eb5b23ab9ecf283e8fb5a08828f1393e91b323b65eab2"
|
|
36
|
+
},
|
|
37
|
+
"working": {
|
|
38
|
+
"file": "blobs/sha256/f63a864e84c4b4f672d6b02a4bcf610b2881fcf64166273b29a642fb76e00f09"
|
|
39
|
+
},
|
|
40
|
+
"error": {
|
|
41
|
+
"file": "blobs/sha256/5d1a1fa59ec9091d9c03d99728b15287ef58d397ea2c787a65c55519482683c8"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"entrypoints": {
|
|
46
|
+
"default": "nous.eikon"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
{
|
|
50
|
+
"path": "nous.eikon",
|
|
51
|
+
"role": "runtime",
|
|
52
|
+
"mediaType": "application/vnd.eikon.stream+jsonl",
|
|
53
|
+
"size": 139822,
|
|
54
|
+
"digest": "sha256:6a74e9ae20ecafe6cf268230272582ef618b31927cd13e11ce59ed8931413883",
|
|
55
|
+
"encoding": "gzip",
|
|
56
|
+
"decodedSize": 1401439,
|
|
57
|
+
"decodedDigest": "sha256:b2685743b05ddf201920b69db58640d4fab644e637fa7d313c6dfa215fa41fb7"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"path": "blobs/sha256/8c4dc411ca159253cc90fa31f5263799054592e6eaeb4e5c99881c8cac29e67b",
|
|
61
|
+
"role": "source.base",
|
|
62
|
+
"mediaType": "image/png",
|
|
63
|
+
"size": 98644,
|
|
64
|
+
"digest": "sha256:8c4dc411ca159253cc90fa31f5263799054592e6eaeb4e5c99881c8cac29e67b"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"path": "blobs/sha256/481c010826d7cacb9c419455bd0f73d020f66492a1236b37e4e53353b7965902",
|
|
68
|
+
"role": "source.clip",
|
|
69
|
+
"mediaType": "video/mp4",
|
|
70
|
+
"size": 105789,
|
|
71
|
+
"digest": "sha256:481c010826d7cacb9c419455bd0f73d020f66492a1236b37e4e53353b7965902",
|
|
72
|
+
"signal": "state.idle"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"path": "blobs/sha256/94f0f4f710c708f516128125142d5dce701f83558e9fad444c1bb376ee3c1fea",
|
|
76
|
+
"role": "source.clip",
|
|
77
|
+
"mediaType": "video/mp4",
|
|
78
|
+
"size": 275110,
|
|
79
|
+
"digest": "sha256:94f0f4f710c708f516128125142d5dce701f83558e9fad444c1bb376ee3c1fea",
|
|
80
|
+
"signal": "state.listening"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"path": "blobs/sha256/5ae0eb2e1889c72bed69144998acc6f80b9d11b67beffccd972842a9d6ed0f24",
|
|
84
|
+
"role": "source.clip",
|
|
85
|
+
"mediaType": "video/mp4",
|
|
86
|
+
"size": 174520,
|
|
87
|
+
"digest": "sha256:5ae0eb2e1889c72bed69144998acc6f80b9d11b67beffccd972842a9d6ed0f24",
|
|
88
|
+
"signal": "state.thinking"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"path": "blobs/sha256/5c15fd3db3fba93b378eb5b23ab9ecf283e8fb5a08828f1393e91b323b65eab2",
|
|
92
|
+
"role": "source.clip",
|
|
93
|
+
"mediaType": "video/mp4",
|
|
94
|
+
"size": 96790,
|
|
95
|
+
"digest": "sha256:5c15fd3db3fba93b378eb5b23ab9ecf283e8fb5a08828f1393e91b323b65eab2",
|
|
96
|
+
"signal": "state.speaking"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"path": "blobs/sha256/f63a864e84c4b4f672d6b02a4bcf610b2881fcf64166273b29a642fb76e00f09",
|
|
100
|
+
"role": "source.clip",
|
|
101
|
+
"mediaType": "video/mp4",
|
|
102
|
+
"size": 160072,
|
|
103
|
+
"digest": "sha256:f63a864e84c4b4f672d6b02a4bcf610b2881fcf64166273b29a642fb76e00f09",
|
|
104
|
+
"signal": "state.working"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"path": "blobs/sha256/5d1a1fa59ec9091d9c03d99728b15287ef58d397ea2c787a65c55519482683c8",
|
|
108
|
+
"role": "source.clip",
|
|
109
|
+
"mediaType": "video/mp4",
|
|
110
|
+
"size": 168804,
|
|
111
|
+
"digest": "sha256:5d1a1fa59ec9091d9c03d99728b15287ef58d397ea2c787a65c55519482683c8",
|
|
112
|
+
"signal": "state.error"
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"origin": {
|
|
116
|
+
"kind": "default-catalog",
|
|
117
|
+
"source": "https://eikon.liftaris.dev/packages/liftaris/nous/1.0.0.json",
|
|
118
|
+
"sourceKey": "registry:eikon.liftaris.dev:liftaris/nous@1.0.0",
|
|
119
|
+
"identityKey": "registry:eikon.liftaris.dev:liftaris/nous@1.0.0",
|
|
120
|
+
"packageUrl": "https://eikon.liftaris.dev/packages/liftaris/nous/1.0.0.json",
|
|
121
|
+
"trust": "verified"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
Binary file
|
|
@@ -1,17 +1,40 @@
|
|
|
1
|
-
"""Eikon
|
|
1
|
+
"""Eikon lifecycle plugin."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from .schemas import
|
|
6
|
-
|
|
5
|
+
from .schemas import (
|
|
6
|
+
EIKON_INSTALL_SCHEMA,
|
|
7
|
+
EIKON_LIST_SCHEMA,
|
|
8
|
+
EIKON_REMOVE_SCHEMA,
|
|
9
|
+
EIKON_SEARCH_SCHEMA,
|
|
10
|
+
EIKON_UPDATE_SCHEMA,
|
|
11
|
+
EIKON_USE_SCHEMA,
|
|
12
|
+
)
|
|
13
|
+
from .tools import (
|
|
14
|
+
_handle_eikon_install,
|
|
15
|
+
_handle_eikon_list,
|
|
16
|
+
_handle_eikon_remove,
|
|
17
|
+
_handle_eikon_search,
|
|
18
|
+
_handle_eikon_update,
|
|
19
|
+
_handle_eikon_use,
|
|
20
|
+
check_herm_available,
|
|
21
|
+
)
|
|
7
22
|
|
|
8
23
|
|
|
9
24
|
def register(ctx) -> None:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
for name, schema, handler in [
|
|
26
|
+
("eikon_install", EIKON_INSTALL_SCHEMA, _handle_eikon_install),
|
|
27
|
+
("eikon_search", EIKON_SEARCH_SCHEMA, _handle_eikon_search),
|
|
28
|
+
("eikon_list", EIKON_LIST_SCHEMA, _handle_eikon_list),
|
|
29
|
+
("eikon_use", EIKON_USE_SCHEMA, _handle_eikon_use),
|
|
30
|
+
("eikon_update", EIKON_UPDATE_SCHEMA, _handle_eikon_update),
|
|
31
|
+
("eikon_remove", EIKON_REMOVE_SCHEMA, _handle_eikon_remove),
|
|
32
|
+
]:
|
|
33
|
+
ctx.register_tool(
|
|
34
|
+
name=name,
|
|
35
|
+
toolset="eikon",
|
|
36
|
+
schema=schema,
|
|
37
|
+
handler=handler,
|
|
38
|
+
check_fn=check_herm_available,
|
|
39
|
+
emoji="⬡",
|
|
40
|
+
)
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
name: eikon
|
|
2
2
|
version: 1.0.0
|
|
3
|
-
description: "Herm eikon
|
|
3
|
+
description: "Herm eikon lifecycle tools. Lets Hermes chat search, install, activate, update, and remove terminal avatars through the existing `herm eikon` CLI path."
|
|
4
4
|
author: Liftaris
|
|
5
5
|
kind: standalone
|
|
6
6
|
provides_tools:
|
|
7
7
|
- eikon_install
|
|
8
|
+
- eikon_search
|
|
9
|
+
- eikon_list
|
|
10
|
+
- eikon_use
|
|
11
|
+
- eikon_update
|
|
12
|
+
- eikon_remove
|
|
@@ -7,7 +7,7 @@ EIKON_INSTALL_SCHEMA = {
|
|
|
7
7
|
"description": (
|
|
8
8
|
"Install a Herm eikon/avatar from the public catalog, a manifest URL, "
|
|
9
9
|
"a git repository, or a local directory. Uses `herm eikon install`; "
|
|
10
|
-
"
|
|
10
|
+
"set_active activates the installed avatar with `herm eikon use`."
|
|
11
11
|
),
|
|
12
12
|
"parameters": {
|
|
13
13
|
"type": "object",
|
|
@@ -32,10 +32,78 @@ EIKON_INSTALL_SCHEMA = {
|
|
|
32
32
|
},
|
|
33
33
|
"set_active": {
|
|
34
34
|
"type": "boolean",
|
|
35
|
-
"description": "
|
|
35
|
+
"description": "Activate the installed eikon after install. Default true.",
|
|
36
36
|
"default": True,
|
|
37
37
|
},
|
|
38
|
+
"active_ok": {
|
|
39
|
+
"type": "boolean",
|
|
40
|
+
"description": "Allow replacing the active eikon's backing package when installing over it.",
|
|
41
|
+
"default": False,
|
|
42
|
+
},
|
|
38
43
|
},
|
|
39
44
|
"required": ["source"],
|
|
40
45
|
},
|
|
41
46
|
}
|
|
47
|
+
|
|
48
|
+
EIKON_SEARCH_SCHEMA = {
|
|
49
|
+
"name": "eikon_search",
|
|
50
|
+
"description": "Search the Herm eikon marketplace/catalog via `herm eikon search --json`.",
|
|
51
|
+
"parameters": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": {
|
|
54
|
+
"query": {"type": "string", "description": "Optional search query."},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
EIKON_LIST_SCHEMA = {
|
|
60
|
+
"name": "eikon_list",
|
|
61
|
+
"description": "List installed Herm eikons via `herm eikon list --json`.",
|
|
62
|
+
"parameters": {"type": "object", "properties": {}},
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
EIKON_USE_SCHEMA = {
|
|
66
|
+
"name": "eikon_use",
|
|
67
|
+
"description": "Set an installed or bundled Herm eikon as active via `herm eikon use --json`.",
|
|
68
|
+
"parameters": {
|
|
69
|
+
"type": "object",
|
|
70
|
+
"properties": {
|
|
71
|
+
"name": {"type": "string", "description": "Installed or bundled eikon name."},
|
|
72
|
+
},
|
|
73
|
+
"required": ["name"],
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
EIKON_UPDATE_SCHEMA = {
|
|
78
|
+
"name": "eikon_update",
|
|
79
|
+
"description": "Update an installed Herm eikon from its recorded source via `herm eikon update --json`.",
|
|
80
|
+
"parameters": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"properties": {
|
|
83
|
+
"name": {"type": "string", "description": "Installed eikon name."},
|
|
84
|
+
"active_ok": {
|
|
85
|
+
"type": "boolean",
|
|
86
|
+
"description": "Allow updating the active avatar's backing package.",
|
|
87
|
+
"default": False,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
"required": ["name"],
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
EIKON_REMOVE_SCHEMA = {
|
|
95
|
+
"name": "eikon_remove",
|
|
96
|
+
"description": "Remove an installed Herm eikon via `herm eikon remove --json`.",
|
|
97
|
+
"parameters": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"properties": {
|
|
100
|
+
"name": {"type": "string", "description": "Installed eikon name."},
|
|
101
|
+
"active_ok": {
|
|
102
|
+
"type": "boolean",
|
|
103
|
+
"description": "Allow clearing the active avatar if this eikon is active.",
|
|
104
|
+
"default": False,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
"required": ["name"],
|
|
108
|
+
},
|
|
109
|
+
}
|
|
@@ -30,40 +30,96 @@ def check_herm_available() -> bool:
|
|
|
30
30
|
return shutil.which(binary) is not None
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def
|
|
34
|
-
source = str(args.get("source") or "").strip()
|
|
35
|
-
if not source:
|
|
36
|
-
return _json({"ok": False, "error": "source is required"})
|
|
37
|
-
|
|
33
|
+
def _run(parts: list[str], label: str, timeout: int = 120) -> dict[str, Any]:
|
|
38
34
|
binary = _herm_bin()
|
|
39
35
|
if not binary:
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
cmd = [binary, "eikon", "install", source, "--json"]
|
|
43
|
-
name = str(args.get("name") or "").strip()
|
|
44
|
-
if name:
|
|
45
|
-
cmd.extend(["--name", name])
|
|
46
|
-
if args.get("media") is False or args.get("no_source") is True:
|
|
47
|
-
cmd.append("--no-source")
|
|
48
|
-
if args.get("set_active") is False:
|
|
49
|
-
cmd.append("--no-use")
|
|
36
|
+
return {"ok": False, "error": "herm executable not found on PATH"}
|
|
50
37
|
|
|
51
38
|
try:
|
|
52
|
-
proc = subprocess.run(
|
|
39
|
+
proc = subprocess.run([binary, *parts], capture_output=True, text=True, timeout=timeout, check=False)
|
|
53
40
|
except FileNotFoundError:
|
|
54
|
-
return
|
|
41
|
+
return {"ok": False, "error": f"herm executable not found: {binary}"}
|
|
55
42
|
except subprocess.TimeoutExpired:
|
|
56
|
-
return
|
|
43
|
+
return {"ok": False, "error": f"herm eikon {label} timed out"}
|
|
57
44
|
|
|
58
45
|
stdout = (proc.stdout or "").strip()
|
|
59
46
|
stderr = (proc.stderr or "").strip()
|
|
60
47
|
if proc.returncode != 0:
|
|
61
48
|
detail = stderr or stdout or f"exit {proc.returncode}"
|
|
62
|
-
return
|
|
49
|
+
return {"ok": False, "error": f"herm eikon {label} failed: {detail}"}
|
|
63
50
|
|
|
64
51
|
line = next((ln for ln in reversed(stdout.splitlines()) if ln.strip()), "")
|
|
65
52
|
try:
|
|
66
53
|
payload = json.loads(line)
|
|
67
54
|
except json.JSONDecodeError:
|
|
68
|
-
return
|
|
69
|
-
|
|
55
|
+
return {"ok": False, "error": f"herm eikon {label} returned non-JSON output", "output": stdout}
|
|
56
|
+
if isinstance(payload, dict):
|
|
57
|
+
return payload
|
|
58
|
+
return {"ok": True, "result": payload}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _name(args: dict[str, Any]) -> str:
|
|
62
|
+
return str(args.get("name") or "").strip()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _handle_eikon_install(args: dict[str, Any], **_: Any) -> str:
|
|
66
|
+
source = str(args.get("source") or "").strip()
|
|
67
|
+
if not source:
|
|
68
|
+
return _json({"ok": False, "error": "source is required"})
|
|
69
|
+
|
|
70
|
+
cmd = ["eikon", "install", source, "--json"]
|
|
71
|
+
name = _name(args)
|
|
72
|
+
if name:
|
|
73
|
+
cmd.extend(["--name", name])
|
|
74
|
+
if args.get("media") is False or args.get("no_source") is True:
|
|
75
|
+
cmd.append("--no-source")
|
|
76
|
+
if args.get("active_ok") is True:
|
|
77
|
+
cmd.append("--active-ok")
|
|
78
|
+
|
|
79
|
+
payload = _run(cmd, "install")
|
|
80
|
+
if not payload.get("ok") or args.get("set_active") is False:
|
|
81
|
+
return _json(payload)
|
|
82
|
+
|
|
83
|
+
active = _run(["eikon", "use", str(payload.get("name") or source), "--json"], "use")
|
|
84
|
+
if not active.get("ok"):
|
|
85
|
+
return _json({"ok": False, "installed": payload, "error": f"installed but activation failed: {active.get('error', 'unknown error')}"})
|
|
86
|
+
return _json({**payload, "active": active.get("active")})
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _handle_eikon_search(args: dict[str, Any], **_: Any) -> str:
|
|
90
|
+
query = str(args.get("query") or "").strip()
|
|
91
|
+
cmd = ["eikon", "search"]
|
|
92
|
+
if query:
|
|
93
|
+
cmd.append(query)
|
|
94
|
+
return _json(_run([*cmd, "--json"], "search"))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _handle_eikon_list(args: dict[str, Any], **_: Any) -> str:
|
|
98
|
+
return _json(_run(["eikon", "list", "--json"], "list"))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _handle_eikon_use(args: dict[str, Any], **_: Any) -> str:
|
|
102
|
+
name = _name(args)
|
|
103
|
+
if not name:
|
|
104
|
+
return _json({"ok": False, "error": "name is required"})
|
|
105
|
+
return _json(_run(["eikon", "use", name, "--json"], "use"))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _handle_eikon_update(args: dict[str, Any], **_: Any) -> str:
|
|
109
|
+
name = _name(args)
|
|
110
|
+
if not name:
|
|
111
|
+
return _json({"ok": False, "error": "name is required"})
|
|
112
|
+
cmd = ["eikon", "update", name, "--json"]
|
|
113
|
+
if args.get("active_ok") is True:
|
|
114
|
+
cmd.append("--active-ok")
|
|
115
|
+
return _json(_run(cmd, "update"))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _handle_eikon_remove(args: dict[str, Any], **_: Any) -> str:
|
|
119
|
+
name = _name(args)
|
|
120
|
+
if not name:
|
|
121
|
+
return _json({"ok": False, "error": "name is required"})
|
|
122
|
+
cmd = ["eikon", "remove", name, "--json"]
|
|
123
|
+
if args.get("active_ok") is True:
|
|
124
|
+
cmd.append("--active-ok")
|
|
125
|
+
return _json(_run(cmd, "remove"))
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eikon
|
|
3
|
-
description:
|
|
3
|
+
description: Use when helping a user create, edit, install, activate, update, remove, or share a Herm eikon through the built-in Eikon tab or the `herm eikon` CLI.
|
|
4
|
+
tags: [eikon, avatar, herm]
|
|
4
5
|
related_skills: [eikon-create]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
|
-
# Building
|
|
8
|
+
# Building and managing eikons in Herm
|
|
8
9
|
|
|
9
|
-
An eikon is a 48×24 monochrome text avatar. It lives
|
|
10
|
+
An eikon is a 48×24 monochrome text avatar. It lives in the active
|
|
11
|
+
Hermes profile, normally:
|
|
10
12
|
|
|
11
13
|
~/.hermes/eikons/<name>/
|
|
12
|
-
<name>.eikon packed NDJSON — written by Studio on Ctrl+S
|
|
14
|
+
<name>.eikon packed NDJSON — written by Studio on Ctrl+S / Ctrl+U
|
|
13
15
|
studio.json Studio's workspace state
|
|
14
16
|
source/ base.<ext>, <state>.<ext>
|
|
15
17
|
|
|
@@ -17,32 +19,99 @@ You do **not** write `.eikon` or `studio.json`. Studio does.
|
|
|
17
19
|
|
|
18
20
|
## Where the user does the work
|
|
19
21
|
|
|
20
|
-
Herm's built-in **Eikon** tab
|
|
21
|
-
the Eikon tab" or "Ctrl+K → Eikon". In Studio:
|
|
22
|
+
Herm's built-in **Eikon** tab has **Library / Catalog / Studio**:
|
|
22
23
|
|
|
23
|
-
-
|
|
24
|
-
|
|
24
|
+
- **Library** — local and bundled eikons; use, edit, update, share, delete,
|
|
25
|
+
and New/install entry points.
|
|
26
|
+
- **Catalog** — shared catalog; install runtime-only, install with source,
|
|
27
|
+
use installed eikons, download source, uninstall, or delist when eligible.
|
|
28
|
+
- **Studio** — edit an existing local/source draft eikon and bake it.
|
|
29
|
+
|
|
30
|
+
Tell the user: "open the Eikon tab"; `/library`, `/catalog`, and `/studio`
|
|
31
|
+
jump directly to the Eikon sub-tabs. In Studio:
|
|
32
|
+
|
|
33
|
+
- `eikon` row → pick an eikon, `+ New…`, or `+ Install…`
|
|
34
|
+
- `source` row → local/downloaded source; Generate rows appear only when the
|
|
35
|
+
corresponding Hermes generation backend is configured
|
|
25
36
|
- `input` section → contrast / invert / flip (pixel-domain, shared)
|
|
26
|
-
- `<rasterizer>` section →
|
|
27
|
-
|
|
28
|
-
-
|
|
37
|
+
- `<rasterizer>` section → rasterizer-specific glyph knobs, e.g. chafa
|
|
38
|
+
symbols/fill/dither or native symbols
|
|
39
|
+
- Preview pane → wheel pans Y, Shift+wheel pans X, Ctrl+wheel zooms; drag the
|
|
40
|
+
pan bars to scrub pan
|
|
41
|
+
- **Ctrl+S** bakes all six states without changing the active avatar
|
|
42
|
+
- **Ctrl+U** bakes all six states and uses it as the active avatar
|
|
43
|
+
- `u` in Studio opens the Submit eikon dialog; `s` in Library opens Share to
|
|
44
|
+
catalog for local unpublished eikons
|
|
29
45
|
|
|
30
46
|
## What makes a good source
|
|
31
47
|
|
|
32
|
-
One line, once: **48×24, one color. Light subject on black, high
|
|
33
|
-
|
|
34
|
-
everything.
|
|
48
|
+
One line, once: **48×24, one color. Light subject on black, high contrast,
|
|
49
|
+
strong silhouette.** Fine detail disappears; outline is everything.
|
|
35
50
|
|
|
36
51
|
## When to do what
|
|
37
52
|
|
|
38
53
|
| user says | you do |
|
|
39
54
|
|---|---|
|
|
40
55
|
| "make me an eikon of X" | Load `eikon-create` and follow it. |
|
|
41
|
-
| drops an image path |
|
|
42
|
-
| "edit my <name> eikon" | "Eikon
|
|
56
|
+
| drops an image path | Copy it to `${HERMES_HOME:-$HOME/.hermes}/eikons/<name>/source/base.<ext>` or use Library → New… → local file, then Studio → `eikon` row → `<name>`. |
|
|
57
|
+
| "edit my <name> eikon" | "Eikon → Studio → `eikon` row → `<name>`." |
|
|
58
|
+
| "install/shared catalog eikon" | "Eikon → Catalog" or `/catalog`. Choose Eikon only or Eikon + Source, then Use when ready. |
|
|
59
|
+
| "install from GitHub / URL / dir" | "Studio → `eikon` row → `+ Install…`", "Library → New… → inspect/install", or `herm eikon install <name|url|dir>`. |
|
|
43
60
|
| "too dark / washed out" | "invert toggle, then contrast slider — under `input`." |
|
|
44
|
-
| "off-center / too small" | "Ctrl+wheel
|
|
45
|
-
| "make it move" | `eikon-create` §5 (video), or Studio's `source` → Generate video
|
|
61
|
+
| "off-center / too small" | "Ctrl+wheel zooms; wheel/Shift+wheel pans; drag pan bars for precise pan." |
|
|
62
|
+
| "make it move" | `eikon-create` §5 (video), or Studio's `source` row → Generate video… if available. |
|
|
63
|
+
| "publish/share my eikon" | "After baking, press `u` in Studio or `s` in Library. Review metadata, bundle, and GitHub PR target before submitting." |
|
|
64
|
+
| "remove from official catalog" | Use Catalog → Delist from Registry when eligible, or `herm eikon delist <name|id>`. |
|
|
65
|
+
|
|
66
|
+
## Install and manage shared eikons
|
|
67
|
+
|
|
68
|
+
For catalog eikons, use **Eikon → Catalog**. Rows show source,
|
|
69
|
+
compatibility, trust (`Verified`, `Unverified`, or `Mismatch`), digest,
|
|
70
|
+
and installed/active state. Catalog installs fetch built package artifacts;
|
|
71
|
+
they do not clone creator repos.
|
|
72
|
+
|
|
73
|
+
Default install is **Eikon only**: runtime package, no activation, no editable
|
|
74
|
+
source. Choose **Eikon + Source**, or later **Download Source**, when the user
|
|
75
|
+
wants to edit it in Studio.
|
|
76
|
+
|
|
77
|
+
For direct sharing, use `github.com/user/repo/eikon-name` for a multi-eikon
|
|
78
|
+
GitHub catalog repo, `github.com/user/repo` for a single-package repo, a git or
|
|
79
|
+
HTTP URL, or a local package directory. Private GitHub repos use normal git
|
|
80
|
+
authentication.
|
|
81
|
+
|
|
82
|
+
The local lifecycle is explicit:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
herm eikon search [query] [--json]
|
|
86
|
+
herm eikon browse [query] [--json]
|
|
87
|
+
herm eikon inspect <name|url|dir> [--json]
|
|
88
|
+
herm eikon install <name|url|dir> [--name N] [--no-source] [--active-ok] [--json]
|
|
89
|
+
herm eikon list [--json]
|
|
90
|
+
herm eikon use <name> [--json]
|
|
91
|
+
herm eikon info <name> [--json]
|
|
92
|
+
herm eikon update <name> [--active-ok] [--json]
|
|
93
|
+
herm eikon remove <name> [--active-ok] [--json]
|
|
94
|
+
herm eikon delist <name|id> [--json]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`install` does not activate. If the installed name is currently active,
|
|
98
|
+
installing replaces the active avatar's backing package and requires
|
|
99
|
+
`--active-ok`. `use` activates. Updating or removing the active eikon also
|
|
100
|
+
requires `--active-ok`.
|
|
101
|
+
|
|
102
|
+
Creators share through normal GitHub repositories. For official registry
|
|
103
|
+
listing, use `u` in Studio or Library → Share to catalog after baking: Herm
|
|
104
|
+
runs registry preflight, asks for title/author/description/glyph, previews the
|
|
105
|
+
public bundle, then creates a GitHub PR through local `gh` auth or gives manual
|
|
106
|
+
PR instructions.
|
|
107
|
+
Use upstream `eikon pack`, `eikon index`, and `eikon manifest` for
|
|
108
|
+
direct-install repos. `eikon publish` is the lower-level GitHub PR contribution
|
|
109
|
+
helper for the configured/default catalog repo, not a hosted account, upload,
|
|
110
|
+
dashboard, or moderation flow.
|
|
111
|
+
|
|
112
|
+
Browser catalog surfaces such as `eikon.liftaris.dev` are discovery-only: they
|
|
113
|
+
preview catalog entries and give copyable `herm eikon install …` instructions.
|
|
114
|
+
Do not imply a browser click installs, activates, authenticates, or mutates Herm.
|
|
46
115
|
|
|
47
116
|
## Quick poster
|
|
48
117
|
|
|
@@ -52,10 +121,14 @@ To show a candidate in chat without Studio:
|
|
|
52
121
|
chafa --size=48x24 --symbols=braille --colors=none --format=symbols --stretch "<path>"
|
|
53
122
|
```
|
|
54
123
|
|
|
55
|
-
Preview-only; Studio's output will differ
|
|
124
|
+
Preview-only; Studio's output will differ because it tone-maps first.
|
|
56
125
|
|
|
57
126
|
## Don'ts
|
|
58
127
|
|
|
59
128
|
- Don't hand-write `.eikon` NDJSON.
|
|
60
129
|
- Don't pick knob values for the user. Name the knob.
|
|
61
130
|
- Don't repeat the 48×24 brief.
|
|
131
|
+
- Don't say install activates. Install only writes the local package; Use
|
|
132
|
+
activates.
|
|
133
|
+
- Don't describe hosted marketplace accounts, upload tokens, dashboards, or
|
|
134
|
+
browser-native install flows for the v1 registry.
|