@usecontextlayer/cli 0.12.0 → 0.13.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-CRgSQabE.mjs} +274 -6
- package/dist/app-CRgSQabE.mjs.map +1 -0
- package/dist/cli.mjs +911 -11
- package/dist/cli.mjs.map +1 -1
- package/dist/template/app/root.tsx +38 -0
- package/dist/template/vite.config.ts +1 -1
- package/dist/template/workers/app.ts +1 -1
- package/dist/template/workers/local-tools/index.ts +1 -1
- package/dist/vite.d.mts +1 -0
- package/dist/vite.mjs +2 -1
- package/dist/vite.mjs.map +1 -1
- package/package.json +5 -1
- 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 { _ as url, a as whoami, c as array, d as literal, f as looseObject, g as unknown, h as string, i as login, l as boolean, m as record, n as getAccessToken, o as env, p as object, r as getCurrentUser, s as _enum, t as getLocalAppId, u as hostname, v as uuid, y as execa } from "./app-CRgSQabE.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,6 +2967,43 @@ 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
|
|
2965
3007
|
//#region connections.ts
|
|
2966
3008
|
async function resolveAppTarget(target) {
|
|
2967
3009
|
if (target !== "local") return target;
|
|
@@ -3045,12 +3087,820 @@ async function listConnections() {
|
|
|
3045
3087
|
console.table(connections);
|
|
3046
3088
|
}
|
|
3047
3089
|
//#endregion
|
|
3090
|
+
//#region git-credential.ts
|
|
3091
|
+
async function setupGit(cli) {
|
|
3092
|
+
const key = `credential.${new URL("/git", env.CTX_PLATFORM_URL).href}.helper`;
|
|
3093
|
+
const command = [
|
|
3094
|
+
process.execPath,
|
|
3095
|
+
fileURLToPath(cli),
|
|
3096
|
+
"git-credential"
|
|
3097
|
+
].map((argument) => `'${argument.replaceAll("'", "'\\''")}'`).join(" ");
|
|
3098
|
+
await execa("git", [
|
|
3099
|
+
"config",
|
|
3100
|
+
"--global",
|
|
3101
|
+
"--replace-all",
|
|
3102
|
+
key,
|
|
3103
|
+
""
|
|
3104
|
+
]);
|
|
3105
|
+
await execa("git", [
|
|
3106
|
+
"config",
|
|
3107
|
+
"--global",
|
|
3108
|
+
"--add",
|
|
3109
|
+
key,
|
|
3110
|
+
`!${command}`
|
|
3111
|
+
]);
|
|
3112
|
+
}
|
|
3113
|
+
async function gitCredential(operation) {
|
|
3114
|
+
if (operation === "capability") {
|
|
3115
|
+
process.stdout.write("version 0\ncapability authtype\n");
|
|
3116
|
+
return;
|
|
3117
|
+
}
|
|
3118
|
+
if (operation !== "get") return;
|
|
3119
|
+
const attributes = new URLSearchParams();
|
|
3120
|
+
const lines = createInterface({ input: process.stdin });
|
|
3121
|
+
for await (const line of lines) {
|
|
3122
|
+
if (line === "") break;
|
|
3123
|
+
const separator = line.indexOf("=");
|
|
3124
|
+
attributes.append(line.slice(0, separator), line.slice(separator + 1));
|
|
3125
|
+
}
|
|
3126
|
+
literal("authtype").parse(attributes.getAll("capability[]").find((c) => c === "authtype"));
|
|
3127
|
+
process.stdout.write(`capability[]=authtype\nauthtype=Bearer\ncredential=${await getAccessToken()}\n\n`);
|
|
3128
|
+
}
|
|
3129
|
+
//#endregion
|
|
3048
3130
|
//#region package.json
|
|
3049
|
-
var version = "0.
|
|
3131
|
+
var version = "0.13.0";
|
|
3132
|
+
//#endregion
|
|
3133
|
+
//#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
3134
|
+
const getCodePointsLength = (() => {
|
|
3135
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
3136
|
+
return (input) => {
|
|
3137
|
+
let surrogatePairsNr = 0;
|
|
3138
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
3139
|
+
while (SURROGATE_PAIR_RE.test(input)) surrogatePairsNr += 1;
|
|
3140
|
+
return input.length - surrogatePairsNr;
|
|
3141
|
+
};
|
|
3142
|
+
})();
|
|
3143
|
+
const isFullWidth = (x) => {
|
|
3144
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
3145
|
+
};
|
|
3146
|
+
const isWideNotCJKTNotEmoji = (x) => {
|
|
3147
|
+
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;
|
|
3148
|
+
};
|
|
3149
|
+
//#endregion
|
|
3150
|
+
//#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
|
|
3151
|
+
const ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
3152
|
+
const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
3153
|
+
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;
|
|
3154
|
+
const TAB_RE = /\t{1,1000}/y;
|
|
3155
|
+
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;
|
|
3156
|
+
const LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
3157
|
+
const MODIFIER_RE = /\p{M}+/gu;
|
|
3158
|
+
const NO_TRUNCATION$1 = {
|
|
3159
|
+
limit: Infinity,
|
|
3160
|
+
ellipsis: ""
|
|
3161
|
+
};
|
|
3162
|
+
const getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
|
|
3163
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
3164
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
3165
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION$1, widthOptions).width : 0);
|
|
3166
|
+
const ANSI_WIDTH = 0;
|
|
3167
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
3168
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
3169
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
3170
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
3171
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
3172
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
3173
|
+
const PARSE_BLOCKS = [
|
|
3174
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
3175
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
3176
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
3177
|
+
[TAB_RE, TAB_WIDTH],
|
|
3178
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
3179
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
3180
|
+
];
|
|
3181
|
+
let indexPrev = 0;
|
|
3182
|
+
let index = 0;
|
|
3183
|
+
let length = input.length;
|
|
3184
|
+
let lengthExtra = 0;
|
|
3185
|
+
let truncationEnabled = false;
|
|
3186
|
+
let truncationIndex = length;
|
|
3187
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
3188
|
+
let unmatchedStart = 0;
|
|
3189
|
+
let unmatchedEnd = 0;
|
|
3190
|
+
let width = 0;
|
|
3191
|
+
let widthExtra = 0;
|
|
3192
|
+
outer: while (true) {
|
|
3193
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
3194
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
3195
|
+
lengthExtra = 0;
|
|
3196
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
3197
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
3198
|
+
if (isFullWidth(codePoint)) widthExtra = FULL_WIDTH_WIDTH;
|
|
3199
|
+
else if (isWideNotCJKTNotEmoji(codePoint)) widthExtra = WIDE_WIDTH;
|
|
3200
|
+
else widthExtra = REGULAR_WIDTH;
|
|
3201
|
+
if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
3202
|
+
if (width + widthExtra > LIMIT) {
|
|
3203
|
+
truncationEnabled = true;
|
|
3204
|
+
break outer;
|
|
3205
|
+
}
|
|
3206
|
+
lengthExtra += char.length;
|
|
3207
|
+
width += widthExtra;
|
|
3208
|
+
}
|
|
3209
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
3210
|
+
}
|
|
3211
|
+
if (index >= length) break outer;
|
|
3212
|
+
for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
|
|
3213
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
3214
|
+
BLOCK_RE.lastIndex = index;
|
|
3215
|
+
if (BLOCK_RE.test(input)) {
|
|
3216
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
3217
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
3218
|
+
if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
3219
|
+
if (width + widthExtra > LIMIT) {
|
|
3220
|
+
truncationEnabled = true;
|
|
3221
|
+
break outer;
|
|
3222
|
+
}
|
|
3223
|
+
width += widthExtra;
|
|
3224
|
+
unmatchedStart = indexPrev;
|
|
3225
|
+
unmatchedEnd = index;
|
|
3226
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
3227
|
+
continue outer;
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
index += 1;
|
|
3231
|
+
}
|
|
3232
|
+
return {
|
|
3233
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
3234
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
3235
|
+
truncated: truncationEnabled,
|
|
3236
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
3237
|
+
};
|
|
3238
|
+
};
|
|
3239
|
+
//#endregion
|
|
3240
|
+
//#region ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
|
|
3241
|
+
const NO_TRUNCATION = {
|
|
3242
|
+
limit: Infinity,
|
|
3243
|
+
ellipsis: "",
|
|
3244
|
+
ellipsisWidth: 0
|
|
3245
|
+
};
|
|
3246
|
+
const fastStringWidth = (input, options = {}) => {
|
|
3247
|
+
return getStringTruncatedWidth(input, NO_TRUNCATION, options).width;
|
|
3248
|
+
};
|
|
3249
|
+
//#endregion
|
|
3250
|
+
//#region ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
|
|
3251
|
+
const ESC = "\x1B";
|
|
3252
|
+
const CSI = "";
|
|
3253
|
+
const END_CODE = 39;
|
|
3254
|
+
const ANSI_ESCAPE_BELL = "\x07";
|
|
3255
|
+
const ANSI_CSI = "[";
|
|
3256
|
+
const ANSI_OSC = "]";
|
|
3257
|
+
const ANSI_SGR_TERMINATOR = "m";
|
|
3258
|
+
const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
3259
|
+
const GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
3260
|
+
const getClosingCode = (openingCode) => {
|
|
3261
|
+
if (openingCode >= 30 && openingCode <= 37) return 39;
|
|
3262
|
+
if (openingCode >= 90 && openingCode <= 97) return 39;
|
|
3263
|
+
if (openingCode >= 40 && openingCode <= 47) return 49;
|
|
3264
|
+
if (openingCode >= 100 && openingCode <= 107) return 49;
|
|
3265
|
+
if (openingCode === 1 || openingCode === 2) return 22;
|
|
3266
|
+
if (openingCode === 3) return 23;
|
|
3267
|
+
if (openingCode === 4) return 24;
|
|
3268
|
+
if (openingCode === 7) return 27;
|
|
3269
|
+
if (openingCode === 8) return 28;
|
|
3270
|
+
if (openingCode === 9) return 29;
|
|
3271
|
+
if (openingCode === 0) return 0;
|
|
3272
|
+
};
|
|
3273
|
+
const wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
3274
|
+
const wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
3275
|
+
const wrapWord = (rows, word, columns) => {
|
|
3276
|
+
const characters = word[Symbol.iterator]();
|
|
3277
|
+
let isInsideEscape = false;
|
|
3278
|
+
let isInsideLinkEscape = false;
|
|
3279
|
+
let lastRow = rows.at(-1);
|
|
3280
|
+
let visible = lastRow === void 0 ? 0 : fastStringWidth(lastRow);
|
|
3281
|
+
let currentCharacter = characters.next();
|
|
3282
|
+
let nextCharacter = characters.next();
|
|
3283
|
+
let rawCharacterIndex = 0;
|
|
3284
|
+
while (!currentCharacter.done) {
|
|
3285
|
+
const character = currentCharacter.value;
|
|
3286
|
+
const characterLength = fastStringWidth(character);
|
|
3287
|
+
if (visible + characterLength <= columns) rows[rows.length - 1] += character;
|
|
3288
|
+
else {
|
|
3289
|
+
rows.push(character);
|
|
3290
|
+
visible = 0;
|
|
3291
|
+
}
|
|
3292
|
+
if (character === ESC || character === CSI) {
|
|
3293
|
+
isInsideEscape = true;
|
|
3294
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
3295
|
+
}
|
|
3296
|
+
if (isInsideEscape) {
|
|
3297
|
+
if (isInsideLinkEscape) {
|
|
3298
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
3299
|
+
isInsideEscape = false;
|
|
3300
|
+
isInsideLinkEscape = false;
|
|
3301
|
+
}
|
|
3302
|
+
} else if (character === ANSI_SGR_TERMINATOR) isInsideEscape = false;
|
|
3303
|
+
} else {
|
|
3304
|
+
visible += characterLength;
|
|
3305
|
+
if (visible === columns && !nextCharacter.done) {
|
|
3306
|
+
rows.push("");
|
|
3307
|
+
visible = 0;
|
|
3308
|
+
}
|
|
3309
|
+
}
|
|
3310
|
+
currentCharacter = nextCharacter;
|
|
3311
|
+
nextCharacter = characters.next();
|
|
3312
|
+
rawCharacterIndex += character.length;
|
|
3313
|
+
}
|
|
3314
|
+
lastRow = rows.at(-1);
|
|
3315
|
+
if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) rows[rows.length - 2] += rows.pop();
|
|
3316
|
+
};
|
|
3317
|
+
const stringVisibleTrimSpacesRight = (string) => {
|
|
3318
|
+
const words = string.split(" ");
|
|
3319
|
+
let last = words.length;
|
|
3320
|
+
while (last) {
|
|
3321
|
+
if (fastStringWidth(words[last - 1])) break;
|
|
3322
|
+
last--;
|
|
3323
|
+
}
|
|
3324
|
+
if (last === words.length) return string;
|
|
3325
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
3326
|
+
};
|
|
3327
|
+
const exec = (string, columns, options = {}) => {
|
|
3328
|
+
if (options.trim !== false && string.trim() === "") return "";
|
|
3329
|
+
let returnValue = "";
|
|
3330
|
+
let escapeCode;
|
|
3331
|
+
let escapeUrl;
|
|
3332
|
+
const words = string.split(" ");
|
|
3333
|
+
let rows = [""];
|
|
3334
|
+
let rowLength = 0;
|
|
3335
|
+
for (let index = 0; index < words.length; index++) {
|
|
3336
|
+
const word = words[index];
|
|
3337
|
+
if (options.trim !== false) {
|
|
3338
|
+
const row = rows.at(-1) ?? "";
|
|
3339
|
+
const trimmed = row.trimStart();
|
|
3340
|
+
if (row.length !== trimmed.length) {
|
|
3341
|
+
rows[rows.length - 1] = trimmed;
|
|
3342
|
+
rowLength = fastStringWidth(trimmed);
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
if (index !== 0) {
|
|
3346
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
3347
|
+
rows.push("");
|
|
3348
|
+
rowLength = 0;
|
|
3349
|
+
}
|
|
3350
|
+
if (rowLength || options.trim === false) {
|
|
3351
|
+
rows[rows.length - 1] += " ";
|
|
3352
|
+
rowLength++;
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
const wordLength = fastStringWidth(word);
|
|
3356
|
+
if (options.hard && wordLength > columns) {
|
|
3357
|
+
const remainingColumns = columns - rowLength;
|
|
3358
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
3359
|
+
if (Math.floor((wordLength - 1) / columns) < breaksStartingThisLine) rows.push("");
|
|
3360
|
+
wrapWord(rows, word, columns);
|
|
3361
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3362
|
+
continue;
|
|
3363
|
+
}
|
|
3364
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
3365
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
3366
|
+
wrapWord(rows, word, columns);
|
|
3367
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3368
|
+
continue;
|
|
3369
|
+
}
|
|
3370
|
+
rows.push("");
|
|
3371
|
+
rowLength = 0;
|
|
3372
|
+
}
|
|
3373
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
3374
|
+
wrapWord(rows, word, columns);
|
|
3375
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3376
|
+
continue;
|
|
3377
|
+
}
|
|
3378
|
+
rows[rows.length - 1] += word;
|
|
3379
|
+
rowLength += wordLength;
|
|
3380
|
+
}
|
|
3381
|
+
if (options.trim !== false) rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
3382
|
+
const preString = rows.join("\n");
|
|
3383
|
+
let inSurrogate = false;
|
|
3384
|
+
for (let i = 0; i < preString.length; i++) {
|
|
3385
|
+
const character = preString[i];
|
|
3386
|
+
returnValue += character;
|
|
3387
|
+
if (!inSurrogate) {
|
|
3388
|
+
inSurrogate = character >= "\ud800" && character <= "\udbff";
|
|
3389
|
+
if (inSurrogate) continue;
|
|
3390
|
+
} else inSurrogate = false;
|
|
3391
|
+
if (character === ESC || character === CSI) {
|
|
3392
|
+
GROUP_REGEX.lastIndex = i + 1;
|
|
3393
|
+
const groups = GROUP_REGEX.exec(preString)?.groups;
|
|
3394
|
+
if (groups?.code !== void 0) {
|
|
3395
|
+
const code = Number.parseFloat(groups.code);
|
|
3396
|
+
escapeCode = code === END_CODE ? void 0 : code;
|
|
3397
|
+
} else if (groups?.uri !== void 0) escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
|
|
3398
|
+
}
|
|
3399
|
+
if (preString[i + 1] === "\n") {
|
|
3400
|
+
if (escapeUrl) returnValue += wrapAnsiHyperlink("");
|
|
3401
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
|
|
3402
|
+
if (escapeCode && closingCode) returnValue += wrapAnsiCode(closingCode);
|
|
3403
|
+
} else if (character === "\n") {
|
|
3404
|
+
if (escapeCode && getClosingCode(escapeCode)) returnValue += wrapAnsiCode(escapeCode);
|
|
3405
|
+
if (escapeUrl) returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
return returnValue;
|
|
3409
|
+
};
|
|
3410
|
+
const CRLF_OR_LF = /\r?\n/;
|
|
3411
|
+
function wrapAnsi(string, columns, options) {
|
|
3412
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
|
|
3413
|
+
}
|
|
3414
|
+
//#endregion
|
|
3415
|
+
//#region ../../node_modules/.pnpm/@clack+core@1.5.1/node_modules/@clack/core/dist/index.mjs
|
|
3416
|
+
var import_src = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
3417
|
+
const ESC = "\x1B";
|
|
3418
|
+
const CSI = `${ESC}[`;
|
|
3419
|
+
const beep = "\x07";
|
|
3420
|
+
const cursor = {
|
|
3421
|
+
to(x, y) {
|
|
3422
|
+
if (!y) return `${CSI}${x + 1}G`;
|
|
3423
|
+
return `${CSI}${y + 1};${x + 1}H`;
|
|
3424
|
+
},
|
|
3425
|
+
move(x, y) {
|
|
3426
|
+
let ret = "";
|
|
3427
|
+
if (x < 0) ret += `${CSI}${-x}D`;
|
|
3428
|
+
else if (x > 0) ret += `${CSI}${x}C`;
|
|
3429
|
+
if (y < 0) ret += `${CSI}${-y}A`;
|
|
3430
|
+
else if (y > 0) ret += `${CSI}${y}B`;
|
|
3431
|
+
return ret;
|
|
3432
|
+
},
|
|
3433
|
+
up: (count = 1) => `${CSI}${count}A`,
|
|
3434
|
+
down: (count = 1) => `${CSI}${count}B`,
|
|
3435
|
+
forward: (count = 1) => `${CSI}${count}C`,
|
|
3436
|
+
backward: (count = 1) => `${CSI}${count}D`,
|
|
3437
|
+
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|
3438
|
+
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|
3439
|
+
left: `${CSI}G`,
|
|
3440
|
+
hide: `${CSI}?25l`,
|
|
3441
|
+
show: `${CSI}?25h`,
|
|
3442
|
+
save: `${ESC}7`,
|
|
3443
|
+
restore: `${ESC}8`
|
|
3444
|
+
};
|
|
3445
|
+
module.exports = {
|
|
3446
|
+
cursor,
|
|
3447
|
+
scroll: {
|
|
3448
|
+
up: (count = 1) => `${CSI}S`.repeat(count),
|
|
3449
|
+
down: (count = 1) => `${CSI}T`.repeat(count)
|
|
3450
|
+
},
|
|
3451
|
+
erase: {
|
|
3452
|
+
screen: `${CSI}2J`,
|
|
3453
|
+
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|
3454
|
+
down: (count = 1) => `${CSI}J`.repeat(count),
|
|
3455
|
+
line: `${CSI}2K`,
|
|
3456
|
+
lineEnd: `${CSI}K`,
|
|
3457
|
+
lineStart: `${CSI}1K`,
|
|
3458
|
+
lines(count) {
|
|
3459
|
+
let clear = "";
|
|
3460
|
+
for (let i = 0; i < count; i++) clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
3461
|
+
if (count) clear += cursor.left;
|
|
3462
|
+
return clear;
|
|
3463
|
+
}
|
|
3464
|
+
},
|
|
3465
|
+
beep
|
|
3466
|
+
};
|
|
3467
|
+
})))();
|
|
3468
|
+
const settings = {
|
|
3469
|
+
actions: /* @__PURE__ */ new Set([
|
|
3470
|
+
"up",
|
|
3471
|
+
"down",
|
|
3472
|
+
"left",
|
|
3473
|
+
"right",
|
|
3474
|
+
"space",
|
|
3475
|
+
"enter",
|
|
3476
|
+
"cancel"
|
|
3477
|
+
]),
|
|
3478
|
+
aliases: /* @__PURE__ */ new Map([
|
|
3479
|
+
["k", "up"],
|
|
3480
|
+
["j", "down"],
|
|
3481
|
+
["h", "left"],
|
|
3482
|
+
["l", "right"],
|
|
3483
|
+
["", "cancel"],
|
|
3484
|
+
["escape", "cancel"]
|
|
3485
|
+
]),
|
|
3486
|
+
messages: {
|
|
3487
|
+
cancel: "Canceled",
|
|
3488
|
+
error: "Something went wrong"
|
|
3489
|
+
},
|
|
3490
|
+
withGuide: true,
|
|
3491
|
+
accessible: void 0,
|
|
3492
|
+
date: {
|
|
3493
|
+
monthNames: [...[
|
|
3494
|
+
"January",
|
|
3495
|
+
"February",
|
|
3496
|
+
"March",
|
|
3497
|
+
"April",
|
|
3498
|
+
"May",
|
|
3499
|
+
"June",
|
|
3500
|
+
"July",
|
|
3501
|
+
"August",
|
|
3502
|
+
"September",
|
|
3503
|
+
"October",
|
|
3504
|
+
"November",
|
|
3505
|
+
"December"
|
|
3506
|
+
]],
|
|
3507
|
+
messages: {
|
|
3508
|
+
required: "Please enter a valid date",
|
|
3509
|
+
invalidMonth: "There are only 12 months in a year",
|
|
3510
|
+
invalidDay: (n, e) => `There are only ${n} days in ${e}`,
|
|
3511
|
+
afterMin: (n) => `Date must be on or after ${n.toISOString().slice(0, 10)}`,
|
|
3512
|
+
beforeMax: (n) => `Date must be on or before ${n.toISOString().slice(0, 10)}`
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
};
|
|
3516
|
+
function isAccessible(n) {
|
|
3517
|
+
if (n !== void 0) return n;
|
|
3518
|
+
if (settings.accessible !== void 0) return settings.accessible;
|
|
3519
|
+
const e = process.env.ACCESSIBLE;
|
|
3520
|
+
return e !== void 0 && e !== "" && e !== "0" && e !== "false";
|
|
3521
|
+
}
|
|
3522
|
+
function isActionKey(n, e) {
|
|
3523
|
+
if (typeof n == "string") return settings.aliases.get(n) === e;
|
|
3524
|
+
for (const s of n) if (s !== void 0 && isActionKey(s, e)) return true;
|
|
3525
|
+
return false;
|
|
3526
|
+
}
|
|
3527
|
+
function diffLines(i, s) {
|
|
3528
|
+
if (i === s) return;
|
|
3529
|
+
const e = i.split(`
|
|
3530
|
+
`), t = s.split(`
|
|
3531
|
+
`), r = Math.max(e.length, t.length), f = [];
|
|
3532
|
+
for (let n = 0; n < r; n++) e[n] !== t[n] && f.push(n);
|
|
3533
|
+
return {
|
|
3534
|
+
lines: f,
|
|
3535
|
+
numLinesBefore: e.length,
|
|
3536
|
+
numLinesAfter: t.length,
|
|
3537
|
+
numLines: r
|
|
3538
|
+
};
|
|
3539
|
+
}
|
|
3540
|
+
globalThis.process.platform.startsWith("win");
|
|
3541
|
+
const CANCEL_SYMBOL = Symbol("clack:cancel");
|
|
3542
|
+
function isCancel(e) {
|
|
3543
|
+
return e === CANCEL_SYMBOL;
|
|
3544
|
+
}
|
|
3545
|
+
function setRawMode(e, r) {
|
|
3546
|
+
const o = e;
|
|
3547
|
+
o.isTTY && o.setRawMode(r);
|
|
3548
|
+
}
|
|
3549
|
+
const getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
|
|
3550
|
+
function runValidation(e, a) {
|
|
3551
|
+
if ("~standard" in e) {
|
|
3552
|
+
const n = e["~standard"].validate(a);
|
|
3553
|
+
return n instanceof Promise ? n.then((r) => r.issues?.at(0)?.message) : n.issues?.at(0)?.message;
|
|
3554
|
+
}
|
|
3555
|
+
return e(a);
|
|
3556
|
+
}
|
|
3557
|
+
var y = class {
|
|
3558
|
+
input;
|
|
3559
|
+
output;
|
|
3560
|
+
_abortSignal;
|
|
3561
|
+
rl;
|
|
3562
|
+
opts;
|
|
3563
|
+
_render;
|
|
3564
|
+
_track = false;
|
|
3565
|
+
_prevFrame = "";
|
|
3566
|
+
_subscribers = /* @__PURE__ */ new Map();
|
|
3567
|
+
_cursor = 0;
|
|
3568
|
+
state = "initial";
|
|
3569
|
+
error = "";
|
|
3570
|
+
value;
|
|
3571
|
+
userInput = "";
|
|
3572
|
+
/**
|
|
3573
|
+
* Whether accessible (static, screen-reader friendly) output is enabled for
|
|
3574
|
+
* this prompt, resolved from the `accessible` option, the global setting,
|
|
3575
|
+
* and the `ACCESSIBLE` env var.
|
|
3576
|
+
*/
|
|
3577
|
+
get accessible() {
|
|
3578
|
+
return isAccessible(this.opts.accessible);
|
|
3579
|
+
}
|
|
3580
|
+
constructor(t, e = true) {
|
|
3581
|
+
const { input: i = stdin, output: s = stdout, render: r, signal: n, ...o } = t;
|
|
3582
|
+
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;
|
|
3583
|
+
}
|
|
3584
|
+
/**
|
|
3585
|
+
* Unsubscribe all listeners
|
|
3586
|
+
*/
|
|
3587
|
+
unsubscribe() {
|
|
3588
|
+
this._subscribers.clear();
|
|
3589
|
+
}
|
|
3590
|
+
/**
|
|
3591
|
+
* Set a subscriber with opts
|
|
3592
|
+
* @param event - The event name
|
|
3593
|
+
*/
|
|
3594
|
+
setSubscriber(t, e) {
|
|
3595
|
+
const i = this._subscribers.get(t) ?? [];
|
|
3596
|
+
i.push(e), this._subscribers.set(t, i);
|
|
3597
|
+
}
|
|
3598
|
+
/**
|
|
3599
|
+
* Subscribe to an event
|
|
3600
|
+
* @param event - The event name
|
|
3601
|
+
* @param cb - The callback
|
|
3602
|
+
*/
|
|
3603
|
+
on(t, e) {
|
|
3604
|
+
this.setSubscriber(t, { cb: e });
|
|
3605
|
+
}
|
|
3606
|
+
/**
|
|
3607
|
+
* Subscribe to an event once
|
|
3608
|
+
* @param event - The event name
|
|
3609
|
+
* @param cb - The callback
|
|
3610
|
+
*/
|
|
3611
|
+
once(t, e) {
|
|
3612
|
+
this.setSubscriber(t, {
|
|
3613
|
+
cb: e,
|
|
3614
|
+
once: true
|
|
3615
|
+
});
|
|
3616
|
+
}
|
|
3617
|
+
/**
|
|
3618
|
+
* Emit an event with data
|
|
3619
|
+
* @param event - The event name
|
|
3620
|
+
* @param data - The data to pass to the callback
|
|
3621
|
+
*/
|
|
3622
|
+
emit(t, ...e) {
|
|
3623
|
+
const i = this._subscribers.get(t) ?? [], s = [];
|
|
3624
|
+
for (const r of i) r.cb(...e), r.once && s.push(() => i.splice(i.indexOf(r), 1));
|
|
3625
|
+
for (const r of s) r();
|
|
3626
|
+
}
|
|
3627
|
+
prompt() {
|
|
3628
|
+
return new Promise((t) => {
|
|
3629
|
+
if (this._abortSignal) {
|
|
3630
|
+
if (this._abortSignal.aborted) return this.state = "cancel", this.close(), t(CANCEL_SYMBOL);
|
|
3631
|
+
this._abortSignal.addEventListener("abort", () => {
|
|
3632
|
+
this.state = "cancel", this.close();
|
|
3633
|
+
}, { once: true });
|
|
3634
|
+
}
|
|
3635
|
+
this.rl = l__default.createInterface({
|
|
3636
|
+
input: this.input,
|
|
3637
|
+
tabSize: 2,
|
|
3638
|
+
prompt: "",
|
|
3639
|
+
escapeCodeTimeout: 50,
|
|
3640
|
+
terminal: true
|
|
3641
|
+
}), 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", () => {
|
|
3642
|
+
this.output.write(import_src.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(this.value);
|
|
3643
|
+
}), this.once("cancel", () => {
|
|
3644
|
+
this.output.write(import_src.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(CANCEL_SYMBOL);
|
|
3645
|
+
});
|
|
3646
|
+
});
|
|
3647
|
+
}
|
|
3648
|
+
_isActionKey(t, e) {
|
|
3649
|
+
return t === " ";
|
|
3650
|
+
}
|
|
3651
|
+
_shouldSubmit(t, e) {
|
|
3652
|
+
return true;
|
|
3653
|
+
}
|
|
3654
|
+
_setValue(t) {
|
|
3655
|
+
this.value = t, this.emit("value", this.value);
|
|
3656
|
+
}
|
|
3657
|
+
_setUserInput(t, e) {
|
|
3658
|
+
this.userInput = t ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
|
|
3659
|
+
}
|
|
3660
|
+
_clearUserInput() {
|
|
3661
|
+
this.rl?.write(null, {
|
|
3662
|
+
ctrl: true,
|
|
3663
|
+
name: "u"
|
|
3664
|
+
}), this._setUserInput("");
|
|
3665
|
+
}
|
|
3666
|
+
async onKeypress(t, e) {
|
|
3667
|
+
if (this.state !== "validating") {
|
|
3668
|
+
if (this._track && e.name !== "return" && (e.name && this._isActionKey(t, e) && this.rl?.write(null, {
|
|
3669
|
+
ctrl: true,
|
|
3670
|
+
name: "h"
|
|
3671
|
+
}), 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)) {
|
|
3672
|
+
if (this.opts.validate) {
|
|
3673
|
+
const i = runValidation(this.opts.validate, this.value);
|
|
3674
|
+
let s;
|
|
3675
|
+
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));
|
|
3676
|
+
}
|
|
3677
|
+
this.state !== "error" && (this.state = "submit");
|
|
3678
|
+
}
|
|
3679
|
+
isActionKey([
|
|
3680
|
+
t,
|
|
3681
|
+
e?.name,
|
|
3682
|
+
e?.sequence
|
|
3683
|
+
], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
close() {
|
|
3687
|
+
this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
|
|
3688
|
+
`), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
|
|
3689
|
+
}
|
|
3690
|
+
restoreCursor() {
|
|
3691
|
+
const t = wrapAnsi(this._prevFrame, process.stdout.columns, {
|
|
3692
|
+
hard: true,
|
|
3693
|
+
trim: false
|
|
3694
|
+
}).split(`
|
|
3695
|
+
`).length - 1;
|
|
3696
|
+
this.output.write(import_src.cursor.move(-999, t * -1));
|
|
3697
|
+
}
|
|
3698
|
+
render() {
|
|
3699
|
+
const t = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
|
|
3700
|
+
hard: true,
|
|
3701
|
+
trim: false
|
|
3702
|
+
});
|
|
3703
|
+
if (t !== this._prevFrame) {
|
|
3704
|
+
if (this.state === "initial") this.output.write(import_src.cursor.hide);
|
|
3705
|
+
else {
|
|
3706
|
+
const e = diffLines(this._prevFrame, t), i = getRows(this.output);
|
|
3707
|
+
if (this.restoreCursor(), e) {
|
|
3708
|
+
const s = Math.max(0, e.numLinesAfter - i), r = Math.max(0, e.numLinesBefore - i);
|
|
3709
|
+
let n = e.lines.find((o) => o >= s);
|
|
3710
|
+
if (n === void 0) {
|
|
3711
|
+
this._prevFrame = t;
|
|
3712
|
+
return;
|
|
3713
|
+
}
|
|
3714
|
+
if (e.lines.length === 1) {
|
|
3715
|
+
this.output.write(import_src.cursor.move(0, n - r)), this.output.write(import_src.erase.lines(1));
|
|
3716
|
+
const o = t.split(`
|
|
3717
|
+
`);
|
|
3718
|
+
this.output.write(o[n]), this._prevFrame = t, this.output.write(import_src.cursor.move(0, o.length - n - 1));
|
|
3719
|
+
return;
|
|
3720
|
+
} else if (e.lines.length > 1) {
|
|
3721
|
+
if (s < r) n = s;
|
|
3722
|
+
else {
|
|
3723
|
+
const h = n - r;
|
|
3724
|
+
h > 0 && this.output.write(import_src.cursor.move(0, h));
|
|
3725
|
+
}
|
|
3726
|
+
this.output.write(import_src.erase.down());
|
|
3727
|
+
const f = t.split(`
|
|
3728
|
+
`).slice(n);
|
|
3729
|
+
this.output.write(f.join(`
|
|
3730
|
+
`)), this._prevFrame = t;
|
|
3731
|
+
return;
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
this.output.write(import_src.erase.down());
|
|
3735
|
+
}
|
|
3736
|
+
this.output.write(t), this.state === "initial" && (this.state = "active"), this._prevFrame = t;
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
};
|
|
3740
|
+
let u$1 = class u extends y {
|
|
3741
|
+
_mask = "•";
|
|
3742
|
+
get cursor() {
|
|
3743
|
+
return this._cursor;
|
|
3744
|
+
}
|
|
3745
|
+
get masked() {
|
|
3746
|
+
return this.userInput.replaceAll(/./g, this._mask);
|
|
3747
|
+
}
|
|
3748
|
+
get userInputWithCursor() {
|
|
3749
|
+
if (this.state === "submit" || this.state === "cancel") return this.masked;
|
|
3750
|
+
const t = this.userInput;
|
|
3751
|
+
if (this.cursor >= t.length) return `${this.masked}${styleText(["inverse", "hidden"], "_")}`;
|
|
3752
|
+
const s = this.masked, r = s.slice(0, this.cursor), i = s.slice(this.cursor, this.cursor + 1), o = s.slice(this.cursor + 1);
|
|
3753
|
+
return `${r}${styleText("inverse", i)}${o}`;
|
|
3754
|
+
}
|
|
3755
|
+
clear() {
|
|
3756
|
+
this._clearUserInput();
|
|
3757
|
+
}
|
|
3758
|
+
constructor({ mask: t, ...s }) {
|
|
3759
|
+
super(s), this._mask = t ?? "•", this.on("userInput", (r) => {
|
|
3760
|
+
this._setValue(r);
|
|
3761
|
+
}), this.on("finalize", () => {
|
|
3762
|
+
this.value === void 0 && (this.value = "");
|
|
3763
|
+
});
|
|
3764
|
+
}
|
|
3765
|
+
};
|
|
3766
|
+
//#endregion
|
|
3767
|
+
//#region ../../node_modules/.pnpm/@clack+prompts@1.8.1/node_modules/@clack/prompts/dist/index.mjs
|
|
3768
|
+
function isUnicodeSupported() {
|
|
3769
|
+
if (process$1.platform !== "win32") return process$1.env.TERM !== "linux";
|
|
3770
|
+
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";
|
|
3771
|
+
}
|
|
3772
|
+
const unicode = isUnicodeSupported();
|
|
3773
|
+
const unicodeOr = (o, e) => unicode ? o : e;
|
|
3774
|
+
const S_STEP_ACTIVE = unicodeOr("◆", "*");
|
|
3775
|
+
const S_STEP_CANCEL = unicodeOr("■", "x");
|
|
3776
|
+
const S_STEP_ERROR = unicodeOr("▲", "x");
|
|
3777
|
+
const S_STEP_SUBMIT = unicodeOr("◇", "o");
|
|
3778
|
+
const S_BAR = unicodeOr("│", "|");
|
|
3779
|
+
const S_BAR_END = unicodeOr("└", "—");
|
|
3780
|
+
const S_PASSWORD_MASK = unicodeOr("▪", "•");
|
|
3781
|
+
const symbol = (o) => {
|
|
3782
|
+
switch (o) {
|
|
3783
|
+
case "initial":
|
|
3784
|
+
case "active": return styleText("cyan", S_STEP_ACTIVE);
|
|
3785
|
+
case "cancel": return styleText("red", S_STEP_CANCEL);
|
|
3786
|
+
case "error": return styleText("yellow", S_STEP_ERROR);
|
|
3787
|
+
case "submit": return styleText("green", S_STEP_SUBMIT);
|
|
3788
|
+
case "validating": return styleText("dim", S_STEP_ACTIVE);
|
|
3789
|
+
}
|
|
3790
|
+
};
|
|
3791
|
+
`${styleText("dim", "↑/↓")}`, `${styleText("dim", "Space:")}`, `${styleText("dim", "Enter:")}`;
|
|
3792
|
+
const password = (e) => new u$1({
|
|
3793
|
+
validate: e.validate,
|
|
3794
|
+
mask: e.mask ?? S_PASSWORD_MASK,
|
|
3795
|
+
signal: e.signal,
|
|
3796
|
+
input: e.input,
|
|
3797
|
+
output: e.output,
|
|
3798
|
+
render() {
|
|
3799
|
+
const r = e.withGuide ?? settings.withGuide, o = `${r ? `${styleText("gray", S_BAR)}
|
|
3800
|
+
` : ""}${symbol(this.state)} ${e.message}
|
|
3801
|
+
`, m = this.userInputWithCursor, i = this.masked;
|
|
3802
|
+
switch (this.state) {
|
|
3803
|
+
case "error": {
|
|
3804
|
+
const s = r ? `${styleText("yellow", S_BAR)} ` : "", n = r ? `${styleText("yellow", S_BAR_END)} ` : "", d = i ?? "";
|
|
3805
|
+
return e.clearOnError && this.clear(), `${o.trim()}
|
|
3806
|
+
${s}${d}
|
|
3807
|
+
${n}${styleText("yellow", this.error)}
|
|
3808
|
+
`;
|
|
3809
|
+
}
|
|
3810
|
+
case "submit": return `${o}${r ? `${styleText("gray", S_BAR)} ` : ""}${i ? styleText("dim", i) : ""}`;
|
|
3811
|
+
case "cancel": return `${o}${r ? `${styleText("gray", S_BAR)} ` : ""}${i ? styleText(["strikethrough", "dim"], i) : ""}${i && r ? `
|
|
3812
|
+
${styleText("gray", S_BAR)}` : ""}`;
|
|
3813
|
+
default: return `${o}${r ? `${styleText("cyan", S_BAR)} ` : ""}${m}
|
|
3814
|
+
${r ? styleText("cyan", S_BAR_END) : ""}
|
|
3815
|
+
`;
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
}).prompt();
|
|
3819
|
+
`${styleText("dim", "↑/↓")}`, `${styleText("dim", "Enter:")}`;
|
|
3820
|
+
`${styleText("gray", S_BAR)}`;
|
|
3821
|
+
//#endregion
|
|
3822
|
+
//#region secrets.ts
|
|
3823
|
+
const secretNameSchema = string().regex(/^[A-Z_][A-Z0-9_]*$/);
|
|
3824
|
+
const secretOptionsSchema = object({
|
|
3825
|
+
org: string().min(1).optional(),
|
|
3826
|
+
stdin: boolean().default(false)
|
|
3827
|
+
});
|
|
3828
|
+
const valueSchema = string().min(1);
|
|
3829
|
+
const confirmationSchema = object({
|
|
3830
|
+
name: secretNameSchema,
|
|
3831
|
+
owner: object({
|
|
3832
|
+
id: string().min(1),
|
|
3833
|
+
type: _enum(["organization", "user"])
|
|
3834
|
+
})
|
|
3835
|
+
});
|
|
3836
|
+
async function resolveSecretUrl(name, org, headers) {
|
|
3837
|
+
let type;
|
|
3838
|
+
let id;
|
|
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);
|
|
3856
|
+
}
|
|
3857
|
+
async function setSecret(name, options) {
|
|
3858
|
+
const headers = { authorization: `Bearer ${await getAccessToken()}` };
|
|
3859
|
+
const url = await resolveSecretUrl(name, options.org, headers);
|
|
3860
|
+
let value;
|
|
3861
|
+
if (options.stdin) {
|
|
3862
|
+
process.stdin.setEncoding("utf8");
|
|
3863
|
+
value = "";
|
|
3864
|
+
for await (const chunk of process.stdin) value += chunk;
|
|
3865
|
+
} else {
|
|
3866
|
+
if (!process.stdin.isTTY) throw new Error("Use --stdin to read a secret without a terminal");
|
|
3867
|
+
const entered = await password({
|
|
3868
|
+
message: `Value for ${name}`,
|
|
3869
|
+
output: process.stderr,
|
|
3870
|
+
validate: valueSchema
|
|
3871
|
+
});
|
|
3872
|
+
if (isCancel(entered)) {
|
|
3873
|
+
process.exitCode = 130;
|
|
3874
|
+
return;
|
|
3875
|
+
}
|
|
3876
|
+
value = entered;
|
|
3877
|
+
}
|
|
3878
|
+
const response = await fetch(url, {
|
|
3879
|
+
body: JSON.stringify({ value: valueSchema.parse(value) }),
|
|
3880
|
+
headers: {
|
|
3881
|
+
...headers,
|
|
3882
|
+
"content-type": "application/json"
|
|
3883
|
+
},
|
|
3884
|
+
method: "PUT"
|
|
3885
|
+
});
|
|
3886
|
+
if (!response.ok) throw new Error(`Secret save failed: HTTP ${response.status}`);
|
|
3887
|
+
console.log(JSON.stringify(confirmationSchema.parse(await response.json())));
|
|
3888
|
+
}
|
|
3889
|
+
async function dropSecret(name, org) {
|
|
3890
|
+
const headers = { authorization: `Bearer ${await getAccessToken()}` };
|
|
3891
|
+
const response = await fetch(await resolveSecretUrl(name, org, headers), {
|
|
3892
|
+
headers,
|
|
3893
|
+
method: "DELETE"
|
|
3894
|
+
});
|
|
3895
|
+
if (!response.ok) throw new Error(`Secret drop failed: HTTP ${response.status}`);
|
|
3896
|
+
console.log(JSON.stringify(confirmationSchema.parse(await response.json())));
|
|
3897
|
+
}
|
|
3050
3898
|
//#endregion
|
|
3051
3899
|
//#region cli.ts
|
|
3052
3900
|
const program = new Command().name("ctx").description("ContextLayer CLI").version(version);
|
|
3053
|
-
program.command("init <directory>").description("Create a Cloudflare React Router project with
|
|
3901
|
+
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) => {
|
|
3902
|
+
const input = object({ organization_slug: string().min(1).optional() }).parse({ organization_slug: options.org });
|
|
3903
|
+
const accessToken = await getAccessToken();
|
|
3054
3904
|
const result = await execa("pnpm", [
|
|
3055
3905
|
"create",
|
|
3056
3906
|
"cloudflare@latest",
|
|
@@ -3067,6 +3917,27 @@ program.command("init <directory>").description("Create a Cloudflare React Route
|
|
|
3067
3917
|
});
|
|
3068
3918
|
process.exitCode = result.exitCode;
|
|
3069
3919
|
if (result.exitCode !== 0) return;
|
|
3920
|
+
const tsconfigPath = join(directory, "tsconfig.json");
|
|
3921
|
+
const tsconfig = looseObject({ compilerOptions: record(string(), unknown()) }).parse(JSON.parse(await readFile(tsconfigPath, "utf8")));
|
|
3922
|
+
tsconfig.compilerOptions.paths = { "~/*": ["./app/*"] };
|
|
3923
|
+
await writeFile(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
|
|
3924
|
+
const ui = await execa("pnpm", [
|
|
3925
|
+
"dlx",
|
|
3926
|
+
"shadcn@latest",
|
|
3927
|
+
"init",
|
|
3928
|
+
"--preset",
|
|
3929
|
+
"nova",
|
|
3930
|
+
"--base",
|
|
3931
|
+
"base",
|
|
3932
|
+
"--yes",
|
|
3933
|
+
"--no-monorepo"
|
|
3934
|
+
], {
|
|
3935
|
+
cwd: directory,
|
|
3936
|
+
reject: false,
|
|
3937
|
+
stdio: "inherit"
|
|
3938
|
+
});
|
|
3939
|
+
process.exitCode = ui.exitCode;
|
|
3940
|
+
if (ui.exitCode !== 0) return;
|
|
3070
3941
|
await cp(new URL("./template/", import.meta.url), directory, { recursive: true });
|
|
3071
3942
|
const configure = await execa("pnpm", [
|
|
3072
3943
|
"config",
|
|
@@ -3074,7 +3945,7 @@ program.command("init <directory>").description("Create a Cloudflare React Route
|
|
|
3074
3945
|
"--location=project",
|
|
3075
3946
|
"--json",
|
|
3076
3947
|
"minimumReleaseAgeExclude",
|
|
3077
|
-
"[\"@usecontextlayer/*\"
|
|
3948
|
+
"[\"@usecontextlayer/*\"]"
|
|
3078
3949
|
], {
|
|
3079
3950
|
cwd: directory,
|
|
3080
3951
|
reject: false,
|
|
@@ -3084,7 +3955,7 @@ program.command("init <directory>").description("Create a Cloudflare React Route
|
|
|
3084
3955
|
if (configure.exitCode !== 0) return;
|
|
3085
3956
|
const install = await execa("pnpm", [
|
|
3086
3957
|
"add",
|
|
3087
|
-
`@
|
|
3958
|
+
`@usecontextlayer/sdk@${version}`,
|
|
3088
3959
|
"zod@^4.4.3"
|
|
3089
3960
|
], {
|
|
3090
3961
|
cwd: directory,
|
|
@@ -3093,7 +3964,14 @@ program.command("init <directory>").description("Create a Cloudflare React Route
|
|
|
3093
3964
|
});
|
|
3094
3965
|
process.exitCode = install.exitCode;
|
|
3095
3966
|
if (install.exitCode !== 0) return;
|
|
3096
|
-
const response = await fetch(new URL("/api/apps", env.CTX_PLATFORM_URL), {
|
|
3967
|
+
const response = await fetch(new URL("/api/apps", env.CTX_PLATFORM_URL), {
|
|
3968
|
+
body: JSON.stringify(input),
|
|
3969
|
+
headers: {
|
|
3970
|
+
authorization: `Bearer ${accessToken}`,
|
|
3971
|
+
"content-type": "application/json"
|
|
3972
|
+
},
|
|
3973
|
+
method: "POST"
|
|
3974
|
+
});
|
|
3097
3975
|
if (!response.ok) throw new Error(`App creation failed: HTTP ${response.status}`);
|
|
3098
3976
|
const app = object({
|
|
3099
3977
|
id: uuid(),
|
|
@@ -3112,7 +3990,12 @@ program.command("init <directory>").description("Create a Cloudflare React Route
|
|
|
3112
3990
|
});
|
|
3113
3991
|
process.exitCode = git.exitCode;
|
|
3114
3992
|
});
|
|
3115
|
-
program.command("login").description("Sign in
|
|
3993
|
+
program.command("login").description("Sign in by approving a browser code and configure Git credentials for ContextLayer repositories").action(async () => {
|
|
3994
|
+
await login();
|
|
3995
|
+
await setupGit(new URL(import.meta.url));
|
|
3996
|
+
console.log("Git credentials configured for ContextLayer.");
|
|
3997
|
+
});
|
|
3998
|
+
program.command("git-credential <operation>").description("Git credential helper using the saved login; invoked automatically by Git").action(gitCredential);
|
|
3116
3999
|
program.command("whoami").description("Show your ContextLayer user ID using the saved login").action(whoami);
|
|
3117
4000
|
const connections = program.command("connections").description("Manage your connected accounts").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
4001
|
if (!target || !operation) connections.error("Expected: ctx connections <target> list");
|
|
@@ -3123,6 +4006,23 @@ connections.command("add <toolset>").description("Print a Composio authorization
|
|
|
3123
4006
|
program.command("connection").description("Assign a connection to an app requirement").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
4007
|
await assignAppConnection(target, slug, connectionId);
|
|
3125
4008
|
});
|
|
4009
|
+
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) => {
|
|
4010
|
+
const input = object({
|
|
4011
|
+
name: string().min(1),
|
|
4012
|
+
prompt: string().min(1)
|
|
4013
|
+
}).parse({
|
|
4014
|
+
name,
|
|
4015
|
+
prompt
|
|
4016
|
+
});
|
|
4017
|
+
console.log(await runLocalAgent(input.name, input.prompt));
|
|
4018
|
+
});
|
|
4019
|
+
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");
|
|
4020
|
+
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) => {
|
|
4021
|
+
await setSecret(secretNameSchema.parse(name), secretOptionsSchema.parse(command.optsWithGlobals()));
|
|
4022
|
+
});
|
|
4023
|
+
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) => {
|
|
4024
|
+
await dropSecret(secretNameSchema.parse(name), secretOptionsSchema.parse(command.optsWithGlobals()).org);
|
|
4025
|
+
});
|
|
3126
4026
|
await program.parseAsync();
|
|
3127
4027
|
//#endregion
|
|
3128
4028
|
export {};
|