@pennyfarthing/cyclist 10.0.2 → 10.1.0
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/api/agent-load.d.ts +3 -0
- package/dist/api/agent-load.d.ts.map +1 -0
- package/dist/api/agent-load.js +124 -0
- package/dist/api/agent-load.js.map +1 -0
- package/dist/api/code-markers.d.ts +9 -0
- package/dist/api/code-markers.d.ts.map +1 -0
- package/dist/api/code-markers.js +62 -0
- package/dist/api/code-markers.js.map +1 -0
- package/dist/api/complexity.d.ts +3 -0
- package/dist/api/complexity.d.ts.map +1 -0
- package/dist/api/complexity.js +47 -0
- package/dist/api/complexity.js.map +1 -0
- package/dist/api/dead-code.d.ts +3 -0
- package/dist/api/dead-code.d.ts.map +1 -0
- package/dist/api/dead-code.js +70 -0
- package/dist/api/dead-code.js.map +1 -0
- package/dist/api/dependencies.d.ts +3 -0
- package/dist/api/dependencies.d.ts.map +1 -0
- package/dist/api/dependencies.js +43 -0
- package/dist/api/dependencies.js.map +1 -0
- package/dist/api/git.d.ts +3 -2
- package/dist/api/git.d.ts.map +1 -1
- package/dist/api/git.js +11 -6
- package/dist/api/git.js.map +1 -1
- package/dist/api/health-score.d.ts +3 -0
- package/dist/api/health-score.d.ts.map +1 -0
- package/dist/api/health-score.js +38 -0
- package/dist/api/health-score.js.map +1 -0
- package/dist/api/hotspots.d.ts.map +1 -1
- package/dist/api/hotspots.js +9 -1
- package/dist/api/hotspots.js.map +1 -1
- package/dist/api/index.d.ts +6 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +11 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/theme-agents.d.ts +1 -0
- package/dist/api/theme-agents.d.ts.map +1 -1
- package/dist/api/theme-agents.js +1 -1
- package/dist/api/theme-agents.js.map +1 -1
- package/dist/git-diff.d.ts.map +1 -1
- package/dist/git-diff.js +6 -5
- package/dist/git-diff.js.map +1 -1
- package/dist/main.js +9 -3
- package/dist/main.js.map +1 -1
- package/dist/preload.js +11 -0
- package/dist/preload.js.map +1 -1
- package/dist/prime.d.ts +3 -2
- package/dist/prime.d.ts.map +1 -1
- package/dist/prime.js +25 -8
- package/dist/prime.js.map +1 -1
- package/dist/public/css/react.css +1 -1
- package/dist/public/js/react/react.js +50 -39
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +16 -1
- package/dist/server.js.map +1 -1
- package/dist/sprint-data.d.ts +6 -0
- package/dist/sprint-data.d.ts.map +1 -1
- package/dist/sprint-data.js +79 -3
- package/dist/sprint-data.js.map +1 -1
- package/dist/websocket.d.ts.map +1 -1
- package/dist/websocket.js +6 -5
- package/dist/websocket.js.map +1 -1
- package/package.json +32 -31
- package/src/public/App.tsx +0 -2
- package/src/public/components/AgentLoadDialog.tsx +202 -0
- package/src/public/components/ControlBar.tsx +4 -3
- package/src/public/components/DeadCodeDialog.tsx +169 -0
- package/src/public/components/DockviewWorkspace.tsx +0 -3
- package/src/public/components/FullFileTree.tsx +18 -4
- package/src/public/components/HealthGauge.tsx +144 -0
- package/src/public/components/MessageView.tsx +25 -22
- package/src/public/components/SubagentSpan.tsx +2 -2
- package/src/public/components/ToolCallBlock.tsx +21 -6
- package/src/public/components/dialogs/CodeMarkersDialog.tsx +169 -0
- package/src/public/components/dialogs/ComplexityDialog.tsx +163 -0
- package/src/public/components/dialogs/DependenciesDialog.tsx +120 -0
- package/src/public/components/dialogs/HotspotsDialog.tsx +451 -0
- package/src/public/components/dialogs/ToolDialog.tsx +43 -0
- package/src/public/components/panels/AcceptanceCriteriaPanel.tsx +15 -30
- package/src/public/components/panels/DebugPanel.tsx +83 -0
- package/src/public/components/panels/GitPanel.tsx +12 -18
- package/src/public/components/panels/SprintPanel.tsx +84 -15
- package/src/public/components/panels/index.ts +0 -1
- package/src/public/components/ui/dialog.tsx +3 -3
- package/src/public/css/theme-system.css +5 -11
- package/src/public/hooks/index.ts +4 -0
- package/src/public/hooks/useAgentLoad.ts +105 -0
- package/src/public/hooks/useCodeMarkers.ts +101 -0
- package/src/public/hooks/useColorScheme.ts +25 -10
- package/src/public/hooks/useComplexity.ts +80 -0
- package/src/public/hooks/useDeadCode.ts +99 -0
- package/src/public/hooks/useDependencies.ts +82 -0
- package/src/public/hooks/useHealthScore.ts +77 -0
- package/src/public/hooks/useHotspots.ts +11 -1
- package/src/public/hooks/useSprint.ts +6 -0
- package/src/public/styles/tailwind.css +90 -78
- package/src/public/utils/messageFilters.ts +77 -6
- package/src/public/utils/slash-commands.ts +2 -18
- package/src/public/utils/subagent-display.ts +6 -3
- package/LICENSE +0 -14
- package/src/public/components/AskUserQuestionBlock.tsx +0 -162
- package/src/public/utils/askUserQuestion.ts +0 -21
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
gap: 0.5rem;
|
|
617
617
|
padding: 0.25rem 0;
|
|
618
618
|
margin-bottom: 0.25rem;
|
|
619
|
+
padding-left: 2.75rem; /* align with message content: avatar 2rem + gap 0.75rem */
|
|
619
620
|
}
|
|
620
621
|
|
|
621
622
|
.turn-speaker {
|
|
@@ -958,7 +959,7 @@
|
|
|
958
959
|
display: flex;
|
|
959
960
|
align-items: center;
|
|
960
961
|
justify-content: center;
|
|
961
|
-
|
|
962
|
+
flex: 1;
|
|
962
963
|
color: var(--text-secondary, #8b8b8b);
|
|
963
964
|
font-size: 0.875rem;
|
|
964
965
|
text-align: center;
|
|
@@ -1510,15 +1511,69 @@
|
|
|
1510
1511
|
background: var(--bg-hover, rgba(255, 255, 255, 0.03));
|
|
1511
1512
|
}
|
|
1512
1513
|
|
|
1513
|
-
.enhanced-sprint-panel .story-item .story-
|
|
1514
|
+
.enhanced-sprint-panel .story-item .story-info {
|
|
1514
1515
|
flex: 1;
|
|
1515
1516
|
min-width: 0;
|
|
1517
|
+
display: flex;
|
|
1518
|
+
flex-direction: column;
|
|
1519
|
+
gap: 1px;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
.enhanced-sprint-panel .story-item .story-title {
|
|
1516
1523
|
overflow: hidden;
|
|
1517
1524
|
text-overflow: ellipsis;
|
|
1518
1525
|
white-space: nowrap;
|
|
1519
1526
|
font-size: 0.75rem;
|
|
1520
1527
|
}
|
|
1521
1528
|
|
|
1529
|
+
.enhanced-sprint-panel .story-item .story-meta {
|
|
1530
|
+
display: flex;
|
|
1531
|
+
align-items: center;
|
|
1532
|
+
gap: 6px;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
.enhanced-sprint-panel .story-item .story-assignee {
|
|
1536
|
+
font-size: 0.625rem;
|
|
1537
|
+
color: var(--text-tertiary, #6b6b6b);
|
|
1538
|
+
font-style: italic;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
.enhanced-sprint-panel .story-item .story-workflow-badge {
|
|
1542
|
+
font-size: 0.5625rem;
|
|
1543
|
+
text-transform: uppercase;
|
|
1544
|
+
letter-spacing: 0.05em;
|
|
1545
|
+
color: var(--text-secondary, #8b8b8b);
|
|
1546
|
+
background: var(--bg-tertiary, #2d2d2d);
|
|
1547
|
+
padding: 0 4px;
|
|
1548
|
+
border-radius: 2px;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
.enhanced-sprint-panel .story-item .story-completed-date {
|
|
1552
|
+
font-size: 0.625rem;
|
|
1553
|
+
font-variant-numeric: tabular-nums;
|
|
1554
|
+
font-family: var(--font-mono, monospace);
|
|
1555
|
+
color: var(--text-tertiary, #6b6b6b);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
.enhanced-sprint-panel .story-item .priority-dot {
|
|
1559
|
+
width: 6px;
|
|
1560
|
+
height: 6px;
|
|
1561
|
+
border-radius: 50%;
|
|
1562
|
+
flex-shrink: 0;
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
.enhanced-sprint-panel .story-item .priority-dot.priority-p0 {
|
|
1566
|
+
background: var(--error-color, #f14c4c);
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
.enhanced-sprint-panel .story-item .priority-dot.priority-p1 {
|
|
1570
|
+
background: var(--warning-color, #cca700);
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
.enhanced-sprint-panel .story-item .priority-dot.priority-p2 {
|
|
1574
|
+
background: var(--text-tertiary, #6b6b6b);
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1522
1577
|
.enhanced-sprint-panel .story-item .story-points {
|
|
1523
1578
|
font-size: 0.65rem;
|
|
1524
1579
|
color: var(--text-secondary, #8b8b8b);
|
|
@@ -1791,42 +1846,25 @@
|
|
|
1791
1846
|
margin-bottom: 4px;
|
|
1792
1847
|
}
|
|
1793
1848
|
|
|
1794
|
-
/*
|
|
1795
|
-
.git-panel .develop-
|
|
1796
|
-
display: flex;
|
|
1849
|
+
/* Sync develop button — subtle icon inline with sync counts */
|
|
1850
|
+
.git-panel .sync-develop-btn {
|
|
1851
|
+
display: inline-flex;
|
|
1797
1852
|
align-items: center;
|
|
1798
|
-
gap:
|
|
1799
|
-
padding:
|
|
1800
|
-
margin-bottom: 8px;
|
|
1801
|
-
background: rgba(204, 167, 0, 0.15);
|
|
1802
|
-
border: 1px solid var(--warning-color, #cca700);
|
|
1803
|
-
border-radius: 4px;
|
|
1804
|
-
font-size: 0.75rem;
|
|
1805
|
-
}
|
|
1806
|
-
|
|
1807
|
-
.git-panel .develop-behind-warning .warning-icon {
|
|
1808
|
-
flex-shrink: 0;
|
|
1809
|
-
}
|
|
1810
|
-
|
|
1811
|
-
.git-panel .develop-behind-warning .warning-text {
|
|
1812
|
-
flex: 1;
|
|
1813
|
-
color: var(--warning-color, #cca700);
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
.git-panel .develop-behind-warning .pull-develop-btn {
|
|
1817
|
-
padding: 2px 8px;
|
|
1818
|
-
background: var(--warning-color, #cca700);
|
|
1819
|
-
color: #000;
|
|
1853
|
+
gap: 3px;
|
|
1854
|
+
padding: 1px 5px;
|
|
1820
1855
|
border: none;
|
|
1821
1856
|
border-radius: 3px;
|
|
1857
|
+
background: none;
|
|
1858
|
+
color: var(--status-warning, #cca700);
|
|
1822
1859
|
font-size: 0.7rem;
|
|
1823
|
-
font-
|
|
1860
|
+
font-family: var(--font-mono);
|
|
1824
1861
|
cursor: pointer;
|
|
1825
|
-
|
|
1862
|
+
transition: background-color 0.15s ease, color 0.15s ease;
|
|
1826
1863
|
}
|
|
1827
1864
|
|
|
1828
|
-
.git-panel .
|
|
1829
|
-
|
|
1865
|
+
.git-panel .sync-develop-btn:hover {
|
|
1866
|
+
background: rgba(204, 167, 0, 0.15);
|
|
1867
|
+
color: var(--text-primary);
|
|
1830
1868
|
}
|
|
1831
1869
|
|
|
1832
1870
|
.git-panel .repo-status .file-status {
|
|
@@ -2196,38 +2234,6 @@
|
|
|
2196
2234
|
padding: 8px 0;
|
|
2197
2235
|
}
|
|
2198
2236
|
|
|
2199
|
-
/* AC content within Progress panel */
|
|
2200
|
-
.ac-content {
|
|
2201
|
-
padding: 4px 0;
|
|
2202
|
-
}
|
|
2203
|
-
|
|
2204
|
-
.ac-content .ac-list {
|
|
2205
|
-
margin-top: 8px;
|
|
2206
|
-
}
|
|
2207
|
-
|
|
2208
|
-
.ac-content .ac-item {
|
|
2209
|
-
display: flex;
|
|
2210
|
-
align-items: flex-start;
|
|
2211
|
-
gap: 6px;
|
|
2212
|
-
padding: 4px 0;
|
|
2213
|
-
font-size: 0.8rem;
|
|
2214
|
-
color: var(--text-primary, #d4d4d4);
|
|
2215
|
-
}
|
|
2216
|
-
|
|
2217
|
-
.ac-content .ac-item.ac-done {
|
|
2218
|
-
color: var(--success-color, #4ec9b0);
|
|
2219
|
-
}
|
|
2220
|
-
|
|
2221
|
-
.ac-content .ac-icon {
|
|
2222
|
-
flex-shrink: 0;
|
|
2223
|
-
width: 14px;
|
|
2224
|
-
}
|
|
2225
|
-
|
|
2226
|
-
.ac-content .ac-text {
|
|
2227
|
-
flex: 1;
|
|
2228
|
-
line-height: 1.3;
|
|
2229
|
-
}
|
|
2230
|
-
|
|
2231
2237
|
/* Todo content wrapper */
|
|
2232
2238
|
.todo-content {
|
|
2233
2239
|
padding: 4px 0;
|
|
@@ -2626,6 +2632,14 @@
|
|
|
2626
2632
|
font-family: var(--font-mono, 'SF Mono', Monaco, monospace);
|
|
2627
2633
|
}
|
|
2628
2634
|
|
|
2635
|
+
/* Tool launcher - MSSCI-14443 */
|
|
2636
|
+
.debug-panel .tool-launcher {
|
|
2637
|
+
display: flex;
|
|
2638
|
+
flex-wrap: wrap;
|
|
2639
|
+
gap: 6px;
|
|
2640
|
+
margin-top: 4px;
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2629
2643
|
/* Settings panel */
|
|
2630
2644
|
.settings-panel {
|
|
2631
2645
|
padding: 8px;
|
|
@@ -4017,15 +4031,13 @@
|
|
|
4017
4031
|
border-color: var(--text-secondary, #8b8b8b);
|
|
4018
4032
|
}
|
|
4019
4033
|
|
|
4020
|
-
.btn-toggle
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
filter: grayscale(100%) opacity(0.5);
|
|
4024
|
-
transition: filter 0.15s ease;
|
|
4034
|
+
.btn-toggle svg {
|
|
4035
|
+
opacity: 0.5;
|
|
4036
|
+
transition: opacity 0.15s ease;
|
|
4025
4037
|
}
|
|
4026
4038
|
|
|
4027
|
-
.btn-toggle:hover
|
|
4028
|
-
|
|
4039
|
+
.btn-toggle:hover svg {
|
|
4040
|
+
opacity: 0.8;
|
|
4029
4041
|
}
|
|
4030
4042
|
|
|
4031
4043
|
/* Bell mode active */
|
|
@@ -4034,8 +4046,8 @@
|
|
|
4034
4046
|
border-color: var(--color-warning, #f59e0b);
|
|
4035
4047
|
}
|
|
4036
4048
|
|
|
4037
|
-
.btn-toggle.bell-toggle.active
|
|
4038
|
-
|
|
4049
|
+
.btn-toggle.bell-toggle.active svg {
|
|
4050
|
+
opacity: 1;
|
|
4039
4051
|
}
|
|
4040
4052
|
|
|
4041
4053
|
/* Relay mode active */
|
|
@@ -4044,8 +4056,8 @@
|
|
|
4044
4056
|
border-color: var(--color-purple, #8b5cf6);
|
|
4045
4057
|
}
|
|
4046
4058
|
|
|
4047
|
-
.btn-toggle.relay-toggle.active
|
|
4048
|
-
|
|
4059
|
+
.btn-toggle.relay-toggle.active svg {
|
|
4060
|
+
opacity: 1;
|
|
4049
4061
|
}
|
|
4050
4062
|
|
|
4051
4063
|
/* Active toggle colors (no animation - too distracting) */
|
|
@@ -4063,8 +4075,8 @@
|
|
|
4063
4075
|
border-color: var(--color-cyan, #06b6d4);
|
|
4064
4076
|
}
|
|
4065
4077
|
|
|
4066
|
-
.btn-toggle.pump-toggle
|
|
4067
|
-
|
|
4078
|
+
.btn-toggle.pump-toggle svg {
|
|
4079
|
+
opacity: 1;
|
|
4068
4080
|
}
|
|
4069
4081
|
|
|
4070
4082
|
/* TirePump warning state at 70%+ context */
|
|
@@ -4074,8 +4086,8 @@
|
|
|
4074
4086
|
animation: pump-pulse 1.5s ease-in-out infinite;
|
|
4075
4087
|
}
|
|
4076
4088
|
|
|
4077
|
-
.btn-toggle.pump-toggle.warning
|
|
4078
|
-
|
|
4089
|
+
.btn-toggle.pump-toggle.warning svg {
|
|
4090
|
+
opacity: 1;
|
|
4079
4091
|
}
|
|
4080
4092
|
|
|
4081
4093
|
@keyframes pump-pulse {
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Story MSSCI-12783 - Bug: Skill Content Displayed as User Message
|
|
5
5
|
*
|
|
6
|
-
* Functions to detect and filter skill
|
|
6
|
+
* Functions to detect and filter skill content from user messages.
|
|
7
7
|
* Skill content is meant for Claude's context, not for display in the UI.
|
|
8
|
+
* Detected skill invocations are replaced with a short label (e.g. "reviewer")
|
|
9
|
+
* so the user sees what happened without the raw skill dump.
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -18,6 +20,36 @@ const SKILL_CONTENT_MARKERS = [
|
|
|
18
20
|
'Launching skill:',
|
|
19
21
|
] as const;
|
|
20
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Patterns that detect skill body content leaked as separate user messages.
|
|
25
|
+
* These are the raw skill markdown bodies that Claude Code sends as user messages
|
|
26
|
+
* after the initial <command-message> wrapper.
|
|
27
|
+
*/
|
|
28
|
+
const SKILL_BODY_PATTERNS = [
|
|
29
|
+
/^```bash\s*\npf agent start\b/, // Agent activation bash block
|
|
30
|
+
/^pf agent start\b/, // Bare agent start command
|
|
31
|
+
/^<purpose>/, // Skill body XML tags
|
|
32
|
+
/^<when-to-use>/,
|
|
33
|
+
/^<execution>/,
|
|
34
|
+
/^<critical>\s*\n/, // Skill body starting with critical block
|
|
35
|
+
] as const;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Agent name to human-readable label mapping.
|
|
39
|
+
*/
|
|
40
|
+
const AGENT_LABELS: Record<string, string> = {
|
|
41
|
+
sm: 'Scrum Master',
|
|
42
|
+
tea: 'Test Engineer',
|
|
43
|
+
dev: 'Developer',
|
|
44
|
+
reviewer: 'Reviewer',
|
|
45
|
+
architect: 'Architect',
|
|
46
|
+
pm: 'Product Manager',
|
|
47
|
+
'tech-writer': 'Tech Writer',
|
|
48
|
+
'ux-designer': 'UX Designer',
|
|
49
|
+
devops: 'DevOps',
|
|
50
|
+
orchestrator: 'Orchestrator',
|
|
51
|
+
};
|
|
52
|
+
|
|
21
53
|
/**
|
|
22
54
|
* Check if a message content string contains skill/command content
|
|
23
55
|
* that should be filtered from user message display.
|
|
@@ -26,13 +58,54 @@ const SKILL_CONTENT_MARKERS = [
|
|
|
26
58
|
* @returns true if the content contains skill markers and should be filtered
|
|
27
59
|
*/
|
|
28
60
|
export function isSkillContent(content: string | null | undefined): boolean {
|
|
29
|
-
// Handle null/undefined/empty gracefully
|
|
30
61
|
if (!content || typeof content !== 'string') {
|
|
31
62
|
return false;
|
|
32
63
|
}
|
|
33
64
|
|
|
34
|
-
|
|
35
|
-
|
|
65
|
+
if (SKILL_CONTENT_MARKERS.some(marker => content.includes(marker))) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const trimmed = content.trimStart();
|
|
70
|
+
return SKILL_BODY_PATTERNS.some(pattern => pattern.test(trimmed));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Extract the skill/agent name from skill content for labeling.
|
|
75
|
+
* Returns a human-readable label like "Scrum Master" or the raw skill name.
|
|
76
|
+
*/
|
|
77
|
+
export function extractSkillLabel(content: string | null | undefined): string | null {
|
|
78
|
+
if (!content || typeof content !== 'string') return null;
|
|
79
|
+
|
|
80
|
+
// Match <command-name>/foo</command-name>
|
|
81
|
+
const cmdMatch = content.match(/<command-name>\/?([^<]+)<\/command-name>/);
|
|
82
|
+
if (cmdMatch) {
|
|
83
|
+
const name = cmdMatch[1].trim();
|
|
84
|
+
return AGENT_LABELS[name] || name;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Match <command-message>foo</command-message>
|
|
88
|
+
const msgMatch = content.match(/<command-message>([^<]+)<\/command-message>/);
|
|
89
|
+
if (msgMatch) {
|
|
90
|
+
const name = msgMatch[1].trim();
|
|
91
|
+
return AGENT_LABELS[name] || name;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Match pf agent start "foo"
|
|
95
|
+
const agentMatch = content.match(/pf agent start\s+"([^"]+)"/);
|
|
96
|
+
if (agentMatch) {
|
|
97
|
+
const name = agentMatch[1].trim();
|
|
98
|
+
return AGENT_LABELS[name] || name;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Match "Launching skill: foo"
|
|
102
|
+
const launchMatch = content.match(/Launching skill:\s*(\S+)/);
|
|
103
|
+
if (launchMatch) {
|
|
104
|
+
const name = launchMatch[1].trim();
|
|
105
|
+
return AGENT_LABELS[name] || name;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return null;
|
|
36
109
|
}
|
|
37
110
|
|
|
38
111
|
/**
|
|
@@ -46,11 +119,9 @@ export function filterSkillContentMessages<T extends { type: string; content?: s
|
|
|
46
119
|
messages: T[]
|
|
47
120
|
): T[] {
|
|
48
121
|
return messages.filter(msg => {
|
|
49
|
-
// Only filter user messages
|
|
50
122
|
if (msg.type !== 'user') {
|
|
51
123
|
return true;
|
|
52
124
|
}
|
|
53
|
-
// Filter out skill content
|
|
54
125
|
return !isSkillContent(msg.content);
|
|
55
126
|
});
|
|
56
127
|
}
|
|
@@ -88,10 +88,6 @@ export const SLASH_COMMANDS: SlashCommand[] = [
|
|
|
88
88
|
"name": "/create-branches-from-story",
|
|
89
89
|
"description": "Create feature branches in both repos from a story"
|
|
90
90
|
},
|
|
91
|
-
{
|
|
92
|
-
"name": "/create-theme",
|
|
93
|
-
"description": "Create a new custom persona theme"
|
|
94
|
-
},
|
|
95
91
|
{
|
|
96
92
|
"name": "/dev",
|
|
97
93
|
"description": "Developer - Feature implementation and coding"
|
|
@@ -128,10 +124,6 @@ export const SLASH_COMMANDS: SlashCommand[] = [
|
|
|
128
124
|
"name": "/job-fair",
|
|
129
125
|
"description": "Discover which characters in a theme excel at each role"
|
|
130
126
|
},
|
|
131
|
-
{
|
|
132
|
-
"name": "/list-themes",
|
|
133
|
-
"description": "List all available persona themes"
|
|
134
|
-
},
|
|
135
127
|
{
|
|
136
128
|
"name": "/login",
|
|
137
129
|
"description": "Authenticate with Anthropic"
|
|
@@ -208,18 +200,10 @@ export const SLASH_COMMANDS: SlashCommand[] = [
|
|
|
208
200
|
"name": "/run-ci",
|
|
209
201
|
"description": "Detect and run CI locally"
|
|
210
202
|
},
|
|
211
|
-
{
|
|
212
|
-
"name": "/set-theme",
|
|
213
|
-
"description": "Set the active persona theme"
|
|
214
|
-
},
|
|
215
203
|
{
|
|
216
204
|
"name": "/setup",
|
|
217
205
|
"description": "setup"
|
|
218
206
|
},
|
|
219
|
-
{
|
|
220
|
-
"name": "/show-theme",
|
|
221
|
-
"description": "Show details of a theme including all agent personas"
|
|
222
|
-
},
|
|
223
207
|
{
|
|
224
208
|
"name": "/sm",
|
|
225
209
|
"description": "Scrum Master - Story coordination and sprint management"
|
|
@@ -269,8 +253,8 @@ export const SLASH_COMMANDS: SlashCommand[] = [
|
|
|
269
253
|
"description": "Configure terminal"
|
|
270
254
|
},
|
|
271
255
|
{
|
|
272
|
-
"name": "/theme
|
|
273
|
-
"description": "
|
|
256
|
+
"name": "/theme",
|
|
257
|
+
"description": "Manage persona themes - list, show, set, create, or interactive wizard"
|
|
274
258
|
},
|
|
275
259
|
{
|
|
276
260
|
"name": "/update-domain-docs",
|
|
@@ -18,6 +18,7 @@ export interface TaskInput {
|
|
|
18
18
|
export interface Helper {
|
|
19
19
|
name: string;
|
|
20
20
|
style: string;
|
|
21
|
+
plural?: boolean;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
// Cache for helper lookups
|
|
@@ -119,7 +120,8 @@ const SUBAGENT_TYPE_MESSAGES: Record<string, string> = {
|
|
|
119
120
|
'Bash': 'Running commands',
|
|
120
121
|
};
|
|
121
122
|
|
|
122
|
-
export function generateFriendlyMessage(context: TaskInput): string {
|
|
123
|
+
export function generateFriendlyMessage(context: TaskInput, options?: { plural?: boolean }): string {
|
|
124
|
+
const verb = options?.plural ? 'are' : 'is';
|
|
123
125
|
// If we have a description, include it
|
|
124
126
|
const description = context.description;
|
|
125
127
|
|
|
@@ -127,10 +129,11 @@ export function generateFriendlyMessage(context: TaskInput): string {
|
|
|
127
129
|
const subagentType = context.subagent_type;
|
|
128
130
|
if (subagentType && SUBAGENT_TYPE_MESSAGES[subagentType]) {
|
|
129
131
|
const action = SUBAGENT_TYPE_MESSAGES[subagentType];
|
|
132
|
+
const lowerAction = action.charAt(0).toLowerCase() + action.slice(1);
|
|
130
133
|
if (description) {
|
|
131
|
-
return `${
|
|
134
|
+
return `${verb} ${lowerAction}: ${description}`;
|
|
132
135
|
}
|
|
133
|
-
return
|
|
136
|
+
return `${verb} ${lowerAction}`;
|
|
134
137
|
}
|
|
135
138
|
|
|
136
139
|
// Fall back to description if available
|
package/LICENSE
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2026 1898 & Co.
|
|
2
|
-
|
|
3
|
-
All rights reserved.
|
|
4
|
-
|
|
5
|
-
This software and associated documentation files (the "Software") are proprietary
|
|
6
|
-
and confidential. No part of this Software may be reproduced, distributed, or
|
|
7
|
-
transmitted in any form or by any means, including photocopying, recording, or
|
|
8
|
-
other electronic or mechanical methods, without the prior written permission of
|
|
9
|
-
the copyright holder.
|
|
10
|
-
|
|
11
|
-
Unauthorized copying, modification, distribution, or use of this Software, via
|
|
12
|
-
any medium, is strictly prohibited.
|
|
13
|
-
|
|
14
|
-
For licensing inquiries, contact: 1898 & Co.
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AskUserQuestionBlock Component
|
|
3
|
-
*
|
|
4
|
-
* Renders interactive buttons for AskUserQuestion tool_use messages.
|
|
5
|
-
* Uses the existing ClaudeContext to send responses back via WebSocket.
|
|
6
|
-
*
|
|
7
|
-
* Story: MSSCI-14395 - Render AskUserQuestion tool via Reflector QuickActions
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import React, { useState, useCallback } from 'react';
|
|
11
|
-
import { Button } from '@/components/ui/button';
|
|
12
|
-
import { Badge } from '@/components/ui/badge';
|
|
13
|
-
import { useClaudeContext } from '../contexts/ClaudeContext';
|
|
14
|
-
|
|
15
|
-
interface QuestionOption {
|
|
16
|
-
label: string;
|
|
17
|
-
description: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface Question {
|
|
21
|
-
question: string;
|
|
22
|
-
header: string;
|
|
23
|
-
options: QuestionOption[];
|
|
24
|
-
multiSelect: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
interface AskUserQuestionToolUse {
|
|
28
|
-
type: 'tool_use';
|
|
29
|
-
tool_name: string;
|
|
30
|
-
tool_id: string;
|
|
31
|
-
input: {
|
|
32
|
-
questions: Question[];
|
|
33
|
-
};
|
|
34
|
-
timestamp: number;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
interface AskUserQuestionBlockProps {
|
|
38
|
-
toolUse: AskUserQuestionToolUse;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function SingleSelectQuestion({ question, onSubmit, disabled }: {
|
|
42
|
-
question: Question;
|
|
43
|
-
onSubmit: (answer: string) => void;
|
|
44
|
-
disabled: boolean;
|
|
45
|
-
}) {
|
|
46
|
-
return (
|
|
47
|
-
<div className="ask-question-group">
|
|
48
|
-
<Badge variant="secondary" className="ask-question-header">{question.header}</Badge>
|
|
49
|
-
<p className="ask-question-text">{question.question}</p>
|
|
50
|
-
<div className="ask-question-options">
|
|
51
|
-
{question.options.map((opt) => (
|
|
52
|
-
<Button
|
|
53
|
-
key={opt.label}
|
|
54
|
-
variant="secondary"
|
|
55
|
-
size="sm"
|
|
56
|
-
className="ask-question-option"
|
|
57
|
-
onClick={() => onSubmit(opt.label)}
|
|
58
|
-
disabled={disabled}
|
|
59
|
-
>
|
|
60
|
-
<span className="ask-option-label">{opt.label}</span>
|
|
61
|
-
<span className="ask-option-desc">{opt.description}</span>
|
|
62
|
-
</Button>
|
|
63
|
-
))}
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function MultiSelectQuestion({ question, onSubmit, disabled }: {
|
|
70
|
-
question: Question;
|
|
71
|
-
onSubmit: (answers: string[]) => void;
|
|
72
|
-
disabled: boolean;
|
|
73
|
-
}) {
|
|
74
|
-
const [selected, setSelected] = useState<Set<string>>(new Set());
|
|
75
|
-
|
|
76
|
-
const toggleOption = useCallback((label: string) => {
|
|
77
|
-
setSelected(prev => {
|
|
78
|
-
const next = new Set(prev);
|
|
79
|
-
if (next.has(label)) {
|
|
80
|
-
next.delete(label);
|
|
81
|
-
} else {
|
|
82
|
-
next.add(label);
|
|
83
|
-
}
|
|
84
|
-
return next;
|
|
85
|
-
});
|
|
86
|
-
}, []);
|
|
87
|
-
|
|
88
|
-
const handleSubmit = useCallback(() => {
|
|
89
|
-
onSubmit(Array.from(selected));
|
|
90
|
-
}, [selected, onSubmit]);
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<div className="ask-question-group">
|
|
94
|
-
<Badge variant="secondary" className="ask-question-header">{question.header}</Badge>
|
|
95
|
-
<p className="ask-question-text">{question.question}</p>
|
|
96
|
-
<div className="ask-question-options">
|
|
97
|
-
{question.options.map((opt) => (
|
|
98
|
-
<Button
|
|
99
|
-
key={opt.label}
|
|
100
|
-
variant="secondary"
|
|
101
|
-
size="sm"
|
|
102
|
-
className="ask-question-option"
|
|
103
|
-
onClick={() => toggleOption(opt.label)}
|
|
104
|
-
disabled={disabled}
|
|
105
|
-
aria-pressed={selected.has(opt.label)}
|
|
106
|
-
>
|
|
107
|
-
<span className="ask-option-label">{opt.label}</span>
|
|
108
|
-
<span className="ask-option-desc">{opt.description}</span>
|
|
109
|
-
</Button>
|
|
110
|
-
))}
|
|
111
|
-
</div>
|
|
112
|
-
<Button
|
|
113
|
-
variant="default"
|
|
114
|
-
size="sm"
|
|
115
|
-
className="ask-question-submit"
|
|
116
|
-
onClick={handleSubmit}
|
|
117
|
-
disabled={disabled || selected.size === 0}
|
|
118
|
-
aria-label="Confirm"
|
|
119
|
-
>
|
|
120
|
-
Confirm
|
|
121
|
-
</Button>
|
|
122
|
-
</div>
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export function AskUserQuestionBlock({ toolUse }: AskUserQuestionBlockProps): React.ReactElement {
|
|
127
|
-
const { send } = useClaudeContext();
|
|
128
|
-
const [isDisabled, setIsDisabled] = useState(false);
|
|
129
|
-
const questions = toolUse.input?.questions || [];
|
|
130
|
-
|
|
131
|
-
const handleSingleSelect = useCallback((answer: string) => {
|
|
132
|
-
setIsDisabled(true);
|
|
133
|
-
send(answer, []);
|
|
134
|
-
}, [send]);
|
|
135
|
-
|
|
136
|
-
const handleMultiSelect = useCallback((answers: string[]) => {
|
|
137
|
-
setIsDisabled(true);
|
|
138
|
-
send(answers.join(', '), []);
|
|
139
|
-
}, [send]);
|
|
140
|
-
|
|
141
|
-
return (
|
|
142
|
-
<div className="ask-user-question-block">
|
|
143
|
-
{questions.map((q, i) => (
|
|
144
|
-
q.multiSelect ? (
|
|
145
|
-
<MultiSelectQuestion
|
|
146
|
-
key={i}
|
|
147
|
-
question={q}
|
|
148
|
-
onSubmit={handleMultiSelect}
|
|
149
|
-
disabled={isDisabled}
|
|
150
|
-
/>
|
|
151
|
-
) : (
|
|
152
|
-
<SingleSelectQuestion
|
|
153
|
-
key={i}
|
|
154
|
-
question={q}
|
|
155
|
-
onSubmit={handleSingleSelect}
|
|
156
|
-
disabled={isDisabled}
|
|
157
|
-
/>
|
|
158
|
-
)
|
|
159
|
-
))}
|
|
160
|
-
</div>
|
|
161
|
-
);
|
|
162
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AskUserQuestion Utility
|
|
3
|
-
*
|
|
4
|
-
* Utility functions for detecting AskUserQuestion tool_use messages.
|
|
5
|
-
*
|
|
6
|
-
* Story: MSSCI-14395 - Render AskUserQuestion tool via Reflector QuickActions
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
interface ToolUseMessage {
|
|
10
|
-
type: string;
|
|
11
|
-
tool_name?: string;
|
|
12
|
-
tool_id?: string;
|
|
13
|
-
input?: Record<string, unknown>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Check if a tool_use message is an AskUserQuestion tool call.
|
|
18
|
-
*/
|
|
19
|
-
export function isAskUserQuestion(toolUse: ToolUseMessage): boolean {
|
|
20
|
-
return toolUse.tool_name === 'AskUserQuestion';
|
|
21
|
-
}
|