@usecontextlayer/cli 0.13.0 → 0.14.0
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/dist/{app-CRgSQabE.mjs → app-DUUpiXEm.mjs} +94 -2
- package/dist/app-DUUpiXEm.mjs.map +1 -0
- package/dist/cli.mjs +69 -43
- package/dist/cli.mjs.map +1 -1
- package/dist/template/public/slate.json +2 -1
- package/dist/vite.d.mts +1 -0
- package/dist/vite.mjs +2 -1
- package/dist/vite.mjs.map +1 -1
- package/package.json +3 -2
- package/dist/app-CRgSQabE.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { _ as
|
|
2
|
+
import { S as execa, _ as record, a as getAccessToken, b as url, c as whoami, d as boolean, f as discriminatedUnion, g as object, h as looseObject, i as secretNameSchema, l as env, m as literal, n as readLocalManifest, o as getCurrentUser, p as hostname, r as credentialModeSchema, s as login, t as getLocalAppId, u as array, v as string, x as uuid, y as unknown } from "./app-DUUpiXEm.mjs";
|
|
3
3
|
import { cp, readFile, writeFile } from "node:fs/promises";
|
|
4
4
|
import path, { join } from "node:path";
|
|
5
5
|
import { EventEmitter } from "node:events";
|
|
@@ -3004,7 +3004,34 @@ async function runLocalAgent(name, prompt) {
|
|
|
3004
3004
|
}
|
|
3005
3005
|
}
|
|
3006
3006
|
//#endregion
|
|
3007
|
+
//#region owner.ts
|
|
3008
|
+
const ownerOptionsSchema = object({ org: string().min(1).optional() });
|
|
3009
|
+
async function resolveOwner(org, headers) {
|
|
3010
|
+
if (!org) return {
|
|
3011
|
+
id: (await getCurrentUser(headers)).id,
|
|
3012
|
+
type: "user"
|
|
3013
|
+
};
|
|
3014
|
+
const response = await fetch(new URL("/api/platform/organizations", env.CTX_AUTH_ISSUER), { headers });
|
|
3015
|
+
if (!response.ok) throw new Error(`Organization lookup failed: HTTP ${response.status}`);
|
|
3016
|
+
const { organizations } = object({ organizations: array(object({
|
|
3017
|
+
id: string().min(1),
|
|
3018
|
+
slug: string()
|
|
3019
|
+
})) }).parse(await response.json());
|
|
3020
|
+
const organization = organizations.find((organization) => organization.slug === org);
|
|
3021
|
+
if (!organization) throw new Error("Organization is not in your memberships");
|
|
3022
|
+
return {
|
|
3023
|
+
id: organization.id,
|
|
3024
|
+
type: "organization"
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
function ownerPath(owner) {
|
|
3028
|
+
return `${owner.type === "organization" ? "org" : "user"}/${encodeURIComponent(owner.id)}`;
|
|
3029
|
+
}
|
|
3030
|
+
//#endregion
|
|
3007
3031
|
//#region connections.ts
|
|
3032
|
+
async function getLocalManifest(target) {
|
|
3033
|
+
return target === "local" ? readLocalManifest() : void 0;
|
|
3034
|
+
}
|
|
3008
3035
|
async function resolveAppTarget(target) {
|
|
3009
3036
|
if (target !== "local") return target;
|
|
3010
3037
|
return getLocalAppId();
|
|
@@ -3014,6 +3041,7 @@ async function assignAppConnection(target, slug, connectionId) {
|
|
|
3014
3041
|
const response = await fetch(new URL(`/api/apps/${encodeURIComponent(appTarget)}/connections/assign`, env.CTX_PLATFORM_URL), {
|
|
3015
3042
|
body: JSON.stringify({
|
|
3016
3043
|
connection_id: connectionId,
|
|
3044
|
+
manifest: await getLocalManifest(target),
|
|
3017
3045
|
slug
|
|
3018
3046
|
}),
|
|
3019
3047
|
headers: {
|
|
@@ -3031,7 +3059,7 @@ async function assignAppConnection(target, slug, connectionId) {
|
|
|
3031
3059
|
}
|
|
3032
3060
|
async function listAppConnections(target) {
|
|
3033
3061
|
const appTarget = await resolveAppTarget(target);
|
|
3034
|
-
const manifest =
|
|
3062
|
+
const manifest = await getLocalManifest(target);
|
|
3035
3063
|
const response = await fetch(new URL(`/api/apps/${encodeURIComponent(appTarget)}/connections/list`, env.CTX_PLATFORM_URL), {
|
|
3036
3064
|
body: JSON.stringify({ manifest }),
|
|
3037
3065
|
headers: {
|
|
@@ -3043,7 +3071,7 @@ async function listAppConnections(target) {
|
|
|
3043
3071
|
if (!response.ok) throw new Error(`App connections request failed: HTTP ${response.status}`);
|
|
3044
3072
|
const { connections } = object({ connections: array(object({
|
|
3045
3073
|
connection_id: string().nullable(),
|
|
3046
|
-
mode:
|
|
3074
|
+
mode: credentialModeSchema,
|
|
3047
3075
|
slug: string(),
|
|
3048
3076
|
toolkit: string()
|
|
3049
3077
|
})) }).parse(await response.json());
|
|
@@ -3056,22 +3084,26 @@ async function listAppConnections(target) {
|
|
|
3056
3084
|
connection: connection_id ?? "unassigned"
|
|
3057
3085
|
})));
|
|
3058
3086
|
}
|
|
3059
|
-
async function addConnection(toolkit) {
|
|
3060
|
-
const
|
|
3087
|
+
async function addConnection(toolkit, org) {
|
|
3088
|
+
const headers = { authorization: `Bearer ${await getAccessToken()}` };
|
|
3089
|
+
const owner = await resolveOwner(org, headers);
|
|
3090
|
+
const response = await fetch(new URL(`/api/connections/${ownerPath(owner)}`, env.CTX_PLATFORM_URL), {
|
|
3061
3091
|
body: JSON.stringify({ toolkit }),
|
|
3062
3092
|
headers: {
|
|
3063
|
-
|
|
3093
|
+
...headers,
|
|
3064
3094
|
"content-type": "application/json"
|
|
3065
3095
|
},
|
|
3066
3096
|
method: "POST"
|
|
3067
3097
|
});
|
|
3068
3098
|
if (!response.ok) throw new Error(`Connection authorization failed: HTTP ${response.status}`);
|
|
3069
3099
|
const { redirect_url } = object({ redirect_url: url() }).parse(await response.json());
|
|
3070
|
-
console.log(`Open this link to
|
|
3071
|
-
console.log(
|
|
3100
|
+
console.log(`Open this link to authorize the Owner's account:\n${redirect_url}`);
|
|
3101
|
+
console.log(`After authorization, run ctx connections${org ? ` --org ${org}` : ""} list to see the Owner's account.`);
|
|
3072
3102
|
}
|
|
3073
|
-
async function listConnections() {
|
|
3074
|
-
const
|
|
3103
|
+
async function listConnections(org) {
|
|
3104
|
+
const headers = { authorization: `Bearer ${await getAccessToken()}` };
|
|
3105
|
+
const owner = await resolveOwner(org, headers);
|
|
3106
|
+
const response = await fetch(new URL(`/api/connections/${ownerPath(owner)}`, env.CTX_PLATFORM_URL), { headers });
|
|
3075
3107
|
if (!response.ok) throw new Error(`Connection list failed: HTTP ${response.status}`);
|
|
3076
3108
|
const { connections } = object({ connections: array(object({
|
|
3077
3109
|
alias: string().nullable(),
|
|
@@ -3128,7 +3160,7 @@ async function gitCredential(operation) {
|
|
|
3128
3160
|
}
|
|
3129
3161
|
//#endregion
|
|
3130
3162
|
//#region package.json
|
|
3131
|
-
var version = "0.
|
|
3163
|
+
var version = "0.14.0";
|
|
3132
3164
|
//#endregion
|
|
3133
3165
|
//#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
3134
3166
|
const getCodePointsLength = (() => {
|
|
@@ -3819,40 +3851,29 @@ ${r ? styleText("cyan", S_BAR_END) : ""}
|
|
|
3819
3851
|
`${styleText("dim", "↑/↓")}`, `${styleText("dim", "Enter:")}`;
|
|
3820
3852
|
`${styleText("gray", S_BAR)}`;
|
|
3821
3853
|
//#endregion
|
|
3822
|
-
//#region
|
|
3823
|
-
const
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3854
|
+
//#region ../shared/dist/app-usage.mjs
|
|
3855
|
+
const ownerSchema = discriminatedUnion("type", [object({
|
|
3856
|
+
id: string().min(1),
|
|
3857
|
+
type: literal("user")
|
|
3858
|
+
}), object({
|
|
3859
|
+
id: string().min(1),
|
|
3860
|
+
type: literal("organization")
|
|
3861
|
+
})]);
|
|
3862
|
+
object({
|
|
3863
|
+
id: uuid(),
|
|
3864
|
+
owner: ownerSchema
|
|
3827
3865
|
});
|
|
3866
|
+
//#endregion
|
|
3867
|
+
//#region secrets.ts
|
|
3868
|
+
const secretOptionsSchema = ownerOptionsSchema.extend({ stdin: boolean().default(false) });
|
|
3828
3869
|
const valueSchema = string().min(1);
|
|
3829
3870
|
const confirmationSchema = object({
|
|
3830
3871
|
name: secretNameSchema,
|
|
3831
|
-
owner:
|
|
3832
|
-
id: string().min(1),
|
|
3833
|
-
type: _enum(["organization", "user"])
|
|
3834
|
-
})
|
|
3872
|
+
owner: ownerSchema
|
|
3835
3873
|
});
|
|
3836
3874
|
async function resolveSecretUrl(name, org, headers) {
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
if (org) {
|
|
3840
|
-
const url = new URL("/api/platform/organizations", env.CTX_AUTH_ISSUER);
|
|
3841
|
-
const response = await fetch(url, { headers });
|
|
3842
|
-
if (!response.ok) throw new Error(`Organization lookup failed: HTTP ${response.status}`);
|
|
3843
|
-
const { organizations } = object({ organizations: array(object({
|
|
3844
|
-
id: string().min(1),
|
|
3845
|
-
slug: string()
|
|
3846
|
-
})) }).parse(await response.json());
|
|
3847
|
-
const organization = organizations.find((organization) => organization.slug === org);
|
|
3848
|
-
if (!organization) throw new Error("Organization is not in your memberships");
|
|
3849
|
-
type = "org";
|
|
3850
|
-
id = organization.id;
|
|
3851
|
-
} else {
|
|
3852
|
-
id = (await getCurrentUser(headers)).id;
|
|
3853
|
-
type = "user";
|
|
3854
|
-
}
|
|
3855
|
-
return new URL(`/api/secrets/${type}/${encodeURIComponent(id)}/${encodeURIComponent(name)}`, env.CTX_PLATFORM_URL);
|
|
3875
|
+
const owner = await resolveOwner(org, headers);
|
|
3876
|
+
return new URL(`/api/secrets/${ownerPath(owner)}/${encodeURIComponent(name)}`, env.CTX_PLATFORM_URL);
|
|
3856
3877
|
}
|
|
3857
3878
|
async function setSecret(name, options) {
|
|
3858
3879
|
const headers = { authorization: `Bearer ${await getAccessToken()}` };
|
|
@@ -3997,13 +4018,18 @@ program.command("login").description("Sign in by approving a browser code and co
|
|
|
3997
4018
|
});
|
|
3998
4019
|
program.command("git-credential <operation>").description("Git credential helper using the saved login; invoked automatically by Git").action(gitCredential);
|
|
3999
4020
|
program.command("whoami").description("Show your ContextLayer user ID using the saved login").action(whoami);
|
|
4000
|
-
const connections = program.command("connections").description("Manage
|
|
4021
|
+
const connections = program.command("connections").description("Manage Owner-owned connected accounts or list an app's requirements").option("--org <org_slug>", "Manage this organization's connections; defaults to the signed-in user").argument("[target]", "AppID, public hostname, or local (run from the app root)").addArgument(new Argument("[operation]", "App connection operation").choices(["list"])).action(async (target, operation) => {
|
|
4001
4022
|
if (!target || !operation) connections.error("Expected: ctx connections <target> list");
|
|
4002
4023
|
await listAppConnections(target);
|
|
4003
4024
|
});
|
|
4004
|
-
connections.command("list").description("List
|
|
4005
|
-
|
|
4006
|
-
|
|
4025
|
+
connections.command("list").description("List the selected Owner's Composio accounts with their toolkit, identity, and status").action(async (_options, command) => {
|
|
4026
|
+
await listConnections(ownerOptionsSchema.parse(command.optsWithGlobals()).org);
|
|
4027
|
+
});
|
|
4028
|
+
connections.command("add <toolkit>").description("Print a Composio authorization link for the selected Owner's account (for example, gmail)").action(async (toolkit, _options, command) => {
|
|
4029
|
+
const options = ownerOptionsSchema.parse(command.optsWithGlobals());
|
|
4030
|
+
await addConnection(string().min(1).parse(toolkit), options.org);
|
|
4031
|
+
});
|
|
4032
|
+
program.command("connection").description("Assign a connection using the requirement’s viewer or owner mode; owner mode requires app management").argument("<target>", "AppID, public hostname, or local (run from the app root)").addArgument(new Argument("<operation>").choices(["assign"])).argument("<slug>", "Connection requirement slug").argument("<connection_id>", "Composio connected-account ID").action(async (target, _operation, slug, connectionId) => {
|
|
4007
4033
|
await assignAppConnection(target, slug, connectionId);
|
|
4008
4034
|
});
|
|
4009
4035
|
program.command("agent").addArgument(new Argument("<target>", "Run from the app root").choices(["local"])).addArgument(new Argument("<operation>").choices(["run"])).argument("<name>", "Agent directory under agents/").argument("<prompt>", "Task to send as the user message").description("Run agents/<name>/instructions.md locally with Claude Agent SDK and native Claude authentication; no platform server or ctx login required").action(async (_target, _operation, name, prompt) => {
|