@pellux/goodvibes-agent 1.0.38 → 1.0.39

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,11 @@
2
2
 
3
3
  Product-facing release notes for GoodVibes Agent.
4
4
 
5
+ ## 1.0.39 - 2026-06-04
6
+
7
+ - Removed the body-scoped onboarding overlay fallback so onboarding can only render through the shell fullscreen composite.
8
+ - Added regression coverage for the fullscreen onboarding composite and nested model workspace composite.
9
+
5
10
  ## 1.0.38 - 2026-06-04
6
11
 
7
12
  - Onboarding now uses the shared fullscreen workspace surface so it owns the full terminal height, including the composer area.
@@ -389782,6 +389782,23 @@ function createSchema2(db) {
389782
389782
  `);
389783
389783
  db.run(`CREATE INDEX IF NOT EXISTS idx_knowledge_schedules_job_id ON knowledge_schedules(job_id)`);
389784
389784
  }
389785
+ function getKnowledgeSchemaStatements() {
389786
+ const statements = [];
389787
+ createSchema2({
389788
+ run(sql) {
389789
+ const normalized = sql.trim();
389790
+ if (normalized.length > 0)
389791
+ statements.push(normalized);
389792
+ }
389793
+ });
389794
+ return statements;
389795
+ }
389796
+ function renderKnowledgeSchemaSql() {
389797
+ return `${getKnowledgeSchemaStatements().map((statement) => statement.endsWith(";") ? statement : `${statement};`).join(`
389798
+
389799
+ `)}
389800
+ `;
389801
+ }
389785
389802
  function rowObject(columns, values2) {
389786
389803
  return Object.fromEntries(columns.map((column, index) => [column, values2[index]]));
389787
389804
  }
@@ -703119,6 +703136,9 @@ var init_ingest = __esm(() => {
703119
703136
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/browser-history/index.js
703120
703137
  var init_browser_history = __esm(() => {
703121
703138
  init_ingest();
703139
+ init_discover();
703140
+ init_readers();
703141
+ init_paths2();
703122
703142
  });
703123
703143
 
703124
703144
  // node_modules/graphql/jsutils/devAssert.mjs
@@ -720758,6 +720778,7 @@ var init_semantic = __esm(() => {
720758
720778
  init_llm();
720759
720779
  init_gap_repair();
720760
720780
  init_service4();
720781
+ init_self_improvement();
720761
720782
  });
720762
720783
 
720763
720784
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/home-graph/helpers.js
@@ -724726,8 +724747,40 @@ var init_map_view = __esm(() => {
724726
724747
  });
724727
724748
 
724728
724749
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/home-graph/types.js
724729
- var HOME_GRAPH_CAPABILITIES;
724750
+ var HOME_GRAPH_NODE_KINDS, HOME_GRAPH_RELATIONS, HOME_GRAPH_CAPABILITIES;
724730
724751
  var init_types6 = __esm(() => {
724752
+ HOME_GRAPH_NODE_KINDS = [
724753
+ "ha_home",
724754
+ "ha_entity",
724755
+ "ha_device",
724756
+ "ha_area",
724757
+ "ha_automation",
724758
+ "ha_script",
724759
+ "ha_scene",
724760
+ "ha_label",
724761
+ "ha_integration",
724762
+ "ha_room",
724763
+ "ha_device_passport",
724764
+ "ha_maintenance_item",
724765
+ "ha_troubleshooting_case",
724766
+ "ha_purchase",
724767
+ "ha_network_node"
724768
+ ];
724769
+ HOME_GRAPH_RELATIONS = [
724770
+ "controls",
724771
+ "located_in",
724772
+ "belongs_to_device",
724773
+ "has_manual",
724774
+ "has_receipt",
724775
+ "has_warranty",
724776
+ "has_issue",
724777
+ "fixed_by",
724778
+ "uses_battery",
724779
+ "connected_via",
724780
+ "part_of_network",
724781
+ "mentioned_by",
724782
+ "source_for"
724783
+ ];
724731
724784
  HOME_GRAPH_CAPABILITIES = [
724732
724785
  "knowledge-space-isolation",
724733
724786
  "snapshot-sync",
@@ -726134,6 +726187,7 @@ var init_service5 = __esm(() => {
726134
726187
  var init_home_graph = __esm(() => {
726135
726188
  init_service5();
726136
726189
  init_extension();
726190
+ init_types6();
726137
726191
  });
726138
726192
 
726139
726193
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/store-refinement.js
@@ -728461,10 +728515,14 @@ var init_service6 = __esm(() => {
728461
728515
  var init_project_planning = __esm(() => {
728462
728516
  init_service6();
728463
728517
  init_helpers3();
728518
+ init_readiness();
728464
728519
  });
728465
728520
 
728466
728521
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/persistence.js
728467
- var init_persistence = () => {};
728522
+ var init_persistence = __esm(() => {
728523
+ init_store_schema();
728524
+ init_store_load();
728525
+ });
728468
728526
 
728469
728527
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/projections.js
728470
728528
  class KnowledgeProjectionService {
@@ -731972,21 +732030,21 @@ var init_service7 = __esm(() => {
731972
732030
  var exports_knowledge = {};
731973
732031
  __export(exports_knowledge, {
731974
732032
  withKnowledgeSpace: () => withKnowledgeSpace,
731975
- uniqKnowledgeValues: () => uniq3,
731976
- stabilizeKnowledgeText: () => stableText2,
731977
- runKnowledgeSemanticSelfImprovement: () => runKnowledgeSemanticSelfImprovement2,
732033
+ uniqKnowledgeValues: () => uniq2,
732034
+ stabilizeKnowledgeText: () => stableText,
732035
+ runKnowledgeSemanticSelfImprovement: () => runKnowledgeSemanticSelfImprovement,
731978
732036
  resolveProjectPlanningSpace: () => resolveProjectPlanningSpace,
731979
- resolveKnowledgeDbPathFromControlPlaneDir: () => resolveKnowledgeDbPathFromControlPlaneDir2,
732037
+ resolveKnowledgeDbPathFromControlPlaneDir: () => resolveKnowledgeDbPathFromControlPlaneDir,
731980
732038
  renderPacket: () => renderPacket,
731981
732039
  renderKnowledgeSchemaSql: () => renderKnowledgeSchemaSql,
731982
732040
  renderKnowledgeMap: () => renderKnowledgeMap,
731983
732041
  readKnowledgeSearchText: () => readKnowledgeSearchText,
731984
- readBrowserKnowledgeProfile: () => readBrowserKnowledgeProfile2,
732042
+ readBrowserKnowledgeProfile: () => readBrowserKnowledgeProfile,
731985
732043
  projectPlanningSourceId: () => projectPlanningSourceId,
731986
732044
  projectPlanningProjectIdFromPath: () => projectPlanningProjectIdFromPath,
731987
732045
  projectPlanningCanonicalUri: () => projectPlanningCanonicalUri,
731988
732046
  projectKnowledgeSpaceId: () => projectKnowledgeSpaceId,
731989
- parseKnowledgeJsonValue: () => parseJsonValue2,
732047
+ parseKnowledgeJsonValue: () => parseJsonValue,
731990
732048
  normalizeProjectId: () => normalizeProjectId,
731991
732049
  normalizeKnowledgeSpaceId: () => normalizeKnowledgeSpaceId,
731992
732050
  normalizeHomeAssistantInstallationId: () => normalizeHomeAssistantInstallationId,
@@ -731994,12 +732052,12 @@ __export(exports_knowledge, {
731994
732052
  materializeGeneratedKnowledgeProjection: () => materializeGeneratedKnowledgeProjection,
731995
732053
  looksLikeRawPdfPayload: () => looksLikeRawPdfPayload,
731996
732054
  looksBinaryLikeText: () => looksBinaryLikeText,
731997
- loadKnowledgeStoreSnapshot: () => loadKnowledgeStoreSnapshot2,
732055
+ loadKnowledgeStoreSnapshot: () => loadKnowledgeStoreSnapshot,
731998
732056
  listGeneratedKnowledgePages: () => listGeneratedKnowledgePages,
731999
- listBrowserKinds: () => listBrowserKinds2,
732057
+ listBrowserKinds: () => listBrowserKinds,
732000
732058
  knowledgeSpaceMetadata: () => knowledgeSpaceMetadata,
732001
732059
  knowledgePageSourceWeight: () => knowledgePageSourceWeight,
732002
- knowledgeNowMs: () => nowMs2,
732060
+ knowledgeNowMs: () => nowMs,
732003
732061
  knowledgeExtractionNeedsRefresh: () => knowledgeExtractionNeedsRefresh,
732004
732062
  isUsefulKnowledgePageSourceCandidate: () => isUsefulKnowledgePageSourceCandidate,
732005
732063
  isUsefulKnowledgePageSource: () => isUsefulKnowledgePageSource,
@@ -732019,12 +732077,12 @@ __export(exports_knowledge, {
732019
732077
  generatedKnowledgeSourceId: () => generatedKnowledgeSourceId,
732020
732078
  generatedKnowledgeCanonicalUri: () => generatedKnowledgeCanonicalUri,
732021
732079
  extractKnowledgeArtifact: () => extractKnowledgeArtifact,
732022
- evaluateProjectPlanningReadiness: () => evaluateProjectPlanningReadiness2,
732023
- discoverBrowserKnowledgeProfiles: () => discoverBrowserKnowledgeProfiles2,
732080
+ evaluateProjectPlanningReadiness: () => evaluateProjectPlanningReadiness,
732081
+ discoverBrowserKnowledgeProfiles: () => discoverBrowserKnowledgeProfiles,
732024
732082
  createWebKnowledgeGapRepairer: () => createWebKnowledgeGapRepairer,
732025
732083
  createProviderBackedKnowledgeSemanticLlm: () => createProviderBackedKnowledgeSemanticLlm,
732026
732084
  createMemoryApi: () => createMemoryApi,
732027
- createKnowledgeSchema: () => createSchema3,
732085
+ createKnowledgeSchema: () => createSchema2,
732028
732086
  createKnowledgeApi: () => createKnowledgeApi,
732029
732087
  createDefaultKnowledgeConnectorRegistry: () => createDefaultKnowledgeConnectorRegistry,
732030
732088
  compareKnowledgePageSources: () => compareKnowledgePageSources,
@@ -734463,7 +734521,7 @@ var init_delivery_manager = __esm(() => {
734463
734521
  });
734464
734522
 
734465
734523
  // node_modules/@pellux/goodvibes-sdk/dist/platform/automation/scheduler-capacity.js
734466
- function computeSchedulerCapacity(slotsTotal, runs, nowMs3 = Date.now()) {
734524
+ function computeSchedulerCapacity(slotsTotal, runs, nowMs2 = Date.now()) {
734467
734525
  let slotsInUse = 0;
734468
734526
  const queuedRuns = [];
734469
734527
  for (const run7 of runs) {
@@ -734473,7 +734531,7 @@ function computeSchedulerCapacity(slotsTotal, runs, nowMs3 = Date.now()) {
734473
734531
  queuedRuns.push(run7);
734474
734532
  }
734475
734533
  const queueDepth = queuedRuns.length;
734476
- const oldestQueuedAgeMs = queueDepth > 0 ? nowMs3 - Math.min(...queuedRuns.map((r5) => r5.queuedAt)) : null;
734534
+ const oldestQueuedAgeMs = queueDepth > 0 ? nowMs2 - Math.min(...queuedRuns.map((r5) => r5.queuedAt)) : null;
734477
734535
  return { slotsTotal, slotsInUse, queueDepth, oldestQueuedAgeMs };
734478
734536
  }
734479
734537
 
@@ -817087,7 +817145,7 @@ var createStyledCell = (char, overrides = {}) => ({
817087
817145
  // src/version.ts
817088
817146
  import { readFileSync } from "fs";
817089
817147
  import { join } from "path";
817090
- var _version = "1.0.38";
817148
+ var _version = "1.0.39";
817091
817149
  try {
817092
817150
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf-8"));
817093
817151
  _version = typeof pkg.version === "string" ? pkg.version : _version;
@@ -840170,7 +840228,7 @@ var WORK_PLAN_STATUSES = [
840170
840228
  "failed",
840171
840229
  "cancelled"
840172
840230
  ];
840173
- function nowMs3() {
840231
+ function nowMs2() {
840174
840232
  return Date.now();
840175
840233
  }
840176
840234
  function isObject5(value) {
@@ -840276,7 +840334,7 @@ class WorkPlanStore {
840276
840334
  if (!normalizedTitle)
840277
840335
  throw new Error("Work plan item title is required.");
840278
840336
  const plan = this.readPlan();
840279
- const time4 = nowMs3();
840337
+ const time4 = nowMs2();
840280
840338
  const item = {
840281
840339
  id: createItemId(),
840282
840340
  title: normalizedTitle,
@@ -840300,7 +840358,7 @@ class WorkPlanStore {
840300
840358
  updateItem(idOrPrefix, patch2) {
840301
840359
  const plan = this.readPlan();
840302
840360
  const item = this.resolveItem(plan, idOrPrefix);
840303
- const time4 = nowMs3();
840361
+ const time4 = nowMs2();
840304
840362
  const nextStatus = patch2.status ?? item.status;
840305
840363
  const next = this.pruneItem({
840306
840364
  ...item,
@@ -840333,7 +840391,7 @@ class WorkPlanStore {
840333
840391
  removeItem(idOrPrefix) {
840334
840392
  const plan = this.readPlan();
840335
840393
  const item = this.resolveItem(plan, idOrPrefix);
840336
- const time4 = nowMs3();
840394
+ const time4 = nowMs2();
840337
840395
  const remaining = plan.items.filter((candidate) => candidate.id !== item.id);
840338
840396
  this.writePlan({
840339
840397
  ...plan,
@@ -840353,7 +840411,7 @@ class WorkPlanStore {
840353
840411
  ...plan,
840354
840412
  items: remaining,
840355
840413
  activeItemId: remaining[0]?.id,
840356
- updatedAt: nowMs3()
840414
+ updatedAt: nowMs2()
840357
840415
  });
840358
840416
  return removed;
840359
840417
  }
@@ -840392,7 +840450,7 @@ class WorkPlanStore {
840392
840450
  const parsed = JSON.parse(raw);
840393
840451
  if (!isObject5(parsed))
840394
840452
  return this.createEmptyPlan();
840395
- const time4 = nowMs3();
840453
+ const time4 = nowMs2();
840396
840454
  const createdAt = typeof parsed.createdAt === "number" ? parsed.createdAt : time4;
840397
840455
  const updatedAt = typeof parsed.updatedAt === "number" ? parsed.updatedAt : createdAt;
840398
840456
  const items = Array.isArray(parsed.items) ? parsed.items.map((item) => normalizeItem(item, createdAt)).filter((item) => item !== null) : [];
@@ -840411,7 +840469,7 @@ class WorkPlanStore {
840411
840469
  };
840412
840470
  }
840413
840471
  createEmptyPlan() {
840414
- const time4 = nowMs3();
840472
+ const time4 = nowMs2();
840415
840473
  return {
840416
840474
  id: createPlanId(this.options.projectId, this.options.projectRoot),
840417
840475
  projectId: this.options.projectId,
@@ -848643,13 +848701,13 @@ init_state3();
848643
848701
 
848644
848702
  // src/input/commands/recall-shared.ts
848645
848703
  var VALID_CLASSES = ["decision", "constraint", "incident", "pattern", "fact", "risk", "runbook", "architecture", "ownership"];
848646
- var VALID_SCOPES2 = ["session", "project", "team"];
848704
+ var VALID_SCOPES = ["session", "project", "team"];
848647
848705
  var VALID_REVIEW_STATES = ["fresh", "reviewed", "stale", "contradicted"];
848648
848706
  function isValidClass(s4) {
848649
848707
  return VALID_CLASSES.includes(s4);
848650
848708
  }
848651
848709
  function isValidScope(s4) {
848652
- return VALID_SCOPES2.includes(s4);
848710
+ return VALID_SCOPES.includes(s4);
848653
848711
  }
848654
848712
  function isValidReviewState(s4) {
848655
848713
  return VALID_REVIEW_STATES.includes(s4);
@@ -848692,7 +848750,7 @@ function handleRecallSearch(args2, context) {
848692
848750
  if (isValidScope(scope))
848693
848751
  filter.scope = scope;
848694
848752
  else {
848695
- context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES2.join(", ")}.`);
848753
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(", ")}.`);
848696
848754
  return;
848697
848755
  }
848698
848756
  }
@@ -848867,7 +848925,7 @@ function handleRecallList(args2, context) {
848867
848925
  if (scopeIdx !== -1 && args2[scopeIdx + 1]) {
848868
848926
  const scope = args2[scopeIdx + 1];
848869
848927
  if (!isValidScope(scope)) {
848870
- context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES2.join(", ")}.`);
848928
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(", ")}.`);
848871
848929
  return;
848872
848930
  }
848873
848931
  filter.scope = scope;
@@ -848917,7 +848975,7 @@ async function handleRecallAdd(args2, context) {
848917
848975
  const tags = tagsRaw ? tagsRaw.split(",").map((token) => token.trim()).filter(Boolean) : [];
848918
848976
  const scope = scopeRaw && isValidScope(scopeRaw) ? scopeRaw : "project";
848919
848977
  if (scopeRaw && !isValidScope(scopeRaw)) {
848920
- context.print(`[memory] Invalid scope "${scopeRaw}". Valid values ${VALID_SCOPES2.join(", ")}.`);
848978
+ context.print(`[memory] Invalid scope "${scopeRaw}". Valid values ${VALID_SCOPES.join(", ")}.`);
848921
848979
  return;
848922
848980
  }
848923
848981
  const provenance = [];
@@ -849051,7 +849109,7 @@ function handleRecallExport(args2, context) {
849051
849109
  if (scopeIdx !== -1 && commandArgs[scopeIdx + 1]) {
849052
849110
  const scope = commandArgs[scopeIdx + 1];
849053
849111
  if (!isValidScope(scope)) {
849054
- context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES2.join(", ")}.`);
849112
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(", ")}.`);
849055
849113
  return;
849056
849114
  }
849057
849115
  filter.scope = scope;
@@ -849130,7 +849188,7 @@ function handleRecallHandoffExport(args2, context) {
849130
849188
  const scopeIdx = commandArgs.indexOf("--scope");
849131
849189
  const scopeRaw = scopeIdx !== -1 ? commandArgs[scopeIdx + 1] : "team";
849132
849190
  if (!scopeRaw || !isValidScope(scopeRaw)) {
849133
- context.print(`[memory] Unknown scope "${scopeRaw ?? ""}". Valid values ${VALID_SCOPES2.join(", ")}.`);
849191
+ context.print(`[memory] Unknown scope "${scopeRaw ?? ""}". Valid values ${VALID_SCOPES.join(", ")}.`);
849134
849192
  return;
849135
849193
  }
849136
849194
  const bundle = memory.exportBundle({ scope: scopeRaw });
@@ -849246,7 +849304,7 @@ function handleRecallPromote(args2, context) {
849246
849304
  const id = parsed.rest[0];
849247
849305
  const scope = parsed.rest[1];
849248
849306
  if (!id || !scope || !isValidScope(scope)) {
849249
- context.print(`[memory] Usage: /memory promote <id> <${VALID_SCOPES2.join("|")}> --yes`);
849307
+ context.print(`[memory] Usage: /memory promote <id> <${VALID_SCOPES.join("|")}> --yes`);
849250
849308
  return;
849251
849309
  }
849252
849310
  if (!parsed.yes) {
@@ -863171,7 +863229,7 @@ import { mkdirSync as mkdirSync64, readFileSync as readFileSync85, writeFileSync
863171
863229
  import { dirname as dirname63, resolve as resolve39 } from "path";
863172
863230
  init_state3();
863173
863231
  var VALID_CLASSES2 = ["decision", "constraint", "incident", "pattern", "fact", "risk", "runbook", "architecture", "ownership"];
863174
- var VALID_SCOPES4 = ["session", "project", "team"];
863232
+ var VALID_SCOPES3 = ["session", "project", "team"];
863175
863233
  var VALID_REVIEW_STATES3 = ["fresh", "reviewed", "stale", "contradicted"];
863176
863234
  var VALID_PROVENANCE_KINDS = ["session", "turn", "task", "event", "file"];
863177
863235
  var VALUE_OPTIONS = new Set([
@@ -863271,7 +863329,7 @@ function isMemoryClass2(value) {
863271
863329
  return VALID_CLASSES2.includes(value);
863272
863330
  }
863273
863331
  function isMemoryScope2(value) {
863274
- return VALID_SCOPES4.includes(value);
863332
+ return VALID_SCOPES3.includes(value);
863275
863333
  }
863276
863334
  function isReviewState(value) {
863277
863335
  return VALID_REVIEW_STATES3.includes(value);
@@ -863286,7 +863344,7 @@ function requireClass(value) {
863286
863344
  }
863287
863345
  function requireScope(value) {
863288
863346
  if (!value || !isMemoryScope2(value))
863289
- throw new Error(`Invalid memory scope "${value ?? ""}". Valid values ${VALID_SCOPES4.join(", ")}`);
863347
+ throw new Error(`Invalid memory scope "${value ?? ""}". Valid values ${VALID_SCOPES3.join(", ")}`);
863290
863348
  return value;
863291
863349
  }
863292
863350
  function optionalScope(value) {
@@ -906062,311 +906120,13 @@ function renderAutocompleteOverlay(autocomplete, width, viewportHeight = 24) {
906062
906120
  return lines;
906063
906121
  }
906064
906122
 
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
906123
  // src/renderer/conversation-overlays.ts
906361
906124
  function applyConversationOverlays(viewport, context) {
906362
906125
  const { input, conversation, commandRegistry, keybindingsManager, conversationWidth, viewportHeight, contextWindow } = context;
906363
906126
  let next = viewport;
906364
906127
  const bottomDockInset = 1 + (input.searchManager.active || input.historySearch.active ? 1 : 0);
906365
906128
  if (input.onboardingWizard.active) {
906366
- const lines = renderOnboardingWizard(input.onboardingWizard, conversationWidth, viewportHeight);
906367
- next = replaceViewportWithOverlay(lines, conversationWidth, viewportHeight);
906368
- if (!input.modelPicker.active)
906369
- return next;
906129
+ return next;
906370
906130
  }
906371
906131
  if (input.filePicker.active) {
906372
906132
  const lines = renderFilePickerOverlay(input.filePicker, conversationWidth, viewportHeight);
@@ -906717,6 +906477,301 @@ function handleBlockingShellInput(options) {
906717
906477
  return { handled: false, pendingPermission, recoveryPending };
906718
906478
  }
906719
906479
 
906480
+ // src/renderer/onboarding/onboarding-wizard.ts
906481
+ function modeLabel(mode) {
906482
+ if (mode === "edit")
906483
+ return "Edit existing";
906484
+ if (mode === "reopen")
906485
+ return "Reopen review";
906486
+ return "New setup";
906487
+ }
906488
+ function changedScreensLabel(wizard) {
906489
+ if (wizard.dirtyStepCount === 0)
906490
+ return "no changes";
906491
+ if (wizard.dirtyStepCount === 1)
906492
+ return "1 changed screen";
906493
+ return `${wizard.dirtyStepCount} changed screens`;
906494
+ }
906495
+ function stepGlyph(wizard, step, stepIndex) {
906496
+ if (stepIndex === wizard.stepIndex)
906497
+ return { glyph: GLYPHS.navigation.selected, fg: FULLSCREEN_PALETTE.info };
906498
+ const total = wizard.getStepFieldCount(stepIndex);
906499
+ const completed = wizard.getCompletedFieldCount(stepIndex);
906500
+ if (wizard.isStepDirty(stepIndex))
906501
+ return { glyph: GLYPHS.status.review, fg: FULLSCREEN_PALETTE.warn };
906502
+ if (total > 0 && completed === total)
906503
+ return { glyph: GLYPHS.status.success, fg: FULLSCREEN_PALETTE.good };
906504
+ return { glyph: GLYPHS.status.pending, fg: FULLSCREEN_PALETTE.muted };
906505
+ }
906506
+ function fieldRowPrefix(wizard, field, selected) {
906507
+ if (selected)
906508
+ return `${GLYPHS.navigation.selected} `;
906509
+ if (wizard.isFieldDirty(field.id))
906510
+ return `${GLYPHS.status.skipped} `;
906511
+ if (field.kind === "checklist")
906512
+ return wizard.getFieldValue(field) ? `${GLYPHS.status.success} ` : "\u25A1 ";
906513
+ if (field.kind === "acknowledgement")
906514
+ return wizard.getFieldValue(field) ? `${GLYPHS.status.success} ` : "\u25A1 ";
906515
+ if (field.kind === "action")
906516
+ return `${GLYPHS.navigation.next} `;
906517
+ if (field.kind === "radio")
906518
+ return `${GLYPHS.status.active} `;
906519
+ return " ";
906520
+ }
906521
+ function fieldColor(wizard, field, selected) {
906522
+ if (selected)
906523
+ return FULLSCREEN_PALETTE.text;
906524
+ if (field.kind === "status" || field.kind === "modelPicker")
906525
+ return FULLSCREEN_PALETTE.info;
906526
+ if (field.kind === "masked")
906527
+ return FULLSCREEN_PALETTE.warn;
906528
+ if (field.kind === "acknowledgement")
906529
+ return wizard.getFieldValue(field) ? FULLSCREEN_PALETTE.good : FULLSCREEN_PALETTE.warn;
906530
+ if (field.kind === "checklist")
906531
+ return wizard.getFieldValue(field) ? FULLSCREEN_PALETTE.good : FULLSCREEN_PALETTE.muted;
906532
+ if (wizard.getFieldValueLabel(field) === "Missing")
906533
+ return FULLSCREEN_PALETTE.warn;
906534
+ return FULLSCREEN_PALETTE.text;
906535
+ }
906536
+ function formatEditingValue(value, multiline) {
906537
+ if (!multiline)
906538
+ return value;
906539
+ const lines = value.split(/\r?\n/);
906540
+ if (lines.length <= 1)
906541
+ return value;
906542
+ const preview4 = lines[lines.length - 1] ?? "";
906543
+ return `${preview4} (${lines.length} lines)`;
906544
+ }
906545
+ function fieldHint(wizard, field, selected) {
906546
+ if (selected && wizard.isEditingTextField() && wizard.editingFieldId === field.id && (field.kind === "text" || field.kind === "masked")) {
906547
+ const rawValue = wizard.editBuffer.length > 0 ? wizard.editBuffer : field.placeholder;
906548
+ 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);
906549
+ return `Editing: ${editingValue}${GLYPHS.surface.cursor}`;
906550
+ }
906551
+ if (selected && field.kind === "modelPicker")
906552
+ return `${field.hint} Press Enter to open picker.`;
906553
+ if (selected && field.kind === "text") {
906554
+ return field.multiline === true ? `${field.hint} Press Enter to edit; Ctrl-J inserts a new line.` : `${field.hint} Press Enter to edit inline.`;
906555
+ }
906556
+ if (selected && field.kind === "masked")
906557
+ return `${field.hint} Press Enter to edit inline.`;
906558
+ return field.hint;
906559
+ }
906560
+ function selectedFieldText(wizard) {
906561
+ if (wizard.isEditingTextField() && wizard.editingFieldId !== null) {
906562
+ const editingField = wizard.getFieldById(wizard.editingFieldId);
906563
+ if (editingField) {
906564
+ return {
906565
+ title: `Editing: ${editingField.label}`,
906566
+ hint: fieldHint(wizard, editingField, true)
906567
+ };
906568
+ }
906569
+ }
906570
+ const field = wizard.getSelectedField();
906571
+ if (!field)
906572
+ return { title: "Selected: none", hint: "No selectable row is active on this screen." };
906573
+ return {
906574
+ title: `Selected: ${field.label} [${wizard.getFieldValueLabel(field)}]`,
906575
+ hint: fieldHint(wizard, field, true)
906576
+ };
906577
+ }
906578
+ function footerText4(wizard) {
906579
+ if (wizard.isEditingTextField()) {
906580
+ 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";
906581
+ }
906582
+ return "Controls: [Enter] toggle/open \xB7 [Esc] close \xB7 [Tab/Shift+Tab] screen \xB7 [Up/Down] move \xB7 [Del/Ctrl+U] clear";
906583
+ }
906584
+ function controlsText(wizard) {
906585
+ if (wizard.isEditingTextField()) {
906586
+ 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.";
906587
+ }
906588
+ return "Controls: Enter selects, Del clears, Tab moves.";
906589
+ }
906590
+ function buildFieldRows(wizard, visibleFields, capacity) {
906591
+ wizard.ensureSelectionVisible(visibleFields);
906592
+ const fields = wizard.currentStep.fields;
906593
+ const rows = [];
906594
+ if (fields.length === 0 || capacity <= 0)
906595
+ return rows;
906596
+ const allRows = [];
906597
+ fields.forEach((field, absoluteIndex) => {
906598
+ const spacerRows = Math.max(0, field.spacerBeforeRows ?? 0);
906599
+ for (let index = 0;index < spacerRows; index += 1)
906600
+ allRows.push({ kind: "empty" });
906601
+ allRows.push({ kind: "field", field, absoluteIndex });
906602
+ });
906603
+ const selectedFieldIndex = wizard.getSelectedFieldIndex();
906604
+ const selectedRowIndex = Math.max(0, allRows.findIndex((row) => row.kind === "field" && row.absoluteIndex === selectedFieldIndex));
906605
+ const scrollFieldIndex = wizard.scrollOffsets[wizard.stepIndex] ?? 0;
906606
+ const scrollRowIndex = allRows.findIndex((row) => row.kind === "field" && row.absoluteIndex === scrollFieldIndex);
906607
+ const maxStart = Math.max(0, allRows.length - capacity);
906608
+ let start2 = Math.max(0, Math.min(scrollRowIndex >= 0 ? scrollRowIndex : 0, maxStart));
906609
+ if (selectedRowIndex < start2)
906610
+ start2 = selectedRowIndex;
906611
+ if (selectedRowIndex >= start2 + capacity)
906612
+ start2 = selectedRowIndex - capacity + 1;
906613
+ start2 = Math.max(0, Math.min(start2, maxStart));
906614
+ if (capacity > 1 && start2 > 0 && selectedRowIndex === start2)
906615
+ start2 = Math.max(0, start2 - 1);
906616
+ if (capacity > 1 && start2 + capacity < allRows.length && selectedRowIndex === start2 + capacity - 1) {
906617
+ start2 = Math.min(maxStart, start2 + 1);
906618
+ }
906619
+ rows.push(...allRows.slice(start2, start2 + capacity));
906620
+ const firstVisibleRow = rows[0];
906621
+ if (start2 > 0 && rows.length > 0 && !(firstVisibleRow?.kind === "field" && firstVisibleRow.absoluteIndex === selectedFieldIndex)) {
906622
+ rows[0] = { kind: "moreAbove", text: `${GLYPHS.navigation.moreAbove} ${start2} more above` };
906623
+ }
906624
+ const hiddenBelow = Math.max(0, allRows.length - (start2 + capacity));
906625
+ const lastVisibleRow = rows[rows.length - 1];
906626
+ if (hiddenBelow > 0 && rows.length > 0 && !(lastVisibleRow?.kind === "field" && lastVisibleRow.absoluteIndex === selectedFieldIndex)) {
906627
+ rows[rows.length - 1] = { kind: "moreBelow", text: `${GLYPHS.navigation.moreBelow} ${hiddenBelow} more below` };
906628
+ }
906629
+ while (rows.length < capacity)
906630
+ rows.push({ kind: "empty" });
906631
+ return rows.slice(0, capacity);
906632
+ }
906633
+ function pushWrapped(rows, text, width, options = {}) {
906634
+ if (text.length === 0) {
906635
+ rows.push({ text: "", kind: "empty" });
906636
+ return;
906637
+ }
906638
+ for (const line2 of wrapText(text, Math.max(1, width))) {
906639
+ rows.push({ text: line2, ...options });
906640
+ }
906641
+ }
906642
+ function buildStepRows(wizard, height) {
906643
+ const rendered = wizard.steps.map((step, stepIndex) => {
906644
+ const selected = stepIndex === wizard.stepIndex;
906645
+ const state4 = stepGlyph(wizard, step, stepIndex);
906646
+ const completion = `${wizard.getCompletedFieldCount(stepIndex)}/${wizard.getStepFieldCount(stepIndex)}`;
906647
+ return {
906648
+ text: `${state4.glyph} ${stepIndex + 1}. ${step.shortLabel} ${completion}`,
906649
+ selected,
906650
+ kind: "item",
906651
+ fg: state4.fg,
906652
+ bold: selected
906653
+ };
906654
+ });
906655
+ const visible = Math.max(1, height);
906656
+ const window3 = stableWindow(rendered.length, wizard.stepIndex, visible);
906657
+ const rows = rendered.slice(window3.start, window3.end);
906658
+ if (window3.start > 0 && rows.length > 0) {
906659
+ rows[0] = { text: `${GLYPHS.navigation.moreAbove} ${window3.start} more step(s) above`, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
906660
+ }
906661
+ if (window3.end < rendered.length && rows.length > 0) {
906662
+ rows[rows.length - 1] = { text: `${GLYPHS.navigation.moreBelow} ${rendered.length - window3.end} more step(s) below`, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
906663
+ }
906664
+ while (rows.length < height)
906665
+ rows.push({ text: "", kind: "empty" });
906666
+ return rows.slice(0, height);
906667
+ }
906668
+ function buildContextRows2(wizard, width) {
906669
+ const step = wizard.currentStep;
906670
+ const selected = selectedFieldText(wizard);
906671
+ const rows = [
906672
+ { text: step.title, fg: FULLSCREEN_PALETTE.title, bold: true }
906673
+ ];
906674
+ const pushSummaryRows = () => {
906675
+ rows.push({ text: "Summary", fg: FULLSCREEN_PALETTE.subtitle, bold: true });
906676
+ rows.push({ text: step.summaryTitle, fg: FULLSCREEN_PALETTE.info, bold: true });
906677
+ for (const line2 of step.summaryLines.slice(0, 4)) {
906678
+ pushWrapped(rows, line2, width, { fg: FULLSCREEN_PALETTE.text });
906679
+ }
906680
+ rows.push({
906681
+ text: `Fields ${wizard.getCompletedFieldCount(wizard.stepIndex)}/${wizard.getStepFieldCount(wizard.stepIndex)} complete \xB7 ${changedScreensLabel(wizard)}`,
906682
+ fg: wizard.dirtyStepCount > 0 ? FULLSCREEN_PALETTE.warn : FULLSCREEN_PALETTE.muted
906683
+ });
906684
+ };
906685
+ const pushSelectedRows = () => {
906686
+ rows.push({ text: selected.title, fg: FULLSCREEN_PALETTE.info, bold: true });
906687
+ pushWrapped(rows, selected.hint, width, { fg: FULLSCREEN_PALETTE.text });
906688
+ pushWrapped(rows, controlsText(wizard), width, { fg: FULLSCREEN_PALETTE.info });
906689
+ };
906690
+ pushWrapped(rows, step.description, width, { fg: FULLSCREEN_PALETTE.text });
906691
+ rows.push({ text: "", kind: "empty" });
906692
+ if (wizard.isEditingTextField()) {
906693
+ pushSelectedRows();
906694
+ rows.push({ text: "", kind: "empty" });
906695
+ pushSummaryRows();
906696
+ } else {
906697
+ pushSummaryRows();
906698
+ rows.push({ text: "", kind: "empty" });
906699
+ pushSelectedRows();
906700
+ }
906701
+ if (wizard.hydrationPending || wizard.hydrationError !== null || wizard.applyFeedback !== null) {
906702
+ rows.push({ text: "", kind: "empty" });
906703
+ }
906704
+ if (wizard.hydrationPending) {
906705
+ rows.push({ text: "Loading current settings...", fg: FULLSCREEN_PALETTE.info, bold: true });
906706
+ }
906707
+ if (wizard.hydrationError !== null) {
906708
+ pushWrapped(rows, `Current settings could not load: ${wizard.hydrationError}`, width, { fg: FULLSCREEN_PALETTE.bad, bold: true });
906709
+ }
906710
+ if (wizard.applyFeedback !== null) {
906711
+ const feedbackColor = wizard.applyFeedback.severity === "error" ? FULLSCREEN_PALETTE.bad : wizard.applyFeedback.severity === "warning" ? FULLSCREEN_PALETTE.warn : FULLSCREEN_PALETTE.info;
906712
+ rows.push({ text: wizard.applyFeedback.title, fg: feedbackColor, bold: true });
906713
+ pushWrapped(rows, wizard.applyFeedback.summary, width, { fg: FULLSCREEN_PALETTE.text });
906714
+ for (const message of wizard.applyFeedback.messages) {
906715
+ pushWrapped(rows, message, width, { fg: FULLSCREEN_PALETTE.muted });
906716
+ }
906717
+ }
906718
+ return rows;
906719
+ }
906720
+ function formatFieldRowText(wizard, field, selected, width) {
906721
+ const badge = `[${wizard.getFieldValueLabel(field)}]`;
906722
+ const badgeWidth = getDisplayWidth(badge);
906723
+ const labelWidth = Math.max(1, width - badgeWidth - 2);
906724
+ const label = truncateDisplay(`${fieldRowPrefix(wizard, field, selected)}${field.label}`, labelWidth);
906725
+ return `${label}${" ".repeat(Math.max(1, width - getDisplayWidth(label) - badgeWidth))}${badge}`;
906726
+ }
906727
+ function buildControlRows2(wizard, width, height) {
906728
+ const visibleFields = Math.max(1, height);
906729
+ const fieldRows = buildFieldRows(wizard, visibleFields, height);
906730
+ const rows = fieldRows.map((row) => {
906731
+ if (row.kind === "empty")
906732
+ return { text: "", kind: "empty" };
906733
+ if (row.kind === "moreAbove" || row.kind === "moreBelow") {
906734
+ return { text: row.text, kind: "more", fg: FULLSCREEN_PALETTE.dim, dim: true };
906735
+ }
906736
+ const selected = row.absoluteIndex === wizard.getSelectedFieldIndex();
906737
+ return {
906738
+ text: formatFieldRowText(wizard, row.field, selected, width),
906739
+ selected,
906740
+ kind: "item",
906741
+ fg: fieldColor(wizard, row.field, selected),
906742
+ bold: selected || row.field.kind === "action"
906743
+ };
906744
+ });
906745
+ while (rows.length < height)
906746
+ rows.push({ text: "", kind: "empty" });
906747
+ return rows.slice(0, height);
906748
+ }
906749
+ function renderOnboardingWizard(wizard, width, viewportHeight) {
906750
+ const layoutOptions = {
906751
+ width,
906752
+ height: viewportHeight,
906753
+ leftWidth: width < 90 ? undefined : 30,
906754
+ contextRatio: 0.42,
906755
+ minContextRows: 8
906756
+ };
906757
+ const metrics = getFullscreenWorkspaceMetrics(layoutOptions);
906758
+ return renderFullscreenWorkspace({
906759
+ width,
906760
+ height: viewportHeight,
906761
+ title: "GoodVibes Agent / Onboarding Wizard",
906762
+ stateLabel: `${modeLabel(wizard.mode)} \xB7 ${wizard.stepIndex + 1}/${wizard.steps.length} \xB7 ${changedScreensLabel(wizard)}`,
906763
+ leftHeader: "Steps",
906764
+ mainHeader: wizard.currentStep.title,
906765
+ leftRows: buildStepRows(wizard, metrics.bodyRows),
906766
+ contextRows: buildContextRows2(wizard, metrics.contextWidth),
906767
+ controlRows: buildControlRows2(wizard, metrics.contextWidth, metrics.controlRows),
906768
+ footer: footerText4(wizard),
906769
+ leftWidth: layoutOptions.leftWidth,
906770
+ contextRatio: layoutOptions.contextRatio,
906771
+ minContextRows: layoutOptions.minContextRows
906772
+ });
906773
+ }
906774
+
906720
906775
  // src/shell/onboarding-fullscreen.ts
906721
906776
  function normalizeFullscreenViewport(lines, width, height) {
906722
906777
  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.38",
3
+ "version": "1.0.39",
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
- const lines = renderOnboardingWizard(input.onboardingWizard, conversationWidth, viewportHeight);
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) {
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.38';
9
+ let _version = '1.0.39';
10
10
  try {
11
11
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {
12
12
  readonly version?: unknown;