@usecontextlayer/cli 0.12.1 → 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-BqaczjqV.mjs → app-DUUpiXEm.mjs} +366 -6
- package/dist/app-DUUpiXEm.mjs.map +1 -0
- package/dist/cli.mjs +948 -22
- package/dist/cli.mjs.map +1 -1
- package/dist/template/app/root.tsx +38 -0
- package/dist/template/public/slate.json +2 -1
- package/dist/template/workers/local-tools/index.ts +1 -1
- package/dist/vite.d.mts +2 -0
- package/dist/vite.mjs +3 -1
- package/dist/vite.mjs.map +1 -1
- package/package.json +7 -2
- package/dist/app-BqaczjqV.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as
|
|
3
|
-
import { cp, readFile } from "node:fs/promises";
|
|
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
|
+
import { cp, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import path, { join } from "node:path";
|
|
4
5
|
import { EventEmitter } from "node:events";
|
|
5
6
|
import childProcess from "node:child_process";
|
|
6
|
-
import path from "node:path";
|
|
7
7
|
import fs from "node:fs";
|
|
8
|
-
import process$1 from "node:process";
|
|
9
|
-
import { stripVTControlCharacters } from "node:util";
|
|
8
|
+
import process$1, { stdin, stdout } from "node:process";
|
|
9
|
+
import { stripVTControlCharacters, styleText } from "node:util";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import l__default, { createInterface } from "node:readline";
|
|
12
|
+
//#region \0rolldown/runtime.js
|
|
13
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
14
|
+
//#endregion
|
|
10
15
|
//#region ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
|
|
11
16
|
/**
|
|
12
17
|
* CommanderError class
|
|
@@ -2962,7 +2967,71 @@ function useColor() {
|
|
|
2962
2967
|
}
|
|
2963
2968
|
new Command();
|
|
2964
2969
|
//#endregion
|
|
2970
|
+
//#region agents.ts
|
|
2971
|
+
const platformInstructions = "You are a ContextLayer app agent. The user message is the task for this run. Work in the app directory and return the task's result.";
|
|
2972
|
+
async function runLocalAgent(name, prompt) {
|
|
2973
|
+
const instructions = await readFile(join("agents", name, "instructions.md"), "utf8");
|
|
2974
|
+
const { query } = await import("@anthropic-ai/claude-agent-sdk");
|
|
2975
|
+
const run = query({
|
|
2976
|
+
options: {
|
|
2977
|
+
cwd: process.cwd(),
|
|
2978
|
+
settingSources: [],
|
|
2979
|
+
systemPrompt: {
|
|
2980
|
+
append: `${platformInstructions}\n\n${instructions}`,
|
|
2981
|
+
preset: "claude_code",
|
|
2982
|
+
type: "preset"
|
|
2983
|
+
}
|
|
2984
|
+
},
|
|
2985
|
+
prompt
|
|
2986
|
+
});
|
|
2987
|
+
try {
|
|
2988
|
+
for await (const message of run) {
|
|
2989
|
+
if (message.type !== "result") continue;
|
|
2990
|
+
switch (message.subtype) {
|
|
2991
|
+
case "success":
|
|
2992
|
+
if (message.is_error) throw new Error(message.result);
|
|
2993
|
+
return message.result;
|
|
2994
|
+
case "error_during_execution":
|
|
2995
|
+
case "error_max_turns":
|
|
2996
|
+
case "error_max_budget_usd":
|
|
2997
|
+
case "error_max_structured_output_retries": throw new Error(message.errors.join("\n"));
|
|
2998
|
+
default: throw new Error(`Unhandled Claude result: ${JSON.stringify(message)}`);
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
throw new Error("Claude ended without a result");
|
|
3002
|
+
} finally {
|
|
3003
|
+
run.close();
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
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
|
|
2965
3031
|
//#region connections.ts
|
|
3032
|
+
async function getLocalManifest(target) {
|
|
3033
|
+
return target === "local" ? readLocalManifest() : void 0;
|
|
3034
|
+
}
|
|
2966
3035
|
async function resolveAppTarget(target) {
|
|
2967
3036
|
if (target !== "local") return target;
|
|
2968
3037
|
return getLocalAppId();
|
|
@@ -2972,6 +3041,7 @@ async function assignAppConnection(target, slug, connectionId) {
|
|
|
2972
3041
|
const response = await fetch(new URL(`/api/apps/${encodeURIComponent(appTarget)}/connections/assign`, env.CTX_PLATFORM_URL), {
|
|
2973
3042
|
body: JSON.stringify({
|
|
2974
3043
|
connection_id: connectionId,
|
|
3044
|
+
manifest: await getLocalManifest(target),
|
|
2975
3045
|
slug
|
|
2976
3046
|
}),
|
|
2977
3047
|
headers: {
|
|
@@ -2989,7 +3059,7 @@ async function assignAppConnection(target, slug, connectionId) {
|
|
|
2989
3059
|
}
|
|
2990
3060
|
async function listAppConnections(target) {
|
|
2991
3061
|
const appTarget = await resolveAppTarget(target);
|
|
2992
|
-
const manifest =
|
|
3062
|
+
const manifest = await getLocalManifest(target);
|
|
2993
3063
|
const response = await fetch(new URL(`/api/apps/${encodeURIComponent(appTarget)}/connections/list`, env.CTX_PLATFORM_URL), {
|
|
2994
3064
|
body: JSON.stringify({ manifest }),
|
|
2995
3065
|
headers: {
|
|
@@ -3001,7 +3071,7 @@ async function listAppConnections(target) {
|
|
|
3001
3071
|
if (!response.ok) throw new Error(`App connections request failed: HTTP ${response.status}`);
|
|
3002
3072
|
const { connections } = object({ connections: array(object({
|
|
3003
3073
|
connection_id: string().nullable(),
|
|
3004
|
-
mode:
|
|
3074
|
+
mode: credentialModeSchema,
|
|
3005
3075
|
slug: string(),
|
|
3006
3076
|
toolkit: string()
|
|
3007
3077
|
})) }).parse(await response.json());
|
|
@@ -3014,22 +3084,26 @@ async function listAppConnections(target) {
|
|
|
3014
3084
|
connection: connection_id ?? "unassigned"
|
|
3015
3085
|
})));
|
|
3016
3086
|
}
|
|
3017
|
-
async function addConnection(toolkit) {
|
|
3018
|
-
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), {
|
|
3019
3091
|
body: JSON.stringify({ toolkit }),
|
|
3020
3092
|
headers: {
|
|
3021
|
-
|
|
3093
|
+
...headers,
|
|
3022
3094
|
"content-type": "application/json"
|
|
3023
3095
|
},
|
|
3024
3096
|
method: "POST"
|
|
3025
3097
|
});
|
|
3026
3098
|
if (!response.ok) throw new Error(`Connection authorization failed: HTTP ${response.status}`);
|
|
3027
3099
|
const { redirect_url } = object({ redirect_url: url() }).parse(await response.json());
|
|
3028
|
-
console.log(`Open this link to
|
|
3029
|
-
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.`);
|
|
3030
3102
|
}
|
|
3031
|
-
async function listConnections() {
|
|
3032
|
-
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 });
|
|
3033
3107
|
if (!response.ok) throw new Error(`Connection list failed: HTTP ${response.status}`);
|
|
3034
3108
|
const { connections } = object({ connections: array(object({
|
|
3035
3109
|
alias: string().nullable(),
|
|
@@ -3045,12 +3119,809 @@ async function listConnections() {
|
|
|
3045
3119
|
console.table(connections);
|
|
3046
3120
|
}
|
|
3047
3121
|
//#endregion
|
|
3122
|
+
//#region git-credential.ts
|
|
3123
|
+
async function setupGit(cli) {
|
|
3124
|
+
const key = `credential.${new URL("/git", env.CTX_PLATFORM_URL).href}.helper`;
|
|
3125
|
+
const command = [
|
|
3126
|
+
process.execPath,
|
|
3127
|
+
fileURLToPath(cli),
|
|
3128
|
+
"git-credential"
|
|
3129
|
+
].map((argument) => `'${argument.replaceAll("'", "'\\''")}'`).join(" ");
|
|
3130
|
+
await execa("git", [
|
|
3131
|
+
"config",
|
|
3132
|
+
"--global",
|
|
3133
|
+
"--replace-all",
|
|
3134
|
+
key,
|
|
3135
|
+
""
|
|
3136
|
+
]);
|
|
3137
|
+
await execa("git", [
|
|
3138
|
+
"config",
|
|
3139
|
+
"--global",
|
|
3140
|
+
"--add",
|
|
3141
|
+
key,
|
|
3142
|
+
`!${command}`
|
|
3143
|
+
]);
|
|
3144
|
+
}
|
|
3145
|
+
async function gitCredential(operation) {
|
|
3146
|
+
if (operation === "capability") {
|
|
3147
|
+
process.stdout.write("version 0\ncapability authtype\n");
|
|
3148
|
+
return;
|
|
3149
|
+
}
|
|
3150
|
+
if (operation !== "get") return;
|
|
3151
|
+
const attributes = new URLSearchParams();
|
|
3152
|
+
const lines = createInterface({ input: process.stdin });
|
|
3153
|
+
for await (const line of lines) {
|
|
3154
|
+
if (line === "") break;
|
|
3155
|
+
const separator = line.indexOf("=");
|
|
3156
|
+
attributes.append(line.slice(0, separator), line.slice(separator + 1));
|
|
3157
|
+
}
|
|
3158
|
+
literal("authtype").parse(attributes.getAll("capability[]").find((c) => c === "authtype"));
|
|
3159
|
+
process.stdout.write(`capability[]=authtype\nauthtype=Bearer\ncredential=${await getAccessToken()}\n\n`);
|
|
3160
|
+
}
|
|
3161
|
+
//#endregion
|
|
3048
3162
|
//#region package.json
|
|
3049
|
-
var version = "0.
|
|
3163
|
+
var version = "0.14.0";
|
|
3164
|
+
//#endregion
|
|
3165
|
+
//#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
3166
|
+
const getCodePointsLength = (() => {
|
|
3167
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
3168
|
+
return (input) => {
|
|
3169
|
+
let surrogatePairsNr = 0;
|
|
3170
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
3171
|
+
while (SURROGATE_PAIR_RE.test(input)) surrogatePairsNr += 1;
|
|
3172
|
+
return input.length - surrogatePairsNr;
|
|
3173
|
+
};
|
|
3174
|
+
})();
|
|
3175
|
+
const isFullWidth = (x) => {
|
|
3176
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
3177
|
+
};
|
|
3178
|
+
const isWideNotCJKTNotEmoji = (x) => {
|
|
3179
|
+
return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
|
|
3180
|
+
};
|
|
3181
|
+
//#endregion
|
|
3182
|
+
//#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
|
|
3183
|
+
const ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
3184
|
+
const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
3185
|
+
const CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy;
|
|
3186
|
+
const TAB_RE = /\t{1,1000}/y;
|
|
3187
|
+
const EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy;
|
|
3188
|
+
const LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
3189
|
+
const MODIFIER_RE = /\p{M}+/gu;
|
|
3190
|
+
const NO_TRUNCATION$1 = {
|
|
3191
|
+
limit: Infinity,
|
|
3192
|
+
ellipsis: ""
|
|
3193
|
+
};
|
|
3194
|
+
const getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
|
|
3195
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
3196
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
3197
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION$1, widthOptions).width : 0);
|
|
3198
|
+
const ANSI_WIDTH = 0;
|
|
3199
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
3200
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
3201
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
3202
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
3203
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
3204
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
3205
|
+
const PARSE_BLOCKS = [
|
|
3206
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
3207
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
3208
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
3209
|
+
[TAB_RE, TAB_WIDTH],
|
|
3210
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
3211
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
3212
|
+
];
|
|
3213
|
+
let indexPrev = 0;
|
|
3214
|
+
let index = 0;
|
|
3215
|
+
let length = input.length;
|
|
3216
|
+
let lengthExtra = 0;
|
|
3217
|
+
let truncationEnabled = false;
|
|
3218
|
+
let truncationIndex = length;
|
|
3219
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
3220
|
+
let unmatchedStart = 0;
|
|
3221
|
+
let unmatchedEnd = 0;
|
|
3222
|
+
let width = 0;
|
|
3223
|
+
let widthExtra = 0;
|
|
3224
|
+
outer: while (true) {
|
|
3225
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
3226
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
3227
|
+
lengthExtra = 0;
|
|
3228
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
3229
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
3230
|
+
if (isFullWidth(codePoint)) widthExtra = FULL_WIDTH_WIDTH;
|
|
3231
|
+
else if (isWideNotCJKTNotEmoji(codePoint)) widthExtra = WIDE_WIDTH;
|
|
3232
|
+
else widthExtra = REGULAR_WIDTH;
|
|
3233
|
+
if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
3234
|
+
if (width + widthExtra > LIMIT) {
|
|
3235
|
+
truncationEnabled = true;
|
|
3236
|
+
break outer;
|
|
3237
|
+
}
|
|
3238
|
+
lengthExtra += char.length;
|
|
3239
|
+
width += widthExtra;
|
|
3240
|
+
}
|
|
3241
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
3242
|
+
}
|
|
3243
|
+
if (index >= length) break outer;
|
|
3244
|
+
for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
|
|
3245
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
3246
|
+
BLOCK_RE.lastIndex = index;
|
|
3247
|
+
if (BLOCK_RE.test(input)) {
|
|
3248
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
3249
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
3250
|
+
if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
3251
|
+
if (width + widthExtra > LIMIT) {
|
|
3252
|
+
truncationEnabled = true;
|
|
3253
|
+
break outer;
|
|
3254
|
+
}
|
|
3255
|
+
width += widthExtra;
|
|
3256
|
+
unmatchedStart = indexPrev;
|
|
3257
|
+
unmatchedEnd = index;
|
|
3258
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
3259
|
+
continue outer;
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
index += 1;
|
|
3263
|
+
}
|
|
3264
|
+
return {
|
|
3265
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
3266
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
3267
|
+
truncated: truncationEnabled,
|
|
3268
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
3269
|
+
};
|
|
3270
|
+
};
|
|
3271
|
+
//#endregion
|
|
3272
|
+
//#region ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
|
|
3273
|
+
const NO_TRUNCATION = {
|
|
3274
|
+
limit: Infinity,
|
|
3275
|
+
ellipsis: "",
|
|
3276
|
+
ellipsisWidth: 0
|
|
3277
|
+
};
|
|
3278
|
+
const fastStringWidth = (input, options = {}) => {
|
|
3279
|
+
return getStringTruncatedWidth(input, NO_TRUNCATION, options).width;
|
|
3280
|
+
};
|
|
3281
|
+
//#endregion
|
|
3282
|
+
//#region ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
|
|
3283
|
+
const ESC = "\x1B";
|
|
3284
|
+
const CSI = "";
|
|
3285
|
+
const END_CODE = 39;
|
|
3286
|
+
const ANSI_ESCAPE_BELL = "\x07";
|
|
3287
|
+
const ANSI_CSI = "[";
|
|
3288
|
+
const ANSI_OSC = "]";
|
|
3289
|
+
const ANSI_SGR_TERMINATOR = "m";
|
|
3290
|
+
const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
3291
|
+
const GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
3292
|
+
const getClosingCode = (openingCode) => {
|
|
3293
|
+
if (openingCode >= 30 && openingCode <= 37) return 39;
|
|
3294
|
+
if (openingCode >= 90 && openingCode <= 97) return 39;
|
|
3295
|
+
if (openingCode >= 40 && openingCode <= 47) return 49;
|
|
3296
|
+
if (openingCode >= 100 && openingCode <= 107) return 49;
|
|
3297
|
+
if (openingCode === 1 || openingCode === 2) return 22;
|
|
3298
|
+
if (openingCode === 3) return 23;
|
|
3299
|
+
if (openingCode === 4) return 24;
|
|
3300
|
+
if (openingCode === 7) return 27;
|
|
3301
|
+
if (openingCode === 8) return 28;
|
|
3302
|
+
if (openingCode === 9) return 29;
|
|
3303
|
+
if (openingCode === 0) return 0;
|
|
3304
|
+
};
|
|
3305
|
+
const wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
3306
|
+
const wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
3307
|
+
const wrapWord = (rows, word, columns) => {
|
|
3308
|
+
const characters = word[Symbol.iterator]();
|
|
3309
|
+
let isInsideEscape = false;
|
|
3310
|
+
let isInsideLinkEscape = false;
|
|
3311
|
+
let lastRow = rows.at(-1);
|
|
3312
|
+
let visible = lastRow === void 0 ? 0 : fastStringWidth(lastRow);
|
|
3313
|
+
let currentCharacter = characters.next();
|
|
3314
|
+
let nextCharacter = characters.next();
|
|
3315
|
+
let rawCharacterIndex = 0;
|
|
3316
|
+
while (!currentCharacter.done) {
|
|
3317
|
+
const character = currentCharacter.value;
|
|
3318
|
+
const characterLength = fastStringWidth(character);
|
|
3319
|
+
if (visible + characterLength <= columns) rows[rows.length - 1] += character;
|
|
3320
|
+
else {
|
|
3321
|
+
rows.push(character);
|
|
3322
|
+
visible = 0;
|
|
3323
|
+
}
|
|
3324
|
+
if (character === ESC || character === CSI) {
|
|
3325
|
+
isInsideEscape = true;
|
|
3326
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
3327
|
+
}
|
|
3328
|
+
if (isInsideEscape) {
|
|
3329
|
+
if (isInsideLinkEscape) {
|
|
3330
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
3331
|
+
isInsideEscape = false;
|
|
3332
|
+
isInsideLinkEscape = false;
|
|
3333
|
+
}
|
|
3334
|
+
} else if (character === ANSI_SGR_TERMINATOR) isInsideEscape = false;
|
|
3335
|
+
} else {
|
|
3336
|
+
visible += characterLength;
|
|
3337
|
+
if (visible === columns && !nextCharacter.done) {
|
|
3338
|
+
rows.push("");
|
|
3339
|
+
visible = 0;
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
currentCharacter = nextCharacter;
|
|
3343
|
+
nextCharacter = characters.next();
|
|
3344
|
+
rawCharacterIndex += character.length;
|
|
3345
|
+
}
|
|
3346
|
+
lastRow = rows.at(-1);
|
|
3347
|
+
if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) rows[rows.length - 2] += rows.pop();
|
|
3348
|
+
};
|
|
3349
|
+
const stringVisibleTrimSpacesRight = (string) => {
|
|
3350
|
+
const words = string.split(" ");
|
|
3351
|
+
let last = words.length;
|
|
3352
|
+
while (last) {
|
|
3353
|
+
if (fastStringWidth(words[last - 1])) break;
|
|
3354
|
+
last--;
|
|
3355
|
+
}
|
|
3356
|
+
if (last === words.length) return string;
|
|
3357
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
3358
|
+
};
|
|
3359
|
+
const exec = (string, columns, options = {}) => {
|
|
3360
|
+
if (options.trim !== false && string.trim() === "") return "";
|
|
3361
|
+
let returnValue = "";
|
|
3362
|
+
let escapeCode;
|
|
3363
|
+
let escapeUrl;
|
|
3364
|
+
const words = string.split(" ");
|
|
3365
|
+
let rows = [""];
|
|
3366
|
+
let rowLength = 0;
|
|
3367
|
+
for (let index = 0; index < words.length; index++) {
|
|
3368
|
+
const word = words[index];
|
|
3369
|
+
if (options.trim !== false) {
|
|
3370
|
+
const row = rows.at(-1) ?? "";
|
|
3371
|
+
const trimmed = row.trimStart();
|
|
3372
|
+
if (row.length !== trimmed.length) {
|
|
3373
|
+
rows[rows.length - 1] = trimmed;
|
|
3374
|
+
rowLength = fastStringWidth(trimmed);
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3377
|
+
if (index !== 0) {
|
|
3378
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
3379
|
+
rows.push("");
|
|
3380
|
+
rowLength = 0;
|
|
3381
|
+
}
|
|
3382
|
+
if (rowLength || options.trim === false) {
|
|
3383
|
+
rows[rows.length - 1] += " ";
|
|
3384
|
+
rowLength++;
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
const wordLength = fastStringWidth(word);
|
|
3388
|
+
if (options.hard && wordLength > columns) {
|
|
3389
|
+
const remainingColumns = columns - rowLength;
|
|
3390
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
3391
|
+
if (Math.floor((wordLength - 1) / columns) < breaksStartingThisLine) rows.push("");
|
|
3392
|
+
wrapWord(rows, word, columns);
|
|
3393
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3394
|
+
continue;
|
|
3395
|
+
}
|
|
3396
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
3397
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
3398
|
+
wrapWord(rows, word, columns);
|
|
3399
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3400
|
+
continue;
|
|
3401
|
+
}
|
|
3402
|
+
rows.push("");
|
|
3403
|
+
rowLength = 0;
|
|
3404
|
+
}
|
|
3405
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
3406
|
+
wrapWord(rows, word, columns);
|
|
3407
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3408
|
+
continue;
|
|
3409
|
+
}
|
|
3410
|
+
rows[rows.length - 1] += word;
|
|
3411
|
+
rowLength += wordLength;
|
|
3412
|
+
}
|
|
3413
|
+
if (options.trim !== false) rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
3414
|
+
const preString = rows.join("\n");
|
|
3415
|
+
let inSurrogate = false;
|
|
3416
|
+
for (let i = 0; i < preString.length; i++) {
|
|
3417
|
+
const character = preString[i];
|
|
3418
|
+
returnValue += character;
|
|
3419
|
+
if (!inSurrogate) {
|
|
3420
|
+
inSurrogate = character >= "\ud800" && character <= "\udbff";
|
|
3421
|
+
if (inSurrogate) continue;
|
|
3422
|
+
} else inSurrogate = false;
|
|
3423
|
+
if (character === ESC || character === CSI) {
|
|
3424
|
+
GROUP_REGEX.lastIndex = i + 1;
|
|
3425
|
+
const groups = GROUP_REGEX.exec(preString)?.groups;
|
|
3426
|
+
if (groups?.code !== void 0) {
|
|
3427
|
+
const code = Number.parseFloat(groups.code);
|
|
3428
|
+
escapeCode = code === END_CODE ? void 0 : code;
|
|
3429
|
+
} else if (groups?.uri !== void 0) escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
|
|
3430
|
+
}
|
|
3431
|
+
if (preString[i + 1] === "\n") {
|
|
3432
|
+
if (escapeUrl) returnValue += wrapAnsiHyperlink("");
|
|
3433
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
|
|
3434
|
+
if (escapeCode && closingCode) returnValue += wrapAnsiCode(closingCode);
|
|
3435
|
+
} else if (character === "\n") {
|
|
3436
|
+
if (escapeCode && getClosingCode(escapeCode)) returnValue += wrapAnsiCode(escapeCode);
|
|
3437
|
+
if (escapeUrl) returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
return returnValue;
|
|
3441
|
+
};
|
|
3442
|
+
const CRLF_OR_LF = /\r?\n/;
|
|
3443
|
+
function wrapAnsi(string, columns, options) {
|
|
3444
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
|
|
3445
|
+
}
|
|
3446
|
+
//#endregion
|
|
3447
|
+
//#region ../../node_modules/.pnpm/@clack+core@1.5.1/node_modules/@clack/core/dist/index.mjs
|
|
3448
|
+
var import_src = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
3449
|
+
const ESC = "\x1B";
|
|
3450
|
+
const CSI = `${ESC}[`;
|
|
3451
|
+
const beep = "\x07";
|
|
3452
|
+
const cursor = {
|
|
3453
|
+
to(x, y) {
|
|
3454
|
+
if (!y) return `${CSI}${x + 1}G`;
|
|
3455
|
+
return `${CSI}${y + 1};${x + 1}H`;
|
|
3456
|
+
},
|
|
3457
|
+
move(x, y) {
|
|
3458
|
+
let ret = "";
|
|
3459
|
+
if (x < 0) ret += `${CSI}${-x}D`;
|
|
3460
|
+
else if (x > 0) ret += `${CSI}${x}C`;
|
|
3461
|
+
if (y < 0) ret += `${CSI}${-y}A`;
|
|
3462
|
+
else if (y > 0) ret += `${CSI}${y}B`;
|
|
3463
|
+
return ret;
|
|
3464
|
+
},
|
|
3465
|
+
up: (count = 1) => `${CSI}${count}A`,
|
|
3466
|
+
down: (count = 1) => `${CSI}${count}B`,
|
|
3467
|
+
forward: (count = 1) => `${CSI}${count}C`,
|
|
3468
|
+
backward: (count = 1) => `${CSI}${count}D`,
|
|
3469
|
+
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|
3470
|
+
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|
3471
|
+
left: `${CSI}G`,
|
|
3472
|
+
hide: `${CSI}?25l`,
|
|
3473
|
+
show: `${CSI}?25h`,
|
|
3474
|
+
save: `${ESC}7`,
|
|
3475
|
+
restore: `${ESC}8`
|
|
3476
|
+
};
|
|
3477
|
+
module.exports = {
|
|
3478
|
+
cursor,
|
|
3479
|
+
scroll: {
|
|
3480
|
+
up: (count = 1) => `${CSI}S`.repeat(count),
|
|
3481
|
+
down: (count = 1) => `${CSI}T`.repeat(count)
|
|
3482
|
+
},
|
|
3483
|
+
erase: {
|
|
3484
|
+
screen: `${CSI}2J`,
|
|
3485
|
+
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|
3486
|
+
down: (count = 1) => `${CSI}J`.repeat(count),
|
|
3487
|
+
line: `${CSI}2K`,
|
|
3488
|
+
lineEnd: `${CSI}K`,
|
|
3489
|
+
lineStart: `${CSI}1K`,
|
|
3490
|
+
lines(count) {
|
|
3491
|
+
let clear = "";
|
|
3492
|
+
for (let i = 0; i < count; i++) clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
3493
|
+
if (count) clear += cursor.left;
|
|
3494
|
+
return clear;
|
|
3495
|
+
}
|
|
3496
|
+
},
|
|
3497
|
+
beep
|
|
3498
|
+
};
|
|
3499
|
+
})))();
|
|
3500
|
+
const settings = {
|
|
3501
|
+
actions: /* @__PURE__ */ new Set([
|
|
3502
|
+
"up",
|
|
3503
|
+
"down",
|
|
3504
|
+
"left",
|
|
3505
|
+
"right",
|
|
3506
|
+
"space",
|
|
3507
|
+
"enter",
|
|
3508
|
+
"cancel"
|
|
3509
|
+
]),
|
|
3510
|
+
aliases: /* @__PURE__ */ new Map([
|
|
3511
|
+
["k", "up"],
|
|
3512
|
+
["j", "down"],
|
|
3513
|
+
["h", "left"],
|
|
3514
|
+
["l", "right"],
|
|
3515
|
+
["", "cancel"],
|
|
3516
|
+
["escape", "cancel"]
|
|
3517
|
+
]),
|
|
3518
|
+
messages: {
|
|
3519
|
+
cancel: "Canceled",
|
|
3520
|
+
error: "Something went wrong"
|
|
3521
|
+
},
|
|
3522
|
+
withGuide: true,
|
|
3523
|
+
accessible: void 0,
|
|
3524
|
+
date: {
|
|
3525
|
+
monthNames: [...[
|
|
3526
|
+
"January",
|
|
3527
|
+
"February",
|
|
3528
|
+
"March",
|
|
3529
|
+
"April",
|
|
3530
|
+
"May",
|
|
3531
|
+
"June",
|
|
3532
|
+
"July",
|
|
3533
|
+
"August",
|
|
3534
|
+
"September",
|
|
3535
|
+
"October",
|
|
3536
|
+
"November",
|
|
3537
|
+
"December"
|
|
3538
|
+
]],
|
|
3539
|
+
messages: {
|
|
3540
|
+
required: "Please enter a valid date",
|
|
3541
|
+
invalidMonth: "There are only 12 months in a year",
|
|
3542
|
+
invalidDay: (n, e) => `There are only ${n} days in ${e}`,
|
|
3543
|
+
afterMin: (n) => `Date must be on or after ${n.toISOString().slice(0, 10)}`,
|
|
3544
|
+
beforeMax: (n) => `Date must be on or before ${n.toISOString().slice(0, 10)}`
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
};
|
|
3548
|
+
function isAccessible(n) {
|
|
3549
|
+
if (n !== void 0) return n;
|
|
3550
|
+
if (settings.accessible !== void 0) return settings.accessible;
|
|
3551
|
+
const e = process.env.ACCESSIBLE;
|
|
3552
|
+
return e !== void 0 && e !== "" && e !== "0" && e !== "false";
|
|
3553
|
+
}
|
|
3554
|
+
function isActionKey(n, e) {
|
|
3555
|
+
if (typeof n == "string") return settings.aliases.get(n) === e;
|
|
3556
|
+
for (const s of n) if (s !== void 0 && isActionKey(s, e)) return true;
|
|
3557
|
+
return false;
|
|
3558
|
+
}
|
|
3559
|
+
function diffLines(i, s) {
|
|
3560
|
+
if (i === s) return;
|
|
3561
|
+
const e = i.split(`
|
|
3562
|
+
`), t = s.split(`
|
|
3563
|
+
`), r = Math.max(e.length, t.length), f = [];
|
|
3564
|
+
for (let n = 0; n < r; n++) e[n] !== t[n] && f.push(n);
|
|
3565
|
+
return {
|
|
3566
|
+
lines: f,
|
|
3567
|
+
numLinesBefore: e.length,
|
|
3568
|
+
numLinesAfter: t.length,
|
|
3569
|
+
numLines: r
|
|
3570
|
+
};
|
|
3571
|
+
}
|
|
3572
|
+
globalThis.process.platform.startsWith("win");
|
|
3573
|
+
const CANCEL_SYMBOL = Symbol("clack:cancel");
|
|
3574
|
+
function isCancel(e) {
|
|
3575
|
+
return e === CANCEL_SYMBOL;
|
|
3576
|
+
}
|
|
3577
|
+
function setRawMode(e, r) {
|
|
3578
|
+
const o = e;
|
|
3579
|
+
o.isTTY && o.setRawMode(r);
|
|
3580
|
+
}
|
|
3581
|
+
const getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
|
|
3582
|
+
function runValidation(e, a) {
|
|
3583
|
+
if ("~standard" in e) {
|
|
3584
|
+
const n = e["~standard"].validate(a);
|
|
3585
|
+
return n instanceof Promise ? n.then((r) => r.issues?.at(0)?.message) : n.issues?.at(0)?.message;
|
|
3586
|
+
}
|
|
3587
|
+
return e(a);
|
|
3588
|
+
}
|
|
3589
|
+
var y = class {
|
|
3590
|
+
input;
|
|
3591
|
+
output;
|
|
3592
|
+
_abortSignal;
|
|
3593
|
+
rl;
|
|
3594
|
+
opts;
|
|
3595
|
+
_render;
|
|
3596
|
+
_track = false;
|
|
3597
|
+
_prevFrame = "";
|
|
3598
|
+
_subscribers = /* @__PURE__ */ new Map();
|
|
3599
|
+
_cursor = 0;
|
|
3600
|
+
state = "initial";
|
|
3601
|
+
error = "";
|
|
3602
|
+
value;
|
|
3603
|
+
userInput = "";
|
|
3604
|
+
/**
|
|
3605
|
+
* Whether accessible (static, screen-reader friendly) output is enabled for
|
|
3606
|
+
* this prompt, resolved from the `accessible` option, the global setting,
|
|
3607
|
+
* and the `ACCESSIBLE` env var.
|
|
3608
|
+
*/
|
|
3609
|
+
get accessible() {
|
|
3610
|
+
return isAccessible(this.opts.accessible);
|
|
3611
|
+
}
|
|
3612
|
+
constructor(t, e = true) {
|
|
3613
|
+
const { input: i = stdin, output: s = stdout, render: r, signal: n, ...o } = t;
|
|
3614
|
+
this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = r.bind(this), this._track = e, this._abortSignal = n, this.input = i, this.output = s;
|
|
3615
|
+
}
|
|
3616
|
+
/**
|
|
3617
|
+
* Unsubscribe all listeners
|
|
3618
|
+
*/
|
|
3619
|
+
unsubscribe() {
|
|
3620
|
+
this._subscribers.clear();
|
|
3621
|
+
}
|
|
3622
|
+
/**
|
|
3623
|
+
* Set a subscriber with opts
|
|
3624
|
+
* @param event - The event name
|
|
3625
|
+
*/
|
|
3626
|
+
setSubscriber(t, e) {
|
|
3627
|
+
const i = this._subscribers.get(t) ?? [];
|
|
3628
|
+
i.push(e), this._subscribers.set(t, i);
|
|
3629
|
+
}
|
|
3630
|
+
/**
|
|
3631
|
+
* Subscribe to an event
|
|
3632
|
+
* @param event - The event name
|
|
3633
|
+
* @param cb - The callback
|
|
3634
|
+
*/
|
|
3635
|
+
on(t, e) {
|
|
3636
|
+
this.setSubscriber(t, { cb: e });
|
|
3637
|
+
}
|
|
3638
|
+
/**
|
|
3639
|
+
* Subscribe to an event once
|
|
3640
|
+
* @param event - The event name
|
|
3641
|
+
* @param cb - The callback
|
|
3642
|
+
*/
|
|
3643
|
+
once(t, e) {
|
|
3644
|
+
this.setSubscriber(t, {
|
|
3645
|
+
cb: e,
|
|
3646
|
+
once: true
|
|
3647
|
+
});
|
|
3648
|
+
}
|
|
3649
|
+
/**
|
|
3650
|
+
* Emit an event with data
|
|
3651
|
+
* @param event - The event name
|
|
3652
|
+
* @param data - The data to pass to the callback
|
|
3653
|
+
*/
|
|
3654
|
+
emit(t, ...e) {
|
|
3655
|
+
const i = this._subscribers.get(t) ?? [], s = [];
|
|
3656
|
+
for (const r of i) r.cb(...e), r.once && s.push(() => i.splice(i.indexOf(r), 1));
|
|
3657
|
+
for (const r of s) r();
|
|
3658
|
+
}
|
|
3659
|
+
prompt() {
|
|
3660
|
+
return new Promise((t) => {
|
|
3661
|
+
if (this._abortSignal) {
|
|
3662
|
+
if (this._abortSignal.aborted) return this.state = "cancel", this.close(), t(CANCEL_SYMBOL);
|
|
3663
|
+
this._abortSignal.addEventListener("abort", () => {
|
|
3664
|
+
this.state = "cancel", this.close();
|
|
3665
|
+
}, { once: true });
|
|
3666
|
+
}
|
|
3667
|
+
this.rl = l__default.createInterface({
|
|
3668
|
+
input: this.input,
|
|
3669
|
+
tabSize: 2,
|
|
3670
|
+
prompt: "",
|
|
3671
|
+
escapeCodeTimeout: 50,
|
|
3672
|
+
terminal: true
|
|
3673
|
+
}), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
|
|
3674
|
+
this.output.write(import_src.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(this.value);
|
|
3675
|
+
}), this.once("cancel", () => {
|
|
3676
|
+
this.output.write(import_src.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(CANCEL_SYMBOL);
|
|
3677
|
+
});
|
|
3678
|
+
});
|
|
3679
|
+
}
|
|
3680
|
+
_isActionKey(t, e) {
|
|
3681
|
+
return t === " ";
|
|
3682
|
+
}
|
|
3683
|
+
_shouldSubmit(t, e) {
|
|
3684
|
+
return true;
|
|
3685
|
+
}
|
|
3686
|
+
_setValue(t) {
|
|
3687
|
+
this.value = t, this.emit("value", this.value);
|
|
3688
|
+
}
|
|
3689
|
+
_setUserInput(t, e) {
|
|
3690
|
+
this.userInput = t ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
|
|
3691
|
+
}
|
|
3692
|
+
_clearUserInput() {
|
|
3693
|
+
this.rl?.write(null, {
|
|
3694
|
+
ctrl: true,
|
|
3695
|
+
name: "u"
|
|
3696
|
+
}), this._setUserInput("");
|
|
3697
|
+
}
|
|
3698
|
+
async onKeypress(t, e) {
|
|
3699
|
+
if (this.state !== "validating") {
|
|
3700
|
+
if (this._track && e.name !== "return" && (e.name && this._isActionKey(t, e) && this.rl?.write(null, {
|
|
3701
|
+
ctrl: true,
|
|
3702
|
+
name: "h"
|
|
3703
|
+
}), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t && (t.toLowerCase() === "y" || t.toLowerCase() === "n") && this.emit("confirm", t.toLowerCase() === "y"), this.emit("key", t, e), e?.name === "return" && this._shouldSubmit(t, e)) {
|
|
3704
|
+
if (this.opts.validate) {
|
|
3705
|
+
const i = runValidation(this.opts.validate, this.value);
|
|
3706
|
+
let s;
|
|
3707
|
+
i instanceof Promise ? (this.state = "validating", this.render(), s = await i) : s = i, s && (this.error = s instanceof Error ? s.message : s, this.state = "error", this.rl?.write(this.userInput));
|
|
3708
|
+
}
|
|
3709
|
+
this.state !== "error" && (this.state = "submit");
|
|
3710
|
+
}
|
|
3711
|
+
isActionKey([
|
|
3712
|
+
t,
|
|
3713
|
+
e?.name,
|
|
3714
|
+
e?.sequence
|
|
3715
|
+
], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
close() {
|
|
3719
|
+
this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
|
|
3720
|
+
`), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
|
|
3721
|
+
}
|
|
3722
|
+
restoreCursor() {
|
|
3723
|
+
const t = wrapAnsi(this._prevFrame, process.stdout.columns, {
|
|
3724
|
+
hard: true,
|
|
3725
|
+
trim: false
|
|
3726
|
+
}).split(`
|
|
3727
|
+
`).length - 1;
|
|
3728
|
+
this.output.write(import_src.cursor.move(-999, t * -1));
|
|
3729
|
+
}
|
|
3730
|
+
render() {
|
|
3731
|
+
const t = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
|
|
3732
|
+
hard: true,
|
|
3733
|
+
trim: false
|
|
3734
|
+
});
|
|
3735
|
+
if (t !== this._prevFrame) {
|
|
3736
|
+
if (this.state === "initial") this.output.write(import_src.cursor.hide);
|
|
3737
|
+
else {
|
|
3738
|
+
const e = diffLines(this._prevFrame, t), i = getRows(this.output);
|
|
3739
|
+
if (this.restoreCursor(), e) {
|
|
3740
|
+
const s = Math.max(0, e.numLinesAfter - i), r = Math.max(0, e.numLinesBefore - i);
|
|
3741
|
+
let n = e.lines.find((o) => o >= s);
|
|
3742
|
+
if (n === void 0) {
|
|
3743
|
+
this._prevFrame = t;
|
|
3744
|
+
return;
|
|
3745
|
+
}
|
|
3746
|
+
if (e.lines.length === 1) {
|
|
3747
|
+
this.output.write(import_src.cursor.move(0, n - r)), this.output.write(import_src.erase.lines(1));
|
|
3748
|
+
const o = t.split(`
|
|
3749
|
+
`);
|
|
3750
|
+
this.output.write(o[n]), this._prevFrame = t, this.output.write(import_src.cursor.move(0, o.length - n - 1));
|
|
3751
|
+
return;
|
|
3752
|
+
} else if (e.lines.length > 1) {
|
|
3753
|
+
if (s < r) n = s;
|
|
3754
|
+
else {
|
|
3755
|
+
const h = n - r;
|
|
3756
|
+
h > 0 && this.output.write(import_src.cursor.move(0, h));
|
|
3757
|
+
}
|
|
3758
|
+
this.output.write(import_src.erase.down());
|
|
3759
|
+
const f = t.split(`
|
|
3760
|
+
`).slice(n);
|
|
3761
|
+
this.output.write(f.join(`
|
|
3762
|
+
`)), this._prevFrame = t;
|
|
3763
|
+
return;
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
this.output.write(import_src.erase.down());
|
|
3767
|
+
}
|
|
3768
|
+
this.output.write(t), this.state === "initial" && (this.state = "active"), this._prevFrame = t;
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
};
|
|
3772
|
+
let u$1 = class u extends y {
|
|
3773
|
+
_mask = "•";
|
|
3774
|
+
get cursor() {
|
|
3775
|
+
return this._cursor;
|
|
3776
|
+
}
|
|
3777
|
+
get masked() {
|
|
3778
|
+
return this.userInput.replaceAll(/./g, this._mask);
|
|
3779
|
+
}
|
|
3780
|
+
get userInputWithCursor() {
|
|
3781
|
+
if (this.state === "submit" || this.state === "cancel") return this.masked;
|
|
3782
|
+
const t = this.userInput;
|
|
3783
|
+
if (this.cursor >= t.length) return `${this.masked}${styleText(["inverse", "hidden"], "_")}`;
|
|
3784
|
+
const s = this.masked, r = s.slice(0, this.cursor), i = s.slice(this.cursor, this.cursor + 1), o = s.slice(this.cursor + 1);
|
|
3785
|
+
return `${r}${styleText("inverse", i)}${o}`;
|
|
3786
|
+
}
|
|
3787
|
+
clear() {
|
|
3788
|
+
this._clearUserInput();
|
|
3789
|
+
}
|
|
3790
|
+
constructor({ mask: t, ...s }) {
|
|
3791
|
+
super(s), this._mask = t ?? "•", this.on("userInput", (r) => {
|
|
3792
|
+
this._setValue(r);
|
|
3793
|
+
}), this.on("finalize", () => {
|
|
3794
|
+
this.value === void 0 && (this.value = "");
|
|
3795
|
+
});
|
|
3796
|
+
}
|
|
3797
|
+
};
|
|
3798
|
+
//#endregion
|
|
3799
|
+
//#region ../../node_modules/.pnpm/@clack+prompts@1.8.1/node_modules/@clack/prompts/dist/index.mjs
|
|
3800
|
+
function isUnicodeSupported() {
|
|
3801
|
+
if (process$1.platform !== "win32") return process$1.env.TERM !== "linux";
|
|
3802
|
+
return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
3803
|
+
}
|
|
3804
|
+
const unicode = isUnicodeSupported();
|
|
3805
|
+
const unicodeOr = (o, e) => unicode ? o : e;
|
|
3806
|
+
const S_STEP_ACTIVE = unicodeOr("◆", "*");
|
|
3807
|
+
const S_STEP_CANCEL = unicodeOr("■", "x");
|
|
3808
|
+
const S_STEP_ERROR = unicodeOr("▲", "x");
|
|
3809
|
+
const S_STEP_SUBMIT = unicodeOr("◇", "o");
|
|
3810
|
+
const S_BAR = unicodeOr("│", "|");
|
|
3811
|
+
const S_BAR_END = unicodeOr("└", "—");
|
|
3812
|
+
const S_PASSWORD_MASK = unicodeOr("▪", "•");
|
|
3813
|
+
const symbol = (o) => {
|
|
3814
|
+
switch (o) {
|
|
3815
|
+
case "initial":
|
|
3816
|
+
case "active": return styleText("cyan", S_STEP_ACTIVE);
|
|
3817
|
+
case "cancel": return styleText("red", S_STEP_CANCEL);
|
|
3818
|
+
case "error": return styleText("yellow", S_STEP_ERROR);
|
|
3819
|
+
case "submit": return styleText("green", S_STEP_SUBMIT);
|
|
3820
|
+
case "validating": return styleText("dim", S_STEP_ACTIVE);
|
|
3821
|
+
}
|
|
3822
|
+
};
|
|
3823
|
+
`${styleText("dim", "↑/↓")}`, `${styleText("dim", "Space:")}`, `${styleText("dim", "Enter:")}`;
|
|
3824
|
+
const password = (e) => new u$1({
|
|
3825
|
+
validate: e.validate,
|
|
3826
|
+
mask: e.mask ?? S_PASSWORD_MASK,
|
|
3827
|
+
signal: e.signal,
|
|
3828
|
+
input: e.input,
|
|
3829
|
+
output: e.output,
|
|
3830
|
+
render() {
|
|
3831
|
+
const r = e.withGuide ?? settings.withGuide, o = `${r ? `${styleText("gray", S_BAR)}
|
|
3832
|
+
` : ""}${symbol(this.state)} ${e.message}
|
|
3833
|
+
`, m = this.userInputWithCursor, i = this.masked;
|
|
3834
|
+
switch (this.state) {
|
|
3835
|
+
case "error": {
|
|
3836
|
+
const s = r ? `${styleText("yellow", S_BAR)} ` : "", n = r ? `${styleText("yellow", S_BAR_END)} ` : "", d = i ?? "";
|
|
3837
|
+
return e.clearOnError && this.clear(), `${o.trim()}
|
|
3838
|
+
${s}${d}
|
|
3839
|
+
${n}${styleText("yellow", this.error)}
|
|
3840
|
+
`;
|
|
3841
|
+
}
|
|
3842
|
+
case "submit": return `${o}${r ? `${styleText("gray", S_BAR)} ` : ""}${i ? styleText("dim", i) : ""}`;
|
|
3843
|
+
case "cancel": return `${o}${r ? `${styleText("gray", S_BAR)} ` : ""}${i ? styleText(["strikethrough", "dim"], i) : ""}${i && r ? `
|
|
3844
|
+
${styleText("gray", S_BAR)}` : ""}`;
|
|
3845
|
+
default: return `${o}${r ? `${styleText("cyan", S_BAR)} ` : ""}${m}
|
|
3846
|
+
${r ? styleText("cyan", S_BAR_END) : ""}
|
|
3847
|
+
`;
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
}).prompt();
|
|
3851
|
+
`${styleText("dim", "↑/↓")}`, `${styleText("dim", "Enter:")}`;
|
|
3852
|
+
`${styleText("gray", S_BAR)}`;
|
|
3853
|
+
//#endregion
|
|
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
|
|
3865
|
+
});
|
|
3866
|
+
//#endregion
|
|
3867
|
+
//#region secrets.ts
|
|
3868
|
+
const secretOptionsSchema = ownerOptionsSchema.extend({ stdin: boolean().default(false) });
|
|
3869
|
+
const valueSchema = string().min(1);
|
|
3870
|
+
const confirmationSchema = object({
|
|
3871
|
+
name: secretNameSchema,
|
|
3872
|
+
owner: ownerSchema
|
|
3873
|
+
});
|
|
3874
|
+
async function resolveSecretUrl(name, org, headers) {
|
|
3875
|
+
const owner = await resolveOwner(org, headers);
|
|
3876
|
+
return new URL(`/api/secrets/${ownerPath(owner)}/${encodeURIComponent(name)}`, env.CTX_PLATFORM_URL);
|
|
3877
|
+
}
|
|
3878
|
+
async function setSecret(name, options) {
|
|
3879
|
+
const headers = { authorization: `Bearer ${await getAccessToken()}` };
|
|
3880
|
+
const url = await resolveSecretUrl(name, options.org, headers);
|
|
3881
|
+
let value;
|
|
3882
|
+
if (options.stdin) {
|
|
3883
|
+
process.stdin.setEncoding("utf8");
|
|
3884
|
+
value = "";
|
|
3885
|
+
for await (const chunk of process.stdin) value += chunk;
|
|
3886
|
+
} else {
|
|
3887
|
+
if (!process.stdin.isTTY) throw new Error("Use --stdin to read a secret without a terminal");
|
|
3888
|
+
const entered = await password({
|
|
3889
|
+
message: `Value for ${name}`,
|
|
3890
|
+
output: process.stderr,
|
|
3891
|
+
validate: valueSchema
|
|
3892
|
+
});
|
|
3893
|
+
if (isCancel(entered)) {
|
|
3894
|
+
process.exitCode = 130;
|
|
3895
|
+
return;
|
|
3896
|
+
}
|
|
3897
|
+
value = entered;
|
|
3898
|
+
}
|
|
3899
|
+
const response = await fetch(url, {
|
|
3900
|
+
body: JSON.stringify({ value: valueSchema.parse(value) }),
|
|
3901
|
+
headers: {
|
|
3902
|
+
...headers,
|
|
3903
|
+
"content-type": "application/json"
|
|
3904
|
+
},
|
|
3905
|
+
method: "PUT"
|
|
3906
|
+
});
|
|
3907
|
+
if (!response.ok) throw new Error(`Secret save failed: HTTP ${response.status}`);
|
|
3908
|
+
console.log(JSON.stringify(confirmationSchema.parse(await response.json())));
|
|
3909
|
+
}
|
|
3910
|
+
async function dropSecret(name, org) {
|
|
3911
|
+
const headers = { authorization: `Bearer ${await getAccessToken()}` };
|
|
3912
|
+
const response = await fetch(await resolveSecretUrl(name, org, headers), {
|
|
3913
|
+
headers,
|
|
3914
|
+
method: "DELETE"
|
|
3915
|
+
});
|
|
3916
|
+
if (!response.ok) throw new Error(`Secret drop failed: HTTP ${response.status}`);
|
|
3917
|
+
console.log(JSON.stringify(confirmationSchema.parse(await response.json())));
|
|
3918
|
+
}
|
|
3050
3919
|
//#endregion
|
|
3051
3920
|
//#region cli.ts
|
|
3052
3921
|
const program = new Command().name("ctx").description("ContextLayer CLI").version(version);
|
|
3053
|
-
program.command("init <directory>").description("Create a Cloudflare React Router project with
|
|
3922
|
+
program.command("init <directory>").description("Create a Cloudflare React Router project with Tailwind and shadcn Base UI, register an app owned by you or an organization (ctx login), and set its immutable Git remote").option("--org <slug>", "Create the app under an organization you belong to").action(async (directory, options) => {
|
|
3923
|
+
const input = object({ organization_slug: string().min(1).optional() }).parse({ organization_slug: options.org });
|
|
3924
|
+
const accessToken = await getAccessToken();
|
|
3054
3925
|
const result = await execa("pnpm", [
|
|
3055
3926
|
"create",
|
|
3056
3927
|
"cloudflare@latest",
|
|
@@ -3067,6 +3938,27 @@ program.command("init <directory>").description("Create a Cloudflare React Route
|
|
|
3067
3938
|
});
|
|
3068
3939
|
process.exitCode = result.exitCode;
|
|
3069
3940
|
if (result.exitCode !== 0) return;
|
|
3941
|
+
const tsconfigPath = join(directory, "tsconfig.json");
|
|
3942
|
+
const tsconfig = looseObject({ compilerOptions: record(string(), unknown()) }).parse(JSON.parse(await readFile(tsconfigPath, "utf8")));
|
|
3943
|
+
tsconfig.compilerOptions.paths = { "~/*": ["./app/*"] };
|
|
3944
|
+
await writeFile(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
|
|
3945
|
+
const ui = await execa("pnpm", [
|
|
3946
|
+
"dlx",
|
|
3947
|
+
"shadcn@latest",
|
|
3948
|
+
"init",
|
|
3949
|
+
"--preset",
|
|
3950
|
+
"nova",
|
|
3951
|
+
"--base",
|
|
3952
|
+
"base",
|
|
3953
|
+
"--yes",
|
|
3954
|
+
"--no-monorepo"
|
|
3955
|
+
], {
|
|
3956
|
+
cwd: directory,
|
|
3957
|
+
reject: false,
|
|
3958
|
+
stdio: "inherit"
|
|
3959
|
+
});
|
|
3960
|
+
process.exitCode = ui.exitCode;
|
|
3961
|
+
if (ui.exitCode !== 0) return;
|
|
3070
3962
|
await cp(new URL("./template/", import.meta.url), directory, { recursive: true });
|
|
3071
3963
|
const configure = await execa("pnpm", [
|
|
3072
3964
|
"config",
|
|
@@ -3093,7 +3985,14 @@ program.command("init <directory>").description("Create a Cloudflare React Route
|
|
|
3093
3985
|
});
|
|
3094
3986
|
process.exitCode = install.exitCode;
|
|
3095
3987
|
if (install.exitCode !== 0) return;
|
|
3096
|
-
const response = await fetch(new URL("/api/apps", env.CTX_PLATFORM_URL), {
|
|
3988
|
+
const response = await fetch(new URL("/api/apps", env.CTX_PLATFORM_URL), {
|
|
3989
|
+
body: JSON.stringify(input),
|
|
3990
|
+
headers: {
|
|
3991
|
+
authorization: `Bearer ${accessToken}`,
|
|
3992
|
+
"content-type": "application/json"
|
|
3993
|
+
},
|
|
3994
|
+
method: "POST"
|
|
3995
|
+
});
|
|
3097
3996
|
if (!response.ok) throw new Error(`App creation failed: HTTP ${response.status}`);
|
|
3098
3997
|
const app = object({
|
|
3099
3998
|
id: uuid(),
|
|
@@ -3112,17 +4011,44 @@ program.command("init <directory>").description("Create a Cloudflare React Route
|
|
|
3112
4011
|
});
|
|
3113
4012
|
process.exitCode = git.exitCode;
|
|
3114
4013
|
});
|
|
3115
|
-
program.command("login").description("Sign in
|
|
4014
|
+
program.command("login").description("Sign in by approving a browser code and configure Git credentials for ContextLayer repositories").action(async () => {
|
|
4015
|
+
await login();
|
|
4016
|
+
await setupGit(new URL(import.meta.url));
|
|
4017
|
+
console.log("Git credentials configured for ContextLayer.");
|
|
4018
|
+
});
|
|
4019
|
+
program.command("git-credential <operation>").description("Git credential helper using the saved login; invoked automatically by Git").action(gitCredential);
|
|
3116
4020
|
program.command("whoami").description("Show your ContextLayer user ID using the saved login").action(whoami);
|
|
3117
|
-
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) => {
|
|
3118
4022
|
if (!target || !operation) connections.error("Expected: ctx connections <target> list");
|
|
3119
4023
|
await listAppConnections(target);
|
|
3120
4024
|
});
|
|
3121
|
-
connections.command("list").description("List
|
|
3122
|
-
|
|
3123
|
-
|
|
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) => {
|
|
3124
4033
|
await assignAppConnection(target, slug, connectionId);
|
|
3125
4034
|
});
|
|
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) => {
|
|
4036
|
+
const input = object({
|
|
4037
|
+
name: string().min(1),
|
|
4038
|
+
prompt: string().min(1)
|
|
4039
|
+
}).parse({
|
|
4040
|
+
name,
|
|
4041
|
+
prompt
|
|
4042
|
+
});
|
|
4043
|
+
console.log(await runLocalAgent(input.name, input.prompt));
|
|
4044
|
+
});
|
|
4045
|
+
const secrets = program.command("secrets").description("Save or drop Owner-owned shared secrets through the authenticated platform").option("--org <org_slug>", "Use this organization's Owner; defaults to the signed-in user");
|
|
4046
|
+
secrets.command("set").argument("<name>", "Secret name: uppercase letters, digits, and underscores; cannot start with a digit").description("Save a secret with a masked password prompt; returns only Owner and name").option("--stdin", "Read the exact UTF-8 value from stdin instead of prompting; preserves whitespace and newlines").action(async (name, _options, command) => {
|
|
4047
|
+
await setSecret(secretNameSchema.parse(name), secretOptionsSchema.parse(command.optsWithGlobals()));
|
|
4048
|
+
});
|
|
4049
|
+
secrets.command("drop").argument("<name>", "Secret name: uppercase letters, digits, and underscores; cannot start with a digit").description("Delete the selected Owner's shared secret; returns only Owner and name").action(async (name, _options, command) => {
|
|
4050
|
+
await dropSecret(secretNameSchema.parse(name), secretOptionsSchema.parse(command.optsWithGlobals()).org);
|
|
4051
|
+
});
|
|
3126
4052
|
await program.parseAsync();
|
|
3127
4053
|
//#endregion
|
|
3128
4054
|
export {};
|