openmates 0.27.0-alpha.34 → 0.27.0-alpha.35
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/{chunk-V6UV747E.js → chunk-QE7VIQMK.js} +737 -145
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/fixtures/privacy-runtime/linux-arm64/libggml-base.so +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-base.so.0 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-base.so.0.15.1 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so.0 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so.0.15.1 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml.so +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml.so.0 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml.so.0.15.1 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/manifest.json +9 -9
- package/package.json +2 -2
|
@@ -20687,9 +20687,9 @@ Required: ${schema.required.join(", ")}`
|
|
|
20687
20687
|
...baseSyncPayload,
|
|
20688
20688
|
...refreshChatIdSet.size > 0 ? { refresh_chat_ids: Array.from(refreshChatIdSet) } : {}
|
|
20689
20689
|
});
|
|
20690
|
-
const
|
|
20690
|
+
const frames2 = await syncFrames;
|
|
20691
20691
|
signal?.throwIfAborted();
|
|
20692
|
-
if (onSyncedCache && !
|
|
20692
|
+
if (onSyncedCache && !frames2.some((frame) => frame.type === "phase_2_last_20_chats_ready")) {
|
|
20693
20693
|
throw new Error("Chat metadata sync ended before history arrived.");
|
|
20694
20694
|
}
|
|
20695
20695
|
if (includeMessageContentRefresh && refreshChatIdSet.size > 0) {
|
|
@@ -20700,9 +20700,9 @@ Required: ${schema.required.join(", ")}`
|
|
|
20700
20700
|
});
|
|
20701
20701
|
const collectedPhase3Frames = await phase3Frames;
|
|
20702
20702
|
signal?.throwIfAborted();
|
|
20703
|
-
|
|
20703
|
+
frames2.push(...collectedPhase3Frames);
|
|
20704
20704
|
}
|
|
20705
|
-
for (const frame of
|
|
20705
|
+
for (const frame of frames2) {
|
|
20706
20706
|
if (frame.type === "phase_1_last_chat_ready") {
|
|
20707
20707
|
const p = frame.payload;
|
|
20708
20708
|
newChatSuggestions = p.new_chat_suggestions ?? [];
|
|
@@ -34031,7 +34031,7 @@ function generateQr(value) {
|
|
|
34031
34031
|
function remotionMeta(c) {
|
|
34032
34032
|
const source = str(c.remotion_source) ?? str(c.source) ?? "";
|
|
34033
34033
|
const fps = firstInt(source, /fps\s*[:=]\s*(\d+)/) ?? 30;
|
|
34034
|
-
const
|
|
34034
|
+
const frames2 = firstInt(source, /durationInFrames\s*[:=]\s*(\d+)/) ?? 150;
|
|
34035
34035
|
const status = str(c.status) ?? "processing";
|
|
34036
34036
|
return {
|
|
34037
34037
|
filename: str(c.filename) ?? str(c.title) ?? "Composition.tsx",
|
|
@@ -34039,7 +34039,7 @@ function remotionMeta(c) {
|
|
|
34039
34039
|
statusText: remotionStatusText(status),
|
|
34040
34040
|
source,
|
|
34041
34041
|
sourceVersion: numberValue(c.current_source_version ?? c.source_version) ?? 1,
|
|
34042
|
-
durationSeconds: Math.max(1, Math.ceil(
|
|
34042
|
+
durationSeconds: Math.max(1, Math.ceil(frames2 / Math.max(1, fps))),
|
|
34043
34043
|
width: firstInt(source, /width\s*[:=]\s*(\d+)/) ?? 1920,
|
|
34044
34044
|
height: firstInt(source, /height\s*[:=]\s*(\d+)/) ?? 1080,
|
|
34045
34045
|
layers: remotionLayers(source),
|
|
@@ -38090,9 +38090,9 @@ function readLocalModelOverlay(path2) {
|
|
|
38090
38090
|
);
|
|
38091
38091
|
}
|
|
38092
38092
|
}
|
|
38093
|
-
function writeLocalModelOverlay(path2,
|
|
38093
|
+
function writeLocalModelOverlay(path2, overlay2) {
|
|
38094
38094
|
mkdirSync13(dirname10(path2), { recursive: true });
|
|
38095
|
-
writeFileSync8(path2, `${JSON.stringify(
|
|
38095
|
+
writeFileSync8(path2, `${JSON.stringify(overlay2, null, 2)}
|
|
38096
38096
|
`);
|
|
38097
38097
|
}
|
|
38098
38098
|
function hasLocalAiModels(installPath) {
|
|
@@ -38841,8 +38841,8 @@ async function testLocalModel(baseUrl, apiKey, modelId) {
|
|
|
38841
38841
|
}
|
|
38842
38842
|
}
|
|
38843
38843
|
function upsertLocalModel(path2, providerId, providerName, model) {
|
|
38844
|
-
const
|
|
38845
|
-
let provider =
|
|
38844
|
+
const overlay2 = readLocalModelOverlay(path2);
|
|
38845
|
+
let provider = overlay2.providers.find((item) => item.provider_id === providerId);
|
|
38846
38846
|
if (!provider) {
|
|
38847
38847
|
provider = {
|
|
38848
38848
|
provider_id: providerId,
|
|
@@ -38850,26 +38850,26 @@ function upsertLocalModel(path2, providerId, providerName, model) {
|
|
|
38850
38850
|
description: `Local self-hosted models for ${providerName}.`,
|
|
38851
38851
|
models: []
|
|
38852
38852
|
};
|
|
38853
|
-
|
|
38853
|
+
overlay2.providers.push(provider);
|
|
38854
38854
|
}
|
|
38855
38855
|
const modelId = model.id;
|
|
38856
38856
|
provider.models = provider.models.filter((existing) => existing.id !== modelId);
|
|
38857
38857
|
provider.models.push(model);
|
|
38858
|
-
writeLocalModelOverlay(path2,
|
|
38858
|
+
writeLocalModelOverlay(path2, overlay2);
|
|
38859
38859
|
}
|
|
38860
38860
|
function removeLocalModel(path2, fullModelId) {
|
|
38861
38861
|
const [providerId, modelId] = fullModelId.split("/", 2);
|
|
38862
38862
|
if (!providerId || !modelId) throw new Error("Use provider/model-id format.");
|
|
38863
|
-
const
|
|
38864
|
-
const provider =
|
|
38863
|
+
const overlay2 = readLocalModelOverlay(path2);
|
|
38864
|
+
const provider = overlay2.providers.find((item) => item.provider_id === providerId);
|
|
38865
38865
|
if (!provider) return false;
|
|
38866
38866
|
const before = provider.models.length;
|
|
38867
38867
|
provider.models = provider.models.filter((model) => model.id !== modelId);
|
|
38868
|
-
writeLocalModelOverlay(path2,
|
|
38868
|
+
writeLocalModelOverlay(path2, overlay2);
|
|
38869
38869
|
return provider.models.length !== before;
|
|
38870
38870
|
}
|
|
38871
|
-
function localModelsFromOverlay(
|
|
38872
|
-
return
|
|
38871
|
+
function localModelsFromOverlay(overlay2) {
|
|
38872
|
+
return overlay2.providers.flatMap((provider) => provider.models.map((model) => ({ providerId: provider.provider_id, model })));
|
|
38873
38873
|
}
|
|
38874
38874
|
async function serverStatus(flags) {
|
|
38875
38875
|
requireDocker();
|
|
@@ -39186,7 +39186,7 @@ async function serverInstall(flags) {
|
|
|
39186
39186
|
const imageTag = requestedImageTag === "stable" ? await resolveStableImageTag() : requestedImageTag;
|
|
39187
39187
|
console.error(`Preparing OpenMates image-mode install at ${installPath}...`);
|
|
39188
39188
|
await writeImageModeRuntimeFiles(installPath, imageTag, role);
|
|
39189
|
-
const
|
|
39189
|
+
const overlay3 = writeDeploymentModeEnv(installPath, deploymentMode, requestedOverlayPath);
|
|
39190
39190
|
const cliUrls2 = deriveSelfHostCliUrls(readFileSync13(join15(installPath, ".env"), "utf-8"));
|
|
39191
39191
|
try {
|
|
39192
39192
|
exec("docker network create openmates", installPath);
|
|
@@ -39202,7 +39202,7 @@ async function serverInstall(flags) {
|
|
|
39202
39202
|
composeFiles: runtimePlan.composeFiles,
|
|
39203
39203
|
installMode: "image",
|
|
39204
39204
|
deploymentMode,
|
|
39205
|
-
openMatesCloudOverlayPath:
|
|
39205
|
+
openMatesCloudOverlayPath: overlay3.overlayPath ?? void 0,
|
|
39206
39206
|
imageTag,
|
|
39207
39207
|
imageChannel: requestedImageTag === "stable" ? "stable" : void 0,
|
|
39208
39208
|
...cliUrls2
|
|
@@ -39277,7 +39277,7 @@ CLI default API: ${cliUrls2.apiUrl}`);
|
|
|
39277
39277
|
process.exit(setupCode);
|
|
39278
39278
|
}
|
|
39279
39279
|
const envPath = join15(installPath, ".env");
|
|
39280
|
-
const
|
|
39280
|
+
const overlay2 = writeDeploymentModeEnv(installPath, deploymentMode, requestedOverlayPath);
|
|
39281
39281
|
const cliUrls = deriveSelfHostCliUrls(existsSync12(envPath) ? readFileSync13(envPath, "utf-8") : "");
|
|
39282
39282
|
saveServerConfig({
|
|
39283
39283
|
installPath,
|
|
@@ -39290,7 +39290,7 @@ CLI default API: ${cliUrls2.apiUrl}`);
|
|
|
39290
39290
|
installMode: "source",
|
|
39291
39291
|
sourceStrategy: "managed_clone",
|
|
39292
39292
|
deploymentMode,
|
|
39293
|
-
openMatesCloudOverlayPath:
|
|
39293
|
+
openMatesCloudOverlayPath: overlay2.overlayPath ?? void 0,
|
|
39294
39294
|
...cliUrls
|
|
39295
39295
|
});
|
|
39296
39296
|
try {
|
|
@@ -40832,8 +40832,8 @@ async function serverAiModelsAdd(flags) {
|
|
|
40832
40832
|
async function serverAiModelsList(flags) {
|
|
40833
40833
|
const installPath = resolveServerPath(flags);
|
|
40834
40834
|
const overlayPath = localModelsOverlayPath(installPath);
|
|
40835
|
-
const
|
|
40836
|
-
const models = localModelsFromOverlay(
|
|
40835
|
+
const overlay2 = readLocalModelOverlay(overlayPath);
|
|
40836
|
+
const models = localModelsFromOverlay(overlay2).map(({ providerId, model }) => ({
|
|
40837
40837
|
id: `${providerId}/${String(model.id ?? "")}`,
|
|
40838
40838
|
name: model.name ?? model.id,
|
|
40839
40839
|
server: Array.isArray(model.servers) ? model.servers[0]?.id : void 0,
|
|
@@ -40858,8 +40858,8 @@ async function serverAiModelsTest(rest, flags) {
|
|
|
40858
40858
|
const fullModelId = rest[0];
|
|
40859
40859
|
if (!fullModelId || !fullModelId.includes("/")) throw new Error("Usage: openmates server ai models test <provider/model-id>");
|
|
40860
40860
|
const [providerId, modelId] = fullModelId.split("/", 2);
|
|
40861
|
-
const
|
|
40862
|
-
const provider =
|
|
40861
|
+
const overlay2 = readLocalModelOverlay(overlayPath);
|
|
40862
|
+
const provider = overlay2.providers.find((item) => item.provider_id === providerId);
|
|
40863
40863
|
const model = provider?.models.find((item) => item.id === modelId);
|
|
40864
40864
|
const server2 = Array.isArray(model?.servers) ? model.servers[0] : void 0;
|
|
40865
40865
|
if (!server2) throw new Error(`Local model not found in ${overlayPath}: ${fullModelId}`);
|
|
@@ -88189,6 +88189,7 @@ var TuiTerminal = class {
|
|
|
88189
88189
|
decoder = new StringDecoder("utf8");
|
|
88190
88190
|
pendingInput = "";
|
|
88191
88191
|
pendingMouse = "";
|
|
88192
|
+
discardingMouse = false;
|
|
88192
88193
|
paste = false;
|
|
88193
88194
|
pasteText = "";
|
|
88194
88195
|
inputTimer = null;
|
|
@@ -88254,6 +88255,7 @@ var TuiTerminal = class {
|
|
|
88254
88255
|
this.inputTimer = null;
|
|
88255
88256
|
this.pendingInput = "";
|
|
88256
88257
|
this.pendingMouse = "";
|
|
88258
|
+
this.discardingMouse = false;
|
|
88257
88259
|
this.paste = false;
|
|
88258
88260
|
this.pasteText = "";
|
|
88259
88261
|
this.output.write("\x1B[?25h");
|
|
@@ -88268,6 +88270,8 @@ var TuiTerminal = class {
|
|
|
88268
88270
|
} finally {
|
|
88269
88271
|
this.suspended = false;
|
|
88270
88272
|
if (this.active) {
|
|
88273
|
+
while (this.input.read() !== null) {
|
|
88274
|
+
}
|
|
88271
88275
|
this.input.on("data", this.rawInput);
|
|
88272
88276
|
if (this.resizeHandler) this.output.on("resize", this.resizeHandler);
|
|
88273
88277
|
if (typeof this.input.setRawMode === "function") {
|
|
@@ -88315,7 +88319,13 @@ var TuiTerminal = class {
|
|
|
88315
88319
|
this.pasteText = (this.pasteText + before).slice(0, 131072);
|
|
88316
88320
|
this.keyHandler?.(this.pasteText, { name: "paste" });
|
|
88317
88321
|
this.pasteText = "";
|
|
88318
|
-
} else
|
|
88322
|
+
} else {
|
|
88323
|
+
this.dispatchInput(before);
|
|
88324
|
+
if (this.mouseTimer) clearTimeout(this.mouseTimer);
|
|
88325
|
+
this.mouseTimer = null;
|
|
88326
|
+
this.pendingMouse = "";
|
|
88327
|
+
this.discardingMouse = false;
|
|
88328
|
+
}
|
|
88319
88329
|
this.paste = !this.paste;
|
|
88320
88330
|
this.pendingInput = this.pendingInput.slice(found + marker.length);
|
|
88321
88331
|
this.receiveInput("");
|
|
@@ -88333,46 +88343,71 @@ var TuiTerminal = class {
|
|
|
88333
88343
|
this.inputTimer = null;
|
|
88334
88344
|
}, 30);
|
|
88335
88345
|
}
|
|
88336
|
-
/**
|
|
88346
|
+
/** Keep SGR mouse bytes out of readline, including malformed and split reports. */
|
|
88337
88347
|
dispatchInput(text7) {
|
|
88338
88348
|
if (this.mouseTimer) clearTimeout(this.mouseTimer);
|
|
88339
88349
|
this.mouseTimer = null;
|
|
88340
88350
|
const input = this.pendingMouse + text7;
|
|
88341
88351
|
this.pendingMouse = "";
|
|
88342
88352
|
let offset = 0;
|
|
88353
|
+
if (this.discardingMouse) {
|
|
88354
|
+
const end = input.search(/[mM\x1b]/);
|
|
88355
|
+
if (end < 0) return;
|
|
88356
|
+
this.discardingMouse = false;
|
|
88357
|
+
offset = input[end] === "\x1B" ? end : end + 1;
|
|
88358
|
+
}
|
|
88343
88359
|
while (offset < input.length) {
|
|
88344
88360
|
const start = input.indexOf("\x1B[<", offset);
|
|
88345
88361
|
if (start < 0) {
|
|
88346
|
-
const
|
|
88347
|
-
|
|
88348
|
-
|
|
88349
|
-
|
|
88350
|
-
this.mouseTimer = setTimeout(() => {
|
|
88351
|
-
const pending = this.pendingMouse;
|
|
88352
|
-
this.pendingMouse = "";
|
|
88353
|
-
this.mouseTimer = null;
|
|
88354
|
-
if (pending === "\x1B") this.keyHandler?.("\x1B", { name: "escape", sequence: pending });
|
|
88355
|
-
else this.keyInput.write(pending);
|
|
88356
|
-
}, 500);
|
|
88357
|
-
}
|
|
88362
|
+
const rest = input.slice(offset);
|
|
88363
|
+
const prefix = rest.endsWith("\x1B[") ? "\x1B[" : rest.endsWith("\x1B") ? "\x1B" : "";
|
|
88364
|
+
this.keyInput.write(prefix ? rest.slice(0, -prefix.length) : rest);
|
|
88365
|
+
if (prefix) this.holdMousePrefix(prefix);
|
|
88358
88366
|
break;
|
|
88359
88367
|
}
|
|
88360
88368
|
this.keyInput.write(input.slice(offset, start));
|
|
88361
|
-
const
|
|
88362
|
-
|
|
88363
|
-
|
|
88364
|
-
|
|
88365
|
-
|
|
88369
|
+
const nextEscape = input.indexOf("\x1B", start + 3);
|
|
88370
|
+
const endM = input.indexOf("M", start + 3);
|
|
88371
|
+
const endm = input.indexOf("m", start + 3);
|
|
88372
|
+
const end = endM < 0 ? endm : endm < 0 ? endM : Math.min(endM, endm);
|
|
88373
|
+
if (end < 0 || nextEscape >= 0 && nextEscape < end) {
|
|
88374
|
+
if (nextEscape >= 0) {
|
|
88375
|
+
offset = nextEscape;
|
|
88376
|
+
continue;
|
|
88366
88377
|
}
|
|
88367
|
-
this.
|
|
88368
|
-
|
|
88369
|
-
|
|
88378
|
+
if (input.length - start < 128) this.holdMousePrefix(input.slice(start));
|
|
88379
|
+
else this.discardingMouse = true;
|
|
88380
|
+
break;
|
|
88370
88381
|
}
|
|
88371
|
-
const
|
|
88372
|
-
|
|
88373
|
-
|
|
88382
|
+
const sequence = input.slice(start, end + 1);
|
|
88383
|
+
const report = /^\x1b\[<(\d+);(\d+);(\d+)([mM])$/.exec(sequence);
|
|
88384
|
+
if (report) {
|
|
88385
|
+
const button = Number(report[1]);
|
|
88386
|
+
const column = Number(report[2]);
|
|
88387
|
+
const row = Number(report[3]);
|
|
88388
|
+
if ([button, column, row].every(Number.isSafeInteger) && column > 0 && row > 0) {
|
|
88389
|
+
const mouse = { row: row - 1, column: column - 1 };
|
|
88390
|
+
if (report[4] === "M" && button === 0 && !this.selectingText) {
|
|
88391
|
+
this.keyHandler?.("", { name: "mouseclick", sequence, mouse });
|
|
88392
|
+
} else if (report[4] === "M" && button & 64 && ((button & 3) === 0 || (button & 3) === 1)) {
|
|
88393
|
+
this.keyHandler?.("", { name: (button & 3) === 0 ? "scrollup" : "scrolldown", sequence, mouse });
|
|
88394
|
+
}
|
|
88395
|
+
}
|
|
88396
|
+
}
|
|
88397
|
+
offset = end + 1;
|
|
88374
88398
|
}
|
|
88375
88399
|
}
|
|
88400
|
+
holdMousePrefix(prefix) {
|
|
88401
|
+
this.pendingMouse = prefix;
|
|
88402
|
+
this.mouseTimer = setTimeout(() => {
|
|
88403
|
+
const pending = this.pendingMouse;
|
|
88404
|
+
this.pendingMouse = "";
|
|
88405
|
+
this.mouseTimer = null;
|
|
88406
|
+
if (pending === "\x1B") this.keyHandler?.("\x1B", { name: "escape", sequence: pending });
|
|
88407
|
+
else if (pending === "\x1B[") this.keyInput.write(pending);
|
|
88408
|
+
else this.discardingMouse = true;
|
|
88409
|
+
}, 500);
|
|
88410
|
+
}
|
|
88376
88411
|
removeListeners() {
|
|
88377
88412
|
if (this.keyHandler) {
|
|
88378
88413
|
this.keyInput.off("keypress", this.keyHandler);
|
|
@@ -88385,6 +88420,7 @@ var TuiTerminal = class {
|
|
|
88385
88420
|
this.inputTimer = null;
|
|
88386
88421
|
this.pendingInput = "";
|
|
88387
88422
|
this.pendingMouse = "";
|
|
88423
|
+
this.discardingMouse = false;
|
|
88388
88424
|
this.paste = false;
|
|
88389
88425
|
this.pasteText = "";
|
|
88390
88426
|
if (this.resizeHandler) {
|
|
@@ -88704,7 +88740,7 @@ function renderCardCarousel(cards, width, selectedIndex, focused) {
|
|
|
88704
88740
|
`\u2502 ${padCells(card2.footer, inner)} \u2502`,
|
|
88705
88741
|
`\u2570${"\u2500".repeat(cardWidth - 2)}\u256F`
|
|
88706
88742
|
];
|
|
88707
|
-
return { rows: rows2, left: center + (index - selected) * stride, background: card2.background, active };
|
|
88743
|
+
return { rows: rows2, left: center + (index - selected) * stride, background: card2.background, active, action: card2.action };
|
|
88708
88744
|
});
|
|
88709
88745
|
return Array.from({ length: visible[0].rows.length }, (_, row) => {
|
|
88710
88746
|
const spans = [];
|
|
@@ -88713,7 +88749,7 @@ function renderCardCarousel(cards, width, selectedIndex, focused) {
|
|
|
88713
88749
|
const start = Math.max(0, card2.left), end = Math.min(width, card2.left + cardWidth);
|
|
88714
88750
|
if (end <= start) continue;
|
|
88715
88751
|
if (start > column) spans.push({ text: " ".repeat(start - column) });
|
|
88716
|
-
spans.push({ text: sliceCells(card2.rows[row], Math.max(0, -card2.left), end - start), background: card2.background, bold: card2.active });
|
|
88752
|
+
spans.push({ text: sliceCells(card2.rows[row], Math.max(0, -card2.left), end - start), background: card2.background, bold: card2.active, action: card2.action });
|
|
88717
88753
|
column = end;
|
|
88718
88754
|
}
|
|
88719
88755
|
if (column < width) spans.push({ text: " ".repeat(width - column) });
|
|
@@ -88743,13 +88779,13 @@ function renderLineCarousel(cards, width, selectedIndex, focused, cardWidth) {
|
|
|
88743
88779
|
const raw = lineText(line), text7 = raw.startsWith("\u2502 ") ? `\u2502 \u203A ${padCells(raw.slice(2, -2), Math.max(0, cardWidth - 6))} \u2502` : padCells("\u203A " + raw, cardWidth);
|
|
88744
88780
|
line = typeof line === "string" ? { text: text7, bold: true, color: "#ff553b" } : { ...line, text: text7, bold: true, spans: line.spans ? [{ ...line.spans[0], text: text7, bold: true }] : void 0 };
|
|
88745
88781
|
}
|
|
88746
|
-
const source = typeof line === "string" ? [{ text: line }] : line.spans ?? [{ text: line.text, color: line.color, background: line.background, bold: line.bold }];
|
|
88782
|
+
const source = typeof line === "string" ? [{ text: line }] : line.spans ?? [{ text: line.text, color: line.color, background: line.background, bold: line.bold, action: line.action }];
|
|
88747
88783
|
let offset = 0, used = 0;
|
|
88748
88784
|
const cropStart = Math.max(0, -card2.left), cropEnd = cropStart + end - start;
|
|
88749
88785
|
for (const part of source) {
|
|
88750
88786
|
const size = cells(part.text), from = Math.max(cropStart, offset), to = Math.min(cropEnd, offset + size);
|
|
88751
88787
|
if (to > from) {
|
|
88752
|
-
spans.push({ ...part, text: sliceCells(part.text, from - offset, to - from) });
|
|
88788
|
+
spans.push({ ...part, action: part.action ?? (typeof line === "string" ? void 0 : line.action), text: sliceCells(part.text, from - offset, to - from) });
|
|
88753
88789
|
used += to - from;
|
|
88754
88790
|
}
|
|
88755
88791
|
offset += size;
|
|
@@ -88762,6 +88798,27 @@ function renderLineCarousel(cards, width, selectedIndex, focused, cardWidth) {
|
|
|
88762
88798
|
});
|
|
88763
88799
|
}
|
|
88764
88800
|
|
|
88801
|
+
// src/tuiPointer.ts
|
|
88802
|
+
var frames = /* @__PURE__ */ new WeakMap();
|
|
88803
|
+
var overlay = (state) => state.questionEditor ?? state.form ?? (state.paletteOpen ? "palette" : null) ?? (state.sidebarOpen ? "sidebar" : null);
|
|
88804
|
+
function beginPointerFrame(state, width, height) {
|
|
88805
|
+
frames.set(state, { width, height, route: state.routeVersion, screen: state.screen, workspace: state.workspace, signedIn: state.signedIn, overlay: overlay(state), targets: [] });
|
|
88806
|
+
}
|
|
88807
|
+
function pointerLine(line, action) {
|
|
88808
|
+
return typeof line === "string" ? { text: line, action } : { ...line, action };
|
|
88809
|
+
}
|
|
88810
|
+
function addPointerTarget(state, column, row, width, action) {
|
|
88811
|
+
const frame = frames.get(state);
|
|
88812
|
+
if (!frame || row < 0 || row >= frame.height) return;
|
|
88813
|
+
const left = Math.max(0, column), right = Math.min(frame.width, column + width);
|
|
88814
|
+
if (right > left) frame.targets.push({ column: left, row, width: right - left, action });
|
|
88815
|
+
}
|
|
88816
|
+
function pointerTargetAt(state, column, row, width, height) {
|
|
88817
|
+
const frame = frames.get(state);
|
|
88818
|
+
if (!frame || state.textSelection || state.startup || state.privacyOffer || frame.width !== width || frame.height !== height || frame.route !== state.routeVersion || frame.screen !== state.screen || frame.workspace !== state.workspace || frame.signedIn !== state.signedIn || frame.overlay !== overlay(state)) return null;
|
|
88819
|
+
return frame.targets.findLast((target) => target.row === row && column >= target.column && column < target.column + target.width)?.action ?? null;
|
|
88820
|
+
}
|
|
88821
|
+
|
|
88765
88822
|
// src/tuiProjectsWorkspace.ts
|
|
88766
88823
|
function contextFor(client2, project) {
|
|
88767
88824
|
const teamId = project ? project.teamId : client2.getActiveTeamId();
|
|
@@ -88987,7 +89044,8 @@ function renderProjectCarousel(projects, width, selectedIndex, focused) {
|
|
|
88987
89044
|
title: safeText(project.name),
|
|
88988
89045
|
description: safeText(project.description),
|
|
88989
89046
|
footer: `${count} ${count === 1 ? "item" : "items"}${project.pinned ? " \xB7 Pinned" : ""}${project.archived ? " \xB7 Archived" : ""}`,
|
|
88990
|
-
background: projectCardColor(project.color)
|
|
89047
|
+
background: projectCardColor(project.color),
|
|
89048
|
+
action: { kind: "command", command: `/project ${project.id}` }
|
|
88991
89049
|
};
|
|
88992
89050
|
});
|
|
88993
89051
|
return [
|
|
@@ -89035,14 +89093,37 @@ function renderProjectTabs(tab, width) {
|
|
|
89035
89093
|
const inset = Math.max(0, Math.floor((width - cells(text7)) / 2));
|
|
89036
89094
|
return ["", `${" ".repeat(inset)}${clip(text7, width)}`, ""];
|
|
89037
89095
|
}
|
|
89096
|
+
function renderProjectPointerTabs(tab, width) {
|
|
89097
|
+
const names = ["overview", "files", "tasks"];
|
|
89098
|
+
const labels = names.map((name, index) => `${name === tab ? "[" : " "}${name[0].toUpperCase() + name.slice(1)} \xB7 ${index + 1}${name === tab ? "]" : " "}`);
|
|
89099
|
+
const full = labels.join(" ");
|
|
89100
|
+
const inset = Math.max(0, Math.floor((width - cells(full)) / 2));
|
|
89101
|
+
const spans = [{ text: " ".repeat(inset) }];
|
|
89102
|
+
let remaining = Math.max(0, width - inset);
|
|
89103
|
+
labels.forEach((label3, index) => {
|
|
89104
|
+
if (index && remaining > 0) {
|
|
89105
|
+
const gap = Math.min(2, remaining);
|
|
89106
|
+
spans.push({ text: " ".repeat(gap) });
|
|
89107
|
+
remaining -= gap;
|
|
89108
|
+
}
|
|
89109
|
+
const text7 = truncateCells(label3, remaining);
|
|
89110
|
+
if (text7) spans.push({ text: text7, action: { kind: "key", name: "", chunk: String(index + 1), focus: "content" } });
|
|
89111
|
+
remaining -= cells(text7);
|
|
89112
|
+
});
|
|
89113
|
+
return ["", { text: spans.map((span) => span.text).join(""), spans }, ""];
|
|
89114
|
+
}
|
|
89038
89115
|
function renderProjectDetail(project, options) {
|
|
89039
89116
|
const width = options.width;
|
|
89040
|
-
const lines = [...renderProjectIdentity(project, { width }), ...
|
|
89117
|
+
const lines = [...renderProjectIdentity(project, { width }), ...renderProjectPointerTabs(options.tab, width)];
|
|
89041
89118
|
if (options.tab === "overview") {
|
|
89042
89119
|
lines.push(...renderProjectCard(false, project.readme ? project.readme.split("\n") : ["No project overview created yet."], width, "OVERVIEW"));
|
|
89043
89120
|
const links = project.items.filter((item) => item.type !== "embed");
|
|
89044
89121
|
if (links.length) {
|
|
89045
|
-
|
|
89122
|
+
const card3 = renderProjectCard(false, links.map((item) => `${item.type}: ${item.name}`), width, "LINKED WORK");
|
|
89123
|
+
lines.push("", ...card3.map((line, index) => {
|
|
89124
|
+
const item = links[index - 1];
|
|
89125
|
+
return item?.type === "chat" || item?.type === "workflow" ? pointerLine(line, { kind: "command", command: `/${item.type} ${item.targetId}` }) : line;
|
|
89126
|
+
}));
|
|
89046
89127
|
}
|
|
89047
89128
|
return lines;
|
|
89048
89129
|
}
|
|
@@ -89071,7 +89152,12 @@ function renderProjectDetail(project, options) {
|
|
|
89071
89152
|
const context = file.sourceId ? ` (${project.sources.find((source) => source.id === file.sourceId)?.name || "source"})` : "";
|
|
89072
89153
|
rows2.push(`${file.id === options.selectedFileId ? ">" : " "} [${icon}] ${file.name}${context}`);
|
|
89073
89154
|
}
|
|
89074
|
-
|
|
89155
|
+
const card2 = renderProjectCard(false, rows2, width, "FILES");
|
|
89156
|
+
const fileOffset = 1 + (rows2.length - visible.length);
|
|
89157
|
+
lines.push(...card2.map((line, index) => {
|
|
89158
|
+
const file = visible[index - fileOffset];
|
|
89159
|
+
return file ? pointerLine(line, { kind: "select", target: "content", index: index - fileOffset, id: file.id, activate: true }) : line;
|
|
89160
|
+
}));
|
|
89075
89161
|
return lines;
|
|
89076
89162
|
}
|
|
89077
89163
|
function buildProjectForm() {
|
|
@@ -89159,7 +89245,7 @@ function joinColumns(rows2, width, gap) {
|
|
|
89159
89245
|
if (index) spans.push({ text: gap });
|
|
89160
89246
|
if (typeof row === "string") spans.push({ text: padCells(row, width) });
|
|
89161
89247
|
else {
|
|
89162
|
-
spans.push(...row.spans ?? [{ text: row.text, background: row.background, bold: row.bold, color: row.color }]);
|
|
89248
|
+
spans.push(...(row.spans ?? [{ text: row.text, background: row.background, bold: row.bold, color: row.color }]).map((span) => ({ ...span, action: span.action ?? row.action })));
|
|
89163
89249
|
const padding = Math.max(0, width - cells(lineText(row)));
|
|
89164
89250
|
if (padding) spans.push({ text: " ".repeat(padding) });
|
|
89165
89251
|
}
|
|
@@ -89201,24 +89287,40 @@ function renderTaskBoard2(tasks, options) {
|
|
|
89201
89287
|
const shown = columns.slice(firstColumn, firstColumn + columnCount);
|
|
89202
89288
|
const colWidth = Math.floor((width - gap.length * (columnCount - 1)) / columnCount);
|
|
89203
89289
|
lines.push(truncateCells(`\u2190/\u2192 columns \xB7 ${STATUS_LABELS2[focused]} ${focusedIndex + 1}/5`, width));
|
|
89204
|
-
lines.push(joinColumns(shown.map(({ status, tasks: tasks2 }) =>
|
|
89290
|
+
lines.push(joinColumns(shown.map(({ status, tasks: tasks2 }) => pointerLine(
|
|
89291
|
+
columnHeader(status, tasks2.length, colWidth),
|
|
89292
|
+
{ kind: "select", target: "task", column: TASK_STATUSES.indexOf(status), index: 0 }
|
|
89293
|
+
)), colWidth, gap));
|
|
89205
89294
|
lines.push(shown.map(() => "\u2500".repeat(colWidth)).join(gap));
|
|
89206
|
-
const stacks = shown.map(({ tasks: group }) => group.length ? group.flatMap((task) => [...taskCard(
|
|
89295
|
+
const stacks = shown.map(({ tasks: group }) => group.length ? group.flatMap((task, index) => [...taskCard(
|
|
89296
|
+
task,
|
|
89297
|
+
colWidth,
|
|
89298
|
+
task.taskId === options.selectedTaskId,
|
|
89299
|
+
{ kind: "select", target: "task", column: TASK_STATUSES.indexOf(task.status), index, id: task.taskId, activate: true }
|
|
89300
|
+
), ""]) : [padCells("No tasks here.", colWidth)]);
|
|
89207
89301
|
for (let row = 0; row < Math.max(...stacks.map((stack) => stack.length)); row++) {
|
|
89208
89302
|
lines.push(joinColumns(stacks.map((stack) => stack[row] ?? ""), colWidth, gap));
|
|
89209
89303
|
}
|
|
89210
89304
|
} else {
|
|
89211
89305
|
const group = columns[focusedIndex]?.tasks ?? [];
|
|
89212
89306
|
lines.push(truncateCells(`\u2190/\u2192 columns \xB7 ${STATUS_LABELS2[focused]} ${focusedIndex + 1}/5`, width));
|
|
89213
|
-
lines.push(
|
|
89307
|
+
lines.push(pointerLine(
|
|
89308
|
+
columnHeader(focused, group.length, Math.min(width, 52)),
|
|
89309
|
+
{ kind: "select", target: "task", column: focusedIndex, index: 0 }
|
|
89310
|
+
), "\u2500".repeat(Math.min(width, 52)));
|
|
89214
89311
|
if (!group.length) lines.push(" No tasks here.");
|
|
89215
|
-
for (const task of group) {
|
|
89216
|
-
lines.push(...taskCard(
|
|
89312
|
+
for (const [index, task] of group.entries()) {
|
|
89313
|
+
lines.push(...taskCard(
|
|
89314
|
+
task,
|
|
89315
|
+
Math.min(width, 52),
|
|
89316
|
+
task.taskId === options.selectedTaskId,
|
|
89317
|
+
{ kind: "select", target: "task", column: focusedIndex, index, id: task.taskId, activate: true }
|
|
89318
|
+
));
|
|
89217
89319
|
}
|
|
89218
89320
|
}
|
|
89219
89321
|
return lines;
|
|
89220
89322
|
}
|
|
89221
|
-
function taskCard(task, width, selected) {
|
|
89323
|
+
function taskCard(task, width, selected, action) {
|
|
89222
89324
|
const inside = Math.max(8, width - 2);
|
|
89223
89325
|
const edge = (selected ? "\u2550" : "\u2500").repeat(inside);
|
|
89224
89326
|
const row = (value, title = false) => {
|
|
@@ -89243,7 +89345,7 @@ function taskCard(task, width, selected) {
|
|
|
89243
89345
|
...metadata.map((item) => row(` ${item}`)),
|
|
89244
89346
|
...task.queueState && task.queueState !== "none" ? [row(`Q ${task.queueState}`)] : [],
|
|
89245
89347
|
border(false)
|
|
89246
|
-
];
|
|
89348
|
+
].map((line) => pointerLine(line, action));
|
|
89247
89349
|
}
|
|
89248
89350
|
async function loadTaskContext(client2, taskId) {
|
|
89249
89351
|
const record10 = await client2.getUserTask(taskId);
|
|
@@ -89268,7 +89370,16 @@ function renderTaskDetails(task, options) {
|
|
|
89268
89370
|
if (task.labels.length) lines.push(truncateCells(`Labels: ${task.labels.join(", ")}`, width));
|
|
89269
89371
|
if (task.dueAt) lines.push(`Due: ${new Date(task.dueAt * 1e3).toISOString().slice(0, 16)} UTC`);
|
|
89270
89372
|
if (task.blockedReason) lines.push(truncateCells(`Blocked: ${task.blockedReason}`, width));
|
|
89271
|
-
|
|
89373
|
+
const firstActions = "c create e edit m status p assignee r reorder";
|
|
89374
|
+
const secondActions = "s start d done b block u unblock k skip x delete";
|
|
89375
|
+
lines.push(
|
|
89376
|
+
"",
|
|
89377
|
+
"Actions",
|
|
89378
|
+
...options.pointer ? pointerTaskShortcuts(firstActions, width) : wrapCells(firstActions, width),
|
|
89379
|
+
...options.pointer ? pointerTaskShortcuts(secondActions, width) : wrapCells(secondActions, width),
|
|
89380
|
+
"",
|
|
89381
|
+
"Description"
|
|
89382
|
+
);
|
|
89272
89383
|
lines.push(...wrapCells(task.description || "No description.", width));
|
|
89273
89384
|
if (options.dependencies) {
|
|
89274
89385
|
lines.push("", `Dependencies (${options.dependencies.dependencies.length})`);
|
|
@@ -89282,6 +89393,27 @@ function renderTaskDetails(task, options) {
|
|
|
89282
89393
|
}
|
|
89283
89394
|
return lines;
|
|
89284
89395
|
}
|
|
89396
|
+
function pointerTaskShortcuts(source, width) {
|
|
89397
|
+
const ranges = [...source.matchAll(/(?:^| {2})([cemprsdbukx]) ([a-z]+)/g)].map((match) => {
|
|
89398
|
+
const index = match.index + (match[0].startsWith(" ") ? 2 : 0);
|
|
89399
|
+
return { start: index, end: index + match[1].length + 1 + match[2].length, chunk: match[1] };
|
|
89400
|
+
});
|
|
89401
|
+
let rowStart = 0;
|
|
89402
|
+
return wrapCells(source, width).map((row) => {
|
|
89403
|
+
const rowEnd = rowStart + row.length, spans = [];
|
|
89404
|
+
let cursor = rowStart;
|
|
89405
|
+
for (const range of ranges) {
|
|
89406
|
+
const from = Math.max(rowStart, range.start), to = Math.min(rowEnd, range.end);
|
|
89407
|
+
if (to <= from) continue;
|
|
89408
|
+
if (from > cursor) spans.push({ text: source.slice(cursor, from) });
|
|
89409
|
+
spans.push({ text: source.slice(from, to), action: { kind: "key", name: "", chunk: range.chunk, focus: "content" } });
|
|
89410
|
+
cursor = to;
|
|
89411
|
+
}
|
|
89412
|
+
if (cursor < rowEnd) spans.push({ text: source.slice(cursor, rowEnd) });
|
|
89413
|
+
rowStart = rowEnd;
|
|
89414
|
+
return { text: row, spans };
|
|
89415
|
+
});
|
|
89416
|
+
}
|
|
89285
89417
|
function relationLabel(reference) {
|
|
89286
89418
|
const match = /^(task|plan):(.+)$/.exec(reference);
|
|
89287
89419
|
if (!match) return truncateCells(reference, 32);
|
|
@@ -89441,7 +89573,8 @@ function renderWorkflowCarousel(workflows, width, selectedIndex, focused) {
|
|
|
89441
89573
|
truncateCells(clean(workflow.trigger_summary || "Manual"), 32)
|
|
89442
89574
|
].filter(Boolean).join("\n"),
|
|
89443
89575
|
footer: `${workflow.enabled ? "Enabled" : "Paused"}${workflow.last_run_status ? ` \xB7 Last: ${clean(workflow.last_run_status)}` : ""}`,
|
|
89444
|
-
background: PRIMARY_GRADIENT.start
|
|
89576
|
+
background: PRIMARY_GRADIENT.start,
|
|
89577
|
+
action: { kind: "command", command: `/workflow ${workflow.id}` }
|
|
89445
89578
|
}));
|
|
89446
89579
|
return [
|
|
89447
89580
|
...renderCardCarousel(cards, width, selected, focused),
|
|
@@ -89466,7 +89599,13 @@ function renderWorkflowIdentity(workflow, options) {
|
|
|
89466
89599
|
];
|
|
89467
89600
|
return rows2.map((row, index) => {
|
|
89468
89601
|
const value = truncateCells(terminalText(row), width);
|
|
89469
|
-
return {
|
|
89602
|
+
return {
|
|
89603
|
+
text: padCells(centered(value, width), width),
|
|
89604
|
+
background: workflowIdentityColor(workflow),
|
|
89605
|
+
color: "#ffffff",
|
|
89606
|
+
bold: index === 0 || index === 2,
|
|
89607
|
+
...index === 3 ? { action: { kind: "command", command: "/workflow-toggle" } } : {}
|
|
89608
|
+
};
|
|
89470
89609
|
});
|
|
89471
89610
|
}
|
|
89472
89611
|
var NODE_FIELDS = {
|
|
@@ -89524,6 +89663,22 @@ function workflowTabs(width, tab) {
|
|
|
89524
89663
|
const inset = " ".repeat(Math.floor((width - tabWidth * 2 - 2) / 2));
|
|
89525
89664
|
return left.map((line, index) => `${inset}${line} ${right[index]}`);
|
|
89526
89665
|
}
|
|
89666
|
+
function workflowPointerTabs(width, tab) {
|
|
89667
|
+
const source = workflowTabs(width, tab);
|
|
89668
|
+
const key = (chunk) => ({ kind: "key", name: "", chunk, focus: "content" });
|
|
89669
|
+
if (width < 36) return source.map((line, index) => pointerLine(line, key(index < 3 ? "g" : "r")));
|
|
89670
|
+
const tabWidth = 18;
|
|
89671
|
+
const inset = Math.max(0, Math.floor((width - tabWidth * 2 - 2) / 2));
|
|
89672
|
+
return source.map((line) => {
|
|
89673
|
+
const spans = [
|
|
89674
|
+
{ text: line.slice(0, inset) },
|
|
89675
|
+
{ text: line.slice(inset, inset + tabWidth), action: key("g") },
|
|
89676
|
+
{ text: line.slice(inset + tabWidth, inset + tabWidth + 2) },
|
|
89677
|
+
{ text: line.slice(inset + tabWidth + 2), action: key("r") }
|
|
89678
|
+
];
|
|
89679
|
+
return { text: line, spans };
|
|
89680
|
+
});
|
|
89681
|
+
}
|
|
89527
89682
|
function orderedWorkflowNodes(graph) {
|
|
89528
89683
|
const byId = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
89529
89684
|
const incoming = new Map(graph.nodes.map((node) => [node.id, 0]));
|
|
@@ -89614,7 +89769,7 @@ function graphCanvas(graph, options, run, width) {
|
|
|
89614
89769
|
const selected = nodes[Math.max(0, Math.min(nodes.length - 1, options.selectedNodeIndex ?? 0))]?.id;
|
|
89615
89770
|
const innerWidth = Math.max(8, width - 4);
|
|
89616
89771
|
const rows2 = [];
|
|
89617
|
-
for (const node of nodes) {
|
|
89772
|
+
for (const [nodeIndex, node] of nodes.entries()) {
|
|
89618
89773
|
const nodeRun = nodeRuns.get(node.id);
|
|
89619
89774
|
const typeLabel = nodeKind(node);
|
|
89620
89775
|
const badge = graph.trigger_node_id === node.id ? " \xB7 trigger" : "";
|
|
@@ -89633,10 +89788,23 @@ function graphCanvas(graph, options, run, width) {
|
|
|
89633
89788
|
...expanded ? expandedStepRows(node, nodeRun, options.tab === "runs", options.edit) : []
|
|
89634
89789
|
];
|
|
89635
89790
|
const color = workflowNodeColor(node);
|
|
89791
|
+
const action = { kind: "select", target: "workflow-node", index: nodeIndex, id: node.id, activate: true };
|
|
89636
89792
|
rows2.push(...panel(expanded ? "Step details" : "Step", cardRows, cardWidth, expanded ? "left" : "center").map((line) => {
|
|
89637
89793
|
const inset = " ".repeat(cardInset);
|
|
89638
89794
|
const text7 = `${inset}${line}`;
|
|
89639
|
-
|
|
89795
|
+
if (expanded && options.tab === "graph" && line.includes("e Edit title \xB7 E Edit config")) {
|
|
89796
|
+
const titleAt = line.indexOf("e Edit title"), configAt = line.indexOf("E Edit config");
|
|
89797
|
+
const spans = [
|
|
89798
|
+
{ text: inset },
|
|
89799
|
+
{ text: line.slice(0, titleAt), background: color, action },
|
|
89800
|
+
{ text: line.slice(titleAt, configAt - 3), background: color, action: { kind: "key", name: "", chunk: "e", focus: "content" } },
|
|
89801
|
+
{ text: line.slice(configAt - 3, configAt), background: color, action },
|
|
89802
|
+
{ text: line.slice(configAt, configAt + 13), background: color, action: { kind: "key", name: "", chunk: "E", focus: "content" } },
|
|
89803
|
+
{ text: line.slice(configAt + 13), background: color, action }
|
|
89804
|
+
];
|
|
89805
|
+
return { text: text7, spans };
|
|
89806
|
+
}
|
|
89807
|
+
return { text: text7, spans: [{ text: inset }, { text: line, background: color, bold: line.includes(typeLabel), action }] };
|
|
89640
89808
|
}));
|
|
89641
89809
|
const outgoing = (graph.edges ?? []).filter((edge) => edge.from === node.id);
|
|
89642
89810
|
const connector = " ".repeat(cardInset + 2);
|
|
@@ -89658,7 +89826,7 @@ function renderWorkflowWorkspace(workflow, options) {
|
|
|
89658
89826
|
const width = Math.max(1, options.width);
|
|
89659
89827
|
const lines = [
|
|
89660
89828
|
...renderWorkflowIdentity(workflow, { width, run: options.tab === "runs" ? run ?? void 0 : void 0 }),
|
|
89661
|
-
...
|
|
89829
|
+
...workflowPointerTabs(width, options.tab),
|
|
89662
89830
|
""
|
|
89663
89831
|
];
|
|
89664
89832
|
const upcoming = workflow.enabled && workflow.next_run_at && workflow.next_run_at > Date.now() / 1e3 ? workflow.next_run_at : null;
|
|
@@ -89669,7 +89837,10 @@ function renderWorkflowWorkspace(workflow, options) {
|
|
|
89669
89837
|
if (!runs.length && !upcoming) lines.push("No runs yet.");
|
|
89670
89838
|
for (const [index, item] of runs.entries()) {
|
|
89671
89839
|
const marker = index === (options.selectedRunIndex ?? 0) ? ">" : " ";
|
|
89672
|
-
lines.push(
|
|
89840
|
+
lines.push(pointerLine(
|
|
89841
|
+
`${marker} ${item.id} \xB7 ${item.status}${item.started_at ? ` \xB7 ${new Date(item.started_at * 1e3).toISOString()}` : ""}`,
|
|
89842
|
+
{ kind: "select", target: "workflow-run", index, id: item.id, activate: true }
|
|
89843
|
+
));
|
|
89673
89844
|
}
|
|
89674
89845
|
if (run) {
|
|
89675
89846
|
lines.push("", `Selected run ${run.id} \xB7 ${run.status} \xB7 version ${run.version_id}`);
|
|
@@ -89909,8 +90080,8 @@ function append(out, value, style = {}) {
|
|
|
89909
90080
|
const text7 = terminalText(value);
|
|
89910
90081
|
if (!text7) return;
|
|
89911
90082
|
const last = out.at(-1);
|
|
89912
|
-
if (last && last.bold === style.bold && last.color === style.color && last.background === style.background) last.text += text7;
|
|
89913
|
-
else out.push({ text: text7, bold: style.bold, color: style.color, background: style.background });
|
|
90083
|
+
if (last && last.bold === style.bold && last.color === style.color && last.background === style.background && JSON.stringify(last.action) === JSON.stringify(style.action)) last.text += text7;
|
|
90084
|
+
else out.push({ text: text7, bold: style.bold, color: style.color, background: style.background, action: style.action });
|
|
89914
90085
|
}
|
|
89915
90086
|
function closing(source, from, delimiter) {
|
|
89916
90087
|
for (let i = from; i <= source.length - delimiter.length; i++) {
|
|
@@ -89982,8 +90153,9 @@ function inline(source, options, base = {}) {
|
|
|
89982
90153
|
} else if (wiki && safeReference(wiki)) action = `/wiki ${wiki}`;
|
|
89983
90154
|
else if (/^https?:\/\/\S+$/i.test(target)) action = target;
|
|
89984
90155
|
if (action) {
|
|
89985
|
-
|
|
89986
|
-
|
|
90156
|
+
const pointerAction = embed || wiki ? { kind: "command", command: action } : void 0;
|
|
90157
|
+
append(out, label3 || (embed ? "Embed" : target), { ...base, color: LINK, action: pointerAction });
|
|
90158
|
+
if (action !== label3) append(out, ` (${action})`, { color: CODE, action: pointerAction });
|
|
89987
90159
|
} else append(out, source.slice(i, link2.end), base);
|
|
89988
90160
|
i = link2.end;
|
|
89989
90161
|
continue;
|
|
@@ -90151,23 +90323,81 @@ function renderQuestionCard(question, width) {
|
|
|
90151
90323
|
const marker = q.type === "choice" ? control.selected ? "[\u2713]" : q.multiple ? "[ ]" : "( )" : "";
|
|
90152
90324
|
rows2.push(...wrapCells(`${marker} ${control.label}${control.value !== void 0 ? ` \xB7 ${control.value || "(empty)"}` : ""}`.trim(), width));
|
|
90153
90325
|
}
|
|
90154
|
-
rows2.push(...wrapCells(answer ? "Answered" : `/question ${question.key} \xB7 Answer${q.multiple ? " \xB7 Choose several" : ""} \xB7 Ctrl+Q latest question`, width).map((text7) => ({
|
|
90326
|
+
rows2.push(...wrapCells(answer ? "Answered" : `/question ${question.key} \xB7 Answer${q.multiple ? " \xB7 Choose several" : ""} \xB7 Ctrl+Q latest question`, width).map((text7) => ({
|
|
90327
|
+
text: text7,
|
|
90328
|
+
color: answer ? "#808080" : "#85c9e8",
|
|
90329
|
+
...answer ? {} : { action: { kind: "question", index: question.key, activate: true } }
|
|
90330
|
+
})), "");
|
|
90155
90331
|
return rows2;
|
|
90156
90332
|
}
|
|
90157
90333
|
function renderQuestionEditor(editor, width) {
|
|
90158
90334
|
const q = editor.question.payload, items = controls(editor), rows2 = [];
|
|
90159
|
-
const add = (text7, color = "#e6e6e6", bold = false) => rows2.push(...wrapCells(text7, width).map((text8) => ({ text: text8, color, bold })));
|
|
90335
|
+
const add = (text7, color = "#e6e6e6", bold = false, action) => rows2.push(...wrapCells(text7, width).map((text8) => ({ text: text8, color, bold, action })));
|
|
90160
90336
|
add(`Answer question ${editor.question.key}`, "#80caff", true);
|
|
90161
90337
|
add(q.question ?? (q.type === "input" ? "Tell us more" : "Review these options"), "#ffffff", true);
|
|
90162
90338
|
rows2.push("");
|
|
90163
90339
|
items.forEach((item, index) => {
|
|
90164
90340
|
const focused = index === editor.fieldIndex, marker = q.type === "choice" ? item.selected ? "[\u2713]" : q.multiple ? "[ ]" : "( )" : "";
|
|
90165
|
-
|
|
90166
|
-
|
|
90341
|
+
const action = { kind: "question", index, activate: q.type === "choice" };
|
|
90342
|
+
add(`${focused ? "\u203A" : " "} ${marker} ${item.label}`, focused ? "#32ade6" : "#e6e6e6", focused, action);
|
|
90343
|
+
if (item.value !== void 0) add(` ${item.value || "(empty)"}${focused && item.text && !editor.busy ? "_" : ""}`, "#e6e6e6", false, action);
|
|
90344
|
+
if (q.type === "rating" && index === 0) {
|
|
90345
|
+
const max = q.max_stars ?? q.max ?? q.scale ?? 5;
|
|
90346
|
+
add(" " + Array.from({ length: Math.min(max, 20) }, (_, star) => `[${star + 1}]`).join(" "), "#85c9e8");
|
|
90347
|
+
const line = rows2.at(-1);
|
|
90348
|
+
if (typeof line !== "string" && line) {
|
|
90349
|
+
const spans = [];
|
|
90350
|
+
let text7 = " ";
|
|
90351
|
+
spans.push({ text: text7 });
|
|
90352
|
+
for (let star = 1; star <= Math.min(max, 20); star++) {
|
|
90353
|
+
text7 = `[${star}]${star < Math.min(max, 20) ? " " : ""}`;
|
|
90354
|
+
spans.push({ text: text7, action: { kind: "question", index, value: star } });
|
|
90355
|
+
}
|
|
90356
|
+
if (spans.map((span) => span.text).join("") === line.text) line.spans = spans;
|
|
90357
|
+
}
|
|
90358
|
+
}
|
|
90359
|
+
if (q.type === "slider") {
|
|
90360
|
+
const min = q.min, max = q.max, step = q.step ?? 1, current = Number(editor.answer.value);
|
|
90361
|
+
const values = [
|
|
90362
|
+
min,
|
|
90363
|
+
Math.max(min, Math.min(max, min + Math.round((current - min) / step - 1) * step)),
|
|
90364
|
+
current,
|
|
90365
|
+
Math.max(min, Math.min(max, min + Math.round((current - min) / step + 1) * step)),
|
|
90366
|
+
max
|
|
90367
|
+
].filter((value, position, all) => position === all.indexOf(value));
|
|
90368
|
+
const text7 = " " + values.map((value) => `[${value}]`).join(" ");
|
|
90369
|
+
if (wrapCells(text7, width).length === 1) {
|
|
90370
|
+
const spans = [{ text: " " }, ...values.map((value, position) => ({
|
|
90371
|
+
text: `[${value}]${position < values.length - 1 ? " " : ""}`,
|
|
90372
|
+
action: { kind: "question", index, value }
|
|
90373
|
+
}))];
|
|
90374
|
+
rows2.push({ text: text7, spans });
|
|
90375
|
+
}
|
|
90376
|
+
}
|
|
90377
|
+
if (q.type === "swipe") {
|
|
90378
|
+
const text7 = " [\u2190 dislike] [like \u2192]";
|
|
90379
|
+
if (wrapCells(text7, width).length === 1) rows2.push({ text: text7, spans: [
|
|
90380
|
+
{ text: " " },
|
|
90381
|
+
{ text: "[\u2190 dislike]", action: { kind: "question", index, value: "dislike" } },
|
|
90382
|
+
{ text: " " },
|
|
90383
|
+
{ text: "[like \u2192]", action: { kind: "question", index, value: "like" } }
|
|
90384
|
+
] });
|
|
90385
|
+
}
|
|
90167
90386
|
});
|
|
90168
90387
|
rows2.push("");
|
|
90169
|
-
add(
|
|
90170
|
-
|
|
90388
|
+
add(
|
|
90389
|
+
`${editor.fieldIndex === items.length ? "\u203A" : " "} [Send answer]`,
|
|
90390
|
+
"#32ade6",
|
|
90391
|
+
true,
|
|
90392
|
+
{ kind: "question", index: items.length, activate: true }
|
|
90393
|
+
);
|
|
90394
|
+
add(
|
|
90395
|
+
`${editor.fieldIndex === items.length + 1 ? "\u203A" : " "} [Clear]`,
|
|
90396
|
+
"#a0a0a0",
|
|
90397
|
+
false,
|
|
90398
|
+
{ kind: "question", index: items.length + 1, activate: true }
|
|
90399
|
+
);
|
|
90400
|
+
add(" [Cancel]", "#a0a0a0", false, { kind: "question", index: items.length + 2, activate: true });
|
|
90171
90401
|
if (editor.error) add(editor.error, "#ff6b6b", true);
|
|
90172
90402
|
add(editor.busy ? "Sending\u2026" : "Tab / \u2191\u2193 move \xB7 Space choose \xB7 \u2190/\u2192 adjust \xB7 Ctrl+S send \xB7 Ctrl+U clear \xB7 Esc cancel", "#a0a0a0");
|
|
90173
90403
|
return rows2;
|
|
@@ -90285,6 +90515,60 @@ async function handleQuestionKey(context, chunk, key) {
|
|
|
90285
90515
|
render();
|
|
90286
90516
|
return true;
|
|
90287
90517
|
}
|
|
90518
|
+
async function handleQuestionPointer(context, action) {
|
|
90519
|
+
const { state, render } = context, editor = state.questionEditor;
|
|
90520
|
+
if (!editor) {
|
|
90521
|
+
if (!action.activate || !["chat", "example"].includes(state.screen)) return;
|
|
90522
|
+
const key = typeof action.index === "number" ? action.index : Number(action.index);
|
|
90523
|
+
if (!Number.isInteger(key) || key < 1) return;
|
|
90524
|
+
try {
|
|
90525
|
+
openQuestion(state, key);
|
|
90526
|
+
} catch (error) {
|
|
90527
|
+
state.status = String(error.message);
|
|
90528
|
+
}
|
|
90529
|
+
render();
|
|
90530
|
+
return;
|
|
90531
|
+
}
|
|
90532
|
+
if (editor.busy) return;
|
|
90533
|
+
const q = editor.question.payload, items = controls(editor), index = typeof action.index === "number" ? action.index : Number(action.index);
|
|
90534
|
+
if (!Number.isInteger(index) || index < 0 || index > items.length + 2) return;
|
|
90535
|
+
if (index >= items.length && !action.activate) return;
|
|
90536
|
+
if (index === items.length + 2) {
|
|
90537
|
+
await handleQuestionKey(context, "", { name: "escape" });
|
|
90538
|
+
return;
|
|
90539
|
+
}
|
|
90540
|
+
if (index === items.length + 1) {
|
|
90541
|
+
await handleQuestionKey(context, "", { name: "u", ctrl: true });
|
|
90542
|
+
return;
|
|
90543
|
+
}
|
|
90544
|
+
if (index === items.length) {
|
|
90545
|
+
await handleQuestionKey(context, "", { name: "s", ctrl: true });
|
|
90546
|
+
return;
|
|
90547
|
+
}
|
|
90548
|
+
editor.fieldIndex = index;
|
|
90549
|
+
if (q.type === "choice" && action.activate) {
|
|
90550
|
+
await handleQuestionKey(context, "", { name: "space" });
|
|
90551
|
+
return;
|
|
90552
|
+
}
|
|
90553
|
+
if (q.type === "slider" && typeof action.value === "number") {
|
|
90554
|
+
const min = q.min, max = q.max, step = q.step ?? 1, value = action.value;
|
|
90555
|
+
if (Number.isFinite(value) && value >= min && value <= max && Math.abs((value - min) / step - Math.round((value - min) / step)) < 1e-7) {
|
|
90556
|
+
editor.answer.value = value;
|
|
90557
|
+
editor.touched = true;
|
|
90558
|
+
editor.error = void 0;
|
|
90559
|
+
}
|
|
90560
|
+
} else if (q.type === "rating" && typeof action.value === "number") {
|
|
90561
|
+
const max = q.max_stars ?? q.max ?? q.scale ?? 5;
|
|
90562
|
+
if (Number.isInteger(action.value) && action.value >= 1 && action.value <= max) {
|
|
90563
|
+
editor.answer.rating = action.value;
|
|
90564
|
+
editor.error = void 0;
|
|
90565
|
+
}
|
|
90566
|
+
} else if (q.type === "swipe" && (action.value === "like" || action.value === "dislike")) {
|
|
90567
|
+
editor.answer.swipes[items[index].id] = action.value;
|
|
90568
|
+
editor.error = void 0;
|
|
90569
|
+
}
|
|
90570
|
+
render();
|
|
90571
|
+
}
|
|
90288
90572
|
|
|
90289
90573
|
// src/tuiActions.ts
|
|
90290
90574
|
var TUI_ACTIONS = [
|
|
@@ -90737,6 +91021,17 @@ function sidebarLines(state) {
|
|
|
90737
91021
|
return ["Apps", "", ...state.apps.map((a, i) => selected(a.name, i)), "", "Ctrl+B close sidebar"];
|
|
90738
91022
|
}
|
|
90739
91023
|
}
|
|
91024
|
+
function sidebarPointerIds(state) {
|
|
91025
|
+
if (state.workspace === "chats") return tuiChatSidebarRows(state).map((row) => row.kind === "section" ? null : JSON.stringify([row.kind, row.chatId, row.projectId, row.folderId]));
|
|
91026
|
+
return (state.workspace === "projects" ? state.projects : state.workspace === "tasks" ? state.tasks : state.workspace === "workflows" ? state.workflows : state.apps).map((item) => "taskId" in item ? item.taskId : item.id);
|
|
91027
|
+
}
|
|
91028
|
+
function pointerSidebarLines(state) {
|
|
91029
|
+
const ids = sidebarPointerIds(state);
|
|
91030
|
+
return sidebarLines(state).map((line, row) => {
|
|
91031
|
+
const index = row - 2, id = ids[index];
|
|
91032
|
+
return id ? pointerLine(line, { kind: "select", target: "sidebar", index, id, activate: true }) : line;
|
|
91033
|
+
});
|
|
91034
|
+
}
|
|
90740
91035
|
function workspaceHint(state) {
|
|
90741
91036
|
if (state.questionEditor) return "Tab / \u2191\u2193 move Space choose \u2190/\u2192 adjust Ctrl+S send Esc cancel";
|
|
90742
91037
|
if (state.form) return "Tab field \u2190/\u2192 choice Ctrl+S save Esc cancel";
|
|
@@ -90767,7 +91062,10 @@ function overlayLines(state, width, height) {
|
|
|
90767
91062
|
if (state.paletteOpen) {
|
|
90768
91063
|
const actions = paletteActions(state.paletteQuery);
|
|
90769
91064
|
const start = Math.max(0, state.paletteIndex - Math.max(1, height - 5));
|
|
90770
|
-
return ["Actions", `Search: ${state.paletteQuery}_`, "", ...actions.slice(start).map((a, i) =>
|
|
91065
|
+
return ["Actions", `Search: ${state.paletteQuery}_`, "", ...actions.slice(start).map((a, i) => pointerLine(
|
|
91066
|
+
`${i + start === state.paletteIndex ? ">" : " "} ${a.label} ${a.command}`,
|
|
91067
|
+
{ kind: "select", target: "palette", index: i + start, id: a.command, activate: true }
|
|
91068
|
+
))];
|
|
90771
91069
|
}
|
|
90772
91070
|
const form = state.form;
|
|
90773
91071
|
if (!form) return [];
|
|
@@ -90785,71 +91083,112 @@ function overlayLines(state, width, height) {
|
|
|
90785
91083
|
for (const [index, field] of form.fields.entries()) {
|
|
90786
91084
|
const focused = index === form.fieldIndex;
|
|
90787
91085
|
const suffix = [field.required ? "required" : "", field.valueType && field.valueType !== "string" ? field.valueType : "", field.options ? "\u2190/\u2192 choose" : ""].filter(Boolean).join(" \xB7 ");
|
|
90788
|
-
|
|
91086
|
+
const action = { kind: "select", target: "form-field", index, id: field.name };
|
|
91087
|
+
rows3.push({ text: `${focused ? "\u203A" : " "} ${field.label}${suffix ? ` \xB7 ${suffix}` : ""}`, bold: true, color: focused ? "#32ade6" : "#e6e6e6", inset, action });
|
|
90789
91088
|
if (panelWidth >= 6) {
|
|
90790
91089
|
const edge = "\u2500".repeat(panelWidth - 2), border = focused ? "#32ade6" : "#626878";
|
|
90791
91090
|
rows3.push({ text: `\u256D${edge}\u256E`, color: border, inset });
|
|
90792
|
-
rows3.push(...wrapCells(`${field.value || "(empty)"}${focused && !form.busy ? "_" : ""}`, panelWidth - 4).map((text7) => ({ text: `\u2502 ${padCells(text7, panelWidth - 4)} \u2502`, color: focused ? "#ffffff" : "#cfcfcf", ...focused ? { background: "#2b3548" } : {}, inset })));
|
|
91091
|
+
rows3.push(...wrapCells(`${field.value || "(empty)"}${focused && !form.busy ? "_" : ""}`, panelWidth - 4).map((text7) => ({ text: `\u2502 ${padCells(text7, panelWidth - 4)} \u2502`, color: focused ? "#ffffff" : "#cfcfcf", ...focused ? { background: "#2b3548" } : {}, inset, action })));
|
|
90793
91092
|
rows3.push({ text: `\u2570${edge}\u256F`, color: border, inset }, "");
|
|
90794
|
-
} else rows3.push(...wrapCells(field.value, panelWidth));
|
|
91093
|
+
} else rows3.push(...wrapCells(field.value, panelWidth).map((line) => pointerLine(line, action)));
|
|
91094
|
+
if (field.options) rows3.push({ text: "\u2039 Previous Next \u203A", inset, spans: [
|
|
91095
|
+
{ text: "\u2039 Previous", action: { ...action, activate: true, name: "left" } },
|
|
91096
|
+
{ text: " " },
|
|
91097
|
+
{ text: "Next \u203A", action: { ...action, activate: true, name: "right" } }
|
|
91098
|
+
] });
|
|
90795
91099
|
}
|
|
90796
91100
|
if (form.error) rows3.push({ text: form.error, color: "#ff6b6b", bold: true, inset });
|
|
90797
|
-
rows3.push({
|
|
91101
|
+
rows3.push({
|
|
91102
|
+
text: form.busy ? "Saving\u2026" : "Save \xB7 Ctrl+S Cancel \xB7 Esc",
|
|
91103
|
+
color: "#a0a0a0",
|
|
91104
|
+
inset,
|
|
91105
|
+
...!form.busy ? { spans: [
|
|
91106
|
+
{ text: "Save \xB7 Ctrl+S", action: { kind: "key", name: "s", ctrl: true } },
|
|
91107
|
+
{ text: " " },
|
|
91108
|
+
{ text: "Cancel \xB7 Esc", action: { kind: "key", name: "escape" } }
|
|
91109
|
+
] } : {}
|
|
91110
|
+
});
|
|
90798
91111
|
return rows3;
|
|
90799
91112
|
}
|
|
90800
91113
|
const rows2 = [form.title, ""];
|
|
90801
91114
|
for (const [index, field] of form.fields.entries()) {
|
|
90802
|
-
|
|
90803
|
-
rows2.push(
|
|
91115
|
+
const action = { kind: "select", target: "form-field", index, id: field.name };
|
|
91116
|
+
rows2.push(pointerLine(`${index === form.fieldIndex ? ">" : " "} ${field.label}${field.options ? " [\u2190/\u2192]" : ""}`, action));
|
|
91117
|
+
rows2.push(...wrapCells(` ${field.value || "(empty)"}${index === form.fieldIndex && !form.busy ? "_" : ""}`, width).map((line) => pointerLine(line, action)));
|
|
91118
|
+
if (field.options) rows2.push({ text: "\u2039 Previous Next \u203A", spans: [
|
|
91119
|
+
{ text: "\u2039 Previous", action: { ...action, activate: true, name: "left" } },
|
|
91120
|
+
{ text: " " },
|
|
91121
|
+
{ text: "Next \u203A", action: { ...action, activate: true, name: "right" } }
|
|
91122
|
+
] });
|
|
90804
91123
|
rows2.push("");
|
|
90805
91124
|
}
|
|
90806
91125
|
if (form.error) rows2.push(`Error: ${form.error}`);
|
|
90807
|
-
rows2.push(form.busy ? "Saving\u2026" :
|
|
91126
|
+
rows2.push(form.busy ? "Saving\u2026" : { text: "Save \xB7 Ctrl+S Cancel \xB7 Esc", spans: [
|
|
91127
|
+
{ text: "Save \xB7 Ctrl+S", action: { kind: "key", name: "s", ctrl: true } },
|
|
91128
|
+
{ text: " " },
|
|
91129
|
+
{ text: "Cancel \xB7 Esc", action: { kind: "key", name: "escape" } }
|
|
91130
|
+
] });
|
|
90808
91131
|
return rows2;
|
|
90809
91132
|
}
|
|
90810
91133
|
function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
90811
91134
|
const { gutter, sidebarWidth, paneWidth, contentWidth, inset, composerWidth, composerInset } = workspaceGeometry(state, rawWidth);
|
|
90812
91135
|
const height = Math.max(1, Math.floor(rawHeight));
|
|
91136
|
+
beginPointerFrame(state, Math.max(1, Math.floor(rawWidth)), height);
|
|
91137
|
+
const modal = Boolean(state.form || state.paletteOpen || state.questionEditor);
|
|
91138
|
+
const bodyColumn = gutter + sidebarWidth + inset;
|
|
90813
91139
|
const mode = options.colorMode ?? "none";
|
|
90814
91140
|
const ascii = options.ascii ?? false;
|
|
90815
91141
|
const line = ascii ? "-" : "\u2500", vertical = ascii ? "|" : "\u2502";
|
|
90816
91142
|
const place = (rendered, side2 = " ".repeat(sidebarWidth)) => " ".repeat(gutter) + side2 + " ".repeat(inset) + rendered + " ".repeat(paneWidth - inset - contentWidth + gutter);
|
|
90817
|
-
const navParts = [{ text: "OpenMates ", color: "#cfcfcf", bold: true }, ...WORKSPACES.map((workspace, index) => {
|
|
91143
|
+
const navParts = [{ text: "OpenMates ", color: "#cfcfcf", bold: true, action: { kind: "command", command: "/chats" } }, ...WORKSPACES.map((workspace, index) => {
|
|
90818
91144
|
const focused = state.focus === "navigation" && index === state.navigationIndex;
|
|
90819
91145
|
const label3 = state.workspace === workspace ? `[${titleCase(workspace)}]` : titleCase(workspace);
|
|
90820
|
-
return {
|
|
91146
|
+
return {
|
|
91147
|
+
text: `${focused ? "\u203A " : ""}${label3} `,
|
|
91148
|
+
color: focused ? "#32ade6" : state.workspace === workspace ? "#ff553b" : "#cfcfcf",
|
|
91149
|
+
bold: true,
|
|
91150
|
+
action: { kind: "command", command: `/${workspace}` }
|
|
91151
|
+
};
|
|
90821
91152
|
})];
|
|
90822
91153
|
if (cells(navParts.map((part) => part.text).join("")) > contentWidth - 6) {
|
|
90823
91154
|
const focused = state.focus === "navigation";
|
|
90824
|
-
navParts.splice(
|
|
91155
|
+
navParts.splice(
|
|
91156
|
+
0,
|
|
91157
|
+
navParts.length,
|
|
91158
|
+
{ text: "OpenMates ", color: "#cfcfcf", bold: true, action: { kind: "command", command: "/chats" } },
|
|
91159
|
+
{ text: `[${titleCase(state.workspace)}] `, color: "#ff553b", bold: true, action: { kind: "command", command: `/${state.workspace}` } },
|
|
91160
|
+
...focused ? [{ text: `\u203A ${titleCase(WORKSPACES[state.navigationIndex])} `, color: "#32ade6", bold: true, action: { kind: "command", command: `/${WORKSPACES[state.navigationIndex]}` } }] : []
|
|
91161
|
+
);
|
|
90825
91162
|
}
|
|
90826
91163
|
const navUsed = cells(navParts.map((part) => part.text).join(""));
|
|
90827
|
-
navParts.push({ text: contentWidth - navUsed >= 18 ? "Ctrl+G navigation" : "^G nav", color: "#808080", bold: false });
|
|
91164
|
+
navParts.push({ text: contentWidth - navUsed >= 18 ? "Ctrl+G navigation" : "^G nav", color: "#808080", bold: false, action: { kind: "key", name: "g", ctrl: true } });
|
|
90828
91165
|
let navRemaining = contentWidth;
|
|
90829
91166
|
const renderedNav = navParts.map((part) => {
|
|
91167
|
+
const column = bodyColumn + contentWidth - navRemaining;
|
|
90830
91168
|
const value = truncateCells(part.text, navRemaining);
|
|
90831
91169
|
navRemaining -= cells(value);
|
|
91170
|
+
if (!modal && part.action) addPointerTarget(state, column, 0, cells(value.trimEnd()), part.action);
|
|
90832
91171
|
return foreground(value, part.color, mode, part.bold);
|
|
90833
91172
|
}).join("") + " ".repeat(navRemaining);
|
|
90834
91173
|
const input = composerViewport(state, composerWidth);
|
|
90835
91174
|
const showComposer = state.workspace !== "apps" || state.focus === "composer" || Boolean(state.input);
|
|
90836
91175
|
const composerRows = showComposer ? input.count : 0;
|
|
90837
91176
|
const bodyHeight = Math.max(1, height - 2 - (showComposer ? composerRows + 3 : 1));
|
|
90838
|
-
const
|
|
90839
|
-
const sidebar = state.sidebarOpen && !
|
|
91177
|
+
const overlay2 = state.form || state.paletteOpen || state.questionEditor;
|
|
91178
|
+
const sidebar = state.sidebarOpen && !overlay2;
|
|
90840
91179
|
const sidebarOverlay = sidebar && !sidebarWidth;
|
|
90841
|
-
let content =
|
|
90842
|
-
const stickyCount = !
|
|
91180
|
+
let content = overlay2 ? overlayLines(state, contentWidth, bodyHeight) : sidebarOverlay ? pointerSidebarLines(state) : body;
|
|
91181
|
+
const stickyCount = !overlay2 && !sidebarOverlay ? Math.min(options.stickyRows ?? 0, Math.max(0, bodyHeight - 8)) : 0;
|
|
90843
91182
|
const fixed = content.slice(0, stickyCount);
|
|
90844
91183
|
content = content.slice(stickyCount);
|
|
90845
91184
|
const viewportHeight = bodyHeight - stickyCount;
|
|
90846
91185
|
const maxStart = Math.max(0, content.length - viewportHeight);
|
|
90847
|
-
let start = !
|
|
91186
|
+
let start = !overlay2 && !sidebarOverlay && state.screen === "chat" ? Math.max(0, maxStart - state.scrollOffset) : Math.min(maxStart, Math.max(0, state.scrollOffset));
|
|
90848
91187
|
if (sidebarOverlay && state.focus === "sidebar") {
|
|
90849
91188
|
const marker = content.findIndex((row) => lineText(row).startsWith("> "));
|
|
90850
91189
|
start = Math.min(maxStart, Math.max(0, marker - bodyHeight + 3));
|
|
90851
91190
|
}
|
|
90852
|
-
if (
|
|
91191
|
+
if (overlay2) {
|
|
90853
91192
|
const marker = content.findIndex((row) => /^[>›] /.test(lineText(row).trimStart()));
|
|
90854
91193
|
start = marker >= bodyHeight - 4 ? Math.max(0, marker - bodyHeight + 6) : 0;
|
|
90855
91194
|
} else if (state.followSelection && ["start", "tasks", "projects", "project", "chat", "chats", "example", "examples", "workflow", "workflows", "apps", "app", "app-skill"].includes(state.screen) && state.focus === "content") {
|
|
@@ -90863,13 +91202,13 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90863
91202
|
if (selectionEnd >= start + viewportHeight) start = Math.min(maxStart, selectionEnd - viewportHeight + 1);
|
|
90864
91203
|
if (marker >= 0 && marker < start) start = marker;
|
|
90865
91204
|
}
|
|
90866
|
-
if (!
|
|
91205
|
+
if (!overlay2 && !sidebarOverlay) state.scrollOffset = state.screen === "chat" ? maxStart - start : start;
|
|
90867
91206
|
state.followSelection = false;
|
|
90868
91207
|
const heroRows = options.headerRows ?? 0;
|
|
90869
91208
|
const category = state.screen === "example" ? state.activeExample?.chat.category : state.activeChat?.category;
|
|
90870
91209
|
const background = chatBackground(category);
|
|
90871
|
-
const allSide = sidebarWidth ?
|
|
90872
|
-
const sideMarker = allSide.findIndex((row) => row.startsWith("> "));
|
|
91210
|
+
const allSide = sidebarWidth ? pointerSidebarLines(state) : [];
|
|
91211
|
+
const sideMarker = allSide.findIndex((row) => lineText(row).startsWith("> "));
|
|
90873
91212
|
const sideStart = Math.max(0, sideMarker - bodyHeight + 3);
|
|
90874
91213
|
const side = sideStart ? [allSide[0], "", ...allSide.slice(sideStart)] : allSide;
|
|
90875
91214
|
const rows2 = [];
|
|
@@ -90879,6 +91218,15 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90879
91218
|
const style = typeof value === "string" ? void 0 : value;
|
|
90880
91219
|
const raw = terminalText(lineText(value)).replace(/\n/g, " ");
|
|
90881
91220
|
let rendered = padCells(raw, contentWidth);
|
|
91221
|
+
const targetInset = Math.max(0, Math.min(Math.floor(contentWidth / 2) - 1, style?.inset ?? 0));
|
|
91222
|
+
const leading = cells(raw) - cells(raw.trimStart());
|
|
91223
|
+
if (style?.action) addPointerTarget(
|
|
91224
|
+
state,
|
|
91225
|
+
bodyColumn + targetInset + leading,
|
|
91226
|
+
i + 2,
|
|
91227
|
+
Math.min(cells(raw.trim()), Math.max(0, contentWidth - 2 * targetInset - leading)),
|
|
91228
|
+
style.action
|
|
91229
|
+
);
|
|
90882
91230
|
if (style && !sidebarOverlay) {
|
|
90883
91231
|
const inset2 = Math.max(0, Math.min(Math.floor(contentWidth / 2) - 1, style.inset ?? 0));
|
|
90884
91232
|
const span = Math.max(1, contentWidth - 2 * inset2);
|
|
@@ -90887,16 +91235,19 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90887
91235
|
rendered = "";
|
|
90888
91236
|
for (const part of style.spans) {
|
|
90889
91237
|
const text7 = truncateCells(terminalText(part.text).replace(/\n/g, " "), remaining), size = cells(text7);
|
|
91238
|
+
if (part.action) addPointerTarget(state, bodyColumn + inset2 + span - remaining, i + 2, size, part.action);
|
|
90890
91239
|
rendered += part.background ? backgroundLine(text7, size, part.background, mode, part.bold, part.color) : foreground(text7, part.color ?? "#e6e6e6", mode, part.bold);
|
|
90891
91240
|
remaining -= size;
|
|
90892
91241
|
if (!remaining) break;
|
|
90893
91242
|
}
|
|
90894
91243
|
rendered = " ".repeat(inset2) + rendered + " ".repeat(remaining + inset2);
|
|
90895
91244
|
} else rendered = " ".repeat(inset2) + (style.background ? backgroundLine(raw, span, style.background, mode, style.bold) : foreground(padCells(raw, span), style.color ?? "#e6e6e6", mode, style.bold)) + " ".repeat(inset2);
|
|
90896
|
-
} else if (!
|
|
91245
|
+
} else if (!overlay2 && !sidebarOverlay && index < heroRows) rendered = backgroundLine(raw, contentWidth, background, mode);
|
|
90897
91246
|
else if (raw.startsWith("> ") || raw.includes("\u203A")) rendered = foreground(rendered, "#ff553b", mode, true);
|
|
90898
91247
|
else if (/^(You|Sophia|Tasks|Projects|Workflows|Recent chats|Suggestions|Actions)$/.test(raw)) rendered = foreground(rendered, "#5a85eb", mode, true);
|
|
90899
|
-
const
|
|
91248
|
+
const sideValue = side[i], sideText = sideValue ? lineText(sideValue) : "";
|
|
91249
|
+
if (sideValue && typeof sideValue !== "string" && sideValue.action) addPointerTarget(state, gutter, i + 2, Math.min(cells(sideText), sidebarWidth - 2), sideValue.action);
|
|
91250
|
+
const sidebarRow = sidebarWidth ? foreground(padCells(sideText, sidebarWidth - 2), "#cfcfcf", mode) + `${vertical} ` : void 0;
|
|
90900
91251
|
rows2.push(place(rendered, sidebarRow));
|
|
90901
91252
|
}
|
|
90902
91253
|
const placeholder = state.screen === "example" ? "Continue from this example, or ask your own question..." : state.workspace === "chats" ? state.screen === "chat" ? "Ask a follow-up, use @file, or type /help" : "Ask anything..." : state.workspace === "projects" ? "Name a new project \xB7 /search to browse" : state.workspace === "workflows" ? "Describe new workflow \xB7 /search to browse" : state.workspace === "tasks" ? "Add or update tasks \xB7 /search to browse" : "Search apps or type / for actions";
|
|
@@ -90904,6 +91255,13 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90904
91255
|
const hintColor = state.focus === "composer" ? "#a0a0a0" : "#ff553b";
|
|
90905
91256
|
const composer = [];
|
|
90906
91257
|
if (showComposer) {
|
|
91258
|
+
if (!modal && !sidebarOverlay) for (let i = 0; i < input.count; i++) addPointerTarget(
|
|
91259
|
+
state,
|
|
91260
|
+
gutter + sidebarWidth + composerInset + (composerWidth < 6 ? 0 : 2),
|
|
91261
|
+
2 + bodyHeight + (composerWidth < 6 ? 0 : 1) + i,
|
|
91262
|
+
Math.max(1, composerWidth - (composerWidth < 6 ? 0 : 4)),
|
|
91263
|
+
{ kind: "focus", focus: "composer" }
|
|
91264
|
+
);
|
|
90907
91265
|
const placeInput = (rendered) => " ".repeat(gutter + sidebarWidth + composerInset) + rendered + " ".repeat(paneWidth - composerInset - composerWidth + gutter);
|
|
90908
91266
|
const inputRows = input.lines.map((text7, i) => `${i ? " " : "> "}${text7 || (!state.input ? placeholder : "")}`);
|
|
90909
91267
|
if (composerWidth < 6) composer.push(...inputRows.map((text7) => placeInput(padCells(text7, composerWidth))), placeInput(foreground(padCells(hint, composerWidth), hintColor, mode)), placeInput(" ".repeat(composerWidth)), placeInput(" ".repeat(composerWidth)));
|
|
@@ -91609,7 +91967,11 @@ function homeHeader(state, width, height) {
|
|
|
91609
91967
|
const title = inspiration?.feature?.title || inspiration?.title || "Daily inspiration";
|
|
91610
91968
|
const banner = [centered2(`DAILY INSPIRATION ${state.focus === "inspiration" ? "\u2039 Enter open \u203A" : "\u2039 Ctrl+O explore \u203A"}`, width), "", ...parts.map((line) => centered2(line, width)), centered2(title, width)];
|
|
91611
91969
|
while (banner.length < rows2) banner.push("");
|
|
91612
|
-
banner.forEach((text7) => result.push({
|
|
91970
|
+
banner.forEach((text7) => result.push({
|
|
91971
|
+
text: text7,
|
|
91972
|
+
background: gradient.start,
|
|
91973
|
+
...inspiration ? { action: { kind: "command", command: "/inspiration" } } : {}
|
|
91974
|
+
}));
|
|
91613
91975
|
result.push("", { text: centered2(state.workspace === "apps" ? prompts.apps : state.username ? `Hey ${state.username}!` : "Hey there!", width), bold: true });
|
|
91614
91976
|
if (state.workspace !== "chats" || !homeChatItems(state).length) result.push({ text: centered2(state.workspace === "apps" ? "Use your apps directly and return to saved results." : prompts[state.workspace], width), color: "#cfcfcf" });
|
|
91615
91977
|
result.push("");
|
|
@@ -91618,7 +91980,7 @@ function homeHeader(state, width, height) {
|
|
|
91618
91980
|
function renderHomeChatCards(state, width, height) {
|
|
91619
91981
|
const items = homeContinueItems(state), result = homeHeader(state, width, height);
|
|
91620
91982
|
const activeCount = runningTuiChatGroups(state).length;
|
|
91621
|
-
if (activeCount) result.push(centered2(`${activeCount} ${activeCount === 1 ? "chat" : "chats"} active\u2026 /active`, width), "");
|
|
91983
|
+
if (activeCount) result.push(pointerLine(centered2(`${activeCount} ${activeCount === 1 ? "chat" : "chats"} active\u2026 /active`, width), { kind: "command", command: "/active" }), "");
|
|
91622
91984
|
if (!items.length) {
|
|
91623
91985
|
result.push(centered2(state.homeChatsLoading ? "Loading your recent chats\u2026" : state.homeError || "Start a chat below. Your recent chats will appear here.", width), "");
|
|
91624
91986
|
return result;
|
|
@@ -91630,14 +91992,16 @@ function renderHomeChatCards(state, width, height) {
|
|
|
91630
91992
|
title: item.title,
|
|
91631
91993
|
description: item.summary || "Open saved item",
|
|
91632
91994
|
footer: `${item.priority.label} \xB7 Saved`,
|
|
91633
|
-
background: (item.category && CATEGORY_GRADIENTS[item.category] || BLUE).start
|
|
91995
|
+
background: (item.category && CATEGORY_GRADIENTS[item.category] || BLUE).start,
|
|
91996
|
+
action: { kind: "command", command: `/embed ${item.embedId}` }
|
|
91634
91997
|
};
|
|
91635
91998
|
const chat = item.chat;
|
|
91636
91999
|
return {
|
|
91637
92000
|
title: chat.title || chat.draftPreview || "Untitled chat",
|
|
91638
92001
|
description: chat.hasDraft ? "Draft" : chat.summary || "Continue this conversation",
|
|
91639
92002
|
footer: item.priority?.label || chat.category?.replaceAll("_", " ") || "Chat",
|
|
91640
|
-
background: (chat.category && CATEGORY_GRADIENTS[chat.category] || BLUE).start
|
|
92003
|
+
background: (chat.category && CATEGORY_GRADIENTS[chat.category] || BLUE).start,
|
|
92004
|
+
action: { kind: "command", command: chat.source === "example" ? `/example ${chat.slug || chat.id}` : `/chat ${chat.id}` }
|
|
91641
92005
|
};
|
|
91642
92006
|
}), width, selected, state.focus === "content"));
|
|
91643
92007
|
result.push(
|
|
@@ -91879,7 +92243,8 @@ function renderTuiAppsHome(apps, options) {
|
|
|
91879
92243
|
title: app.name,
|
|
91880
92244
|
description: app.description,
|
|
91881
92245
|
footer: `${app.skills.length} skills${app.category ? ` \xB7 ${app.category.replaceAll("_", " ")}` : ""}`,
|
|
91882
|
-
background: (APP_GRADIENTS[app.id] ?? PRIMARY_GRADIENT).start
|
|
92246
|
+
background: (APP_GRADIENTS[app.id] ?? PRIMARY_GRADIENT).start,
|
|
92247
|
+
action: { kind: "command", command: `/app ${app.id}` }
|
|
91883
92248
|
})), width, selected, options.selectedId !== void 0),
|
|
91884
92249
|
"",
|
|
91885
92250
|
centeredCarouselText(`${selected > 0 ? "\u2039" : " "} App ${selected + 1} of ${visible.length} ${selected < visible.length - 1 ? "\u203A" : " "}`, width),
|
|
@@ -91923,6 +92288,50 @@ function outlinedTabs(tabs, labels, selected, width) {
|
|
|
91923
92288
|
});
|
|
91924
92289
|
return ["", `\u256D${edges.join("\u252C")}\u256E`, `\u2502${row.join("\u2502")}\u2502`, `\u2570${edges.join("\u2534")}\u256F`, ""];
|
|
91925
92290
|
}
|
|
92291
|
+
function outlinedPointerTabs(tabs, labels, selected, width) {
|
|
92292
|
+
const rendered = outlinedTabs(tabs, labels, selected, width);
|
|
92293
|
+
const action = (index) => ({ kind: "key", name: "", chunk: String(index + 1), focus: "content" });
|
|
92294
|
+
if (width < tabs.length * 8 + 1) {
|
|
92295
|
+
const spans = [];
|
|
92296
|
+
let remaining = Math.max(1, width);
|
|
92297
|
+
tabs.forEach((tab, index) => {
|
|
92298
|
+
if (index && remaining) {
|
|
92299
|
+
const separator = truncateCells(" | ", remaining);
|
|
92300
|
+
spans.push({ text: separator });
|
|
92301
|
+
remaining -= cells(separator);
|
|
92302
|
+
}
|
|
92303
|
+
const label3 = truncateCells(`${index + 1} ${tab === selected ? `[${labels[tab]}]` : labels[tab]}`, remaining);
|
|
92304
|
+
if (label3) spans.push({ text: label3, action: action(index) });
|
|
92305
|
+
remaining -= cells(label3);
|
|
92306
|
+
});
|
|
92307
|
+
return ["", { text: rendered[1], spans }, ""];
|
|
92308
|
+
}
|
|
92309
|
+
const available = width - tabs.length - 1, base = Math.floor(available / tabs.length);
|
|
92310
|
+
const sizes = tabs.map((_, index) => base + (index < available % tabs.length ? 1 : 0));
|
|
92311
|
+
return rendered.map((line, row) => {
|
|
92312
|
+
if (row === 0 || row === rendered.length - 1) return line;
|
|
92313
|
+
const spans = [{ text: line.slice(0, 1) }];
|
|
92314
|
+
let offset = 1;
|
|
92315
|
+
sizes.forEach((size, index) => {
|
|
92316
|
+
spans.push({ text: line.slice(offset, offset + size), action: action(index) });
|
|
92317
|
+
offset += size;
|
|
92318
|
+
spans.push({ text: line.slice(offset, offset + 1) });
|
|
92319
|
+
offset++;
|
|
92320
|
+
});
|
|
92321
|
+
return { text: line, spans };
|
|
92322
|
+
});
|
|
92323
|
+
}
|
|
92324
|
+
function pointerPageLine(offset, hasMore) {
|
|
92325
|
+
const prefix = `Page ${Math.floor(offset / RESULT_PAGE_SIZE) + 1} \xB7 `;
|
|
92326
|
+
const spans = [
|
|
92327
|
+
{ text: prefix },
|
|
92328
|
+
{ text: "previous", ...offset > 0 ? { action: { kind: "key", name: "", chunk: "[", focus: "content" } } : {} },
|
|
92329
|
+
{ text: "/" },
|
|
92330
|
+
{ text: "next", ...hasMore ? { action: { kind: "key", name: "", chunk: "]", focus: "content" } } : {} },
|
|
92331
|
+
{ text: " available" }
|
|
92332
|
+
];
|
|
92333
|
+
return { text: spans.map((span) => span.text).join(""), spans };
|
|
92334
|
+
}
|
|
91926
92335
|
function renderTuiAppIdentity(app, width) {
|
|
91927
92336
|
return identityCard([
|
|
91928
92337
|
`APP / ${app.id.toUpperCase()}`,
|
|
@@ -91931,24 +92340,25 @@ function renderTuiAppIdentity(app, width) {
|
|
|
91931
92340
|
`${app.skills.length} skills \xB7 ${app.focusModes.length} focus modes`
|
|
91932
92341
|
], width, "APP WORKSPACE");
|
|
91933
92342
|
}
|
|
91934
|
-
function renderTuiAppTabs(tab, width) {
|
|
92343
|
+
function renderTuiAppTabs(tab, width, options) {
|
|
91935
92344
|
const tabs = ["skills", "focus_modes", "settings_memories", "embeds", "workflows"];
|
|
91936
92345
|
const labels = { skills: "Skills", focus_modes: "Focus modes", settings_memories: "Memories", embeds: "Embeds", workflows: "Workflows" };
|
|
91937
|
-
return outlinedTabs(tabs, labels, tab, width);
|
|
92346
|
+
return options?.pointer ? outlinedPointerTabs(tabs, labels, tab, width) : outlinedTabs(tabs, labels, tab, width);
|
|
91938
92347
|
}
|
|
91939
92348
|
function renderTuiApp(app, options) {
|
|
91940
92349
|
const width = Math.max(1, options.width);
|
|
91941
|
-
const lines = [...renderTuiAppIdentity(app, width), ...renderTuiAppTabs(options.tab, width)];
|
|
92350
|
+
const lines = [...renderTuiAppIdentity(app, width), ...options.pointer ? renderTuiAppTabs(options.tab, width, { pointer: true }) : renderTuiAppTabs(options.tab, width)];
|
|
91942
92351
|
if (options.tab === "skills") {
|
|
91943
92352
|
lines.push("Which app skill do you want to use?", "");
|
|
91944
92353
|
if (!app.skills.length) lines.push("No skills available.");
|
|
91945
92354
|
for (const skill of app.skills) {
|
|
91946
|
-
|
|
92355
|
+
const card2 = cardLines(
|
|
91947
92356
|
`${skill.id === options.selectedId ? "\u203A" : " "} ${skill.name}`,
|
|
91948
92357
|
skill.description,
|
|
91949
92358
|
skill.providers.length ? `via ${skill.providers.join(", ")}` : `${app.id}/${skill.id}`,
|
|
91950
92359
|
width
|
|
91951
|
-
)
|
|
92360
|
+
);
|
|
92361
|
+
lines.push(...options.pointer ? card2.map((line) => pointerLine(line, { kind: "command", command: `/app-skill ${app.id}/${skill.id}` })) : card2, "");
|
|
91952
92362
|
}
|
|
91953
92363
|
} else if (options.tab === "focus_modes" || options.tab === "settings_memories") {
|
|
91954
92364
|
const items = options.tab === "focus_modes" ? app.focusModes : app.settingsMemories;
|
|
@@ -91956,7 +92366,7 @@ function renderTuiApp(app, options) {
|
|
|
91956
92366
|
for (const item of items) {
|
|
91957
92367
|
lines.push(truncateCells(`${item.id === options.selectedId ? ">" : " "} ${item.name}`, width));
|
|
91958
92368
|
if (item.description) lines.push(...textLines(` ${oneLine2(item.description)}`, width));
|
|
91959
|
-
if ("body" in item && item.body && item.id === options.selectedId) lines.push(...textLines(item.body, width));
|
|
92369
|
+
if ("body" in item && typeof item.body === "string" && item.body && item.id === options.selectedId) lines.push(...textLines(item.body, width));
|
|
91960
92370
|
}
|
|
91961
92371
|
lines.push("", "Manage private Memories in the web app.");
|
|
91962
92372
|
} else if (options.tab === "embeds") lines.push("Saved results load from the encrypted Apps history. Use Enter to inspect a result.");
|
|
@@ -91983,7 +92393,7 @@ async function loadTuiAppsSkill(client2, appId, skillId) {
|
|
|
91983
92393
|
}
|
|
91984
92394
|
function renderTuiAppsSkill(skill, options) {
|
|
91985
92395
|
const width = Math.max(1, options.width);
|
|
91986
|
-
const lines = [...renderTuiAppsSkillIdentity(skill, width), ...renderTuiAppsSkillTabs(options.tab, width)];
|
|
92396
|
+
const lines = [...renderTuiAppsSkillIdentity(skill, width), ...options.pointer ? renderTuiAppsSkillTabs(options.tab, width, { pointer: true }) : renderTuiAppsSkillTabs(options.tab, width)];
|
|
91987
92397
|
if (options.tab === "overview") {
|
|
91988
92398
|
lines.push("Use this skill manually. Your mates can also use it in chats.", "");
|
|
91989
92399
|
for (const path2 of skillLeafPaths(skill.schema)) {
|
|
@@ -91991,7 +92401,7 @@ function renderTuiAppsSkill(skill, options) {
|
|
|
91991
92401
|
const value = getSkillPath(skill.defaults, path2);
|
|
91992
92402
|
lines.push(truncateCells(`${path2}${isRequired(skill.schema, path2) ? " *" : ""} \xB7 ${field?.type ?? "value"}${value !== void 0 ? ` \xB7 ${typeof value === "string" ? value : JSON.stringify(value)}` : ""}`, width));
|
|
91993
92403
|
}
|
|
91994
|
-
lines.push("", skill.executionAvailable ? "Enter opens the input form. Running may spend credits." : `Unavailable: ${skill.unavailableReason ?? "This skill cannot run here."}`);
|
|
92404
|
+
lines.push("", skill.executionAvailable && options.pointer ? pointerLine("Enter opens the input form. Running may spend credits.", { kind: "command", command: "/app-run" }) : skill.executionAvailable ? "Enter opens the input form. Running may spend credits." : `Unavailable: ${skill.unavailableReason ?? "This skill cannot run here."}`);
|
|
91995
92405
|
const fixed = skill.pricing?.fixed;
|
|
91996
92406
|
if (typeof fixed === "number") lines.push(`${fixed} credits per request`);
|
|
91997
92407
|
} else if (options.tab === "embeds") lines.push("Saved results are listed in the app's Embeds tab.");
|
|
@@ -92007,10 +92417,10 @@ function renderTuiAppsSkillIdentity(skill, width) {
|
|
|
92007
92417
|
skill.executionAvailable ? "Use skill \xB7 review input and confirm credits before running" : "Skill unavailable"
|
|
92008
92418
|
], width, "APP SKILL");
|
|
92009
92419
|
}
|
|
92010
|
-
function renderTuiAppsSkillTabs(tab, width) {
|
|
92420
|
+
function renderTuiAppsSkillTabs(tab, width, options) {
|
|
92011
92421
|
const tabs = ["overview", "embeds", "workflows"];
|
|
92012
92422
|
const labels = { overview: "Overview", embeds: "Embeds", workflows: "Workflows" };
|
|
92013
|
-
return outlinedTabs(tabs, labels, tab, width);
|
|
92423
|
+
return options?.pointer ? outlinedPointerTabs(tabs, labels, tab, width) : outlinedTabs(tabs, labels, tab, width);
|
|
92014
92424
|
}
|
|
92015
92425
|
function isRequired(schema, path2) {
|
|
92016
92426
|
const parts = path2.replaceAll("[]", "").split(".");
|
|
@@ -92230,8 +92640,11 @@ function renderTuiAppsWorkflows(page, options) {
|
|
|
92230
92640
|
const width = Math.max(1, options.width);
|
|
92231
92641
|
const lines = ["Related workflows", ""];
|
|
92232
92642
|
if (!page.items.length) lines.push("No workflows for this app.");
|
|
92233
|
-
for (const workflow of page.items)
|
|
92234
|
-
|
|
92643
|
+
for (const workflow of page.items) {
|
|
92644
|
+
const line = truncateCells(`${workflow.id === options.selectedId ? ">" : " "} ${workflow.title} \xB7 ${workflow.id.slice(0, 8)}`, width);
|
|
92645
|
+
lines.push(options.pointer ? pointerLine(line, { kind: "command", command: `/workflow ${workflow.id}` }) : line);
|
|
92646
|
+
}
|
|
92647
|
+
if (page.offset > 0 || page.hasMore) lines.push("", options.pointer ? pointerPageLine(page.offset, page.hasMore) : `Page ${Math.floor(page.offset / RESULT_PAGE_SIZE) + 1} \xB7 previous/next available`);
|
|
92235
92648
|
return lines;
|
|
92236
92649
|
}
|
|
92237
92650
|
async function decryptedRow(row, key) {
|
|
@@ -92256,8 +92669,11 @@ function renderTuiAppsResults(page, options) {
|
|
|
92256
92669
|
const width = Math.max(1, options.width);
|
|
92257
92670
|
const lines = ["Saved results", ""];
|
|
92258
92671
|
if (!page.items.length) lines.push("No saved results for this app.");
|
|
92259
|
-
for (const item of page.items)
|
|
92260
|
-
|
|
92672
|
+
for (const item of page.items) {
|
|
92673
|
+
const line = truncateCells(`${item.embedId === options.selectedId ? ">" : " "} ${item.skillId} \xB7 ${item.status} \xB7 ${item.embedId.slice(0, 8)}`, width);
|
|
92674
|
+
lines.push(options.pointer ? pointerLine(line, { kind: "command", command: `/app-result ${item.embedId}` }) : line);
|
|
92675
|
+
}
|
|
92676
|
+
if (page.offset > 0 || page.hasMore) lines.push("", options.pointer ? pointerPageLine(page.offset, page.hasMore) : `Page ${Math.floor(page.offset / RESULT_PAGE_SIZE) + 1} \xB7 previous/next available`);
|
|
92261
92677
|
return lines;
|
|
92262
92678
|
}
|
|
92263
92679
|
function renderTuiAppsResult(result, width) {
|
|
@@ -92656,10 +93072,6 @@ function chatResultsViews(state) {
|
|
|
92656
93072
|
const messages = state.activeExample && (state.screen === "example" || state.embedOrigin?.screen === "example" || state.resultsViewOrigin?.screen === "example") ? state.activeExample.messages : state.messages;
|
|
92657
93073
|
return messages.flatMap((message) => messageResultsViews(message.content));
|
|
92658
93074
|
}
|
|
92659
|
-
function renderChatResultsView(state, descriptor, key, width, mode) {
|
|
92660
|
-
const data = buildTuiResultsViewData(descriptor, { ...exampleEmbedMap(state), ...state.chatEmbeds });
|
|
92661
|
-
return renderTuiResultsViewLines(data, { viewKey: key, mode: mode ?? state.resultsViewModes[key], aliasForEmbed: (id) => aliasForEmbed(state, id) }).flatMap((row, index) => wrapCells(row, width).map((text7) => index === 0 ? { text: text7, bold: true, color: "#80caff" } : index === 1 && row.includes("/view") ? { text: text7, color: "#85c9e8" } : text7));
|
|
92662
|
-
}
|
|
92663
93075
|
|
|
92664
93076
|
// ../ui/src/components/embeds/fitness/fitnessEmbedData.ts
|
|
92665
93077
|
function normalizeFitnessStatus(value) {
|
|
@@ -92754,7 +93166,11 @@ function fitnessSkillName(skillId) {
|
|
|
92754
93166
|
function card(details, width, appName, skillName, alias, appId, emphasizeSecond = true) {
|
|
92755
93167
|
const cardWidth = Math.max(1, Math.min(62, Math.floor(width) || 1));
|
|
92756
93168
|
const shortcut = `/embed ${readable(alias)}`;
|
|
92757
|
-
|
|
93169
|
+
const action = /^[\p{L}\p{N}_.:()-]{1,300}$/u.test(alias) ? { kind: "command", command: shortcut } : null;
|
|
93170
|
+
if (cardWidth < 6) {
|
|
93171
|
+
const line = truncateCells(shortcut, cardWidth);
|
|
93172
|
+
return [action ? pointerLine(line, action) : line];
|
|
93173
|
+
}
|
|
92758
93174
|
const inner = cardWidth - 4;
|
|
92759
93175
|
const colors = appColors(appId);
|
|
92760
93176
|
const row = (value, color = DETAIL, background, bold = false) => {
|
|
@@ -92773,7 +93189,7 @@ function card(details, width, appName, skillName, alias, appId, emphasizeSecond
|
|
|
92773
93189
|
lines.push(row(truncateCells(`${appName} \xB7 ${skillName}`, inner), colors.foreground, colors.background, true));
|
|
92774
93190
|
lines.push(row(truncateCells(shortcut, inner), colors.foreground, colors.background));
|
|
92775
93191
|
lines.push({ text: `\u2570${"\u2500".repeat(cardWidth - 2)}\u256F`, color: BORDER });
|
|
92776
|
-
return lines;
|
|
93192
|
+
return action ? lines.map((line) => pointerLine(line, action)) : lines;
|
|
92777
93193
|
}
|
|
92778
93194
|
function recordingDetails(content, title, width, status) {
|
|
92779
93195
|
if (status === "error" || status === "cancelled") {
|
|
@@ -93218,6 +93634,7 @@ function rankExamples(examples, interests) {
|
|
|
93218
93634
|
}).sort((a, b) => b.score - a.score || a.index - b.index).map((entry) => entry.example);
|
|
93219
93635
|
}
|
|
93220
93636
|
function renderTuiFrame(state, width, height, options = {}) {
|
|
93637
|
+
beginPointerFrame(state, width, height);
|
|
93221
93638
|
if (state.startup || state.privacyOffer) return renderStartupFrame(state, width, height, options.colorMode ?? "none");
|
|
93222
93639
|
const bodyWidth = workspaceGeometry(state, width).contentWidth;
|
|
93223
93640
|
const stickyRows = state.screen === "embed" ? 3 : state.screen === "results-view" ? 2 : state.screen === "project" && state.activeProject ? renderProjectIdentity(state.activeProject, { width: bodyWidth }).length + renderProjectTabs(state.projectTab, bodyWidth).length : state.screen === "app" && state.activeApp ? renderTuiAppIdentity(state.activeApp, bodyWidth).length + renderTuiAppTabs(state.appTab, bodyWidth).length : state.screen === "app-skill" && state.activeAppSkill ? renderTuiAppsSkillIdentity(state.activeAppSkill, bodyWidth).length + renderTuiAppsSkillTabs(state.appSkillTab, bodyWidth).length : state.screen === "workflow" && state.activeWorkflow ? renderWorkflowIdentity(state.activeWorkflow, { width: bodyWidth, run: state.workflowTab === "runs" ? state.workflowRuns[state.selectedWorkflowRunIndex] : void 0 }).length + (bodyWidth < 36 ? 7 : 4) : 0;
|
|
@@ -93258,7 +93675,23 @@ function renderStartupFrame(state, width, height, colorMode) {
|
|
|
93258
93675
|
return [...lines.slice(0, Math.max(0, height - footer.length)), ...footer.slice(-height)].join("\n");
|
|
93259
93676
|
}
|
|
93260
93677
|
function coloredHero(lines, rows2, gradient = PRIMARY_GRADIENT) {
|
|
93261
|
-
return lines.map((
|
|
93678
|
+
return lines.map((line, index) => index < rows2 ? typeof line === "string" ? { text: line, background: gradient.start } : { ...line, background: gradient.start } : line);
|
|
93679
|
+
}
|
|
93680
|
+
function appsHomeCommandLine(showAll, width) {
|
|
93681
|
+
const browse = showAll ? "/browse Featured apps" : "/browse Show all";
|
|
93682
|
+
const separator = " \xB7 ", search = "/search Search apps";
|
|
93683
|
+
const visible = truncateCells(browse + separator + search, width);
|
|
93684
|
+
const text7 = centeredCarouselText(browse + separator + search, width);
|
|
93685
|
+
const left = text7.slice(0, text7.length - visible.length);
|
|
93686
|
+
const shownBrowse = visible.slice(0, browse.length);
|
|
93687
|
+
const shownSeparator = visible.slice(browse.length, browse.length + separator.length);
|
|
93688
|
+
const shownSearch = visible.slice(browse.length + separator.length);
|
|
93689
|
+
return { text: text7, spans: [
|
|
93690
|
+
{ text: left },
|
|
93691
|
+
{ text: shownBrowse, action: { kind: "command", command: "/browse" } },
|
|
93692
|
+
{ text: shownSeparator },
|
|
93693
|
+
{ text: shownSearch, action: shownSearch.startsWith("/search") ? { kind: "command", command: "/search" } : void 0 }
|
|
93694
|
+
] };
|
|
93262
93695
|
}
|
|
93263
93696
|
function renderBody(state, width, height) {
|
|
93264
93697
|
return renderScreenBody(state, width, height);
|
|
@@ -93283,7 +93716,7 @@ function renderScreenBody(state, width, height) {
|
|
|
93283
93716
|
...homeHeader(state, width, height),
|
|
93284
93717
|
...renderTuiAppsHome(apps, { width, selectedIndex: state.selectedIndex, selectedId: state.focus === "content" ? apps[state.selectedIndex]?.id : void 0 }),
|
|
93285
93718
|
"",
|
|
93286
|
-
|
|
93719
|
+
appsHomeCommandLine(state.homeShowAll, width)
|
|
93287
93720
|
];
|
|
93288
93721
|
}
|
|
93289
93722
|
case "app": {
|
|
@@ -93292,10 +93725,10 @@ function renderScreenBody(state, width, height) {
|
|
|
93292
93725
|
const header2 = renderTuiAppIdentity(app, width), gradient = APP_GRADIENTS[app.id] ?? PRIMARY_GRADIENT;
|
|
93293
93726
|
if (state.appTab === "embeds" || state.appTab === "workflows") return [
|
|
93294
93727
|
...coloredHero(header2, header2.length, gradient),
|
|
93295
|
-
...renderTuiAppTabs(state.appTab, width),
|
|
93296
|
-
...state.appTab === "embeds" ? renderTuiAppsResults(state.appResults, { width, selectedId: state.appResults.items[state.selectedIndex]?.embedId }) : renderTuiAppsWorkflows(state.appWorkflows, { width, selectedId: state.appWorkflows.items[state.selectedIndex]?.id })
|
|
93728
|
+
...renderTuiAppTabs(state.appTab, width, { pointer: true }),
|
|
93729
|
+
...state.appTab === "embeds" ? renderTuiAppsResults(state.appResults, { width, selectedId: state.appResults.items[state.selectedIndex]?.embedId, pointer: true }) : renderTuiAppsWorkflows(state.appWorkflows, { width, selectedId: state.appWorkflows.items[state.selectedIndex]?.id, pointer: true })
|
|
93297
93730
|
];
|
|
93298
|
-
return coloredHero(renderTuiApp(app, { width, tab: state.appTab, selectedId: app.skills[state.selectedIndex]?.id }), header2.length, gradient);
|
|
93731
|
+
return coloredHero(renderTuiApp(app, { width, tab: state.appTab, selectedId: app.skills[state.selectedIndex]?.id, pointer: true }), header2.length, gradient);
|
|
93299
93732
|
}
|
|
93300
93733
|
case "app-skill": {
|
|
93301
93734
|
const skill = state.activeAppSkill;
|
|
@@ -93303,28 +93736,43 @@ function renderScreenBody(state, width, height) {
|
|
|
93303
93736
|
const header2 = renderTuiAppsSkillIdentity(skill, width), gradient = APP_GRADIENTS[skill.appId] ?? PRIMARY_GRADIENT;
|
|
93304
93737
|
if (state.appSkillTab === "embeds" || state.appSkillTab === "workflows") return [
|
|
93305
93738
|
...coloredHero(header2, header2.length, gradient),
|
|
93306
|
-
...renderTuiAppsSkillTabs(state.appSkillTab, width),
|
|
93307
|
-
...state.appSkillTab === "embeds" ? renderTuiAppsResults(state.appResults, { width, selectedId: state.appResults.items[state.selectedIndex]?.embedId }) : renderTuiAppsWorkflows(state.appWorkflows, { width, selectedId: state.appWorkflows.items[state.selectedIndex]?.id })
|
|
93739
|
+
...renderTuiAppsSkillTabs(state.appSkillTab, width, { pointer: true }),
|
|
93740
|
+
...state.appSkillTab === "embeds" ? renderTuiAppsResults(state.appResults, { width, selectedId: state.appResults.items[state.selectedIndex]?.embedId, pointer: true }) : renderTuiAppsWorkflows(state.appWorkflows, { width, selectedId: state.appWorkflows.items[state.selectedIndex]?.id, pointer: true })
|
|
93308
93741
|
];
|
|
93309
|
-
return coloredHero(renderTuiAppsSkill(skill, { width, tab: state.appSkillTab }), header2.length, gradient);
|
|
93742
|
+
return coloredHero(renderTuiAppsSkill(skill, { width, tab: state.appSkillTab, pointer: true }), header2.length, gradient);
|
|
93310
93743
|
}
|
|
93311
93744
|
case "app-result":
|
|
93312
93745
|
return state.activeAppResult ? renderTuiAppsResult(state.activeAppResult, width) : ["Loading saved result\u2026"];
|
|
93313
93746
|
case "projects":
|
|
93314
93747
|
return [...homeHeader(state, width, height), ...renderProjectCarousel(filteredProjects(state.projects, state.filter), width, state.selectedIndex, state.focus === "content")];
|
|
93315
93748
|
case "project":
|
|
93316
|
-
return state.activeProject ? state.projectTab === "tasks" ? [...renderProjectIdentity(state.activeProject, { width }), ...
|
|
93749
|
+
return state.activeProject ? state.projectTab === "tasks" ? [...renderProjectIdentity(state.activeProject, { width }), ...renderProjectPointerTabs("tasks", width), "", ...renderTaskBoard2(state.tasks, { width, selectedTaskId: filterTasks(state.tasks, state.filter)[state.selectedIndex]?.taskId, query: state.filter })] : renderProjectDetail(state.activeProject, { width, tab: state.projectTab, files: state.projectFiles, selectedFileId: filteredProjectFiles(state.projectFiles, state.filter)[state.selectedIndex]?.id, query: state.filter, folderId: state.projectFolderId ?? void 0, sourceId: state.projectSourceId ?? void 0, path: state.projectPath }) : ["Projects", "Loading project\u2026"];
|
|
93317
93750
|
case "status":
|
|
93318
93751
|
return renderStatus(state, width);
|
|
93319
93752
|
case "results-view": {
|
|
93320
93753
|
const key = state.activeResultsView ?? 1, descriptor = chatResultsViews(state)[key - 1];
|
|
93321
|
-
return descriptor ? [
|
|
93754
|
+
return descriptor ? [
|
|
93755
|
+
...pointerResultsView(state, descriptor, key, width),
|
|
93756
|
+
"",
|
|
93757
|
+
{ text: "m Map \xB7 c Calendar \xB7 l List \xB7 Esc back", spans: [
|
|
93758
|
+
{ text: "m Map", action: { kind: "command", command: `/view ${key} map` } },
|
|
93759
|
+
{ text: " \xB7 " },
|
|
93760
|
+
{ text: "c Calendar", action: { kind: "command", command: `/view ${key} calendar` } },
|
|
93761
|
+
{ text: " \xB7 " },
|
|
93762
|
+
{ text: "l List", action: { kind: "command", command: `/view ${key} list` } },
|
|
93763
|
+
{ text: " \xB7 " },
|
|
93764
|
+
{ text: "Esc back", action: { kind: "key", name: "escape" } }
|
|
93765
|
+
] }
|
|
93766
|
+
] : ["Results view unavailable. Escape returns to the chat."];
|
|
93322
93767
|
}
|
|
93323
93768
|
case "embed": {
|
|
93324
93769
|
const app = state.detailEmbed?.appId ?? "", gradient = APP_GRADIENTS[app] ?? PRIMARY_GRADIENT;
|
|
93325
93770
|
const title = state.detailTitle || "Embed";
|
|
93326
93771
|
const header2 = [title, state.detailEmbed ? `${state.detailEmbed.type?.replaceAll("-", " ") ?? "Saved item"} \xB7 ${state.detailEmbed.embedId.slice(0, 8)}` : "Saved embeds"];
|
|
93327
|
-
return [...coloredHero(header2, header2.length, gradient), "", ...
|
|
93772
|
+
return [...coloredHero(header2, header2.length, gradient), "", ...state.embedChoices.length ? state.embedChoices.map((alias, index) => pointerLine(
|
|
93773
|
+
`${index === state.selectedIndex ? ">" : " "} /embed ${alias} \xB7 Enter open`,
|
|
93774
|
+
{ kind: "command", command: `/embed ${alias}` }
|
|
93775
|
+
)) : state.detailLines].flatMap((line) => wrap(lineText(line), width).map((text7) => typeof line === "string" ? text7 : { ...line, text: text7, spans: void 0 }));
|
|
93328
93776
|
}
|
|
93329
93777
|
case "workflows":
|
|
93330
93778
|
return [...homeHeader(state, width, height), ...renderWorkflowCarousel(state.workflows.filter((w) => w.title.toLowerCase().includes(state.filter.toLowerCase())), width, state.selectedIndex, state.focus === "content")];
|
|
@@ -93378,7 +93826,12 @@ function renderTasks(state, width) {
|
|
|
93378
93826
|
}
|
|
93379
93827
|
function renderTaskDetail2(state, width) {
|
|
93380
93828
|
if (!state.activeTask) return renderTasks(state, width);
|
|
93381
|
-
return renderTaskDetails(state.activeTask, {
|
|
93829
|
+
return renderTaskDetails(state.activeTask, {
|
|
93830
|
+
width,
|
|
93831
|
+
activity: state.taskContext?.activity,
|
|
93832
|
+
dependencies: state.taskContext?.dependencies,
|
|
93833
|
+
pointer: true
|
|
93834
|
+
});
|
|
93382
93835
|
}
|
|
93383
93836
|
function renderWorkflows(state, width) {
|
|
93384
93837
|
const lines = ["Workflows", ""];
|
|
@@ -93544,7 +93997,10 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93544
93997
|
...card2.slice(-4)
|
|
93545
93998
|
]);
|
|
93546
93999
|
lines.push(...renderLineCarousel(cards, width, Math.max(0, selected), Boolean(state?.focus === "content" && selected >= 0), cardWidth));
|
|
93547
|
-
if (state && selected >= 0) lines.push(
|
|
94000
|
+
if (state && selected >= 0) lines.push(pointerLine(
|
|
94001
|
+
centeredCarouselText(`Embed ${selected + 1}/${unique4.length} \xB7 \u2190/\u2192 choose \xB7 Enter open \xB7 /embed ${aliasForEmbed(state, id)}`, width),
|
|
94002
|
+
{ kind: "command", command: `/embed ${aliasForEmbed(state, id)}` }
|
|
94003
|
+
));
|
|
93548
94004
|
pending = [];
|
|
93549
94005
|
};
|
|
93550
94006
|
const text7 = (value) => {
|
|
@@ -93556,7 +94012,7 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93556
94012
|
lines.push(...renderQuestionCard(question ?? { key, messageIndex: 0, payload: block.payload }, width));
|
|
93557
94013
|
} else if (block.type === "results-view") {
|
|
93558
94014
|
const key = ++viewIndex;
|
|
93559
|
-
if (state) lines.push(...
|
|
94015
|
+
if (state) lines.push(...pointerResultsView(state, block, key, width));
|
|
93560
94016
|
else lines.push(...renderTuiResultsViewLines(buildTuiResultsViewData(block, embeds), { viewKey: key }).flatMap((row) => wrap(row, width)));
|
|
93561
94017
|
}
|
|
93562
94018
|
}
|
|
@@ -93573,6 +94029,23 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93573
94029
|
flush();
|
|
93574
94030
|
return lines;
|
|
93575
94031
|
}
|
|
94032
|
+
function pointerResultsView(state, descriptor, key, width) {
|
|
94033
|
+
const data = buildTuiResultsViewData(descriptor, { ...exampleEmbedMap(state), ...state.chatEmbeds });
|
|
94034
|
+
const actions = data.entries.map((entry, index) => {
|
|
94035
|
+
const alias = aliasForEmbed(state, entry.ref);
|
|
94036
|
+
return { index, title: entry.title, command: `/embed ${alias}` };
|
|
94037
|
+
}).filter((entry) => /^[\p{L}\p{N}_.:()-]{1,300}$/u.test(entry.command.slice(7)));
|
|
94038
|
+
const rows2 = renderTuiResultsViewLines(data, {
|
|
94039
|
+
viewKey: key,
|
|
94040
|
+
mode: state.resultsViewModes[key],
|
|
94041
|
+
aliasForEmbed: (id) => aliasForEmbed(state, id)
|
|
94042
|
+
});
|
|
94043
|
+
return rows2.flatMap((row, index) => {
|
|
94044
|
+
const value = row.trim(), entry = actions.find((item) => value === item.command || value.startsWith(`${item.index + 1}. ${item.title}`) || value.startsWith(`\u2605 ${item.index + 1}. ${item.title}`) || value.startsWith(`\u25B6 ${item.index + 1}. ${item.title}`));
|
|
94045
|
+
const action = index === 1 && value.startsWith(`/view ${key} `) ? { kind: "command", command: `/view ${key}` } : entry ? { kind: "command", command: entry.command } : void 0;
|
|
94046
|
+
return wrap(row, width).map((text7) => action ? pointerLine(index === 0 ? { text: text7, bold: true, color: "#80caff" } : index === 1 ? { text: text7, color: "#85c9e8" } : text7, action) : index === 0 ? { text: text7, bold: true, color: "#80caff" } : index === 1 && row.includes("/view") ? { text: text7, color: "#85c9e8" } : text7);
|
|
94047
|
+
});
|
|
94048
|
+
}
|
|
93576
94049
|
function renderEmbedReference(segment, width, embeds, state) {
|
|
93577
94050
|
const meta = segment.meta ?? {}, saved = embeds.get(segment.value);
|
|
93578
94051
|
const alias = state ? aliasForEmbed(state, segment.value) : segment.value;
|
|
@@ -95817,6 +96290,115 @@ async function prepareTuiMessage(client2, message) {
|
|
|
95817
96290
|
};
|
|
95818
96291
|
}
|
|
95819
96292
|
|
|
96293
|
+
// src/tuiPointerActions.ts
|
|
96294
|
+
async function handleTuiPointer(context, action, keyboard) {
|
|
96295
|
+
const { state, render } = context;
|
|
96296
|
+
if (state.textSelection || state.startup || state.privacyOffer) return;
|
|
96297
|
+
if (action.kind === "question") {
|
|
96298
|
+
await handleQuestionPointer(context, action);
|
|
96299
|
+
return;
|
|
96300
|
+
}
|
|
96301
|
+
if (action.kind === "command") {
|
|
96302
|
+
await context.command(action.command);
|
|
96303
|
+
return;
|
|
96304
|
+
}
|
|
96305
|
+
if (action.kind === "focus") {
|
|
96306
|
+
state.focus = action.focus;
|
|
96307
|
+
render();
|
|
96308
|
+
return;
|
|
96309
|
+
}
|
|
96310
|
+
if (action.kind === "key") {
|
|
96311
|
+
if (action.focus) state.focus = action.focus;
|
|
96312
|
+
else if (state.form || state.paletteOpen) state.focus = "content";
|
|
96313
|
+
await keyboard(action.chunk ?? "", { name: action.name, ctrl: action.ctrl });
|
|
96314
|
+
return;
|
|
96315
|
+
}
|
|
96316
|
+
if (!Number.isInteger(action.index) || action.index < 0) return;
|
|
96317
|
+
let index = action.index;
|
|
96318
|
+
switch (action.target) {
|
|
96319
|
+
case "sidebar": {
|
|
96320
|
+
const ids = sidebarPointerIds(state);
|
|
96321
|
+
index = action.id ? ids.indexOf(action.id) : index;
|
|
96322
|
+
if (index < 0 || !ids[index]) return;
|
|
96323
|
+
state.sidebarIndex = index;
|
|
96324
|
+
state.focus = "sidebar";
|
|
96325
|
+
break;
|
|
96326
|
+
}
|
|
96327
|
+
case "palette": {
|
|
96328
|
+
if (!state.paletteOpen) return;
|
|
96329
|
+
const actions = paletteActions(state.paletteQuery);
|
|
96330
|
+
index = action.id ? actions.findIndex((item) => item.command === action.id) : index;
|
|
96331
|
+
if (index < 0 || !actions[index]) return;
|
|
96332
|
+
state.paletteIndex = index;
|
|
96333
|
+
state.focus = "content";
|
|
96334
|
+
break;
|
|
96335
|
+
}
|
|
96336
|
+
case "form-field": {
|
|
96337
|
+
const form = state.form;
|
|
96338
|
+
if (!form || form.busy) return;
|
|
96339
|
+
index = action.id ? form.fields.findIndex((field) => field.name === action.id) : index;
|
|
96340
|
+
if (index < 0 || !form.fields[index]) return;
|
|
96341
|
+
form.fieldIndex = index;
|
|
96342
|
+
state.focus = "content";
|
|
96343
|
+
break;
|
|
96344
|
+
}
|
|
96345
|
+
case "task": {
|
|
96346
|
+
if (state.screen !== "tasks" && !(state.screen === "project" && state.projectTab === "tasks")) return;
|
|
96347
|
+
const status = action.column === void 0 ? void 0 : TASK_STATUSES[action.column];
|
|
96348
|
+
if (action.column !== void 0 && !status) return;
|
|
96349
|
+
const tasks = filterTasks(state.tasks, state.filter, status);
|
|
96350
|
+
if (!action.id && !action.activate && state.screen === "tasks") {
|
|
96351
|
+
state.taskStatusFilter = status ?? "";
|
|
96352
|
+
state.selectedIndex = Math.min(index, Math.max(0, tasks.length - 1));
|
|
96353
|
+
state.focus = "content";
|
|
96354
|
+
render();
|
|
96355
|
+
return;
|
|
96356
|
+
}
|
|
96357
|
+
index = action.id ? tasks.findIndex((task) => task.taskId === action.id) : index;
|
|
96358
|
+
if (index < 0 || !tasks[index]) return;
|
|
96359
|
+
state.taskStatusFilter = status ?? "";
|
|
96360
|
+
state.selectedIndex = index;
|
|
96361
|
+
state.focus = "content";
|
|
96362
|
+
if (state.screen === "project") state.selectedIndex = filterTasks(state.tasks, state.filter).findIndex((task) => task.taskId === tasks[index].taskId);
|
|
96363
|
+
break;
|
|
96364
|
+
}
|
|
96365
|
+
case "workflow-node": {
|
|
96366
|
+
if (state.screen !== "workflow") return;
|
|
96367
|
+
const graph = state.workflowTab === "runs" ? state.workflowRunGraph : state.activeWorkflow?.graph;
|
|
96368
|
+
const nodes = graph ? orderedWorkflowNodes(graph) : [];
|
|
96369
|
+
index = action.id ? nodes.findIndex((node) => node.id === action.id) : index;
|
|
96370
|
+
if (index < 0 || !nodes[index]) return;
|
|
96371
|
+
state.selectedWorkflowNodeIndex = index;
|
|
96372
|
+
state.focus = "content";
|
|
96373
|
+
break;
|
|
96374
|
+
}
|
|
96375
|
+
case "workflow-run": {
|
|
96376
|
+
if (state.screen !== "workflow" || state.workflowTab !== "runs") return;
|
|
96377
|
+
index = action.id ? state.workflowRuns.findIndex((run) => run.id === action.id) : index;
|
|
96378
|
+
if (index < 0 || !state.workflowRuns[index]) return;
|
|
96379
|
+
state.selectedWorkflowRunIndex = index;
|
|
96380
|
+
state.focus = "content";
|
|
96381
|
+
if (action.activate) {
|
|
96382
|
+
await keyboard("r", { name: "" });
|
|
96383
|
+
return;
|
|
96384
|
+
}
|
|
96385
|
+
break;
|
|
96386
|
+
}
|
|
96387
|
+
case "content":
|
|
96388
|
+
if (action.id) {
|
|
96389
|
+
if (state.screen !== "project" || state.projectTab !== "files") return;
|
|
96390
|
+
index = filteredProjectFiles(state.projectFiles, state.filter).findIndex((file) => file.id === action.id);
|
|
96391
|
+
if (index < 0) return;
|
|
96392
|
+
}
|
|
96393
|
+
state.selectedIndex = index;
|
|
96394
|
+
state.focus = "content";
|
|
96395
|
+
break;
|
|
96396
|
+
}
|
|
96397
|
+
state.followSelection = true;
|
|
96398
|
+
if (action.activate) await keyboard(action.chunk ?? "", { name: action.name ?? "return" });
|
|
96399
|
+
else render();
|
|
96400
|
+
}
|
|
96401
|
+
|
|
95820
96402
|
// src/tui.ts
|
|
95821
96403
|
function defaultModeForStreams(input, output) {
|
|
95822
96404
|
return input.isTTY === true && output.isTTY === true ? "tui" : "quickstart";
|
|
@@ -95919,6 +96501,10 @@ async function runTui(client2, terminal = new TuiTerminal(), startupServices) {
|
|
|
95919
96501
|
return;
|
|
95920
96502
|
}
|
|
95921
96503
|
void (async () => {
|
|
96504
|
+
if (key.name === "mouseclick") {
|
|
96505
|
+
await handleKey({ chunk, key, state, client: client2, terminal, render, finish });
|
|
96506
|
+
return;
|
|
96507
|
+
}
|
|
95922
96508
|
if (await startup.handleKey(chunk, key)) return;
|
|
95923
96509
|
await handleKey({ chunk, key, state, client: client2, terminal, render, finish });
|
|
95924
96510
|
})().catch((error) => {
|
|
@@ -95957,6 +96543,12 @@ async function handleKey(params) {
|
|
|
95957
96543
|
command: (command) => handleCommand({ command, state, client: client2, terminal, render, finish }),
|
|
95958
96544
|
send: (message, options) => sendTuiMessage({ message, state, client: client2, render, questionAnswer: options?.questionAnswer })
|
|
95959
96545
|
};
|
|
96546
|
+
if (key.name === "mouseclick") {
|
|
96547
|
+
if (!key.mouse || key.ctrl || key.meta || key.shift) return;
|
|
96548
|
+
const action = pointerTargetAt(state, key.mouse.column, key.mouse.row, terminal.width, terminal.height);
|
|
96549
|
+
if (action) await handleTuiPointer(context, action, (text7, pressed) => handleKey({ ...params, chunk: text7, key: pressed }));
|
|
96550
|
+
return;
|
|
96551
|
+
}
|
|
95960
96552
|
if (await handleWorkspaceKey(context, chunk, key)) return;
|
|
95961
96553
|
if (key.name === "escape") {
|
|
95962
96554
|
if (state.workflowEdit) {
|