openmates 0.27.0-alpha.34 → 0.27.0-alpha.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-V6UV747E.js → chunk-WJ4U3HDH.js} +815 -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}`);
|
|
@@ -62758,6 +62758,44 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
|
|
|
62758
62758
|
text: "Choose a location and dates."
|
|
62759
62759
|
}
|
|
62760
62760
|
},
|
|
62761
|
+
artifact_history: {
|
|
62762
|
+
title: {
|
|
62763
|
+
text: "Version history"
|
|
62764
|
+
},
|
|
62765
|
+
loaded: {
|
|
62766
|
+
text: "{count} versions loaded"
|
|
62767
|
+
},
|
|
62768
|
+
more: {
|
|
62769
|
+
text: "Show more"
|
|
62770
|
+
},
|
|
62771
|
+
current: {
|
|
62772
|
+
text: "Current version v{version}"
|
|
62773
|
+
},
|
|
62774
|
+
historical: {
|
|
62775
|
+
text: "Viewing historical version v{version}"
|
|
62776
|
+
},
|
|
62777
|
+
empty: {
|
|
62778
|
+
text: "No version history available yet."
|
|
62779
|
+
},
|
|
62780
|
+
readonly: {
|
|
62781
|
+
text: "Read-only history"
|
|
62782
|
+
},
|
|
62783
|
+
snapshot_required: {
|
|
62784
|
+
text: "This version is waiting for a readable snapshot. Retry when it becomes available."
|
|
62785
|
+
},
|
|
62786
|
+
access_changed: {
|
|
62787
|
+
text: "History access changed. Reopen this artifact and retry."
|
|
62788
|
+
},
|
|
62789
|
+
too_large: {
|
|
62790
|
+
text: "This version exceeds this device\u2019s history read limit."
|
|
62791
|
+
},
|
|
62792
|
+
failed: {
|
|
62793
|
+
text: "Version history could not be loaded. Retry."
|
|
62794
|
+
},
|
|
62795
|
+
select: {
|
|
62796
|
+
text: "Select a version to load its content."
|
|
62797
|
+
}
|
|
62798
|
+
},
|
|
62761
62799
|
audio: {
|
|
62762
62800
|
playback_progress: {
|
|
62763
62801
|
text: "Audio playback progress"
|
|
@@ -63064,6 +63102,9 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
|
|
|
63064
63102
|
text: "privacy & personal data"
|
|
63065
63103
|
}
|
|
63066
63104
|
},
|
|
63105
|
+
open_chat: {
|
|
63106
|
+
text: "Open chat"
|
|
63107
|
+
},
|
|
63067
63108
|
new_chat: {
|
|
63068
63109
|
text: "New chat"
|
|
63069
63110
|
},
|
|
@@ -64384,6 +64425,9 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
|
|
|
64384
64425
|
text: "Chat history"
|
|
64385
64426
|
},
|
|
64386
64427
|
search: {
|
|
64428
|
+
scope_all_teams: {
|
|
64429
|
+
text: "Personal and all Teams"
|
|
64430
|
+
},
|
|
64387
64431
|
placeholder: {
|
|
64388
64432
|
text: "Search chats, settings & apps..."
|
|
64389
64433
|
},
|
|
@@ -82659,7 +82703,7 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
82659
82703
|
text: "Measured at"
|
|
82660
82704
|
},
|
|
82661
82705
|
storage_pricing_policy: {
|
|
82662
|
-
text: "Personal storage includes 1 GiB free. Each started GiB above that costs 3 credits per week, billed on Sundays at 03:00 UTC. Uploads, saved chat history, large messages, older chat archives, outputs waiting to sync, and artifact history count toward storage. Team
|
|
82706
|
+
text: "Personal storage includes 1 GiB free. Each started GiB above that costs 3 credits per week, billed on Sundays at 03:00 UTC. Uploads, saved chat history, large messages, older chat archives, outputs waiting to sync, and artifact history count toward storage. Each Team has a separate 1 GiB allowance."
|
|
82663
82707
|
},
|
|
82664
82708
|
storage_logical_breakdown: {
|
|
82665
82709
|
text: "Chat and artifact storage"
|
|
@@ -82711,6 +82755,39 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
82711
82755
|
},
|
|
82712
82756
|
storage_notice_error: {
|
|
82713
82757
|
text: "Could not load the affected storage units. Please try again."
|
|
82758
|
+
},
|
|
82759
|
+
storage_outstanding: {
|
|
82760
|
+
text: "Outstanding credits"
|
|
82761
|
+
},
|
|
82762
|
+
storage_expiry_due: {
|
|
82763
|
+
text: "The removal deadline has been reached. The server checks payment and safe removal eligibility; listed data is not confirmed removed."
|
|
82764
|
+
},
|
|
82765
|
+
storage_expiry_disabled: {
|
|
82766
|
+
text: "Automatic removal is currently disabled."
|
|
82767
|
+
},
|
|
82768
|
+
storage_invoice_period: {
|
|
82769
|
+
text: "Invoice period begins"
|
|
82770
|
+
},
|
|
82771
|
+
storage_invoice_status: {
|
|
82772
|
+
text: "Invoice status"
|
|
82773
|
+
},
|
|
82774
|
+
storage_more_invoices: {
|
|
82775
|
+
text: "Additional invoices are not shown in this bounded summary."
|
|
82776
|
+
},
|
|
82777
|
+
storage_more_units: {
|
|
82778
|
+
text: "Additional affected units are available through the payment notice."
|
|
82779
|
+
},
|
|
82780
|
+
storage_invoice_paid: {
|
|
82781
|
+
text: "Paid"
|
|
82782
|
+
},
|
|
82783
|
+
storage_invoice_waived: {
|
|
82784
|
+
text: "Waived"
|
|
82785
|
+
},
|
|
82786
|
+
storage_invoice_unpaid: {
|
|
82787
|
+
text: "Unpaid"
|
|
82788
|
+
},
|
|
82789
|
+
storage_invoice_pending: {
|
|
82790
|
+
text: "Pending"
|
|
82714
82791
|
}
|
|
82715
82792
|
},
|
|
82716
82793
|
team_invitation: {
|
|
@@ -88189,6 +88266,7 @@ var TuiTerminal = class {
|
|
|
88189
88266
|
decoder = new StringDecoder("utf8");
|
|
88190
88267
|
pendingInput = "";
|
|
88191
88268
|
pendingMouse = "";
|
|
88269
|
+
discardingMouse = false;
|
|
88192
88270
|
paste = false;
|
|
88193
88271
|
pasteText = "";
|
|
88194
88272
|
inputTimer = null;
|
|
@@ -88254,6 +88332,7 @@ var TuiTerminal = class {
|
|
|
88254
88332
|
this.inputTimer = null;
|
|
88255
88333
|
this.pendingInput = "";
|
|
88256
88334
|
this.pendingMouse = "";
|
|
88335
|
+
this.discardingMouse = false;
|
|
88257
88336
|
this.paste = false;
|
|
88258
88337
|
this.pasteText = "";
|
|
88259
88338
|
this.output.write("\x1B[?25h");
|
|
@@ -88268,6 +88347,8 @@ var TuiTerminal = class {
|
|
|
88268
88347
|
} finally {
|
|
88269
88348
|
this.suspended = false;
|
|
88270
88349
|
if (this.active) {
|
|
88350
|
+
while (this.input.read() !== null) {
|
|
88351
|
+
}
|
|
88271
88352
|
this.input.on("data", this.rawInput);
|
|
88272
88353
|
if (this.resizeHandler) this.output.on("resize", this.resizeHandler);
|
|
88273
88354
|
if (typeof this.input.setRawMode === "function") {
|
|
@@ -88315,7 +88396,13 @@ var TuiTerminal = class {
|
|
|
88315
88396
|
this.pasteText = (this.pasteText + before).slice(0, 131072);
|
|
88316
88397
|
this.keyHandler?.(this.pasteText, { name: "paste" });
|
|
88317
88398
|
this.pasteText = "";
|
|
88318
|
-
} else
|
|
88399
|
+
} else {
|
|
88400
|
+
this.dispatchInput(before);
|
|
88401
|
+
if (this.mouseTimer) clearTimeout(this.mouseTimer);
|
|
88402
|
+
this.mouseTimer = null;
|
|
88403
|
+
this.pendingMouse = "";
|
|
88404
|
+
this.discardingMouse = false;
|
|
88405
|
+
}
|
|
88319
88406
|
this.paste = !this.paste;
|
|
88320
88407
|
this.pendingInput = this.pendingInput.slice(found + marker.length);
|
|
88321
88408
|
this.receiveInput("");
|
|
@@ -88333,46 +88420,71 @@ var TuiTerminal = class {
|
|
|
88333
88420
|
this.inputTimer = null;
|
|
88334
88421
|
}, 30);
|
|
88335
88422
|
}
|
|
88336
|
-
/**
|
|
88423
|
+
/** Keep SGR mouse bytes out of readline, including malformed and split reports. */
|
|
88337
88424
|
dispatchInput(text7) {
|
|
88338
88425
|
if (this.mouseTimer) clearTimeout(this.mouseTimer);
|
|
88339
88426
|
this.mouseTimer = null;
|
|
88340
88427
|
const input = this.pendingMouse + text7;
|
|
88341
88428
|
this.pendingMouse = "";
|
|
88342
88429
|
let offset = 0;
|
|
88430
|
+
if (this.discardingMouse) {
|
|
88431
|
+
const end = input.search(/[mM\x1b]/);
|
|
88432
|
+
if (end < 0) return;
|
|
88433
|
+
this.discardingMouse = false;
|
|
88434
|
+
offset = input[end] === "\x1B" ? end : end + 1;
|
|
88435
|
+
}
|
|
88343
88436
|
while (offset < input.length) {
|
|
88344
88437
|
const start = input.indexOf("\x1B[<", offset);
|
|
88345
88438
|
if (start < 0) {
|
|
88346
|
-
const
|
|
88347
|
-
|
|
88348
|
-
|
|
88349
|
-
|
|
88350
|
-
this.mouseTimer = setTimeout(() => {
|
|
88351
|
-
const pending = this.pendingMouse;
|
|
88352
|
-
this.pendingMouse = "";
|
|
88353
|
-
this.mouseTimer = null;
|
|
88354
|
-
if (pending === "\x1B") this.keyHandler?.("\x1B", { name: "escape", sequence: pending });
|
|
88355
|
-
else this.keyInput.write(pending);
|
|
88356
|
-
}, 500);
|
|
88357
|
-
}
|
|
88439
|
+
const rest = input.slice(offset);
|
|
88440
|
+
const prefix = rest.endsWith("\x1B[") ? "\x1B[" : rest.endsWith("\x1B") ? "\x1B" : "";
|
|
88441
|
+
this.keyInput.write(prefix ? rest.slice(0, -prefix.length) : rest);
|
|
88442
|
+
if (prefix) this.holdMousePrefix(prefix);
|
|
88358
88443
|
break;
|
|
88359
88444
|
}
|
|
88360
88445
|
this.keyInput.write(input.slice(offset, start));
|
|
88361
|
-
const
|
|
88362
|
-
|
|
88363
|
-
|
|
88364
|
-
|
|
88365
|
-
|
|
88446
|
+
const nextEscape = input.indexOf("\x1B", start + 3);
|
|
88447
|
+
const endM = input.indexOf("M", start + 3);
|
|
88448
|
+
const endm = input.indexOf("m", start + 3);
|
|
88449
|
+
const end = endM < 0 ? endm : endm < 0 ? endM : Math.min(endM, endm);
|
|
88450
|
+
if (end < 0 || nextEscape >= 0 && nextEscape < end) {
|
|
88451
|
+
if (nextEscape >= 0) {
|
|
88452
|
+
offset = nextEscape;
|
|
88453
|
+
continue;
|
|
88454
|
+
}
|
|
88455
|
+
if (input.length - start < 128) this.holdMousePrefix(input.slice(start));
|
|
88456
|
+
else this.discardingMouse = true;
|
|
88457
|
+
break;
|
|
88458
|
+
}
|
|
88459
|
+
const sequence = input.slice(start, end + 1);
|
|
88460
|
+
const report = /^\x1b\[<(\d+);(\d+);(\d+)([mM])$/.exec(sequence);
|
|
88461
|
+
if (report) {
|
|
88462
|
+
const button = Number(report[1]);
|
|
88463
|
+
const column = Number(report[2]);
|
|
88464
|
+
const row = Number(report[3]);
|
|
88465
|
+
if ([button, column, row].every(Number.isSafeInteger) && column > 0 && row > 0) {
|
|
88466
|
+
const mouse = { row: row - 1, column: column - 1 };
|
|
88467
|
+
if (report[4] === "M" && button === 0 && !this.selectingText) {
|
|
88468
|
+
this.keyHandler?.("", { name: "mouseclick", sequence, mouse });
|
|
88469
|
+
} else if (report[4] === "M" && button & 64 && ((button & 3) === 0 || (button & 3) === 1)) {
|
|
88470
|
+
this.keyHandler?.("", { name: (button & 3) === 0 ? "scrollup" : "scrolldown", sequence, mouse });
|
|
88471
|
+
}
|
|
88366
88472
|
}
|
|
88367
|
-
this.keyInput.write(rest.slice(0, 3));
|
|
88368
|
-
offset = start + 3;
|
|
88369
|
-
continue;
|
|
88370
88473
|
}
|
|
88371
|
-
|
|
88372
|
-
if (report[4] === "M" && button & 64 && ((button & 3) === 0 || (button & 3) === 1)) this.keyHandler?.("", { name: (button & 3) === 0 ? "scrollup" : "scrolldown", sequence: report[0] });
|
|
88373
|
-
offset = start + report[0].length;
|
|
88474
|
+
offset = end + 1;
|
|
88374
88475
|
}
|
|
88375
88476
|
}
|
|
88477
|
+
holdMousePrefix(prefix) {
|
|
88478
|
+
this.pendingMouse = prefix;
|
|
88479
|
+
this.mouseTimer = setTimeout(() => {
|
|
88480
|
+
const pending = this.pendingMouse;
|
|
88481
|
+
this.pendingMouse = "";
|
|
88482
|
+
this.mouseTimer = null;
|
|
88483
|
+
if (pending === "\x1B") this.keyHandler?.("\x1B", { name: "escape", sequence: pending });
|
|
88484
|
+
else if (pending === "\x1B[") this.keyInput.write(pending);
|
|
88485
|
+
else this.discardingMouse = true;
|
|
88486
|
+
}, 500);
|
|
88487
|
+
}
|
|
88376
88488
|
removeListeners() {
|
|
88377
88489
|
if (this.keyHandler) {
|
|
88378
88490
|
this.keyInput.off("keypress", this.keyHandler);
|
|
@@ -88385,6 +88497,7 @@ var TuiTerminal = class {
|
|
|
88385
88497
|
this.inputTimer = null;
|
|
88386
88498
|
this.pendingInput = "";
|
|
88387
88499
|
this.pendingMouse = "";
|
|
88500
|
+
this.discardingMouse = false;
|
|
88388
88501
|
this.paste = false;
|
|
88389
88502
|
this.pasteText = "";
|
|
88390
88503
|
if (this.resizeHandler) {
|
|
@@ -88704,7 +88817,7 @@ function renderCardCarousel(cards, width, selectedIndex, focused) {
|
|
|
88704
88817
|
`\u2502 ${padCells(card2.footer, inner)} \u2502`,
|
|
88705
88818
|
`\u2570${"\u2500".repeat(cardWidth - 2)}\u256F`
|
|
88706
88819
|
];
|
|
88707
|
-
return { rows: rows2, left: center + (index - selected) * stride, background: card2.background, active };
|
|
88820
|
+
return { rows: rows2, left: center + (index - selected) * stride, background: card2.background, active, action: card2.action };
|
|
88708
88821
|
});
|
|
88709
88822
|
return Array.from({ length: visible[0].rows.length }, (_, row) => {
|
|
88710
88823
|
const spans = [];
|
|
@@ -88713,7 +88826,7 @@ function renderCardCarousel(cards, width, selectedIndex, focused) {
|
|
|
88713
88826
|
const start = Math.max(0, card2.left), end = Math.min(width, card2.left + cardWidth);
|
|
88714
88827
|
if (end <= start) continue;
|
|
88715
88828
|
if (start > column) spans.push({ text: " ".repeat(start - column) });
|
|
88716
|
-
spans.push({ text: sliceCells(card2.rows[row], Math.max(0, -card2.left), end - start), background: card2.background, bold: card2.active });
|
|
88829
|
+
spans.push({ text: sliceCells(card2.rows[row], Math.max(0, -card2.left), end - start), background: card2.background, bold: card2.active, action: card2.action });
|
|
88717
88830
|
column = end;
|
|
88718
88831
|
}
|
|
88719
88832
|
if (column < width) spans.push({ text: " ".repeat(width - column) });
|
|
@@ -88743,13 +88856,13 @@ function renderLineCarousel(cards, width, selectedIndex, focused, cardWidth) {
|
|
|
88743
88856
|
const raw = lineText(line), text7 = raw.startsWith("\u2502 ") ? `\u2502 \u203A ${padCells(raw.slice(2, -2), Math.max(0, cardWidth - 6))} \u2502` : padCells("\u203A " + raw, cardWidth);
|
|
88744
88857
|
line = typeof line === "string" ? { text: text7, bold: true, color: "#ff553b" } : { ...line, text: text7, bold: true, spans: line.spans ? [{ ...line.spans[0], text: text7, bold: true }] : void 0 };
|
|
88745
88858
|
}
|
|
88746
|
-
const source = typeof line === "string" ? [{ text: line }] : line.spans ?? [{ text: line.text, color: line.color, background: line.background, bold: line.bold }];
|
|
88859
|
+
const source = typeof line === "string" ? [{ text: line }] : line.spans ?? [{ text: line.text, color: line.color, background: line.background, bold: line.bold, action: line.action }];
|
|
88747
88860
|
let offset = 0, used = 0;
|
|
88748
88861
|
const cropStart = Math.max(0, -card2.left), cropEnd = cropStart + end - start;
|
|
88749
88862
|
for (const part of source) {
|
|
88750
88863
|
const size = cells(part.text), from = Math.max(cropStart, offset), to = Math.min(cropEnd, offset + size);
|
|
88751
88864
|
if (to > from) {
|
|
88752
|
-
spans.push({ ...part, text: sliceCells(part.text, from - offset, to - from) });
|
|
88865
|
+
spans.push({ ...part, action: part.action ?? (typeof line === "string" ? void 0 : line.action), text: sliceCells(part.text, from - offset, to - from) });
|
|
88753
88866
|
used += to - from;
|
|
88754
88867
|
}
|
|
88755
88868
|
offset += size;
|
|
@@ -88762,6 +88875,27 @@ function renderLineCarousel(cards, width, selectedIndex, focused, cardWidth) {
|
|
|
88762
88875
|
});
|
|
88763
88876
|
}
|
|
88764
88877
|
|
|
88878
|
+
// src/tuiPointer.ts
|
|
88879
|
+
var frames = /* @__PURE__ */ new WeakMap();
|
|
88880
|
+
var overlay = (state) => state.questionEditor ?? state.form ?? (state.paletteOpen ? "palette" : null) ?? (state.sidebarOpen ? "sidebar" : null);
|
|
88881
|
+
function beginPointerFrame(state, width, height) {
|
|
88882
|
+
frames.set(state, { width, height, route: state.routeVersion, screen: state.screen, workspace: state.workspace, signedIn: state.signedIn, overlay: overlay(state), targets: [] });
|
|
88883
|
+
}
|
|
88884
|
+
function pointerLine(line, action) {
|
|
88885
|
+
return typeof line === "string" ? { text: line, action } : { ...line, action };
|
|
88886
|
+
}
|
|
88887
|
+
function addPointerTarget(state, column, row, width, action) {
|
|
88888
|
+
const frame = frames.get(state);
|
|
88889
|
+
if (!frame || row < 0 || row >= frame.height) return;
|
|
88890
|
+
const left = Math.max(0, column), right = Math.min(frame.width, column + width);
|
|
88891
|
+
if (right > left) frame.targets.push({ column: left, row, width: right - left, action });
|
|
88892
|
+
}
|
|
88893
|
+
function pointerTargetAt(state, column, row, width, height) {
|
|
88894
|
+
const frame = frames.get(state);
|
|
88895
|
+
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;
|
|
88896
|
+
return frame.targets.findLast((target) => target.row === row && column >= target.column && column < target.column + target.width)?.action ?? null;
|
|
88897
|
+
}
|
|
88898
|
+
|
|
88765
88899
|
// src/tuiProjectsWorkspace.ts
|
|
88766
88900
|
function contextFor(client2, project) {
|
|
88767
88901
|
const teamId = project ? project.teamId : client2.getActiveTeamId();
|
|
@@ -88987,7 +89121,8 @@ function renderProjectCarousel(projects, width, selectedIndex, focused) {
|
|
|
88987
89121
|
title: safeText(project.name),
|
|
88988
89122
|
description: safeText(project.description),
|
|
88989
89123
|
footer: `${count} ${count === 1 ? "item" : "items"}${project.pinned ? " \xB7 Pinned" : ""}${project.archived ? " \xB7 Archived" : ""}`,
|
|
88990
|
-
background: projectCardColor(project.color)
|
|
89124
|
+
background: projectCardColor(project.color),
|
|
89125
|
+
action: { kind: "command", command: `/project ${project.id}` }
|
|
88991
89126
|
};
|
|
88992
89127
|
});
|
|
88993
89128
|
return [
|
|
@@ -89035,14 +89170,37 @@ function renderProjectTabs(tab, width) {
|
|
|
89035
89170
|
const inset = Math.max(0, Math.floor((width - cells(text7)) / 2));
|
|
89036
89171
|
return ["", `${" ".repeat(inset)}${clip(text7, width)}`, ""];
|
|
89037
89172
|
}
|
|
89173
|
+
function renderProjectPointerTabs(tab, width) {
|
|
89174
|
+
const names = ["overview", "files", "tasks"];
|
|
89175
|
+
const labels = names.map((name, index) => `${name === tab ? "[" : " "}${name[0].toUpperCase() + name.slice(1)} \xB7 ${index + 1}${name === tab ? "]" : " "}`);
|
|
89176
|
+
const full = labels.join(" ");
|
|
89177
|
+
const inset = Math.max(0, Math.floor((width - cells(full)) / 2));
|
|
89178
|
+
const spans = [{ text: " ".repeat(inset) }];
|
|
89179
|
+
let remaining = Math.max(0, width - inset);
|
|
89180
|
+
labels.forEach((label3, index) => {
|
|
89181
|
+
if (index && remaining > 0) {
|
|
89182
|
+
const gap = Math.min(2, remaining);
|
|
89183
|
+
spans.push({ text: " ".repeat(gap) });
|
|
89184
|
+
remaining -= gap;
|
|
89185
|
+
}
|
|
89186
|
+
const text7 = truncateCells(label3, remaining);
|
|
89187
|
+
if (text7) spans.push({ text: text7, action: { kind: "key", name: "", chunk: String(index + 1), focus: "content" } });
|
|
89188
|
+
remaining -= cells(text7);
|
|
89189
|
+
});
|
|
89190
|
+
return ["", { text: spans.map((span) => span.text).join(""), spans }, ""];
|
|
89191
|
+
}
|
|
89038
89192
|
function renderProjectDetail(project, options) {
|
|
89039
89193
|
const width = options.width;
|
|
89040
|
-
const lines = [...renderProjectIdentity(project, { width }), ...
|
|
89194
|
+
const lines = [...renderProjectIdentity(project, { width }), ...renderProjectPointerTabs(options.tab, width)];
|
|
89041
89195
|
if (options.tab === "overview") {
|
|
89042
89196
|
lines.push(...renderProjectCard(false, project.readme ? project.readme.split("\n") : ["No project overview created yet."], width, "OVERVIEW"));
|
|
89043
89197
|
const links = project.items.filter((item) => item.type !== "embed");
|
|
89044
89198
|
if (links.length) {
|
|
89045
|
-
|
|
89199
|
+
const card3 = renderProjectCard(false, links.map((item) => `${item.type}: ${item.name}`), width, "LINKED WORK");
|
|
89200
|
+
lines.push("", ...card3.map((line, index) => {
|
|
89201
|
+
const item = links[index - 1];
|
|
89202
|
+
return item?.type === "chat" || item?.type === "workflow" ? pointerLine(line, { kind: "command", command: `/${item.type} ${item.targetId}` }) : line;
|
|
89203
|
+
}));
|
|
89046
89204
|
}
|
|
89047
89205
|
return lines;
|
|
89048
89206
|
}
|
|
@@ -89071,7 +89229,12 @@ function renderProjectDetail(project, options) {
|
|
|
89071
89229
|
const context = file.sourceId ? ` (${project.sources.find((source) => source.id === file.sourceId)?.name || "source"})` : "";
|
|
89072
89230
|
rows2.push(`${file.id === options.selectedFileId ? ">" : " "} [${icon}] ${file.name}${context}`);
|
|
89073
89231
|
}
|
|
89074
|
-
|
|
89232
|
+
const card2 = renderProjectCard(false, rows2, width, "FILES");
|
|
89233
|
+
const fileOffset = 1 + (rows2.length - visible.length);
|
|
89234
|
+
lines.push(...card2.map((line, index) => {
|
|
89235
|
+
const file = visible[index - fileOffset];
|
|
89236
|
+
return file ? pointerLine(line, { kind: "select", target: "content", index: index - fileOffset, id: file.id, activate: true }) : line;
|
|
89237
|
+
}));
|
|
89075
89238
|
return lines;
|
|
89076
89239
|
}
|
|
89077
89240
|
function buildProjectForm() {
|
|
@@ -89159,7 +89322,7 @@ function joinColumns(rows2, width, gap) {
|
|
|
89159
89322
|
if (index) spans.push({ text: gap });
|
|
89160
89323
|
if (typeof row === "string") spans.push({ text: padCells(row, width) });
|
|
89161
89324
|
else {
|
|
89162
|
-
spans.push(...row.spans ?? [{ text: row.text, background: row.background, bold: row.bold, color: row.color }]);
|
|
89325
|
+
spans.push(...(row.spans ?? [{ text: row.text, background: row.background, bold: row.bold, color: row.color }]).map((span) => ({ ...span, action: span.action ?? row.action })));
|
|
89163
89326
|
const padding = Math.max(0, width - cells(lineText(row)));
|
|
89164
89327
|
if (padding) spans.push({ text: " ".repeat(padding) });
|
|
89165
89328
|
}
|
|
@@ -89201,24 +89364,40 @@ function renderTaskBoard2(tasks, options) {
|
|
|
89201
89364
|
const shown = columns.slice(firstColumn, firstColumn + columnCount);
|
|
89202
89365
|
const colWidth = Math.floor((width - gap.length * (columnCount - 1)) / columnCount);
|
|
89203
89366
|
lines.push(truncateCells(`\u2190/\u2192 columns \xB7 ${STATUS_LABELS2[focused]} ${focusedIndex + 1}/5`, width));
|
|
89204
|
-
lines.push(joinColumns(shown.map(({ status, tasks: tasks2 }) =>
|
|
89367
|
+
lines.push(joinColumns(shown.map(({ status, tasks: tasks2 }) => pointerLine(
|
|
89368
|
+
columnHeader(status, tasks2.length, colWidth),
|
|
89369
|
+
{ kind: "select", target: "task", column: TASK_STATUSES.indexOf(status), index: 0 }
|
|
89370
|
+
)), colWidth, gap));
|
|
89205
89371
|
lines.push(shown.map(() => "\u2500".repeat(colWidth)).join(gap));
|
|
89206
|
-
const stacks = shown.map(({ tasks: group }) => group.length ? group.flatMap((task) => [...taskCard(
|
|
89372
|
+
const stacks = shown.map(({ tasks: group }) => group.length ? group.flatMap((task, index) => [...taskCard(
|
|
89373
|
+
task,
|
|
89374
|
+
colWidth,
|
|
89375
|
+
task.taskId === options.selectedTaskId,
|
|
89376
|
+
{ kind: "select", target: "task", column: TASK_STATUSES.indexOf(task.status), index, id: task.taskId, activate: true }
|
|
89377
|
+
), ""]) : [padCells("No tasks here.", colWidth)]);
|
|
89207
89378
|
for (let row = 0; row < Math.max(...stacks.map((stack) => stack.length)); row++) {
|
|
89208
89379
|
lines.push(joinColumns(stacks.map((stack) => stack[row] ?? ""), colWidth, gap));
|
|
89209
89380
|
}
|
|
89210
89381
|
} else {
|
|
89211
89382
|
const group = columns[focusedIndex]?.tasks ?? [];
|
|
89212
89383
|
lines.push(truncateCells(`\u2190/\u2192 columns \xB7 ${STATUS_LABELS2[focused]} ${focusedIndex + 1}/5`, width));
|
|
89213
|
-
lines.push(
|
|
89384
|
+
lines.push(pointerLine(
|
|
89385
|
+
columnHeader(focused, group.length, Math.min(width, 52)),
|
|
89386
|
+
{ kind: "select", target: "task", column: focusedIndex, index: 0 }
|
|
89387
|
+
), "\u2500".repeat(Math.min(width, 52)));
|
|
89214
89388
|
if (!group.length) lines.push(" No tasks here.");
|
|
89215
|
-
for (const task of group) {
|
|
89216
|
-
lines.push(...taskCard(
|
|
89389
|
+
for (const [index, task] of group.entries()) {
|
|
89390
|
+
lines.push(...taskCard(
|
|
89391
|
+
task,
|
|
89392
|
+
Math.min(width, 52),
|
|
89393
|
+
task.taskId === options.selectedTaskId,
|
|
89394
|
+
{ kind: "select", target: "task", column: focusedIndex, index, id: task.taskId, activate: true }
|
|
89395
|
+
));
|
|
89217
89396
|
}
|
|
89218
89397
|
}
|
|
89219
89398
|
return lines;
|
|
89220
89399
|
}
|
|
89221
|
-
function taskCard(task, width, selected) {
|
|
89400
|
+
function taskCard(task, width, selected, action) {
|
|
89222
89401
|
const inside = Math.max(8, width - 2);
|
|
89223
89402
|
const edge = (selected ? "\u2550" : "\u2500").repeat(inside);
|
|
89224
89403
|
const row = (value, title = false) => {
|
|
@@ -89243,7 +89422,7 @@ function taskCard(task, width, selected) {
|
|
|
89243
89422
|
...metadata.map((item) => row(` ${item}`)),
|
|
89244
89423
|
...task.queueState && task.queueState !== "none" ? [row(`Q ${task.queueState}`)] : [],
|
|
89245
89424
|
border(false)
|
|
89246
|
-
];
|
|
89425
|
+
].map((line) => pointerLine(line, action));
|
|
89247
89426
|
}
|
|
89248
89427
|
async function loadTaskContext(client2, taskId) {
|
|
89249
89428
|
const record10 = await client2.getUserTask(taskId);
|
|
@@ -89268,7 +89447,16 @@ function renderTaskDetails(task, options) {
|
|
|
89268
89447
|
if (task.labels.length) lines.push(truncateCells(`Labels: ${task.labels.join(", ")}`, width));
|
|
89269
89448
|
if (task.dueAt) lines.push(`Due: ${new Date(task.dueAt * 1e3).toISOString().slice(0, 16)} UTC`);
|
|
89270
89449
|
if (task.blockedReason) lines.push(truncateCells(`Blocked: ${task.blockedReason}`, width));
|
|
89271
|
-
|
|
89450
|
+
const firstActions = "c create e edit m status p assignee r reorder";
|
|
89451
|
+
const secondActions = "s start d done b block u unblock k skip x delete";
|
|
89452
|
+
lines.push(
|
|
89453
|
+
"",
|
|
89454
|
+
"Actions",
|
|
89455
|
+
...options.pointer ? pointerTaskShortcuts(firstActions, width) : wrapCells(firstActions, width),
|
|
89456
|
+
...options.pointer ? pointerTaskShortcuts(secondActions, width) : wrapCells(secondActions, width),
|
|
89457
|
+
"",
|
|
89458
|
+
"Description"
|
|
89459
|
+
);
|
|
89272
89460
|
lines.push(...wrapCells(task.description || "No description.", width));
|
|
89273
89461
|
if (options.dependencies) {
|
|
89274
89462
|
lines.push("", `Dependencies (${options.dependencies.dependencies.length})`);
|
|
@@ -89282,6 +89470,27 @@ function renderTaskDetails(task, options) {
|
|
|
89282
89470
|
}
|
|
89283
89471
|
return lines;
|
|
89284
89472
|
}
|
|
89473
|
+
function pointerTaskShortcuts(source, width) {
|
|
89474
|
+
const ranges = [...source.matchAll(/(?:^| {2})([cemprsdbukx]) ([a-z]+)/g)].map((match) => {
|
|
89475
|
+
const index = match.index + (match[0].startsWith(" ") ? 2 : 0);
|
|
89476
|
+
return { start: index, end: index + match[1].length + 1 + match[2].length, chunk: match[1] };
|
|
89477
|
+
});
|
|
89478
|
+
let rowStart = 0;
|
|
89479
|
+
return wrapCells(source, width).map((row) => {
|
|
89480
|
+
const rowEnd = rowStart + row.length, spans = [];
|
|
89481
|
+
let cursor = rowStart;
|
|
89482
|
+
for (const range of ranges) {
|
|
89483
|
+
const from = Math.max(rowStart, range.start), to = Math.min(rowEnd, range.end);
|
|
89484
|
+
if (to <= from) continue;
|
|
89485
|
+
if (from > cursor) spans.push({ text: source.slice(cursor, from) });
|
|
89486
|
+
spans.push({ text: source.slice(from, to), action: { kind: "key", name: "", chunk: range.chunk, focus: "content" } });
|
|
89487
|
+
cursor = to;
|
|
89488
|
+
}
|
|
89489
|
+
if (cursor < rowEnd) spans.push({ text: source.slice(cursor, rowEnd) });
|
|
89490
|
+
rowStart = rowEnd;
|
|
89491
|
+
return { text: row, spans };
|
|
89492
|
+
});
|
|
89493
|
+
}
|
|
89285
89494
|
function relationLabel(reference) {
|
|
89286
89495
|
const match = /^(task|plan):(.+)$/.exec(reference);
|
|
89287
89496
|
if (!match) return truncateCells(reference, 32);
|
|
@@ -89441,7 +89650,8 @@ function renderWorkflowCarousel(workflows, width, selectedIndex, focused) {
|
|
|
89441
89650
|
truncateCells(clean(workflow.trigger_summary || "Manual"), 32)
|
|
89442
89651
|
].filter(Boolean).join("\n"),
|
|
89443
89652
|
footer: `${workflow.enabled ? "Enabled" : "Paused"}${workflow.last_run_status ? ` \xB7 Last: ${clean(workflow.last_run_status)}` : ""}`,
|
|
89444
|
-
background: PRIMARY_GRADIENT.start
|
|
89653
|
+
background: PRIMARY_GRADIENT.start,
|
|
89654
|
+
action: { kind: "command", command: `/workflow ${workflow.id}` }
|
|
89445
89655
|
}));
|
|
89446
89656
|
return [
|
|
89447
89657
|
...renderCardCarousel(cards, width, selected, focused),
|
|
@@ -89466,7 +89676,13 @@ function renderWorkflowIdentity(workflow, options) {
|
|
|
89466
89676
|
];
|
|
89467
89677
|
return rows2.map((row, index) => {
|
|
89468
89678
|
const value = truncateCells(terminalText(row), width);
|
|
89469
|
-
return {
|
|
89679
|
+
return {
|
|
89680
|
+
text: padCells(centered(value, width), width),
|
|
89681
|
+
background: workflowIdentityColor(workflow),
|
|
89682
|
+
color: "#ffffff",
|
|
89683
|
+
bold: index === 0 || index === 2,
|
|
89684
|
+
...index === 3 ? { action: { kind: "command", command: "/workflow-toggle" } } : {}
|
|
89685
|
+
};
|
|
89470
89686
|
});
|
|
89471
89687
|
}
|
|
89472
89688
|
var NODE_FIELDS = {
|
|
@@ -89524,6 +89740,22 @@ function workflowTabs(width, tab) {
|
|
|
89524
89740
|
const inset = " ".repeat(Math.floor((width - tabWidth * 2 - 2) / 2));
|
|
89525
89741
|
return left.map((line, index) => `${inset}${line} ${right[index]}`);
|
|
89526
89742
|
}
|
|
89743
|
+
function workflowPointerTabs(width, tab) {
|
|
89744
|
+
const source = workflowTabs(width, tab);
|
|
89745
|
+
const key = (chunk) => ({ kind: "key", name: "", chunk, focus: "content" });
|
|
89746
|
+
if (width < 36) return source.map((line, index) => pointerLine(line, key(index < 3 ? "g" : "r")));
|
|
89747
|
+
const tabWidth = 18;
|
|
89748
|
+
const inset = Math.max(0, Math.floor((width - tabWidth * 2 - 2) / 2));
|
|
89749
|
+
return source.map((line) => {
|
|
89750
|
+
const spans = [
|
|
89751
|
+
{ text: line.slice(0, inset) },
|
|
89752
|
+
{ text: line.slice(inset, inset + tabWidth), action: key("g") },
|
|
89753
|
+
{ text: line.slice(inset + tabWidth, inset + tabWidth + 2) },
|
|
89754
|
+
{ text: line.slice(inset + tabWidth + 2), action: key("r") }
|
|
89755
|
+
];
|
|
89756
|
+
return { text: line, spans };
|
|
89757
|
+
});
|
|
89758
|
+
}
|
|
89527
89759
|
function orderedWorkflowNodes(graph) {
|
|
89528
89760
|
const byId = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
89529
89761
|
const incoming = new Map(graph.nodes.map((node) => [node.id, 0]));
|
|
@@ -89614,7 +89846,7 @@ function graphCanvas(graph, options, run, width) {
|
|
|
89614
89846
|
const selected = nodes[Math.max(0, Math.min(nodes.length - 1, options.selectedNodeIndex ?? 0))]?.id;
|
|
89615
89847
|
const innerWidth = Math.max(8, width - 4);
|
|
89616
89848
|
const rows2 = [];
|
|
89617
|
-
for (const node of nodes) {
|
|
89849
|
+
for (const [nodeIndex, node] of nodes.entries()) {
|
|
89618
89850
|
const nodeRun = nodeRuns.get(node.id);
|
|
89619
89851
|
const typeLabel = nodeKind(node);
|
|
89620
89852
|
const badge = graph.trigger_node_id === node.id ? " \xB7 trigger" : "";
|
|
@@ -89633,10 +89865,23 @@ function graphCanvas(graph, options, run, width) {
|
|
|
89633
89865
|
...expanded ? expandedStepRows(node, nodeRun, options.tab === "runs", options.edit) : []
|
|
89634
89866
|
];
|
|
89635
89867
|
const color = workflowNodeColor(node);
|
|
89868
|
+
const action = { kind: "select", target: "workflow-node", index: nodeIndex, id: node.id, activate: true };
|
|
89636
89869
|
rows2.push(...panel(expanded ? "Step details" : "Step", cardRows, cardWidth, expanded ? "left" : "center").map((line) => {
|
|
89637
89870
|
const inset = " ".repeat(cardInset);
|
|
89638
89871
|
const text7 = `${inset}${line}`;
|
|
89639
|
-
|
|
89872
|
+
if (expanded && options.tab === "graph" && line.includes("e Edit title \xB7 E Edit config")) {
|
|
89873
|
+
const titleAt = line.indexOf("e Edit title"), configAt = line.indexOf("E Edit config");
|
|
89874
|
+
const spans = [
|
|
89875
|
+
{ text: inset },
|
|
89876
|
+
{ text: line.slice(0, titleAt), background: color, action },
|
|
89877
|
+
{ text: line.slice(titleAt, configAt - 3), background: color, action: { kind: "key", name: "", chunk: "e", focus: "content" } },
|
|
89878
|
+
{ text: line.slice(configAt - 3, configAt), background: color, action },
|
|
89879
|
+
{ text: line.slice(configAt, configAt + 13), background: color, action: { kind: "key", name: "", chunk: "E", focus: "content" } },
|
|
89880
|
+
{ text: line.slice(configAt + 13), background: color, action }
|
|
89881
|
+
];
|
|
89882
|
+
return { text: text7, spans };
|
|
89883
|
+
}
|
|
89884
|
+
return { text: text7, spans: [{ text: inset }, { text: line, background: color, bold: line.includes(typeLabel), action }] };
|
|
89640
89885
|
}));
|
|
89641
89886
|
const outgoing = (graph.edges ?? []).filter((edge) => edge.from === node.id);
|
|
89642
89887
|
const connector = " ".repeat(cardInset + 2);
|
|
@@ -89658,7 +89903,7 @@ function renderWorkflowWorkspace(workflow, options) {
|
|
|
89658
89903
|
const width = Math.max(1, options.width);
|
|
89659
89904
|
const lines = [
|
|
89660
89905
|
...renderWorkflowIdentity(workflow, { width, run: options.tab === "runs" ? run ?? void 0 : void 0 }),
|
|
89661
|
-
...
|
|
89906
|
+
...workflowPointerTabs(width, options.tab),
|
|
89662
89907
|
""
|
|
89663
89908
|
];
|
|
89664
89909
|
const upcoming = workflow.enabled && workflow.next_run_at && workflow.next_run_at > Date.now() / 1e3 ? workflow.next_run_at : null;
|
|
@@ -89669,7 +89914,10 @@ function renderWorkflowWorkspace(workflow, options) {
|
|
|
89669
89914
|
if (!runs.length && !upcoming) lines.push("No runs yet.");
|
|
89670
89915
|
for (const [index, item] of runs.entries()) {
|
|
89671
89916
|
const marker = index === (options.selectedRunIndex ?? 0) ? ">" : " ";
|
|
89672
|
-
lines.push(
|
|
89917
|
+
lines.push(pointerLine(
|
|
89918
|
+
`${marker} ${item.id} \xB7 ${item.status}${item.started_at ? ` \xB7 ${new Date(item.started_at * 1e3).toISOString()}` : ""}`,
|
|
89919
|
+
{ kind: "select", target: "workflow-run", index, id: item.id, activate: true }
|
|
89920
|
+
));
|
|
89673
89921
|
}
|
|
89674
89922
|
if (run) {
|
|
89675
89923
|
lines.push("", `Selected run ${run.id} \xB7 ${run.status} \xB7 version ${run.version_id}`);
|
|
@@ -89909,8 +90157,8 @@ function append(out, value, style = {}) {
|
|
|
89909
90157
|
const text7 = terminalText(value);
|
|
89910
90158
|
if (!text7) return;
|
|
89911
90159
|
const last = out.at(-1);
|
|
89912
|
-
if (last && last.bold === style.bold && last.color === style.color && last.background === style.background) last.text += text7;
|
|
89913
|
-
else out.push({ text: text7, bold: style.bold, color: style.color, background: style.background });
|
|
90160
|
+
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;
|
|
90161
|
+
else out.push({ text: text7, bold: style.bold, color: style.color, background: style.background, action: style.action });
|
|
89914
90162
|
}
|
|
89915
90163
|
function closing(source, from, delimiter) {
|
|
89916
90164
|
for (let i = from; i <= source.length - delimiter.length; i++) {
|
|
@@ -89982,8 +90230,9 @@ function inline(source, options, base = {}) {
|
|
|
89982
90230
|
} else if (wiki && safeReference(wiki)) action = `/wiki ${wiki}`;
|
|
89983
90231
|
else if (/^https?:\/\/\S+$/i.test(target)) action = target;
|
|
89984
90232
|
if (action) {
|
|
89985
|
-
|
|
89986
|
-
|
|
90233
|
+
const pointerAction = embed || wiki ? { kind: "command", command: action } : void 0;
|
|
90234
|
+
append(out, label3 || (embed ? "Embed" : target), { ...base, color: LINK, action: pointerAction });
|
|
90235
|
+
if (action !== label3) append(out, ` (${action})`, { color: CODE, action: pointerAction });
|
|
89987
90236
|
} else append(out, source.slice(i, link2.end), base);
|
|
89988
90237
|
i = link2.end;
|
|
89989
90238
|
continue;
|
|
@@ -90151,23 +90400,81 @@ function renderQuestionCard(question, width) {
|
|
|
90151
90400
|
const marker = q.type === "choice" ? control.selected ? "[\u2713]" : q.multiple ? "[ ]" : "( )" : "";
|
|
90152
90401
|
rows2.push(...wrapCells(`${marker} ${control.label}${control.value !== void 0 ? ` \xB7 ${control.value || "(empty)"}` : ""}`.trim(), width));
|
|
90153
90402
|
}
|
|
90154
|
-
rows2.push(...wrapCells(answer ? "Answered" : `/question ${question.key} \xB7 Answer${q.multiple ? " \xB7 Choose several" : ""} \xB7 Ctrl+Q latest question`, width).map((text7) => ({
|
|
90403
|
+
rows2.push(...wrapCells(answer ? "Answered" : `/question ${question.key} \xB7 Answer${q.multiple ? " \xB7 Choose several" : ""} \xB7 Ctrl+Q latest question`, width).map((text7) => ({
|
|
90404
|
+
text: text7,
|
|
90405
|
+
color: answer ? "#808080" : "#85c9e8",
|
|
90406
|
+
...answer ? {} : { action: { kind: "question", index: question.key, activate: true } }
|
|
90407
|
+
})), "");
|
|
90155
90408
|
return rows2;
|
|
90156
90409
|
}
|
|
90157
90410
|
function renderQuestionEditor(editor, width) {
|
|
90158
90411
|
const q = editor.question.payload, items = controls(editor), rows2 = [];
|
|
90159
|
-
const add = (text7, color = "#e6e6e6", bold = false) => rows2.push(...wrapCells(text7, width).map((text8) => ({ text: text8, color, bold })));
|
|
90412
|
+
const add = (text7, color = "#e6e6e6", bold = false, action) => rows2.push(...wrapCells(text7, width).map((text8) => ({ text: text8, color, bold, action })));
|
|
90160
90413
|
add(`Answer question ${editor.question.key}`, "#80caff", true);
|
|
90161
90414
|
add(q.question ?? (q.type === "input" ? "Tell us more" : "Review these options"), "#ffffff", true);
|
|
90162
90415
|
rows2.push("");
|
|
90163
90416
|
items.forEach((item, index) => {
|
|
90164
90417
|
const focused = index === editor.fieldIndex, marker = q.type === "choice" ? item.selected ? "[\u2713]" : q.multiple ? "[ ]" : "( )" : "";
|
|
90165
|
-
|
|
90166
|
-
|
|
90418
|
+
const action = { kind: "question", index, activate: q.type === "choice" };
|
|
90419
|
+
add(`${focused ? "\u203A" : " "} ${marker} ${item.label}`, focused ? "#32ade6" : "#e6e6e6", focused, action);
|
|
90420
|
+
if (item.value !== void 0) add(` ${item.value || "(empty)"}${focused && item.text && !editor.busy ? "_" : ""}`, "#e6e6e6", false, action);
|
|
90421
|
+
if (q.type === "rating" && index === 0) {
|
|
90422
|
+
const max = q.max_stars ?? q.max ?? q.scale ?? 5;
|
|
90423
|
+
add(" " + Array.from({ length: Math.min(max, 20) }, (_, star) => `[${star + 1}]`).join(" "), "#85c9e8");
|
|
90424
|
+
const line = rows2.at(-1);
|
|
90425
|
+
if (typeof line !== "string" && line) {
|
|
90426
|
+
const spans = [];
|
|
90427
|
+
let text7 = " ";
|
|
90428
|
+
spans.push({ text: text7 });
|
|
90429
|
+
for (let star = 1; star <= Math.min(max, 20); star++) {
|
|
90430
|
+
text7 = `[${star}]${star < Math.min(max, 20) ? " " : ""}`;
|
|
90431
|
+
spans.push({ text: text7, action: { kind: "question", index, value: star } });
|
|
90432
|
+
}
|
|
90433
|
+
if (spans.map((span) => span.text).join("") === line.text) line.spans = spans;
|
|
90434
|
+
}
|
|
90435
|
+
}
|
|
90436
|
+
if (q.type === "slider") {
|
|
90437
|
+
const min = q.min, max = q.max, step = q.step ?? 1, current = Number(editor.answer.value);
|
|
90438
|
+
const values = [
|
|
90439
|
+
min,
|
|
90440
|
+
Math.max(min, Math.min(max, min + Math.round((current - min) / step - 1) * step)),
|
|
90441
|
+
current,
|
|
90442
|
+
Math.max(min, Math.min(max, min + Math.round((current - min) / step + 1) * step)),
|
|
90443
|
+
max
|
|
90444
|
+
].filter((value, position, all) => position === all.indexOf(value));
|
|
90445
|
+
const text7 = " " + values.map((value) => `[${value}]`).join(" ");
|
|
90446
|
+
if (wrapCells(text7, width).length === 1) {
|
|
90447
|
+
const spans = [{ text: " " }, ...values.map((value, position) => ({
|
|
90448
|
+
text: `[${value}]${position < values.length - 1 ? " " : ""}`,
|
|
90449
|
+
action: { kind: "question", index, value }
|
|
90450
|
+
}))];
|
|
90451
|
+
rows2.push({ text: text7, spans });
|
|
90452
|
+
}
|
|
90453
|
+
}
|
|
90454
|
+
if (q.type === "swipe") {
|
|
90455
|
+
const text7 = " [\u2190 dislike] [like \u2192]";
|
|
90456
|
+
if (wrapCells(text7, width).length === 1) rows2.push({ text: text7, spans: [
|
|
90457
|
+
{ text: " " },
|
|
90458
|
+
{ text: "[\u2190 dislike]", action: { kind: "question", index, value: "dislike" } },
|
|
90459
|
+
{ text: " " },
|
|
90460
|
+
{ text: "[like \u2192]", action: { kind: "question", index, value: "like" } }
|
|
90461
|
+
] });
|
|
90462
|
+
}
|
|
90167
90463
|
});
|
|
90168
90464
|
rows2.push("");
|
|
90169
|
-
add(
|
|
90170
|
-
|
|
90465
|
+
add(
|
|
90466
|
+
`${editor.fieldIndex === items.length ? "\u203A" : " "} [Send answer]`,
|
|
90467
|
+
"#32ade6",
|
|
90468
|
+
true,
|
|
90469
|
+
{ kind: "question", index: items.length, activate: true }
|
|
90470
|
+
);
|
|
90471
|
+
add(
|
|
90472
|
+
`${editor.fieldIndex === items.length + 1 ? "\u203A" : " "} [Clear]`,
|
|
90473
|
+
"#a0a0a0",
|
|
90474
|
+
false,
|
|
90475
|
+
{ kind: "question", index: items.length + 1, activate: true }
|
|
90476
|
+
);
|
|
90477
|
+
add(" [Cancel]", "#a0a0a0", false, { kind: "question", index: items.length + 2, activate: true });
|
|
90171
90478
|
if (editor.error) add(editor.error, "#ff6b6b", true);
|
|
90172
90479
|
add(editor.busy ? "Sending\u2026" : "Tab / \u2191\u2193 move \xB7 Space choose \xB7 \u2190/\u2192 adjust \xB7 Ctrl+S send \xB7 Ctrl+U clear \xB7 Esc cancel", "#a0a0a0");
|
|
90173
90480
|
return rows2;
|
|
@@ -90285,6 +90592,60 @@ async function handleQuestionKey(context, chunk, key) {
|
|
|
90285
90592
|
render();
|
|
90286
90593
|
return true;
|
|
90287
90594
|
}
|
|
90595
|
+
async function handleQuestionPointer(context, action) {
|
|
90596
|
+
const { state, render } = context, editor = state.questionEditor;
|
|
90597
|
+
if (!editor) {
|
|
90598
|
+
if (!action.activate || !["chat", "example"].includes(state.screen)) return;
|
|
90599
|
+
const key = typeof action.index === "number" ? action.index : Number(action.index);
|
|
90600
|
+
if (!Number.isInteger(key) || key < 1) return;
|
|
90601
|
+
try {
|
|
90602
|
+
openQuestion(state, key);
|
|
90603
|
+
} catch (error) {
|
|
90604
|
+
state.status = String(error.message);
|
|
90605
|
+
}
|
|
90606
|
+
render();
|
|
90607
|
+
return;
|
|
90608
|
+
}
|
|
90609
|
+
if (editor.busy) return;
|
|
90610
|
+
const q = editor.question.payload, items = controls(editor), index = typeof action.index === "number" ? action.index : Number(action.index);
|
|
90611
|
+
if (!Number.isInteger(index) || index < 0 || index > items.length + 2) return;
|
|
90612
|
+
if (index >= items.length && !action.activate) return;
|
|
90613
|
+
if (index === items.length + 2) {
|
|
90614
|
+
await handleQuestionKey(context, "", { name: "escape" });
|
|
90615
|
+
return;
|
|
90616
|
+
}
|
|
90617
|
+
if (index === items.length + 1) {
|
|
90618
|
+
await handleQuestionKey(context, "", { name: "u", ctrl: true });
|
|
90619
|
+
return;
|
|
90620
|
+
}
|
|
90621
|
+
if (index === items.length) {
|
|
90622
|
+
await handleQuestionKey(context, "", { name: "s", ctrl: true });
|
|
90623
|
+
return;
|
|
90624
|
+
}
|
|
90625
|
+
editor.fieldIndex = index;
|
|
90626
|
+
if (q.type === "choice" && action.activate) {
|
|
90627
|
+
await handleQuestionKey(context, "", { name: "space" });
|
|
90628
|
+
return;
|
|
90629
|
+
}
|
|
90630
|
+
if (q.type === "slider" && typeof action.value === "number") {
|
|
90631
|
+
const min = q.min, max = q.max, step = q.step ?? 1, value = action.value;
|
|
90632
|
+
if (Number.isFinite(value) && value >= min && value <= max && Math.abs((value - min) / step - Math.round((value - min) / step)) < 1e-7) {
|
|
90633
|
+
editor.answer.value = value;
|
|
90634
|
+
editor.touched = true;
|
|
90635
|
+
editor.error = void 0;
|
|
90636
|
+
}
|
|
90637
|
+
} else if (q.type === "rating" && typeof action.value === "number") {
|
|
90638
|
+
const max = q.max_stars ?? q.max ?? q.scale ?? 5;
|
|
90639
|
+
if (Number.isInteger(action.value) && action.value >= 1 && action.value <= max) {
|
|
90640
|
+
editor.answer.rating = action.value;
|
|
90641
|
+
editor.error = void 0;
|
|
90642
|
+
}
|
|
90643
|
+
} else if (q.type === "swipe" && (action.value === "like" || action.value === "dislike")) {
|
|
90644
|
+
editor.answer.swipes[items[index].id] = action.value;
|
|
90645
|
+
editor.error = void 0;
|
|
90646
|
+
}
|
|
90647
|
+
render();
|
|
90648
|
+
}
|
|
90288
90649
|
|
|
90289
90650
|
// src/tuiActions.ts
|
|
90290
90651
|
var TUI_ACTIONS = [
|
|
@@ -90737,6 +91098,17 @@ function sidebarLines(state) {
|
|
|
90737
91098
|
return ["Apps", "", ...state.apps.map((a, i) => selected(a.name, i)), "", "Ctrl+B close sidebar"];
|
|
90738
91099
|
}
|
|
90739
91100
|
}
|
|
91101
|
+
function sidebarPointerIds(state) {
|
|
91102
|
+
if (state.workspace === "chats") return tuiChatSidebarRows(state).map((row) => row.kind === "section" ? null : JSON.stringify([row.kind, row.chatId, row.projectId, row.folderId]));
|
|
91103
|
+
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);
|
|
91104
|
+
}
|
|
91105
|
+
function pointerSidebarLines(state) {
|
|
91106
|
+
const ids = sidebarPointerIds(state);
|
|
91107
|
+
return sidebarLines(state).map((line, row) => {
|
|
91108
|
+
const index = row - 2, id = ids[index];
|
|
91109
|
+
return id ? pointerLine(line, { kind: "select", target: "sidebar", index, id, activate: true }) : line;
|
|
91110
|
+
});
|
|
91111
|
+
}
|
|
90740
91112
|
function workspaceHint(state) {
|
|
90741
91113
|
if (state.questionEditor) return "Tab / \u2191\u2193 move Space choose \u2190/\u2192 adjust Ctrl+S send Esc cancel";
|
|
90742
91114
|
if (state.form) return "Tab field \u2190/\u2192 choice Ctrl+S save Esc cancel";
|
|
@@ -90767,7 +91139,10 @@ function overlayLines(state, width, height) {
|
|
|
90767
91139
|
if (state.paletteOpen) {
|
|
90768
91140
|
const actions = paletteActions(state.paletteQuery);
|
|
90769
91141
|
const start = Math.max(0, state.paletteIndex - Math.max(1, height - 5));
|
|
90770
|
-
return ["Actions", `Search: ${state.paletteQuery}_`, "", ...actions.slice(start).map((a, i) =>
|
|
91142
|
+
return ["Actions", `Search: ${state.paletteQuery}_`, "", ...actions.slice(start).map((a, i) => pointerLine(
|
|
91143
|
+
`${i + start === state.paletteIndex ? ">" : " "} ${a.label} ${a.command}`,
|
|
91144
|
+
{ kind: "select", target: "palette", index: i + start, id: a.command, activate: true }
|
|
91145
|
+
))];
|
|
90771
91146
|
}
|
|
90772
91147
|
const form = state.form;
|
|
90773
91148
|
if (!form) return [];
|
|
@@ -90785,71 +91160,112 @@ function overlayLines(state, width, height) {
|
|
|
90785
91160
|
for (const [index, field] of form.fields.entries()) {
|
|
90786
91161
|
const focused = index === form.fieldIndex;
|
|
90787
91162
|
const suffix = [field.required ? "required" : "", field.valueType && field.valueType !== "string" ? field.valueType : "", field.options ? "\u2190/\u2192 choose" : ""].filter(Boolean).join(" \xB7 ");
|
|
90788
|
-
|
|
91163
|
+
const action = { kind: "select", target: "form-field", index, id: field.name };
|
|
91164
|
+
rows3.push({ text: `${focused ? "\u203A" : " "} ${field.label}${suffix ? ` \xB7 ${suffix}` : ""}`, bold: true, color: focused ? "#32ade6" : "#e6e6e6", inset, action });
|
|
90789
91165
|
if (panelWidth >= 6) {
|
|
90790
91166
|
const edge = "\u2500".repeat(panelWidth - 2), border = focused ? "#32ade6" : "#626878";
|
|
90791
91167
|
rows3.push({ text: `\u256D${edge}\u256E`, color: border, inset });
|
|
90792
|
-
rows3.push(...wrapCells(`${field.value || "(empty)"}${focused && !form.busy ? "_" : ""}`, panelWidth - 4).map((text7) => ({ text: `\u2502 ${padCells(text7, panelWidth - 4)} \u2502`, color: focused ? "#ffffff" : "#cfcfcf", ...focused ? { background: "#2b3548" } : {}, inset })));
|
|
91168
|
+
rows3.push(...wrapCells(`${field.value || "(empty)"}${focused && !form.busy ? "_" : ""}`, panelWidth - 4).map((text7) => ({ text: `\u2502 ${padCells(text7, panelWidth - 4)} \u2502`, color: focused ? "#ffffff" : "#cfcfcf", ...focused ? { background: "#2b3548" } : {}, inset, action })));
|
|
90793
91169
|
rows3.push({ text: `\u2570${edge}\u256F`, color: border, inset }, "");
|
|
90794
|
-
} else rows3.push(...wrapCells(field.value, panelWidth));
|
|
91170
|
+
} else rows3.push(...wrapCells(field.value, panelWidth).map((line) => pointerLine(line, action)));
|
|
91171
|
+
if (field.options) rows3.push({ text: "\u2039 Previous Next \u203A", inset, spans: [
|
|
91172
|
+
{ text: "\u2039 Previous", action: { ...action, activate: true, name: "left" } },
|
|
91173
|
+
{ text: " " },
|
|
91174
|
+
{ text: "Next \u203A", action: { ...action, activate: true, name: "right" } }
|
|
91175
|
+
] });
|
|
90795
91176
|
}
|
|
90796
91177
|
if (form.error) rows3.push({ text: form.error, color: "#ff6b6b", bold: true, inset });
|
|
90797
|
-
rows3.push({
|
|
91178
|
+
rows3.push({
|
|
91179
|
+
text: form.busy ? "Saving\u2026" : "Save \xB7 Ctrl+S Cancel \xB7 Esc",
|
|
91180
|
+
color: "#a0a0a0",
|
|
91181
|
+
inset,
|
|
91182
|
+
...!form.busy ? { spans: [
|
|
91183
|
+
{ text: "Save \xB7 Ctrl+S", action: { kind: "key", name: "s", ctrl: true } },
|
|
91184
|
+
{ text: " " },
|
|
91185
|
+
{ text: "Cancel \xB7 Esc", action: { kind: "key", name: "escape" } }
|
|
91186
|
+
] } : {}
|
|
91187
|
+
});
|
|
90798
91188
|
return rows3;
|
|
90799
91189
|
}
|
|
90800
91190
|
const rows2 = [form.title, ""];
|
|
90801
91191
|
for (const [index, field] of form.fields.entries()) {
|
|
90802
|
-
|
|
90803
|
-
rows2.push(
|
|
91192
|
+
const action = { kind: "select", target: "form-field", index, id: field.name };
|
|
91193
|
+
rows2.push(pointerLine(`${index === form.fieldIndex ? ">" : " "} ${field.label}${field.options ? " [\u2190/\u2192]" : ""}`, action));
|
|
91194
|
+
rows2.push(...wrapCells(` ${field.value || "(empty)"}${index === form.fieldIndex && !form.busy ? "_" : ""}`, width).map((line) => pointerLine(line, action)));
|
|
91195
|
+
if (field.options) rows2.push({ text: "\u2039 Previous Next \u203A", spans: [
|
|
91196
|
+
{ text: "\u2039 Previous", action: { ...action, activate: true, name: "left" } },
|
|
91197
|
+
{ text: " " },
|
|
91198
|
+
{ text: "Next \u203A", action: { ...action, activate: true, name: "right" } }
|
|
91199
|
+
] });
|
|
90804
91200
|
rows2.push("");
|
|
90805
91201
|
}
|
|
90806
91202
|
if (form.error) rows2.push(`Error: ${form.error}`);
|
|
90807
|
-
rows2.push(form.busy ? "Saving\u2026" :
|
|
91203
|
+
rows2.push(form.busy ? "Saving\u2026" : { text: "Save \xB7 Ctrl+S Cancel \xB7 Esc", spans: [
|
|
91204
|
+
{ text: "Save \xB7 Ctrl+S", action: { kind: "key", name: "s", ctrl: true } },
|
|
91205
|
+
{ text: " " },
|
|
91206
|
+
{ text: "Cancel \xB7 Esc", action: { kind: "key", name: "escape" } }
|
|
91207
|
+
] });
|
|
90808
91208
|
return rows2;
|
|
90809
91209
|
}
|
|
90810
91210
|
function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
90811
91211
|
const { gutter, sidebarWidth, paneWidth, contentWidth, inset, composerWidth, composerInset } = workspaceGeometry(state, rawWidth);
|
|
90812
91212
|
const height = Math.max(1, Math.floor(rawHeight));
|
|
91213
|
+
beginPointerFrame(state, Math.max(1, Math.floor(rawWidth)), height);
|
|
91214
|
+
const modal = Boolean(state.form || state.paletteOpen || state.questionEditor);
|
|
91215
|
+
const bodyColumn = gutter + sidebarWidth + inset;
|
|
90813
91216
|
const mode = options.colorMode ?? "none";
|
|
90814
91217
|
const ascii = options.ascii ?? false;
|
|
90815
91218
|
const line = ascii ? "-" : "\u2500", vertical = ascii ? "|" : "\u2502";
|
|
90816
91219
|
const place = (rendered, side2 = " ".repeat(sidebarWidth)) => " ".repeat(gutter) + side2 + " ".repeat(inset) + rendered + " ".repeat(paneWidth - inset - contentWidth + gutter);
|
|
90817
|
-
const navParts = [{ text: "OpenMates ", color: "#cfcfcf", bold: true }, ...WORKSPACES.map((workspace, index) => {
|
|
91220
|
+
const navParts = [{ text: "OpenMates ", color: "#cfcfcf", bold: true, action: { kind: "command", command: "/chats" } }, ...WORKSPACES.map((workspace, index) => {
|
|
90818
91221
|
const focused = state.focus === "navigation" && index === state.navigationIndex;
|
|
90819
91222
|
const label3 = state.workspace === workspace ? `[${titleCase(workspace)}]` : titleCase(workspace);
|
|
90820
|
-
return {
|
|
91223
|
+
return {
|
|
91224
|
+
text: `${focused ? "\u203A " : ""}${label3} `,
|
|
91225
|
+
color: focused ? "#32ade6" : state.workspace === workspace ? "#ff553b" : "#cfcfcf",
|
|
91226
|
+
bold: true,
|
|
91227
|
+
action: { kind: "command", command: `/${workspace}` }
|
|
91228
|
+
};
|
|
90821
91229
|
})];
|
|
90822
91230
|
if (cells(navParts.map((part) => part.text).join("")) > contentWidth - 6) {
|
|
90823
91231
|
const focused = state.focus === "navigation";
|
|
90824
|
-
navParts.splice(
|
|
91232
|
+
navParts.splice(
|
|
91233
|
+
0,
|
|
91234
|
+
navParts.length,
|
|
91235
|
+
{ text: "OpenMates ", color: "#cfcfcf", bold: true, action: { kind: "command", command: "/chats" } },
|
|
91236
|
+
{ text: `[${titleCase(state.workspace)}] `, color: "#ff553b", bold: true, action: { kind: "command", command: `/${state.workspace}` } },
|
|
91237
|
+
...focused ? [{ text: `\u203A ${titleCase(WORKSPACES[state.navigationIndex])} `, color: "#32ade6", bold: true, action: { kind: "command", command: `/${WORKSPACES[state.navigationIndex]}` } }] : []
|
|
91238
|
+
);
|
|
90825
91239
|
}
|
|
90826
91240
|
const navUsed = cells(navParts.map((part) => part.text).join(""));
|
|
90827
|
-
navParts.push({ text: contentWidth - navUsed >= 18 ? "Ctrl+G navigation" : "^G nav", color: "#808080", bold: false });
|
|
91241
|
+
navParts.push({ text: contentWidth - navUsed >= 18 ? "Ctrl+G navigation" : "^G nav", color: "#808080", bold: false, action: { kind: "key", name: "g", ctrl: true } });
|
|
90828
91242
|
let navRemaining = contentWidth;
|
|
90829
91243
|
const renderedNav = navParts.map((part) => {
|
|
91244
|
+
const column = bodyColumn + contentWidth - navRemaining;
|
|
90830
91245
|
const value = truncateCells(part.text, navRemaining);
|
|
90831
91246
|
navRemaining -= cells(value);
|
|
91247
|
+
if (!modal && part.action) addPointerTarget(state, column, 0, cells(value.trimEnd()), part.action);
|
|
90832
91248
|
return foreground(value, part.color, mode, part.bold);
|
|
90833
91249
|
}).join("") + " ".repeat(navRemaining);
|
|
90834
91250
|
const input = composerViewport(state, composerWidth);
|
|
90835
91251
|
const showComposer = state.workspace !== "apps" || state.focus === "composer" || Boolean(state.input);
|
|
90836
91252
|
const composerRows = showComposer ? input.count : 0;
|
|
90837
91253
|
const bodyHeight = Math.max(1, height - 2 - (showComposer ? composerRows + 3 : 1));
|
|
90838
|
-
const
|
|
90839
|
-
const sidebar = state.sidebarOpen && !
|
|
91254
|
+
const overlay2 = state.form || state.paletteOpen || state.questionEditor;
|
|
91255
|
+
const sidebar = state.sidebarOpen && !overlay2;
|
|
90840
91256
|
const sidebarOverlay = sidebar && !sidebarWidth;
|
|
90841
|
-
let content =
|
|
90842
|
-
const stickyCount = !
|
|
91257
|
+
let content = overlay2 ? overlayLines(state, contentWidth, bodyHeight) : sidebarOverlay ? pointerSidebarLines(state) : body;
|
|
91258
|
+
const stickyCount = !overlay2 && !sidebarOverlay ? Math.min(options.stickyRows ?? 0, Math.max(0, bodyHeight - 8)) : 0;
|
|
90843
91259
|
const fixed = content.slice(0, stickyCount);
|
|
90844
91260
|
content = content.slice(stickyCount);
|
|
90845
91261
|
const viewportHeight = bodyHeight - stickyCount;
|
|
90846
91262
|
const maxStart = Math.max(0, content.length - viewportHeight);
|
|
90847
|
-
let start = !
|
|
91263
|
+
let start = !overlay2 && !sidebarOverlay && state.screen === "chat" ? Math.max(0, maxStart - state.scrollOffset) : Math.min(maxStart, Math.max(0, state.scrollOffset));
|
|
90848
91264
|
if (sidebarOverlay && state.focus === "sidebar") {
|
|
90849
91265
|
const marker = content.findIndex((row) => lineText(row).startsWith("> "));
|
|
90850
91266
|
start = Math.min(maxStart, Math.max(0, marker - bodyHeight + 3));
|
|
90851
91267
|
}
|
|
90852
|
-
if (
|
|
91268
|
+
if (overlay2) {
|
|
90853
91269
|
const marker = content.findIndex((row) => /^[>›] /.test(lineText(row).trimStart()));
|
|
90854
91270
|
start = marker >= bodyHeight - 4 ? Math.max(0, marker - bodyHeight + 6) : 0;
|
|
90855
91271
|
} else if (state.followSelection && ["start", "tasks", "projects", "project", "chat", "chats", "example", "examples", "workflow", "workflows", "apps", "app", "app-skill"].includes(state.screen) && state.focus === "content") {
|
|
@@ -90863,13 +91279,13 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90863
91279
|
if (selectionEnd >= start + viewportHeight) start = Math.min(maxStart, selectionEnd - viewportHeight + 1);
|
|
90864
91280
|
if (marker >= 0 && marker < start) start = marker;
|
|
90865
91281
|
}
|
|
90866
|
-
if (!
|
|
91282
|
+
if (!overlay2 && !sidebarOverlay) state.scrollOffset = state.screen === "chat" ? maxStart - start : start;
|
|
90867
91283
|
state.followSelection = false;
|
|
90868
91284
|
const heroRows = options.headerRows ?? 0;
|
|
90869
91285
|
const category = state.screen === "example" ? state.activeExample?.chat.category : state.activeChat?.category;
|
|
90870
91286
|
const background = chatBackground(category);
|
|
90871
|
-
const allSide = sidebarWidth ?
|
|
90872
|
-
const sideMarker = allSide.findIndex((row) => row.startsWith("> "));
|
|
91287
|
+
const allSide = sidebarWidth ? pointerSidebarLines(state) : [];
|
|
91288
|
+
const sideMarker = allSide.findIndex((row) => lineText(row).startsWith("> "));
|
|
90873
91289
|
const sideStart = Math.max(0, sideMarker - bodyHeight + 3);
|
|
90874
91290
|
const side = sideStart ? [allSide[0], "", ...allSide.slice(sideStart)] : allSide;
|
|
90875
91291
|
const rows2 = [];
|
|
@@ -90879,6 +91295,15 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90879
91295
|
const style = typeof value === "string" ? void 0 : value;
|
|
90880
91296
|
const raw = terminalText(lineText(value)).replace(/\n/g, " ");
|
|
90881
91297
|
let rendered = padCells(raw, contentWidth);
|
|
91298
|
+
const targetInset = Math.max(0, Math.min(Math.floor(contentWidth / 2) - 1, style?.inset ?? 0));
|
|
91299
|
+
const leading = cells(raw) - cells(raw.trimStart());
|
|
91300
|
+
if (style?.action) addPointerTarget(
|
|
91301
|
+
state,
|
|
91302
|
+
bodyColumn + targetInset + leading,
|
|
91303
|
+
i + 2,
|
|
91304
|
+
Math.min(cells(raw.trim()), Math.max(0, contentWidth - 2 * targetInset - leading)),
|
|
91305
|
+
style.action
|
|
91306
|
+
);
|
|
90882
91307
|
if (style && !sidebarOverlay) {
|
|
90883
91308
|
const inset2 = Math.max(0, Math.min(Math.floor(contentWidth / 2) - 1, style.inset ?? 0));
|
|
90884
91309
|
const span = Math.max(1, contentWidth - 2 * inset2);
|
|
@@ -90887,16 +91312,19 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90887
91312
|
rendered = "";
|
|
90888
91313
|
for (const part of style.spans) {
|
|
90889
91314
|
const text7 = truncateCells(terminalText(part.text).replace(/\n/g, " "), remaining), size = cells(text7);
|
|
91315
|
+
if (part.action) addPointerTarget(state, bodyColumn + inset2 + span - remaining, i + 2, size, part.action);
|
|
90890
91316
|
rendered += part.background ? backgroundLine(text7, size, part.background, mode, part.bold, part.color) : foreground(text7, part.color ?? "#e6e6e6", mode, part.bold);
|
|
90891
91317
|
remaining -= size;
|
|
90892
91318
|
if (!remaining) break;
|
|
90893
91319
|
}
|
|
90894
91320
|
rendered = " ".repeat(inset2) + rendered + " ".repeat(remaining + inset2);
|
|
90895
91321
|
} else rendered = " ".repeat(inset2) + (style.background ? backgroundLine(raw, span, style.background, mode, style.bold) : foreground(padCells(raw, span), style.color ?? "#e6e6e6", mode, style.bold)) + " ".repeat(inset2);
|
|
90896
|
-
} else if (!
|
|
91322
|
+
} else if (!overlay2 && !sidebarOverlay && index < heroRows) rendered = backgroundLine(raw, contentWidth, background, mode);
|
|
90897
91323
|
else if (raw.startsWith("> ") || raw.includes("\u203A")) rendered = foreground(rendered, "#ff553b", mode, true);
|
|
90898
91324
|
else if (/^(You|Sophia|Tasks|Projects|Workflows|Recent chats|Suggestions|Actions)$/.test(raw)) rendered = foreground(rendered, "#5a85eb", mode, true);
|
|
90899
|
-
const
|
|
91325
|
+
const sideValue = side[i], sideText = sideValue ? lineText(sideValue) : "";
|
|
91326
|
+
if (sideValue && typeof sideValue !== "string" && sideValue.action) addPointerTarget(state, gutter, i + 2, Math.min(cells(sideText), sidebarWidth - 2), sideValue.action);
|
|
91327
|
+
const sidebarRow = sidebarWidth ? foreground(padCells(sideText, sidebarWidth - 2), "#cfcfcf", mode) + `${vertical} ` : void 0;
|
|
90900
91328
|
rows2.push(place(rendered, sidebarRow));
|
|
90901
91329
|
}
|
|
90902
91330
|
const placeholder = state.screen === "example" ? "Continue from this example, or ask your own question..." : state.workspace === "chats" ? state.screen === "chat" ? "Ask a follow-up, use @file, or type /help" : "Ask anything..." : state.workspace === "projects" ? "Name a new project \xB7 /search to browse" : state.workspace === "workflows" ? "Describe new workflow \xB7 /search to browse" : state.workspace === "tasks" ? "Add or update tasks \xB7 /search to browse" : "Search apps or type / for actions";
|
|
@@ -90904,6 +91332,13 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
90904
91332
|
const hintColor = state.focus === "composer" ? "#a0a0a0" : "#ff553b";
|
|
90905
91333
|
const composer = [];
|
|
90906
91334
|
if (showComposer) {
|
|
91335
|
+
if (!modal && !sidebarOverlay) for (let i = 0; i < input.count; i++) addPointerTarget(
|
|
91336
|
+
state,
|
|
91337
|
+
gutter + sidebarWidth + composerInset + (composerWidth < 6 ? 0 : 2),
|
|
91338
|
+
2 + bodyHeight + (composerWidth < 6 ? 0 : 1) + i,
|
|
91339
|
+
Math.max(1, composerWidth - (composerWidth < 6 ? 0 : 4)),
|
|
91340
|
+
{ kind: "focus", focus: "composer" }
|
|
91341
|
+
);
|
|
90907
91342
|
const placeInput = (rendered) => " ".repeat(gutter + sidebarWidth + composerInset) + rendered + " ".repeat(paneWidth - composerInset - composerWidth + gutter);
|
|
90908
91343
|
const inputRows = input.lines.map((text7, i) => `${i ? " " : "> "}${text7 || (!state.input ? placeholder : "")}`);
|
|
90909
91344
|
if (composerWidth < 6) composer.push(...inputRows.map((text7) => placeInput(padCells(text7, composerWidth))), placeInput(foreground(padCells(hint, composerWidth), hintColor, mode)), placeInput(" ".repeat(composerWidth)), placeInput(" ".repeat(composerWidth)));
|
|
@@ -91609,7 +92044,11 @@ function homeHeader(state, width, height) {
|
|
|
91609
92044
|
const title = inspiration?.feature?.title || inspiration?.title || "Daily inspiration";
|
|
91610
92045
|
const banner = [centered2(`DAILY INSPIRATION ${state.focus === "inspiration" ? "\u2039 Enter open \u203A" : "\u2039 Ctrl+O explore \u203A"}`, width), "", ...parts.map((line) => centered2(line, width)), centered2(title, width)];
|
|
91611
92046
|
while (banner.length < rows2) banner.push("");
|
|
91612
|
-
banner.forEach((text7) => result.push({
|
|
92047
|
+
banner.forEach((text7) => result.push({
|
|
92048
|
+
text: text7,
|
|
92049
|
+
background: gradient.start,
|
|
92050
|
+
...inspiration ? { action: { kind: "command", command: "/inspiration" } } : {}
|
|
92051
|
+
}));
|
|
91613
92052
|
result.push("", { text: centered2(state.workspace === "apps" ? prompts.apps : state.username ? `Hey ${state.username}!` : "Hey there!", width), bold: true });
|
|
91614
92053
|
if (state.workspace !== "chats" || !homeChatItems(state).length) result.push({ text: centered2(state.workspace === "apps" ? "Use your apps directly and return to saved results." : prompts[state.workspace], width), color: "#cfcfcf" });
|
|
91615
92054
|
result.push("");
|
|
@@ -91618,7 +92057,7 @@ function homeHeader(state, width, height) {
|
|
|
91618
92057
|
function renderHomeChatCards(state, width, height) {
|
|
91619
92058
|
const items = homeContinueItems(state), result = homeHeader(state, width, height);
|
|
91620
92059
|
const activeCount = runningTuiChatGroups(state).length;
|
|
91621
|
-
if (activeCount) result.push(centered2(`${activeCount} ${activeCount === 1 ? "chat" : "chats"} active\u2026 /active`, width), "");
|
|
92060
|
+
if (activeCount) result.push(pointerLine(centered2(`${activeCount} ${activeCount === 1 ? "chat" : "chats"} active\u2026 /active`, width), { kind: "command", command: "/active" }), "");
|
|
91622
92061
|
if (!items.length) {
|
|
91623
92062
|
result.push(centered2(state.homeChatsLoading ? "Loading your recent chats\u2026" : state.homeError || "Start a chat below. Your recent chats will appear here.", width), "");
|
|
91624
92063
|
return result;
|
|
@@ -91630,14 +92069,16 @@ function renderHomeChatCards(state, width, height) {
|
|
|
91630
92069
|
title: item.title,
|
|
91631
92070
|
description: item.summary || "Open saved item",
|
|
91632
92071
|
footer: `${item.priority.label} \xB7 Saved`,
|
|
91633
|
-
background: (item.category && CATEGORY_GRADIENTS[item.category] || BLUE).start
|
|
92072
|
+
background: (item.category && CATEGORY_GRADIENTS[item.category] || BLUE).start,
|
|
92073
|
+
action: { kind: "command", command: `/embed ${item.embedId}` }
|
|
91634
92074
|
};
|
|
91635
92075
|
const chat = item.chat;
|
|
91636
92076
|
return {
|
|
91637
92077
|
title: chat.title || chat.draftPreview || "Untitled chat",
|
|
91638
92078
|
description: chat.hasDraft ? "Draft" : chat.summary || "Continue this conversation",
|
|
91639
92079
|
footer: item.priority?.label || chat.category?.replaceAll("_", " ") || "Chat",
|
|
91640
|
-
background: (chat.category && CATEGORY_GRADIENTS[chat.category] || BLUE).start
|
|
92080
|
+
background: (chat.category && CATEGORY_GRADIENTS[chat.category] || BLUE).start,
|
|
92081
|
+
action: { kind: "command", command: chat.source === "example" ? `/example ${chat.slug || chat.id}` : `/chat ${chat.id}` }
|
|
91641
92082
|
};
|
|
91642
92083
|
}), width, selected, state.focus === "content"));
|
|
91643
92084
|
result.push(
|
|
@@ -91879,7 +92320,8 @@ function renderTuiAppsHome(apps, options) {
|
|
|
91879
92320
|
title: app.name,
|
|
91880
92321
|
description: app.description,
|
|
91881
92322
|
footer: `${app.skills.length} skills${app.category ? ` \xB7 ${app.category.replaceAll("_", " ")}` : ""}`,
|
|
91882
|
-
background: (APP_GRADIENTS[app.id] ?? PRIMARY_GRADIENT).start
|
|
92323
|
+
background: (APP_GRADIENTS[app.id] ?? PRIMARY_GRADIENT).start,
|
|
92324
|
+
action: { kind: "command", command: `/app ${app.id}` }
|
|
91883
92325
|
})), width, selected, options.selectedId !== void 0),
|
|
91884
92326
|
"",
|
|
91885
92327
|
centeredCarouselText(`${selected > 0 ? "\u2039" : " "} App ${selected + 1} of ${visible.length} ${selected < visible.length - 1 ? "\u203A" : " "}`, width),
|
|
@@ -91923,6 +92365,50 @@ function outlinedTabs(tabs, labels, selected, width) {
|
|
|
91923
92365
|
});
|
|
91924
92366
|
return ["", `\u256D${edges.join("\u252C")}\u256E`, `\u2502${row.join("\u2502")}\u2502`, `\u2570${edges.join("\u2534")}\u256F`, ""];
|
|
91925
92367
|
}
|
|
92368
|
+
function outlinedPointerTabs(tabs, labels, selected, width) {
|
|
92369
|
+
const rendered = outlinedTabs(tabs, labels, selected, width);
|
|
92370
|
+
const action = (index) => ({ kind: "key", name: "", chunk: String(index + 1), focus: "content" });
|
|
92371
|
+
if (width < tabs.length * 8 + 1) {
|
|
92372
|
+
const spans = [];
|
|
92373
|
+
let remaining = Math.max(1, width);
|
|
92374
|
+
tabs.forEach((tab, index) => {
|
|
92375
|
+
if (index && remaining) {
|
|
92376
|
+
const separator = truncateCells(" | ", remaining);
|
|
92377
|
+
spans.push({ text: separator });
|
|
92378
|
+
remaining -= cells(separator);
|
|
92379
|
+
}
|
|
92380
|
+
const label3 = truncateCells(`${index + 1} ${tab === selected ? `[${labels[tab]}]` : labels[tab]}`, remaining);
|
|
92381
|
+
if (label3) spans.push({ text: label3, action: action(index) });
|
|
92382
|
+
remaining -= cells(label3);
|
|
92383
|
+
});
|
|
92384
|
+
return ["", { text: rendered[1], spans }, ""];
|
|
92385
|
+
}
|
|
92386
|
+
const available = width - tabs.length - 1, base = Math.floor(available / tabs.length);
|
|
92387
|
+
const sizes = tabs.map((_, index) => base + (index < available % tabs.length ? 1 : 0));
|
|
92388
|
+
return rendered.map((line, row) => {
|
|
92389
|
+
if (row === 0 || row === rendered.length - 1) return line;
|
|
92390
|
+
const spans = [{ text: line.slice(0, 1) }];
|
|
92391
|
+
let offset = 1;
|
|
92392
|
+
sizes.forEach((size, index) => {
|
|
92393
|
+
spans.push({ text: line.slice(offset, offset + size), action: action(index) });
|
|
92394
|
+
offset += size;
|
|
92395
|
+
spans.push({ text: line.slice(offset, offset + 1) });
|
|
92396
|
+
offset++;
|
|
92397
|
+
});
|
|
92398
|
+
return { text: line, spans };
|
|
92399
|
+
});
|
|
92400
|
+
}
|
|
92401
|
+
function pointerPageLine(offset, hasMore) {
|
|
92402
|
+
const prefix = `Page ${Math.floor(offset / RESULT_PAGE_SIZE) + 1} \xB7 `;
|
|
92403
|
+
const spans = [
|
|
92404
|
+
{ text: prefix },
|
|
92405
|
+
{ text: "previous", ...offset > 0 ? { action: { kind: "key", name: "", chunk: "[", focus: "content" } } : {} },
|
|
92406
|
+
{ text: "/" },
|
|
92407
|
+
{ text: "next", ...hasMore ? { action: { kind: "key", name: "", chunk: "]", focus: "content" } } : {} },
|
|
92408
|
+
{ text: " available" }
|
|
92409
|
+
];
|
|
92410
|
+
return { text: spans.map((span) => span.text).join(""), spans };
|
|
92411
|
+
}
|
|
91926
92412
|
function renderTuiAppIdentity(app, width) {
|
|
91927
92413
|
return identityCard([
|
|
91928
92414
|
`APP / ${app.id.toUpperCase()}`,
|
|
@@ -91931,24 +92417,25 @@ function renderTuiAppIdentity(app, width) {
|
|
|
91931
92417
|
`${app.skills.length} skills \xB7 ${app.focusModes.length} focus modes`
|
|
91932
92418
|
], width, "APP WORKSPACE");
|
|
91933
92419
|
}
|
|
91934
|
-
function renderTuiAppTabs(tab, width) {
|
|
92420
|
+
function renderTuiAppTabs(tab, width, options) {
|
|
91935
92421
|
const tabs = ["skills", "focus_modes", "settings_memories", "embeds", "workflows"];
|
|
91936
92422
|
const labels = { skills: "Skills", focus_modes: "Focus modes", settings_memories: "Memories", embeds: "Embeds", workflows: "Workflows" };
|
|
91937
|
-
return outlinedTabs(tabs, labels, tab, width);
|
|
92423
|
+
return options?.pointer ? outlinedPointerTabs(tabs, labels, tab, width) : outlinedTabs(tabs, labels, tab, width);
|
|
91938
92424
|
}
|
|
91939
92425
|
function renderTuiApp(app, options) {
|
|
91940
92426
|
const width = Math.max(1, options.width);
|
|
91941
|
-
const lines = [...renderTuiAppIdentity(app, width), ...renderTuiAppTabs(options.tab, width)];
|
|
92427
|
+
const lines = [...renderTuiAppIdentity(app, width), ...options.pointer ? renderTuiAppTabs(options.tab, width, { pointer: true }) : renderTuiAppTabs(options.tab, width)];
|
|
91942
92428
|
if (options.tab === "skills") {
|
|
91943
92429
|
lines.push("Which app skill do you want to use?", "");
|
|
91944
92430
|
if (!app.skills.length) lines.push("No skills available.");
|
|
91945
92431
|
for (const skill of app.skills) {
|
|
91946
|
-
|
|
92432
|
+
const card2 = cardLines(
|
|
91947
92433
|
`${skill.id === options.selectedId ? "\u203A" : " "} ${skill.name}`,
|
|
91948
92434
|
skill.description,
|
|
91949
92435
|
skill.providers.length ? `via ${skill.providers.join(", ")}` : `${app.id}/${skill.id}`,
|
|
91950
92436
|
width
|
|
91951
|
-
)
|
|
92437
|
+
);
|
|
92438
|
+
lines.push(...options.pointer ? card2.map((line) => pointerLine(line, { kind: "command", command: `/app-skill ${app.id}/${skill.id}` })) : card2, "");
|
|
91952
92439
|
}
|
|
91953
92440
|
} else if (options.tab === "focus_modes" || options.tab === "settings_memories") {
|
|
91954
92441
|
const items = options.tab === "focus_modes" ? app.focusModes : app.settingsMemories;
|
|
@@ -91956,7 +92443,7 @@ function renderTuiApp(app, options) {
|
|
|
91956
92443
|
for (const item of items) {
|
|
91957
92444
|
lines.push(truncateCells(`${item.id === options.selectedId ? ">" : " "} ${item.name}`, width));
|
|
91958
92445
|
if (item.description) lines.push(...textLines(` ${oneLine2(item.description)}`, width));
|
|
91959
|
-
if ("body" in item && item.body && item.id === options.selectedId) lines.push(...textLines(item.body, width));
|
|
92446
|
+
if ("body" in item && typeof item.body === "string" && item.body && item.id === options.selectedId) lines.push(...textLines(item.body, width));
|
|
91960
92447
|
}
|
|
91961
92448
|
lines.push("", "Manage private Memories in the web app.");
|
|
91962
92449
|
} else if (options.tab === "embeds") lines.push("Saved results load from the encrypted Apps history. Use Enter to inspect a result.");
|
|
@@ -91983,7 +92470,7 @@ async function loadTuiAppsSkill(client2, appId, skillId) {
|
|
|
91983
92470
|
}
|
|
91984
92471
|
function renderTuiAppsSkill(skill, options) {
|
|
91985
92472
|
const width = Math.max(1, options.width);
|
|
91986
|
-
const lines = [...renderTuiAppsSkillIdentity(skill, width), ...renderTuiAppsSkillTabs(options.tab, width)];
|
|
92473
|
+
const lines = [...renderTuiAppsSkillIdentity(skill, width), ...options.pointer ? renderTuiAppsSkillTabs(options.tab, width, { pointer: true }) : renderTuiAppsSkillTabs(options.tab, width)];
|
|
91987
92474
|
if (options.tab === "overview") {
|
|
91988
92475
|
lines.push("Use this skill manually. Your mates can also use it in chats.", "");
|
|
91989
92476
|
for (const path2 of skillLeafPaths(skill.schema)) {
|
|
@@ -91991,7 +92478,7 @@ function renderTuiAppsSkill(skill, options) {
|
|
|
91991
92478
|
const value = getSkillPath(skill.defaults, path2);
|
|
91992
92479
|
lines.push(truncateCells(`${path2}${isRequired(skill.schema, path2) ? " *" : ""} \xB7 ${field?.type ?? "value"}${value !== void 0 ? ` \xB7 ${typeof value === "string" ? value : JSON.stringify(value)}` : ""}`, width));
|
|
91993
92480
|
}
|
|
91994
|
-
lines.push("", skill.executionAvailable ? "Enter opens the input form. Running may spend credits." : `Unavailable: ${skill.unavailableReason ?? "This skill cannot run here."}`);
|
|
92481
|
+
lines.push("", skill.executionAvailable && options.pointer ? pointerLine("Enter opens the input form. Running may spend credits.", { kind: "command", command: "/app-run" }) : skill.executionAvailable ? "Enter opens the input form. Running may spend credits." : `Unavailable: ${skill.unavailableReason ?? "This skill cannot run here."}`);
|
|
91995
92482
|
const fixed = skill.pricing?.fixed;
|
|
91996
92483
|
if (typeof fixed === "number") lines.push(`${fixed} credits per request`);
|
|
91997
92484
|
} else if (options.tab === "embeds") lines.push("Saved results are listed in the app's Embeds tab.");
|
|
@@ -92007,10 +92494,10 @@ function renderTuiAppsSkillIdentity(skill, width) {
|
|
|
92007
92494
|
skill.executionAvailable ? "Use skill \xB7 review input and confirm credits before running" : "Skill unavailable"
|
|
92008
92495
|
], width, "APP SKILL");
|
|
92009
92496
|
}
|
|
92010
|
-
function renderTuiAppsSkillTabs(tab, width) {
|
|
92497
|
+
function renderTuiAppsSkillTabs(tab, width, options) {
|
|
92011
92498
|
const tabs = ["overview", "embeds", "workflows"];
|
|
92012
92499
|
const labels = { overview: "Overview", embeds: "Embeds", workflows: "Workflows" };
|
|
92013
|
-
return outlinedTabs(tabs, labels, tab, width);
|
|
92500
|
+
return options?.pointer ? outlinedPointerTabs(tabs, labels, tab, width) : outlinedTabs(tabs, labels, tab, width);
|
|
92014
92501
|
}
|
|
92015
92502
|
function isRequired(schema, path2) {
|
|
92016
92503
|
const parts = path2.replaceAll("[]", "").split(".");
|
|
@@ -92230,8 +92717,11 @@ function renderTuiAppsWorkflows(page, options) {
|
|
|
92230
92717
|
const width = Math.max(1, options.width);
|
|
92231
92718
|
const lines = ["Related workflows", ""];
|
|
92232
92719
|
if (!page.items.length) lines.push("No workflows for this app.");
|
|
92233
|
-
for (const workflow of page.items)
|
|
92234
|
-
|
|
92720
|
+
for (const workflow of page.items) {
|
|
92721
|
+
const line = truncateCells(`${workflow.id === options.selectedId ? ">" : " "} ${workflow.title} \xB7 ${workflow.id.slice(0, 8)}`, width);
|
|
92722
|
+
lines.push(options.pointer ? pointerLine(line, { kind: "command", command: `/workflow ${workflow.id}` }) : line);
|
|
92723
|
+
}
|
|
92724
|
+
if (page.offset > 0 || page.hasMore) lines.push("", options.pointer ? pointerPageLine(page.offset, page.hasMore) : `Page ${Math.floor(page.offset / RESULT_PAGE_SIZE) + 1} \xB7 previous/next available`);
|
|
92235
92725
|
return lines;
|
|
92236
92726
|
}
|
|
92237
92727
|
async function decryptedRow(row, key) {
|
|
@@ -92256,8 +92746,11 @@ function renderTuiAppsResults(page, options) {
|
|
|
92256
92746
|
const width = Math.max(1, options.width);
|
|
92257
92747
|
const lines = ["Saved results", ""];
|
|
92258
92748
|
if (!page.items.length) lines.push("No saved results for this app.");
|
|
92259
|
-
for (const item of page.items)
|
|
92260
|
-
|
|
92749
|
+
for (const item of page.items) {
|
|
92750
|
+
const line = truncateCells(`${item.embedId === options.selectedId ? ">" : " "} ${item.skillId} \xB7 ${item.status} \xB7 ${item.embedId.slice(0, 8)}`, width);
|
|
92751
|
+
lines.push(options.pointer ? pointerLine(line, { kind: "command", command: `/app-result ${item.embedId}` }) : line);
|
|
92752
|
+
}
|
|
92753
|
+
if (page.offset > 0 || page.hasMore) lines.push("", options.pointer ? pointerPageLine(page.offset, page.hasMore) : `Page ${Math.floor(page.offset / RESULT_PAGE_SIZE) + 1} \xB7 previous/next available`);
|
|
92261
92754
|
return lines;
|
|
92262
92755
|
}
|
|
92263
92756
|
function renderTuiAppsResult(result, width) {
|
|
@@ -92656,10 +93149,6 @@ function chatResultsViews(state) {
|
|
|
92656
93149
|
const messages = state.activeExample && (state.screen === "example" || state.embedOrigin?.screen === "example" || state.resultsViewOrigin?.screen === "example") ? state.activeExample.messages : state.messages;
|
|
92657
93150
|
return messages.flatMap((message) => messageResultsViews(message.content));
|
|
92658
93151
|
}
|
|
92659
|
-
function renderChatResultsView(state, descriptor, key, width, mode) {
|
|
92660
|
-
const data = buildTuiResultsViewData(descriptor, { ...exampleEmbedMap(state), ...state.chatEmbeds });
|
|
92661
|
-
return renderTuiResultsViewLines(data, { viewKey: key, mode: mode ?? state.resultsViewModes[key], aliasForEmbed: (id) => aliasForEmbed(state, id) }).flatMap((row, index) => wrapCells(row, width).map((text7) => index === 0 ? { text: text7, bold: true, color: "#80caff" } : index === 1 && row.includes("/view") ? { text: text7, color: "#85c9e8" } : text7));
|
|
92662
|
-
}
|
|
92663
93152
|
|
|
92664
93153
|
// ../ui/src/components/embeds/fitness/fitnessEmbedData.ts
|
|
92665
93154
|
function normalizeFitnessStatus(value) {
|
|
@@ -92754,7 +93243,11 @@ function fitnessSkillName(skillId) {
|
|
|
92754
93243
|
function card(details, width, appName, skillName, alias, appId, emphasizeSecond = true) {
|
|
92755
93244
|
const cardWidth = Math.max(1, Math.min(62, Math.floor(width) || 1));
|
|
92756
93245
|
const shortcut = `/embed ${readable(alias)}`;
|
|
92757
|
-
|
|
93246
|
+
const action = /^[\p{L}\p{N}_.:()-]{1,300}$/u.test(alias) ? { kind: "command", command: shortcut } : null;
|
|
93247
|
+
if (cardWidth < 6) {
|
|
93248
|
+
const line = truncateCells(shortcut, cardWidth);
|
|
93249
|
+
return [action ? pointerLine(line, action) : line];
|
|
93250
|
+
}
|
|
92758
93251
|
const inner = cardWidth - 4;
|
|
92759
93252
|
const colors = appColors(appId);
|
|
92760
93253
|
const row = (value, color = DETAIL, background, bold = false) => {
|
|
@@ -92773,7 +93266,7 @@ function card(details, width, appName, skillName, alias, appId, emphasizeSecond
|
|
|
92773
93266
|
lines.push(row(truncateCells(`${appName} \xB7 ${skillName}`, inner), colors.foreground, colors.background, true));
|
|
92774
93267
|
lines.push(row(truncateCells(shortcut, inner), colors.foreground, colors.background));
|
|
92775
93268
|
lines.push({ text: `\u2570${"\u2500".repeat(cardWidth - 2)}\u256F`, color: BORDER });
|
|
92776
|
-
return lines;
|
|
93269
|
+
return action ? lines.map((line) => pointerLine(line, action)) : lines;
|
|
92777
93270
|
}
|
|
92778
93271
|
function recordingDetails(content, title, width, status) {
|
|
92779
93272
|
if (status === "error" || status === "cancelled") {
|
|
@@ -93218,6 +93711,7 @@ function rankExamples(examples, interests) {
|
|
|
93218
93711
|
}).sort((a, b) => b.score - a.score || a.index - b.index).map((entry) => entry.example);
|
|
93219
93712
|
}
|
|
93220
93713
|
function renderTuiFrame(state, width, height, options = {}) {
|
|
93714
|
+
beginPointerFrame(state, width, height);
|
|
93221
93715
|
if (state.startup || state.privacyOffer) return renderStartupFrame(state, width, height, options.colorMode ?? "none");
|
|
93222
93716
|
const bodyWidth = workspaceGeometry(state, width).contentWidth;
|
|
93223
93717
|
const stickyRows = state.screen === "embed" ? 3 : state.screen === "results-view" ? 2 : state.screen === "project" && state.activeProject ? renderProjectIdentity(state.activeProject, { width: bodyWidth }).length + renderProjectTabs(state.projectTab, bodyWidth).length : state.screen === "app" && state.activeApp ? renderTuiAppIdentity(state.activeApp, bodyWidth).length + renderTuiAppTabs(state.appTab, bodyWidth).length : state.screen === "app-skill" && state.activeAppSkill ? renderTuiAppsSkillIdentity(state.activeAppSkill, bodyWidth).length + renderTuiAppsSkillTabs(state.appSkillTab, bodyWidth).length : state.screen === "workflow" && state.activeWorkflow ? renderWorkflowIdentity(state.activeWorkflow, { width: bodyWidth, run: state.workflowTab === "runs" ? state.workflowRuns[state.selectedWorkflowRunIndex] : void 0 }).length + (bodyWidth < 36 ? 7 : 4) : 0;
|
|
@@ -93258,7 +93752,23 @@ function renderStartupFrame(state, width, height, colorMode) {
|
|
|
93258
93752
|
return [...lines.slice(0, Math.max(0, height - footer.length)), ...footer.slice(-height)].join("\n");
|
|
93259
93753
|
}
|
|
93260
93754
|
function coloredHero(lines, rows2, gradient = PRIMARY_GRADIENT) {
|
|
93261
|
-
return lines.map((
|
|
93755
|
+
return lines.map((line, index) => index < rows2 ? typeof line === "string" ? { text: line, background: gradient.start } : { ...line, background: gradient.start } : line);
|
|
93756
|
+
}
|
|
93757
|
+
function appsHomeCommandLine(showAll, width) {
|
|
93758
|
+
const browse = showAll ? "/browse Featured apps" : "/browse Show all";
|
|
93759
|
+
const separator = " \xB7 ", search = "/search Search apps";
|
|
93760
|
+
const visible = truncateCells(browse + separator + search, width);
|
|
93761
|
+
const text7 = centeredCarouselText(browse + separator + search, width);
|
|
93762
|
+
const left = text7.slice(0, text7.length - visible.length);
|
|
93763
|
+
const shownBrowse = visible.slice(0, browse.length);
|
|
93764
|
+
const shownSeparator = visible.slice(browse.length, browse.length + separator.length);
|
|
93765
|
+
const shownSearch = visible.slice(browse.length + separator.length);
|
|
93766
|
+
return { text: text7, spans: [
|
|
93767
|
+
{ text: left },
|
|
93768
|
+
{ text: shownBrowse, action: { kind: "command", command: "/browse" } },
|
|
93769
|
+
{ text: shownSeparator },
|
|
93770
|
+
{ text: shownSearch, action: shownSearch.startsWith("/search") ? { kind: "command", command: "/search" } : void 0 }
|
|
93771
|
+
] };
|
|
93262
93772
|
}
|
|
93263
93773
|
function renderBody(state, width, height) {
|
|
93264
93774
|
return renderScreenBody(state, width, height);
|
|
@@ -93283,7 +93793,7 @@ function renderScreenBody(state, width, height) {
|
|
|
93283
93793
|
...homeHeader(state, width, height),
|
|
93284
93794
|
...renderTuiAppsHome(apps, { width, selectedIndex: state.selectedIndex, selectedId: state.focus === "content" ? apps[state.selectedIndex]?.id : void 0 }),
|
|
93285
93795
|
"",
|
|
93286
|
-
|
|
93796
|
+
appsHomeCommandLine(state.homeShowAll, width)
|
|
93287
93797
|
];
|
|
93288
93798
|
}
|
|
93289
93799
|
case "app": {
|
|
@@ -93292,10 +93802,10 @@ function renderScreenBody(state, width, height) {
|
|
|
93292
93802
|
const header2 = renderTuiAppIdentity(app, width), gradient = APP_GRADIENTS[app.id] ?? PRIMARY_GRADIENT;
|
|
93293
93803
|
if (state.appTab === "embeds" || state.appTab === "workflows") return [
|
|
93294
93804
|
...coloredHero(header2, header2.length, gradient),
|
|
93295
|
-
...renderTuiAppTabs(state.appTab, width),
|
|
93296
|
-
...state.appTab === "embeds" ? renderTuiAppsResults(state.appResults, { width, selectedId: state.appResults.items[state.selectedIndex]?.embedId }) : renderTuiAppsWorkflows(state.appWorkflows, { width, selectedId: state.appWorkflows.items[state.selectedIndex]?.id })
|
|
93805
|
+
...renderTuiAppTabs(state.appTab, width, { pointer: true }),
|
|
93806
|
+
...state.appTab === "embeds" ? renderTuiAppsResults(state.appResults, { width, selectedId: state.appResults.items[state.selectedIndex]?.embedId, pointer: true }) : renderTuiAppsWorkflows(state.appWorkflows, { width, selectedId: state.appWorkflows.items[state.selectedIndex]?.id, pointer: true })
|
|
93297
93807
|
];
|
|
93298
|
-
return coloredHero(renderTuiApp(app, { width, tab: state.appTab, selectedId: app.skills[state.selectedIndex]?.id }), header2.length, gradient);
|
|
93808
|
+
return coloredHero(renderTuiApp(app, { width, tab: state.appTab, selectedId: app.skills[state.selectedIndex]?.id, pointer: true }), header2.length, gradient);
|
|
93299
93809
|
}
|
|
93300
93810
|
case "app-skill": {
|
|
93301
93811
|
const skill = state.activeAppSkill;
|
|
@@ -93303,28 +93813,43 @@ function renderScreenBody(state, width, height) {
|
|
|
93303
93813
|
const header2 = renderTuiAppsSkillIdentity(skill, width), gradient = APP_GRADIENTS[skill.appId] ?? PRIMARY_GRADIENT;
|
|
93304
93814
|
if (state.appSkillTab === "embeds" || state.appSkillTab === "workflows") return [
|
|
93305
93815
|
...coloredHero(header2, header2.length, gradient),
|
|
93306
|
-
...renderTuiAppsSkillTabs(state.appSkillTab, width),
|
|
93307
|
-
...state.appSkillTab === "embeds" ? renderTuiAppsResults(state.appResults, { width, selectedId: state.appResults.items[state.selectedIndex]?.embedId }) : renderTuiAppsWorkflows(state.appWorkflows, { width, selectedId: state.appWorkflows.items[state.selectedIndex]?.id })
|
|
93816
|
+
...renderTuiAppsSkillTabs(state.appSkillTab, width, { pointer: true }),
|
|
93817
|
+
...state.appSkillTab === "embeds" ? renderTuiAppsResults(state.appResults, { width, selectedId: state.appResults.items[state.selectedIndex]?.embedId, pointer: true }) : renderTuiAppsWorkflows(state.appWorkflows, { width, selectedId: state.appWorkflows.items[state.selectedIndex]?.id, pointer: true })
|
|
93308
93818
|
];
|
|
93309
|
-
return coloredHero(renderTuiAppsSkill(skill, { width, tab: state.appSkillTab }), header2.length, gradient);
|
|
93819
|
+
return coloredHero(renderTuiAppsSkill(skill, { width, tab: state.appSkillTab, pointer: true }), header2.length, gradient);
|
|
93310
93820
|
}
|
|
93311
93821
|
case "app-result":
|
|
93312
93822
|
return state.activeAppResult ? renderTuiAppsResult(state.activeAppResult, width) : ["Loading saved result\u2026"];
|
|
93313
93823
|
case "projects":
|
|
93314
93824
|
return [...homeHeader(state, width, height), ...renderProjectCarousel(filteredProjects(state.projects, state.filter), width, state.selectedIndex, state.focus === "content")];
|
|
93315
93825
|
case "project":
|
|
93316
|
-
return state.activeProject ? state.projectTab === "tasks" ? [...renderProjectIdentity(state.activeProject, { width }), ...
|
|
93826
|
+
return state.activeProject ? state.projectTab === "tasks" ? [...renderProjectIdentity(state.activeProject, { width }), ...renderProjectPointerTabs("tasks", width), "", ...renderTaskBoard2(state.tasks, { width, selectedTaskId: filterTasks(state.tasks, state.filter)[state.selectedIndex]?.taskId, query: state.filter })] : renderProjectDetail(state.activeProject, { width, tab: state.projectTab, files: state.projectFiles, selectedFileId: filteredProjectFiles(state.projectFiles, state.filter)[state.selectedIndex]?.id, query: state.filter, folderId: state.projectFolderId ?? void 0, sourceId: state.projectSourceId ?? void 0, path: state.projectPath }) : ["Projects", "Loading project\u2026"];
|
|
93317
93827
|
case "status":
|
|
93318
93828
|
return renderStatus(state, width);
|
|
93319
93829
|
case "results-view": {
|
|
93320
93830
|
const key = state.activeResultsView ?? 1, descriptor = chatResultsViews(state)[key - 1];
|
|
93321
|
-
return descriptor ? [
|
|
93831
|
+
return descriptor ? [
|
|
93832
|
+
...pointerResultsView(state, descriptor, key, width),
|
|
93833
|
+
"",
|
|
93834
|
+
{ text: "m Map \xB7 c Calendar \xB7 l List \xB7 Esc back", spans: [
|
|
93835
|
+
{ text: "m Map", action: { kind: "command", command: `/view ${key} map` } },
|
|
93836
|
+
{ text: " \xB7 " },
|
|
93837
|
+
{ text: "c Calendar", action: { kind: "command", command: `/view ${key} calendar` } },
|
|
93838
|
+
{ text: " \xB7 " },
|
|
93839
|
+
{ text: "l List", action: { kind: "command", command: `/view ${key} list` } },
|
|
93840
|
+
{ text: " \xB7 " },
|
|
93841
|
+
{ text: "Esc back", action: { kind: "key", name: "escape" } }
|
|
93842
|
+
] }
|
|
93843
|
+
] : ["Results view unavailable. Escape returns to the chat."];
|
|
93322
93844
|
}
|
|
93323
93845
|
case "embed": {
|
|
93324
93846
|
const app = state.detailEmbed?.appId ?? "", gradient = APP_GRADIENTS[app] ?? PRIMARY_GRADIENT;
|
|
93325
93847
|
const title = state.detailTitle || "Embed";
|
|
93326
93848
|
const header2 = [title, state.detailEmbed ? `${state.detailEmbed.type?.replaceAll("-", " ") ?? "Saved item"} \xB7 ${state.detailEmbed.embedId.slice(0, 8)}` : "Saved embeds"];
|
|
93327
|
-
return [...coloredHero(header2, header2.length, gradient), "", ...
|
|
93849
|
+
return [...coloredHero(header2, header2.length, gradient), "", ...state.embedChoices.length ? state.embedChoices.map((alias, index) => pointerLine(
|
|
93850
|
+
`${index === state.selectedIndex ? ">" : " "} /embed ${alias} \xB7 Enter open`,
|
|
93851
|
+
{ kind: "command", command: `/embed ${alias}` }
|
|
93852
|
+
)) : state.detailLines].flatMap((line) => wrap(lineText(line), width).map((text7) => typeof line === "string" ? text7 : { ...line, text: text7, spans: void 0 }));
|
|
93328
93853
|
}
|
|
93329
93854
|
case "workflows":
|
|
93330
93855
|
return [...homeHeader(state, width, height), ...renderWorkflowCarousel(state.workflows.filter((w) => w.title.toLowerCase().includes(state.filter.toLowerCase())), width, state.selectedIndex, state.focus === "content")];
|
|
@@ -93378,7 +93903,12 @@ function renderTasks(state, width) {
|
|
|
93378
93903
|
}
|
|
93379
93904
|
function renderTaskDetail2(state, width) {
|
|
93380
93905
|
if (!state.activeTask) return renderTasks(state, width);
|
|
93381
|
-
return renderTaskDetails(state.activeTask, {
|
|
93906
|
+
return renderTaskDetails(state.activeTask, {
|
|
93907
|
+
width,
|
|
93908
|
+
activity: state.taskContext?.activity,
|
|
93909
|
+
dependencies: state.taskContext?.dependencies,
|
|
93910
|
+
pointer: true
|
|
93911
|
+
});
|
|
93382
93912
|
}
|
|
93383
93913
|
function renderWorkflows(state, width) {
|
|
93384
93914
|
const lines = ["Workflows", ""];
|
|
@@ -93544,7 +94074,10 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93544
94074
|
...card2.slice(-4)
|
|
93545
94075
|
]);
|
|
93546
94076
|
lines.push(...renderLineCarousel(cards, width, Math.max(0, selected), Boolean(state?.focus === "content" && selected >= 0), cardWidth));
|
|
93547
|
-
if (state && selected >= 0) lines.push(
|
|
94077
|
+
if (state && selected >= 0) lines.push(pointerLine(
|
|
94078
|
+
centeredCarouselText(`Embed ${selected + 1}/${unique4.length} \xB7 \u2190/\u2192 choose \xB7 Enter open \xB7 /embed ${aliasForEmbed(state, id)}`, width),
|
|
94079
|
+
{ kind: "command", command: `/embed ${aliasForEmbed(state, id)}` }
|
|
94080
|
+
));
|
|
93548
94081
|
pending = [];
|
|
93549
94082
|
};
|
|
93550
94083
|
const text7 = (value) => {
|
|
@@ -93556,7 +94089,7 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93556
94089
|
lines.push(...renderQuestionCard(question ?? { key, messageIndex: 0, payload: block.payload }, width));
|
|
93557
94090
|
} else if (block.type === "results-view") {
|
|
93558
94091
|
const key = ++viewIndex;
|
|
93559
|
-
if (state) lines.push(...
|
|
94092
|
+
if (state) lines.push(...pointerResultsView(state, block, key, width));
|
|
93560
94093
|
else lines.push(...renderTuiResultsViewLines(buildTuiResultsViewData(block, embeds), { viewKey: key }).flatMap((row) => wrap(row, width)));
|
|
93561
94094
|
}
|
|
93562
94095
|
}
|
|
@@ -93573,6 +94106,23 @@ function renderMessageContentStyled(content, width, embeds = /* @__PURE__ */ new
|
|
|
93573
94106
|
flush();
|
|
93574
94107
|
return lines;
|
|
93575
94108
|
}
|
|
94109
|
+
function pointerResultsView(state, descriptor, key, width) {
|
|
94110
|
+
const data = buildTuiResultsViewData(descriptor, { ...exampleEmbedMap(state), ...state.chatEmbeds });
|
|
94111
|
+
const actions = data.entries.map((entry, index) => {
|
|
94112
|
+
const alias = aliasForEmbed(state, entry.ref);
|
|
94113
|
+
return { index, title: entry.title, command: `/embed ${alias}` };
|
|
94114
|
+
}).filter((entry) => /^[\p{L}\p{N}_.:()-]{1,300}$/u.test(entry.command.slice(7)));
|
|
94115
|
+
const rows2 = renderTuiResultsViewLines(data, {
|
|
94116
|
+
viewKey: key,
|
|
94117
|
+
mode: state.resultsViewModes[key],
|
|
94118
|
+
aliasForEmbed: (id) => aliasForEmbed(state, id)
|
|
94119
|
+
});
|
|
94120
|
+
return rows2.flatMap((row, index) => {
|
|
94121
|
+
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}`));
|
|
94122
|
+
const action = index === 1 && value.startsWith(`/view ${key} `) ? { kind: "command", command: `/view ${key}` } : entry ? { kind: "command", command: entry.command } : void 0;
|
|
94123
|
+
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);
|
|
94124
|
+
});
|
|
94125
|
+
}
|
|
93576
94126
|
function renderEmbedReference(segment, width, embeds, state) {
|
|
93577
94127
|
const meta = segment.meta ?? {}, saved = embeds.get(segment.value);
|
|
93578
94128
|
const alias = state ? aliasForEmbed(state, segment.value) : segment.value;
|
|
@@ -95817,6 +96367,115 @@ async function prepareTuiMessage(client2, message) {
|
|
|
95817
96367
|
};
|
|
95818
96368
|
}
|
|
95819
96369
|
|
|
96370
|
+
// src/tuiPointerActions.ts
|
|
96371
|
+
async function handleTuiPointer(context, action, keyboard) {
|
|
96372
|
+
const { state, render } = context;
|
|
96373
|
+
if (state.textSelection || state.startup || state.privacyOffer) return;
|
|
96374
|
+
if (action.kind === "question") {
|
|
96375
|
+
await handleQuestionPointer(context, action);
|
|
96376
|
+
return;
|
|
96377
|
+
}
|
|
96378
|
+
if (action.kind === "command") {
|
|
96379
|
+
await context.command(action.command);
|
|
96380
|
+
return;
|
|
96381
|
+
}
|
|
96382
|
+
if (action.kind === "focus") {
|
|
96383
|
+
state.focus = action.focus;
|
|
96384
|
+
render();
|
|
96385
|
+
return;
|
|
96386
|
+
}
|
|
96387
|
+
if (action.kind === "key") {
|
|
96388
|
+
if (action.focus) state.focus = action.focus;
|
|
96389
|
+
else if (state.form || state.paletteOpen) state.focus = "content";
|
|
96390
|
+
await keyboard(action.chunk ?? "", { name: action.name, ctrl: action.ctrl });
|
|
96391
|
+
return;
|
|
96392
|
+
}
|
|
96393
|
+
if (!Number.isInteger(action.index) || action.index < 0) return;
|
|
96394
|
+
let index = action.index;
|
|
96395
|
+
switch (action.target) {
|
|
96396
|
+
case "sidebar": {
|
|
96397
|
+
const ids = sidebarPointerIds(state);
|
|
96398
|
+
index = action.id ? ids.indexOf(action.id) : index;
|
|
96399
|
+
if (index < 0 || !ids[index]) return;
|
|
96400
|
+
state.sidebarIndex = index;
|
|
96401
|
+
state.focus = "sidebar";
|
|
96402
|
+
break;
|
|
96403
|
+
}
|
|
96404
|
+
case "palette": {
|
|
96405
|
+
if (!state.paletteOpen) return;
|
|
96406
|
+
const actions = paletteActions(state.paletteQuery);
|
|
96407
|
+
index = action.id ? actions.findIndex((item) => item.command === action.id) : index;
|
|
96408
|
+
if (index < 0 || !actions[index]) return;
|
|
96409
|
+
state.paletteIndex = index;
|
|
96410
|
+
state.focus = "content";
|
|
96411
|
+
break;
|
|
96412
|
+
}
|
|
96413
|
+
case "form-field": {
|
|
96414
|
+
const form = state.form;
|
|
96415
|
+
if (!form || form.busy) return;
|
|
96416
|
+
index = action.id ? form.fields.findIndex((field) => field.name === action.id) : index;
|
|
96417
|
+
if (index < 0 || !form.fields[index]) return;
|
|
96418
|
+
form.fieldIndex = index;
|
|
96419
|
+
state.focus = "content";
|
|
96420
|
+
break;
|
|
96421
|
+
}
|
|
96422
|
+
case "task": {
|
|
96423
|
+
if (state.screen !== "tasks" && !(state.screen === "project" && state.projectTab === "tasks")) return;
|
|
96424
|
+
const status = action.column === void 0 ? void 0 : TASK_STATUSES[action.column];
|
|
96425
|
+
if (action.column !== void 0 && !status) return;
|
|
96426
|
+
const tasks = filterTasks(state.tasks, state.filter, status);
|
|
96427
|
+
if (!action.id && !action.activate && state.screen === "tasks") {
|
|
96428
|
+
state.taskStatusFilter = status ?? "";
|
|
96429
|
+
state.selectedIndex = Math.min(index, Math.max(0, tasks.length - 1));
|
|
96430
|
+
state.focus = "content";
|
|
96431
|
+
render();
|
|
96432
|
+
return;
|
|
96433
|
+
}
|
|
96434
|
+
index = action.id ? tasks.findIndex((task) => task.taskId === action.id) : index;
|
|
96435
|
+
if (index < 0 || !tasks[index]) return;
|
|
96436
|
+
state.taskStatusFilter = status ?? "";
|
|
96437
|
+
state.selectedIndex = index;
|
|
96438
|
+
state.focus = "content";
|
|
96439
|
+
if (state.screen === "project") state.selectedIndex = filterTasks(state.tasks, state.filter).findIndex((task) => task.taskId === tasks[index].taskId);
|
|
96440
|
+
break;
|
|
96441
|
+
}
|
|
96442
|
+
case "workflow-node": {
|
|
96443
|
+
if (state.screen !== "workflow") return;
|
|
96444
|
+
const graph = state.workflowTab === "runs" ? state.workflowRunGraph : state.activeWorkflow?.graph;
|
|
96445
|
+
const nodes = graph ? orderedWorkflowNodes(graph) : [];
|
|
96446
|
+
index = action.id ? nodes.findIndex((node) => node.id === action.id) : index;
|
|
96447
|
+
if (index < 0 || !nodes[index]) return;
|
|
96448
|
+
state.selectedWorkflowNodeIndex = index;
|
|
96449
|
+
state.focus = "content";
|
|
96450
|
+
break;
|
|
96451
|
+
}
|
|
96452
|
+
case "workflow-run": {
|
|
96453
|
+
if (state.screen !== "workflow" || state.workflowTab !== "runs") return;
|
|
96454
|
+
index = action.id ? state.workflowRuns.findIndex((run) => run.id === action.id) : index;
|
|
96455
|
+
if (index < 0 || !state.workflowRuns[index]) return;
|
|
96456
|
+
state.selectedWorkflowRunIndex = index;
|
|
96457
|
+
state.focus = "content";
|
|
96458
|
+
if (action.activate) {
|
|
96459
|
+
await keyboard("r", { name: "" });
|
|
96460
|
+
return;
|
|
96461
|
+
}
|
|
96462
|
+
break;
|
|
96463
|
+
}
|
|
96464
|
+
case "content":
|
|
96465
|
+
if (action.id) {
|
|
96466
|
+
if (state.screen !== "project" || state.projectTab !== "files") return;
|
|
96467
|
+
index = filteredProjectFiles(state.projectFiles, state.filter).findIndex((file) => file.id === action.id);
|
|
96468
|
+
if (index < 0) return;
|
|
96469
|
+
}
|
|
96470
|
+
state.selectedIndex = index;
|
|
96471
|
+
state.focus = "content";
|
|
96472
|
+
break;
|
|
96473
|
+
}
|
|
96474
|
+
state.followSelection = true;
|
|
96475
|
+
if (action.activate) await keyboard(action.chunk ?? "", { name: action.name ?? "return" });
|
|
96476
|
+
else render();
|
|
96477
|
+
}
|
|
96478
|
+
|
|
95820
96479
|
// src/tui.ts
|
|
95821
96480
|
function defaultModeForStreams(input, output) {
|
|
95822
96481
|
return input.isTTY === true && output.isTTY === true ? "tui" : "quickstart";
|
|
@@ -95919,6 +96578,10 @@ async function runTui(client2, terminal = new TuiTerminal(), startupServices) {
|
|
|
95919
96578
|
return;
|
|
95920
96579
|
}
|
|
95921
96580
|
void (async () => {
|
|
96581
|
+
if (key.name === "mouseclick") {
|
|
96582
|
+
await handleKey({ chunk, key, state, client: client2, terminal, render, finish });
|
|
96583
|
+
return;
|
|
96584
|
+
}
|
|
95922
96585
|
if (await startup.handleKey(chunk, key)) return;
|
|
95923
96586
|
await handleKey({ chunk, key, state, client: client2, terminal, render, finish });
|
|
95924
96587
|
})().catch((error) => {
|
|
@@ -95957,6 +96620,12 @@ async function handleKey(params) {
|
|
|
95957
96620
|
command: (command) => handleCommand({ command, state, client: client2, terminal, render, finish }),
|
|
95958
96621
|
send: (message, options) => sendTuiMessage({ message, state, client: client2, render, questionAnswer: options?.questionAnswer })
|
|
95959
96622
|
};
|
|
96623
|
+
if (key.name === "mouseclick") {
|
|
96624
|
+
if (!key.mouse || key.ctrl || key.meta || key.shift) return;
|
|
96625
|
+
const action = pointerTargetAt(state, key.mouse.column, key.mouse.row, terminal.width, terminal.height);
|
|
96626
|
+
if (action) await handleTuiPointer(context, action, (text7, pressed) => handleKey({ ...params, chunk: text7, key: pressed }));
|
|
96627
|
+
return;
|
|
96628
|
+
}
|
|
95960
96629
|
if (await handleWorkspaceKey(context, chunk, key)) return;
|
|
95961
96630
|
if (key.name === "escape") {
|
|
95962
96631
|
if (state.workflowEdit) {
|