@joshski/dust 0.1.74 → 0.1.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audits.js +110 -0
- package/dist/dust.js +144 -23
- package/package.json +1 -1
package/dist/audits.js
CHANGED
|
@@ -670,6 +670,114 @@ function globalState() {
|
|
|
670
670
|
- [ ] Proposed ideas for refactoring global state to explicit dependencies
|
|
671
671
|
`;
|
|
672
672
|
}
|
|
673
|
+
function repositoryContext() {
|
|
674
|
+
return dedent`
|
|
675
|
+
# Repository Context
|
|
676
|
+
|
|
677
|
+
Compile or update \`.dust/repository.md\` with a high-level overview of the repository's purpose, capabilities, and design philosophy.
|
|
678
|
+
|
|
679
|
+
## Purpose
|
|
680
|
+
|
|
681
|
+
The repository context document helps downstream agents quickly understand the project without reading individual files. It describes features, scenarios, and design philosophy rather than implementation details. This enables high-level planning where agents reason about capabilities rather than code structure.
|
|
682
|
+
|
|
683
|
+
## Scope
|
|
684
|
+
|
|
685
|
+
Review the current state of the codebase and produce a document covering:
|
|
686
|
+
|
|
687
|
+
1. **What the project is** - A one-sentence summary of its purpose
|
|
688
|
+
2. **What it does** - The key capabilities and features it provides
|
|
689
|
+
3. **How it fits into workflows** - How users or other systems interact with it
|
|
690
|
+
4. **Design philosophy** - The guiding principles behind its architecture
|
|
691
|
+
5. **Key scenarios** - The main use cases or user journeys it supports
|
|
692
|
+
|
|
693
|
+
Avoid mentioning specific file paths, class names, or implementation details. Write for someone who needs to make high-level suggestions about the project's direction, not someone about to edit a specific file.
|
|
694
|
+
|
|
695
|
+
## Analysis Steps
|
|
696
|
+
|
|
697
|
+
1. Read the existing \`.dust/repository.md\` if it exists
|
|
698
|
+
2. Review README, package.json, and top-level documentation for project purpose
|
|
699
|
+
3. Scan the codebase to understand features and capabilities
|
|
700
|
+
4. Review \`.dust/principles/\` for design philosophy
|
|
701
|
+
5. Review \`.dust/facts/\` for context on current state
|
|
702
|
+
6. Update \`.dust/repository.md\` with current findings, preserving any sections that are still accurate
|
|
703
|
+
|
|
704
|
+
## Principles
|
|
705
|
+
|
|
706
|
+
(none)
|
|
707
|
+
|
|
708
|
+
## Blocked By
|
|
709
|
+
|
|
710
|
+
(none)
|
|
711
|
+
|
|
712
|
+
## Definition of Done
|
|
713
|
+
|
|
714
|
+
- [ ] \`.dust/repository.md\` exists and is up to date
|
|
715
|
+
- [ ] Document describes what the project does without referencing specific files
|
|
716
|
+
- [ ] Key capabilities and features are listed
|
|
717
|
+
- [ ] Design philosophy or guiding approach is captured
|
|
718
|
+
- [ ] Document is concise enough to fit comfortably in an agent context window
|
|
719
|
+
- [ ] A new agent reading only this document could make sensible high-level suggestions
|
|
720
|
+
`;
|
|
721
|
+
}
|
|
722
|
+
function slowTests() {
|
|
723
|
+
return dedent`
|
|
724
|
+
# Slow Tests
|
|
725
|
+
|
|
726
|
+
Identify slow-running tests that impact feedback loop speed.
|
|
727
|
+
|
|
728
|
+
${ideasHint}
|
|
729
|
+
|
|
730
|
+
## Scope
|
|
731
|
+
|
|
732
|
+
Focus on these areas:
|
|
733
|
+
|
|
734
|
+
1. **Test execution times** - Identify tests that exceed a reasonable duration threshold (e.g., 100ms for unit tests, 1s for integration tests)
|
|
735
|
+
2. **I/O-bound tests** - Tests that perform actual file system, network, or database operations
|
|
736
|
+
3. **Sleep/delay usage** - Tests using \`setTimeout\`, \`sleep\`, or similar timing functions
|
|
737
|
+
4. **Missing mocks** - Tests that make real HTTP requests or database calls instead of using stubs
|
|
738
|
+
5. **Setup overhead** - Expensive \`beforeEach\`/\`beforeAll\` setup that could be optimized or shared
|
|
739
|
+
6. **Serial test execution** - Tests that could run in parallel but are forced to run serially
|
|
740
|
+
|
|
741
|
+
## Analysis Steps
|
|
742
|
+
|
|
743
|
+
1. Run the test suite with timing output: \`npm test -- --reporter=verbose\` or equivalent
|
|
744
|
+
2. Identify tests taking longer than the threshold (100ms+ for unit, 1s+ for integration)
|
|
745
|
+
3. Search for \`setTimeout\`, \`sleep\`, \`delay\`, and similar timing patterns in test files
|
|
746
|
+
4. Look for real I/O: \`fetch\`, \`axios\`, database clients, file system operations without mocks
|
|
747
|
+
5. Review \`beforeEach\`/\`beforeAll\` blocks for expensive operations
|
|
748
|
+
6. Check test configuration for parallelization settings
|
|
749
|
+
|
|
750
|
+
## Output
|
|
751
|
+
|
|
752
|
+
For each slow test identified, provide:
|
|
753
|
+
- **Test name** - The describe/it block name
|
|
754
|
+
- **File path** - Location of the test
|
|
755
|
+
- **Duration** - How long the test takes (if measurable)
|
|
756
|
+
- **Cause** - Why the test is slow (I/O, sleep, setup, etc.)
|
|
757
|
+
- **Suggestion** - Specific optimization (mock the API, use fake timers, share setup, etc.)
|
|
758
|
+
|
|
759
|
+
## Principles
|
|
760
|
+
|
|
761
|
+
- [Fast Feedback Loops](../principles/fast-feedback-loops.md) - Tests should run quickly for tight iteration cycles
|
|
762
|
+
- [Fast Feedback](../principles/fast-feedback.md) - Slow tests discourage frequent validation
|
|
763
|
+
- [Keep Unit Tests Pure](../principles/keep-unit-tests-pure.md) - Pure tests are faster and more reliable
|
|
764
|
+
- [Stubs Over Mocks](../principles/stubs-over-mocks.md) - Use stubs to avoid slow real dependencies
|
|
765
|
+
|
|
766
|
+
## Blocked By
|
|
767
|
+
|
|
768
|
+
(none)
|
|
769
|
+
|
|
770
|
+
## Definition of Done
|
|
771
|
+
|
|
772
|
+
- [ ] Ran test suite with timing information
|
|
773
|
+
- [ ] Listed tests exceeding duration thresholds (100ms unit, 1s integration)
|
|
774
|
+
- [ ] Identified tests using sleep/setTimeout/delay patterns
|
|
775
|
+
- [ ] Found tests with unmocked I/O (network, database, file system)
|
|
776
|
+
- [ ] Reviewed beforeEach/beforeAll for optimization opportunities
|
|
777
|
+
- [ ] Checked test parallelization configuration
|
|
778
|
+
- [ ] Proposed ideas for optimizing the slowest tests
|
|
779
|
+
`;
|
|
780
|
+
}
|
|
673
781
|
function ubiquitousLanguage() {
|
|
674
782
|
return dedent`
|
|
675
783
|
# Ubiquitous Language
|
|
@@ -736,7 +844,9 @@ var stockAuditFunctions = {
|
|
|
736
844
|
"ideas-from-principles": ideasFromPrinciples,
|
|
737
845
|
"performance-review": performanceReview,
|
|
738
846
|
"refactoring-opportunities": refactoringOpportunities,
|
|
847
|
+
"repository-context": repositoryContext,
|
|
739
848
|
"security-review": securityReview,
|
|
849
|
+
"slow-tests": slowTests,
|
|
740
850
|
"stale-ideas": staleIdeas,
|
|
741
851
|
"test-coverage": testCoverage,
|
|
742
852
|
"ubiquitous-language": ubiquitousLanguage
|
package/dist/dust.js
CHANGED
|
@@ -275,7 +275,7 @@ async function loadSettings(cwd, fileSystem) {
|
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
// lib/version.ts
|
|
278
|
-
var DUST_VERSION = "0.1.
|
|
278
|
+
var DUST_VERSION = "0.1.76";
|
|
279
279
|
|
|
280
280
|
// lib/session.ts
|
|
281
281
|
var DUST_UNATTENDED = "DUST_UNATTENDED";
|
|
@@ -1217,6 +1217,114 @@ function globalState() {
|
|
|
1217
1217
|
- [ ] Proposed ideas for refactoring global state to explicit dependencies
|
|
1218
1218
|
`;
|
|
1219
1219
|
}
|
|
1220
|
+
function repositoryContext() {
|
|
1221
|
+
return dedent`
|
|
1222
|
+
# Repository Context
|
|
1223
|
+
|
|
1224
|
+
Compile or update \`.dust/repository.md\` with a high-level overview of the repository's purpose, capabilities, and design philosophy.
|
|
1225
|
+
|
|
1226
|
+
## Purpose
|
|
1227
|
+
|
|
1228
|
+
The repository context document helps downstream agents quickly understand the project without reading individual files. It describes features, scenarios, and design philosophy rather than implementation details. This enables high-level planning where agents reason about capabilities rather than code structure.
|
|
1229
|
+
|
|
1230
|
+
## Scope
|
|
1231
|
+
|
|
1232
|
+
Review the current state of the codebase and produce a document covering:
|
|
1233
|
+
|
|
1234
|
+
1. **What the project is** - A one-sentence summary of its purpose
|
|
1235
|
+
2. **What it does** - The key capabilities and features it provides
|
|
1236
|
+
3. **How it fits into workflows** - How users or other systems interact with it
|
|
1237
|
+
4. **Design philosophy** - The guiding principles behind its architecture
|
|
1238
|
+
5. **Key scenarios** - The main use cases or user journeys it supports
|
|
1239
|
+
|
|
1240
|
+
Avoid mentioning specific file paths, class names, or implementation details. Write for someone who needs to make high-level suggestions about the project's direction, not someone about to edit a specific file.
|
|
1241
|
+
|
|
1242
|
+
## Analysis Steps
|
|
1243
|
+
|
|
1244
|
+
1. Read the existing \`.dust/repository.md\` if it exists
|
|
1245
|
+
2. Review README, package.json, and top-level documentation for project purpose
|
|
1246
|
+
3. Scan the codebase to understand features and capabilities
|
|
1247
|
+
4. Review \`.dust/principles/\` for design philosophy
|
|
1248
|
+
5. Review \`.dust/facts/\` for context on current state
|
|
1249
|
+
6. Update \`.dust/repository.md\` with current findings, preserving any sections that are still accurate
|
|
1250
|
+
|
|
1251
|
+
## Principles
|
|
1252
|
+
|
|
1253
|
+
(none)
|
|
1254
|
+
|
|
1255
|
+
## Blocked By
|
|
1256
|
+
|
|
1257
|
+
(none)
|
|
1258
|
+
|
|
1259
|
+
## Definition of Done
|
|
1260
|
+
|
|
1261
|
+
- [ ] \`.dust/repository.md\` exists and is up to date
|
|
1262
|
+
- [ ] Document describes what the project does without referencing specific files
|
|
1263
|
+
- [ ] Key capabilities and features are listed
|
|
1264
|
+
- [ ] Design philosophy or guiding approach is captured
|
|
1265
|
+
- [ ] Document is concise enough to fit comfortably in an agent context window
|
|
1266
|
+
- [ ] A new agent reading only this document could make sensible high-level suggestions
|
|
1267
|
+
`;
|
|
1268
|
+
}
|
|
1269
|
+
function slowTests() {
|
|
1270
|
+
return dedent`
|
|
1271
|
+
# Slow Tests
|
|
1272
|
+
|
|
1273
|
+
Identify slow-running tests that impact feedback loop speed.
|
|
1274
|
+
|
|
1275
|
+
${ideasHint}
|
|
1276
|
+
|
|
1277
|
+
## Scope
|
|
1278
|
+
|
|
1279
|
+
Focus on these areas:
|
|
1280
|
+
|
|
1281
|
+
1. **Test execution times** - Identify tests that exceed a reasonable duration threshold (e.g., 100ms for unit tests, 1s for integration tests)
|
|
1282
|
+
2. **I/O-bound tests** - Tests that perform actual file system, network, or database operations
|
|
1283
|
+
3. **Sleep/delay usage** - Tests using \`setTimeout\`, \`sleep\`, or similar timing functions
|
|
1284
|
+
4. **Missing mocks** - Tests that make real HTTP requests or database calls instead of using stubs
|
|
1285
|
+
5. **Setup overhead** - Expensive \`beforeEach\`/\`beforeAll\` setup that could be optimized or shared
|
|
1286
|
+
6. **Serial test execution** - Tests that could run in parallel but are forced to run serially
|
|
1287
|
+
|
|
1288
|
+
## Analysis Steps
|
|
1289
|
+
|
|
1290
|
+
1. Run the test suite with timing output: \`npm test -- --reporter=verbose\` or equivalent
|
|
1291
|
+
2. Identify tests taking longer than the threshold (100ms+ for unit, 1s+ for integration)
|
|
1292
|
+
3. Search for \`setTimeout\`, \`sleep\`, \`delay\`, and similar timing patterns in test files
|
|
1293
|
+
4. Look for real I/O: \`fetch\`, \`axios\`, database clients, file system operations without mocks
|
|
1294
|
+
5. Review \`beforeEach\`/\`beforeAll\` blocks for expensive operations
|
|
1295
|
+
6. Check test configuration for parallelization settings
|
|
1296
|
+
|
|
1297
|
+
## Output
|
|
1298
|
+
|
|
1299
|
+
For each slow test identified, provide:
|
|
1300
|
+
- **Test name** - The describe/it block name
|
|
1301
|
+
- **File path** - Location of the test
|
|
1302
|
+
- **Duration** - How long the test takes (if measurable)
|
|
1303
|
+
- **Cause** - Why the test is slow (I/O, sleep, setup, etc.)
|
|
1304
|
+
- **Suggestion** - Specific optimization (mock the API, use fake timers, share setup, etc.)
|
|
1305
|
+
|
|
1306
|
+
## Principles
|
|
1307
|
+
|
|
1308
|
+
- [Fast Feedback Loops](../principles/fast-feedback-loops.md) - Tests should run quickly for tight iteration cycles
|
|
1309
|
+
- [Fast Feedback](../principles/fast-feedback.md) - Slow tests discourage frequent validation
|
|
1310
|
+
- [Keep Unit Tests Pure](../principles/keep-unit-tests-pure.md) - Pure tests are faster and more reliable
|
|
1311
|
+
- [Stubs Over Mocks](../principles/stubs-over-mocks.md) - Use stubs to avoid slow real dependencies
|
|
1312
|
+
|
|
1313
|
+
## Blocked By
|
|
1314
|
+
|
|
1315
|
+
(none)
|
|
1316
|
+
|
|
1317
|
+
## Definition of Done
|
|
1318
|
+
|
|
1319
|
+
- [ ] Ran test suite with timing information
|
|
1320
|
+
- [ ] Listed tests exceeding duration thresholds (100ms unit, 1s integration)
|
|
1321
|
+
- [ ] Identified tests using sleep/setTimeout/delay patterns
|
|
1322
|
+
- [ ] Found tests with unmocked I/O (network, database, file system)
|
|
1323
|
+
- [ ] Reviewed beforeEach/beforeAll for optimization opportunities
|
|
1324
|
+
- [ ] Checked test parallelization configuration
|
|
1325
|
+
- [ ] Proposed ideas for optimizing the slowest tests
|
|
1326
|
+
`;
|
|
1327
|
+
}
|
|
1220
1328
|
function ubiquitousLanguage() {
|
|
1221
1329
|
return dedent`
|
|
1222
1330
|
# Ubiquitous Language
|
|
@@ -1283,7 +1391,9 @@ var stockAuditFunctions = {
|
|
|
1283
1391
|
"ideas-from-principles": ideasFromPrinciples,
|
|
1284
1392
|
"performance-review": performanceReview,
|
|
1285
1393
|
"refactoring-opportunities": refactoringOpportunities,
|
|
1394
|
+
"repository-context": repositoryContext,
|
|
1286
1395
|
"security-review": securityReview,
|
|
1396
|
+
"slow-tests": slowTests,
|
|
1287
1397
|
"stale-ideas": staleIdeas,
|
|
1288
1398
|
"test-coverage": testCoverage,
|
|
1289
1399
|
"ubiquitous-language": ubiquitousLanguage
|
|
@@ -2214,7 +2324,8 @@ function getRepoPath(repoName, reposDir) {
|
|
|
2214
2324
|
async function cloneRepository(repository, targetPath, spawn, context) {
|
|
2215
2325
|
return new Promise((resolve) => {
|
|
2216
2326
|
const proc = spawn("git", ["clone", repository.gitUrl, targetPath], {
|
|
2217
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
2327
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2328
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
2218
2329
|
});
|
|
2219
2330
|
let stderr = "";
|
|
2220
2331
|
proc.stderr?.on("data", (data) => {
|
|
@@ -2438,26 +2549,26 @@ function getEnvironmentContext(cwd) {
|
|
|
2438
2549
|
function formatLoopEvent(event) {
|
|
2439
2550
|
switch (event.type) {
|
|
2440
2551
|
case "loop.warning":
|
|
2441
|
-
return "
|
|
2552
|
+
return "WARNING: This command skips all permission checks. Only use in a sandbox environment!";
|
|
2442
2553
|
case "loop.started": {
|
|
2443
2554
|
const agent2 = event.agentType ?? "claude";
|
|
2444
|
-
return
|
|
2555
|
+
return `Starting dust loop ${agent2} (max ${event.maxIterations} iterations)...`;
|
|
2445
2556
|
}
|
|
2446
2557
|
case "loop.syncing":
|
|
2447
|
-
return "
|
|
2558
|
+
return "Syncing with remote";
|
|
2448
2559
|
case "loop.sync_skipped":
|
|
2449
2560
|
return `Note: git pull skipped (${event.reason})`;
|
|
2450
2561
|
case "loop.checking_tasks":
|
|
2451
2562
|
return null;
|
|
2452
2563
|
case "loop.no_tasks":
|
|
2453
|
-
return "
|
|
2564
|
+
return "No tasks available. Sleeping...";
|
|
2454
2565
|
case "loop.tasks_found":
|
|
2455
|
-
return
|
|
2566
|
+
return `Found a task. Going to work!
|
|
2456
2567
|
`;
|
|
2457
2568
|
case "loop.iteration_complete":
|
|
2458
|
-
return
|
|
2569
|
+
return `Completed iteration ${event.iteration}/${event.maxIterations}`;
|
|
2459
2570
|
case "loop.ended":
|
|
2460
|
-
return
|
|
2571
|
+
return `Reached max iterations (${event.maxIterations}). Exiting.`;
|
|
2461
2572
|
}
|
|
2462
2573
|
}
|
|
2463
2574
|
function createPostEvent(fetchFn) {
|
|
@@ -2515,7 +2626,8 @@ async function gitPull(cwd, spawn) {
|
|
|
2515
2626
|
return new Promise((resolve) => {
|
|
2516
2627
|
const proc = spawn("git", ["pull"], {
|
|
2517
2628
|
cwd,
|
|
2518
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
2629
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2630
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
2519
2631
|
});
|
|
2520
2632
|
let stderr = "";
|
|
2521
2633
|
proc.stderr?.on("data", (data) => {
|
|
@@ -3065,6 +3177,15 @@ function parseServerMessage(data) {
|
|
|
3065
3177
|
}
|
|
3066
3178
|
|
|
3067
3179
|
// lib/bucket/terminal-ui.ts
|
|
3180
|
+
var CHARS = {
|
|
3181
|
+
dot: "*",
|
|
3182
|
+
sparkle: "",
|
|
3183
|
+
ellipsis: "...",
|
|
3184
|
+
hline: "-",
|
|
3185
|
+
arrows_lr: "<->",
|
|
3186
|
+
arrows_ud: "up/dn",
|
|
3187
|
+
scroll_down: "v"
|
|
3188
|
+
};
|
|
3068
3189
|
var ANSI = {
|
|
3069
3190
|
HIDE_CURSOR: "\x1B[?25l",
|
|
3070
3191
|
SHOW_CURSOR: "\x1B[?25h",
|
|
@@ -3119,8 +3240,8 @@ function truncateLine(text, maxWidth) {
|
|
|
3119
3240
|
for (let match = ansiRegex.exec(text);match !== null; match = ansiRegex.exec(text)) {
|
|
3120
3241
|
const textBefore = text.slice(lastIndex, match.index);
|
|
3121
3242
|
for (const char of textBefore) {
|
|
3122
|
-
if (visibleCount >= maxWidth -
|
|
3123
|
-
result +=
|
|
3243
|
+
if (visibleCount >= maxWidth - CHARS.ellipsis.length) {
|
|
3244
|
+
result += CHARS.ellipsis;
|
|
3124
3245
|
return result + ANSI.RESET;
|
|
3125
3246
|
}
|
|
3126
3247
|
result += char;
|
|
@@ -3131,8 +3252,8 @@ function truncateLine(text, maxWidth) {
|
|
|
3131
3252
|
}
|
|
3132
3253
|
const remaining = text.slice(lastIndex);
|
|
3133
3254
|
for (const char of remaining) {
|
|
3134
|
-
if (visibleCount >= maxWidth -
|
|
3135
|
-
result +=
|
|
3255
|
+
if (visibleCount >= maxWidth - CHARS.ellipsis.length) {
|
|
3256
|
+
result += CHARS.ellipsis;
|
|
3136
3257
|
return result + ANSI.RESET;
|
|
3137
3258
|
}
|
|
3138
3259
|
result += char;
|
|
@@ -3232,7 +3353,7 @@ function getTabRowCount(state) {
|
|
|
3232
3353
|
return 1;
|
|
3233
3354
|
const tabWidths = [5];
|
|
3234
3355
|
for (const name of state.repositories) {
|
|
3235
|
-
tabWidths.push(name.length +
|
|
3356
|
+
tabWidths.push(name.length + 2 + CHARS.dot.length + 1);
|
|
3236
3357
|
}
|
|
3237
3358
|
let rows = 1;
|
|
3238
3359
|
let currentRowWidth = 0;
|
|
@@ -3302,8 +3423,8 @@ function renderTabs(state) {
|
|
|
3302
3423
|
const color = getRepoColor(name, i);
|
|
3303
3424
|
const agentStatus = state.agentStatuses.get(name) ?? "idle";
|
|
3304
3425
|
const dotColor = agentStatus === "busy" ? ANSI.FG_GREEN : ANSI.DIM;
|
|
3305
|
-
const dot = `${dotColor}
|
|
3306
|
-
const width = name.length +
|
|
3426
|
+
const dot = `${dotColor}${CHARS.dot}${ANSI.RESET}`;
|
|
3427
|
+
const width = name.length + 2 + CHARS.dot.length + 1;
|
|
3307
3428
|
if (i === state.selectedIndex) {
|
|
3308
3429
|
tabs.push({
|
|
3309
3430
|
text: ` ${dot}${color} ${ANSI.INVERSE}${name}${ANSI.RESET} `,
|
|
@@ -3328,10 +3449,10 @@ function renderTabs(state) {
|
|
|
3328
3449
|
return rows.map((row) => row.map((t) => t.text).join("|"));
|
|
3329
3450
|
}
|
|
3330
3451
|
function renderHelpLine() {
|
|
3331
|
-
return `${ANSI.DIM}[
|
|
3452
|
+
return `${ANSI.DIM}[${CHARS.arrows_lr}] select [${CHARS.arrows_ud}] scroll [PgUp/PgDn] page [g/G] top/bottom [o] open [q] quit${ANSI.RESET}`;
|
|
3332
3453
|
}
|
|
3333
3454
|
function renderSeparator(width) {
|
|
3334
|
-
return
|
|
3455
|
+
return CHARS.hline.repeat(Math.max(0, width));
|
|
3335
3456
|
}
|
|
3336
3457
|
function formatLogLine(line, prefixAlign, maxWidth) {
|
|
3337
3458
|
let prefix = "";
|
|
@@ -3363,7 +3484,7 @@ function formatLogLine(line, prefixAlign, maxWidth) {
|
|
|
3363
3484
|
function renderFrame(state) {
|
|
3364
3485
|
const lines = [];
|
|
3365
3486
|
const hostLabel = state.connectedHost ? ` ${ANSI.DIM}[connected to ${state.connectedHost}]${ANSI.RESET}` : "";
|
|
3366
|
-
lines.push(`${ANSI.BOLD}
|
|
3487
|
+
lines.push(`${ANSI.BOLD}${CHARS.sparkle}dust bucket${ANSI.RESET}${hostLabel}`);
|
|
3367
3488
|
const tabRows = renderTabs(state);
|
|
3368
3489
|
for (const tabRow of tabRows) {
|
|
3369
3490
|
lines.push(tabRow);
|
|
@@ -3386,7 +3507,7 @@ function renderFrame(state) {
|
|
|
3386
3507
|
lines.push("");
|
|
3387
3508
|
}
|
|
3388
3509
|
if (state.scrollOffset > 0) {
|
|
3389
|
-
const indicator = `${ANSI.DIM}
|
|
3510
|
+
const indicator = `${ANSI.DIM}${CHARS.scroll_down} ${state.scrollOffset} more${ANSI.RESET}`;
|
|
3390
3511
|
lines[lines.length - 1] = indicator;
|
|
3391
3512
|
}
|
|
3392
3513
|
const output = [];
|
|
@@ -3534,8 +3655,8 @@ function defaultSetupResize(onResize) {
|
|
|
3534
3655
|
}
|
|
3535
3656
|
function defaultGetTerminalSize() {
|
|
3536
3657
|
return {
|
|
3537
|
-
width: process.stdout.columns
|
|
3538
|
-
height: process.stdout.rows
|
|
3658
|
+
width: process.stdout.columns || 80,
|
|
3659
|
+
height: process.stdout.rows || 24
|
|
3539
3660
|
};
|
|
3540
3661
|
}
|
|
3541
3662
|
function defaultWriteStdout(data) {
|