openmates 0.27.0-alpha.33 → 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-LJHQR2XS.js → chunk-QE7VIQMK.js} +762 -146
- 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}`);
|
|
@@ -76687,7 +76687,25 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
76687
76687
|
text: "Cache read"
|
|
76688
76688
|
},
|
|
76689
76689
|
cache_pricing_explanation: {
|
|
76690
|
-
text: "Cache reads reuse earlier input at a lower price. Cache writes create it and may cost more. Your receipt shows the usage charged."
|
|
76690
|
+
text: "Cache reads reuse earlier input at a lower price. Cache writes create it and may cost more. These rates apply to normal authenticated personal and team chats. Billing for workflows and orchestrated subchats remains unchanged. Your receipt shows the usage charged."
|
|
76691
|
+
},
|
|
76692
|
+
automatic_summary_title: {
|
|
76693
|
+
text: "Automatic long-chat summaries"
|
|
76694
|
+
},
|
|
76695
|
+
automatic_summary_explanation: {
|
|
76696
|
+
text: "In normal authenticated personal and team chats, automatic long-chat summaries are billed separately only when needed. If no summary runs, there is no summary charge. Billing for workflows and orchestrated subchats remains unchanged. Your receipt shows the rates used."
|
|
76697
|
+
},
|
|
76698
|
+
automatic_summary_fallback: {
|
|
76699
|
+
text: "Fallback"
|
|
76700
|
+
},
|
|
76701
|
+
standard_pricing: {
|
|
76702
|
+
text: "Standard"
|
|
76703
|
+
},
|
|
76704
|
+
over_272k_pricing: {
|
|
76705
|
+
text: "Over 272,000 input tokens"
|
|
76706
|
+
},
|
|
76707
|
+
over_272k_explanation: {
|
|
76708
|
+
text: "Total input includes cached input. Above 272,000 input tokens, these rates apply to the whole request."
|
|
76691
76709
|
},
|
|
76692
76710
|
cache_write: {
|
|
76693
76711
|
text: "Cache write"
|
|
@@ -79242,6 +79260,9 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
79242
79260
|
cache_receipt_title: {
|
|
79243
79261
|
text: "LLM billing receipt"
|
|
79244
79262
|
},
|
|
79263
|
+
cache_receipt_automatic_summary: {
|
|
79264
|
+
text: "Automatic long-chat summary"
|
|
79265
|
+
},
|
|
79245
79266
|
cache_receipt_source: {
|
|
79246
79267
|
text: "Usage source"
|
|
79247
79268
|
},
|
|
@@ -79266,6 +79287,9 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
79266
79287
|
cache_receipt_pricing_version: {
|
|
79267
79288
|
text: "Pricing version"
|
|
79268
79289
|
},
|
|
79290
|
+
cache_receipt_context_band: {
|
|
79291
|
+
text: "Pricing tier"
|
|
79292
|
+
},
|
|
79269
79293
|
cache_receipt_raw: {
|
|
79270
79294
|
text: "Raw credits"
|
|
79271
79295
|
},
|
|
@@ -88165,6 +88189,7 @@ var TuiTerminal = class {
|
|
|
88165
88189
|
decoder = new StringDecoder("utf8");
|
|
88166
88190
|
pendingInput = "";
|
|
88167
88191
|
pendingMouse = "";
|
|
88192
|
+
discardingMouse = false;
|
|
88168
88193
|
paste = false;
|
|
88169
88194
|
pasteText = "";
|
|
88170
88195
|
inputTimer = null;
|
|
@@ -88230,6 +88255,7 @@ var TuiTerminal = class {
|
|
|
88230
88255
|
this.inputTimer = null;
|
|
88231
88256
|
this.pendingInput = "";
|
|
88232
88257
|
this.pendingMouse = "";
|
|
88258
|
+
this.discardingMouse = false;
|
|
88233
88259
|
this.paste = false;
|
|
88234
88260
|
this.pasteText = "";
|
|
88235
88261
|
this.output.write("\x1B[?25h");
|
|
@@ -88244,6 +88270,8 @@ var TuiTerminal = class {
|
|
|
88244
88270
|
} finally {
|
|
88245
88271
|
this.suspended = false;
|
|
88246
88272
|
if (this.active) {
|
|
88273
|
+
while (this.input.read() !== null) {
|
|
88274
|
+
}
|
|
88247
88275
|
this.input.on("data", this.rawInput);
|
|
88248
88276
|
if (this.resizeHandler) this.output.on("resize", this.resizeHandler);
|
|
88249
88277
|
if (typeof this.input.setRawMode === "function") {
|
|
@@ -88291,7 +88319,13 @@ var TuiTerminal = class {
|
|
|
88291
88319
|
this.pasteText = (this.pasteText + before).slice(0, 131072);
|
|
88292
88320
|
this.keyHandler?.(this.pasteText, { name: "paste" });
|
|
88293
88321
|
this.pasteText = "";
|
|
88294
|
-
} 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
|
+
}
|
|
88295
88329
|
this.paste = !this.paste;
|
|
88296
88330
|
this.pendingInput = this.pendingInput.slice(found + marker.length);
|
|
88297
88331
|
this.receiveInput("");
|
|
@@ -88309,46 +88343,71 @@ var TuiTerminal = class {
|
|
|
88309
88343
|
this.inputTimer = null;
|
|
88310
88344
|
}, 30);
|
|
88311
88345
|
}
|
|
88312
|
-
/**
|
|
88346
|
+
/** Keep SGR mouse bytes out of readline, including malformed and split reports. */
|
|
88313
88347
|
dispatchInput(text7) {
|
|
88314
88348
|
if (this.mouseTimer) clearTimeout(this.mouseTimer);
|
|
88315
88349
|
this.mouseTimer = null;
|
|
88316
88350
|
const input = this.pendingMouse + text7;
|
|
88317
88351
|
this.pendingMouse = "";
|
|
88318
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
|
+
}
|
|
88319
88359
|
while (offset < input.length) {
|
|
88320
88360
|
const start = input.indexOf("\x1B[<", offset);
|
|
88321
88361
|
if (start < 0) {
|
|
88322
|
-
const
|
|
88323
|
-
|
|
88324
|
-
|
|
88325
|
-
|
|
88326
|
-
this.mouseTimer = setTimeout(() => {
|
|
88327
|
-
const pending = this.pendingMouse;
|
|
88328
|
-
this.pendingMouse = "";
|
|
88329
|
-
this.mouseTimer = null;
|
|
88330
|
-
if (pending === "\x1B") this.keyHandler?.("\x1B", { name: "escape", sequence: pending });
|
|
88331
|
-
else this.keyInput.write(pending);
|
|
88332
|
-
}, 500);
|
|
88333
|
-
}
|
|
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);
|
|
88334
88366
|
break;
|
|
88335
88367
|
}
|
|
88336
88368
|
this.keyInput.write(input.slice(offset, start));
|
|
88337
|
-
const
|
|
88338
|
-
|
|
88339
|
-
|
|
88340
|
-
|
|
88341
|
-
|
|
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;
|
|
88342
88377
|
}
|
|
88343
|
-
this.
|
|
88344
|
-
|
|
88345
|
-
|
|
88378
|
+
if (input.length - start < 128) this.holdMousePrefix(input.slice(start));
|
|
88379
|
+
else this.discardingMouse = true;
|
|
88380
|
+
break;
|
|
88346
88381
|
}
|
|
88347
|
-
const
|
|
88348
|
-
|
|
88349
|
-
|
|
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;
|
|
88350
88398
|
}
|
|
88351
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
|
+
}
|
|
88352
88411
|
removeListeners() {
|
|
88353
88412
|
if (this.keyHandler) {
|
|
88354
88413
|
this.keyInput.off("keypress", this.keyHandler);
|
|
@@ -88361,6 +88420,7 @@ var TuiTerminal = class {
|
|
|
88361
88420
|
this.inputTimer = null;
|
|
88362
88421
|
this.pendingInput = "";
|
|
88363
88422
|
this.pendingMouse = "";
|
|
88423
|
+
this.discardingMouse = false;
|
|
88364
88424
|
this.paste = false;
|
|
88365
88425
|
this.pasteText = "";
|
|
88366
88426
|
if (this.resizeHandler) {
|
|
@@ -88680,7 +88740,7 @@ function renderCardCarousel(cards, width, selectedIndex, focused) {
|
|
|
88680
88740
|
`\u2502 ${padCells(card2.footer, inner)} \u2502`,
|
|
88681
88741
|
`\u2570${"\u2500".repeat(cardWidth - 2)}\u256F`
|
|
88682
88742
|
];
|
|
88683
|
-
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 };
|
|
88684
88744
|
});
|
|
88685
88745
|
return Array.from({ length: visible[0].rows.length }, (_, row) => {
|
|
88686
88746
|
const spans = [];
|
|
@@ -88689,7 +88749,7 @@ function renderCardCarousel(cards, width, selectedIndex, focused) {
|
|
|
88689
88749
|
const start = Math.max(0, card2.left), end = Math.min(width, card2.left + cardWidth);
|
|
88690
88750
|
if (end <= start) continue;
|
|
88691
88751
|
if (start > column) spans.push({ text: " ".repeat(start - column) });
|
|
88692
|
-
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 });
|
|
88693
88753
|
column = end;
|
|
88694
88754
|
}
|
|
88695
88755
|
if (column < width) spans.push({ text: " ".repeat(width - column) });
|
|
@@ -88719,13 +88779,13 @@ function renderLineCarousel(cards, width, selectedIndex, focused, cardWidth) {
|
|
|
88719
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);
|
|
88720
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 };
|
|
88721
88781
|
}
|
|
88722
|
-
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 }];
|
|
88723
88783
|
let offset = 0, used = 0;
|
|
88724
88784
|
const cropStart = Math.max(0, -card2.left), cropEnd = cropStart + end - start;
|
|
88725
88785
|
for (const part of source) {
|
|
88726
88786
|
const size = cells(part.text), from = Math.max(cropStart, offset), to = Math.min(cropEnd, offset + size);
|
|
88727
88787
|
if (to > from) {
|
|
88728
|
-
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) });
|
|
88729
88789
|
used += to - from;
|
|
88730
88790
|
}
|
|
88731
88791
|
offset += size;
|
|
@@ -88738,6 +88798,27 @@ function renderLineCarousel(cards, width, selectedIndex, focused, cardWidth) {
|
|
|
88738
88798
|
});
|
|
88739
88799
|
}
|
|
88740
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
|
+
|
|
88741
88822
|
// src/tuiProjectsWorkspace.ts
|
|
88742
88823
|
function contextFor(client2, project) {
|
|
88743
88824
|
const teamId = project ? project.teamId : client2.getActiveTeamId();
|
|
@@ -88963,7 +89044,8 @@ function renderProjectCarousel(projects, width, selectedIndex, focused) {
|
|
|
88963
89044
|
title: safeText(project.name),
|
|
88964
89045
|
description: safeText(project.description),
|
|
88965
89046
|
footer: `${count} ${count === 1 ? "item" : "items"}${project.pinned ? " \xB7 Pinned" : ""}${project.archived ? " \xB7 Archived" : ""}`,
|
|
88966
|
-
background: projectCardColor(project.color)
|
|
89047
|
+
background: projectCardColor(project.color),
|
|
89048
|
+
action: { kind: "command", command: `/project ${project.id}` }
|
|
88967
89049
|
};
|
|
88968
89050
|
});
|
|
88969
89051
|
return [
|
|
@@ -89011,14 +89093,37 @@ function renderProjectTabs(tab, width) {
|
|
|
89011
89093
|
const inset = Math.max(0, Math.floor((width - cells(text7)) / 2));
|
|
89012
89094
|
return ["", `${" ".repeat(inset)}${clip(text7, width)}`, ""];
|
|
89013
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
|
+
}
|
|
89014
89115
|
function renderProjectDetail(project, options) {
|
|
89015
89116
|
const width = options.width;
|
|
89016
|
-
const lines = [...renderProjectIdentity(project, { width }), ...
|
|
89117
|
+
const lines = [...renderProjectIdentity(project, { width }), ...renderProjectPointerTabs(options.tab, width)];
|
|
89017
89118
|
if (options.tab === "overview") {
|
|
89018
89119
|
lines.push(...renderProjectCard(false, project.readme ? project.readme.split("\n") : ["No project overview created yet."], width, "OVERVIEW"));
|
|
89019
89120
|
const links = project.items.filter((item) => item.type !== "embed");
|
|
89020
89121
|
if (links.length) {
|
|
89021
|
-
|
|
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
|
+
}));
|
|
89022
89127
|
}
|
|
89023
89128
|
return lines;
|
|
89024
89129
|
}
|
|
@@ -89047,7 +89152,12 @@ function renderProjectDetail(project, options) {
|
|
|
89047
89152
|
const context = file.sourceId ? ` (${project.sources.find((source) => source.id === file.sourceId)?.name || "source"})` : "";
|
|
89048
89153
|
rows2.push(`${file.id === options.selectedFileId ? ">" : " "} [${icon}] ${file.name}${context}`);
|
|
89049
89154
|
}
|
|
89050
|
-
|
|
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
|
+
}));
|
|
89051
89161
|
return lines;
|
|
89052
89162
|
}
|
|
89053
89163
|
function buildProjectForm() {
|
|
@@ -89135,7 +89245,7 @@ function joinColumns(rows2, width, gap) {
|
|
|
89135
89245
|
if (index) spans.push({ text: gap });
|
|
89136
89246
|
if (typeof row === "string") spans.push({ text: padCells(row, width) });
|
|
89137
89247
|
else {
|
|
89138
|
-
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 })));
|
|
89139
89249
|
const padding = Math.max(0, width - cells(lineText(row)));
|
|
89140
89250
|
if (padding) spans.push({ text: " ".repeat(padding) });
|
|
89141
89251
|
}
|
|
@@ -89177,24 +89287,40 @@ function renderTaskBoard2(tasks, options) {
|
|
|
89177
89287
|
const shown = columns.slice(firstColumn, firstColumn + columnCount);
|
|
89178
89288
|
const colWidth = Math.floor((width - gap.length * (columnCount - 1)) / columnCount);
|
|
89179
89289
|
lines.push(truncateCells(`\u2190/\u2192 columns \xB7 ${STATUS_LABELS2[focused]} ${focusedIndex + 1}/5`, width));
|
|
89180
|
-
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));
|
|
89181
89294
|
lines.push(shown.map(() => "\u2500".repeat(colWidth)).join(gap));
|
|
89182
|
-
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)]);
|
|
89183
89301
|
for (let row = 0; row < Math.max(...stacks.map((stack) => stack.length)); row++) {
|
|
89184
89302
|
lines.push(joinColumns(stacks.map((stack) => stack[row] ?? ""), colWidth, gap));
|
|
89185
89303
|
}
|
|
89186
89304
|
} else {
|
|
89187
89305
|
const group = columns[focusedIndex]?.tasks ?? [];
|
|
89188
89306
|
lines.push(truncateCells(`\u2190/\u2192 columns \xB7 ${STATUS_LABELS2[focused]} ${focusedIndex + 1}/5`, width));
|
|
89189
|
-
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)));
|
|
89190
89311
|
if (!group.length) lines.push(" No tasks here.");
|
|
89191
|
-
for (const task of group) {
|
|
89192
|
-
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
|
+
));
|
|
89193
89319
|
}
|
|
89194
89320
|
}
|
|
89195
89321
|
return lines;
|
|
89196
89322
|
}
|
|
89197
|
-
function taskCard(task, width, selected) {
|
|
89323
|
+
function taskCard(task, width, selected, action) {
|
|
89198
89324
|
const inside = Math.max(8, width - 2);
|
|
89199
89325
|
const edge = (selected ? "\u2550" : "\u2500").repeat(inside);
|
|
89200
89326
|
const row = (value, title = false) => {
|
|
@@ -89219,7 +89345,7 @@ function taskCard(task, width, selected) {
|
|
|
89219
89345
|
...metadata.map((item) => row(` ${item}`)),
|
|
89220
89346
|
...task.queueState && task.queueState !== "none" ? [row(`Q ${task.queueState}`)] : [],
|
|
89221
89347
|
border(false)
|
|
89222
|
-
];
|
|
89348
|
+
].map((line) => pointerLine(line, action));
|
|
89223
89349
|
}
|
|
89224
89350
|
async function loadTaskContext(client2, taskId) {
|
|
89225
89351
|
const record10 = await client2.getUserTask(taskId);
|
|
@@ -89244,7 +89370,16 @@ function renderTaskDetails(task, options) {
|
|
|
89244
89370
|
if (task.labels.length) lines.push(truncateCells(`Labels: ${task.labels.join(", ")}`, width));
|
|
89245
89371
|
if (task.dueAt) lines.push(`Due: ${new Date(task.dueAt * 1e3).toISOString().slice(0, 16)} UTC`);
|
|
89246
89372
|
if (task.blockedReason) lines.push(truncateCells(`Blocked: ${task.blockedReason}`, width));
|
|
89247
|
-
|
|
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
|
+
);
|
|
89248
89383
|
lines.push(...wrapCells(task.description || "No description.", width));
|
|
89249
89384
|
if (options.dependencies) {
|
|
89250
89385
|
lines.push("", `Dependencies (${options.dependencies.dependencies.length})`);
|
|
@@ -89258,6 +89393,27 @@ function renderTaskDetails(task, options) {
|
|
|
89258
89393
|
}
|
|
89259
89394
|
return lines;
|
|
89260
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
|
+
}
|
|
89261
89417
|
function relationLabel(reference) {
|
|
89262
89418
|
const match = /^(task|plan):(.+)$/.exec(reference);
|
|
89263
89419
|
if (!match) return truncateCells(reference, 32);
|
|
@@ -89417,7 +89573,8 @@ function renderWorkflowCarousel(workflows, width, selectedIndex, focused) {
|
|
|
89417
89573
|
truncateCells(clean(workflow.trigger_summary || "Manual"), 32)
|
|
89418
89574
|
].filter(Boolean).join("\n"),
|
|
89419
89575
|
footer: `${workflow.enabled ? "Enabled" : "Paused"}${workflow.last_run_status ? ` \xB7 Last: ${clean(workflow.last_run_status)}` : ""}`,
|
|
89420
|
-
background: PRIMARY_GRADIENT.start
|
|
89576
|
+
background: PRIMARY_GRADIENT.start,
|
|
89577
|
+
action: { kind: "command", command: `/workflow ${workflow.id}` }
|
|
89421
89578
|
}));
|
|
89422
89579
|
return [
|
|
89423
89580
|
...renderCardCarousel(cards, width, selected, focused),
|
|
@@ -89442,7 +89599,13 @@ function renderWorkflowIdentity(workflow, options) {
|
|
|
89442
89599
|
];
|
|
89443
89600
|
return rows2.map((row, index) => {
|
|
89444
89601
|
const value = truncateCells(terminalText(row), width);
|
|
89445
|
-
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
|
+
};
|
|
89446
89609
|
});
|
|
89447
89610
|
}
|
|
89448
89611
|
var NODE_FIELDS = {
|
|
@@ -89500,6 +89663,22 @@ function workflowTabs(width, tab) {
|
|
|
89500
89663
|
const inset = " ".repeat(Math.floor((width - tabWidth * 2 - 2) / 2));
|
|
89501
89664
|
return left.map((line, index) => `${inset}${line} ${right[index]}`);
|
|
89502
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
|
+
}
|
|
89503
89682
|
function orderedWorkflowNodes(graph) {
|
|
89504
89683
|
const byId = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
89505
89684
|
const incoming = new Map(graph.nodes.map((node) => [node.id, 0]));
|
|
@@ -89590,7 +89769,7 @@ function graphCanvas(graph, options, run, width) {
|
|
|
89590
89769
|
const selected = nodes[Math.max(0, Math.min(nodes.length - 1, options.selectedNodeIndex ?? 0))]?.id;
|
|
89591
89770
|
const innerWidth = Math.max(8, width - 4);
|
|
89592
89771
|
const rows2 = [];
|
|
89593
|
-
for (const node of nodes) {
|
|
89772
|
+
for (const [nodeIndex, node] of nodes.entries()) {
|
|
89594
89773
|
const nodeRun = nodeRuns.get(node.id);
|
|
89595
89774
|
const typeLabel = nodeKind(node);
|
|
89596
89775
|
const badge = graph.trigger_node_id === node.id ? " \xB7 trigger" : "";
|
|
@@ -89609,10 +89788,23 @@ function graphCanvas(graph, options, run, width) {
|
|
|
89609
89788
|
...expanded ? expandedStepRows(node, nodeRun, options.tab === "runs", options.edit) : []
|
|
89610
89789
|
];
|
|
89611
89790
|
const color = workflowNodeColor(node);
|
|
89791
|
+
const action = { kind: "select", target: "workflow-node", index: nodeIndex, id: node.id, activate: true };
|
|
89612
89792
|
rows2.push(...panel(expanded ? "Step details" : "Step", cardRows, cardWidth, expanded ? "left" : "center").map((line) => {
|
|
89613
89793
|
const inset = " ".repeat(cardInset);
|
|
89614
89794
|
const text7 = `${inset}${line}`;
|
|
89615
|
-
|
|
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 }] };
|
|
89616
89808
|
}));
|
|
89617
89809
|
const outgoing = (graph.edges ?? []).filter((edge) => edge.from === node.id);
|
|
89618
89810
|
const connector = " ".repeat(cardInset + 2);
|
|
@@ -89634,7 +89826,7 @@ function renderWorkflowWorkspace(workflow, options) {
|
|
|
89634
89826
|
const width = Math.max(1, options.width);
|
|
89635
89827
|
const lines = [
|
|
89636
89828
|
...renderWorkflowIdentity(workflow, { width, run: options.tab === "runs" ? run ?? void 0 : void 0 }),
|
|
89637
|
-
...
|
|
89829
|
+
...workflowPointerTabs(width, options.tab),
|
|
89638
89830
|
""
|
|
89639
89831
|
];
|
|
89640
89832
|
const upcoming = workflow.enabled && workflow.next_run_at && workflow.next_run_at > Date.now() / 1e3 ? workflow.next_run_at : null;
|
|
@@ -89645,7 +89837,10 @@ function renderWorkflowWorkspace(workflow, options) {
|
|
|
89645
89837
|
if (!runs.length && !upcoming) lines.push("No runs yet.");
|
|
89646
89838
|
for (const [index, item] of runs.entries()) {
|
|
89647
89839
|
const marker = index === (options.selectedRunIndex ?? 0) ? ">" : " ";
|
|
89648
|
-
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
|
+
));
|
|
89649
89844
|
}
|
|
89650
89845
|
if (run) {
|
|
89651
89846
|
lines.push("", `Selected run ${run.id} \xB7 ${run.status} \xB7 version ${run.version_id}`);
|
|
@@ -89885,8 +90080,8 @@ function append(out, value, style = {}) {
|
|
|
89885
90080
|
const text7 = terminalText(value);
|
|
89886
90081
|
if (!text7) return;
|
|
89887
90082
|
const last = out.at(-1);
|
|
89888
|
-
if (last && last.bold === style.bold && last.color === style.color && last.background === style.background) last.text += text7;
|
|
89889
|
-
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 });
|
|
89890
90085
|
}
|
|
89891
90086
|
function closing(source, from, delimiter) {
|
|
89892
90087
|
for (let i = from; i <= source.length - delimiter.length; i++) {
|
|
@@ -89958,8 +90153,9 @@ function inline(source, options, base = {}) {
|
|
|
89958
90153
|
} else if (wiki && safeReference(wiki)) action = `/wiki ${wiki}`;
|
|
89959
90154
|
else if (/^https?:\/\/\S+$/i.test(target)) action = target;
|
|
89960
90155
|
if (action) {
|
|
89961
|
-
|
|
89962
|
-
|
|
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 });
|
|
89963
90159
|
} else append(out, source.slice(i, link2.end), base);
|
|
89964
90160
|
i = link2.end;
|
|
89965
90161
|
continue;
|
|
@@ -90127,23 +90323,81 @@ function renderQuestionCard(question, width) {
|
|
|
90127
90323
|
const marker = q.type === "choice" ? control.selected ? "[\u2713]" : q.multiple ? "[ ]" : "( )" : "";
|
|
90128
90324
|
rows2.push(...wrapCells(`${marker} ${control.label}${control.value !== void 0 ? ` \xB7 ${control.value || "(empty)"}` : ""}`.trim(), width));
|
|
90129
90325
|
}
|
|
90130
|
-
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
|
+
})), "");
|
|
90131
90331
|
return rows2;
|
|
90132
90332
|
}
|
|
90133
90333
|
function renderQuestionEditor(editor, width) {
|
|
90134
90334
|
const q = editor.question.payload, items = controls(editor), rows2 = [];
|
|
90135
|
-
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 })));
|
|
90136
90336
|
add(`Answer question ${editor.question.key}`, "#80caff", true);
|
|
90137
90337
|
add(q.question ?? (q.type === "input" ? "Tell us more" : "Review these options"), "#ffffff", true);
|
|
90138
90338
|
rows2.push("");
|
|
90139
90339
|
items.forEach((item, index) => {
|
|
90140
90340
|
const focused = index === editor.fieldIndex, marker = q.type === "choice" ? item.selected ? "[\u2713]" : q.multiple ? "[ ]" : "( )" : "";
|
|
90141
|
-
|
|
90142
|
-
|
|
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
|
+
}
|
|
90143
90386
|
});
|
|
90144
90387
|
rows2.push("");
|
|
90145
|
-
add(
|
|
90146
|
-
|
|
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 });
|
|
90147
90401
|
if (editor.error) add(editor.error, "#ff6b6b", true);
|
|
90148
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");
|
|
90149
90403
|
return rows2;
|
|
@@ -90261,6 +90515,60 @@ async function handleQuestionKey(context, chunk, key) {
|
|
|
90261
90515
|
render();
|
|
90262
90516
|
return true;
|
|
90263
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
|
+
}
|
|
90264
90572
|
|
|
90265
90573
|
// src/tuiActions.ts
|
|
90266
90574
|
var TUI_ACTIONS = [
|
|
@@ -90713,6 +91021,17 @@ function sidebarLines(state) {
|
|
|
90713
91021
|
return ["Apps", "", ...state.apps.map((a, i) => selected(a.name, i)), "", "Ctrl+B close sidebar"];
|
|
90714
91022
|
}
|
|
90715
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
|
+
}
|
|
90716
91035
|
function workspaceHint(state) {
|
|
90717
91036
|
if (state.questionEditor) return "Tab / \u2191\u2193 move Space choose \u2190/\u2192 adjust Ctrl+S send Esc cancel";
|
|
90718
91037
|
if (state.form) return "Tab field \u2190/\u2192 choice Ctrl+S save Esc cancel";
|
|
@@ -90743,7 +91062,10 @@ function overlayLines(state, width, height) {
|
|
|
90743
91062
|
if (state.paletteOpen) {
|
|
90744
91063
|
const actions = paletteActions(state.paletteQuery);
|
|
90745
91064
|
const start = Math.max(0, state.paletteIndex - Math.max(1, height - 5));
|
|
90746
|
-
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
|
+
))];
|
|
90747
91069
|
}
|
|
90748
91070
|
const form = state.form;
|
|
90749
91071
|
if (!form) return [];
|
|
@@ -90761,71 +91083,112 @@ function overlayLines(state, width, height) {
|
|
|
90761
91083
|
for (const [index, field] of form.fields.entries()) {
|
|
90762
91084
|
const focused = index === form.fieldIndex;
|
|
90763
91085
|
const suffix = [field.required ? "required" : "", field.valueType && field.valueType !== "string" ? field.valueType : "", field.options ? "\u2190/\u2192 choose" : ""].filter(Boolean).join(" \xB7 ");
|
|
90764
|
-
|
|
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 });
|
|
90765
91088
|
if (panelWidth >= 6) {
|
|
90766
91089
|
const edge = "\u2500".repeat(panelWidth - 2), border = focused ? "#32ade6" : "#626878";
|
|
90767
91090
|
rows3.push({ text: `\u256D${edge}\u256E`, color: border, inset });
|
|
90768
|
-
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 })));
|
|
90769
91092
|
rows3.push({ text: `\u2570${edge}\u256F`, color: border, inset }, "");
|
|
90770
|
-
} 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
|
+
] });
|
|
90771
91099
|
}
|
|
90772
91100
|
if (form.error) rows3.push({ text: form.error, color: "#ff6b6b", bold: true, inset });
|
|
90773
|
-
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
|
+
});
|
|
90774
91111
|
return rows3;
|
|
90775
91112
|
}
|
|
90776
91113
|
const rows2 = [form.title, ""];
|
|
90777
91114
|
for (const [index, field] of form.fields.entries()) {
|
|
90778
|
-
|
|
90779
|
-
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
|
+
] });
|
|
90780
91123
|
rows2.push("");
|
|
90781
91124
|
}
|
|
90782
91125
|
if (form.error) rows2.push(`Error: ${form.error}`);
|
|
90783
|
-
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
|
+
] });
|
|
90784
91131
|
return rows2;
|
|
90785
91132
|
}
|
|
90786
91133
|
function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
90787
91134
|
const { gutter, sidebarWidth, paneWidth, contentWidth, inset, composerWidth, composerInset } = workspaceGeometry(state, rawWidth);
|
|
90788
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;
|
|
90789
91139
|
const mode = options.colorMode ?? "none";
|
|
90790
91140
|
const ascii = options.ascii ?? false;
|
|
90791
91141
|
const line = ascii ? "-" : "\u2500", vertical = ascii ? "|" : "\u2502";
|
|
90792
91142
|
const place = (rendered, side2 = " ".repeat(sidebarWidth)) => " ".repeat(gutter) + side2 + " ".repeat(inset) + rendered + " ".repeat(paneWidth - inset - contentWidth + gutter);
|
|
90793
|
-
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) => {
|
|
90794
91144
|
const focused = state.focus === "navigation" && index === state.navigationIndex;
|
|
90795
91145
|
const label3 = state.workspace === workspace ? `[${titleCase(workspace)}]` : titleCase(workspace);
|
|
90796
|
-
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
|
+
};
|
|
90797
91152
|
})];
|
|
90798
91153
|
if (cells(navParts.map((part) => part.text).join("")) > contentWidth - 6) {
|
|
90799
91154
|
const focused = state.focus === "navigation";
|
|
90800
|
-
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
|
+
);
|
|
90801
91162
|
}
|
|
90802
91163
|
const navUsed = cells(navParts.map((part) => part.text).join(""));
|
|
90803
|
-
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 } });
|
|
90804
91165
|
let navRemaining = contentWidth;
|
|
90805
91166
|
const renderedNav = navParts.map((part) => {
|
|
91167
|
+
const column = bodyColumn + contentWidth - navRemaining;
|
|
90806
91168
|
const value = truncateCells(part.text, navRemaining);
|
|
90807
91169
|
navRemaining -= cells(value);
|
|
91170
|
+
if (!modal && part.action) addPointerTarget(state, column, 0, cells(value.trimEnd()), part.action);
|
|
90808
91171
|
return foreground(value, part.color, mode, part.bold);
|
|
90809
91172
|
}).join("") + " ".repeat(navRemaining);
|
|
90810
91173
|
const input = composerViewport(state, composerWidth);
|
|
90811
91174
|
const showComposer = state.workspace !== "apps" || state.focus === "composer" || Boolean(state.input);
|
|
90812
91175
|
const composerRows = showComposer ? input.count : 0;
|
|
90813
91176
|
const bodyHeight = Math.max(1, height - 2 - (showComposer ? composerRows + 3 : 1));
|
|
90814
|
-
const
|
|
90815
|
-
const sidebar = state.sidebarOpen && !
|
|
91177
|
+
const overlay2 = state.form || state.paletteOpen || state.questionEditor;
|
|
91178
|
+
const sidebar = state.sidebarOpen && !overlay2;
|
|
90816
91179
|
const sidebarOverlay = sidebar && !sidebarWidth;
|
|
90817
|
-
let content =
|
|
90818
|
-
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;
|
|
90819
91182
|
const fixed = content.slice(0, stickyCount);
|
|
90820
91183
|
content = content.slice(stickyCount);
|
|
90821
91184
|
const viewportHeight = bodyHeight - stickyCount;
|
|
90822
91185
|
const maxStart = Math.max(0, content.length - viewportHeight);
|
|
90823
|
-
let start = !
|
|
91186
|
+
let start = !overlay2 && !sidebarOverlay && state.screen === "chat" ? Math.max(0, maxStart - state.scrollOffset) : Math.min(maxStart, Math.max(0, state.scrollOffset));
|
|
90824
91187
|
if (sidebarOverlay && state.focus === "sidebar") {
|
|
90825
91188
|
const marker = content.findIndex((row) => lineText(row).startsWith("> "));
|
|
90826
91189
|
start = Math.min(maxStart, Math.max(0, marker - bodyHeight + 3));
|
|
90827
91190
|
}
|
|
90828
|
-
if (
|
|
91191
|
+
if (overlay2) {
|
|
90829
91192
|
const marker = content.findIndex((row) => /^[>›] /.test(lineText(row).trimStart()));
|
|
90830
91193
|
start = marker >= bodyHeight - 4 ? Math.max(0, marker - bodyHeight + 6) : 0;
|
|
90831
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") {
|
|
@@ -90839,13 +91202,13 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90839
91202
|
if (selectionEnd >= start + viewportHeight) start = Math.min(maxStart, selectionEnd - viewportHeight + 1);
|
|
90840
91203
|
if (marker >= 0 && marker < start) start = marker;
|
|
90841
91204
|
}
|
|
90842
|
-
if (!
|
|
91205
|
+
if (!overlay2 && !sidebarOverlay) state.scrollOffset = state.screen === "chat" ? maxStart - start : start;
|
|
90843
91206
|
state.followSelection = false;
|
|
90844
91207
|
const heroRows = options.headerRows ?? 0;
|
|
90845
91208
|
const category = state.screen === "example" ? state.activeExample?.chat.category : state.activeChat?.category;
|
|
90846
91209
|
const background = chatBackground(category);
|
|
90847
|
-
const allSide = sidebarWidth ?
|
|
90848
|
-
const sideMarker = allSide.findIndex((row) => row.startsWith("> "));
|
|
91210
|
+
const allSide = sidebarWidth ? pointerSidebarLines(state) : [];
|
|
91211
|
+
const sideMarker = allSide.findIndex((row) => lineText(row).startsWith("> "));
|
|
90849
91212
|
const sideStart = Math.max(0, sideMarker - bodyHeight + 3);
|
|
90850
91213
|
const side = sideStart ? [allSide[0], "", ...allSide.slice(sideStart)] : allSide;
|
|
90851
91214
|
const rows2 = [];
|
|
@@ -90855,6 +91218,15 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90855
91218
|
const style = typeof value === "string" ? void 0 : value;
|
|
90856
91219
|
const raw = terminalText(lineText(value)).replace(/\n/g, " ");
|
|
90857
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
|
+
);
|
|
90858
91230
|
if (style && !sidebarOverlay) {
|
|
90859
91231
|
const inset2 = Math.max(0, Math.min(Math.floor(contentWidth / 2) - 1, style.inset ?? 0));
|
|
90860
91232
|
const span = Math.max(1, contentWidth - 2 * inset2);
|
|
@@ -90863,16 +91235,19 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90863
91235
|
rendered = "";
|
|
90864
91236
|
for (const part of style.spans) {
|
|
90865
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);
|
|
90866
91239
|
rendered += part.background ? backgroundLine(text7, size, part.background, mode, part.bold, part.color) : foreground(text7, part.color ?? "#e6e6e6", mode, part.bold);
|
|
90867
91240
|
remaining -= size;
|
|
90868
91241
|
if (!remaining) break;
|
|
90869
91242
|
}
|
|
90870
91243
|
rendered = " ".repeat(inset2) + rendered + " ".repeat(remaining + inset2);
|
|
90871
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);
|
|
90872
|
-
} else if (!
|
|
91245
|
+
} else if (!overlay2 && !sidebarOverlay && index < heroRows) rendered = backgroundLine(raw, contentWidth, background, mode);
|
|
90873
91246
|
else if (raw.startsWith("> ") || raw.includes("\u203A")) rendered = foreground(rendered, "#ff553b", mode, true);
|
|
90874
91247
|
else if (/^(You|Sophia|Tasks|Projects|Workflows|Recent chats|Suggestions|Actions)$/.test(raw)) rendered = foreground(rendered, "#5a85eb", mode, true);
|
|
90875
|
-
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;
|
|
90876
91251
|
rows2.push(place(rendered, sidebarRow));
|
|
90877
91252
|
}
|
|
90878
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";
|
|
@@ -90880,6 +91255,13 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90880
91255
|
const hintColor = state.focus === "composer" ? "#a0a0a0" : "#ff553b";
|
|
90881
91256
|
const composer = [];
|
|
90882
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
|
+
);
|
|
90883
91265
|
const placeInput = (rendered) => " ".repeat(gutter + sidebarWidth + composerInset) + rendered + " ".repeat(paneWidth - composerInset - composerWidth + gutter);
|
|
90884
91266
|
const inputRows = input.lines.map((text7, i) => `${i ? " " : "> "}${text7 || (!state.input ? placeholder : "")}`);
|
|
90885
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)));
|
|
@@ -91585,7 +91967,11 @@ function homeHeader(state, width, height) {
|
|
|
91585
91967
|
const title = inspiration?.feature?.title || inspiration?.title || "Daily inspiration";
|
|
91586
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)];
|
|
91587
91969
|
while (banner.length < rows2) banner.push("");
|
|
91588
|
-
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
|
+
}));
|
|
91589
91975
|
result.push("", { text: centered2(state.workspace === "apps" ? prompts.apps : state.username ? `Hey ${state.username}!` : "Hey there!", width), bold: true });
|
|
91590
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" });
|
|
91591
91977
|
result.push("");
|
|
@@ -91594,7 +91980,7 @@ function homeHeader(state, width, height) {
|
|
|
91594
91980
|
function renderHomeChatCards(state, width, height) {
|
|
91595
91981
|
const items = homeContinueItems(state), result = homeHeader(state, width, height);
|
|
91596
91982
|
const activeCount = runningTuiChatGroups(state).length;
|
|
91597
|
-
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" }), "");
|
|
91598
91984
|
if (!items.length) {
|
|
91599
91985
|
result.push(centered2(state.homeChatsLoading ? "Loading your recent chats\u2026" : state.homeError || "Start a chat below. Your recent chats will appear here.", width), "");
|
|
91600
91986
|
return result;
|
|
@@ -91606,14 +91992,16 @@ function renderHomeChatCards(state, width, height) {
|
|
|
91606
91992
|
title: item.title,
|
|
91607
91993
|
description: item.summary || "Open saved item",
|
|
91608
91994
|
footer: `${item.priority.label} \xB7 Saved`,
|
|
91609
|
-
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}` }
|
|
91610
91997
|
};
|
|
91611
91998
|
const chat = item.chat;
|
|
91612
91999
|
return {
|
|
91613
92000
|
title: chat.title || chat.draftPreview || "Untitled chat",
|
|
91614
92001
|
description: chat.hasDraft ? "Draft" : chat.summary || "Continue this conversation",
|
|
91615
92002
|
footer: item.priority?.label || chat.category?.replaceAll("_", " ") || "Chat",
|
|
91616
|
-
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}` }
|
|
91617
92005
|
};
|
|
91618
92006
|
}), width, selected, state.focus === "content"));
|
|
91619
92007
|
result.push(
|
|
@@ -91855,7 +92243,8 @@ function renderTuiAppsHome(apps, options) {
|
|
|
91855
92243
|
title: app.name,
|
|
91856
92244
|
description: app.description,
|
|
91857
92245
|
footer: `${app.skills.length} skills${app.category ? ` \xB7 ${app.category.replaceAll("_", " ")}` : ""}`,
|
|
91858
|
-
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}` }
|
|
91859
92248
|
})), width, selected, options.selectedId !== void 0),
|
|
91860
92249
|
"",
|
|
91861
92250
|
centeredCarouselText(`${selected > 0 ? "\u2039" : " "} App ${selected + 1} of ${visible.length} ${selected < visible.length - 1 ? "\u203A" : " "}`, width),
|
|
@@ -91899,6 +92288,50 @@ function outlinedTabs(tabs, labels, selected, width) {
|
|
|
91899
92288
|
});
|
|
91900
92289
|
return ["", `\u256D${edges.join("\u252C")}\u256E`, `\u2502${row.join("\u2502")}\u2502`, `\u2570${edges.join("\u2534")}\u256F`, ""];
|
|
91901
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
|
+
}
|
|
91902
92335
|
function renderTuiAppIdentity(app, width) {
|
|
91903
92336
|
return identityCard([
|
|
91904
92337
|
`APP / ${app.id.toUpperCase()}`,
|
|
@@ -91907,24 +92340,25 @@ function renderTuiAppIdentity(app, width) {
|
|
|
91907
92340
|
`${app.skills.length} skills \xB7 ${app.focusModes.length} focus modes`
|
|
91908
92341
|
], width, "APP WORKSPACE");
|
|
91909
92342
|
}
|
|
91910
|
-
function renderTuiAppTabs(tab, width) {
|
|
92343
|
+
function renderTuiAppTabs(tab, width, options) {
|
|
91911
92344
|
const tabs = ["skills", "focus_modes", "settings_memories", "embeds", "workflows"];
|
|
91912
92345
|
const labels = { skills: "Skills", focus_modes: "Focus modes", settings_memories: "Memories", embeds: "Embeds", workflows: "Workflows" };
|
|
91913
|
-
return outlinedTabs(tabs, labels, tab, width);
|
|
92346
|
+
return options?.pointer ? outlinedPointerTabs(tabs, labels, tab, width) : outlinedTabs(tabs, labels, tab, width);
|
|
91914
92347
|
}
|
|
91915
92348
|
function renderTuiApp(app, options) {
|
|
91916
92349
|
const width = Math.max(1, options.width);
|
|
91917
|
-
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)];
|
|
91918
92351
|
if (options.tab === "skills") {
|
|
91919
92352
|
lines.push("Which app skill do you want to use?", "");
|
|
91920
92353
|
if (!app.skills.length) lines.push("No skills available.");
|
|
91921
92354
|
for (const skill of app.skills) {
|
|
91922
|
-
|
|
92355
|
+
const card2 = cardLines(
|
|
91923
92356
|
`${skill.id === options.selectedId ? "\u203A" : " "} ${skill.name}`,
|
|
91924
92357
|
skill.description,
|
|
91925
92358
|
skill.providers.length ? `via ${skill.providers.join(", ")}` : `${app.id}/${skill.id}`,
|
|
91926
92359
|
width
|
|
91927
|
-
)
|
|
92360
|
+
);
|
|
92361
|
+
lines.push(...options.pointer ? card2.map((line) => pointerLine(line, { kind: "command", command: `/app-skill ${app.id}/${skill.id}` })) : card2, "");
|
|
91928
92362
|
}
|
|
91929
92363
|
} else if (options.tab === "focus_modes" || options.tab === "settings_memories") {
|
|
91930
92364
|
const items = options.tab === "focus_modes" ? app.focusModes : app.settingsMemories;
|
|
@@ -91932,7 +92366,7 @@ function renderTuiApp(app, options) {
|
|
|
91932
92366
|
for (const item of items) {
|
|
91933
92367
|
lines.push(truncateCells(`${item.id === options.selectedId ? ">" : " "} ${item.name}`, width));
|
|
91934
92368
|
if (item.description) lines.push(...textLines(` ${oneLine2(item.description)}`, width));
|
|
91935
|
-
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));
|
|
91936
92370
|
}
|
|
91937
92371
|
lines.push("", "Manage private Memories in the web app.");
|
|
91938
92372
|
} else if (options.tab === "embeds") lines.push("Saved results load from the encrypted Apps history. Use Enter to inspect a result.");
|
|
@@ -91959,7 +92393,7 @@ async function loadTuiAppsSkill(client2, appId, skillId) {
|
|
|
91959
92393
|
}
|
|
91960
92394
|
function renderTuiAppsSkill(skill, options) {
|
|
91961
92395
|
const width = Math.max(1, options.width);
|
|
91962
|
-
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)];
|
|
91963
92397
|
if (options.tab === "overview") {
|
|
91964
92398
|
lines.push("Use this skill manually. Your mates can also use it in chats.", "");
|
|
91965
92399
|
for (const path2 of skillLeafPaths(skill.schema)) {
|
|
@@ -91967,7 +92401,7 @@ function renderTuiAppsSkill(skill, options) {
|
|
|
91967
92401
|
const value = getSkillPath(skill.defaults, path2);
|
|
91968
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));
|
|
91969
92403
|
}
|
|
91970
|
-
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."}`);
|
|
91971
92405
|
const fixed = skill.pricing?.fixed;
|
|
91972
92406
|
if (typeof fixed === "number") lines.push(`${fixed} credits per request`);
|
|
91973
92407
|
} else if (options.tab === "embeds") lines.push("Saved results are listed in the app's Embeds tab.");
|
|
@@ -91983,10 +92417,10 @@ function renderTuiAppsSkillIdentity(skill, width) {
|
|
|
91983
92417
|
skill.executionAvailable ? "Use skill \xB7 review input and confirm credits before running" : "Skill unavailable"
|
|
91984
92418
|
], width, "APP SKILL");
|
|
91985
92419
|
}
|
|
91986
|
-
function renderTuiAppsSkillTabs(tab, width) {
|
|
92420
|
+
function renderTuiAppsSkillTabs(tab, width, options) {
|
|
91987
92421
|
const tabs = ["overview", "embeds", "workflows"];
|
|
91988
92422
|
const labels = { overview: "Overview", embeds: "Embeds", workflows: "Workflows" };
|
|
91989
|
-
return outlinedTabs(tabs, labels, tab, width);
|
|
92423
|
+
return options?.pointer ? outlinedPointerTabs(tabs, labels, tab, width) : outlinedTabs(tabs, labels, tab, width);
|
|
91990
92424
|
}
|
|
91991
92425
|
function isRequired(schema, path2) {
|
|
91992
92426
|
const parts = path2.replaceAll("[]", "").split(".");
|
|
@@ -92206,8 +92640,11 @@ function renderTuiAppsWorkflows(page, options) {
|
|
|
92206
92640
|
const width = Math.max(1, options.width);
|
|
92207
92641
|
const lines = ["Related workflows", ""];
|
|
92208
92642
|
if (!page.items.length) lines.push("No workflows for this app.");
|
|
92209
|
-
for (const workflow of page.items)
|
|
92210
|
-
|
|
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`);
|
|
92211
92648
|
return lines;
|
|
92212
92649
|
}
|
|
92213
92650
|
async function decryptedRow(row, key) {
|
|
@@ -92232,8 +92669,11 @@ function renderTuiAppsResults(page, options) {
|
|
|
92232
92669
|
const width = Math.max(1, options.width);
|
|
92233
92670
|
const lines = ["Saved results", ""];
|
|
92234
92671
|
if (!page.items.length) lines.push("No saved results for this app.");
|
|
92235
|
-
for (const item of page.items)
|
|
92236
|
-
|
|
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`);
|
|
92237
92677
|
return lines;
|
|
92238
92678
|
}
|
|
92239
92679
|
function renderTuiAppsResult(result, width) {
|
|
@@ -92632,10 +93072,6 @@ function chatResultsViews(state) {
|
|
|
92632
93072
|
const messages = state.activeExample && (state.screen === "example" || state.embedOrigin?.screen === "example" || state.resultsViewOrigin?.screen === "example") ? state.activeExample.messages : state.messages;
|
|
92633
93073
|
return messages.flatMap((message) => messageResultsViews(message.content));
|
|
92634
93074
|
}
|
|
92635
|
-
function renderChatResultsView(state, descriptor, key, width, mode) {
|
|
92636
|
-
const data = buildTuiResultsViewData(descriptor, { ...exampleEmbedMap(state), ...state.chatEmbeds });
|
|
92637
|
-
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));
|
|
92638
|
-
}
|
|
92639
93075
|
|
|
92640
93076
|
// ../ui/src/components/embeds/fitness/fitnessEmbedData.ts
|
|
92641
93077
|
function normalizeFitnessStatus(value) {
|
|
@@ -92730,7 +93166,11 @@ function fitnessSkillName(skillId) {
|
|
|
92730
93166
|
function card(details, width, appName, skillName, alias, appId, emphasizeSecond = true) {
|
|
92731
93167
|
const cardWidth = Math.max(1, Math.min(62, Math.floor(width) || 1));
|
|
92732
93168
|
const shortcut = `/embed ${readable(alias)}`;
|
|
92733
|
-
|
|
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
|
+
}
|
|
92734
93174
|
const inner = cardWidth - 4;
|
|
92735
93175
|
const colors = appColors(appId);
|
|
92736
93176
|
const row = (value, color = DETAIL, background, bold = false) => {
|
|
@@ -92749,7 +93189,7 @@ function card(details, width, appName, skillName, alias, appId, emphasizeSecond
|
|
|
92749
93189
|
lines.push(row(truncateCells(`${appName} \xB7 ${skillName}`, inner), colors.foreground, colors.background, true));
|
|
92750
93190
|
lines.push(row(truncateCells(shortcut, inner), colors.foreground, colors.background));
|
|
92751
93191
|
lines.push({ text: `\u2570${"\u2500".repeat(cardWidth - 2)}\u256F`, color: BORDER });
|
|
92752
|
-
return lines;
|
|
93192
|
+
return action ? lines.map((line) => pointerLine(line, action)) : lines;
|
|
92753
93193
|
}
|
|
92754
93194
|
function recordingDetails(content, title, width, status) {
|
|
92755
93195
|
if (status === "error" || status === "cancelled") {
|
|
@@ -93194,6 +93634,7 @@ function rankExamples(examples, interests) {
|
|
|
93194
93634
|
}).sort((a, b) => b.score - a.score || a.index - b.index).map((entry) => entry.example);
|
|
93195
93635
|
}
|
|
93196
93636
|
function renderTuiFrame(state, width, height, options = {}) {
|
|
93637
|
+
beginPointerFrame(state, width, height);
|
|
93197
93638
|
if (state.startup || state.privacyOffer) return renderStartupFrame(state, width, height, options.colorMode ?? "none");
|
|
93198
93639
|
const bodyWidth = workspaceGeometry(state, width).contentWidth;
|
|
93199
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;
|
|
@@ -93234,7 +93675,23 @@ function renderStartupFrame(state, width, height, colorMode) {
|
|
|
93234
93675
|
return [...lines.slice(0, Math.max(0, height - footer.length)), ...footer.slice(-height)].join("\n");
|
|
93235
93676
|
}
|
|
93236
93677
|
function coloredHero(lines, rows2, gradient = PRIMARY_GRADIENT) {
|
|
93237
|
-
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
|
+
] };
|
|
93238
93695
|
}
|
|
93239
93696
|
function renderBody(state, width, height) {
|
|
93240
93697
|
return renderScreenBody(state, width, height);
|
|
@@ -93259,7 +93716,7 @@ function renderScreenBody(state, width, height) {
|
|
|
93259
93716
|
...homeHeader(state, width, height),
|
|
93260
93717
|
...renderTuiAppsHome(apps, { width, selectedIndex: state.selectedIndex, selectedId: state.focus === "content" ? apps[state.selectedIndex]?.id : void 0 }),
|
|
93261
93718
|
"",
|
|
93262
|
-
|
|
93719
|
+
appsHomeCommandLine(state.homeShowAll, width)
|
|
93263
93720
|
];
|
|
93264
93721
|
}
|
|
93265
93722
|
case "app": {
|
|
@@ -93268,10 +93725,10 @@ function renderScreenBody(state, width, height) {
|
|
|
93268
93725
|
const header2 = renderTuiAppIdentity(app, width), gradient = APP_GRADIENTS[app.id] ?? PRIMARY_GRADIENT;
|
|
93269
93726
|
if (state.appTab === "embeds" || state.appTab === "workflows") return [
|
|
93270
93727
|
...coloredHero(header2, header2.length, gradient),
|
|
93271
|
-
...renderTuiAppTabs(state.appTab, width),
|
|
93272
|
-
...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 })
|
|
93273
93730
|
];
|
|
93274
|
-
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);
|
|
93275
93732
|
}
|
|
93276
93733
|
case "app-skill": {
|
|
93277
93734
|
const skill = state.activeAppSkill;
|
|
@@ -93279,28 +93736,43 @@ function renderScreenBody(state, width, height) {
|
|
|
93279
93736
|
const header2 = renderTuiAppsSkillIdentity(skill, width), gradient = APP_GRADIENTS[skill.appId] ?? PRIMARY_GRADIENT;
|
|
93280
93737
|
if (state.appSkillTab === "embeds" || state.appSkillTab === "workflows") return [
|
|
93281
93738
|
...coloredHero(header2, header2.length, gradient),
|
|
93282
|
-
...renderTuiAppsSkillTabs(state.appSkillTab, width),
|
|
93283
|
-
...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 })
|
|
93284
93741
|
];
|
|
93285
|
-
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);
|
|
93286
93743
|
}
|
|
93287
93744
|
case "app-result":
|
|
93288
93745
|
return state.activeAppResult ? renderTuiAppsResult(state.activeAppResult, width) : ["Loading saved result\u2026"];
|
|
93289
93746
|
case "projects":
|
|
93290
93747
|
return [...homeHeader(state, width, height), ...renderProjectCarousel(filteredProjects(state.projects, state.filter), width, state.selectedIndex, state.focus === "content")];
|
|
93291
93748
|
case "project":
|
|
93292
|
-
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"];
|
|
93293
93750
|
case "status":
|
|
93294
93751
|
return renderStatus(state, width);
|
|
93295
93752
|
case "results-view": {
|
|
93296
93753
|
const key = state.activeResultsView ?? 1, descriptor = chatResultsViews(state)[key - 1];
|
|
93297
|
-
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."];
|
|
93298
93767
|
}
|
|
93299
93768
|
case "embed": {
|
|
93300
93769
|
const app = state.detailEmbed?.appId ?? "", gradient = APP_GRADIENTS[app] ?? PRIMARY_GRADIENT;
|
|
93301
93770
|
const title = state.detailTitle || "Embed";
|
|
93302
93771
|
const header2 = [title, state.detailEmbed ? `${state.detailEmbed.type?.replaceAll("-", " ") ?? "Saved item"} \xB7 ${state.detailEmbed.embedId.slice(0, 8)}` : "Saved embeds"];
|
|
93303
|
-
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 }));
|
|
93304
93776
|
}
|
|
93305
93777
|
case "workflows":
|
|
93306
93778
|
return [...homeHeader(state, width, height), ...renderWorkflowCarousel(state.workflows.filter((w) => w.title.toLowerCase().includes(state.filter.toLowerCase())), width, state.selectedIndex, state.focus === "content")];
|
|
@@ -93354,7 +93826,12 @@ function renderTasks(state, width) {
|
|
|
93354
93826
|
}
|
|
93355
93827
|
function renderTaskDetail2(state, width) {
|
|
93356
93828
|
if (!state.activeTask) return renderTasks(state, width);
|
|
93357
|
-
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
|
+
});
|
|
93358
93835
|
}
|
|
93359
93836
|
function renderWorkflows(state, width) {
|
|
93360
93837
|
const lines = ["Workflows", ""];
|
|
@@ -93520,7 +93997,10 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93520
93997
|
...card2.slice(-4)
|
|
93521
93998
|
]);
|
|
93522
93999
|
lines.push(...renderLineCarousel(cards, width, Math.max(0, selected), Boolean(state?.focus === "content" && selected >= 0), cardWidth));
|
|
93523
|
-
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
|
+
));
|
|
93524
94004
|
pending = [];
|
|
93525
94005
|
};
|
|
93526
94006
|
const text7 = (value) => {
|
|
@@ -93532,7 +94012,7 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93532
94012
|
lines.push(...renderQuestionCard(question ?? { key, messageIndex: 0, payload: block.payload }, width));
|
|
93533
94013
|
} else if (block.type === "results-view") {
|
|
93534
94014
|
const key = ++viewIndex;
|
|
93535
|
-
if (state) lines.push(...
|
|
94015
|
+
if (state) lines.push(...pointerResultsView(state, block, key, width));
|
|
93536
94016
|
else lines.push(...renderTuiResultsViewLines(buildTuiResultsViewData(block, embeds), { viewKey: key }).flatMap((row) => wrap(row, width)));
|
|
93537
94017
|
}
|
|
93538
94018
|
}
|
|
@@ -93549,6 +94029,23 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93549
94029
|
flush();
|
|
93550
94030
|
return lines;
|
|
93551
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
|
+
}
|
|
93552
94049
|
function renderEmbedReference(segment, width, embeds, state) {
|
|
93553
94050
|
const meta = segment.meta ?? {}, saved = embeds.get(segment.value);
|
|
93554
94051
|
const alias = state ? aliasForEmbed(state, segment.value) : segment.value;
|
|
@@ -95793,6 +96290,115 @@ async function prepareTuiMessage(client2, message) {
|
|
|
95793
96290
|
};
|
|
95794
96291
|
}
|
|
95795
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
|
+
|
|
95796
96402
|
// src/tui.ts
|
|
95797
96403
|
function defaultModeForStreams(input, output) {
|
|
95798
96404
|
return input.isTTY === true && output.isTTY === true ? "tui" : "quickstart";
|
|
@@ -95895,6 +96501,10 @@ async function runTui(client2, terminal = new TuiTerminal(), startupServices) {
|
|
|
95895
96501
|
return;
|
|
95896
96502
|
}
|
|
95897
96503
|
void (async () => {
|
|
96504
|
+
if (key.name === "mouseclick") {
|
|
96505
|
+
await handleKey({ chunk, key, state, client: client2, terminal, render, finish });
|
|
96506
|
+
return;
|
|
96507
|
+
}
|
|
95898
96508
|
if (await startup.handleKey(chunk, key)) return;
|
|
95899
96509
|
await handleKey({ chunk, key, state, client: client2, terminal, render, finish });
|
|
95900
96510
|
})().catch((error) => {
|
|
@@ -95933,6 +96543,12 @@ async function handleKey(params) {
|
|
|
95933
96543
|
command: (command) => handleCommand({ command, state, client: client2, terminal, render, finish }),
|
|
95934
96544
|
send: (message, options) => sendTuiMessage({ message, state, client: client2, render, questionAnswer: options?.questionAnswer })
|
|
95935
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
|
+
}
|
|
95936
96552
|
if (await handleWorkspaceKey(context, chunk, key)) return;
|
|
95937
96553
|
if (key.name === "escape") {
|
|
95938
96554
|
if (state.workflowEdit) {
|