multi-agent-platform 0.1.0__py3-none-any.whl
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.
- cli/__init__.py +0 -0
- cli/action_item_escalation.py +177 -0
- cli/agent_client.py +554 -0
- cli/bridge_state.py +43 -0
- cli/commands/__init__.py +13 -0
- cli/commands/action.py +142 -0
- cli/commands/agent.py +117 -0
- cli/commands/audit.py +68 -0
- cli/commands/docs.py +179 -0
- cli/commands/experiment.py +755 -0
- cli/commands/feedback.py +106 -0
- cli/commands/notification.py +213 -0
- cli/commands/persona.py +63 -0
- cli/commands/project.py +87 -0
- cli/commands/runtime.py +105 -0
- cli/commands/topic.py +361 -0
- cli/e2e_collab.py +602 -0
- cli/git_checkpoint.py +68 -0
- cli/host_worker_types.py +151 -0
- cli/main.py +1553 -0
- cli/map_command_client.py +497 -0
- cli/participant_worker.py +255 -0
- cli/reviewer_worker.py +263 -0
- cli/runtime/__init__.py +5 -0
- cli/runtime/run_lock.py +497 -0
- cli/runtime_chat.py +317 -0
- cli/session_wake_log.py +235 -0
- cli/simple_waker.py +950 -0
- cli/table_render.py +113 -0
- cli/wake_backend.py +236 -0
- cli/worker_cycle_log.py +36 -0
- map_client/__init__.py +37 -0
- map_client/bootstrap.py +193 -0
- map_client/client.py +1045 -0
- map_client/config.py +21 -0
- map_client/errors.py +283 -0
- map_client/exceptions.py +130 -0
- map_client/plan_evidence.py +159 -0
- map_client/project_config.py +153 -0
- map_client/result_template.py +167 -0
- map_client/testing.py +27 -0
- map_mcp/__init__.py +4 -0
- map_mcp/_utils.py +28 -0
- map_mcp/auth.py +34 -0
- map_mcp/config.py +50 -0
- map_mcp/context.py +39 -0
- map_mcp/main.py +75 -0
- map_mcp/server.py +573 -0
- map_mcp/session.py +79 -0
- map_sdk/__init__.py +29 -0
- map_sdk/evidence.py +68 -0
- map_types/__init__.py +203 -0
- map_types/enums.py +199 -0
- map_types/schemas.py +1351 -0
- multi_agent_platform-0.1.0.dist-info/METADATA +298 -0
- multi_agent_platform-0.1.0.dist-info/RECORD +144 -0
- multi_agent_platform-0.1.0.dist-info/WHEEL +5 -0
- multi_agent_platform-0.1.0.dist-info/entry_points.txt +6 -0
- multi_agent_platform-0.1.0.dist-info/licenses/LICENSE +21 -0
- multi_agent_platform-0.1.0.dist-info/top_level.txt +6 -0
- server/__init__.py +0 -0
- server/__version__.py +14 -0
- server/api/__init__.py +0 -0
- server/api/action_items.py +138 -0
- server/api/agents.py +412 -0
- server/api/audit.py +54 -0
- server/api/background_tasks.py +18 -0
- server/api/common.py +117 -0
- server/api/deps.py +30 -0
- server/api/experiments.py +858 -0
- server/api/feedback.py +75 -0
- server/api/notifications.py +22 -0
- server/api/projects.py +209 -0
- server/api/router.py +25 -0
- server/api/status.py +33 -0
- server/api/topics.py +302 -0
- server/api/webhooks.py +74 -0
- server/auth/__init__.py +8 -0
- server/auth/experiment_access.py +66 -0
- server/config.py +38 -0
- server/db/__init__.py +3 -0
- server/db/base.py +5 -0
- server/db/deadlock_retry.py +146 -0
- server/db/session.py +41 -0
- server/domain/__init__.py +3 -0
- server/domain/encrypted_types.py +63 -0
- server/domain/models.py +713 -0
- server/domain/schemas.py +3 -0
- server/domain/state_machine.py +79 -0
- server/domain/topic_ack_constants.py +9 -0
- server/main.py +148 -0
- server/scripts/__init__.py +0 -0
- server/scripts/migrate_notification_unique.py +231 -0
- server/scripts/purge_audit_pollution.py +116 -0
- server/services/__init__.py +0 -0
- server/services/_lookups.py +26 -0
- server/services/acceptance_service.py +90 -0
- server/services/action_item_migration_service.py +190 -0
- server/services/action_item_service.py +200 -0
- server/services/agent_work_service.py +405 -0
- server/services/archive_lint_service.py +156 -0
- server/services/audit_service.py +457 -0
- server/services/auth.py +66 -0
- server/services/comment_service.py +173 -0
- server/services/errors.py +65 -0
- server/services/escalation_resolver.py +248 -0
- server/services/evidence_service.py +88 -0
- server/services/experiment_capabilities_service.py +277 -0
- server/services/inbound_event_service.py +111 -0
- server/services/lock_service.py +273 -0
- server/services/log_service.py +202 -0
- server/services/mention_service.py +730 -0
- server/services/notification_service.py +939 -0
- server/services/notification_stream.py +138 -0
- server/services/permissions.py +147 -0
- server/services/persona_activity_service.py +108 -0
- server/services/phase_owner_resolver.py +95 -0
- server/services/phase_service.py +381 -0
- server/services/plan_marker_service.py +235 -0
- server/services/plan_service.py +186 -0
- server/services/platform_feedback_service.py +114 -0
- server/services/project_service.py +534 -0
- server/services/project_status_service.py +132 -0
- server/services/review_service.py +707 -0
- server/services/secret_encryption.py +97 -0
- server/services/similarity_service.py +119 -0
- server/services/sse_event_schemas.py +17 -0
- server/services/status_service.py +68 -0
- server/services/template_service.py +134 -0
- server/services/text_utils.py +19 -0
- server/services/thread_activity.py +180 -0
- server/services/todo_persona_filter.py +73 -0
- server/services/todo_service.py +604 -0
- server/services/topic_ack_service.py +312 -0
- server/services/topic_action_item_ops.py +538 -0
- server/services/topic_comment_kind.py +14 -0
- server/services/topic_comment_service.py +237 -0
- server/services/topic_helpers.py +32 -0
- server/services/topic_lifecycle_service.py +478 -0
- server/services/topic_progress_service.py +40 -0
- server/services/topic_resolve_service.py +234 -0
- server/services/topic_service.py +102 -0
- server/services/topic_work_item_service.py +570 -0
- server/services/webhook_service.py +273 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""Topic resolve + decision read helpers.
|
|
2
|
+
|
|
3
|
+
拆分自 ``topic_service.py``。本模块负责:
|
|
4
|
+
- ``resolve_topic``(决策 upsert + action_item 二次约束)
|
|
5
|
+
- ``topic_decision_read`` / ``_load_decision`` / ``list_project_decisions``
|
|
6
|
+
|
|
7
|
+
Action-item 序列化委托 ``topic_action_item_ops``;
|
|
8
|
+
``topic_service`` re-exports 保持 import 兼容。
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import uuid
|
|
13
|
+
from datetime import UTC, datetime
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from map_types.enums import AgentRole, TopicActionItemStatus
|
|
17
|
+
from sqlalchemy import select
|
|
18
|
+
from sqlalchemy.orm import Session, joinedload
|
|
19
|
+
|
|
20
|
+
from server.domain.models import Agent, Experiment, Topic, TopicActionItem, TopicDecision
|
|
21
|
+
from server.domain.schemas import TopicDecisionRead, TopicResolve
|
|
22
|
+
from server.services import audit_service
|
|
23
|
+
from server.services._lookups import get_project
|
|
24
|
+
from server.services.errors import NotFoundError
|
|
25
|
+
from server.services.topic_action_item_ops import (
|
|
26
|
+
_action_item_read,
|
|
27
|
+
_linked_experiment_phases_batch,
|
|
28
|
+
_suggest_linked_experiments_batch,
|
|
29
|
+
)
|
|
30
|
+
from server.services.topic_helpers import _get_topic
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def topic_decision_read(db: Session, decision: TopicDecision) -> TopicDecisionRead:
|
|
34
|
+
author_name = None
|
|
35
|
+
author = getattr(decision, "author", None)
|
|
36
|
+
if author is None:
|
|
37
|
+
author = db.get(Agent, decision.author_agent_id)
|
|
38
|
+
if author is not None:
|
|
39
|
+
author_name = author.name
|
|
40
|
+
|
|
41
|
+
topic_title = None
|
|
42
|
+
topic = getattr(decision, "topic", None)
|
|
43
|
+
if topic is None:
|
|
44
|
+
topic = db.get(Topic, decision.topic_id)
|
|
45
|
+
if topic is not None:
|
|
46
|
+
topic_title = topic.title
|
|
47
|
+
|
|
48
|
+
suggested_map = _suggest_linked_experiments_batch(db, list(decision.action_items))
|
|
49
|
+
phase_map = _linked_experiment_phases_batch(db, list(decision.action_items))
|
|
50
|
+
return TopicDecisionRead(
|
|
51
|
+
id=decision.id,
|
|
52
|
+
project_id=decision.project_id,
|
|
53
|
+
topic_id=decision.topic_id,
|
|
54
|
+
topic_title=topic_title,
|
|
55
|
+
author_agent_id=decision.author_agent_id,
|
|
56
|
+
author_name=author_name,
|
|
57
|
+
decision=decision.decision,
|
|
58
|
+
rationale=decision.rationale,
|
|
59
|
+
rejected_options=decision.rejected_options,
|
|
60
|
+
open_questions=decision.open_questions,
|
|
61
|
+
no_decision_reason=decision.no_decision_reason,
|
|
62
|
+
action_items=[
|
|
63
|
+
_action_item_read(
|
|
64
|
+
db,
|
|
65
|
+
item,
|
|
66
|
+
suggested=suggested_map.get(item.id),
|
|
67
|
+
linked_experiment_phase=phase_map.get(item.id),
|
|
68
|
+
linked_experiment_phase_provided=True,
|
|
69
|
+
)
|
|
70
|
+
for item in decision.action_items
|
|
71
|
+
],
|
|
72
|
+
created_at=decision.created_at,
|
|
73
|
+
updated_at=decision.updated_at,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _load_decision(db: Session, topic_id: uuid.UUID) -> TopicDecision | None:
|
|
78
|
+
stmt = (
|
|
79
|
+
select(TopicDecision)
|
|
80
|
+
.where(TopicDecision.topic_id == topic_id)
|
|
81
|
+
.options(
|
|
82
|
+
joinedload(TopicDecision.author),
|
|
83
|
+
joinedload(TopicDecision.topic),
|
|
84
|
+
joinedload(TopicDecision.action_items).joinedload(TopicActionItem.owner),
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
return db.execute(stmt).unique().scalar_one_or_none()
|
|
88
|
+
def resolve_topic(
|
|
89
|
+
db: Session,
|
|
90
|
+
topic_id: uuid.UUID,
|
|
91
|
+
author: Agent,
|
|
92
|
+
payload: TopicResolve,
|
|
93
|
+
) -> TopicDecision:
|
|
94
|
+
topic = _get_topic(db, topic_id)
|
|
95
|
+
decision = db.scalar(select(TopicDecision).where(TopicDecision.topic_id == topic_id))
|
|
96
|
+
if decision is None:
|
|
97
|
+
decision = TopicDecision(
|
|
98
|
+
project_id=topic.project_id,
|
|
99
|
+
topic_id=topic.id,
|
|
100
|
+
author_agent_id=author.id,
|
|
101
|
+
)
|
|
102
|
+
db.add(decision)
|
|
103
|
+
db.flush()
|
|
104
|
+
else:
|
|
105
|
+
decision.author_agent_id = author.id
|
|
106
|
+
|
|
107
|
+
decision.decision = payload.decision
|
|
108
|
+
decision.rationale = payload.rationale
|
|
109
|
+
decision.rejected_options = payload.rejected_options
|
|
110
|
+
decision.open_questions = payload.open_questions
|
|
111
|
+
decision.no_decision_reason = payload.no_decision_reason
|
|
112
|
+
|
|
113
|
+
# --- 二次约束: 旧项不在新 payload 中 → 等价显式 done (A1 resolve idempotency) -
|
|
114
|
+
# Up until v0.x the resolver did ``db.execute(delete(TopicActionItem))`` and
|
|
115
|
+
# re-inserted from payload, which made every re-resolve a destructive
|
|
116
|
+
# delete-and-rebuild and made ``status=done`` impossible to persist. The new
|
|
117
|
+
# rule is: items not present in the new payload (by id) are auto-closed as
|
|
118
|
+
# ``done``; items present are upserted by id (fields updated, status
|
|
119
|
+
# preserved); items with no id are inserted as open.
|
|
120
|
+
existing = list(
|
|
121
|
+
db.scalars(select(TopicActionItem).where(TopicActionItem.decision_id == decision.id))
|
|
122
|
+
)
|
|
123
|
+
existing_by_id = {item.id: item for item in existing}
|
|
124
|
+
new_payload_ids: set[uuid.UUID] = {
|
|
125
|
+
item.id for item in payload.action_items if item.id is not None
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
audit_entries: list[dict[str, Any]] = []
|
|
129
|
+
for old_item in existing:
|
|
130
|
+
if old_item.id in new_payload_ids:
|
|
131
|
+
continue
|
|
132
|
+
# 旧项不在新 payload:若仍为 open,等价显式 done(写 audit;已 closed 项保持原状)。
|
|
133
|
+
if old_item.status == TopicActionItemStatus.open:
|
|
134
|
+
prev_status = old_item.status
|
|
135
|
+
old_item.status = TopicActionItemStatus.done
|
|
136
|
+
old_item.updated_at = datetime.now(UTC)
|
|
137
|
+
audit_entries.append(
|
|
138
|
+
{
|
|
139
|
+
"action": "action_item.completed",
|
|
140
|
+
"target_id": old_item.id,
|
|
141
|
+
"payload": {
|
|
142
|
+
"action_item_id": str(old_item.id),
|
|
143
|
+
"prev_status": prev_status.value,
|
|
144
|
+
"new_status": old_item.status.value,
|
|
145
|
+
"triggered_by": "topic_resolve",
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
for item_payload in payload.action_items:
|
|
151
|
+
if item_payload.owner_agent_id is not None:
|
|
152
|
+
owner = db.get(Agent, item_payload.owner_agent_id)
|
|
153
|
+
if owner is None or (owner.project_id != topic.project_id and owner.role != AgentRole.admin):
|
|
154
|
+
raise NotFoundError("Action item owner agent not found")
|
|
155
|
+
if item_payload.linked_experiment_id is not None:
|
|
156
|
+
experiment = db.get(Experiment, item_payload.linked_experiment_id)
|
|
157
|
+
if experiment is None or experiment.deleted_at is not None or experiment.project_id != topic.project_id:
|
|
158
|
+
raise NotFoundError("Linked experiment not found")
|
|
159
|
+
if item_payload.id is not None and item_payload.id in existing_by_id:
|
|
160
|
+
old_item = existing_by_id[item_payload.id]
|
|
161
|
+
old_item.title = item_payload.title
|
|
162
|
+
old_item.description = item_payload.description
|
|
163
|
+
old_item.owner_agent_id = item_payload.owner_agent_id
|
|
164
|
+
old_item.due_at = item_payload.due_at
|
|
165
|
+
old_item.linked_experiment_id = item_payload.linked_experiment_id
|
|
166
|
+
old_item.topic_id = topic.id
|
|
167
|
+
if item_payload.category is not None:
|
|
168
|
+
old_item.category = item_payload.category.value
|
|
169
|
+
else:
|
|
170
|
+
# Stamp first_open_at at creation so the waker's T+24h / T+72h
|
|
171
|
+
# escalation timer starts immediately on resolve. Plan §2: open
|
|
172
|
+
# transitions are the moment the timer anchors to. Existing open
|
|
173
|
+
# items are backfilled by alembic migration 027.
|
|
174
|
+
db.add(
|
|
175
|
+
TopicActionItem(
|
|
176
|
+
decision_id=decision.id,
|
|
177
|
+
project_id=topic.project_id,
|
|
178
|
+
topic_id=topic.id,
|
|
179
|
+
title=item_payload.title,
|
|
180
|
+
description=item_payload.description,
|
|
181
|
+
owner_agent_id=item_payload.owner_agent_id,
|
|
182
|
+
status=TopicActionItemStatus.open,
|
|
183
|
+
due_at=item_payload.due_at,
|
|
184
|
+
linked_experiment_id=item_payload.linked_experiment_id,
|
|
185
|
+
category=item_payload.category.value if item_payload.category else None,
|
|
186
|
+
first_open_at=datetime.now(UTC),
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Audit 与状态变更同事务:audit_entries 收集的「旧项等价 done」事件用
|
|
191
|
+
# log_no_commit 累积,与上面的 decision / action_item 变更在单次 commit 内
|
|
192
|
+
# 一起落库。commit 失败则全部回滚——不再出现「decision 已存但 audit 缺失」。
|
|
193
|
+
for entry in audit_entries:
|
|
194
|
+
audit_service.log_no_commit(
|
|
195
|
+
db,
|
|
196
|
+
action=entry["action"],
|
|
197
|
+
target_type="topic_action_item",
|
|
198
|
+
target_id=entry["target_id"],
|
|
199
|
+
agent_id=author.id,
|
|
200
|
+
project_id=topic.project_id,
|
|
201
|
+
summary="resolve 二次约束关闭 action_item",
|
|
202
|
+
payload=entry["payload"],
|
|
203
|
+
)
|
|
204
|
+
db.commit()
|
|
205
|
+
|
|
206
|
+
loaded = _load_decision(db, topic.id)
|
|
207
|
+
if loaded is None:
|
|
208
|
+
raise NotFoundError("Topic decision not found")
|
|
209
|
+
return loaded
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def list_project_decisions(
|
|
213
|
+
db: Session,
|
|
214
|
+
project_id: uuid.UUID,
|
|
215
|
+
*,
|
|
216
|
+
limit: int = 20,
|
|
217
|
+
) -> list[TopicDecisionRead]:
|
|
218
|
+
get_project(db, project_id)
|
|
219
|
+
rows = list(
|
|
220
|
+
db.scalars(
|
|
221
|
+
select(TopicDecision)
|
|
222
|
+
.where(TopicDecision.project_id == project_id)
|
|
223
|
+
.options(
|
|
224
|
+
joinedload(TopicDecision.author),
|
|
225
|
+
joinedload(TopicDecision.topic),
|
|
226
|
+
joinedload(TopicDecision.action_items).joinedload(TopicActionItem.owner),
|
|
227
|
+
)
|
|
228
|
+
.order_by(TopicDecision.updated_at.desc())
|
|
229
|
+
.limit(max(1, min(limit, 100)))
|
|
230
|
+
)
|
|
231
|
+
.unique()
|
|
232
|
+
)
|
|
233
|
+
return [topic_decision_read(db, row) for row in rows]
|
|
234
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Topic domain service facade.
|
|
2
|
+
|
|
3
|
+
Business logic lives in:
|
|
4
|
+
- ``topic_lifecycle_service`` — CRUD / summaries / rounds
|
|
5
|
+
- ``topic_resolve_service`` — resolve + decisions
|
|
6
|
+
- ``topic_action_item_ops`` — action-item mutations + reads
|
|
7
|
+
- ``topic_comment_service`` — comments (earlier split)
|
|
8
|
+
- ``topic_helpers`` — shared ``_get_topic`` / ``_agent_names_by_ids``
|
|
9
|
+
|
|
10
|
+
This module re-exports the public (and historically private) API so
|
|
11
|
+
existing ``from server.services.topic_service import ...`` call sites
|
|
12
|
+
and ``topic_service.<name>`` attribute access keep working.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from server.services import topic_comment_service
|
|
17
|
+
from server.services.topic_action_item_ops import (
|
|
18
|
+
_action_item_read,
|
|
19
|
+
_complete_action_item_no_commit,
|
|
20
|
+
_ensure_action_item_accessor,
|
|
21
|
+
_linked_experiment_phases_batch,
|
|
22
|
+
_suggest_linked_experiment,
|
|
23
|
+
_suggest_linked_experiments_batch,
|
|
24
|
+
cancel_action_item,
|
|
25
|
+
complete_action_item,
|
|
26
|
+
deliver_action_item,
|
|
27
|
+
deliver_action_item_no_commit,
|
|
28
|
+
link_action_item,
|
|
29
|
+
list_action_items,
|
|
30
|
+
mark_stale_action_item,
|
|
31
|
+
mark_wake_sent_action_item,
|
|
32
|
+
)
|
|
33
|
+
from server.services.topic_helpers import _agent_names_by_ids, _get_topic
|
|
34
|
+
from server.services.topic_lifecycle_service import (
|
|
35
|
+
advance_topic_round,
|
|
36
|
+
create_topic,
|
|
37
|
+
dismiss_topic,
|
|
38
|
+
get_topic_detail,
|
|
39
|
+
list_topics,
|
|
40
|
+
mark_topic_read,
|
|
41
|
+
record_participant_round_ack,
|
|
42
|
+
set_topic_status,
|
|
43
|
+
soft_delete_topic,
|
|
44
|
+
topic_summaries_for_topics,
|
|
45
|
+
topic_summary,
|
|
46
|
+
update_topic,
|
|
47
|
+
)
|
|
48
|
+
from server.services.topic_resolve_service import (
|
|
49
|
+
_load_decision,
|
|
50
|
+
list_project_decisions,
|
|
51
|
+
resolve_topic,
|
|
52
|
+
topic_decision_read,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Comment CRUD / tree / seq — re-export for backward compatibility.
|
|
56
|
+
_build_comment_tree = topic_comment_service._build_comment_tree
|
|
57
|
+
_ensure_comment_seq_values = topic_comment_service._ensure_comment_seq_values
|
|
58
|
+
_next_topic_comment_seq = topic_comment_service._next_topic_comment_seq
|
|
59
|
+
create_topic_comment = topic_comment_service.create_topic_comment
|
|
60
|
+
topic_comment_read = topic_comment_service.topic_comment_read
|
|
61
|
+
list_topic_comments = topic_comment_service.list_topic_comments
|
|
62
|
+
|
|
63
|
+
__all__ = [
|
|
64
|
+
"_agent_names_by_ids",
|
|
65
|
+
"_get_topic",
|
|
66
|
+
"_action_item_read",
|
|
67
|
+
"_complete_action_item_no_commit",
|
|
68
|
+
"_ensure_action_item_accessor",
|
|
69
|
+
"_linked_experiment_phases_batch",
|
|
70
|
+
"_load_decision",
|
|
71
|
+
"_suggest_linked_experiment",
|
|
72
|
+
"_suggest_linked_experiments_batch",
|
|
73
|
+
"_build_comment_tree",
|
|
74
|
+
"_ensure_comment_seq_values",
|
|
75
|
+
"_next_topic_comment_seq",
|
|
76
|
+
"advance_topic_round",
|
|
77
|
+
"cancel_action_item",
|
|
78
|
+
"complete_action_item",
|
|
79
|
+
"create_topic",
|
|
80
|
+
"create_topic_comment",
|
|
81
|
+
"deliver_action_item",
|
|
82
|
+
"deliver_action_item_no_commit",
|
|
83
|
+
"dismiss_topic",
|
|
84
|
+
"get_topic_detail",
|
|
85
|
+
"link_action_item",
|
|
86
|
+
"list_action_items",
|
|
87
|
+
"list_project_decisions",
|
|
88
|
+
"list_topic_comments",
|
|
89
|
+
"list_topics",
|
|
90
|
+
"mark_stale_action_item",
|
|
91
|
+
"mark_topic_read",
|
|
92
|
+
"mark_wake_sent_action_item",
|
|
93
|
+
"record_participant_round_ack",
|
|
94
|
+
"resolve_topic",
|
|
95
|
+
"set_topic_status",
|
|
96
|
+
"soft_delete_topic",
|
|
97
|
+
"topic_comment_read",
|
|
98
|
+
"topic_decision_read",
|
|
99
|
+
"topic_summaries_for_topics",
|
|
100
|
+
"topic_summary",
|
|
101
|
+
"update_topic",
|
|
102
|
+
]
|