@base44-preview/cli 0.1.15-pr.630.5b0c119 → 0.1.15-pr.630.5b86d26
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 +652 -45
- 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);
|
|
@@ -270204,6 +270208,14 @@ ${indent(shown)}`;
|
|
|
270204
270208
|
}
|
|
270205
270209
|
}
|
|
270206
270210
|
var FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
270211
|
+
var SHIMMER = ["·", "✢", "✳", "✶", "✻", "✽"];
|
|
270212
|
+
var SHIMMER_STEP_MS = 120;
|
|
270213
|
+
function shimmer(now = Date.now()) {
|
|
270214
|
+
const period = SHIMMER.length * 2 - 2;
|
|
270215
|
+
const step = Math.floor(now / SHIMMER_STEP_MS) % period;
|
|
270216
|
+
const index = step < SHIMMER.length ? step : period - step;
|
|
270217
|
+
return SHIMMER[index];
|
|
270218
|
+
}
|
|
270207
270219
|
var MUSINGS = [
|
|
270208
270220
|
"Shmoozing",
|
|
270209
270221
|
"Shmoogling",
|
|
@@ -270267,7 +270279,7 @@ function createTurnStream(interactive, write = (text) => process.stdout.write(te
|
|
|
270267
270279
|
return;
|
|
270268
270280
|
const lines = [
|
|
270269
270281
|
...footer.length ? ["", ...footer] : [],
|
|
270270
|
-
source_default.dim(`${FRAMES[frame]} ${statusLabel()}`)
|
|
270282
|
+
running.size === 0 ? `${source_default.magenta(shimmer())} ${source_default.dim(statusLabel())}` : source_default.dim(`${FRAMES[frame]} ${statusLabel()}`)
|
|
270271
270283
|
];
|
|
270272
270284
|
write(lines.join(`
|
|
270273
270285
|
`));
|
|
@@ -270343,6 +270355,10 @@ var CreatedAppSchema = object({
|
|
|
270343
270355
|
name: string2().nullish(),
|
|
270344
270356
|
imported_repo_url: string2().nullish()
|
|
270345
270357
|
});
|
|
270358
|
+
var WixCreatedAppSchema = object({
|
|
270359
|
+
app_id: string2().min(1),
|
|
270360
|
+
client_creation_id: string2().min(1)
|
|
270361
|
+
});
|
|
270346
270362
|
var AppStateSchema = object({
|
|
270347
270363
|
id: string2(),
|
|
270348
270364
|
app_type: string2().nullish(),
|
|
@@ -270382,7 +270398,8 @@ var ConversationMessageSchema = object({
|
|
|
270382
270398
|
name: string2(),
|
|
270383
270399
|
arguments_string: string2().nullish(),
|
|
270384
270400
|
status: string2().nullish(),
|
|
270385
|
-
results: unknown().nullish()
|
|
270401
|
+
results: unknown().nullish(),
|
|
270402
|
+
waiting_on: object({ kind: string2().nullish() }).nullish()
|
|
270386
270403
|
})).nullish()
|
|
270387
270404
|
});
|
|
270388
270405
|
var FullConversationSchema = object({
|
|
@@ -270399,6 +270416,24 @@ function parseOrThrow(schema, payload, what) {
|
|
|
270399
270416
|
function branchScope(branchId) {
|
|
270400
270417
|
return branchId ? { branch_id: branchId } : {};
|
|
270401
270418
|
}
|
|
270419
|
+
async function createWixLaunchedApp(options) {
|
|
270420
|
+
let response;
|
|
270421
|
+
try {
|
|
270422
|
+
response = await base44Client.post("api/wix/create-app", {
|
|
270423
|
+
timeout: false,
|
|
270424
|
+
context: { __redactBody: true },
|
|
270425
|
+
json: {
|
|
270426
|
+
prompt: options.prompt,
|
|
270427
|
+
signed_instance: options.signedInstance,
|
|
270428
|
+
...options.wixClientId ? { wix_client_id: options.wixClientId } : {}
|
|
270429
|
+
}
|
|
270430
|
+
});
|
|
270431
|
+
} catch (error) {
|
|
270432
|
+
throw await ApiError.fromHttpError(error, "creating app via Wix launch");
|
|
270433
|
+
}
|
|
270434
|
+
const created = parseOrThrow(WixCreatedAppSchema, await response.json(), "app");
|
|
270435
|
+
return { id: created.app_id, client_creation_id: created.client_creation_id };
|
|
270436
|
+
}
|
|
270402
270437
|
async function createApp(options) {
|
|
270403
270438
|
let response;
|
|
270404
270439
|
try {
|
|
@@ -270456,6 +270491,25 @@ async function getAppState(appId) {
|
|
|
270456
270491
|
}
|
|
270457
270492
|
return parseOrThrow(AppStateSchema, await response.json(), "app status");
|
|
270458
270493
|
}
|
|
270494
|
+
async function answerToolCall(options, branchId) {
|
|
270495
|
+
let response;
|
|
270496
|
+
try {
|
|
270497
|
+
response = await getAppClient().post("chat/submit-tool-call-input", {
|
|
270498
|
+
timeout: false,
|
|
270499
|
+
context: { __redactBody: true },
|
|
270500
|
+
searchParams: branchScope(branchId),
|
|
270501
|
+
json: {
|
|
270502
|
+
tool_call_id: options.toolCallId,
|
|
270503
|
+
action: options.action,
|
|
270504
|
+
extra_user_input: options.input ?? {},
|
|
270505
|
+
...options.messageId ? { message_id: options.messageId } : {}
|
|
270506
|
+
}
|
|
270507
|
+
});
|
|
270508
|
+
} catch (error) {
|
|
270509
|
+
throw await ApiError.fromHttpError(error, "answering the agent");
|
|
270510
|
+
}
|
|
270511
|
+
return parseOrThrow(ChatTurnSchema, await response.json(), "chat turn");
|
|
270512
|
+
}
|
|
270459
270513
|
async function sendTurn(content, branchId) {
|
|
270460
270514
|
let response;
|
|
270461
270515
|
try {
|
|
@@ -270544,7 +270598,15 @@ async function createAndLinkApp(options) {
|
|
|
270544
270598
|
if (await appConfigExists(targetDir)) {
|
|
270545
270599
|
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
270600
|
}
|
|
270547
|
-
|
|
270601
|
+
let clientCreationId;
|
|
270602
|
+
const created = options.wixInstance ? await createWixLaunchedApp({
|
|
270603
|
+
prompt: options.prompt ?? "",
|
|
270604
|
+
signedInstance: options.wixInstance.signedInstance,
|
|
270605
|
+
wixClientId: options.wixInstance.wixClientId
|
|
270606
|
+
}).then((c) => {
|
|
270607
|
+
clientCreationId = c.client_creation_id;
|
|
270608
|
+
return c;
|
|
270609
|
+
}) : options.importRepo ? await createImportedApp({
|
|
270548
270610
|
appName: name,
|
|
270549
270611
|
repoUrl: options.importRepo,
|
|
270550
270612
|
sourceMode: options.mode ?? "direct",
|
|
@@ -270568,7 +270630,8 @@ async function createAndLinkApp(options) {
|
|
|
270568
270630
|
repoUrl: created.imported_repo_url ?? undefined,
|
|
270569
270631
|
dirName,
|
|
270570
270632
|
targetDir,
|
|
270571
|
-
here
|
|
270633
|
+
here,
|
|
270634
|
+
...clientCreationId ? { clientCreationId } : {}
|
|
270572
270635
|
};
|
|
270573
270636
|
}
|
|
270574
270637
|
function repoLabel(url) {
|
|
@@ -270920,6 +270983,12 @@ function getSendCommand() {
|
|
|
270920
270983
|
// src/cli/commands/builder/new.ts
|
|
270921
270984
|
var POLL_TIMEOUT_MS = 20 * 60000;
|
|
270922
270985
|
var MODES = ["direct", "fork", "copy"];
|
|
270986
|
+
async function readStdin2() {
|
|
270987
|
+
const chunks = [];
|
|
270988
|
+
for await (const chunk of process.stdin)
|
|
270989
|
+
chunks.push(chunk);
|
|
270990
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
270991
|
+
}
|
|
270923
270992
|
async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
270924
270993
|
if (options.mode && !MODES.includes(options.mode)) {
|
|
270925
270994
|
throw new InvalidInputError("--mode must be direct, fork, or copy.");
|
|
@@ -270927,6 +270996,20 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
270927
270996
|
if ((options.mode || options.repoName || options.fromBranch) && !options.import) {
|
|
270928
270997
|
throw new InvalidInputError("--mode, --repo-name and --from-branch apply only with --import <repo>.");
|
|
270929
270998
|
}
|
|
270999
|
+
if (options.wixInstance && options.import) {
|
|
271000
|
+
throw new InvalidInputError("--wix-instance and --import are exclusive.");
|
|
271001
|
+
}
|
|
271002
|
+
if (options.wixClientId && !options.wixInstance) {
|
|
271003
|
+
throw new InvalidInputError("--wix-client-id applies only with --wix-instance.");
|
|
271004
|
+
}
|
|
271005
|
+
const signedInstance = options.wixInstance ? (options.wixInstance === "-" ? await readStdin2() : options.wixInstance).trim() : undefined;
|
|
271006
|
+
if (options.wixInstance && !signedInstance) {
|
|
271007
|
+
throw new InvalidInputError("--wix-instance is empty.");
|
|
271008
|
+
}
|
|
271009
|
+
const wixInstance = signedInstance ? { signedInstance, wixClientId: options.wixClientId?.trim() || undefined } : undefined;
|
|
271010
|
+
if (wixInstance && !prompt) {
|
|
271011
|
+
throw new InvalidInputError("--wix-instance needs the prompt argument: what the agent should build.");
|
|
271012
|
+
}
|
|
270930
271013
|
if (!prompt && !options.import) {
|
|
270931
271014
|
throw new InvalidInputError('Describe the app ("<prompt>") or pass --import <repo>.');
|
|
270932
271015
|
}
|
|
@@ -270943,7 +271026,8 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
270943
271026
|
mode: options.mode,
|
|
270944
271027
|
repoName: options.repoName,
|
|
270945
271028
|
fromBranch: options.fromBranch,
|
|
270946
|
-
path: options.path
|
|
271029
|
+
path: options.path,
|
|
271030
|
+
wixInstance
|
|
270947
271031
|
}));
|
|
270948
271032
|
} catch (error) {
|
|
270949
271033
|
for (const line of await githubReauthLines(error) ?? [])
|
|
@@ -270957,11 +271041,15 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
270957
271041
|
repo_url: app.repoUrl ?? null,
|
|
270958
271042
|
editor_url: app.editorUrl,
|
|
270959
271043
|
dir: app.dirName,
|
|
270960
|
-
path: app.targetDir
|
|
271044
|
+
path: app.targetDir,
|
|
271045
|
+
...app.clientCreationId ? { client_creation_id: app.clientCreationId } : {}
|
|
270961
271046
|
});
|
|
270962
271047
|
} else if (!jsonMode) {
|
|
270963
271048
|
if (app.repoUrl)
|
|
270964
271049
|
log.message(source_default.dim(`repo ${app.repoUrl}`));
|
|
271050
|
+
if (app.clientCreationId) {
|
|
271051
|
+
log.message(source_default.dim("wix launched — connector connected before the first turn"));
|
|
271052
|
+
}
|
|
270965
271053
|
log.message(source_default.dim(`editor ${app.editorUrl}`));
|
|
270966
271054
|
log.message(source_default.dim(`linked ${app.here ? "./ (this directory)" : `./${app.dirName}`}`));
|
|
270967
271055
|
}
|
|
@@ -271012,7 +271100,8 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
271012
271100
|
preview_url: previewUrl ?? null,
|
|
271013
271101
|
dir: app.dirName,
|
|
271014
271102
|
path: app.targetDir,
|
|
271015
|
-
status: finalState ?? "created"
|
|
271103
|
+
status: finalState ?? "created",
|
|
271104
|
+
...app.clientCreationId ? { client_creation_id: app.clientCreationId } : {}
|
|
271016
271105
|
})}
|
|
271017
271106
|
`
|
|
271018
271107
|
};
|
|
@@ -271037,7 +271126,7 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
|
|
|
271037
271126
|
}
|
|
271038
271127
|
function getNewCommand() {
|
|
271039
271128
|
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);
|
|
271129
|
+
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-instance <token>", 'Create through the Wix route with this signed instance (the Wix connector is connected before the first turn); "-" reads the token from stdin').env("BASE44_WIX_INSTANCE")).option("--wix-client-id <id>", "The companion OAuth app's client id, when the Wix launch has one").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
271130
|
return command;
|
|
271042
271131
|
}
|
|
271043
271132
|
|
|
@@ -276232,6 +276321,393 @@ function createPasteFriendlyStdin(real) {
|
|
|
276232
276321
|
return proxy;
|
|
276233
276322
|
}
|
|
276234
276323
|
|
|
276324
|
+
// src/core/resources/apps/pending.ts
|
|
276325
|
+
var CHOICE_TOOLS = new Set([
|
|
276326
|
+
"ask_clarifying_questions",
|
|
276327
|
+
"ask_plan_questions"
|
|
276328
|
+
]);
|
|
276329
|
+
var SECRET_TOOLS = new Set(["set_secrets"]);
|
|
276330
|
+
var PERMISSION_TOOLS = new Set(["request_agent_tool_permissions"]);
|
|
276331
|
+
var BROWSER_TOOLS = new Set([
|
|
276332
|
+
"connect_github_account",
|
|
276333
|
+
"request_oauth_authorization",
|
|
276334
|
+
"register_workspace_connector",
|
|
276335
|
+
"configure_psp_credentials",
|
|
276336
|
+
"plaid_connect"
|
|
276337
|
+
]);
|
|
276338
|
+
var str2 = (v) => typeof v === "string" && v.trim() ? v.trim() : undefined;
|
|
276339
|
+
function parseArgs(raw) {
|
|
276340
|
+
try {
|
|
276341
|
+
const parsed = JSON.parse(raw ?? "");
|
|
276342
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
276343
|
+
} catch {
|
|
276344
|
+
return {};
|
|
276345
|
+
}
|
|
276346
|
+
}
|
|
276347
|
+
function questionsFrom(args) {
|
|
276348
|
+
const raw = Array.isArray(args.questions) ? args.questions : [];
|
|
276349
|
+
return raw.flatMap((q) => {
|
|
276350
|
+
if (!q || typeof q !== "object")
|
|
276351
|
+
return [];
|
|
276352
|
+
const item = q;
|
|
276353
|
+
const question = str2(item.question);
|
|
276354
|
+
if (!question)
|
|
276355
|
+
return [];
|
|
276356
|
+
const options = (Array.isArray(item.options) ? item.options : []).flatMap((o) => {
|
|
276357
|
+
const opt = o;
|
|
276358
|
+
const label = str2(opt?.label);
|
|
276359
|
+
return label ? [{ label, description: str2(opt.description) }] : [];
|
|
276360
|
+
});
|
|
276361
|
+
return [
|
|
276362
|
+
{
|
|
276363
|
+
question,
|
|
276364
|
+
description: str2(item.description),
|
|
276365
|
+
options,
|
|
276366
|
+
multiSelect: item.multi_select === true
|
|
276367
|
+
}
|
|
276368
|
+
];
|
|
276369
|
+
});
|
|
276370
|
+
}
|
|
276371
|
+
function secretsFrom(args) {
|
|
276372
|
+
const raw = Array.isArray(args.secrets_schema) ? args.secrets_schema : [];
|
|
276373
|
+
return raw.flatMap((s) => {
|
|
276374
|
+
const item = s;
|
|
276375
|
+
const name = str2(item?.secretName) ?? str2(item?.name);
|
|
276376
|
+
return name ? [{ name, description: str2(item.description) }] : [];
|
|
276377
|
+
});
|
|
276378
|
+
}
|
|
276379
|
+
function permissionKey(row) {
|
|
276380
|
+
switch (row.type) {
|
|
276381
|
+
case "entity":
|
|
276382
|
+
return row.entity_name ? `entity:${row.entity_name}` : null;
|
|
276383
|
+
case "backend_function":
|
|
276384
|
+
return row.function_name ? `backend_function:${row.function_name}` : null;
|
|
276385
|
+
case "app_user_connector":
|
|
276386
|
+
return row.connector_id ? `app_user_connector:${row.connector_id}` : null;
|
|
276387
|
+
default:
|
|
276388
|
+
return null;
|
|
276389
|
+
}
|
|
276390
|
+
}
|
|
276391
|
+
function permissionsFrom(args) {
|
|
276392
|
+
const raw = Array.isArray(args.requested_permissions) ? args.requested_permissions : [];
|
|
276393
|
+
return raw.flatMap((r) => {
|
|
276394
|
+
const row = r;
|
|
276395
|
+
const key = permissionKey(row);
|
|
276396
|
+
if (!key)
|
|
276397
|
+
return [];
|
|
276398
|
+
const ops = Array.isArray(row.allowed_operations) ? ` (${row.allowed_operations.join(", ")})` : "";
|
|
276399
|
+
const target = str2(row.entity_name) ?? str2(row.function_name) ?? str2(row.connector_name) ?? key;
|
|
276400
|
+
return [
|
|
276401
|
+
{ key, label: `${row.type}: ${target}${ops}`, reason: str2(row.reason) }
|
|
276402
|
+
];
|
|
276403
|
+
});
|
|
276404
|
+
}
|
|
276405
|
+
function guardFrom(results) {
|
|
276406
|
+
const value = typeof results === "string" ? (() => {
|
|
276407
|
+
try {
|
|
276408
|
+
return JSON.parse(results);
|
|
276409
|
+
} catch {
|
|
276410
|
+
return null;
|
|
276411
|
+
}
|
|
276412
|
+
})() : results;
|
|
276413
|
+
if (!value || typeof value !== "object")
|
|
276414
|
+
return null;
|
|
276415
|
+
const g = value;
|
|
276416
|
+
if (!str2(g.guard))
|
|
276417
|
+
return null;
|
|
276418
|
+
return { title: `${g.guard}: needs your approval`, detail: str2(g.reason) };
|
|
276419
|
+
}
|
|
276420
|
+
function humanize(tool) {
|
|
276421
|
+
return tool.replace(/_/g, " ");
|
|
276422
|
+
}
|
|
276423
|
+
function pendingInputs(messages) {
|
|
276424
|
+
const out = [];
|
|
276425
|
+
for (const message of messages) {
|
|
276426
|
+
for (const call of message.tool_calls ?? []) {
|
|
276427
|
+
if (call.status !== "waiting_for_user_input")
|
|
276428
|
+
continue;
|
|
276429
|
+
const args = parseArgs(call.arguments_string);
|
|
276430
|
+
const base = {
|
|
276431
|
+
toolCallId: call.id,
|
|
276432
|
+
messageId: message.id,
|
|
276433
|
+
tool: call.name
|
|
276434
|
+
};
|
|
276435
|
+
const summary = str2(args.summary);
|
|
276436
|
+
if (CHOICE_TOOLS.has(call.name)) {
|
|
276437
|
+
out.push({
|
|
276438
|
+
...base,
|
|
276439
|
+
kind: "choice",
|
|
276440
|
+
title: summary ?? "The agent has a few questions",
|
|
276441
|
+
questions: questionsFrom(args)
|
|
276442
|
+
});
|
|
276443
|
+
} else if (SECRET_TOOLS.has(call.name)) {
|
|
276444
|
+
out.push({
|
|
276445
|
+
...base,
|
|
276446
|
+
kind: "secrets",
|
|
276447
|
+
title: summary ?? "The agent needs secrets",
|
|
276448
|
+
secrets: secretsFrom(args)
|
|
276449
|
+
});
|
|
276450
|
+
} else if (PERMISSION_TOOLS.has(call.name)) {
|
|
276451
|
+
out.push({
|
|
276452
|
+
...base,
|
|
276453
|
+
kind: "permissions",
|
|
276454
|
+
title: summary ?? "Grant the app's agent these permissions?",
|
|
276455
|
+
detail: str2(args.reason),
|
|
276456
|
+
permissions: permissionsFrom(args)
|
|
276457
|
+
});
|
|
276458
|
+
} else if (BROWSER_TOOLS.has(call.name)) {
|
|
276459
|
+
out.push({
|
|
276460
|
+
...base,
|
|
276461
|
+
kind: "browser",
|
|
276462
|
+
title: summary ?? humanize(call.name),
|
|
276463
|
+
detail: str2(args.reason)
|
|
276464
|
+
});
|
|
276465
|
+
} else {
|
|
276466
|
+
const guard = guardFrom(call.results);
|
|
276467
|
+
const integration = str2(args.integration_type);
|
|
276468
|
+
out.push({
|
|
276469
|
+
...base,
|
|
276470
|
+
kind: "approval",
|
|
276471
|
+
title: guard?.title ?? (integration ? `Enable ${integration}?` : summary ?? `${humanize(call.name)}?`),
|
|
276472
|
+
detail: guard?.detail ?? (integration ? summary : undefined)
|
|
276473
|
+
});
|
|
276474
|
+
}
|
|
276475
|
+
}
|
|
276476
|
+
}
|
|
276477
|
+
return out;
|
|
276478
|
+
}
|
|
276479
|
+
function choiceAnswers(questions, selections) {
|
|
276480
|
+
const answers = questions.flatMap((q, index) => {
|
|
276481
|
+
const sel = selections[index];
|
|
276482
|
+
if (!sel || sel.labels.length === 0 && !sel.customText)
|
|
276483
|
+
return [];
|
|
276484
|
+
const answer = { question_index: index };
|
|
276485
|
+
if (q.multiSelect) {
|
|
276486
|
+
if (sel.labels.length)
|
|
276487
|
+
answer.selected_labels = sel.labels;
|
|
276488
|
+
} else if (sel.labels[0]) {
|
|
276489
|
+
answer.selected_label = sel.labels[0];
|
|
276490
|
+
}
|
|
276491
|
+
if (sel.customText)
|
|
276492
|
+
answer.custom_text = sel.customText;
|
|
276493
|
+
return [answer];
|
|
276494
|
+
});
|
|
276495
|
+
return { answers };
|
|
276496
|
+
}
|
|
276497
|
+
|
|
276498
|
+
// src/cli/commands/code/pending-card.ts
|
|
276499
|
+
function openCard(pending) {
|
|
276500
|
+
return {
|
|
276501
|
+
pending,
|
|
276502
|
+
step: 0,
|
|
276503
|
+
cursor: 0,
|
|
276504
|
+
selections: (pending.questions ?? []).map(() => ({ labels: [] })),
|
|
276505
|
+
granted: new Set((pending.permissions ?? []).map((p) => p.key)),
|
|
276506
|
+
typing: pending.kind === "secrets" ? "secret" : null,
|
|
276507
|
+
secretValues: {}
|
|
276508
|
+
};
|
|
276509
|
+
}
|
|
276510
|
+
var done = (action, input = {}) => ({ state: null, submit: { action, input } });
|
|
276511
|
+
var later = { state: null, dismissed: true };
|
|
276512
|
+
function choiceRows(state) {
|
|
276513
|
+
return (state.pending.questions?.[state.step]?.options.length ?? 0) + 1;
|
|
276514
|
+
}
|
|
276515
|
+
function advanceChoice(state) {
|
|
276516
|
+
const questions = state.pending.questions ?? [];
|
|
276517
|
+
if (state.step + 1 < questions.length) {
|
|
276518
|
+
return {
|
|
276519
|
+
state: { ...state, step: state.step + 1, cursor: 0, typing: null }
|
|
276520
|
+
};
|
|
276521
|
+
}
|
|
276522
|
+
return done("approved", choiceAnswers(questions, state.selections));
|
|
276523
|
+
}
|
|
276524
|
+
function choiceKey(state, key) {
|
|
276525
|
+
const question = state.pending.questions?.[state.step];
|
|
276526
|
+
if (!question)
|
|
276527
|
+
return done("approved", { answers: [] });
|
|
276528
|
+
const rows = choiceRows(state);
|
|
276529
|
+
const custom = state.cursor === rows - 1;
|
|
276530
|
+
const sel = state.selections[state.step] ?? { labels: [] };
|
|
276531
|
+
const setSel = (next) => {
|
|
276532
|
+
const selections = [...state.selections];
|
|
276533
|
+
selections[state.step] = next;
|
|
276534
|
+
return { ...state, selections };
|
|
276535
|
+
};
|
|
276536
|
+
switch (key) {
|
|
276537
|
+
case "up":
|
|
276538
|
+
return { state: { ...state, cursor: (state.cursor - 1 + rows) % rows } };
|
|
276539
|
+
case "down":
|
|
276540
|
+
return { state: { ...state, cursor: (state.cursor + 1) % rows } };
|
|
276541
|
+
case "space": {
|
|
276542
|
+
if (custom)
|
|
276543
|
+
return { state: { ...state, typing: "custom" } };
|
|
276544
|
+
const label = question.options[state.cursor].label;
|
|
276545
|
+
const labels = question.multiSelect ? sel.labels.includes(label) ? sel.labels.filter((l) => l !== label) : [...sel.labels, label] : [label];
|
|
276546
|
+
return { state: setSel({ ...sel, labels }) };
|
|
276547
|
+
}
|
|
276548
|
+
case "enter": {
|
|
276549
|
+
if (custom)
|
|
276550
|
+
return { state: { ...state, typing: "custom" } };
|
|
276551
|
+
if (question.multiSelect) {
|
|
276552
|
+
if (sel.labels.length === 0 && !sel.customText)
|
|
276553
|
+
return { state };
|
|
276554
|
+
return advanceChoice(state);
|
|
276555
|
+
}
|
|
276556
|
+
const label = question.options[state.cursor].label;
|
|
276557
|
+
return advanceChoice(setSel({ labels: [label] }));
|
|
276558
|
+
}
|
|
276559
|
+
case "s":
|
|
276560
|
+
return done("approved", { answers: [] });
|
|
276561
|
+
case "escape":
|
|
276562
|
+
return later;
|
|
276563
|
+
default:
|
|
276564
|
+
return { state };
|
|
276565
|
+
}
|
|
276566
|
+
}
|
|
276567
|
+
function permissionsKey(state, key) {
|
|
276568
|
+
const rows = state.pending.permissions ?? [];
|
|
276569
|
+
switch (key) {
|
|
276570
|
+
case "up":
|
|
276571
|
+
return {
|
|
276572
|
+
state: {
|
|
276573
|
+
...state,
|
|
276574
|
+
cursor: (state.cursor - 1 + rows.length) % rows.length
|
|
276575
|
+
}
|
|
276576
|
+
};
|
|
276577
|
+
case "down":
|
|
276578
|
+
return { state: { ...state, cursor: (state.cursor + 1) % rows.length } };
|
|
276579
|
+
case "space": {
|
|
276580
|
+
const k = rows[state.cursor]?.key;
|
|
276581
|
+
if (!k)
|
|
276582
|
+
return { state };
|
|
276583
|
+
const granted = new Set(state.granted);
|
|
276584
|
+
if (granted.has(k))
|
|
276585
|
+
granted.delete(k);
|
|
276586
|
+
else
|
|
276587
|
+
granted.add(k);
|
|
276588
|
+
return { state: { ...state, granted } };
|
|
276589
|
+
}
|
|
276590
|
+
case "enter":
|
|
276591
|
+
case "y":
|
|
276592
|
+
return done("approved", {
|
|
276593
|
+
approved_permission_keys: rows.map((r) => r.key).filter((k) => state.granted.has(k))
|
|
276594
|
+
});
|
|
276595
|
+
case "n":
|
|
276596
|
+
return done("rejected");
|
|
276597
|
+
case "escape":
|
|
276598
|
+
return later;
|
|
276599
|
+
default:
|
|
276600
|
+
return { state };
|
|
276601
|
+
}
|
|
276602
|
+
}
|
|
276603
|
+
function cardKey(state, key) {
|
|
276604
|
+
if (state.typing) {
|
|
276605
|
+
if (key === "escape") {
|
|
276606
|
+
return state.typing === "secret" ? later : { state: { ...state, typing: null } };
|
|
276607
|
+
}
|
|
276608
|
+
return { state };
|
|
276609
|
+
}
|
|
276610
|
+
switch (state.pending.kind) {
|
|
276611
|
+
case "choice":
|
|
276612
|
+
return choiceKey(state, key);
|
|
276613
|
+
case "permissions":
|
|
276614
|
+
return permissionsKey(state, key);
|
|
276615
|
+
default:
|
|
276616
|
+
if (key === "y" || key === "enter")
|
|
276617
|
+
return done("approved");
|
|
276618
|
+
if (key === "n")
|
|
276619
|
+
return done("rejected");
|
|
276620
|
+
if (key === "escape")
|
|
276621
|
+
return later;
|
|
276622
|
+
return { state };
|
|
276623
|
+
}
|
|
276624
|
+
}
|
|
276625
|
+
function cardText(state, text) {
|
|
276626
|
+
const value = text.trim();
|
|
276627
|
+
if (state.typing === "custom") {
|
|
276628
|
+
if (!value)
|
|
276629
|
+
return { state: { ...state, typing: null } };
|
|
276630
|
+
const selections = [...state.selections];
|
|
276631
|
+
const current = selections[state.step] ?? { labels: [] };
|
|
276632
|
+
selections[state.step] = { ...current, customText: value };
|
|
276633
|
+
return advanceChoice({ ...state, selections, typing: null });
|
|
276634
|
+
}
|
|
276635
|
+
if (state.typing === "secret") {
|
|
276636
|
+
const fields = state.pending.secrets ?? [];
|
|
276637
|
+
const field = fields[state.step];
|
|
276638
|
+
if (!field || !value)
|
|
276639
|
+
return { state };
|
|
276640
|
+
const secretValues = { ...state.secretValues, [field.name]: value };
|
|
276641
|
+
if (state.step + 1 < fields.length) {
|
|
276642
|
+
return { state: { ...state, secretValues, step: state.step + 1 } };
|
|
276643
|
+
}
|
|
276644
|
+
return done("approved", { secrets: secretValues });
|
|
276645
|
+
}
|
|
276646
|
+
return { state };
|
|
276647
|
+
}
|
|
276648
|
+
function cardLines(state) {
|
|
276649
|
+
const p = state.pending;
|
|
276650
|
+
const head = [source_default.bold(`⏸ ${p.title}`)];
|
|
276651
|
+
if (p.detail)
|
|
276652
|
+
head.push(source_default.dim(` ${p.detail}`));
|
|
276653
|
+
switch (p.kind) {
|
|
276654
|
+
case "choice": {
|
|
276655
|
+
const q = p.questions?.[state.step];
|
|
276656
|
+
if (!q)
|
|
276657
|
+
return [...head, source_default.dim(" (no questions) · Enter to continue")];
|
|
276658
|
+
const total = p.questions?.length ?? 1;
|
|
276659
|
+
const sel = state.selections[state.step] ?? { labels: [] };
|
|
276660
|
+
const rows = q.options.map((o, i) => {
|
|
276661
|
+
const on = sel.labels.includes(o.label);
|
|
276662
|
+
const mark = q.multiSelect ? on ? "☑" : "☐" : on ? "●" : "○";
|
|
276663
|
+
const text = `${state.cursor === i ? "▸" : " "} ${mark} ${o.label}${o.description ? source_default.dim(` — ${o.description}`) : ""}`;
|
|
276664
|
+
return state.cursor === i ? source_default.cyan(text) : text;
|
|
276665
|
+
});
|
|
276666
|
+
const customRow = `${state.cursor === q.options.length ? "▸" : " "} ✎ something else${sel.customText ? source_default.dim(` — ${sel.customText}`) : ""}`;
|
|
276667
|
+
rows.push(state.cursor === q.options.length ? source_default.cyan(customRow) : customRow);
|
|
276668
|
+
return [
|
|
276669
|
+
...head,
|
|
276670
|
+
` ${source_default.bold(q.question)} ${source_default.dim(`(${state.step + 1}/${total})`)}`,
|
|
276671
|
+
...q.description ? [source_default.dim(` ${q.description}`)] : [],
|
|
276672
|
+
...rows.map((r) => ` ${r}`),
|
|
276673
|
+
source_default.dim(q.multiSelect ? " ↑↓ move · space toggle · Enter next · s skip all · Esc later" : " ↑↓ move · Enter choose · s skip all · Esc later")
|
|
276674
|
+
];
|
|
276675
|
+
}
|
|
276676
|
+
case "permissions": {
|
|
276677
|
+
const rows = (p.permissions ?? []).map((r, i) => {
|
|
276678
|
+
const text = `${state.cursor === i ? "▸" : " "} ${state.granted.has(r.key) ? "☑" : "☐"} ${r.label}${r.reason ? source_default.dim(` — ${r.reason}`) : ""}`;
|
|
276679
|
+
return ` ${state.cursor === i ? source_default.cyan(text) : text}`;
|
|
276680
|
+
});
|
|
276681
|
+
return [
|
|
276682
|
+
...head,
|
|
276683
|
+
...rows,
|
|
276684
|
+
source_default.dim(" space toggle · Enter grant ticked · n reject all · Esc later")
|
|
276685
|
+
];
|
|
276686
|
+
}
|
|
276687
|
+
case "secrets": {
|
|
276688
|
+
const fields = p.secrets ?? [];
|
|
276689
|
+
const rows = fields.map((f, i) => {
|
|
276690
|
+
const filled = f.name in state.secretValues;
|
|
276691
|
+
const mark = filled ? source_default.green("✓") : i === state.step ? "▸" : "○";
|
|
276692
|
+
return ` ${mark} ${f.name}${f.description ? source_default.dim(` — ${f.description}`) : ""}`;
|
|
276693
|
+
});
|
|
276694
|
+
return [
|
|
276695
|
+
...head,
|
|
276696
|
+
...rows,
|
|
276697
|
+
source_default.dim(" type the value below (hidden) · Enter next · Esc later")
|
|
276698
|
+
];
|
|
276699
|
+
}
|
|
276700
|
+
case "browser":
|
|
276701
|
+
return [
|
|
276702
|
+
...head,
|
|
276703
|
+
source_default.dim(" finish this step in the editor (footer link), then press y"),
|
|
276704
|
+
source_default.dim(" y continue · n reject · Esc later")
|
|
276705
|
+
];
|
|
276706
|
+
default:
|
|
276707
|
+
return [...head, source_default.dim(" y approve · n reject · Esc later")];
|
|
276708
|
+
}
|
|
276709
|
+
}
|
|
276710
|
+
|
|
276235
276711
|
// src/cli/commands/code/session-engine.ts
|
|
276236
276712
|
var POLL_MS = 1000;
|
|
276237
276713
|
function createSessionEngine(options) {
|
|
@@ -276251,6 +276727,28 @@ function createSessionEngine(options) {
|
|
|
276251
276727
|
let awaitingTurn = options.awaitingTurnLabel ?? null;
|
|
276252
276728
|
const awaitingSince = Date.now();
|
|
276253
276729
|
let lastEventAt = Date.now();
|
|
276730
|
+
let pending = [];
|
|
276731
|
+
const answered = new Set;
|
|
276732
|
+
const answer = (p, action, input = {}) => {
|
|
276733
|
+
answered.add(p.toolCallId);
|
|
276734
|
+
pending = pending.filter((x) => x.toolCallId !== p.toolCallId);
|
|
276735
|
+
const verb = action === "rejected" ? source_default.red("✗ rejected") : Object.keys(input).length ? source_default.green("→ answered") : source_default.green("✓ approved");
|
|
276736
|
+
options.onLine(`${verb} ${source_default.dim("—")} ${p.title}`);
|
|
276737
|
+
pendingSubmitAt = Date.now();
|
|
276738
|
+
sendsInFlight++;
|
|
276739
|
+
answerToolCall({ toolCallId: p.toolCallId, messageId: p.messageId, action, input }, options.branchId).catch((error) => {
|
|
276740
|
+
const status = error instanceof ApiError ? error.statusCode : undefined;
|
|
276741
|
+
const edgeDrop = status === 502 || status === 503 || status === 504 || /timeout|gateway/i.test(error instanceof Error ? error.message : "");
|
|
276742
|
+
if (edgeDrop && (turnStartedAt != null || pendingSubmitAt == null)) {
|
|
276743
|
+
return;
|
|
276744
|
+
}
|
|
276745
|
+
answered.delete(p.toolCallId);
|
|
276746
|
+
pendingSubmitAt = null;
|
|
276747
|
+
options.onLine(source_default.red(`✗ answer failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
276748
|
+
}).finally(() => {
|
|
276749
|
+
sendsInFlight--;
|
|
276750
|
+
});
|
|
276751
|
+
};
|
|
276254
276752
|
const submit = (raw) => {
|
|
276255
276753
|
const typed = raw.trim();
|
|
276256
276754
|
if (!typed)
|
|
@@ -276291,6 +276789,12 @@ function createSessionEngine(options) {
|
|
|
276291
276789
|
return;
|
|
276292
276790
|
}
|
|
276293
276791
|
const events = diffConversation(diffState, messages);
|
|
276792
|
+
const waiting = pendingInputs(messages);
|
|
276793
|
+
for (const id of answered) {
|
|
276794
|
+
if (!waiting.some((w) => w.toolCallId === id))
|
|
276795
|
+
answered.delete(id);
|
|
276796
|
+
}
|
|
276797
|
+
pending = waiting.filter((w) => !answered.has(w.toolCallId));
|
|
276294
276798
|
if (!prime) {
|
|
276295
276799
|
for (const event of events) {
|
|
276296
276800
|
if (event.kind === "tool_start") {
|
|
@@ -276314,7 +276818,9 @@ function createSessionEngine(options) {
|
|
|
276314
276818
|
});
|
|
276315
276819
|
continue;
|
|
276316
276820
|
}
|
|
276317
|
-
const line = eventLine(event
|
|
276821
|
+
const line = eventLine(event, undefined, {
|
|
276822
|
+
waitingHint: "answer in the card below"
|
|
276823
|
+
});
|
|
276318
276824
|
if (line != null) {
|
|
276319
276825
|
lastEventAt = Date.now();
|
|
276320
276826
|
options.onLine(line);
|
|
@@ -276381,6 +276887,7 @@ function createSessionEngine(options) {
|
|
|
276381
276887
|
});
|
|
276382
276888
|
},
|
|
276383
276889
|
submit,
|
|
276890
|
+
answer,
|
|
276384
276891
|
status() {
|
|
276385
276892
|
let phase = "idle";
|
|
276386
276893
|
if (awaitingTurn != null)
|
|
@@ -276403,7 +276910,8 @@ function createSessionEngine(options) {
|
|
|
276403
276910
|
turnStartedAt,
|
|
276404
276911
|
runningTool,
|
|
276405
276912
|
lastTurnMs,
|
|
276406
|
-
lastTurnOk
|
|
276913
|
+
lastTurnOk,
|
|
276914
|
+
pending
|
|
276407
276915
|
};
|
|
276408
276916
|
},
|
|
276409
276917
|
turnRunning() {
|
|
@@ -276454,7 +276962,7 @@ function statusText(status, musingSeed) {
|
|
|
276454
276962
|
case "running": {
|
|
276455
276963
|
const turnFor = formatDuration2(Date.now() - (status.turnStartedAt ?? Date.now()));
|
|
276456
276964
|
const quiet = status.quietForMs > 60000 ? " · a long private step — details render in the editor" : "";
|
|
276457
|
-
return `${source_default.magenta(
|
|
276965
|
+
return `${source_default.magenta(shimmer())} ${source_default.dim(`${idleMusing(musingSeed)} (${turnFor})${quiet}`)}`;
|
|
276458
276966
|
}
|
|
276459
276967
|
case "sending":
|
|
276460
276968
|
return source_default.dim(`${frame} sending…`);
|
|
@@ -276475,6 +276983,8 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276475
276983
|
const [musingSeed] = import_react23.useState(() => Math.floor(Math.random() * 97));
|
|
276476
276984
|
const [currentModel, setCurrentModel] = import_react23.useState(null);
|
|
276477
276985
|
const [pickerIndex, setPickerIndex] = import_react23.useState(null);
|
|
276986
|
+
const [card, setCard] = import_react23.useState(null);
|
|
276987
|
+
const dismissedRef = import_react23.useRef(new Set);
|
|
276478
276988
|
const maxScrollRef = import_react23.useRef(0);
|
|
276479
276989
|
const meIdRef = import_react23.useRef(null);
|
|
276480
276990
|
const emit = (entry) => setItems((h) => withEntry(h, entry));
|
|
@@ -276520,6 +277030,29 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276520
277030
|
emit(source_default.red(` /model: ${error instanceof Error ? error.message : String(error)}`));
|
|
276521
277031
|
}
|
|
276522
277032
|
};
|
|
277033
|
+
const applyCard = (outcome) => {
|
|
277034
|
+
if (outcome.submit && card) {
|
|
277035
|
+
engine.answer(card.pending, outcome.submit.action, outcome.submit.input);
|
|
277036
|
+
}
|
|
277037
|
+
if (outcome.dismissed && card) {
|
|
277038
|
+
dismissedRef.current.add(card.pending.toolCallId);
|
|
277039
|
+
}
|
|
277040
|
+
setCard(outcome.state);
|
|
277041
|
+
};
|
|
277042
|
+
const pending = engine.status().pending;
|
|
277043
|
+
import_react23.useEffect(() => {
|
|
277044
|
+
if (card) {
|
|
277045
|
+
if (!pending.some((p) => p.toolCallId === card.pending.toolCallId)) {
|
|
277046
|
+
setCard(null);
|
|
277047
|
+
}
|
|
277048
|
+
return;
|
|
277049
|
+
}
|
|
277050
|
+
if (pickerIndex !== null)
|
|
277051
|
+
return;
|
|
277052
|
+
const next = pending.find((p) => !dismissedRef.current.has(p.toolCallId));
|
|
277053
|
+
if (next)
|
|
277054
|
+
setCard(openCard(next));
|
|
277055
|
+
}, [pending, card, pickerIndex]);
|
|
276523
277056
|
use_input_default((char, key) => {
|
|
276524
277057
|
if (pickerIndex !== null) {
|
|
276525
277058
|
if (key.upArrow)
|
|
@@ -276535,6 +277068,23 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276535
277068
|
}
|
|
276536
277069
|
return;
|
|
276537
277070
|
}
|
|
277071
|
+
if (key.tab && !card) {
|
|
277072
|
+
const next = pending.find((p) => dismissedRef.current.has(p.toolCallId));
|
|
277073
|
+
if (next) {
|
|
277074
|
+
dismissedRef.current.delete(next.toolCallId);
|
|
277075
|
+
setCard(openCard(next));
|
|
277076
|
+
}
|
|
277077
|
+
return;
|
|
277078
|
+
}
|
|
277079
|
+
if (card) {
|
|
277080
|
+
const mapped = key.upArrow ? "up" : key.downArrow ? "down" : key.return ? "enter" : key.escape ? "escape" : char === " " ? "space" : char === "y" || char === "n" || char === "s" ? char : null;
|
|
277081
|
+
if (card.typing && mapped !== "escape")
|
|
277082
|
+
return;
|
|
277083
|
+
if (mapped)
|
|
277084
|
+
applyCard(cardKey(card, mapped));
|
|
277085
|
+
if (mapped || !card.typing)
|
|
277086
|
+
return;
|
|
277087
|
+
}
|
|
276538
277088
|
if (key.ctrl && char === "c") {
|
|
276539
277089
|
if (input)
|
|
276540
277090
|
setInput("");
|
|
@@ -276579,7 +277129,9 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276579
277129
|
const innerWidth = Math.max(10, width - 4);
|
|
276580
277130
|
const inputRows = Math.max(1, Math.ceil((input.length + 3) / innerWidth));
|
|
276581
277131
|
const pickerOpen = pickerIndex !== null;
|
|
276582
|
-
const
|
|
277132
|
+
const cardOpen = card !== null && !card.typing;
|
|
277133
|
+
const cardRows = card ? cardLines(card).length : 0;
|
|
277134
|
+
const inputBlockHeight = pickerOpen ? MODELS.length + 3 : cardOpen ? cardRows + 2 : inputRows + 2 + (card?.typing ? 1 : 0);
|
|
276583
277135
|
const widgetHeight = inputBlockHeight + 3 + (footer.length ? 1 : 0);
|
|
276584
277136
|
const viewHeight = Math.max(3, rows - widgetHeight - 1);
|
|
276585
277137
|
const lines = items.flatMap((item) => hardWrapAnsi(`${renderEntry(item, { verbose, foldHint: "Ctrl+O to expand" })}
|
|
@@ -276630,29 +277182,64 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276630
277182
|
}, m.name, false, undefined, this);
|
|
276631
277183
|
})
|
|
276632
277184
|
]
|
|
276633
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
277185
|
+
}, undefined, true, undefined, this) : cardOpen && card ? /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
277186
|
+
flexDirection: "column",
|
|
276634
277187
|
borderStyle: "round",
|
|
276635
|
-
borderColor: "
|
|
277188
|
+
borderColor: "yellow",
|
|
277189
|
+
paddingX: 1,
|
|
277190
|
+
width,
|
|
277191
|
+
children: cardLines(card).map((line, i) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
277192
|
+
wrap: "truncate-end",
|
|
277193
|
+
children: line
|
|
277194
|
+
}, i, false, undefined, this))
|
|
277195
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
277196
|
+
flexDirection: "column",
|
|
277197
|
+
borderStyle: "round",
|
|
277198
|
+
borderColor: card?.typing ? "yellow" : "gray",
|
|
276636
277199
|
paddingX: 1,
|
|
276637
277200
|
width,
|
|
276638
277201
|
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
|
-
|
|
277202
|
+
card?.typing === "secret" && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
277203
|
+
wrap: "truncate-end",
|
|
277204
|
+
children: [
|
|
277205
|
+
source_default.bold(card.pending.secrets?.[card.step]?.name ?? "secret"),
|
|
277206
|
+
source_default.dim(" — value is hidden · Enter to save · Esc to cancel")
|
|
277207
|
+
]
|
|
277208
|
+
}, undefined, true, undefined, this),
|
|
277209
|
+
card?.typing === "custom" && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
277210
|
+
wrap: "truncate-end",
|
|
277211
|
+
children: [
|
|
277212
|
+
source_default.bold(card.pending.questions?.[card.step]?.question ?? ""),
|
|
277213
|
+
source_default.dim(" — your own answer · Enter to save · Esc to go back")
|
|
277214
|
+
]
|
|
277215
|
+
}, undefined, true, undefined, this),
|
|
277216
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
277217
|
+
children: [
|
|
277218
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
277219
|
+
color: "cyan",
|
|
277220
|
+
children: "❯ "
|
|
277221
|
+
}, undefined, false, undefined, this),
|
|
277222
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(build_default, {
|
|
277223
|
+
value: input,
|
|
277224
|
+
onChange: setInput,
|
|
277225
|
+
mask: card?.typing === "secret" ? "•" : undefined,
|
|
277226
|
+
onSubmit: (value) => {
|
|
277227
|
+
if (card?.typing) {
|
|
277228
|
+
applyCard(cardText(card, value));
|
|
277229
|
+
setInput("");
|
|
277230
|
+
return;
|
|
277231
|
+
}
|
|
277232
|
+
const trimmed = value.trim();
|
|
277233
|
+
if (trimmed === "/model" || trimmed.startsWith("/model ")) {
|
|
277234
|
+
runModelSlash(trimmed.slice("/model".length).trim());
|
|
277235
|
+
} else if (trimmed) {
|
|
277236
|
+
engine.submit(value);
|
|
277237
|
+
}
|
|
277238
|
+
setInput("");
|
|
277239
|
+
}
|
|
277240
|
+
}, undefined, false, undefined, this)
|
|
277241
|
+
]
|
|
277242
|
+
}, undefined, true, undefined, this)
|
|
276656
277243
|
]
|
|
276657
277244
|
}, undefined, true, undefined, this),
|
|
276658
277245
|
footer.length > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
@@ -276666,7 +277253,7 @@ function SessionView({ engine, footer, subscribe }) {
|
|
|
276666
277253
|
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
276667
277254
|
dimColor: true,
|
|
276668
277255
|
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"
|
|
277256
|
+
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
277257
|
}, undefined, false, undefined, this)
|
|
276671
277258
|
]
|
|
276672
277259
|
}, undefined, true, undefined, this);
|
|
@@ -276791,6 +277378,7 @@ async function runGenesisSession(options) {
|
|
|
276791
277378
|
runningTool: null,
|
|
276792
277379
|
lastTurnMs: null,
|
|
276793
277380
|
lastTurnOk: true,
|
|
277381
|
+
pending: [],
|
|
276794
277382
|
quietForMs: 0
|
|
276795
277383
|
};
|
|
276796
277384
|
const genesis = {
|
|
@@ -276846,6 +277434,9 @@ async function runGenesisSession(options) {
|
|
|
276846
277434
|
}
|
|
276847
277435
|
return IDLE_STATUS;
|
|
276848
277436
|
},
|
|
277437
|
+
answer(p, action, input) {
|
|
277438
|
+
inner?.answer(p, action, input);
|
|
277439
|
+
},
|
|
276849
277440
|
turnRunning() {
|
|
276850
277441
|
return inner?.turnRunning() ?? creating;
|
|
276851
277442
|
}
|
|
@@ -276878,10 +277469,10 @@ async function runGenesisSession(options) {
|
|
|
276878
277469
|
|
|
276879
277470
|
// src/cli/commands/code/index.ts
|
|
276880
277471
|
var BRAND_ORANGE2 = "#E86B3C";
|
|
276881
|
-
async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path) {
|
|
277472
|
+
async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path, wixInstance) {
|
|
276882
277473
|
let app;
|
|
276883
277474
|
try {
|
|
276884
|
-
app = await createAndLinkApp({ prompt, importRepo, path });
|
|
277475
|
+
app = await createAndLinkApp({ prompt, importRepo, path, wixInstance });
|
|
276885
277476
|
} catch (error) {
|
|
276886
277477
|
for (const line of await githubReauthLines(error) ?? [])
|
|
276887
277478
|
emit(line);
|
|
@@ -276928,8 +277519,8 @@ async function codeAction({ log }, options, appId) {
|
|
|
276928
277519
|
linked = true;
|
|
276929
277520
|
} catch {}
|
|
276930
277521
|
if (linked) {
|
|
276931
|
-
if (options.import || options.path) {
|
|
276932
|
-
throw new InvalidInputError("--import and --
|
|
277522
|
+
if (options.import || options.path || options.wixInstance) {
|
|
277523
|
+
throw new InvalidInputError("--import, --path and --wix-instance create a new app; run them outside a linked project, without --app-id.");
|
|
276933
277524
|
}
|
|
276934
277525
|
const { id, projectRoot } = getAppContext();
|
|
276935
277526
|
const state = await assertBuilderApp(id);
|
|
@@ -276952,16 +277543,25 @@ async function codeAction({ log }, options, appId) {
|
|
|
276952
277543
|
outroMessage: `Session closed. Resume with \`base44 code --app-id ${id}\`.`
|
|
276953
277544
|
};
|
|
276954
277545
|
}
|
|
277546
|
+
if (options.wixInstance && options.import) {
|
|
277547
|
+
throw new InvalidInputError("--wix-instance and --import are exclusive.");
|
|
277548
|
+
}
|
|
277549
|
+
const wixInstance = options.wixInstance?.trim() ? {
|
|
277550
|
+
signedInstance: options.wixInstance.trim(),
|
|
277551
|
+
wixClientId: options.wixClientId?.trim() || undefined
|
|
277552
|
+
} : undefined;
|
|
276955
277553
|
let created;
|
|
276956
|
-
const footer = [
|
|
277554
|
+
const footer = [
|
|
277555
|
+
chip(options.import ? repoLabel(options.import) : wixInstance ? "web app · wix" : "web app")
|
|
277556
|
+
];
|
|
276957
277557
|
await runGenesisSession({
|
|
276958
277558
|
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
277559
|
creatingLabel: options.import ? "importing the repository" : "creating your app",
|
|
276960
|
-
modeLabel: options.import ? `Repository — ${repoLabel(options.import)}` : "Web app — Base44 template + builder agent",
|
|
277560
|
+
modeLabel: options.import ? `Repository — ${repoLabel(options.import)}` : wixInstance ? "Web app — Wix launch (connector connected first)" : "Web app — Base44 template + builder agent",
|
|
276961
277561
|
footer,
|
|
276962
277562
|
createApp: (prompt, emit) => bootstrapApp(prompt, footer, emit, (app) => {
|
|
276963
277563
|
created = app;
|
|
276964
|
-
}, options.import, options.path)
|
|
277564
|
+
}, options.import, options.path, wixInstance)
|
|
276965
277565
|
});
|
|
276966
277566
|
if (!created) {
|
|
276967
277567
|
return { outroMessage: "Session closed. No app was created." };
|
|
@@ -276973,7 +277573,7 @@ async function codeAction({ log }, options, appId) {
|
|
|
276973
277573
|
}
|
|
276974
277574
|
function getCodeCommand() {
|
|
276975
277575
|
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));
|
|
277576
|
+
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-instance <token>", "Create the new app through the Wix route with this signed instance (your first prompt is what the agent runs)").option("--wix-client-id <id>", "The companion OAuth app's client id").action((ctx, options) => codeAction(ctx, options, command.optsWithGlobals().appId));
|
|
276977
277577
|
return command;
|
|
276978
277578
|
}
|
|
276979
277579
|
|
|
@@ -284356,7 +284956,7 @@ async function runScript(options) {
|
|
|
284356
284956
|
}
|
|
284357
284957
|
}
|
|
284358
284958
|
// src/cli/commands/exec.ts
|
|
284359
|
-
function
|
|
284959
|
+
function readStdin3() {
|
|
284360
284960
|
return new Promise((resolve, reject) => {
|
|
284361
284961
|
let data = "";
|
|
284362
284962
|
process.stdin.setEncoding("utf-8");
|
|
@@ -284400,7 +285000,7 @@ async function execAction({ app, isNonInteractive }, options) {
|
|
|
284400
285000
|
if (!isNonInteractive) {
|
|
284401
285001
|
throw noInputError;
|
|
284402
285002
|
}
|
|
284403
|
-
const code = await
|
|
285003
|
+
const code = await readStdin3();
|
|
284404
285004
|
if (!code.trim()) {
|
|
284405
285005
|
throw noInputError;
|
|
284406
285006
|
}
|
|
@@ -288581,6 +289181,13 @@ function getFullCommandName(command) {
|
|
|
288581
289181
|
}
|
|
288582
289182
|
return parts.join(" ");
|
|
288583
289183
|
}
|
|
289184
|
+
var SENSITIVE_OPTION = /secret|token|password|launch|instance|key$/i;
|
|
289185
|
+
function redactSensitiveOptions(options) {
|
|
289186
|
+
return Object.fromEntries(Object.entries(options).map(([k, v]) => [
|
|
289187
|
+
k,
|
|
289188
|
+
SENSITIVE_OPTION.test(k) && v != null && v !== false ? "[redacted]" : v
|
|
289189
|
+
]));
|
|
289190
|
+
}
|
|
288584
289191
|
function addCommandInfoToErrorReporter(program, errorReporter) {
|
|
288585
289192
|
program.hook("preAction", (_, actionCommand) => {
|
|
288586
289193
|
const fullCommandName = getFullCommandName(actionCommand);
|
|
@@ -288588,7 +289195,7 @@ function addCommandInfoToErrorReporter(program, errorReporter) {
|
|
|
288588
289195
|
command: {
|
|
288589
289196
|
name: fullCommandName,
|
|
288590
289197
|
args: actionCommand.args,
|
|
288591
|
-
options: actionCommand.opts()
|
|
289198
|
+
options: redactSensitiveOptions(actionCommand.opts())
|
|
288592
289199
|
}
|
|
288593
289200
|
});
|
|
288594
289201
|
});
|
|
@@ -288635,4 +289242,4 @@ export {
|
|
|
288635
289242
|
runCLI
|
|
288636
289243
|
};
|
|
288637
289244
|
|
|
288638
|
-
//# debugId=
|
|
289245
|
+
//# debugId=0CC1ED72A6CEBFAC64756E2164756E21
|