hermes-a365 0.1.1__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.
- hermes_a365-0.1.1/.gitignore +58 -0
- hermes_a365-0.1.1/CHANGELOG.md +154 -0
- hermes_a365-0.1.1/LICENSE +21 -0
- hermes_a365-0.1.1/PKG-INFO +622 -0
- hermes_a365-0.1.1/README.md +595 -0
- hermes_a365-0.1.1/SKILL.md +342 -0
- hermes_a365-0.1.1/pyproject.toml +84 -0
- hermes_a365-0.1.1/references/README.md +31 -0
- hermes_a365-0.1.1/src/hermes_a365/__init__.py +3 -0
- hermes_a365-0.1.1/src/hermes_a365/_common.py +204 -0
- hermes_a365-0.1.1/src/hermes_a365/_data/__init__.py +0 -0
- hermes_a365-0.1.1/src/hermes_a365/_data/templates/adaptive-cards/confirmation.json.j2 +29 -0
- hermes_a365-0.1.1/src/hermes_a365/_data/templates/adaptive-cards/error.json.j2 +30 -0
- hermes_a365-0.1.1/src/hermes_a365/_data/templates/adaptive-cards/greeting.json.j2 +34 -0
- hermes_a365-0.1.1/src/hermes_a365/_data/templates/blueprint.json.j2 +19 -0
- hermes_a365-0.1.1/src/hermes_a365/_data/templates/consent-url.txt.j2 +13 -0
- hermes_a365-0.1.1/src/hermes_a365/_data/templates/instance.env.j2 +16 -0
- hermes_a365-0.1.1/src/hermes_a365/a365_config.py +104 -0
- hermes_a365-0.1.1/src/hermes_a365/activity_bridge.py +1775 -0
- hermes_a365-0.1.1/src/hermes_a365/cleanup.py +600 -0
- hermes_a365-0.1.1/src/hermes_a365/cli.py +128 -0
- hermes_a365-0.1.1/src/hermes_a365/consent.py +261 -0
- hermes_a365-0.1.1/src/hermes_a365/doctor.py +422 -0
- hermes_a365-0.1.1/src/hermes_a365/emit_card.py +209 -0
- hermes_a365-0.1.1/src/hermes_a365/hermes_responder.py +385 -0
- hermes_a365-0.1.1/src/hermes_a365/instance_create.py +328 -0
- hermes_a365-0.1.1/src/hermes_a365/keychain.py +407 -0
- hermes_a365-0.1.1/src/hermes_a365/license.py +217 -0
- hermes_a365-0.1.1/src/hermes_a365/mutator.py +265 -0
- hermes_a365-0.1.1/src/hermes_a365/plugin/README.md +112 -0
- hermes_a365-0.1.1/src/hermes_a365/plugin/__init__.py +47 -0
- hermes_a365-0.1.1/src/hermes_a365/plugin/adapter.py +756 -0
- hermes_a365-0.1.1/src/hermes_a365/plugin/cli.py +142 -0
- hermes_a365-0.1.1/src/hermes_a365/plugin/conversations.py +213 -0
- hermes_a365-0.1.1/src/hermes_a365/plugin/plugin.yaml +17 -0
- hermes_a365-0.1.1/src/hermes_a365/publish.py +268 -0
- hermes_a365-0.1.1/src/hermes_a365/reconcile_app.py +183 -0
- hermes_a365-0.1.1/src/hermes_a365/reconcile_blueprint.py +147 -0
- hermes_a365-0.1.1/src/hermes_a365/register.py +687 -0
- hermes_a365-0.1.1/src/hermes_a365/render_instance_env.py +112 -0
- hermes_a365-0.1.1/src/hermes_a365/status.py +558 -0
- hermes_a365-0.1.1/tests/conftest.py +18 -0
- hermes_a365-0.1.1/tests/golden/adaptive-cards/confirmation_action_only.json +15 -0
- hermes_a365-0.1.1/tests/golden/adaptive-cards/confirmation_with_facts.json +33 -0
- hermes_a365-0.1.1/tests/golden/adaptive-cards/error_minimal.json +20 -0
- hermes_a365-0.1.1/tests/golden/adaptive-cards/error_with_detail.json +27 -0
- hermes_a365-0.1.1/tests/golden/adaptive-cards/greeting_minimal.json +19 -0
- hermes_a365-0.1.1/tests/golden/adaptive-cards/greeting_with_commands.json +36 -0
- hermes_a365-0.1.1/tests/golden/blueprint/minimal.json +25 -0
- hermes_a365-0.1.1/tests/golden/blueprint/with_workiq.json +31 -0
- hermes_a365-0.1.1/tests/golden/instance_env/minimal.env +7 -0
- hermes_a365-0.1.1/tests/golden/instance_env/with_business_hours.env +10 -0
- hermes_a365-0.1.1/tests/golden/license/addon_small_team.txt +15 -0
- hermes_a365-0.1.1/tests/golden/license/e7_large_team.txt +16 -0
- hermes_a365-0.1.1/tests/test_a365_config.py +138 -0
- hermes_a365-0.1.1/tests/test_activity_bridge.py +1555 -0
- hermes_a365-0.1.1/tests/test_agent365_plugin.py +1374 -0
- hermes_a365-0.1.1/tests/test_cleanup.py +772 -0
- hermes_a365-0.1.1/tests/test_common.py +196 -0
- hermes_a365-0.1.1/tests/test_consent.py +310 -0
- hermes_a365-0.1.1/tests/test_doctor.py +380 -0
- hermes_a365-0.1.1/tests/test_emit_card.py +266 -0
- hermes_a365-0.1.1/tests/test_hermes_responder.py +322 -0
- hermes_a365-0.1.1/tests/test_instance_create.py +264 -0
- hermes_a365-0.1.1/tests/test_keychain.py +405 -0
- hermes_a365-0.1.1/tests/test_license.py +249 -0
- hermes_a365-0.1.1/tests/test_mutator.py +208 -0
- hermes_a365-0.1.1/tests/test_publish.py +260 -0
- hermes_a365-0.1.1/tests/test_reconcile_app.py +192 -0
- hermes_a365-0.1.1/tests/test_reconcile_blueprint.py +136 -0
- hermes_a365-0.1.1/tests/test_register.py +724 -0
- hermes_a365-0.1.1/tests/test_render_instance_env.py +86 -0
- hermes_a365-0.1.1/tests/test_status.py +433 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Secrets / local config
|
|
2
|
+
.env
|
|
3
|
+
.env.*
|
|
4
|
+
!.env.example
|
|
5
|
+
*.pem
|
|
6
|
+
*.key
|
|
7
|
+
|
|
8
|
+
# A365 CLI runtime config — `a365.config.json` is operator-edited; the
|
|
9
|
+
# `*.generated.config.json` files emitted by `a365 setup blueprint`
|
|
10
|
+
# contain the agent blueprint client secret in plaintext on platforms
|
|
11
|
+
# where DPAPI is unavailable (macOS, Linux). Never commit.
|
|
12
|
+
#
|
|
13
|
+
# The trailing `*` also catches operator-suffixed snapshots
|
|
14
|
+
# (e.g. `a365.generated.config.json.r5-cleared`, `…json.bak`) so a
|
|
15
|
+
# stray `git add .` can't ship a tenant-shaped artefact.
|
|
16
|
+
a365.config.json*
|
|
17
|
+
a365.generated.config.json*
|
|
18
|
+
*.generated.config.json*
|
|
19
|
+
# Newcomers seed `a365.config.json` from this template — keep it tracked.
|
|
20
|
+
!a365.config.json.example
|
|
21
|
+
# `a365 cleanup -y` writes timestamped backups of the above files.
|
|
22
|
+
a365.config.backup-*.json
|
|
23
|
+
a365.generated.config.backup-*.json
|
|
24
|
+
# `a365 publish --aiteammate` extracts manifest templates + zips them
|
|
25
|
+
# under ./manifest/ as a build artefact (slice 19g, walkthrough finding).
|
|
26
|
+
# Regenerated each publish — keep it out of git.
|
|
27
|
+
manifest/
|
|
28
|
+
|
|
29
|
+
# Python
|
|
30
|
+
__pycache__/
|
|
31
|
+
*.py[cod]
|
|
32
|
+
*$py.class
|
|
33
|
+
*.egg-info/
|
|
34
|
+
.venv/
|
|
35
|
+
venv/
|
|
36
|
+
.pytest_cache/
|
|
37
|
+
.mypy_cache/
|
|
38
|
+
.ruff_cache/
|
|
39
|
+
|
|
40
|
+
# Node (in case templates/scripts pull anything)
|
|
41
|
+
node_modules/
|
|
42
|
+
|
|
43
|
+
# macOS
|
|
44
|
+
.DS_Store
|
|
45
|
+
._*
|
|
46
|
+
|
|
47
|
+
# Editors
|
|
48
|
+
.vscode/
|
|
49
|
+
.idea/
|
|
50
|
+
*.swp
|
|
51
|
+
|
|
52
|
+
# Build / dist
|
|
53
|
+
dist/
|
|
54
|
+
build/
|
|
55
|
+
|
|
56
|
+
# Local-only working files
|
|
57
|
+
local/
|
|
58
|
+
scratch/
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `hermes-a365` skill / plugin live here. Format
|
|
4
|
+
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions
|
|
5
|
+
follow [SemVer](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.1] — 2026-05-11
|
|
10
|
+
|
|
11
|
+
Repackaging-only release: `hermes-a365` is now `pip install`-able from
|
|
12
|
+
PyPI. No behavioural changes; the apply paths, read paths, and Bot
|
|
13
|
+
Framework activity bridge are identical to `v0.1.0`.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Distribution.** Source tree moved to a real `src/hermes_a365/`
|
|
18
|
+
layout. `[tool.uv] package = false` is gone; the wheel is built via
|
|
19
|
+
`hatchling` and published to PyPI. Two install paths now supported:
|
|
20
|
+
- **Standalone CLI:** `pipx install 'hermes-a365[bridge]'` exposes a
|
|
21
|
+
`hermes-a365 <verb>` console script for operators who drive the
|
|
22
|
+
wrappers without spinning up a Hermes gateway.
|
|
23
|
+
- **Gateway plugin:** `~/.hermes/hermes-agent/venv/bin/pip install
|
|
24
|
+
'hermes-a365[bridge]'`. The Hermes plugin loader auto-discovers
|
|
25
|
+
`agent365` via the `hermes_agent.plugins` entry point — no
|
|
26
|
+
`~/.hermes/plugins/agent365/` directory, no symlink.
|
|
27
|
+
- **Imports.** Every module is now `hermes_a365.<x>`. The
|
|
28
|
+
symlink-walking `Path(__file__).resolve().parent.parent.parent /
|
|
29
|
+
"scripts"` trick in the plugin (`plugins/agent365/{adapter,cli}.py`)
|
|
30
|
+
is retired; the plugin imports `from hermes_a365 import
|
|
31
|
+
activity_bridge` directly.
|
|
32
|
+
- **Templates.** `templates/` is now packaged as `hermes_a365._data/
|
|
33
|
+
templates/` and resolved via `importlib.resources` so lookups work
|
|
34
|
+
for both editable installs and wheels.
|
|
35
|
+
- **Tests.** Bare imports (`from a365_config import …`) rewritten to
|
|
36
|
+
`from hermes_a365.a365_config import …`. `tests/conftest.py` no
|
|
37
|
+
longer pokes `scripts/` onto `sys.path`. 624 tests still passing.
|
|
38
|
+
- **Docs.** README, SKILL.md, and the `references/` runbooks updated
|
|
39
|
+
to drop the symlink instructions and the `uv run python scripts/<x>.py`
|
|
40
|
+
invocation style in favour of `pipx install` + `hermes-a365 <verb>`
|
|
41
|
+
(or `python -m hermes_a365.<x>` for the modules that aren't surfaced
|
|
42
|
+
as CLI subcommands).
|
|
43
|
+
|
|
44
|
+
## [0.1.0] — 2026-05-08
|
|
45
|
+
|
|
46
|
+
First operator-targeted release. Validated end-to-end against
|
|
47
|
+
Microsoft.Agents.A365.DevTools.Cli **1.1.171** (round-5 walkthrough,
|
|
48
|
+
2026-05-06) and the secret-null regression-recovery path on **1.1.174**
|
|
49
|
+
(round-6, 2026-05-07).
|
|
50
|
+
|
|
51
|
+
### Added — apply path (operator-side wrappers)
|
|
52
|
+
|
|
53
|
+
- `hermes a365 register` — orchestrates `a365 setup blueprint` +
|
|
54
|
+
`setup permissions mcp` + `setup permissions bot` with AADSTS-aware
|
|
55
|
+
retry, layer-1 client-secret regression detection, and opt-in
|
|
56
|
+
`--auto-recover-secret` (handles Microsoft#408 on macOS / Linux).
|
|
57
|
+
- `hermes a365 consent` — render admin-consent URL, optionally launch a
|
|
58
|
+
browser, poll `query-entra blueprint-scopes` until consent is granted.
|
|
59
|
+
- `hermes a365 instance create <slug>` — write the per-agent runtime
|
|
60
|
+
`~/.hermes/agents/<slug>/.env` (no cloud step).
|
|
61
|
+
- `hermes a365 publish` — package the AI Teammate manifest zip for
|
|
62
|
+
Microsoft 365 Admin Centre upload.
|
|
63
|
+
- `hermes a365 cleanup` — destructive teardown with `--purge-orphans`
|
|
64
|
+
for blueprint-flow agentic users + agentRegistry instances. AI
|
|
65
|
+
Teammate-flow store-managed instances always 403 on delete (Microsoft
|
|
66
|
+
platform limitation, documented in `references/live-tenant-test.md`).
|
|
67
|
+
- `hermes a365 license` — recommends an A365 license tier given a user
|
|
68
|
+
+ agent count and plan.
|
|
69
|
+
|
|
70
|
+
### Added — read path
|
|
71
|
+
|
|
72
|
+
- `hermes a365 doctor` — read-only environment probe (CLI version, az
|
|
73
|
+
signed-in, pwsh on PATH, network reachability, OS keychain backend).
|
|
74
|
+
- `hermes a365 status [<slug>]` — per-component status report against
|
|
75
|
+
`query-entra` (local config, blueprint scopes, instance scopes, local
|
|
76
|
+
bridge PID).
|
|
77
|
+
|
|
78
|
+
### Added — runtime
|
|
79
|
+
|
|
80
|
+
- **`agent365` Hermes platform adapter** (`plugins/agent365/`).
|
|
81
|
+
Validated end-to-end against a Frontier-Preview tenant on Microsoft
|
|
82
|
+
Teams 1:1 chat (rounds 3 → 5). Inbound activities go through AAD-v2
|
|
83
|
+
JWT validation, BF idempotency dedupe, and `serviceUrl` host-suffix
|
|
84
|
+
allowlist before reaching the agent loop.
|
|
85
|
+
- **`hermes a365 activity-bridge`** — Bot Framework adapter daemon.
|
|
86
|
+
- `verify` — one-shot diagnostic (config + auth + reachability).
|
|
87
|
+
- `serve` — long-running `/api/messages` webhook (FastAPI + uvicorn
|
|
88
|
+
via the optional `bridge` extras).
|
|
89
|
+
- `update-endpoint` — re-points the agent's messaging endpoint at a
|
|
90
|
+
public tunnel URL.
|
|
91
|
+
- **Three-stage user-FIC token chain** for outbound replies (BF S2S →
|
|
92
|
+
agent FMI delegation → user FIC), plus per-conversation
|
|
93
|
+
durable registry that survives gateway restarts
|
|
94
|
+
(`~/.hermes/agents/<slug>/conversations.json`).
|
|
95
|
+
- **`agents`-channel synthetic-event filter** — drops M365 onboarding
|
|
96
|
+
probes + email-template render activities so they don't waste an
|
|
97
|
+
agent turn (round-5 walkthrough finding).
|
|
98
|
+
|
|
99
|
+
### Added — CLI surface
|
|
100
|
+
|
|
101
|
+
- `hermes a365 <verb>` is wired via the supported Hermes plugin
|
|
102
|
+
`register_cli_command` API (slice 19x-a, this release). Each verb
|
|
103
|
+
delegates to the matching `scripts/<x>.py` module; running
|
|
104
|
+
`python scripts/<x>.py` continues to work for development.
|
|
105
|
+
|
|
106
|
+
### Added — references / runbooks
|
|
107
|
+
|
|
108
|
+
- `references/live-tenant-test.md` — end-to-end runbook for a
|
|
109
|
+
Frontier-Preview tenant; flags macOS 26 device-code prompt-volume
|
|
110
|
+
failure mode (~10–12 prompts per `register --apply --m365`).
|
|
111
|
+
- `references/m365-surface-coverage.md` — per-surface coverage matrix.
|
|
112
|
+
- `references/exposing-the-bot-endpoint.md` — operator-side options
|
|
113
|
+
(cloudflared, devtunnels, ngrok, reverse-proxy) — non-prescriptive.
|
|
114
|
+
- `references/a365-cli-reference.md`, `webhook-contract.md`,
|
|
115
|
+
`activity-protocol-shapes.md`, `error-codes.md`,
|
|
116
|
+
`entra-blueprint-properties.md`, `opentelemetry-config.md`,
|
|
117
|
+
`license-cost-table.md`.
|
|
118
|
+
|
|
119
|
+
### Filed upstream
|
|
120
|
+
|
|
121
|
+
- **microsoft/Agent365-devTools#402** — cosmetic logging fixes when
|
|
122
|
+
Observability-only S2S app-role assignment is the intended state.
|
|
123
|
+
Microsoft confirmed intent + shipped fixes in CLI 1.1.174.
|
|
124
|
+
- **microsoft/Agent365-devTools#408** — `agentBlueprintClientSecret`
|
|
125
|
+
null-on-disk regression on macOS (DPAPI unavailable). Layer 1
|
|
126
|
+
detection + auto-recovery shipped in this release; Layer 2 is the
|
|
127
|
+
upstream fix.
|
|
128
|
+
|
|
129
|
+
### Known limitations
|
|
130
|
+
|
|
131
|
+
- **M365 Copilot streaming** ([#3](https://github.com/satscryption/Hermes-A365/issues/3))
|
|
132
|
+
not yet implemented — `Agent365Adapter.edit_message` is a no-op and
|
|
133
|
+
`REQUIRES_EDIT_FINALIZE` is unset. Required for Copilot Chat surface.
|
|
134
|
+
- **Proactive replies for >10 s agent thinking**
|
|
135
|
+
([#4](https://github.com/satscryption/Hermes-A365/issues/4)) — `send()`
|
|
136
|
+
still requires a cached inbound; cron-driven sends do not work yet.
|
|
137
|
+
- **`hermes gateway setup` wizard**
|
|
138
|
+
([#13](https://github.com/satscryption/Hermes-A365/issues/13)) not yet
|
|
139
|
+
shipped — operators must hand-edit `~/.hermes/config.yaml` and
|
|
140
|
+
`~/.hermes/.env` per the README quickstart.
|
|
141
|
+
- **Invoke activities** (Outlook compose-action, Teams compose
|
|
142
|
+
extensions, search, signin) tracked under
|
|
143
|
+
[#18](https://github.com/satscryption/Hermes-A365/issues/18); umbrella
|
|
144
|
+
not yet implemented.
|
|
145
|
+
- **Plaintext on-disk secret on macOS / Linux.** DPAPI is Windows-only;
|
|
146
|
+
the keychain shim in `scripts/keychain.py` writes the agent blueprint
|
|
147
|
+
client secret to `a365.generated.config.json` with mode `0600`. See
|
|
148
|
+
README "Security model".
|
|
149
|
+
- **AI Teammate-flow agentRegistry entries cannot be deleted** by
|
|
150
|
+
operators (only "blocked" via the M365 Admin Centre). Microsoft
|
|
151
|
+
platform limitation; not a wrapper bug.
|
|
152
|
+
|
|
153
|
+
[Unreleased]: https://github.com/satscryption/Hermes-A365/compare/v0.1.0...HEAD
|
|
154
|
+
[0.1.0]: https://github.com/satscryption/Hermes-A365/releases/tag/v0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sadiq Jaffer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|