@chorus-aidlc/chorus 0.7.0 → 0.7.1
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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-build-manifest.json +313 -313
- package/.next/standalone/.next/app-path-routes-manifest.json +45 -45
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +33 -33
- package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/ideas/[ideaUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/ideas/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/companies/[uuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies/new.html +1 -1
- package/.next/standalone/.next/server/app/admin/companies/new.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/companies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies.html +1 -1
- package/.next/standalone/.next/server/app/admin/companies.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin.html +1 -1
- package/.next/standalone/.next/server/app/admin.rsc +1 -1
- package/.next/standalone/.next/server/app/api/admin/companies/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/companies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/login/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/session/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/api-keys/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/api-keys/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/callback/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/check-default/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/company-oidc/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/default-login/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/identify/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/me/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/refresh/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/session/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/sync-token/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/comments/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/documents/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/events/notifications/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/events/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/mcp/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/me/assignments/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/mentionables/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/preferences/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/read-all/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/unread-count/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/[uuid]/dashboard/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/activity/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/documents/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/group/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/[proposalUuid]/validate/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/summary/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/stats/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/approve/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/close/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/reject/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/revoke/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +1 -1
- package/.next/standalone/.next/server/app/login/admin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/admin.html +1 -1
- package/.next/standalone/.next/server/app/login/admin.rsc +1 -1
- package/.next/standalone/.next/server/app/login/callback/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/callback.html +1 -1
- package/.next/standalone/.next/server/app/login/callback.rsc +1 -1
- package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/pick-workspace/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/pick-workspace.html +1 -1
- package/.next/standalone/.next/server/app/login/pick-workspace.rsc +1 -1
- package/.next/standalone/.next/server/app/login/silent-refresh/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/silent-refresh.html +1 -1
- package/.next/standalone/.next/server/app/login/silent-refresh.rsc +1 -1
- package/.next/standalone/.next/server/app/login.html +1 -1
- package/.next/standalone/.next/server/app/login.rsc +1 -1
- package/.next/standalone/.next/server/app/onboarding/page.js +3 -2
- package/.next/standalone/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/onboarding.html +1 -1
- package/.next/standalone/.next/server/app/onboarding.rsc +2 -2
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects.html +1 -1
- package/.next/standalone/.next/server/app/projects.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.html +1 -1
- package/.next/standalone/.next/server/app/settings.rsc +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +45 -45
- package/.next/standalone/.next/server/chunks/2961.js +1 -1
- package/.next/standalone/.next/server/chunks/6113.js +1 -1
- package/.next/standalone/.next/server/chunks/7368.js +1 -1
- package/.next/standalone/.next/server/chunks/920.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/.next/standalone/.next/server/middleware-manifest.json +1 -1
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/pages-manifest.json +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/{4860.d626399834b496e5.js → 4860.15c9ae5b6268c6fc.js} +1 -1
- package/.next/standalone/.next/static/chunks/{99373.aedaca88297c6d8b.js → 99373.9939e11f5b4e0615.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/onboarding/page-8d755192f0f67938.js +1 -0
- package/.next/standalone/.next/static/chunks/{webpack-da41e6b9f3fe2f48.js → webpack-1bb984dd0934fa96.js} +1 -1
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/public/install-opencode.sh +284 -0
- package/README.md +12 -5
- package/README.zh.md +12 -5
- package/package.json +1 -1
- package/.next/standalone/.next/static/chunks/app/onboarding/page-e9409a2935c3c480.js +0 -1
- /package/.next/standalone/.next/static/{CQcM9hNpa5m8P_K5qveuk → TJ6qFSxjQGUSajvwbI2qu}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{CQcM9hNpa5m8P_K5qveuk → TJ6qFSxjQGUSajvwbI2qu}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Chorus + OpenCode one-shot plugin installer
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# curl -fsSL https://<your-chorus>/install-opencode.sh | bash
|
|
6
|
+
#
|
|
7
|
+
# What this does (idempotent, safe to re-run):
|
|
8
|
+
# 1. Verifies `opencode` CLI is installed.
|
|
9
|
+
# 2. Adds "opencode-chorus" to the `plugin` array in
|
|
10
|
+
# ~/.config/opencode/opencode.json. Creates the file if missing.
|
|
11
|
+
# Preserves any existing plugins.
|
|
12
|
+
# 3. Sets file permissions to 600.
|
|
13
|
+
#
|
|
14
|
+
# What this does NOT do:
|
|
15
|
+
# - Write to ~/.bashrc / ~/.zshrc. You must export CHORUS_URL and
|
|
16
|
+
# CHORUS_API_KEY yourself before launching opencode (the plugin reads
|
|
17
|
+
# process.env on startup).
|
|
18
|
+
# - Invoke jq / node / python. Pure POSIX awk/sed/grep only.
|
|
19
|
+
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
# ---------- cosmetics ----------
|
|
23
|
+
BOLD=$'\033[1m'; DIM=$'\033[2m'; GREEN=$'\033[32m'; YELLOW=$'\033[33m'; RED=$'\033[31m'; RESET=$'\033[0m'
|
|
24
|
+
ok() { printf "${GREEN}\xe2\x9c\x93${RESET} %s\n" "$*"; }
|
|
25
|
+
warn() { printf "${YELLOW}!${RESET} %s\n" "$*" >&2; }
|
|
26
|
+
die() { printf "${RED}\xe2\x9c\x97${RESET} %s\n" "$*" >&2; exit 1; }
|
|
27
|
+
hdr() { printf "\n${BOLD}%s${RESET}\n" "$*"; }
|
|
28
|
+
|
|
29
|
+
# ---------- config ----------
|
|
30
|
+
PLUGIN_NAME="opencode-chorus"
|
|
31
|
+
CONFIG_DIR="${OPENCODE_CONFIG_DIR:-$HOME/.config/opencode}"
|
|
32
|
+
CONFIG_FILE="$CONFIG_DIR/opencode.json"
|
|
33
|
+
BACKUP_FILE="$CONFIG_FILE.chorus-bak"
|
|
34
|
+
|
|
35
|
+
# ---------- step 1: check opencode ----------
|
|
36
|
+
hdr "1/3 Checking OpenCode CLI"
|
|
37
|
+
if command -v opencode >/dev/null 2>&1; then
|
|
38
|
+
ok "Found $(opencode --version 2>/dev/null | head -1)"
|
|
39
|
+
else
|
|
40
|
+
warn "opencode not found in PATH — install it first: https://opencode.ai/docs/"
|
|
41
|
+
warn "Proceeding to write the config anyway. OpenCode will pick it up on install."
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# ---------- step 2: ensure config dir ----------
|
|
45
|
+
hdr "2/3 Updating $CONFIG_FILE"
|
|
46
|
+
mkdir -p "$CONFIG_DIR"
|
|
47
|
+
|
|
48
|
+
# Helper: print the manual instructions and exit 0 (non-fatal).
|
|
49
|
+
print_manual_hint() {
|
|
50
|
+
warn "Could not automatically update $CONFIG_FILE."
|
|
51
|
+
warn "Please add \"$PLUGIN_NAME\" to the \"plugin\" array manually:"
|
|
52
|
+
cat >&2 <<HINT
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
"\$schema": "https://opencode.ai/config.json",
|
|
56
|
+
"plugin": ["$PLUGIN_NAME"${EXISTING_PLUGIN_HINT:-}]
|
|
57
|
+
...
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
HINT
|
|
61
|
+
exit 0
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# ---------- Case A: file does not exist ----------
|
|
65
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
66
|
+
cat > "$CONFIG_FILE" <<JSON
|
|
67
|
+
{
|
|
68
|
+
"\$schema": "https://opencode.ai/config.json",
|
|
69
|
+
"plugin": ["$PLUGIN_NAME"]
|
|
70
|
+
}
|
|
71
|
+
JSON
|
|
72
|
+
chmod 600 "$CONFIG_FILE"
|
|
73
|
+
ok "Created $CONFIG_FILE with $PLUGIN_NAME"
|
|
74
|
+
else
|
|
75
|
+
# File exists — back it up once.
|
|
76
|
+
if [ ! -f "$BACKUP_FILE" ]; then
|
|
77
|
+
cp "$CONFIG_FILE" "$BACKUP_FILE"
|
|
78
|
+
chmod 600 "$BACKUP_FILE"
|
|
79
|
+
ok "Backed up original config to $BACKUP_FILE"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# Reject JSONC (comments). Presence of // or /* strongly suggests the file
|
|
83
|
+
# is hand-edited JSONC; our line-based awk would mangle it. Bail cleanly.
|
|
84
|
+
if grep -qE '^[[:space:]]*//|/\*' "$CONFIG_FILE"; then
|
|
85
|
+
warn "Detected // or /* in $CONFIG_FILE — looks like JSONC with comments."
|
|
86
|
+
print_manual_hint
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Case C1: plugin array already contains opencode-chorus → no-op.
|
|
90
|
+
# Scope the check to the "plugin" array itself: a top-level occurrence of
|
|
91
|
+
# "opencode-chorus" outside that array (e.g. in a "lastInstalled" field)
|
|
92
|
+
# must not trigger the no-op shortcut.
|
|
93
|
+
plugin_contains_self() {
|
|
94
|
+
awk -v plugin="$PLUGIN_NAME" '
|
|
95
|
+
# Track whether we are currently inside the first "plugin" array.
|
|
96
|
+
# State machine:
|
|
97
|
+
# 0 = before the plugin key
|
|
98
|
+
# 1 = inside the plugin array (between its [ and matching ])
|
|
99
|
+
BEGIN { state = 0 }
|
|
100
|
+
state == 0 {
|
|
101
|
+
# Is the "plugin" key on this line?
|
|
102
|
+
if (match($0, /"plugin"[[:space:]]*:[[:space:]]*\[/)) {
|
|
103
|
+
# Consume the rest of the line starting at the [
|
|
104
|
+
rest = substr($0, RSTART + RLENGTH - 1)
|
|
105
|
+
state = 1
|
|
106
|
+
# Fall through to state == 1 handling for this rest.
|
|
107
|
+
$0 = rest
|
|
108
|
+
} else {
|
|
109
|
+
next
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
state == 1 {
|
|
113
|
+
# Look for the closing ] on this line (naive — good enough for
|
|
114
|
+
# standard JSON because plugin entries are plain strings).
|
|
115
|
+
close_pos = index($0, "]")
|
|
116
|
+
if (close_pos > 0) {
|
|
117
|
+
chunk = substr($0, 1, close_pos - 1)
|
|
118
|
+
} else {
|
|
119
|
+
chunk = $0
|
|
120
|
+
}
|
|
121
|
+
# Check for the quoted token inside the array chunk only.
|
|
122
|
+
if (index(chunk, "\"" plugin "\"") > 0) {
|
|
123
|
+
print "yes"
|
|
124
|
+
exit 0
|
|
125
|
+
}
|
|
126
|
+
if (close_pos > 0) exit 0
|
|
127
|
+
}
|
|
128
|
+
' "$CONFIG_FILE"
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if [ "$(plugin_contains_self)" = "yes" ]; then
|
|
132
|
+
ok "$PLUGIN_NAME already present in $CONFIG_FILE — nothing to do"
|
|
133
|
+
else
|
|
134
|
+
# Decide: Case B (no plugin key) vs Case C2 (plugin key exists without this plugin).
|
|
135
|
+
if grep -qE '"plugin"[[:space:]]*:' "$CONFIG_FILE"; then
|
|
136
|
+
# Case C2: insert into existing plugin array.
|
|
137
|
+
# Strategy: find the first "plugin" key, locate its array bracket pair,
|
|
138
|
+
# insert "opencode-chorus" before the closing ].
|
|
139
|
+
#
|
|
140
|
+
# Only handle the common cases where the array is on a single line or
|
|
141
|
+
# a multi-line array that has one entry per line. Otherwise bail to hint.
|
|
142
|
+
tmp="$(mktemp "${TMPDIR:-/tmp}/chorus-opencode.XXXXXX")"
|
|
143
|
+
if awk -v plugin="$PLUGIN_NAME" '
|
|
144
|
+
BEGIN { done = 0 }
|
|
145
|
+
# Single-line empty array: "plugin": []
|
|
146
|
+
!done && /"plugin"[[:space:]]*:[[:space:]]*\[[[:space:]]*\]/ {
|
|
147
|
+
sub(/\[[[:space:]]*\]/, "[\"" plugin "\"]")
|
|
148
|
+
done = 1
|
|
149
|
+
print
|
|
150
|
+
next
|
|
151
|
+
}
|
|
152
|
+
# Single-line non-empty array: "plugin": [ "foo", "bar" ]
|
|
153
|
+
!done && match($0, /"plugin"[[:space:]]*:[[:space:]]*\[[^\]]*\]/) {
|
|
154
|
+
line = $0
|
|
155
|
+
pre = substr(line, 1, RSTART - 1)
|
|
156
|
+
match_text = substr(line, RSTART, RLENGTH)
|
|
157
|
+
post = substr(line, RSTART + RLENGTH)
|
|
158
|
+
# Insert before the closing ]
|
|
159
|
+
sub(/\][[:space:]]*$/, ", \"" plugin "\"]", match_text)
|
|
160
|
+
# If the match still ends in ] (no trailing whitespace stripped), fall through
|
|
161
|
+
print pre match_text post
|
|
162
|
+
done = 1
|
|
163
|
+
next
|
|
164
|
+
}
|
|
165
|
+
# Multi-line array opener: "plugin": [ (and not on same line closer)
|
|
166
|
+
!done && /"plugin"[[:space:]]*:[[:space:]]*\[[[:space:]]*$/ {
|
|
167
|
+
print
|
|
168
|
+
getline nextline
|
|
169
|
+
# Empty multi-line array: next line is just ]
|
|
170
|
+
if (nextline ~ /^[[:space:]]*\][[:space:]]*,?[[:space:]]*$/) {
|
|
171
|
+
print " \"" plugin "\""
|
|
172
|
+
print nextline
|
|
173
|
+
done = 1
|
|
174
|
+
next
|
|
175
|
+
}
|
|
176
|
+
# Non-empty multi-line: emit entries verbatim until we hit the ]
|
|
177
|
+
buffer[++bn] = nextline
|
|
178
|
+
while ((getline nextline) > 0) {
|
|
179
|
+
if (nextline ~ /^[[:space:]]*\][[:space:]]*,?[[:space:]]*$/) {
|
|
180
|
+
# Last existing entry may not have trailing comma; add one.
|
|
181
|
+
last = buffer[bn]
|
|
182
|
+
if (last !~ /,[[:space:]]*$/) {
|
|
183
|
+
sub(/[[:space:]]*$/, ",", buffer[bn])
|
|
184
|
+
}
|
|
185
|
+
for (i = 1; i <= bn; i++) print buffer[i]
|
|
186
|
+
# Insert new entry before the closing ]
|
|
187
|
+
# Determine indentation from first buffered entry.
|
|
188
|
+
match(buffer[1], /^[[:space:]]*/)
|
|
189
|
+
indent = substr(buffer[1], 1, RLENGTH)
|
|
190
|
+
print indent "\"" plugin "\""
|
|
191
|
+
print nextline
|
|
192
|
+
done = 1
|
|
193
|
+
bn = 0
|
|
194
|
+
break
|
|
195
|
+
}
|
|
196
|
+
buffer[++bn] = nextline
|
|
197
|
+
}
|
|
198
|
+
next
|
|
199
|
+
}
|
|
200
|
+
{ print }
|
|
201
|
+
END {
|
|
202
|
+
if (!done) exit 2
|
|
203
|
+
}
|
|
204
|
+
' "$CONFIG_FILE" > "$tmp"; then
|
|
205
|
+
mv "$tmp" "$CONFIG_FILE"
|
|
206
|
+
chmod 600 "$CONFIG_FILE"
|
|
207
|
+
ok "Added $PLUGIN_NAME to existing \"plugin\" array"
|
|
208
|
+
else
|
|
209
|
+
rm -f "$tmp"
|
|
210
|
+
warn "The \"plugin\" key exists but I could not safely determine where to insert the new entry."
|
|
211
|
+
EXISTING_PLUGIN_HINT=", ...your existing entries..."
|
|
212
|
+
print_manual_hint
|
|
213
|
+
fi
|
|
214
|
+
else
|
|
215
|
+
# Case B: no plugin key in file → inject it.
|
|
216
|
+
# We look for the first top-level "{" then insert `"plugin": [...]` on the next line.
|
|
217
|
+
# Safer: look for the first line containing just "{" optionally with whitespace.
|
|
218
|
+
tmp="$(mktemp "${TMPDIR:-/tmp}/chorus-opencode.XXXXXX")"
|
|
219
|
+
if awk -v plugin="$PLUGIN_NAME" '
|
|
220
|
+
BEGIN { inserted = 0 }
|
|
221
|
+
!inserted && /^[[:space:]]*\{[[:space:]]*$/ {
|
|
222
|
+
print
|
|
223
|
+
print " \"plugin\": [\"" plugin "\"],"
|
|
224
|
+
inserted = 1
|
|
225
|
+
next
|
|
226
|
+
}
|
|
227
|
+
{ print }
|
|
228
|
+
END { if (!inserted) exit 2 }
|
|
229
|
+
' "$CONFIG_FILE" > "$tmp"; then
|
|
230
|
+
mv "$tmp" "$CONFIG_FILE"
|
|
231
|
+
chmod 600 "$CONFIG_FILE"
|
|
232
|
+
ok "Added \"plugin\" field with $PLUGIN_NAME to $CONFIG_FILE"
|
|
233
|
+
else
|
|
234
|
+
rm -f "$tmp"
|
|
235
|
+
warn "Could not find a line with just \"{\" to inject the plugin array."
|
|
236
|
+
print_manual_hint
|
|
237
|
+
fi
|
|
238
|
+
fi
|
|
239
|
+
fi
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
# ---------- step 3: reminders ----------
|
|
243
|
+
hdr "3/3 Final reminders"
|
|
244
|
+
|
|
245
|
+
# Environment check — read-only warning, don't export.
|
|
246
|
+
missing_env=""
|
|
247
|
+
if [ -z "${CHORUS_URL:-}" ]; then
|
|
248
|
+
missing_env="$missing_env CHORUS_URL"
|
|
249
|
+
fi
|
|
250
|
+
if [ -z "${CHORUS_API_KEY:-}" ]; then
|
|
251
|
+
missing_env="$missing_env CHORUS_API_KEY"
|
|
252
|
+
fi
|
|
253
|
+
|
|
254
|
+
if [ -n "$missing_env" ]; then
|
|
255
|
+
warn "The following environment variables are not set in this shell:$missing_env"
|
|
256
|
+
warn "The plugin reads them on OpenCode startup. Please export them in your shell rc:"
|
|
257
|
+
cat >&2 <<'HINT'
|
|
258
|
+
|
|
259
|
+
export CHORUS_URL="https://<your-chorus-instance>"
|
|
260
|
+
export CHORUS_API_KEY="cho_..."
|
|
261
|
+
|
|
262
|
+
HINT
|
|
263
|
+
warn "Then re-source your shell rc, or launch opencode from a shell where they are exported."
|
|
264
|
+
else
|
|
265
|
+
ok "CHORUS_URL and CHORUS_API_KEY are set in this shell"
|
|
266
|
+
fi
|
|
267
|
+
|
|
268
|
+
hdr "Done."
|
|
269
|
+
cat <<'NEXT'
|
|
270
|
+
Start OpenCode — Bun will fetch opencode-chorus on first launch:
|
|
271
|
+
|
|
272
|
+
opencode
|
|
273
|
+
|
|
274
|
+
Then in OpenCode, ask the agent:
|
|
275
|
+
|
|
276
|
+
check in to chorus
|
|
277
|
+
|
|
278
|
+
If the plugin fails to load, clear the package cache and retry:
|
|
279
|
+
|
|
280
|
+
rm -rf ~/.cache/opencode/packages/opencode-chorus@latest
|
|
281
|
+
|
|
282
|
+
To roll back this change:
|
|
283
|
+
NEXT
|
|
284
|
+
printf " mv %s %s\n\n" "$BACKUP_FILE" "$CONFIG_FILE"
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
<p align="center"><a href="README.zh.md">中文</a></p>
|
|
17
17
|
|
|
18
|
-
Chorus is an agent harness — the infrastructure that wraps around LLM agents to manage session lifecycle, task state, sub-agent orchestration, observability, and failure recovery. It lets multiple AI Agents (
|
|
18
|
+
Chorus is an agent harness — the infrastructure that wraps around LLM agents to manage session lifecycle, task state, sub-agent orchestration, observability, and failure recovery. It lets multiple AI Agents (with fine-grained, configurable permissions) and humans collaborate through the full workflow from requirements to delivery.
|
|
19
19
|
|
|
20
20
|
Inspired by the **[AI-DLC (AI-Driven Development Lifecycle)](https://aws.amazon.com/blogs/devops/ai-driven-development-life-cycle/)** methodology. Core philosophy: **Reversed Conversation** — AI proposes, humans verify.
|
|
21
21
|
|
|
@@ -35,6 +35,8 @@ creates analyzes drafts PRD codes & reviews closes
|
|
|
35
35
|
|
|
36
36
|
## What's New
|
|
37
37
|
|
|
38
|
+
**[v0.7.0](https://chorus-ai.dev/blog/chorus-v0.7.0-release/)** — Fine-grained agent permissions: 5 resources × 3 actions grid replaces the PM/Developer/Admin three-way choice, with presets + a Custom option for free combination.
|
|
39
|
+
|
|
38
40
|
**[v0.6.7](https://chorus-ai.dev/blog/chorus-v0.6.7-release/)** — Chorus plugin for Codex CLI (one-command installer), workspace picker when one email belongs to multiple Companies, per-client connect guides.
|
|
39
41
|
|
|
40
42
|
**[v0.6.6](https://chorus-ai.dev/blog/chorus-v0.6.6-release/)** — npm one-click install (`npx @chorus-aidlc/chorus`), document export (MD/PDF/Word), proposal revoke, faster agent checkin with work status at a glance.
|
|
@@ -153,6 +155,7 @@ A Cmd+K command palette for searching across all 6 entity types (Tasks, Ideas, P
|
|
|
153
155
|
- **Task DAG** — Dependency modeling, cycle detection, and interactive visualization
|
|
154
156
|
- **Kanban** — Real-time task flow with Worker badges and agent presence
|
|
155
157
|
- **Multi-Agent Collaboration** — Claude Code Agent Teams (Swarm Mode) for parallel execution
|
|
158
|
+
- **Fine-Grained Agent Permissions** — 5 resources × 3 actions grid with preset + custom combinations ([details](docs/PERMISSIONS.md))
|
|
156
159
|
- **Chorus Plugin** — Lifecycle hooks automate session create/close, heartbeats, and context injection
|
|
157
160
|
- **Requirements Elaboration** — Structured Q&A rounds before proposal creation
|
|
158
161
|
- **Proposal Approval Flow** — PM drafts, Admin approves, drafts materialize into real entities
|
|
@@ -178,7 +181,7 @@ A Cmd+K command palette for searching across all 6 entity types (Tasks, Ideas, P
|
|
|
178
181
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
179
182
|
│ │
|
|
180
183
|
│ ┌── API Layer ──────────────────────────────────────────────┐ │
|
|
181
|
-
│ │ /api/mcp — MCP
|
|
184
|
+
│ │ /api/mcp — MCP Streaming (50+ tools, permission-gated) │ │
|
|
182
185
|
│ │ /api/* — REST API (Web UI + SSE push) │ │
|
|
183
186
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
184
187
|
│ │
|
|
@@ -191,8 +194,9 @@ A Cmd+K command palette for searching across all 6 entity types (Tasks, Ideas, P
|
|
|
191
194
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
192
195
|
└──────────────────────────────────────────────────────────────────┘
|
|
193
196
|
↑ ↑ ↑ ↑
|
|
194
|
-
|
|
195
|
-
(
|
|
197
|
+
Agent w/ Agent w/ Agent w/ Human
|
|
198
|
+
PM perms Developer perms Admin perms (Browser)
|
|
199
|
+
(LLM) (LLM) (LLM)
|
|
196
200
|
│
|
|
197
201
|
┌──────────▼──────────┐ ┌─────────────────────┐
|
|
198
202
|
│ PostgreSQL + Prisma │ │ Redis (optional) │
|
|
@@ -290,7 +294,7 @@ The interactive installer provisions VPC, Aurora Serverless v2, ElastiCache Serv
|
|
|
290
294
|
|
|
291
295
|
### Connect AI Agents
|
|
292
296
|
|
|
293
|
-
The fastest path is the in-app setup wizard: open the Web UI, go to **Settings → Setup Guide → Open setup guide**, and follow the step-by-step instructions for your client (Claude Code, Codex, OpenClaw, or other agents). The wizard creates the API key for you, shows the exact commands, and walks through verifying the connection.
|
|
297
|
+
The fastest path is the in-app setup wizard: open the Web UI, go to **Settings → Setup Guide → Open setup guide**, and follow the step-by-step instructions for your client (Claude Code, Codex, OpenCode, OpenClaw, or other agents). The wizard creates the API key for you, shows the exact commands, and walks through verifying the connection.
|
|
294
298
|
|
|
295
299
|
If you'd rather read the full docs:
|
|
296
300
|
|
|
@@ -298,8 +302,11 @@ If you'd rather read the full docs:
|
|
|
298
302
|
|--------|-------|
|
|
299
303
|
| Claude Code | [CONNECT_CLAUDE_CODE.md](docs/CONNECT_CLAUDE_CODE.md) |
|
|
300
304
|
| Codex CLI | [CONNECT_CODEX.md](docs/CONNECT_CODEX.md) |
|
|
305
|
+
| OpenCode † | [CONNECT_OPENCODE.md](docs/CONNECT_OPENCODE.md) |
|
|
301
306
|
| Other MCP agents (Cursor, Continue, custom, …) | [CONNECT_OTHER_AGENTS.md](docs/CONNECT_OTHER_AGENTS.md) |
|
|
302
307
|
|
|
308
|
+
† OpenCode support is provided by the community-maintained [`opencode-chorus`](https://github.com/etnperlong/opencode-chorus) plugin (npm: [`opencode-chorus`](https://www.npmjs.com/package/opencode-chorus)), authored by [@etnperlong](https://github.com/etnperlong). Thanks!
|
|
309
|
+
|
|
303
310
|
Create API Keys in the Web UI under **Settings → Agents → Create API Key**. Keys start with `cho_` and are shown only once.
|
|
304
311
|
|
|
305
312
|

|
package/README.zh.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p align="center"><a href="README.md">English</a></p>
|
|
8
8
|
|
|
9
|
-
Chorus 是一个 Agent Harness——包裹在 LLM 外面的基础设施层,负责管理会话生命周期、任务状态、子 Agent
|
|
9
|
+
Chorus 是一个 Agent Harness——包裹在 LLM 外面的基础设施层,负责管理会话生命周期、任务状态、子 Agent 编排、可观测性和故障恢复。它让多个具备细粒度权限配置的 AI Agent 和人类在同一平台上协作,完成从需求到交付的全流程。
|
|
10
10
|
|
|
11
11
|
受 **[AI-DLC(AI-Driven Development Lifecycle)](https://aws.amazon.com/blogs/devops/ai-driven-development-life-cycle/)** 方法论启发。核心理念:**Reversed Conversation**——AI 提议,人类验证。
|
|
12
12
|
|
|
@@ -26,6 +26,8 @@ creates analyzes drafts PRD codes & reviews closes
|
|
|
26
26
|
|
|
27
27
|
## 最近更新
|
|
28
28
|
|
|
29
|
+
**[v0.7.0](https://chorus-ai.dev/zh/blog/chorus-v0.7.0-release/)** — 细粒度 Agent 权限:5 类资源 × 3 个动作组成的网格,取代 PM / Developer / Admin 三选一。保留原有预设,新增 Custom 选项自由组合。
|
|
30
|
+
|
|
29
31
|
**[v0.6.7](https://chorus-ai.dev/zh/blog/chorus-v0.6.7-release/)** — Codex CLI 版 Chorus 插件(一条命令装完)、同一邮箱属于多个 Company 时的工作区选择器、每种客户端的接入文档。
|
|
30
32
|
|
|
31
33
|
**[v0.6.6](https://chorus-ai.dev/zh/blog/chorus-v0.6.6-release/)** — npm 一键安装(`npx @chorus-aidlc/chorus`)、文档导出(MD/PDF/Word)、Proposal 撤回、优化 Agent Checkin 快速获取工作状态。
|
|
@@ -144,6 +146,7 @@ Cmd+K 命令面板,支持跨 6 种实体类型搜索。支持范围筛选(
|
|
|
144
146
|
- **任务 DAG** — 依赖建模、环检测、交互式可视化
|
|
145
147
|
- **Kanban** — 实时任务流转,Worker 徽标与 Agent Presence
|
|
146
148
|
- **Multi-Agent 协作** — Claude Code Agent Teams (Swarm Mode) 并行执行
|
|
149
|
+
- **细粒度 Agent 权限** — 5 类资源 × 3 个动作组成的权限网格,支持预设 + 自定义组合([详细说明](docs/PERMISSIONS.md) · 英文)
|
|
147
150
|
- **Chorus Plugin** — 生命周期钩子自动管理 Session 创建/关闭、心跳、上下文注入
|
|
148
151
|
- **需求澄清** — Proposal 创建前的结构化问答轮次
|
|
149
152
|
- **Proposal 审批流** — PM 起草,Admin 审批,草稿物化为正式实体
|
|
@@ -169,7 +172,7 @@ Cmd+K 命令面板,支持跨 6 种实体类型搜索。支持范围筛选(
|
|
|
169
172
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
170
173
|
│ │
|
|
171
174
|
│ ┌── API Layer ──────────────────────────────────────────────┐ │
|
|
172
|
-
│ │ /api/mcp — MCP
|
|
175
|
+
│ │ /api/mcp — MCP Streaming (50+ tools, permission-gated) │ │
|
|
173
176
|
│ │ /api/* — REST API (Web UI + SSE push) │ │
|
|
174
177
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
175
178
|
│ │
|
|
@@ -182,8 +185,9 @@ Cmd+K 命令面板,支持跨 6 种实体类型搜索。支持范围筛选(
|
|
|
182
185
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
183
186
|
└──────────────────────────────────────────────────────────────────┘
|
|
184
187
|
↑ ↑ ↑ ↑
|
|
185
|
-
|
|
186
|
-
(
|
|
188
|
+
Agent w/ Agent w/ Agent w/ Human
|
|
189
|
+
PM perms Developer perms Admin perms (Browser)
|
|
190
|
+
(LLM) (LLM) (LLM)
|
|
187
191
|
│
|
|
188
192
|
┌──────────▼──────────┐ ┌─────────────────────┐
|
|
189
193
|
│ PostgreSQL + Prisma │ │ Redis(可选) │
|
|
@@ -281,7 +285,7 @@ PGlite 在端口 5433 运行嵌入式 PostgreSQL。数据存储在 `.pglite/`,
|
|
|
281
285
|
|
|
282
286
|
### 连接 AI Agent
|
|
283
287
|
|
|
284
|
-
最快的方式是用应用内的 setup 向导:打开 Web UI,进入 **Settings → Setup Guide → 打开设置向导**,按照向导给出的分步指引接入自己的客户端(Claude Code、Codex、OpenClaw 或其他 agent)。向导会帮你创建 API Key、展示完整命令,并引导你验证连接。
|
|
288
|
+
最快的方式是用应用内的 setup 向导:打开 Web UI,进入 **Settings → Setup Guide → 打开设置向导**,按照向导给出的分步指引接入自己的客户端(Claude Code、Codex、OpenCode、OpenClaw 或其他 agent)。向导会帮你创建 API Key、展示完整命令,并引导你验证连接。
|
|
285
289
|
|
|
286
290
|
如果偏好文档:
|
|
287
291
|
|
|
@@ -289,8 +293,11 @@ PGlite 在端口 5433 运行嵌入式 PostgreSQL。数据存储在 `.pglite/`,
|
|
|
289
293
|
|--------|---------|
|
|
290
294
|
| Claude Code | [CONNECT_CLAUDE_CODE.zh.md](docs/CONNECT_CLAUDE_CODE.zh.md) |
|
|
291
295
|
| Codex CLI | [CONNECT_CODEX.zh.md](docs/CONNECT_CODEX.zh.md) |
|
|
296
|
+
| OpenCode † | [CONNECT_OPENCODE.zh.md](docs/CONNECT_OPENCODE.zh.md) |
|
|
292
297
|
| 其他 MCP agent(Cursor / Continue / 自研等) | [CONNECT_OTHER_AGENTS.zh.md](docs/CONNECT_OTHER_AGENTS.zh.md) |
|
|
293
298
|
|
|
299
|
+
† OpenCode 的接入由社区维护的 [`opencode-chorus`](https://github.com/etnperlong/opencode-chorus) 插件提供(npm: [`opencode-chorus`](https://www.npmjs.com/package/opencode-chorus)),作者 [@etnperlong](https://github.com/etnperlong),特此感谢!
|
|
300
|
+
|
|
294
301
|
在 Web UI 的 **Settings → Agents → Create API Key** 创建 API Key。Key 以 `cho_` 开头,仅在创建时显示一次。
|
|
295
302
|
|
|
296
303
|

|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chorus-aidlc/chorus",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "The Agent Harness for AI-Human Collaboration — session lifecycle, task state, sub-agent orchestration, observability, and failure recovery",
|
|
5
5
|
"homepage": "https://github.com/Chorus-AIDLC/Chorus",
|
|
6
6
|
"repository": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[69566],{23387:(e,t,s)=>{"use strict";s.r(t),s.d(t,{default:()=>H});var n=s(90508),a=s(1856),l=s(23675),i=s(39268),r=s(22922),c=s(67103),o=s(60532);let d=["welcome","createAgent","copyKey","installGuide","testConnection","completion"];function x(e){let{currentStep:t,totalSteps:s}=e,a=(0,i.c)("onboarding");return(0,n.jsx)("div",{className:"flex items-start",children:Array.from({length:s},(e,l)=>{let i=l<t,r=l===t;return(0,n.jsxs)("div",{className:"flex flex-col items-center",style:{minWidth:56},children:[(0,n.jsxs)("div",{className:"flex w-full items-center",children:[(0,n.jsx)("div",{className:"h-px flex-1 ".concat(0===l?"bg-transparent":i?"bg-primary":"bg-border")}),(0,n.jsx)("div",{className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-xs font-medium transition-colors ".concat(i?"bg-primary text-primary-foreground":r?"border-2 border-primary bg-background text-primary":"border border-border bg-background text-muted-foreground"),children:i?(0,n.jsx)(o.A,{className:"h-4 w-4"}):l+1}),(0,n.jsx)("div",{className:"h-px flex-1 ".concat(l===s-1?"bg-transparent":l<t?"bg-primary":"bg-border")})]}),(0,n.jsx)("span",{className:"mt-1.5 hidden text-[10px] sm:block ".concat(r?"font-medium text-foreground":"text-muted-foreground"),children:a("steps.".concat(d[l]))})]},l)})})}var m=s(48416),u=s(29767),p=s(56770),f=s(23217),h=s(62482),g=s(21104),j=s(24705),N=s(62898),b=s(16544),w=s(65626);let v=[{icon:u.A,key:"idea"},{icon:p.A,key:"proposal"},{icon:f.A,key:"task"},{icon:h.A,key:"execute"},{icon:g.A,key:"verify"},{icon:j.A,key:"done"}];function y(e){let{onNext:t}=e,s=(0,i.c)("onboarding");return(0,n.jsxs)(b.P.div,{variants:w.tE,initial:"initial",animate:"animate",exit:"exit",className:"flex w-full max-w-lg flex-col items-center gap-8",children:[(0,n.jsxs)("div",{className:"flex flex-col items-center gap-3 text-center",children:[(0,n.jsx)("img",{src:"/chorus-icon.png",alt:"Chorus",className:"h-16 w-16"}),(0,n.jsx)("h1",{className:"text-2xl font-semibold text-foreground",children:s("welcome.title")}),(0,n.jsx)("p",{className:"max-w-md text-sm text-muted-foreground",children:s("welcome.description")})]}),(0,n.jsx)(m.Zp,{className:"w-full",children:(0,n.jsxs)(m.Wu,{className:"p-6",children:[(0,n.jsx)("p",{className:"mb-4 text-center text-xs font-medium uppercase tracking-wider text-muted-foreground",children:s("welcome.pipelineTitle")}),(0,n.jsx)(b.P.div,{variants:w.bK,initial:"initial",animate:"animate",className:"flex flex-wrap items-center justify-center gap-2",children:v.map((e,t)=>{let a=e.icon;return(0,n.jsxs)(b.P.div,{variants:w.Rf,className:"flex items-center gap-2",children:[(0,n.jsxs)("div",{className:"flex flex-col items-center gap-1",children:[(0,n.jsx)("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-secondary",children:(0,n.jsx)(a,{className:"h-5 w-5 text-primary"})}),(0,n.jsx)("span",{className:"text-[10px] font-medium text-muted-foreground",children:s("welcome.pipeline.".concat(e.key))})]}),t<v.length-1&&(0,n.jsx)(N.A,{className:"h-3 w-3 text-muted-foreground"})]},e.key)})})]})}),(0,n.jsx)(r.$,{size:"lg",onClick:t,className:"w-full max-w-xs",children:s("welcome.getStarted")})]})}var k=s(37750),C=s(21323);function A(e){let{onNext:t,onAgentCreated:s}=e,a=(0,i.c)("onboarding.createAgent");return(0,n.jsx)(b.P.div,{variants:w.tE,initial:"initial",animate:"animate",exit:"exit",className:"flex w-full max-w-2xl flex-col items-center gap-6",children:(0,n.jsxs)(m.Zp,{className:"w-full",children:[(0,n.jsxs)(m.aR,{className:"text-center",children:[(0,n.jsx)(m.ZB,{children:a("title")}),(0,n.jsx)(m.BT,{children:a("description")})]}),(0,n.jsx)(m.Wu,{children:(0,n.jsx)(k.Y,{embedded:!0,createAgentAndKey:C.I,submitLabel:a("submit"),submittingLabel:a("creating"),onAgentCreated:(e,n)=>{s(e,n),t()}})})]})})}var _=s(25373),S=s(17475),T=s(67712);function K(e){let{onNext:t,apiKey:s}=e,l=(0,i.c)("onboarding"),[c,d]=(0,a.useState)(!1),x=(0,a.useCallback)(e=>{e.preventDefault()},[]);(0,a.useEffect)(()=>(window.addEventListener("beforeunload",x),()=>{window.removeEventListener("beforeunload",x)}),[x]);let u=async()=>{if(s)try{await navigator.clipboard.writeText(s),d(!0),setTimeout(()=>d(!1),2e3)}catch(e){T.q.error("Failed to copy to clipboard:",e)}};return(0,n.jsx)(b.P.div,{variants:w.tE,initial:"initial",animate:"animate",exit:"exit",className:"flex w-full max-w-lg flex-col items-center gap-8",children:(0,n.jsxs)(m.Zp,{className:"w-full",children:[(0,n.jsxs)(m.aR,{className:"text-center",children:[(0,n.jsx)(m.ZB,{children:l("copyKey.title")}),(0,n.jsx)(m.BT,{children:l("copyKey.description")})]}),(0,n.jsxs)(m.Wu,{className:"flex flex-col gap-4",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)("code",{className:"flex-1 overflow-x-auto rounded bg-foreground px-3 py-2 font-mono text-sm text-background",children:null!=s?s:""}),(0,n.jsx)(r.$,{variant:"outline",size:"sm",onClick:u,className:"flex-shrink-0",children:c?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.A,{className:"mr-1 h-4 w-4 text-green-500"}),l("copyKey.copied")]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(_.A,{className:"mr-1 h-4 w-4"}),l("copyKey.copy")]})})]}),(0,n.jsxs)("div",{className:"flex items-start gap-2 rounded-lg border border-yellow-300 bg-yellow-50 p-3 dark:border-yellow-800 dark:bg-yellow-950",children:[(0,n.jsx)(S.A,{className:"mt-0.5 h-4 w-4 flex-shrink-0 text-yellow-600 dark:text-yellow-400"}),(0,n.jsx)("p",{className:"text-sm font-medium text-yellow-700 dark:text-yellow-300",children:l("copyKey.warning")})]}),(0,n.jsx)(r.$,{onClick:t,className:"w-full",children:l("next")})]})]})})}var P=s(39674),E=s(81750),R=s(17730),O=s(37021),L=s(51708);function U(e){let{code:t,language:s}=e,a="```".concat(s||"","\n").concat(t,"\n```");return(0,n.jsx)(O.jH,{plugins:{code:L.a},children:a})}function I(e){let{apiKey:t,onNext:s,onBack:a}=e,l=(0,i.c)("onboarding"),c=window.location.origin,o=t||"<YOUR_API_KEY>";return(0,n.jsxs)(b.P.div,{variants:w.tE,initial:"initial",animate:"animate",exit:"exit",className:"flex w-full max-w-2xl flex-col items-center gap-6",children:[(0,n.jsxs)("div",{className:"text-center",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-foreground",children:l("steps.installGuide")}),(0,n.jsx)("p",{className:"mt-1 text-sm text-muted-foreground",children:l("install.description")})]}),(0,n.jsx)(m.Zp,{className:"w-full",children:(0,n.jsx)(m.Wu,{className:"p-6",children:(0,n.jsxs)(P.tU,{defaultValue:"claude-code",className:"w-full",children:[(0,n.jsxs)(P.j7,{className:"w-full",children:[(0,n.jsx)(P.Xi,{value:"claude-code",className:"flex-1",children:l("install.tabs.claudeCode")}),(0,n.jsx)(P.Xi,{value:"codex",className:"flex-1",children:l("install.tabs.codex")}),(0,n.jsx)(P.Xi,{value:"openclaw",className:"flex-1",children:l("install.tabs.openClaw")}),(0,n.jsx)(P.Xi,{value:"other",className:"flex-1",children:l("install.tabs.other")})]}),(0,n.jsxs)(P.av,{value:"claude-code",className:"mt-4 space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.claudeCode.step1Title")}),(0,n.jsx)(U,{language:"bash",code:'export CHORUS_URL="'.concat(c,'"\nexport CHORUS_API_KEY="').concat(o,'"')}),(0,n.jsx)("p",{className:"mt-2 text-xs text-muted-foreground",children:l("install.claudeCode.step1Tip")})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.claudeCode.step2Title")}),(0,n.jsx)(U,{language:"bash",code:"/plugin marketplace add Chorus-AIDLC/chorus\n/plugin install chorus@chorus-plugins"})]})]}),(0,n.jsxs)(P.av,{value:"codex",className:"mt-4 space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.codex.step1Title")}),(0,n.jsx)(U,{language:"bash",code:'export CHORUS_URL="'.concat(c,'"\nexport CHORUS_API_KEY="').concat(o,'"')}),(0,n.jsx)("p",{className:"mt-2 text-xs text-muted-foreground",children:l("install.codex.step1Tip")})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.codex.step2Title")}),(0,n.jsx)(U,{language:"bash",code:"curl -fsSL ".concat(c,"/install-codex.sh | bash")}),(0,n.jsx)("p",{className:"mt-2 text-xs text-muted-foreground",children:l("install.codex.step2Tip")})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.codex.step3Title")}),(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:l("install.codex.step3Desc")})]})]}),(0,n.jsxs)(P.av,{value:"openclaw",className:"mt-4 space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.openClaw.step1Title")}),(0,n.jsx)(U,{language:"bash",code:"openclaw plugins install @chorus-aidlc/chorus-openclaw-plugin"})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.openClaw.step2Title")}),(0,n.jsx)(U,{language:"json",code:'{\n "hooks": { "enabled": true, "token": "<your-token>" },\n "plugins": {\n "enabled": true,\n "entries": {\n "chorus-openclaw-plugin": {\n "enabled": true,\n "config": {\n "chorusUrl": "'.concat(c,'",\n "apiKey": "').concat(o,'",\n "autoStart": true\n }\n }\n }\n }\n}')})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.openClaw.step3Title")}),(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:l("install.openClaw.step3Desc")})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 text-sm font-medium text-foreground",children:l("install.openClaw.step4Title")}),(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:l("install.openClaw.step4Desc")}),(0,n.jsx)(U,{code:"/chorus status"})]}),(0,n.jsxs)(E.Nt,{children:[(0,n.jsxs)(E.R6,{className:"flex w-full items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors",children:[(0,n.jsx)(R.A,{className:"size-4 transition-transform duration-200 [[data-state=open]>&]:rotate-180"}),l("install.openClaw.troubleshootingTitle")]}),(0,n.jsx)(E.Ke,{children:(0,n.jsxs)("div",{className:"mt-2 rounded-md border border-amber-500/20 bg-amber-500/5 p-3",children:[(0,n.jsx)("p",{className:"text-sm font-medium text-amber-600 dark:text-amber-400",children:l("install.openClaw.troubleshootingError")}),(0,n.jsx)("p",{className:"mt-1 text-sm text-muted-foreground",children:l("install.openClaw.troubleshootingFix")})]})})]})]}),(0,n.jsxs)(P.av,{value:"other",className:"mt-4 space-y-4",children:[(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:l("install.other.description")}),(0,n.jsx)(U,{code:"Please install and configure the Chorus AI-DLC collaboration platform.\n\nChorus URL: ".concat(c,"\nAPI Key: ").concat(o,"\n\nRead the setup instructions from:\n").concat(c,'/skill/chorus/SKILL.md\n\nFollow the "Setup" section to configure the MCP server,\nthen call chorus_checkin() to verify the connection.')})]})]})})}),(0,n.jsxs)("div",{className:"flex gap-2",children:[a&&(0,n.jsx)(r.$,{variant:"outline",onClick:a,children:l("back")}),(0,n.jsx)(r.$,{onClick:s,children:l("next")})]})]})}var $=s(85226),z=s(42533);function Z(e){let{onNext:t,onBack:s,agentUuid:l,agentName:c,onConnectionVerified:o}=e,d=(0,i.c)("onboarding"),[x,u]=(0,a.useState)("waiting"),p=(0,a.useRef)(null),f=(0,a.useCallback)(()=>{p.current&&(p.current.close(),p.current=null)},[]),h=(0,a.useCallback)(()=>{f(),u("waiting");let e=new EventSource("/api/events/notifications");p.current=e,e.onmessage=e=>{try{let t=JSON.parse(e.data);"new_notification"===t.type&&"agent_checkin"===t.action&&t.entityUuid===l&&(u("connected"),f(),o())}catch(e){}},e.onerror=()=>{}},[l,f,o]);return(0,a.useEffect)(()=>(h(),f),[h,f]),(0,n.jsx)(b.P.div,{variants:w.tE,initial:"initial",animate:"animate",exit:"exit",className:"flex w-full max-w-lg flex-col items-center gap-8",children:(0,n.jsx)(m.Zp,{className:"w-full",children:(0,n.jsxs)(m.Wu,{className:"flex flex-col items-center gap-6 p-8",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-foreground",children:d("testConnection.title")}),"waiting"===x&&(0,n.jsxs)("div",{className:"flex w-full flex-col items-center gap-4",children:[(0,n.jsxs)("div",{className:"relative flex h-16 w-16 items-center justify-center",children:[(0,n.jsx)("div",{className:"absolute h-16 w-16 animate-ping rounded-full bg-primary/20"}),(0,n.jsx)($.A,{className:"h-8 w-8 animate-spin text-primary"})]}),(0,n.jsx)("p",{className:"text-center text-sm text-muted-foreground",children:d("testConnection.waiting")}),c&&(0,n.jsx)("p",{className:"text-center text-xs text-muted-foreground",children:d("testConnection.waitingFor",{name:c})}),(0,n.jsxs)("div",{className:"w-full",children:[(0,n.jsx)("p",{className:"mb-2 text-center text-xs text-muted-foreground",children:d("testConnection.checkinHint")}),(0,n.jsx)(U,{code:d("testConnection.checkinPrompt")})]}),s&&(0,n.jsx)(r.$,{variant:"outline",onClick:s,children:d("back")})]}),"connected"===x&&(0,n.jsxs)("div",{className:"flex flex-col items-center gap-4",children:[(0,n.jsx)(b.P.div,{initial:{scale:0},animate:{scale:1},transition:{type:"spring",stiffness:300,damping:20},children:(0,n.jsx)(z.A,{className:"h-16 w-16 text-green-500"})}),(0,n.jsx)("p",{className:"text-center text-sm font-medium text-green-600",children:d("testConnection.connected")}),(0,n.jsx)(r.$,{onClick:t,children:d("next")})]})]})})})}var D=s(94152),F=s(52309);function W(e){let{createdAgent:t}=e,s=(0,l.useRouter)(),c=(0,i.c)("onboarding"),o=(0,i.c)("agent.permissions");(0,a.useEffect)(()=>{localStorage.setItem("chorus_onboarding_completed","done")},[]);let d=t?o(t.roles.includes("admin_agent")?"presetAdmin":t.roles.includes("pm_agent")?"presetPm":t.roles.includes("developer_agent")?"presetDev":"presetCustom"):null;return(0,n.jsxs)(b.P.div,{variants:w.tE,initial:"initial",animate:"animate",exit:"exit",className:"flex w-full max-w-lg flex-col items-center gap-8",children:[(0,n.jsxs)("div",{className:"flex flex-col items-center gap-3 text-center",children:[(0,n.jsx)("div",{className:"flex h-16 w-16 items-center justify-center rounded-full bg-primary/10",children:(0,n.jsx)(z.A,{className:"h-10 w-10 text-primary"})}),(0,n.jsx)("h1",{className:"text-2xl font-semibold text-foreground",children:c("completion.title")}),(0,n.jsx)("p",{className:"max-w-md text-sm text-muted-foreground",children:c("completion.description")})]}),t&&(0,n.jsx)(m.Zp,{className:"w-full",children:(0,n.jsxs)(m.Wu,{className:"p-6",children:[(0,n.jsx)("h3",{className:"mb-3 text-sm font-medium text-foreground",children:c("completion.summary")}),(0,n.jsxs)("div",{className:"space-y-2 text-sm text-muted-foreground",children:[(0,n.jsxs)("div",{className:"flex justify-between",children:[(0,n.jsx)("span",{children:c("completion.agentName")}),(0,n.jsx)("span",{className:"font-medium text-foreground",children:t.name})]}),(0,n.jsxs)("div",{className:"flex justify-between",children:[(0,n.jsx)("span",{children:c("completion.agentPreset")}),(0,n.jsx)("span",{className:"font-medium text-foreground",children:d})]}),0===t.roles.length&&t.permissions.length>0&&(0,n.jsxs)("div",{className:"flex justify-between",children:[(0,n.jsx)("span",{children:c("completion.agentPermissions")}),(0,n.jsx)("span",{className:"font-medium text-foreground",children:c("completion.permissionsCount",{count:t.permissions.length})})]})]})]})}),(0,n.jsxs)("div",{className:"flex w-full max-w-xs flex-col gap-3",children:[(0,n.jsxs)(r.$,{size:"lg",onClick:()=>s.push("/projects"),className:"w-full gap-2",children:[(0,n.jsx)(D.A,{className:"h-4 w-4"}),c("completion.goToProjects")]}),(0,n.jsxs)(r.$,{variant:"outline",size:"lg",onClick:()=>s.push("/settings"),className:"w-full gap-2",children:[(0,n.jsx)(F.A,{className:"h-4 w-4"}),c("completion.goToSettings")]})]})]})}function B(){var e,t;let s=(0,l.useRouter)(),o=(0,i.c)("onboarding"),[d,m]=(0,a.useState)(0),[u,p]=(0,a.useState)(null),[f,h]=(0,a.useState)(null),[g,j]=(0,a.useState)(null),[N,b]=(0,a.useState)(!1),w=(0,a.useCallback)(()=>{m(e=>Math.min(e+1,5))},[]),v=(0,a.useCallback)(()=>{m(e=>Math.max(e-1,0))},[]),k=(0,a.useCallback)(()=>{localStorage.setItem("chorus_onboarding_completed","skipped"),s.push("/projects")},[s]),C=(0,a.useCallback)((e,t)=>{p(e),h(t)},[]),_=(0,a.useCallback)(()=>{b(!0),m(5)},[]),S=5===d;return(0,n.jsxs)("div",{className:"flex w-full max-w-2xl flex-col items-center gap-8",children:[(0,n.jsx)(x,{currentStep:d,totalSteps:6}),(0,n.jsxs)(c.N,{mode:"wait",children:[0===d&&(0,n.jsx)(y,{onNext:w},"welcome"),1===d&&(0,n.jsx)(A,{onNext:w,onAgentCreated:C},"createAgent"),2===d&&(0,n.jsx)(K,{onNext:w,apiKey:f},"copyKey"),3===d&&(0,n.jsx)(I,{apiKey:f,onNext:w,onBack:v},"installGuide"),4===d&&(0,n.jsx)(Z,{onNext:w,onBack:v,agentUuid:null!=(e=null==u?void 0:u.uuid)?e:null,agentName:null!=(t=null==u?void 0:u.name)?t:null,onConnectionVerified:_},"testConnection"),5===d&&(0,n.jsx)(W,{createdAgent:u},"completion")]}),!S&&(0,n.jsx)(r.$,{variant:"link",size:"sm",onClick:k,className:"text-muted-foreground",children:o("skip")})]})}function H(){return(0,n.jsx)("div",{className:"flex min-h-screen items-center justify-center bg-background p-4",children:(0,n.jsx)(B,{})})}},39674:(e,t,s)=>{"use strict";s.d(t,{Xi:()=>c,av:()=>o,j7:()=>r,tU:()=>i});var n=s(90508);s(1856);var a=s(79834),l=s(24377);function i(e){let{className:t,...s}=e;return(0,n.jsx)(a.Root,{"data-slot":"tabs",className:(0,l.cn)("flex flex-col gap-2",t),...s})}function r(e){let{className:t,...s}=e;return(0,n.jsx)(a.List,{"data-slot":"tabs-list",className:(0,l.cn)("bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",t),...s})}function c(e){let{className:t,...s}=e;return(0,n.jsx)(a.Trigger,{"data-slot":"tabs-trigger",className:(0,l.cn)("data-[state=active]:bg-background data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring inline-flex items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",t),...s})}function o(e){let{className:t,...s}=e;return(0,n.jsx)(a.Content,{"data-slot":"tabs-content",className:(0,l.cn)("flex-1 outline-none",t),...s})}},65626:(e,t,s)=>{"use strict";s.d(t,{K5:()=>c,Rf:()=>r,Yv:()=>n,bK:()=>i,qG:()=>l,tE:()=>a});let n={fast:.15,normal:.2,slow:.3,easeOut:[0,0,.2,1],easeInOut:[.4,0,.2,1],stagger:.04,staggerFast:.03,spring:{type:"spring",stiffness:500,damping:30},tween:{type:"tween",duration:.2,ease:[0,0,.2,1]}},a={initial:{opacity:0,y:8},animate:{opacity:1,y:0,transition:{duration:n.normal,ease:n.easeOut}},exit:{opacity:0,y:-4,transition:{duration:n.fast,ease:n.easeOut}}},l={initial:{opacity:0},animate:{opacity:1,transition:{duration:n.normal,ease:n.easeOut}},exit:{opacity:0,transition:{duration:n.fast,ease:n.easeOut}}};n.normal,n.easeOut,n.fast,n.easeOut;let i={initial:{},animate:{transition:{staggerChildren:n.stagger}}},r={initial:{opacity:0,y:8},animate:{opacity:1,y:0,transition:{duration:n.normal,ease:n.easeOut}}},c={initial:{opacity:0,scale:.95,y:-4},animate:{opacity:1,scale:1,y:0,transition:{duration:n.fast,ease:n.easeOut}},exit:{opacity:0,scale:.95,y:-4,transition:{duration:n.fast,ease:n.easeOut}}}},81750:(e,t,s)=>{"use strict";s.d(t,{Ke:()=>c,Nt:()=>i,R6:()=>r});var n=s(90508),a=s(38476),l=s(24377);function i(e){let{...t}=e;return(0,n.jsx)(a.Root,{"data-slot":"collapsible",...t})}function r(e){let{...t}=e;return(0,n.jsx)(a.Trigger,{"data-slot":"collapsible-trigger",...t})}function c(e){let{className:t,...s}=e;return(0,n.jsx)(a.Content,{"data-slot":"collapsible-content",className:(0,l.cn)("overflow-hidden data-[state=open]:animate-[collapsible-down_250ms_ease-in-out] data-[state=closed]:animate-[collapsible-up_200ms_ease-in-out]",t),...s})}},99576:(e,t,s)=>{Promise.resolve().then(s.bind(s,23387))}},e=>{e.O(0,[12079,18944,26885,21932,16544,53298,30724,27201,14945,14753,45532,70552,57908,37880,4457,99513,74951,65496,77358],()=>e(e.s=99576)),_N_E=e.O()}]);
|
|
File without changes
|
|
File without changes
|