@vellumai/assistant 0.4.2 → 0.4.4
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/.env.example +3 -0
- package/ARCHITECTURE.md +124 -10
- package/README.md +43 -35
- package/docs/trusted-contact-access.md +20 -0
- package/package.json +1 -1
- package/scripts/ipc/generate-swift.ts +1 -0
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +58 -120
- package/src/__tests__/access-request-decision.test.ts +0 -1
- package/src/__tests__/actor-token-service.test.ts +1099 -0
- package/src/__tests__/agent-loop.test.ts +51 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +7 -5
- package/src/__tests__/assistant-id-boundary-guard.test.ts +415 -0
- package/src/__tests__/call-controller.test.ts +49 -0
- package/src/__tests__/call-pointer-message-composer.test.ts +171 -0
- package/src/__tests__/call-pointer-messages.test.ts +93 -3
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +42 -0
- package/src/__tests__/call-routes-http.test.ts +0 -25
- package/src/__tests__/callback-handoff-copy.test.ts +186 -0
- package/src/__tests__/channel-approval-routes.test.ts +133 -12
- package/src/__tests__/channel-guardian.test.ts +0 -86
- package/src/__tests__/channel-readiness-service.test.ts +10 -16
- package/src/__tests__/checker.test.ts +33 -12
- package/src/__tests__/config-schema.test.ts +6 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +410 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +256 -0
- package/src/__tests__/conversation-routes.test.ts +12 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/daemon-server-session-init.test.ts +4 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
- package/src/__tests__/guardian-actions-endpoint.test.ts +39 -13
- package/src/__tests__/guardian-dispatch.test.ts +8 -0
- package/src/__tests__/guardian-outbound-http.test.ts +4 -5
- package/src/__tests__/guardian-question-mode.test.ts +200 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +178 -0
- package/src/__tests__/guardian-routing-state.test.ts +525 -0
- package/src/__tests__/handle-user-message-secret-resume.test.ts +2 -0
- package/src/__tests__/handlers-telegram-config.test.ts +0 -83
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +55 -0
- package/src/__tests__/headless-browser-navigate.test.ts +2 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
- package/src/__tests__/ingress-routes-http.test.ts +55 -0
- package/src/__tests__/ipc-snapshot.test.ts +18 -51
- package/src/__tests__/non-member-access-request.test.ts +159 -9
- package/src/__tests__/notification-decision-fallback.test.ts +129 -4
- package/src/__tests__/notification-decision-strategy.test.ts +106 -2
- package/src/__tests__/notification-guardian-path.test.ts +3 -0
- package/src/__tests__/recording-intent-handler.test.ts +1 -0
- package/src/__tests__/relay-server.test.ts +1475 -33
- package/src/__tests__/send-endpoint-busy.test.ts +5 -0
- package/src/__tests__/session-agent-loop.test.ts +1 -0
- package/src/__tests__/session-confirmation-signals.test.ts +523 -0
- package/src/__tests__/session-init.benchmark.test.ts +0 -2
- package/src/__tests__/session-runtime-assembly.test.ts +4 -1
- package/src/__tests__/session-surfaces-task-progress.test.ts +44 -1
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +81 -2
- package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -1
- package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +21 -2
- package/src/__tests__/tool-grant-request-escalation.test.ts +333 -27
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +678 -0
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1064 -0
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +11 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/trusted-contact-verification.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +2 -13
- package/src/__tests__/twilio-routes.test.ts +4 -3
- package/src/__tests__/update-bulletin.test.ts +0 -1
- package/src/agent/loop.ts +1 -1
- package/src/approvals/guardian-decision-primitive.ts +12 -3
- package/src/approvals/guardian-request-resolvers.ts +169 -11
- package/src/calls/call-constants.ts +29 -0
- package/src/calls/call-controller.ts +11 -3
- package/src/calls/call-domain.ts +33 -11
- package/src/calls/call-pointer-message-composer.ts +154 -0
- package/src/calls/call-pointer-messages.ts +106 -27
- package/src/calls/guardian-dispatch.ts +4 -2
- package/src/calls/relay-server.ts +921 -112
- package/src/calls/twilio-config.ts +4 -11
- package/src/calls/twilio-routes.ts +4 -6
- package/src/calls/types.ts +3 -1
- package/src/calls/voice-session-bridge.ts +4 -3
- package/src/cli/core-commands.ts +7 -4
- package/src/cli.ts +5 -4
- package/src/config/bundled-skills/agentmail/SKILL.md +4 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +309 -10
- package/src/config/bundled-skills/app-builder/TOOLS.json +1 -1
- package/src/config/bundled-skills/email-setup/SKILL.md +1 -1
- package/src/config/bundled-skills/google-oauth-setup/SKILL.md +105 -81
- package/src/config/bundled-skills/messaging/SKILL.md +61 -12
- package/src/config/bundled-skills/messaging/TOOLS.json +58 -0
- package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +6 -1
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +35 -0
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +52 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +30 -39
- package/src/config/bundled-skills/twitter/SKILL.md +3 -3
- package/src/config/bundled-skills/vercel-token-setup/SKILL.md +215 -0
- package/src/config/calls-schema.ts +36 -0
- package/src/config/env.ts +22 -0
- package/src/config/feature-flag-registry.json +8 -8
- package/src/config/schema.ts +2 -2
- package/src/config/skills.ts +11 -0
- package/src/config/system-prompt.ts +11 -1
- package/src/config/templates/SOUL.md +2 -0
- package/src/config/vellum-skills/sms-setup/SKILL.md +71 -82
- package/src/config/vellum-skills/trusted-contacts/SKILL.md +8 -1
- package/src/config/vellum-skills/twilio-setup/SKILL.md +88 -73
- package/src/daemon/call-pointer-generators.ts +59 -0
- package/src/daemon/computer-use-session.ts +2 -5
- package/src/daemon/handlers/apps.ts +76 -20
- package/src/daemon/handlers/config-channels.ts +9 -61
- package/src/daemon/handlers/config-inbox.ts +11 -3
- package/src/daemon/handlers/config-ingress.ts +28 -3
- package/src/daemon/handlers/config-telegram.ts +12 -0
- package/src/daemon/handlers/config.ts +2 -6
- package/src/daemon/handlers/index.ts +2 -1
- package/src/daemon/handlers/pairing.ts +2 -0
- package/src/daemon/handlers/publish.ts +11 -46
- package/src/daemon/handlers/sessions.ts +59 -5
- package/src/daemon/handlers/shared.ts +17 -2
- package/src/daemon/ipc-contract/apps.ts +1 -0
- package/src/daemon/ipc-contract/inbox.ts +4 -0
- package/src/daemon/ipc-contract/integrations.ts +1 -97
- package/src/daemon/ipc-contract/messages.ts +47 -1
- package/src/daemon/ipc-contract/notifications.ts +11 -0
- package/src/daemon/ipc-contract-inventory.json +2 -4
- package/src/daemon/lifecycle.ts +17 -0
- package/src/daemon/server.ts +16 -2
- package/src/daemon/session-agent-loop-handlers.ts +20 -0
- package/src/daemon/session-agent-loop.ts +24 -12
- package/src/daemon/session-lifecycle.ts +1 -1
- package/src/daemon/session-process.ts +11 -1
- package/src/daemon/session-runtime-assembly.ts +6 -1
- package/src/daemon/session-surfaces.ts +32 -3
- package/src/daemon/session.ts +88 -1
- package/src/daemon/tool-side-effects.ts +22 -0
- package/src/home-base/prebuilt/brain-graph.html +1483 -0
- package/src/home-base/prebuilt/index.html +40 -0
- package/src/inbound/platform-callback-registration.ts +157 -0
- package/src/memory/canonical-guardian-store.ts +1 -1
- package/src/memory/conversation-crud.ts +2 -1
- package/src/memory/conversation-title-service.ts +16 -2
- package/src/memory/db-init.ts +8 -0
- package/src/memory/delivery-crud.ts +2 -1
- package/src/memory/guardian-action-store.ts +2 -1
- package/src/memory/guardian-approvals.ts +3 -2
- package/src/memory/ingress-invite-store.ts +12 -2
- package/src/memory/ingress-member-store.ts +4 -3
- package/src/memory/migrations/038-actor-token-records.ts +39 -0
- package/src/memory/migrations/124-voice-invite-display-metadata.ts +14 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/schema.ts +26 -5
- package/src/messaging/provider-types.ts +24 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/adapter.ts +127 -0
- package/src/messaging/providers/sms/adapter.ts +40 -37
- package/src/notifications/adapters/macos.ts +45 -2
- package/src/notifications/broadcaster.ts +16 -0
- package/src/notifications/copy-composer.ts +50 -2
- package/src/notifications/decision-engine.ts +22 -9
- package/src/notifications/destination-resolver.ts +16 -2
- package/src/notifications/emit-signal.ts +18 -9
- package/src/notifications/guardian-question-mode.ts +419 -0
- package/src/notifications/signal.ts +14 -3
- package/src/permissions/checker.ts +13 -1
- package/src/permissions/prompter.ts +14 -0
- package/src/providers/anthropic/client.ts +20 -0
- package/src/providers/provider-send-message.ts +15 -3
- package/src/runtime/access-request-helper.ts +82 -4
- package/src/runtime/actor-token-service.ts +234 -0
- package/src/runtime/actor-token-store.ts +236 -0
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/assistant-scope.ts +10 -0
- package/src/runtime/channel-approvals.ts +5 -3
- package/src/runtime/channel-readiness-service.ts +23 -64
- package/src/runtime/channel-readiness-types.ts +3 -4
- package/src/runtime/channel-retry-sweep.ts +4 -1
- package/src/runtime/confirmation-request-guardian-bridge.ts +197 -0
- package/src/runtime/guardian-action-followup-executor.ts +1 -1
- package/src/runtime/guardian-context-resolver.ts +82 -0
- package/src/runtime/guardian-outbound-actions.ts +5 -7
- package/src/runtime/guardian-reply-router.ts +67 -30
- package/src/runtime/guardian-vellum-migration.ts +57 -0
- package/src/runtime/http-server.ts +75 -31
- package/src/runtime/http-types.ts +13 -0
- package/src/runtime/ingress-service.ts +14 -0
- package/src/runtime/invite-redemption-service.ts +10 -1
- package/src/runtime/local-actor-identity.ts +76 -0
- package/src/runtime/middleware/actor-token.ts +271 -0
- package/src/runtime/middleware/twilio-validation.ts +2 -4
- package/src/runtime/routes/approval-routes.ts +82 -7
- package/src/runtime/routes/brain-graph-routes.ts +222 -0
- package/src/runtime/routes/call-routes.ts +2 -1
- package/src/runtime/routes/channel-readiness-routes.ts +71 -0
- package/src/runtime/routes/channel-route-shared.ts +3 -3
- package/src/runtime/routes/conversation-attention-routes.ts +2 -1
- package/src/runtime/routes/conversation-routes.ts +142 -53
- package/src/runtime/routes/events-routes.ts +22 -8
- package/src/runtime/routes/guardian-action-routes.ts +45 -3
- package/src/runtime/routes/guardian-approval-interception.ts +29 -0
- package/src/runtime/routes/guardian-bootstrap-routes.ts +145 -0
- package/src/runtime/routes/inbound-conversation.ts +4 -3
- package/src/runtime/routes/inbound-message-handler.ts +147 -5
- package/src/runtime/routes/ingress-routes.ts +2 -0
- package/src/runtime/routes/integration-routes.ts +7 -15
- package/src/runtime/routes/pairing-routes.ts +163 -0
- package/src/runtime/routes/twilio-routes.ts +934 -0
- package/src/runtime/tool-grant-request-helper.ts +3 -1
- package/src/security/oauth2.ts +27 -2
- package/src/security/token-manager.ts +46 -10
- package/src/tools/browser/browser-execution.ts +4 -3
- package/src/tools/browser/browser-handoff.ts +10 -18
- package/src/tools/browser/browser-manager.ts +80 -25
- package/src/tools/browser/browser-screencast.ts +35 -119
- package/src/tools/calls/call-start.ts +2 -1
- package/src/tools/permission-checker.ts +15 -4
- package/src/tools/terminal/parser.ts +12 -0
- package/src/tools/tool-approval-handler.ts +244 -19
- package/src/workspace/git-service.ts +19 -0
- package/src/__tests__/handlers-twilio-config.test.ts +0 -1928
- package/src/daemon/handlers/config-twilio.ts +0 -1082
|
@@ -9,20 +9,18 @@ You are helping your user set up SMS messaging. This skill orchestrates Twilio s
|
|
|
9
9
|
|
|
10
10
|
## Step 1: Check Channel Readiness
|
|
11
11
|
|
|
12
|
-
First, check the current SMS channel readiness state
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
"channel": "sms"
|
|
19
|
-
}
|
|
12
|
+
First, check the current SMS channel readiness state via the gateway:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
16
|
+
curl -s "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/config" \
|
|
17
|
+
-H "Authorization: Bearer $TOKEN"
|
|
20
18
|
```
|
|
21
19
|
|
|
22
|
-
Inspect the
|
|
20
|
+
Inspect the response for `hasCredentials` and `phoneNumber`.
|
|
23
21
|
|
|
24
|
-
- If
|
|
25
|
-
- If
|
|
22
|
+
- If both are present and all baseline requirements are met, skip to Step 3.
|
|
23
|
+
- If credentials or phone number are missing, proceed to Step 2 to fix the baseline.
|
|
26
24
|
|
|
27
25
|
## Step 2: Establish Baseline (Twilio Setup)
|
|
28
26
|
|
|
@@ -34,47 +32,35 @@ skill_load skill=twilio-setup
|
|
|
34
32
|
|
|
35
33
|
Tell the user: *"SMS needs Twilio configured first. I've loaded the Twilio setup guide — let's walk through it."*
|
|
36
34
|
|
|
37
|
-
After twilio-setup completes, re-check readiness:
|
|
35
|
+
After twilio-setup completes, re-check readiness by calling the config endpoint again:
|
|
38
36
|
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"channel": "sms"
|
|
44
|
-
}
|
|
37
|
+
```bash
|
|
38
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
39
|
+
curl -s "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/config" \
|
|
40
|
+
-H "Authorization: Bearer $TOKEN"
|
|
45
41
|
```
|
|
46
42
|
|
|
47
43
|
If baseline is still not ready, report the specific failures and ask the user to address them before continuing.
|
|
48
44
|
|
|
49
45
|
## Step 3: Remote Compliance Check
|
|
50
46
|
|
|
51
|
-
Once baseline is ready,
|
|
47
|
+
Once baseline is ready, check SMS compliance status including remote (Twilio API) checks:
|
|
52
48
|
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
"channel": "sms",
|
|
58
|
-
"includeRemote": true
|
|
59
|
-
}
|
|
49
|
+
```bash
|
|
50
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
51
|
+
curl -s "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/sms/compliance" \
|
|
52
|
+
-H "Authorization: Bearer $TOKEN"
|
|
60
53
|
```
|
|
61
54
|
|
|
62
|
-
Examine the
|
|
63
|
-
- If all
|
|
55
|
+
Examine the compliance results:
|
|
56
|
+
- If all checks pass, proceed to Step 4.
|
|
64
57
|
- If compliance issues are found (e.g., toll-free verification needed), guide the user through the compliance flow.
|
|
65
58
|
|
|
66
59
|
### Toll-Free Verification Submission
|
|
67
60
|
|
|
68
|
-
When the
|
|
61
|
+
When the compliance check returns a toll-free verification requirement, use the gateway's compliance endpoints. These handle credential lookup, phone number SID resolution, field validation, and Twilio API calls internally.
|
|
69
62
|
|
|
70
|
-
**Step 3a: Check compliance status.** First check if a verification already exists:
|
|
71
|
-
|
|
72
|
-
```json
|
|
73
|
-
{
|
|
74
|
-
"type": "twilio_config",
|
|
75
|
-
"action": "sms_compliance_status"
|
|
76
|
-
}
|
|
77
|
-
```
|
|
63
|
+
**Step 3a: Check compliance status.** First check if a verification already exists (use the response from the compliance check above):
|
|
78
64
|
|
|
79
65
|
The response includes a `compliance` object with `numberType`, `tollfreePhoneNumberSid`, `verificationSid`, `verificationStatus`, `rejectionReason`, `rejectionReasons`, `editAllowed`, and `editExpiration` fields. For toll-free numbers, `tollfreePhoneNumberSid` contains the Twilio phone number SID needed for verification submission.
|
|
80
66
|
|
|
@@ -98,15 +84,16 @@ The response includes a `compliance` object with `numberType`, `tollfreePhoneNum
|
|
|
98
84
|
| Opt-in type | `optInType` | `VERBAL`, `WEB_FORM`, `PAPER_FORM`, `VIA_TEXT`, `MOBILE_QR_CODE` |
|
|
99
85
|
| Opt-in image URL | `optInImageUrls` | Array of URLs showing opt-in mechanism (can be website URL) |
|
|
100
86
|
|
|
101
|
-
The `tollfreePhoneNumberSid` is returned by the
|
|
87
|
+
The `tollfreePhoneNumberSid` is returned by the compliance status response in the `compliance` object. Use `compliance.tollfreePhoneNumberSid` from the Step 3a response as the value for `tollfreePhoneNumberSid` when submitting. Do NOT ask for EIN, business registration number, or business registration authority. Explain that Twilio labels some fields as "business" fields even for individual submitters.
|
|
102
88
|
|
|
103
89
|
**Step 3c: Submit verification:**
|
|
104
90
|
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
"
|
|
109
|
-
"
|
|
91
|
+
```bash
|
|
92
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
93
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/sms/compliance/tollfree" \
|
|
94
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
95
|
+
-H "Content-Type: application/json" \
|
|
96
|
+
-d '{
|
|
110
97
|
"tollfreePhoneNumberSid": "<compliance.tollfreePhoneNumberSid from Step 3a>",
|
|
111
98
|
"businessName": "...",
|
|
112
99
|
"businessWebsite": "...",
|
|
@@ -118,11 +105,10 @@ The `tollfreePhoneNumberSid` is returned by the `sms_compliance_status` response
|
|
|
118
105
|
"optInType": "VERBAL",
|
|
119
106
|
"messageVolume": "100",
|
|
120
107
|
"businessType": "SOLE_PROPRIETOR"
|
|
121
|
-
}
|
|
122
|
-
}
|
|
108
|
+
}'
|
|
123
109
|
```
|
|
124
110
|
|
|
125
|
-
The
|
|
111
|
+
The endpoint validates all fields before submitting to Twilio and returns clear error messages for invalid values.
|
|
126
112
|
|
|
127
113
|
**On success:** The response contains `compliance.verificationSid` and `compliance.verificationStatus` (typically `PENDING_REVIEW`). Tell the user Twilio typically reviews within 1-5 business days.
|
|
128
114
|
|
|
@@ -130,36 +116,33 @@ The daemon validates all fields before submitting to Twilio and returns clear er
|
|
|
130
116
|
|
|
131
117
|
**Step 3d: Update a rejected verification** (if `editAllowed` is true):
|
|
132
118
|
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
|
|
119
|
+
```bash
|
|
120
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
121
|
+
curl -s -X PATCH "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/sms/compliance/tollfree/<verificationSid>" \
|
|
122
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
123
|
+
-H "Content-Type: application/json" \
|
|
124
|
+
-d '{
|
|
139
125
|
"businessName": "updated value",
|
|
140
126
|
"useCaseSummary": "updated value"
|
|
141
|
-
}
|
|
142
|
-
}
|
|
127
|
+
}'
|
|
143
128
|
```
|
|
144
129
|
|
|
145
|
-
Only include fields that need to change. The
|
|
130
|
+
Only include fields that need to change. The endpoint checks edit eligibility and expiration before attempting the update.
|
|
146
131
|
|
|
147
132
|
**Step 3e: Delete and resubmit** (if editing is not allowed):
|
|
148
133
|
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
"
|
|
153
|
-
"verificationSid": "<sid from compliance status>"
|
|
154
|
-
}
|
|
134
|
+
```bash
|
|
135
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
136
|
+
curl -s -X DELETE "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/sms/compliance/tollfree/<verificationSid>" \
|
|
137
|
+
-H "Authorization: Bearer $TOKEN"
|
|
155
138
|
```
|
|
156
139
|
|
|
157
140
|
After deletion, return to Step 3b to collect information and resubmit. Warn the user that deleting resets their position in the review queue.
|
|
158
141
|
|
|
159
142
|
**Common errors:**
|
|
160
143
|
- `"Customer profiles submitted with verifications must be either ISV Starters or Secondary Customer Profiles"` — The number is linked to a Primary Customer Profile in Trust Hub, which blocks toll-free verification. Tell the user and suggest they resolve the profile assignment in the Twilio Console.
|
|
161
|
-
- Missing required fields — The
|
|
162
|
-
- Invalid enum values — The
|
|
144
|
+
- Missing required fields — The endpoint validates and reports which fields are missing.
|
|
145
|
+
- Invalid enum values — The endpoint validates `optInType`, `messageVolume`, and `useCaseCategories` and reports valid values.
|
|
163
146
|
|
|
164
147
|
**On success:** Tell the user the verification has been submitted and is now `PENDING_REVIEW`. Twilio typically reviews within 1-5 business days. They'll receive status updates at the notification email provided.
|
|
165
148
|
|
|
@@ -195,11 +178,31 @@ Tell the user: *"Let's send a test SMS to verify everything works. What phone nu
|
|
|
195
178
|
|
|
196
179
|
**Trial account limitation:** On Twilio trial accounts, SMS can only be sent to verified phone numbers. If the send fails with a "not verified" error, tell the user to verify the recipient number in the Twilio Console under Verified Caller IDs, or upgrade their account.
|
|
197
180
|
|
|
198
|
-
After the user provides a number, send a test message
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
181
|
+
After the user provides a number, send a test message via the gateway:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
185
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/sms/test" \
|
|
186
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
187
|
+
-H "Content-Type: application/json" \
|
|
188
|
+
-d '{"phoneNumber":"<recipient phone number>","text":"Test SMS from your Vellum assistant."}'
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Report the result honestly:
|
|
192
|
+
- If the send succeeds: *"The message was accepted by Twilio. Note: 'accepted' means Twilio received it for delivery, not that it reached the handset yet. Delivery can take a few seconds to a few minutes. If verification is still pending, carriers may silently drop the message."*
|
|
193
|
+
- If the send fails: report the error and suggest troubleshooting steps
|
|
194
|
+
|
|
195
|
+
### SMS Diagnostics
|
|
196
|
+
|
|
197
|
+
If the test fails or the user reports SMS issues, run the SMS doctor:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
201
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/sms/doctor" \
|
|
202
|
+
-H "Authorization: Bearer $TOKEN"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
This runs a comprehensive health diagnostic, checking channel readiness, compliance/toll-free verification status, and the last test result. Report the diagnostics and actionable items to the user.
|
|
203
206
|
|
|
204
207
|
## Step 5: Final Status Report
|
|
205
208
|
|
|
@@ -229,17 +232,3 @@ Common issues:
|
|
|
229
232
|
- **"Twilio error on send"** — Check credentials, phone number assignment, and ingress
|
|
230
233
|
- **"Trial account limitations"** — Explain that trial accounts can only send to verified numbers
|
|
231
234
|
- **"Customer profiles must be ISV Starters or Secondary"** — The toll-free number is linked to a Primary Customer Profile in Trust Hub. Must be unlinked or reassigned before verification can be submitted.
|
|
232
|
-
|
|
233
|
-
## Accessing the Twilio API
|
|
234
|
-
|
|
235
|
-
The skill references IPC messages (`channel_readiness`, `twilio_config`) that are sent via Unix socket to the daemon. The assistant does not have an HTTP endpoint for IPC. Use the following pattern to send IPC messages:
|
|
236
|
-
|
|
237
|
-
```bash
|
|
238
|
-
cd "$(git rev-parse --show-toplevel)/assistant" && bun -e '
|
|
239
|
-
import { sendOneMessage } from "./src/cli/ipc-client.js";
|
|
240
|
-
const res = await sendOneMessage({ type: "twilio_config", action: "get" });
|
|
241
|
-
console.log(JSON.stringify(res, null, 2));
|
|
242
|
-
'
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
All compliance operations (status checks, verification submission, updates, and deletion) are handled through the `twilio_config` IPC actions — no direct Twilio REST calls are needed.
|
|
@@ -254,6 +254,8 @@ INVITE_JSON=$(curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/ingress/invites" \
|
|
|
254
254
|
-d '{
|
|
255
255
|
"sourceChannel": "voice",
|
|
256
256
|
"expectedExternalUserId": "<phone_number_E164>",
|
|
257
|
+
"friendName": "<invitee display name>",
|
|
258
|
+
"guardianName": "<guardian display name>",
|
|
257
259
|
"maxUses": 1,
|
|
258
260
|
"note": "<optional note, e.g. the person it is for>"
|
|
259
261
|
}')
|
|
@@ -263,6 +265,8 @@ printf '%s\n' "$INVITE_JSON"
|
|
|
263
265
|
Required fields:
|
|
264
266
|
- `sourceChannel` — must be `"voice"`
|
|
265
267
|
- `expectedExternalUserId` — the invitee's phone number in E.164 format (e.g., `+15551234567`)
|
|
268
|
+
- `friendName` — the invitee's display name (e.g., "Mom", "Dr. Smith"). Used during the voice verification call to personalize the experience.
|
|
269
|
+
- `guardianName` — the guardian's display name (e.g., "Alex"). Used during the voice verification call so the invitee knows who invited them.
|
|
266
270
|
|
|
267
271
|
Optional fields:
|
|
268
272
|
- `maxUses` — how many times the code can be used (default: 1)
|
|
@@ -270,8 +274,9 @@ Optional fields:
|
|
|
270
274
|
- ~~`voiceCodeDigits`~~ — always 6 digits; this parameter is accepted but ignored
|
|
271
275
|
- `note` — a human-readable label for the invite (e.g., "For Mom", "Dr. Smith")
|
|
272
276
|
|
|
273
|
-
The create response contains `{ ok: true, invite: { id, voiceCode, expectedExternalUserId, ... } }`.
|
|
277
|
+
The create response contains `{ ok: true, invite: { id, voiceCode, expectedExternalUserId, friendName, guardianName, ... } }`.
|
|
274
278
|
- `voiceCode` is the numeric code the invitee must enter and is only returned at creation time.
|
|
279
|
+
- `friendName` and `guardianName` are echoed back in the response.
|
|
275
280
|
- Voice invite responses do **not** include `token` or `share.url`. Do not try to build or send a deep link for voice invites.
|
|
276
281
|
|
|
277
282
|
**Presenting to the guardian**: Give the guardian clear instructions to relay to the invitee:
|
|
@@ -348,6 +353,8 @@ Replace `<invite_id>` with the invite's `id` from the list response. The same re
|
|
|
348
353
|
- `sourceChannel is required for create` — when creating an invite, always pass `"sourceChannel": "telegram"` for Telegram or `"sourceChannel": "voice"` for voice invites.
|
|
349
354
|
- `expectedExternalUserId is required for voice invites` — voice invites must include the invitee's phone number.
|
|
350
355
|
- `expectedExternalUserId must be in E.164 format` — the phone number must start with `+` followed by country code and number (e.g., `+15551234567`).
|
|
356
|
+
- `friendName is required for voice invites` — voice invites must include the invitee's display name.
|
|
357
|
+
- `guardianName is required for voice invites` — voice invites must include the guardian's display name.
|
|
351
358
|
- `Invite not found or already revoked` — the invite ID may be invalid or the invite is already revoked.
|
|
352
359
|
|
|
353
360
|
## Typical Workflows
|
|
@@ -6,7 +6,26 @@ includes: ["public-ingress"]
|
|
|
6
6
|
metadata: {"vellum": {"emoji": "\ud83d\udcf1"}}
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
You are helping your user configure Twilio for voice calls and SMS messaging. Twilio is the shared telephony provider for both the **phone-calls** and **SMS messaging** capabilities. When this skill is invoked, walk through each step below using the
|
|
9
|
+
You are helping your user configure Twilio for voice calls and SMS messaging. Twilio is the shared telephony provider for both the **phone-calls** and **SMS messaging** capabilities. When this skill is invoked, walk through each step below using the Twilio HTTP control-plane endpoints and existing tools.
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
15
|
+
# 1. Check current status
|
|
16
|
+
curl -s "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/config" \
|
|
17
|
+
-H "Authorization: Bearer $TOKEN"
|
|
18
|
+
# 2. Store credentials (after collecting via credential_store prompt)
|
|
19
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/credentials" \
|
|
20
|
+
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
21
|
+
-d '{"accountSid":"ACxxx","authToken":"xxx"}'
|
|
22
|
+
# 3. Provision or assign a number
|
|
23
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/numbers/provision" \
|
|
24
|
+
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
25
|
+
-d '{"country":"US","areaCode":"415"}'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
For voice call setup after Twilio is configured, use `phone-calls` + `call_start`.
|
|
10
29
|
|
|
11
30
|
## Overview
|
|
12
31
|
|
|
@@ -16,42 +35,40 @@ This skill manages the full Twilio lifecycle:
|
|
|
16
35
|
- **Phone number assignment** — Assign an existing Twilio number to the assistant
|
|
17
36
|
- **Status checking** — Verify credentials and assigned number
|
|
18
37
|
|
|
19
|
-
All operations go through the
|
|
38
|
+
All operations go through the Twilio HTTP control-plane endpoints on the gateway, which validates inputs, stores credentials securely, and manages phone number state.
|
|
20
39
|
|
|
21
40
|
### Multi-Assistant Setups
|
|
22
41
|
|
|
23
|
-
In a multi-assistant environment (multiple assistants sharing the same daemon), some
|
|
42
|
+
In a multi-assistant environment (multiple assistants sharing the same daemon), some actions are **assistant-scoped** while others are **global** (shared across all assistants):
|
|
24
43
|
|
|
25
44
|
**Global actions** (ignore `assistantId` — credentials are shared across all assistants):
|
|
26
|
-
- `
|
|
27
|
-
- `
|
|
45
|
+
- `POST /v1/integrations/twilio/credentials` — Stores Account SID and Auth Token in global secure storage (`credential:twilio:*` keys). All assistants share the same Twilio account credentials.
|
|
46
|
+
- `DELETE /v1/integrations/twilio/credentials` — Removes the globally stored Account SID and Auth Token. This affects all assistants.
|
|
28
47
|
|
|
29
|
-
**Assistant-scoped actions** (use `assistantId` to scope phone number configuration per assistant):
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
32
|
-
- `
|
|
33
|
-
- `
|
|
48
|
+
**Assistant-scoped actions** (use `assistantId` query parameter to scope phone number configuration per assistant):
|
|
49
|
+
- `GET /v1/integrations/twilio/config` — Returns the phone number assigned to the specified assistant (falls back to the legacy global number if no per-assistant mapping exists).
|
|
50
|
+
- `POST /v1/integrations/twilio/numbers/assign` — Assigns a phone number to a specific assistant via the per-assistant mapping.
|
|
51
|
+
- `POST /v1/integrations/twilio/numbers/provision` — Provisions a new number and assigns it to the specified assistant.
|
|
52
|
+
- `GET /v1/integrations/twilio/numbers` — Lists all phone numbers on the shared Twilio account (uses global credentials).
|
|
34
53
|
|
|
35
|
-
Include `assistantId` in assistant-scoped
|
|
54
|
+
Include `assistantId` as a query parameter in assistant-scoped requests whenever:
|
|
36
55
|
- Multiple assistants share the same Twilio account but use different phone numbers
|
|
37
56
|
- You want to ensure configuration changes only affect a specific assistant
|
|
38
57
|
- The user has explicitly selected or referenced a particular assistant
|
|
39
58
|
|
|
40
|
-
All
|
|
59
|
+
All HTTP examples below include the optional `assistantId` query parameter in assistant-scoped requests. Omit it in single-assistant setups. For global actions (credentials), the `assistantId` parameter is accepted but ignored.
|
|
41
60
|
|
|
42
61
|
## Step 1: Check Current Configuration
|
|
43
62
|
|
|
44
|
-
First, check whether Twilio is already configured
|
|
63
|
+
First, check whether Twilio is already configured:
|
|
45
64
|
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"assistantId": "<optional — omit for single-assistant setups>"
|
|
51
|
-
}
|
|
65
|
+
```bash
|
|
66
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
67
|
+
curl -s "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/config" \
|
|
68
|
+
-H "Authorization: Bearer $TOKEN"
|
|
52
69
|
```
|
|
53
70
|
|
|
54
|
-
The
|
|
71
|
+
The response includes:
|
|
55
72
|
- `hasCredentials` — whether Account SID and Auth Token are stored
|
|
56
73
|
- `phoneNumber` — the currently assigned phone number (if any)
|
|
57
74
|
|
|
@@ -71,20 +88,19 @@ If credentials are not yet stored, guide the user through Twilio account setup:
|
|
|
71
88
|
- Call `credential_store` with `action: "prompt"`, `service: "twilio"`, `field: "account_sid"`, `label: "Twilio Account SID"`, `description: "Enter your Account SID from the Twilio Console dashboard"`, and `placeholder: "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"`.
|
|
72
89
|
- Call `credential_store` with `action: "prompt"`, `service: "twilio"`, `field: "auth_token"`, `label: "Twilio Auth Token"`, `description: "Enter your Auth Token from the Twilio Console dashboard"`, and `placeholder: "your_auth_token"`.
|
|
73
90
|
|
|
74
|
-
After both credentials are collected, retrieve them from secure storage and
|
|
91
|
+
After both credentials are collected, retrieve them from secure storage and send them to the gateway:
|
|
75
92
|
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
}
|
|
93
|
+
```bash
|
|
94
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
95
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/credentials" \
|
|
96
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
97
|
+
-H "Content-Type: application/json" \
|
|
98
|
+
-d '{"accountSid":"<value from credential_store for twilio/account_sid>","authToken":"<value from credential_store for twilio/auth_token>"}'
|
|
83
99
|
```
|
|
84
100
|
|
|
85
|
-
Both `accountSid` and `authToken` are required — the
|
|
101
|
+
Both `accountSid` and `authToken` are required — the endpoint validates the credentials against the Twilio API before storing them. If credentials are invalid, the response returns an error. Tell the user and ask them to re-enter via the secure prompt.
|
|
86
102
|
|
|
87
|
-
**Note:**
|
|
103
|
+
**Note:** Setting credentials is a global operation — credentials are stored once and shared across all assistants. The `assistantId` parameter is accepted but ignored.
|
|
88
104
|
|
|
89
105
|
## Step 3: Get a Phone Number
|
|
90
106
|
|
|
@@ -92,24 +108,22 @@ The assistant needs a phone number to make calls and send SMS. There are two pat
|
|
|
92
108
|
|
|
93
109
|
### Option A: Provision a New Number
|
|
94
110
|
|
|
95
|
-
If the user wants to buy a new number through Twilio
|
|
111
|
+
If the user wants to buy a new number through Twilio:
|
|
96
112
|
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"country":
|
|
103
|
-
"assistantId": "<optional — omit for single-assistant setups>"
|
|
104
|
-
}
|
|
113
|
+
```bash
|
|
114
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
115
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/numbers/provision" \
|
|
116
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
117
|
+
-H "Content-Type: application/json" \
|
|
118
|
+
-d '{"country":"US","areaCode":"415"}'
|
|
105
119
|
```
|
|
106
120
|
|
|
107
121
|
- `areaCode` is optional — ask the user if they have a preferred area code
|
|
108
122
|
- `country` defaults to `"US"` — ask if they want a different country (ISO 3166-1 alpha-2)
|
|
109
123
|
|
|
110
|
-
The
|
|
124
|
+
The endpoint provisions the number via the Twilio API, automatically assigns it to the assistant (persisting to both secure storage and config), and configures Twilio webhooks (voice, status callback, SMS) if a public ingress URL is available. The response includes the new `phoneNumber`. No separate assign call is needed.
|
|
111
125
|
|
|
112
|
-
**Webhook auto-configuration:** When `ingress.publicBaseUrl` is configured, the
|
|
126
|
+
**Webhook auto-configuration:** When `ingress.publicBaseUrl` is configured, the endpoint automatically sets the following webhooks on the Twilio phone number:
|
|
113
127
|
- Voice webhook: `{publicBaseUrl}/webhooks/twilio/voice`
|
|
114
128
|
- Voice status callback: `{publicBaseUrl}/webhooks/twilio/status`
|
|
115
129
|
- SMS webhook: `{publicBaseUrl}/webhooks/twilio/sms`
|
|
@@ -122,28 +136,25 @@ If ingress is not yet configured, webhook setup is skipped gracefully — the nu
|
|
|
122
136
|
|
|
123
137
|
If the user already has a Twilio phone number, first list available numbers:
|
|
124
138
|
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
"
|
|
129
|
-
"assistantId": "<optional — omit for single-assistant setups>"
|
|
130
|
-
}
|
|
139
|
+
```bash
|
|
140
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
141
|
+
curl -s "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/numbers" \
|
|
142
|
+
-H "Authorization: Bearer $TOKEN"
|
|
131
143
|
```
|
|
132
144
|
|
|
133
145
|
The response includes a `numbers` array with each number's `phoneNumber`, `friendlyName`, and `capabilities` (voice, SMS). Present these to the user and let them choose.
|
|
134
146
|
|
|
135
147
|
Then assign the chosen number:
|
|
136
148
|
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
}
|
|
149
|
+
```bash
|
|
150
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
151
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/numbers/assign" \
|
|
152
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
153
|
+
-H "Content-Type: application/json" \
|
|
154
|
+
-d '{"phoneNumber":"+14155551234"}'
|
|
144
155
|
```
|
|
145
156
|
|
|
146
|
-
The phone number must be in E.164 format. Like
|
|
157
|
+
The phone number must be in E.164 format. Like provisioning, assigning also auto-configures Twilio webhooks when a public ingress URL is available.
|
|
147
158
|
|
|
148
159
|
### Option C: Manual Entry
|
|
149
160
|
|
|
@@ -153,15 +164,14 @@ If the user wants to enter a number directly (e.g., they know it already), store
|
|
|
153
164
|
credential_store action=store service=twilio field=phone_number value=+14155551234
|
|
154
165
|
```
|
|
155
166
|
|
|
156
|
-
Then assign it through the
|
|
167
|
+
Then assign it through the gateway:
|
|
157
168
|
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"
|
|
164
|
-
}
|
|
169
|
+
```bash
|
|
170
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
171
|
+
curl -s -X POST "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/numbers/assign" \
|
|
172
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
173
|
+
-H "Content-Type: application/json" \
|
|
174
|
+
-d '{"phoneNumber":"+14155551234"}'
|
|
165
175
|
```
|
|
166
176
|
|
|
167
177
|
## Step 4: Set Up Public Ingress
|
|
@@ -187,11 +197,17 @@ skill_load skill=public-ingress
|
|
|
187
197
|
- ConversationRelay WebSocket: `{publicBaseUrl}/webhooks/twilio/relay` (wss://)
|
|
188
198
|
- SMS webhook: `{publicBaseUrl}/webhooks/twilio/sms`
|
|
189
199
|
|
|
190
|
-
Webhook URLs are automatically configured on the Twilio phone number when
|
|
200
|
+
Webhook URLs are automatically configured on the Twilio phone number when provisioning or assigning a number with a valid ingress URL. No manual Twilio Console webhook configuration is needed.
|
|
191
201
|
|
|
192
202
|
## Step 5: Verify Setup
|
|
193
203
|
|
|
194
|
-
After configuration, verify by
|
|
204
|
+
After configuration, verify by checking the config endpoint again.
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
208
|
+
curl -s "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/config" \
|
|
209
|
+
-H "Authorization: Bearer $TOKEN"
|
|
210
|
+
```
|
|
195
211
|
|
|
196
212
|
Confirm:
|
|
197
213
|
- `hasCredentials` is `true`
|
|
@@ -251,18 +267,17 @@ SMS is available automatically once Twilio is configured — no additional featu
|
|
|
251
267
|
|
|
252
268
|
## Clearing Credentials
|
|
253
269
|
|
|
254
|
-
If the user wants to disconnect Twilio
|
|
270
|
+
If the user wants to disconnect Twilio:
|
|
255
271
|
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
"
|
|
260
|
-
}
|
|
272
|
+
```bash
|
|
273
|
+
TOKEN=$(cat ~/.vellum/http-token)
|
|
274
|
+
curl -s -X DELETE "$INTERNAL_GATEWAY_BASE_URL/v1/integrations/twilio/credentials" \
|
|
275
|
+
-H "Authorization: Bearer $TOKEN"
|
|
261
276
|
```
|
|
262
277
|
|
|
263
278
|
This removes the stored Account SID and Auth Token. Phone number assignments are preserved. Voice calls and SMS will stop working until credentials are reconfigured.
|
|
264
279
|
|
|
265
|
-
**Note:**
|
|
280
|
+
**Note:** Clearing credentials is a global operation — it removes credentials for all assistants, not just the current one. The `assistantId` parameter is accepted but ignored. In multi-assistant setups, warn the user that clearing credentials will affect all assistants sharing this Twilio account.
|
|
266
281
|
|
|
267
282
|
## Troubleshooting
|
|
268
283
|
|
|
@@ -284,5 +299,5 @@ Run Step 3 to provision or assign a phone number.
|
|
|
284
299
|
|
|
285
300
|
### "Number not found" when assigning
|
|
286
301
|
- The number must be owned by the same Twilio account
|
|
287
|
-
- Use
|
|
302
|
+
- Use the list numbers endpoint to see available numbers
|
|
288
303
|
- Ensure the number is in E.164 format (`+` followed by country code and number)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildPointerGenerationPrompt,
|
|
3
|
+
getPointerFallbackMessage,
|
|
4
|
+
includesRequiredFacts,
|
|
5
|
+
POINTER_COPY_MAX_TOKENS,
|
|
6
|
+
POINTER_COPY_SYSTEM_PROMPT,
|
|
7
|
+
POINTER_COPY_TIMEOUT_MS,
|
|
8
|
+
} from '../calls/call-pointer-message-composer.js';
|
|
9
|
+
import { loadConfig } from '../config/loader.js';
|
|
10
|
+
import { getFailoverProvider } from '../providers/registry.js';
|
|
11
|
+
import type { PointerCopyGenerator } from '../runtime/http-types.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create the daemon-owned pointer copy generator that resolves providers
|
|
15
|
+
* and calls `provider.sendMessage` to generate pointer message text.
|
|
16
|
+
* This keeps all provider awareness in the daemon lifecycle, away from
|
|
17
|
+
* the runtime composer.
|
|
18
|
+
*/
|
|
19
|
+
export function createPointerCopyGenerator(): PointerCopyGenerator {
|
|
20
|
+
return async (context, options = {}) => {
|
|
21
|
+
const config = loadConfig();
|
|
22
|
+
let provider;
|
|
23
|
+
try {
|
|
24
|
+
provider = getFailoverProvider(config.provider, config.providerOrder);
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const fallbackText = options.fallbackText?.trim() || getPointerFallbackMessage(context);
|
|
30
|
+
const requiredFacts = options.requiredFacts
|
|
31
|
+
?.map((f) => f.trim())
|
|
32
|
+
.filter((f) => f.length > 0);
|
|
33
|
+
const prompt = buildPointerGenerationPrompt(context, fallbackText, requiredFacts);
|
|
34
|
+
|
|
35
|
+
const response = await provider.sendMessage(
|
|
36
|
+
[{ role: 'user', content: [{ type: 'text', text: prompt }] }],
|
|
37
|
+
[],
|
|
38
|
+
POINTER_COPY_SYSTEM_PROMPT,
|
|
39
|
+
{
|
|
40
|
+
config: {
|
|
41
|
+
max_tokens: options.maxTokens ?? POINTER_COPY_MAX_TOKENS,
|
|
42
|
+
modelIntent: 'latency-optimized',
|
|
43
|
+
},
|
|
44
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? POINTER_COPY_TIMEOUT_MS),
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const block = response.content.find((entry) => entry.type === 'text');
|
|
49
|
+
const text = block && 'text' in block ? block.text.trim() : '';
|
|
50
|
+
if (!text) return null;
|
|
51
|
+
const cleaned = text
|
|
52
|
+
.replace(/^["'`]+/, '')
|
|
53
|
+
.replace(/["'`]+$/, '')
|
|
54
|
+
.trim();
|
|
55
|
+
if (!cleaned) return null;
|
|
56
|
+
if (!includesRequiredFacts(cleaned, requiredFacts)) return null;
|
|
57
|
+
return cleaned;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -79,7 +79,7 @@ export class ComputerUseSession {
|
|
|
79
79
|
private pendingSurfaceActions = new Map<string, {
|
|
80
80
|
resolve: (result: ToolExecutionResult) => void;
|
|
81
81
|
}>();
|
|
82
|
-
private surfaceState = new Map<string, { surfaceType: SurfaceType; data: SurfaceData }>();
|
|
82
|
+
private surfaceState = new Map<string, { surfaceType: SurfaceType; data: SurfaceData; title?: string }>();
|
|
83
83
|
private terminalNotified = false;
|
|
84
84
|
private prompter: PermissionPrompter | null = null;
|
|
85
85
|
|
|
@@ -337,7 +337,7 @@ export class ComputerUseSession {
|
|
|
337
337
|
const awaitAction = (input.await_action as boolean) ?? isInteractive;
|
|
338
338
|
|
|
339
339
|
// Track surface state for ui_update merging
|
|
340
|
-
this.surfaceState.set(surfaceId, { surfaceType, data });
|
|
340
|
+
this.surfaceState.set(surfaceId, { surfaceType, data, title });
|
|
341
341
|
|
|
342
342
|
this.sendToClient({
|
|
343
343
|
type: 'ui_surface_show',
|
|
@@ -532,9 +532,6 @@ export class ComputerUseSession {
|
|
|
532
532
|
maxTokens: 4096,
|
|
533
533
|
maxInputTokens: cuConfig.contextWindow.maxInputTokens,
|
|
534
534
|
toolChoice: { type: 'any' },
|
|
535
|
-
// Allow MAX_STEPS non-terminal actions plus one terminal turn
|
|
536
|
-
// (computer_use_done/computer_use_respond), since AgentLoop caps tool turns globally.
|
|
537
|
-
maxToolUseTurns: MAX_STEPS + 1,
|
|
538
535
|
},
|
|
539
536
|
toolDefs,
|
|
540
537
|
toolExecutor,
|