@yagni-app/code 1.0.2 → 1.0.4

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.
@@ -309,14 +309,31 @@ class QuestionComponent {
309
309
  const indexText = `${this.otherIndex + 1}.`.padEnd(indexPad);
310
310
  if (isSelected) {
311
311
  // Inline input: show current text + inverse-video cursor at end.
312
+ // Wraps like a growing text field (the prompt input), never truncated.
312
313
  const cursor = "\x1b[7m \x1b[27m"; // space with reverse video = visible cursor
314
+ const gutter = `${marker} ${indexText}`;
315
+ const gutterWidth = visibleWidth(gutter);
316
+ // Reserve one column so the trailing cursor always fits on the last line.
317
+ const wrapWidth = Math.max(1, width - gutterWidth - 1);
313
318
  const text = this.otherValue || " ";
314
- lines.push(clampLine(`${marker} ${indexText}${text}${cursor}`, width));
319
+ const wrapped = wrapTextWithAnsi(text, wrapWidth);
320
+ wrapped.forEach((w, i) => {
321
+ const prefix = i === 0 ? gutter : " ".repeat(gutterWidth);
322
+ const body = i === wrapped.length - 1 ? `${w}${cursor}` : w;
323
+ lines.push(clampLine(prefix + body, width));
324
+ });
315
325
  }
316
326
  else {
317
327
  // Not focused: show placeholder or current text in dim.
318
328
  const display = this.otherValue || "(type a custom answer)";
319
- lines.push(clampLine(`${marker} ${indexText}${t.fg("dim", display)}`, width));
329
+ const gutter = `${marker} ${indexText}`;
330
+ const gutterWidth = visibleWidth(gutter);
331
+ const wrapWidth = Math.max(1, width - gutterWidth);
332
+ const wrapped = wrapTextWithAnsi(t.fg("dim", display), wrapWidth);
333
+ wrapped.forEach((w, i) => {
334
+ const prefix = i === 0 ? gutter : " ".repeat(gutterWidth);
335
+ lines.push(clampLine(prefix + w, width));
336
+ });
320
337
  }
321
338
  }
