This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/packages/workflow-chat/script.star
Jeffrey Smith fa2c4808d6
Some checks failed
CI/CD / detect-changes (pull_request) Successful in 21s
CI/CD / build-and-deploy (pull_request) Has been cancelled
CI/CD / test-frontend (pull_request) Has been cancelled
CI/CD / test-sqlite (pull_request) Has been cancelled
CI/CD / test-go-pg (pull_request) Has been cancelled
Feat v0.5.3 chat polish + integration testing
Conversation search (db.query search_like, chat-core /search endpoint,
sidebar search UI), message pagination polish (scroll preservation,
loading spinner), workflow-chat integration package, and multi-user
E2E test infrastructure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:03:50 +00:00

89 lines
2.7 KiB
Plaintext

# 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}