agent-first-data 0.13.2__tar.gz → 0.14.0__tar.gz
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.
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/PKG-INFO +5 -5
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/README.md +4 -4
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data/skill.py +24 -16
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data.egg-info/PKG-INFO +5 -5
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/pyproject.toml +1 -1
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/tests/test_skill.py +36 -9
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data/__init__.py +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data/afdata_logging.py +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data/cli.py +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data/format.py +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data.egg-info/SOURCES.txt +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data.egg-info/dependency_links.txt +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data.egg-info/top_level.txt +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/setup.cfg +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/tests/test_afdata_logging.py +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/tests/test_cli.py +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/tests/test_format.py +0 -0
- {agent_first_data-0.13.2 → agent_first_data-0.14.0}/tests/test_no_stderr_policy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-first-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: A naming convention that lets AI agents understand your data without being told what it means.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/agentfirstkit/agent-first-data
|
|
@@ -50,7 +50,7 @@ init_logging_json("INFO", secret_names=("authorization",))
|
|
|
50
50
|
|
|
51
51
|
## Reference
|
|
52
52
|
|
|
53
|
-
- Full convention and API groups: [
|
|
54
|
-
- Formal cross-language contract: [
|
|
55
|
-
- Conformance fixtures: [
|
|
56
|
-
- Agent skill: [
|
|
53
|
+
- Full convention and API groups: [docs/overview.md](https://github.com/agentfirstkit/agent-first-data/blob/main/docs/overview.md)
|
|
54
|
+
- Formal cross-language contract: [spec/agent-first-data.md](https://github.com/agentfirstkit/agent-first-data/blob/main/spec/agent-first-data.md)
|
|
55
|
+
- Conformance fixtures: [spec/fixtures](https://github.com/agentfirstkit/agent-first-data/tree/main/spec/fixtures)
|
|
56
|
+
- Agent skill: [skills/agent-first-data.md](https://github.com/agentfirstkit/agent-first-data/blob/main/skills/agent-first-data.md)
|
|
@@ -41,7 +41,7 @@ init_logging_json("INFO", secret_names=("authorization",))
|
|
|
41
41
|
|
|
42
42
|
## Reference
|
|
43
43
|
|
|
44
|
-
- Full convention and API groups: [
|
|
45
|
-
- Formal cross-language contract: [
|
|
46
|
-
- Conformance fixtures: [
|
|
47
|
-
- Agent skill: [
|
|
44
|
+
- Full convention and API groups: [docs/overview.md](https://github.com/agentfirstkit/agent-first-data/blob/main/docs/overview.md)
|
|
45
|
+
- Formal cross-language contract: [spec/agent-first-data.md](https://github.com/agentfirstkit/agent-first-data/blob/main/spec/agent-first-data.md)
|
|
46
|
+
- Conformance fixtures: [spec/fixtures](https://github.com/agentfirstkit/agent-first-data/tree/main/spec/fixtures)
|
|
47
|
+
- Agent skill: [skills/agent-first-data.md](https://github.com/agentfirstkit/agent-first-data/blob/main/skills/agent-first-data.md)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A spore that embeds its ``SKILL.md`` describes itself with a :class:`SkillSpec` and
|
|
4
4
|
calls :func:`run_skill_admin` to install, uninstall, or report status of that skill
|
|
5
|
-
across supported coding agents (Codex, Claude Code, opencode).
|
|
5
|
+
across supported coding agents (Codex, Claude Code, opencode, Hermes).
|
|
6
6
|
|
|
7
7
|
The function performs the filesystem work and returns the protocol ``dict`` (rendered
|
|
8
8
|
by the caller with ``cli_output``) or raises :class:`SkillError`. It never writes to
|
|
@@ -52,7 +52,7 @@ class SkillScope(enum.Enum):
|
|
|
52
52
|
"""Where to install the skill."""
|
|
53
53
|
|
|
54
54
|
PERSONAL = "personal"
|
|
55
|
-
|
|
55
|
+
WORKSPACE = "workspace"
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
class SkillAgentSelection(enum.Enum):
|
|
@@ -62,6 +62,7 @@ class SkillAgentSelection(enum.Enum):
|
|
|
62
62
|
CODEX = "codex"
|
|
63
63
|
CLAUDE_CODE = "claude-code"
|
|
64
64
|
OPENCODE = "opencode"
|
|
65
|
+
HERMES = "hermes"
|
|
65
66
|
|
|
66
67
|
|
|
67
68
|
class SkillAgent(enum.Enum):
|
|
@@ -70,6 +71,7 @@ class SkillAgent(enum.Enum):
|
|
|
70
71
|
CODEX = "codex"
|
|
71
72
|
CLAUDE_CODE = "claude-code"
|
|
72
73
|
OPENCODE = "opencode"
|
|
74
|
+
HERMES = "hermes"
|
|
73
75
|
|
|
74
76
|
|
|
75
77
|
@dataclass
|
|
@@ -310,24 +312,23 @@ def _resolve_targets(spec: SkillSpec, options: SkillOptions) -> list[_SkillTarge
|
|
|
310
312
|
_resolve_target(spec, SkillAgent.CODEX, SkillScope.PERSONAL, None),
|
|
311
313
|
_resolve_target(spec, SkillAgent.CLAUDE_CODE, SkillScope.PERSONAL, None),
|
|
312
314
|
_resolve_target(spec, SkillAgent.OPENCODE, SkillScope.PERSONAL, None),
|
|
315
|
+
_resolve_target(spec, SkillAgent.HERMES, SkillScope.PERSONAL, None),
|
|
313
316
|
]
|
|
314
|
-
|
|
315
|
-
if agent is SkillAgentSelection.ALL and scope is SkillScope.PROJECT:
|
|
317
|
+
if agent is SkillAgentSelection.ALL and scope is SkillScope.WORKSPACE:
|
|
316
318
|
return [
|
|
317
|
-
_resolve_target(spec, SkillAgent.
|
|
318
|
-
_resolve_target(spec, SkillAgent.
|
|
319
|
+
_resolve_target(spec, SkillAgent.CODEX, SkillScope.WORKSPACE, None),
|
|
320
|
+
_resolve_target(spec, SkillAgent.CLAUDE_CODE, SkillScope.WORKSPACE, None),
|
|
321
|
+
_resolve_target(spec, SkillAgent.OPENCODE, SkillScope.WORKSPACE, None),
|
|
322
|
+
_resolve_target(spec, SkillAgent.HERMES, SkillScope.WORKSPACE, None),
|
|
319
323
|
]
|
|
320
|
-
if agent is SkillAgentSelection.CODEX and scope is SkillScope.PROJECT:
|
|
321
|
-
raise SkillError(
|
|
322
|
-
"Codex project skill scope is not supported",
|
|
323
|
-
"use personal scope for Codex, or --agent claude-code/opencode --scope project",
|
|
324
|
-
)
|
|
325
324
|
if agent is SkillAgentSelection.CODEX:
|
|
326
|
-
return [_resolve_target(spec, SkillAgent.CODEX,
|
|
325
|
+
return [_resolve_target(spec, SkillAgent.CODEX, scope, options.skills_dir)]
|
|
327
326
|
if agent is SkillAgentSelection.CLAUDE_CODE:
|
|
328
327
|
return [_resolve_target(spec, SkillAgent.CLAUDE_CODE, scope, options.skills_dir)]
|
|
329
328
|
if agent is SkillAgentSelection.OPENCODE:
|
|
330
329
|
return [_resolve_target(spec, SkillAgent.OPENCODE, scope, options.skills_dir)]
|
|
330
|
+
if agent is SkillAgentSelection.HERMES:
|
|
331
|
+
return [_resolve_target(spec, SkillAgent.HERMES, scope, options.skills_dir)]
|
|
331
332
|
raise SkillError(f"invalid --agent {agent!r}")
|
|
332
333
|
|
|
333
334
|
|
|
@@ -350,23 +351,30 @@ def _resolve_target(
|
|
|
350
351
|
|
|
351
352
|
def _default_skills_dir(agent: SkillAgent, scope: SkillScope) -> Path:
|
|
352
353
|
if agent is SkillAgent.CODEX:
|
|
353
|
-
if scope is SkillScope.
|
|
354
|
-
|
|
354
|
+
if scope is not SkillScope.PERSONAL:
|
|
355
|
+
return Path.cwd() / ".codex" / "skills"
|
|
355
356
|
codex_home = os.environ.get("CODEX_HOME")
|
|
356
357
|
if codex_home is not None:
|
|
357
358
|
return Path(codex_home) / "skills"
|
|
358
359
|
return _home_dir() / ".codex" / "skills"
|
|
359
360
|
if agent is SkillAgent.CLAUDE_CODE:
|
|
360
|
-
if scope is SkillScope.
|
|
361
|
+
if scope is not SkillScope.PERSONAL:
|
|
361
362
|
return Path.cwd() / ".claude" / "skills"
|
|
362
363
|
return _home_dir() / ".claude" / "skills"
|
|
363
364
|
if agent is SkillAgent.OPENCODE:
|
|
364
|
-
if scope is SkillScope.
|
|
365
|
+
if scope is not SkillScope.PERSONAL:
|
|
365
366
|
return Path.cwd() / ".opencode" / "skills"
|
|
366
367
|
xdg = os.environ.get("XDG_CONFIG_HOME")
|
|
367
368
|
if xdg is not None:
|
|
368
369
|
return Path(xdg) / "opencode" / "skills"
|
|
369
370
|
return _home_dir() / ".config" / "opencode" / "skills"
|
|
371
|
+
if agent is SkillAgent.HERMES:
|
|
372
|
+
if scope is not SkillScope.PERSONAL:
|
|
373
|
+
return Path.cwd() / ".hermes" / "skills"
|
|
374
|
+
hermes_home = os.environ.get("HERMES_HOME")
|
|
375
|
+
if hermes_home is not None:
|
|
376
|
+
return Path(hermes_home) / "skills"
|
|
377
|
+
return _home_dir() / ".hermes" / "skills"
|
|
370
378
|
raise SkillError(f"unknown agent {agent!r}")
|
|
371
379
|
|
|
372
380
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-first-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: A naming convention that lets AI agents understand your data without being told what it means.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/agentfirstkit/agent-first-data
|
|
@@ -50,7 +50,7 @@ init_logging_json("INFO", secret_names=("authorization",))
|
|
|
50
50
|
|
|
51
51
|
## Reference
|
|
52
52
|
|
|
53
|
-
- Full convention and API groups: [
|
|
54
|
-
- Formal cross-language contract: [
|
|
55
|
-
- Conformance fixtures: [
|
|
56
|
-
- Agent skill: [
|
|
53
|
+
- Full convention and API groups: [docs/overview.md](https://github.com/agentfirstkit/agent-first-data/blob/main/docs/overview.md)
|
|
54
|
+
- Formal cross-language contract: [spec/agent-first-data.md](https://github.com/agentfirstkit/agent-first-data/blob/main/spec/agent-first-data.md)
|
|
55
|
+
- Conformance fixtures: [spec/fixtures](https://github.com/agentfirstkit/agent-first-data/tree/main/spec/fixtures)
|
|
56
|
+
- Agent skill: [skills/agent-first-data.md](https://github.com/agentfirstkit/agent-first-data/blob/main/skills/agent-first-data.md)
|
|
@@ -62,6 +62,7 @@ def test_rejects_unquoted_colon_space():
|
|
|
62
62
|
(SkillAgentSelection.CODEX, "codex"),
|
|
63
63
|
(SkillAgentSelection.CLAUDE_CODE, "claude-code"),
|
|
64
64
|
(SkillAgentSelection.OPENCODE, "opencode"),
|
|
65
|
+
(SkillAgentSelection.HERMES, "hermes"),
|
|
65
66
|
],
|
|
66
67
|
)
|
|
67
68
|
def test_install_status_uninstall(agent, expect, tmp_path):
|
|
@@ -218,22 +219,48 @@ def test_force_uninstall_removes_symlink_without_following(tmp_path):
|
|
|
218
219
|
assert external.read_text(encoding="utf-8") == "external"
|
|
219
220
|
|
|
220
221
|
|
|
221
|
-
def
|
|
222
|
+
def test_all_personal_resolves_four_targets():
|
|
222
223
|
opts = SkillOptions(agent=SkillAgentSelection.ALL, scope=SkillScope.PERSONAL)
|
|
223
224
|
targets = _resolve_targets(spec(), opts)
|
|
224
|
-
assert [t.agent for t in targets] == [
|
|
225
|
+
assert [t.agent for t in targets] == [
|
|
226
|
+
SkillAgent.CODEX,
|
|
227
|
+
SkillAgent.CLAUDE_CODE,
|
|
228
|
+
SkillAgent.OPENCODE,
|
|
229
|
+
SkillAgent.HERMES,
|
|
230
|
+
]
|
|
225
231
|
|
|
226
232
|
|
|
227
|
-
def
|
|
228
|
-
opts = SkillOptions(agent=SkillAgentSelection.ALL, scope=SkillScope.
|
|
233
|
+
def test_all_workspace_resolves_four_targets():
|
|
234
|
+
opts = SkillOptions(agent=SkillAgentSelection.ALL, scope=SkillScope.WORKSPACE)
|
|
229
235
|
targets = _resolve_targets(spec(), opts)
|
|
230
|
-
assert [t.agent for t in targets] == [
|
|
236
|
+
assert [t.agent for t in targets] == [
|
|
237
|
+
SkillAgent.CODEX,
|
|
238
|
+
SkillAgent.CLAUDE_CODE,
|
|
239
|
+
SkillAgent.OPENCODE,
|
|
240
|
+
SkillAgent.HERMES,
|
|
241
|
+
]
|
|
242
|
+
assert [t.scope for t in targets] == [
|
|
243
|
+
SkillScope.WORKSPACE,
|
|
244
|
+
SkillScope.WORKSPACE,
|
|
245
|
+
SkillScope.WORKSPACE,
|
|
246
|
+
SkillScope.WORKSPACE,
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def test_codex_workspace_scope_uses_codex_skills_dir():
|
|
251
|
+
opts = SkillOptions(agent=SkillAgentSelection.CODEX, scope=SkillScope.WORKSPACE)
|
|
252
|
+
targets = _resolve_targets(spec(), opts)
|
|
253
|
+
assert [t.agent for t in targets] == [SkillAgent.CODEX]
|
|
254
|
+
assert targets[0].scope is SkillScope.WORKSPACE
|
|
255
|
+
assert str(targets[0].skills_dir).endswith(".codex/skills")
|
|
231
256
|
|
|
232
257
|
|
|
233
|
-
def
|
|
234
|
-
opts = SkillOptions(agent=SkillAgentSelection.
|
|
235
|
-
|
|
236
|
-
|
|
258
|
+
def test_hermes_workspace_scope_uses_hermes_skills_dir():
|
|
259
|
+
opts = SkillOptions(agent=SkillAgentSelection.HERMES, scope=SkillScope.WORKSPACE)
|
|
260
|
+
targets = _resolve_targets(spec(), opts)
|
|
261
|
+
assert [t.agent for t in targets] == [SkillAgent.HERMES]
|
|
262
|
+
assert targets[0].scope is SkillScope.WORKSPACE
|
|
263
|
+
assert str(targets[0].skills_dir).endswith(".hermes/skills")
|
|
237
264
|
|
|
238
265
|
|
|
239
266
|
def test_skills_dir_requires_single_agent():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_first_data-0.13.2 → agent_first_data-0.14.0}/agent_first_data.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|