@andreprado/agentkit 0.1.0-alpha.16 → 0.1.0-alpha.17
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 +8 -0
- package/docs/guides/add-channel.md +2 -0
- package/docs/guides/add-managed-composio.md +137 -0
- package/docs/guides/channels-production-handoff.md +1 -1
- package/docs/guides/connect-telegram.md +3 -1
- package/docs/guides/prepare-deploy.md +3 -1
- package/docs/llms-full.txt +13 -1
- package/docs/llms.txt +7 -0
- package/package.json +1 -1
- package/src/cli/commands/channels.ts +119 -7
- package/src/cli/commands/transcribe.ts +171 -0
- package/src/cli/deploy-readiness.ts +59 -3
- package/src/cli/help.ts +15 -0
- package/src/cli/index.ts +130 -0
- package/src/create-project.ts +4 -32
- package/src/index.ts +145 -0
- package/src/runtime/chat.ts +2 -1
- package/src/runtime/config.ts +129 -0
- package/src/runtime/core/manifest.ts +29 -2
- package/src/runtime/deploy-readiness.ts +31 -1
- package/src/runtime/inspect.ts +108 -4
- package/src/runtime/integrations/composio.ts +257 -0
- package/src/runtime/skills.ts +95 -0
- package/src/runtime/targets/cloudflare/build.ts +160 -5
- package/src/runtime/tool-runner.ts +2 -1
- package/src/templates/skills/agentkit-capsule/SKILL.md +1 -0
- package/src/templates/skills/agentkit-channels/SKILL.md +2 -0
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +3 -1
- package/src/templates/skills/agentkit-channels/references/telegram.md +3 -1
- package/src/templates/skills/agentkit-deploy/SKILL.md +1 -1
- package/src/templates/skills/agentkit-integrations/SKILL.md +66 -0
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +3 -2
package/README.md
CHANGED
|
@@ -37,6 +37,8 @@ agentkit tool <name> [--input <path-or-json>]
|
|
|
37
37
|
agentkit knowledge add <path-or-url>
|
|
38
38
|
agentkit knowledge sync
|
|
39
39
|
agentkit knowledge search <query> [--top-k <number>]
|
|
40
|
+
agentkit integrations status
|
|
41
|
+
agentkit integrations connect composio --toolkit gmail
|
|
40
42
|
agentkit spec init --brief <text>
|
|
41
43
|
agentkit db migrate
|
|
42
44
|
agentkit sync run
|
|
@@ -50,18 +52,24 @@ Knowledge indexes local `.md`, `.txt`, and `.csv` sources into the capsule datab
|
|
|
50
52
|
|
|
51
53
|
Every chat run receives dynamic runtime date context: current ISO timestamp, local date, weekday, local date/time, and timezone. Set `timeZone` in `agentkit.config.ts` for scheduling agents so relative dates like "today" and "next Friday" resolve in the right business/user timezone.
|
|
52
54
|
|
|
55
|
+
AgentKit-managed Composio is a paid hosted integration layer for per-agent connected apps. Configure it with `composioManaged({...})`, deploy with a `managed_composio` entitlement, then use `agentkit integrations connect composio --toolkit <slug>` to create hosted Connect Links. BYO Composio remains available through normal `defineTool` wrappers.
|
|
56
|
+
|
|
53
57
|
## Deploy Later
|
|
54
58
|
|
|
55
59
|
```sh
|
|
56
60
|
agentkit login --token <token>
|
|
57
61
|
agentkit deploy doctor
|
|
62
|
+
agentkit skills status
|
|
58
63
|
agentkit secret set OPENAI_API_KEY --from-local-env
|
|
59
64
|
agentkit deploy
|
|
60
65
|
agentkit deploy status
|
|
66
|
+
agentkit channels test support-telegram --message "hello"
|
|
67
|
+
agentkit transcribe smoke --provider groq
|
|
61
68
|
agentkit chat-ui --deploy
|
|
62
69
|
```
|
|
63
70
|
|
|
64
71
|
Production secrets are managed secrets, not committed `.env` values.
|
|
72
|
+
After upgrading AgentKit in an existing capsule, run `agentkit skills status` and `agentkit skills sync` if local agent-facing skills are stale.
|
|
65
73
|
Private hosted deploys automatically store a local chat/UI deploy access token at `.agentkit/chat-access-token.json`. `agentkit chat-ui --deploy` serves a local UI pointed at the hosted deploy without exposing that token to browser code.
|
|
66
74
|
|
|
67
75
|
The npm package contains the public CLI/runtime/client surface only. AgentKit Cloud's control-plane server, operator commands, Postgres store, and Cloudflare/Turso/R2 publisher live in the private repo workspace and are not part of the published package.
|
|
@@ -160,6 +160,8 @@ bun test
|
|
|
160
160
|
agentkit inspect
|
|
161
161
|
agentkit channels list
|
|
162
162
|
agentkit channels test support-telegram --message "hello"
|
|
163
|
+
agentkit channels test-audio support-telegram --fixture voice-note
|
|
164
|
+
agentkit transcribe smoke --provider groq
|
|
163
165
|
agentkit channels deliveries list support-telegram
|
|
164
166
|
agentkit channels buffers list support-telegram
|
|
165
167
|
```
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Add Managed Composio
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Enable AgentKit-managed Composio for one deployed agent so the agent can use explicitly allowed external app actions without the user owning Composio credentials.
|
|
6
|
+
|
|
7
|
+
Use BYO `defineTool` wrappers instead when the user wants to use their own Composio account/API key for free.
|
|
8
|
+
|
|
9
|
+
## Contract
|
|
10
|
+
|
|
11
|
+
Managed Composio is paid hosted AgentKit infrastructure:
|
|
12
|
+
|
|
13
|
+
- It works per agent/project, not per client.
|
|
14
|
+
- It requires an AgentKit Cloud account with `managed_composio`.
|
|
15
|
+
- AgentKit Cloud injects `COMPOSIO_API_KEY`; do not put it in `.env`, `.env.schema`, or `agentkit.config.ts`.
|
|
16
|
+
- AgentKit Cloud assigns the deployed Composio `user_id` from the account, project, agent, and integration name. The local inspect/build id is only a preview.
|
|
17
|
+
- The agent gets one generated tool, `agentkit_composio_execute`, only when explicit Composio action slugs are configured.
|
|
18
|
+
- Anonymous deploys cannot use managed Composio.
|
|
19
|
+
|
|
20
|
+
## Minimal Config
|
|
21
|
+
|
|
22
|
+
Edit `agentkit.config.ts`:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { composioManaged, defineAgent } from "@andreprado/agentkit";
|
|
26
|
+
|
|
27
|
+
export default defineAgent({
|
|
28
|
+
name: "acme-receptionist",
|
|
29
|
+
runtime: "edge",
|
|
30
|
+
provider: {
|
|
31
|
+
name: "test",
|
|
32
|
+
model: "fake",
|
|
33
|
+
},
|
|
34
|
+
instructions: "./prompts/instructions.md",
|
|
35
|
+
secrets: [],
|
|
36
|
+
tools: [],
|
|
37
|
+
integrations: [
|
|
38
|
+
composioManaged({
|
|
39
|
+
toolkits: ["gmail", "googlecalendar"],
|
|
40
|
+
tools: {
|
|
41
|
+
gmail: ["GMAIL_FETCH_EMAILS", "GMAIL_SEND_EMAIL"],
|
|
42
|
+
googlecalendar: ["GOOGLECALENDAR_CREATE_EVENT"],
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
],
|
|
46
|
+
access: {
|
|
47
|
+
mode: "private",
|
|
48
|
+
},
|
|
49
|
+
storage: {
|
|
50
|
+
driver: "agentkit",
|
|
51
|
+
database: {
|
|
52
|
+
driver: "turso",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Deploy
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
agentkit login --token agk_user_...
|
|
62
|
+
agentkit deploy doctor
|
|
63
|
+
agentkit deploy
|
|
64
|
+
agentkit integrations status
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Expected readiness:
|
|
68
|
+
|
|
69
|
+
- `cloudflare_deploy_alpha` is active.
|
|
70
|
+
- `managed_composio` is active.
|
|
71
|
+
- `COMPOSIO_API_KEY` appears as an AgentKit-managed secret, not a user-managed hosted secret.
|
|
72
|
+
|
|
73
|
+
## Connect Apps
|
|
74
|
+
|
|
75
|
+
After deploy, create a hosted Composio Connect Link:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
agentkit integrations connect composio --toolkit gmail
|
|
79
|
+
agentkit integrations connect composio --toolkit googlecalendar
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
AgentKit prints a URL. Send that URL to the person who owns the app account.
|
|
83
|
+
|
|
84
|
+
If the deploy has only one toolkit, `--toolkit` can be omitted.
|
|
85
|
+
|
|
86
|
+
## Operator Setup
|
|
87
|
+
|
|
88
|
+
Trusted AgentKit Cloud operators grant access and configure Composio auth configs:
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
npm run agentkit:operator -- accounts grant user@example.com --managed-composio
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Required control-plane environment:
|
|
95
|
+
|
|
96
|
+
```txt
|
|
97
|
+
AGENTKIT_SECRET_COMPOSIO_API_KEY=<project API key>
|
|
98
|
+
AGENTKIT_COMPOSIO_AUTH_CONFIG_GMAIL=<auth config id>
|
|
99
|
+
AGENTKIT_COMPOSIO_AUTH_CONFIG_GOOGLECALENDAR=<auth config id>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Use one `AGENTKIT_COMPOSIO_AUTH_CONFIG_<TOOLKIT>` value per toolkit slug, uppercased with non-alphanumeric characters converted to `_`.
|
|
103
|
+
|
|
104
|
+
## Verification
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
agentkit inspect
|
|
108
|
+
agentkit build --target cloudflare
|
|
109
|
+
agentkit deploy doctor
|
|
110
|
+
agentkit integrations status
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Expected:
|
|
114
|
+
|
|
115
|
+
- `inspect.integrations[0].provider` is `composio`.
|
|
116
|
+
- `inspect.tools` includes `agentkit_composio_execute` when allowed actions are configured.
|
|
117
|
+
- Build manifest includes `integrations`.
|
|
118
|
+
- Build manifest includes `COMPOSIO_API_KEY`.
|
|
119
|
+
- `deploy doctor` does not ask the user to set `COMPOSIO_API_KEY`.
|
|
120
|
+
|
|
121
|
+
## Troubleshooting
|
|
122
|
+
|
|
123
|
+
`managed_composio_entitlement_required`:
|
|
124
|
+
|
|
125
|
+
Log in with a paid AgentKit Cloud account that has `managed_composio`.
|
|
126
|
+
|
|
127
|
+
`managed_composio_auth_config_missing`:
|
|
128
|
+
|
|
129
|
+
An operator must set `AGENTKIT_COMPOSIO_AUTH_CONFIG_<TOOLKIT>` on the control plane.
|
|
130
|
+
|
|
131
|
+
`managed_composio_not_configured`:
|
|
132
|
+
|
|
133
|
+
An operator must set `AGENTKIT_SECRET_COMPOSIO_API_KEY` on the control plane.
|
|
134
|
+
|
|
135
|
+
`integration_toolkit_required`:
|
|
136
|
+
|
|
137
|
+
The deploy has multiple configured toolkits. Re-run connect with `--toolkit <slug>`.
|
|
@@ -67,7 +67,7 @@ Telegram channel URL: https://<deploy-host>/channels/support-telegram/telegram/t
|
|
|
67
67
|
Zapster channel URL: https://<deploy-host>/channels/support-whatsapp/whatsapp/zapster/webhook
|
|
68
68
|
Required provider webhook settings: Telegram setWebhook URL/secret token; Zapster webhook URL plus optional ZAPSTER_WEBHOOK_TOKEN query parameter
|
|
69
69
|
Required managed secrets: TELEGRAM_BOT_TOKEN, TELEGRAM_WEBHOOK_SECRET, ZAPSTER_API_KEY, ZAPSTER_INSTANCE_ID, ZAPSTER_WEBHOOK_ID
|
|
70
|
-
Smoke commands: agentkit channels doctor <name>; agentkit channels test <name> --message "hello"; agentkit channels deliveries list <name> --since 1h
|
|
70
|
+
Smoke commands: agentkit channels doctor <name>; agentkit channels test <name> --message "hello"; agentkit channels test-audio <name> --fixture voice-note for audio channels; agentkit transcribe smoke --provider groq for transcription; agentkit channels deliveries list <name> --since 1h
|
|
71
71
|
Rollback command: curl -X DELETE "$AGENTKIT_CLOUD_API_URL/v1/channels/<channel-id>" -H "Authorization: Bearer $AGENTKIT_CLOUD_API_TOKEN"; then remove provider webhook registration before rolling back the Worker
|
|
72
72
|
Known unverified items: any channel with no real provider inbound, no provider_sent outbound, stale buffers, or AGENTKIT_CHANNEL_SEND_DRY_RUN=1
|
|
73
73
|
```
|
|
@@ -141,6 +141,8 @@ Against AgentKit Cloud, `--apply` runs through the Cloud API and uses managed ho
|
|
|
141
141
|
```sh
|
|
142
142
|
agentkit channels status support-telegram
|
|
143
143
|
agentkit channels test support-telegram --message "hello"
|
|
144
|
+
agentkit channels test-audio support-telegram --fixture voice-note
|
|
145
|
+
agentkit transcribe smoke --provider groq
|
|
144
146
|
agentkit channels deliveries show <delivery-id>
|
|
145
147
|
```
|
|
146
148
|
|
|
@@ -165,4 +167,4 @@ The update is malformed or is not a supported private text message.
|
|
|
165
167
|
Set `GROQ_API_KEY` or the custom secret named in `transcription.secret` as a managed hosted secret.
|
|
166
168
|
|
|
167
169
|
`transcription_audio_format_unsupported`:
|
|
168
|
-
The configured transcription provider does not accept the Telegram file format. Use Groq for OGG/Opus voice notes in V1.
|
|
170
|
+
The configured transcription provider does not accept the Telegram file format. Use Groq for OGG/Opus voice notes in V1. `agentkit inspect` warns when a Telegram channel uses `audio.mode: "transcribe"` with OpenAI transcription.
|
|
@@ -192,7 +192,9 @@ Before a hosted production deploy, run:
|
|
|
192
192
|
npm run agentkit -- deploy doctor
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
-
The doctor checks AgentKit Cloud login, alpha deploy entitlement, online deploy capacity, declared hosted secrets, local `.env` names that have not been uploaded with `agentkit secret set`, and private-access runtime token handling. `agentkit deploy` runs the same readiness check automatically before building and uploading the artifact.
|
|
195
|
+
The doctor checks AgentKit Cloud login, Node version, alpha deploy entitlement, online deploy capacity, declared hosted secrets, local `.env` names that have not been uploaded with `npm run agentkit -- secret set`, and private-access runtime token handling. `agentkit deploy` runs the same readiness check automatically before building and uploading the artifact.
|
|
196
|
+
|
|
197
|
+
If the capsule configures `composioManaged({...})`, the doctor also checks the paid `managed_composio` entitlement. `COMPOSIO_API_KEY` is AgentKit-managed in this path; the user must not set it with `agentkit secret set`. Operators configure `AGENTKIT_SECRET_COMPOSIO_API_KEY` and per-toolkit `AGENTKIT_COMPOSIO_AUTH_CONFIG_<TOOLKIT>` values on the control plane.
|
|
196
198
|
|
|
197
199
|
`alpha_access_required`:
|
|
198
200
|
|
package/docs/llms-full.txt
CHANGED
|
@@ -56,8 +56,13 @@ agentkit channels add <website|telegram|whatsapp> <name> [--provider zapster|met
|
|
|
56
56
|
agentkit channels setup <name> [--apply] [--api <url>]
|
|
57
57
|
agentkit channels status <name> [--api <url>]
|
|
58
58
|
agentkit channels test <name> [--message <text>] [--fixture <path>] [--api <url>]
|
|
59
|
+
agentkit channels test-audio <name> [--fixture voice-note|audio-file|<path>] [--api <url>]
|
|
59
60
|
agentkit channels deliveries list <name> [--api <url>]
|
|
60
61
|
agentkit channels deliveries show <delivery-id> [--api <url>]
|
|
62
|
+
agentkit integrations status [--api <url>]
|
|
63
|
+
agentkit integrations connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]
|
|
64
|
+
agentkit skills status
|
|
65
|
+
agentkit skills sync
|
|
61
66
|
agentkit inspect
|
|
62
67
|
agentkit build [--target cloudflare|container]
|
|
63
68
|
agentkit login --token <token>
|
|
@@ -68,6 +73,7 @@ agentkit deploy smoke [--message <text>] [--api <url>]
|
|
|
68
73
|
agentkit deploy status
|
|
69
74
|
agentkit deploy pause
|
|
70
75
|
agentkit deploy resume
|
|
76
|
+
agentkit transcribe smoke [--provider test|openai|groq] [--model <model>] [--fixture <audio-file>]
|
|
71
77
|
agentkit secret set <NAME> <VALUE>
|
|
72
78
|
agentkit secret set <NAME> --stdin
|
|
73
79
|
agentkit secret set <NAME> --from-env [ENV_NAME]
|
|
@@ -93,6 +99,8 @@ agentkit help commands
|
|
|
93
99
|
|
|
94
100
|
Prefer `env set --stdin` or `--from-env` for local secret values, and prefer `secret set --stdin`, `--from-env`, or `--from-local-env` for hosted secrets. Inline `<VALUE>` forms exist for simple non-sensitive values, but agents should avoid putting secrets in shell history.
|
|
95
101
|
|
|
102
|
+
Managed Composio is configured with `composioManaged({...})` in `agentkit.config.ts` and is paid hosted AgentKit infrastructure. It requires a non-anonymous AgentKit Cloud deploy with `managed_composio`, uses one Composio settings profile per agent, injects `COMPOSIO_API_KEY` as an AgentKit-managed secret, and exposes the generated `agentkit_composio_execute` tool only for explicit configured action slugs. See `docs/guides/add-managed-composio.md`.
|
|
103
|
+
|
|
96
104
|
Planned commands described by the contract but not implemented yet:
|
|
97
105
|
|
|
98
106
|
```sh
|
|
@@ -398,11 +406,13 @@ agentkit channels list
|
|
|
398
406
|
agentkit channels add telegram support-telegram
|
|
399
407
|
agentkit channels setup support-telegram
|
|
400
408
|
agentkit channels test support-telegram --message "hello"
|
|
409
|
+
agentkit channels test-audio support-telegram --fixture voice-note
|
|
410
|
+
agentkit transcribe smoke --provider groq
|
|
401
411
|
agentkit channels deliveries list support-telegram
|
|
402
412
|
agentkit channels deliveries show <delivery-id>
|
|
403
413
|
```
|
|
404
414
|
|
|
405
|
-
`channels setup` is read-only by default. `channels setup <telegram-name> --apply` calls Telegram `setWebhook` and requires `TELEGRAM_BOT_TOKEN` plus `TELEGRAM_WEBHOOK_SECRET`.
|
|
415
|
+
`channels connect` creates or refreshes the channel resource, validates secrets, runs provider setup when supported, then runs the official synthetic smoke. `channels setup` is read-only by default. `channels setup <telegram-name> --apply` calls Telegram `setWebhook` and requires `TELEGRAM_BOT_TOKEN` plus `TELEGRAM_WEBHOOK_SECRET`.
|
|
406
416
|
|
|
407
417
|
Default tests are offline. Real provider smoke tests are opt-in:
|
|
408
418
|
|
|
@@ -796,6 +806,8 @@ Account/access flow:
|
|
|
796
806
|
agentkit secret set OPENAI_API_KEY --from-local-env
|
|
797
807
|
agentkit secret sync --from-local
|
|
798
808
|
agentkit secret list
|
|
809
|
+
agentkit skills status
|
|
810
|
+
agentkit skills sync
|
|
799
811
|
agentkit access token create website-chat --out .agentkit/website-chat-access-token.json
|
|
800
812
|
agentkit access token list
|
|
801
813
|
```
|
package/docs/llms.txt
CHANGED
|
@@ -16,6 +16,7 @@ Task guides:
|
|
|
16
16
|
- Build container artifact: `agentkit build --target container`
|
|
17
17
|
- Generate VPS handoff: `agentkit deploy --target vps --host agent.example.com --dry-run`
|
|
18
18
|
- Add hosted channels: `docs/guides/add-channel.md`
|
|
19
|
+
- Add AgentKit-managed Composio: `docs/guides/add-managed-composio.md`
|
|
19
20
|
- Buffer rapid channel messages: `docs/guides/add-channel.md#buffer-bursty-messages`
|
|
20
21
|
- Connect Telegram: `docs/guides/connect-telegram.md`
|
|
21
22
|
- Connect WhatsApp through Zapster: `docs/guides/connect-whatsapp-zapster.md`
|
|
@@ -48,7 +49,13 @@ agentkit channels add telegram support-telegram
|
|
|
48
49
|
agentkit channels setup support-telegram
|
|
49
50
|
agentkit channels status support-telegram
|
|
50
51
|
agentkit channels test support-telegram --message "hello"
|
|
52
|
+
agentkit channels test-audio support-telegram --fixture voice-note
|
|
53
|
+
agentkit transcribe smoke --provider groq
|
|
51
54
|
agentkit channels deliveries list support-telegram
|
|
55
|
+
agentkit integrations status
|
|
56
|
+
agentkit integrations connect composio --toolkit gmail
|
|
57
|
+
agentkit skills status
|
|
58
|
+
agentkit skills sync
|
|
52
59
|
agentkit login --token agk_user_...
|
|
53
60
|
agentkit deploy doctor
|
|
54
61
|
agentkit deploy --smoke "hello"
|
package/package.json
CHANGED
|
@@ -162,8 +162,10 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
|
|
|
162
162
|
let channel = created.channel;
|
|
163
163
|
printChannelStatus(channel);
|
|
164
164
|
printSecretRepairHint(channel);
|
|
165
|
+
console.log("Channel resource: created_or_updated");
|
|
165
166
|
|
|
166
167
|
if (hasMissingRequiredSecrets(channel)) {
|
|
168
|
+
console.log("Secrets: missing");
|
|
167
169
|
console.log("");
|
|
168
170
|
console.log("Connect blocked: set the missing managed secrets, then rerun this same command.");
|
|
169
171
|
console.log("Run: npm run agentkit -- secret sync --from-local");
|
|
@@ -171,31 +173,40 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
|
|
|
171
173
|
return;
|
|
172
174
|
}
|
|
173
175
|
|
|
176
|
+
console.log("Secrets: validated");
|
|
177
|
+
|
|
174
178
|
if (channel.type === "telegram") {
|
|
175
179
|
const setup = await applyTelegramWebhook(channel, args.flags.api);
|
|
176
180
|
channel = setup.channel ?? channel;
|
|
181
|
+
console.log("Telegram setWebhook: OK");
|
|
177
182
|
console.log("Telegram webhook confirmed.");
|
|
178
183
|
if (setup.setup?.get_webhook_info) {
|
|
179
184
|
console.log(`Telegram pending updates: ${setup.setup.get_webhook_info.pending_update_count}`);
|
|
180
185
|
}
|
|
181
186
|
|
|
182
|
-
const smoke = await runChannelSmoke(channel, args.flags.api, args.flags.message);
|
|
183
|
-
console.log(`Smoke: ${smoke.status}${smoke.delivery_id ? ` (${smoke.delivery_id})` : ""}`);
|
|
187
|
+
const smoke = await runConnectSmoke(() => runChannelSmoke(channel, args.flags.api, args.flags.message));
|
|
184
188
|
printTelegramHumanNextStep(channel.name, setup.setup?.bot_username);
|
|
189
|
+
if (!smoke) {
|
|
190
|
+
process.exitCode = 1;
|
|
191
|
+
}
|
|
185
192
|
return;
|
|
186
193
|
}
|
|
187
194
|
|
|
188
195
|
if (channel.type === "whatsapp" && channel.provider === "zapster") {
|
|
189
|
-
const smoke = await runChannelSmoke(channel, args.flags.api, args.flags.message);
|
|
190
|
-
console.log(`Webhook smoke: ${smoke.status}${smoke.delivery_id ? ` (${smoke.delivery_id})` : ""}`);
|
|
196
|
+
const smoke = await runConnectSmoke(() => runChannelSmoke(channel, args.flags.api, args.flags.message));
|
|
191
197
|
console.log(`Next human step: paste ${channel.webhook_url} into ${channel.provider}'s webhook settings.`);
|
|
198
|
+
if (!smoke) {
|
|
199
|
+
process.exitCode = 1;
|
|
200
|
+
}
|
|
192
201
|
} else if (channel.type === "whatsapp") {
|
|
193
202
|
console.log("Smoke: skipped until the provider webhook is configured.");
|
|
194
203
|
console.log(`Next human step: paste ${channel.webhook_url} into ${channel.provider}'s webhook settings.`);
|
|
195
204
|
} else {
|
|
196
|
-
const smoke = await runChannelSmoke(channel, args.flags.api, args.flags.message);
|
|
197
|
-
console.log(`Smoke: ${smoke.status}${smoke.delivery_id ? ` (${smoke.delivery_id})` : ""}`);
|
|
205
|
+
const smoke = await runConnectSmoke(() => runChannelSmoke(channel, args.flags.api, args.flags.message));
|
|
198
206
|
console.log(`Next human step: use ${channel.webhook_url} from your website client.`);
|
|
207
|
+
if (!smoke) {
|
|
208
|
+
process.exitCode = 1;
|
|
209
|
+
}
|
|
199
210
|
}
|
|
200
211
|
return;
|
|
201
212
|
}
|
|
@@ -274,6 +285,25 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
|
|
|
274
285
|
return;
|
|
275
286
|
}
|
|
276
287
|
|
|
288
|
+
if (subcommand === "test-audio") {
|
|
289
|
+
if (!first) {
|
|
290
|
+
throw new Error("Usage: agentkit channels test-audio <name> [--fixture voice-note|audio-file|<path>]");
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const channel = await resolveCloudChannelByName(first, args.flags.api);
|
|
294
|
+
const apiUrl = parseCloudApiUrl(args.flags.api);
|
|
295
|
+
const body = await channelAudioTestBody(channel, args.flags.fixture);
|
|
296
|
+
const signed = await runServerSignedChannelTest(channel, apiUrl, body);
|
|
297
|
+
const response = signed.response;
|
|
298
|
+
const payload = signed.payload;
|
|
299
|
+
|
|
300
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
301
|
+
if (!response.ok) {
|
|
302
|
+
process.exitCode = 1;
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
277
307
|
if (subcommand === "deliveries") {
|
|
278
308
|
if (first === "list") {
|
|
279
309
|
if (!second) {
|
|
@@ -367,7 +397,7 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
|
|
|
367
397
|
}
|
|
368
398
|
|
|
369
399
|
throw new Error(
|
|
370
|
-
"Usage: agentkit channels list | add | connect | setup | status | doctor | test | deliveries list | deliveries show | buffers list | buffers show | buffers flush | buffers clear | buffers retry",
|
|
400
|
+
"Usage: agentkit channels list | add | connect | setup | status | doctor | test | test-audio | deliveries list | deliveries show | buffers list | buffers show | buffers flush | buffers clear | buffers retry",
|
|
371
401
|
);
|
|
372
402
|
}
|
|
373
403
|
|
|
@@ -419,6 +449,20 @@ async function runChannelSmoke(
|
|
|
419
449
|
return { status: "unknown" };
|
|
420
450
|
}
|
|
421
451
|
|
|
452
|
+
async function runConnectSmoke(
|
|
453
|
+
run: () => Promise<{ status: string; delivery_id?: string }>,
|
|
454
|
+
): Promise<{ status: string; delivery_id?: string } | null> {
|
|
455
|
+
try {
|
|
456
|
+
const smoke = await run();
|
|
457
|
+
console.log(`Synthetic smoke: ${smoke.status}${smoke.delivery_id ? ` (${smoke.delivery_id})` : ""}`);
|
|
458
|
+
return smoke;
|
|
459
|
+
} catch (error) {
|
|
460
|
+
console.log("Synthetic smoke: failed");
|
|
461
|
+
console.log(` ${formatCommandError(error)}`);
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
422
466
|
async function runServerSignedChannelTest(
|
|
423
467
|
channel: CloudChannel,
|
|
424
468
|
apiUrl: string,
|
|
@@ -601,6 +645,10 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
601
645
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
602
646
|
}
|
|
603
647
|
|
|
648
|
+
function formatCommandError(error: unknown): string {
|
|
649
|
+
return error instanceof Error ? error.message : String(error);
|
|
650
|
+
}
|
|
651
|
+
|
|
604
652
|
async function readDeployStateIfExists(cwd: string): Promise<DeployState | null> {
|
|
605
653
|
return readLocalDeployStateIfExists(cwd);
|
|
606
654
|
}
|
|
@@ -974,6 +1022,70 @@ async function channelTestBody(
|
|
|
974
1022
|
});
|
|
975
1023
|
}
|
|
976
1024
|
|
|
1025
|
+
async function channelAudioTestBody(
|
|
1026
|
+
channel: CloudChannel,
|
|
1027
|
+
fixtureFlag: string | boolean | undefined,
|
|
1028
|
+
): Promise<string> {
|
|
1029
|
+
if (typeof fixtureFlag === "string" && isExplicitFixturePath(fixtureFlag)) {
|
|
1030
|
+
return readFile(resolve(process.cwd(), fixtureFlag), "utf8");
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
const fixture = typeof fixtureFlag === "string" ? fixtureFlag : "voice-note";
|
|
1034
|
+
|
|
1035
|
+
if (channel.type === "telegram") {
|
|
1036
|
+
if (fixture !== "voice-note" && fixture !== "telegram-voice-note" && fixture !== "telegram-audio-message") {
|
|
1037
|
+
throw new Error('Telegram audio smoke supports --fixture voice-note or --fixture telegram-voice-note.');
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
return JSON.stringify({
|
|
1041
|
+
update_id: Date.now(),
|
|
1042
|
+
message: {
|
|
1043
|
+
message_id: 1,
|
|
1044
|
+
date: Math.floor(Date.now() / 1000),
|
|
1045
|
+
chat: { id: 456, type: "private" },
|
|
1046
|
+
from: { id: 123, first_name: "AgentKit" },
|
|
1047
|
+
voice: {
|
|
1048
|
+
file_id: `agentkit_voice_${Date.now()}`,
|
|
1049
|
+
file_unique_id: `agentkit_voice_unique_${Date.now()}`,
|
|
1050
|
+
duration: 12,
|
|
1051
|
+
mime_type: "audio/ogg",
|
|
1052
|
+
file_size: 42,
|
|
1053
|
+
},
|
|
1054
|
+
},
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
if (channel.type === "whatsapp" && channel.provider === "zapster") {
|
|
1059
|
+
if (fixture !== "voice-note" && fixture !== "audio-file" && fixture !== "zapster-audio" && fixture !== "zapster-audio-message") {
|
|
1060
|
+
throw new Error('Zapster audio smoke supports --fixture voice-note, --fixture audio-file, or --fixture zapster-audio.');
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
return JSON.stringify({
|
|
1064
|
+
event_id: `zap_evt_audio_${Date.now()}`,
|
|
1065
|
+
instance_id: "local",
|
|
1066
|
+
message: {
|
|
1067
|
+
id: `wamid.audio.${Date.now()}`,
|
|
1068
|
+
from: "5511999999999",
|
|
1069
|
+
type: "audio",
|
|
1070
|
+
audio: {
|
|
1071
|
+
id: `media_audio_${Date.now()}`,
|
|
1072
|
+
url: `https://api.zapsterapi.com/media/audio/media_audio_${Date.now()}.ogg`,
|
|
1073
|
+
mime_type: "audio/ogg",
|
|
1074
|
+
duration: 12,
|
|
1075
|
+
file_size: 42,
|
|
1076
|
+
...(fixture === "voice-note" ? { ptt: "true" } : {}),
|
|
1077
|
+
},
|
|
1078
|
+
},
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
throw new Error(`Audio smoke is not supported for ${channel.type}/${channel.provider}.`);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
function isExplicitFixturePath(value: string): boolean {
|
|
1086
|
+
return value.includes("/") || value.startsWith(".") || value.endsWith(".json");
|
|
1087
|
+
}
|
|
1088
|
+
|
|
977
1089
|
function channelTestHeaders(channel: CloudChannel): Headers {
|
|
978
1090
|
const headers = new Headers({ "Content-Type": "application/json" });
|
|
979
1091
|
|