322
339
  handleInput(data) {
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Renders three lines:
5
5
  * 1. folder · [worktree] · branch (git context; ~-path fallback off-repo)
6
- * 2. model · ↑in ↓out $cost · ctx% (session stats; context % is an integer)
6
+ * 2. ↑in ↓out $cost · ctx% (session stats; context % is an integer)
7
7
  * 3. extension statuses (branding, todo counter, mode) joined by " · "
8
8
  *
9
9
  * --- How to customize the status bar (for future tickets) ---
@@ -24,11 +24,11 @@
24
24
  * - `footerData` — ReadonlyFooterDataProvider: `getGitBranch()`,
25
25
  * `getExtensionStatuses()` (statuses set via `ctx.ui.setStatus(key, text)`),
26
26
  * `getAvailableProviderCount()`
27
- * Model info, token stats, and context usage are NOT on `footerData` — they're
28
- * on `ctx` (the ExtensionContext passed to the session_start handler):
29
- * `ctx.model`, `ctx.sessionManager`, `ctx.getContextUsage()`. Thread them
30
- * through a closure if the footer needs them (this module's
31
- * `createYagniFooterFactory` does exactly that).
27
+ * Token stats and context usage are NOT on `footerData` — they're on `ctx`
28
+ * (the ExtensionContext passed to the session_start handler):
29
+ * `ctx.sessionManager`, `ctx.getContextUsage()`. Thread them through a closure
30
+ * if the footer needs them (this module's `createYagniFooterFactory` does
31
+ * exactly that).
32
32
  *
33
33
  * COMPONENT CONTRACT: the returned object needs `render(width: number): string[]`
34
34
  * (returns the lines to display, one string per row) and `invalidate()` (called
@@ -94,8 +94,7 @@ export declare function detectGitInfo(cwd: string, home: string | undefined): Gi
94
94
  /** Pure line-builder, exported for tests. All data injected; colors via theme. */
95
95
  export declare function renderFooterLines(input: {
96
96
  git: GitInfo;
97
- model: string;
98
- /** Current permission mode; shown on line 2 to the left of the model as "<mode> mode". */
97
+ /** Current permission mode; shown on line 2 to the left of the stats as "<mode> mode". */
99
98
  mode?: PermissionMode | null;
100
99
  /** Formatted `+N -M` / `±`, or null when clean — appended to the branch as `[ … ]`. */
101
100
  diff?: string | null;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Renders three lines:
5
5
  * 1. folder · [worktree] · branch (git context; ~-path fallback off-repo)
6
- * 2. model · ↑in ↓out $cost · ctx% (session stats; context % is an integer)
6
+ * 2. ↑in ↓out $cost · ctx% (session stats; context % is an integer)
7
7
  * 3. extension statuses (branding, todo counter, mode) joined by " · "
8
8
  *
9
9
  * --- How to customize the status bar (for future tickets) ---
@@ -24,11 +24,11 @@
24
24
  * - `footerData` — ReadonlyFooterDataProvider: `getGitBranch()`,
25
25
  * `getExtensionStatuses()` (statuses set via `ctx.ui.setStatus(key, text)`),
26
26
  * `getAvailableProviderCount()`
27
- * Model info, token stats, and context usage are NOT on `footerData` — they're
28
- * on `ctx` (the ExtensionContext passed to the session_start handler):
29
- * `ctx.model`, `ctx.sessionManager`, `ctx.getContextUsage()`. Thread them
30
- * through a closure if the footer needs them (this module's
31
- * `createYagniFooterFactory` does exactly that).
27
+ * Token stats and context usage are NOT on `footerData` — they're on `ctx`
28
+ * (the ExtensionContext passed to the session_start handler):
29
+ * `ctx.sessionManager`, `ctx.getContextUsage()`. Thread them through a closure
30
+ * if the footer needs them (this module's `createYagniFooterFactory` does
31
+ * exactly that).
32
32
  *
33
33
  * COMPONENT CONTRACT: the returned object needs `render(width: number): string[]`
34
34
  * (returns the lines to display, one string per row) and `invalidate()` (called
@@ -244,7 +244,7 @@ export function renderFooterLines(input, theme, width, padX = 0) {
244
244
  }
245
245
  }
246
246
  const line1 = pad + truncateToWidth(line1Parts.join(sep), contentWidth, dim("…"));
247
- // Line 2: [mode ·] model · ↑in ↓out $cost · ctx%
247
+ // Line 2: [mode ·] ↑in ↓out $cost · ctx%
248
248
  // Child-process spend (subagents, advisor, /go) joins the driver totals so
249
249
  // the footer matches the per-child receipts and /cost's session scope.
250
250
  const child = input.childUsage;
@@ -265,7 +265,6 @@ export function renderFooterLines(input, theme, width, padX = 0) {
265
265
  const modeLabel = modeDisplay(input.mode);
266
266
  line2Parts.push(theme.fg(modeLabel.color, modeLabel.text) + dim(" (shift+tab to change)"));
267
267
  }
268
- line2Parts.push(dim(input.model));
269
268
  if (stats)
270
269
  line2Parts.push(dim(stats));
271
270
  line2Parts.push(theme.fg(contextColor(input.contextPercent), percentText));
@@ -307,7 +306,6 @@ export function createYagniFooterFactory(ctx, modeHolder, invalidateHandle, chil
307
306
  .map(([, text]) => text);
308
307
  return renderFooterLines({
309
308
  git: gitInfo(),
310
- model: ctx.model?.id ?? "no-model",
311
309
  mode: modeHolder?.get() ?? null,
312
310
  diff: formatDiffStat(diffStatCache?.get() ?? null),
313
311
  usage: collectUsage(ctx.sessionManager),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yagni-app/code",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "YAGNI Code: a terminal coding agent that already knows your company. One YAGNI login routes the model and grounds the agent in your team's context.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "YAGNI, Inc. <jack@yagni.app> (https://yagni.app)",
@@ -41,5 +41,5 @@
41
41
  "turndown": "^7.2.4",
42
42
  "typebox": "^1.3.15"
43
43
  },
44
- "yagniSourceSha": "431d2548899146f7522a21fed3488b204b4e77d0"
44
+ "yagniSourceSha": "58371f52233aaff50f140f858c9018d3e500e4e1"
45
45
  }