@yagni-app/code 1.0.3 → 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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* `ctx.
|
|
30
|
-
*
|
|
31
|
-
*
|
|
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
|
-
|
|
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;
|
package/dist/extension/footer.js
CHANGED
|
@@ -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.
|
|
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
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* `ctx.
|
|
30
|
-
*
|
|
31
|
-
*
|
|
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 ·]
|
|
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.
|
|
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": "
|
|
44
|
+
"yagniSourceSha": "58371f52233aaff50f140f858c9018d3e500e4e1"
|
|
45
45
|
}
|