@base44-preview/cli 0.1.15-pr.630.5b0c119 → 0.1.15-pr.630.5c9bc15
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/cli/index.js +655 -46
- package/dist/cli/index.js.map +14 -12
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -268401,6 +268401,10 @@ async function captureRequestBody(request, options) {
|
|
|
268401
268401
|
if (request.body == null) {
|
|
268402
268402
|
return;
|
|
268403
268403
|
}
|
|
268404
|
+
if (options.context.__redactBody) {
|
|
268405
|
+
options.context.__requestBody = "[redacted]";
|
|
268406
|
+
return;
|
|
268407
|
+
}
|
|
268404
268408
|
try {
|
|
268405
268409
|
const cloned = request.clone();
|
|
268406
268410
|
const text = await cloned.text();
|
|
@@ -270155,7 +270159,7 @@ function eventLine(event, elapsedMs, options = {}) {
|
|
|
270155
270159
|
return null;
|
|
270156
270160
|
case "waiting": {
|
|
270157
270161
|
const what = event.label || toolAlias(event.name);
|
|
270158
|
-
return source_default.yellow(`⏸ ${what} — needs your input (answer in the editor)`);
|
|
270162
|
+
return source_default.yellow(`⏸ ${what} — needs your input (${options.waitingHint ?? "answer in the editor"})`);
|
|
270159
270163
|
}
|
|
270160
270164
|
case "tool_end": {
|
|
270161
270165
|
const alias = toolAlias(event.name);
|
|
@@ -270343,6 +270347,10 @@ var CreatedAppSchema = object({
|
|
|
270343
270347
|
name: string2().nullish(),
|
|
270344
270348
|
imported_repo_url: string2().nullish()
|
|
270345
270349
|
});
|
|
270350
|
+
var WixCreatedAppSchema = object({
|
|
270351
|
+
app_id: string2().min(1),
|
|
270352
|
+
client_creation_id: string2().min(1)
|
|
270353
|
+
});
|
|
270346
270354
|
var AppStateSchema = object({
|
|
270347
270355
|
id: string2(),
|
|
270348
270356
|
app_type: string2().nullish(),
|
|
@@ -270382,7 +270390,8 @@ var ConversationMessageSchema = object({
|
|
|
270382
270390
|
name: string2(),
|
|
270383
270391
|
arguments_string: string2().nullish(),
|
|
270384
270392
|
status: string2().nullish(),
|
|
270385
|
-
results: unknown().nullish()
|
|
270393
|
+
results: unknown().nullish(),
|
|
270394
|
+
waiting_on: object({ kind: string2().nullish() }).nullish()
|
|
270386
270395
|
})).nullish()
|
|
270387
270396
|
});
|
|
270388
270397
|
var FullConversationSchema = object({
|
|
@@ -270399,6 +270408,24 @@ function parseOrThrow(schema, payload, what) {
|
|
|
270399
270408
|
function branchScope(branchId) {
|
|
270400
270409
|
return branchId ? { branch_id: branchId } : {};
|
|
270401
270410
|
}
|
|
270411
|
+
async function createWixLaunchedApp(options) {
|
|
270412
|
+
let response;
|
|
270413
|
+
try {
|
|
270414
|
+
response = await base44Client.post("api/wix/create-app", {
|
|
270415
|
+
timeout: false,
|
|
270416
|
+
context: { __redactBody: true },
|
|
270417
|
+
json: {
|
|
270418
|
+
prompt: options.prompt,
|
|
270419
|
+
signed_instance: options.signedInstance,
|
|
270420
|
+
...options.wixClientId ? { wix_client_id: options.wixClientId } : {}
|
|
270421
|
+
}
|
|
270422
|
+
});
|
|
270423
|
+
} catch (error) {
|
|
270424
|
+
throw await ApiError.fromHttpError(error, "creating app via Wix launch");
|
|
270425
|
+
}
|
|
270426
|
+
const created = parseOrThrow(WixCreatedAppSchema, await response.json(), "app");
|
|
270427
|
+
return { id: created.app_id, client_creation_id: created.client_creation_id };
|
|
270428
|
+
}
|
|
270402
270429
|
async function createApp(options) {
|
|
270403
270430
|
let response;
|
|
270404
270431
|
try {
|
|
@@ -270456,6 +270483,25 @@ async function getAppState(appId) {
|
|
|
270456
270483
|
}
|
|
270457
270484
|
return parseOrThrow(AppStateSchema, await response.json(), "app status");
|
|
270458
270485
|
}
|
|
270486
|
+
async function answerToolCall(options, branchId) {
|
|
270487
|
+
let response;
|
|
270488
|
+
try {
|
|
270489
|
+
response = await getAppClient().post("chat/submit-tool-call-input", {
|
|
270490
|
+
timeout: false,
|
|
270491
|
+
context: { __redactBody: true },
|
|
270492
|
+
searchParams: branchScope(branchId),
|
|
270493
|
+
json: {
|
|
270494
|
+
tool_call_id: options.toolCallId,
|
|
270495
|
+
action: options.action,
|
|
270496
|
+
extra_user_input: options.input ?? {},
|
|
270497
|
+
...options.messageId ? { message_id: options.messageId } : {}
|
|
270498
|
+
}
|
|
270499
|
+
});
|
|
270500
|
+
} catch (error) {
|
|
270501
|
+
throw await ApiError.fromHttpError(error, "answering the agent");
|
|
270502
|
+
}
|
|
270503
|
+
return parseOrThrow(ChatTurnSchema, await response.json(), "chat turn");
|
|
270504
|
+
}
|
|
270459
270505
|
async function sendTurn(content, branchId) {
|
|
270460
270506
|
let response;
|
|
270461
270507
|
try {
|
|
@@ -270528,12 +270574,32 @@ function inventAppName(prompt) {
|
|
|
270528
270574
|
function repoBasename(repoUrl) {
|
|
270529
270575
|
return repoUrl.replace(/\/+$/, "").replace(/\.git$/, "").split("/").pop() ?? "app";
|
|
270530
270576
|
}
|
|
270577
|
+
function parseWixLaunchUrl(raw) {
|
|
270578
|
+
let url;
|
|
270579
|
+
try {
|
|
270580
|
+
url = new URL(raw.trim());
|
|
270581
|
+
} catch {
|
|
270582
|
+
throw new InvalidInputError("--wix-launch expects the full launch URL.");
|
|
270583
|
+
}
|
|
270584
|
+
const fragment = new URLSearchParams(url.hash.replace(/^#/, ""));
|
|
270585
|
+
const signedInstance = fragment.get("wix-signed-instance")?.trim();
|
|
270586
|
+
if (!signedInstance) {
|
|
270587
|
+
throw new InvalidInputError("The launch URL has no #wix-signed-instance — copy the whole URL the funnel printed.");
|
|
270588
|
+
}
|
|
270589
|
+
const prompt = url.searchParams.get("prompt")?.trim();
|
|
270590
|
+
const wixClientId = fragment.get("wix-client-id")?.trim();
|
|
270591
|
+
return {
|
|
270592
|
+
...prompt ? { prompt } : {},
|
|
270593
|
+
signedInstance,
|
|
270594
|
+
...wixClientId ? { wixClientId } : {}
|
|
270595
|
+
};
|
|
270596
|
+
}
|
|
270531
270597
|
async function createAndLinkApp(options) {
|
|
270532
270598
|
if (options.name && !APP_NAME_RE.test(options.name)) {
|
|
270533
270599
|
throw new InvalidInputError("The name becomes a directory — letters, digits, dots, dashes and underscores only.");
|
|
270534
270600
|
}
|
|
270535
270601
|
const cwd = process.cwd();
|
|
270536
|
-
const fallbackName = () => options.importRepo ? repoBasename(options.importRepo) : inventAppName(options.prompt);
|
|
270602
|
+
const fallbackName = () => options.importRepo ? repoBasename(options.importRepo) : inventAppName(options.prompt ?? options.wixLaunch?.prompt);
|
|
270537
270603
|
const chosenDir = options.path ? resolve8(cwd, options.path) : await isDirEmpty(cwd) ? cwd : undefined;
|
|
270538
270604
|
const dirBase = chosenDir ? basename6(chosenDir) : undefined;
|
|
270539
270605
|
const name = options.name ?? (dirBase && APP_NAME_RE.test(dirBase) ? dirBase : fallbackName());
|
|
@@ -270544,7 +270610,15 @@ async function createAndLinkApp(options) {
|
|
|
270544
270610
|
if (await appConfigExists(targetDir)) {
|
|
270545
270611
|
throw new InvalidInputError(here ? "This directory is already linked to a Base44 app. Run `base44 code` here to keep building it, or pass --path for a new one." : `./${dirName} is already linked to a Base44 app. Pick another name or --path.`);
|
|
270546
270612
|
}
|
|
270547
|
-
|
|
270613
|
+
let clientCreationId;
|
|
270614
|
+
const created = options.wixLaunch ? await createWixLaunchedApp({
|
|
270615
|
+
prompt: options.prompt ?? options.wixLaunch.prompt ?? "",
|
|
270616
|
+
signedInstance: options.wixLaunch.signedInstance,
|
|
270617
|
+
wixClientId: options.wixLaunch.wixClientId
|
|
270618
|
+
}).then((c) => {
|
|
270619
|
+
clientCreationId = c.client_creation_id;
|
|
270620
|
+
return c;
|
|
270621
|
+
}) : options.importRepo ? await createImportedApp({
|
|
270548
270622
|
appName: name,
|
|
270549
270623
|
repoUrl: options.importRepo,
|
|
270550
270624
|
sourceMode: options.mode ?? "direct",
|
|
@@ -270568,7 +270642,8 @@ async function createAndLinkApp(options) {
|
|
|
270568
270642
|
repoUrl: created.imported_repo_url ?? undefined,
|
|
270569
270643
|
dirName,
|
|
270570
270644
|
targetDir,
|
|
270571
|
-
here
|
|
270645
|
+
here,
|
|
270646
|
+
...clientCreationId ? { clientCreationId } : {}
|
|
270572
270647
|
};
|
|
270573
270648
|
}
|
|
270574
270649
|
function repoLabel(url) {
|
|
@@ -270920,6 +270995,12 @@ function getSendCommand() {
|
|
|
270920
270995
|
// src/cli/commands/builder/new.ts
|
|
270921
270996
|
var POLL_TIMEOUT_MS = 20 * 60000;
|
|
270922
270997
|
var MODES = ["direct", "fork", "copy"];
|
|
270998
|
+
async function readStdin2() {
|
|
270999
|
+
const chunks = [];
|
|
271000
|
+
for await (const chunk of process.stdin)
|
|
271001
|
+
chunks.push(chunk);
|
|
271002
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
271003
|
+
}
|
|
270923
271004
|
async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
270924
271005
|
if (options.mode && !MODES.includes(options.mode)) {
|
|
270925
271006
|
throw new InvalidInputError("--mode must be direct, fork, or copy.");
|
|
@@ -270927,8 +271008,15 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
270927
271008
|
if ((options.mode || options.repoName || options.fromBranch) && !options.import) {
|
|
270928
271009
|
throw new InvalidInputError("--mode, --repo-name and --from-branch apply only with --import <repo>.");
|
|
270929
271010
|
}
|
|
270930
|
-
if (
|
|
270931
|
-
throw new InvalidInputError(
|
|
271011
|
+
if (options.wixLaunch && options.import) {
|
|
271012
|
+
throw new InvalidInputError("--wix-launch and --import are exclusive.");
|
|
271013
|
+
}
|
|
271014
|
+
const wixLaunch = options.wixLaunch ? parseWixLaunchUrl(options.wixLaunch === "-" ? await readStdin2() : options.wixLaunch) : undefined;
|
|
271015
|
+
if (wixLaunch && !prompt && !wixLaunch.prompt) {
|
|
271016
|
+
throw new InvalidInputError("The launch URL has no ?prompt= — pass the prompt as the argument.");
|
|
271017
|
+
}
|
|
271018
|
+
if (!prompt && !options.import && !wixLaunch) {
|
|
271019
|
+
throw new InvalidInputError('Describe the app ("<prompt>") or pass --import <repo> / --wix-launch <url>.');
|
|
270932
271020
|
}
|
|
270933
271021
|
if (options.streamJson && jsonMode) {
|
|
270934
271022
|
throw new InvalidInputError("--stream-json and --json are exclusive.");
|
|
@@ -270943,7 +271031,8 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
270943
271031
|
mode: options.mode,
|
|
270944
271032
|
repoName: options.repoName,
|
|
270945
271033
|
fromBranch: options.fromBranch,
|
|
270946
|
-
path: options.path
|
|
271034
|
+
path: options.path,
|
|
271035
|
+
wixLaunch
|
|
270947
271036
|
}));
|
|
270948
271037
|
} catch (error) {
|
|
270949
271038
|
for (const line of await githubReauthLines(error) ?? [])
|
|
@@ -270957,11 +271046,15 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
270957
271046
|
repo_url: app.repoUrl ?? null,
|
|
270958
271047
|
editor_url: app.editorUrl,
|
|
270959
271048
|
dir: app.dirName,
|
|
270960
|
-
path: app.targetDir
|
|
271049
|
+
path: app.targetDir,
|
|
271050
|
+
...app.clientCreationId ? { client_creation_id: app.clientCreationId } : {}
|
|
270961
271051
|
});
|
|
270962
271052
|
} else if (!jsonMode) {
|
|
270963
271053
|
if (app.repoUrl)
|
|
270964
271054
|
log.message(source_default.dim(`repo ${app.repoUrl}`));
|
|
271055
|
+
if (app.clientCreationId) {
|
|
271056
|
+
log.message(source_default.dim("wix launched — connector connected before the first turn"));
|
|
271057
|
+
}
|
|
270965
271058
|
log.message(source_default.dim(`editor ${app.editorUrl}`));
|
|
270966
271059
|
log.message(source_default.dim(`linked ${app.here ? "./ (this directory)" : `./${app.dirName}`}`));
|
|
270967
271060
|
}
|
|
@@ -271012,7 +271105,8 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
271012
271105
|
preview_url: previewUrl ?? null,
|
|
271013
271106
|
dir: app.dirName,
|
|
271014
271107
|
path: app.targetDir,
|
|
271015
|
-
status: finalState ?? "created"
|
|
271108
|
+
status: finalState ?? "created",
|
|
271109
|
+
...app.clientCreationId ? { client_creation_id: app.clientCreationId } : {}
|
|
271016
271110
|
})}
|
|
271017
271111
|
`
|
|
271018
271112
|
};
|
|
@@ -271037,7 +271131,7 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
271037
271131
|
}
|
|
271038
271132
|
function getNewCommand() {
|
|
271039
271133
|
const command = new Base44Command("new", { requireAppContext: false });
|
|
271040
|
-
command.description("Create an app and start building: from a prompt (the Base44 template), or over an existing GitHub repo with --import").argument("[prompt]", "What to build; the first agent turn starts immediately").option("--import <repo>", "Build over an existing GitHub repository instead of the template").option("--mode <mode>", "How to import: direct, fork, or copy (default: direct)").option("--name <name>", "Directory and app name (invented when omitted)").option("--path <dir>", "Directory to link (default: the current directory when empty, else ./<name>)").option("--repo-name <name>", "Name for the new GitHub repo when forking/copying").option("--from-branch <name>", "Import a specific branch of the repo").option("--verbose", "Show every tool result in full (no folding)").option("--stream-json", "Emit each stream event as a JSON line as it happens, then a final result line").action(newAction);
|
|
271134
|
+
command.description("Create an app and start building: from a prompt (the Base44 template), or over an existing GitHub repo with --import").argument("[prompt]", "What to build; the first agent turn starts immediately").option("--import <repo>", "Build over an existing GitHub repository instead of the template").option("--mode <mode>", "How to import: direct, fork, or copy (default: direct)").option("--name <name>", "Directory and app name (invented when omitted)").option("--path <dir>", "Directory to link (default: the current directory when empty, else ./<name>)").option("--repo-name <name>", "Name for the new GitHub repo when forking/copying").option("--from-branch <name>", "Import a specific branch of the repo").addOption(new Option2("--wix-launch <url>", `Create through a Wix launch URL (the funnel's ?prompt= and #wix-signed-instance); "-" reads it from stdin. A prompt argument is what the agent runs instead of the URL's`).env("BASE44_WIX_LAUNCH_URL")).option("--verbose", "Show every tool result in full (no folding)").option("--stream-json", "Emit each stream event as a JSON line as it happens, then a final result line").action(newAction);
|
|
271041
271135
|
return command;
|
|
271042
271136
|
}
|
|
271043
271137
|
|
|
@@ -276232,6 +276326,393 @@ function createPasteFriendlyStdin(real) {
|
|
|
276232
276326
|
return proxy;
|
|
276233
276327
|
}
|
|
276234
276328
|
|
|
276329
|
+
// src/core/resources/apps/pending.ts
|
|
276330
|
+
var CHOICE_TOOLS = new Set([
|
|
276331
|
+
"ask_clarifying_questions",
|
|
276332
|
+
"ask_plan_questions"
|
|
276333
|
+
]);
|
|
276334
|
+
var SECRET_TOOLS = new Set(["set_secrets"]);
|
|
276335
|
+
var PERMISSION_TOOLS = new Set(["request_agent_tool_permissions"]);
|
|
276336
|
+
var BROWSER_TOOLS = new Set([
|
|
276337
|
+
"connect_github_account",
|
|
276338
|
+
"request_oauth_authorization",
|
|
276339
|
+
"register_workspace_connector",
|
|
276340
|
+
"configure_psp_credentials",
|
|
276341
|
+
"plaid_connect"
|
|
276342
|
+
]);
|
|
276343
|
+
var str2 = (v) => typeof v === "string" && v.trim() ? v.trim() : undefined;
|
|
276344
|
+
function parseArgs(raw) {
|
|
276345
|
+
try {
|
|
276346
|
+
const parsed = JSON.parse(raw ?? "");
|
|
276347
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
276348
|
+
} catch {
|
|
276349
|
+
return {};
|
|
276350
|
+
}
|
|
276351
|
+
}
|
|
276352
|
+
function questionsFrom(args) {
|
|
276353
|
+
const raw = Array.isArray(args.questions) ? args.questions : [];
|
|
276354
|
+
return raw.flatMap((q) => {
|
|
276355
|
+
if (!q || typeof q !== "object")
|
|
276356
|
+
return [];
|
|
276357
|
+
const item = q;
|
|
276358
|
+
const question = str2(item.question);
|
|
276359
|
+
if (!question)
|
|
276360
|
+
return [];
|
|
276361
|
+
const options = (Array.isArray(item.options) ? item.options : []).flatMap((o) => {
|
|
276362
|
+
const opt = o;
|
|
276363
|
+
const label = str2(opt?.label);
|
|
276364
|
+
return label ? [{ label, description: str2(opt.description) }] : [];
|
|
276365
|
+
});
|
|
276366
|
+
return [
|
|
276367
|
+
{
|
|
276368
|
+
question,
|
|
276369
|
+
description: str2(item.description),
|
|
276370
|
+
options,
|
|
276371
|
+
multiSelect: item.multi_select === true
|
|
276372
|
+
}
|
|
276373
|
+
];
|
|
276374
|
+
});
|
|
276375
|
+
}
|
|
276376
|
+
function secretsFrom(args) {
|
|
276377
|
+
const raw = Array.isArray(args.secrets_schema) ? args.secrets_schema : [];
|
|
276378
|
+
return raw.flatMap((s) => {
|
|
276379
|
+
const item = s;
|
|
276380
|
+
const name = str2(item?.secretName) ?? str2(item?.name);
|
|
276381
|
+
return name ? [{ name, description: str2(item.description) }] : [];
|
|
276382
|
+
});
|
|
276383
|
+
}
|
|
276384
|
+
function permissionKey(row) {
|
|
276385
|
+
switch (row.type) {
|
|
276386
|
+
case "entity":
|
|
276387
|
+
return row.entity_name ? `entity:${row.entity_name}` : null;
|
|
276388
|
+
case "backend_function":
|
|
276389
|
+
return row.function_name ? `backend_function:${row.function_name}` : null;
|
|
276390
|
+
case "app_user_connector":
|
|
276391
|
+
return row.connector_id ? `app_user_connector:${row.connector_id}` : null;
|
|
276392
|
+
default:
|
|
276393
|
+
return null;
|
|
276394
|
+
}
|
|
276395
|
+
}
|
|
276396
|
+
function permissionsFrom(args) {
|
|
276397
|
+
const raw = Array.isArray(args.requested_permissions) ? args.requested_permissions : [];
|
|
276398
|
+
return raw.flatMap((r) => {
|
|
276399
|
+
const row = r;
|
|
276400
|
+
const key = permissionKey(row);
|
|
276401
|
+
if (!key)
|
|
276402
|
+
return [];
|
|
276403
|
+
const ops = Array.isArray(row.allowed_operations) ? ` (${row.allowed_operations.join(", ")})` : "";
|
|
276404
|
+
const target = str2(row.entity_name) ?? str2(row.function_name) ?? str2(row.connector_name) ?? key;
|
|
276405
|
+
return [
|
|
276406
|
+
{ key, label: `${row.type}: ${target}${ops}`, reason: str2(row.reason) }
|
|
276407
|
+
];
|
|
276408
|
+
});
|
|
276409
|
+
}
|
|
276410
|
+
function guardFrom(results) {
|
|
276411
|
+
const value = typeof results === "string" ? (() => {
|
|
276412
|
+
try {
|
|
276413
|
+
return JSON.parse(results);
|
|
276414
|
+
} catch {
|
|
276415
|
+
return null;
|
|
276416
|
+
}
|
|
276417
|
+
})() : results;
|
|
276418
|
+
if (!value || typeof value !== "object")
|
|
276419
|
+
return null;
|
|
276420
|
+
const g = value;
|
|
276421
|
+
if (!str2(g.guard))
|
|
276422
|
+
return null;
|
|
276423
|
+
return { title: `${g.guard}: needs your approval`, detail: str2(g.reason) };
|
|
276424
|
+
}
|
|
276425
|
+
function humanize(tool) {
|
|
276426
|
+
return tool.replace(/_/g, " ");
|
|
276427
|
+
}
|
|
276428
|
+
function pendingInputs(messages) {
|
|
276429
|
+
const out = [];
|
|
276430
|
+
for (const message of messages) {
|
|
276431
|
+
for (const call of message.tool_calls ?? []) {
|
|
276432
|
+
if (call.status !== "waiting_for_user_input")
|
|
276433
|
+
continue;
|
|
276434
|
+
const args = parseArgs(call.arguments_string);
|
|
276435
|
+
const base = {
|
|
276436
|
+
toolCallId: call.id,
|
|
276437
|
+
messageId: message.id,
|
|
276438
|
+
tool: call.name
|
|
276439
|
+
};
|
|
276440
|
+
const summary = str2(args.summary);
|
|
276441
|
+
if (CHOICE_TOOLS.has(call.name)) {
|
|
276442
|
+
out.push({
|
|
276443
|
+
...base,
|
|
276444
|
+
kind: "choice",
|
|
276445
|
+
title: summary ?? "The agent has a few questions",
|
|
276446
|
+
questions: questionsFrom(args)
|
|
276447
|
+
});
|
|
276448
|
+
} else if (SECRET_TOOLS.has(call.name)) {
|
|
276449
|
+
out.push({
|
|
276450
|
+
...base,
|
|
276451
|
+
kind: "secrets",
|
|
276452
|
+
title: summary ?? "The agent needs secrets",
|
|
276453
|
+
secrets: secretsFrom(args)
|
|
276454
|
+
});
|
|
276455
|
+
} else if (PERMISSION_TOOLS.has(call.name)) {
|
|
276456
|
+
out.push({
|
|
276457
|
+
...base,
|
|
276458
|
+
kind: "permissions",
|
|
276459
|
+
title: summary ?? "Grant the app's agent these permissions?",
|
|
276460
|
+
detail: str2(args.reason),
|
|
276461
|
+
permissions: permissionsFrom(args)
|
|
276462
|
+
});
|
|
276463
|
+
} else if (BROWSER_TOOLS.has(call.name)) {
|
|
276464
|
+
out.push({
|
|
276465
|
+
...base,
|
|
276466
|
+
kind: "browser",
|
|
276467
|
+
title: summary ?? humanize(call.name),
|
|
276468
|
+
detail: str2(args.reason)
|
|
276469
|
+
});
|
|
276470
|
+
} else {
|
|
276471
|
+
const guard = guardFrom(call.results);
|
|
276472
|
+
const integration = str2(args.integration_type);
|
|
276473
|
+
out.push({
|
|
276474
|
+
...base,
|
|
276475
|
+
kind: "approval",
|
|
276476
|
+
title: guard?.title ?? (integration ? `Enable ${integration}?` : summary ?? `${humanize(call.name)}?`),
|
|
276477
|
+
detail: guard?.detail ?? (integration ? summary : undefined)
|
|
276478
|
+
});
|
|
276479
|
+
}
|
|
276480
|
+
}
|
|
276481
|
+
}
|
|
276482
|
+
return out;
|
|
276483
|
+
}
|
|
276484
|
+
function choiceAnswers(questions, selections) {
|
|
276485
|
+
const answers = questions.flatMap((q, index) => {
|
|
276486
|
+
const sel = selections[index];
|
|
276487
|
+
if (!sel || sel.labels.length === 0 && !sel.customText)
|
|
276488
|
+
return [];
|
|
276489
|
+
const answer = { question_index: index };
|
|
276490
|
+
if (q.multiSelect) {
|
|
276491
|
+
if (sel.labels.length)
|
|
276492
|
+
answer.selected_labels = sel.labels;
|
|
276493
|
+
} else if (sel.labels[0]) {
|
|
276494
|
+
answer.selected_label = sel.labels[0];
|
|
276495
|
+
}
|
|
276496
|
+
if (sel.customText)
|
|
276497
|
+
answer.custom_text = sel.customText;
|
|
276498
|
+
return [answer];
|
|
276499
|
+
});
|
|
276500
|
+
return { answers };
|
|
276501
|
+
}
|
|
276502
|
+
|
|
276503
|
+
// src/cli/commands/code/pending-card.ts
|
|
276504
|
+
function openCard(pending) {
|
|
276505
|
+
return {
|
|
276506
|
+
pending,
|
|
276507
|
+
step: 0,
|
|
276508
|
+
cursor: 0,
|
|
276509
|
+
selections: (pending.questions ?? []).map(() => ({ labels: [] })),
|
|
276510
|
+
granted: new Set((pending.permissions ?? []).map((p) => p.key)),
|
|
276511
|
+
typing: pending.kind === "secrets" ? "secret" : null,
|
|
276512
|
+
secretValues: {}
|
|
276513
|
+
};
|
|
276514
|
+
}
|
|
276515
|
+
var done = (action, input = {}) => ({ state: null, submit: { action, input } });
|
|
276516
|
+
var later = { state: null, dismissed: true };
|
|
276517
|
+
function choiceRows(state) {
|
|
276518
|
+
return (state.pending.questions?.[state.step]?.options.length ?? 0) + 1;
|
|
276519
|
+
}
|
|
276520
|
+
function advanceChoice(state) {
|
|
276521
|
+
const questions = state.pending.questions ?? [];
|
|
276522
|
+
if (state.step + 1 < questions.length) {
|
|
276523
|
+
return {
|
|
276524
|
+
state: { ...state, step: state.step + 1, cursor: 0, typing: null }
|
|
276525
|
+
};
|
|
276526
|
+
}
|
|
276527
|
+
return done("approved", choiceAnswers(questions, state.selections));
|
|
276528
|
+
}
|
|
276529
|
+
function choiceKey(state, key) {
|
|
276530
|
+
const question = state.pending.questions?.[state.step];
|
|
276531
|
+
if (!question)
|
|
276532
|
+
return done("approved", { answers: [] });
|
|
276533
|
+
const rows = choiceRows(state);
|
|
276534
|
+
const custom = state.cursor === rows - 1;
|
|
276535
|
+
const sel = state.selections[state.step] ?? { labels: [] };
|
|
276536
|
+
const setSel = (next) => {
|
|
276537
|
+
const selections = [...state.selections];
|
|
276538
|
+
selections[state.step] = next;
|
|
276539
|
+
return { ...state, selections };
|
|
276540
|
+
};
|
|
276541
|
+
switch (key) {
|
|
276542
|
+
case "up":
|
|
276543
|
+
return { state: { ...state, cursor: (state.cursor - 1 + rows) % rows } };
|
|
276544
|
+
case "down":
|
|
276545
|
+
return { state: { ...state, cursor: (state.cursor + 1) % rows } };
|
|
276546
|
+
case "space": {
|
|
276547
|
+
if (custom)
|
|
276548
|
+
return { state: { ...state, typing: "custom" } };
|
|
276549
|
+
const label = question.options[state.cursor].label;
|
|
276550
|
+
const labels = question.multiSelect ? sel.labels.includes(label) ? sel.labels.filter((l) => l !== label) : [...sel.labels, label] : [label];
|
|
276551
|
+
return { state: setSel({ ...sel, labels }) };
|
|
276552
|
+
}
|
|
276553
|
+
case "enter": {
|
|
276554
|
+
if (custom)
|
|
276555
|
+
return { state: { ...state, typing: "custom" } };
|
|
276556
|
+
if (question.multiSelect) {
|
|
276557
|
+
if (sel.labels.length === 0 && !sel.customText)
|
|
276558
|
+
return { state };
|
|
276559
|
+
return advanceChoice(state);
|
|
276560
|
+
}
|
|
276561
|
+
const label = question.options[state.cursor].label;
|
|
276562
|
+
return advanceChoice(setSel({ labels: [label] }));
|
|
276563
|
+
}
|
|
276564
|
+
case "s":
|
|
276565
|
+
return done("approved", { answers: [] });
|
|
276566
|
+
case "escape":
|
|
276567
|
+
return later;
|
|
276568
|
+
default:
|
|
276569
|
+
return { state };
|
|
276570
|
+
}
|
|
276571
|
+
}
|
|
276572
|
+
function permissionsKey(state, key) {
|
|
276573
|
+
const rows = state.pending.permissions ?? [];
|
|
276574
|
+
switch (key) {
|
|
276575
|
+
case "up":
|
|
276576
|
+
return {
|
|
276577
|
+
state: {
|
|
276578
|
+
...state,
|
|
276579
|
+
cursor: (state.cursor - 1 + rows.length) % rows.length
|
|
276580
|
+
}
|
|
276581
|
+
};
|
|
276582
|
+
case "down":
|
|
276583
|
+
return { state: { ...state, cursor: (state.cursor + 1) % rows.length } };
|
|
276584
|
+
case "space": {
|
|
276585
|
+
const k = rows[state.cursor]?.key;
|
|
276586
|
+
if (!k)
|
|
276587
|
+
return { state };
|
|
276588
|
+
const granted = new Set(state.granted);
|
|
276589
|
+
if (granted.has(k))
|
|
276590
|
+
granted.delete(k);
|
|
276591
|
+
else
|
|
276592
|
+
granted.add(k);
|
|
276593
|
+
return { state: { ...state, granted } };
|
|
276594
|
+
}
|
|
276595
|
+
case "enter":
|
|
276596
|
+
case "y":
|
|
276597
|
+
return done("approved", {
|
|
276598
|
+
approved_permission_keys: rows.map((r) => r.key).filter((k) => state.granted.has(k))
|
|
276599
|
+
});
|
|
276600
|
+
case "n":
|
|
276601
|
+
return done("rejected");
|
|
276602
|
+
case "escape":
|
|
276603
|
+
return later;
|
|
276604
|
+
default:
|
|
276605
|
+
return { state };
|
|
276606
|
+
}
|
|
276607
|
+
}
|
|
276608
|
+
function cardKey(state, key) {
|
|
276609
|
+
if (state.typing) {
|
|
276610
|
+
if (key === "escape") {
|
|
276611
|
+
return state.typing === "secret" ? later : { state: { ...state, typing: null } };
|
|
276612
|
+
}
|
|
276613
|
+
return { state };
|
|
276614
|
+
}
|
|
276615
|
+
switch (state.pending.kind) {
|
|
276616
|
+
case "choice":
|
|
276617
|
+
return choiceKey(state, key);
|
|
276618
|
+
case "permissions":
|
|
276619
|
+
return permissionsKey(state, key);
|
|
276620
|
+
default:
|
|
276621
|
+
if (key === "y" || key === "enter")
|
|
276622
|
+
return done("approved");
|
|
276623
|
+
if (key === "n")
|
|
276624
|
+
return done("rejected");
|
|
276625
|
+
if (key === "escape")
|
|
276626
|
+
return later;
|
|
276627
|
+
return { state };
|
|
276628
|
+
}
|
|
276629
|
+
}
|
|
276630
|
+
function cardText(state, text) {
|
|
276631
|
+
const value = text.trim();
|
|
276632
|
+
if (state.typing === "custom") {
|
|
276633
|
+
if (!value)
|
|
276634
|
+
return { state: { ...state, typing: null } };
|
|
276635
|
+
const selections = [...state.selections];
|
|
276636
|
+
const current = selections[state.step] ?? { labels: [] };
|
|
276637
|
+
selections[state.step] = { ...current, customText: value };
|
|
276638
|
+
return advanceChoice({ ...state, selections, typing: null });
|
|
276639
|
+
}
|
|
276640
|
+
if (state.typing === "secret") {
|
|
276641
|
+
const fields = state.pending.secrets ?? [];
|
|
276642
|
+
const field = fields[state.step];
|
|
276643
|
+
if (!field || !value)
|
|
276644
|
+
return { state };
|
|
276645
|
+
const secretValues = { ...state.secretValues, [field.name]: value };
|
|
276646
|
+
if (state.step + 1 < fields.length) {
|
|
276647
|
+
return { state: { ...state, secretValues, step: state.step + 1 } };
|
|
276648
|
+
}
|
|
276649
|
+
return done("approved", { secrets: secretValues });
|
|
276650
|
+
}
|
|
276651
|
+
return { state };
|
|
276652
|
+
}
|
|
276653
|
+
function cardLines(state) {
|
|
276654
|
+
const p = state.pending;
|
|
276655
|
+
const head = [source_default.bold(`⏸ ${p.title}`)];
|
|
276656
|
+
if (p.detail)
|
|
276657
|
+
head.push(source_default.dim(` ${p.detail}`));
|
|
276658
|
+
switch (p.kind) {
|
|
276659
|
+
case "choice": {
|
|
276660
|
+
const q = p.questions?.[state.step];
|
|
276661
|
+
if (!q)
|
|
276662
|
+
return [...head, source_default.dim(" (no questions) · Enter to continue")];
|
|
276663
|
+
const total = p.questions?.length ?? 1;
|
|
276664
|
+
const sel = state.selections[state.step] ?? { labels: [] };
|
|
276665
|
+
const rows = q.options.map((o, i) => {
|
|
276666
|
+
const on = sel.labels.includes(o.label);
|
|
276667
|
+
const mark = q.multiSelect ? on ? "☑" : "☐" : on ? "●" : "○";
|
|
276668
|
+
const text = `${state.cursor === i ? "▸" : " "} ${mark} ${o.label}${o.description ? source_default.dim(` — ${o.description}`) : ""}`;
|
|
276669
|
+
return state.cursor === i ? source_default.cyan(text) : text;
|
|
276670
|
+
});
|
|
276671
|
+
const customRow = `${state.cursor === q.options.length ? "▸" : " "} ✎ something else${sel.customText ? source_default.dim(` — ${sel.customText}`) : ""}`;
|
|
276672
|
+
rows.push(state.cursor === q.options.length ? source_default.cyan(customRow) : customRow);
|
|
276673
|
+
return [
|
|
276674
|
+
...head,
|
|
276675
|
+
` ${source_default.bold(q.question)} ${source_default.dim(`(${state.step + 1}/${total})`)}`,
|
|
276676
|
+
...q.description ? [source_default.dim(` ${q.description}`)] : [],
|
|
276677
|
+
...rows.map((r) => ` ${r}`),
|
|
276678
|
+
source_default.dim(q.multiSelect ? " ↑↓ move · space toggle · Enter next · s skip all · Esc later" : " ↑↓ move · Enter choose · s skip all · Esc later")
|
|
276679
|
+
];
|
|
276680
|
+
}
|
|
276681
|
+
case "permissions": {
|
|
276682
|
+
const rows = (p.permissions ?? []).map((r, i) => {
|
|
276683
|
+
const text = `${state.cursor === i ? "▸" : " "} ${state.granted.has(r.key) ? "☑" : "☐"} ${r.label}${r.reason ? source_default.dim(` — ${r.reason}`) : ""}`;
|
|
276684
|
+
return ` ${state.cursor === i ? source_default.cyan(text) : text}`;
|
|
276685
|
+
});
|
|
276686
|
+
return [
|
|
276687
|
+
...head,
|
|
276688
|
+
...rows,
|
|
276689
|
+
source_default.dim(" space toggle · Enter grant ticked · n reject all · Esc later")
|
|
276690
|
+
];
|
|
276691
|
+
}
|
|
276692
|
+
case "secrets": {
|
|
276693
|
+
const fields = p.secrets ?? [];
|
|
276694
|
+
const rows = fields.map((f, i) => {
|
|
276695
|
+
const filled = f.name in state.secretValues;
|
|
276696
|
+
const mark = filled ? source_default.green("✓") : i === state.step ? "▸" : "○";
|
|
276697
|
+
return ` ${mark} ${f.name}${f.description ? source_default.dim(` — ${f.description}`) : ""}`;
|
|
276698
|
+
});
|
|
276699
|
+
return [
|
|
276700
|
+
...head,
|
|
276701
|
+
...rows,
|
|
276702
|
+
source_default.dim(" type the value below (hidden) · Enter next · Esc later")
|
|
276703
|
+
];
|
|
276704
|
+
}
|
|
276705
|
+
case "browser":
|
|
276706
|
+
return [
|
|
276707
|
+
...head,
|
|
276708
|
+
source_default.dim(" finish this step in the editor (footer link), then press y"),
|
|
276709
|
+
source_default.dim(" y continue · n reject · Esc later")
|
|
276710
|
+
];
|
|
276711
|
+
default:
|
|
276712
|
+
return [...head, source_default.dim(" y approve · n reject · Esc later")];
|
|
276713
|
+
}
|
|
276714
|
+
}
|
|
276715
|
+
|
|
276235
276716
|
// src/cli/commands/code/session-engine.ts
|
|
276236
276717
|
var POLL_MS = 1000;
|
|
276237
276718
|
function createSessionEngine(options) {
|
|
@@ -276251,6 +276732,28 @@ function createSessionEngine(options) {
|
|
|
276251
276732
|
let awaitingTurn = options.awaitingTurnLabel ?? null;
|
|
276252
276733
|
const awaitingSince = Date.now();
|
|
276253
276734
|
let lastEventAt = Date.now();
|
|
276735
|
+
let pending = [];
|
|
276736
|
+
const answered = new Set;
|
|
276737
|
+
const answer = (p, action, input = {}) => {
|
|
276738
|
+
answered.add(p.toolCallId);
|
|
276739
|
+
pending = pending.filter((x) => x.toolCallId !== p.toolCallId);
|
|
276740
|
+
const verb = action === "rejected" ? source_default.red("✗ rejected") : Object.keys(input).length ? source_default.green("→ answered") : source_default.green("✓ approved");
|
|
276741
|
+
options.onLine(`${verb} ${source_default.dim("—")} ${p.title}`);
|
|
276742
|
+
pendingSubmitAt = Date.now();
|
|
276743
|
+
sendsInFlight++;
|
|
276744
|
+
answerToolCall({ toolCallId: p.toolCallId, messageId: p.messageId, action, input }, options.branchId).catch((error) => {
|
|
276745
|
+
const status = error instanceof ApiError ? error.statusCode : undefined;
|
|
276746
|
+
const edgeDrop = status === 502 || status === 503 || status === 504 || /timeout|gateway/i.test(error instanceof Error ? error.message : "");
|
|
276747
|
+
if (edgeDrop && (turnStartedAt != null || pendingSubmitAt == null)) {
|
|
276748
|
+
return;
|
|
276749
|
+
}
|
|
276750
|
+
answered.delete(p.toolCallId);
|
|
276751
|
+
pendingSubmitAt = null;
|
|
276752
|
+
options.onLine(source_default.red(`✗ answer failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
276753
|
+
}).finally(() => {
|
|
276754
|
+
sendsInFlight--;
|
|
276755
|
+
});
|
|
276756
|
+
};
|
|
276254
276757
|
const submit = (raw) => {
|
|
276255
276758
|
const typed = raw.trim();
|
|
276256
276759
|
if (!typed)
|
|
@@ -276291,6 +276794,12 @@ function createSessionEngine(options) {
|
|
|
276291
276794
|
return;
|
|
276292
276795
|
}
|
|
276293
276796
|
const events = diffConversation(diffState, messages);
|
|
276797
|
+
const waiting = pendingInputs(messages);
|
|
276798
|
+
for (const id of answered) {
|
|
276799
|
+
if (!waiting.some((w) => w.toolCallId === id))
|
|
276800
|
+
answered.delete(id);
|
|
276801
|
+
}
|
|
276802
|
+
pending = waiting.filter((w) => !answered.has(w.toolCallId));
|
|
276294
276803
|
if (!prime) {
|
|
276295
276804
|
for (const event of events) {
|
|
276296
276805
|
if (event.kind === "tool_start") {
|
|
@@ -276314,7 +276823,9 @@ function createSessionEngine(options) {
|
|
|
276314
276823
|
});
|
|
276315
276824
|
continue;
|
|
276316
276825
|
}
|
|
276317
|
-
const line = eventLine(event
|
|
276826
|
+
const line = eventLine(event, undefined, {
|
|
276827
|
+
waitingHint: "answer in the card below"
|
|
276828
|
+
});
|
|
276318
276829
|
if (line != null) {
|
|
276319
276830
|
lastEventAt = Date.now();
|
|
276320
276831
|
options.onLine(line);
|
|
@@ -276381,6 +276892,7 @@ function createSessionEngine(options) {
|
|
|
276381
276892
|
});
|
|
276382
276893
|
},
|
|
276383
276894
|
submit,
|
|
276895
|
+
answer,
|
|
276384
276896
|
status() {
|
|
276385
276897
|
let phase = "idle";
|
|
276386
276898
|
if (awaitingTurn != null)
|
|
@@ -276403,7 +276915,8 @@ function createSessionEngine(options) {
|
|
|
276403
276915
|
turnStartedAt,
|
|
276404
276916
|
runningTool,
|
|
276405
276917
|
lastTurnMs,
|
|
276406
|
-
lastTurnOk
|
|
276918
|
+
lastTurnOk,
|
|
276919
|
+
pending
|
|
276407
276920
|
};
|
|
276408
276921
|
},
|
|
276409
276922
|
turnRunning() {
|
|
@@ -276475,6 +276988,8 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276475
276988
|
const [musingSeed] = import_react23.useState(() => Math.floor(Math.random() * 97));
|
|
276476
276989
|
const [currentModel, setCurrentModel] = import_react23.useState(null);
|
|
276477
276990
|
const [pickerIndex, setPickerIndex] = import_react23.useState(null);
|
|
276991
|
+
const [card, setCard] = import_react23.useState(null);
|
|
276992
|
+
const dismissedRef = import_react23.useRef(new Set);
|
|
276478
276993
|
const maxScrollRef = import_react23.useRef(0);
|
|
276479
276994
|
const meIdRef = import_react23.useRef(null);
|
|
276480
276995
|
const emit = (entry) => setItems((h) => withEntry(h, entry));
|
|
@@ -276520,6 +277035,29 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276520
277035
|
emit(source_default.red(` /model: ${error instanceof Error ? error.message : String(error)}`));
|
|
276521
277036
|
}
|
|
276522
277037
|
};
|
|
277038
|
+
const applyCard = (outcome) => {
|
|
277039
|
+
if (outcome.submit && card) {
|
|
277040
|
+
engine.answer(card.pending, outcome.submit.action, outcome.submit.input);
|
|
277041
|
+
}
|
|
277042
|
+
if (outcome.dismissed && card) {
|
|
277043
|
+
dismissedRef.current.add(card.pending.toolCallId);
|
|
277044
|
+
}
|
|
277045
|
+
setCard(outcome.state);
|
|
277046
|
+
};
|
|
277047
|
+
const pending = engine.status().pending;
|
|
277048
|
+
import_react23.useEffect(() => {
|
|
277049
|
+
if (card) {
|
|
277050
|
+
if (!pending.some((p) => p.toolCallId === card.pending.toolCallId)) {
|
|
277051
|
+
setCard(null);
|
|
277052
|
+
}
|
|
277053
|
+
return;
|
|
277054
|
+
}
|
|
277055
|
+
if (pickerIndex !== null)
|
|
277056
|
+
return;
|
|
277057
|
+
const next = pending.find((p) => !dismissedRef.current.has(p.toolCallId));
|
|
277058
|
+
if (next)
|
|
277059
|
+
setCard(openCard(next));
|
|
277060
|
+
}, [pending, card, pickerIndex]);
|
|
276523
277061
|
use_input_default((char, key) => {
|
|
276524
277062
|
if (pickerIndex !== null) {
|
|
276525
277063
|
if (key.upArrow)
|
|
@@ -276535,6 +277073,23 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276535
277073
|
}
|
|
276536
277074
|
return;
|
|
276537
277075
|
}
|
|
277076
|
+
if (key.tab && !card) {
|
|
277077
|
+
const next = pending.find((p) => dismissedRef.current.has(p.toolCallId));
|
|
277078
|
+
if (next) {
|
|
277079
|
+
dismissedRef.current.delete(next.toolCallId);
|
|
277080
|
+
setCard(openCard(next));
|
|
277081
|
+
}
|
|
277082
|
+
return;
|
|
277083
|
+
}
|
|
277084
|
+
if (card) {
|
|
277085
|
+
const mapped = key.upArrow ? "up" : key.downArrow ? "down" : key.return ? "enter" : key.escape ? "escape" : char === " " ? "space" : char === "y" || char === "n" || char === "s" ? char : null;
|
|
277086
|
+
if (card.typing && mapped !== "escape")
|
|
277087
|
+
return;
|
|
277088
|
+
if (mapped)
|
|
277089
|
+
applyCard(cardKey(card, mapped));
|
|
277090
|
+
if (mapped || !card.typing)
|
|
277091
|
+
return;
|
|
277092
|
+
}
|
|
276538
277093
|
if (key.ctrl && char === "c") {
|
|
276539
277094
|
if (input)
|
|
276540
277095
|
setInput("");
|
|
@@ -276579,7 +277134,9 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276579
277134
|
const innerWidth = Math.max(10, width - 4);
|
|
276580
277135
|
const inputRows = Math.max(1, Math.ceil((input.length + 3) / innerWidth));
|
|
276581
277136
|
const pickerOpen = pickerIndex !== null;
|
|
276582
|
-
const
|
|
277137
|
+
const cardOpen = card !== null && !card.typing;
|
|
277138
|
+
const cardRows = card ? cardLines(card).length : 0;
|
|
277139
|
+
const inputBlockHeight = pickerOpen ? MODELS.length + 3 : cardOpen ? cardRows + 2 : inputRows + 2 + (card?.typing ? 1 : 0);
|
|
276583
277140
|
const widgetHeight = inputBlockHeight + 3 + (footer.length ? 1 : 0);
|
|
276584
277141
|
const viewHeight = Math.max(3, rows - widgetHeight - 1);
|
|
276585
277142
|
const lines = items.flatMap((item) => hardWrapAnsi(`${renderEntry(item, { verbose, foldHint: "Ctrl+O to expand" })}
|
|
@@ -276630,29 +277187,64 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276630
277187
|
}, m.name, false, undefined, this);
|
|
276631
277188
|
})
|
|
276632
277189
|
]
|
|
276633
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
277190
|
+
}, undefined, true, undefined, this) : cardOpen && card ? /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
277191
|
+
flexDirection: "column",
|
|
277192
|
+
borderStyle: "round",
|
|
277193
|
+
borderColor: "yellow",
|
|
277194
|
+
paddingX: 1,
|
|
277195
|
+
width,
|
|
277196
|
+
children: cardLines(card).map((line, i) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
277197
|
+
wrap: "truncate-end",
|
|
277198
|
+
children: line
|
|
277199
|
+
}, i, false, undefined, this))
|
|
277200
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
277201
|
+
flexDirection: "column",
|
|
276634
277202
|
borderStyle: "round",
|
|
276635
|
-
borderColor: "gray",
|
|
277203
|
+
borderColor: card?.typing ? "yellow" : "gray",
|
|
276636
277204
|
paddingX: 1,
|
|
276637
277205
|
width,
|
|
276638
277206
|
children: [
|
|
276639
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
276640
|
-
|
|
276641
|
-
children:
|
|
276642
|
-
|
|
276643
|
-
|
|
276644
|
-
|
|
276645
|
-
|
|
276646
|
-
|
|
276647
|
-
|
|
276648
|
-
|
|
276649
|
-
|
|
276650
|
-
|
|
276651
|
-
|
|
276652
|
-
|
|
276653
|
-
|
|
276654
|
-
|
|
276655
|
-
|
|
277207
|
+
card?.typing === "secret" && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
277208
|
+
wrap: "truncate-end",
|
|
277209
|
+
children: [
|
|
277210
|
+
source_default.bold(card.pending.secrets?.[card.step]?.name ?? "secret"),
|
|
277211
|
+
source_default.dim(" — value is hidden · Enter to save · Esc to cancel")
|
|
277212
|
+
]
|
|
277213
|
+
}, undefined, true, undefined, this),
|
|
277214
|
+
card?.typing === "custom" && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
277215
|
+
wrap: "truncate-end",
|
|
277216
|
+
children: [
|
|
277217
|
+
source_default.bold(card.pending.questions?.[card.step]?.question ?? ""),
|
|
277218
|
+
source_default.dim(" — your own answer · Enter to save · Esc to go back")
|
|
277219
|
+
]
|
|
277220
|
+
}, undefined, true, undefined, this),
|
|
277221
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
277222
|
+
children: [
|
|
277223
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
277224
|
+
color: "cyan",
|
|
277225
|
+
children: "❯ "
|
|
277226
|
+
}, undefined, false, undefined, this),
|
|
277227
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(build_default, {
|
|
277228
|
+
value: input,
|
|
277229
|
+
onChange: setInput,
|
|
277230
|
+
mask: card?.typing === "secret" ? "•" : undefined,
|
|
277231
|
+
onSubmit: (value) => {
|
|
277232
|
+
if (card?.typing) {
|
|
277233
|
+
applyCard(cardText(card, value));
|
|
277234
|
+
setInput("");
|
|
277235
|
+
return;
|
|
277236
|
+
}
|
|
277237
|
+
const trimmed = value.trim();
|
|
277238
|
+
if (trimmed === "/model" || trimmed.startsWith("/model ")) {
|
|
277239
|
+
runModelSlash(trimmed.slice("/model".length).trim());
|
|
277240
|
+
} else if (trimmed) {
|
|
277241
|
+
engine.submit(value);
|
|
277242
|
+
}
|
|
277243
|
+
setInput("");
|
|
277244
|
+
}
|
|
277245
|
+
}, undefined, false, undefined, this)
|
|
277246
|
+
]
|
|
277247
|
+
}, undefined, true, undefined, this)
|
|
276656
277248
|
]
|
|
276657
277249
|
}, undefined, true, undefined, this),
|
|
276658
277250
|
footer.length > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
@@ -276666,7 +277258,7 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276666
277258
|
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
276667
277259
|
dimColor: true,
|
|
276668
277260
|
wrap: "truncate-end",
|
|
276669
|
-
children: pickerOpen ? " ↑↓ to move · Enter to select · Esc to cancel" : engine.turnRunning() ? " Esc to stop · type to queue · scroll to read · Ctrl+O to expand · Ctrl+C to exit" : " Enter to send · /model to switch model · Esc for live · Ctrl+O to expand · Ctrl+C to exit"
|
|
277261
|
+
children: pickerOpen ? " ↑↓ to move · Enter to select · Esc to cancel" : cardOpen ? " the agent is waiting on you · answer above, or Esc for later" : pending.length > 0 && !card ? ` ⏸ ${pending[0].title} — Tab to answer · Ctrl+C to exit` : engine.turnRunning() ? " Esc to stop · type to queue · scroll to read · Ctrl+O to expand · Ctrl+C to exit" : " Enter to send · /model to switch model · Esc for live · Ctrl+O to expand · Ctrl+C to exit"
|
|
276670
277262
|
}, undefined, false, undefined, this)
|
|
276671
277263
|
]
|
|
276672
277264
|
}, undefined, true, undefined, this);
|
|
@@ -276791,6 +277383,7 @@ async function runGenesisSession(options) {
|
|
|
276791
277383
|
runningTool: null,
|
|
276792
277384
|
lastTurnMs: null,
|
|
276793
277385
|
lastTurnOk: true,
|
|
277386
|
+
pending: [],
|
|
276794
277387
|
quietForMs: 0
|
|
276795
277388
|
};
|
|
276796
277389
|
const genesis = {
|
|
@@ -276846,6 +277439,9 @@ async function runGenesisSession(options) {
|
|
|
276846
277439
|
}
|
|
276847
277440
|
return IDLE_STATUS;
|
|
276848
277441
|
},
|
|
277442
|
+
answer(p, action, input) {
|
|
277443
|
+
inner?.answer(p, action, input);
|
|
277444
|
+
},
|
|
276849
277445
|
turnRunning() {
|
|
276850
277446
|
return inner?.turnRunning() ?? creating;
|
|
276851
277447
|
}
|
|
@@ -276878,10 +277474,10 @@ async function runGenesisSession(options) {
|
|
|
276878
277474
|
|
|
276879
277475
|
// src/cli/commands/code/index.ts
|
|
276880
277476
|
var BRAND_ORANGE2 = "#E86B3C";
|
|
276881
|
-
async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path) {
|
|
277477
|
+
async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path, wixLaunch) {
|
|
276882
277478
|
let app;
|
|
276883
277479
|
try {
|
|
276884
|
-
app = await createAndLinkApp({ prompt, importRepo, path });
|
|
277480
|
+
app = await createAndLinkApp({ prompt, importRepo, path, wixLaunch });
|
|
276885
277481
|
} catch (error) {
|
|
276886
277482
|
for (const line of await githubReauthLines(error) ?? [])
|
|
276887
277483
|
emit(line);
|
|
@@ -276928,8 +277524,8 @@ async function codeAction({ log }, options, appId) {
|
|
|
276928
277524
|
linked = true;
|
|
276929
277525
|
} catch {}
|
|
276930
277526
|
if (linked) {
|
|
276931
|
-
if (options.import || options.path) {
|
|
276932
|
-
throw new InvalidInputError("--import and --
|
|
277527
|
+
if (options.import || options.path || options.wixLaunch) {
|
|
277528
|
+
throw new InvalidInputError("--import, --path and --wix-launch create a new app; run them outside a linked project, without --app-id.");
|
|
276933
277529
|
}
|
|
276934
277530
|
const { id, projectRoot } = getAppContext();
|
|
276935
277531
|
const state = await assertBuilderApp(id);
|
|
@@ -276952,16 +277548,22 @@ async function codeAction({ log }, options, appId) {
|
|
|
276952
277548
|
outroMessage: `Session closed. Resume with \`base44 code --app-id ${id}\`.`
|
|
276953
277549
|
};
|
|
276954
277550
|
}
|
|
277551
|
+
if (options.wixLaunch && options.import) {
|
|
277552
|
+
throw new InvalidInputError("--wix-launch and --import are exclusive.");
|
|
277553
|
+
}
|
|
277554
|
+
const wixLaunch = options.wixLaunch ? parseWixLaunchUrl(options.wixLaunch) : undefined;
|
|
276955
277555
|
let created;
|
|
276956
|
-
const footer = [
|
|
277556
|
+
const footer = [
|
|
277557
|
+
chip(options.import ? repoLabel(options.import) : wixLaunch ? "web app · wix" : "web app")
|
|
277558
|
+
];
|
|
276957
277559
|
await runGenesisSession({
|
|
276958
277560
|
idleHint: options.import ? "describe what to build over the repository" : "describe the app you want to build · have one already? base44 code --app-id <id>, or base44 link",
|
|
276959
277561
|
creatingLabel: options.import ? "importing the repository" : "creating your app",
|
|
276960
|
-
modeLabel: options.import ? `Repository — ${repoLabel(options.import)}` : "Web app — Base44 template + builder agent",
|
|
277562
|
+
modeLabel: options.import ? `Repository — ${repoLabel(options.import)}` : wixLaunch ? "Web app — Wix launch (connector connected first)" : "Web app — Base44 template + builder agent",
|
|
276961
277563
|
footer,
|
|
276962
277564
|
createApp: (prompt, emit) => bootstrapApp(prompt, footer, emit, (app) => {
|
|
276963
277565
|
created = app;
|
|
276964
|
-
}, options.import, options.path)
|
|
277566
|
+
}, options.import, options.path, wixLaunch)
|
|
276965
277567
|
});
|
|
276966
277568
|
if (!created) {
|
|
276967
277569
|
return { outroMessage: "Session closed. No app was created." };
|
|
@@ -276973,7 +277575,7 @@ async function codeAction({ log }, options, appId) {
|
|
|
276973
277575
|
}
|
|
276974
277576
|
function getCodeCommand() {
|
|
276975
277577
|
const command = new Base44Command("code", { requireAppContext: false });
|
|
276976
|
-
command.description("Open Base44 Code, an interactive builder session. In a linked directory (or with --app-id <id>) it opens that app; anywhere else your first prompt creates one (--import <repo> to build over your own repository). Attach a directory to an existing app with base44 link.").option("--import <repo>", "Build over an existing GitHub repository instead of the Base44 template").option("--path <dir>", "Directory to link the new app to (default: the current directory when empty, else ./<name>)").action((ctx, options) => codeAction(ctx, options, command.optsWithGlobals().appId));
|
|
277578
|
+
command.description("Open Base44 Code, an interactive builder session. In a linked directory (or with --app-id <id>) it opens that app; anywhere else your first prompt creates one (--import <repo> to build over your own repository). Attach a directory to an existing app with base44 link.").option("--import <repo>", "Build over an existing GitHub repository instead of the Base44 template").option("--path <dir>", "Directory to link the new app to (default: the current directory when empty, else ./<name>)").option("--wix-launch <url>", "Create the new app through a Wix launch URL (your first prompt is what the agent runs)").action((ctx, options) => codeAction(ctx, options, command.optsWithGlobals().appId));
|
|
276977
277579
|
return command;
|
|
276978
277580
|
}
|
|
276979
277581
|
|
|
@@ -284356,7 +284958,7 @@ async function runScript(options) {
|
|
|
284356
284958
|
}
|
|
284357
284959
|
}
|
|
284358
284960
|
// src/cli/commands/exec.ts
|
|
284359
|
-
function
|
|
284961
|
+
function readStdin3() {
|
|
284360
284962
|
return new Promise((resolve, reject) => {
|
|
284361
284963
|
let data = "";
|
|
284362
284964
|
process.stdin.setEncoding("utf-8");
|
|
@@ -284400,7 +285002,7 @@ async function execAction({ app, isNonInteractive }, options) {
|
|
|
284400
285002
|
if (!isNonInteractive) {
|
|
284401
285003
|
throw noInputError;
|
|
284402
285004
|
}
|
|
284403
|
-
const code = await
|
|
285005
|
+
const code = await readStdin3();
|
|
284404
285006
|
if (!code.trim()) {
|
|
284405
285007
|
throw noInputError;
|
|
284406
285008
|
}
|
|
@@ -288581,6 +289183,13 @@ function getFullCommandName(command) {
|
|
|
288581
289183
|
}
|
|
288582
289184
|
return parts.join(" ");
|
|
288583
289185
|
}
|
|
289186
|
+
var SENSITIVE_OPTION = /secret|token|password|launch|instance|key$/i;
|
|
289187
|
+
function redactSensitiveOptions(options) {
|
|
289188
|
+
return Object.fromEntries(Object.entries(options).map(([k, v]) => [
|
|
289189
|
+
k,
|
|
289190
|
+
SENSITIVE_OPTION.test(k) && v != null && v !== false ? "[redacted]" : v
|
|
289191
|
+
]));
|
|
289192
|
+
}
|
|
288584
289193
|
function addCommandInfoToErrorReporter(program, errorReporter) {
|
|
288585
289194
|
program.hook("preAction", (_, actionCommand) => {
|
|
288586
289195
|
const fullCommandName = getFullCommandName(actionCommand);
|
|
@@ -288588,7 +289197,7 @@ function addCommandInfoToErrorReporter(program, errorReporter) {
|
|
|
288588
289197
|
command: {
|
|
288589
289198
|
name: fullCommandName,
|
|
288590
289199
|
args: actionCommand.args,
|
|
288591
|
-
options: actionCommand.opts()
|
|
289200
|
+
options: redactSensitiveOptions(actionCommand.opts())
|
|
288592
289201
|
}
|
|
288593
289202
|
});
|
|
288594
289203
|
});
|
|
@@ -288635,4 +289244,4 @@ export {
|
|
|
288635
289244
|
runCLI
|
|
288636
289245
|
};
|
|
288637
289246
|
|
|
288638
|
-
//# debugId=
|
|
289247
|
+
//# debugId=D93D1396A8EFA10D64756E2164756E21
|