agent-messenger 2.0.0 → 2.2.0
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/.claude-plugin/marketplace.json +14 -1
- package/.claude-plugin/plugin.json +4 -2
- package/.env.template +35 -17
- package/README.md +37 -33
- package/bun.lock +6 -6
- package/dist/package.json +11 -3
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +3 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/auth.js +35 -28
- package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/channeltalk/ensure-auth.js +6 -6
- package/dist/src/platforms/channeltalk/ensure-auth.js.map +1 -1
- package/dist/src/platforms/channeltalk/token-extractor.d.ts +23 -1
- package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/token-extractor.js +299 -29
- package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
- package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/auth.js +57 -49
- package/dist/src/platforms/discord/commands/auth.js.map +1 -1
- package/dist/src/platforms/discord/ensure-auth.js +3 -3
- package/dist/src/platforms/discord/ensure-auth.js.map +1 -1
- package/dist/src/platforms/discord/token-extractor.d.ts +6 -1
- package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/discord/token-extractor.js +167 -14
- package/dist/src/platforms/discord/token-extractor.js.map +1 -1
- package/dist/src/platforms/instagram/client.d.ts +2 -0
- package/dist/src/platforms/instagram/client.d.ts.map +1 -1
- package/dist/src/platforms/instagram/client.js +2 -2
- package/dist/src/platforms/instagram/client.js.map +1 -1
- package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/instagram/commands/auth.js +107 -14
- package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
- package/dist/src/platforms/instagram/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/instagram/ensure-auth.js +57 -11
- package/dist/src/platforms/instagram/ensure-auth.js.map +1 -1
- package/dist/src/platforms/instagram/index.d.ts +1 -0
- package/dist/src/platforms/instagram/index.d.ts.map +1 -1
- package/dist/src/platforms/instagram/index.js +1 -0
- package/dist/src/platforms/instagram/index.js.map +1 -1
- package/dist/src/platforms/instagram/token-extractor.d.ts +44 -0
- package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -0
- package/dist/src/platforms/instagram/token-extractor.js +407 -0
- package/dist/src/platforms/instagram/token-extractor.js.map +1 -0
- package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/client.js +2 -1
- package/dist/src/platforms/kakaotalk/client.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/auth.js +14 -13
- package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/connection.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/connection.js +2 -1
- package/dist/src/platforms/kakaotalk/protocol/connection.js.map +1 -1
- package/dist/src/platforms/line/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/line/commands/auth.js +6 -5
- package/dist/src/platforms/line/commands/auth.js.map +1 -1
- package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/auth.js +11 -10
- package/dist/src/platforms/slack/commands/auth.js.map +1 -1
- package/dist/src/platforms/slack/token-extractor.d.ts +9 -0
- package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/slack/token-extractor.js +300 -23
- package/dist/src/platforms/slack/token-extractor.js.map +1 -1
- package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/auth.js +9 -8
- package/dist/src/platforms/teams/commands/auth.js.map +1 -1
- package/dist/src/platforms/teams/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/ensure-auth.js +2 -1
- package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
- package/dist/src/platforms/teams/token-extractor.d.ts +5 -0
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/teams/token-extractor.js +161 -29
- package/dist/src/platforms/teams/token-extractor.js.map +1 -1
- package/dist/src/platforms/telegram/client.d.ts.map +1 -1
- package/dist/src/platforms/telegram/client.js +25 -7
- package/dist/src/platforms/telegram/client.js.map +1 -1
- package/dist/src/platforms/telegram/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/telegram/commands/auth.js +6 -5
- package/dist/src/platforms/telegram/commands/auth.js.map +1 -1
- package/dist/src/platforms/webex/app-config.d.ts +7 -0
- package/dist/src/platforms/webex/app-config.d.ts.map +1 -0
- package/dist/src/platforms/webex/app-config.js +20 -0
- package/dist/src/platforms/webex/app-config.js.map +1 -0
- package/dist/src/platforms/webex/cli.d.ts +5 -0
- package/dist/src/platforms/webex/cli.d.ts.map +1 -0
- package/dist/src/platforms/webex/cli.js +32 -0
- package/dist/src/platforms/webex/cli.js.map +1 -0
- package/dist/src/platforms/webex/client.d.ts +55 -0
- package/dist/src/platforms/webex/client.d.ts.map +1 -0
- package/dist/src/platforms/webex/client.js +299 -0
- package/dist/src/platforms/webex/client.js.map +1 -0
- package/dist/src/platforms/webex/commands/auth.d.ts +19 -0
- package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -0
- package/dist/src/platforms/webex/commands/auth.js +166 -0
- package/dist/src/platforms/webex/commands/auth.js.map +1 -0
- package/dist/src/platforms/webex/commands/index.d.ts +6 -0
- package/dist/src/platforms/webex/commands/index.d.ts.map +1 -0
- package/dist/src/platforms/webex/commands/index.js +6 -0
- package/dist/src/platforms/webex/commands/index.js.map +1 -0
- package/dist/src/platforms/webex/commands/member.d.ts +7 -0
- package/dist/src/platforms/webex/commands/member.d.ts.map +1 -0
- package/dist/src/platforms/webex/commands/member.js +34 -0
- package/dist/src/platforms/webex/commands/member.js.map +1 -0
- package/dist/src/platforms/webex/commands/message.d.ts +26 -0
- package/dist/src/platforms/webex/commands/message.d.ts.map +1 -0
- package/dist/src/platforms/webex/commands/message.js +153 -0
- package/dist/src/platforms/webex/commands/message.js.map +1 -0
- package/dist/src/platforms/webex/commands/snapshot.d.ts +9 -0
- package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -0
- package/dist/src/platforms/webex/commands/snapshot.js +72 -0
- package/dist/src/platforms/webex/commands/snapshot.js.map +1 -0
- package/dist/src/platforms/webex/commands/space.d.ts +11 -0
- package/dist/src/platforms/webex/commands/space.d.ts.map +1 -0
- package/dist/src/platforms/webex/commands/space.js +59 -0
- package/dist/src/platforms/webex/commands/space.js.map +1 -0
- package/dist/src/platforms/webex/credential-manager.d.ts +23 -0
- package/dist/src/platforms/webex/credential-manager.d.ts.map +1 -0
- package/dist/src/platforms/webex/credential-manager.js +148 -0
- package/dist/src/platforms/webex/credential-manager.js.map +1 -0
- package/dist/src/platforms/webex/ensure-auth.d.ts +2 -0
- package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -0
- package/dist/src/platforms/webex/ensure-auth.js +36 -0
- package/dist/src/platforms/webex/ensure-auth.js.map +1 -0
- package/dist/src/platforms/webex/index.d.ts +8 -0
- package/dist/src/platforms/webex/index.d.ts.map +1 -0
- package/dist/src/platforms/webex/index.js +6 -0
- package/dist/src/platforms/webex/index.js.map +1 -0
- package/dist/src/platforms/webex/token-extractor.d.ts +28 -0
- package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -0
- package/dist/src/platforms/webex/token-extractor.js +344 -0
- package/dist/src/platforms/webex/token-extractor.js.map +1 -0
- package/dist/src/platforms/webex/types.d.ts +127 -0
- package/dist/src/platforms/webex/types.d.ts.map +1 -0
- package/dist/src/platforms/webex/types.js +64 -0
- package/dist/src/platforms/webex/types.js.map +1 -0
- package/dist/src/platforms/whatsapp/client.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/client.js +6 -2
- package/dist/src/platforms/whatsapp/client.js.map +1 -1
- package/dist/src/shared/utils/derived-key-cache.d.ts +1 -1
- package/dist/src/shared/utils/derived-key-cache.d.ts.map +1 -1
- package/dist/src/shared/utils/error-handler.d.ts +1 -1
- package/dist/src/shared/utils/error-handler.d.ts.map +1 -1
- package/dist/src/shared/utils/error-handler.js +3 -2
- package/dist/src/shared/utils/error-handler.js.map +1 -1
- package/dist/src/shared/utils/stderr.d.ts +5 -0
- package/dist/src/shared/utils/stderr.d.ts.map +1 -0
- package/dist/src/shared/utils/stderr.js +18 -0
- package/dist/src/shared/utils/stderr.js.map +1 -0
- package/dist/src/tui/adapters/webex-adapter.d.ts +14 -0
- package/dist/src/tui/adapters/webex-adapter.d.ts.map +1 -0
- package/dist/src/tui/adapters/webex-adapter.js +79 -0
- package/dist/src/tui/adapters/webex-adapter.js.map +1 -0
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +2 -0
- package/dist/src/tui/app.js.map +1 -1
- package/docs/content/docs/cli/channeltalk.mdx +7 -7
- package/docs/content/docs/cli/discord.mdx +3 -3
- package/docs/content/docs/cli/instagram.mdx +28 -6
- package/docs/content/docs/cli/meta.json +1 -0
- package/docs/content/docs/cli/slack.mdx +2 -2
- package/docs/content/docs/cli/teams.mdx +6 -4
- package/docs/content/docs/cli/webex.mdx +310 -0
- package/docs/content/docs/sdk/meta.json +1 -1
- package/docs/content/docs/sdk/webex.mdx +260 -0
- package/docs/content/docs/tui.mdx +4 -3
- package/docs/src/app/page.tsx +2 -2
- package/e2e/README.md +132 -8
- package/e2e/channeltalk.e2e.test.ts +2 -7
- package/e2e/channeltalkbot.e2e.test.ts +2 -6
- package/e2e/config.ts +172 -10
- package/e2e/helpers.ts +7 -0
- package/e2e/instagram.e2e.test.ts +97 -0
- package/e2e/kakaotalk.e2e.test.ts +74 -0
- package/e2e/line.e2e.test.ts +92 -0
- package/e2e/teams.e2e.test.ts +46 -1
- package/e2e/telegram.e2e.test.ts +84 -0
- package/e2e/webex.e2e.test.ts +190 -0
- package/e2e/whatsapp.e2e.test.ts +90 -0
- package/e2e/whatsappbot.e2e.test.ts +78 -0
- package/package.json +11 -3
- package/skills/agent-channeltalk/SKILL.md +9 -9
- package/skills/agent-channeltalk/references/authentication.md +21 -18
- package/skills/agent-channeltalkbot/SKILL.md +1 -1
- package/skills/agent-discord/SKILL.md +5 -5
- package/skills/agent-discord/references/authentication.md +8 -8
- package/skills/agent-discordbot/SKILL.md +1 -1
- package/skills/agent-instagram/SKILL.md +51 -9
- package/skills/agent-instagram/references/authentication.md +35 -3
- package/skills/agent-kakaotalk/SKILL.md +1 -1
- package/skills/agent-line/SKILL.md +1 -1
- package/skills/agent-slack/SKILL.md +5 -5
- package/skills/agent-slack/references/authentication.md +8 -8
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +6 -6
- package/skills/agent-teams/references/authentication.md +8 -8
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +406 -0
- package/skills/agent-webex/references/authentication.md +371 -0
- package/skills/agent-webex/references/common-patterns.md +726 -0
- package/skills/agent-webex/templates/monitor-space.sh +165 -0
- package/skills/agent-webex/templates/post-message.sh +170 -0
- package/skills/agent-whatsapp/SKILL.md +1 -1
- package/skills/agent-whatsappbot/SKILL.md +1 -1
- package/src/cli.ts +4 -0
- package/src/platforms/channeltalk/commands/auth.test.ts +5 -5
- package/src/platforms/channeltalk/commands/auth.ts +38 -32
- package/src/platforms/channeltalk/ensure-auth.test.ts +6 -6
- package/src/platforms/channeltalk/ensure-auth.ts +6 -6
- package/src/platforms/channeltalk/token-extractor.test.ts +182 -15
- package/src/platforms/channeltalk/token-extractor.ts +344 -30
- package/src/platforms/discord/commands/auth.test.ts +3 -3
- package/src/platforms/discord/commands/auth.ts +58 -54
- package/src/platforms/discord/ensure-auth.test.ts +3 -3
- package/src/platforms/discord/ensure-auth.ts +3 -3
- package/src/platforms/discord/token-extractor.test.ts +199 -27
- package/src/platforms/discord/token-extractor.ts +190 -17
- package/src/platforms/instagram/client.ts +2 -2
- package/src/platforms/instagram/commands/auth.ts +133 -14
- package/src/platforms/instagram/ensure-auth.ts +63 -12
- package/src/platforms/instagram/index.ts +1 -0
- package/src/platforms/instagram/token-extractor.test.ts +424 -0
- package/src/platforms/instagram/token-extractor.ts +478 -0
- package/src/platforms/kakaotalk/client.ts +3 -1
- package/src/platforms/kakaotalk/commands/auth.ts +14 -13
- package/src/platforms/kakaotalk/protocol/connection.ts +3 -1
- package/src/platforms/line/commands/auth.ts +7 -6
- package/src/platforms/slack/cli.test.ts +6 -5
- package/src/platforms/slack/commands/auth.test.ts +11 -7
- package/src/platforms/slack/commands/auth.ts +11 -10
- package/src/platforms/slack/token-extractor.test.ts +98 -1
- package/src/platforms/slack/token-extractor.ts +338 -26
- package/src/platforms/teams/commands/auth.ts +9 -8
- package/src/platforms/teams/ensure-auth.ts +3 -1
- package/src/platforms/teams/token-extractor.test.ts +136 -17
- package/src/platforms/teams/token-extractor.ts +182 -31
- package/src/platforms/telegram/client.test.ts +134 -0
- package/src/platforms/telegram/client.ts +27 -6
- package/src/platforms/telegram/commands/auth.ts +6 -5
- package/src/platforms/webex/app-config.test.ts +98 -0
- package/src/platforms/webex/app-config.ts +31 -0
- package/src/platforms/webex/cli.test.ts +58 -0
- package/src/platforms/webex/cli.ts +39 -0
- package/src/platforms/webex/client.test.ts +743 -0
- package/src/platforms/webex/client.ts +405 -0
- package/src/platforms/webex/commands/auth.test.ts +222 -0
- package/src/platforms/webex/commands/auth.ts +243 -0
- package/src/platforms/webex/commands/index.ts +5 -0
- package/src/platforms/webex/commands/member.test.ts +112 -0
- package/src/platforms/webex/commands/member.ts +45 -0
- package/src/platforms/webex/commands/message.test.ts +235 -0
- package/src/platforms/webex/commands/message.ts +204 -0
- package/src/platforms/webex/commands/snapshot.test.ts +105 -0
- package/src/platforms/webex/commands/snapshot.ts +91 -0
- package/src/platforms/webex/commands/space.test.ts +216 -0
- package/src/platforms/webex/commands/space.ts +74 -0
- package/src/platforms/webex/credential-manager.test.ts +314 -0
- package/src/platforms/webex/credential-manager.ts +197 -0
- package/src/platforms/webex/ensure-auth.test.ts +89 -0
- package/src/platforms/webex/ensure-auth.ts +38 -0
- package/src/platforms/webex/index.test.ts +25 -0
- package/src/platforms/webex/index.ts +19 -0
- package/src/platforms/webex/token-extractor.test.ts +327 -0
- package/src/platforms/webex/token-extractor.ts +393 -0
- package/src/platforms/webex/types.test.ts +307 -0
- package/src/platforms/webex/types.ts +129 -0
- package/src/platforms/whatsapp/client.ts +11 -7
- package/src/shared/utils/derived-key-cache.ts +1 -1
- package/src/shared/utils/error-handler.ts +4 -2
- package/src/shared/utils/stderr.ts +22 -0
- package/src/tui/adapters/webex-adapter.ts +103 -0
- package/src/tui/app.ts +2 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# monitor-space.sh - Monitor a Webex space for new messages
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./monitor-space.sh <space-id> [interval]
|
|
7
|
+
#
|
|
8
|
+
# Arguments:
|
|
9
|
+
# space-id - Space ID to monitor (use 'space list' to find IDs)
|
|
10
|
+
# interval - Polling interval in seconds (default: 10)
|
|
11
|
+
#
|
|
12
|
+
# Example:
|
|
13
|
+
# ./monitor-space.sh "Y2lzY29zcGFyazovL..."
|
|
14
|
+
# ./monitor-space.sh "Y2lzY29zcGFyazovL..." 5
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
if [ $# -lt 1 ]; then
|
|
19
|
+
echo "Usage: $0 <space-id> [interval]"
|
|
20
|
+
echo ""
|
|
21
|
+
echo "Examples:"
|
|
22
|
+
echo " $0 'Y2lzY29zcGFyazovL...' # Monitor space, poll every 10s"
|
|
23
|
+
echo " $0 'Y2lzY29zcGFyazovL...' 5 # Monitor space, poll every 5s"
|
|
24
|
+
echo ""
|
|
25
|
+
echo "To find space IDs, run: agent-webex space list"
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
SPACE_ID="$1"
|
|
30
|
+
INTERVAL="${2:-10}"
|
|
31
|
+
|
|
32
|
+
RED='\033[0;31m'
|
|
33
|
+
GREEN='\033[0;32m'
|
|
34
|
+
YELLOW='\033[1;33m'
|
|
35
|
+
BLUE='\033[0;34m'
|
|
36
|
+
NC='\033[0m'
|
|
37
|
+
|
|
38
|
+
LAST_ID=""
|
|
39
|
+
FIRST_RUN=true
|
|
40
|
+
|
|
41
|
+
format_time() {
|
|
42
|
+
local ts=$1
|
|
43
|
+
if command -v gdate &> /dev/null; then
|
|
44
|
+
gdate -d "$ts" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$ts"
|
|
45
|
+
else
|
|
46
|
+
date -d "$ts" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$ts"
|
|
47
|
+
fi
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
truncate_text() {
|
|
51
|
+
local text=$1
|
|
52
|
+
local max_length=100
|
|
53
|
+
|
|
54
|
+
if [ ${#text} -gt $max_length ]; then
|
|
55
|
+
echo "${text:0:$max_length}..."
|
|
56
|
+
else
|
|
57
|
+
echo "$text"
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
check_messages() {
|
|
62
|
+
MESSAGES=$(agent-webex message list "$SPACE_ID" --limit 1 2>&1)
|
|
63
|
+
|
|
64
|
+
if echo "$MESSAGES" | jq -e '.error' > /dev/null 2>&1; then
|
|
65
|
+
ERROR_MSG=$(echo "$MESSAGES" | jq -r '.error // "Unknown error"')
|
|
66
|
+
echo -e "${RED}Error: $ERROR_MSG${NC}"
|
|
67
|
+
|
|
68
|
+
if echo "$ERROR_MSG" | grep -Eqi "401|unauthorized"; then
|
|
69
|
+
echo -e "${RED}Token expired or invalid. Get a new token from https://developer.webex.com${NC}"
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
return 1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
LATEST_ID=$(echo "$MESSAGES" | jq -r '.[0].id // ""')
|
|
77
|
+
|
|
78
|
+
if [ -z "$LATEST_ID" ]; then
|
|
79
|
+
if [ "$FIRST_RUN" = true ]; then
|
|
80
|
+
echo -e "${YELLOW}No messages in space yet${NC}"
|
|
81
|
+
fi
|
|
82
|
+
FIRST_RUN=false
|
|
83
|
+
return 0
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
if [ "$LATEST_ID" != "$LAST_ID" ]; then
|
|
87
|
+
if [ "$FIRST_RUN" = false ] && [ -n "$LAST_ID" ]; then
|
|
88
|
+
TEXT=$(echo "$MESSAGES" | jq -r '.[0].text // ""')
|
|
89
|
+
AUTHOR=$(echo "$MESSAGES" | jq -r '.[0].personEmail // "Unknown"')
|
|
90
|
+
TIMESTAMP=$(echo "$MESSAGES" | jq -r '.[0].created // ""')
|
|
91
|
+
|
|
92
|
+
TIME=$(format_time "$TIMESTAMP")
|
|
93
|
+
|
|
94
|
+
echo ""
|
|
95
|
+
echo -e "${GREEN}----------------------------------------------${NC}"
|
|
96
|
+
echo -e "${BLUE}New message in space${NC}"
|
|
97
|
+
echo -e "${GREEN}----------------------------------------------${NC}"
|
|
98
|
+
echo -e "Time: $TIME"
|
|
99
|
+
echo -e "From: $AUTHOR"
|
|
100
|
+
echo -e "Message: $(truncate_text "$TEXT")"
|
|
101
|
+
echo -e "${GREEN}----------------------------------------------${NC}"
|
|
102
|
+
|
|
103
|
+
# Uncomment to auto-respond to keywords:
|
|
104
|
+
# if echo "$TEXT" | grep -qi "status"; then
|
|
105
|
+
# agent-webex message send "$SPACE_ID" "All systems operational."
|
|
106
|
+
# fi
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
LAST_ID="$LATEST_ID"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
FIRST_RUN=false
|
|
113
|
+
return 0
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if ! command -v agent-webex &> /dev/null; then
|
|
117
|
+
echo -e "${RED}Error: agent-webex not found${NC}"
|
|
118
|
+
echo ""
|
|
119
|
+
echo "Install it with:"
|
|
120
|
+
echo " npm install -g agent-messenger"
|
|
121
|
+
exit 1
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
echo "Checking authentication..."
|
|
125
|
+
AUTH_STATUS=$(agent-webex auth status 2>&1)
|
|
126
|
+
|
|
127
|
+
if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
|
|
128
|
+
echo -e "${RED}Not authenticated!${NC}"
|
|
129
|
+
echo ""
|
|
130
|
+
echo "Run this to authenticate:"
|
|
131
|
+
echo " agent-webex auth login --token <token>"
|
|
132
|
+
echo ""
|
|
133
|
+
echo "Get a token at: https://developer.webex.com/docs/getting-started"
|
|
134
|
+
exit 1
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
USER_NAME=$(echo "$AUTH_STATUS" | jq -r '.displayName // "Unknown"')
|
|
138
|
+
echo -e "${GREEN}Authenticated as: $USER_NAME${NC}"
|
|
139
|
+
echo ""
|
|
140
|
+
|
|
141
|
+
echo "Verifying space..."
|
|
142
|
+
SPACE_INFO=$(agent-webex space info "$SPACE_ID" 2>&1)
|
|
143
|
+
|
|
144
|
+
if echo "$SPACE_INFO" | jq -e '.error' > /dev/null 2>&1; then
|
|
145
|
+
echo -e "${RED}Space '$SPACE_ID' not found${NC}"
|
|
146
|
+
echo ""
|
|
147
|
+
echo "List available spaces with:"
|
|
148
|
+
echo " agent-webex space list"
|
|
149
|
+
exit 1
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
SPACE_TITLE=$(echo "$SPACE_INFO" | jq -r '.title // "Unknown"')
|
|
153
|
+
echo -e "${GREEN}Monitoring: $SPACE_TITLE ($SPACE_ID)${NC}"
|
|
154
|
+
echo ""
|
|
155
|
+
|
|
156
|
+
echo -e "${YELLOW}Monitoring for new messages (polling every ${INTERVAL}s)...${NC}"
|
|
157
|
+
echo -e "${YELLOW}Press Ctrl+C to stop${NC}"
|
|
158
|
+
echo ""
|
|
159
|
+
|
|
160
|
+
trap 'echo -e "\n${YELLOW}Monitoring stopped${NC}"; exit 0' INT
|
|
161
|
+
|
|
162
|
+
while true; do
|
|
163
|
+
check_messages
|
|
164
|
+
sleep "$INTERVAL"
|
|
165
|
+
done
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# post-message.sh - Send a message to a Webex space with error handling
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./post-message.sh <space-id> <message>
|
|
7
|
+
# ./post-message.sh --space-title <title> <message>
|
|
8
|
+
#
|
|
9
|
+
# Example:
|
|
10
|
+
# ./post-message.sh "Y2lzY29zcGFyazovL..." "Hello from script!"
|
|
11
|
+
# ./post-message.sh --space-title Engineering "Deployment completed"
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
# Colors for output
|
|
16
|
+
RED='\033[0;31m'
|
|
17
|
+
GREEN='\033[0;32m'
|
|
18
|
+
YELLOW='\033[1;33m'
|
|
19
|
+
NC='\033[0m' # No Color
|
|
20
|
+
|
|
21
|
+
# Parse arguments
|
|
22
|
+
SPACE_ID=""
|
|
23
|
+
SPACE_TITLE=""
|
|
24
|
+
MESSAGE=""
|
|
25
|
+
|
|
26
|
+
if [ "$1" = "--space-title" ]; then
|
|
27
|
+
if [ $# -lt 3 ]; then
|
|
28
|
+
echo "Usage: $0 --space-title <title> <message>"
|
|
29
|
+
echo ""
|
|
30
|
+
echo "Example:"
|
|
31
|
+
echo " $0 --space-title Engineering 'Build completed'"
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
SPACE_TITLE="$2"
|
|
35
|
+
MESSAGE="$3"
|
|
36
|
+
elif [ $# -lt 2 ]; then
|
|
37
|
+
echo "Usage: $0 <space-id> <message>"
|
|
38
|
+
echo " $0 --space-title <title> <message>"
|
|
39
|
+
echo ""
|
|
40
|
+
echo "Examples:"
|
|
41
|
+
echo " $0 'Y2lzY29zcGFyazovL...' 'Hello world!'"
|
|
42
|
+
echo " $0 --space-title Engineering 'Build completed'"
|
|
43
|
+
exit 1
|
|
44
|
+
else
|
|
45
|
+
SPACE_ID="$1"
|
|
46
|
+
MESSAGE="$2"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Function to send message with retry logic
|
|
50
|
+
send_message() {
|
|
51
|
+
local space_id=$1
|
|
52
|
+
local message=$2
|
|
53
|
+
local max_attempts=3
|
|
54
|
+
local attempt=1
|
|
55
|
+
|
|
56
|
+
while [ $attempt -le $max_attempts ]; do
|
|
57
|
+
echo -e "${YELLOW}Attempt $attempt/$max_attempts...${NC}"
|
|
58
|
+
|
|
59
|
+
# Send message and capture result
|
|
60
|
+
RESULT=$(agent-webex message send "$space_id" "$message" 2>&1)
|
|
61
|
+
|
|
62
|
+
# Check if successful (has an 'id' field)
|
|
63
|
+
if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
|
|
64
|
+
echo -e "${GREEN}Message sent successfully!${NC}"
|
|
65
|
+
|
|
66
|
+
MSG_ID=$(echo "$RESULT" | jq -r '.id')
|
|
67
|
+
|
|
68
|
+
echo ""
|
|
69
|
+
echo "Message details:"
|
|
70
|
+
echo " Space: $space_id"
|
|
71
|
+
echo " Message ID: $MSG_ID"
|
|
72
|
+
|
|
73
|
+
return 0
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Extract error information
|
|
77
|
+
if echo "$RESULT" | jq -e '.error' > /dev/null 2>&1; then
|
|
78
|
+
ERROR_MSG=$(echo "$RESULT" | jq -r '.error // "Unknown error"')
|
|
79
|
+
echo -e "${RED}Failed: $ERROR_MSG${NC}"
|
|
80
|
+
|
|
81
|
+
# Don't retry on auth errors
|
|
82
|
+
if echo "$ERROR_MSG" | grep -Eqi "401|unauthorized|not authenticated"; then
|
|
83
|
+
echo ""
|
|
84
|
+
echo "Not authenticated. Run:"
|
|
85
|
+
echo " agent-webex auth login --token <token>"
|
|
86
|
+
return 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Don't retry on not-found errors
|
|
90
|
+
if echo "$ERROR_MSG" | grep -qi "not found"; then
|
|
91
|
+
echo ""
|
|
92
|
+
echo "Space '$space_id' not found. Check space ID."
|
|
93
|
+
echo "List spaces with: agent-webex space list"
|
|
94
|
+
return 1
|
|
95
|
+
fi
|
|
96
|
+
else
|
|
97
|
+
echo -e "${RED}Unexpected error: $RESULT${NC}"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Exponential backoff before retry
|
|
101
|
+
if [ $attempt -lt $max_attempts ]; then
|
|
102
|
+
SLEEP_TIME=$((attempt * 2))
|
|
103
|
+
echo "Retrying in ${SLEEP_TIME}s..."
|
|
104
|
+
sleep $SLEEP_TIME
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
attempt=$((attempt + 1))
|
|
108
|
+
done
|
|
109
|
+
|
|
110
|
+
echo -e "${RED}Failed after $max_attempts attempts${NC}"
|
|
111
|
+
return 1
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Check if agent-webex is installed
|
|
115
|
+
if ! command -v agent-webex &> /dev/null; then
|
|
116
|
+
echo -e "${RED}Error: agent-webex not found${NC}"
|
|
117
|
+
echo ""
|
|
118
|
+
echo "Install it with:"
|
|
119
|
+
echo " npm install -g agent-messenger"
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Check authentication
|
|
124
|
+
echo "Checking authentication..."
|
|
125
|
+
AUTH_STATUS=$(agent-webex auth status 2>&1)
|
|
126
|
+
|
|
127
|
+
if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
|
|
128
|
+
echo -e "${RED}Not authenticated!${NC}"
|
|
129
|
+
echo ""
|
|
130
|
+
echo "Run this to authenticate:"
|
|
131
|
+
echo " agent-webex auth login --token <token>"
|
|
132
|
+
echo ""
|
|
133
|
+
echo "Get a token at: https://developer.webex.com/docs/getting-started"
|
|
134
|
+
exit 1
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
USER_NAME=$(echo "$AUTH_STATUS" | jq -r '.displayName // "Unknown"')
|
|
138
|
+
echo -e "${GREEN}Authenticated as: $USER_NAME${NC}"
|
|
139
|
+
|
|
140
|
+
# If space title provided, look up space ID
|
|
141
|
+
if [ -n "$SPACE_TITLE" ]; then
|
|
142
|
+
echo "Looking up space '$SPACE_TITLE'..."
|
|
143
|
+
SPACES=$(agent-webex space list 2>&1)
|
|
144
|
+
|
|
145
|
+
if echo "$SPACES" | jq -e '.error' > /dev/null 2>&1; then
|
|
146
|
+
echo -e "${RED}Failed to list spaces${NC}"
|
|
147
|
+
exit 1
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
SPACE_ID=$(echo "$SPACES" | jq -r --arg title "$SPACE_TITLE" '.[] | select(.title==$title) | .id')
|
|
151
|
+
|
|
152
|
+
if [ -z "$SPACE_ID" ]; then
|
|
153
|
+
echo -e "${RED}Space '$SPACE_TITLE' not found${NC}"
|
|
154
|
+
echo ""
|
|
155
|
+
echo "Available spaces:"
|
|
156
|
+
echo "$SPACES" | jq -r '.[] | " \(.title) (\(.id))"'
|
|
157
|
+
exit 1
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
echo -e "${GREEN}Found space: $SPACE_ID${NC}"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
echo ""
|
|
164
|
+
|
|
165
|
+
# Send the message
|
|
166
|
+
echo "Sending message to space $SPACE_ID..."
|
|
167
|
+
echo "Message: $MESSAGE"
|
|
168
|
+
echo ""
|
|
169
|
+
|
|
170
|
+
send_message "$SPACE_ID" "$MESSAGE"
|
package/src/cli.ts
CHANGED
|
@@ -68,6 +68,10 @@ program.command('channeltalkbot', 'Interact with Channel Talk using API credenti
|
|
|
68
68
|
executableFile: join(__dirname, 'platforms', 'channeltalkbot', `cli${ext}`),
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
+
program.command('webex', 'Interact with Cisco Webex', {
|
|
72
|
+
executableFile: join(__dirname, 'platforms', 'webex', `cli${ext}`),
|
|
73
|
+
})
|
|
74
|
+
|
|
71
75
|
program.command('tui', 'Launch unified messenger TUI', {
|
|
72
76
|
executableFile: join(__dirname, 'tui', `cli${ext}`),
|
|
73
77
|
})
|
|
@@ -19,8 +19,8 @@ const mockListChannels = mock(() =>
|
|
|
19
19
|
{ id: 'ws-2', name: 'Workspace 2' },
|
|
20
20
|
]),
|
|
21
21
|
)
|
|
22
|
-
const mockExtract = mock
|
|
23
|
-
Promise.resolve({ accountCookie: 'fresh-account', sessionCookie: 'fresh-session' }),
|
|
22
|
+
const mockExtract = mock(() =>
|
|
23
|
+
Promise.resolve([{ accountCookie: 'fresh-account', sessionCookie: 'fresh-session' }]),
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
import {
|
|
@@ -113,7 +113,7 @@ describe('channel auth commands', () => {
|
|
|
113
113
|
{ id: 'ws-2', name: 'Workspace 2' },
|
|
114
114
|
]),
|
|
115
115
|
)
|
|
116
|
-
mockExtract.mockImplementation(() => Promise.resolve({ accountCookie: 'fresh-account', sessionCookie: 'fresh-session' }))
|
|
116
|
+
mockExtract.mockImplementation(() => Promise.resolve([{ accountCookie: 'fresh-account', sessionCookie: 'fresh-session' }]))
|
|
117
117
|
})
|
|
118
118
|
|
|
119
119
|
describe('extractAction', () => {
|
|
@@ -177,7 +177,7 @@ describe('channel auth commands', () => {
|
|
|
177
177
|
})
|
|
178
178
|
|
|
179
179
|
test('returns error when token extraction fails', async () => {
|
|
180
|
-
mockExtract.mockImplementation(() => Promise.resolve(
|
|
180
|
+
mockExtract.mockImplementation(() => Promise.resolve([]))
|
|
181
181
|
|
|
182
182
|
const result = await extractAction()
|
|
183
183
|
|
|
@@ -192,7 +192,7 @@ describe('channel auth commands', () => {
|
|
|
192
192
|
const result = await extractAction()
|
|
193
193
|
|
|
194
194
|
expect(result).toEqual({
|
|
195
|
-
error: 'No
|
|
195
|
+
error: 'No valid credentials found. Make sure Channel Talk desktop app or browser is logged in.',
|
|
196
196
|
})
|
|
197
197
|
})
|
|
198
198
|
})
|
|
@@ -82,45 +82,51 @@ export async function extractAction(options: ActionOptions = {}): Promise<Extrac
|
|
|
82
82
|
const extractor = createTokenExtractor()
|
|
83
83
|
const extracted = await extractor.extract()
|
|
84
84
|
|
|
85
|
-
if (
|
|
85
|
+
if (extracted.length === 0) {
|
|
86
86
|
return {
|
|
87
87
|
error: 'No credentials. Make sure Channel Talk desktop app is installed and logged in.',
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
91
|
+
for (const cookies of extracted) {
|
|
92
|
+
try {
|
|
93
|
+
const client = await createChannelClient(cookies.accountCookie, cookies.sessionCookie)
|
|
94
|
+
const account = await client.getAccount()
|
|
95
|
+
const channels = await client.listChannels()
|
|
96
|
+
|
|
97
|
+
if (channels.length === 0) continue
|
|
98
|
+
|
|
99
|
+
const previousCurrent = await credManager.getCredentials()
|
|
100
|
+
|
|
101
|
+
for (const channel of channels) {
|
|
102
|
+
await credManager.setCredentials({
|
|
103
|
+
workspace_id: channel.id,
|
|
104
|
+
workspace_name: channel.name,
|
|
105
|
+
account_id: account.id,
|
|
106
|
+
account_name: account.name,
|
|
107
|
+
account_cookie: cookies.accountCookie,
|
|
108
|
+
session_cookie: cookies.sessionCookie,
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const previousStillExists = previousCurrent && channels.some((ch) => ch.id === previousCurrent.workspace_id)
|
|
113
|
+
const currentId = previousStillExists ? previousCurrent.workspace_id : channels[0].id
|
|
114
|
+
await credManager.setCurrent(currentId)
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
success: true,
|
|
118
|
+
workspaces: channels.map((ch) => ({
|
|
119
|
+
workspace_id: ch.id,
|
|
120
|
+
workspace_name: ch.name,
|
|
121
|
+
})),
|
|
122
|
+
current_workspace_id: currentId,
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
continue
|
|
126
|
+
}
|
|
110
127
|
}
|
|
111
128
|
|
|
112
|
-
|
|
113
|
-
const currentId = previousStillExists ? previousCurrent.workspace_id : channels[0].id
|
|
114
|
-
await credManager.setCurrent(currentId)
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
success: true,
|
|
118
|
-
workspaces: channels.map((ch) => ({
|
|
119
|
-
workspace_id: ch.id,
|
|
120
|
-
workspace_name: ch.name,
|
|
121
|
-
})),
|
|
122
|
-
current_workspace_id: currentId,
|
|
123
|
-
}
|
|
129
|
+
return { error: 'No valid credentials found. Make sure Channel Talk desktop app or browser is logged in.' }
|
|
124
130
|
} catch (error: unknown) {
|
|
125
131
|
return { error: (error as Error).message }
|
|
126
132
|
}
|
|
@@ -17,7 +17,7 @@ const mockGetCredentials = mock<() => Promise<
|
|
|
17
17
|
>>(() => Promise.resolve(null))
|
|
18
18
|
const mockSetCredentials = mock(() => Promise.resolve())
|
|
19
19
|
const mockSetCurrent = mock(() => Promise.resolve(true))
|
|
20
|
-
const mockExtract = mock(() => Promise.resolve(
|
|
20
|
+
const mockExtract = mock(() => Promise.resolve([]))
|
|
21
21
|
const mockGetAccount = mock(() => Promise.resolve({ id: 'acct-1', name: 'Alice' }))
|
|
22
22
|
const mockListChannels = mock(() => Promise.resolve([{ id: 'ws-1', name: 'Workspace 1' }]))
|
|
23
23
|
|
|
@@ -58,17 +58,17 @@ describe('ensureChannelAuth', () => {
|
|
|
58
58
|
mockGetCredentials.mockImplementation(() => Promise.resolve(null))
|
|
59
59
|
mockSetCredentials.mockImplementation(() => Promise.resolve())
|
|
60
60
|
mockSetCurrent.mockImplementation(() => Promise.resolve(true))
|
|
61
|
-
mockExtract.mockImplementation(() => Promise.resolve(
|
|
61
|
+
mockExtract.mockImplementation(() => Promise.resolve([]))
|
|
62
62
|
mockGetAccount.mockImplementation(() => Promise.resolve({ id: 'acct-1', name: 'Alice' }))
|
|
63
63
|
mockListChannels.mockImplementation(() => Promise.resolve([{ id: 'ws-1', name: 'Workspace 1' }]))
|
|
64
64
|
})
|
|
65
65
|
|
|
66
66
|
test('extracts and saves workspaces when no credentials exist', async () => {
|
|
67
67
|
mockExtract.mockImplementation(() =>
|
|
68
|
-
Promise.resolve({
|
|
68
|
+
Promise.resolve([{
|
|
69
69
|
accountCookie: 'account-cookie',
|
|
70
70
|
sessionCookie: 'session-cookie',
|
|
71
|
-
}),
|
|
71
|
+
}]),
|
|
72
72
|
)
|
|
73
73
|
mockListChannels.mockImplementation(() =>
|
|
74
74
|
Promise.resolve([
|
|
@@ -128,10 +128,10 @@ describe('ensureChannelAuth', () => {
|
|
|
128
128
|
)
|
|
129
129
|
mockGetAccount.mockImplementationOnce(() => Promise.reject(new Error('Unauthorized')))
|
|
130
130
|
mockExtract.mockImplementation(() =>
|
|
131
|
-
Promise.resolve({
|
|
131
|
+
Promise.resolve([{
|
|
132
132
|
accountCookie: 'fresh-account',
|
|
133
133
|
sessionCookie: 'fresh-session',
|
|
134
|
-
}),
|
|
134
|
+
}]),
|
|
135
135
|
)
|
|
136
136
|
|
|
137
137
|
await ensureChannelAuth()
|
|
@@ -58,11 +58,11 @@ export async function ensureChannelAuth(): Promise<void> {
|
|
|
58
58
|
|
|
59
59
|
const extractor = createTokenExtractor()
|
|
60
60
|
const extracted = await extractor.extract()
|
|
61
|
-
if (
|
|
61
|
+
if (extracted.length === 0) {
|
|
62
62
|
return
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
const client = await createChannelClient(extracted.accountCookie, extracted.sessionCookie)
|
|
65
|
+
const client = await createChannelClient(extracted[0].accountCookie, extracted[0].sessionCookie)
|
|
66
66
|
const account = await client.getAccount()
|
|
67
67
|
const channels = await client.listChannels()
|
|
68
68
|
if (channels.length === 0) {
|
|
@@ -76,8 +76,8 @@ export async function ensureChannelAuth(): Promise<void> {
|
|
|
76
76
|
workspace_name: currentChannel.name,
|
|
77
77
|
account_id: account.id,
|
|
78
78
|
account_name: account.name,
|
|
79
|
-
account_cookie: extracted.accountCookie,
|
|
80
|
-
session_cookie: extracted.sessionCookie,
|
|
79
|
+
account_cookie: extracted[0].accountCookie,
|
|
80
|
+
session_cookie: extracted[0].sessionCookie,
|
|
81
81
|
})
|
|
82
82
|
|
|
83
83
|
for (const channel of otherChannels) {
|
|
@@ -86,8 +86,8 @@ export async function ensureChannelAuth(): Promise<void> {
|
|
|
86
86
|
workspace_name: channel.name,
|
|
87
87
|
account_id: account.id,
|
|
88
88
|
account_name: account.name,
|
|
89
|
-
account_cookie: extracted.accountCookie,
|
|
90
|
-
session_cookie: extracted.sessionCookie,
|
|
89
|
+
account_cookie: extracted[0].accountCookie,
|
|
90
|
+
session_cookie: extracted[0].sessionCookie,
|
|
91
91
|
})
|
|
92
92
|
}
|
|
93
93
|
|