Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
845af29
fix(agents): use allowedtools for v2 sdk tool permissions (#534)
blackpc Apr 6, 2026
a8edb49
chore(release): 1.175.1 [skip ci]
semantic-release-bot Apr 6, 2026
95fe57a
feat(tsp): add messaging remote control domain models
arielshad Apr 2, 2026
46c6246
feat(domain): add messaging remote control service
arielshad Apr 2, 2026
ffdb594
fix(domain): add messaging service mock to serve command tests and fi…
arielshad Apr 2, 2026
90318bf
chore(agents): capture evidence for messaging remote control feature
arielshad Apr 2, 2026
f3682c1
chore(agents): capture evidence for messaging remote control feature
arielshad Apr 2, 2026
cea80fd
chore(agents): capture evidence for messaging remote control feature
arielshad Apr 2, 2026
42c9b9d
chore(specs): update feature yaml with completed phases tracking
arielshad Apr 2, 2026
2c53d31
fix(ci): attempt 1/10 — replace fake api key in test to pass gitleaks…
arielshad Apr 2, 2026
e94aaed
feat(domain): wire real gateway tunnel and telegram remote control
arielshad Apr 6, 2026
d333ae0
fix(ci): update gitleaksignore sha after rebase on main
arielshad Apr 6, 2026
e133e37
fix(domain): make messaging remote control work end-to-end
arielshad Apr 9, 2026
757b0cb
fix(domain): merge main into feat/messaging-remote-control
arielshad Apr 12, 2026
2529d68
fix(ci): attempt 1/10 — stub gateway client for e2e tests
arielshad Apr 12, 2026
3ae33e6
fix(domain): merge main into feat/messaging-remote-control
arielshad Apr 13, 2026
6e5deaf
fix(domain): merge main into feat/messaging-remote-control
arielshad Apr 26, 2026
e37c020
fix(ci): attempt 1/10 — add ws to electron package dependencies
arielshad Apr 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
dc0ca49a66f0ffe3ce9b37bd283513bb714ecada:src/presentation/web/components/common/feature-drawer/feature-drawer.stories.tsx:generic-api-key:124
42204c37eaad7947bf332782e4609f6480593abb:tests/unit/infrastructure/services/agents/executors/cursor-executor.test.ts:generic-api-key:599
1c6b4761ae042411095cb1af81524853ef48bad7:tests/unit/infrastructure/services/messaging/content-sanitizer.test.ts:generic-api-key:24
3173676049f52fb4ff16805d1c50c27e652b7b75:tests/unit/infrastructure/services/messaging/content-sanitizer.test.ts:generic-api-key:24
cbe61f9d8b22bc0176339855f08b06ceee68fb49:src/presentation/web/components/features/settings/agent-settings-section.stories.tsx:generic-api-key:68
cbe61f9d8b22bc0176339855f08b06ceee68fb49:src/presentation/web/components/features/settings/agent-settings-section.stories.tsx:generic-api-key:78
Expand Down
41 changes: 41 additions & 0 deletions .storybook/mocks/app/actions/messaging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { MessagingPlatform } from '@shepai/core/domain/generated/output';

export async function beginMessagingPairingAction(input: {
platform: MessagingPlatform;
gatewayUrl: string;
}): Promise<{
success: boolean;
error?: string;
session?: {
platform: MessagingPlatform;
code: string;
expiresAt: string;
gatewayUrl: string;
publicUrl: string;
routeId: string;
};
}> {
return {
success: true,
session: {
platform: input.platform,
code: '482913',
expiresAt: new Date(Date.now() + 10 * 60 * 1000).toISOString(),
gatewayUrl: input.gatewayUrl,
publicUrl: `${input.gatewayUrl.replace(/\/$/, '')}/integrations/route-demo/token-demo`,
routeId: 'route-demo',
},
};
}

export async function confirmMessagingPairingAction(
_input: unknown
): Promise<{ success: boolean; error?: string }> {
return { success: true };
}

export async function disconnectMessagingAction(
_input: unknown
): Promise<{ success: boolean; error?: string }> {
return { success: true };
}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@

* **tsp:** add ukrainian (uk) translation ([#535](https://github.com/shep-ai/shep/issues/535)) ([a9170fb](https://github.com/shep-ai/shep/commit/a9170fbdf081870469c58bc3433b17b000e83316))


## [1.175.1](https://github.com/shep-ai/shep/compare/v1.175.0...v1.175.1) (2026-04-06)


Expand Down
24 changes: 24 additions & 0 deletions LESSONS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Lessons Learned

## Messaging Remote Control: HttpGatewayClient Uses an Unsupported OAuth Grant

`HttpGatewayClient.fetchAccessToken` (feat/messaging-remote-control, feature 082) hardcodes
`grant_type=client_credentials` in its call to `POST /oauth/token`. The OSS Commands Gateway
demo mode (`AUTH_MODE=demo`) advertises only `authorization_code` and `refresh_token` in its
`.well-known/openid-configuration` and returns `400 {"error":"unsupported grant_type"}` for
`client_credentials`. As a result, `BeginMessagingPairingUseCase` always throws
"Gateway authentication failed: ..." and the web pairing dialog never opens — the Pair button
silently fails because (a) the server action returns `{ success: false, error }` and
(b) no `<Toaster />` is mounted in the web layout, so the `toast.error(...)` never renders.

**What to fix before this can work end-to-end against a real gateway:**
1. Swap `HttpGatewayClient.fetchAccessToken` to the authorization-code + PKCE flow
(matches the gateway's supported grants), OR add device-code support on the gateway side.
2. Mount a sonner `<Toaster />` in the web root layout so pairing failures are visible to
the user instead of silently failing.
3. The feature was marked `fast-implement` complete and merged to main without ever being
exercised against a live OSS gateway. Add a smoke test that spins up the gateway Go binary
in CI and runs `BeginMessagingPairingUseCase` against it.

**Rule:** Any time a feature integrates with an external service, it must be validated against
a live instance of that service — unit tests with fetch mocks are not sufficient because they
only verify what you *think* the protocol is.

## Adding a Web Feature Flag — Full Wiring Checklist

Feature flags are persisted in the Settings singleton and toggled via the Settings page. A new flag is NOT just an env var or a hardcoded boolean — it must be wired end-to-end or the Settings toggle will silently fail to persist.
Expand Down
28 changes: 28 additions & 0 deletions apis/json-schema/MessagingCommand.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: MessagingCommand.yaml
type: object
properties:
type:
$ref: MessagingFrameType.yaml
description: "Type of frame: command, chat_message, or chat_control"
command:
$ref: MessagingCommandType.yaml
description: The slash command name (new, approve, reject, stop, resume, status)
featureId:
type: string
description: Target feature ID (short numeric or full UUID)
args:
type: string
description: Free-text arguments (feature description, rejection feedback, chat text)
chatId:
type: string
description: Chat ID for routing responses back to the correct conversation
platform:
$ref: MessagingPlatform.yaml
description: Platform for routing responses back (telegram or whatsapp)
required:
- type
- command
- chatId
- platform
description: A parsed command received from a messaging platform via the Gateway tunnel
17 changes: 17 additions & 0 deletions apis/json-schema/MessagingCommandType.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: MessagingCommandType.yaml
type: string
enum:
- new
- approve
- reject
- stop
- resume
- status
- mute
- unmute
- list
- chat
- end
- help
description: Slash commands supported via messaging remote control
40 changes: 40 additions & 0 deletions apis/json-schema/MessagingConfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: MessagingConfig.yaml
type: object
properties:
enabled:
type: boolean
default: false
description: Whether messaging remote control is enabled
gatewayUrl:
type: string
description: URL of the Commands.com Gateway instance
deviceId:
type: string
description: Device ID used when registering integration routes and opening the tunnel
gatewayClientId:
type: string
description: OAuth client ID for fetching gateway access tokens (demo mode uses public client)
telegram:
$ref: MessagingPlatformConfig.yaml
description: Telegram platform configuration
whatsapp:
$ref: MessagingPlatformConfig.yaml
description: WhatsApp platform configuration
debounceMs:
type: integer
minimum: -2147483648
maximum: 2147483647
default: 5000
description: "Debounce window in milliseconds for notification delivery (default: 5000)"
chatBufferMs:
type: integer
minimum: -2147483648
maximum: 2147483647
default: 3000
description: "Buffer interval in milliseconds for chat relay output batching (default: 3000)"
required:
- enabled
- debounceMs
- chatBufferMs
description: Messaging remote control configuration
8 changes: 8 additions & 0 deletions apis/json-schema/MessagingFrameType.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: MessagingFrameType.yaml
type: string
enum:
- command
- chat_message
- chat_control
description: Types of messages exchanged through the messaging tunnel
22 changes: 22 additions & 0 deletions apis/json-schema/MessagingNotification.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: MessagingNotification.yaml
type: object
properties:
event:
type: string
description: "Event type: feature lifecycle, CI status, gate waiting, command response, chat response"
featureId:
type: string
description: ID of the feature this notification relates to
title:
type: string
description: Human-readable feature name or title
message:
type: string
description: Human-readable notification body (sanitized, no code or secrets)
required:
- event
- featureId
- title
- message
description: A notification or response sent from Shep to a messaging platform via the Gateway tunnel
7 changes: 7 additions & 0 deletions apis/json-schema/MessagingPlatform.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: MessagingPlatform.yaml
type: string
enum:
- telegram
- whatsapp
description: Supported external messaging platforms
38 changes: 38 additions & 0 deletions apis/json-schema/MessagingPlatformConfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: MessagingPlatformConfig.yaml
type: object
properties:
enabled:
type: boolean
default: false
description: Whether this platform connection is active
chatId:
type: string
description: Platform-specific chat ID for message routing (set during pairing)
paired:
type: boolean
default: false
description: Whether the chat has been verified via pairing code
pendingPairingCode:
type: string
description: One-time code shown to the user during pairing, cleared once confirmed
pendingPairingExpiresAt:
type: string
format: date-time
description: Expiry timestamp for the pending pairing code (ISO-8601)
routeId:
type: string
description: Gateway integration route ID allocated during pairing
routeToken:
type: string
description: Gateway integration route token (path-auth) allocated during pairing
publicUrl:
type: string
description: Public webhook URL that the messaging platform should POST updates to
botToken:
type: string
description: "Bot API token used by the daemon to send outbound messages (Telegram: 123456:ABC...)"
required:
- enabled
- paired
description: Configuration for a single messaging platform connection
3 changes: 3 additions & 0 deletions apis/json-schema/Settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ properties:
fabLayout:
$ref: FabLayoutConfig.yaml
description: FAB layout configuration (optional, defaults applied at runtime)
messaging:
$ref: MessagingConfig.yaml
description: Messaging remote control configuration (optional, defaults applied at runtime)
required:
- models
- user
Expand Down
Loading
Loading