instar 0.26.3 → 0.26.5
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/README.md +61 -7
- package/dashboard/index.html +55 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +2 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +188 -3
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/slack-cli.d.ts.map +1 -1
- package/dist/commands/slack-cli.js +6 -0
- package/dist/commands/slack-cli.js.map +1 -1
- package/dist/core/CapabilityMapper.d.ts.map +1 -1
- package/dist/core/CapabilityMapper.js +2 -0
- package/dist/core/CapabilityMapper.js.map +1 -1
- package/dist/core/EvolutionManager.d.ts +17 -0
- package/dist/core/EvolutionManager.d.ts.map +1 -1
- package/dist/core/EvolutionManager.js +64 -0
- package/dist/core/EvolutionManager.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +37 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts +31 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +169 -16
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/messaging/imessage/IMessageAdapter.d.ts +128 -0
- package/dist/messaging/imessage/IMessageAdapter.d.ts.map +1 -0
- package/dist/messaging/imessage/IMessageAdapter.js +541 -0
- package/dist/messaging/imessage/IMessageAdapter.js.map +1 -0
- package/dist/messaging/imessage/NativeBackend.d.ts +82 -0
- package/dist/messaging/imessage/NativeBackend.d.ts.map +1 -0
- package/dist/messaging/imessage/NativeBackend.js +353 -0
- package/dist/messaging/imessage/NativeBackend.js.map +1 -0
- package/dist/messaging/imessage/OutboundAuditLog.d.ts +49 -0
- package/dist/messaging/imessage/OutboundAuditLog.d.ts.map +1 -0
- package/dist/messaging/imessage/OutboundAuditLog.js +58 -0
- package/dist/messaging/imessage/OutboundAuditLog.js.map +1 -0
- package/dist/messaging/imessage/OutboundRateLimiter.d.ts +54 -0
- package/dist/messaging/imessage/OutboundRateLimiter.d.ts.map +1 -0
- package/dist/messaging/imessage/OutboundRateLimiter.js +111 -0
- package/dist/messaging/imessage/OutboundRateLimiter.js.map +1 -0
- package/dist/messaging/imessage/index.d.ts +10 -0
- package/dist/messaging/imessage/index.d.ts.map +1 -0
- package/dist/messaging/imessage/index.js +13 -0
- package/dist/messaging/imessage/index.js.map +1 -0
- package/dist/messaging/imessage/normalize-phone.d.ts +26 -0
- package/dist/messaging/imessage/normalize-phone.d.ts.map +1 -0
- package/dist/messaging/imessage/normalize-phone.js +55 -0
- package/dist/messaging/imessage/normalize-phone.js.map +1 -0
- package/dist/messaging/imessage/types.d.ts +95 -0
- package/dist/messaging/imessage/types.d.ts.map +1 -0
- package/dist/messaging/imessage/types.js +5 -0
- package/dist/messaging/imessage/types.js.map +1 -0
- package/dist/messaging/shared/MessagingEventBus.d.ts +5 -0
- package/dist/messaging/shared/MessagingEventBus.d.ts.map +1 -1
- package/dist/messaging/shared/MessagingEventBus.js.map +1 -1
- package/dist/messaging/slack/SlackAdapter.d.ts.map +1 -1
- package/dist/messaging/slack/SlackAdapter.js +65 -1
- package/dist/messaging/slack/SlackAdapter.js.map +1 -1
- package/dist/messaging/slack/SocketModeClient.d.ts.map +1 -1
- package/dist/messaging/slack/SocketModeClient.js +6 -0
- package/dist/messaging/slack/SocketModeClient.js.map +1 -1
- package/dist/monitoring/PresenceProxy.d.ts +6 -0
- package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
- package/dist/monitoring/PresenceProxy.js +46 -0
- package/dist/monitoring/PresenceProxy.js.map +1 -1
- package/dist/monitoring/QuotaExhaustionDetector.d.ts +15 -0
- package/dist/monitoring/QuotaExhaustionDetector.d.ts.map +1 -1
- package/dist/monitoring/QuotaExhaustionDetector.js +26 -3
- package/dist/monitoring/QuotaExhaustionDetector.js.map +1 -1
- package/dist/monitoring/SessionMonitor.d.ts.map +1 -1
- package/dist/monitoring/SessionMonitor.js +5 -2
- package/dist/monitoring/SessionMonitor.js.map +1 -1
- package/dist/monitoring/SessionRecovery.d.ts +16 -1
- package/dist/monitoring/SessionRecovery.d.ts.map +1 -1
- package/dist/monitoring/SessionRecovery.js +71 -8
- package/dist/monitoring/SessionRecovery.js.map +1 -1
- package/dist/scaffold/templates.d.ts +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +32 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/scheduler/JobScheduler.js +1 -1
- package/dist/scheduler/JobScheduler.js.map +1 -1
- package/dist/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +1 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +169 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +83 -67
- package/src/templates/hooks/intercept-imsg-send.js +68 -0
- package/src/templates/hooks/settings-template.json +11 -0
- package/src/templates/scripts/imessage-reply.sh +130 -0
- package/upgrades/0.26.4.md +17 -0
- package/upgrades/0.26.5.md +15 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* intercept-imsg-send.js — PreToolUse hook to block direct iMessage sending.
|
|
3
|
+
*
|
|
4
|
+
* Layer 2 of the 5-layer outbound safety defense-in-depth.
|
|
5
|
+
*
|
|
6
|
+
* Blocks: imsg send, osascript+Messages.app, common indirect execution patterns.
|
|
7
|
+
* Allows: imsg chats, imsg --version, imsg --help (read-only operations).
|
|
8
|
+
*
|
|
9
|
+
* Known limitations (Phase 1 accepted risks):
|
|
10
|
+
* - Scripts written to files and executed bypass inline pattern matching
|
|
11
|
+
* - Base64-encoded commands bypass regex detection
|
|
12
|
+
* - macOS Shortcuts.app could be invoked to send messages
|
|
13
|
+
* - Addressed structurally in Phase 2 (OS-level permission revocation)
|
|
14
|
+
*
|
|
15
|
+
* Install: Place in .claude/hooks/ and register as PreToolUse hook on Bash tool.
|
|
16
|
+
* Integrity: chmod 444 after install. Server verifies SHA-256 hash periodically.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// Hook receives tool input on stdin
|
|
20
|
+
const input = await new Promise((resolve) => {
|
|
21
|
+
let data = '';
|
|
22
|
+
process.stdin.on('data', (chunk) => { data += chunk; });
|
|
23
|
+
process.stdin.on('end', () => {
|
|
24
|
+
try { resolve(JSON.parse(data)); }
|
|
25
|
+
catch { resolve({}); }
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const toolName = input.tool_name || '';
|
|
30
|
+
const toolInput = input.tool_input || {};
|
|
31
|
+
|
|
32
|
+
// Only intercept Bash tool calls
|
|
33
|
+
if (toolName !== 'Bash') {
|
|
34
|
+
// Allow all non-Bash tools
|
|
35
|
+
process.stdout.write(JSON.stringify({ decision: 'allow' }));
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const command = (toolInput.command || '').toString();
|
|
40
|
+
|
|
41
|
+
// Patterns that indicate direct iMessage sending
|
|
42
|
+
const BLOCKED_PATTERNS = [
|
|
43
|
+
// Direct imsg send
|
|
44
|
+
/\bimsg\s+send\b/i,
|
|
45
|
+
// AppleScript targeting Messages.app
|
|
46
|
+
/\bosascript\b.*\bMessages\b/i,
|
|
47
|
+
/\btell\s+application\s+"Messages"/i,
|
|
48
|
+
/\btell\s+application\s+'Messages'/i,
|
|
49
|
+
// Indirect execution with iMessage references
|
|
50
|
+
/\b(?:python3?|node|ruby|perl)\s+(?:-[ce]|--eval)\s+.*\b(?:imsg\s+send|Messages)\b/i,
|
|
51
|
+
// Piped execution
|
|
52
|
+
/\becho\s+.*\b(?:imsg\s+send|Messages)\b.*\|\s*(?:ba)?sh/i,
|
|
53
|
+
// Crontab modification (could schedule sends)
|
|
54
|
+
/\bcrontab\s+-[elr]/i,
|
|
55
|
+
// macOS Shortcuts that could send messages
|
|
56
|
+
/\bshortcuts\s+run\b.*(?:message|sms|imessage|send)/i,
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
const isBlocked = BLOCKED_PATTERNS.some((p) => p.test(command));
|
|
60
|
+
|
|
61
|
+
if (isBlocked) {
|
|
62
|
+
process.stdout.write(JSON.stringify({
|
|
63
|
+
decision: 'block',
|
|
64
|
+
reason: 'Direct iMessage sending is blocked. Use imessage-reply.sh for authorized sends.',
|
|
65
|
+
}));
|
|
66
|
+
} else {
|
|
67
|
+
process.stdout.write(JSON.stringify({ decision: 'allow' }));
|
|
68
|
+
}
|
|
@@ -38,6 +38,17 @@
|
|
|
38
38
|
}
|
|
39
39
|
]
|
|
40
40
|
},
|
|
41
|
+
{
|
|
42
|
+
"matcher": "mcp__.*",
|
|
43
|
+
"hooks": [
|
|
44
|
+
{
|
|
45
|
+
"type": "command",
|
|
46
|
+
"command": "node .instar/hooks/instar/external-operation-gate.js",
|
|
47
|
+
"blocking": true,
|
|
48
|
+
"timeout": 5000
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
41
52
|
{
|
|
42
53
|
"matcher": "AskUserQuestion",
|
|
43
54
|
"hooks": [
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# imessage-reply.sh — Send a reply via iMessage with validate-before-send safety.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./imessage-reply.sh RECIPIENT "message text"
|
|
6
|
+
# echo "message text" | ./imessage-reply.sh RECIPIENT
|
|
7
|
+
# cat <<'EOF' | ./imessage-reply.sh RECIPIENT
|
|
8
|
+
# Multi-line message here
|
|
9
|
+
# EOF
|
|
10
|
+
#
|
|
11
|
+
# RECIPIENT is a phone number (+14081234567) or email (user@icloud.com).
|
|
12
|
+
#
|
|
13
|
+
# This script implements Layer 1 of the 5-layer outbound safety defense:
|
|
14
|
+
# 1. Validates recipient with server BEFORE sending (gets single-use token)
|
|
15
|
+
# 2. Sends the iMessage via `imsg send` CLI (requires Automation permission)
|
|
16
|
+
# 3. Confirms delivery to server with token (for logging + stall tracking)
|
|
17
|
+
#
|
|
18
|
+
# If validation fails, the message is NOT sent. This is the reverse of the
|
|
19
|
+
# original flow which sent first and notified second.
|
|
20
|
+
|
|
21
|
+
RECIPIENT="$1"
|
|
22
|
+
shift
|
|
23
|
+
|
|
24
|
+
if [ -z "$RECIPIENT" ]; then
|
|
25
|
+
echo "Usage: imessage-reply.sh RECIPIENT [message]" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Read message from args or stdin
|
|
30
|
+
if [ $# -gt 0 ]; then
|
|
31
|
+
MSG="$*"
|
|
32
|
+
else
|
|
33
|
+
MSG="$(cat)"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if [ -z "$MSG" ]; then
|
|
37
|
+
echo "No message provided" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# ── Setup ─────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
PORT="${INSTAR_PORT:-4042}"
|
|
44
|
+
|
|
45
|
+
AUTH_TOKEN=""
|
|
46
|
+
if [ -f ".instar/config.json" ]; then
|
|
47
|
+
AUTH_TOKEN=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('authToken',''))" 2>/dev/null)
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Escape message for JSON
|
|
51
|
+
JSON_MSG=$(printf '%s' "$MSG" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))' 2>/dev/null)
|
|
52
|
+
if [ -z "$JSON_MSG" ]; then
|
|
53
|
+
JSON_MSG="\"$(printf '%s' "$MSG" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\n/\\n/g')\""
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# URL-encode the recipient
|
|
57
|
+
ENCODED_RECIPIENT=$(printf '%s' "$RECIPIENT" | python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip(), safe=""))' 2>/dev/null)
|
|
58
|
+
if [ -z "$ENCODED_RECIPIENT" ]; then
|
|
59
|
+
ENCODED_RECIPIENT="$RECIPIENT"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
AUTH_HEADER=""
|
|
63
|
+
if [ -n "$AUTH_TOKEN" ]; then
|
|
64
|
+
AUTH_HEADER="Authorization: Bearer ${AUTH_TOKEN}"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# ── Step 1: Validate with server BEFORE sending (get single-use token) ──
|
|
68
|
+
|
|
69
|
+
VALIDATE_RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
70
|
+
-X POST "http://localhost:${PORT}/imessage/validate-send/${ENCODED_RECIPIENT}" \
|
|
71
|
+
${AUTH_HEADER:+-H "$AUTH_HEADER"} \
|
|
72
|
+
-H 'Content-Type: application/json' \
|
|
73
|
+
-d "{\"text\":${JSON_MSG}}" 2>/dev/null)
|
|
74
|
+
|
|
75
|
+
VALIDATE_BODY=$(echo "$VALIDATE_RESPONSE" | head -n -1)
|
|
76
|
+
VALIDATE_CODE=$(echo "$VALIDATE_RESPONSE" | tail -n 1)
|
|
77
|
+
|
|
78
|
+
if [ "$VALIDATE_CODE" != "200" ]; then
|
|
79
|
+
# Validation failed — DO NOT SEND
|
|
80
|
+
REASON=$(echo "$VALIDATE_BODY" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("reason","unknown"))' 2>/dev/null || echo "unknown")
|
|
81
|
+
echo "BLOCKED: $REASON" >&2
|
|
82
|
+
|
|
83
|
+
# Log blocked attempt locally as backup
|
|
84
|
+
echo "{\"blocked\":true,\"recipient\":\"${RECIPIENT}\",\"reason\":\"${REASON}\",\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" >> .instar/imessage-outbound-local.jsonl 2>/dev/null
|
|
85
|
+
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Extract send token
|
|
90
|
+
SEND_TOKEN=$(echo "$VALIDATE_BODY" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("token",""))' 2>/dev/null)
|
|
91
|
+
|
|
92
|
+
if [ -z "$SEND_TOKEN" ]; then
|
|
93
|
+
echo "BLOCKED: no send token received from server" >&2
|
|
94
|
+
exit 1
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# ── Step 2: Send via imsg CLI (only after validation passes) ──────────
|
|
98
|
+
|
|
99
|
+
IMSG="${IMSG_PATH:-imsg}"
|
|
100
|
+
if ! command -v "$IMSG" &>/dev/null; then
|
|
101
|
+
for candidate in /opt/homebrew/bin/imsg /usr/local/bin/imsg "$HOME/homebrew/bin/imsg"; do
|
|
102
|
+
if [ -x "$candidate" ]; then
|
|
103
|
+
IMSG="$candidate"
|
|
104
|
+
break
|
|
105
|
+
fi
|
|
106
|
+
done
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
if ! command -v "$IMSG" &>/dev/null && [ ! -x "$IMSG" ]; then
|
|
110
|
+
echo "imsg not found. Install: brew install steipete/tap/imsg" >&2
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
"$IMSG" send --to "$RECIPIENT" --text "$MSG" --service imessage 2>/dev/null
|
|
115
|
+
SEND_STATUS=$?
|
|
116
|
+
|
|
117
|
+
if [ $SEND_STATUS -ne 0 ]; then
|
|
118
|
+
echo "imsg send failed (exit $SEND_STATUS)" >&2
|
|
119
|
+
exit 1
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# ── Step 3: Confirm delivery to server (with token to bind validate→send) ──
|
|
123
|
+
|
|
124
|
+
curl -s -o /dev/null -w "" -X POST "http://localhost:${PORT}/imessage/reply/${ENCODED_RECIPIENT}" \
|
|
125
|
+
${AUTH_HEADER:+-H "$AUTH_HEADER"} \
|
|
126
|
+
-H 'Content-Type: application/json' \
|
|
127
|
+
-d "{\"text\":${JSON_MSG},\"sendToken\":\"${SEND_TOKEN}\"}" 2>/dev/null || \
|
|
128
|
+
echo "Warning: server confirmation failed (message was sent)" >&2
|
|
129
|
+
|
|
130
|
+
echo "Sent $(echo "$MSG" | wc -c | tr -d ' ') chars to $RECIPIENT"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# v0.26.4 — Inline Slack Text Snippets
|
|
2
|
+
|
|
3
|
+
## What Changed
|
|
4
|
+
|
|
5
|
+
**Text snippet inlining** — When users share text-based content in Slack (code snippets, meeting transcripts, plain text, markdown, CSV, JSON, etc.), the content is now inlined directly into the message as a code block. Previously, snippets were saved as file references that sessions often did not read, causing agents to hallucinate content instead of working with the actual snippet.
|
|
6
|
+
|
|
7
|
+
Detects text-based mimetypes and Slack-specific filetypes (text, snippet, post). Content up to 10KB is inlined. Larger content is truncated with a reference to the full file.
|
|
8
|
+
|
|
9
|
+
## What to Tell Your User
|
|
10
|
+
|
|
11
|
+
When you share text snippets or code blocks in Slack, the bot now reads and processes the actual content instead of just noting that a file was attached. This means meeting transcripts, code snippets, and other text content will be analyzed correctly.
|
|
12
|
+
|
|
13
|
+
## Summary of New Capabilities
|
|
14
|
+
|
|
15
|
+
| Capability | How to Use |
|
|
16
|
+
|-----------|-----------|
|
|
17
|
+
| Snippet inlining | Share a text snippet or code block in Slack — content is read directly |
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# v0.26.5 — Fix Slack Snippet Content Retrieval
|
|
2
|
+
|
|
3
|
+
## What Changed
|
|
4
|
+
|
|
5
|
+
**Three-tier snippet content resolution** — Slack snippet downloads were returning HTML pages instead of actual content (auth/redirect issue). Now uses a three-tier approach: (1) check file preview from the event payload, (2) use files.info API to get content directly, (3) fall back to downloaded file but reject HTML responses. This prevents agents from hallucinating based on HTML markup.
|
|
6
|
+
|
|
7
|
+
## What to Tell Your User
|
|
8
|
+
|
|
9
|
+
Fixed an issue where text snippets shared in Slack were not being read correctly. The bot now properly retrieves snippet content using multiple fallback methods, so it will respond based on what you actually shared rather than making up content.
|
|
10
|
+
|
|
11
|
+
## Summary of New Capabilities
|
|
12
|
+
|
|
13
|
+
| Capability | How to Use |
|
|
14
|
+
|-----------|-----------|
|
|
15
|
+
| Reliable snippet reading | Share a text snippet in Slack — content is now reliably retrieved |
|