@opencomputer/blue 0.0.3 → 0.0.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/README.md +61 -13
- package/dist/auth/cli-auth.d.ts +1 -0
- package/dist/auth/cli-auth.js +1 -1
- package/dist/auth/cli-auth.js.map +1 -1
- package/dist/channels/composio.d.ts +32 -0
- package/dist/channels/composio.js +149 -0
- package/dist/channels/composio.js.map +1 -0
- package/dist/cli/index.js +69 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/core/artifact.d.ts +1 -0
- package/dist/core/artifact.js +18 -0
- package/dist/core/artifact.js.map +1 -1
- package/dist/dev/local-control-plane.d.ts +2 -0
- package/dist/dev/local-control-plane.js +16 -0
- package/dist/dev/local-control-plane.js.map +1 -1
- package/dist/dev/manager.js +16 -0
- package/dist/dev/manager.js.map +1 -1
- package/dist/landing/agent.d.ts +12 -0
- package/dist/landing/agent.js +122 -0
- package/dist/landing/agent.js.map +1 -0
- package/dist/protocol.d.ts +27 -0
- package/dist/protocol.js.map +1 -1
- package/dist/sdk/client.d.ts +4 -1
- package/dist/sdk/client.js +14 -0
- package/dist/sdk/client.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ control-plane contract:
|
|
|
14
14
|
and hibernating WebSockets;
|
|
15
15
|
- WorkOS device authentication for the hosted CLI;
|
|
16
16
|
- a Blue model gateway that keeps the platform OpenRouter key server-side;
|
|
17
|
+
- managed remote Slack connections through Composio Connect Links and triggers;
|
|
17
18
|
- sub-second content-addressed agent artifacts on a generic Lambda MicroVM
|
|
18
19
|
runtime image;
|
|
19
20
|
- an AccountDO registry for agents, immutable deployments, and aliases;
|
|
@@ -153,12 +154,40 @@ messages, and updates the status with reasoning and tool activity. The final
|
|
|
153
154
|
reply clears the indicator automatically. Each Slack thread maps to one
|
|
154
155
|
persistent local Blue session, with the mapping stored under `.blue/dev/`.
|
|
155
156
|
|
|
156
|
-
The HTTP Events API remains available as a fallback. Set
|
|
157
|
+
The HTTP Events API remains available as a local fallback. Set
|
|
157
158
|
`SLACK_SIGNING_SECRET` and `SLACK_BOT_TOKEN`, expose the webhook printed by
|
|
158
159
|
`blue dev`, and configure it as the Slack app's Events API request URL.
|
|
159
160
|
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
### Remote Slack
|
|
162
|
+
|
|
163
|
+
Remote agents use Composio's managed Slack app. Slack credentials stay in
|
|
164
|
+
Composio; Blue stores only the connected-account and trigger IDs. First declare
|
|
165
|
+
Slack in the agent and deploy it:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
blue channels add slack
|
|
169
|
+
blue deploy
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`blue deploy` prints the agent's hosted landing page. Connect one Slack channel
|
|
173
|
+
using its Slack channel ID:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
blue channels connect slack --channel C0123456789
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The CLI opens a hosted Composio Connect Link. Complete Slack authorization,
|
|
180
|
+
invite the managed app to the selected channel when Slack requires it, then
|
|
181
|
+
send a message there. Each Slack thread maps to one persistent remote Blue
|
|
182
|
+
session. Blue resumes that session's MicroVM for later turns, posts the answer
|
|
183
|
+
in the same thread, and suspends the MicroVM after delivery.
|
|
184
|
+
|
|
185
|
+
Inspect and remove managed connections with:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
blue channels list
|
|
189
|
+
blue channels disconnect slack <connection-id>
|
|
190
|
+
```
|
|
162
191
|
|
|
163
192
|
## Hosted Flow
|
|
164
193
|
|
|
@@ -183,8 +212,10 @@ boundary for agents, deployments, and sessions.
|
|
|
183
212
|
|
|
184
213
|
`blue deploy` builds the immutable agent artifact locally, requests a
|
|
185
214
|
platform-owned upload, uploads directly to the returned signed URL, and
|
|
186
|
-
registers the deployment.
|
|
187
|
-
|
|
215
|
+
registers the deployment. It also prints a public agent page with the exact CLI
|
|
216
|
+
and Slack interaction commands. Session create, resume, suspend, and terminate
|
|
217
|
+
call the Blue runtime service. The user machine does not require AWS
|
|
218
|
+
credentials.
|
|
188
219
|
|
|
189
220
|
### Service configuration
|
|
190
221
|
|
|
@@ -193,6 +224,8 @@ The hosted Worker requires:
|
|
|
193
224
|
- `BLUE_WORKOS_CLIENT_ID` and optionally `BLUE_WORKOS_ISSUER` /
|
|
194
225
|
`BLUE_WORKOS_JWKS_URL`;
|
|
195
226
|
- `OPENROUTER_API_KEY` as a Worker secret;
|
|
227
|
+
- `COMPOSIO_API_KEY`, `COMPOSIO_SLACK_AUTH_CONFIG_ID`, and
|
|
228
|
+
`COMPOSIO_WEBHOOK_SECRET` as Worker secrets;
|
|
196
229
|
- `BLUE_RUNTIME_IMAGE_ARN` and `BLUE_RUNTIME_IMAGE_VERSION`;
|
|
197
230
|
- a `DEPLOYMENTS` service binding that returns signed platform artifact
|
|
198
231
|
uploads;
|
|
@@ -211,8 +244,24 @@ npx wrangler secret put BLUE_RUNTIME_IMAGE_ARN \
|
|
|
211
244
|
--config wrangler.production.jsonc
|
|
212
245
|
npx wrangler secret put BLUE_RUNTIME_IMAGE_VERSION \
|
|
213
246
|
--config wrangler.production.jsonc
|
|
247
|
+
npx wrangler secret put COMPOSIO_API_KEY \
|
|
248
|
+
--config wrangler.production.jsonc
|
|
249
|
+
npx wrangler secret put COMPOSIO_SLACK_AUTH_CONFIG_ID \
|
|
250
|
+
--config wrangler.production.jsonc
|
|
251
|
+
npx wrangler secret put COMPOSIO_WEBHOOK_SECRET \
|
|
252
|
+
--config wrangler.production.jsonc
|
|
214
253
|
```
|
|
215
254
|
|
|
255
|
+
Create one Composio webhook subscription for the project:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
https://blue.opencomputer.dev/v1/webhooks/composio
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Enable `composio.trigger.message` and use the subscription's signing secret as
|
|
262
|
+
`COMPOSIO_WEBHOOK_SECRET`. Blue creates one
|
|
263
|
+
`SLACK_CHANNEL_MESSAGE_RECEIVED` trigger per connected agent/channel.
|
|
264
|
+
|
|
216
265
|
Configure the platform Worker's AWS secrets plus
|
|
217
266
|
`BLUE_AWS_REGION`, `BLUE_ARTIFACT_BUCKET`, `BLUE_EXECUTION_ROLE_ARN`,
|
|
218
267
|
`BLUE_NETWORK_CONNECTOR_ARN`, `BLUE_S3_FILESYSTEM_ID`, and
|
|
@@ -291,11 +340,10 @@ delivery phases are in [PLAN.md](./PLAN.md).
|
|
|
291
340
|
|
|
292
341
|
The standalone local control plane, WorkOS device login, token refresh,
|
|
293
342
|
tenant-isolated Durable Object routing, signed-upload API, runtime lifecycle
|
|
294
|
-
API,
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
remain subsequent milestones.
|
|
343
|
+
API, authenticated OpenRouter proxy, deployed Slack routing, and local/remote
|
|
344
|
+
agent landing pages are implemented.
|
|
345
|
+
|
|
346
|
+
The platform services own AWS credentials, signed S3 uploads, Lambda MicroVM
|
|
347
|
+
calls, and S3 Files access points. Versioned checkpoint replacement,
|
|
348
|
+
permissions, evals, cleanup, and the unified management dashboard remain
|
|
349
|
+
subsequent milestones.
|
package/dist/auth/cli-auth.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export interface BlueCredentials {
|
|
|
22
22
|
updatedAt: string;
|
|
23
23
|
}
|
|
24
24
|
export declare function credentialsPath(): string;
|
|
25
|
+
export declare function openBrowser(url: string): void;
|
|
25
26
|
export declare function readCredentials(): Promise<BlueCredentials | null>;
|
|
26
27
|
export declare function logout(): Promise<boolean>;
|
|
27
28
|
export declare function login(apiUrl?: string): Promise<BlueCredentials>;
|
package/dist/auth/cli-auth.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-auth.js","sourceRoot":"","sources":["../../src/auth/cli-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,EAAE,EACF,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,CAAC,MAAM,oBAAoB,GAAG,+BAA+B,CAAC;AAgDpE,SAAS,UAAU;IACjB,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACxD,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,CAAC,UAAU,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,YAAY,CAAI,QAAkB;IAC/C,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC/D,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,oCAAoC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,WAAW,IAAI,wBAAwB,SAAS,QAAQ,CAAC,GAAG,EAAE,CAC9H,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,MAAM,GACV,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YACvC,CAAC,CAAE,IAAgC;YACnC,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,OAAO,GACX,OAAO,MAAM,CAAC,iBAAiB,KAAK,QAAQ;YAC1C,CAAC,CAAC,MAAM,CAAC,iBAAiB;YAC1B,CAAC,CAAC,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ;gBAClC,CAAC,CAAC,MAAM,CAAC,OAAO;gBAChB,CAAC,CAAC,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;oBAChC,CAAC,CAAC,MAAM,CAAC,KAAK;oBACd,CAAC,CAAC,8BAA8B,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAS,CAAC;AACnB,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"cli-auth.js","sourceRoot":"","sources":["../../src/auth/cli-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface ComposioConfiguration {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
slackAuthConfigId: string;
|
|
4
|
+
webhookSecret: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ComposioLink {
|
|
7
|
+
connectedAccountId: string;
|
|
8
|
+
redirectUrl: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function composioUserId(accountId: string, connectionId: string): string;
|
|
11
|
+
export declare function parseComposioUserId(userId: string): {
|
|
12
|
+
accountId: string;
|
|
13
|
+
connectionId: string;
|
|
14
|
+
} | null;
|
|
15
|
+
export declare function createSlackLink(configuration: ComposioConfiguration, input: {
|
|
16
|
+
userId: string;
|
|
17
|
+
callbackUrl: string;
|
|
18
|
+
alias: string;
|
|
19
|
+
}): Promise<ComposioLink>;
|
|
20
|
+
export declare function createSlackTrigger(configuration: ComposioConfiguration, input: {
|
|
21
|
+
userId: string;
|
|
22
|
+
connectedAccountId: string;
|
|
23
|
+
channelId: string;
|
|
24
|
+
}): Promise<string>;
|
|
25
|
+
export declare function deleteSlackTrigger(configuration: ComposioConfiguration, triggerId: string): Promise<void>;
|
|
26
|
+
export declare function postSlackMessage(configuration: ComposioConfiguration, input: {
|
|
27
|
+
connectedAccountId: string;
|
|
28
|
+
channelId: string;
|
|
29
|
+
threadTimestamp: string;
|
|
30
|
+
text: string;
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
export declare function verifyComposioWebhook(payload: string, headers: Headers, secret: string, now?: number): Promise<boolean>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { isRecord } from "../protocol.js";
|
|
2
|
+
const COMPOSIO_API = "https://backend.composio.dev";
|
|
3
|
+
const SLACK_VERSION = "20260702_00";
|
|
4
|
+
function bytesToBase64(bytes) {
|
|
5
|
+
let binary = "";
|
|
6
|
+
for (const byte of bytes)
|
|
7
|
+
binary += String.fromCharCode(byte);
|
|
8
|
+
return btoa(binary);
|
|
9
|
+
}
|
|
10
|
+
function constantTimeEqual(left, right) {
|
|
11
|
+
const size = Math.max(left.length, right.length);
|
|
12
|
+
let difference = left.length ^ right.length;
|
|
13
|
+
for (let index = 0; index < size; index += 1) {
|
|
14
|
+
difference |=
|
|
15
|
+
(left.charCodeAt(index) || 0) ^ (right.charCodeAt(index) || 0);
|
|
16
|
+
}
|
|
17
|
+
return difference === 0;
|
|
18
|
+
}
|
|
19
|
+
async function request(configuration, path, init) {
|
|
20
|
+
const headers = new Headers(init.headers);
|
|
21
|
+
headers.set("content-type", "application/json");
|
|
22
|
+
headers.set("x-api-key", configuration.apiKey);
|
|
23
|
+
const response = await fetch(`${COMPOSIO_API}${path}`, {
|
|
24
|
+
...init,
|
|
25
|
+
headers,
|
|
26
|
+
});
|
|
27
|
+
const body = await response.json().catch(() => null);
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
const error = isRecord(body) && isRecord(body.error) ? body.error : body;
|
|
30
|
+
const message = isRecord(error) && typeof error.message === "string"
|
|
31
|
+
? error.message
|
|
32
|
+
: `Composio request failed with status ${String(response.status)}`;
|
|
33
|
+
throw new Error(message);
|
|
34
|
+
}
|
|
35
|
+
if (!isRecord(body))
|
|
36
|
+
throw new Error("Composio returned an invalid response");
|
|
37
|
+
return body;
|
|
38
|
+
}
|
|
39
|
+
export function composioUserId(accountId, connectionId) {
|
|
40
|
+
return `blue_${btoa(JSON.stringify({ accountId, connectionId }))
|
|
41
|
+
.replace(/\+/g, "-")
|
|
42
|
+
.replace(/\//g, "_")
|
|
43
|
+
.replace(/=+$/, "")}`;
|
|
44
|
+
}
|
|
45
|
+
export function parseComposioUserId(userId) {
|
|
46
|
+
if (!userId.startsWith("blue_"))
|
|
47
|
+
return null;
|
|
48
|
+
try {
|
|
49
|
+
const encoded = userId.slice(5).replace(/-/g, "+").replace(/_/g, "/");
|
|
50
|
+
const padded = encoded.padEnd(Math.ceil(encoded.length / 4) * 4, "=");
|
|
51
|
+
const parsed = JSON.parse(atob(padded));
|
|
52
|
+
return isRecord(parsed) &&
|
|
53
|
+
typeof parsed.accountId === "string" &&
|
|
54
|
+
typeof parsed.connectionId === "string"
|
|
55
|
+
? {
|
|
56
|
+
accountId: parsed.accountId,
|
|
57
|
+
connectionId: parsed.connectionId,
|
|
58
|
+
}
|
|
59
|
+
: null;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function createSlackLink(configuration, input) {
|
|
66
|
+
const body = await request(configuration, "/api/v3/connected_accounts/link", {
|
|
67
|
+
method: "POST",
|
|
68
|
+
body: JSON.stringify({
|
|
69
|
+
auth_config_id: configuration.slackAuthConfigId,
|
|
70
|
+
user_id: input.userId,
|
|
71
|
+
callback_url: input.callbackUrl,
|
|
72
|
+
alias: input.alias,
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
if (typeof body.connected_account_id !== "string" ||
|
|
76
|
+
typeof body.redirect_url !== "string") {
|
|
77
|
+
throw new Error("Composio did not return a Slack connection link");
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
connectedAccountId: body.connected_account_id,
|
|
81
|
+
redirectUrl: body.redirect_url,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export async function createSlackTrigger(configuration, input) {
|
|
85
|
+
const body = await request(configuration, "/api/v3.1/trigger_instances/SLACK_CHANNEL_MESSAGE_RECEIVED/upsert", {
|
|
86
|
+
method: "POST",
|
|
87
|
+
body: JSON.stringify({
|
|
88
|
+
user_id: input.userId,
|
|
89
|
+
connected_account_id: input.connectedAccountId,
|
|
90
|
+
trigger_config: {
|
|
91
|
+
channel_id: input.channelId,
|
|
92
|
+
message_type: "all",
|
|
93
|
+
},
|
|
94
|
+
toolkit_versions: { slack: SLACK_VERSION },
|
|
95
|
+
}),
|
|
96
|
+
});
|
|
97
|
+
const triggerId = typeof body.trigger_id === "string"
|
|
98
|
+
? body.trigger_id
|
|
99
|
+
: typeof body.id === "string"
|
|
100
|
+
? body.id
|
|
101
|
+
: isRecord(body.trigger) && typeof body.trigger.id === "string"
|
|
102
|
+
? body.trigger.id
|
|
103
|
+
: undefined;
|
|
104
|
+
if (!triggerId)
|
|
105
|
+
throw new Error("Composio did not return a trigger ID");
|
|
106
|
+
return triggerId;
|
|
107
|
+
}
|
|
108
|
+
export async function deleteSlackTrigger(configuration, triggerId) {
|
|
109
|
+
await request(configuration, `/api/v3.1/trigger_instances/manage/${encodeURIComponent(triggerId)}`, { method: "DELETE" });
|
|
110
|
+
}
|
|
111
|
+
export async function postSlackMessage(configuration, input) {
|
|
112
|
+
const body = await request(configuration, "/api/v3/tools/execute/SLACK_CHAT_POST_MESSAGE", {
|
|
113
|
+
method: "POST",
|
|
114
|
+
body: JSON.stringify({
|
|
115
|
+
connected_account_id: input.connectedAccountId,
|
|
116
|
+
version: SLACK_VERSION,
|
|
117
|
+
arguments: {
|
|
118
|
+
channel: input.channelId,
|
|
119
|
+
thread_ts: input.threadTimestamp,
|
|
120
|
+
text: input.text.slice(0, 35_000),
|
|
121
|
+
mrkdwn: true,
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
124
|
+
});
|
|
125
|
+
if (body.successful === false) {
|
|
126
|
+
throw new Error(typeof body.error === "string"
|
|
127
|
+
? body.error
|
|
128
|
+
: "Composio could not post the Slack reply");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export async function verifyComposioWebhook(payload, headers, secret, now = Date.now()) {
|
|
132
|
+
const webhookId = headers.get("webhook-id");
|
|
133
|
+
const timestamp = headers.get("webhook-timestamp");
|
|
134
|
+
const signatures = headers.get("webhook-signature");
|
|
135
|
+
if (!webhookId || !timestamp || !signatures)
|
|
136
|
+
return false;
|
|
137
|
+
const seconds = Number(timestamp);
|
|
138
|
+
if (!Number.isFinite(seconds) || Math.abs(now - seconds * 1_000) > 300_000) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
142
|
+
const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`${webhookId}.${timestamp}.${payload}`));
|
|
143
|
+
const expected = bytesToBase64(new Uint8Array(signature));
|
|
144
|
+
return signatures
|
|
145
|
+
.split(/\s+/)
|
|
146
|
+
.some((candidate) => candidate.startsWith("v1,") &&
|
|
147
|
+
constantTimeEqual(candidate.slice(3), expected));
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=composio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composio.js","sourceRoot":"","sources":["../../src/channels/composio.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
-
import { mkdirSync } from "node:fs";
|
|
3
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
4
4
|
import { basename, dirname, resolve } from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import { createInterface } from "node:readline/promises";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { DEFAULT_BLUE_API_URL, accessTokenFor, login, logout, readCredentials, } from "../auth/cli-auth.js";
|
|
8
|
+
import { DEFAULT_BLUE_API_URL, accessTokenFor, login, logout, openBrowser, readCredentials, } from "../auth/cli-auth.js";
|
|
9
9
|
import { addSlackChannel, findAgentRoot, initializeAgent, prepareAgent, } from "../core/agent.js";
|
|
10
10
|
import { buildAgentArtifact } from "../core/artifact.js";
|
|
11
11
|
import { findDevState, requestDevManager, startDevManager, } from "../dev/manager.js";
|
|
12
12
|
import { startLocalControlPlane } from "../dev/local-control-plane.js";
|
|
13
13
|
import { authenticateOpenRouter, readOpenRouterCredential, } from "../openrouter/auth.js";
|
|
14
|
+
import { agentLandingPath } from "../landing/agent.js";
|
|
14
15
|
import { BlueClient } from "../sdk/client.js";
|
|
15
16
|
const DEFAULT_EDGE = DEFAULT_BLUE_API_URL;
|
|
16
17
|
function argument(name) {
|
|
@@ -53,6 +54,9 @@ function hostedEdge() {
|
|
|
53
54
|
process.env.BLUE_EDGE_URL ??
|
|
54
55
|
DEFAULT_EDGE);
|
|
55
56
|
}
|
|
57
|
+
function builtInSlackChannel(agentRoot) {
|
|
58
|
+
return ["slack.ts", "slack.js"].some((file) => existsSync(resolve(agentRoot, "agent", "channels", file)));
|
|
59
|
+
}
|
|
56
60
|
function spawnRuntime(edge, sessionId, token, harness, directory) {
|
|
57
61
|
const usingTypescript = import.meta.url.endsWith(".ts");
|
|
58
62
|
const blueRuntimeDirectory = resolve(directory, ".blue");
|
|
@@ -507,14 +511,54 @@ async function deployAgent(edge) {
|
|
|
507
511
|
const deployment = await client.registerDeployment({
|
|
508
512
|
agentId: built.agentId,
|
|
509
513
|
alias,
|
|
514
|
+
channels: built.channels,
|
|
510
515
|
artifact: upload.artifact,
|
|
511
516
|
});
|
|
517
|
+
const identity = await client.whoami();
|
|
518
|
+
const agentUrl = new URL(agentLandingPath(identity.accountId, deployment.agentId), edge).toString();
|
|
512
519
|
process.stdout.write(`agent: ${deployment.agentId}\n` +
|
|
513
520
|
`deployment: ${deployment.id}\n` +
|
|
514
521
|
`alias: ${deployment.alias}\n` +
|
|
522
|
+
`url: ${agentUrl}\n` +
|
|
523
|
+
`channels: ${deployment.channels.join(", ") || "none"}\n` +
|
|
515
524
|
`artifact: s3://${deployment.artifact.bucket}/${deployment.artifact.key}\n` +
|
|
516
525
|
`ready in: ${String(built.elapsedMs)}ms\n`);
|
|
517
526
|
}
|
|
527
|
+
async function connectRemoteSlack(edge) {
|
|
528
|
+
const channelId = argument("channel");
|
|
529
|
+
if (!channelId) {
|
|
530
|
+
throw new Error("A Slack channel ID is required with --channel");
|
|
531
|
+
}
|
|
532
|
+
const agentId = argument("agent") ?? (await inferDeployedAgent());
|
|
533
|
+
if (!agentId) {
|
|
534
|
+
throw new Error("Run this inside an agent repository or pass --agent");
|
|
535
|
+
}
|
|
536
|
+
const result = await (await clientFor(edge)).createSlackConnection({
|
|
537
|
+
agentId,
|
|
538
|
+
channelId,
|
|
539
|
+
});
|
|
540
|
+
process.stdout.write(`connection: ${result.connection.id}\n` +
|
|
541
|
+
`agent: ${result.connection.agentId}@${result.connection.alias}\n` +
|
|
542
|
+
`channel: ${result.connection.channelId}\n` +
|
|
543
|
+
`Open ${result.redirectUrl}\n`);
|
|
544
|
+
openBrowser(result.redirectUrl);
|
|
545
|
+
}
|
|
546
|
+
async function listRemoteChannels(edge) {
|
|
547
|
+
const connections = await (await clientFor(edge)).listChannelConnections();
|
|
548
|
+
if (connections.length === 0) {
|
|
549
|
+
process.stdout.write("No channel connections.\n");
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
for (const connection of connections) {
|
|
553
|
+
process.stdout.write(`${connection.id} slack ${connection.status.padEnd(12)} ` +
|
|
554
|
+
`${connection.agentId}@${connection.alias} ${connection.channelId}\n`);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
async function disconnectRemoteSlack(edge, connectionId) {
|
|
558
|
+
const connection = await (await clientFor(edge)).disconnectSlack(connectionId);
|
|
559
|
+
process.stdout.write(`disconnected: ${connection.id}\n` +
|
|
560
|
+
`agent: ${connection.agentId}@${connection.alias}\n`);
|
|
561
|
+
}
|
|
518
562
|
function printSession(session) {
|
|
519
563
|
const separator = session.deploymentId.lastIndexOf(":");
|
|
520
564
|
const deployment = separator >= 0
|
|
@@ -590,6 +634,8 @@ async function dev() {
|
|
|
590
634
|
"openrouter/anthropic/claude-sonnet-4.6";
|
|
591
635
|
const local = await startLocalControlPlane({
|
|
592
636
|
port,
|
|
637
|
+
agentId: prepared.name,
|
|
638
|
+
slackEnabled: builtInSlackChannel(prepared.root),
|
|
593
639
|
statePath: resolve(prepared.root, ".blue", "dev", "control-plane.json"),
|
|
594
640
|
openRouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
595
641
|
model: process.env.BLUE_MODEL,
|
|
@@ -637,6 +683,7 @@ async function demo() {
|
|
|
637
683
|
? Number.parseInt(requestedPort, 10)
|
|
638
684
|
: undefined,
|
|
639
685
|
statePath: resolve(".blue", "dev", "demo-control-plane.json"),
|
|
686
|
+
agentId: "demo",
|
|
640
687
|
openRouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
641
688
|
model: argument("model") ??
|
|
642
689
|
process.env.BLUE_MODEL ??
|
|
@@ -663,6 +710,9 @@ Usage:
|
|
|
663
710
|
blue run <prompt> [--agent <agent>@<alias>]
|
|
664
711
|
blue auth openrouter
|
|
665
712
|
blue channels add slack [--agent-dir path]
|
|
713
|
+
blue channels connect slack --channel C0123456789 [--agent agent@alias]
|
|
714
|
+
blue channels list
|
|
715
|
+
blue channels disconnect slack <connection-id>
|
|
666
716
|
blue deploy [--agent-dir path] [--alias production] [--edge URL]
|
|
667
717
|
blue remote <prompt> [--edge URL] [--api-key key] [--keep]
|
|
668
718
|
blue agents list
|
|
@@ -731,12 +781,24 @@ async function main() {
|
|
|
731
781
|
return;
|
|
732
782
|
}
|
|
733
783
|
if (command === "channels") {
|
|
734
|
-
const [action, channel] = positional(3);
|
|
735
|
-
if (action
|
|
736
|
-
|
|
784
|
+
const [action, channel, connectionId] = positional(3);
|
|
785
|
+
if (action === "add" && channel === "slack") {
|
|
786
|
+
process.stdout.write(`created: ${await addSlackChannel(argument("agent-dir") ?? process.cwd())}\n`);
|
|
787
|
+
return;
|
|
737
788
|
}
|
|
738
|
-
|
|
739
|
-
|
|
789
|
+
if (action === "connect" && channel === "slack") {
|
|
790
|
+
await connectRemoteSlack(hostedEdge());
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (action === "list") {
|
|
794
|
+
await listRemoteChannels(hostedEdge());
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
if (action === "disconnect" && channel === "slack" && connectionId) {
|
|
798
|
+
await disconnectRemoteSlack(hostedEdge(), connectionId);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
throw new Error("Use `blue channels add|connect|list|disconnect`");
|
|
740
802
|
}
|
|
741
803
|
if (command === "deploy") {
|
|
742
804
|
await deployAgent(hostedEdge());
|