Feat v0.5.3 chat polish (#33)
All checks were successful
All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #33.
This commit is contained in:
41
packages/workflow-chat/README.md
Normal file
41
packages/workflow-chat/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Workflow Chat Integration
|
||||
|
||||
Creates scoped chat conversations when workflow stages require team collaboration.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Install the `workflow-chat` and `chat-core` packages.
|
||||
2. In your workflow stage with `audience: team`, set `stage_config`:
|
||||
|
||||
```json
|
||||
{
|
||||
"on_advance": {
|
||||
"package_id": "workflow-chat",
|
||||
"entry_point": "on_advance"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. When the workflow advances to that stage, ensure `stage_data` includes:
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Bug Triage Discussion",
|
||||
"team_members": [
|
||||
{"id": "user-1", "display_name": "Alice"},
|
||||
{"id": "user-2", "display_name": "Bob"}
|
||||
],
|
||||
"creator_id": "user-1",
|
||||
"creator_display_name": "Alice"
|
||||
}
|
||||
```
|
||||
|
||||
The hook will:
|
||||
- Create a group conversation titled `"Bug Triage Discussion [abcd1234]"` (suffixed with instance ID)
|
||||
- Add all team members as participants
|
||||
- Send a system message linking to the workflow instance
|
||||
- Enrich `stage_data` with the `conversation_id`
|
||||
|
||||
## Idempotency
|
||||
|
||||
If `stage_data` already contains a `conversation_id`, the hook returns `None` (no-op).
|
||||
15
packages/workflow-chat/manifest.json
Normal file
15
packages/workflow-chat/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"id": "workflow-chat",
|
||||
"title": "Workflow Chat",
|
||||
"type": "library",
|
||||
"tier": "starlark",
|
||||
"version": "0.1.0",
|
||||
"description": "Creates scoped chat conversations when workflow stages require team collaboration. Wire into stage_config as an on_advance hook.",
|
||||
"author": "switchboard",
|
||||
|
||||
"permissions": ["db.write", "realtime.publish"],
|
||||
|
||||
"depends": ["chat-core"],
|
||||
|
||||
"exports": ["on_advance"]
|
||||
}
|
||||
88
packages/workflow-chat/script.star
Normal file
88
packages/workflow-chat/script.star
Normal file
@@ -0,0 +1,88 @@
|
||||
# Workflow Chat — Starlark Backend (v0.1.0)
|
||||
#
|
||||
# Library package that creates scoped chat conversations when
|
||||
# workflow stages require team collaboration.
|
||||
#
|
||||
# Usage: wire into stage_config as an on_advance hook:
|
||||
# {"on_advance": {"package_id": "workflow-chat", "entry_point": "on_advance"}}
|
||||
#
|
||||
# Expected stage_data keys:
|
||||
# title — conversation title (optional, defaults to "Workflow Discussion")
|
||||
# team_members — list of {id, display_name} dicts
|
||||
# creator_id — user ID of the workflow initiator
|
||||
# creator_display_name — display name of the workflow initiator
|
||||
#
|
||||
# Modules: db, json, realtime (via chat-core dependency)
|
||||
|
||||
chat = lib.require("chat-core")
|
||||
|
||||
|
||||
def _str(v):
|
||||
if v == None:
|
||||
return ""
|
||||
return str(v)
|
||||
|
||||
|
||||
def on_advance(ctx):
|
||||
"""Hook called when a workflow advances to a team-audience stage.
|
||||
|
||||
Creates a group conversation with all team members and sends
|
||||
a system message linking back to the workflow instance.
|
||||
|
||||
Args:
|
||||
ctx: dict with {instance_id, previous_stage, current_stage, stage_data}
|
||||
|
||||
Returns:
|
||||
dict with {stage_data} containing enriched data with conversation_id,
|
||||
or None if no team members are present.
|
||||
"""
|
||||
data = ctx.get("stage_data", {})
|
||||
if type(data) == "string":
|
||||
data = json.decode(data) if data else {}
|
||||
|
||||
instance_id = _str(ctx.get("instance_id", ""))
|
||||
members = data.get("team_members", [])
|
||||
creator_id = _str(data.get("creator_id", ""))
|
||||
creator_name = _str(data.get("creator_display_name", ""))
|
||||
title = _str(data.get("title", "")) or "Workflow Discussion"
|
||||
|
||||
# Skip if no team members to add
|
||||
if not members:
|
||||
return None
|
||||
|
||||
# Check if conversation already exists for this instance (idempotency)
|
||||
existing_cid = _str(data.get("conversation_id", ""))
|
||||
if existing_cid:
|
||||
return None
|
||||
|
||||
# Build participants list
|
||||
participants = []
|
||||
for m in members:
|
||||
mid = _str(m.get("id", ""))
|
||||
if mid and mid != creator_id:
|
||||
participants.append({
|
||||
"id": mid,
|
||||
"display_name": _str(m.get("display_name", "")),
|
||||
})
|
||||
|
||||
# Create conversation scoped to this workflow instance
|
||||
conv = chat.create(
|
||||
title=title + " [" + instance_id[:8] + "]",
|
||||
type="group",
|
||||
participants=participants,
|
||||
creator_id=creator_id,
|
||||
creator_display_name=creator_name,
|
||||
)
|
||||
|
||||
cid = _str(conv.get("id", ""))
|
||||
|
||||
# Send system message linking to the workflow
|
||||
chat.send(cid, creator_id, "Conversation created for workflow instance " + instance_id, "system")
|
||||
|
||||
# Return enriched stage_data with conversation_id
|
||||
enriched = {}
|
||||
for k in data:
|
||||
enriched[k] = data[k]
|
||||
enriched["conversation_id"] = cid
|
||||
|
||||
return {"stage_data": enriched}
|
||||
Reference in New Issue
Block a user