hermes-agent/hermes_cli
otsune 3fccd698fd feat(kanban): attachment toolset + CLI to match the dashboard surface
The kanban board has had full attachment storage and a dashboard HTTP
API (upload/list/download/delete) since #35338, but there was no agent
toolset tool and no `hermes kanban` CLI verb for attachments. Agents and
scripts that don't go through the dashboard server (or can't touch the DB
directly) had no way to create or read real attachments — only links in
comments.

Close that gap by mirroring the existing comment surface:

- `kanban_db.store_attachment_bytes()` — one shared write path (validate
  name, enforce the 25 MB cap, write the blob under the per-task dir with
  collision-free naming, insert the metadata row, clean up an orphan blob
  if the insert fails). `_MAX_ATTACHMENT_BYTES`, `_safe_attachment_name`,
  and a new `_collision_free_path` move here so the dashboard, the tool,
  and the CLI all share one implementation and can't drift.
- Tools (`tools/kanban_tools.py`): `kanban_attach` (inline base64),
  `kanban_attach_url` (server-side http/https fetch with the same cap),
  `kanban_attachments` (list). Write tools respect worker task-ownership;
  list is read-only. Registered in the `kanban` toolset.
- CLI (`hermes_cli/kanban.py`): `attach <id> <path>`, `attachments <id>`,
  `attach-rm <attachment_id>`.
- Dashboard `upload_task_attachment` now imports the shared helpers and
  uses `_collision_free_path` — behavior identical (still streams to disk
  with the cap, still 413 on overflow).
- Docs (AGENTS.md, kanban-worker skill) and toolset membership updated.

Tests: tool round-trip + oversize + bad base64 + ownership; attach_url
against a local HTTP fixture incl. oversize-mid-stream and non-http
scheme rejection; CLI attach/attachments/attach-rm; shared-helper unit
tests; dashboard parity preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 07:33:14 -07:00
..
dashboard_auth
proxy
subcommands feat(config): add get and unset commands 2026-07-16 05:44:43 -07:00
__init__.py
_parser.py
_subprocess_compat.py
active_sessions.py
auth.py fix(auth): key reentrancy by auth store path 2026-07-16 06:14:56 -07:00
auth_commands.py
azure_detect.py
backup.py
banner.py
blueprint_cmd.py
browser_connect.py
build_info.py
bundles.py
callbacks.py
checkpoints.py
claw.py
cli_agent_setup_mixin.py fix(auth): honor per-entry key_env when resolving fallback providers 2026-07-16 07:19:36 -07:00
cli_commands_mixin.py
cli_output.py
clipboard.py
codex_models.py
codex_runtime_plugin_migration.py
codex_runtime_switch.py
colors.py
commands.py
completion.py
config.py feat(config): add get and unset commands 2026-07-16 05:44:43 -07:00
console_engine.py
container_boot.py
context_switch_guard.py
copilot_auth.py
cron.py
curator.py
curses_ui.py
dashboard_register.py
debug.py
default_soul.py
dep_ensure.py
diagnostics_upload.py
dingtalk_auth.py
doctor.py
dump.py
env_loader.py
fallback_cmd.py
fallback_config.py fix(auth): honor per-entry key_env when resolving fallback providers 2026-07-16 07:19:36 -07:00
gateway.py fix(gateway): preserve external supervisor ownership 2026-07-16 05:08:56 -07:00
gateway_enroll.py
gateway_windows.py
goals.py
gui_uninstall.py
hooks.py
input_sanitize.py
inventory.py
journey.py
kanban.py feat(kanban): attachment toolset + CLI to match the dashboard surface 2026-07-16 07:33:14 -07:00
kanban_db.py feat(kanban): attachment toolset + CLI to match the dashboard surface 2026-07-16 07:33:14 -07:00
kanban_decompose.py
kanban_diagnostics.py
kanban_specify.py
kanban_swarm.py
logs.py
main.py fix(gateway): preserve external supervisor ownership 2026-07-16 05:08:56 -07:00
managed_scope.py
managed_uv.py
mcp_catalog.py
mcp_config.py
mcp_picker.py
mcp_security.py
mcp_startup.py
memory_oauth.py
memory_providers.py
memory_setup.py
middleware.py
migrate.py
moa_cmd.py
moa_config.py fix(moa): route per-slot reasoning effort through the canonical parser 2026-07-16 06:14:58 -07:00
model_catalog.py
model_cost_guard.py
model_normalize.py
model_setup_flows.py feat(pricing): refresh Fireworks snapshot to 2026-07, cover full serverless catalog + cached picker pricing 2026-07-16 04:24:14 -07:00
model_switch.py
models.py feat(pricing): refresh Fireworks snapshot to 2026-07, cover full serverless catalog + cached picker pricing 2026-07-16 04:24:14 -07:00
nous_account.py
nous_auth_keepalive.py
nous_billing.py
nous_subscription.py
onepassword_secrets_cli.py
oneshot.py
pairing.py
partial_compress.py
pets.py
platforms.py
plugins.py
plugins_cmd.py
portal_cli.py
profile_describer.py
profile_distribution.py
profiles.py
projects_cmd.py
projects_db.py
prompt_size.py
provider_catalog.py
providers.py
psutil_android.py
pt_input_extras.py
pty_bridge.py
pty_session.py
relaunch.py
runtime_provider.py
secret_prompt.py
secrets_cli.py
security_advisories.py
security_audit.py
security_audit_startup.py
send_cmd.py
service_manager.py
session_export.py
session_export_html.py
session_export_md.py
session_filters.py
session_listing.py
session_recap.py
setup.py
setup_whatsapp_cloud.py
skills_config.py
skills_hub.py
skin_engine.py
slack_cli.py
sqlite_util.py
status.py
stdio.py
suggestions_cmd.py
telegram_managed_bot.py
timeouts.py
tips.py
tools_config.py fix(tools): don't report platform-restricted toolsets as enabled 2026-07-16 01:17:11 -07:00
toolset_validation.py
uninstall.py
urllib_security.py
voice.py
web_git.py
web_server.py fix(dashboard): theme bootstrap emits real bundle CSS vars; canvas rule flows through vars 2026-07-16 07:28:22 -07:00
webhook.py
win_pty_bridge.py
write_approval_commands.py
xai_retirement.py