@adaptic/maestro 1.6.0 → 1.7.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/package.json +1 -1
- package/scripts/continuous-monitor.sh +11 -6
- package/scripts/daemon/context-compiler.mjs +8 -8
- package/scripts/daemon/health.mjs +2 -2
- package/scripts/daemon/maestro-daemon.mjs +4 -3
- package/scripts/email_thread_dedup.py +4 -3
- package/scripts/huddle/huddle-server.mjs +50 -29
- package/scripts/llm_email_dedup.py +23 -15
- package/scripts/local-triggers/generate-plists.sh +2 -1
- package/scripts/media-generation/README.md +1 -1
- package/scripts/outbound-dedup-cleanup.sh +4 -4
- package/scripts/outbound-dedup.sh +4 -3
- package/scripts/pdf-generation/README.md +1 -1
- package/scripts/pdf-generation/templates/memo.latex +1 -1
- package/scripts/poll-slack-events.sh +4 -2
- package/scripts/poller/imap-client.mjs +11 -10
- package/scripts/poller/index.mjs +6 -6
- package/scripts/poller/intra-session-check.mjs +35 -18
- package/scripts/poller/mehran-gmail-poller.mjs +63 -29
- package/scripts/poller/slack-poller.mjs +45 -31
- package/scripts/poller/trigger.mjs +22 -5
- package/scripts/pre-draft-context.py +2 -2
- package/scripts/rag-indexer.py +3 -3
- package/scripts/send-sms.sh +7 -7
- package/scripts/send-whatsapp.sh +11 -11
- package/scripts/setup/configure-macos.sh +4 -2
- package/scripts/setup/init-agent.sh +1 -1
- package/scripts/slack-react.mjs +1 -1
- package/scripts/slack-typing.mjs +3 -3
- package/scripts/system-verify.sh +28 -15
- package/scripts/user-context-search.py +4 -4
- package/scripts/validate-outbound.py +29 -18
- package/scripts/sophie-inbox-poller.py +0 -406
package/scripts/send-sms.sh
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# send-sms.sh — Send outbound SMS via Twilio REST API as
|
|
2
|
+
# send-sms.sh — Send outbound SMS via Twilio REST API as the running agent
|
|
3
3
|
# Usage: ./scripts/send-sms.sh --to "+1234567890" --body "message text"
|
|
4
4
|
#
|
|
5
5
|
# Environment variables (from .env):
|
|
6
6
|
# TWILIO_ACCOUNT_SID — Twilio account SID
|
|
7
7
|
# TWILIO_AUTH_TOKEN — Twilio auth token
|
|
8
|
-
# TWILIO_PHONE_NUMBER —
|
|
8
|
+
# TWILIO_PHONE_NUMBER — The agent's Twilio phone number
|
|
9
9
|
set -e
|
|
10
10
|
|
|
11
11
|
# Load environment
|
|
12
12
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
13
|
-
|
|
13
|
+
AGENT_REPO_DIR="${AGENT_DIR:-$(dirname "$SCRIPT_DIR")}"
|
|
14
14
|
|
|
15
|
-
if [ -f "$
|
|
16
|
-
source "$
|
|
15
|
+
if [ -f "$AGENT_REPO_DIR/.env" ]; then
|
|
16
|
+
source "$AGENT_REPO_DIR/.env"
|
|
17
17
|
fi
|
|
18
18
|
|
|
19
19
|
# Defaults
|
|
@@ -110,7 +110,7 @@ MESSAGE_SID=$(echo "$RESPONSE_BODY" | grep -o '"sid": *"[^"]*"' | head -1 | sed
|
|
|
110
110
|
STATUS=$(echo "$RESPONSE_BODY" | grep -o '"status": *"[^"]*"' | head -1 | sed 's/"status": *"//' | sed 's/"//')
|
|
111
111
|
|
|
112
112
|
# Log to SMS log
|
|
113
|
-
LOG_DIR="$
|
|
113
|
+
LOG_DIR="$AGENT_REPO_DIR/logs/sms/$(date +%Y-%m-%d)"
|
|
114
114
|
mkdir -p "$LOG_DIR"
|
|
115
115
|
LOG_FILE="$LOG_DIR/$(date +%Y-%m-%d)-sms.jsonl"
|
|
116
116
|
|
|
@@ -121,7 +121,7 @@ LOGEOF
|
|
|
121
121
|
echo "$LOG_ENTRY" >> "$LOG_FILE"
|
|
122
122
|
|
|
123
123
|
# Log to audit trail
|
|
124
|
-
AUDIT_DIR="$
|
|
124
|
+
AUDIT_DIR="$AGENT_REPO_DIR/logs/audit"
|
|
125
125
|
mkdir -p "$AUDIT_DIR"
|
|
126
126
|
AUDIT_FILE="$AUDIT_DIR/$(date +%Y-%m-%d)-actions.jsonl"
|
|
127
127
|
|
package/scripts/send-whatsapp.sh
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# send-whatsapp.sh — Send outbound WhatsApp message via Twilio REST API as
|
|
2
|
+
# send-whatsapp.sh — Send outbound WhatsApp message via Twilio REST API as the agent
|
|
3
3
|
#
|
|
4
4
|
# Supports two modes:
|
|
5
5
|
# 1. Sandbox mode (default until production WABA is active):
|
|
6
6
|
# Uses Twilio sandbox number +14155238886
|
|
7
7
|
# Recipients must have joined the sandbox first
|
|
8
8
|
# 2. Production mode (--production flag or WHATSAPP_MODE=production):
|
|
9
|
-
# Uses
|
|
9
|
+
# Uses the agent's own Twilio number as WhatsApp Business sender
|
|
10
10
|
#
|
|
11
11
|
# Usage:
|
|
12
|
-
# ./scripts/send-whatsapp.sh --to "+971501234567" --body "Hello
|
|
12
|
+
# ./scripts/send-whatsapp.sh --to "+971501234567" --body "Hello"
|
|
13
13
|
# ./scripts/send-whatsapp.sh --to "+971501234567" --body "Hello" --production
|
|
14
|
-
# ./scripts/send-whatsapp.sh --to "+971501234567" --template "intro_greeting" --vars "
|
|
14
|
+
# ./scripts/send-whatsapp.sh --to "+971501234567" --template "intro_greeting" --vars "Var1,Var2"
|
|
15
15
|
#
|
|
16
16
|
# Environment variables (from .env):
|
|
17
17
|
# TWILIO_ACCOUNT_SID — Twilio account SID
|
|
18
18
|
# TWILIO_AUTH_TOKEN — Twilio auth token
|
|
19
|
-
# TWILIO_PHONE_NUMBER —
|
|
19
|
+
# TWILIO_PHONE_NUMBER — The agent's Twilio phone number
|
|
20
20
|
# WHATSAPP_MODE — "sandbox" (default) or "production"
|
|
21
21
|
# WHATSAPP_SANDBOX_NUMBER — Sandbox sender (default: +14155238886)
|
|
22
22
|
set -e
|
|
23
23
|
|
|
24
24
|
# Load environment
|
|
25
25
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
26
|
-
|
|
26
|
+
AGENT_REPO_DIR="${AGENT_DIR:-$(dirname "$SCRIPT_DIR")}"
|
|
27
27
|
|
|
28
|
-
if [ -f "$
|
|
29
|
-
source "$
|
|
28
|
+
if [ -f "$AGENT_REPO_DIR/.env" ]; then
|
|
29
|
+
source "$AGENT_REPO_DIR/.env"
|
|
30
30
|
fi
|
|
31
31
|
|
|
32
32
|
# Defaults
|
|
@@ -77,7 +77,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
77
77
|
echo " --to Recipient phone number (E.164 format, required)"
|
|
78
78
|
echo " --body Message text (required unless --template is used)"
|
|
79
79
|
echo " --template WhatsApp message template name (for business-initiated messages)"
|
|
80
|
-
echo " --vars Comma-separated template variables (e.g. \"
|
|
80
|
+
echo " --vars Comma-separated template variables (e.g. \"Name,Company\")"
|
|
81
81
|
echo " --media URL of media to attach (image, PDF, etc.)"
|
|
82
82
|
echo " --production Use production WhatsApp Business number"
|
|
83
83
|
echo " --sandbox Use Twilio WhatsApp sandbox (default)"
|
|
@@ -207,7 +207,7 @@ ERROR_CODE=$(echo "$RESPONSE_BODY" | grep -o '"code": *[0-9]*' | head -1 | sed '
|
|
|
207
207
|
ERROR_MSG=$(echo "$RESPONSE_BODY" | grep -o '"message": *"[^"]*"' | head -1 | sed 's/"message": *"//' | sed 's/"//')
|
|
208
208
|
|
|
209
209
|
# Log to WhatsApp log
|
|
210
|
-
LOG_DIR="$
|
|
210
|
+
LOG_DIR="$AGENT_REPO_DIR/logs/whatsapp/$(date +%Y-%m-%d)"
|
|
211
211
|
mkdir -p "$LOG_DIR"
|
|
212
212
|
LOG_FILE="$LOG_DIR/$(date +%Y-%m-%d)-whatsapp.jsonl"
|
|
213
213
|
|
|
@@ -220,7 +220,7 @@ LOGEOF
|
|
|
220
220
|
echo "$LOG_ENTRY" >> "$LOG_FILE"
|
|
221
221
|
|
|
222
222
|
# Log to audit trail
|
|
223
|
-
AUDIT_DIR="$
|
|
223
|
+
AUDIT_DIR="$AGENT_REPO_DIR/logs/audit"
|
|
224
224
|
mkdir -p "$AUDIT_DIR"
|
|
225
225
|
AUDIT_FILE="$AUDIT_DIR/$(date +%Y-%m-%d)-actions.jsonl"
|
|
226
226
|
|
|
@@ -30,7 +30,7 @@ AGENT_NAME=$(basename "$AGENT_DIR")
|
|
|
30
30
|
CURRENT_USER=$(whoami)
|
|
31
31
|
|
|
32
32
|
# The directory from which this script was invoked — used as the boot-time
|
|
33
|
-
# Claude Code working directory (e.g. ~/
|
|
33
|
+
# Claude Code working directory (e.g. ~/agent-name, ~/wundr, etc.)
|
|
34
34
|
CALLER_DIR="${PWD}"
|
|
35
35
|
|
|
36
36
|
# Colours
|
|
@@ -419,7 +419,9 @@ configure_memory_watchdog() {
|
|
|
419
419
|
local PLIST_DEST="$real_home/Library/LaunchAgents/ai.maestro.memory-watchdog.plist"
|
|
420
420
|
|
|
421
421
|
# Install the plist (update paths for this agent directory)
|
|
422
|
-
|
|
422
|
+
# Template plists may contain `__AGENT_DIR__` (preferred) or the legacy
|
|
423
|
+
# `/Users/sophie/maestro` literal — substitute both for compatibility.
|
|
424
|
+
sed -e "s|__AGENT_DIR__|$AGENT_DIR|g" -e "s|/Users/sophie/maestro|$AGENT_DIR|g" "$PLIST_SOURCE" > "$PLIST_DEST"
|
|
423
425
|
chown "$real_user:staff" "$PLIST_DEST" 2>/dev/null || true
|
|
424
426
|
|
|
425
427
|
# Load it (as the real user)
|
|
@@ -31,7 +31,7 @@ set -e
|
|
|
31
31
|
|
|
32
32
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
33
33
|
AGENT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
34
|
-
AGENT_NAME=$(basename "$AGENT_DIR") # e.g. "
|
|
34
|
+
AGENT_NAME=$(basename "$AGENT_DIR") # e.g. "ravi-ai", "jacob-ai"
|
|
35
35
|
|
|
36
36
|
# Colours
|
|
37
37
|
RED='\033[0;31m'
|
package/scripts/slack-react.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Slack Reaction Utility — Add emoji reactions to Slack messages.
|
|
4
4
|
*
|
|
5
|
-
* Used by
|
|
5
|
+
* Used by the agent's Claude Code sessions to react to messages.
|
|
6
6
|
* This is a thin wrapper around the Slack reactions.add API.
|
|
7
7
|
*
|
|
8
8
|
* Usage:
|
package/scripts/slack-typing.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env /opt/homebrew/bin/node
|
|
2
2
|
/**
|
|
3
|
-
* slack-typing.mjs — Send Slack typing indicator as
|
|
3
|
+
* slack-typing.mjs — Send Slack typing indicator as the running agent
|
|
4
4
|
*
|
|
5
|
-
* Shows the "
|
|
6
|
-
* a message is sent, making
|
|
5
|
+
* Shows the "<Agent> is typing..." indicator in a channel/DM before
|
|
6
|
+
* a message is sent, making the agent's presence feel human and real.
|
|
7
7
|
*
|
|
8
8
|
* Approach: Connect to Slack RTM (WebSocket), send a `typing` event,
|
|
9
9
|
* hold the connection for the specified duration, then disconnect.
|
package/scripts/system-verify.sh
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
2
|
+
# Agent System Verification — checks all components are operational
|
|
3
3
|
# Usage: ./scripts/system-verify.sh
|
|
4
4
|
#
|
|
5
5
|
# Run this anytime to verify the full system is working.
|
|
6
6
|
|
|
7
7
|
set -e
|
|
8
|
-
|
|
9
|
-
cd "$
|
|
8
|
+
AGENT_REPO_DIR="${AGENT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
|
9
|
+
cd "$AGENT_REPO_DIR"
|
|
10
|
+
|
|
11
|
+
# Load identity (AGENT_LAUNCHD_PREFIX in particular) — the verification
|
|
12
|
+
# checks read launchd labels with the agent-specific prefix.
|
|
13
|
+
if [ -f "$AGENT_REPO_DIR/config/agent.env" ]; then
|
|
14
|
+
# shellcheck disable=SC1091
|
|
15
|
+
source "$AGENT_REPO_DIR/config/agent.env"
|
|
16
|
+
fi
|
|
17
|
+
LAUNCHD_PREFIX="${AGENT_LAUNCHD_PREFIX:-ai.adaptic.agent}"
|
|
10
18
|
|
|
11
19
|
RED='\033[0;31m'
|
|
12
20
|
GREEN='\033[0;32m'
|
|
@@ -38,23 +46,28 @@ warn_check() {
|
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
echo "╔══════════════════════════════════════════════╗"
|
|
41
|
-
|
|
49
|
+
printf "║ %-44s║\n" "$(echo "${AGENT_FULL_NAME:-AGENT}" | tr '[:lower:]' '[:upper:]') SYSTEM VERIFICATION"
|
|
42
50
|
echo "║ $(date '+%Y-%m-%d %H:%M %Z') ║"
|
|
43
51
|
echo "╚══════════════════════════════════════════════╝"
|
|
44
52
|
echo ""
|
|
45
53
|
|
|
46
54
|
echo "=== DAEMONS ==="
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
check "
|
|
53
|
-
check "
|
|
54
|
-
check "
|
|
55
|
-
check "
|
|
56
|
-
check "
|
|
57
|
-
check "
|
|
55
|
+
# Launchd labels start with AGENT_LAUNCHD_PREFIX (e.g. ai.adaptic.ravi).
|
|
56
|
+
# The legacy code searched for "sophie-poller" etc.; we now derive the
|
|
57
|
+
# agent-specific component from the prefix's last segment so the check
|
|
58
|
+
# works for any agent.
|
|
59
|
+
LAUNCHD_AGENT_SLUG="$(basename "$LAUNCHD_PREFIX" | tr -d ' ')" # e.g. "ravi" from "ai.adaptic.ravi"
|
|
60
|
+
check "Poller daemon loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-poller"
|
|
61
|
+
check "Inbox processor loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-inbox-processor"
|
|
62
|
+
check "Meeting prep loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-meeting-prep"
|
|
63
|
+
check "Meeting capture loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-meeting-action-capture"
|
|
64
|
+
check "Midday sweep loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-midday-sweep"
|
|
65
|
+
check "Weekly hiring loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-weekly-hiring"
|
|
66
|
+
check "Weekly priorities loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-weekly-priorities"
|
|
67
|
+
check "Weekly eng health loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-weekly-engineering-health"
|
|
68
|
+
check "Weekly execution loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-weekly-execution"
|
|
69
|
+
check "Weekly strategic memo loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-weekly-strategic-memo"
|
|
70
|
+
check "Quarterly self-assessment loaded" "launchctl list | grep -q ${LAUNCHD_AGENT_SLUG}-quarterly"
|
|
58
71
|
echo ""
|
|
59
72
|
|
|
60
73
|
echo "=== REMOTE TRIGGERS ==="
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""
|
|
3
3
|
user-context-search.py — Per-user ring-fenced context search (Phase 1 + Phase 2)
|
|
4
4
|
|
|
5
|
-
Searches
|
|
5
|
+
Searches the agent repo's files scoped to a user's access level.
|
|
6
6
|
Supports two backends:
|
|
7
7
|
- grep (default): file-based grep with user-scoped directory paths (Phase 1)
|
|
8
8
|
- sqlite: FTS5 full-text search over pre-indexed SQLite database (Phase 2)
|
|
@@ -15,7 +15,7 @@ Usage:
|
|
|
15
15
|
python3 scripts/user-context-search.py --user unknown --query "adaptic" --format text
|
|
16
16
|
python3 scripts/user-context-search.py --user mehran --query "flight" --backend sqlite
|
|
17
17
|
|
|
18
|
-
Author:
|
|
18
|
+
Author: Adaptic.ai
|
|
19
19
|
Date: 2026-04-03
|
|
20
20
|
"""
|
|
21
21
|
|
|
@@ -30,7 +30,7 @@ from pathlib import Path
|
|
|
30
30
|
|
|
31
31
|
# ── Constants ──────────────────────────────────────────────────────────────────
|
|
32
32
|
|
|
33
|
-
BASE_DIR = Path(__file__).resolve().parent.parent #
|
|
33
|
+
BASE_DIR = Path(os.environ.get("AGENT_DIR", str(Path(__file__).resolve().parent.parent))) # agent repo root
|
|
34
34
|
CONFIG_PATH = BASE_DIR / "config" / "caller-id-map.yaml"
|
|
35
35
|
DEFAULT_DB_PATH = BASE_DIR / "state" / "rag" / "search.db"
|
|
36
36
|
DEFAULT_MAX_RESULTS = 10
|
|
@@ -569,7 +569,7 @@ def format_text(user_slug, user_data, access_level, paths_searched, matches, que
|
|
|
569
569
|
def main():
|
|
570
570
|
parser = argparse.ArgumentParser(
|
|
571
571
|
description="Per-user ring-fenced context search (Phase 1 + Phase 2). "
|
|
572
|
-
"Searches
|
|
572
|
+
"Searches the agent repo's files scoped to a user's access level.",
|
|
573
573
|
epilog="Examples:\n"
|
|
574
574
|
" %(prog)s --user mehran --query \"DFSA\"\n"
|
|
575
575
|
" %(prog)s --user hootan --query \"portal\" --max-results 5\n"
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
Checks outbound messages for:
|
|
5
5
|
1. Relationship claims — "our project manager" must match confirmed status
|
|
6
6
|
2. Title/role accuracy — titles must match org chart / profiles
|
|
7
|
-
3. AI self-disclosure —
|
|
8
|
-
4. In-person meeting self-scheduling —
|
|
7
|
+
3. AI self-disclosure — the agent must never reveal it is AI
|
|
8
|
+
4. In-person meeting self-scheduling — the agent must not attend physical meetings
|
|
9
9
|
5. Unverified commitment claims — flag strong commitment language
|
|
10
10
|
|
|
11
11
|
Usage:
|
|
@@ -47,7 +47,16 @@ except Exception:
|
|
|
47
47
|
|
|
48
48
|
# Resolve paths relative to the repo root
|
|
49
49
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
50
|
-
REPO_ROOT = SCRIPT_DIR.parent
|
|
50
|
+
REPO_ROOT = Path(os.environ.get("AGENT_DIR", SCRIPT_DIR.parent))
|
|
51
|
+
|
|
52
|
+
# Load agent identity (canonical SOT) so validation patterns can be
|
|
53
|
+
# parameterised by the running agent's first name.
|
|
54
|
+
try:
|
|
55
|
+
with open(REPO_ROOT / "config" / "agent.json") as _f:
|
|
56
|
+
_AGENT = json.load(_f)
|
|
57
|
+
except Exception:
|
|
58
|
+
_AGENT = {"firstName": "Agent", "fullName": "Agent"}
|
|
59
|
+
AGENT_FIRST_NAME = _AGENT.get("firstName", "Agent")
|
|
51
60
|
|
|
52
61
|
# Data source paths
|
|
53
62
|
CONTACTS_PATH = REPO_ROOT / "config" / "contacts.yaml"
|
|
@@ -914,7 +923,7 @@ def check_title_accuracy(message):
|
|
|
914
923
|
|
|
915
924
|
|
|
916
925
|
def check_ai_self_disclosure(message):
|
|
917
|
-
"""Scan for language that reveals
|
|
926
|
+
"""Scan for language that reveals the agent is AI.
|
|
918
927
|
|
|
919
928
|
Must NOT flag general business discussion of Adaptic's AI products.
|
|
920
929
|
Returns list of issue dicts.
|
|
@@ -941,8 +950,8 @@ def check_ai_self_disclosure(message):
|
|
|
941
950
|
"Self-referential 'as an AI'"),
|
|
942
951
|
(r'\b(?:my|I)\s+(?:training|training data|knowledge cutoff|neural network|parameters)\b',
|
|
943
952
|
"AI-specific self-reference"),
|
|
944
|
-
(
|
|
945
|
-
"Third-person AI disclosure about
|
|
953
|
+
(rf'\b{re.escape(AGENT_FIRST_NAME)}\s+is\s+(?:an?\s+)?(?:AI|bot|automated|virtual|artificial)\b',
|
|
954
|
+
f"Third-person AI disclosure about {AGENT_FIRST_NAME}"),
|
|
946
955
|
(r'\b(?:automated|AI[- ]powered|AI[- ]operated|machine[- ]generated)\s+(?:assistant|chief of staff|executive|system)\b',
|
|
947
956
|
"Role described as automated"),
|
|
948
957
|
(r'\b(?:I don\'t have|I lack)\s+(?:feelings|emotions|a body|physical form|consciousness)\b',
|
|
@@ -971,7 +980,7 @@ def check_ai_self_disclosure(message):
|
|
|
971
980
|
"severity": "block",
|
|
972
981
|
"matched_text": matched_text,
|
|
973
982
|
"description": f"AI self-disclosure detected: {description}",
|
|
974
|
-
"suggestion": "Remove or rephrase to avoid revealing
|
|
983
|
+
"suggestion": f"Remove or rephrase to avoid revealing {AGENT_FIRST_NAME}'s AI nature.",
|
|
975
984
|
"context": context_window.strip(),
|
|
976
985
|
})
|
|
977
986
|
|
|
@@ -979,27 +988,29 @@ def check_ai_self_disclosure(message):
|
|
|
979
988
|
|
|
980
989
|
|
|
981
990
|
def check_in_person_self_scheduling(message):
|
|
982
|
-
"""Detect
|
|
991
|
+
"""Detect the agent scheduling itself for in-person meetings.
|
|
983
992
|
|
|
984
|
-
Should NOT flag scheduling for
|
|
993
|
+
Should NOT flag scheduling for the principal or team members.
|
|
985
994
|
Returns list of issue dicts.
|
|
986
995
|
"""
|
|
987
996
|
issues = []
|
|
988
997
|
|
|
989
|
-
|
|
998
|
+
_principal_name = (_AGENT.get("principal") or {}).get("firstName", "the principal")
|
|
999
|
+
|
|
1000
|
+
# Patterns where the agent offers to physically attend
|
|
990
1001
|
self_attend_patterns = [
|
|
991
1002
|
(r'\bI\'ll\s+(?:attend|be there|come to|visit|meet you at|stop by|drop by|come by|swing by|show up)\b',
|
|
992
|
-
"
|
|
1003
|
+
f"{AGENT_FIRST_NAME} offering to physically attend"),
|
|
993
1004
|
(r'\b(?:meet me at|see you at|I\'ll see you|I can meet|let me come|I\'ll come)\b',
|
|
994
|
-
"
|
|
1005
|
+
f"{AGENT_FIRST_NAME} scheduling itself for physical meeting"),
|
|
995
1006
|
(r'\b(?:I\'ll be in|I\'m in|I will be at)\s+(?:the office|DIFC|Innovation|your office|the meeting room|the boardroom)\b',
|
|
996
|
-
"
|
|
997
|
-
(
|
|
998
|
-
"Third-person
|
|
1007
|
+
f"{AGENT_FIRST_NAME} placing itself in physical location"),
|
|
1008
|
+
(rf'\b{re.escape(AGENT_FIRST_NAME)}\s+(?:will attend|will be at|will meet|will visit)\b',
|
|
1009
|
+
f"Third-person {AGENT_FIRST_NAME} physical attendance"),
|
|
999
1010
|
(r'\bI\'ll\s+(?:fly|travel|drive|take a cab|take a taxi)\b',
|
|
1000
|
-
"
|
|
1011
|
+
f"{AGENT_FIRST_NAME} describing physical travel"),
|
|
1001
1012
|
(r'\b(?:looking forward to meeting you|see you (?:there|soon|Monday|Tuesday|Wednesday|Thursday|Friday|tomorrow|next week))\b',
|
|
1002
|
-
"
|
|
1013
|
+
f"{AGENT_FIRST_NAME} implying physical presence at meeting"),
|
|
1003
1014
|
]
|
|
1004
1015
|
|
|
1005
1016
|
# Exception patterns — scheduling others is fine
|
|
@@ -1029,7 +1040,7 @@ def check_in_person_self_scheduling(message):
|
|
|
1029
1040
|
"severity": "block",
|
|
1030
1041
|
"matched_text": matched_text,
|
|
1031
1042
|
"description": f"In-person self-scheduling detected: {description}",
|
|
1032
|
-
"suggestion": "
|
|
1043
|
+
"suggestion": f"{AGENT_FIRST_NAME} cannot attend in-person meetings. Propose {_principal_name} or a team member instead.",
|
|
1033
1044
|
"context": context_window.strip(),
|
|
1034
1045
|
})
|
|
1035
1046
|
|