@joshski/dust 0.1.75 → 0.1.77
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/agent-events.d.ts +1 -0
- package/dist/audits.js +131 -1
- package/dist/bucket/repository-loop.d.ts +1 -0
- package/dist/dust.js +169 -24
- package/package.json +1 -1
package/dist/agent-events.d.ts
CHANGED
package/dist/audits.js
CHANGED
|
@@ -719,6 +719,65 @@ function repositoryContext() {
|
|
|
719
719
|
- [ ] A new agent reading only this document could make sensible high-level suggestions
|
|
720
720
|
`;
|
|
721
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
|
+
}
|
|
722
781
|
function ubiquitousLanguage() {
|
|
723
782
|
return dedent`
|
|
724
783
|
# Ubiquitous Language
|
|
@@ -772,6 +831,75 @@ function ubiquitousLanguage() {
|
|
|
772
831
|
- [ ] Proposed ideas for standardizing inconsistent terminology
|
|
773
832
|
`;
|
|
774
833
|
}
|
|
834
|
+
function uxAudit() {
|
|
835
|
+
return dedent`
|
|
836
|
+
# UX Audit
|
|
837
|
+
|
|
838
|
+
Review the end user experience by capturing visual or interactive evidence at key scenarios.
|
|
839
|
+
|
|
840
|
+
${ideasHint}
|
|
841
|
+
|
|
842
|
+
## Scope
|
|
843
|
+
|
|
844
|
+
1. **Identify key scenarios** - What are the main user journeys? (e.g., signup, login, checkout, onboarding, core workflows)
|
|
845
|
+
2. **Capture evidence** - For each scenario:
|
|
846
|
+
- Web apps: Take screenshots at each step using browser automation (Playwright, Puppeteer, Cypress, or similar)
|
|
847
|
+
- Terminal apps: Capture command output and interactive sessions
|
|
848
|
+
3. **Review captured evidence** for UX issues:
|
|
849
|
+
- Confusing or unclear states
|
|
850
|
+
- Missing feedback or loading indicators
|
|
851
|
+
- Error messages that don't guide recovery
|
|
852
|
+
- Inconsistent styling or layout
|
|
853
|
+
4. **Document findings** with screenshots/output and specific recommendations
|
|
854
|
+
|
|
855
|
+
## Applicability
|
|
856
|
+
|
|
857
|
+
Determine the application type and available tooling:
|
|
858
|
+
- If browser tests exist (Playwright, Puppeteer, Cypress), extend them to capture screenshots
|
|
859
|
+
- If no browser tests exist, write a standalone script for key scenarios
|
|
860
|
+
- For terminal apps, capture representative sessions using command output or terminal recording
|
|
861
|
+
|
|
862
|
+
If the project has no user-facing interface, document that finding and skip the detailed analysis.
|
|
863
|
+
|
|
864
|
+
## Analysis Steps
|
|
865
|
+
|
|
866
|
+
1. Identify the application type (web, terminal, hybrid, no UI)
|
|
867
|
+
2. List the key user scenarios from documentation, tests, or code analysis
|
|
868
|
+
3. Capture screenshots or output at each stage of each scenario
|
|
869
|
+
4. Store artifacts in a temporary directory for review during this audit
|
|
870
|
+
5. Review each artifact for UX issues
|
|
871
|
+
6. Document findings with evidence and specific recommendations
|
|
872
|
+
|
|
873
|
+
## Output
|
|
874
|
+
|
|
875
|
+
For each UX issue identified, provide:
|
|
876
|
+
- **Location** - Which scenario and step
|
|
877
|
+
- **Evidence** - Screenshot filename or captured output
|
|
878
|
+
- **Problem** - What's wrong from the user's perspective
|
|
879
|
+
- **Impact** - How it affects the user's ability to complete their goal
|
|
880
|
+
- **Recommendation** - Specific fix
|
|
881
|
+
- **Verification** - How to verify the fix (e.g., "Screenshot at step 3 should show success message instead of spinner")
|
|
882
|
+
|
|
883
|
+
## Principles
|
|
884
|
+
|
|
885
|
+
- [Actionable Errors](../principles/actionable-errors.md) - Error messages should tell users what to do next
|
|
886
|
+
- [Unsurprising UX](../principles/unsurprising-ux.md) - The interface should be as guessable as possible
|
|
887
|
+
|
|
888
|
+
## Blocked By
|
|
889
|
+
|
|
890
|
+
(none)
|
|
891
|
+
|
|
892
|
+
## Definition of Done
|
|
893
|
+
|
|
894
|
+
- [ ] Identified the application type (web, terminal, hybrid, or no UI)
|
|
895
|
+
- [ ] Listed key user scenarios
|
|
896
|
+
- [ ] Captured screenshots or output at each stage of key scenarios
|
|
897
|
+
- [ ] Reviewed evidence for UX issues
|
|
898
|
+
- [ ] Documented findings with evidence and recommendations
|
|
899
|
+
- [ ] Included verification criteria for each issue
|
|
900
|
+
- [ ] Created ideas for any UX improvements needed
|
|
901
|
+
`;
|
|
902
|
+
}
|
|
775
903
|
var stockAuditFunctions = {
|
|
776
904
|
"agent-developer-experience": agentDeveloperExperience,
|
|
777
905
|
"component-reuse": componentReuse,
|
|
@@ -787,9 +915,11 @@ var stockAuditFunctions = {
|
|
|
787
915
|
"refactoring-opportunities": refactoringOpportunities,
|
|
788
916
|
"repository-context": repositoryContext,
|
|
789
917
|
"security-review": securityReview,
|
|
918
|
+
"slow-tests": slowTests,
|
|
790
919
|
"stale-ideas": staleIdeas,
|
|
791
920
|
"test-coverage": testCoverage,
|
|
792
|
-
"ubiquitous-language": ubiquitousLanguage
|
|
921
|
+
"ubiquitous-language": ubiquitousLanguage,
|
|
922
|
+
"ux-audit": uxAudit
|
|
793
923
|
};
|
|
794
924
|
function loadStockAudits() {
|
|
795
925
|
return Object.entries(stockAuditFunctions).sort(([a], [b]) => a.localeCompare(b)).map(([name, render]) => {
|
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.77";
|
|
279
279
|
|
|
280
280
|
// lib/session.ts
|
|
281
281
|
var DUST_UNATTENDED = "DUST_UNATTENDED";
|
|
@@ -1266,6 +1266,65 @@ function repositoryContext() {
|
|
|
1266
1266
|
- [ ] A new agent reading only this document could make sensible high-level suggestions
|
|
1267
1267
|
`;
|
|
1268
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
|
+
}
|
|
1269
1328
|
function ubiquitousLanguage() {
|
|
1270
1329
|
return dedent`
|
|
1271
1330
|
# Ubiquitous Language
|
|
@@ -1319,6 +1378,75 @@ function ubiquitousLanguage() {
|
|
|
1319
1378
|
- [ ] Proposed ideas for standardizing inconsistent terminology
|
|
1320
1379
|
`;
|
|
1321
1380
|
}
|
|
1381
|
+
function uxAudit() {
|
|
1382
|
+
return dedent`
|
|
1383
|
+
# UX Audit
|
|
1384
|
+
|
|
1385
|
+
Review the end user experience by capturing visual or interactive evidence at key scenarios.
|
|
1386
|
+
|
|
1387
|
+
${ideasHint}
|
|
1388
|
+
|
|
1389
|
+
## Scope
|
|
1390
|
+
|
|
1391
|
+
1. **Identify key scenarios** - What are the main user journeys? (e.g., signup, login, checkout, onboarding, core workflows)
|
|
1392
|
+
2. **Capture evidence** - For each scenario:
|
|
1393
|
+
- Web apps: Take screenshots at each step using browser automation (Playwright, Puppeteer, Cypress, or similar)
|
|
1394
|
+
- Terminal apps: Capture command output and interactive sessions
|
|
1395
|
+
3. **Review captured evidence** for UX issues:
|
|
1396
|
+
- Confusing or unclear states
|
|
1397
|
+
- Missing feedback or loading indicators
|
|
1398
|
+
- Error messages that don't guide recovery
|
|
1399
|
+
- Inconsistent styling or layout
|
|
1400
|
+
4. **Document findings** with screenshots/output and specific recommendations
|
|
1401
|
+
|
|
1402
|
+
## Applicability
|
|
1403
|
+
|
|
1404
|
+
Determine the application type and available tooling:
|
|
1405
|
+
- If browser tests exist (Playwright, Puppeteer, Cypress), extend them to capture screenshots
|
|
1406
|
+
- If no browser tests exist, write a standalone script for key scenarios
|
|
1407
|
+
- For terminal apps, capture representative sessions using command output or terminal recording
|
|
1408
|
+
|
|
1409
|
+
If the project has no user-facing interface, document that finding and skip the detailed analysis.
|
|
1410
|
+
|
|
1411
|
+
## Analysis Steps
|
|
1412
|
+
|
|
1413
|
+
1. Identify the application type (web, terminal, hybrid, no UI)
|
|
1414
|
+
2. List the key user scenarios from documentation, tests, or code analysis
|
|
1415
|
+
3. Capture screenshots or output at each stage of each scenario
|
|
1416
|
+
4. Store artifacts in a temporary directory for review during this audit
|
|
1417
|
+
5. Review each artifact for UX issues
|
|
1418
|
+
6. Document findings with evidence and specific recommendations
|
|
1419
|
+
|
|
1420
|
+
## Output
|
|
1421
|
+
|
|
1422
|
+
For each UX issue identified, provide:
|
|
1423
|
+
- **Location** - Which scenario and step
|
|
1424
|
+
- **Evidence** - Screenshot filename or captured output
|
|
1425
|
+
- **Problem** - What's wrong from the user's perspective
|
|
1426
|
+
- **Impact** - How it affects the user's ability to complete their goal
|
|
1427
|
+
- **Recommendation** - Specific fix
|
|
1428
|
+
- **Verification** - How to verify the fix (e.g., "Screenshot at step 3 should show success message instead of spinner")
|
|
1429
|
+
|
|
1430
|
+
## Principles
|
|
1431
|
+
|
|
1432
|
+
- [Actionable Errors](../principles/actionable-errors.md) - Error messages should tell users what to do next
|
|
1433
|
+
- [Unsurprising UX](../principles/unsurprising-ux.md) - The interface should be as guessable as possible
|
|
1434
|
+
|
|
1435
|
+
## Blocked By
|
|
1436
|
+
|
|
1437
|
+
(none)
|
|
1438
|
+
|
|
1439
|
+
## Definition of Done
|
|
1440
|
+
|
|
1441
|
+
- [ ] Identified the application type (web, terminal, hybrid, or no UI)
|
|
1442
|
+
- [ ] Listed key user scenarios
|
|
1443
|
+
- [ ] Captured screenshots or output at each stage of key scenarios
|
|
1444
|
+
- [ ] Reviewed evidence for UX issues
|
|
1445
|
+
- [ ] Documented findings with evidence and recommendations
|
|
1446
|
+
- [ ] Included verification criteria for each issue
|
|
1447
|
+
- [ ] Created ideas for any UX improvements needed
|
|
1448
|
+
`;
|
|
1449
|
+
}
|
|
1322
1450
|
var stockAuditFunctions = {
|
|
1323
1451
|
"agent-developer-experience": agentDeveloperExperience,
|
|
1324
1452
|
"component-reuse": componentReuse,
|
|
@@ -1334,9 +1462,11 @@ var stockAuditFunctions = {
|
|
|
1334
1462
|
"refactoring-opportunities": refactoringOpportunities,
|
|
1335
1463
|
"repository-context": repositoryContext,
|
|
1336
1464
|
"security-review": securityReview,
|
|
1465
|
+
"slow-tests": slowTests,
|
|
1337
1466
|
"stale-ideas": staleIdeas,
|
|
1338
1467
|
"test-coverage": testCoverage,
|
|
1339
|
-
"ubiquitous-language": ubiquitousLanguage
|
|
1468
|
+
"ubiquitous-language": ubiquitousLanguage,
|
|
1469
|
+
"ux-audit": uxAudit
|
|
1340
1470
|
};
|
|
1341
1471
|
function loadStockAudits() {
|
|
1342
1472
|
return Object.entries(stockAuditFunctions).sort(([a], [b]) => a.localeCompare(b)).map(([name, render]) => {
|
|
@@ -2264,7 +2394,8 @@ function getRepoPath(repoName, reposDir) {
|
|
|
2264
2394
|
async function cloneRepository(repository, targetPath, spawn, context) {
|
|
2265
2395
|
return new Promise((resolve) => {
|
|
2266
2396
|
const proc = spawn("git", ["clone", repository.gitUrl, targetPath], {
|
|
2267
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
2397
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2398
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
2268
2399
|
});
|
|
2269
2400
|
let stderr = "";
|
|
2270
2401
|
proc.stderr?.on("data", (data) => {
|
|
@@ -2488,26 +2619,26 @@ function getEnvironmentContext(cwd) {
|
|
|
2488
2619
|
function formatLoopEvent(event) {
|
|
2489
2620
|
switch (event.type) {
|
|
2490
2621
|
case "loop.warning":
|
|
2491
|
-
return "
|
|
2622
|
+
return "WARNING: This command skips all permission checks. Only use in a sandbox environment!";
|
|
2492
2623
|
case "loop.started": {
|
|
2493
2624
|
const agent2 = event.agentType ?? "claude";
|
|
2494
|
-
return
|
|
2625
|
+
return `Starting dust loop ${agent2} (max ${event.maxIterations} iterations)...`;
|
|
2495
2626
|
}
|
|
2496
2627
|
case "loop.syncing":
|
|
2497
|
-
return "
|
|
2628
|
+
return "Syncing with remote";
|
|
2498
2629
|
case "loop.sync_skipped":
|
|
2499
2630
|
return `Note: git pull skipped (${event.reason})`;
|
|
2500
2631
|
case "loop.checking_tasks":
|
|
2501
2632
|
return null;
|
|
2502
2633
|
case "loop.no_tasks":
|
|
2503
|
-
return "
|
|
2634
|
+
return "No tasks available. Sleeping...";
|
|
2504
2635
|
case "loop.tasks_found":
|
|
2505
|
-
return
|
|
2636
|
+
return `Found a task. Going to work!
|
|
2506
2637
|
`;
|
|
2507
2638
|
case "loop.iteration_complete":
|
|
2508
|
-
return
|
|
2639
|
+
return `Completed iteration ${event.iteration}/${event.maxIterations}`;
|
|
2509
2640
|
case "loop.ended":
|
|
2510
|
-
return
|
|
2641
|
+
return `Reached max iterations (${event.maxIterations}). Exiting.`;
|
|
2511
2642
|
}
|
|
2512
2643
|
}
|
|
2513
2644
|
function createPostEvent(fetchFn) {
|
|
@@ -2565,7 +2696,8 @@ async function gitPull(cwd, spawn) {
|
|
|
2565
2696
|
return new Promise((resolve) => {
|
|
2566
2697
|
const proc = spawn("git", ["pull"], {
|
|
2567
2698
|
cwd,
|
|
2568
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
2699
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2700
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
2569
2701
|
});
|
|
2570
2702
|
let stderr = "";
|
|
2571
2703
|
proc.stderr?.on("data", (data) => {
|
|
@@ -2815,6 +2947,9 @@ function buildEventMessage(parameters) {
|
|
|
2815
2947
|
repository: parameters.repository,
|
|
2816
2948
|
event: parameters.event
|
|
2817
2949
|
};
|
|
2950
|
+
if (parameters.repoId !== undefined) {
|
|
2951
|
+
msg.repoId = parameters.repoId;
|
|
2952
|
+
}
|
|
2818
2953
|
if (parameters.agentSessionId) {
|
|
2819
2954
|
msg.agentSessionId = parameters.agentSessionId;
|
|
2820
2955
|
}
|
|
@@ -2900,6 +3035,7 @@ async function runRepositoryLoop(repoState, repoDeps, sendEvent, sessionId) {
|
|
|
2900
3035
|
sequence,
|
|
2901
3036
|
sessionId,
|
|
2902
3037
|
repository: repoName,
|
|
3038
|
+
repoId: repoState.repository.id,
|
|
2903
3039
|
event,
|
|
2904
3040
|
agentSessionId
|
|
2905
3041
|
}));
|
|
@@ -3115,6 +3251,15 @@ function parseServerMessage(data) {
|
|
|
3115
3251
|
}
|
|
3116
3252
|
|
|
3117
3253
|
// lib/bucket/terminal-ui.ts
|
|
3254
|
+
var CHARS = {
|
|
3255
|
+
dot: "*",
|
|
3256
|
+
sparkle: "",
|
|
3257
|
+
ellipsis: "...",
|
|
3258
|
+
hline: "-",
|
|
3259
|
+
arrows_lr: "<->",
|
|
3260
|
+
arrows_ud: "up/dn",
|
|
3261
|
+
scroll_down: "v"
|
|
3262
|
+
};
|
|
3118
3263
|
var ANSI = {
|
|
3119
3264
|
HIDE_CURSOR: "\x1B[?25l",
|
|
3120
3265
|
SHOW_CURSOR: "\x1B[?25h",
|
|
@@ -3169,8 +3314,8 @@ function truncateLine(text, maxWidth) {
|
|
|
3169
3314
|
for (let match = ansiRegex.exec(text);match !== null; match = ansiRegex.exec(text)) {
|
|
3170
3315
|
const textBefore = text.slice(lastIndex, match.index);
|
|
3171
3316
|
for (const char of textBefore) {
|
|
3172
|
-
if (visibleCount >= maxWidth -
|
|
3173
|
-
result +=
|
|
3317
|
+
if (visibleCount >= maxWidth - CHARS.ellipsis.length) {
|
|
3318
|
+
result += CHARS.ellipsis;
|
|
3174
3319
|
return result + ANSI.RESET;
|
|
3175
3320
|
}
|
|
3176
3321
|
result += char;
|
|
@@ -3181,8 +3326,8 @@ function truncateLine(text, maxWidth) {
|
|
|
3181
3326
|
}
|
|
3182
3327
|
const remaining = text.slice(lastIndex);
|
|
3183
3328
|
for (const char of remaining) {
|
|
3184
|
-
if (visibleCount >= maxWidth -
|
|
3185
|
-
result +=
|
|
3329
|
+
if (visibleCount >= maxWidth - CHARS.ellipsis.length) {
|
|
3330
|
+
result += CHARS.ellipsis;
|
|
3186
3331
|
return result + ANSI.RESET;
|
|
3187
3332
|
}
|
|
3188
3333
|
result += char;
|
|
@@ -3282,7 +3427,7 @@ function getTabRowCount(state) {
|
|
|
3282
3427
|
return 1;
|
|
3283
3428
|
const tabWidths = [5];
|
|
3284
3429
|
for (const name of state.repositories) {
|
|
3285
|
-
tabWidths.push(name.length +
|
|
3430
|
+
tabWidths.push(name.length + 2 + CHARS.dot.length + 1);
|
|
3286
3431
|
}
|
|
3287
3432
|
let rows = 1;
|
|
3288
3433
|
let currentRowWidth = 0;
|
|
@@ -3352,8 +3497,8 @@ function renderTabs(state) {
|
|
|
3352
3497
|
const color = getRepoColor(name, i);
|
|
3353
3498
|
const agentStatus = state.agentStatuses.get(name) ?? "idle";
|
|
3354
3499
|
const dotColor = agentStatus === "busy" ? ANSI.FG_GREEN : ANSI.DIM;
|
|
3355
|
-
const dot = `${dotColor}
|
|
3356
|
-
const width = name.length +
|
|
3500
|
+
const dot = `${dotColor}${CHARS.dot}${ANSI.RESET}`;
|
|
3501
|
+
const width = name.length + 2 + CHARS.dot.length + 1;
|
|
3357
3502
|
if (i === state.selectedIndex) {
|
|
3358
3503
|
tabs.push({
|
|
3359
3504
|
text: ` ${dot}${color} ${ANSI.INVERSE}${name}${ANSI.RESET} `,
|
|
@@ -3378,10 +3523,10 @@ function renderTabs(state) {
|
|
|
3378
3523
|
return rows.map((row) => row.map((t) => t.text).join("|"));
|
|
3379
3524
|
}
|
|
3380
3525
|
function renderHelpLine() {
|
|
3381
|
-
return `${ANSI.DIM}[
|
|
3526
|
+
return `${ANSI.DIM}[${CHARS.arrows_lr}] select [${CHARS.arrows_ud}] scroll [PgUp/PgDn] page [g/G] top/bottom [o] open [q] quit${ANSI.RESET}`;
|
|
3382
3527
|
}
|
|
3383
3528
|
function renderSeparator(width) {
|
|
3384
|
-
return
|
|
3529
|
+
return CHARS.hline.repeat(Math.max(0, width));
|
|
3385
3530
|
}
|
|
3386
3531
|
function formatLogLine(line, prefixAlign, maxWidth) {
|
|
3387
3532
|
let prefix = "";
|
|
@@ -3413,7 +3558,7 @@ function formatLogLine(line, prefixAlign, maxWidth) {
|
|
|
3413
3558
|
function renderFrame(state) {
|
|
3414
3559
|
const lines = [];
|
|
3415
3560
|
const hostLabel = state.connectedHost ? ` ${ANSI.DIM}[connected to ${state.connectedHost}]${ANSI.RESET}` : "";
|
|
3416
|
-
lines.push(`${ANSI.BOLD}
|
|
3561
|
+
lines.push(`${ANSI.BOLD}${CHARS.sparkle}dust bucket${ANSI.RESET}${hostLabel}`);
|
|
3417
3562
|
const tabRows = renderTabs(state);
|
|
3418
3563
|
for (const tabRow of tabRows) {
|
|
3419
3564
|
lines.push(tabRow);
|
|
@@ -3436,7 +3581,7 @@ function renderFrame(state) {
|
|
|
3436
3581
|
lines.push("");
|
|
3437
3582
|
}
|
|
3438
3583
|
if (state.scrollOffset > 0) {
|
|
3439
|
-
const indicator = `${ANSI.DIM}
|
|
3584
|
+
const indicator = `${ANSI.DIM}${CHARS.scroll_down} ${state.scrollOffset} more${ANSI.RESET}`;
|
|
3440
3585
|
lines[lines.length - 1] = indicator;
|
|
3441
3586
|
}
|
|
3442
3587
|
const output = [];
|
|
@@ -3584,8 +3729,8 @@ function defaultSetupResize(onResize) {
|
|
|
3584
3729
|
}
|
|
3585
3730
|
function defaultGetTerminalSize() {
|
|
3586
3731
|
return {
|
|
3587
|
-
width: process.stdout.columns
|
|
3588
|
-
height: process.stdout.rows
|
|
3732
|
+
width: process.stdout.columns || 80,
|
|
3733
|
+
height: process.stdout.rows || 24
|
|
3589
3734
|
};
|
|
3590
3735
|
}
|
|
3591
3736
|
function defaultWriteStdout(data) {
|