feat(node2): wire calendar-service and core automation tools in router
This commit is contained in:
64
config/nodes_registry.yml
Normal file
64
config/nodes_registry.yml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
defaults:
|
||||||
|
health_timeout_sec: 10
|
||||||
|
tools_timeout_sec: 30
|
||||||
|
# Per-node timeout defaults (overridable per-node)
|
||||||
|
gateway_timeout_ms: 2500 # ms for gateway health/agent fetch
|
||||||
|
apply_timeout_ms: 10000 # ms for apply POST
|
||||||
|
get_retry: 1 # max retries for GET (health check)
|
||||||
|
post_retry: 0 # no retry for mutating calls
|
||||||
|
nodes:
|
||||||
|
NODA1:
|
||||||
|
label: Production (NODA1)
|
||||||
|
node_role: prod # prod = always-on, higher timeouts
|
||||||
|
gateway_timeout_ms: 2500
|
||||||
|
apply_timeout_ms: 10000
|
||||||
|
router_url: http://144.76.224.179:9102
|
||||||
|
gateway_url: http://144.76.224.179:9300
|
||||||
|
monitor_url: http://144.76.224.179:9102
|
||||||
|
supervisor_url: ''
|
||||||
|
ssh:
|
||||||
|
host: 144.76.224.179
|
||||||
|
ipv6: 2a01:4f8:201:2a6::2
|
||||||
|
port: 22
|
||||||
|
user: root
|
||||||
|
auth:
|
||||||
|
password_env: NODES_NODA1_SSH_PASSWORD
|
||||||
|
host_keys:
|
||||||
|
- type: rsa
|
||||||
|
bits: 3072
|
||||||
|
sha256: OzbVMM7CC4SatdE2CSoxh5qgJdCyYO22MLjchXXBIro
|
||||||
|
- type: ecdsa
|
||||||
|
bits: 256
|
||||||
|
sha256: YPQUigtDm3HiEp4MYYeREE+M3ig/2CrZXy2ozr4OWQw
|
||||||
|
- type: ed25519
|
||||||
|
bits: 256
|
||||||
|
sha256: 79LG0tKQ1B1DsdVZ/BhLYSX2v08eCWqqWihHtn+Y8FU
|
||||||
|
NODA2:
|
||||||
|
label: Control Plane (NODA2 · MacBook)
|
||||||
|
node_role: dev # dev = optional, short timeout, canary-default
|
||||||
|
gateway_timeout_ms: 1000 # fast timeout — dev laptop may sleep/NAT
|
||||||
|
apply_timeout_ms: 5000
|
||||||
|
get_retry: 1
|
||||||
|
post_retry: 0
|
||||||
|
router_url: http://127.0.0.1:9102
|
||||||
|
gateway_url: http://127.0.0.1:9300
|
||||||
|
monitor_url: http://127.0.0.1:9102
|
||||||
|
supervisor_url: http://127.0.0.1:8084
|
||||||
|
NODA3:
|
||||||
|
label: AI/ML Experiments (NODA3)
|
||||||
|
node_role: dev
|
||||||
|
gateway_timeout_ms: 800
|
||||||
|
router_url: ''
|
||||||
|
gateway_url: ''
|
||||||
|
monitor_url: ''
|
||||||
|
supervisor_url: ''
|
||||||
|
enabled: false
|
||||||
|
NODA4:
|
||||||
|
label: Reserve Node (NODA4)
|
||||||
|
node_role: dev
|
||||||
|
gateway_timeout_ms: 1500
|
||||||
|
router_url: http://10.0.0.44:9102
|
||||||
|
gateway_url: http://10.0.0.44:9300
|
||||||
|
monitor_url: http://10.0.0.44:9102
|
||||||
|
supervisor_url: ''
|
||||||
|
enabled: false
|
||||||
507
config/rbac_tools_matrix.yml
Normal file
507
config/rbac_tools_matrix.yml
Normal file
@@ -0,0 +1,507 @@
|
|||||||
|
# RBAC Tools Matrix
|
||||||
|
# Maps tool → action → entitlements required
|
||||||
|
# Enforced by tool_governance.py in gateway dispatch
|
||||||
|
#
|
||||||
|
# Entitlement format: tools.<tool_short>.<scope>
|
||||||
|
# Agents/users must have ALL listed entitlements to perform an action.
|
||||||
|
|
||||||
|
tools:
|
||||||
|
|
||||||
|
repo_tool:
|
||||||
|
actions:
|
||||||
|
tree:
|
||||||
|
entitlements: ["tools.repo.read"]
|
||||||
|
read:
|
||||||
|
entitlements: ["tools.repo.read"]
|
||||||
|
search:
|
||||||
|
entitlements: ["tools.repo.read"]
|
||||||
|
metadata:
|
||||||
|
entitlements: ["tools.repo.read"]
|
||||||
|
|
||||||
|
kb_tool:
|
||||||
|
actions:
|
||||||
|
search:
|
||||||
|
entitlements: ["tools.kb.read"]
|
||||||
|
snippets:
|
||||||
|
entitlements: ["tools.kb.read"]
|
||||||
|
open:
|
||||||
|
entitlements: ["tools.kb.read"]
|
||||||
|
sources:
|
||||||
|
entitlements: ["tools.kb.read"]
|
||||||
|
|
||||||
|
oncall_tool:
|
||||||
|
actions:
|
||||||
|
services_list:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
service_health:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
service_status:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
runbook_search:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
runbook_read:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
deployments_recent:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
incident_list:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
incident_get:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
incident_create:
|
||||||
|
entitlements: ["tools.oncall.incident_write"]
|
||||||
|
incident_close:
|
||||||
|
entitlements: ["tools.oncall.incident_write"]
|
||||||
|
incident_append_event:
|
||||||
|
entitlements: ["tools.oncall.incident_write"]
|
||||||
|
incident_attach_artifact:
|
||||||
|
entitlements: ["tools.oncall.incident_write"]
|
||||||
|
incident_followups_summary:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
alert_to_incident:
|
||||||
|
entitlements: ["tools.oncall.incident_write", "tools.alerts.read", "tools.alerts.ack"]
|
||||||
|
|
||||||
|
incident_escalation_tool:
|
||||||
|
actions:
|
||||||
|
evaluate:
|
||||||
|
entitlements: ["tools.oncall.incident_write"]
|
||||||
|
auto_resolve_candidates:
|
||||||
|
entitlements: ["tools.oncall.incident_write"]
|
||||||
|
|
||||||
|
risk_engine_tool:
|
||||||
|
actions:
|
||||||
|
service:
|
||||||
|
entitlements: ["tools.risk.read"]
|
||||||
|
dashboard:
|
||||||
|
entitlements: ["tools.risk.read"]
|
||||||
|
policy:
|
||||||
|
entitlements: ["tools.risk.read"]
|
||||||
|
|
||||||
|
risk_history_tool:
|
||||||
|
actions:
|
||||||
|
snapshot:
|
||||||
|
entitlements: ["tools.risk.write"]
|
||||||
|
cleanup:
|
||||||
|
entitlements: ["tools.risk.write"]
|
||||||
|
series:
|
||||||
|
entitlements: ["tools.risk.read"]
|
||||||
|
digest:
|
||||||
|
entitlements: ["tools.risk.write"]
|
||||||
|
|
||||||
|
backlog_tool:
|
||||||
|
actions:
|
||||||
|
list:
|
||||||
|
entitlements: ["tools.backlog.read"]
|
||||||
|
get:
|
||||||
|
entitlements: ["tools.backlog.read"]
|
||||||
|
dashboard:
|
||||||
|
entitlements: ["tools.backlog.read"]
|
||||||
|
create:
|
||||||
|
entitlements: ["tools.backlog.write"]
|
||||||
|
upsert:
|
||||||
|
entitlements: ["tools.backlog.write"]
|
||||||
|
set_status:
|
||||||
|
entitlements: ["tools.backlog.write"]
|
||||||
|
add_comment:
|
||||||
|
entitlements: ["tools.backlog.write"]
|
||||||
|
close:
|
||||||
|
entitlements: ["tools.backlog.write"]
|
||||||
|
auto_generate_weekly:
|
||||||
|
entitlements: ["tools.backlog.admin"]
|
||||||
|
cleanup:
|
||||||
|
entitlements: ["tools.backlog.admin"]
|
||||||
|
|
||||||
|
architecture_pressure_tool:
|
||||||
|
actions:
|
||||||
|
service:
|
||||||
|
entitlements: ["tools.pressure.read"]
|
||||||
|
dashboard:
|
||||||
|
entitlements: ["tools.pressure.read"]
|
||||||
|
digest:
|
||||||
|
entitlements: ["tools.pressure.write"]
|
||||||
|
|
||||||
|
incident_intelligence_tool:
|
||||||
|
actions:
|
||||||
|
correlate:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
recurrence:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
buckets:
|
||||||
|
entitlements: ["tools.oncall.read"]
|
||||||
|
weekly_digest:
|
||||||
|
entitlements: ["tools.oncall.incident_write"] # writes FS artifacts + autofollowups
|
||||||
|
|
||||||
|
alert_ingest_tool:
|
||||||
|
actions:
|
||||||
|
ingest:
|
||||||
|
entitlements: ["tools.alerts.ingest"]
|
||||||
|
list:
|
||||||
|
entitlements: ["tools.alerts.read"]
|
||||||
|
get:
|
||||||
|
entitlements: ["tools.alerts.read"]
|
||||||
|
ack:
|
||||||
|
entitlements: ["tools.alerts.ack"]
|
||||||
|
claim:
|
||||||
|
entitlements: ["tools.alerts.claim"]
|
||||||
|
fail:
|
||||||
|
entitlements: ["tools.alerts.ack"]
|
||||||
|
|
||||||
|
observability_tool:
|
||||||
|
actions:
|
||||||
|
metrics_query:
|
||||||
|
entitlements: ["tools.observability.read"]
|
||||||
|
metrics_range:
|
||||||
|
entitlements: ["tools.observability.read"]
|
||||||
|
logs_query:
|
||||||
|
entitlements: ["tools.observability.read"]
|
||||||
|
traces_query:
|
||||||
|
entitlements: ["tools.observability.traces"]
|
||||||
|
service_overview:
|
||||||
|
entitlements: ["tools.observability.read"]
|
||||||
|
slo_snapshot:
|
||||||
|
entitlements: ["tools.observability.read"]
|
||||||
|
|
||||||
|
monitor_tool:
|
||||||
|
actions:
|
||||||
|
status:
|
||||||
|
entitlements: ["tools.monitor.read"]
|
||||||
|
|
||||||
|
pr_reviewer_tool:
|
||||||
|
actions:
|
||||||
|
review:
|
||||||
|
entitlements: ["tools.pr_review.use"]
|
||||||
|
gate:
|
||||||
|
entitlements: ["tools.pr_review.gate"]
|
||||||
|
|
||||||
|
contract_tool:
|
||||||
|
actions:
|
||||||
|
lint_openapi:
|
||||||
|
entitlements: ["tools.contract.use"]
|
||||||
|
diff_openapi:
|
||||||
|
entitlements: ["tools.contract.use"]
|
||||||
|
generate_client_stub:
|
||||||
|
entitlements: ["tools.contract.use"]
|
||||||
|
gate:
|
||||||
|
entitlements: ["tools.contract.gate"]
|
||||||
|
|
||||||
|
config_linter_tool:
|
||||||
|
actions:
|
||||||
|
lint:
|
||||||
|
entitlements: ["tools.config_lint.use"]
|
||||||
|
gate:
|
||||||
|
entitlements: ["tools.config_lint.gate"]
|
||||||
|
|
||||||
|
threatmodel_tool:
|
||||||
|
actions:
|
||||||
|
analyze_service:
|
||||||
|
entitlements: ["tools.threatmodel.use"]
|
||||||
|
analyze_diff:
|
||||||
|
entitlements: ["tools.threatmodel.use"]
|
||||||
|
generate_checklist:
|
||||||
|
entitlements: ["tools.threatmodel.use"]
|
||||||
|
gate:
|
||||||
|
entitlements: ["tools.threatmodel.gate"]
|
||||||
|
|
||||||
|
job_orchestrator_tool:
|
||||||
|
actions:
|
||||||
|
list_tasks:
|
||||||
|
entitlements: ["tools.jobs.use"]
|
||||||
|
start_task:
|
||||||
|
entitlements: ["tools.jobs.use"]
|
||||||
|
get_job:
|
||||||
|
entitlements: ["tools.jobs.use"]
|
||||||
|
cancel_job:
|
||||||
|
entitlements: ["tools.jobs.cancel"]
|
||||||
|
|
||||||
|
memory_search:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.memory.read"]
|
||||||
|
|
||||||
|
graph_query:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.memory.read"]
|
||||||
|
|
||||||
|
remember_fact:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.memory.write"]
|
||||||
|
|
||||||
|
web_search:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.web.read"]
|
||||||
|
|
||||||
|
web_extract:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.web.read"]
|
||||||
|
|
||||||
|
crawl4ai_scrape:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.web.read"]
|
||||||
|
|
||||||
|
image_generate:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.media.generate"]
|
||||||
|
|
||||||
|
comfy_generate_image:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.media.generate"]
|
||||||
|
|
||||||
|
comfy_generate_video:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.media.generate"]
|
||||||
|
|
||||||
|
tts_speak:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.media.generate"]
|
||||||
|
|
||||||
|
presentation_create:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.docs.create"]
|
||||||
|
|
||||||
|
presentation_status:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.docs.create"]
|
||||||
|
|
||||||
|
presentation_download:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.docs.create"]
|
||||||
|
|
||||||
|
file_tool:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.docs.create"]
|
||||||
|
|
||||||
|
market_data:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.market.read"]
|
||||||
|
|
||||||
|
data_governance_tool:
|
||||||
|
actions:
|
||||||
|
digest_audit:
|
||||||
|
entitlements: ["tools.data_gov.read"]
|
||||||
|
scan_repo:
|
||||||
|
entitlements: ["tools.data_gov.read"]
|
||||||
|
scan_audit:
|
||||||
|
entitlements: ["tools.data_gov.read"]
|
||||||
|
retention_check:
|
||||||
|
entitlements: ["tools.data_gov.read"]
|
||||||
|
policy:
|
||||||
|
entitlements: ["tools.data_gov.read"]
|
||||||
|
gate:
|
||||||
|
entitlements: ["tools.data_gov.gate"]
|
||||||
|
|
||||||
|
cost_analyzer_tool:
|
||||||
|
actions:
|
||||||
|
digest:
|
||||||
|
entitlements: ["tools.cost.read"]
|
||||||
|
report:
|
||||||
|
entitlements: ["tools.cost.read"]
|
||||||
|
top:
|
||||||
|
entitlements: ["tools.cost.read"]
|
||||||
|
anomalies:
|
||||||
|
entitlements: ["tools.cost.read"]
|
||||||
|
weights:
|
||||||
|
entitlements: ["tools.cost.read"]
|
||||||
|
gate:
|
||||||
|
entitlements: ["tools.cost.gate"]
|
||||||
|
|
||||||
|
dependency_scanner_tool:
|
||||||
|
actions:
|
||||||
|
scan:
|
||||||
|
entitlements: ["tools.deps.read"]
|
||||||
|
gate:
|
||||||
|
entitlements: ["tools.deps.gate"]
|
||||||
|
|
||||||
|
drift_analyzer_tool:
|
||||||
|
actions:
|
||||||
|
analyze:
|
||||||
|
entitlements: ["tools.drift.read"]
|
||||||
|
gate:
|
||||||
|
entitlements: ["tools.drift.gate"]
|
||||||
|
|
||||||
|
calendar_tool:
|
||||||
|
actions:
|
||||||
|
connect:
|
||||||
|
entitlements: ["tools.calendar.use"]
|
||||||
|
list_calendars:
|
||||||
|
entitlements: ["tools.calendar.use"]
|
||||||
|
list_events:
|
||||||
|
entitlements: ["tools.calendar.use"]
|
||||||
|
get_event:
|
||||||
|
entitlements: ["tools.calendar.use"]
|
||||||
|
create_event:
|
||||||
|
entitlements: ["tools.calendar.use"]
|
||||||
|
update_event:
|
||||||
|
entitlements: ["tools.calendar.use"]
|
||||||
|
delete_event:
|
||||||
|
entitlements: ["tools.calendar.use"]
|
||||||
|
set_reminder:
|
||||||
|
entitlements: ["tools.calendar.use"]
|
||||||
|
|
||||||
|
agent_email_tool:
|
||||||
|
actions:
|
||||||
|
create_inbox:
|
||||||
|
entitlements: ["tools.email.use"]
|
||||||
|
list_inboxes:
|
||||||
|
entitlements: ["tools.email.use"]
|
||||||
|
delete_inbox:
|
||||||
|
entitlements: ["tools.email.use"]
|
||||||
|
send:
|
||||||
|
entitlements: ["tools.email.use"]
|
||||||
|
receive:
|
||||||
|
entitlements: ["tools.email.use"]
|
||||||
|
analyze_email:
|
||||||
|
entitlements: ["tools.email.use"]
|
||||||
|
|
||||||
|
browser_tool:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.browser.use"]
|
||||||
|
|
||||||
|
safe_code_executor_tool:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.exec.safe"]
|
||||||
|
|
||||||
|
secure_vault_tool:
|
||||||
|
actions:
|
||||||
|
_default:
|
||||||
|
entitlements: ["tools.vault.manage"]
|
||||||
|
|
||||||
|
# ─── Role → Entitlements ─────────────────────────────────────────────────────
|
||||||
|
# Lists which entitlements each role has.
|
||||||
|
# Used by tool_governance.py to resolve agent role → entitlement set.
|
||||||
|
|
||||||
|
role_entitlements:
|
||||||
|
agent_default:
|
||||||
|
- tools.repo.read
|
||||||
|
- tools.kb.read
|
||||||
|
- tools.oncall.read
|
||||||
|
- tools.observability.read
|
||||||
|
- tools.memory.read
|
||||||
|
- tools.memory.write
|
||||||
|
- tools.web.read
|
||||||
|
- tools.media.generate
|
||||||
|
- tools.docs.create
|
||||||
|
- tools.jobs.use
|
||||||
|
|
||||||
|
agent_cto:
|
||||||
|
- tools.repo.read
|
||||||
|
- tools.kb.read
|
||||||
|
- tools.oncall.read
|
||||||
|
- tools.oncall.incident_write
|
||||||
|
- tools.alerts.ingest
|
||||||
|
- tools.alerts.read
|
||||||
|
- tools.alerts.ack
|
||||||
|
- tools.alerts.claim
|
||||||
|
- tools.observability.read
|
||||||
|
- tools.observability.traces
|
||||||
|
- tools.monitor.read
|
||||||
|
- tools.memory.read
|
||||||
|
- tools.memory.write
|
||||||
|
- tools.web.read
|
||||||
|
- tools.media.generate
|
||||||
|
- tools.docs.create
|
||||||
|
- tools.pr_review.use
|
||||||
|
- tools.pr_review.gate
|
||||||
|
- tools.contract.use
|
||||||
|
- tools.contract.gate
|
||||||
|
- tools.config_lint.use
|
||||||
|
- tools.config_lint.gate
|
||||||
|
- tools.threatmodel.use
|
||||||
|
- tools.threatmodel.gate
|
||||||
|
- tools.jobs.use
|
||||||
|
- tools.jobs.cancel
|
||||||
|
- tools.jobs.run.smoke
|
||||||
|
- tools.jobs.run.drift
|
||||||
|
- tools.jobs.run.backup
|
||||||
|
- tools.jobs.run.migrate
|
||||||
|
- tools.jobs.run.deploy
|
||||||
|
- tools.jobs.run.ops
|
||||||
|
- tools.deps.read
|
||||||
|
- tools.deps.gate
|
||||||
|
- tools.cost.read
|
||||||
|
- tools.cost.gate
|
||||||
|
- tools.data_gov.read
|
||||||
|
- tools.data_gov.gate
|
||||||
|
- tools.drift.read
|
||||||
|
- tools.drift.gate
|
||||||
|
- tools.risk.read
|
||||||
|
- tools.risk.write
|
||||||
|
- tools.pressure.read
|
||||||
|
- tools.pressure.write
|
||||||
|
- tools.backlog.read
|
||||||
|
- tools.backlog.write
|
||||||
|
- tools.backlog.admin
|
||||||
|
- tools.calendar.use
|
||||||
|
- tools.email.use
|
||||||
|
- tools.browser.use
|
||||||
|
- tools.exec.safe
|
||||||
|
- tools.vault.manage
|
||||||
|
|
||||||
|
agent_oncall:
|
||||||
|
- tools.repo.read
|
||||||
|
- tools.kb.read
|
||||||
|
- tools.oncall.read
|
||||||
|
- tools.oncall.incident_write
|
||||||
|
- tools.alerts.read
|
||||||
|
- tools.alerts.ack
|
||||||
|
- tools.alerts.claim
|
||||||
|
- tools.observability.read
|
||||||
|
- tools.monitor.read
|
||||||
|
- tools.memory.read
|
||||||
|
- tools.web.read
|
||||||
|
- tools.jobs.use
|
||||||
|
- tools.jobs.run.smoke
|
||||||
|
- tools.jobs.run.drift
|
||||||
|
- tools.jobs.run.ops
|
||||||
|
- tools.deps.read
|
||||||
|
- tools.drift.read
|
||||||
|
- tools.cost.read
|
||||||
|
- tools.data_gov.read
|
||||||
|
- tools.risk.read
|
||||||
|
- tools.risk.write
|
||||||
|
- tools.pressure.read
|
||||||
|
- tools.backlog.read
|
||||||
|
- tools.backlog.write
|
||||||
|
|
||||||
|
agent_media:
|
||||||
|
- tools.repo.read
|
||||||
|
- tools.kb.read
|
||||||
|
- tools.oncall.read
|
||||||
|
- tools.observability.read
|
||||||
|
- tools.memory.read
|
||||||
|
- tools.memory.write
|
||||||
|
- tools.web.read
|
||||||
|
- tools.media.generate
|
||||||
|
- tools.docs.create
|
||||||
|
- tools.jobs.use
|
||||||
|
|
||||||
|
agent_monitor:
|
||||||
|
# Read-only: observability, health, KB — no incident write, no jobs
|
||||||
|
# Can INGEST alerts (detect → alert), but NOT create incidents
|
||||||
|
- tools.oncall.read
|
||||||
|
- tools.observability.read
|
||||||
|
- tools.monitor.read
|
||||||
|
- tools.kb.read
|
||||||
|
- tools.alerts.ingest
|
||||||
|
- tools.risk.read
|
||||||
|
|
||||||
|
agent_interface:
|
||||||
|
# Minimal: KB + incident list/get + alert list/get + backlog read (read-only)
|
||||||
|
- tools.kb.read
|
||||||
|
- tools.oncall.read
|
||||||
|
- tools.alerts.read
|
||||||
|
- tools.backlog.read
|
||||||
339
config/tool_limits.yml
Normal file
339
config/tool_limits.yml
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
# Tool Safety Limits Configuration
|
||||||
|
# Controls per-tool: timeout, input/output sizes, rate limits, concurrency.
|
||||||
|
# Applied by tool_governance.py middleware before dispatch.
|
||||||
|
|
||||||
|
# ─── Global Defaults ─────────────────────────────────────────────────────────
|
||||||
|
defaults:
|
||||||
|
timeout_ms: 30000 # 30s
|
||||||
|
max_chars_in: 200000 # 200KB input
|
||||||
|
max_bytes_out: 524288 # 512KB output
|
||||||
|
rate_limit_rpm: 60 # 60 req/min per agent
|
||||||
|
concurrency: 5 # max parallel calls per agent
|
||||||
|
|
||||||
|
# ─── Per-Tool Overrides ───────────────────────────────────────────────────────
|
||||||
|
tools:
|
||||||
|
|
||||||
|
repo_tool:
|
||||||
|
timeout_ms: 10000
|
||||||
|
max_chars_in: 10000 # path + params only, not file content input
|
||||||
|
max_bytes_out: 524288 # 512KB (file read result)
|
||||||
|
rate_limit_rpm: 120
|
||||||
|
|
||||||
|
kb_tool:
|
||||||
|
timeout_ms: 15000
|
||||||
|
max_chars_in: 5000
|
||||||
|
max_bytes_out: 262144 # 256KB
|
||||||
|
rate_limit_rpm: 60
|
||||||
|
|
||||||
|
oncall_tool:
|
||||||
|
timeout_ms: 10000
|
||||||
|
max_chars_in: 10000
|
||||||
|
max_bytes_out: 131072 # 128KB
|
||||||
|
rate_limit_rpm: 30
|
||||||
|
concurrency: 3
|
||||||
|
actions:
|
||||||
|
incident_followups_summary:
|
||||||
|
timeout_ms: 10000
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
|
||||||
|
incident_escalation_tool:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_bytes_out: 524288
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
|
||||||
|
risk_engine_tool:
|
||||||
|
actions:
|
||||||
|
service:
|
||||||
|
timeout_seconds: 10
|
||||||
|
rpm: 20
|
||||||
|
dashboard:
|
||||||
|
timeout_seconds: 20
|
||||||
|
rpm: 5
|
||||||
|
policy:
|
||||||
|
timeout_seconds: 2
|
||||||
|
rpm: 60
|
||||||
|
|
||||||
|
risk_history_tool:
|
||||||
|
actions:
|
||||||
|
snapshot:
|
||||||
|
timeout_seconds: 60
|
||||||
|
rpm: 1
|
||||||
|
cleanup:
|
||||||
|
timeout_seconds: 30
|
||||||
|
rpm: 2
|
||||||
|
series:
|
||||||
|
timeout_seconds: 5
|
||||||
|
rpm: 30
|
||||||
|
digest:
|
||||||
|
timeout_seconds: 30
|
||||||
|
rpm: 2
|
||||||
|
|
||||||
|
incident_intelligence_tool:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_bytes_out: 524288 # 512KB (digests can be large)
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
actions:
|
||||||
|
correlate:
|
||||||
|
timeout_ms: 10000
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
recurrence:
|
||||||
|
timeout_ms: 15000
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
buckets:
|
||||||
|
timeout_ms: 15000
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
weekly_digest:
|
||||||
|
timeout_ms: 30000 # longer: writes artifacts + autofollowups
|
||||||
|
rate_limit_rpm: 2
|
||||||
|
|
||||||
|
alert_ingest_tool:
|
||||||
|
timeout_ms: 5000
|
||||||
|
max_chars_in: 32768 # 32KB — alert payload cap
|
||||||
|
max_bytes_out: 65536 # 64KB
|
||||||
|
rate_limit_rpm: 60 # monitor can send up to 60 alerts/min
|
||||||
|
concurrency: 5
|
||||||
|
actions:
|
||||||
|
ingest:
|
||||||
|
rate_limit_rpm: 60 # monitor rate: 1/s
|
||||||
|
list:
|
||||||
|
rate_limit_rpm: 30
|
||||||
|
timeout_ms: 5000
|
||||||
|
ack:
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
claim:
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
timeout_ms: 5000
|
||||||
|
fail:
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
|
||||||
|
observability_tool:
|
||||||
|
timeout_ms: 15000
|
||||||
|
max_chars_in: 5000
|
||||||
|
max_bytes_out: 524288 # 512KB (metrics can be large)
|
||||||
|
rate_limit_rpm: 30
|
||||||
|
concurrency: 3
|
||||||
|
actions:
|
||||||
|
slo_snapshot:
|
||||||
|
timeout_ms: 10000
|
||||||
|
rate_limit_rpm: 30
|
||||||
|
|
||||||
|
pr_reviewer_tool:
|
||||||
|
timeout_ms: 60000 # 60s (diff analysis can be slow)
|
||||||
|
max_chars_in: 409600 # 400KB (diff text)
|
||||||
|
max_bytes_out: 262144 # 256KB
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
concurrency: 2
|
||||||
|
|
||||||
|
contract_tool:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_chars_in: 819200 # 800KB (openapi specs)
|
||||||
|
max_bytes_out: 262144
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
|
||||||
|
config_linter_tool:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_chars_in: 409600 # 400KB
|
||||||
|
max_bytes_out: 131072
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
|
||||||
|
threatmodel_tool:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_chars_in: 614400 # 600KB
|
||||||
|
max_bytes_out: 262144
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
|
||||||
|
job_orchestrator_tool:
|
||||||
|
timeout_ms: 600000 # 10 min (job execution)
|
||||||
|
max_chars_in: 10000
|
||||||
|
max_bytes_out: 131072
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
concurrency: 2
|
||||||
|
|
||||||
|
memory_search:
|
||||||
|
timeout_ms: 5000
|
||||||
|
max_chars_in: 2000
|
||||||
|
max_bytes_out: 65536
|
||||||
|
rate_limit_rpm: 120
|
||||||
|
|
||||||
|
graph_query:
|
||||||
|
timeout_ms: 5000
|
||||||
|
max_chars_in: 2000
|
||||||
|
max_bytes_out: 65536
|
||||||
|
rate_limit_rpm: 60
|
||||||
|
|
||||||
|
web_search:
|
||||||
|
timeout_ms: 15000
|
||||||
|
max_chars_in: 500
|
||||||
|
max_bytes_out: 131072
|
||||||
|
rate_limit_rpm: 30
|
||||||
|
|
||||||
|
web_extract:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_chars_in: 2000
|
||||||
|
max_bytes_out: 524288
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
|
||||||
|
crawl4ai_scrape:
|
||||||
|
timeout_ms: 60000
|
||||||
|
max_chars_in: 2000
|
||||||
|
max_bytes_out: 1048576 # 1MB
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
|
||||||
|
image_generate:
|
||||||
|
timeout_ms: 60000
|
||||||
|
max_chars_in: 5000
|
||||||
|
max_bytes_out: 5242880 # 5MB (base64 image)
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
concurrency: 1
|
||||||
|
|
||||||
|
comfy_generate_image:
|
||||||
|
timeout_ms: 120000
|
||||||
|
max_chars_in: 5000
|
||||||
|
max_bytes_out: 10485760 # 10MB
|
||||||
|
rate_limit_rpm: 3
|
||||||
|
concurrency: 1
|
||||||
|
|
||||||
|
comfy_generate_video:
|
||||||
|
timeout_ms: 300000
|
||||||
|
max_chars_in: 5000
|
||||||
|
max_bytes_out: 52428800 # 50MB
|
||||||
|
rate_limit_rpm: 1
|
||||||
|
concurrency: 1
|
||||||
|
|
||||||
|
tts_speak:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_chars_in: 5000
|
||||||
|
max_bytes_out: 5242880
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
|
||||||
|
presentation_create:
|
||||||
|
timeout_ms: 120000
|
||||||
|
max_chars_in: 100000
|
||||||
|
max_bytes_out: 20971520 # 20MB
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
|
||||||
|
file_tool:
|
||||||
|
timeout_ms: 60000
|
||||||
|
max_chars_in: 524288
|
||||||
|
max_bytes_out: 20971520
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
|
||||||
|
data_governance_tool:
|
||||||
|
timeout_ms: 30000 # 30s (file I/O + regex scanning)
|
||||||
|
max_chars_in: 3000 # params only
|
||||||
|
max_bytes_out: 1048576 # 1MB (findings list can be verbose)
|
||||||
|
rate_limit_rpm: 5 # read-heavy, limit frequency
|
||||||
|
concurrency: 1 # serial: filesystem-bound
|
||||||
|
actions:
|
||||||
|
digest_audit:
|
||||||
|
timeout_ms: 20000
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
|
||||||
|
cost_analyzer_tool:
|
||||||
|
timeout_ms: 30000 # raised: Postgres queries may take longer
|
||||||
|
max_chars_in: 2000 # params only
|
||||||
|
max_bytes_out: 1048576 # 1MB (report may include many breakdowns)
|
||||||
|
rate_limit_rpm: 10 # light reads, allow more
|
||||||
|
concurrency: 2
|
||||||
|
actions:
|
||||||
|
digest:
|
||||||
|
timeout_ms: 20000
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
|
||||||
|
dependency_scanner_tool:
|
||||||
|
timeout_ms: 45000 # 45s (online mode may need more time)
|
||||||
|
max_chars_in: 3000 # params only
|
||||||
|
max_bytes_out: 1048576 # 1MB (vuln list can be verbose)
|
||||||
|
rate_limit_rpm: 5 # expensive scan
|
||||||
|
concurrency: 1 # serial: avoids hammering OSV API
|
||||||
|
|
||||||
|
drift_analyzer_tool:
|
||||||
|
timeout_ms: 30000 # 30s (reads many files)
|
||||||
|
max_chars_in: 5000 # params only, no large input
|
||||||
|
max_bytes_out: 524288 # 512KB (findings can be verbose)
|
||||||
|
rate_limit_rpm: 5 # expensive — limit calls
|
||||||
|
concurrency: 1
|
||||||
|
|
||||||
|
market_data:
|
||||||
|
timeout_ms: 10000
|
||||||
|
max_chars_in: 1000
|
||||||
|
max_bytes_out: 65536
|
||||||
|
rate_limit_rpm: 60
|
||||||
|
|
||||||
|
architecture_pressure_tool:
|
||||||
|
service:
|
||||||
|
timeout_ms: 10000
|
||||||
|
rate_limit_rpm: 30
|
||||||
|
dashboard:
|
||||||
|
timeout_ms: 20000
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
digest:
|
||||||
|
timeout_ms: 30000
|
||||||
|
rate_limit_rpm: 2
|
||||||
|
|
||||||
|
backlog_tool:
|
||||||
|
list:
|
||||||
|
timeout_ms: 10000
|
||||||
|
rate_limit_rpm: 30
|
||||||
|
get:
|
||||||
|
timeout_ms: 5000
|
||||||
|
rate_limit_rpm: 60
|
||||||
|
dashboard:
|
||||||
|
timeout_ms: 10000
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
create:
|
||||||
|
timeout_ms: 20000
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
upsert:
|
||||||
|
timeout_ms: 20000
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
set_status:
|
||||||
|
timeout_ms: 10000
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
add_comment:
|
||||||
|
timeout_ms: 5000
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
close:
|
||||||
|
timeout_ms: 10000
|
||||||
|
rate_limit_rpm: 5
|
||||||
|
auto_generate_weekly:
|
||||||
|
timeout_ms: 30000
|
||||||
|
rate_limit_rpm: 2
|
||||||
|
cleanup:
|
||||||
|
timeout_ms: 30000
|
||||||
|
rate_limit_rpm: 2
|
||||||
|
|
||||||
|
calendar_tool:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_chars_in: 12000
|
||||||
|
max_bytes_out: 262144
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
concurrency: 2
|
||||||
|
|
||||||
|
agent_email_tool:
|
||||||
|
timeout_ms: 30000
|
||||||
|
max_chars_in: 10000
|
||||||
|
max_bytes_out: 262144
|
||||||
|
rate_limit_rpm: 10
|
||||||
|
concurrency: 1
|
||||||
|
|
||||||
|
browser_tool:
|
||||||
|
timeout_ms: 60000
|
||||||
|
max_chars_in: 8000
|
||||||
|
max_bytes_out: 262144
|
||||||
|
rate_limit_rpm: 8
|
||||||
|
concurrency: 1
|
||||||
|
|
||||||
|
safe_code_executor_tool:
|
||||||
|
timeout_ms: 10000
|
||||||
|
max_chars_in: 12000
|
||||||
|
max_bytes_out: 131072
|
||||||
|
rate_limit_rpm: 12
|
||||||
|
concurrency: 2
|
||||||
|
|
||||||
|
secure_vault_tool:
|
||||||
|
timeout_ms: 15000
|
||||||
|
max_chars_in: 4000
|
||||||
|
max_bytes_out: 65536
|
||||||
|
rate_limit_rpm: 20
|
||||||
|
concurrency: 2
|
||||||
118
config/tools_rollout.yml
Normal file
118
config/tools_rollout.yml
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# Tool Rollout Configuration
|
||||||
|
# Defines default tool groups and role → tools mapping
|
||||||
|
# Used by agent_tools_config.py for automatic merge policy
|
||||||
|
#
|
||||||
|
# Syntax:
|
||||||
|
# - @group_name → expands to all tools in that group
|
||||||
|
# - tool_name → literal tool name
|
||||||
|
|
||||||
|
# ─── Tool Groups ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
default_tools_read:
|
||||||
|
- repo_tool
|
||||||
|
- kb_tool
|
||||||
|
- oncall_tool
|
||||||
|
- observability_tool
|
||||||
|
- memory_search
|
||||||
|
- graph_query
|
||||||
|
- web_search
|
||||||
|
- web_extract
|
||||||
|
- remember_fact
|
||||||
|
|
||||||
|
cto_tools:
|
||||||
|
- pr_reviewer_tool
|
||||||
|
- contract_tool
|
||||||
|
- config_linter_tool
|
||||||
|
- threatmodel_tool
|
||||||
|
- job_orchestrator_tool
|
||||||
|
- dependency_scanner_tool
|
||||||
|
- drift_analyzer_tool
|
||||||
|
- cost_analyzer_tool
|
||||||
|
- data_governance_tool
|
||||||
|
- calendar_tool
|
||||||
|
- agent_email_tool
|
||||||
|
- browser_tool
|
||||||
|
- safe_code_executor_tool
|
||||||
|
- secure_vault_tool
|
||||||
|
|
||||||
|
content_tools:
|
||||||
|
- image_generate
|
||||||
|
- tts_speak
|
||||||
|
- presentation_create
|
||||||
|
- presentation_status
|
||||||
|
- presentation_download
|
||||||
|
- file_tool
|
||||||
|
- crawl4ai_scrape
|
||||||
|
|
||||||
|
media_tools:
|
||||||
|
- comfy_generate_image
|
||||||
|
- comfy_generate_video
|
||||||
|
|
||||||
|
# ─── Role Map ────────────────────────────────────────────────────────────────
|
||||||
|
# Maps role → list of tool groups/tools
|
||||||
|
# Agents inherit tools from their role automatically.
|
||||||
|
# agent_specific tools are additive on top of role tools.
|
||||||
|
|
||||||
|
role_map:
|
||||||
|
agent_default:
|
||||||
|
# All agents get read + content tools by default
|
||||||
|
tools:
|
||||||
|
- "@default_tools_read"
|
||||||
|
- "@content_tools"
|
||||||
|
|
||||||
|
agent_cto:
|
||||||
|
# CTO-role agents (sofiia, yaromir) get everything
|
||||||
|
tools:
|
||||||
|
- "@default_tools_read"
|
||||||
|
- "@cto_tools"
|
||||||
|
- "@content_tools"
|
||||||
|
- "@media_tools"
|
||||||
|
|
||||||
|
agent_oncall:
|
||||||
|
# Oncall agents: read + job orchestration
|
||||||
|
tools:
|
||||||
|
- "@default_tools_read"
|
||||||
|
- job_orchestrator_tool
|
||||||
|
|
||||||
|
agent_media:
|
||||||
|
# Media/content agents: read + all media
|
||||||
|
tools:
|
||||||
|
- "@default_tools_read"
|
||||||
|
- "@content_tools"
|
||||||
|
- "@media_tools"
|
||||||
|
|
||||||
|
agent_monitor:
|
||||||
|
# Monitor agents (per-node): read-only observability + health + KB
|
||||||
|
tools:
|
||||||
|
- observability_tool
|
||||||
|
- oncall_tool
|
||||||
|
- kb_tool
|
||||||
|
|
||||||
|
agent_interface:
|
||||||
|
# Interface agents (AISTALK): minimal read + incident list
|
||||||
|
tools:
|
||||||
|
- kb_tool
|
||||||
|
- oncall_tool
|
||||||
|
|
||||||
|
# ─── Agent → Role Assignment ─────────────────────────────────────────────────
|
||||||
|
agent_roles:
|
||||||
|
sofiia: agent_cto
|
||||||
|
admin: agent_cto
|
||||||
|
yaromir: agent_cto
|
||||||
|
helion: agent_oncall
|
||||||
|
alateya: agent_media
|
||||||
|
nutra: agent_media
|
||||||
|
agromatrix: agent_media
|
||||||
|
greenfood: agent_media
|
||||||
|
druid: agent_media
|
||||||
|
daarwizz: agent_default
|
||||||
|
clan: agent_default
|
||||||
|
eonarch: agent_media
|
||||||
|
senpai: agent_default
|
||||||
|
soul: agent_media
|
||||||
|
daarion: agent_media
|
||||||
|
oneok: agent_default
|
||||||
|
# Infrastructure / monitoring agents
|
||||||
|
monitor: agent_monitor
|
||||||
|
aistalk: agent_interface
|
||||||
|
# Fallback: unknown agents get agent_default
|
||||||
@@ -37,8 +37,10 @@ services:
|
|||||||
- BACKLOG_BACKEND=auto
|
- BACKLOG_BACKEND=auto
|
||||||
- INCIDENT_BACKEND=auto
|
- INCIDENT_BACKEND=auto
|
||||||
- AUDIT_BACKEND=auto
|
- AUDIT_BACKEND=auto
|
||||||
|
- CALENDAR_SERVICE_URL=http://calendar-service:8001
|
||||||
volumes:
|
volumes:
|
||||||
- ./services/router/router-config.node2.yml:/app/router-config.yml:ro
|
- ./services/router/router-config.node2.yml:/app/router-config.yml:ro
|
||||||
|
- ./tools:/app/tools:ro
|
||||||
- ./logs:/app/logs
|
- ./logs:/app/logs
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.docker.internal:host-gateway"
|
- "host.docker.internal:host-gateway"
|
||||||
@@ -47,6 +49,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- dagi-nats
|
- dagi-nats
|
||||||
- node-capabilities
|
- node-capabilities
|
||||||
|
- calendar-service
|
||||||
networks:
|
networks:
|
||||||
- dagi-network
|
- dagi-network
|
||||||
- dagi-memory-network
|
- dagi-memory-network
|
||||||
@@ -77,6 +80,62 @@ services:
|
|||||||
- dagi-memory-network
|
- dagi-memory-network
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
|
aurora-service:
|
||||||
|
build:
|
||||||
|
context: ./services/aurora-service
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: aurora-service-node2
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:9401:9401"
|
||||||
|
environment:
|
||||||
|
- AURORA_DATA_DIR=/data/aurora
|
||||||
|
- AURORA_PUBLIC_BASE_URL=http://127.0.0.1:9401
|
||||||
|
- AURORA_CORS_ORIGINS=*
|
||||||
|
- AURORA_MODELS_DIR=/data/aurora/models
|
||||||
|
- AURORA_FORCE_CPU=false
|
||||||
|
- AURORA_PREFER_MPS=true
|
||||||
|
- AURORA_ENABLE_VIDEOTOOLBOX=true
|
||||||
|
volumes:
|
||||||
|
- sofiia-data:/data
|
||||||
|
networks:
|
||||||
|
- dagi-network
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
radicale:
|
||||||
|
image: tomsquest/docker-radicale:latest
|
||||||
|
container_name: daarion-radicale-node2
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5232:5232"
|
||||||
|
environment:
|
||||||
|
- RADICALE_HOST=0.0.0.0
|
||||||
|
- RADICALE_PORT=5232
|
||||||
|
- RADICALE_LOG_LEVEL=INFO
|
||||||
|
volumes:
|
||||||
|
- radicale-data:/data
|
||||||
|
- radicale-config:/config
|
||||||
|
networks:
|
||||||
|
- dagi-network
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
calendar-service:
|
||||||
|
build:
|
||||||
|
context: ./services/calendar-service
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: calendar-service-node2
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8001:8001"
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=sqlite:////data/calendar.db
|
||||||
|
- RADICALE_URL=http://radicale:5232
|
||||||
|
- PYTHONUNBUFFERED=1
|
||||||
|
depends_on:
|
||||||
|
- radicale
|
||||||
|
volumes:
|
||||||
|
- sofiia-data:/data
|
||||||
|
networks:
|
||||||
|
- dagi-network
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
dagi-nats:
|
dagi-nats:
|
||||||
image: nats:2.10-alpine
|
image: nats:2.10-alpine
|
||||||
container_name: dagi-nats-node2
|
container_name: dagi-nats-node2
|
||||||
@@ -157,11 +216,17 @@ services:
|
|||||||
- NODE_DEFAULT_VISION=llava:13b
|
- NODE_DEFAULT_VISION=llava:13b
|
||||||
- NODE_WORKER_MAX_CONCURRENCY=2
|
- NODE_WORKER_MAX_CONCURRENCY=2
|
||||||
- NCS_REPORT_URL=http://node-capabilities:8099
|
- NCS_REPORT_URL=http://node-capabilities:8099
|
||||||
# Capability providers (none = not available on this node)
|
# Capability providers: delegate STT/TTS to Memory Service (Phase 1)
|
||||||
- STT_PROVIDER=none
|
# Set to mlx_whisper/mlx_kokoro for Phase 2 MLX upgrade
|
||||||
- TTS_PROVIDER=none
|
- STT_PROVIDER=memory_service
|
||||||
|
- TTS_PROVIDER=memory_service
|
||||||
|
- MEMORY_SERVICE_URL=http://memory-service:8000
|
||||||
- OCR_PROVIDER=vision_prompted
|
- OCR_PROVIDER=vision_prompted
|
||||||
- IMAGE_PROVIDER=none
|
- IMAGE_PROVIDER=none
|
||||||
|
# Voice HA: dedicated concurrency limits for voice.*.request subjects
|
||||||
|
- VOICE_MAX_CONCURRENT_TTS=4
|
||||||
|
- VOICE_MAX_CONCURRENT_LLM=2
|
||||||
|
- VOICE_MAX_CONCURRENT_STT=2
|
||||||
depends_on:
|
depends_on:
|
||||||
- dagi-nats
|
- dagi-nats
|
||||||
networks:
|
networks:
|
||||||
@@ -187,15 +252,30 @@ services:
|
|||||||
- OLLAMA_URL=${OLLAMA_URL:-http://host.docker.internal:11434}
|
- OLLAMA_URL=${OLLAMA_URL:-http://host.docker.internal:11434}
|
||||||
- NOTION_API_KEY=${NOTION_API_KEY:-}
|
- NOTION_API_KEY=${NOTION_API_KEY:-}
|
||||||
- OPENCODE_URL=${OPENCODE_URL:-}
|
- OPENCODE_URL=${OPENCODE_URL:-}
|
||||||
|
- AURORA_SERVICE_URL=http://aurora-service:9401
|
||||||
# P1 SECURITY: SSH_PASSWORD removed — use key file instead
|
# P1 SECURITY: SSH_PASSWORD removed — use key file instead
|
||||||
# NODES_NODA1_SSH_PASSWORD is NO LONGER passed; sofiia-console reads from key file
|
# NODES_NODA1_SSH_PASSWORD is NO LONGER passed; sofiia-console reads from key file
|
||||||
- NODES_NODA1_SSH_PRIVATE_KEY=/run/secrets/noda1_ssh_key
|
- NODES_NODA1_SSH_PRIVATE_KEY=/run/secrets/noda1_ssh_key
|
||||||
- SUPERVISOR_API_KEY=${SUPERVISOR_API_KEY}
|
- SUPERVISOR_API_KEY=${SUPERVISOR_API_KEY}
|
||||||
- SOFIIA_CONSOLE_API_KEY=${SOFIIA_CONSOLE_API_KEY}
|
- SOFIIA_CONSOLE_API_KEY=${SOFIIA_CONSOLE_API_KEY}
|
||||||
- CORS_ORIGINS=${CORS_ORIGINS:-}
|
- CORS_ORIGINS=${CORS_ORIGINS:-}
|
||||||
|
# Voice HA feature flag (default: false = legacy direct path to memory-service)
|
||||||
|
- VOICE_HA_ENABLED=${VOICE_HA_ENABLED:-false}
|
||||||
|
- VOICE_HA_ROUTER_URL=${VOICE_HA_ROUTER_URL:-http://router:8000}
|
||||||
|
# Projects / Documents / Sessions / Dialog Map (SQLite)
|
||||||
|
- SOFIIA_DATA_DIR=/app/data
|
||||||
|
- UPLOAD_MAX_IMAGE_MB=${UPLOAD_MAX_IMAGE_MB:-10}
|
||||||
|
- UPLOAD_MAX_VIDEO_MB=${UPLOAD_MAX_VIDEO_MB:-200}
|
||||||
|
- UPLOAD_MAX_DOC_MB=${UPLOAD_MAX_DOC_MB:-50}
|
||||||
|
# Phase 2 feature flags (disabled by default)
|
||||||
|
- USE_FABRIC_OCR=${USE_FABRIC_OCR:-false}
|
||||||
|
- USE_EMBEDDINGS=${USE_EMBEDDINGS:-false}
|
||||||
|
# Supervisor proxy (LangGraph workflows)
|
||||||
|
- SUPERVISOR_URL=${SUPERVISOR_URL:-http://sofiia-supervisor:8080}
|
||||||
volumes:
|
volumes:
|
||||||
- ./config:/app/config
|
- ./config:/app/config
|
||||||
- ./secrets/noda1_id_ed25519:/run/secrets/noda1_ssh_key:ro
|
- ./secrets/noda1_id_ed25519:/run/secrets/noda1_ssh_key:ro
|
||||||
|
- sofiia-data:/app/data
|
||||||
depends_on:
|
depends_on:
|
||||||
- router
|
- router
|
||||||
networks:
|
networks:
|
||||||
@@ -210,3 +290,11 @@ networks:
|
|||||||
dagi-memory-network:
|
dagi-memory-network:
|
||||||
external: true
|
external: true
|
||||||
name: dagi-memory-network-node2
|
name: dagi-memory-network-node2
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
sofiia-data:
|
||||||
|
driver: local
|
||||||
|
radicale-data:
|
||||||
|
driver: local
|
||||||
|
radicale-config:
|
||||||
|
driver: local
|
||||||
|
|||||||
12
services/calendar-service/Dockerfile
Normal file
12
services/calendar-service/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 8001
|
||||||
|
|
||||||
|
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8001"]
|
||||||
198
services/calendar-service/storage.py
Normal file
198
services/calendar-service/storage.py
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
"""
|
||||||
|
Calendar Storage - Database models and operations
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional, List
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# Simple SQLite-based storage (can be replaced with Postgres)
|
||||||
|
class CalendarStorage:
|
||||||
|
"""In-memory/SQLite storage for calendar accounts and reminders"""
|
||||||
|
|
||||||
|
def __init__(self, db_session=None):
|
||||||
|
self.db = db_session
|
||||||
|
self._accounts = {}
|
||||||
|
self._reminders = {}
|
||||||
|
self._idempotency_keys = {}
|
||||||
|
self._next_id = 1
|
||||||
|
|
||||||
|
def create_account(
|
||||||
|
self,
|
||||||
|
workspace_id: str,
|
||||||
|
user_id: str,
|
||||||
|
provider: str,
|
||||||
|
username: str,
|
||||||
|
password: str,
|
||||||
|
principal_url: str = None,
|
||||||
|
default_calendar_id: str = None
|
||||||
|
):
|
||||||
|
"""Create calendar account"""
|
||||||
|
# Check if exists
|
||||||
|
for acc in self._accounts.values():
|
||||||
|
if (acc.workspace_id == workspace_id and
|
||||||
|
acc.user_id == user_id and
|
||||||
|
acc.provider == provider):
|
||||||
|
# Update
|
||||||
|
acc.username = username
|
||||||
|
acc.password = password
|
||||||
|
acc.principal_url = principal_url
|
||||||
|
acc.default_calendar_id = default_calendar_id
|
||||||
|
acc.updated_at = datetime.utcnow()
|
||||||
|
return acc
|
||||||
|
|
||||||
|
# Create new
|
||||||
|
account = CalendarAccount(
|
||||||
|
id=f"acc_{self._next_id}",
|
||||||
|
workspace_id=workspace_id,
|
||||||
|
user_id=user_id,
|
||||||
|
provider=provider,
|
||||||
|
username=username,
|
||||||
|
password=password, # In production, encrypt this!
|
||||||
|
principal_url=principal_url,
|
||||||
|
default_calendar_id=default_calendar_id
|
||||||
|
)
|
||||||
|
|
||||||
|
self._accounts[account.id] = account
|
||||||
|
self._next_id += 1
|
||||||
|
|
||||||
|
logger.info(f"Created calendar account: {account.id}")
|
||||||
|
|
||||||
|
return account
|
||||||
|
|
||||||
|
def get_account(self, account_id: str) -> Optional[CalendarAccount]:
|
||||||
|
"""Get account by ID"""
|
||||||
|
return self._accounts.get(account_id)
|
||||||
|
|
||||||
|
def list_accounts(
|
||||||
|
self,
|
||||||
|
workspace_id: str,
|
||||||
|
user_id: str
|
||||||
|
) -> List[CalendarAccount]:
|
||||||
|
"""List accounts for user"""
|
||||||
|
return [
|
||||||
|
acc for acc in self._accounts.values()
|
||||||
|
if acc.workspace_id == workspace_id and acc.user_id == user_id
|
||||||
|
]
|
||||||
|
|
||||||
|
def count_accounts(self) -> int:
|
||||||
|
"""Count total accounts"""
|
||||||
|
return len(self._accounts)
|
||||||
|
|
||||||
|
def create_reminder(
|
||||||
|
self,
|
||||||
|
workspace_id: str,
|
||||||
|
user_id: str,
|
||||||
|
account_id: str,
|
||||||
|
event_uid: str,
|
||||||
|
remind_at: str,
|
||||||
|
channel: str = "inapp"
|
||||||
|
) -> "CalendarReminder":
|
||||||
|
"""Create reminder"""
|
||||||
|
reminder = CalendarReminder(
|
||||||
|
id=f"rem_{self._next_id}",
|
||||||
|
workspace_id=workspace_id,
|
||||||
|
user_id=user_id,
|
||||||
|
account_id=account_id,
|
||||||
|
event_uid=event_uid,
|
||||||
|
remind_at=datetime.fromisoformat(remind_at),
|
||||||
|
channel=channel,
|
||||||
|
status="pending"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._reminders[reminder.id] = reminder
|
||||||
|
self._next_id += 1
|
||||||
|
|
||||||
|
logger.info(f"Created reminder: {reminder.id}")
|
||||||
|
|
||||||
|
return reminder
|
||||||
|
|
||||||
|
def get_pending_reminders(self) -> List["CalendarReminder"]:
|
||||||
|
"""Get pending reminders"""
|
||||||
|
now = datetime.utcnow()
|
||||||
|
return [
|
||||||
|
r for r in self._reminders.values()
|
||||||
|
if r.status == "pending" and r.remind_at <= now
|
||||||
|
]
|
||||||
|
|
||||||
|
def update_reminder_status(
|
||||||
|
self,
|
||||||
|
reminder_id: str,
|
||||||
|
status: str,
|
||||||
|
error: str = None
|
||||||
|
):
|
||||||
|
"""Update reminder status"""
|
||||||
|
if reminder_id in self._reminders:
|
||||||
|
self._reminders[reminder_id].status = status
|
||||||
|
self._reminders[reminder_id].attempts += 1
|
||||||
|
if error:
|
||||||
|
self._reminders[reminder_id].last_error = error
|
||||||
|
|
||||||
|
def count_pending_reminders(self) -> int:
|
||||||
|
"""Count pending reminders"""
|
||||||
|
return len([r for r in self._reminders.values() if r.status == "pending"])
|
||||||
|
|
||||||
|
def store_idempotency_key(
|
||||||
|
self,
|
||||||
|
key: str,
|
||||||
|
workspace_id: str,
|
||||||
|
user_id: str,
|
||||||
|
event_uid: str
|
||||||
|
):
|
||||||
|
"""Store idempotency key"""
|
||||||
|
self._idempotency_keys[key] = {
|
||||||
|
"workspace_id": workspace_id,
|
||||||
|
"user_id": user_id,
|
||||||
|
"event_uid": event_uid
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_by_idempotency_key(self, key: str) -> Optional[dict]:
|
||||||
|
"""Get event UID by idempotency key"""
|
||||||
|
return self._idempotency_keys.get(key)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CalendarAccount:
|
||||||
|
"""Calendar account model"""
|
||||||
|
id: str
|
||||||
|
workspace_id: str
|
||||||
|
user_id: str
|
||||||
|
provider: str
|
||||||
|
username: str
|
||||||
|
password: str
|
||||||
|
principal_url: str = None
|
||||||
|
default_calendar_id: str = None
|
||||||
|
created_at: datetime = None
|
||||||
|
updated_at: datetime = None
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.created_at is None:
|
||||||
|
self.created_at = datetime.utcnow()
|
||||||
|
if self.updated_at is None:
|
||||||
|
self.updated_at = datetime.utcnow()
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CalendarReminder:
|
||||||
|
"""Calendar reminder model"""
|
||||||
|
id: str
|
||||||
|
workspace_id: str
|
||||||
|
user_id: str
|
||||||
|
account_id: str
|
||||||
|
event_uid: str
|
||||||
|
remind_at: datetime
|
||||||
|
channel: str
|
||||||
|
status: str = "pending"
|
||||||
|
attempts: int = 0
|
||||||
|
last_error: str = None
|
||||||
|
created_at: datetime = None
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.created_at is None:
|
||||||
|
self.created_at = datetime.utcnow()
|
||||||
@@ -10,6 +10,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
# Install dependencies
|
# Install dependencies
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
RUN python -m playwright install --with-deps chromium
|
||||||
|
|
||||||
# Copy application
|
# Copy application
|
||||||
COPY . .
|
COPY . .
|
||||||
@@ -37,4 +38,3 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,11 @@ AGENT_SPECIALIZED_TOOLS = {
|
|||||||
'cost_analyzer_tool',
|
'cost_analyzer_tool',
|
||||||
'pieces_tool',
|
'pieces_tool',
|
||||||
'notion_tool',
|
'notion_tool',
|
||||||
|
'calendar_tool',
|
||||||
|
'agent_email_tool',
|
||||||
|
'browser_tool',
|
||||||
|
'safe_code_executor_tool',
|
||||||
|
'secure_vault_tool',
|
||||||
],
|
],
|
||||||
|
|
||||||
# Admin - platform operations
|
# Admin - platform operations
|
||||||
@@ -154,6 +159,11 @@ AGENT_SPECIALIZED_TOOLS = {
|
|||||||
'cost_analyzer_tool',
|
'cost_analyzer_tool',
|
||||||
'pieces_tool',
|
'pieces_tool',
|
||||||
'notion_tool',
|
'notion_tool',
|
||||||
|
'calendar_tool',
|
||||||
|
'agent_email_tool',
|
||||||
|
'browser_tool',
|
||||||
|
'safe_code_executor_tool',
|
||||||
|
'secure_vault_tool',
|
||||||
],
|
],
|
||||||
|
|
||||||
# Daarion - Media Generation
|
# Daarion - Media Generation
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ pypdf>=5.1.0
|
|||||||
python-pptx>=0.6.23
|
python-pptx>=0.6.23
|
||||||
odfpy>=1.4.1
|
odfpy>=1.4.1
|
||||||
pyarrow>=18.0.0
|
pyarrow>=18.0.0
|
||||||
|
cryptography>=41.0.0
|
||||||
|
aiofiles>=23.2.1
|
||||||
|
playwright>=1.40.0
|
||||||
|
|
||||||
# Memory Retrieval v3.0
|
# Memory Retrieval v3.0
|
||||||
asyncpg>=0.29.0
|
asyncpg>=0.29.0
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user