@pellux/goodvibes-agent 1.0.38 → 1.0.40
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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Product-facing release notes for GoodVibes Agent.
|
|
4
4
|
|
|
5
|
+
## 1.0.40 - 2026-06-04
|
|
6
|
+
|
|
7
|
+
- Onboarding now uses a dedicated fullscreen workspace renderer copied from the settings-style workspace, so setup can be tuned without changing Settings, MCP, or Agent workspaces.
|
|
8
|
+
- First-run setup keeps the settings-style left rail, detail pane, field pane, and footer while the shell gives it the full terminal height, hiding the prompt/input area until setup is complete.
|
|
9
|
+
|
|
10
|
+
## 1.0.39 - 2026-06-04
|
|
11
|
+
|
|
12
|
+
- Removed the body-scoped onboarding overlay fallback so onboarding can only render through the shell fullscreen composite.
|
|
13
|
+
- Added regression coverage for the fullscreen onboarding composite and nested model workspace composite.
|
|
14
|
+
|
|
5
15
|
## 1.0.38 - 2026-06-04
|
|
6
16
|
|
|
7
17
|
- Onboarding now uses the shared fullscreen workspace surface so it owns the full terminal height, including the composer area.
|
package/dist/package/main.js
CHANGED
|
@@ -817087,7 +817087,7 @@ var createStyledCell = (char, overrides = {}) => ({
|
|
|
817087
817087
|
// src/version.ts
|
|
817088
817088
|
import { readFileSync } from "fs";
|
|
817089
817089
|
import { join } from "path";
|
|
817090
|
-
var _version = "1.0.
|
|
817090
|
+
var _version = "1.0.40";
|
|
817091
817091
|
try {
|
|
817092
817092
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf-8"));
|
|
817093
817093
|
_version = typeof pkg.version === "string" ? pkg.version : _version;
|
|
@@ -906062,311 +906062,13 @@ function renderAutocompleteOverlay(autocomplete, width, viewportHeight = 24) {
|
|
|
906062
906062
|
return lines;
|
|
906063
906063
|
}
|
|
906064
906064
|
|
|
906065
|
-
// src/renderer/onboarding/onboarding-wizard.ts
|
|
906066
|
-
function modeLabel(mode) {
|
|
906067
|
-
if (mode === "edit")
|
|
906068
|
-
return "Edit existing";
|
|
906069
|
-
if (mode === "reopen")
|
|
906070
|
-
return "Reopen review";
|
|
906071
|
-
return "New setup";
|
|
906072
|
-
}
|
|
906073
|
-
function changedScreensLabel(wizard) {
|
|
906074
|
-
if (wizard.dirtyStepCount === 0)
|
|
906075
|
-
return "no changes";
|
|
906076
|
-
if (wizard.dirtyStepCount === 1)
|
|
906077
|
-
return "1 changed screen";
|
|
906078
|
-
return `${wizard.dirtyStepCount} changed screens`;
|
|
906079
|
-
}
|
|
906080
|
-
function stepGlyph(wizard, step, stepIndex) {
|
|
906081
|
-
if (stepIndex === wizard.stepIndex)
|
|
906082
|
-
return { glyph: GLYPHS.navigation.selected, fg: FULLSCREEN_PALETTE.info };
|
|
906083
|
-
const total = wizard.getStepFieldCount(stepIndex);
|
|
906084
|
-
const completed = wizard.getCompletedFieldCount(stepIndex);
|
|
906085
|
-
if (wizard.isStepDirty(stepIndex))
|
|
906086
|
-
return { glyph: GLYPHS.status.review, fg: FULLSCREEN_PALETTE.warn };
|
|
906087
|
-
if (total > 0 && completed === total)
|
|
906088
|
-
return { glyph: GLYPHS.status.success, fg: FULLSCREEN_PALETTE.good };
|
|
906089
|
-
return { glyph: GLYPHS.status.pending, fg: FULLSCREEN_PALETTE.muted };
|
|
906090
|
-
}
|
|
906091
|
-
function fieldRowPrefix(wizard, field, selected) {
|
|
906092
|
-
if (selected)
|
|
906093
|
-
return `${GLYPHS.navigation.selected} `;
|
|
906094
|
-
if (wizard.isFieldDirty(field.id))
|
|
906095
|
-
return `${GLYPHS.status.skipped} `;
|
|
906096
|
-
if (field.kind === "checklist")
|
|
906097
|
-
return wizard.getFieldValue(field) ? `${GLYPHS.status.success} ` : "\u25A1 ";
|
|
906098
|
-
if (field.kind === "acknowledgement")
|
|
906099
|
-
return wizard.getFieldValue(field) ? `${GLYPHS.status.success} ` : "\u25A1 ";
|
|
906100
|
-
if (field.kind === "action")
|
|
906101
|
-
return `${GLYPHS.navigation.next} `;
|
|
906102
|
-
if (field.kind === "radio")
|
|
906103
|
-
return `${GLYPHS.status.active} `;
|
|
906104
|
-
return " ";
|
|
906105
|
-
}
|
|
906106
|
-
function fieldColor(wizard, field, selected) {
|
|
906107
|
-
if (selected)
|
|
906108
|
-
return FULLSCREEN_PALETTE.text;
|
|
906109
|
-
if (field.kind === "status" || field.kind === "modelPicker")
|
|
906110
|
-
return FULLSCREEN_PALETTE.info;
|
|
906111
|
-
if (field.kind === "masked")
|
|
906112
|
-
return FULLSCREEN_PALETTE.warn;
|
|
906113
|
-
if (field.kind === "acknowledgement")
|
|
906114
|
-
return wizard.getFieldValue(field) ? FULLSCREEN_PALETTE.good : FULLSCREEN_PALETTE.warn;
|
|
906115
|
-
if (field.kind === "checklist")
|
|
906116
|
-
return wizard.getFieldValue(field) ? FULLSCREEN_PALETTE.good : FULLSCREEN_PALETTE.muted;
|
|
906117
|
-
if (wizard.getFieldValueLabel(field) === "Missing")
|
|
906118
|
-
return FULLSCREEN_PALETTE.warn;
|
|
906119
|
-
return FULLSCREEN_PALETTE.text;
|
|
906120
|
-
}
|
|
906121
|
-
function formatEditingValue(value, multiline) {
|
|
906122
|
-
if (!multiline)
|
|
906123
|
-
return value;
|
|
906124
|
-
const lines = value.split(/\r?\n/);
|
|
906125
|
-
if (lines.length <= 1)
|
|
906126
|
-
return value;
|
|
906127
|
-
const preview4 = lines[lines.length - 1] ?? "";
|
|
906128
|
-
return `${preview4} (${lines.length} lines)`;
|
|
906129
|
-
}
|
|
906130
|
-
function fieldHint(wizard, field, selected) {
|
|
906131
|
-
if (selected && wizard.isEditingTextField() && wizard.editingFieldId === field.id && (field.kind === "text" || field.kind === "masked")) {
|
|
906132
|
-
const rawValue = wizard.editBuffer.length > 0 ? wizard.editBuffer : field.placeholder;
|
|
906133
|
-
const editingValue = field.kind === "masked" && wizard.editBuffer.length > 0 ? "\u2022".repeat(Math.min(12, Math.max(4, wizard.editBuffer.length))) : formatEditingValue(rawValue, field.kind === "text" && field.multiline === true);
|
|
906134
|
-
return `Editing: ${editingValue}${GLYPHS.surface.cursor}`;
|
|
906135
|
-
}
|
|
906136
|
-
if (selected && field.kind === "modelPicker")
|
|
906137
|
-
return `${field.hint} Press Enter to open picker.`;
|
|
906138
|
-
if (selected && field.kind === "text") {
|
|
906139
|
-
return field.multiline === true ? `${field.hint} Press Enter to edit; Ctrl-J inserts a new line.` : `${field.hint} Press Enter to edit inline.`;
|
|
906140
|
-
}
|
|
906141
|
-
if (selected && field.kind === "masked")
|
|
906142
|
-
return `${field.hint} Press Enter to edit inline.`;
|
|
906143
|
-
return field.hint;
|
|
906144
|
-
}
|
|
906145
|
-
function selectedFieldText(wizard) {
|
|
906146
|
-
if (wizard.isEditingTextField() && wizard.editingFieldId !== null) {
|
|
906147
|
-
const editingField = wizard.getFieldById(wizard.editingFieldId);
|
|
906148
|
-
if (editingField) {
|
|
906149
|
-
return {
|
|
906150
|
-
title: `Editing: ${editingField.label}`,
|
|
906151
|
-
hint: fieldHint(wizard, editingField, true)
|
|
906152
|
-
};
|
|
906153
|
-
}
|
|
906154
|
-
}
|
|
906155
|
-
const field = wizard.getSelectedField();
|
|
906156
|
-
if (!field)
|
|
906157
|
-
return { title: "Selected: none", hint: "No selectable row is active on this screen." };
|
|
906158
|
-
return {
|
|
906159
|
-
title: `Selected: ${field.label} [${wizard.getFieldValueLabel(field)}]`,
|
|
906160
|
-
hint: fieldHint(wizard, field, true)
|
|
906161
|
-
};
|
|
906162
|
-
}
|
|
906163
|
-
function footerText4(wizard) {
|
|
906164
|
-
if (wizard.isEditingTextField()) {
|
|
906165
|
-
return wizard.isEditingMultilineTextField() ? "Controls: [Enter] save \xB7 [Ctrl-J] new line \xB7 [Esc] cancel \xB7 [Backspace] delete \xB7 [Del/Ctrl+U] clear" : "Controls: [Enter] save \xB7 [Esc] cancel \xB7 [Backspace] delete \xB7 [Del/Ctrl+U] clear";
|
|
906166
|
-
}
|
|
906167
|
-
return "Controls: [Enter] toggle/open \xB7 [Esc] close \xB7 [Tab/Shift+Tab] screen \xB7 [Up/Down] move \xB7 [Del/Ctrl+U] clear";
|
|
906168
|
-
}
|
|
906169
|
-
function controlsText(wizard) {
|
|
906170
|
-
if (wizard.isEditingTextField()) {
|
|
906171
|
-
return wizard.isEditingMultilineTextField() ? "Controls: Enter saves, Ctrl-J inserts a line, Esc cancels, Backspace deletes, Del clears." : "Controls: Enter saves, Esc cancels, Backspace deletes, Del clears.";
|
|
906172
|
-
}
|
|
906173
|
-
return "Controls: Enter selects, Del clears, Tab moves.";
|
|
906174
|
-
}
|
|
906175
|
-
function buildFieldRows(wizard, visibleFields, capacity) {
|
|
906176
|
-
wizard.ensureSelectionVisible(visibleFields);
|
|
906177
|
-
const fields = wizard.currentStep.fields;
|
|
906178
|
-
const rows = [];
|
|
906179
|
-
if (fields.length === 0 || capacity <= 0)
|
|
906180
|
-
return rows;
|
|
906181
|
-
const allRows = [];
|
|
906182
|
-
fields.forEach((field, absoluteIndex) => {
|
|
906183
|
-
const spacerRows = Math.max(0, field.spacerBeforeRows ?? 0);
|
|
906184
|
-
for (let index = 0;index < spacerRows; index += 1)
|
|
906185
|
-
allRows.push({ kind: "empty" });
|
|
906186
|
-
allRows.push({ kind: "field", field, absoluteIndex });
|
|
906187
|
-
});
|
|
906188
|
-
const selectedFieldIndex = wizard.getSelectedFieldIndex();
|
|
906189
|
-
const selectedRowIndex = Math.max(0, allRows.findIndex((row) => row.kind === "field" && row.absoluteIndex === selectedFieldIndex));
|
|
906190
|
-
const scrollFieldIndex = wizard.scrollOffsets[wizard.stepIndex] ?? 0;
|
|
906191
|
-
const scrollRowIndex = allRows.findIndex((row) => row.kind === "field" && row.absoluteIndex === scrollFieldIndex);
|
|
906192
|
-
const maxStart = Math.max(0, allRows.length - capacity);
|
|
906193
|
-
let start2 = Math.max(0, Math.min(scrollRowIndex >= 0 ? scrollRowIndex : 0, maxStart));
|
|
906194
|
-
if (selectedRowIndex < start2)
|
|
906195
|
-
start2 = selectedRowIndex;
|
|
906196
|
-
if (selectedRowIndex >= start2 + capacity)
|
|
906197
|
-
start2 = selectedRowIndex - capacity + 1;
|
|
906198
|
-
start2 = Math.max(0, Math.min(start2, maxStart));
|
|
906199
|
-
if (capacity > 1 && start2 > 0 && selectedRowIndex === start2)
|
|
906200
|
-
start2 = Math.max(0, start2 - 1);
|
|
906201
|
-
if (capacity > 1 && start2 + capacity < allRows.length && selectedRowIndex === start2 + capacity - 1) {
|
|
906202
|
-
start2 = Math.min(maxStart, start2 + 1);
|
|
906203
|
-
}
|
|
906204
|
-
rows.push(...allRows.slice(start2, start2 + capacity));
|
|
906205
|
-
const firstVisibleRow = rows[0];
|
|
906206
|
-
if (start2 > 0 && rows.length > 0 && !(firstVisibleRow?.kind === "field" && firstVisibleRow.absoluteIndex === selectedFieldIndex)) {
|
|
906207
|
-
rows[0] = { kind: "moreAbove", text: `${GLYPHS.navigation.moreAbove} ${start2} more above` };
|
|
906208
|
-
}
|
|
906209
|
-
const hiddenBelow = Math.max(0, allRows.length - (start2 + capacity));
|
|
906210
|
-
const lastVisibleRow = rows[rows.length - 1];
|
|
906211
|
-
if (hiddenBelow > 0 && rows.length > 0 && !(lastVisibleRow?.kind === "field" && lastVisibleRow.absoluteIndex === selectedFieldIndex)) {
|
|
906212
|
-
rows[rows.length - 1] = { kind: "moreBelow", text: `${GLYPHS.navigation.moreBelow} ${hiddenBelow} more below` };
|
|
906213
|
-
}
|
|
906214
|
-
while (rows.length < capacity)
|
|
906215
|
-
rows.push({ kind: "empty" });
|
|
906216
|
-
return rows.slice(0, capacity);
|
|
906217
|
-
}
|
|
906218
|
-
function pushWrapped(rows, text, width, options = {}) {
|
|
906219
|
-
if (text.length === 0) {
|
|
906220
|
-
rows.push({ text: "", kind: "empty" });
|
|
906221
|
-
return;
|
|
906222
|
-
}
|
|
906223
|
-
for (const line2 of wrapText(text, Math.max(1, width))) {
|
|
906224
|
-
rows.push({ text: line2, ...options });
|
|
906225
|
-
}
|
|
906226
|
-
}
|
|
906227
|
-
function buildStepRows(wizard, height) {
|
|
906228
|
-
const rendered = wizard.steps.map((step, stepIndex) => {
|
|
906229
|
-
const selected = stepIndex === wizard.stepIndex;
|
|
906230
|
-
const state4 = stepGlyph(wizard, step, stepIndex);
|
|
906231
|
-
const completion = `${wizard.getCompletedFieldCount(stepIndex)}/${wizard.getStepFieldCount(stepIndex)}`;
|
|
906232
|
-
return {
|
|
906233
|
-
text: `${state4.glyph} ${stepIndex + 1}. ${step.shortLabel} ${completion}`,
|
|
906234
|
-
selected,
|
|
906235
|
-
kind: "item",
|
|
906236
|
-
fg: state4.fg,
|
|
906237
|
-
bold: selected
|
|
906238
|
-
};
|
|
906239
|
-
});
|
|
906240
|
-
const visible = Math.max(1, height);
|
|
906241
|
-
const window3 = stableWindow(rendered.length, wizard.stepIndex, visible);
|
|
906242
|
-
const rows = rendered.slice(window3.start, window3.end);
|
|
906243
|
-
if (window3.start > 0 && rows.length > 0) {
|
|
906244
|
-
rows[0] = { text: `${GLYPHS.navigation.moreAbove} ${window3.start} more step(s) above`, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
|
|
906245
|
-
}
|
|
906246
|
-
if (window3.end < rendered.length && rows.length > 0) {
|
|
906247
|
-
rows[rows.length - 1] = { text: `${GLYPHS.navigation.moreBelow} ${rendered.length - window3.end} more step(s) below`, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
|
|
906248
|
-
}
|
|
906249
|
-
while (rows.length < height)
|
|
906250
|
-
rows.push({ text: "", kind: "empty" });
|
|
906251
|
-
return rows.slice(0, height);
|
|
906252
|
-
}
|
|
906253
|
-
function buildContextRows2(wizard, width) {
|
|
906254
|
-
const step = wizard.currentStep;
|
|
906255
|
-
const selected = selectedFieldText(wizard);
|
|
906256
|
-
const rows = [
|
|
906257
|
-
{ text: step.title, fg: FULLSCREEN_PALETTE.title, bold: true }
|
|
906258
|
-
];
|
|
906259
|
-
const pushSummaryRows = () => {
|
|
906260
|
-
rows.push({ text: "Summary", fg: FULLSCREEN_PALETTE.subtitle, bold: true });
|
|
906261
|
-
rows.push({ text: step.summaryTitle, fg: FULLSCREEN_PALETTE.info, bold: true });
|
|
906262
|
-
for (const line2 of step.summaryLines.slice(0, 4)) {
|
|
906263
|
-
pushWrapped(rows, line2, width, { fg: FULLSCREEN_PALETTE.text });
|
|
906264
|
-
}
|
|
906265
|
-
rows.push({
|
|
906266
|
-
text: `Fields ${wizard.getCompletedFieldCount(wizard.stepIndex)}/${wizard.getStepFieldCount(wizard.stepIndex)} complete \xB7 ${changedScreensLabel(wizard)}`,
|
|
906267
|
-
fg: wizard.dirtyStepCount > 0 ? FULLSCREEN_PALETTE.warn : FULLSCREEN_PALETTE.muted
|
|
906268
|
-
});
|
|
906269
|
-
};
|
|
906270
|
-
const pushSelectedRows = () => {
|
|
906271
|
-
rows.push({ text: selected.title, fg: FULLSCREEN_PALETTE.info, bold: true });
|
|
906272
|
-
pushWrapped(rows, selected.hint, width, { fg: FULLSCREEN_PALETTE.text });
|
|
906273
|
-
pushWrapped(rows, controlsText(wizard), width, { fg: FULLSCREEN_PALETTE.info });
|
|
906274
|
-
};
|
|
906275
|
-
pushWrapped(rows, step.description, width, { fg: FULLSCREEN_PALETTE.text });
|
|
906276
|
-
rows.push({ text: "", kind: "empty" });
|
|
906277
|
-
if (wizard.isEditingTextField()) {
|
|
906278
|
-
pushSelectedRows();
|
|
906279
|
-
rows.push({ text: "", kind: "empty" });
|
|
906280
|
-
pushSummaryRows();
|
|
906281
|
-
} else {
|
|
906282
|
-
pushSummaryRows();
|
|
906283
|
-
rows.push({ text: "", kind: "empty" });
|
|
906284
|
-
pushSelectedRows();
|
|
906285
|
-
}
|
|
906286
|
-
if (wizard.hydrationPending || wizard.hydrationError !== null || wizard.applyFeedback !== null) {
|
|
906287
|
-
rows.push({ text: "", kind: "empty" });
|
|
906288
|
-
}
|
|
906289
|
-
if (wizard.hydrationPending) {
|
|
906290
|
-
rows.push({ text: "Loading current settings...", fg: FULLSCREEN_PALETTE.info, bold: true });
|
|
906291
|
-
}
|
|
906292
|
-
if (wizard.hydrationError !== null) {
|
|
906293
|
-
pushWrapped(rows, `Current settings could not load: ${wizard.hydrationError}`, width, { fg: FULLSCREEN_PALETTE.bad, bold: true });
|
|
906294
|
-
}
|
|
906295
|
-
if (wizard.applyFeedback !== null) {
|
|
906296
|
-
const feedbackColor = wizard.applyFeedback.severity === "error" ? FULLSCREEN_PALETTE.bad : wizard.applyFeedback.severity === "warning" ? FULLSCREEN_PALETTE.warn : FULLSCREEN_PALETTE.info;
|
|
906297
|
-
rows.push({ text: wizard.applyFeedback.title, fg: feedbackColor, bold: true });
|
|
906298
|
-
pushWrapped(rows, wizard.applyFeedback.summary, width, { fg: FULLSCREEN_PALETTE.text });
|
|
906299
|
-
for (const message of wizard.applyFeedback.messages) {
|
|
906300
|
-
pushWrapped(rows, message, width, { fg: FULLSCREEN_PALETTE.muted });
|
|
906301
|
-
}
|
|
906302
|
-
}
|
|
906303
|
-
return rows;
|
|
906304
|
-
}
|
|
906305
|
-
function formatFieldRowText(wizard, field, selected, width) {
|
|
906306
|
-
const badge = `[${wizard.getFieldValueLabel(field)}]`;
|
|
906307
|
-
const badgeWidth = getDisplayWidth(badge);
|
|
906308
|
-
const labelWidth = Math.max(1, width - badgeWidth - 2);
|
|
906309
|
-
const label = truncateDisplay(`${fieldRowPrefix(wizard, field, selected)}${field.label}`, labelWidth);
|
|
906310
|
-
return `${label}${" ".repeat(Math.max(1, width - getDisplayWidth(label) - badgeWidth))}${badge}`;
|
|
906311
|
-
}
|
|
906312
|
-
function buildControlRows2(wizard, width, height) {
|
|
906313
|
-
const visibleFields = Math.max(1, height);
|
|
906314
|
-
const fieldRows = buildFieldRows(wizard, visibleFields, height);
|
|
906315
|
-
const rows = fieldRows.map((row) => {
|
|
906316
|
-
if (row.kind === "empty")
|
|
906317
|
-
return { text: "", kind: "empty" };
|
|
906318
|
-
if (row.kind === "moreAbove" || row.kind === "moreBelow") {
|
|
906319
|
-
return { text: row.text, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
|
|
906320
|
-
}
|
|
906321
|
-
const selected = row.absoluteIndex === wizard.getSelectedFieldIndex();
|
|
906322
|
-
return {
|
|
906323
|
-
text: formatFieldRowText(wizard, row.field, selected, width),
|
|
906324
|
-
selected,
|
|
906325
|
-
kind: "item",
|
|
906326
|
-
fg: fieldColor(wizard, row.field, selected),
|
|
906327
|
-
bold: selected || row.field.kind === "action"
|
|
906328
|
-
};
|
|
906329
|
-
});
|
|
906330
|
-
while (rows.length < height)
|
|
906331
|
-
rows.push({ text: "", kind: "empty" });
|
|
906332
|
-
return rows.slice(0, height);
|
|
906333
|
-
}
|
|
906334
|
-
function renderOnboardingWizard(wizard, width, viewportHeight) {
|
|
906335
|
-
const layoutOptions = {
|
|
906336
|
-
width,
|
|
906337
|
-
height: viewportHeight,
|
|
906338
|
-
leftWidth: width < 90 ? undefined : 30,
|
|
906339
|
-
contextRatio: 0.42,
|
|
906340
|
-
minContextRows: 8
|
|
906341
|
-
};
|
|
906342
|
-
const metrics = getFullscreenWorkspaceMetrics(layoutOptions);
|
|
906343
|
-
return renderFullscreenWorkspace({
|
|
906344
|
-
width,
|
|
906345
|
-
height: viewportHeight,
|
|
906346
|
-
title: "GoodVibes Agent / Onboarding Wizard",
|
|
906347
|
-
stateLabel: `${modeLabel(wizard.mode)} \xB7 ${wizard.stepIndex + 1}/${wizard.steps.length} \xB7 ${changedScreensLabel(wizard)}`,
|
|
906348
|
-
leftHeader: "Steps",
|
|
906349
|
-
mainHeader: wizard.currentStep.title,
|
|
906350
|
-
leftRows: buildStepRows(wizard, metrics.bodyRows),
|
|
906351
|
-
contextRows: buildContextRows2(wizard, metrics.contextWidth),
|
|
906352
|
-
controlRows: buildControlRows2(wizard, metrics.contextWidth, metrics.controlRows),
|
|
906353
|
-
footer: footerText4(wizard),
|
|
906354
|
-
leftWidth: layoutOptions.leftWidth,
|
|
906355
|
-
contextRatio: layoutOptions.contextRatio,
|
|
906356
|
-
minContextRows: layoutOptions.minContextRows
|
|
906357
|
-
});
|
|
906358
|
-
}
|
|
906359
|
-
|
|
906360
906065
|
// src/renderer/conversation-overlays.ts
|
|
906361
906066
|
function applyConversationOverlays(viewport, context) {
|
|
906362
906067
|
const { input, conversation, commandRegistry, keybindingsManager, conversationWidth, viewportHeight, contextWindow } = context;
|
|
906363
906068
|
let next = viewport;
|
|
906364
906069
|
const bottomDockInset = 1 + (input.searchManager.active || input.historySearch.active ? 1 : 0);
|
|
906365
906070
|
if (input.onboardingWizard.active) {
|
|
906366
|
-
|
|
906367
|
-
next = replaceViewportWithOverlay(lines, conversationWidth, viewportHeight);
|
|
906368
|
-
if (!input.modelPicker.active)
|
|
906369
|
-
return next;
|
|
906071
|
+
return next;
|
|
906370
906072
|
}
|
|
906371
906073
|
if (input.filePicker.active) {
|
|
906372
906074
|
const lines = renderFilePickerOverlay(input.filePicker, conversationWidth, viewportHeight);
|
|
@@ -906717,6 +906419,423 @@ function handleBlockingShellInput(options) {
|
|
|
906717
906419
|
return { handled: false, pendingPermission, recoveryPending };
|
|
906718
906420
|
}
|
|
906719
906421
|
|
|
906422
|
+
// src/renderer/onboarding/onboarding-workspace.ts
|
|
906423
|
+
var WORKSPACE_PALETTE2 = FULLSCREEN_PALETTE;
|
|
906424
|
+
function drawVertical3(line2, x2, bg = "") {
|
|
906425
|
+
if (x2 <= 0 || x2 >= line2.length - 1)
|
|
906426
|
+
return;
|
|
906427
|
+
drawVerticalRule(line2, x2, WORKSPACE_PALETTE2.border, bg);
|
|
906428
|
+
}
|
|
906429
|
+
function drawHorizontalRange2(line2, startX, endX, bg = "") {
|
|
906430
|
+
drawHorizontalRule(line2, Math.max(1, startX), Math.min(line2.length - 2, endX), WORKSPACE_PALETTE2.border, bg);
|
|
906431
|
+
}
|
|
906432
|
+
function leftWidthFor2(width, explicit) {
|
|
906433
|
+
if (explicit !== undefined)
|
|
906434
|
+
return clamp3(explicit, 14, Math.max(14, width - 24));
|
|
906435
|
+
return width < 80 ? clamp3(Math.round(width * 0.32), 14, Math.max(14, width - 24)) : clamp3(Math.round(width * 0.22), 24, 34);
|
|
906436
|
+
}
|
|
906437
|
+
function getFullscreenWorkspaceMetrics2(options) {
|
|
906438
|
+
const safeWidth = Math.max(1, options.width);
|
|
906439
|
+
const safeHeight = Math.max(12, options.height);
|
|
906440
|
+
const leftWidth = leftWidthFor2(safeWidth, options.leftWidth);
|
|
906441
|
+
const centerWidth = Math.max(20, safeWidth - leftWidth - 3);
|
|
906442
|
+
const bodyTop = 3;
|
|
906443
|
+
const footerY = safeHeight - 2;
|
|
906444
|
+
const bodyRows = Math.max(4, footerY - bodyTop);
|
|
906445
|
+
const contextWidth = Math.max(10, centerWidth - 2);
|
|
906446
|
+
const maxContextRows = Math.max(3, bodyRows - 4);
|
|
906447
|
+
const minContextRows = clamp3(options.minContextRows ?? 10, 3, maxContextRows);
|
|
906448
|
+
const contextRows = clamp3(Math.round(bodyRows * (options.contextRatio ?? 0.4)), Math.min(minContextRows, maxContextRows), maxContextRows);
|
|
906449
|
+
const controlRows = Math.max(3, bodyRows - contextRows - 1);
|
|
906450
|
+
return { safeWidth, safeHeight, leftWidth, centerWidth, bodyRows, contextWidth, contextRows, controlRows };
|
|
906451
|
+
}
|
|
906452
|
+
function rowFg2(row, fallback) {
|
|
906453
|
+
if (row.fg)
|
|
906454
|
+
return row.fg;
|
|
906455
|
+
if (row.kind === "group")
|
|
906456
|
+
return WORKSPACE_PALETTE2.subtitle;
|
|
906457
|
+
if (row.kind === "more")
|
|
906458
|
+
return WORKSPACE_PALETTE2.dim;
|
|
906459
|
+
return fallback;
|
|
906460
|
+
}
|
|
906461
|
+
function renderFullscreenWorkspace2(options) {
|
|
906462
|
+
const { safeWidth, safeHeight, leftWidth, centerWidth, bodyRows, contextWidth, contextRows } = getFullscreenWorkspaceMetrics2(options);
|
|
906463
|
+
const leftStart = 1;
|
|
906464
|
+
const dividerX = leftWidth + 1;
|
|
906465
|
+
const centerStart = dividerX + 1;
|
|
906466
|
+
const centerEnd = safeWidth - 2;
|
|
906467
|
+
const bodyTop = 3;
|
|
906468
|
+
const separatorY = bodyTop + contextRows;
|
|
906469
|
+
const lines = [];
|
|
906470
|
+
const top = borderLine(safeWidth, GLYPHS.frame.topLeft, GLYPHS.frame.horizontal, GLYPHS.frame.topRight);
|
|
906471
|
+
writeText2(top, 2, safeWidth - 4, ` ${options.title} `, { fg: WORKSPACE_PALETTE2.title, bold: true });
|
|
906472
|
+
if (options.stateLabel) {
|
|
906473
|
+
writeText2(top, Math.max(2, safeWidth - options.stateLabel.length - 4), options.stateLabel.length, options.stateLabel, {
|
|
906474
|
+
fg: WORKSPACE_PALETTE2.subtitle
|
|
906475
|
+
});
|
|
906476
|
+
}
|
|
906477
|
+
lines.push(top);
|
|
906478
|
+
const header = contentLine(safeWidth, WORKSPACE_PALETTE2.footerBg);
|
|
906479
|
+
drawVertical3(header, dividerX, WORKSPACE_PALETTE2.footerBg);
|
|
906480
|
+
writeText2(header, leftStart + 1, leftWidth - 2, options.leftHeader, {
|
|
906481
|
+
fg: WORKSPACE_PALETTE2.subtitle,
|
|
906482
|
+
bold: true,
|
|
906483
|
+
bg: WORKSPACE_PALETTE2.footerBg
|
|
906484
|
+
});
|
|
906485
|
+
writeText2(header, centerStart + 1, centerWidth - 2, options.mainHeader, {
|
|
906486
|
+
fg: WORKSPACE_PALETTE2.subtitle,
|
|
906487
|
+
bold: true,
|
|
906488
|
+
bg: WORKSPACE_PALETTE2.footerBg
|
|
906489
|
+
});
|
|
906490
|
+
lines.push(header);
|
|
906491
|
+
const headerSep = contentLine(safeWidth, "");
|
|
906492
|
+
drawVertical3(headerSep, dividerX);
|
|
906493
|
+
drawHorizontalRange2(headerSep, 1, safeWidth - 2);
|
|
906494
|
+
lines.push(headerSep);
|
|
906495
|
+
for (let row = 0;row < bodyRows; row += 1) {
|
|
906496
|
+
const y2 = bodyTop + row;
|
|
906497
|
+
const inContext = y2 < separatorY;
|
|
906498
|
+
const inSeparator = y2 === separatorY;
|
|
906499
|
+
const bg = inSeparator ? "" : inContext ? WORKSPACE_PALETTE2.contextBg : WORKSPACE_PALETTE2.controlsBg;
|
|
906500
|
+
const line2 = contentLine(safeWidth, bg);
|
|
906501
|
+
fillRange(line2, 1, dividerX - 1, WORKSPACE_PALETTE2.categoryBg);
|
|
906502
|
+
drawVertical3(line2, dividerX, bg);
|
|
906503
|
+
const leftRow = options.leftRows[row] ?? { text: "", kind: "empty" };
|
|
906504
|
+
if (leftRow.selected)
|
|
906505
|
+
fillRange(line2, leftStart, dividerX - 1, WORKSPACE_PALETTE2.selectedBg);
|
|
906506
|
+
writeText2(line2, leftStart + 1, leftWidth - 3, leftRow.text, {
|
|
906507
|
+
fg: leftRow.selected ? WORKSPACE_PALETTE2.text : rowFg2(leftRow, WORKSPACE_PALETTE2.muted),
|
|
906508
|
+
bg: leftRow.selected ? WORKSPACE_PALETTE2.selectedBg : WORKSPACE_PALETTE2.categoryBg,
|
|
906509
|
+
bold: leftRow.bold ?? (leftRow.selected || leftRow.kind === "group"),
|
|
906510
|
+
dim: leftRow.dim
|
|
906511
|
+
});
|
|
906512
|
+
if (inSeparator) {
|
|
906513
|
+
drawHorizontalRange2(line2, centerStart, centerEnd);
|
|
906514
|
+
} else if (inContext) {
|
|
906515
|
+
const contextRow = options.contextRows[row] ?? { text: "", kind: "empty" };
|
|
906516
|
+
writeText2(line2, centerStart + 1, contextWidth, contextRow.text, {
|
|
906517
|
+
fg: rowFg2(contextRow, WORKSPACE_PALETTE2.text),
|
|
906518
|
+
bg,
|
|
906519
|
+
bold: contextRow.bold,
|
|
906520
|
+
dim: contextRow.dim ?? contextRow.text.length === 0
|
|
906521
|
+
});
|
|
906522
|
+
} else {
|
|
906523
|
+
const controlRow = options.controlRows[row - contextRows - 1] ?? { text: "", kind: "empty" };
|
|
906524
|
+
if (controlRow.selected)
|
|
906525
|
+
fillRange(line2, centerStart, centerEnd, WORKSPACE_PALETTE2.selectedBg);
|
|
906526
|
+
writeText2(line2, centerStart + 1, contextWidth, controlRow.text, {
|
|
906527
|
+
fg: controlRow.selected ? WORKSPACE_PALETTE2.text : rowFg2(controlRow, WORKSPACE_PALETTE2.text),
|
|
906528
|
+
bg: controlRow.selected ? WORKSPACE_PALETTE2.selectedBg : bg,
|
|
906529
|
+
bold: controlRow.bold ?? controlRow.selected,
|
|
906530
|
+
dim: controlRow.dim ?? controlRow.text.length === 0
|
|
906531
|
+
});
|
|
906532
|
+
}
|
|
906533
|
+
lines.push(line2);
|
|
906534
|
+
}
|
|
906535
|
+
const footer = contentLine(safeWidth, WORKSPACE_PALETTE2.footerBg);
|
|
906536
|
+
writeText2(footer, 2, safeWidth - 4, options.footer, { fg: WORKSPACE_PALETTE2.muted, bg: WORKSPACE_PALETTE2.footerBg });
|
|
906537
|
+
lines.push(footer);
|
|
906538
|
+
lines.push(borderLine(safeWidth, GLYPHS.frame.bottomLeft, GLYPHS.frame.horizontal, GLYPHS.frame.bottomRight));
|
|
906539
|
+
while (lines.length < safeHeight)
|
|
906540
|
+
lines.unshift(makeLine(safeWidth));
|
|
906541
|
+
return lines.slice(-safeHeight);
|
|
906542
|
+
}
|
|
906543
|
+
|
|
906544
|
+
// src/renderer/onboarding/onboarding-wizard.ts
|
|
906545
|
+
function modeLabel(mode) {
|
|
906546
|
+
if (mode === "edit")
|
|
906547
|
+
return "Edit existing";
|
|
906548
|
+
if (mode === "reopen")
|
|
906549
|
+
return "Reopen review";
|
|
906550
|
+
return "New setup";
|
|
906551
|
+
}
|
|
906552
|
+
function changedScreensLabel(wizard) {
|
|
906553
|
+
if (wizard.dirtyStepCount === 0)
|
|
906554
|
+
return "no changes";
|
|
906555
|
+
if (wizard.dirtyStepCount === 1)
|
|
906556
|
+
return "1 changed screen";
|
|
906557
|
+
return `${wizard.dirtyStepCount} changed screens`;
|
|
906558
|
+
}
|
|
906559
|
+
function stepGlyph(wizard, step, stepIndex) {
|
|
906560
|
+
if (stepIndex === wizard.stepIndex)
|
|
906561
|
+
return { glyph: GLYPHS.navigation.selected, fg: FULLSCREEN_PALETTE.info };
|
|
906562
|
+
const total = wizard.getStepFieldCount(stepIndex);
|
|
906563
|
+
const completed = wizard.getCompletedFieldCount(stepIndex);
|
|
906564
|
+
if (wizard.isStepDirty(stepIndex))
|
|
906565
|
+
return { glyph: GLYPHS.status.review, fg: FULLSCREEN_PALETTE.warn };
|
|
906566
|
+
if (total > 0 && completed === total)
|
|
906567
|
+
return { glyph: GLYPHS.status.success, fg: FULLSCREEN_PALETTE.good };
|
|
906568
|
+
return { glyph: GLYPHS.status.pending, fg: FULLSCREEN_PALETTE.muted };
|
|
906569
|
+
}
|
|
906570
|
+
function fieldRowPrefix(wizard, field, selected) {
|
|
906571
|
+
if (selected)
|
|
906572
|
+
return `${GLYPHS.navigation.selected} `;
|
|
906573
|
+
if (wizard.isFieldDirty(field.id))
|
|
906574
|
+
return `${GLYPHS.status.skipped} `;
|
|
906575
|
+
if (field.kind === "checklist")
|
|
906576
|
+
return wizard.getFieldValue(field) ? `${GLYPHS.status.success} ` : "\u25A1 ";
|
|
906577
|
+
if (field.kind === "acknowledgement")
|
|
906578
|
+
return wizard.getFieldValue(field) ? `${GLYPHS.status.success} ` : "\u25A1 ";
|
|
906579
|
+
if (field.kind === "action")
|
|
906580
|
+
return `${GLYPHS.navigation.next} `;
|
|
906581
|
+
if (field.kind === "radio")
|
|
906582
|
+
return `${GLYPHS.status.active} `;
|
|
906583
|
+
return " ";
|
|
906584
|
+
}
|
|
906585
|
+
function fieldColor(wizard, field, selected) {
|
|
906586
|
+
if (selected)
|
|
906587
|
+
return FULLSCREEN_PALETTE.text;
|
|
906588
|
+
if (field.kind === "status" || field.kind === "modelPicker")
|
|
906589
|
+
return FULLSCREEN_PALETTE.info;
|
|
906590
|
+
if (field.kind === "masked")
|
|
906591
|
+
return FULLSCREEN_PALETTE.warn;
|
|
906592
|
+
if (field.kind === "acknowledgement")
|
|
906593
|
+
return wizard.getFieldValue(field) ? FULLSCREEN_PALETTE.good : FULLSCREEN_PALETTE.warn;
|
|
906594
|
+
if (field.kind === "checklist")
|
|
906595
|
+
return wizard.getFieldValue(field) ? FULLSCREEN_PALETTE.good : FULLSCREEN_PALETTE.muted;
|
|
906596
|
+
if (wizard.getFieldValueLabel(field) === "Missing")
|
|
906597
|
+
return FULLSCREEN_PALETTE.warn;
|
|
906598
|
+
return FULLSCREEN_PALETTE.text;
|
|
906599
|
+
}
|
|
906600
|
+
function formatEditingValue(value, multiline) {
|
|
906601
|
+
if (!multiline)
|
|
906602
|
+
return value;
|
|
906603
|
+
const lines = value.split(/\r?\n/);
|
|
906604
|
+
if (lines.length <= 1)
|
|
906605
|
+
return value;
|
|
906606
|
+
const preview4 = lines[lines.length - 1] ?? "";
|
|
906607
|
+
return `${preview4} (${lines.length} lines)`;
|
|
906608
|
+
}
|
|
906609
|
+
function fieldHint(wizard, field, selected) {
|
|
906610
|
+
if (selected && wizard.isEditingTextField() && wizard.editingFieldId === field.id && (field.kind === "text" || field.kind === "masked")) {
|
|
906611
|
+
const rawValue = wizard.editBuffer.length > 0 ? wizard.editBuffer : field.placeholder;
|
|
906612
|
+
const editingValue = field.kind === "masked" && wizard.editBuffer.length > 0 ? "\u2022".repeat(Math.min(12, Math.max(4, wizard.editBuffer.length))) : formatEditingValue(rawValue, field.kind === "text" && field.multiline === true);
|
|
906613
|
+
return `Editing: ${editingValue}${GLYPHS.surface.cursor}`;
|
|
906614
|
+
}
|
|
906615
|
+
if (selected && field.kind === "modelPicker")
|
|
906616
|
+
return `${field.hint} Press Enter to open picker.`;
|
|
906617
|
+
if (selected && field.kind === "text") {
|
|
906618
|
+
return field.multiline === true ? `${field.hint} Press Enter to edit; Ctrl-J inserts a new line.` : `${field.hint} Press Enter to edit inline.`;
|
|
906619
|
+
}
|
|
906620
|
+
if (selected && field.kind === "masked")
|
|
906621
|
+
return `${field.hint} Press Enter to edit inline.`;
|
|
906622
|
+
return field.hint;
|
|
906623
|
+
}
|
|
906624
|
+
function selectedFieldText(wizard) {
|
|
906625
|
+
if (wizard.isEditingTextField() && wizard.editingFieldId !== null) {
|
|
906626
|
+
const editingField = wizard.getFieldById(wizard.editingFieldId);
|
|
906627
|
+
if (editingField) {
|
|
906628
|
+
return {
|
|
906629
|
+
title: `Editing: ${editingField.label}`,
|
|
906630
|
+
hint: fieldHint(wizard, editingField, true)
|
|
906631
|
+
};
|
|
906632
|
+
}
|
|
906633
|
+
}
|
|
906634
|
+
const field = wizard.getSelectedField();
|
|
906635
|
+
if (!field)
|
|
906636
|
+
return { title: "Selected: none", hint: "No selectable row is active on this screen." };
|
|
906637
|
+
return {
|
|
906638
|
+
title: `Selected: ${field.label} [${wizard.getFieldValueLabel(field)}]`,
|
|
906639
|
+
hint: fieldHint(wizard, field, true)
|
|
906640
|
+
};
|
|
906641
|
+
}
|
|
906642
|
+
function footerText4(wizard) {
|
|
906643
|
+
if (wizard.isEditingTextField()) {
|
|
906644
|
+
return wizard.isEditingMultilineTextField() ? "Controls: [Enter] save \xB7 [Ctrl-J] new line \xB7 [Esc] cancel \xB7 [Backspace] delete \xB7 [Del/Ctrl+U] clear" : "Controls: [Enter] save \xB7 [Esc] cancel \xB7 [Backspace] delete \xB7 [Del/Ctrl+U] clear";
|
|
906645
|
+
}
|
|
906646
|
+
return "Controls: [Enter] toggle/open \xB7 [Esc] close \xB7 [Tab/Shift+Tab] screen \xB7 [Up/Down] move \xB7 [Del/Ctrl+U] clear";
|
|
906647
|
+
}
|
|
906648
|
+
function controlsText(wizard) {
|
|
906649
|
+
if (wizard.isEditingTextField()) {
|
|
906650
|
+
return wizard.isEditingMultilineTextField() ? "Controls: Enter saves, Ctrl-J inserts a line, Esc cancels, Backspace deletes, Del clears." : "Controls: Enter saves, Esc cancels, Backspace deletes, Del clears.";
|
|
906651
|
+
}
|
|
906652
|
+
return "Controls: Enter selects, Del clears, Tab moves.";
|
|
906653
|
+
}
|
|
906654
|
+
function buildFieldRows(wizard, visibleFields, capacity) {
|
|
906655
|
+
wizard.ensureSelectionVisible(visibleFields);
|
|
906656
|
+
const fields = wizard.currentStep.fields;
|
|
906657
|
+
const rows = [];
|
|
906658
|
+
if (fields.length === 0 || capacity <= 0)
|
|
906659
|
+
return rows;
|
|
906660
|
+
const allRows = [];
|
|
906661
|
+
fields.forEach((field, absoluteIndex) => {
|
|
906662
|
+
const spacerRows = Math.max(0, field.spacerBeforeRows ?? 0);
|
|
906663
|
+
for (let index = 0;index < spacerRows; index += 1)
|
|
906664
|
+
allRows.push({ kind: "empty" });
|
|
906665
|
+
allRows.push({ kind: "field", field, absoluteIndex });
|
|
906666
|
+
});
|
|
906667
|
+
const selectedFieldIndex = wizard.getSelectedFieldIndex();
|
|
906668
|
+
const selectedRowIndex = Math.max(0, allRows.findIndex((row) => row.kind === "field" && row.absoluteIndex === selectedFieldIndex));
|
|
906669
|
+
const scrollFieldIndex = wizard.scrollOffsets[wizard.stepIndex] ?? 0;
|
|
906670
|
+
const scrollRowIndex = allRows.findIndex((row) => row.kind === "field" && row.absoluteIndex === scrollFieldIndex);
|
|
906671
|
+
const maxStart = Math.max(0, allRows.length - capacity);
|
|
906672
|
+
let start2 = Math.max(0, Math.min(scrollRowIndex >= 0 ? scrollRowIndex : 0, maxStart));
|
|
906673
|
+
if (selectedRowIndex < start2)
|
|
906674
|
+
start2 = selectedRowIndex;
|
|
906675
|
+
if (selectedRowIndex >= start2 + capacity)
|
|
906676
|
+
start2 = selectedRowIndex - capacity + 1;
|
|
906677
|
+
start2 = Math.max(0, Math.min(start2, maxStart));
|
|
906678
|
+
if (capacity > 1 && start2 > 0 && selectedRowIndex === start2)
|
|
906679
|
+
start2 = Math.max(0, start2 - 1);
|
|
906680
|
+
if (capacity > 1 && start2 + capacity < allRows.length && selectedRowIndex === start2 + capacity - 1) {
|
|
906681
|
+
start2 = Math.min(maxStart, start2 + 1);
|
|
906682
|
+
}
|
|
906683
|
+
rows.push(...allRows.slice(start2, start2 + capacity));
|
|
906684
|
+
const firstVisibleRow = rows[0];
|
|
906685
|
+
if (start2 > 0 && rows.length > 0 && !(firstVisibleRow?.kind === "field" && firstVisibleRow.absoluteIndex === selectedFieldIndex)) {
|
|
906686
|
+
rows[0] = { kind: "moreAbove", text: `${GLYPHS.navigation.moreAbove} ${start2} more above` };
|
|
906687
|
+
}
|
|
906688
|
+
const hiddenBelow = Math.max(0, allRows.length - (start2 + capacity));
|
|
906689
|
+
const lastVisibleRow = rows[rows.length - 1];
|
|
906690
|
+
if (hiddenBelow > 0 && rows.length > 0 && !(lastVisibleRow?.kind === "field" && lastVisibleRow.absoluteIndex === selectedFieldIndex)) {
|
|
906691
|
+
rows[rows.length - 1] = { kind: "moreBelow", text: `${GLYPHS.navigation.moreBelow} ${hiddenBelow} more below` };
|
|
906692
|
+
}
|
|
906693
|
+
while (rows.length < capacity)
|
|
906694
|
+
rows.push({ kind: "empty" });
|
|
906695
|
+
return rows.slice(0, capacity);
|
|
906696
|
+
}
|
|
906697
|
+
function pushWrapped(rows, text, width, options = {}) {
|
|
906698
|
+
if (text.length === 0) {
|
|
906699
|
+
rows.push({ text: "", kind: "empty" });
|
|
906700
|
+
return;
|
|
906701
|
+
}
|
|
906702
|
+
for (const line2 of wrapText(text, Math.max(1, width))) {
|
|
906703
|
+
rows.push({ text: line2, ...options });
|
|
906704
|
+
}
|
|
906705
|
+
}
|
|
906706
|
+
function buildStepRows(wizard, height) {
|
|
906707
|
+
const rendered = wizard.steps.map((step, stepIndex) => {
|
|
906708
|
+
const selected = stepIndex === wizard.stepIndex;
|
|
906709
|
+
const state4 = stepGlyph(wizard, step, stepIndex);
|
|
906710
|
+
const completion = `${wizard.getCompletedFieldCount(stepIndex)}/${wizard.getStepFieldCount(stepIndex)}`;
|
|
906711
|
+
return {
|
|
906712
|
+
text: `${state4.glyph} ${stepIndex + 1}. ${step.shortLabel} ${completion}`,
|
|
906713
|
+
selected,
|
|
906714
|
+
kind: "item",
|
|
906715
|
+
fg: state4.fg,
|
|
906716
|
+
bold: selected
|
|
906717
|
+
};
|
|
906718
|
+
});
|
|
906719
|
+
const visible = Math.max(1, height);
|
|
906720
|
+
const window3 = stableWindow(rendered.length, wizard.stepIndex, visible);
|
|
906721
|
+
const rows = rendered.slice(window3.start, window3.end);
|
|
906722
|
+
if (window3.start > 0 && rows.length > 0) {
|
|
906723
|
+
rows[0] = { text: `${GLYPHS.navigation.moreAbove} ${window3.start} more step(s) above`, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
|
|
906724
|
+
}
|
|
906725
|
+
if (window3.end < rendered.length && rows.length > 0) {
|
|
906726
|
+
rows[rows.length - 1] = { text: `${GLYPHS.navigation.moreBelow} ${rendered.length - window3.end} more step(s) below`, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
|
|
906727
|
+
}
|
|
906728
|
+
while (rows.length < height)
|
|
906729
|
+
rows.push({ text: "", kind: "empty" });
|
|
906730
|
+
return rows.slice(0, height);
|
|
906731
|
+
}
|
|
906732
|
+
function buildContextRows2(wizard, width) {
|
|
906733
|
+
const step = wizard.currentStep;
|
|
906734
|
+
const selected = selectedFieldText(wizard);
|
|
906735
|
+
const rows = [
|
|
906736
|
+
{ text: step.title, fg: FULLSCREEN_PALETTE.title, bold: true }
|
|
906737
|
+
];
|
|
906738
|
+
const pushSummaryRows = () => {
|
|
906739
|
+
rows.push({ text: "Summary", fg: FULLSCREEN_PALETTE.subtitle, bold: true });
|
|
906740
|
+
rows.push({ text: step.summaryTitle, fg: FULLSCREEN_PALETTE.info, bold: true });
|
|
906741
|
+
for (const line2 of step.summaryLines.slice(0, 4)) {
|
|
906742
|
+
pushWrapped(rows, line2, width, { fg: FULLSCREEN_PALETTE.text });
|
|
906743
|
+
}
|
|
906744
|
+
rows.push({
|
|
906745
|
+
text: `Fields ${wizard.getCompletedFieldCount(wizard.stepIndex)}/${wizard.getStepFieldCount(wizard.stepIndex)} complete \xB7 ${changedScreensLabel(wizard)}`,
|
|
906746
|
+
fg: wizard.dirtyStepCount > 0 ? FULLSCREEN_PALETTE.warn : FULLSCREEN_PALETTE.muted
|
|
906747
|
+
});
|
|
906748
|
+
};
|
|
906749
|
+
const pushSelectedRows = () => {
|
|
906750
|
+
rows.push({ text: selected.title, fg: FULLSCREEN_PALETTE.info, bold: true });
|
|
906751
|
+
pushWrapped(rows, selected.hint, width, { fg: FULLSCREEN_PALETTE.text });
|
|
906752
|
+
pushWrapped(rows, controlsText(wizard), width, { fg: FULLSCREEN_PALETTE.info });
|
|
906753
|
+
};
|
|
906754
|
+
pushWrapped(rows, step.description, width, { fg: FULLSCREEN_PALETTE.text });
|
|
906755
|
+
rows.push({ text: "", kind: "empty" });
|
|
906756
|
+
if (wizard.isEditingTextField()) {
|
|
906757
|
+
pushSelectedRows();
|
|
906758
|
+
rows.push({ text: "", kind: "empty" });
|
|
906759
|
+
pushSummaryRows();
|
|
906760
|
+
} else {
|
|
906761
|
+
pushSummaryRows();
|
|
906762
|
+
rows.push({ text: "", kind: "empty" });
|
|
906763
|
+
pushSelectedRows();
|
|
906764
|
+
}
|
|
906765
|
+
if (wizard.hydrationPending || wizard.hydrationError !== null || wizard.applyFeedback !== null) {
|
|
906766
|
+
rows.push({ text: "", kind: "empty" });
|
|
906767
|
+
}
|
|
906768
|
+
if (wizard.hydrationPending) {
|
|
906769
|
+
rows.push({ text: "Loading current settings...", fg: FULLSCREEN_PALETTE.info, bold: true });
|
|
906770
|
+
}
|
|
906771
|
+
if (wizard.hydrationError !== null) {
|
|
906772
|
+
pushWrapped(rows, `Current settings could not load: ${wizard.hydrationError}`, width, { fg: FULLSCREEN_PALETTE.bad, bold: true });
|
|
906773
|
+
}
|
|
906774
|
+
if (wizard.applyFeedback !== null) {
|
|
906775
|
+
const feedbackColor = wizard.applyFeedback.severity === "error" ? FULLSCREEN_PALETTE.bad : wizard.applyFeedback.severity === "warning" ? FULLSCREEN_PALETTE.warn : FULLSCREEN_PALETTE.info;
|
|
906776
|
+
rows.push({ text: wizard.applyFeedback.title, fg: feedbackColor, bold: true });
|
|
906777
|
+
pushWrapped(rows, wizard.applyFeedback.summary, width, { fg: FULLSCREEN_PALETTE.text });
|
|
906778
|
+
for (const message of wizard.applyFeedback.messages) {
|
|
906779
|
+
pushWrapped(rows, message, width, { fg: FULLSCREEN_PALETTE.muted });
|
|
906780
|
+
}
|
|
906781
|
+
}
|
|
906782
|
+
return rows;
|
|
906783
|
+
}
|
|
906784
|
+
function formatFieldRowText(wizard, field, selected, width) {
|
|
906785
|
+
const badge = `[${wizard.getFieldValueLabel(field)}]`;
|
|
906786
|
+
const badgeWidth = getDisplayWidth(badge);
|
|
906787
|
+
const labelWidth = Math.max(1, width - badgeWidth - 2);
|
|
906788
|
+
const label = truncateDisplay(`${fieldRowPrefix(wizard, field, selected)}${field.label}`, labelWidth);
|
|
906789
|
+
return `${label}${" ".repeat(Math.max(1, width - getDisplayWidth(label) - badgeWidth))}${badge}`;
|
|
906790
|
+
}
|
|
906791
|
+
function buildControlRows2(wizard, width, height) {
|
|
906792
|
+
const visibleFields = Math.max(1, height);
|
|
906793
|
+
const fieldRows = buildFieldRows(wizard, visibleFields, height);
|
|
906794
|
+
const rows = fieldRows.map((row) => {
|
|
906795
|
+
if (row.kind === "empty")
|
|
906796
|
+
return { text: "", kind: "empty" };
|
|
906797
|
+
if (row.kind === "moreAbove" || row.kind === "moreBelow") {
|
|
906798
|
+
return { text: row.text, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
|
|
906799
|
+
}
|
|
906800
|
+
const selected = row.absoluteIndex === wizard.getSelectedFieldIndex();
|
|
906801
|
+
return {
|
|
906802
|
+
text: formatFieldRowText(wizard, row.field, selected, width),
|
|
906803
|
+
selected,
|
|
906804
|
+
kind: "item",
|
|
906805
|
+
fg: fieldColor(wizard, row.field, selected),
|
|
906806
|
+
bold: selected || row.field.kind === "action"
|
|
906807
|
+
};
|
|
906808
|
+
});
|
|
906809
|
+
while (rows.length < height)
|
|
906810
|
+
rows.push({ text: "", kind: "empty" });
|
|
906811
|
+
return rows.slice(0, height);
|
|
906812
|
+
}
|
|
906813
|
+
function renderOnboardingWizard(wizard, width, viewportHeight) {
|
|
906814
|
+
const layoutOptions = {
|
|
906815
|
+
width,
|
|
906816
|
+
height: viewportHeight,
|
|
906817
|
+
leftWidth: width < 90 ? undefined : 30,
|
|
906818
|
+
contextRatio: 0.42,
|
|
906819
|
+
minContextRows: 8
|
|
906820
|
+
};
|
|
906821
|
+
const metrics = getFullscreenWorkspaceMetrics2(layoutOptions);
|
|
906822
|
+
return renderFullscreenWorkspace2({
|
|
906823
|
+
width,
|
|
906824
|
+
height: viewportHeight,
|
|
906825
|
+
title: "GoodVibes Agent / Onboarding Wizard",
|
|
906826
|
+
stateLabel: `${modeLabel(wizard.mode)} \xB7 ${wizard.stepIndex + 1}/${wizard.steps.length} \xB7 ${changedScreensLabel(wizard)}`,
|
|
906827
|
+
leftHeader: "Steps",
|
|
906828
|
+
mainHeader: wizard.currentStep.title,
|
|
906829
|
+
leftRows: buildStepRows(wizard, metrics.bodyRows),
|
|
906830
|
+
contextRows: buildContextRows2(wizard, metrics.contextWidth),
|
|
906831
|
+
controlRows: buildControlRows2(wizard, metrics.contextWidth, metrics.controlRows),
|
|
906832
|
+
footer: footerText4(wizard),
|
|
906833
|
+
leftWidth: layoutOptions.leftWidth,
|
|
906834
|
+
contextRatio: layoutOptions.contextRatio,
|
|
906835
|
+
minContextRows: layoutOptions.minContextRows
|
|
906836
|
+
});
|
|
906837
|
+
}
|
|
906838
|
+
|
|
906720
906839
|
// src/shell/onboarding-fullscreen.ts
|
|
906721
906840
|
function normalizeFullscreenViewport(lines, width, height) {
|
|
906722
906841
|
const viewport = lines.slice(0, height).map((line2) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-agent",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.40",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
|
|
6
6
|
"type": "module",
|
|
@@ -19,7 +19,6 @@ import { renderProfilePickerModal } from './profile-picker-modal.ts';
|
|
|
19
19
|
import { renderBookmarkModal } from './bookmark-modal.ts';
|
|
20
20
|
import { renderHelpOverlay, renderShortcutsOverlay } from './help-overlay.ts';
|
|
21
21
|
import { renderAutocompleteOverlay } from './autocomplete-overlay.ts';
|
|
22
|
-
import { renderOnboardingWizard } from './onboarding/onboarding-wizard.ts';
|
|
23
22
|
import { overlayViewportBottom, replaceViewportWithOverlay } from './conversation-layout.ts';
|
|
24
23
|
|
|
25
24
|
export interface ConversationOverlayContext {
|
|
@@ -41,9 +40,7 @@ export function applyConversationOverlays(
|
|
|
41
40
|
const bottomDockInset = 1 + (input.searchManager.active || input.historySearch.active ? 1 : 0);
|
|
42
41
|
|
|
43
42
|
if (input.onboardingWizard.active) {
|
|
44
|
-
|
|
45
|
-
next = replaceViewportWithOverlay(lines, conversationWidth, viewportHeight);
|
|
46
|
-
if (!input.modelPicker.active) return next;
|
|
43
|
+
return next;
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
if (input.filePicker.active) {
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { Line } from '../../types/grid.ts';
|
|
2
|
+
import { GLYPHS } from '../ui-primitives.ts';
|
|
3
|
+
import {
|
|
4
|
+
borderLine,
|
|
5
|
+
clamp,
|
|
6
|
+
contentLine,
|
|
7
|
+
drawHorizontalRule,
|
|
8
|
+
drawVerticalRule,
|
|
9
|
+
fillRange,
|
|
10
|
+
FULLSCREEN_PALETTE,
|
|
11
|
+
makeLine,
|
|
12
|
+
writeText,
|
|
13
|
+
} from '../fullscreen-primitives.ts';
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
borderLine,
|
|
17
|
+
clamp,
|
|
18
|
+
contentLine,
|
|
19
|
+
fillRange,
|
|
20
|
+
makeLine,
|
|
21
|
+
padDisplay,
|
|
22
|
+
stableWindow,
|
|
23
|
+
writeText,
|
|
24
|
+
} from '../fullscreen-primitives.ts';
|
|
25
|
+
export { FULLSCREEN_PALETTE as WORKSPACE_PALETTE } from '../fullscreen-primitives.ts';
|
|
26
|
+
|
|
27
|
+
const WORKSPACE_PALETTE = FULLSCREEN_PALETTE;
|
|
28
|
+
|
|
29
|
+
export interface WorkspaceRow {
|
|
30
|
+
readonly text: string;
|
|
31
|
+
readonly selected?: boolean;
|
|
32
|
+
readonly bold?: boolean;
|
|
33
|
+
readonly dim?: boolean;
|
|
34
|
+
readonly fg?: string;
|
|
35
|
+
readonly bg?: string;
|
|
36
|
+
readonly kind?: 'group' | 'item' | 'more' | 'empty';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface FullscreenWorkspaceRenderOptions {
|
|
40
|
+
readonly width: number;
|
|
41
|
+
readonly height: number;
|
|
42
|
+
readonly title: string;
|
|
43
|
+
readonly stateLabel?: string;
|
|
44
|
+
readonly leftHeader: string;
|
|
45
|
+
readonly mainHeader: string;
|
|
46
|
+
readonly leftRows: readonly WorkspaceRow[];
|
|
47
|
+
readonly contextRows: readonly WorkspaceRow[];
|
|
48
|
+
readonly controlRows: readonly WorkspaceRow[];
|
|
49
|
+
readonly footer: string;
|
|
50
|
+
readonly leftWidth?: number;
|
|
51
|
+
readonly contextRatio?: number;
|
|
52
|
+
readonly minContextRows?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface FullscreenWorkspaceMetrics {
|
|
56
|
+
readonly safeWidth: number;
|
|
57
|
+
readonly safeHeight: number;
|
|
58
|
+
readonly leftWidth: number;
|
|
59
|
+
readonly centerWidth: number;
|
|
60
|
+
readonly bodyRows: number;
|
|
61
|
+
readonly contextWidth: number;
|
|
62
|
+
readonly contextRows: number;
|
|
63
|
+
readonly controlRows: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function drawVertical(line: Line, x: number, bg = ''): void {
|
|
67
|
+
if (x <= 0 || x >= line.length - 1) return;
|
|
68
|
+
drawVerticalRule(line, x, WORKSPACE_PALETTE.border, bg);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function drawHorizontalRange(line: Line, startX: number, endX: number, bg = ''): void {
|
|
72
|
+
drawHorizontalRule(line, Math.max(1, startX), Math.min(line.length - 2, endX), WORKSPACE_PALETTE.border, bg);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function leftWidthFor(width: number, explicit?: number): number {
|
|
76
|
+
if (explicit !== undefined) return clamp(explicit, 14, Math.max(14, width - 24));
|
|
77
|
+
return width < 80
|
|
78
|
+
? clamp(Math.round(width * 0.32), 14, Math.max(14, width - 24))
|
|
79
|
+
: clamp(Math.round(width * 0.22), 24, 34);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getFullscreenWorkspaceMetrics(options: Pick<
|
|
83
|
+
FullscreenWorkspaceRenderOptions,
|
|
84
|
+
'width' | 'height' | 'leftWidth' | 'contextRatio' | 'minContextRows'
|
|
85
|
+
>): FullscreenWorkspaceMetrics {
|
|
86
|
+
const safeWidth = Math.max(1, options.width);
|
|
87
|
+
const safeHeight = Math.max(12, options.height);
|
|
88
|
+
const leftWidth = leftWidthFor(safeWidth, options.leftWidth);
|
|
89
|
+
const centerWidth = Math.max(20, safeWidth - leftWidth - 3);
|
|
90
|
+
const bodyTop = 3;
|
|
91
|
+
const footerY = safeHeight - 2;
|
|
92
|
+
const bodyRows = Math.max(4, footerY - bodyTop);
|
|
93
|
+
const contextWidth = Math.max(10, centerWidth - 2);
|
|
94
|
+
const maxContextRows = Math.max(3, bodyRows - 4);
|
|
95
|
+
const minContextRows = clamp(options.minContextRows ?? 10, 3, maxContextRows);
|
|
96
|
+
const contextRows = clamp(
|
|
97
|
+
Math.round(bodyRows * (options.contextRatio ?? 0.4)),
|
|
98
|
+
Math.min(minContextRows, maxContextRows),
|
|
99
|
+
maxContextRows,
|
|
100
|
+
);
|
|
101
|
+
const controlRows = Math.max(3, bodyRows - contextRows - 1);
|
|
102
|
+
return { safeWidth, safeHeight, leftWidth, centerWidth, bodyRows, contextWidth, contextRows, controlRows };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function rowFg(row: WorkspaceRow, fallback: string): string {
|
|
106
|
+
if (row.fg) return row.fg;
|
|
107
|
+
if (row.kind === 'group') return WORKSPACE_PALETTE.subtitle;
|
|
108
|
+
if (row.kind === 'more') return WORKSPACE_PALETTE.dim;
|
|
109
|
+
return fallback;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function renderFullscreenWorkspace(options: FullscreenWorkspaceRenderOptions): Line[] {
|
|
113
|
+
const { safeWidth, safeHeight, leftWidth, centerWidth, bodyRows, contextWidth, contextRows } = getFullscreenWorkspaceMetrics(options);
|
|
114
|
+
const leftStart = 1;
|
|
115
|
+
const dividerX = leftWidth + 1;
|
|
116
|
+
const centerStart = dividerX + 1;
|
|
117
|
+
const centerEnd = safeWidth - 2;
|
|
118
|
+
const bodyTop = 3;
|
|
119
|
+
const separatorY = bodyTop + contextRows;
|
|
120
|
+
const lines: Line[] = [];
|
|
121
|
+
|
|
122
|
+
const top = borderLine(safeWidth, GLYPHS.frame.topLeft, GLYPHS.frame.horizontal, GLYPHS.frame.topRight);
|
|
123
|
+
writeText(top, 2, safeWidth - 4, ` ${options.title} `, { fg: WORKSPACE_PALETTE.title, bold: true });
|
|
124
|
+
if (options.stateLabel) {
|
|
125
|
+
writeText(top, Math.max(2, safeWidth - options.stateLabel.length - 4), options.stateLabel.length, options.stateLabel, {
|
|
126
|
+
fg: WORKSPACE_PALETTE.subtitle,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
lines.push(top);
|
|
130
|
+
|
|
131
|
+
const header = contentLine(safeWidth, WORKSPACE_PALETTE.footerBg);
|
|
132
|
+
drawVertical(header, dividerX, WORKSPACE_PALETTE.footerBg);
|
|
133
|
+
writeText(header, leftStart + 1, leftWidth - 2, options.leftHeader, {
|
|
134
|
+
fg: WORKSPACE_PALETTE.subtitle,
|
|
135
|
+
bold: true,
|
|
136
|
+
bg: WORKSPACE_PALETTE.footerBg,
|
|
137
|
+
});
|
|
138
|
+
writeText(header, centerStart + 1, centerWidth - 2, options.mainHeader, {
|
|
139
|
+
fg: WORKSPACE_PALETTE.subtitle,
|
|
140
|
+
bold: true,
|
|
141
|
+
bg: WORKSPACE_PALETTE.footerBg,
|
|
142
|
+
});
|
|
143
|
+
lines.push(header);
|
|
144
|
+
|
|
145
|
+
const headerSep = contentLine(safeWidth, '');
|
|
146
|
+
drawVertical(headerSep, dividerX);
|
|
147
|
+
drawHorizontalRange(headerSep, 1, safeWidth - 2);
|
|
148
|
+
lines.push(headerSep);
|
|
149
|
+
|
|
150
|
+
for (let row = 0; row < bodyRows; row += 1) {
|
|
151
|
+
const y = bodyTop + row;
|
|
152
|
+
const inContext = y < separatorY;
|
|
153
|
+
const inSeparator = y === separatorY;
|
|
154
|
+
const bg = inSeparator ? '' : inContext ? WORKSPACE_PALETTE.contextBg : WORKSPACE_PALETTE.controlsBg;
|
|
155
|
+
const line = contentLine(safeWidth, bg);
|
|
156
|
+
fillRange(line, 1, dividerX - 1, WORKSPACE_PALETTE.categoryBg);
|
|
157
|
+
drawVertical(line, dividerX, bg);
|
|
158
|
+
|
|
159
|
+
const leftRow = options.leftRows[row] ?? { text: '', kind: 'empty' as const };
|
|
160
|
+
if (leftRow.selected) fillRange(line, leftStart, dividerX - 1, WORKSPACE_PALETTE.selectedBg);
|
|
161
|
+
writeText(line, leftStart + 1, leftWidth - 3, leftRow.text, {
|
|
162
|
+
fg: leftRow.selected ? WORKSPACE_PALETTE.text : rowFg(leftRow, WORKSPACE_PALETTE.muted),
|
|
163
|
+
bg: leftRow.selected ? WORKSPACE_PALETTE.selectedBg : WORKSPACE_PALETTE.categoryBg,
|
|
164
|
+
bold: leftRow.bold ?? (leftRow.selected || leftRow.kind === 'group'),
|
|
165
|
+
dim: leftRow.dim,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (inSeparator) {
|
|
169
|
+
drawHorizontalRange(line, centerStart, centerEnd);
|
|
170
|
+
} else if (inContext) {
|
|
171
|
+
const contextRow = options.contextRows[row] ?? { text: '', kind: 'empty' as const };
|
|
172
|
+
writeText(line, centerStart + 1, contextWidth, contextRow.text, {
|
|
173
|
+
fg: rowFg(contextRow, WORKSPACE_PALETTE.text),
|
|
174
|
+
bg,
|
|
175
|
+
bold: contextRow.bold,
|
|
176
|
+
dim: contextRow.dim ?? contextRow.text.length === 0,
|
|
177
|
+
});
|
|
178
|
+
} else {
|
|
179
|
+
const controlRow = options.controlRows[row - contextRows - 1] ?? { text: '', kind: 'empty' as const };
|
|
180
|
+
if (controlRow.selected) fillRange(line, centerStart, centerEnd, WORKSPACE_PALETTE.selectedBg);
|
|
181
|
+
writeText(line, centerStart + 1, contextWidth, controlRow.text, {
|
|
182
|
+
fg: controlRow.selected ? WORKSPACE_PALETTE.text : rowFg(controlRow, WORKSPACE_PALETTE.text),
|
|
183
|
+
bg: controlRow.selected ? WORKSPACE_PALETTE.selectedBg : bg,
|
|
184
|
+
bold: controlRow.bold ?? controlRow.selected,
|
|
185
|
+
dim: controlRow.dim ?? controlRow.text.length === 0,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
lines.push(line);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const footer = contentLine(safeWidth, WORKSPACE_PALETTE.footerBg);
|
|
193
|
+
writeText(footer, 2, safeWidth - 4, options.footer, { fg: WORKSPACE_PALETTE.muted, bg: WORKSPACE_PALETTE.footerBg });
|
|
194
|
+
lines.push(footer);
|
|
195
|
+
lines.push(borderLine(safeWidth, GLYPHS.frame.bottomLeft, GLYPHS.frame.horizontal, GLYPHS.frame.bottomRight));
|
|
196
|
+
|
|
197
|
+
while (lines.length < safeHeight) lines.unshift(makeLine(safeWidth));
|
|
198
|
+
return lines.slice(-safeHeight);
|
|
199
|
+
}
|
package/src/version.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { join } from 'node:path';
|
|
|
6
6
|
// The prebuild script updates the fallback value before compilation.
|
|
7
7
|
// Uses import.meta.dir (Bun) to locate package.json relative to this file,
|
|
8
8
|
// which is correct regardless of the process working directory.
|
|
9
|
-
let _version = '1.0.
|
|
9
|
+
let _version = '1.0.40';
|
|
10
10
|
try {
|
|
11
11
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {
|
|
12
12
|
readonly version?: unknown;
|